diff --git a/404.html b/404.html new file mode 100644 index 0000000..bdd40bd --- /dev/null +++ b/404.html @@ -0,0 +1 @@ +Eli | Page not found

Error 404: Page not found

The page you were looking for could not be found. Maybe it was moved?

\ No newline at end of file diff --git a/CNAME b/CNAME new file mode 100644 index 0000000..26b3e94 --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +elihunter173.com diff --git a/asteroids/AstroSpace.otf b/asteroids/AstroSpace.otf new file mode 100644 index 0000000..627380f Binary files /dev/null and b/asteroids/AstroSpace.otf differ diff --git a/asteroids/bundle.js b/asteroids/bundle.js new file mode 100644 index 0000000..cd00573 --- /dev/null +++ b/asteroids/bundle.js @@ -0,0 +1,2 @@ +(()=>{"use strict";var e={d:(r,t)=>{for(var n in t)e.o(t,n)&&!e.o(r,n)&&Object.defineProperty(r,n,{enumerable:!0,get:t[n]})},o:(e,r)=>Object.prototype.hasOwnProperty.call(e,r),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},r={};e.r(r),e.d(r,{add:()=>f,angle:()=>O,bezier:()=>R,ceil:()=>y,clone:()=>i,copy:()=>u,create:()=>o,cross:()=>L,dist:()=>X,distance:()=>M,div:()=>Q,divide:()=>d,dot:()=>F,equals:()=>z,exactEquals:()=>K,floor:()=>m,forEach:()=>$,fromValues:()=>l,hermite:()=>B,inverse:()=>P,len:()=>J,length:()=>s,lerp:()=>j,max:()=>g,min:()=>v,mul:()=>Y,multiply:()=>p,negate:()=>A,normalize:()=>E,random:()=>k,rotateX:()=>I,rotateY:()=>U,rotateZ:()=>C,round:()=>b,scale:()=>w,scaleAndAdd:()=>x,set:()=>c,sqrDist:()=>W,sqrLen:()=>Z,squaredDistance:()=>T,squaredLength:()=>S,str:()=>q,sub:()=>H,subtract:()=>h,transformMat3:()=>_,transformMat4:()=>D,transformQuat:()=>V,zero:()=>N});var t=1e-6,n="undefined"!=typeof Float32Array?Float32Array:Array,a=Math.random;function o(){var e=new n(3);return n!=Float32Array&&(e[0]=0,e[1]=0,e[2]=0),e}function i(e){var r=new n(3);return r[0]=e[0],r[1]=e[1],r[2]=e[2],r}function s(e){var r=e[0],t=e[1],n=e[2];return Math.hypot(r,t,n)}function l(e,r,t){var a=new n(3);return a[0]=e,a[1]=r,a[2]=t,a}function u(e,r){return e[0]=r[0],e[1]=r[1],e[2]=r[2],e}function c(e,r,t,n){return e[0]=r,e[1]=t,e[2]=n,e}function f(e,r,t){return e[0]=r[0]+t[0],e[1]=r[1]+t[1],e[2]=r[2]+t[2],e}function h(e,r,t){return e[0]=r[0]-t[0],e[1]=r[1]-t[1],e[2]=r[2]-t[2],e}function p(e,r,t){return e[0]=r[0]*t[0],e[1]=r[1]*t[1],e[2]=r[2]*t[2],e}function d(e,r,t){return e[0]=r[0]/t[0],e[1]=r[1]/t[1],e[2]=r[2]/t[2],e}function y(e,r){return e[0]=Math.ceil(r[0]),e[1]=Math.ceil(r[1]),e[2]=Math.ceil(r[2]),e}function m(e,r){return e[0]=Math.floor(r[0]),e[1]=Math.floor(r[1]),e[2]=Math.floor(r[2]),e}function v(e,r,t){return e[0]=Math.min(r[0],t[0]),e[1]=Math.min(r[1],t[1]),e[2]=Math.min(r[2],t[2]),e}function g(e,r,t){return e[0]=Math.max(r[0],t[0]),e[1]=Math.max(r[1],t[1]),e[2]=Math.max(r[2],t[2]),e}function b(e,r){return e[0]=Math.round(r[0]),e[1]=Math.round(r[1]),e[2]=Math.round(r[2]),e}function w(e,r,t){return e[0]=r[0]*t,e[1]=r[1]*t,e[2]=r[2]*t,e}function x(e,r,t,n){return e[0]=r[0]+t[0]*n,e[1]=r[1]+t[1]*n,e[2]=r[2]+t[2]*n,e}function M(e,r){var t=r[0]-e[0],n=r[1]-e[1],a=r[2]-e[2];return Math.hypot(t,n,a)}function T(e,r){var t=r[0]-e[0],n=r[1]-e[1],a=r[2]-e[2];return t*t+n*n+a*a}function S(e){var r=e[0],t=e[1],n=e[2];return r*r+t*t+n*n}function A(e,r){return e[0]=-r[0],e[1]=-r[1],e[2]=-r[2],e}function P(e,r){return e[0]=1/r[0],e[1]=1/r[1],e[2]=1/r[2],e}function E(e,r){var t=r[0],n=r[1],a=r[2],o=t*t+n*n+a*a;return o>0&&(o=1/Math.sqrt(o)),e[0]=r[0]*o,e[1]=r[1]*o,e[2]=r[2]*o,e}function F(e,r){return e[0]*r[0]+e[1]*r[1]+e[2]*r[2]}function L(e,r,t){var n=r[0],a=r[1],o=r[2],i=t[0],s=t[1],l=t[2];return e[0]=a*l-o*s,e[1]=o*i-n*l,e[2]=n*s-a*i,e}function j(e,r,t,n){var a=r[0],o=r[1],i=r[2];return e[0]=a+n*(t[0]-a),e[1]=o+n*(t[1]-o),e[2]=i+n*(t[2]-i),e}function B(e,r,t,n,a,o){var i=o*o,s=i*(2*o-3)+1,l=i*(o-2)+o,u=i*(o-1),c=i*(3-2*o);return e[0]=r[0]*s+t[0]*l+n[0]*u+a[0]*c,e[1]=r[1]*s+t[1]*l+n[1]*u+a[1]*c,e[2]=r[2]*s+t[2]*l+n[2]*u+a[2]*c,e}function R(e,r,t,n,a,o){var i=1-o,s=i*i,l=o*o,u=s*i,c=3*o*s,f=3*l*i,h=l*o;return e[0]=r[0]*u+t[0]*c+n[0]*f+a[0]*h,e[1]=r[1]*u+t[1]*c+n[1]*f+a[1]*h,e[2]=r[2]*u+t[2]*c+n[2]*f+a[2]*h,e}function k(e,r){r=r||1;var t=2*a()*Math.PI,n=2*a()-1,o=Math.sqrt(1-n*n)*r;return e[0]=Math.cos(t)*o,e[1]=Math.sin(t)*o,e[2]=n*r,e}function D(e,r,t){var n=r[0],a=r[1],o=r[2],i=t[3]*n+t[7]*a+t[11]*o+t[15];return i=i||1,e[0]=(t[0]*n+t[4]*a+t[8]*o+t[12])/i,e[1]=(t[1]*n+t[5]*a+t[9]*o+t[13])/i,e[2]=(t[2]*n+t[6]*a+t[10]*o+t[14])/i,e}function _(e,r,t){var n=r[0],a=r[1],o=r[2];return e[0]=n*t[0]+a*t[3]+o*t[6],e[1]=n*t[1]+a*t[4]+o*t[7],e[2]=n*t[2]+a*t[5]+o*t[8],e}function V(e,r,t){var n=t[0],a=t[1],o=t[2],i=t[3],s=r[0],l=r[1],u=r[2],c=a*u-o*l,f=o*s-n*u,h=n*l-a*s,p=a*h-o*f,d=o*c-n*h,y=n*f-a*c,m=2*i;return c*=m,f*=m,h*=m,p*=2,d*=2,y*=2,e[0]=s+c+p,e[1]=l+f+d,e[2]=u+h+y,e}function I(e,r,t,n){var a=[],o=[];return a[0]=r[0]-t[0],a[1]=r[1]-t[1],a[2]=r[2]-t[2],o[0]=a[0],o[1]=a[1]*Math.cos(n)-a[2]*Math.sin(n),o[2]=a[1]*Math.sin(n)+a[2]*Math.cos(n),e[0]=o[0]+t[0],e[1]=o[1]+t[1],e[2]=o[2]+t[2],e}function U(e,r,t,n){var a=[],o=[];return a[0]=r[0]-t[0],a[1]=r[1]-t[1],a[2]=r[2]-t[2],o[0]=a[2]*Math.sin(n)+a[0]*Math.cos(n),o[1]=a[1],o[2]=a[2]*Math.cos(n)-a[0]*Math.sin(n),e[0]=o[0]+t[0],e[1]=o[1]+t[1],e[2]=o[2]+t[2],e}function C(e,r,t,n){var a=[],o=[];return a[0]=r[0]-t[0],a[1]=r[1]-t[1],a[2]=r[2]-t[2],o[0]=a[0]*Math.cos(n)-a[1]*Math.sin(n),o[1]=a[0]*Math.sin(n)+a[1]*Math.cos(n),o[2]=a[2],e[0]=o[0]+t[0],e[1]=o[1]+t[1],e[2]=o[2]+t[2],e}function O(e,r){var t=e[0],n=e[1],a=e[2],o=r[0],i=r[1],s=r[2],l=Math.sqrt(t*t+n*n+a*a)*Math.sqrt(o*o+i*i+s*s),u=l&&F(e,r)/l;return Math.acos(Math.min(Math.max(u,-1),1))}function N(e){return e[0]=0,e[1]=0,e[2]=0,e}function q(e){return"vec3("+e[0]+", "+e[1]+", "+e[2]+")"}function K(e,r){return e[0]===r[0]&&e[1]===r[1]&&e[2]===r[2]}function z(e,r){var n=e[0],a=e[1],o=e[2],i=r[0],s=r[1],l=r[2];return Math.abs(n-i)<=t*Math.max(1,Math.abs(n),Math.abs(i))&&Math.abs(a-s)<=t*Math.max(1,Math.abs(a),Math.abs(s))&&Math.abs(o-l)<=t*Math.max(1,Math.abs(o),Math.abs(l))}Math.PI,Math.hypot||(Math.hypot=function(){for(var e=0,r=arguments.length;r--;)e+=arguments[r]*arguments[r];return Math.sqrt(e)});var G,H=h,Y=p,Q=d,X=M,W=T,J=s,Z=S,$=(G=o(),function(e,r,t,n,a,o){var i,s;for(r||(r=3),t||(t=0),s=n?Math.min(n*r+t,e.length):e.length,i=t;i=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(r?"Object is not iterable.":"Symbol.iterator is not defined.")}),pe=function(e,r){var t="function"==typeof Symbol&&e[Symbol.iterator];if(!t)return e;var n,a,o=t.call(e),i=[];try{for(;(void 0===r||r-- >0)&&!(n=o.next()).done;)i.push(n.value)}catch(e){a={error:e}}finally{try{n&&!n.done&&(t=o.return)&&t.call(o)}finally{if(a)throw a.error}}return i},de=function(e,r,t){if(t||2===arguments.length)for(var n,a=0,o=r.length;a0)&&!(n=o.next()).done;)i.push(n.value)}catch(e){a={error:e}}finally{try{n&&!n.done&&(t=o.return)&&t.call(o)}finally{if(a)throw a.error}}return i},ke=function(e,r,t){if(t||2===arguments.length)for(var n,a=0,o=r.length;a=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(r?"Object is not iterable.":"Symbol.iterator is not defined.")},_e=be,Ve=function(){function e(e,r,t){void 0===t&&(t=ee());var n=r.vertices.flat(),a=e.createBuffer();if(null==a)throw"could not create webgl buffer";e.bindBuffer(e.ARRAY_BUFFER,a),e.bufferData(e.ARRAY_BUFFER,new Float32Array(n),e.STATIC_DRAW);var o=r.triangles.flat(),i=e.createBuffer();if(null==i)throw"could not create webgl buffer";e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,i),e.bufferData(e.ELEMENT_ARRAY_BUFFER,new Uint16Array(o),e.STATIC_DRAW),this.vertexPosBuffer=a,this.triangleBuffer=i,this.triangleBufferSize=o.length,this.model=r,this.vertexTransform=t}return e.prototype.translate=function(e){re(this.vertexTransform,function(e,r){return e[0]=1,e[1]=0,e[2]=0,e[3]=0,e[4]=0,e[5]=1,e[6]=0,e[7]=0,e[8]=0,e[9]=0,e[10]=1,e[11]=0,e[12]=r[0],e[13]=r[1],e[14]=r[2],e[15]=1,e}(ee(),e),this.vertexTransform)},e.prototype.rotate=function(e){!function(e,r,t){var n=Math.sin(t),a=Math.cos(t),o=r[0],i=r[1],s=r[2],l=r[3],u=r[4],c=r[5],f=r[6],h=r[7];r!==e&&(e[8]=r[8],e[9]=r[9],e[10]=r[10],e[11]=r[11],e[12]=r[12],e[13]=r[13],e[14]=r[14],e[15]=r[15]),e[0]=o*a+u*n,e[1]=i*a+c*n,e[2]=s*a+f*n,e[3]=l*a+h*n,e[4]=u*a-o*n,e[5]=c*a-i*n,e[6]=f*a-s*n,e[7]=h*a-l*n}(this.vertexTransform,this.vertexTransform,e)},e.prototype.pos=function(){return function(e,r){return e[0]=r[12],e[1]=r[13],e[2]=r[14],e}(o(),this.vertexTransform)},e}(),Ie=["aVertexPos"],Ue=["uViewingTransform","uPerspectiveTransform","uVertexTransform","uLights","uNumLights","uEyePos","uFog","uMaterial.ambient","uMaterial.diffuse","uMaterial.specular","uMaterial.shine"];function Ce(e){var r,t,n,a;e.getExtension("OES_standard_derivatives");var o=e.createShader(e.VERTEX_SHADER);if(null==o)throw"could not create webgl shader";if(e.shaderSource(o,"\nprecision highp float;\n\nuniform mat4 uViewingTransform;\nuniform mat4 uPerspectiveTransform;\n\nuniform mat4 uVertexTransform;\n\nattribute vec3 aVertexPos;\nvarying vec4 vSurfacePos;\n\nvoid main(void) {\n vSurfacePos = uVertexTransform * vec4(aVertexPos, 1.0);\n\n gl_Position = uPerspectiveTransform * uViewingTransform * vSurfacePos;\n}\n"),e.compileShader(o),!e.getShaderParameter(o,e.COMPILE_STATUS))throw"error during vertex shader compile: "+e.getShaderInfoLog(o);var i="\n#extension GL_OES_standard_derivatives : enable\n\nprecision highp float;\n\nconst int NUM_SUNS = ".concat(4,";\nconst float FOG_START = ").concat(24..toFixed(10),";\nconst float FOG_END = ").concat(32..toFixed(10),";\nconst vec3 FOG_COLOR = vec3(").concat(_e[0],", ").concat(_e[1],", ").concat(_e[2],");\n\nuniform vec3 uLights[NUM_SUNS];\nuniform int uNumLights;\nuniform vec3 uEyePos;\nuniform int uFog;\n\nstruct Material {\n vec3 ambient;\n vec3 diffuse;\n vec3 specular;\n float shine;\n};\n\nuniform Material uMaterial;\n\nvarying vec4 vSurfacePos;\n\n// The function 1 / (1 + 0.002x^3) == 0.5 at 7.937\nfloat attenuation(float x) {\n if (x < 8.0) {\n return 1.0;\n } else {\n x -= 8.0;\n float a = 1.0 / (1.0 + 0.05*x + 0.004*x*x*x);\n return clamp(a, 0.0, 1.0);\n }\n}\n\nvoid main(void) {\n vec3 color = uMaterial.ambient;\n\n vec3 viewVector = normalize(uEyePos - vSurfacePos.xyz);\n vec3 normalVector = normalize(cross(\n dFdx(vSurfacePos.xyz),\n dFdy(vSurfacePos.xyz)\n ));\n\n for (int i = 0; i < NUM_SUNS; i++) {\n if (i >= uNumLights) {\n break;\n }\n\n vec3 lightVector = normalize(uLights[i] - vSurfacePos.xyz);\n vec3 halfVector = normalize(viewVector + lightVector);\n\n float lightDist = length(uLights[i] - vSurfacePos.xyz);\n float atten = attenuation(lightDist);\n\n vec3 diffuse = atten * uMaterial.diffuse * max(0.0, dot(normalVector, lightVector));\n vec3 specular = atten * uMaterial.specular * pow(max(0.0, dot(normalVector, halfVector)), uMaterial.shine);\n color += diffuse + specular;\n }\n\n float fogFactor = 0.0;\n if (uFog == 1) {\n float dist = length(uEyePos - vSurfacePos.xyz);\n fogFactor = min(1.0, max(0.0, dist - FOG_START) / (FOG_END - FOG_START));\n }\n\n gl_FragColor = vec4(mix(color, FOG_COLOR, fogFactor), 1.0);\n}\n"),s=e.createShader(e.FRAGMENT_SHADER);if(null==s)throw"could not create webgl shader";if(e.shaderSource(s,i),e.compileShader(s),!e.getShaderParameter(s,e.COMPILE_STATUS))throw"error during fragment shader compile: "+e.getShaderInfoLog(s);var l=e.createProgram();if(null==l)throw"could not create webgl program";if(e.attachShader(l,s),e.attachShader(l,o),e.linkProgram(l),!e.getProgramParameter(l,e.LINK_STATUS))throw"error during shader program linking: "+e.getProgramInfoLog(l);e.useProgram(l);var u={attribs:{},uniforms:{}};try{for(var c=De(Ie),f=c.next();!f.done;f=c.next()){var h=f.value,p=e.getAttribLocation(l,h);if(-1==p)throw"invalid attribute ".concat(h);e.enableVertexAttribArray(p),u.attribs[h]=p}}catch(e){r={error:e}}finally{try{f&&!f.done&&(t=c.return)&&t.call(c)}finally{if(r)throw r.error}}try{for(var d=De(Ue),y=d.next();!y.done;y=d.next()){var m=y.value,v=e.getUniformLocation(l,m);u.uniforms[m]=v}}catch(e){n={error:e}}finally{try{y&&!y.done&&(a=d.return)&&a.call(d)}finally{if(n)throw n.error}}return u}function Oe(e,r,t,n,a,o,i){var s,l,u,c;null==i&&(i={fog:!0}),e.clear(e.COLOR_BUFFER_BIT|e.DEPTH_BUFFER_BIT);var f=[],h=0;try{for(var p=De(r),d=p.next();!d.done;d=p.next()){var y=d.value;f.push.apply(f,ke([],Re(y),!1)),h+=1}}catch(e){s={error:e}}finally{try{d&&!d.done&&(l=p.return)&&l.call(p)}finally{if(s)throw s.error}}function m(r){var t,n;t=r.vertexPosBuffer,n=a.attribs.aVertexPos,e.bindBuffer(e.ARRAY_BUFFER,t),e.vertexAttribPointer(n,3,e.FLOAT,!1,0,0),e.uniformMatrix4fv(a.uniforms.uVertexTransform,!1,r.vertexTransform);var o=r.model.material;e.uniform3fv(a.uniforms["uMaterial.ambient"],o.ambient),e.uniform3fv(a.uniforms["uMaterial.diffuse"],o.diffuse),e.uniform3fv(a.uniforms["uMaterial.specular"],o.specular),e.uniform1f(a.uniforms["uMaterial.shine"],o.n),e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,r.triangleBuffer),e.drawElements(e.TRIANGLES,r.triangleBufferSize,e.UNSIGNED_SHORT,0)}e.uniform3fv(a.uniforms.uLights,f),e.uniform1i(a.uniforms.uNumLights,h),e.uniform1i(a.uniforms.uFog,i.fog?1:0),e.uniform3fv(a.uniforms.uEyePos,o.eye),e.uniformMatrix4fv(a.uniforms.uViewingTransform,!1,o.viewingTransform),e.uniformMatrix4fv(a.uniforms.uPerspectiveTransform,!1,o.perspectiveTransform),e.enable(e.DEPTH_TEST);var v=Array.from(t);try{for(var g=De(v),b=g.next();!b.done;b=g.next())m(b.value)}catch(e){u={error:e}}finally{try{b&&!b.done&&(c=g.return)&&c.call(g)}finally{if(u)throw u.error}}e.disable(e.DEPTH_TEST),Array.from(n).forEach(m)}var Ne=function(){function e(e,r){this.getTime=e,this.debounceTime=r,this.lastChange=-r}return e.prototype.reset=function(){this.lastChange=-this.debounceTime},e.prototype.set=function(){this.lastChange=this.getTime()},e.prototype.ready=function(){return this.getTime()-this.lastChange>=this.debounceTime},e.prototype.try=function(e){var r=this.getTime();r-this.lastChange>=this.debounceTime&&(e(),this.lastChange=r)},e}(),qe=function(){function e(){this.pressed=new Set}return e.prototype.register=function(){var e=this;document.addEventListener("keydown",(function(r){e.pressed.add(r.code)})),document.addEventListener("keyup",(function(r){e.pressed.delete(r.code)}))},e}(),Ke=function(e,r){var t,n,a,o,i={label:0,sent:function(){if(1&a[0])throw a[1];return a[1]},trys:[],ops:[]};return o={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function s(o){return function(s){return function(o){if(t)throw new TypeError("Generator is already executing.");for(;i;)try{if(t=1,n&&(a=2&o[0]?n.return:o[0]?n.throw||((a=n.return)&&a.call(n),0):n.next)&&!(a=a.call(n,o[1])).done)return a;switch(n=0,a&&(o=[2&o[0],a.value]),o[0]){case 0:case 1:a=o;break;case 4:return i.label++,{value:o[1],done:!1};case 5:i.label++,n=o[1],o=[0];continue;case 7:o=i.ops.pop(),i.trys.pop();continue;default:if(!((a=(a=i.trys).length>0&&a[a.length-1])||6!==o[0]&&2!==o[0])){i=0;continue}if(3===o[0]&&(!a||o[1]>a[0]&&o[1]0)&&!(n=o.next()).done;)i.push(n.value)}catch(e){a={error:e}}finally{try{n&&!n.done&&(t=o.return)&&t.call(o)}finally{if(a)throw a.error}}return i},Ge=function(e,r,t){if(t||2===arguments.length)for(var n,a=0,o=r.length;a=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(r?"Object is not iterable.":"Symbol.iterator is not defined.")};function Ye(e,r){return(r-e)*Math.random()+e}function Qe(e,r){return Math.min(r[1],Math.max(r[0],e))}function Xe(e){return e*(Math.PI/180)}function We(e,r){return Je(e,[0,r])}function Je(e,r){var t=l(e[0]+1,e[1],e[2]);Math.abs(t[0])<.01&&(t=l(e[0],e[1]+1,e[2])),L(t,e,t),E(t,t);var n=u(o(),e),a=ne(ee(),Ye.apply(void 0,Ge([],ze(r),!1)),t),i=ne(ee(),Ye(0,2*Math.PI),e);return D(n,n,a),D(n,n,i),n}var Ze=1/32,$e=[[1.4,1.8],[.6,.8]],er=[2,1],rr=[100,50],tr=[.005,.1],nr=[.01,.08],ar=[16,32],or=Xe(120),ir=Xe(45),sr=[10,28],lr=[Xe(2.5),Xe(50)],ur=[-1/9,1/15],cr=[80,86],fr=Xe(.3),hr=Math.round(34),pr=.005,dr=[Xe(3),Xe(45)],yr=Xe(120),mr=[.01,.1],vr=200;function gr(e){return[Math.round(.5*e*e+8*e),Math.round(1/8*e*e+4*e+4)]}var br=new Audio("missile.mp3"),wr=new Audio("music.wav");wr.volume=.75,wr.loop=!0;var xr,Mr=function(){function e(e,r){this.want=e,this.current=e,this.speedLimit=r}return e.prototype.set=function(e){this.want=e},e.prototype.get=function(){return this.current},e.prototype.step=function(){this.current+=Qe(this.want-this.current,this.speedLimit)},e}(),Tr=function(){function e(e){this.velocity=o(),this.obj=new Ve(e,Me),this.flame=new Ve(e,Ae),this.flameAccent=new Ve(e,Pe),this.flameAccent.vertexTransform=this.flame.vertexTransform,this.reticle=new Ve(e,Ee),this.reticle.vertexTransform=this.obj.vertexTransform,this.lastFired=Number.NEGATIVE_INFINITY,this.throttle=new Mr(0,ur),this.worldRotation=se(),this.up=l(0,0,-1),this.forward=l(0,1,0),this.right=l(-1,0,0),this.thrusterSfx=new Audio("thruster.wav"),this.thrusterSfx.loop=!0}return e.prototype.objects=function(){return Ke(this,(function(e){switch(e.label){case 0:return[4,this.obj];case 1:return e.sent(),this.throttle.get()>0?[4,this.flame]:[3,4];case 2:return e.sent(),[4,this.flameAccent];case 3:e.sent(),e.label=4;case 4:return[2]}}))},e.prototype.setThrottle=function(e){0!=e&&this.thrusterSfx.play(),this.throttle.set(e)},e.prototype.pitchUp=function(e){this.rotate(e,this.right)},e.prototype.yawLeft=function(e){this.rotate(e,this.up)},e.prototype.rollRight=function(e){this.rotate(e,this.forward)},e.prototype.rotate=function(e,r){var t=le(se(),r,e);ue(this.worldRotation,this.worldRotation,t)},e.prototype.collisionPoints=function(){var e=this;return Se.map((function(r){return D(o(),r,e.obj.vertexTransform)}))},e.prototype.tryFire=function(e){if(!(e.play.ticks-this.lastFired<=30)){this.lastFired=e.play.ticks;var r=br.cloneNode();r.volume=.15,r.play();var t=o();x(t,this.velocity,this.forward,1);var n=new Ve(e.gl,Fe);!function(e,r,t){var n,a,o,i,s,l,u,c,f,h,p,d,y=t[0],m=t[1],v=t[2];r===e?(e[12]=r[0]*y+r[4]*m+r[8]*v+r[12],e[13]=r[1]*y+r[5]*m+r[9]*v+r[13],e[14]=r[2]*y+r[6]*m+r[10]*v+r[14],e[15]=r[3]*y+r[7]*m+r[11]*v+r[15]):(n=r[0],a=r[1],o=r[2],i=r[3],s=r[4],l=r[5],u=r[6],c=r[7],f=r[8],h=r[9],p=r[10],d=r[11],e[0]=n,e[1]=a,e[2]=o,e[3]=i,e[4]=s,e[5]=l,e[6]=u,e[7]=c,e[8]=f,e[9]=h,e[10]=p,e[11]=d,e[12]=n*y+s*m+f*v+r[12],e[13]=a*y+l*m+h*v+r[13],e[14]=o*y+u*m+p*v+r[14],e[15]=i*y+c*m+d*v+r[15])}(n.vertexTransform,n.vertexTransform,Te),re(n.vertexTransform,this.obj.vertexTransform,n.vertexTransform),e.play.missiles.push({birth:e.play.ticks,velocity:t,obj:n})}},e.prototype.eye=function(){var e=this.obj.pos();return x(e,e,this.forward,-.65),x(e,e,this.up,.3),e},e.prototype.camera=function(e){var r,t,n=this.eye(),a=this.throttle.get(),i=(r=a*a)*(t=cr)[1]+(1-r)*t[0];return j(n,e,n,.6),{eye:n,viewingTransform:ie(ee(),n,f(o(),n,this.forward),this.up),perspectiveTransform:oe(ee(),Xe(i),Nr.width/Nr.height,Ze,32)}},e}(),Sr=function(){function e(e,r,t,n){var a=$e[r],i=null!=n?Math.min(a[1],Math.max(a[0],n.radius)):Ye.apply(void 0,Ge([],ze(a),!1)),s=ze(function(e){var r,t,n=e*(2/Math.sqrt(3)),a=[[0,0,0],[n,0,0],[n,0,n],[0,0,n],[0,n,0],[n,n,0],[n,n,n],[0,n,n]].map((function(e){var r=k(o(),(n/2-0)*Math.random()+0);return[e[0]+r[0],e[1]+r[1],e[2]+r[2]]})),i=me({material:JSON.parse(JSON.stringify(Be)),vertices:a,triangles:[[0,1,2],[2,3,0],[4,5,6],[6,7,4],[0,1,4],[4,5,1],[1,2,5],[2,5,6],[2,3,6],[3,6,7],[3,0,7],[0,7,4]]}),s=0;try{for(var l=he(i.vertices),u=l.next();!u.done;u=l.next()){var c=u.value;s+=Math.hypot.apply(Math,de([],pe(c),!1))}}catch(e){r={error:e}}finally{try{u&&!u.done&&(t=l.return)&&t.call(l)}finally{if(r)throw r.error}}return[s/=i.vertices.length,i]}(i),2),l=s[0],u=s[1];if(this.obj=new Ve(e,u),this.radius=l,this.tier=r,this.health=er[r],this.velocity=t,null==n){var c=Ye.apply(void 0,Ge([],ze(tr),!1)),f=k(o());this.rotation=le(se(),f,c)}else this.rotation=n.rotation}return e.prototype.split=function(r){var t=k(o()),n=Ye.apply(void 0,Ge([],ze(nr),!1)),a=x(o(),this.velocity,t,n),i=new e(r,this.tier+1,a,{radius:this.radius/2,rotation:fe(this.rotation)}),s=this.obj.pos();i.obj.translate(s);var l=x(o(),this.velocity,t,-n),u=new e(r,this.tier+1,l,{radius:this.radius/2,rotation:fe(this.rotation)});return u.obj.translate(s),[i,u]},e.prototype.damage=function(){this.health-=1;for(var e=this.obj.model.material,r=this.health/er[this.tier],t=0;t<3;t++){var n=Le[t]*r+je[t]*(1-r);e.ambient[t]=.5*n,e.diffuse[t]=1*n}},e}();function Ar(e,r){var t=e.pos();return[0,1,2].every((function(e){return t[e]-1<=r[e]&&r[e]<=t[e]+1}))}function Pr(e){var r,t,n,a,o,i;return Ke(this,(function(s){switch(s.label){case 0:s.trys.push([0,5,6,7]),r=He(e.play.tieredAsteroids),t=r.next(),s.label=1;case 1:return t.done?[3,4]:(n=t.value,[5,He(n)]);case 2:s.sent(),s.label=3;case 3:return t=r.next(),[3,1];case 4:return[3,7];case 5:return a=s.sent(),o={error:a},[3,7];case 6:try{t&&!t.done&&(i=r.return)&&i.call(r)}finally{if(o)throw o.error}return[7];case 7:return[2]}}))}function Er(e){var r,t,n,a,o,i,s,l,u,c,f,h,p,d,y,m,v;return Ke(this,(function(g){switch(g.label){case 0:return[5,He(e.play.ship.objects())];case 1:if(g.sent(),!e.freecam.showShipCollisions)return[3,9];g.label=2;case 2:g.trys.push([2,7,8,9]),r=He(e.play.ship.collisionPoints()),t=r.next(),g.label=3;case 3:return t.done?[3,6]:(n=t.value,(a=new Ve(e.gl,xe)).translate(n),[4,a]);case 4:g.sent(),g.label=5;case 5:return t=r.next(),[3,3];case 6:return[3,9];case 7:return o=g.sent(),h={error:o},[3,9];case 8:try{t&&!t.done&&(p=r.return)&&p.call(r)}finally{if(h)throw h.error}return[7];case 9:g.trys.push([9,14,15,16]),i=He(e.play.missiles),s=i.next(),g.label=10;case 10:return s.done?[3,13]:[4,s.value.obj];case 11:g.sent(),g.label=12;case 12:return s=i.next(),[3,10];case 13:return[3,16];case 14:return l=g.sent(),d={error:l},[3,16];case 15:try{s&&!s.done&&(y=i.return)&&y.call(i)}finally{if(d)throw d.error}return[7];case 16:g.trys.push([16,21,22,23]),u=He(Pr(e)),c=u.next(),g.label=17;case 17:return c.done?[3,20]:[4,c.value.obj];case 18:g.sent(),g.label=19;case 19:return c=u.next(),[3,17];case 20:return[3,23];case 21:return f=g.sent(),m={error:f},[3,23];case 22:try{c&&!c.done&&(v=u.return)&&v.call(u)}finally{if(m)throw m.error}return[7];case 23:return[5,He(e.play.suns)];case 24:return g.sent(),[2]}}))}function Fr(e){return Ke(this,(function(r){switch(r.label){case 0:return[4,e.play.ship.reticle];case 1:return r.sent(),[2]}}))}function Lr(e){var r,t,n,a,o;return Ke(this,(function(i){switch(i.label){case 0:i.trys.push([0,5,6,7]),r=He(e.play.suns),t=r.next(),i.label=1;case 1:return t.done?[3,4]:[4,t.value.pos()];case 2:i.sent(),i.label=3;case 3:return t=r.next(),[3,1];case 4:return[3,7];case 5:return n=i.sent(),a={error:n},[3,7];case 6:try{t&&!t.done&&(o=r.return)&&o.call(r)}finally{if(a)throw a.error}return[7];case 7:return[2]}}))}function jr(e){e.mode==xr.Menu?requestAnimationFrame((function(){return function(e){var r,t;(function(e){var r,t,n=[];try{for(var a=He(e.menu.asteroids.entries()),o=a.next();!o.done;o=a.next()){var i=ze(o.value,2),s=i[0],l=i[1];M(e.menu.camera.eye,l.obj.pos())>34&&n.push(s)}}catch(e){r={error:e}}finally{try{o&&!o.done&&(t=a.return)&&t.call(a)}finally{if(r)throw r.error}}for(var u=n.length-1;u>=0;u--)e.menu.asteroids.splice(n[u],1)})(e),function(e){for(var r=e.menu.camera;e.menu.asteroids.length<64;){var t=We(r.forward,yr),n=Je(w(o(),t,-1),dr);x(t,r.eye,t,33),w(n,n,Ye.apply(void 0,Ge([],ze(mr),!1)));var a=new Sr(e.gl,1,n);a.velocity=n,a.obj.translate(t),e.menu.asteroids.push(a)}}(e);try{for(var n=He(e.menu.asteroids),a=n.next();!a.done;a=n.next()){var i=a.value;i.obj.translate(i.velocity);var s=ae(ee(),i.rotation);re(i.obj.vertexTransform,i.obj.vertexTransform,s)}}catch(e){r={error:e}}finally{try{a&&!a.done&&(t=n.return)&&t.call(n)}finally{if(r)throw r.error}}e.inputs.keyboard.pressed.has("KeyB")&&e.menu.moveModeDebouncer.try((function(){e.menu.movingCamera?(document.exitPointerLock(),e.menu.movingCamera=!1):(Nr.requestPointerLock(),e.menu.movingCamera=!0)})),e.menu.movingCamera&&Or(e.inputs.keyboard,e.menu.camera),Oe(e.gl,function(e){var r,t,n,a,o;return Ke(this,(function(i){switch(i.label){case 0:i.trys.push([0,5,6,7]),r=He(e.menu.suns),t=r.next(),i.label=1;case 1:return t.done?[3,4]:[4,t.value.pos()];case 2:i.sent(),i.label=3;case 3:return t=r.next(),[3,1];case 4:return[3,7];case 5:return n=i.sent(),a={error:n},[3,7];case 6:try{t&&!t.done&&(o=r.return)&&o.call(r)}finally{if(a)throw a.error}return[7];case 7:return[2]}}))}(e),function(e){var r,t,n,a,o;return Ke(this,(function(i){switch(i.label){case 0:i.trys.push([0,5,6,7]),r=He(e.menu.asteroids),t=r.next(),i.label=1;case 1:return t.done?[3,4]:[4,t.value.obj];case 2:i.sent(),i.label=3;case 3:return t=r.next(),[3,1];case 4:return[3,7];case 5:return n=i.sent(),a={error:n},[3,7];case 6:try{t&&!t.done&&(o=r.return)&&o.call(r)}finally{if(a)throw a.error}return[7];case 7:return[5,He(e.menu.suns)];case 8:return i.sent(),[2]}}))}(e),[],e.shaderInfo,e.menu.camera),jr(e)}(e)})):e.mode==xr.Pause?requestAnimationFrame((function(){return function(e){e.inputs.keyboard.pressed.has("KeyP")&&e.inputs.pauseDebouncer.try((function(){return Dr(e)})),Oe(e.gl,Lr(e),Er(e),Fr(e),e.shaderInfo,e.play.camera),jr(e)}(e)})):e.mode==xr.Play?requestAnimationFrame((function(){return function(e){(function(e){if(null!=e.play.levelFinishedAt){if(e.play.ticks-e.play.levelFinishedAt<30)return;_r(e,e.play.level+1)}e.play.numAsteroids.every((function(e){return 0==e}))&&(e.play.levelFinishedAt=e.play.ticks)})(e),function(e){var r=e.inputs.keyboard;e.inputs.mouseDown&&e.play.ship.tryFire(e),r.pressed.has("KeyP")&&e.inputs.pauseDebouncer.try((function(){return kr(e)})),r.pressed.has("KeyE")&&e.play.ship.rollRight(fr),r.pressed.has("KeyQ")&&e.play.ship.rollRight(-fr),r.pressed.has("KeyW")?e.play.ship.setThrottle(1):e.play.ship.setThrottle(0),r.pressed.has("Space")&&e.play.ship.tryFire(e)}(e),function(e){var r=navigator.getGamepads()[e.inputs.gamepad];if(null!=r){e.play.ship.pitchUp(.003*r.axes[1]),e.play.ship.yawLeft(-.003*r.axes[0]),e.play.ship.rollRight(.003*r.axes[2]),e.play.ship.setThrottle(r.buttons[7].value),(r.buttons[5].pressed||r.buttons[0].pressed)&&e.play.ship.tryFire(e),console.log(r)}}(e),function(e){var r,t,n=[];try{for(var a=He(e.play.suns.entries()),o=a.next();!o.done;o=a.next()){var i=ze(o.value,2),s=i[0],l=i[1];M(e.play.ship.obj.pos(),l.pos())>34&&n.push(s)}}catch(e){r={error:e}}finally{try{o&&!o.done&&(t=a.return)&&t.call(a)}finally{if(r)throw r.error}}for(var u=n.length-1;u>=0;u--)e.play.suns.splice(n[u],1)}(e),function(e){var r,t,n,a,o,i,s=[[],[]];try{for(var l=He(e.play.tieredAsteroids.entries()),u=l.next();!u.done;u=l.next()){var c=ze(u.value,2),f=c[0],h=c[1];try{for(var p=(n=void 0,He(h.entries())),d=p.next();!d.done;d=p.next()){var y=ze(d.value,2),m=y[0],v=y[1];M(e.play.ship.obj.pos(),v.obj.pos())>34&&s[f].push(m)}}catch(e){n={error:e}}finally{try{d&&!d.done&&(a=p.return)&&a.call(p)}finally{if(n)throw n.error}}}}catch(e){r={error:e}}finally{try{u&&!u.done&&(t=l.return)&&t.call(l)}finally{if(r)throw r.error}}try{for(var g=He(s.entries()),b=g.next();!b.done;b=g.next())for(var w=ze(b.value,2),x=(f=w[0],w[1]),T=x.length-1;T>=0;T--)e.play.tieredAsteroids[f].splice(x[T],1)}catch(e){o={error:e}}finally{try{b&&!b.done&&(i=g.return)&&i.call(g)}finally{if(o)throw o.error}}}(e),function(e){for(;e.play.missiles.length>0&&e.play.ticks-e.play.missiles[0].birth>hr;)e.play.missiles.shift()}(e),function(e){for(;e.play.suns.length<4;){var r=new Ve(e.gl,we),t=void 0;x(t=s(e.play.ship.velocity)<1e-10?k(o()):Je(E(o(),e.play.ship.velocity),lr),e.play.ship.obj.pos(),t,33),r.translate(t),e.play.suns.push(r)}}(e),function(e){for(var r=0;r<2;r++)for(;e.play.tieredAsteroids[r].length=0;p--)e.play.missiles.splice(o[p],1)}(e),function(e){var r,t,n,a,i=[];try{for(var l=He(Pr(e)),u=l.next();!u.done;u=l.next()){var c=u.value;try{for(var f=(n=void 0,He(e.play.missiles.entries())),p=f.next();!p.done;p=f.next()){var d=ze(p.value,2),y=d[0],m=d[1];if(M(c.obj.pos(),m.obj.pos())<=c.radius){i.push(y),c.damage();var v=4/3*Math.PI*Math.pow(c.radius,3)*1,g=.4*v*Math.pow(c.radius,2),b=h(o(),m.obj.pos(),c.obj.pos()),w=s(b);E(b,b);var T=Math.abs(F(b,m.velocity)),S=x(o(),m.velocity,b,-T);x(c.velocity,c.velocity,b,.3/v*-T);var A=L(o(),b,S);E(A,A);var P=w*s(S)*.3,j=le(se(),A,P/g);ue(c.rotation,c.rotation,j)}}}catch(e){n={error:e}}finally{try{p&&!p.done&&(a=f.return)&&a.call(f)}finally{if(n)throw n.error}}}}catch(e){r={error:e}}finally{try{u&&!u.done&&(t=l.return)&&t.call(l)}finally{if(r)throw r.error}}for(var B=i.length-1;B>=0;B--)e.play.missiles.splice(i[B],1)}(e),function(e){for(var r,t=0;t<2;t++)for(var n=e.play.tieredAsteroids[t].length-1;n>=0;n--){var a=e.play.tieredAsteroids[t][n];if(a.health<=0){if(t+1<2){var o=a.split(e.gl);(r=e.play.tieredAsteroids[t+1]).push.apply(r,Ge([],ze(o),!1)),e.play.numAsteroids[t+1]+=o.length}e.play.tieredAsteroids[t].splice(n,1),e.play.numAsteroids[t]-=1,e.play.score+=rr[t],Ir(e)}}}(e),function(e){x(e.play.ship.velocity,e.play.ship.velocity,e.play.ship.forward,.001*e.play.ship.throttle.get())}(e),function(e){e.play.ship.obj.translate(e.play.ship.velocity)}(e),function(e){var r,t;try{for(var n=He(e.play.missiles),a=n.next();!a.done;a=n.next()){var o=a.value;o.obj.translate(o.velocity)}}catch(e){r={error:e}}finally{try{a&&!a.done&&(t=n.return)&&t.call(n)}finally{if(r)throw r.error}}}(e),function(e){var r,t;try{for(var n=He(Pr(e)),a=n.next();!a.done;a=n.next()){var i=a.value;i.obj.translate(i.velocity);var s=i.obj.pos();i.obj.translate(w(o(),s,-1));var l=ae(ee(),i.rotation);re(i.obj.vertexTransform,l,i.obj.vertexTransform),i.obj.translate(s)}}catch(e){r={error:e}}finally{try{a&&!a.done&&(t=n.return)&&t.call(n)}finally{if(r)throw r.error}}}(e),null==e.play.levelFinishedAt&&(function(e){var r,t,n,a;try{for(var o=He(Pr(e)),i=o.next();!i.done;i=o.next()){var s=i.value;try{for(var l=(n=void 0,He(e.play.ship.collisionPoints())),u=l.next();!u.done;u=l.next()){var c=u.value;M(s.obj.pos(),c)<=.85*s.radius&&Rr(e)}}catch(e){n={error:e}}finally{try{u&&!u.done&&(a=l.return)&&a.call(l)}finally{if(n)throw n.error}}}}catch(e){r={error:e}}finally{try{i&&!i.done&&(t=o.return)&&t.call(o)}finally{if(r)throw r.error}}}(e),function(e){var r,t,n,a;try{for(var o=He(e.play.suns),i=o.next();!i.done;i=o.next()){var s=i.value;try{for(var l=(n=void 0,He(e.play.ship.collisionPoints())),u=l.next();!u.done;u=l.next())Ar(s,u.value)&&Rr(e)}catch(e){n={error:e}}finally{try{u&&!u.done&&(a=l.return)&&a.call(l)}finally{if(n)throw n.error}}}}catch(e){r={error:e}}finally{try{i&&!i.done&&(t=o.return)&&t.call(o)}finally{if(r)throw r.error}}}(e)),Ur(e),function(e){e.play.camera=e.play.ship.camera(e.play.lastCameraPosition),e.play.lastCameraPosition=e.play.ship.eye()}(e),function(e){var r=e.play.ship;r.throttle.step();var t=r.throttle.get();!function(e,r,t){var n=t[0],a=t[1],o=t[2];e[0]=r[0]*n,e[1]=r[1]*n,e[2]=r[2]*n,e[3]=r[3]*n,e[4]=r[4]*a,e[5]=r[5]*a,e[6]=r[6]*a,e[7]=r[7]*a,e[8]=r[8]*o,e[9]=r[9]*o,e[10]=r[10]*o,e[11]=r[11]*o,e[12]=r[12],e[13]=r[13],e[14]=r[14],e[15]=r[15]}(r.flame.vertexTransform,r.obj.vertexTransform,l(1,t,1));var n=.006*Math.sin(.707106781187*e.play.ticks),a=.004*Math.sin(.809015*e.play.ticks);te(r.flame.vertexTransform,r.flame.vertexTransform,n,l(1,0,0)),te(r.flame.vertexTransform,r.flame.vertexTransform,a,l(0,0,1)),r.thrusterSfx.volume=1*t}(e),function(e){var r,n,a,i,s=e.play.ship,l=(r=o(),n=s.worldRotation,a=2*Math.acos(n[3]),(i=Math.sin(a/2))>t?(r[0]=n[0]/i,r[1]=n[1]/i,r[2]=n[2]/i):(r[0]=1,r[1]=0,r[2]=0),a),u=(Math.log(l)-Math.log(1e-10))/(Math.log(.01)-Math.log(1e-10)),c=.925*(u=Qe(u,[0,1]));(function(e,r,t){e[0]=r[0]*t,e[1]=r[1]*t,e[2]=r[2]*t,e[3]=r[3]*t})(s.worldRotation,s.worldRotation,c),function(e,r){var t=r[0],n=r[1],a=r[2];e[0]=t,e[1]=n,e[2]=a,e[3]=Math.sqrt(Math.abs(1-t*t-n*n-a*a))}(s.worldRotation,s.worldRotation),V(s.forward,s.forward,s.worldRotation),V(s.up,s.up,s.worldRotation),V(s.right,s.right,s.worldRotation);var f=s.obj.pos();s.obj.translate(w(o(),f,-1));var h=ae(ee(),s.worldRotation);re(s.obj.vertexTransform,h,s.obj.vertexTransform),s.obj.translate(f)}(e),e.inputs.keyboard.pressed.has("KeyB")&&e.freecam.freecamModeDebouncer.try((function(){return function(e){e.freecam.camera.sync(e.play.ship,e.play.camera),e.mode=xr.Freecam}(e)})),e.play.ticks+=1,Oe(e.gl,Lr(e),Er(e),Fr(e),e.shaderInfo,e.play.camera),jr(e)}(e)})):e.mode==xr.Freecam&&requestAnimationFrame((function(){return function(e){var r=e.inputs.keyboard;Or(r,e.freecam.camera),r.pressed.has("ArrowLeft")&&e.freecam.generalDebouncer.try((function(){e.play.level=Math.max(1,e.play.level-1),e.play.numAsteroids=gr(e.play.level),Cr(e)})),r.pressed.has("ArrowRight")&&e.freecam.generalDebouncer.try((function(){e.play.level+=1,e.play.numAsteroids=gr(e.play.level),Cr(e)})),r.pressed.has("KeyF")&&e.freecam.generalDebouncer.try((function(){e.freecam.fog=!e.freecam.fog})),r.pressed.has("KeyC")&&e.freecam.generalDebouncer.try((function(){e.freecam.showShipCollisions=!e.freecam.showShipCollisions})),r.pressed.has("KeyB")&&e.freecam.freecamModeDebouncer.try((function(){return function(e){e.mode=xr.Play}(e)})),Oe(e.gl,Lr(e),Er(e),Fr(e),e.shaderInfo,e.freecam.camera,{fog:e.freecam.fog}),jr(e)}(e)}))}function Br(e){qr.time.hidden=!0,qr.score.hidden=!0,qr.level.hidden=!0,qr.mainText.innerHTML="Asteroids",qr.mainText.hidden=!1,qr.menuButton.innerHTML="Start",qr.menuButton.hidden=!1,qr.menuButton.onclick=function(){_r(e,1)},qr.menuButton2.hidden=!0,e.mode=xr.Menu}function Rr(e){qr.time.hidden=!1,qr.score.hidden=!1,qr.level.hidden=!1,qr.mainText.innerHTML="Game Over",qr.mainText.hidden=!1,qr.menuButton.innerHTML="Restart",qr.menuButton.hidden=!1,qr.menuButton.onclick=function(){_r(e,1)},qr.menuButton2.innerHTML="Quit",qr.menuButton2.hidden=!1,qr.menuButton2.onclick=function(){Br(e)},e.play.ship.thrusterSfx.pause(),document.exitPointerLock(),e.mode=xr.Pause}function kr(e){qr.score.hidden=!1,qr.time.hidden=!1,qr.level.hidden=!1,qr.mainText.innerHTML="Pause",qr.mainText.hidden=!1,qr.menuButton.innerHTML="Unpause",qr.menuButton.hidden=!1,qr.menuButton.onclick=function(){Dr(e)},qr.menuButton2.innerHTML="Quit",qr.menuButton2.hidden=!1,qr.menuButton2.onclick=function(){Br(e)},wr.pause(),e.play.ship.thrusterSfx.pause(),document.exitPointerLock(),e.mode=xr.Pause}function Dr(e){qr.time.hidden=!1,qr.score.hidden=!1,qr.level.hidden=!1,qr.mainText.hidden=!0,qr.menuButton.hidden=!0,qr.menuButton2.hidden=!0,wr.play(),Nr.requestPointerLock(),e.mode=xr.Play}function _r(e,r){var t,n;qr.time.hidden=!1,qr.score.hidden=!1,qr.level.hidden=!1,qr.mainText.hidden=!0,qr.menuButton.hidden=!0,qr.menuButton2.hidden=!0,1==r&&(wr.play(),wr.currentTime=0),Nr.requestPointerLock(),e.mode=xr.Play,e.play.ship=new Tr(e.gl),e.play.missiles=[],e.play.tieredAsteroids=[[],[]],e.play.numAsteroids=gr(r),e.play.asteroidSpeed=function(e){return[.01+.005*e,.09+.03*e]}(r),e.play.suns=[],e.play.score=0,e.play.ticks=0,e.play.lastCameraPosition=e.play.ship.eye(),e.play.camera=e.play.ship.camera(e.play.ship.eye()),e.play.level=r,e.play.levelFinishedAt=null,Ir(e),Ur(e),Cr(e);try{for(var a=He(e.play.numAsteroids.entries()),i=a.next();!i.done;i=a.next())for(var s=ze(i.value,2),l=s[0],u=s[1],c=0;cpr&&(r.moveSpeed-=pr)}var Nr=document.getElementById("game-canvas"),qr={score:document.getElementById("score-text"),time:document.getElementById("time-text"),level:document.getElementById("level-text"),menuButton:document.getElementById("menu-button"),menuButton2:document.getElementById("menu-button2"),mainText:document.getElementById("main-text")};!function(){var e=function(e){var r=e.getContext("webgl");if(null==r)throw"unable to create gl context -- is your browser gl ready?";return r.clearDepth(1),r.clearColor.apply(r,ke(ke([],Re(be),!1),[1],!1)),r.enable(r.DEPTH_TEST),r}(Nr),r=function(e){var r=new qe;r.register();var t=new Tr(e),n={gl:e,shaderInfo:Ce(e),mode:xr.Menu,inputs:{keyboard:r,gamepad:0,pauseDebouncer:new Ne(Date.now,vr),mouseDown:!1},play:{ship:t,missiles:[],tieredAsteroids:[[],[]],numAsteroids:[0,0],suns:[],ticks:0,score:0,lastCameraPosition:t.eye(),camera:t.camera(t.eye()),asteroidSpeed:[0,0],level:0,levelFinishedAt:null},freecam:{camera:new Vr({eye:l(0,0,-5),lookAt:l(0,0,1),lookUp:l(0,1,0),width:Nr.width,height:Nr.height,fovDegrees:cr[0],near:.03125,far:64,moveSpeed:.04}),freecamModeDebouncer:new Ne(Date.now,vr),generalDebouncer:new Ne(Date.now,vr),fog:!0,showShipCollisions:!1},menu:{camera:new Vr({eye:l(0,0,0),lookAt:l(0,0,1),lookUp:l(0,1,0),width:Nr.width,height:Nr.height,fovDegrees:cr[0],near:Ze,far:32,moveSpeed:.04}),asteroids:[],suns:[],movingCamera:!1,moveModeDebouncer:new Ne(Date.now,vr)}};return function(e){var r=e.menu.camera;r.yawLeft(Xe(-30)),r.pitchUp(Xe(-20));var t=new Ve(e.gl,we);t.translate(l(3.5,-4,10)),e.menu.suns.push(t);var n=new Ve(e.gl,we);n.translate(x(o(),r.eye,r.forward,-4)),e.menu.suns.push(n)}(n),n}(e);function t(e){r.mode==xr.Freecam?(r.freecam.camera.yawLeft(-.002*e.movementX),r.freecam.camera.pitchUp(-.002*e.movementY)):r.mode==xr.Play?(r.play.ship.yawLeft(-1e-4*e.movementX),r.play.ship.pitchUp(-1e-4*e.movementY)):r.mode==xr.Menu&&(r.menu.camera.yawLeft(-.002*e.movementX),r.menu.camera.pitchUp(-.002*e.movementY))}window.addEventListener("blur",(function(){r.mode==xr.Play&&kr(r),wr.pause()})),qr.menuButton.onclick=function(){_r(r,1)},Nr.onclick=function(){r.mode!=xr.Play&&r.mode!=xr.Freecam||Nr.requestPointerLock()},document.addEventListener("pointerlockchange",(function(){document.pointerLockElement===Nr?document.addEventListener("mousemove",t):document.removeEventListener("mousemove",t)})),document.addEventListener("mousedown",(function(){r.inputs.mouseDown=!0})),document.addEventListener("mouseup",(function(){r.inputs.mouseDown=!1})),jr(r)}()})(); +//# sourceMappingURL=data:application/json;charset=utf-8;base64,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UWhGLEVBQUtvRCxNQUFRakYsR0FBUzBLLFNBQ3REbkksR0FBTzZELHNCQUdYcEosU0FBU0MsaUJBQWlCLHFCQUFxQixXQUN6Q0QsU0FBUzJRLHFCQUF1QnBMLEdBQ2xDdkYsU0FBU0MsaUJBQWlCLFlBQWFzUSxHQUV2Q3ZRLFNBQVM0USxvQkFBb0IsWUFBYUwsTUFlOUN2USxTQUFTQyxpQkFBaUIsYUFBYSxXQUNyQzRFLEVBQUtpRSxPQUFPbUIsV0FBWSxLQUUxQmpLLFNBQVNDLGlCQUFpQixXQUFXLFdBQ25DNEUsRUFBS2lFLE9BQU9tQixXQUFZLEtBRzFCakMsR0FBa0JuRCxHQUdwQmdNLEkiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vd2VicGFjay9ib290c3RyYXAiLCJ3ZWJwYWNrOi8vL3dlYnBhY2svcnVudGltZS9kZWZpbmUgcHJvcGVydHkgZ2V0dGVycyIsIndlYnBhY2s6Ly8vd2VicGFjay9ydW50aW1lL2hhc093blByb3BlcnR5IHNob3J0aGFuZCIsIndlYnBhY2s6Ly8vd2VicGFjay9ydW50aW1lL21ha2UgbmFtZXNwYWNlIG9iamVjdCIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvZ2wtbWF0cml4L2VzbS9jb21tb24uanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2dsLW1hdHJpeC9lc20vdmVjMy5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvZ2wtbWF0cml4L2VzbS9tYXQ0LmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9nbC1tYXRyaXgvZXNtL3F1YXQuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2dsLW1hdHJpeC9lc20vdmVjNC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvZ2wtbWF0cml4L2VzbS9tYXQzLmpzIiwid2VicGFjazovLy8uL3NyYy9tb2RlbHMudHMiLCJ3ZWJwYWNrOi8vLy4vc3JjL3JlbmRlci50cyIsIndlYnBhY2s6Ly8vLi9zcmMvaW5wdXRzLnRzIiwid2VicGFjazovLy8uL3NyYy9nYW1lLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8vIFRoZSByZXF1aXJlIHNjb3BlXG52YXIgX193ZWJwYWNrX3JlcXVpcmVfXyA9IHt9O1xuXG4iLCIvLyBkZWZpbmUgZ2V0dGVyIGZ1bmN0aW9ucyBmb3IgaGFybW9ueSBleHBvcnRzXG5fX3dlYnBhY2tfcmVxdWlyZV9fLmQgPSAoZXhwb3J0cywgZGVmaW5pdGlvbikgPT4ge1xuXHRmb3IodmFyIGtleSBpbiBkZWZpbml0aW9uKSB7XG5cdFx0aWYoX193ZWJwYWNrX3JlcXVpcmVfXy5vKGRlZmluaXRpb24sIGtleSkgJiYgIV9fd2VicGFja19yZXF1aXJlX18ubyhleHBvcnRzLCBrZXkpKSB7XG5cdFx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywga2V5LCB7IGVudW1lcmFibGU6IHRydWUsIGdldDogZGVmaW5pdGlvbltrZXldIH0pO1xuXHRcdH1cblx0fVxufTsiLCJfX3dlYnBhY2tfcmVxdWlyZV9fLm8gPSAob2JqLCBwcm9wKSA9PiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwgcHJvcCkpIiwiLy8gZGVmaW5lIF9fZXNNb2R1bGUgb24gZXhwb3J0c1xuX193ZWJwYWNrX3JlcXVpcmVfXy5yID0gKGV4cG9ydHMpID0+IHtcblx0aWYodHlwZW9mIFN5bWJvbCAhPT0gJ3VuZGVmaW5lZCcgJiYgU3ltYm9sLnRvU3RyaW5nVGFnKSB7XG5cdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFN5bWJvbC50b1N0cmluZ1RhZywgeyB2YWx1ZTogJ01vZHVsZScgfSk7XG5cdH1cblx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcbn07IiwiLyoqXG4gKiBDb21tb24gdXRpbGl0aWVzXG4gKiBAbW9kdWxlIGdsTWF0cml4XG4gKi9cbi8vIENvbmZpZ3VyYXRpb24gQ29uc3RhbnRzXG5leHBvcnQgdmFyIEVQU0lMT04gPSAwLjAwMDAwMTtcbmV4cG9ydCB2YXIgQVJSQVlfVFlQRSA9IHR5cGVvZiBGbG9hdDMyQXJyYXkgIT09ICd1bmRlZmluZWQnID8gRmxvYXQzMkFycmF5IDogQXJyYXk7XG5leHBvcnQgdmFyIFJBTkRPTSA9IE1hdGgucmFuZG9tO1xuLyoqXG4gKiBTZXRzIHRoZSB0eXBlIG9mIGFycmF5IHVzZWQgd2hlbiBjcmVhdGluZyBuZXcgdmVjdG9ycyBhbmQgbWF0cmljZXNcbiAqXG4gKiBAcGFyYW0ge0Zsb2F0MzJBcnJheUNvbnN0cnVjdG9yIHwgQXJyYXlDb25zdHJ1Y3Rvcn0gdHlwZSBBcnJheSB0eXBlLCBzdWNoIGFzIEZsb2F0MzJBcnJheSBvciBBcnJheVxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBzZXRNYXRyaXhBcnJheVR5cGUodHlwZSkge1xuICBBUlJBWV9UWVBFID0gdHlwZTtcbn1cbnZhciBkZWdyZWUgPSBNYXRoLlBJIC8gMTgwO1xuLyoqXG4gKiBDb252ZXJ0IERlZ3JlZSBUbyBSYWRpYW5cbiAqXG4gKiBAcGFyYW0ge051bWJlcn0gYSBBbmdsZSBpbiBEZWdyZWVzXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIHRvUmFkaWFuKGEpIHtcbiAgcmV0dXJuIGEgKiBkZWdyZWU7XG59XG4vKipcbiAqIFRlc3RzIHdoZXRoZXIgb3Igbm90IHRoZSBhcmd1bWVudHMgaGF2ZSBhcHByb3hpbWF0ZWx5IHRoZSBzYW1lIHZhbHVlLCB3aXRoaW4gYW4gYWJzb2x1dGVcbiAqIG9yIHJlbGF0aXZlIHRvbGVyYW5jZSBvZiBnbE1hdHJpeC5FUFNJTE9OIChhbiBhYnNvbHV0ZSB0b2xlcmFuY2UgaXMgdXNlZCBmb3IgdmFsdWVzIGxlc3NcbiAqIHRoYW4gb3IgZXF1YWwgdG8gMS4wLCBhbmQgYSByZWxhdGl2ZSB0b2xlcmFuY2UgaXMgdXNlZCBmb3IgbGFyZ2VyIHZhbHVlcylcbiAqXG4gKiBAcGFyYW0ge051bWJlcn0gYSBUaGUgZmlyc3QgbnVtYmVyIHRvIHRlc3QuXG4gKiBAcGFyYW0ge051bWJlcn0gYiBUaGUgc2Vjb25kIG51bWJlciB0byB0ZXN0LlxuICogQHJldHVybnMge0Jvb2xlYW59IFRydWUgaWYgdGhlIG51bWJlcnMgYXJlIGFwcHJveGltYXRlbHkgZXF1YWwsIGZhbHNlIG90aGVyd2lzZS5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gZXF1YWxzKGEsIGIpIHtcbiAgcmV0dXJuIE1hdGguYWJzKGEgLSBiKSA8PSBFUFNJTE9OICogTWF0aC5tYXgoMS4wLCBNYXRoLmFicyhhKSwgTWF0aC5hYnMoYikpO1xufVxuaWYgKCFNYXRoLmh5cG90KSBNYXRoLmh5cG90ID0gZnVuY3Rpb24gKCkge1xuICB2YXIgeSA9IDAsXG4gICAgICBpID0gYXJndW1lbnRzLmxlbmd0aDtcblxuICB3aGlsZSAoaS0tKSB7XG4gICAgeSArPSBhcmd1bWVudHNbaV0gKiBhcmd1bWVudHNbaV07XG4gIH1cblxuICByZXR1cm4gTWF0aC5zcXJ0KHkpO1xufTsiLCJpbXBvcnQgKiBhcyBnbE1hdHJpeCBmcm9tIFwiLi9jb21tb24uanNcIjtcbi8qKlxuICogMyBEaW1lbnNpb25hbCBWZWN0b3JcbiAqIEBtb2R1bGUgdmVjM1xuICovXG5cbi8qKlxuICogQ3JlYXRlcyBhIG5ldywgZW1wdHkgdmVjM1xuICpcbiAqIEByZXR1cm5zIHt2ZWMzfSBhIG5ldyAzRCB2ZWN0b3JcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlKCkge1xuICB2YXIgb3V0ID0gbmV3IGdsTWF0cml4LkFSUkFZX1RZUEUoMyk7XG5cbiAgaWYgKGdsTWF0cml4LkFSUkFZX1RZUEUgIT0gRmxvYXQzMkFycmF5KSB7XG4gICAgb3V0WzBdID0gMDtcbiAgICBvdXRbMV0gPSAwO1xuICAgIG91dFsyXSA9IDA7XG4gIH1cblxuICByZXR1cm4gb3V0O1xufVxuLyoqXG4gKiBDcmVhdGVzIGEgbmV3IHZlYzMgaW5pdGlhbGl6ZWQgd2l0aCB2YWx1ZXMgZnJvbSBhbiBleGlzdGluZyB2ZWN0b3JcbiAqXG4gKiBAcGFyYW0ge1JlYWRvbmx5VmVjM30gYSB2ZWN0b3IgdG8gY2xvbmVcbiAqIEByZXR1cm5zIHt2ZWMzfSBhIG5ldyAzRCB2ZWN0b3JcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gY2xvbmUoYSkge1xuICB2YXIgb3V0ID0gbmV3IGdsTWF0cml4LkFSUkFZX1RZUEUoMyk7XG4gIG91dFswXSA9IGFbMF07XG4gIG91dFsxXSA9IGFbMV07XG4gIG91dFsyXSA9IGFbMl07XG4gIHJldHVybiBvdXQ7XG59XG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIGxlbmd0aCBvZiBhIHZlYzNcbiAqXG4gKiBAcGFyYW0ge1JlYWRvbmx5VmVjM30gYSB2ZWN0b3IgdG8gY2FsY3VsYXRlIGxlbmd0aCBvZlxuICogQHJldHVybnMge051bWJlcn0gbGVuZ3RoIG9mIGFcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gbGVuZ3RoKGEpIHtcbiAgdmFyIHggPSBhWzBdO1xuICB2YXIgeSA9IGFbMV07XG4gIHZhciB6ID0gYVsyXTtcbiAgcmV0dXJuIE1hdGguaHlwb3QoeCwgeSwgeik7XG59XG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgdmVjMyBpbml0aWFsaXplZCB3aXRoIHRoZSBnaXZlbiB2YWx1ZXNcbiAqXG4gKiBAcGFyYW0ge051bWJlcn0geCBYIGNvbXBvbmVudFxuICogQHBhcmFtIHtOdW1iZXJ9IHkgWSBjb21wb25lbnRcbiAqIEBwYXJhbSB7TnVtYmVyfSB6IFogY29tcG9uZW50XG4gKiBAcmV0dXJucyB7dmVjM30gYSBuZXcgM0QgdmVjdG9yXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGZyb21WYWx1ZXMoeCwgeSwgeikge1xuICB2YXIgb3V0ID0gbmV3IGdsTWF0cml4LkFSUkFZX1RZUEUoMyk7XG4gIG91dFswXSA9IHg7XG4gIG91dFsxXSA9IHk7XG4gIG91dFsyXSA9IHo7XG4gIHJldHVybiBvdXQ7XG59XG4vKipcbiAqIENvcHkgdGhlIHZhbHVlcyBmcm9tIG9uZSB2ZWMzIHRvIGFub3RoZXJcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHtSZWFkb25seVZlYzN9IGEgdGhlIHNvdXJjZSB2ZWN0b3JcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gY29weShvdXQsIGEpIHtcbiAgb3V0WzBdID0gYVswXTtcbiAgb3V0WzFdID0gYVsxXTtcbiAgb3V0WzJdID0gYVsyXTtcbiAgcmV0dXJuIG91dDtcbn1cbi8qKlxuICogU2V0IHRoZSBjb21wb25lbnRzIG9mIGEgdmVjMyB0byB0aGUgZ2l2ZW4gdmFsdWVzXG4gKlxuICogQHBhcmFtIHt2ZWMzfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7TnVtYmVyfSB4IFggY29tcG9uZW50XG4gKiBAcGFyYW0ge051bWJlcn0geSBZIGNvbXBvbmVudFxuICogQHBhcmFtIHtOdW1iZXJ9IHogWiBjb21wb25lbnRcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gc2V0KG91dCwgeCwgeSwgeikge1xuICBvdXRbMF0gPSB4O1xuICBvdXRbMV0gPSB5O1xuICBvdXRbMl0gPSB6O1xuICByZXR1cm4gb3V0O1xufVxuLyoqXG4gKiBBZGRzIHR3byB2ZWMzJ3NcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHtSZWFkb25seVZlYzN9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7UmVhZG9ubHlWZWMzfSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge3ZlYzN9IG91dFxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBhZGQob3V0LCBhLCBiKSB7XG4gIG91dFswXSA9IGFbMF0gKyBiWzBdO1xuICBvdXRbMV0gPSBhWzFdICsgYlsxXTtcbiAgb3V0WzJdID0gYVsyXSArIGJbMl07XG4gIHJldHVybiBvdXQ7XG59XG4vKipcbiAqIFN1YnRyYWN0cyB2ZWN0b3IgYiBmcm9tIHZlY3RvciBhXG4gKlxuICogQHBhcmFtIHt2ZWMzfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7UmVhZG9ubHlWZWMzfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge1JlYWRvbmx5VmVjM30gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gc3VidHJhY3Qob3V0LCBhLCBiKSB7XG4gIG91dFswXSA9IGFbMF0gLSBiWzBdO1xuICBvdXRbMV0gPSBhWzFdIC0gYlsxXTtcbiAgb3V0WzJdID0gYVsyXSAtIGJbMl07XG4gIHJldHVybiBvdXQ7XG59XG4vKipcbiAqIE11bHRpcGxpZXMgdHdvIHZlYzMnc1xuICpcbiAqIEBwYXJhbSB7dmVjM30gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge1JlYWRvbmx5VmVjM30gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHtSZWFkb25seVZlYzN9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7dmVjM30gb3V0XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIG11bHRpcGx5KG91dCwgYSwgYikge1xuICBvdXRbMF0gPSBhWzBdICogYlswXTtcbiAgb3V0WzFdID0gYVsxXSAqIGJbMV07XG4gIG91dFsyXSA9IGFbMl0gKiBiWzJdO1xuICByZXR1cm4gb3V0O1xufVxuLyoqXG4gKiBEaXZpZGVzIHR3byB2ZWMzJ3NcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHtSZWFkb25seVZlYzN9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7UmVhZG9ubHlWZWMzfSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge3ZlYzN9IG91dFxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBkaXZpZGUob3V0LCBhLCBiKSB7XG4gIG91dFswXSA9IGFbMF0gLyBiWzBdO1xuICBvdXRbMV0gPSBhWzFdIC8gYlsxXTtcbiAgb3V0WzJdID0gYVsyXSAvIGJbMl07XG4gIHJldHVybiBvdXQ7XG59XG4vKipcbiAqIE1hdGguY2VpbCB0aGUgY29tcG9uZW50cyBvZiBhIHZlYzNcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHtSZWFkb25seVZlYzN9IGEgdmVjdG9yIHRvIGNlaWxcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gY2VpbChvdXQsIGEpIHtcbiAgb3V0WzBdID0gTWF0aC5jZWlsKGFbMF0pO1xuICBvdXRbMV0gPSBNYXRoLmNlaWwoYVsxXSk7XG4gIG91dFsyXSA9IE1hdGguY2VpbChhWzJdKTtcbiAgcmV0dXJuIG91dDtcbn1cbi8qKlxuICogTWF0aC5mbG9vciB0aGUgY29tcG9uZW50cyBvZiBhIHZlYzNcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHtSZWFkb25seVZlYzN9IGEgdmVjdG9yIHRvIGZsb29yXG4gKiBAcmV0dXJucyB7dmVjM30gb3V0XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGZsb29yKG91dCwgYSkge1xuICBvdXRbMF0gPSBNYXRoLmZsb29yKGFbMF0pO1xuICBvdXRbMV0gPSBNYXRoLmZsb29yKGFbMV0pO1xuICBvdXRbMl0gPSBNYXRoLmZsb29yKGFbMl0pO1xuICByZXR1cm4gb3V0O1xufVxuLyoqXG4gKiBSZXR1cm5zIHRoZSBtaW5pbXVtIG9mIHR3byB2ZWMzJ3NcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHtSZWFkb25seVZlYzN9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7UmVhZG9ubHlWZWMzfSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge3ZlYzN9IG91dFxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBtaW4ob3V0LCBhLCBiKSB7XG4gIG91dFswXSA9IE1hdGgubWluKGFbMF0sIGJbMF0pO1xuICBvdXRbMV0gPSBNYXRoLm1pbihhWzFdLCBiWzFdKTtcbiAgb3V0WzJdID0gTWF0aC5taW4oYVsyXSwgYlsyXSk7XG4gIHJldHVybiBvdXQ7XG59XG4vKipcbiAqIFJldHVybnMgdGhlIG1heGltdW0gb2YgdHdvIHZlYzMnc1xuICpcbiAqIEBwYXJhbSB7dmVjM30gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge1JlYWRvbmx5VmVjM30gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHtSZWFkb25seVZlYzN9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7dmVjM30gb3V0XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIG1heChvdXQsIGEsIGIpIHtcbiAgb3V0WzBdID0gTWF0aC5tYXgoYVswXSwgYlswXSk7XG4gIG91dFsxXSA9IE1hdGgubWF4KGFbMV0sIGJbMV0pO1xuICBvdXRbMl0gPSBNYXRoLm1heChhWzJdLCBiWzJdKTtcbiAgcmV0dXJuIG91dDtcbn1cbi8qKlxuICogTWF0aC5yb3VuZCB0aGUgY29tcG9uZW50cyBvZiBhIHZlYzNcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHtSZWFkb25seVZlYzN9IGEgdmVjdG9yIHRvIHJvdW5kXG4gKiBAcmV0dXJucyB7dmVjM30gb3V0XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIHJvdW5kKG91dCwgYSkge1xuICBvdXRbMF0gPSBNYXRoLnJvdW5kKGFbMF0pO1xuICBvdXRbMV0gPSBNYXRoLnJvdW5kKGFbMV0pO1xuICBvdXRbMl0gPSBNYXRoLnJvdW5kKGFbMl0pO1xuICByZXR1cm4gb3V0O1xufVxuLyoqXG4gKiBTY2FsZXMgYSB2ZWMzIGJ5IGEgc2NhbGFyIG51bWJlclxuICpcbiAqIEBwYXJhbSB7dmVjM30gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge1JlYWRvbmx5VmVjM30gYSB0aGUgdmVjdG9yIHRvIHNjYWxlXG4gKiBAcGFyYW0ge051bWJlcn0gYiBhbW91bnQgdG8gc2NhbGUgdGhlIHZlY3RvciBieVxuICogQHJldHVybnMge3ZlYzN9IG91dFxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBzY2FsZShvdXQsIGEsIGIpIHtcbiAgb3V0WzBdID0gYVswXSAqIGI7XG4gIG91dFsxXSA9IGFbMV0gKiBiO1xuICBvdXRbMl0gPSBhWzJdICogYjtcbiAgcmV0dXJuIG91dDtcbn1cbi8qKlxuICogQWRkcyB0d28gdmVjMydzIGFmdGVyIHNjYWxpbmcgdGhlIHNlY29uZCBvcGVyYW5kIGJ5IGEgc2NhbGFyIHZhbHVlXG4gKlxuICogQHBhcmFtIHt2ZWMzfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7UmVhZG9ubHlWZWMzfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge1JlYWRvbmx5VmVjM30gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEBwYXJhbSB7TnVtYmVyfSBzY2FsZSB0aGUgYW1vdW50IHRvIHNjYWxlIGIgYnkgYmVmb3JlIGFkZGluZ1xuICogQHJldHVybnMge3ZlYzN9IG91dFxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBzY2FsZUFuZEFkZChvdXQsIGEsIGIsIHNjYWxlKSB7XG4gIG91dFswXSA9IGFbMF0gKyBiWzBdICogc2NhbGU7XG4gIG91dFsxXSA9IGFbMV0gKyBiWzFdICogc2NhbGU7XG4gIG91dFsyXSA9IGFbMl0gKyBiWzJdICogc2NhbGU7XG4gIHJldHVybiBvdXQ7XG59XG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIGV1Y2xpZGlhbiBkaXN0YW5jZSBiZXR3ZWVuIHR3byB2ZWMzJ3NcbiAqXG4gKiBAcGFyYW0ge1JlYWRvbmx5VmVjM30gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHtSZWFkb25seVZlYzN9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7TnVtYmVyfSBkaXN0YW5jZSBiZXR3ZWVuIGEgYW5kIGJcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gZGlzdGFuY2UoYSwgYikge1xuICB2YXIgeCA9IGJbMF0gLSBhWzBdO1xuICB2YXIgeSA9IGJbMV0gLSBhWzFdO1xuICB2YXIgeiA9IGJbMl0gLSBhWzJdO1xuICByZXR1cm4gTWF0aC5oeXBvdCh4LCB5LCB6KTtcbn1cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgc3F1YXJlZCBldWNsaWRpYW4gZGlzdGFuY2UgYmV0d2VlbiB0d28gdmVjMydzXG4gKlxuICogQHBhcmFtIHtSZWFkb25seVZlYzN9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7UmVhZG9ubHlWZWMzfSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge051bWJlcn0gc3F1YXJlZCBkaXN0YW5jZSBiZXR3ZWVuIGEgYW5kIGJcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gc3F1YXJlZERpc3RhbmNlKGEsIGIpIHtcbiAgdmFyIHggPSBiWzBdIC0gYVswXTtcbiAgdmFyIHkgPSBiWzFdIC0gYVsxXTtcbiAgdmFyIHogPSBiWzJdIC0gYVsyXTtcbiAgcmV0dXJuIHggKiB4ICsgeSAqIHkgKyB6ICogejtcbn1cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgc3F1YXJlZCBsZW5ndGggb2YgYSB2ZWMzXG4gKlxuICogQHBhcmFtIHtSZWFkb25seVZlYzN9IGEgdmVjdG9yIHRvIGNhbGN1bGF0ZSBzcXVhcmVkIGxlbmd0aCBvZlxuICogQHJldHVybnMge051bWJlcn0gc3F1YXJlZCBsZW5ndGggb2YgYVxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBzcXVhcmVkTGVuZ3RoKGEpIHtcbiAgdmFyIHggPSBhWzBdO1xuICB2YXIgeSA9IGFbMV07XG4gIHZhciB6ID0gYVsyXTtcbiAgcmV0dXJuIHggKiB4ICsgeSAqIHkgKyB6ICogejtcbn1cbi8qKlxuICogTmVnYXRlcyB0aGUgY29tcG9uZW50cyBvZiBhIHZlYzNcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHtSZWFkb25seVZlYzN9IGEgdmVjdG9yIHRvIG5lZ2F0ZVxuICogQHJldHVybnMge3ZlYzN9IG91dFxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBuZWdhdGUob3V0LCBhKSB7XG4gIG91dFswXSA9IC1hWzBdO1xuICBvdXRbMV0gPSAtYVsxXTtcbiAgb3V0WzJdID0gLWFbMl07XG4gIHJldHVybiBvdXQ7XG59XG4vKipcbiAqIFJldHVybnMgdGhlIGludmVyc2Ugb2YgdGhlIGNvbXBvbmVudHMgb2YgYSB2ZWMzXG4gKlxuICogQHBhcmFtIHt2ZWMzfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7UmVhZG9ubHlWZWMzfSBhIHZlY3RvciB0byBpbnZlcnRcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gaW52ZXJzZShvdXQsIGEpIHtcbiAgb3V0WzBdID0gMS4wIC8gYVswXTtcbiAgb3V0WzFdID0gMS4wIC8gYVsxXTtcbiAgb3V0WzJdID0gMS4wIC8gYVsyXTtcbiAgcmV0dXJuIG91dDtcbn1cbi8qKlxuICogTm9ybWFsaXplIGEgdmVjM1xuICpcbiAqIEBwYXJhbSB7dmVjM30gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge1JlYWRvbmx5VmVjM30gYSB2ZWN0b3IgdG8gbm9ybWFsaXplXG4gKiBAcmV0dXJucyB7dmVjM30gb3V0XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIG5vcm1hbGl6ZShvdXQsIGEpIHtcbiAgdmFyIHggPSBhWzBdO1xuICB2YXIgeSA9IGFbMV07XG4gIHZhciB6ID0gYVsyXTtcbiAgdmFyIGxlbiA9IHggKiB4ICsgeSAqIHkgKyB6ICogejtcblxuICBpZiAobGVuID4gMCkge1xuICAgIC8vVE9ETzogZXZhbHVhdGUgdXNlIG9mIGdsbV9pbnZzcXJ0IGhlcmU/XG4gICAgbGVuID0gMSAvIE1hdGguc3FydChsZW4pO1xuICB9XG5cbiAgb3V0WzBdID0gYVswXSAqIGxlbjtcbiAgb3V0WzFdID0gYVsxXSAqIGxlbjtcbiAgb3V0WzJdID0gYVsyXSAqIGxlbjtcbiAgcmV0dXJuIG91dDtcbn1cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgZG90IHByb2R1Y3Qgb2YgdHdvIHZlYzMnc1xuICpcbiAqIEBwYXJhbSB7UmVhZG9ubHlWZWMzfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge1JlYWRvbmx5VmVjM30gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHtOdW1iZXJ9IGRvdCBwcm9kdWN0IG9mIGEgYW5kIGJcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gZG90KGEsIGIpIHtcbiAgcmV0dXJuIGFbMF0gKiBiWzBdICsgYVsxXSAqIGJbMV0gKyBhWzJdICogYlsyXTtcbn1cbi8qKlxuICogQ29tcHV0ZXMgdGhlIGNyb3NzIHByb2R1Y3Qgb2YgdHdvIHZlYzMnc1xuICpcbiAqIEBwYXJhbSB7dmVjM30gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge1JlYWRvbmx5VmVjM30gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHtSZWFkb25seVZlYzN9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7dmVjM30gb3V0XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGNyb3NzKG91dCwgYSwgYikge1xuICB2YXIgYXggPSBhWzBdLFxuICAgICAgYXkgPSBhWzFdLFxuICAgICAgYXogPSBhWzJdO1xuICB2YXIgYnggPSBiWzBdLFxuICAgICAgYnkgPSBiWzFdLFxuICAgICAgYnogPSBiWzJdO1xuICBvdXRbMF0gPSBheSAqIGJ6IC0gYXogKiBieTtcbiAgb3V0WzFdID0gYXogKiBieCAtIGF4ICogYno7XG4gIG91dFsyXSA9IGF4ICogYnkgLSBheSAqIGJ4O1xuICByZXR1cm4gb3V0O1xufVxuLyoqXG4gKiBQZXJmb3JtcyBhIGxpbmVhciBpbnRlcnBvbGF0aW9uIGJldHdlZW4gdHdvIHZlYzMnc1xuICpcbiAqIEBwYXJhbSB7dmVjM30gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge1JlYWRvbmx5VmVjM30gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHtSZWFkb25seVZlYzN9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcGFyYW0ge051bWJlcn0gdCBpbnRlcnBvbGF0aW9uIGFtb3VudCwgaW4gdGhlIHJhbmdlIFswLTFdLCBiZXR3ZWVuIHRoZSB0d28gaW5wdXRzXG4gKiBAcmV0dXJucyB7dmVjM30gb3V0XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGxlcnAob3V0LCBhLCBiLCB0KSB7XG4gIHZhciBheCA9IGFbMF07XG4gIHZhciBheSA9IGFbMV07XG4gIHZhciBheiA9IGFbMl07XG4gIG91dFswXSA9IGF4ICsgdCAqIChiWzBdIC0gYXgpO1xuICBvdXRbMV0gPSBheSArIHQgKiAoYlsxXSAtIGF5KTtcbiAgb3V0WzJdID0gYXogKyB0ICogKGJbMl0gLSBheik7XG4gIHJldHVybiBvdXQ7XG59XG4vKipcbiAqIFBlcmZvcm1zIGEgaGVybWl0ZSBpbnRlcnBvbGF0aW9uIHdpdGggdHdvIGNvbnRyb2wgcG9pbnRzXG4gKlxuICogQHBhcmFtIHt2ZWMzfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7UmVhZG9ubHlWZWMzfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge1JlYWRvbmx5VmVjM30gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEBwYXJhbSB7UmVhZG9ubHlWZWMzfSBjIHRoZSB0aGlyZCBvcGVyYW5kXG4gKiBAcGFyYW0ge1JlYWRvbmx5VmVjM30gZCB0aGUgZm91cnRoIG9wZXJhbmRcbiAqIEBwYXJhbSB7TnVtYmVyfSB0IGludGVycG9sYXRpb24gYW1vdW50LCBpbiB0aGUgcmFuZ2UgWzAtMV0sIGJldHdlZW4gdGhlIHR3byBpbnB1dHNcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gaGVybWl0ZShvdXQsIGEsIGIsIGMsIGQsIHQpIHtcbiAgdmFyIGZhY3RvclRpbWVzMiA9IHQgKiB0O1xuICB2YXIgZmFjdG9yMSA9IGZhY3RvclRpbWVzMiAqICgyICogdCAtIDMpICsgMTtcbiAgdmFyIGZhY3RvcjIgPSBmYWN0b3JUaW1lczIgKiAodCAtIDIpICsgdDtcbiAgdmFyIGZhY3RvcjMgPSBmYWN0b3JUaW1lczIgKiAodCAtIDEpO1xuICB2YXIgZmFjdG9yNCA9IGZhY3RvclRpbWVzMiAqICgzIC0gMiAqIHQpO1xuICBvdXRbMF0gPSBhWzBdICogZmFjdG9yMSArIGJbMF0gKiBmYWN0b3IyICsgY1swXSAqIGZhY3RvcjMgKyBkWzBdICogZmFjdG9yNDtcbiAgb3V0WzFdID0gYVsxXSAqIGZhY3RvcjEgKyBiWzFdICogZmFjdG9yMiArIGNbMV0gKiBmYWN0b3IzICsgZFsxXSAqIGZhY3RvcjQ7XG4gIG91dFsyXSA9IGFbMl0gKiBmYWN0b3IxICsgYlsyXSAqIGZhY3RvcjIgKyBjWzJdICogZmFjdG9yMyArIGRbMl0gKiBmYWN0b3I0O1xuICByZXR1cm4gb3V0O1xufVxuLyoqXG4gKiBQZXJmb3JtcyBhIGJlemllciBpbnRlcnBvbGF0aW9uIHdpdGggdHdvIGNvbnRyb2wgcG9pbnRzXG4gKlxuICogQHBhcmFtIHt2ZWMzfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7UmVhZG9ubHlWZWMzfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge1JlYWRvbmx5VmVjM30gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEBwYXJhbSB7UmVhZG9ubHlWZWMzfSBjIHRoZSB0aGlyZCBvcGVyYW5kXG4gKiBAcGFyYW0ge1JlYWRvbmx5VmVjM30gZCB0aGUgZm91cnRoIG9wZXJhbmRcbiAqIEBwYXJhbSB7TnVtYmVyfSB0IGludGVycG9sYXRpb24gYW1vdW50LCBpbiB0aGUgcmFuZ2UgWzAtMV0sIGJldHdlZW4gdGhlIHR3byBpbnB1dHNcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gYmV6aWVyKG91dCwgYSwgYiwgYywgZCwgdCkge1xuICB2YXIgaW52ZXJzZUZhY3RvciA9IDEgLSB0O1xuICB2YXIgaW52ZXJzZUZhY3RvclRpbWVzVHdvID0gaW52ZXJzZUZhY3RvciAqIGludmVyc2VGYWN0b3I7XG4gIHZhciBmYWN0b3JUaW1lczIgPSB0ICogdDtcbiAgdmFyIGZhY3RvcjEgPSBpbnZlcnNlRmFjdG9yVGltZXNUd28gKiBpbnZlcnNlRmFjdG9yO1xuICB2YXIgZmFjdG9yMiA9IDMgKiB0ICogaW52ZXJzZUZhY3RvclRpbWVzVHdvO1xuICB2YXIgZmFjdG9yMyA9IDMgKiBmYWN0b3JUaW1lczIgKiBpbnZlcnNlRmFjdG9yO1xuICB2YXIgZmFjdG9yNCA9IGZhY3RvclRpbWVzMiAqIHQ7XG4gIG91dFswXSA9IGFbMF0gKiBmYWN0b3IxICsgYlswXSAqIGZhY3RvcjIgKyBjWzBdICogZmFjdG9yMyArIGRbMF0gKiBmYWN0b3I0O1xuICBvdXRbMV0gPSBhWzFdICogZmFjdG9yMSArIGJbMV0gKiBmYWN0b3IyICsgY1sxXSAqIGZhY3RvcjMgKyBkWzFdICogZmFjdG9yNDtcbiAgb3V0WzJdID0gYVsyXSAqIGZhY3RvcjEgKyBiWzJdICogZmFjdG9yMiArIGNbMl0gKiBmYWN0b3IzICsgZFsyXSAqIGZhY3RvcjQ7XG4gIHJldHVybiBvdXQ7XG59XG4vKipcbiAqIEdlbmVyYXRlcyBhIHJhbmRvbSB2ZWN0b3Igd2l0aCB0aGUgZ2l2ZW4gc2NhbGVcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHtOdW1iZXJ9IFtzY2FsZV0gTGVuZ3RoIG9mIHRoZSByZXN1bHRpbmcgdmVjdG9yLiBJZiBvbW1pdHRlZCwgYSB1bml0IHZlY3RvciB3aWxsIGJlIHJldHVybmVkXG4gKiBAcmV0dXJucyB7dmVjM30gb3V0XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIHJhbmRvbShvdXQsIHNjYWxlKSB7XG4gIHNjYWxlID0gc2NhbGUgfHwgMS4wO1xuICB2YXIgciA9IGdsTWF0cml4LlJBTkRPTSgpICogMi4wICogTWF0aC5QSTtcbiAgdmFyIHogPSBnbE1hdHJpeC5SQU5ET00oKSAqIDIuMCAtIDEuMDtcbiAgdmFyIHpTY2FsZSA9IE1hdGguc3FydCgxLjAgLSB6ICogeikgKiBzY2FsZTtcbiAgb3V0WzBdID0gTWF0aC5jb3MocikgKiB6U2NhbGU7XG4gIG91dFsxXSA9IE1hdGguc2luKHIpICogelNjYWxlO1xuICBvdXRbMl0gPSB6ICogc2NhbGU7XG4gIHJldHVybiBvdXQ7XG59XG4vKipcbiAqIFRyYW5zZm9ybXMgdGhlIHZlYzMgd2l0aCBhIG1hdDQuXG4gKiA0dGggdmVjdG9yIGNvbXBvbmVudCBpcyBpbXBsaWNpdGx5ICcxJ1xuICpcbiAqIEBwYXJhbSB7dmVjM30gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge1JlYWRvbmx5VmVjM30gYSB0aGUgdmVjdG9yIHRvIHRyYW5zZm9ybVxuICogQHBhcmFtIHtSZWFkb25seU1hdDR9IG0gbWF0cml4IHRvIHRyYW5zZm9ybSB3aXRoXG4gKiBAcmV0dXJucyB7dmVjM30gb3V0XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIHRyYW5zZm9ybU1hdDQob3V0LCBhLCBtKSB7XG4gIHZhciB4ID0gYVswXSxcbiAgICAgIHkgPSBhWzFdLFxuICAgICAgeiA9IGFbMl07XG4gIHZhciB3ID0gbVszXSAqIHggKyBtWzddICogeSArIG1bMTFdICogeiArIG1bMTVdO1xuICB3ID0gdyB8fCAxLjA7XG4gIG91dFswXSA9IChtWzBdICogeCArIG1bNF0gKiB5ICsgbVs4XSAqIHogKyBtWzEyXSkgLyB3O1xuICBvdXRbMV0gPSAobVsxXSAqIHggKyBtWzVdICogeSArIG1bOV0gKiB6ICsgbVsxM10pIC8gdztcbiAgb3V0WzJdID0gKG1bMl0gKiB4ICsgbVs2XSAqIHkgKyBtWzEwXSAqIHogKyBtWzE0XSkgLyB3O1xuICByZXR1cm4gb3V0O1xufVxuLyoqXG4gKiBUcmFuc2Zvcm1zIHRoZSB2ZWMzIHdpdGggYSBtYXQzLlxuICpcbiAqIEBwYXJhbSB7dmVjM30gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge1JlYWRvbmx5VmVjM30gYSB0aGUgdmVjdG9yIHRvIHRyYW5zZm9ybVxuICogQHBhcmFtIHtSZWFkb25seU1hdDN9IG0gdGhlIDN4MyBtYXRyaXggdG8gdHJhbnNmb3JtIHdpdGhcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gdHJhbnNmb3JtTWF0MyhvdXQsIGEsIG0pIHtcbiAgdmFyIHggPSBhWzBdLFxuICAgICAgeSA9IGFbMV0sXG4gICAgICB6ID0gYVsyXTtcbiAgb3V0WzBdID0geCAqIG1bMF0gKyB5ICogbVszXSArIHogKiBtWzZdO1xuICBvdXRbMV0gPSB4ICogbVsxXSArIHkgKiBtWzRdICsgeiAqIG1bN107XG4gIG91dFsyXSA9IHggKiBtWzJdICsgeSAqIG1bNV0gKyB6ICogbVs4XTtcbiAgcmV0dXJuIG91dDtcbn1cbi8qKlxuICogVHJhbnNmb3JtcyB0aGUgdmVjMyB3aXRoIGEgcXVhdFxuICogQ2FuIGFsc28gYmUgdXNlZCBmb3IgZHVhbCBxdWF0ZXJuaW9ucy4gKE11bHRpcGx5IGl0IHdpdGggdGhlIHJlYWwgcGFydClcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHtSZWFkb25seVZlYzN9IGEgdGhlIHZlY3RvciB0byB0cmFuc2Zvcm1cbiAqIEBwYXJhbSB7UmVhZG9ubHlRdWF0fSBxIHF1YXRlcm5pb24gdG8gdHJhbnNmb3JtIHdpdGhcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gdHJhbnNmb3JtUXVhdChvdXQsIGEsIHEpIHtcbiAgLy8gYmVuY2htYXJrczogaHR0cHM6Ly9qc3BlcmYuY29tL3F1YXRlcm5pb24tdHJhbnNmb3JtLXZlYzMtaW1wbGVtZW50YXRpb25zLWZpeGVkXG4gIHZhciBxeCA9IHFbMF0sXG4gICAgICBxeSA9IHFbMV0sXG4gICAgICBxeiA9IHFbMl0sXG4gICAgICBxdyA9IHFbM107XG4gIHZhciB4ID0gYVswXSxcbiAgICAgIHkgPSBhWzFdLFxuICAgICAgeiA9IGFbMl07IC8vIHZhciBxdmVjID0gW3F4LCBxeSwgcXpdO1xuICAvLyB2YXIgdXYgPSB2ZWMzLmNyb3NzKFtdLCBxdmVjLCBhKTtcblxuICB2YXIgdXZ4ID0gcXkgKiB6IC0gcXogKiB5LFxuICAgICAgdXZ5ID0gcXogKiB4IC0gcXggKiB6LFxuICAgICAgdXZ6ID0gcXggKiB5IC0gcXkgKiB4OyAvLyB2YXIgdXV2ID0gdmVjMy5jcm9zcyhbXSwgcXZlYywgdXYpO1xuXG4gIHZhciB1dXZ4ID0gcXkgKiB1dnogLSBxeiAqIHV2eSxcbiAgICAgIHV1dnkgPSBxeiAqIHV2eCAtIHF4ICogdXZ6LFxuICAgICAgdXV2eiA9IHF4ICogdXZ5IC0gcXkgKiB1dng7IC8vIHZlYzMuc2NhbGUodXYsIHV2LCAyICogdyk7XG5cbiAgdmFyIHcyID0gcXcgKiAyO1xuICB1dnggKj0gdzI7XG4gIHV2eSAqPSB3MjtcbiAgdXZ6ICo9IHcyOyAvLyB2ZWMzLnNjYWxlKHV1diwgdXV2LCAyKTtcblxuICB1dXZ4ICo9IDI7XG4gIHV1dnkgKj0gMjtcbiAgdXV2eiAqPSAyOyAvLyByZXR1cm4gdmVjMy5hZGQob3V0LCBhLCB2ZWMzLmFkZChvdXQsIHV2LCB1dXYpKTtcblxuICBvdXRbMF0gPSB4ICsgdXZ4ICsgdXV2eDtcbiAgb3V0WzFdID0geSArIHV2eSArIHV1dnk7XG4gIG91dFsyXSA9IHogKyB1dnogKyB1dXZ6O1xuICByZXR1cm4gb3V0O1xufVxuLyoqXG4gKiBSb3RhdGUgYSAzRCB2ZWN0b3IgYXJvdW5kIHRoZSB4LWF4aXNcbiAqIEBwYXJhbSB7dmVjM30gb3V0IFRoZSByZWNlaXZpbmcgdmVjM1xuICogQHBhcmFtIHtSZWFkb25seVZlYzN9IGEgVGhlIHZlYzMgcG9pbnQgdG8gcm90YXRlXG4gKiBAcGFyYW0ge1JlYWRvbmx5VmVjM30gYiBUaGUgb3JpZ2luIG9mIHRoZSByb3RhdGlvblxuICogQHBhcmFtIHtOdW1iZXJ9IHJhZCBUaGUgYW5nbGUgb2Ygcm90YXRpb24gaW4gcmFkaWFuc1xuICogQHJldHVybnMge3ZlYzN9IG91dFxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiByb3RhdGVYKG91dCwgYSwgYiwgcmFkKSB7XG4gIHZhciBwID0gW10sXG4gICAgICByID0gW107IC8vVHJhbnNsYXRlIHBvaW50IHRvIHRoZSBvcmlnaW5cblxuICBwWzBdID0gYVswXSAtIGJbMF07XG4gIHBbMV0gPSBhWzFdIC0gYlsxXTtcbiAgcFsyXSA9IGFbMl0gLSBiWzJdOyAvL3BlcmZvcm0gcm90YXRpb25cblxuICByWzBdID0gcFswXTtcbiAgclsxXSA9IHBbMV0gKiBNYXRoLmNvcyhyYWQpIC0gcFsyXSAqIE1hdGguc2luKHJhZCk7XG4gIHJbMl0gPSBwWzFdICogTWF0aC5zaW4ocmFkKSArIHBbMl0gKiBNYXRoLmNvcyhyYWQpOyAvL3RyYW5zbGF0ZSB0byBjb3JyZWN0IHBvc2l0aW9uXG5cbiAgb3V0WzBdID0gclswXSArIGJbMF07XG4gIG91dFsxXSA9IHJbMV0gKyBiWzFdO1xuICBvdXRbMl0gPSByWzJdICsgYlsyXTtcbiAgcmV0dXJuIG91dDtcbn1cbi8qKlxuICogUm90YXRlIGEgM0QgdmVjdG9yIGFyb3VuZCB0aGUgeS1heGlzXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCBUaGUgcmVjZWl2aW5nIHZlYzNcbiAqIEBwYXJhbSB7UmVhZG9ubHlWZWMzfSBhIFRoZSB2ZWMzIHBvaW50IHRvIHJvdGF0ZVxuICogQHBhcmFtIHtSZWFkb25seVZlYzN9IGIgVGhlIG9yaWdpbiBvZiB0aGUgcm90YXRpb25cbiAqIEBwYXJhbSB7TnVtYmVyfSByYWQgVGhlIGFuZ2xlIG9mIHJvdGF0aW9uIGluIHJhZGlhbnNcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gcm90YXRlWShvdXQsIGEsIGIsIHJhZCkge1xuICB2YXIgcCA9IFtdLFxuICAgICAgciA9IFtdOyAvL1RyYW5zbGF0ZSBwb2ludCB0byB0aGUgb3JpZ2luXG5cbiAgcFswXSA9IGFbMF0gLSBiWzBdO1xuICBwWzFdID0gYVsxXSAtIGJbMV07XG4gIHBbMl0gPSBhWzJdIC0gYlsyXTsgLy9wZXJmb3JtIHJvdGF0aW9uXG5cbiAgclswXSA9IHBbMl0gKiBNYXRoLnNpbihyYWQpICsgcFswXSAqIE1hdGguY29zKHJhZCk7XG4gIHJbMV0gPSBwWzFdO1xuICByWzJdID0gcFsyXSAqIE1hdGguY29zKHJhZCkgLSBwWzBdICogTWF0aC5zaW4ocmFkKTsgLy90cmFuc2xhdGUgdG8gY29ycmVjdCBwb3NpdGlvblxuXG4gIG91dFswXSA9IHJbMF0gKyBiWzBdO1xuICBvdXRbMV0gPSByWzFdICsgYlsxXTtcbiAgb3V0WzJdID0gclsyXSArIGJbMl07XG4gIHJldHVybiBvdXQ7XG59XG4vKipcbiAqIFJvdGF0ZSBhIDNEIHZlY3RvciBhcm91bmQgdGhlIHotYXhpc1xuICogQHBhcmFtIHt2ZWMzfSBvdXQgVGhlIHJlY2VpdmluZyB2ZWMzXG4gKiBAcGFyYW0ge1JlYWRvbmx5VmVjM30gYSBUaGUgdmVjMyBwb2ludCB0byByb3RhdGVcbiAqIEBwYXJhbSB7UmVhZG9ubHlWZWMzfSBiIFRoZSBvcmlnaW4gb2YgdGhlIHJvdGF0aW9uXG4gKiBAcGFyYW0ge051bWJlcn0gcmFkIFRoZSBhbmdsZSBvZiByb3RhdGlvbiBpbiByYWRpYW5zXG4gKiBAcmV0dXJucyB7dmVjM30gb3V0XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIHJvdGF0ZVoob3V0LCBhLCBiLCByYWQpIHtcbiAgdmFyIHAgPSBbXSxcbiAgICAgIHIgPSBbXTsgLy9UcmFuc2xhdGUgcG9pbnQgdG8gdGhlIG9yaWdpblxuXG4gIHBbMF0gPSBhWzBdIC0gYlswXTtcbiAgcFsxXSA9IGFbMV0gLSBiWzFdO1xuICBwWzJdID0gYVsyXSAtIGJbMl07IC8vcGVyZm9ybSByb3RhdGlvblxuXG4gIHJbMF0gPSBwWzBdICogTWF0aC5jb3MocmFkKSAtIHBbMV0gKiBNYXRoLnNpbihyYWQpO1xuICByWzFdID0gcFswXSAqIE1hdGguc2luKHJhZCkgKyBwWzFdICogTWF0aC5jb3MocmFkKTtcbiAgclsyXSA9IHBbMl07IC8vdHJhbnNsYXRlIHRvIGNvcnJlY3QgcG9zaXRpb25cblxuICBvdXRbMF0gPSByWzBdICsgYlswXTtcbiAgb3V0WzFdID0gclsxXSArIGJbMV07XG4gIG91dFsyXSA9IHJbMl0gKyBiWzJdO1xuICByZXR1cm4gb3V0O1xufVxuLyoqXG4gKiBHZXQgdGhlIGFuZ2xlIGJldHdlZW4gdHdvIDNEIHZlY3RvcnNcbiAqIEBwYXJhbSB7UmVhZG9ubHlWZWMzfSBhIFRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge1JlYWRvbmx5VmVjM30gYiBUaGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHtOdW1iZXJ9IFRoZSBhbmdsZSBpbiByYWRpYW5zXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGFuZ2xlKGEsIGIpIHtcbiAgdmFyIGF4ID0gYVswXSxcbiAgICAgIGF5ID0gYVsxXSxcbiAgICAgIGF6ID0gYVsyXSxcbiAgICAgIGJ4ID0gYlswXSxcbiAgICAgIGJ5ID0gYlsxXSxcbiAgICAgIGJ6ID0gYlsyXSxcbiAgICAgIG1hZzEgPSBNYXRoLnNxcnQoYXggKiBheCArIGF5ICogYXkgKyBheiAqIGF6KSxcbiAgICAgIG1hZzIgPSBNYXRoLnNxcnQoYnggKiBieCArIGJ5ICogYnkgKyBieiAqIGJ6KSxcbiAgICAgIG1hZyA9IG1hZzEgKiBtYWcyLFxuICAgICAgY29zaW5lID0gbWFnICYmIGRvdChhLCBiKSAvIG1hZztcbiAgcmV0dXJuIE1hdGguYWNvcyhNYXRoLm1pbihNYXRoLm1heChjb3NpbmUsIC0xKSwgMSkpO1xufVxuLyoqXG4gKiBTZXQgdGhlIGNvbXBvbmVudHMgb2YgYSB2ZWMzIHRvIHplcm9cbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHJldHVybnMge3ZlYzN9IG91dFxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiB6ZXJvKG91dCkge1xuICBvdXRbMF0gPSAwLjA7XG4gIG91dFsxXSA9IDAuMDtcbiAgb3V0WzJdID0gMC4wO1xuICByZXR1cm4gb3V0O1xufVxuLyoqXG4gKiBSZXR1cm5zIGEgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIGEgdmVjdG9yXG4gKlxuICogQHBhcmFtIHtSZWFkb25seVZlYzN9IGEgdmVjdG9yIHRvIHJlcHJlc2VudCBhcyBhIHN0cmluZ1xuICogQHJldHVybnMge1N0cmluZ30gc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIHRoZSB2ZWN0b3JcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gc3RyKGEpIHtcbiAgcmV0dXJuIFwidmVjMyhcIiArIGFbMF0gKyBcIiwgXCIgKyBhWzFdICsgXCIsIFwiICsgYVsyXSArIFwiKVwiO1xufVxuLyoqXG4gKiBSZXR1cm5zIHdoZXRoZXIgb3Igbm90IHRoZSB2ZWN0b3JzIGhhdmUgZXhhY3RseSB0aGUgc2FtZSBlbGVtZW50cyBpbiB0aGUgc2FtZSBwb3NpdGlvbiAod2hlbiBjb21wYXJlZCB3aXRoID09PSlcbiAqXG4gKiBAcGFyYW0ge1JlYWRvbmx5VmVjM30gYSBUaGUgZmlyc3QgdmVjdG9yLlxuICogQHBhcmFtIHtSZWFkb25seVZlYzN9IGIgVGhlIHNlY29uZCB2ZWN0b3IuXG4gKiBAcmV0dXJucyB7Qm9vbGVhbn0gVHJ1ZSBpZiB0aGUgdmVjdG9ycyBhcmUgZXF1YWwsIGZhbHNlIG90aGVyd2lzZS5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gZXhhY3RFcXVhbHMoYSwgYikge1xuICByZXR1cm4gYVswXSA9PT0gYlswXSAmJiBhWzFdID09PSBiWzFdICYmIGFbMl0gPT09IGJbMl07XG59XG4vKipcbiAqIFJldHVybnMgd2hldGhlciBvciBub3QgdGhlIHZlY3RvcnMgaGF2ZSBhcHByb3hpbWF0ZWx5IHRoZSBzYW1lIGVsZW1lbnRzIGluIHRoZSBzYW1lIHBvc2l0aW9uLlxuICpcbiAqIEBwYXJhbSB7UmVhZG9ubHlWZWMzfSBhIFRoZSBmaXJzdCB2ZWN0b3IuXG4gKiBAcGFyYW0ge1JlYWRvbmx5VmVjM30gYiBUaGUgc2Vjb25kIHZlY3Rvci5cbiAqIEByZXR1cm5zIHtCb29sZWFufSBUcnVlIGlmIHRoZSB2ZWN0b3JzIGFyZSBlcXVhbCwgZmFsc2Ugb3RoZXJ3aXNlLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBlcXVhbHMoYSwgYikge1xuICB2YXIgYTAgPSBhWzBdLFxuICAgICAgYTEgPSBhWzFdLFxuICAgICAgYTIgPSBhWzJdO1xuICB2YXIgYjAgPSBiWzBdLFxuICAgICAgYjEgPSBiWzFdLFxuICAgICAgYjIgPSBiWzJdO1xuICByZXR1cm4gTWF0aC5hYnMoYTAgLSBiMCkgPD0gZ2xNYXRyaXguRVBTSUxPTiAqIE1hdGgubWF4KDEuMCwgTWF0aC5hYnMoYTApLCBNYXRoLmFicyhiMCkpICYmIE1hdGguYWJzKGExIC0gYjEpIDw9IGdsTWF0cml4LkVQU0lMT04gKiBNYXRoLm1heCgxLjAsIE1hdGguYWJzKGExKSwgTWF0aC5hYnMoYjEpKSAmJiBNYXRoLmFicyhhMiAtIGIyKSA8PSBnbE1hdHJpeC5FUFNJTE9OICogTWF0aC5tYXgoMS4wLCBNYXRoLmFicyhhMiksIE1hdGguYWJzKGIyKSk7XG59XG4vKipcbiAqIEFsaWFzIGZvciB7QGxpbmsgdmVjMy5zdWJ0cmFjdH1cbiAqIEBmdW5jdGlvblxuICovXG5cbmV4cG9ydCB2YXIgc3ViID0gc3VidHJhY3Q7XG4vKipcbiAqIEFsaWFzIGZvciB7QGxpbmsgdmVjMy5tdWx0aXBseX1cbiAqIEBmdW5jdGlvblxuICovXG5cbmV4cG9ydCB2YXIgbXVsID0gbXVsdGlwbHk7XG4vKipcbiAqIEFsaWFzIGZvciB7QGxpbmsgdmVjMy5kaXZpZGV9XG4gKiBAZnVuY3Rpb25cbiAqL1xuXG5leHBvcnQgdmFyIGRpdiA9IGRpdmlkZTtcbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayB2ZWMzLmRpc3RhbmNlfVxuICogQGZ1bmN0aW9uXG4gKi9cblxuZXhwb3J0IHZhciBkaXN0ID0gZGlzdGFuY2U7XG4vKipcbiAqIEFsaWFzIGZvciB7QGxpbmsgdmVjMy5zcXVhcmVkRGlzdGFuY2V9XG4gKiBAZnVuY3Rpb25cbiAqL1xuXG5leHBvcnQgdmFyIHNxckRpc3QgPSBzcXVhcmVkRGlzdGFuY2U7XG4vKipcbiAqIEFsaWFzIGZvciB7QGxpbmsgdmVjMy5sZW5ndGh9XG4gKiBAZnVuY3Rpb25cbiAqL1xuXG5leHBvcnQgdmFyIGxlbiA9IGxlbmd0aDtcbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayB2ZWMzLnNxdWFyZWRMZW5ndGh9XG4gKiBAZnVuY3Rpb25cbiAqL1xuXG5leHBvcnQgdmFyIHNxckxlbiA9IHNxdWFyZWRMZW5ndGg7XG4vKipcbiAqIFBlcmZvcm0gc29tZSBvcGVyYXRpb24gb3ZlciBhbiBhcnJheSBvZiB2ZWMzcy5cbiAqXG4gKiBAcGFyYW0ge0FycmF5fSBhIHRoZSBhcnJheSBvZiB2ZWN0b3JzIHRvIGl0ZXJhdGUgb3ZlclxuICogQHBhcmFtIHtOdW1iZXJ9IHN0cmlkZSBOdW1iZXIgb2YgZWxlbWVudHMgYmV0d2VlbiB0aGUgc3RhcnQgb2YgZWFjaCB2ZWMzLiBJZiAwIGFzc3VtZXMgdGlnaHRseSBwYWNrZWRcbiAqIEBwYXJhbSB7TnVtYmVyfSBvZmZzZXQgTnVtYmVyIG9mIGVsZW1lbnRzIHRvIHNraXAgYXQgdGhlIGJlZ2lubmluZyBvZiB0aGUgYXJyYXlcbiAqIEBwYXJhbSB7TnVtYmVyfSBjb3VudCBOdW1iZXIgb2YgdmVjM3MgdG8gaXRlcmF0ZSBvdmVyLiBJZiAwIGl0ZXJhdGVzIG92ZXIgZW50aXJlIGFycmF5XG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmbiBGdW5jdGlvbiB0byBjYWxsIGZvciBlYWNoIHZlY3RvciBpbiB0aGUgYXJyYXlcbiAqIEBwYXJhbSB7T2JqZWN0fSBbYXJnXSBhZGRpdGlvbmFsIGFyZ3VtZW50IHRvIHBhc3MgdG8gZm5cbiAqIEByZXR1cm5zIHtBcnJheX0gYVxuICogQGZ1bmN0aW9uXG4gKi9cblxuZXhwb3J0IHZhciBmb3JFYWNoID0gZnVuY3Rpb24gKCkge1xuICB2YXIgdmVjID0gY3JlYXRlKCk7XG4gIHJldHVybiBmdW5jdGlvbiAoYSwgc3RyaWRlLCBvZmZzZXQsIGNvdW50LCBmbiwgYXJnKSB7XG4gICAgdmFyIGksIGw7XG5cbiAgICBpZiAoIXN0cmlkZSkge1xuICAgICAgc3RyaWRlID0gMztcbiAgICB9XG5cbiAgICBpZiAoIW9mZnNldCkge1xuICAgICAgb2Zmc2V0ID0gMDtcbiAgICB9XG5cbiAgICBpZiAoY291bnQpIHtcbiAgICAgIGwgPSBNYXRoLm1pbihjb3VudCAqIHN0cmlkZSArIG9mZnNldCwgYS5sZW5ndGgpO1xuICAgIH0gZWxzZSB7XG4gICAgICBsID0gYS5sZW5ndGg7XG4gICAgfVxuXG4gICAgZm9yIChpID0gb2Zmc2V0OyBpIDwgbDsgaSArPSBzdHJpZGUpIHtcbiAgICAgIHZlY1swXSA9IGFbaV07XG4gICAgICB2ZWNbMV0gPSBhW2kgKyAxXTtcbiAgICAgIHZlY1syXSA9IGFbaSArIDJdO1xuICAgICAgZm4odmVjLCB2ZWMsIGFyZyk7XG4gICAgICBhW2ldID0gdmVjWzBdO1xuICAgICAgYVtpICsgMV0gPSB2ZWNbMV07XG4gICAgICBhW2kgKyAyXSA9IHZlY1syXTtcbiAgICB9XG5cbiAgICByZXR1cm4gYTtcbiAgfTtcbn0oKTsiLCJpbXBvcnQgKiBhcyBnbE1hdHJpeCBmcm9tIFwiLi9jb21tb24uanNcIjtcbi8qKlxuICogNHg0IE1hdHJpeDxicj5Gb3JtYXQ6IGNvbHVtbi1tYWpvciwgd2hlbiB0eXBlZCBvdXQgaXQgbG9va3MgbGlrZSByb3ctbWFqb3I8YnI+VGhlIG1hdHJpY2VzIGFyZSBiZWluZyBwb3N0IG11bHRpcGxpZWQuXG4gKiBAbW9kdWxlIG1hdDRcbiAqL1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgaWRlbnRpdHkgbWF0NFxuICpcbiAqIEByZXR1cm5zIHttYXQ0fSBhIG5ldyA0eDQgbWF0cml4XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZSgpIHtcbiAgdmFyIG91dCA9IG5ldyBnbE1hdHJpeC5BUlJBWV9UWVBFKDE2KTtcblxuICBpZiAoZ2xNYXRyaXguQVJSQVlfVFlQRSAhPSBGbG9hdDMyQXJyYXkpIHtcbiAgICBvdXRbMV0gPSAwO1xuICAgIG91dFsyXSA9IDA7XG4gICAgb3V0WzNdID0gMDtcbiAgICBvdXRbNF0gPSAwO1xuICAgIG91dFs2XSA9IDA7XG4gICAgb3V0WzddID0gMDtcbiAgICBvdXRbOF0gPSAwO1xuICAgIG91dFs5XSA9IDA7XG4gICAgb3V0WzExXSA9IDA7XG4gICAgb3V0WzEyXSA9IDA7XG4gICAgb3V0WzEzXSA9IDA7XG4gICAgb3V0WzE0XSA9IDA7XG4gIH1cblxuICBvdXRbMF0gPSAxO1xuICBvdXRbNV0gPSAxO1xuICBvdXRbMTBdID0gMTtcbiAgb3V0WzE1XSA9IDE7XG4gIHJldHVybiBvdXQ7XG59XG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgbWF0NCBpbml0aWFsaXplZCB3aXRoIHZhbHVlcyBmcm9tIGFuIGV4aXN0aW5nIG1hdHJpeFxuICpcbiAqIEBwYXJhbSB7UmVhZG9ubHlNYXQ0fSBhIG1hdHJpeCB0byBjbG9uZVxuICogQHJldHVybnMge21hdDR9IGEgbmV3IDR4NCBtYXRyaXhcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gY2xvbmUoYSkge1xuICB2YXIgb3V0ID0gbmV3IGdsTWF0cml4LkFSUkFZX1RZUEUoMTYpO1xuICBvdXRbMF0gPSBhWzBdO1xuICBvdXRbMV0gPSBhWzFdO1xuICBvdXRbMl0gPSBhWzJdO1xuICBvdXRbM10gPSBhWzNdO1xuICBvdXRbNF0gPSBhWzRdO1xuICBvdXRbNV0gPSBhWzVdO1xuICBvdXRbNl0gPSBhWzZdO1xuICBvdXRbN10gPSBhWzddO1xuICBvdXRbOF0gPSBhWzhdO1xuICBvdXRbOV0gPSBhWzldO1xuICBvdXRbMTBdID0gYVsxMF07XG4gIG91dFsxMV0gPSBhWzExXTtcbiAgb3V0WzEyXSA9IGFbMTJdO1xuICBvdXRbMTNdID0gYVsxM107XG4gIG91dFsxNF0gPSBhWzE0XTtcbiAgb3V0WzE1XSA9IGFbMTVdO1xuICByZXR1cm4gb3V0O1xufVxuLyoqXG4gKiBDb3B5IHRoZSB2YWx1ZXMgZnJvbSBvbmUgbWF0NCB0byBhbm90aGVyXG4gKlxuICogQHBhcmFtIHttYXQ0fSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7UmVhZG9ubHlNYXQ0fSBhIHRoZSBzb3VyY2UgbWF0cml4XG4gKiBAcmV0dXJucyB7bWF0NH0gb3V0XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGNvcHkob3V0LCBhKSB7XG4gIG91dFswXSA9IGFbMF07XG4gIG91dFsxXSA9IGFbMV07XG4gIG91dFsyXSA9IGFbMl07XG4gIG91dFszXSA9IGFbM107XG4gIG91dFs0XSA9IGFbNF07XG4gIG91dFs1XSA9IGFbNV07XG4gIG91dFs2XSA9IGFbNl07XG4gIG91dFs3XSA9IGFbN107XG4gIG91dFs4XSA9IGFbOF07XG4gIG91dFs5XSA9IGFbOV07XG4gIG91dFsxMF0gPSBhWzEwXTtcbiAgb3V0WzExXSA9IGFbMTFdO1xuICBvdXRbMTJdID0gYVsxMl07XG4gIG91dFsxM10gPSBhWzEzXTtcbiAgb3V0WzE0XSA9IGFbMTRdO1xuICBvdXRbMTVdID0gYVsxNV07XG4gIHJldHVybiBvdXQ7XG59XG4vKipcbiAqIENyZWF0ZSBhIG5ldyBtYXQ0IHdpdGggdGhlIGdpdmVuIHZhbHVlc1xuICpcbiAqIEBwYXJhbSB7TnVtYmVyfSBtMDAgQ29tcG9uZW50IGluIGNvbHVtbiAwLCByb3cgMCBwb3NpdGlvbiAoaW5kZXggMClcbiAqIEBwYXJhbSB7TnVtYmVyfSBtMDEgQ29tcG9uZW50IGluIGNvbHVtbiAwLCByb3cgMSBwb3NpdGlvbiAoaW5kZXggMSlcbiAqIEBwYXJhbSB7TnVtYmVyfSBtMDIgQ29tcG9uZW50IGluIGNvbHVtbiAwLCByb3cgMiBwb3NpdGlvbiAoaW5kZXggMilcbiAqIEBwYXJhbSB7TnVtYmVyfSBtMDMgQ29tcG9uZW50IGluIGNvbHVtbiAwLCByb3cgMyBwb3NpdGlvbiAoaW5kZXggMylcbiAqIEBwYXJhbSB7TnVtYmVyfSBtMTAgQ29tcG9uZW50IGluIGNvbHVtbiAxLCByb3cgMCBwb3NpdGlvbiAoaW5kZXggNClcbiAqIEBwYXJhbSB7TnVtYmVyfSBtMTEgQ29tcG9uZW50IGluIGNvbHVtbiAxLCByb3cgMSBwb3NpdGlvbiAoaW5kZXggNSlcbiAqIEBwYXJhbSB7TnVtYmVyfSBtMTIgQ29tcG9uZW50IGluIGNvbHVtbiAxLCByb3cgMiBwb3NpdGlvbiAoaW5kZXggNilcbiAqIEBwYXJhbSB7TnVtYmVyfSBtMTMgQ29tcG9uZW50IGluIGNvbHVtbiAxLCByb3cgMyBwb3NpdGlvbiAoaW5kZXggNylcbiAqIEBwYXJhbSB7TnVtYmVyfSBtMjAgQ29tcG9uZW50IGluIGNvbHVtbiAyLCByb3cgMCBwb3NpdGlvbiAoaW5kZXggOClcbiAqIEBwYXJhbSB7TnVtYmVyfSBtMjEgQ29tcG9uZW50IGluIGNvbHVtbiAyLCByb3cgMSBwb3NpdGlvbiAoaW5kZXggOSlcbiAqIEBwYXJhbSB7TnVtYmVyfSBtMjIgQ29tcG9uZW50IGluIGNvbHVtbiAyLCByb3cgMiBwb3NpdGlvbiAoaW5kZXggMTApXG4gKiBAcGFyYW0ge051bWJlcn0gbTIzIENvbXBvbmVudCBpbiBjb2x1bW4gMiwgcm93IDMgcG9zaXRpb24gKGluZGV4IDExKVxuICogQHBhcmFtIHtOdW1iZXJ9IG0zMCBDb21wb25lbnQgaW4gY29sdW1uIDMsIHJvdyAwIHBvc2l0aW9uIChpbmRleCAxMilcbiAqIEBwYXJhbSB7TnVtYmVyfSBtMzEgQ29tcG9uZW50IGluIGNvbHVtbiAzLCByb3cgMSBwb3NpdGlvbiAoaW5kZXggMTMpXG4gKiBAcGFyYW0ge051bWJlcn0gbTMyIENvbXBvbmVudCBpbiBjb2x1bW4gMywgcm93IDIgcG9zaXRpb24gKGluZGV4IDE0KVxuICogQHBhcmFtIHtOdW1iZXJ9IG0zMyBDb21wb25lbnQgaW4gY29sdW1uIDMsIHJvdyAzIHBvc2l0aW9uIChpbmRleCAxNSlcbiAqIEByZXR1cm5zIHttYXQ0fSBBIG5ldyBtYXQ0XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGZyb21WYWx1ZXMobTAwLCBtMDEsIG0wMiwgbTAzLCBtMTAsIG0xMSwgbTEyLCBtMTMsIG0yMCwgbTIxLCBtMjIsIG0yMywgbTMwLCBtMzEsIG0zMiwgbTMzKSB7XG4gIHZhciBvdXQgPSBuZXcgZ2xNYXRyaXguQVJSQVlfVFlQRSgxNik7XG4gIG91dFswXSA9IG0wMDtcbiAgb3V0WzFdID0gbTAxO1xuICBvdXRbMl0gPSBtMDI7XG4gIG91dFszXSA9IG0wMztcbiAgb3V0WzRdID0gbTEwO1xuICBvdXRbNV0gPSBtMTE7XG4gIG91dFs2XSA9IG0xMjtcbiAgb3V0WzddID0gbTEzO1xuICBvdXRbOF0gPSBtMjA7XG4gIG91dFs5XSA9IG0yMTtcbiAgb3V0WzEwXSA9IG0yMjtcbiAgb3V0WzExXSA9IG0yMztcbiAgb3V0WzEyXSA9IG0zMDtcbiAgb3V0WzEzXSA9IG0zMTtcbiAgb3V0WzE0XSA9IG0zMjtcbiAgb3V0WzE1XSA9IG0zMztcbiAgcmV0dXJuIG91dDtcbn1cbi8qKlxuICogU2V0IHRoZSBjb21wb25lbnRzIG9mIGEgbWF0NCB0byB0aGUgZ2l2ZW4gdmFsdWVzXG4gKlxuICogQHBhcmFtIHttYXQ0fSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7TnVtYmVyfSBtMDAgQ29tcG9uZW50IGluIGNvbHVtbiAwLCByb3cgMCBwb3NpdGlvbiAoaW5kZXggMClcbiAqIEBwYXJhbSB7TnVtYmVyfSBtMDEgQ29tcG9uZW50IGluIGNvbHVtbiAwLCByb3cgMSBwb3NpdGlvbiAoaW5kZXggMSlcbiAqIEBwYXJhbSB7TnVtYmVyfSBtMDIgQ29tcG9uZW50IGluIGNvbHVtbiAwLCByb3cgMiBwb3NpdGlvbiAoaW5kZXggMilcbiAqIEBwYXJhbSB7TnVtYmVyfSBtMDMgQ29tcG9uZW50IGluIGNvbHVtbiAwLCByb3cgMyBwb3NpdGlvbiAoaW5kZXggMylcbiAqIEBwYXJhbSB7TnVtYmVyfSBtMTAgQ29tcG9uZW50IGluIGNvbHVtbiAxLCByb3cgMCBwb3NpdGlvbiAoaW5kZXggNClcbiAqIEBwYXJhbSB7TnVtYmVyfSBtMTEgQ29tcG9uZW50IGluIGNvbHVtbiAxLCByb3cgMSBwb3NpdGlvbiAoaW5kZXggNSlcbiAqIEBwYXJhbSB7TnVtYmVyfSBtMTIgQ29tcG9uZW50IGluIGNvbHVtbiAxLCByb3cgMiBwb3NpdGlvbiAoaW5kZXggNilcbiAqIEBwYXJhbSB7TnVtYmVyfSBtMTMgQ29tcG9uZW50IGluIGNvbHVtbiAxLCByb3cgMyBwb3NpdGlvbiAoaW5kZXggNylcbiAqIEBwYXJhbSB7TnVtYmVyfSBtMjAgQ29tcG9uZW50IGluIGNvbHVtbiAyLCByb3cgMCBwb3NpdGlvbiAoaW5kZXggOClcbiAqIEBwYXJhbSB7TnVtYmVyfSBtMjEgQ29tcG9uZW50IGluIGNvbHVtbiAyLCByb3cgMSBwb3NpdGlvbiAoaW5kZXggOSlcbiAqIEBwYXJhbSB7TnVtYmVyfSBtMjIgQ29tcG9uZW50IGluIGNvbHVtbiAyLCByb3cgMiBwb3NpdGlvbiAoaW5kZXggMTApXG4gKiBAcGFyYW0ge051bWJlcn0gbTIzIENvbXBvbmVudCBpbiBjb2x1bW4gMiwgcm93IDMgcG9zaXRpb24gKGluZGV4IDExKVxuICogQHBhcmFtIHtOdW1iZXJ9IG0zMCBDb21wb25lbnQgaW4gY29sdW1uIDMsIHJvdyAwIHBvc2l0aW9uIChpbmRleCAxMilcbiAqIEBwYXJhbSB7TnVtYmVyfSBtMzEgQ29tcG9uZW50IGluIGNvbHVtbiAzLCByb3cgMSBwb3NpdGlvbiAoaW5kZXggMTMpXG4gKiBAcGFyYW0ge051bWJlcn0gbTMyIENvbXBvbmVudCBpbiBjb2x1bW4gMywgcm93IDIgcG9zaXRpb24gKGluZGV4IDE0KVxuICogQHBhcmFtIHtOdW1iZXJ9IG0zMyBDb21wb25lbnQgaW4gY29sdW1uIDMsIHJvdyAzIHBvc2l0aW9uIChpbmRleCAxNSlcbiAqIEByZXR1cm5zIHttYXQ0fSBvdXRcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gc2V0KG91dCwgbTAwLCBtMDEsIG0wMiwgbTAzLCBtMTAsIG0xMSwgbTEyLCBtMTMsIG0yMCwgbTIxLCBtMjIsIG0yMywgbTMwLCBtMzEsIG0zMiwgbTMzKSB7XG4gIG91dFswXSA9IG0wMDtcbiAgb3V0WzFdID0gbTAxO1xuICBvdXRbMl0gPSBtMDI7XG4gIG91dFszXSA9IG0wMztcbiAgb3V0WzRdID0gbTEwO1xuICBvdXRbNV0gPSBtMTE7XG4gIG91dFs2XSA9IG0xMjtcbiAgb3V0WzddID0gbTEzO1xuICBvdXRbOF0gPSBtMjA7XG4gIG91dFs5XSA9IG0yMTtcbiAgb3V0WzEwXSA9IG0yMjtcbiAgb3V0WzExXSA9IG0yMztcbiAgb3V0WzEyXSA9IG0zMDtcbiAgb3V0WzEzXSA9IG0zMTtcbiAgb3V0WzE0XSA9IG0zMjtcbiAgb3V0WzE1XSA9IG0zMztcbiAgcmV0dXJuIG91dDtcbn1cbi8qKlxuICogU2V0IGEgbWF0NCB0byB0aGUgaWRlbnRpdHkgbWF0cml4XG4gKlxuICogQHBhcmFtIHttYXQ0fSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEByZXR1cm5zIHttYXQ0fSBvdXRcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gaWRlbnRpdHkob3V0KSB7XG4gIG91dFswXSA9IDE7XG4gIG91dFsxXSA9IDA7XG4gIG91dFsyXSA9IDA7XG4gIG91dFszXSA9IDA7XG4gIG91dFs0XSA9IDA7XG4gIG91dFs1XSA9IDE7XG4gIG91dFs2XSA9IDA7XG4gIG91dFs3XSA9IDA7XG4gIG91dFs4XSA9IDA7XG4gIG91dFs5XSA9IDA7XG4gIG91dFsxMF0gPSAxO1xuICBvdXRbMTFdID0gMDtcbiAgb3V0WzEyXSA9IDA7XG4gIG91dFsxM10gPSAwO1xuICBvdXRbMTRdID0gMDtcbiAgb3V0WzE1XSA9IDE7XG4gIHJldHVybiBvdXQ7XG59XG4vKipcbiAqIFRyYW5zcG9zZSB0aGUgdmFsdWVzIG9mIGEgbWF0NFxuICpcbiAqIEBwYXJhbSB7bWF0NH0gb3V0IHRoZSByZWNlaXZpbmcgbWF0cml4XG4gKiBAcGFyYW0ge1JlYWRvbmx5TWF0NH0gYSB0aGUgc291cmNlIG1hdHJpeFxuICogQHJldHVybnMge21hdDR9IG91dFxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiB0cmFuc3Bvc2Uob3V0LCBhKSB7XG4gIC8vIElmIHdlIGFyZSB0cmFuc3Bvc2luZyBvdXJzZWx2ZXMgd2UgY2FuIHNraXAgYSBmZXcgc3RlcHMgYnV0IGhhdmUgdG8gY2FjaGUgc29tZSB2YWx1ZXNcbiAgaWYgKG91dCA9PT0gYSkge1xuICAgIHZhciBhMDEgPSBhWzFdLFxuICAgICAgICBhMDIgPSBhWzJdLFxuICAgICAgICBhMDMgPSBhWzNdO1xuICAgIHZhciBhMTIgPSBhWzZdLFxuICAgICAgICBhMTMgPSBhWzddO1xuICAgIHZhciBhMjMgPSBhWzExXTtcbiAgICBvdXRbMV0gPSBhWzRdO1xuICAgIG91dFsyXSA9IGFbOF07XG4gICAgb3V0WzNdID0gYVsxMl07XG4gICAgb3V0WzRdID0gYTAxO1xuICAgIG91dFs2XSA9IGFbOV07XG4gICAgb3V0WzddID0gYVsxM107XG4gICAgb3V0WzhdID0gYTAyO1xuICAgIG91dFs5XSA9IGExMjtcbiAgICBvdXRbMTFdID0gYVsxNF07XG4gICAgb3V0WzEyXSA9IGEwMztcbiAgICBvdXRbMTNdID0gYTEzO1xuICAgIG91dFsxNF0gPSBhMjM7XG4gIH0gZWxzZSB7XG4gICAgb3V0WzBdID0gYVswXTtcbiAgICBvdXRbMV0gPSBhWzRdO1xuICAgIG91dFsyXSA9IGFbOF07XG4gICAgb3V0WzNdID0gYVsxMl07XG4gICAgb3V0WzRdID0gYVsxXTtcbiAgICBvdXRbNV0gPSBhWzVdO1xuICAgIG91dFs2XSA9IGFbOV07XG4gICAgb3V0WzddID0gYVsxM107XG4gICAgb3V0WzhdID0gYVsyXTtcbiAgICBvdXRbOV0gPSBhWzZdO1xuICAgIG91dFsxMF0gPSBhWzEwXTtcbiAgICBvdXRbMTFdID0gYVsxNF07XG4gICAgb3V0WzEyXSA9IGFbM107XG4gICAgb3V0WzEzXSA9IGFbN107XG4gICAgb3V0WzE0XSA9IGFbMTFdO1xuICAgIG91dFsxNV0gPSBhWzE1XTtcbiAgfVxuXG4gIHJldHVybiBvdXQ7XG59XG4vKipcbiAqIEludmVydHMgYSBtYXQ0XG4gKlxuICogQHBhcmFtIHttYXQ0fSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7UmVhZG9ubHlNYXQ0fSBhIHRoZSBzb3VyY2UgbWF0cml4XG4gKiBAcmV0dXJucyB7bWF0NH0gb3V0XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGludmVydChvdXQsIGEpIHtcbiAgdmFyIGEwMCA9IGFbMF0sXG4gICAgICBhMDEgPSBhWzFdLFxuICAgICAgYTAyID0gYVsyXSxcbiAgICAgIGEwMyA9IGFbM107XG4gIHZhciBhMTAgPSBhWzRdLFxuICAgICAgYTExID0gYVs1XSxcbiAgICAgIGExMiA9IGFbNl0sXG4gICAgICBhMTMgPSBhWzddO1xuICB2YXIgYTIwID0gYVs4XSxcbiAgICAgIGEyMSA9IGFbOV0sXG4gICAgICBhMjIgPSBhWzEwXSxcbiAgICAgIGEyMyA9IGFbMTFdO1xuICB2YXIgYTMwID0gYVsxMl0sXG4gICAgICBhMzEgPSBhWzEzXSxcbiAgICAgIGEzMiA9IGFbMTRdLFxuICAgICAgYTMzID0gYVsxNV07XG4gIHZhciBiMDAgPSBhMDAgKiBhMTEgLSBhMDEgKiBhMTA7XG4gIHZhciBiMDEgPSBhMDAgKiBhMTIgLSBhMDIgKiBhMTA7XG4gIHZhciBiMDIgPSBhMDAgKiBhMTMgLSBhMDMgKiBhMTA7XG4gIHZhciBiMDMgPSBhMDEgKiBhMTIgLSBhMDIgKiBhMTE7XG4gIHZhciBiMDQgPSBhMDEgKiBhMTMgLSBhMDMgKiBhMTE7XG4gIHZhciBiMDUgPSBhMDIgKiBhMTMgLSBhMDMgKiBhMTI7XG4gIHZhciBiMDYgPSBhMjAgKiBhMzEgLSBhMjEgKiBhMzA7XG4gIHZhciBiMDcgPSBhMjAgKiBhMzIgLSBhMjIgKiBhMzA7XG4gIHZhciBiMDggPSBhMjAgKiBhMzMgLSBhMjMgKiBhMzA7XG4gIHZhciBiMDkgPSBhMjEgKiBhMzIgLSBhMjIgKiBhMzE7XG4gIHZhciBiMTAgPSBhMjEgKiBhMzMgLSBhMjMgKiBhMzE7XG4gIHZhciBiMTEgPSBhMjIgKiBhMzMgLSBhMjMgKiBhMzI7IC8vIENhbGN1bGF0ZSB0aGUgZGV0ZXJtaW5hbnRcblxuICB2YXIgZGV0ID0gYjAwICogYjExIC0gYjAxICogYjEwICsgYjAyICogYjA5ICsgYjAzICogYjA4IC0gYjA0ICogYjA3ICsgYjA1ICogYjA2O1xuXG4gIGlmICghZGV0KSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBkZXQgPSAxLjAgLyBkZXQ7XG4gIG91dFswXSA9IChhMTEgKiBiMTEgLSBhMTIgKiBiMTAgKyBhMTMgKiBiMDkpICogZGV0O1xuICBvdXRbMV0gPSAoYTAyICogYjEwIC0gYTAxICogYjExIC0gYTAzICogYjA5KSAqIGRldDtcbiAgb3V0WzJdID0gKGEzMSAqIGIwNSAtIGEzMiAqIGIwNCArIGEzMyAqIGIwMykgKiBkZXQ7XG4gIG91dFszXSA9IChhMjIgKiBiMDQgLSBhMjEgKiBiMDUgLSBhMjMgKiBiMDMpICogZGV0O1xuICBvdXRbNF0gPSAoYTEyICogYjA4IC0gYTEwICogYjExIC0gYTEzICogYjA3KSAqIGRldDtcbiAgb3V0WzVdID0gKGEwMCAqIGIxMSAtIGEwMiAqIGIwOCArIGEwMyAqIGIwNykgKiBkZXQ7XG4gIG91dFs2XSA9IChhMzIgKiBiMDIgLSBhMzAgKiBiMDUgLSBhMzMgKiBiMDEpICogZGV0O1xuICBvdXRbN10gPSAoYTIwICogYjA1IC0gYTIyICogYjAyICsgYTIzICogYjAxKSAqIGRldDtcbiAgb3V0WzhdID0gKGExMCAqIGIxMCAtIGExMSAqIGIwOCArIGExMyAqIGIwNikgKiBkZXQ7XG4gIG91dFs5XSA9IChhMDEgKiBiMDggLSBhMDAgKiBiMTAgLSBhMDMgKiBiMDYpICogZGV0O1xuICBvdXRbMTBdID0gKGEzMCAqIGIwNCAtIGEzMSAqIGIwMiArIGEzMyAqIGIwMCkgKiBkZXQ7XG4gIG91dFsxMV0gPSAoYTIxICogYjAyIC0gYTIwICogYjA0IC0gYTIzICogYjAwKSAqIGRldDtcbiAgb3V0WzEyXSA9IChhMTEgKiBiMDcgLSBhMTAgKiBiMDkgLSBhMTIgKiBiMDYpICogZGV0O1xuICBvdXRbMTNdID0gKGEwMCAqIGIwOSAtIGEwMSAqIGIwNyArIGEwMiAqIGIwNikgKiBkZXQ7XG4gIG91dFsxNF0gPSAoYTMxICogYjAxIC0gYTMwICogYjAzIC0gYTMyICogYjAwKSAqIGRldDtcbiAgb3V0WzE1XSA9IChhMjAgKiBiMDMgLSBhMjEgKiBiMDEgKyBhMjIgKiBiMDApICogZGV0O1xuICByZXR1cm4gb3V0O1xufVxuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSBhZGp1Z2F0ZSBvZiBhIG1hdDRcbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHtSZWFkb25seU1hdDR9IGEgdGhlIHNvdXJjZSBtYXRyaXhcbiAqIEByZXR1cm5zIHttYXQ0fSBvdXRcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gYWRqb2ludChvdXQsIGEpIHtcbiAgdmFyIGEwMCA9IGFbMF0sXG4gICAgICBhMDEgPSBhWzFdLFxuICAgICAgYTAyID0gYVsyXSxcbiAgICAgIGEwMyA9IGFbM107XG4gIHZhciBhMTAgPSBhWzRdLFxuICAgICAgYTExID0gYVs1XSxcbiAgICAgIGExMiA9IGFbNl0sXG4gICAgICBhMTMgPSBhWzddO1xuICB2YXIgYTIwID0gYVs4XSxcbiAgICAgIGEyMSA9IGFbOV0sXG4gICAgICBhMjIgPSBhWzEwXSxcbiAgICAgIGEyMyA9IGFbMTFdO1xuICB2YXIgYTMwID0gYVsxMl0sXG4gICAgICBhMzEgPSBhWzEzXSxcbiAgICAgIGEzMiA9IGFbMTRdLFxuICAgICAgYTMzID0gYVsxNV07XG4gIG91dFswXSA9IGExMSAqIChhMjIgKiBhMzMgLSBhMjMgKiBhMzIpIC0gYTIxICogKGExMiAqIGEzMyAtIGExMyAqIGEzMikgKyBhMzEgKiAoYTEyICogYTIzIC0gYTEzICogYTIyKTtcbiAgb3V0WzFdID0gLShhMDEgKiAoYTIyICogYTMzIC0gYTIzICogYTMyKSAtIGEyMSAqIChhMDIgKiBhMzMgLSBhMDMgKiBhMzIpICsgYTMxICogKGEwMiAqIGEyMyAtIGEwMyAqIGEyMikpO1xuICBvdXRbMl0gPSBhMDEgKiAoYTEyICogYTMzIC0gYTEzICogYTMyKSAtIGExMSAqIChhMDIgKiBhMzMgLSBhMDMgKiBhMzIpICsgYTMxICogKGEwMiAqIGExMyAtIGEwMyAqIGExMik7XG4gIG91dFszXSA9IC0oYTAxICogKGExMiAqIGEyMyAtIGExMyAqIGEyMikgLSBhMTEgKiAoYTAyICogYTIzIC0gYTAzICogYTIyKSArIGEyMSAqIChhMDIgKiBhMTMgLSBhMDMgKiBhMTIpKTtcbiAgb3V0WzRdID0gLShhMTAgKiAoYTIyICogYTMzIC0gYTIzICogYTMyKSAtIGEyMCAqIChhMTIgKiBhMzMgLSBhMTMgKiBhMzIpICsgYTMwICogKGExMiAqIGEyMyAtIGExMyAqIGEyMikpO1xuICBvdXRbNV0gPSBhMDAgKiAoYTIyICogYTMzIC0gYTIzICogYTMyKSAtIGEyMCAqIChhMDIgKiBhMzMgLSBhMDMgKiBhMzIpICsgYTMwICogKGEwMiAqIGEyMyAtIGEwMyAqIGEyMik7XG4gIG91dFs2XSA9IC0oYTAwICogKGExMiAqIGEzMyAtIGExMyAqIGEzMikgLSBhMTAgKiAoYTAyICogYTMzIC0gYTAzICogYTMyKSArIGEzMCAqIChhMDIgKiBhMTMgLSBhMDMgKiBhMTIpKTtcbiAgb3V0WzddID0gYTAwICogKGExMiAqIGEyMyAtIGExMyAqIGEyMikgLSBhMTAgKiAoYTAyICogYTIzIC0gYTAzICogYTIyKSArIGEyMCAqIChhMDIgKiBhMTMgLSBhMDMgKiBhMTIpO1xuICBvdXRbOF0gPSBhMTAgKiAoYTIxICogYTMzIC0gYTIzICogYTMxKSAtIGEyMCAqIChhMTEgKiBhMzMgLSBhMTMgKiBhMzEpICsgYTMwICogKGExMSAqIGEyMyAtIGExMyAqIGEyMSk7XG4gIG91dFs5XSA9IC0oYTAwICogKGEyMSAqIGEzMyAtIGEyMyAqIGEzMSkgLSBhMjAgKiAoYTAxICogYTMzIC0gYTAzICogYTMxKSArIGEzMCAqIChhMDEgKiBhMjMgLSBhMDMgKiBhMjEpKTtcbiAgb3V0WzEwXSA9IGEwMCAqIChhMTEgKiBhMzMgLSBhMTMgKiBhMzEpIC0gYTEwICogKGEwMSAqIGEzMyAtIGEwMyAqIGEzMSkgKyBhMzAgKiAoYTAxICogYTEzIC0gYTAzICogYTExKTtcbiAgb3V0WzExXSA9IC0oYTAwICogKGExMSAqIGEyMyAtIGExMyAqIGEyMSkgLSBhMTAgKiAoYTAxICogYTIzIC0gYTAzICogYTIxKSArIGEyMCAqIChhMDEgKiBhMTMgLSBhMDMgKiBhMTEpKTtcbiAgb3V0WzEyXSA9IC0oYTEwICogKGEyMSAqIGEzMiAtIGEyMiAqIGEzMSkgLSBhMjAgKiAoYTExICogYTMyIC0gYTEyICogYTMxKSArIGEzMCAqIChhMTEgKiBhMjIgLSBhMTIgKiBhMjEpKTtcbiAgb3V0WzEzXSA9IGEwMCAqIChhMjEgKiBhMzIgLSBhMjIgKiBhMzEpIC0gYTIwICogKGEwMSAqIGEzMiAtIGEwMiAqIGEzMSkgKyBhMzAgKiAoYTAxICogYTIyIC0gYTAyICogYTIxKTtcbiAgb3V0WzE0XSA9IC0oYTAwICogKGExMSAqIGEzMiAtIGExMiAqIGEzMSkgLSBhMTAgKiAoYTAxICogYTMyIC0gYTAyICogYTMxKSArIGEzMCAqIChhMDEgKiBhMTIgLSBhMDIgKiBhMTEpKTtcbiAgb3V0WzE1XSA9IGEwMCAqIChhMTEgKiBhMjIgLSBhMTIgKiBhMjEpIC0gYTEwICogKGEwMSAqIGEyMiAtIGEwMiAqIGEyMSkgKyBhMjAgKiAoYTAxICogYTEyIC0gYTAyICogYTExKTtcbiAgcmV0dXJuIG91dDtcbn1cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgZGV0ZXJtaW5hbnQgb2YgYSBtYXQ0XG4gKlxuICogQHBhcmFtIHtSZWFkb25seU1hdDR9IGEgdGhlIHNvdXJjZSBtYXRyaXhcbiAqIEByZXR1cm5zIHtOdW1iZXJ9IGRldGVybWluYW50IG9mIGFcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gZGV0ZXJtaW5hbnQoYSkge1xuICB2YXIgYTAwID0gYVswXSxcbiAgICAgIGEwMSA9IGFbMV0sXG4gICAgICBhMDIgPSBhWzJdLFxuICAgICAgYTAzID0gYVszXTtcbiAgdmFyIGExMCA9IGFbNF0sXG4gICAgICBhMTEgPSBhWzVdLFxuICAgICAgYTEyID0gYVs2XSxcbiAgICAgIGExMyA9IGFbN107XG4gIHZhciBhMjAgPSBhWzhdLFxuICAgICAgYTIxID0gYVs5XSxcbiAgICAgIGEyMiA9IGFbMTBdLFxuICAgICAgYTIzID0gYVsxMV07XG4gIHZhciBhMzAgPSBhWzEyXSxcbiAgICAgIGEzMSA9IGFbMTNdLFxuICAgICAgYTMyID0gYVsxNF0sXG4gICAgICBhMzMgPSBhWzE1XTtcbiAgdmFyIGIwMCA9IGEwMCAqIGExMSAtIGEwMSAqIGExMDtcbiAgdmFyIGIwMSA9IGEwMCAqIGExMiAtIGEwMiAqIGExMDtcbiAgdmFyIGIwMiA9IGEwMCAqIGExMyAtIGEwMyAqIGExMDtcbiAgdmFyIGIwMyA9IGEwMSAqIGExMiAtIGEwMiAqIGExMTtcbiAgdmFyIGIwNCA9IGEwMSAqIGExMyAtIGEwMyAqIGExMTtcbiAgdmFyIGIwNSA9IGEwMiAqIGExMyAtIGEwMyAqIGExMjtcbiAgdmFyIGIwNiA9IGEyMCAqIGEzMSAtIGEyMSAqIGEzMDtcbiAgdmFyIGIwNyA9IGEyMCAqIGEzMiAtIGEyMiAqIGEzMDtcbiAgdmFyIGIwOCA9IGEyMCAqIGEzMyAtIGEyMyAqIGEzMDtcbiAgdmFyIGIwOSA9IGEyMSAqIGEzMiAtIGEyMiAqIGEzMTtcbiAgdmFyIGIxMCA9IGEyMSAqIGEzMyAtIGEyMyAqIGEzMTtcbiAgdmFyIGIxMSA9IGEyMiAqIGEzMyAtIGEyMyAqIGEzMjsgLy8gQ2FsY3VsYXRlIHRoZSBkZXRlcm1pbmFudFxuXG4gIHJldHVybiBiMDAgKiBiMTEgLSBiMDEgKiBiMTAgKyBiMDIgKiBiMDkgKyBiMDMgKiBiMDggLSBiMDQgKiBiMDcgKyBiMDUgKiBiMDY7XG59XG4vKipcbiAqIE11bHRpcGxpZXMgdHdvIG1hdDRzXG4gKlxuICogQHBhcmFtIHttYXQ0fSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7UmVhZG9ubHlNYXQ0fSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge1JlYWRvbmx5TWF0NH0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHttYXQ0fSBvdXRcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gbXVsdGlwbHkob3V0LCBhLCBiKSB7XG4gIHZhciBhMDAgPSBhWzBdLFxuICAgICAgYTAxID0gYVsxXSxcbiAgICAgIGEwMiA9IGFbMl0sXG4gICAgICBhMDMgPSBhWzNdO1xuICB2YXIgYTEwID0gYVs0XSxcbiAgICAgIGExMSA9IGFbNV0sXG4gICAgICBhMTIgPSBhWzZdLFxuICAgICAgYTEzID0gYVs3XTtcbiAgdmFyIGEyMCA9IGFbOF0sXG4gICAgICBhMjEgPSBhWzldLFxuICAgICAgYTIyID0gYVsxMF0sXG4gICAgICBhMjMgPSBhWzExXTtcbiAgdmFyIGEzMCA9IGFbMTJdLFxuICAgICAgYTMxID0gYVsxM10sXG4gICAgICBhMzIgPSBhWzE0XSxcbiAgICAgIGEzMyA9IGFbMTVdOyAvLyBDYWNoZSBvbmx5IHRoZSBjdXJyZW50IGxpbmUgb2YgdGhlIHNlY29uZCBtYXRyaXhcblxuICB2YXIgYjAgPSBiWzBdLFxuICAgICAgYjEgPSBiWzFdLFxuICAgICAgYjIgPSBiWzJdLFxuICAgICAgYjMgPSBiWzNdO1xuICBvdXRbMF0gPSBiMCAqIGEwMCArIGIxICogYTEwICsgYjIgKiBhMjAgKyBiMyAqIGEzMDtcbiAgb3V0WzFdID0gYjAgKiBhMDEgKyBiMSAqIGExMSArIGIyICogYTIxICsgYjMgKiBhMzE7XG4gIG91dFsyXSA9IGIwICogYTAyICsgYjEgKiBhMTIgKyBiMiAqIGEyMiArIGIzICogYTMyO1xuICBvdXRbM10gPSBiMCAqIGEwMyArIGIxICogYTEzICsgYjIgKiBhMjMgKyBiMyAqIGEzMztcbiAgYjAgPSBiWzRdO1xuICBiMSA9IGJbNV07XG4gIGIyID0gYls2XTtcbiAgYjMgPSBiWzddO1xuICBvdXRbNF0gPSBiMCAqIGEwMCArIGIxICogYTEwICsgYjIgKiBhMjAgKyBiMyAqIGEzMDtcbiAgb3V0WzVdID0gYjAgKiBhMDEgKyBiMSAqIGExMSArIGIyICogYTIxICsgYjMgKiBhMzE7XG4gIG91dFs2XSA9IGIwICogYTAyICsgYjEgKiBhMTIgKyBiMiAqIGEyMiArIGIzICogYTMyO1xuICBvdXRbN10gPSBiMCAqIGEwMyArIGIxICogYTEzICsgYjIgKiBhMjMgKyBiMyAqIGEzMztcbiAgYjAgPSBiWzhdO1xuICBiMSA9IGJbOV07XG4gIGIyID0gYlsxMF07XG4gIGIzID0gYlsxMV07XG4gIG91dFs4XSA9IGIwICogYTAwICsgYjEgKiBhMTAgKyBiMiAqIGEyMCArIGIzICogYTMwO1xuICBvdXRbOV0gPSBiMCAqIGEwMSArIGIxICogYTExICsgYjIgKiBhMjEgKyBiMyAqIGEzMTtcbiAgb3V0WzEwXSA9IGIwICogYTAyICsgYjEgKiBhMTIgKyBiMiAqIGEyMiArIGIzICogYTMyO1xuICBvdXRbMTFdID0gYjAgKiBhMDMgKyBiMSAqIGExMyArIGIyICogYTIzICsgYjMgKiBhMzM7XG4gIGIwID0gYlsxMl07XG4gIGIxID0gYlsxM107XG4gIGIyID0gYlsxNF07XG4gIGIzID0gYlsxNV07XG4gIG91dFsxMl0gPSBiMCAqIGEwMCArIGIxICogYTEwICsgYjIgKiBhMjAgKyBiMyAqIGEzMDtcbiAgb3V0WzEzXSA9IGIwICogYTAxICsgYjEgKiBhMTEgKyBiMiAqIGEyMSArIGIzICogYTMxO1xuICBvdXRbMTRdID0gYjAgKiBhMDIgKyBiMSAqIGExMiArIGIyICogYTIyICsgYjMgKiBhMzI7XG4gIG91dFsxNV0gPSBiMCAqIGEwMyArIGIxICogYTEzICsgYjIgKiBhMjMgKyBiMyAqIGEzMztcbiAgcmV0dXJuIG91dDtcbn1cbi8qKlxuICogVHJhbnNsYXRlIGEgbWF0NCBieSB0aGUgZ2l2ZW4gdmVjdG9yXG4gKlxuICogQHBhcmFtIHttYXQ0fSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7UmVhZG9ubHlNYXQ0fSBhIHRoZSBtYXRyaXggdG8gdHJhbnNsYXRlXG4gKiBAcGFyYW0ge1JlYWRvbmx5VmVjM30gdiB2ZWN0b3IgdG8gdHJhbnNsYXRlIGJ5XG4gKiBAcmV0dXJucyB7bWF0NH0gb3V0XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIHRyYW5zbGF0ZShvdXQsIGEsIHYpIHtcbiAgdmFyIHggPSB2WzBdLFxuICAgICAgeSA9IHZbMV0sXG4gICAgICB6ID0gdlsyXTtcbiAgdmFyIGEwMCwgYTAxLCBhMDIsIGEwMztcbiAgdmFyIGExMCwgYTExLCBhMTIsIGExMztcbiAgdmFyIGEyMCwgYTIxLCBhMjIsIGEyMztcblxuICBpZiAoYSA9PT0gb3V0KSB7XG4gICAgb3V0WzEyXSA9IGFbMF0gKiB4ICsgYVs0XSAqIHkgKyBhWzhdICogeiArIGFbMTJdO1xuICAgIG91dFsxM10gPSBhWzFdICogeCArIGFbNV0gKiB5ICsgYVs5XSAqIHogKyBhWzEzXTtcbiAgICBvdXRbMTRdID0gYVsyXSAqIHggKyBhWzZdICogeSArIGFbMTBdICogeiArIGFbMTRdO1xuICAgIG91dFsxNV0gPSBhWzNdICogeCArIGFbN10gKiB5ICsgYVsxMV0gKiB6ICsgYVsxNV07XG4gIH0gZWxzZSB7XG4gICAgYTAwID0gYVswXTtcbiAgICBhMDEgPSBhWzFdO1xuICAgIGEwMiA9IGFbMl07XG4gICAgYTAzID0gYVszXTtcbiAgICBhMTAgPSBhWzRdO1xuICAgIGExMSA9IGFbNV07XG4gICAgYTEyID0gYVs2XTtcbiAgICBhMTMgPSBhWzddO1xuICAgIGEyMCA9IGFbOF07XG4gICAgYTIxID0gYVs5XTtcbiAgICBhMjIgPSBhWzEwXTtcbiAgICBhMjMgPSBhWzExXTtcbiAgICBvdXRbMF0gPSBhMDA7XG4gICAgb3V0WzFdID0gYTAxO1xuICAgIG91dFsyXSA9IGEwMjtcbiAgICBvdXRbM10gPSBhMDM7XG4gICAgb3V0WzRdID0gYTEwO1xuICAgIG91dFs1XSA9IGExMTtcbiAgICBvdXRbNl0gPSBhMTI7XG4gICAgb3V0WzddID0gYTEzO1xuICAgIG91dFs4XSA9IGEyMDtcbiAgICBvdXRbOV0gPSBhMjE7XG4gICAgb3V0WzEwXSA9IGEyMjtcbiAgICBvdXRbMTFdID0gYTIzO1xuICAgIG91dFsxMl0gPSBhMDAgKiB4ICsgYTEwICogeSArIGEyMCAqIHogKyBhWzEyXTtcbiAgICBvdXRbMTNdID0gYTAxICogeCArIGExMSAqIHkgKyBhMjEgKiB6ICsgYVsxM107XG4gICAgb3V0WzE0XSA9IGEwMiAqIHggKyBhMTIgKiB5ICsgYTIyICogeiArIGFbMTRdO1xuICAgIG91dFsxNV0gPSBhMDMgKiB4ICsgYTEzICogeSArIGEyMyAqIHogKyBhWzE1XTtcbiAgfVxuXG4gIHJldHVybiBvdXQ7XG59XG4vKipcbiAqIFNjYWxlcyB0aGUgbWF0NCBieSB0aGUgZGltZW5zaW9ucyBpbiB0aGUgZ2l2ZW4gdmVjMyBub3QgdXNpbmcgdmVjdG9yaXphdGlvblxuICpcbiAqIEBwYXJhbSB7bWF0NH0gb3V0IHRoZSByZWNlaXZpbmcgbWF0cml4XG4gKiBAcGFyYW0ge1JlYWRvbmx5TWF0NH0gYSB0aGUgbWF0cml4IHRvIHNjYWxlXG4gKiBAcGFyYW0ge1JlYWRvbmx5VmVjM30gdiB0aGUgdmVjMyB0byBzY2FsZSB0aGUgbWF0cml4IGJ5XG4gKiBAcmV0dXJucyB7bWF0NH0gb3V0XG4gKiovXG5cbmV4cG9ydCBmdW5jdGlvbiBzY2FsZShvdXQsIGEsIHYpIHtcbiAgdmFyIHggPSB2WzBdLFxuICAgICAgeSA9IHZbMV0sXG4gICAgICB6ID0gdlsyXTtcbiAgb3V0WzBdID0gYVswXSAqIHg7XG4gIG91dFsxXSA9IGFbMV0gKiB4O1xuICBvdXRbMl0gPSBhWzJdICogeDtcbiAgb3V0WzNdID0gYVszXSAqIHg7XG4gIG91dFs0XSA9IGFbNF0gKiB5O1xuICBvdXRbNV0gPSBhWzVdICogeTtcbiAgb3V0WzZdID0gYVs2XSAqIHk7XG4gIG91dFs3XSA9IGFbN10gKiB5O1xuICBvdXRbOF0gPSBhWzhdICogejtcbiAgb3V0WzldID0gYVs5XSAqIHo7XG4gIG91dFsxMF0gPSBhWzEwXSAqIHo7XG4gIG91dFsxMV0gPSBhWzExXSAqIHo7XG4gIG91dFsxMl0gPSBhWzEyXTtcbiAgb3V0WzEzXSA9IGFbMTNdO1xuICBvdXRbMTRdID0gYVsxNF07XG4gIG91dFsxNV0gPSBhWzE1XTtcbiAgcmV0dXJuIG91dDtcbn1cbi8qKlxuICogUm90YXRlcyBhIG1hdDQgYnkgdGhlIGdpdmVuIGFuZ2xlIGFyb3VuZCB0aGUgZ2l2ZW4gYXhpc1xuICpcbiAqIEBwYXJhbSB7bWF0NH0gb3V0IHRoZSByZWNlaXZpbmcgbWF0cml4XG4gKiBAcGFyYW0ge1JlYWRvbmx5TWF0NH0gYSB0aGUgbWF0cml4IHRvIHJvdGF0ZVxuICogQHBhcmFtIHtOdW1iZXJ9IHJhZCB0aGUgYW5nbGUgdG8gcm90YXRlIHRoZSBtYXRyaXggYnlcbiAqIEBwYXJhbSB7UmVhZG9ubHlWZWMzfSBheGlzIHRoZSBheGlzIHRvIHJvdGF0ZSBhcm91bmRcbiAqIEByZXR1cm5zIHttYXQ0fSBvdXRcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gcm90YXRlKG91dCwgYSwgcmFkLCBheGlzKSB7XG4gIHZhciB4ID0gYXhpc1swXSxcbiAgICAgIHkgPSBheGlzWzFdLFxuICAgICAgeiA9IGF4aXNbMl07XG4gIHZhciBsZW4gPSBNYXRoLmh5cG90KHgsIHksIHopO1xuICB2YXIgcywgYywgdDtcbiAgdmFyIGEwMCwgYTAxLCBhMDIsIGEwMztcbiAgdmFyIGExMCwgYTExLCBhMTIsIGExMztcbiAgdmFyIGEyMCwgYTIxLCBhMjIsIGEyMztcbiAgdmFyIGIwMCwgYjAxLCBiMDI7XG4gIHZhciBiMTAsIGIxMSwgYjEyO1xuICB2YXIgYjIwLCBiMjEsIGIyMjtcblxuICBpZiAobGVuIDwgZ2xNYXRyaXguRVBTSUxPTikge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgbGVuID0gMSAvIGxlbjtcbiAgeCAqPSBsZW47XG4gIHkgKj0gbGVuO1xuICB6ICo9IGxlbjtcbiAgcyA9IE1hdGguc2luKHJhZCk7XG4gIGMgPSBNYXRoLmNvcyhyYWQpO1xuICB0ID0gMSAtIGM7XG4gIGEwMCA9IGFbMF07XG4gIGEwMSA9IGFbMV07XG4gIGEwMiA9IGFbMl07XG4gIGEwMyA9IGFbM107XG4gIGExMCA9IGFbNF07XG4gIGExMSA9IGFbNV07XG4gIGExMiA9IGFbNl07XG4gIGExMyA9IGFbN107XG4gIGEyMCA9IGFbOF07XG4gIGEyMSA9IGFbOV07XG4gIGEyMiA9IGFbMTBdO1xuICBhMjMgPSBhWzExXTsgLy8gQ29uc3RydWN0IHRoZSBlbGVtZW50cyBvZiB0aGUgcm90YXRpb24gbWF0cml4XG5cbiAgYjAwID0geCAqIHggKiB0ICsgYztcbiAgYjAxID0geSAqIHggKiB0ICsgeiAqIHM7XG4gIGIwMiA9IHogKiB4ICogdCAtIHkgKiBzO1xuICBiMTAgPSB4ICogeSAqIHQgLSB6ICogcztcbiAgYjExID0geSAqIHkgKiB0ICsgYztcbiAgYjEyID0geiAqIHkgKiB0ICsgeCAqIHM7XG4gIGIyMCA9IHggKiB6ICogdCArIHkgKiBzO1xuICBiMjEgPSB5ICogeiAqIHQgLSB4ICogcztcbiAgYjIyID0geiAqIHogKiB0ICsgYzsgLy8gUGVyZm9ybSByb3RhdGlvbi1zcGVjaWZpYyBtYXRyaXggbXVsdGlwbGljYXRpb25cblxuICBvdXRbMF0gPSBhMDAgKiBiMDAgKyBhMTAgKiBiMDEgKyBhMjAgKiBiMDI7XG4gIG91dFsxXSA9IGEwMSAqIGIwMCArIGExMSAqIGIwMSArIGEyMSAqIGIwMjtcbiAgb3V0WzJdID0gYTAyICogYjAwICsgYTEyICogYjAxICsgYTIyICogYjAyO1xuICBvdXRbM10gPSBhMDMgKiBiMDAgKyBhMTMgKiBiMDEgKyBhMjMgKiBiMDI7XG4gIG91dFs0XSA9IGEwMCAqIGIxMCArIGExMCAqIGIxMSArIGEyMCAqIGIxMjtcbiAgb3V0WzVdID0gYTAxICogYjEwICsgYTExICogYjExICsgYTIxICogYjEyO1xuICBvdXRbNl0gPSBhMDIgKiBiMTAgKyBhMTIgKiBiMTEgKyBhMjIgKiBiMTI7XG4gIG91dFs3XSA9IGEwMyAqIGIxMCArIGExMyAqIGIxMSArIGEyMyAqIGIxMjtcbiAgb3V0WzhdID0gYTAwICogYjIwICsgYTEwICogYjIxICsgYTIwICogYjIyO1xuICBvdXRbOV0gPSBhMDEgKiBiMjAgKyBhMTEgKiBiMjEgKyBhMjEgKiBiMjI7XG4gIG91dFsxMF0gPSBhMDIgKiBiMjAgKyBhMTIgKiBiMjEgKyBhMjIgKiBiMjI7XG4gIG91dFsxMV0gPSBhMDMgKiBiMjAgKyBhMTMgKiBiMjEgKyBhMjMgKiBiMjI7XG5cbiAgaWYgKGEgIT09IG91dCkge1xuICAgIC8vIElmIHRoZSBzb3VyY2UgYW5kIGRlc3RpbmF0aW9uIGRpZmZlciwgY29weSB0aGUgdW5jaGFuZ2VkIGxhc3Qgcm93XG4gICAgb3V0WzEyXSA9IGFbMTJdO1xuICAgIG91dFsxM10gPSBhWzEzXTtcbiAgICBvdXRbMTRdID0gYVsxNF07XG4gICAgb3V0WzE1XSA9IGFbMTVdO1xuICB9XG5cbiAgcmV0dXJuIG91dDtcbn1cbi8qKlxuICogUm90YXRlcyBhIG1hdHJpeCBieSB0aGUgZ2l2ZW4gYW5nbGUgYXJvdW5kIHRoZSBYIGF4aXNcbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHtSZWFkb25seU1hdDR9IGEgdGhlIG1hdHJpeCB0byByb3RhdGVcbiAqIEBwYXJhbSB7TnVtYmVyfSByYWQgdGhlIGFuZ2xlIHRvIHJvdGF0ZSB0aGUgbWF0cml4IGJ5XG4gKiBAcmV0dXJucyB7bWF0NH0gb3V0XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIHJvdGF0ZVgob3V0LCBhLCByYWQpIHtcbiAgdmFyIHMgPSBNYXRoLnNpbihyYWQpO1xuICB2YXIgYyA9IE1hdGguY29zKHJhZCk7XG4gIHZhciBhMTAgPSBhWzRdO1xuICB2YXIgYTExID0gYVs1XTtcbiAgdmFyIGExMiA9IGFbNl07XG4gIHZhciBhMTMgPSBhWzddO1xuICB2YXIgYTIwID0gYVs4XTtcbiAgdmFyIGEyMSA9IGFbOV07XG4gIHZhciBhMjIgPSBhWzEwXTtcbiAgdmFyIGEyMyA9IGFbMTFdO1xuXG4gIGlmIChhICE9PSBvdXQpIHtcbiAgICAvLyBJZiB0aGUgc291cmNlIGFuZCBkZXN0aW5hdGlvbiBkaWZmZXIsIGNvcHkgdGhlIHVuY2hhbmdlZCByb3dzXG4gICAgb3V0WzBdID0gYVswXTtcbiAgICBvdXRbMV0gPSBhWzFdO1xuICAgIG91dFsyXSA9IGFbMl07XG4gICAgb3V0WzNdID0gYVszXTtcbiAgICBvdXRbMTJdID0gYVsxMl07XG4gICAgb3V0WzEzXSA9IGFbMTNdO1xuICAgIG91dFsxNF0gPSBhWzE0XTtcbiAgICBvdXRbMTVdID0gYVsxNV07XG4gIH0gLy8gUGVyZm9ybSBheGlzLXNwZWNpZmljIG1hdHJpeCBtdWx0aXBsaWNhdGlvblxuXG5cbiAgb3V0WzRdID0gYTEwICogYyArIGEyMCAqIHM7XG4gIG91dFs1XSA9IGExMSAqIGMgKyBhMjEgKiBzO1xuICBvdXRbNl0gPSBhMTIgKiBjICsgYTIyICogcztcbiAgb3V0WzddID0gYTEzICogYyArIGEyMyAqIHM7XG4gIG91dFs4XSA9IGEyMCAqIGMgLSBhMTAgKiBzO1xuICBvdXRbOV0gPSBhMjEgKiBjIC0gYTExICogcztcbiAgb3V0WzEwXSA9IGEyMiAqIGMgLSBhMTIgKiBzO1xuICBvdXRbMTFdID0gYTIzICogYyAtIGExMyAqIHM7XG4gIHJldHVybiBvdXQ7XG59XG4vKipcbiAqIFJvdGF0ZXMgYSBtYXRyaXggYnkgdGhlIGdpdmVuIGFuZ2xlIGFyb3VuZCB0aGUgWSBheGlzXG4gKlxuICogQHBhcmFtIHttYXQ0fSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7UmVhZG9ubHlNYXQ0fSBhIHRoZSBtYXRyaXggdG8gcm90YXRlXG4gKiBAcGFyYW0ge051bWJlcn0gcmFkIHRoZSBhbmdsZSB0byByb3RhdGUgdGhlIG1hdHJpeCBieVxuICogQHJldHVybnMge21hdDR9IG91dFxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiByb3RhdGVZKG91dCwgYSwgcmFkKSB7XG4gIHZhciBzID0gTWF0aC5zaW4ocmFkKTtcbiAgdmFyIGMgPSBNYXRoLmNvcyhyYWQpO1xuICB2YXIgYTAwID0gYVswXTtcbiAgdmFyIGEwMSA9IGFbMV07XG4gIHZhciBhMDIgPSBhWzJdO1xuICB2YXIgYTAzID0gYVszXTtcbiAgdmFyIGEyMCA9IGFbOF07XG4gIHZhciBhMjEgPSBhWzldO1xuICB2YXIgYTIyID0gYVsxMF07XG4gIHZhciBhMjMgPSBhWzExXTtcblxuICBpZiAoYSAhPT0gb3V0KSB7XG4gICAgLy8gSWYgdGhlIHNvdXJjZSBhbmQgZGVzdGluYXRpb24gZGlmZmVyLCBjb3B5IHRoZSB1bmNoYW5nZWQgcm93c1xuICAgIG91dFs0XSA9IGFbNF07XG4gICAgb3V0WzVdID0gYVs1XTtcbiAgICBvdXRbNl0gPSBhWzZdO1xuICAgIG91dFs3XSA9IGFbN107XG4gICAgb3V0WzEyXSA9IGFbMTJdO1xuICAgIG91dFsxM10gPSBhWzEzXTtcbiAgICBvdXRbMTRdID0gYVsxNF07XG4gICAgb3V0WzE1XSA9IGFbMTVdO1xuICB9IC8vIFBlcmZvcm0gYXhpcy1zcGVjaWZpYyBtYXRyaXggbXVsdGlwbGljYXRpb25cblxuXG4gIG91dFswXSA9IGEwMCAqIGMgLSBhMjAgKiBzO1xuICBvdXRbMV0gPSBhMDEgKiBjIC0gYTIxICogcztcbiAgb3V0WzJdID0gYTAyICogYyAtIGEyMiAqIHM7XG4gIG91dFszXSA9IGEwMyAqIGMgLSBhMjMgKiBzO1xuICBvdXRbOF0gPSBhMDAgKiBzICsgYTIwICogYztcbiAgb3V0WzldID0gYTAxICogcyArIGEyMSAqIGM7XG4gIG91dFsxMF0gPSBhMDIgKiBzICsgYTIyICogYztcbiAgb3V0WzExXSA9IGEwMyAqIHMgKyBhMjMgKiBjO1xuICByZXR1cm4gb3V0O1xufVxuLyoqXG4gKiBSb3RhdGVzIGEgbWF0cml4IGJ5IHRoZSBnaXZlbiBhbmdsZSBhcm91bmQgdGhlIFogYXhpc1xuICpcbiAqIEBwYXJhbSB7bWF0NH0gb3V0IHRoZSByZWNlaXZpbmcgbWF0cml4XG4gKiBAcGFyYW0ge1JlYWRvbmx5TWF0NH0gYSB0aGUgbWF0cml4IHRvIHJvdGF0ZVxuICogQHBhcmFtIHtOdW1iZXJ9IHJhZCB0aGUgYW5nbGUgdG8gcm90YXRlIHRoZSBtYXRyaXggYnlcbiAqIEByZXR1cm5zIHttYXQ0fSBvdXRcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gcm90YXRlWihvdXQsIGEsIHJhZCkge1xuICB2YXIgcyA9IE1hdGguc2luKHJhZCk7XG4gIHZhciBjID0gTWF0aC5jb3MocmFkKTtcbiAgdmFyIGEwMCA9IGFbMF07XG4gIHZhciBhMDEgPSBhWzFdO1xuICB2YXIgYTAyID0gYVsyXTtcbiAgdmFyIGEwMyA9IGFbM107XG4gIHZhciBhMTAgPSBhWzRdO1xuICB2YXIgYTExID0gYVs1XTtcbiAgdmFyIGExMiA9IGFbNl07XG4gIHZhciBhMTMgPSBhWzddO1xuXG4gIGlmIChhICE9PSBvdXQpIHtcbiAgICAvLyBJZiB0aGUgc291cmNlIGFuZCBkZXN0aW5hdGlvbiBkaWZmZXIsIGNvcHkgdGhlIHVuY2hhbmdlZCBsYXN0IHJvd1xuICAgIG91dFs4XSA9IGFbOF07XG4gICAgb3V0WzldID0gYVs5XTtcbiAgICBvdXRbMTBdID0gYVsxMF07XG4gICAgb3V0WzExXSA9IGFbMTFdO1xuICAgIG91dFsxMl0gPSBhWzEyXTtcbiAgICBvdXRbMTNdID0gYVsxM107XG4gICAgb3V0WzE0XSA9IGFbMTRdO1xuICAgIG91dFsxNV0gPSBhWzE1XTtcbiAgfSAvLyBQZXJmb3JtIGF4aXMtc3BlY2lmaWMgbWF0cml4IG11bHRpcGxpY2F0aW9uXG5cblxuICBvdXRbMF0gPSBhMDAgKiBjICsgYTEwICogcztcbiAgb3V0WzFdID0gYTAxICogYyArIGExMSAqIHM7XG4gIG91dFsyXSA9IGEwMiAqIGMgKyBhMTIgKiBzO1xuICBvdXRbM10gPSBhMDMgKiBjICsgYTEzICogcztcbiAgb3V0WzRdID0gYTEwICogYyAtIGEwMCAqIHM7XG4gIG91dFs1XSA9IGExMSAqIGMgLSBhMDEgKiBzO1xuICBvdXRbNl0gPSBhMTIgKiBjIC0gYTAyICogcztcbiAgb3V0WzddID0gYTEzICogYyAtIGEwMyAqIHM7XG4gIHJldHVybiBvdXQ7XG59XG4vKipcbiAqIENyZWF0ZXMgYSBtYXRyaXggZnJvbSBhIHZlY3RvciB0cmFuc2xhdGlvblxuICogVGhpcyBpcyBlcXVpdmFsZW50IHRvIChidXQgbXVjaCBmYXN0ZXIgdGhhbik6XG4gKlxuICogICAgIG1hdDQuaWRlbnRpdHkoZGVzdCk7XG4gKiAgICAgbWF0NC50cmFuc2xhdGUoZGVzdCwgZGVzdCwgdmVjKTtcbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCBtYXQ0IHJlY2VpdmluZyBvcGVyYXRpb24gcmVzdWx0XG4gKiBAcGFyYW0ge1JlYWRvbmx5VmVjM30gdiBUcmFuc2xhdGlvbiB2ZWN0b3JcbiAqIEByZXR1cm5zIHttYXQ0fSBvdXRcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gZnJvbVRyYW5zbGF0aW9uKG91dCwgdikge1xuICBvdXRbMF0gPSAxO1xuICBvdXRbMV0gPSAwO1xuICBvdXRbMl0gPSAwO1xuICBvdXRbM10gPSAwO1xuICBvdXRbNF0gPSAwO1xuICBvdXRbNV0gPSAxO1xuICBvdXRbNl0gPSAwO1xuICBvdXRbN10gPSAwO1xuICBvdXRbOF0gPSAwO1xuICBvdXRbOV0gPSAwO1xuICBvdXRbMTBdID0gMTtcbiAgb3V0WzExXSA9IDA7XG4gIG91dFsxMl0gPSB2WzBdO1xuICBvdXRbMTNdID0gdlsxXTtcbiAgb3V0WzE0XSA9IHZbMl07XG4gIG91dFsxNV0gPSAxO1xuICByZXR1cm4gb3V0O1xufVxuLyoqXG4gKiBDcmVhdGVzIGEgbWF0cml4IGZyb20gYSB2ZWN0b3Igc2NhbGluZ1xuICogVGhpcyBpcyBlcXVpdmFsZW50IHRvIChidXQgbXVjaCBmYXN0ZXIgdGhhbik6XG4gKlxuICogICAgIG1hdDQuaWRlbnRpdHkoZGVzdCk7XG4gKiAgICAgbWF0NC5zY2FsZShkZXN0LCBkZXN0LCB2ZWMpO1xuICpcbiAqIEBwYXJhbSB7bWF0NH0gb3V0IG1hdDQgcmVjZWl2aW5nIG9wZXJhdGlvbiByZXN1bHRcbiAqIEBwYXJhbSB7UmVhZG9ubHlWZWMzfSB2IFNjYWxpbmcgdmVjdG9yXG4gKiBAcmV0dXJucyB7bWF0NH0gb3V0XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGZyb21TY2FsaW5nKG91dCwgdikge1xuICBvdXRbMF0gPSB2WzBdO1xuICBvdXRbMV0gPSAwO1xuICBvdXRbMl0gPSAwO1xuICBvdXRbM10gPSAwO1xuICBvdXRbNF0gPSAwO1xuICBvdXRbNV0gPSB2WzFdO1xuICBvdXRbNl0gPSAwO1xuICBvdXRbN10gPSAwO1xuICBvdXRbOF0gPSAwO1xuICBvdXRbOV0gPSAwO1xuICBvdXRbMTBdID0gdlsyXTtcbiAgb3V0WzExXSA9IDA7XG4gIG91dFsxMl0gPSAwO1xuICBvdXRbMTNdID0gMDtcbiAgb3V0WzE0XSA9IDA7XG4gIG91dFsxNV0gPSAxO1xuICByZXR1cm4gb3V0O1xufVxuLyoqXG4gKiBDcmVhdGVzIGEgbWF0cml4IGZyb20gYSBnaXZlbiBhbmdsZSBhcm91bmQgYSBnaXZlbiBheGlzXG4gKiBUaGlzIGlzIGVxdWl2YWxlbnQgdG8gKGJ1dCBtdWNoIGZhc3RlciB0aGFuKTpcbiAqXG4gKiAgICAgbWF0NC5pZGVudGl0eShkZXN0KTtcbiAqICAgICBtYXQ0LnJvdGF0ZShkZXN0LCBkZXN0LCByYWQsIGF4aXMpO1xuICpcbiAqIEBwYXJhbSB7bWF0NH0gb3V0IG1hdDQgcmVjZWl2aW5nIG9wZXJhdGlvbiByZXN1bHRcbiAqIEBwYXJhbSB7TnVtYmVyfSByYWQgdGhlIGFuZ2xlIHRvIHJvdGF0ZSB0aGUgbWF0cml4IGJ5XG4gKiBAcGFyYW0ge1JlYWRvbmx5VmVjM30gYXhpcyB0aGUgYXhpcyB0byByb3RhdGUgYXJvdW5kXG4gKiBAcmV0dXJucyB7bWF0NH0gb3V0XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGZyb21Sb3RhdGlvbihvdXQsIHJhZCwgYXhpcykge1xuICB2YXIgeCA9IGF4aXNbMF0sXG4gICAgICB5ID0gYXhpc1sxXSxcbiAgICAgIHogPSBheGlzWzJdO1xuICB2YXIgbGVuID0gTWF0aC5oeXBvdCh4LCB5LCB6KTtcbiAgdmFyIHMsIGMsIHQ7XG5cbiAgaWYgKGxlbiA8IGdsTWF0cml4LkVQU0lMT04pIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGxlbiA9IDEgLyBsZW47XG4gIHggKj0gbGVuO1xuICB5ICo9IGxlbjtcbiAgeiAqPSBsZW47XG4gIHMgPSBNYXRoLnNpbihyYWQpO1xuICBjID0gTWF0aC5jb3MocmFkKTtcbiAgdCA9IDEgLSBjOyAvLyBQZXJmb3JtIHJvdGF0aW9uLXNwZWNpZmljIG1hdHJpeCBtdWx0aXBsaWNhdGlvblxuXG4gIG91dFswXSA9IHggKiB4ICogdCArIGM7XG4gIG91dFsxXSA9IHkgKiB4ICogdCArIHogKiBzO1xuICBvdXRbMl0gPSB6ICogeCAqIHQgLSB5ICogcztcbiAgb3V0WzNdID0gMDtcbiAgb3V0WzRdID0geCAqIHkgKiB0IC0geiAqIHM7XG4gIG91dFs1XSA9IHkgKiB5ICogdCArIGM7XG4gIG91dFs2XSA9IHogKiB5ICogdCArIHggKiBzO1xuICBvdXRbN10gPSAwO1xuICBvdXRbOF0gPSB4ICogeiAqIHQgKyB5ICogcztcbiAgb3V0WzldID0geSAqIHogKiB0IC0geCAqIHM7XG4gIG91dFsxMF0gPSB6ICogeiAqIHQgKyBjO1xuICBvdXRbMTFdID0gMDtcbiAgb3V0WzEyXSA9IDA7XG4gIG91dFsxM10gPSAwO1xuICBvdXRbMTRdID0gMDtcbiAgb3V0WzE1XSA9IDE7XG4gIHJldHVybiBvdXQ7XG59XG4vKipcbiAqIENyZWF0ZXMgYSBtYXRyaXggZnJvbSB0aGUgZ2l2ZW4gYW5nbGUgYXJvdW5kIHRoZSBYIGF4aXNcbiAqIFRoaXMgaXMgZXF1aXZhbGVudCB0byAoYnV0IG11Y2ggZmFzdGVyIHRoYW4pOlxuICpcbiAqICAgICBtYXQ0LmlkZW50aXR5KGRlc3QpO1xuICogICAgIG1hdDQucm90YXRlWChkZXN0LCBkZXN0LCByYWQpO1xuICpcbiAqIEBwYXJhbSB7bWF0NH0gb3V0IG1hdDQgcmVjZWl2aW5nIG9wZXJhdGlvbiByZXN1bHRcbiAqIEBwYXJhbSB7TnVtYmVyfSByYWQgdGhlIGFuZ2xlIHRvIHJvdGF0ZSB0aGUgbWF0cml4IGJ5XG4gKiBAcmV0dXJucyB7bWF0NH0gb3V0XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGZyb21YUm90YXRpb24ob3V0LCByYWQpIHtcbiAgdmFyIHMgPSBNYXRoLnNpbihyYWQpO1xuICB2YXIgYyA9IE1hdGguY29zKHJhZCk7IC8vIFBlcmZvcm0gYXhpcy1zcGVjaWZpYyBtYXRyaXggbXVsdGlwbGljYXRpb25cblxuICBvdXRbMF0gPSAxO1xuICBvdXRbMV0gPSAwO1xuICBvdXRbMl0gPSAwO1xuICBvdXRbM10gPSAwO1xuICBvdXRbNF0gPSAwO1xuICBvdXRbNV0gPSBjO1xuICBvdXRbNl0gPSBzO1xuICBvdXRbN10gPSAwO1xuICBvdXRbOF0gPSAwO1xuICBvdXRbOV0gPSAtcztcbiAgb3V0WzEwXSA9IGM7XG4gIG91dFsxMV0gPSAwO1xuICBvdXRbMTJdID0gMDtcbiAgb3V0WzEzXSA9IDA7XG4gIG91dFsxNF0gPSAwO1xuICBvdXRbMTVdID0gMTtcbiAgcmV0dXJuIG91dDtcbn1cbi8qKlxuICogQ3JlYXRlcyBhIG1hdHJpeCBmcm9tIHRoZSBnaXZlbiBhbmdsZSBhcm91bmQgdGhlIFkgYXhpc1xuICogVGhpcyBpcyBlcXVpdmFsZW50IHRvIChidXQgbXVjaCBmYXN0ZXIgdGhhbik6XG4gKlxuICogICAgIG1hdDQuaWRlbnRpdHkoZGVzdCk7XG4gKiAgICAgbWF0NC5yb3RhdGVZKGRlc3QsIGRlc3QsIHJhZCk7XG4gKlxuICogQHBhcmFtIHttYXQ0fSBvdXQgbWF0NCByZWNlaXZpbmcgb3BlcmF0aW9uIHJlc3VsdFxuICogQHBhcmFtIHtOdW1iZXJ9IHJhZCB0aGUgYW5nbGUgdG8gcm90YXRlIHRoZSBtYXRyaXggYnlcbiAqIEByZXR1cm5zIHttYXQ0fSBvdXRcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gZnJvbVlSb3RhdGlvbihvdXQsIHJhZCkge1xuICB2YXIgcyA9IE1hdGguc2luKHJhZCk7XG4gIHZhciBjID0gTWF0aC5jb3MocmFkKTsgLy8gUGVyZm9ybSBheGlzLXNwZWNpZmljIG1hdHJpeCBtdWx0aXBsaWNhdGlvblxuXG4gIG91dFswXSA9IGM7XG4gIG91dFsxXSA9IDA7XG4gIG91dFsyXSA9IC1zO1xuICBvdXRbM10gPSAwO1xuICBvdXRbNF0gPSAwO1xuICBvdXRbNV0gPSAxO1xuICBvdXRbNl0gPSAwO1xuICBvdXRbN10gPSAwO1xuICBvdXRbOF0gPSBzO1xuICBvdXRbOV0gPSAwO1xuICBvdXRbMTBdID0gYztcbiAgb3V0WzExXSA9IDA7XG4gIG91dFsxMl0gPSAwO1xuICBvdXRbMTNdID0gMDtcbiAgb3V0WzE0XSA9IDA7XG4gIG91dFsxNV0gPSAxO1xuICByZXR1cm4gb3V0O1xufVxuLyoqXG4gKiBDcmVhdGVzIGEgbWF0cml4IGZyb20gdGhlIGdpdmVuIGFuZ2xlIGFyb3VuZCB0aGUgWiBheGlzXG4gKiBUaGlzIGlzIGVxdWl2YWxlbnQgdG8gKGJ1dCBtdWNoIGZhc3RlciB0aGFuKTpcbiAqXG4gKiAgICAgbWF0NC5pZGVudGl0eShkZXN0KTtcbiAqICAgICBtYXQ0LnJvdGF0ZVooZGVzdCwgZGVzdCwgcmFkKTtcbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCBtYXQ0IHJlY2VpdmluZyBvcGVyYXRpb24gcmVzdWx0XG4gKiBAcGFyYW0ge051bWJlcn0gcmFkIHRoZSBhbmdsZSB0byByb3RhdGUgdGhlIG1hdHJpeCBieVxuICogQHJldHVybnMge21hdDR9IG91dFxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBmcm9tWlJvdGF0aW9uKG91dCwgcmFkKSB7XG4gIHZhciBzID0gTWF0aC5zaW4ocmFkKTtcbiAgdmFyIGMgPSBNYXRoLmNvcyhyYWQpOyAvLyBQZXJmb3JtIGF4aXMtc3BlY2lmaWMgbWF0cml4IG11bHRpcGxpY2F0aW9uXG5cbiAgb3V0WzBdID0gYztcbiAgb3V0WzFdID0gcztcbiAgb3V0WzJdID0gMDtcbiAgb3V0WzNdID0gMDtcbiAgb3V0WzRdID0gLXM7XG4gIG91dFs1XSA9IGM7XG4gIG91dFs2XSA9IDA7XG4gIG91dFs3XSA9IDA7XG4gIG91dFs4XSA9IDA7XG4gIG91dFs5XSA9IDA7XG4gIG91dFsxMF0gPSAxO1xuICBvdXRbMTFdID0gMDtcbiAgb3V0WzEyXSA9IDA7XG4gIG91dFsxM10gPSAwO1xuICBvdXRbMTRdID0gMDtcbiAgb3V0WzE1XSA9IDE7XG4gIHJldHVybiBvdXQ7XG59XG4vKipcbiAqIENyZWF0ZXMgYSBtYXRyaXggZnJvbSBhIHF1YXRlcm5pb24gcm90YXRpb24gYW5kIHZlY3RvciB0cmFuc2xhdGlvblxuICogVGhpcyBpcyBlcXVpdmFsZW50IHRvIChidXQgbXVjaCBmYXN0ZXIgdGhhbik6XG4gKlxuICogICAgIG1hdDQuaWRlbnRpdHkoZGVzdCk7XG4gKiAgICAgbWF0NC50cmFuc2xhdGUoZGVzdCwgdmVjKTtcbiAqICAgICBsZXQgcXVhdE1hdCA9IG1hdDQuY3JlYXRlKCk7XG4gKiAgICAgcXVhdDQudG9NYXQ0KHF1YXQsIHF1YXRNYXQpO1xuICogICAgIG1hdDQubXVsdGlwbHkoZGVzdCwgcXVhdE1hdCk7XG4gKlxuICogQHBhcmFtIHttYXQ0fSBvdXQgbWF0NCByZWNlaXZpbmcgb3BlcmF0aW9uIHJlc3VsdFxuICogQHBhcmFtIHtxdWF0NH0gcSBSb3RhdGlvbiBxdWF0ZXJuaW9uXG4gKiBAcGFyYW0ge1JlYWRvbmx5VmVjM30gdiBUcmFuc2xhdGlvbiB2ZWN0b3JcbiAqIEByZXR1cm5zIHttYXQ0fSBvdXRcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gZnJvbVJvdGF0aW9uVHJhbnNsYXRpb24ob3V0LCBxLCB2KSB7XG4gIC8vIFF1YXRlcm5pb24gbWF0aFxuICB2YXIgeCA9IHFbMF0sXG4gICAgICB5ID0gcVsxXSxcbiAgICAgIHogPSBxWzJdLFxuICAgICAgdyA9IHFbM107XG4gIHZhciB4MiA9IHggKyB4O1xuICB2YXIgeTIgPSB5ICsgeTtcbiAgdmFyIHoyID0geiArIHo7XG4gIHZhciB4eCA9IHggKiB4MjtcbiAgdmFyIHh5ID0geCAqIHkyO1xuICB2YXIgeHogPSB4ICogejI7XG4gIHZhciB5eSA9IHkgKiB5MjtcbiAgdmFyIHl6ID0geSAqIHoyO1xuICB2YXIgenogPSB6ICogejI7XG4gIHZhciB3eCA9IHcgKiB4MjtcbiAgdmFyIHd5ID0gdyAqIHkyO1xuICB2YXIgd3ogPSB3ICogejI7XG4gIG91dFswXSA9IDEgLSAoeXkgKyB6eik7XG4gIG91dFsxXSA9IHh5ICsgd3o7XG4gIG91dFsyXSA9IHh6IC0gd3k7XG4gIG91dFszXSA9IDA7XG4gIG91dFs0XSA9IHh5IC0gd3o7XG4gIG91dFs1XSA9IDEgLSAoeHggKyB6eik7XG4gIG91dFs2XSA9IHl6ICsgd3g7XG4gIG91dFs3XSA9IDA7XG4gIG91dFs4XSA9IHh6ICsgd3k7XG4gIG91dFs5XSA9IHl6IC0gd3g7XG4gIG91dFsxMF0gPSAxIC0gKHh4ICsgeXkpO1xuICBvdXRbMTFdID0gMDtcbiAgb3V0WzEyXSA9IHZbMF07XG4gIG91dFsxM10gPSB2WzFdO1xuICBvdXRbMTRdID0gdlsyXTtcbiAgb3V0WzE1XSA9IDE7XG4gIHJldHVybiBvdXQ7XG59XG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgbWF0NCBmcm9tIGEgZHVhbCBxdWF0LlxuICpcbiAqIEBwYXJhbSB7bWF0NH0gb3V0IE1hdHJpeFxuICogQHBhcmFtIHtSZWFkb25seVF1YXQyfSBhIER1YWwgUXVhdGVybmlvblxuICogQHJldHVybnMge21hdDR9IG1hdDQgcmVjZWl2aW5nIG9wZXJhdGlvbiByZXN1bHRcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gZnJvbVF1YXQyKG91dCwgYSkge1xuICB2YXIgdHJhbnNsYXRpb24gPSBuZXcgZ2xNYXRyaXguQVJSQVlfVFlQRSgzKTtcbiAgdmFyIGJ4ID0gLWFbMF0sXG4gICAgICBieSA9IC1hWzFdLFxuICAgICAgYnogPSAtYVsyXSxcbiAgICAgIGJ3ID0gYVszXSxcbiAgICAgIGF4ID0gYVs0XSxcbiAgICAgIGF5ID0gYVs1XSxcbiAgICAgIGF6ID0gYVs2XSxcbiAgICAgIGF3ID0gYVs3XTtcbiAgdmFyIG1hZ25pdHVkZSA9IGJ4ICogYnggKyBieSAqIGJ5ICsgYnogKiBieiArIGJ3ICogYnc7IC8vT25seSBzY2FsZSBpZiBpdCBtYWtlcyBzZW5zZVxuXG4gIGlmIChtYWduaXR1ZGUgPiAwKSB7XG4gICAgdHJhbnNsYXRpb25bMF0gPSAoYXggKiBidyArIGF3ICogYnggKyBheSAqIGJ6IC0gYXogKiBieSkgKiAyIC8gbWFnbml0dWRlO1xuICAgIHRyYW5zbGF0aW9uWzFdID0gKGF5ICogYncgKyBhdyAqIGJ5ICsgYXogKiBieCAtIGF4ICogYnopICogMiAvIG1hZ25pdHVkZTtcbiAgICB0cmFuc2xhdGlvblsyXSA9IChheiAqIGJ3ICsgYXcgKiBieiArIGF4ICogYnkgLSBheSAqIGJ4KSAqIDIgLyBtYWduaXR1ZGU7XG4gIH0gZWxzZSB7XG4gICAgdHJhbnNsYXRpb25bMF0gPSAoYXggKiBidyArIGF3ICogYnggKyBheSAqIGJ6IC0gYXogKiBieSkgKiAyO1xuICAgIHRyYW5zbGF0aW9uWzFdID0gKGF5ICogYncgKyBhdyAqIGJ5ICsgYXogKiBieCAtIGF4ICogYnopICogMjtcbiAgICB0cmFuc2xhdGlvblsyXSA9IChheiAqIGJ3ICsgYXcgKiBieiArIGF4ICogYnkgLSBheSAqIGJ4KSAqIDI7XG4gIH1cblxuICBmcm9tUm90YXRpb25UcmFuc2xhdGlvbihvdXQsIGEsIHRyYW5zbGF0aW9uKTtcbiAgcmV0dXJuIG91dDtcbn1cbi8qKlxuICogUmV0dXJucyB0aGUgdHJhbnNsYXRpb24gdmVjdG9yIGNvbXBvbmVudCBvZiBhIHRyYW5zZm9ybWF0aW9uXG4gKiAgbWF0cml4LiBJZiBhIG1hdHJpeCBpcyBidWlsdCB3aXRoIGZyb21Sb3RhdGlvblRyYW5zbGF0aW9uLFxuICogIHRoZSByZXR1cm5lZCB2ZWN0b3Igd2lsbCBiZSB0aGUgc2FtZSBhcyB0aGUgdHJhbnNsYXRpb24gdmVjdG9yXG4gKiAgb3JpZ2luYWxseSBzdXBwbGllZC5cbiAqIEBwYXJhbSAge3ZlYzN9IG91dCBWZWN0b3IgdG8gcmVjZWl2ZSB0cmFuc2xhdGlvbiBjb21wb25lbnRcbiAqIEBwYXJhbSAge1JlYWRvbmx5TWF0NH0gbWF0IE1hdHJpeCB0byBiZSBkZWNvbXBvc2VkIChpbnB1dClcbiAqIEByZXR1cm4ge3ZlYzN9IG91dFxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRUcmFuc2xhdGlvbihvdXQsIG1hdCkge1xuICBvdXRbMF0gPSBtYXRbMTJdO1xuICBvdXRbMV0gPSBtYXRbMTNdO1xuICBvdXRbMl0gPSBtYXRbMTRdO1xuICByZXR1cm4gb3V0O1xufVxuLyoqXG4gKiBSZXR1cm5zIHRoZSBzY2FsaW5nIGZhY3RvciBjb21wb25lbnQgb2YgYSB0cmFuc2Zvcm1hdGlvblxuICogIG1hdHJpeC4gSWYgYSBtYXRyaXggaXMgYnVpbHQgd2l0aCBmcm9tUm90YXRpb25UcmFuc2xhdGlvblNjYWxlXG4gKiAgd2l0aCBhIG5vcm1hbGl6ZWQgUXVhdGVybmlvbiBwYXJhbXRlciwgdGhlIHJldHVybmVkIHZlY3RvciB3aWxsIGJlXG4gKiAgdGhlIHNhbWUgYXMgdGhlIHNjYWxpbmcgdmVjdG9yXG4gKiAgb3JpZ2luYWxseSBzdXBwbGllZC5cbiAqIEBwYXJhbSAge3ZlYzN9IG91dCBWZWN0b3IgdG8gcmVjZWl2ZSBzY2FsaW5nIGZhY3RvciBjb21wb25lbnRcbiAqIEBwYXJhbSAge1JlYWRvbmx5TWF0NH0gbWF0IE1hdHJpeCB0byBiZSBkZWNvbXBvc2VkIChpbnB1dClcbiAqIEByZXR1cm4ge3ZlYzN9IG91dFxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRTY2FsaW5nKG91dCwgbWF0KSB7XG4gIHZhciBtMTEgPSBtYXRbMF07XG4gIHZhciBtMTIgPSBtYXRbMV07XG4gIHZhciBtMTMgPSBtYXRbMl07XG4gIHZhciBtMjEgPSBtYXRbNF07XG4gIHZhciBtMjIgPSBtYXRbNV07XG4gIHZhciBtMjMgPSBtYXRbNl07XG4gIHZhciBtMzEgPSBtYXRbOF07XG4gIHZhciBtMzIgPSBtYXRbOV07XG4gIHZhciBtMzMgPSBtYXRbMTBdO1xuICBvdXRbMF0gPSBNYXRoLmh5cG90KG0xMSwgbTEyLCBtMTMpO1xuICBvdXRbMV0gPSBNYXRoLmh5cG90KG0yMSwgbTIyLCBtMjMpO1xuICBvdXRbMl0gPSBNYXRoLmh5cG90KG0zMSwgbTMyLCBtMzMpO1xuICByZXR1cm4gb3V0O1xufVxuLyoqXG4gKiBSZXR1cm5zIGEgcXVhdGVybmlvbiByZXByZXNlbnRpbmcgdGhlIHJvdGF0aW9uYWwgY29tcG9uZW50XG4gKiAgb2YgYSB0cmFuc2Zvcm1hdGlvbiBtYXRyaXguIElmIGEgbWF0cml4IGlzIGJ1aWx0IHdpdGhcbiAqICBmcm9tUm90YXRpb25UcmFuc2xhdGlvbiwgdGhlIHJldHVybmVkIHF1YXRlcm5pb24gd2lsbCBiZSB0aGVcbiAqICBzYW1lIGFzIHRoZSBxdWF0ZXJuaW9uIG9yaWdpbmFsbHkgc3VwcGxpZWQuXG4gKiBAcGFyYW0ge3F1YXR9IG91dCBRdWF0ZXJuaW9uIHRvIHJlY2VpdmUgdGhlIHJvdGF0aW9uIGNvbXBvbmVudFxuICogQHBhcmFtIHtSZWFkb25seU1hdDR9IG1hdCBNYXRyaXggdG8gYmUgZGVjb21wb3NlZCAoaW5wdXQpXG4gKiBAcmV0dXJuIHtxdWF0fSBvdXRcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gZ2V0Um90YXRpb24ob3V0LCBtYXQpIHtcbiAgdmFyIHNjYWxpbmcgPSBuZXcgZ2xNYXRyaXguQVJSQVlfVFlQRSgzKTtcbiAgZ2V0U2NhbGluZyhzY2FsaW5nLCBtYXQpO1xuICB2YXIgaXMxID0gMSAvIHNjYWxpbmdbMF07XG4gIHZhciBpczIgPSAxIC8gc2NhbGluZ1sxXTtcbiAgdmFyIGlzMyA9IDEgLyBzY2FsaW5nWzJdO1xuICB2YXIgc20xMSA9IG1hdFswXSAqIGlzMTtcbiAgdmFyIHNtMTIgPSBtYXRbMV0gKiBpczI7XG4gIHZhciBzbTEzID0gbWF0WzJdICogaXMzO1xuICB2YXIgc20yMSA9IG1hdFs0XSAqIGlzMTtcbiAgdmFyIHNtMjIgPSBtYXRbNV0gKiBpczI7XG4gIHZhciBzbTIzID0gbWF0WzZdICogaXMzO1xuICB2YXIgc20zMSA9IG1hdFs4XSAqIGlzMTtcbiAgdmFyIHNtMzIgPSBtYXRbOV0gKiBpczI7XG4gIHZhciBzbTMzID0gbWF0WzEwXSAqIGlzMztcbiAgdmFyIHRyYWNlID0gc20xMSArIHNtMjIgKyBzbTMzO1xuICB2YXIgUyA9IDA7XG5cbiAgaWYgKHRyYWNlID4gMCkge1xuICAgIFMgPSBNYXRoLnNxcnQodHJhY2UgKyAxLjApICogMjtcbiAgICBvdXRbM10gPSAwLjI1ICogUztcbiAgICBvdXRbMF0gPSAoc20yMyAtIHNtMzIpIC8gUztcbiAgICBvdXRbMV0gPSAoc20zMSAtIHNtMTMpIC8gUztcbiAgICBvdXRbMl0gPSAoc20xMiAtIHNtMjEpIC8gUztcbiAgfSBlbHNlIGlmIChzbTExID4gc20yMiAmJiBzbTExID4gc20zMykge1xuICAgIFMgPSBNYXRoLnNxcnQoMS4wICsgc20xMSAtIHNtMjIgLSBzbTMzKSAqIDI7XG4gICAgb3V0WzNdID0gKHNtMjMgLSBzbTMyKSAvIFM7XG4gICAgb3V0WzBdID0gMC4yNSAqIFM7XG4gICAgb3V0WzFdID0gKHNtMTIgKyBzbTIxKSAvIFM7XG4gICAgb3V0WzJdID0gKHNtMzEgKyBzbTEzKSAvIFM7XG4gIH0gZWxzZSBpZiAoc20yMiA+IHNtMzMpIHtcbiAgICBTID0gTWF0aC5zcXJ0KDEuMCArIHNtMjIgLSBzbTExIC0gc20zMykgKiAyO1xuICAgIG91dFszXSA9IChzbTMxIC0gc20xMykgLyBTO1xuICAgIG91dFswXSA9IChzbTEyICsgc20yMSkgLyBTO1xuICAgIG91dFsxXSA9IDAuMjUgKiBTO1xuICAgIG91dFsyXSA9IChzbTIzICsgc20zMikgLyBTO1xuICB9IGVsc2Uge1xuICAgIFMgPSBNYXRoLnNxcnQoMS4wICsgc20zMyAtIHNtMTEgLSBzbTIyKSAqIDI7XG4gICAgb3V0WzNdID0gKHNtMTIgLSBzbTIxKSAvIFM7XG4gICAgb3V0WzBdID0gKHNtMzEgKyBzbTEzKSAvIFM7XG4gICAgb3V0WzFdID0gKHNtMjMgKyBzbTMyKSAvIFM7XG4gICAgb3V0WzJdID0gMC4yNSAqIFM7XG4gIH1cblxuICByZXR1cm4gb3V0O1xufVxuLyoqXG4gKiBDcmVhdGVzIGEgbWF0cml4IGZyb20gYSBxdWF0ZXJuaW9uIHJvdGF0aW9uLCB2ZWN0b3IgdHJhbnNsYXRpb24gYW5kIHZlY3RvciBzY2FsZVxuICogVGhpcyBpcyBlcXVpdmFsZW50IHRvIChidXQgbXVjaCBmYXN0ZXIgdGhhbik6XG4gKlxuICogICAgIG1hdDQuaWRlbnRpdHkoZGVzdCk7XG4gKiAgICAgbWF0NC50cmFuc2xhdGUoZGVzdCwgdmVjKTtcbiAqICAgICBsZXQgcXVhdE1hdCA9IG1hdDQuY3JlYXRlKCk7XG4gKiAgICAgcXVhdDQudG9NYXQ0KHF1YXQsIHF1YXRNYXQpO1xuICogICAgIG1hdDQubXVsdGlwbHkoZGVzdCwgcXVhdE1hdCk7XG4gKiAgICAgbWF0NC5zY2FsZShkZXN0LCBzY2FsZSlcbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCBtYXQ0IHJlY2VpdmluZyBvcGVyYXRpb24gcmVzdWx0XG4gKiBAcGFyYW0ge3F1YXQ0fSBxIFJvdGF0aW9uIHF1YXRlcm5pb25cbiAqIEBwYXJhbSB7UmVhZG9ubHlWZWMzfSB2IFRyYW5zbGF0aW9uIHZlY3RvclxuICogQHBhcmFtIHtSZWFkb25seVZlYzN9IHMgU2NhbGluZyB2ZWN0b3JcbiAqIEByZXR1cm5zIHttYXQ0fSBvdXRcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gZnJvbVJvdGF0aW9uVHJhbnNsYXRpb25TY2FsZShvdXQsIHEsIHYsIHMpIHtcbiAgLy8gUXVhdGVybmlvbiBtYXRoXG4gIHZhciB4ID0gcVswXSxcbiAgICAgIHkgPSBxWzFdLFxuICAgICAgeiA9IHFbMl0sXG4gICAgICB3ID0gcVszXTtcbiAgdmFyIHgyID0geCArIHg7XG4gIHZhciB5MiA9IHkgKyB5O1xuICB2YXIgejIgPSB6ICsgejtcbiAgdmFyIHh4ID0geCAqIHgyO1xuICB2YXIgeHkgPSB4ICogeTI7XG4gIHZhciB4eiA9IHggKiB6MjtcbiAgdmFyIHl5ID0geSAqIHkyO1xuICB2YXIgeXogPSB5ICogejI7XG4gIHZhciB6eiA9IHogKiB6MjtcbiAgdmFyIHd4ID0gdyAqIHgyO1xuICB2YXIgd3kgPSB3ICogeTI7XG4gIHZhciB3eiA9IHcgKiB6MjtcbiAgdmFyIHN4ID0gc1swXTtcbiAgdmFyIHN5ID0gc1sxXTtcbiAgdmFyIHN6ID0gc1syXTtcbiAgb3V0WzBdID0gKDEgLSAoeXkgKyB6eikpICogc3g7XG4gIG91dFsxXSA9ICh4eSArIHd6KSAqIHN4O1xuICBvdXRbMl0gPSAoeHogLSB3eSkgKiBzeDtcbiAgb3V0WzNdID0gMDtcbiAgb3V0WzRdID0gKHh5IC0gd3opICogc3k7XG4gIG91dFs1XSA9ICgxIC0gKHh4ICsgenopKSAqIHN5O1xuICBvdXRbNl0gPSAoeXogKyB3eCkgKiBzeTtcbiAgb3V0WzddID0gMDtcbiAgb3V0WzhdID0gKHh6ICsgd3kpICogc3o7XG4gIG91dFs5XSA9ICh5eiAtIHd4KSAqIHN6O1xuICBvdXRbMTBdID0gKDEgLSAoeHggKyB5eSkpICogc3o7XG4gIG91dFsxMV0gPSAwO1xuICBvdXRbMTJdID0gdlswXTtcbiAgb3V0WzEzXSA9IHZbMV07XG4gIG91dFsxNF0gPSB2WzJdO1xuICBvdXRbMTVdID0gMTtcbiAgcmV0dXJuIG91dDtcbn1cbi8qKlxuICogQ3JlYXRlcyBhIG1hdHJpeCBmcm9tIGEgcXVhdGVybmlvbiByb3RhdGlvbiwgdmVjdG9yIHRyYW5zbGF0aW9uIGFuZCB2ZWN0b3Igc2NhbGUsIHJvdGF0aW5nIGFuZCBzY2FsaW5nIGFyb3VuZCB0aGUgZ2l2ZW4gb3JpZ2luXG4gKiBUaGlzIGlzIGVxdWl2YWxlbnQgdG8gKGJ1dCBtdWNoIGZhc3RlciB0aGFuKTpcbiAqXG4gKiAgICAgbWF0NC5pZGVudGl0eShkZXN0KTtcbiAqICAgICBtYXQ0LnRyYW5zbGF0ZShkZXN0LCB2ZWMpO1xuICogICAgIG1hdDQudHJhbnNsYXRlKGRlc3QsIG9yaWdpbik7XG4gKiAgICAgbGV0IHF1YXRNYXQgPSBtYXQ0LmNyZWF0ZSgpO1xuICogICAgIHF1YXQ0LnRvTWF0NChxdWF0LCBxdWF0TWF0KTtcbiAqICAgICBtYXQ0Lm11bHRpcGx5KGRlc3QsIHF1YXRNYXQpO1xuICogICAgIG1hdDQuc2NhbGUoZGVzdCwgc2NhbGUpXG4gKiAgICAgbWF0NC50cmFuc2xhdGUoZGVzdCwgbmVnYXRpdmVPcmlnaW4pO1xuICpcbiAqIEBwYXJhbSB7bWF0NH0gb3V0IG1hdDQgcmVjZWl2aW5nIG9wZXJhdGlvbiByZXN1bHRcbiAqIEBwYXJhbSB7cXVhdDR9IHEgUm90YXRpb24gcXVhdGVybmlvblxuICogQHBhcmFtIHtSZWFkb25seVZlYzN9IHYgVHJhbnNsYXRpb24gdmVjdG9yXG4gKiBAcGFyYW0ge1JlYWRvbmx5VmVjM30gcyBTY2FsaW5nIHZlY3RvclxuICogQHBhcmFtIHtSZWFkb25seVZlYzN9IG8gVGhlIG9yaWdpbiB2ZWN0b3IgYXJvdW5kIHdoaWNoIHRvIHNjYWxlIGFuZCByb3RhdGVcbiAqIEByZXR1cm5zIHttYXQ0fSBvdXRcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gZnJvbVJvdGF0aW9uVHJhbnNsYXRpb25TY2FsZU9yaWdpbihvdXQsIHEsIHYsIHMsIG8pIHtcbiAgLy8gUXVhdGVybmlvbiBtYXRoXG4gIHZhciB4ID0gcVswXSxcbiAgICAgIHkgPSBxWzFdLFxuICAgICAgeiA9IHFbMl0sXG4gICAgICB3ID0gcVszXTtcbiAgdmFyIHgyID0geCArIHg7XG4gIHZhciB5MiA9IHkgKyB5O1xuICB2YXIgejIgPSB6ICsgejtcbiAgdmFyIHh4ID0geCAqIHgyO1xuICB2YXIgeHkgPSB4ICogeTI7XG4gIHZhciB4eiA9IHggKiB6MjtcbiAgdmFyIHl5ID0geSAqIHkyO1xuICB2YXIgeXogPSB5ICogejI7XG4gIHZhciB6eiA9IHogKiB6MjtcbiAgdmFyIHd4ID0gdyAqIHgyO1xuICB2YXIgd3kgPSB3ICogeTI7XG4gIHZhciB3eiA9IHcgKiB6MjtcbiAgdmFyIHN4ID0gc1swXTtcbiAgdmFyIHN5ID0gc1sxXTtcbiAgdmFyIHN6ID0gc1syXTtcbiAgdmFyIG94ID0gb1swXTtcbiAgdmFyIG95ID0gb1sxXTtcbiAgdmFyIG96ID0gb1syXTtcbiAgdmFyIG91dDAgPSAoMSAtICh5eSArIHp6KSkgKiBzeDtcbiAgdmFyIG91dDEgPSAoeHkgKyB3eikgKiBzeDtcbiAgdmFyIG91dDIgPSAoeHogLSB3eSkgKiBzeDtcbiAgdmFyIG91dDQgPSAoeHkgLSB3eikgKiBzeTtcbiAgdmFyIG91dDUgPSAoMSAtICh4eCArIHp6KSkgKiBzeTtcbiAgdmFyIG91dDYgPSAoeXogKyB3eCkgKiBzeTtcbiAgdmFyIG91dDggPSAoeHogKyB3eSkgKiBzejtcbiAgdmFyIG91dDkgPSAoeXogLSB3eCkgKiBzejtcbiAgdmFyIG91dDEwID0gKDEgLSAoeHggKyB5eSkpICogc3o7XG4gIG91dFswXSA9IG91dDA7XG4gIG91dFsxXSA9IG91dDE7XG4gIG91dFsyXSA9IG91dDI7XG4gIG91dFszXSA9IDA7XG4gIG91dFs0XSA9IG91dDQ7XG4gIG91dFs1XSA9IG91dDU7XG4gIG91dFs2XSA9IG91dDY7XG4gIG91dFs3XSA9IDA7XG4gIG91dFs4XSA9IG91dDg7XG4gIG91dFs5XSA9IG91dDk7XG4gIG91dFsxMF0gPSBvdXQxMDtcbiAgb3V0WzExXSA9IDA7XG4gIG91dFsxMl0gPSB2WzBdICsgb3ggLSAob3V0MCAqIG94ICsgb3V0NCAqIG95ICsgb3V0OCAqIG96KTtcbiAgb3V0WzEzXSA9IHZbMV0gKyBveSAtIChvdXQxICogb3ggKyBvdXQ1ICogb3kgKyBvdXQ5ICogb3opO1xuICBvdXRbMTRdID0gdlsyXSArIG96IC0gKG91dDIgKiBveCArIG91dDYgKiBveSArIG91dDEwICogb3opO1xuICBvdXRbMTVdID0gMTtcbiAgcmV0dXJuIG91dDtcbn1cbi8qKlxuICogQ2FsY3VsYXRlcyBhIDR4NCBtYXRyaXggZnJvbSB0aGUgZ2l2ZW4gcXVhdGVybmlvblxuICpcbiAqIEBwYXJhbSB7bWF0NH0gb3V0IG1hdDQgcmVjZWl2aW5nIG9wZXJhdGlvbiByZXN1bHRcbiAqIEBwYXJhbSB7UmVhZG9ubHlRdWF0fSBxIFF1YXRlcm5pb24gdG8gY3JlYXRlIG1hdHJpeCBmcm9tXG4gKlxuICogQHJldHVybnMge21hdDR9IG91dFxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBmcm9tUXVhdChvdXQsIHEpIHtcbiAgdmFyIHggPSBxWzBdLFxuICAgICAgeSA9IHFbMV0sXG4gICAgICB6ID0gcVsyXSxcbiAgICAgIHcgPSBxWzNdO1xuICB2YXIgeDIgPSB4ICsgeDtcbiAgdmFyIHkyID0geSArIHk7XG4gIHZhciB6MiA9IHogKyB6O1xuICB2YXIgeHggPSB4ICogeDI7XG4gIHZhciB5eCA9IHkgKiB4MjtcbiAgdmFyIHl5ID0geSAqIHkyO1xuICB2YXIgenggPSB6ICogeDI7XG4gIHZhciB6eSA9IHogKiB5MjtcbiAgdmFyIHp6ID0geiAqIHoyO1xuICB2YXIgd3ggPSB3ICogeDI7XG4gIHZhciB3eSA9IHcgKiB5MjtcbiAgdmFyIHd6ID0gdyAqIHoyO1xuICBvdXRbMF0gPSAxIC0geXkgLSB6ejtcbiAgb3V0WzFdID0geXggKyB3ejtcbiAgb3V0WzJdID0genggLSB3eTtcbiAgb3V0WzNdID0gMDtcbiAgb3V0WzRdID0geXggLSB3ejtcbiAgb3V0WzVdID0gMSAtIHh4IC0geno7XG4gIG91dFs2XSA9IHp5ICsgd3g7XG4gIG91dFs3XSA9IDA7XG4gIG91dFs4XSA9IHp4ICsgd3k7XG4gIG91dFs5XSA9IHp5IC0gd3g7XG4gIG91dFsxMF0gPSAxIC0geHggLSB5eTtcbiAgb3V0WzExXSA9IDA7XG4gIG91dFsxMl0gPSAwO1xuICBvdXRbMTNdID0gMDtcbiAgb3V0WzE0XSA9IDA7XG4gIG91dFsxNV0gPSAxO1xuICByZXR1cm4gb3V0O1xufVxuLyoqXG4gKiBHZW5lcmF0ZXMgYSBmcnVzdHVtIG1hdHJpeCB3aXRoIHRoZSBnaXZlbiBib3VuZHNcbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCBtYXQ0IGZydXN0dW0gbWF0cml4IHdpbGwgYmUgd3JpdHRlbiBpbnRvXG4gKiBAcGFyYW0ge051bWJlcn0gbGVmdCBMZWZ0IGJvdW5kIG9mIHRoZSBmcnVzdHVtXG4gKiBAcGFyYW0ge051bWJlcn0gcmlnaHQgUmlnaHQgYm91bmQgb2YgdGhlIGZydXN0dW1cbiAqIEBwYXJhbSB7TnVtYmVyfSBib3R0b20gQm90dG9tIGJvdW5kIG9mIHRoZSBmcnVzdHVtXG4gKiBAcGFyYW0ge051bWJlcn0gdG9wIFRvcCBib3VuZCBvZiB0aGUgZnJ1c3R1bVxuICogQHBhcmFtIHtOdW1iZXJ9IG5lYXIgTmVhciBib3VuZCBvZiB0aGUgZnJ1c3R1bVxuICogQHBhcmFtIHtOdW1iZXJ9IGZhciBGYXIgYm91bmQgb2YgdGhlIGZydXN0dW1cbiAqIEByZXR1cm5zIHttYXQ0fSBvdXRcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gZnJ1c3R1bShvdXQsIGxlZnQsIHJpZ2h0LCBib3R0b20sIHRvcCwgbmVhciwgZmFyKSB7XG4gIHZhciBybCA9IDEgLyAocmlnaHQgLSBsZWZ0KTtcbiAgdmFyIHRiID0gMSAvICh0b3AgLSBib3R0b20pO1xuICB2YXIgbmYgPSAxIC8gKG5lYXIgLSBmYXIpO1xuICBvdXRbMF0gPSBuZWFyICogMiAqIHJsO1xuICBvdXRbMV0gPSAwO1xuICBvdXRbMl0gPSAwO1xuICBvdXRbM10gPSAwO1xuICBvdXRbNF0gPSAwO1xuICBvdXRbNV0gPSBuZWFyICogMiAqIHRiO1xuICBvdXRbNl0gPSAwO1xuICBvdXRbN10gPSAwO1xuICBvdXRbOF0gPSAocmlnaHQgKyBsZWZ0KSAqIHJsO1xuICBvdXRbOV0gPSAodG9wICsgYm90dG9tKSAqIHRiO1xuICBvdXRbMTBdID0gKGZhciArIG5lYXIpICogbmY7XG4gIG91dFsxMV0gPSAtMTtcbiAgb3V0WzEyXSA9IDA7XG4gIG91dFsxM10gPSAwO1xuICBvdXRbMTRdID0gZmFyICogbmVhciAqIDIgKiBuZjtcbiAgb3V0WzE1XSA9IDA7XG4gIHJldHVybiBvdXQ7XG59XG4vKipcbiAqIEdlbmVyYXRlcyBhIHBlcnNwZWN0aXZlIHByb2plY3Rpb24gbWF0cml4IHdpdGggdGhlIGdpdmVuIGJvdW5kcy5cbiAqIFRoZSBuZWFyL2ZhciBjbGlwIHBsYW5lcyBjb3JyZXNwb25kIHRvIGEgbm9ybWFsaXplZCBkZXZpY2UgY29vcmRpbmF0ZSBaIHJhbmdlIG9mIFstMSwgMV0sXG4gKiB3aGljaCBtYXRjaGVzIFdlYkdML09wZW5HTCdzIGNsaXAgdm9sdW1lLlxuICogUGFzc2luZyBudWxsL3VuZGVmaW5lZC9ubyB2YWx1ZSBmb3IgZmFyIHdpbGwgZ2VuZXJhdGUgaW5maW5pdGUgcHJvamVjdGlvbiBtYXRyaXguXG4gKlxuICogQHBhcmFtIHttYXQ0fSBvdXQgbWF0NCBmcnVzdHVtIG1hdHJpeCB3aWxsIGJlIHdyaXR0ZW4gaW50b1xuICogQHBhcmFtIHtudW1iZXJ9IGZvdnkgVmVydGljYWwgZmllbGQgb2YgdmlldyBpbiByYWRpYW5zXG4gKiBAcGFyYW0ge251bWJlcn0gYXNwZWN0IEFzcGVjdCByYXRpby4gdHlwaWNhbGx5IHZpZXdwb3J0IHdpZHRoL2hlaWdodFxuICogQHBhcmFtIHtudW1iZXJ9IG5lYXIgTmVhciBib3VuZCBvZiB0aGUgZnJ1c3R1bVxuICogQHBhcmFtIHtudW1iZXJ9IGZhciBGYXIgYm91bmQgb2YgdGhlIGZydXN0dW0sIGNhbiBiZSBudWxsIG9yIEluZmluaXR5XG4gKiBAcmV0dXJucyB7bWF0NH0gb3V0XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIHBlcnNwZWN0aXZlTk8ob3V0LCBmb3Z5LCBhc3BlY3QsIG5lYXIsIGZhcikge1xuICB2YXIgZiA9IDEuMCAvIE1hdGgudGFuKGZvdnkgLyAyKSxcbiAgICAgIG5mO1xuICBvdXRbMF0gPSBmIC8gYXNwZWN0O1xuICBvdXRbMV0gPSAwO1xuICBvdXRbMl0gPSAwO1xuICBvdXRbM10gPSAwO1xuICBvdXRbNF0gPSAwO1xuICBvdXRbNV0gPSBmO1xuICBvdXRbNl0gPSAwO1xuICBvdXRbN10gPSAwO1xuICBvdXRbOF0gPSAwO1xuICBvdXRbOV0gPSAwO1xuICBvdXRbMTFdID0gLTE7XG4gIG91dFsxMl0gPSAwO1xuICBvdXRbMTNdID0gMDtcbiAgb3V0WzE1XSA9IDA7XG5cbiAgaWYgKGZhciAhPSBudWxsICYmIGZhciAhPT0gSW5maW5pdHkpIHtcbiAgICBuZiA9IDEgLyAobmVhciAtIGZhcik7XG4gICAgb3V0WzEwXSA9IChmYXIgKyBuZWFyKSAqIG5mO1xuICAgIG91dFsxNF0gPSAyICogZmFyICogbmVhciAqIG5mO1xuICB9IGVsc2Uge1xuICAgIG91dFsxMF0gPSAtMTtcbiAgICBvdXRbMTRdID0gLTIgKiBuZWFyO1xuICB9XG5cbiAgcmV0dXJuIG91dDtcbn1cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayBtYXQ0LnBlcnNwZWN0aXZlTk99XG4gKiBAZnVuY3Rpb25cbiAqL1xuXG5leHBvcnQgdmFyIHBlcnNwZWN0aXZlID0gcGVyc3BlY3RpdmVOTztcbi8qKlxuICogR2VuZXJhdGVzIGEgcGVyc3BlY3RpdmUgcHJvamVjdGlvbiBtYXRyaXggc3VpdGFibGUgZm9yIFdlYkdQVSB3aXRoIHRoZSBnaXZlbiBib3VuZHMuXG4gKiBUaGUgbmVhci9mYXIgY2xpcCBwbGFuZXMgY29ycmVzcG9uZCB0byBhIG5vcm1hbGl6ZWQgZGV2aWNlIGNvb3JkaW5hdGUgWiByYW5nZSBvZiBbMCwgMV0sXG4gKiB3aGljaCBtYXRjaGVzIFdlYkdQVS9WdWxrYW4vRGlyZWN0WC9NZXRhbCdzIGNsaXAgdm9sdW1lLlxuICogUGFzc2luZyBudWxsL3VuZGVmaW5lZC9ubyB2YWx1ZSBmb3IgZmFyIHdpbGwgZ2VuZXJhdGUgaW5maW5pdGUgcHJvamVjdGlvbiBtYXRyaXguXG4gKlxuICogQHBhcmFtIHttYXQ0fSBvdXQgbWF0NCBmcnVzdHVtIG1hdHJpeCB3aWxsIGJlIHdyaXR0ZW4gaW50b1xuICogQHBhcmFtIHtudW1iZXJ9IGZvdnkgVmVydGljYWwgZmllbGQgb2YgdmlldyBpbiByYWRpYW5zXG4gKiBAcGFyYW0ge251bWJlcn0gYXNwZWN0IEFzcGVjdCByYXRpby4gdHlwaWNhbGx5IHZpZXdwb3J0IHdpZHRoL2hlaWdodFxuICogQHBhcmFtIHtudW1iZXJ9IG5lYXIgTmVhciBib3VuZCBvZiB0aGUgZnJ1c3R1bVxuICogQHBhcmFtIHtudW1iZXJ9IGZhciBGYXIgYm91bmQgb2YgdGhlIGZydXN0dW0sIGNhbiBiZSBudWxsIG9yIEluZmluaXR5XG4gKiBAcmV0dXJucyB7bWF0NH0gb3V0XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIHBlcnNwZWN0aXZlWk8ob3V0LCBmb3Z5LCBhc3BlY3QsIG5lYXIsIGZhcikge1xuICB2YXIgZiA9IDEuMCAvIE1hdGgudGFuKGZvdnkgLyAyKSxcbiAgICAgIG5mO1xuICBvdXRbMF0gPSBmIC8gYXNwZWN0O1xuICBvdXRbMV0gPSAwO1xuICBvdXRbMl0gPSAwO1xuICBvdXRbM10gPSAwO1xuICBvdXRbNF0gPSAwO1xuICBvdXRbNV0gPSBmO1xuICBvdXRbNl0gPSAwO1xuICBvdXRbN10gPSAwO1xuICBvdXRbOF0gPSAwO1xuICBvdXRbOV0gPSAwO1xuICBvdXRbMTFdID0gLTE7XG4gIG91dFsxMl0gPSAwO1xuICBvdXRbMTNdID0gMDtcbiAgb3V0WzE1XSA9IDA7XG5cbiAgaWYgKGZhciAhPSBudWxsICYmIGZhciAhPT0gSW5maW5pdHkpIHtcbiAgICBuZiA9IDEgLyAobmVhciAtIGZhcik7XG4gICAgb3V0WzEwXSA9IGZhciAqIG5mO1xuICAgIG91dFsxNF0gPSBmYXIgKiBuZWFyICogbmY7XG4gIH0gZWxzZSB7XG4gICAgb3V0WzEwXSA9IC0xO1xuICAgIG91dFsxNF0gPSAtbmVhcjtcbiAgfVxuXG4gIHJldHVybiBvdXQ7XG59XG4vKipcbiAqIEdlbmVyYXRlcyBhIHBlcnNwZWN0aXZlIHByb2plY3Rpb24gbWF0cml4IHdpdGggdGhlIGdpdmVuIGZpZWxkIG9mIHZpZXcuXG4gKiBUaGlzIGlzIHByaW1hcmlseSB1c2VmdWwgZm9yIGdlbmVyYXRpbmcgcHJvamVjdGlvbiBtYXRyaWNlcyB0byBiZSB1c2VkXG4gKiB3aXRoIHRoZSBzdGlsbCBleHBlcmllbWVudGFsIFdlYlZSIEFQSS5cbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCBtYXQ0IGZydXN0dW0gbWF0cml4IHdpbGwgYmUgd3JpdHRlbiBpbnRvXG4gKiBAcGFyYW0ge09iamVjdH0gZm92IE9iamVjdCBjb250YWluaW5nIHRoZSBmb2xsb3dpbmcgdmFsdWVzOiB1cERlZ3JlZXMsIGRvd25EZWdyZWVzLCBsZWZ0RGVncmVlcywgcmlnaHREZWdyZWVzXG4gKiBAcGFyYW0ge251bWJlcn0gbmVhciBOZWFyIGJvdW5kIG9mIHRoZSBmcnVzdHVtXG4gKiBAcGFyYW0ge251bWJlcn0gZmFyIEZhciBib3VuZCBvZiB0aGUgZnJ1c3R1bVxuICogQHJldHVybnMge21hdDR9IG91dFxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBwZXJzcGVjdGl2ZUZyb21GaWVsZE9mVmlldyhvdXQsIGZvdiwgbmVhciwgZmFyKSB7XG4gIHZhciB1cFRhbiA9IE1hdGgudGFuKGZvdi51cERlZ3JlZXMgKiBNYXRoLlBJIC8gMTgwLjApO1xuICB2YXIgZG93blRhbiA9IE1hdGgudGFuKGZvdi5kb3duRGVncmVlcyAqIE1hdGguUEkgLyAxODAuMCk7XG4gIHZhciBsZWZ0VGFuID0gTWF0aC50YW4oZm92LmxlZnREZWdyZWVzICogTWF0aC5QSSAvIDE4MC4wKTtcbiAgdmFyIHJpZ2h0VGFuID0gTWF0aC50YW4oZm92LnJpZ2h0RGVncmVlcyAqIE1hdGguUEkgLyAxODAuMCk7XG4gIHZhciB4U2NhbGUgPSAyLjAgLyAobGVmdFRhbiArIHJpZ2h0VGFuKTtcbiAgdmFyIHlTY2FsZSA9IDIuMCAvICh1cFRhbiArIGRvd25UYW4pO1xuICBvdXRbMF0gPSB4U2NhbGU7XG4gIG91dFsxXSA9IDAuMDtcbiAgb3V0WzJdID0gMC4wO1xuICBvdXRbM10gPSAwLjA7XG4gIG91dFs0XSA9IDAuMDtcbiAgb3V0WzVdID0geVNjYWxlO1xuICBvdXRbNl0gPSAwLjA7XG4gIG91dFs3XSA9IDAuMDtcbiAgb3V0WzhdID0gLSgobGVmdFRhbiAtIHJpZ2h0VGFuKSAqIHhTY2FsZSAqIDAuNSk7XG4gIG91dFs5XSA9ICh1cFRhbiAtIGRvd25UYW4pICogeVNjYWxlICogMC41O1xuICBvdXRbMTBdID0gZmFyIC8gKG5lYXIgLSBmYXIpO1xuICBvdXRbMTFdID0gLTEuMDtcbiAgb3V0WzEyXSA9IDAuMDtcbiAgb3V0WzEzXSA9IDAuMDtcbiAgb3V0WzE0XSA9IGZhciAqIG5lYXIgLyAobmVhciAtIGZhcik7XG4gIG91dFsxNV0gPSAwLjA7XG4gIHJldHVybiBvdXQ7XG59XG4vKipcbiAqIEdlbmVyYXRlcyBhIG9ydGhvZ29uYWwgcHJvamVjdGlvbiBtYXRyaXggd2l0aCB0aGUgZ2l2ZW4gYm91bmRzLlxuICogVGhlIG5lYXIvZmFyIGNsaXAgcGxhbmVzIGNvcnJlc3BvbmQgdG8gYSBub3JtYWxpemVkIGRldmljZSBjb29yZGluYXRlIFogcmFuZ2Ugb2YgWy0xLCAxXSxcbiAqIHdoaWNoIG1hdGNoZXMgV2ViR0wvT3BlbkdMJ3MgY2xpcCB2b2x1bWUuXG4gKlxuICogQHBhcmFtIHttYXQ0fSBvdXQgbWF0NCBmcnVzdHVtIG1hdHJpeCB3aWxsIGJlIHdyaXR0ZW4gaW50b1xuICogQHBhcmFtIHtudW1iZXJ9IGxlZnQgTGVmdCBib3VuZCBvZiB0aGUgZnJ1c3R1bVxuICogQHBhcmFtIHtudW1iZXJ9IHJpZ2h0IFJpZ2h0IGJvdW5kIG9mIHRoZSBmcnVzdHVtXG4gKiBAcGFyYW0ge251bWJlcn0gYm90dG9tIEJvdHRvbSBib3VuZCBvZiB0aGUgZnJ1c3R1bVxuICogQHBhcmFtIHtudW1iZXJ9IHRvcCBUb3AgYm91bmQgb2YgdGhlIGZydXN0dW1cbiAqIEBwYXJhbSB7bnVtYmVyfSBuZWFyIE5lYXIgYm91bmQgb2YgdGhlIGZydXN0dW1cbiAqIEBwYXJhbSB7bnVtYmVyfSBmYXIgRmFyIGJvdW5kIG9mIHRoZSBmcnVzdHVtXG4gKiBAcmV0dXJucyB7bWF0NH0gb3V0XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIG9ydGhvTk8ob3V0LCBsZWZ0LCByaWdodCwgYm90dG9tLCB0b3AsIG5lYXIsIGZhcikge1xuICB2YXIgbHIgPSAxIC8gKGxlZnQgLSByaWdodCk7XG4gIHZhciBidCA9IDEgLyAoYm90dG9tIC0gdG9wKTtcbiAgdmFyIG5mID0gMSAvIChuZWFyIC0gZmFyKTtcbiAgb3V0WzBdID0gLTIgKiBscjtcbiAgb3V0WzFdID0gMDtcbiAgb3V0WzJdID0gMDtcbiAgb3V0WzNdID0gMDtcbiAgb3V0WzRdID0gMDtcbiAgb3V0WzVdID0gLTIgKiBidDtcbiAgb3V0WzZdID0gMDtcbiAgb3V0WzddID0gMDtcbiAgb3V0WzhdID0gMDtcbiAgb3V0WzldID0gMDtcbiAgb3V0WzEwXSA9IDIgKiBuZjtcbiAgb3V0WzExXSA9IDA7XG4gIG91dFsxMl0gPSAobGVmdCArIHJpZ2h0KSAqIGxyO1xuICBvdXRbMTNdID0gKHRvcCArIGJvdHRvbSkgKiBidDtcbiAgb3V0WzE0XSA9IChmYXIgKyBuZWFyKSAqIG5mO1xuICBvdXRbMTVdID0gMTtcbiAgcmV0dXJuIG91dDtcbn1cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayBtYXQ0Lm9ydGhvTk99XG4gKiBAZnVuY3Rpb25cbiAqL1xuXG5leHBvcnQgdmFyIG9ydGhvID0gb3J0aG9OTztcbi8qKlxuICogR2VuZXJhdGVzIGEgb3J0aG9nb25hbCBwcm9qZWN0aW9uIG1hdHJpeCB3aXRoIHRoZSBnaXZlbiBib3VuZHMuXG4gKiBUaGUgbmVhci9mYXIgY2xpcCBwbGFuZXMgY29ycmVzcG9uZCB0byBhIG5vcm1hbGl6ZWQgZGV2aWNlIGNvb3JkaW5hdGUgWiByYW5nZSBvZiBbMCwgMV0sXG4gKiB3aGljaCBtYXRjaGVzIFdlYkdQVS9WdWxrYW4vRGlyZWN0WC9NZXRhbCdzIGNsaXAgdm9sdW1lLlxuICpcbiAqIEBwYXJhbSB7bWF0NH0gb3V0IG1hdDQgZnJ1c3R1bSBtYXRyaXggd2lsbCBiZSB3cml0dGVuIGludG9cbiAqIEBwYXJhbSB7bnVtYmVyfSBsZWZ0IExlZnQgYm91bmQgb2YgdGhlIGZydXN0dW1cbiAqIEBwYXJhbSB7bnVtYmVyfSByaWdodCBSaWdodCBib3VuZCBvZiB0aGUgZnJ1c3R1bVxuICogQHBhcmFtIHtudW1iZXJ9IGJvdHRvbSBCb3R0b20gYm91bmQgb2YgdGhlIGZydXN0dW1cbiAqIEBwYXJhbSB7bnVtYmVyfSB0b3AgVG9wIGJvdW5kIG9mIHRoZSBmcnVzdHVtXG4gKiBAcGFyYW0ge251bWJlcn0gbmVhciBOZWFyIGJvdW5kIG9mIHRoZSBmcnVzdHVtXG4gKiBAcGFyYW0ge251bWJlcn0gZmFyIEZhciBib3VuZCBvZiB0aGUgZnJ1c3R1bVxuICogQHJldHVybnMge21hdDR9IG91dFxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBvcnRob1pPKG91dCwgbGVmdCwgcmlnaHQsIGJvdHRvbSwgdG9wLCBuZWFyLCBmYXIpIHtcbiAgdmFyIGxyID0gMSAvIChsZWZ0IC0gcmlnaHQpO1xuICB2YXIgYnQgPSAxIC8gKGJvdHRvbSAtIHRvcCk7XG4gIHZhciBuZiA9IDEgLyAobmVhciAtIGZhcik7XG4gIG91dFswXSA9IC0yICogbHI7XG4gIG91dFsxXSA9IDA7XG4gIG91dFsyXSA9IDA7XG4gIG91dFszXSA9IDA7XG4gIG91dFs0XSA9IDA7XG4gIG91dFs1XSA9IC0yICogYnQ7XG4gIG91dFs2XSA9IDA7XG4gIG91dFs3XSA9IDA7XG4gIG91dFs4XSA9IDA7XG4gIG91dFs5XSA9IDA7XG4gIG91dFsxMF0gPSBuZjtcbiAgb3V0WzExXSA9IDA7XG4gIG91dFsxMl0gPSAobGVmdCArIHJpZ2h0KSAqIGxyO1xuICBvdXRbMTNdID0gKHRvcCArIGJvdHRvbSkgKiBidDtcbiAgb3V0WzE0XSA9IG5lYXIgKiBuZjtcbiAgb3V0WzE1XSA9IDE7XG4gIHJldHVybiBvdXQ7XG59XG4vKipcbiAqIEdlbmVyYXRlcyBhIGxvb2stYXQgbWF0cml4IHdpdGggdGhlIGdpdmVuIGV5ZSBwb3NpdGlvbiwgZm9jYWwgcG9pbnQsIGFuZCB1cCBheGlzLlxuICogSWYgeW91IHdhbnQgYSBtYXRyaXggdGhhdCBhY3R1YWxseSBtYWtlcyBhbiBvYmplY3QgbG9vayBhdCBhbm90aGVyIG9iamVjdCwgeW91IHNob3VsZCB1c2UgdGFyZ2V0VG8gaW5zdGVhZC5cbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCBtYXQ0IGZydXN0dW0gbWF0cml4IHdpbGwgYmUgd3JpdHRlbiBpbnRvXG4gKiBAcGFyYW0ge1JlYWRvbmx5VmVjM30gZXllIFBvc2l0aW9uIG9mIHRoZSB2aWV3ZXJcbiAqIEBwYXJhbSB7UmVhZG9ubHlWZWMzfSBjZW50ZXIgUG9pbnQgdGhlIHZpZXdlciBpcyBsb29raW5nIGF0XG4gKiBAcGFyYW0ge1JlYWRvbmx5VmVjM30gdXAgdmVjMyBwb2ludGluZyB1cFxuICogQHJldHVybnMge21hdDR9IG91dFxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBsb29rQXQob3V0LCBleWUsIGNlbnRlciwgdXApIHtcbiAgdmFyIHgwLCB4MSwgeDIsIHkwLCB5MSwgeTIsIHowLCB6MSwgejIsIGxlbjtcbiAgdmFyIGV5ZXggPSBleWVbMF07XG4gIHZhciBleWV5ID0gZXllWzFdO1xuICB2YXIgZXlleiA9IGV5ZVsyXTtcbiAgdmFyIHVweCA9IHVwWzBdO1xuICB2YXIgdXB5ID0gdXBbMV07XG4gIHZhciB1cHogPSB1cFsyXTtcbiAgdmFyIGNlbnRlcnggPSBjZW50ZXJbMF07XG4gIHZhciBjZW50ZXJ5ID0gY2VudGVyWzFdO1xuICB2YXIgY2VudGVyeiA9IGNlbnRlclsyXTtcblxuICBpZiAoTWF0aC5hYnMoZXlleCAtIGNlbnRlcngpIDwgZ2xNYXRyaXguRVBTSUxPTiAmJiBNYXRoLmFicyhleWV5IC0gY2VudGVyeSkgPCBnbE1hdHJpeC5FUFNJTE9OICYmIE1hdGguYWJzKGV5ZXogLSBjZW50ZXJ6KSA8IGdsTWF0cml4LkVQU0lMT04pIHtcbiAgICByZXR1cm4gaWRlbnRpdHkob3V0KTtcbiAgfVxuXG4gIHowID0gZXlleCAtIGNlbnRlcng7XG4gIHoxID0gZXlleSAtIGNlbnRlcnk7XG4gIHoyID0gZXlleiAtIGNlbnRlcno7XG4gIGxlbiA9IDEgLyBNYXRoLmh5cG90KHowLCB6MSwgejIpO1xuICB6MCAqPSBsZW47XG4gIHoxICo9IGxlbjtcbiAgejIgKj0gbGVuO1xuICB4MCA9IHVweSAqIHoyIC0gdXB6ICogejE7XG4gIHgxID0gdXB6ICogejAgLSB1cHggKiB6MjtcbiAgeDIgPSB1cHggKiB6MSAtIHVweSAqIHowO1xuICBsZW4gPSBNYXRoLmh5cG90KHgwLCB4MSwgeDIpO1xuXG4gIGlmICghbGVuKSB7XG4gICAgeDAgPSAwO1xuICAgIHgxID0gMDtcbiAgICB4MiA9IDA7XG4gIH0gZWxzZSB7XG4gICAgbGVuID0gMSAvIGxlbjtcbiAgICB4MCAqPSBsZW47XG4gICAgeDEgKj0gbGVuO1xuICAgIHgyICo9IGxlbjtcbiAgfVxuXG4gIHkwID0gejEgKiB4MiAtIHoyICogeDE7XG4gIHkxID0gejIgKiB4MCAtIHowICogeDI7XG4gIHkyID0gejAgKiB4MSAtIHoxICogeDA7XG4gIGxlbiA9IE1hdGguaHlwb3QoeTAsIHkxLCB5Mik7XG5cbiAgaWYgKCFsZW4pIHtcbiAgICB5MCA9IDA7XG4gICAgeTEgPSAwO1xuICAgIHkyID0gMDtcbiAgfSBlbHNlIHtcbiAgICBsZW4gPSAxIC8gbGVuO1xuICAgIHkwICo9IGxlbjtcbiAgICB5MSAqPSBsZW47XG4gICAgeTIgKj0gbGVuO1xuICB9XG5cbiAgb3V0WzBdID0geDA7XG4gIG91dFsxXSA9IHkwO1xuICBvdXRbMl0gPSB6MDtcbiAgb3V0WzNdID0gMDtcbiAgb3V0WzRdID0geDE7XG4gIG91dFs1XSA9IHkxO1xuICBvdXRbNl0gPSB6MTtcbiAgb3V0WzddID0gMDtcbiAgb3V0WzhdID0geDI7XG4gIG91dFs5XSA9IHkyO1xuICBvdXRbMTBdID0gejI7XG4gIG91dFsxMV0gPSAwO1xuICBvdXRbMTJdID0gLSh4MCAqIGV5ZXggKyB4MSAqIGV5ZXkgKyB4MiAqIGV5ZXopO1xuICBvdXRbMTNdID0gLSh5MCAqIGV5ZXggKyB5MSAqIGV5ZXkgKyB5MiAqIGV5ZXopO1xuICBvdXRbMTRdID0gLSh6MCAqIGV5ZXggKyB6MSAqIGV5ZXkgKyB6MiAqIGV5ZXopO1xuICBvdXRbMTVdID0gMTtcbiAgcmV0dXJuIG91dDtcbn1cbi8qKlxuICogR2VuZXJhdGVzIGEgbWF0cml4IHRoYXQgbWFrZXMgc29tZXRoaW5nIGxvb2sgYXQgc29tZXRoaW5nIGVsc2UuXG4gKlxuICogQHBhcmFtIHttYXQ0fSBvdXQgbWF0NCBmcnVzdHVtIG1hdHJpeCB3aWxsIGJlIHdyaXR0ZW4gaW50b1xuICogQHBhcmFtIHtSZWFkb25seVZlYzN9IGV5ZSBQb3NpdGlvbiBvZiB0aGUgdmlld2VyXG4gKiBAcGFyYW0ge1JlYWRvbmx5VmVjM30gY2VudGVyIFBvaW50IHRoZSB2aWV3ZXIgaXMgbG9va2luZyBhdFxuICogQHBhcmFtIHtSZWFkb25seVZlYzN9IHVwIHZlYzMgcG9pbnRpbmcgdXBcbiAqIEByZXR1cm5zIHttYXQ0fSBvdXRcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gdGFyZ2V0VG8ob3V0LCBleWUsIHRhcmdldCwgdXApIHtcbiAgdmFyIGV5ZXggPSBleWVbMF0sXG4gICAgICBleWV5ID0gZXllWzFdLFxuICAgICAgZXlleiA9IGV5ZVsyXSxcbiAgICAgIHVweCA9IHVwWzBdLFxuICAgICAgdXB5ID0gdXBbMV0sXG4gICAgICB1cHogPSB1cFsyXTtcbiAgdmFyIHowID0gZXlleCAtIHRhcmdldFswXSxcbiAgICAgIHoxID0gZXlleSAtIHRhcmdldFsxXSxcbiAgICAgIHoyID0gZXlleiAtIHRhcmdldFsyXTtcbiAgdmFyIGxlbiA9IHowICogejAgKyB6MSAqIHoxICsgejIgKiB6MjtcblxuICBpZiAobGVuID4gMCkge1xuICAgIGxlbiA9IDEgLyBNYXRoLnNxcnQobGVuKTtcbiAgICB6MCAqPSBsZW47XG4gICAgejEgKj0gbGVuO1xuICAgIHoyICo9IGxlbjtcbiAgfVxuXG4gIHZhciB4MCA9IHVweSAqIHoyIC0gdXB6ICogejEsXG4gICAgICB4MSA9IHVweiAqIHowIC0gdXB4ICogejIsXG4gICAgICB4MiA9IHVweCAqIHoxIC0gdXB5ICogejA7XG4gIGxlbiA9IHgwICogeDAgKyB4MSAqIHgxICsgeDIgKiB4MjtcblxuICBpZiAobGVuID4gMCkge1xuICAgIGxlbiA9IDEgLyBNYXRoLnNxcnQobGVuKTtcbiAgICB4MCAqPSBsZW47XG4gICAgeDEgKj0gbGVuO1xuICAgIHgyICo9IGxlbjtcbiAgfVxuXG4gIG91dFswXSA9IHgwO1xuICBvdXRbMV0gPSB4MTtcbiAgb3V0WzJdID0geDI7XG4gIG91dFszXSA9IDA7XG4gIG91dFs0XSA9IHoxICogeDIgLSB6MiAqIHgxO1xuICBvdXRbNV0gPSB6MiAqIHgwIC0gejAgKiB4MjtcbiAgb3V0WzZdID0gejAgKiB4MSAtIHoxICogeDA7XG4gIG91dFs3XSA9IDA7XG4gIG91dFs4XSA9IHowO1xuICBvdXRbOV0gPSB6MTtcbiAgb3V0WzEwXSA9IHoyO1xuICBvdXRbMTFdID0gMDtcbiAgb3V0WzEyXSA9IGV5ZXg7XG4gIG91dFsxM10gPSBleWV5O1xuICBvdXRbMTRdID0gZXllejtcbiAgb3V0WzE1XSA9IDE7XG4gIHJldHVybiBvdXQ7XG59XG4vKipcbiAqIFJldHVybnMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgYSBtYXQ0XG4gKlxuICogQHBhcmFtIHtSZWFkb25seU1hdDR9IGEgbWF0cml4IHRvIHJlcHJlc2VudCBhcyBhIHN0cmluZ1xuICogQHJldHVybnMge1N0cmluZ30gc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBtYXRyaXhcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gc3RyKGEpIHtcbiAgcmV0dXJuIFwibWF0NChcIiArIGFbMF0gKyBcIiwgXCIgKyBhWzFdICsgXCIsIFwiICsgYVsyXSArIFwiLCBcIiArIGFbM10gKyBcIiwgXCIgKyBhWzRdICsgXCIsIFwiICsgYVs1XSArIFwiLCBcIiArIGFbNl0gKyBcIiwgXCIgKyBhWzddICsgXCIsIFwiICsgYVs4XSArIFwiLCBcIiArIGFbOV0gKyBcIiwgXCIgKyBhWzEwXSArIFwiLCBcIiArIGFbMTFdICsgXCIsIFwiICsgYVsxMl0gKyBcIiwgXCIgKyBhWzEzXSArIFwiLCBcIiArIGFbMTRdICsgXCIsIFwiICsgYVsxNV0gKyBcIilcIjtcbn1cbi8qKlxuICogUmV0dXJucyBGcm9iZW5pdXMgbm9ybSBvZiBhIG1hdDRcbiAqXG4gKiBAcGFyYW0ge1JlYWRvbmx5TWF0NH0gYSB0aGUgbWF0cml4IHRvIGNhbGN1bGF0ZSBGcm9iZW5pdXMgbm9ybSBvZlxuICogQHJldHVybnMge051bWJlcn0gRnJvYmVuaXVzIG5vcm1cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gZnJvYihhKSB7XG4gIHJldHVybiBNYXRoLmh5cG90KGFbMF0sIGFbMV0sIGFbMl0sIGFbM10sIGFbNF0sIGFbNV0sIGFbNl0sIGFbN10sIGFbOF0sIGFbOV0sIGFbMTBdLCBhWzExXSwgYVsxMl0sIGFbMTNdLCBhWzE0XSwgYVsxNV0pO1xufVxuLyoqXG4gKiBBZGRzIHR3byBtYXQ0J3NcbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHtSZWFkb25seU1hdDR9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7UmVhZG9ubHlNYXQ0fSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge21hdDR9IG91dFxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBhZGQob3V0LCBhLCBiKSB7XG4gIG91dFswXSA9IGFbMF0gKyBiWzBdO1xuICBvdXRbMV0gPSBhWzFdICsgYlsxXTtcbiAgb3V0WzJdID0gYVsyXSArIGJbMl07XG4gIG91dFszXSA9IGFbM10gKyBiWzNdO1xuICBvdXRbNF0gPSBhWzRdICsgYls0XTtcbiAgb3V0WzVdID0gYVs1XSArIGJbNV07XG4gIG91dFs2XSA9IGFbNl0gKyBiWzZdO1xuICBvdXRbN10gPSBhWzddICsgYls3XTtcbiAgb3V0WzhdID0gYVs4XSArIGJbOF07XG4gIG91dFs5XSA9IGFbOV0gKyBiWzldO1xuICBvdXRbMTBdID0gYVsxMF0gKyBiWzEwXTtcbiAgb3V0WzExXSA9IGFbMTFdICsgYlsxMV07XG4gIG91dFsxMl0gPSBhWzEyXSArIGJbMTJdO1xuICBvdXRbMTNdID0gYVsxM10gKyBiWzEzXTtcbiAgb3V0WzE0XSA9IGFbMTRdICsgYlsxNF07XG4gIG91dFsxNV0gPSBhWzE1XSArIGJbMTVdO1xuICByZXR1cm4gb3V0O1xufVxuLyoqXG4gKiBTdWJ0cmFjdHMgbWF0cml4IGIgZnJvbSBtYXRyaXggYVxuICpcbiAqIEBwYXJhbSB7bWF0NH0gb3V0IHRoZSByZWNlaXZpbmcgbWF0cml4XG4gKiBAcGFyYW0ge1JlYWRvbmx5TWF0NH0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHtSZWFkb25seU1hdDR9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7bWF0NH0gb3V0XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIHN1YnRyYWN0KG91dCwgYSwgYikge1xuICBvdXRbMF0gPSBhWzBdIC0gYlswXTtcbiAgb3V0WzFdID0gYVsxXSAtIGJbMV07XG4gIG91dFsyXSA9IGFbMl0gLSBiWzJdO1xuICBvdXRbM10gPSBhWzNdIC0gYlszXTtcbiAgb3V0WzRdID0gYVs0XSAtIGJbNF07XG4gIG91dFs1XSA9IGFbNV0gLSBiWzVdO1xuICBvdXRbNl0gPSBhWzZdIC0gYls2XTtcbiAgb3V0WzddID0gYVs3XSAtIGJbN107XG4gIG91dFs4XSA9IGFbOF0gLSBiWzhdO1xuICBvdXRbOV0gPSBhWzldIC0gYls5XTtcbiAgb3V0WzEwXSA9IGFbMTBdIC0gYlsxMF07XG4gIG91dFsxMV0gPSBhWzExXSAtIGJbMTFdO1xuICBvdXRbMTJdID0gYVsxMl0gLSBiWzEyXTtcbiAgb3V0WzEzXSA9IGFbMTNdIC0gYlsxM107XG4gIG91dFsxNF0gPSBhWzE0XSAtIGJbMTRdO1xuICBvdXRbMTVdID0gYVsxNV0gLSBiWzE1XTtcbiAgcmV0dXJuIG91dDtcbn1cbi8qKlxuICogTXVsdGlwbHkgZWFjaCBlbGVtZW50IG9mIHRoZSBtYXRyaXggYnkgYSBzY2FsYXIuXG4gKlxuICogQHBhcmFtIHttYXQ0fSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7UmVhZG9ubHlNYXQ0fSBhIHRoZSBtYXRyaXggdG8gc2NhbGVcbiAqIEBwYXJhbSB7TnVtYmVyfSBiIGFtb3VudCB0byBzY2FsZSB0aGUgbWF0cml4J3MgZWxlbWVudHMgYnlcbiAqIEByZXR1cm5zIHttYXQ0fSBvdXRcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gbXVsdGlwbHlTY2FsYXIob3V0LCBhLCBiKSB7XG4gIG91dFswXSA9IGFbMF0gKiBiO1xuICBvdXRbMV0gPSBhWzFdICogYjtcbiAgb3V0WzJdID0gYVsyXSAqIGI7XG4gIG91dFszXSA9IGFbM10gKiBiO1xuICBvdXRbNF0gPSBhWzRdICogYjtcbiAgb3V0WzVdID0gYVs1XSAqIGI7XG4gIG91dFs2XSA9IGFbNl0gKiBiO1xuICBvdXRbN10gPSBhWzddICogYjtcbiAgb3V0WzhdID0gYVs4XSAqIGI7XG4gIG91dFs5XSA9IGFbOV0gKiBiO1xuICBvdXRbMTBdID0gYVsxMF0gKiBiO1xuICBvdXRbMTFdID0gYVsxMV0gKiBiO1xuICBvdXRbMTJdID0gYVsxMl0gKiBiO1xuICBvdXRbMTNdID0gYVsxM10gKiBiO1xuICBvdXRbMTRdID0gYVsxNF0gKiBiO1xuICBvdXRbMTVdID0gYVsxNV0gKiBiO1xuICByZXR1cm4gb3V0O1xufVxuLyoqXG4gKiBBZGRzIHR3byBtYXQ0J3MgYWZ0ZXIgbXVsdGlwbHlpbmcgZWFjaCBlbGVtZW50IG9mIHRoZSBzZWNvbmQgb3BlcmFuZCBieSBhIHNjYWxhciB2YWx1ZS5cbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHtSZWFkb25seU1hdDR9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7UmVhZG9ubHlNYXQ0fSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHBhcmFtIHtOdW1iZXJ9IHNjYWxlIHRoZSBhbW91bnQgdG8gc2NhbGUgYidzIGVsZW1lbnRzIGJ5IGJlZm9yZSBhZGRpbmdcbiAqIEByZXR1cm5zIHttYXQ0fSBvdXRcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gbXVsdGlwbHlTY2FsYXJBbmRBZGQob3V0LCBhLCBiLCBzY2FsZSkge1xuICBvdXRbMF0gPSBhWzBdICsgYlswXSAqIHNjYWxlO1xuICBvdXRbMV0gPSBhWzFdICsgYlsxXSAqIHNjYWxlO1xuICBvdXRbMl0gPSBhWzJdICsgYlsyXSAqIHNjYWxlO1xuICBvdXRbM10gPSBhWzNdICsgYlszXSAqIHNjYWxlO1xuICBvdXRbNF0gPSBhWzRdICsgYls0XSAqIHNjYWxlO1xuICBvdXRbNV0gPSBhWzVdICsgYls1XSAqIHNjYWxlO1xuICBvdXRbNl0gPSBhWzZdICsgYls2XSAqIHNjYWxlO1xuICBvdXRbN10gPSBhWzddICsgYls3XSAqIHNjYWxlO1xuICBvdXRbOF0gPSBhWzhdICsgYls4XSAqIHNjYWxlO1xuICBvdXRbOV0gPSBhWzldICsgYls5XSAqIHNjYWxlO1xuICBvdXRbMTBdID0gYVsxMF0gKyBiWzEwXSAqIHNjYWxlO1xuICBvdXRbMTFdID0gYVsxMV0gKyBiWzExXSAqIHNjYWxlO1xuICBvdXRbMTJdID0gYVsxMl0gKyBiWzEyXSAqIHNjYWxlO1xuICBvdXRbMTNdID0gYVsxM10gKyBiWzEzXSAqIHNjYWxlO1xuICBvdXRbMTRdID0gYVsxNF0gKyBiWzE0XSAqIHNjYWxlO1xuICBvdXRbMTVdID0gYVsxNV0gKyBiWzE1XSAqIHNjYWxlO1xuICByZXR1cm4gb3V0O1xufVxuLyoqXG4gKiBSZXR1cm5zIHdoZXRoZXIgb3Igbm90IHRoZSBtYXRyaWNlcyBoYXZlIGV4YWN0bHkgdGhlIHNhbWUgZWxlbWVudHMgaW4gdGhlIHNhbWUgcG9zaXRpb24gKHdoZW4gY29tcGFyZWQgd2l0aCA9PT0pXG4gKlxuICogQHBhcmFtIHtSZWFkb25seU1hdDR9IGEgVGhlIGZpcnN0IG1hdHJpeC5cbiAqIEBwYXJhbSB7UmVhZG9ubHlNYXQ0fSBiIFRoZSBzZWNvbmQgbWF0cml4LlxuICogQHJldHVybnMge0Jvb2xlYW59IFRydWUgaWYgdGhlIG1hdHJpY2VzIGFyZSBlcXVhbCwgZmFsc2Ugb3RoZXJ3aXNlLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBleGFjdEVxdWFscyhhLCBiKSB7XG4gIHJldHVybiBhWzBdID09PSBiWzBdICYmIGFbMV0gPT09IGJbMV0gJiYgYVsyXSA9PT0gYlsyXSAmJiBhWzNdID09PSBiWzNdICYmIGFbNF0gPT09IGJbNF0gJiYgYVs1XSA9PT0gYls1XSAmJiBhWzZdID09PSBiWzZdICYmIGFbN10gPT09IGJbN10gJiYgYVs4XSA9PT0gYls4XSAmJiBhWzldID09PSBiWzldICYmIGFbMTBdID09PSBiWzEwXSAmJiBhWzExXSA9PT0gYlsxMV0gJiYgYVsxMl0gPT09IGJbMTJdICYmIGFbMTNdID09PSBiWzEzXSAmJiBhWzE0XSA9PT0gYlsxNF0gJiYgYVsxNV0gPT09IGJbMTVdO1xufVxuLyoqXG4gKiBSZXR1cm5zIHdoZXRoZXIgb3Igbm90IHRoZSBtYXRyaWNlcyBoYXZlIGFwcHJveGltYXRlbHkgdGhlIHNhbWUgZWxlbWVudHMgaW4gdGhlIHNhbWUgcG9zaXRpb24uXG4gKlxuICogQHBhcmFtIHtSZWFkb25seU1hdDR9IGEgVGhlIGZpcnN0IG1hdHJpeC5cbiAqIEBwYXJhbSB7UmVhZG9ubHlNYXQ0fSBiIFRoZSBzZWNvbmQgbWF0cml4LlxuICogQHJldHVybnMge0Jvb2xlYW59IFRydWUgaWYgdGhlIG1hdHJpY2VzIGFyZSBlcXVhbCwgZmFsc2Ugb3RoZXJ3aXNlLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBlcXVhbHMoYSwgYikge1xuICB2YXIgYTAgPSBhWzBdLFxuICAgICAgYTEgPSBhWzFdLFxuICAgICAgYTIgPSBhWzJdLFxuICAgICAgYTMgPSBhWzNdO1xuICB2YXIgYTQgPSBhWzRdLFxuICAgICAgYTUgPSBhWzVdLFxuICAgICAgYTYgPSBhWzZdLFxuICAgICAgYTcgPSBhWzddO1xuICB2YXIgYTggPSBhWzhdLFxuICAgICAgYTkgPSBhWzldLFxuICAgICAgYTEwID0gYVsxMF0sXG4gICAgICBhMTEgPSBhWzExXTtcbiAgdmFyIGExMiA9IGFbMTJdLFxuICAgICAgYTEzID0gYVsxM10sXG4gICAgICBhMTQgPSBhWzE0XSxcbiAgICAgIGExNSA9IGFbMTVdO1xuICB2YXIgYjAgPSBiWzBdLFxuICAgICAgYjEgPSBiWzFdLFxuICAgICAgYjIgPSBiWzJdLFxuICAgICAgYjMgPSBiWzNdO1xuICB2YXIgYjQgPSBiWzRdLFxuICAgICAgYjUgPSBiWzVdLFxuICAgICAgYjYgPSBiWzZdLFxuICAgICAgYjcgPSBiWzddO1xuICB2YXIgYjggPSBiWzhdLFxuICAgICAgYjkgPSBiWzldLFxuICAgICAgYjEwID0gYlsxMF0sXG4gICAgICBiMTEgPSBiWzExXTtcbiAgdmFyIGIxMiA9IGJbMTJdLFxuICAgICAgYjEzID0gYlsxM10sXG4gICAgICBiMTQgPSBiWzE0XSxcbiAgICAgIGIxNSA9IGJbMTVdO1xuICByZXR1cm4gTWF0aC5hYnMoYTAgLSBiMCkgPD0gZ2xNYXRyaXguRVBTSUxPTiAqIE1hdGgubWF4KDEuMCwgTWF0aC5hYnMoYTApLCBNYXRoLmFicyhiMCkpICYmIE1hdGguYWJzKGExIC0gYjEpIDw9IGdsTWF0cml4LkVQU0lMT04gKiBNYXRoLm1heCgxLjAsIE1hdGguYWJzKGExKSwgTWF0aC5hYnMoYjEpKSAmJiBNYXRoLmFicyhhMiAtIGIyKSA8PSBnbE1hdHJpeC5FUFNJTE9OICogTWF0aC5tYXgoMS4wLCBNYXRoLmFicyhhMiksIE1hdGguYWJzKGIyKSkgJiYgTWF0aC5hYnMoYTMgLSBiMykgPD0gZ2xNYXRyaXguRVBTSUxPTiAqIE1hdGgubWF4KDEuMCwgTWF0aC5hYnMoYTMpLCBNYXRoLmFicyhiMykpICYmIE1hdGguYWJzKGE0IC0gYjQpIDw9IGdsTWF0cml4LkVQU0lMT04gKiBNYXRoLm1heCgxLjAsIE1hdGguYWJzKGE0KSwgTWF0aC5hYnMoYjQpKSAmJiBNYXRoLmFicyhhNSAtIGI1KSA8PSBnbE1hdHJpeC5FUFNJTE9OICogTWF0aC5tYXgoMS4wLCBNYXRoLmFicyhhNSksIE1hdGguYWJzKGI1KSkgJiYgTWF0aC5hYnMoYTYgLSBiNikgPD0gZ2xNYXRyaXguRVBTSUxPTiAqIE1hdGgubWF4KDEuMCwgTWF0aC5hYnMoYTYpLCBNYXRoLmFicyhiNikpICYmIE1hdGguYWJzKGE3IC0gYjcpIDw9IGdsTWF0cml4LkVQU0lMT04gKiBNYXRoLm1heCgxLjAsIE1hdGguYWJzKGE3KSwgTWF0aC5hYnMoYjcpKSAmJiBNYXRoLmFicyhhOCAtIGI4KSA8PSBnbE1hdHJpeC5FUFNJTE9OICogTWF0aC5tYXgoMS4wLCBNYXRoLmFicyhhOCksIE1hdGguYWJzKGI4KSkgJiYgTWF0aC5hYnMoYTkgLSBiOSkgPD0gZ2xNYXRyaXguRVBTSUxPTiAqIE1hdGgubWF4KDEuMCwgTWF0aC5hYnMoYTkpLCBNYXRoLmFicyhiOSkpICYmIE1hdGguYWJzKGExMCAtIGIxMCkgPD0gZ2xNYXRyaXguRVBTSUxPTiAqIE1hdGgubWF4KDEuMCwgTWF0aC5hYnMoYTEwKSwgTWF0aC5hYnMoYjEwKSkgJiYgTWF0aC5hYnMoYTExIC0gYjExKSA8PSBnbE1hdHJpeC5FUFNJTE9OICogTWF0aC5tYXgoMS4wLCBNYXRoLmFicyhhMTEpLCBNYXRoLmFicyhiMTEpKSAmJiBNYXRoLmFicyhhMTIgLSBiMTIpIDw9IGdsTWF0cml4LkVQU0lMT04gKiBNYXRoLm1heCgxLjAsIE1hdGguYWJzKGExMiksIE1hdGguYWJzKGIxMikpICYmIE1hdGguYWJzKGExMyAtIGIxMykgPD0gZ2xNYXRyaXguRVBTSUxPTiAqIE1hdGgubWF4KDEuMCwgTWF0aC5hYnMoYTEzKSwgTWF0aC5hYnMoYjEzKSkgJiYgTWF0aC5hYnMoYTE0IC0gYjE0KSA8PSBnbE1hdHJpeC5FUFNJTE9OICogTWF0aC5tYXgoMS4wLCBNYXRoLmFicyhhMTQpLCBNYXRoLmFicyhiMTQpKSAmJiBNYXRoLmFicyhhMTUgLSBiMTUpIDw9IGdsTWF0cml4LkVQU0lMT04gKiBNYXRoLm1heCgxLjAsIE1hdGguYWJzKGExNSksIE1hdGguYWJzKGIxNSkpO1xufVxuLyoqXG4gKiBBbGlhcyBmb3Ige0BsaW5rIG1hdDQubXVsdGlwbHl9XG4gKiBAZnVuY3Rpb25cbiAqL1xuXG5leHBvcnQgdmFyIG11bCA9IG11bHRpcGx5O1xuLyoqXG4gKiBBbGlhcyBmb3Ige0BsaW5rIG1hdDQuc3VidHJhY3R9XG4gKiBAZnVuY3Rpb25cbiAqL1xuXG5leHBvcnQgdmFyIHN1YiA9IHN1YnRyYWN0OyIsImltcG9ydCAqIGFzIGdsTWF0cml4IGZyb20gXCIuL2NvbW1vbi5qc1wiO1xuaW1wb3J0ICogYXMgbWF0MyBmcm9tIFwiLi9tYXQzLmpzXCI7XG5pbXBvcnQgKiBhcyB2ZWMzIGZyb20gXCIuL3ZlYzMuanNcIjtcbmltcG9ydCAqIGFzIHZlYzQgZnJvbSBcIi4vdmVjNC5qc1wiO1xuLyoqXG4gKiBRdWF0ZXJuaW9uXG4gKiBAbW9kdWxlIHF1YXRcbiAqL1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgaWRlbnRpdHkgcXVhdFxuICpcbiAqIEByZXR1cm5zIHtxdWF0fSBhIG5ldyBxdWF0ZXJuaW9uXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZSgpIHtcbiAgdmFyIG91dCA9IG5ldyBnbE1hdHJpeC5BUlJBWV9UWVBFKDQpO1xuXG4gIGlmIChnbE1hdHJpeC5BUlJBWV9UWVBFICE9IEZsb2F0MzJBcnJheSkge1xuICAgIG91dFswXSA9IDA7XG4gICAgb3V0WzFdID0gMDtcbiAgICBvdXRbMl0gPSAwO1xuICB9XG5cbiAgb3V0WzNdID0gMTtcbiAgcmV0dXJuIG91dDtcbn1cbi8qKlxuICogU2V0IGEgcXVhdCB0byB0aGUgaWRlbnRpdHkgcXVhdGVybmlvblxuICpcbiAqIEBwYXJhbSB7cXVhdH0gb3V0IHRoZSByZWNlaXZpbmcgcXVhdGVybmlvblxuICogQHJldHVybnMge3F1YXR9IG91dFxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBpZGVudGl0eShvdXQpIHtcbiAgb3V0WzBdID0gMDtcbiAgb3V0WzFdID0gMDtcbiAgb3V0WzJdID0gMDtcbiAgb3V0WzNdID0gMTtcbiAgcmV0dXJuIG91dDtcbn1cbi8qKlxuICogU2V0cyBhIHF1YXQgZnJvbSB0aGUgZ2l2ZW4gYW5nbGUgYW5kIHJvdGF0aW9uIGF4aXMsXG4gKiB0aGVuIHJldHVybnMgaXQuXG4gKlxuICogQHBhcmFtIHtxdWF0fSBvdXQgdGhlIHJlY2VpdmluZyBxdWF0ZXJuaW9uXG4gKiBAcGFyYW0ge1JlYWRvbmx5VmVjM30gYXhpcyB0aGUgYXhpcyBhcm91bmQgd2hpY2ggdG8gcm90YXRlXG4gKiBAcGFyYW0ge051bWJlcn0gcmFkIHRoZSBhbmdsZSBpbiByYWRpYW5zXG4gKiBAcmV0dXJucyB7cXVhdH0gb3V0XG4gKiovXG5cbmV4cG9ydCBmdW5jdGlvbiBzZXRBeGlzQW5nbGUob3V0LCBheGlzLCByYWQpIHtcbiAgcmFkID0gcmFkICogMC41O1xuICB2YXIgcyA9IE1hdGguc2luKHJhZCk7XG4gIG91dFswXSA9IHMgKiBheGlzWzBdO1xuICBvdXRbMV0gPSBzICogYXhpc1sxXTtcbiAgb3V0WzJdID0gcyAqIGF4aXNbMl07XG4gIG91dFszXSA9IE1hdGguY29zKHJhZCk7XG4gIHJldHVybiBvdXQ7XG59XG4vKipcbiAqIEdldHMgdGhlIHJvdGF0aW9uIGF4aXMgYW5kIGFuZ2xlIGZvciBhIGdpdmVuXG4gKiAgcXVhdGVybmlvbi4gSWYgYSBxdWF0ZXJuaW9uIGlzIGNyZWF0ZWQgd2l0aFxuICogIHNldEF4aXNBbmdsZSwgdGhpcyBtZXRob2Qgd2lsbCByZXR1cm4gdGhlIHNhbWVcbiAqICB2YWx1ZXMgYXMgcHJvdmlkaWVkIGluIHRoZSBvcmlnaW5hbCBwYXJhbWV0ZXIgbGlzdFxuICogIE9SIGZ1bmN0aW9uYWxseSBlcXVpdmFsZW50IHZhbHVlcy5cbiAqIEV4YW1wbGU6IFRoZSBxdWF0ZXJuaW9uIGZvcm1lZCBieSBheGlzIFswLCAwLCAxXSBhbmRcbiAqICBhbmdsZSAtOTAgaXMgdGhlIHNhbWUgYXMgdGhlIHF1YXRlcm5pb24gZm9ybWVkIGJ5XG4gKiAgWzAsIDAsIDFdIGFuZCAyNzAuIFRoaXMgbWV0aG9kIGZhdm9ycyB0aGUgbGF0dGVyLlxuICogQHBhcmFtICB7dmVjM30gb3V0X2F4aXMgIFZlY3RvciByZWNlaXZpbmcgdGhlIGF4aXMgb2Ygcm90YXRpb25cbiAqIEBwYXJhbSAge1JlYWRvbmx5UXVhdH0gcSAgICAgUXVhdGVybmlvbiB0byBiZSBkZWNvbXBvc2VkXG4gKiBAcmV0dXJuIHtOdW1iZXJ9ICAgICBBbmdsZSwgaW4gcmFkaWFucywgb2YgdGhlIHJvdGF0aW9uXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGdldEF4aXNBbmdsZShvdXRfYXhpcywgcSkge1xuICB2YXIgcmFkID0gTWF0aC5hY29zKHFbM10pICogMi4wO1xuICB2YXIgcyA9IE1hdGguc2luKHJhZCAvIDIuMCk7XG5cbiAgaWYgKHMgPiBnbE1hdHJpeC5FUFNJTE9OKSB7XG4gICAgb3V0X2F4aXNbMF0gPSBxWzBdIC8gcztcbiAgICBvdXRfYXhpc1sxXSA9IHFbMV0gLyBzO1xuICAgIG91dF9heGlzWzJdID0gcVsyXSAvIHM7XG4gIH0gZWxzZSB7XG4gICAgLy8gSWYgcyBpcyB6ZXJvLCByZXR1cm4gYW55IGF4aXMgKG5vIHJvdGF0aW9uIC0gYXhpcyBkb2VzIG5vdCBtYXR0ZXIpXG4gICAgb3V0X2F4aXNbMF0gPSAxO1xuICAgIG91dF9heGlzWzFdID0gMDtcbiAgICBvdXRfYXhpc1syXSA9IDA7XG4gIH1cblxuICByZXR1cm4gcmFkO1xufVxuLyoqXG4gKiBHZXRzIHRoZSBhbmd1bGFyIGRpc3RhbmNlIGJldHdlZW4gdHdvIHVuaXQgcXVhdGVybmlvbnNcbiAqXG4gKiBAcGFyYW0gIHtSZWFkb25seVF1YXR9IGEgICAgIE9yaWdpbiB1bml0IHF1YXRlcm5pb25cbiAqIEBwYXJhbSAge1JlYWRvbmx5UXVhdH0gYiAgICAgRGVzdGluYXRpb24gdW5pdCBxdWF0ZXJuaW9uXG4gKiBAcmV0dXJuIHtOdW1iZXJ9ICAgICBBbmdsZSwgaW4gcmFkaWFucywgYmV0d2VlbiB0aGUgdHdvIHF1YXRlcm5pb25zXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGdldEFuZ2xlKGEsIGIpIHtcbiAgdmFyIGRvdHByb2R1Y3QgPSBkb3QoYSwgYik7XG4gIHJldHVybiBNYXRoLmFjb3MoMiAqIGRvdHByb2R1Y3QgKiBkb3Rwcm9kdWN0IC0gMSk7XG59XG4vKipcbiAqIE11bHRpcGxpZXMgdHdvIHF1YXQnc1xuICpcbiAqIEBwYXJhbSB7cXVhdH0gb3V0IHRoZSByZWNlaXZpbmcgcXVhdGVybmlvblxuICogQHBhcmFtIHtSZWFkb25seVF1YXR9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7UmVhZG9ubHlRdWF0fSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge3F1YXR9IG91dFxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBtdWx0aXBseShvdXQsIGEsIGIpIHtcbiAgdmFyIGF4ID0gYVswXSxcbiAgICAgIGF5ID0gYVsxXSxcbiAgICAgIGF6ID0gYVsyXSxcbiAgICAgIGF3ID0gYVszXTtcbiAgdmFyIGJ4ID0gYlswXSxcbiAgICAgIGJ5ID0gYlsxXSxcbiAgICAgIGJ6ID0gYlsyXSxcbiAgICAgIGJ3ID0gYlszXTtcbiAgb3V0WzBdID0gYXggKiBidyArIGF3ICogYnggKyBheSAqIGJ6IC0gYXogKiBieTtcbiAgb3V0WzFdID0gYXkgKiBidyArIGF3ICogYnkgKyBheiAqIGJ4IC0gYXggKiBiejtcbiAgb3V0WzJdID0gYXogKiBidyArIGF3ICogYnogKyBheCAqIGJ5IC0gYXkgKiBieDtcbiAgb3V0WzNdID0gYXcgKiBidyAtIGF4ICogYnggLSBheSAqIGJ5IC0gYXogKiBiejtcbiAgcmV0dXJuIG91dDtcbn1cbi8qKlxuICogUm90YXRlcyBhIHF1YXRlcm5pb24gYnkgdGhlIGdpdmVuIGFuZ2xlIGFib3V0IHRoZSBYIGF4aXNcbiAqXG4gKiBAcGFyYW0ge3F1YXR9IG91dCBxdWF0IHJlY2VpdmluZyBvcGVyYXRpb24gcmVzdWx0XG4gKiBAcGFyYW0ge1JlYWRvbmx5UXVhdH0gYSBxdWF0IHRvIHJvdGF0ZVxuICogQHBhcmFtIHtudW1iZXJ9IHJhZCBhbmdsZSAoaW4gcmFkaWFucykgdG8gcm90YXRlXG4gKiBAcmV0dXJucyB7cXVhdH0gb3V0XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIHJvdGF0ZVgob3V0LCBhLCByYWQpIHtcbiAgcmFkICo9IDAuNTtcbiAgdmFyIGF4ID0gYVswXSxcbiAgICAgIGF5ID0gYVsxXSxcbiAgICAgIGF6ID0gYVsyXSxcbiAgICAgIGF3ID0gYVszXTtcbiAgdmFyIGJ4ID0gTWF0aC5zaW4ocmFkKSxcbiAgICAgIGJ3ID0gTWF0aC5jb3MocmFkKTtcbiAgb3V0WzBdID0gYXggKiBidyArIGF3ICogYng7XG4gIG91dFsxXSA9IGF5ICogYncgKyBheiAqIGJ4O1xuICBvdXRbMl0gPSBheiAqIGJ3IC0gYXkgKiBieDtcbiAgb3V0WzNdID0gYXcgKiBidyAtIGF4ICogYng7XG4gIHJldHVybiBvdXQ7XG59XG4vKipcbiAqIFJvdGF0ZXMgYSBxdWF0ZXJuaW9uIGJ5IHRoZSBnaXZlbiBhbmdsZSBhYm91dCB0aGUgWSBheGlzXG4gKlxuICogQHBhcmFtIHtxdWF0fSBvdXQgcXVhdCByZWNlaXZpbmcgb3BlcmF0aW9uIHJlc3VsdFxuICogQHBhcmFtIHtSZWFkb25seVF1YXR9IGEgcXVhdCB0byByb3RhdGVcbiAqIEBwYXJhbSB7bnVtYmVyfSByYWQgYW5nbGUgKGluIHJhZGlhbnMpIHRvIHJvdGF0ZVxuICogQHJldHVybnMge3F1YXR9IG91dFxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiByb3RhdGVZKG91dCwgYSwgcmFkKSB7XG4gIHJhZCAqPSAwLjU7XG4gIHZhciBheCA9IGFbMF0sXG4gICAgICBheSA9IGFbMV0sXG4gICAgICBheiA9IGFbMl0sXG4gICAgICBhdyA9IGFbM107XG4gIHZhciBieSA9IE1hdGguc2luKHJhZCksXG4gICAgICBidyA9IE1hdGguY29zKHJhZCk7XG4gIG91dFswXSA9IGF4ICogYncgLSBheiAqIGJ5O1xuICBvdXRbMV0gPSBheSAqIGJ3ICsgYXcgKiBieTtcbiAgb3V0WzJdID0gYXogKiBidyArIGF4ICogYnk7XG4gIG91dFszXSA9IGF3ICogYncgLSBheSAqIGJ5O1xuICByZXR1cm4gb3V0O1xufVxuLyoqXG4gKiBSb3RhdGVzIGEgcXVhdGVybmlvbiBieSB0aGUgZ2l2ZW4gYW5nbGUgYWJvdXQgdGhlIFogYXhpc1xuICpcbiAqIEBwYXJhbSB7cXVhdH0gb3V0IHF1YXQgcmVjZWl2aW5nIG9wZXJhdGlvbiByZXN1bHRcbiAqIEBwYXJhbSB7UmVhZG9ubHlRdWF0fSBhIHF1YXQgdG8gcm90YXRlXG4gKiBAcGFyYW0ge251bWJlcn0gcmFkIGFuZ2xlIChpbiByYWRpYW5zKSB0byByb3RhdGVcbiAqIEByZXR1cm5zIHtxdWF0fSBvdXRcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gcm90YXRlWihvdXQsIGEsIHJhZCkge1xuICByYWQgKj0gMC41O1xuICB2YXIgYXggPSBhWzBdLFxuICAgICAgYXkgPSBhWzFdLFxuICAgICAgYXogPSBhWzJdLFxuICAgICAgYXcgPSBhWzNdO1xuICB2YXIgYnogPSBNYXRoLnNpbihyYWQpLFxuICAgICAgYncgPSBNYXRoLmNvcyhyYWQpO1xuICBvdXRbMF0gPSBheCAqIGJ3ICsgYXkgKiBiejtcbiAgb3V0WzFdID0gYXkgKiBidyAtIGF4ICogYno7XG4gIG91dFsyXSA9IGF6ICogYncgKyBhdyAqIGJ6O1xuICBvdXRbM10gPSBhdyAqIGJ3IC0gYXogKiBiejtcbiAgcmV0dXJuIG91dDtcbn1cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgVyBjb21wb25lbnQgb2YgYSBxdWF0IGZyb20gdGhlIFgsIFksIGFuZCBaIGNvbXBvbmVudHMuXG4gKiBBc3N1bWVzIHRoYXQgcXVhdGVybmlvbiBpcyAxIHVuaXQgaW4gbGVuZ3RoLlxuICogQW55IGV4aXN0aW5nIFcgY29tcG9uZW50IHdpbGwgYmUgaWdub3JlZC5cbiAqXG4gKiBAcGFyYW0ge3F1YXR9IG91dCB0aGUgcmVjZWl2aW5nIHF1YXRlcm5pb25cbiAqIEBwYXJhbSB7UmVhZG9ubHlRdWF0fSBhIHF1YXQgdG8gY2FsY3VsYXRlIFcgY29tcG9uZW50IG9mXG4gKiBAcmV0dXJucyB7cXVhdH0gb3V0XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGNhbGN1bGF0ZVcob3V0LCBhKSB7XG4gIHZhciB4ID0gYVswXSxcbiAgICAgIHkgPSBhWzFdLFxuICAgICAgeiA9IGFbMl07XG4gIG91dFswXSA9IHg7XG4gIG91dFsxXSA9IHk7XG4gIG91dFsyXSA9IHo7XG4gIG91dFszXSA9IE1hdGguc3FydChNYXRoLmFicygxLjAgLSB4ICogeCAtIHkgKiB5IC0geiAqIHopKTtcbiAgcmV0dXJuIG91dDtcbn1cbi8qKlxuICogQ2FsY3VsYXRlIHRoZSBleHBvbmVudGlhbCBvZiBhIHVuaXQgcXVhdGVybmlvbi5cbiAqXG4gKiBAcGFyYW0ge3F1YXR9IG91dCB0aGUgcmVjZWl2aW5nIHF1YXRlcm5pb25cbiAqIEBwYXJhbSB7UmVhZG9ubHlRdWF0fSBhIHF1YXQgdG8gY2FsY3VsYXRlIHRoZSBleHBvbmVudGlhbCBvZlxuICogQHJldHVybnMge3F1YXR9IG91dFxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBleHAob3V0LCBhKSB7XG4gIHZhciB4ID0gYVswXSxcbiAgICAgIHkgPSBhWzFdLFxuICAgICAgeiA9IGFbMl0sXG4gICAgICB3ID0gYVszXTtcbiAgdmFyIHIgPSBNYXRoLnNxcnQoeCAqIHggKyB5ICogeSArIHogKiB6KTtcbiAgdmFyIGV0ID0gTWF0aC5leHAodyk7XG4gIHZhciBzID0gciA+IDAgPyBldCAqIE1hdGguc2luKHIpIC8gciA6IDA7XG4gIG91dFswXSA9IHggKiBzO1xuICBvdXRbMV0gPSB5ICogcztcbiAgb3V0WzJdID0geiAqIHM7XG4gIG91dFszXSA9IGV0ICogTWF0aC5jb3Mocik7XG4gIHJldHVybiBvdXQ7XG59XG4vKipcbiAqIENhbGN1bGF0ZSB0aGUgbmF0dXJhbCBsb2dhcml0aG0gb2YgYSB1bml0IHF1YXRlcm5pb24uXG4gKlxuICogQHBhcmFtIHtxdWF0fSBvdXQgdGhlIHJlY2VpdmluZyBxdWF0ZXJuaW9uXG4gKiBAcGFyYW0ge1JlYWRvbmx5UXVhdH0gYSBxdWF0IHRvIGNhbGN1bGF0ZSB0aGUgZXhwb25lbnRpYWwgb2ZcbiAqIEByZXR1cm5zIHtxdWF0fSBvdXRcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gbG4ob3V0LCBhKSB7XG4gIHZhciB4ID0gYVswXSxcbiAgICAgIHkgPSBhWzFdLFxuICAgICAgeiA9IGFbMl0sXG4gICAgICB3ID0gYVszXTtcbiAgdmFyIHIgPSBNYXRoLnNxcnQoeCAqIHggKyB5ICogeSArIHogKiB6KTtcbiAgdmFyIHQgPSByID4gMCA/IE1hdGguYXRhbjIociwgdykgLyByIDogMDtcbiAgb3V0WzBdID0geCAqIHQ7XG4gIG91dFsxXSA9IHkgKiB0O1xuICBvdXRbMl0gPSB6ICogdDtcbiAgb3V0WzNdID0gMC41ICogTWF0aC5sb2coeCAqIHggKyB5ICogeSArIHogKiB6ICsgdyAqIHcpO1xuICByZXR1cm4gb3V0O1xufVxuLyoqXG4gKiBDYWxjdWxhdGUgdGhlIHNjYWxhciBwb3dlciBvZiBhIHVuaXQgcXVhdGVybmlvbi5cbiAqXG4gKiBAcGFyYW0ge3F1YXR9IG91dCB0aGUgcmVjZWl2aW5nIHF1YXRlcm5pb25cbiAqIEBwYXJhbSB7UmVhZG9ubHlRdWF0fSBhIHF1YXQgdG8gY2FsY3VsYXRlIHRoZSBleHBvbmVudGlhbCBvZlxuICogQHBhcmFtIHtOdW1iZXJ9IGIgYW1vdW50IHRvIHNjYWxlIHRoZSBxdWF0ZXJuaW9uIGJ5XG4gKiBAcmV0dXJucyB7cXVhdH0gb3V0XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIHBvdyhvdXQsIGEsIGIpIHtcbiAgbG4ob3V0LCBhKTtcbiAgc2NhbGUob3V0LCBvdXQsIGIpO1xuICBleHAob3V0LCBvdXQpO1xuICByZXR1cm4gb3V0O1xufVxuLyoqXG4gKiBQZXJmb3JtcyBhIHNwaGVyaWNhbCBsaW5lYXIgaW50ZXJwb2xhdGlvbiBiZXR3ZWVuIHR3byBxdWF0XG4gKlxuICogQHBhcmFtIHtxdWF0fSBvdXQgdGhlIHJlY2VpdmluZyBxdWF0ZXJuaW9uXG4gKiBAcGFyYW0ge1JlYWRvbmx5UXVhdH0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHtSZWFkb25seVF1YXR9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcGFyYW0ge051bWJlcn0gdCBpbnRlcnBvbGF0aW9uIGFtb3VudCwgaW4gdGhlIHJhbmdlIFswLTFdLCBiZXR3ZWVuIHRoZSB0d28gaW5wdXRzXG4gKiBAcmV0dXJucyB7cXVhdH0gb3V0XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIHNsZXJwKG91dCwgYSwgYiwgdCkge1xuICAvLyBiZW5jaG1hcmtzOlxuICAvLyAgICBodHRwOi8vanNwZXJmLmNvbS9xdWF0ZXJuaW9uLXNsZXJwLWltcGxlbWVudGF0aW9uc1xuICB2YXIgYXggPSBhWzBdLFxuICAgICAgYXkgPSBhWzFdLFxuICAgICAgYXogPSBhWzJdLFxuICAgICAgYXcgPSBhWzNdO1xuICB2YXIgYnggPSBiWzBdLFxuICAgICAgYnkgPSBiWzFdLFxuICAgICAgYnogPSBiWzJdLFxuICAgICAgYncgPSBiWzNdO1xuICB2YXIgb21lZ2EsIGNvc29tLCBzaW5vbSwgc2NhbGUwLCBzY2FsZTE7IC8vIGNhbGMgY29zaW5lXG5cbiAgY29zb20gPSBheCAqIGJ4ICsgYXkgKiBieSArIGF6ICogYnogKyBhdyAqIGJ3OyAvLyBhZGp1c3Qgc2lnbnMgKGlmIG5lY2Vzc2FyeSlcblxuICBpZiAoY29zb20gPCAwLjApIHtcbiAgICBjb3NvbSA9IC1jb3NvbTtcbiAgICBieCA9IC1ieDtcbiAgICBieSA9IC1ieTtcbiAgICBieiA9IC1iejtcbiAgICBidyA9IC1idztcbiAgfSAvLyBjYWxjdWxhdGUgY29lZmZpY2llbnRzXG5cblxuICBpZiAoMS4wIC0gY29zb20gPiBnbE1hdHJpeC5FUFNJTE9OKSB7XG4gICAgLy8gc3RhbmRhcmQgY2FzZSAoc2xlcnApXG4gICAgb21lZ2EgPSBNYXRoLmFjb3MoY29zb20pO1xuICAgIHNpbm9tID0gTWF0aC5zaW4ob21lZ2EpO1xuICAgIHNjYWxlMCA9IE1hdGguc2luKCgxLjAgLSB0KSAqIG9tZWdhKSAvIHNpbm9tO1xuICAgIHNjYWxlMSA9IE1hdGguc2luKHQgKiBvbWVnYSkgLyBzaW5vbTtcbiAgfSBlbHNlIHtcbiAgICAvLyBcImZyb21cIiBhbmQgXCJ0b1wiIHF1YXRlcm5pb25zIGFyZSB2ZXJ5IGNsb3NlXG4gICAgLy8gIC4uLiBzbyB3ZSBjYW4gZG8gYSBsaW5lYXIgaW50ZXJwb2xhdGlvblxuICAgIHNjYWxlMCA9IDEuMCAtIHQ7XG4gICAgc2NhbGUxID0gdDtcbiAgfSAvLyBjYWxjdWxhdGUgZmluYWwgdmFsdWVzXG5cblxuICBvdXRbMF0gPSBzY2FsZTAgKiBheCArIHNjYWxlMSAqIGJ4O1xuICBvdXRbMV0gPSBzY2FsZTAgKiBheSArIHNjYWxlMSAqIGJ5O1xuICBvdXRbMl0gPSBzY2FsZTAgKiBheiArIHNjYWxlMSAqIGJ6O1xuICBvdXRbM10gPSBzY2FsZTAgKiBhdyArIHNjYWxlMSAqIGJ3O1xuICByZXR1cm4gb3V0O1xufVxuLyoqXG4gKiBHZW5lcmF0ZXMgYSByYW5kb20gdW5pdCBxdWF0ZXJuaW9uXG4gKlxuICogQHBhcmFtIHtxdWF0fSBvdXQgdGhlIHJlY2VpdmluZyBxdWF0ZXJuaW9uXG4gKiBAcmV0dXJucyB7cXVhdH0gb3V0XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIHJhbmRvbShvdXQpIHtcbiAgLy8gSW1wbGVtZW50YXRpb24gb2YgaHR0cDovL3BsYW5uaW5nLmNzLnVpdWMuZWR1L25vZGUxOTguaHRtbFxuICAvLyBUT0RPOiBDYWxsaW5nIHJhbmRvbSAzIHRpbWVzIGlzIHByb2JhYmx5IG5vdCB0aGUgZmFzdGVzdCBzb2x1dGlvblxuICB2YXIgdTEgPSBnbE1hdHJpeC5SQU5ET00oKTtcbiAgdmFyIHUyID0gZ2xNYXRyaXguUkFORE9NKCk7XG4gIHZhciB1MyA9IGdsTWF0cml4LlJBTkRPTSgpO1xuICB2YXIgc3FydDFNaW51c1UxID0gTWF0aC5zcXJ0KDEgLSB1MSk7XG4gIHZhciBzcXJ0VTEgPSBNYXRoLnNxcnQodTEpO1xuICBvdXRbMF0gPSBzcXJ0MU1pbnVzVTEgKiBNYXRoLnNpbigyLjAgKiBNYXRoLlBJICogdTIpO1xuICBvdXRbMV0gPSBzcXJ0MU1pbnVzVTEgKiBNYXRoLmNvcygyLjAgKiBNYXRoLlBJICogdTIpO1xuICBvdXRbMl0gPSBzcXJ0VTEgKiBNYXRoLnNpbigyLjAgKiBNYXRoLlBJICogdTMpO1xuICBvdXRbM10gPSBzcXJ0VTEgKiBNYXRoLmNvcygyLjAgKiBNYXRoLlBJICogdTMpO1xuICByZXR1cm4gb3V0O1xufVxuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSBpbnZlcnNlIG9mIGEgcXVhdFxuICpcbiAqIEBwYXJhbSB7cXVhdH0gb3V0IHRoZSByZWNlaXZpbmcgcXVhdGVybmlvblxuICogQHBhcmFtIHtSZWFkb25seVF1YXR9IGEgcXVhdCB0byBjYWxjdWxhdGUgaW52ZXJzZSBvZlxuICogQHJldHVybnMge3F1YXR9IG91dFxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBpbnZlcnQob3V0LCBhKSB7XG4gIHZhciBhMCA9IGFbMF0sXG4gICAgICBhMSA9IGFbMV0sXG4gICAgICBhMiA9IGFbMl0sXG4gICAgICBhMyA9IGFbM107XG4gIHZhciBkb3QgPSBhMCAqIGEwICsgYTEgKiBhMSArIGEyICogYTIgKyBhMyAqIGEzO1xuICB2YXIgaW52RG90ID0gZG90ID8gMS4wIC8gZG90IDogMDsgLy8gVE9ETzogV291bGQgYmUgZmFzdGVyIHRvIHJldHVybiBbMCwwLDAsMF0gaW1tZWRpYXRlbHkgaWYgZG90ID09IDBcblxuICBvdXRbMF0gPSAtYTAgKiBpbnZEb3Q7XG4gIG91dFsxXSA9IC1hMSAqIGludkRvdDtcbiAgb3V0WzJdID0gLWEyICogaW52RG90O1xuICBvdXRbM10gPSBhMyAqIGludkRvdDtcbiAgcmV0dXJuIG91dDtcbn1cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgY29uanVnYXRlIG9mIGEgcXVhdFxuICogSWYgdGhlIHF1YXRlcm5pb24gaXMgbm9ybWFsaXplZCwgdGhpcyBmdW5jdGlvbiBpcyBmYXN0ZXIgdGhhbiBxdWF0LmludmVyc2UgYW5kIHByb2R1Y2VzIHRoZSBzYW1lIHJlc3VsdC5cbiAqXG4gKiBAcGFyYW0ge3F1YXR9IG91dCB0aGUgcmVjZWl2aW5nIHF1YXRlcm5pb25cbiAqIEBwYXJhbSB7UmVhZG9ubHlRdWF0fSBhIHF1YXQgdG8gY2FsY3VsYXRlIGNvbmp1Z2F0ZSBvZlxuICogQHJldHVybnMge3F1YXR9IG91dFxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBjb25qdWdhdGUob3V0LCBhKSB7XG4gIG91dFswXSA9IC1hWzBdO1xuICBvdXRbMV0gPSAtYVsxXTtcbiAgb3V0WzJdID0gLWFbMl07XG4gIG91dFszXSA9IGFbM107XG4gIHJldHVybiBvdXQ7XG59XG4vKipcbiAqIENyZWF0ZXMgYSBxdWF0ZXJuaW9uIGZyb20gdGhlIGdpdmVuIDN4MyByb3RhdGlvbiBtYXRyaXguXG4gKlxuICogTk9URTogVGhlIHJlc3VsdGFudCBxdWF0ZXJuaW9uIGlzIG5vdCBub3JtYWxpemVkLCBzbyB5b3Ugc2hvdWxkIGJlIHN1cmVcbiAqIHRvIHJlbm9ybWFsaXplIHRoZSBxdWF0ZXJuaW9uIHlvdXJzZWxmIHdoZXJlIG5lY2Vzc2FyeS5cbiAqXG4gKiBAcGFyYW0ge3F1YXR9IG91dCB0aGUgcmVjZWl2aW5nIHF1YXRlcm5pb25cbiAqIEBwYXJhbSB7UmVhZG9ubHlNYXQzfSBtIHJvdGF0aW9uIG1hdHJpeFxuICogQHJldHVybnMge3F1YXR9IG91dFxuICogQGZ1bmN0aW9uXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGZyb21NYXQzKG91dCwgbSkge1xuICAvLyBBbGdvcml0aG0gaW4gS2VuIFNob2VtYWtlJ3MgYXJ0aWNsZSBpbiAxOTg3IFNJR0dSQVBIIGNvdXJzZSBub3Rlc1xuICAvLyBhcnRpY2xlIFwiUXVhdGVybmlvbiBDYWxjdWx1cyBhbmQgRmFzdCBBbmltYXRpb25cIi5cbiAgdmFyIGZUcmFjZSA9IG1bMF0gKyBtWzRdICsgbVs4XTtcbiAgdmFyIGZSb290O1xuXG4gIGlmIChmVHJhY2UgPiAwLjApIHtcbiAgICAvLyB8d3wgPiAxLzIsIG1heSBhcyB3ZWxsIGNob29zZSB3ID4gMS8yXG4gICAgZlJvb3QgPSBNYXRoLnNxcnQoZlRyYWNlICsgMS4wKTsgLy8gMndcblxuICAgIG91dFszXSA9IDAuNSAqIGZSb290O1xuICAgIGZSb290ID0gMC41IC8gZlJvb3Q7IC8vIDEvKDR3KVxuXG4gICAgb3V0WzBdID0gKG1bNV0gLSBtWzddKSAqIGZSb290O1xuICAgIG91dFsxXSA9IChtWzZdIC0gbVsyXSkgKiBmUm9vdDtcbiAgICBvdXRbMl0gPSAobVsxXSAtIG1bM10pICogZlJvb3Q7XG4gIH0gZWxzZSB7XG4gICAgLy8gfHd8IDw9IDEvMlxuICAgIHZhciBpID0gMDtcbiAgICBpZiAobVs0XSA+IG1bMF0pIGkgPSAxO1xuICAgIGlmIChtWzhdID4gbVtpICogMyArIGldKSBpID0gMjtcbiAgICB2YXIgaiA9IChpICsgMSkgJSAzO1xuICAgIHZhciBrID0gKGkgKyAyKSAlIDM7XG4gICAgZlJvb3QgPSBNYXRoLnNxcnQobVtpICogMyArIGldIC0gbVtqICogMyArIGpdIC0gbVtrICogMyArIGtdICsgMS4wKTtcbiAgICBvdXRbaV0gPSAwLjUgKiBmUm9vdDtcbiAgICBmUm9vdCA9IDAuNSAvIGZSb290O1xuICAgIG91dFszXSA9IChtW2ogKiAzICsga10gLSBtW2sgKiAzICsgal0pICogZlJvb3Q7XG4gICAgb3V0W2pdID0gKG1baiAqIDMgKyBpXSArIG1baSAqIDMgKyBqXSkgKiBmUm9vdDtcbiAgICBvdXRba10gPSAobVtrICogMyArIGldICsgbVtpICogMyArIGtdKSAqIGZSb290O1xuICB9XG5cbiAgcmV0dXJuIG91dDtcbn1cbi8qKlxuICogQ3JlYXRlcyBhIHF1YXRlcm5pb24gZnJvbSB0aGUgZ2l2ZW4gZXVsZXIgYW5nbGUgeCwgeSwgei5cbiAqXG4gKiBAcGFyYW0ge3F1YXR9IG91dCB0aGUgcmVjZWl2aW5nIHF1YXRlcm5pb25cbiAqIEBwYXJhbSB7eH0gQW5nbGUgdG8gcm90YXRlIGFyb3VuZCBYIGF4aXMgaW4gZGVncmVlcy5cbiAqIEBwYXJhbSB7eX0gQW5nbGUgdG8gcm90YXRlIGFyb3VuZCBZIGF4aXMgaW4gZGVncmVlcy5cbiAqIEBwYXJhbSB7en0gQW5nbGUgdG8gcm90YXRlIGFyb3VuZCBaIGF4aXMgaW4gZGVncmVlcy5cbiAqIEByZXR1cm5zIHtxdWF0fSBvdXRcbiAqIEBmdW5jdGlvblxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBmcm9tRXVsZXIob3V0LCB4LCB5LCB6KSB7XG4gIHZhciBoYWxmVG9SYWQgPSAwLjUgKiBNYXRoLlBJIC8gMTgwLjA7XG4gIHggKj0gaGFsZlRvUmFkO1xuICB5ICo9IGhhbGZUb1JhZDtcbiAgeiAqPSBoYWxmVG9SYWQ7XG4gIHZhciBzeCA9IE1hdGguc2luKHgpO1xuICB2YXIgY3ggPSBNYXRoLmNvcyh4KTtcbiAgdmFyIHN5ID0gTWF0aC5zaW4oeSk7XG4gIHZhciBjeSA9IE1hdGguY29zKHkpO1xuICB2YXIgc3ogPSBNYXRoLnNpbih6KTtcbiAgdmFyIGN6ID0gTWF0aC5jb3Moeik7XG4gIG91dFswXSA9IHN4ICogY3kgKiBjeiAtIGN4ICogc3kgKiBzejtcbiAgb3V0WzFdID0gY3ggKiBzeSAqIGN6ICsgc3ggKiBjeSAqIHN6O1xuICBvdXRbMl0gPSBjeCAqIGN5ICogc3ogLSBzeCAqIHN5ICogY3o7XG4gIG91dFszXSA9IGN4ICogY3kgKiBjeiArIHN4ICogc3kgKiBzejtcbiAgcmV0dXJuIG91dDtcbn1cbi8qKlxuICogUmV0dXJucyBhIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiBhIHF1YXRlbmlvblxuICpcbiAqIEBwYXJhbSB7UmVhZG9ubHlRdWF0fSBhIHZlY3RvciB0byByZXByZXNlbnQgYXMgYSBzdHJpbmdcbiAqIEByZXR1cm5zIHtTdHJpbmd9IHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiB0aGUgdmVjdG9yXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIHN0cihhKSB7XG4gIHJldHVybiBcInF1YXQoXCIgKyBhWzBdICsgXCIsIFwiICsgYVsxXSArIFwiLCBcIiArIGFbMl0gKyBcIiwgXCIgKyBhWzNdICsgXCIpXCI7XG59XG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgcXVhdCBpbml0aWFsaXplZCB3aXRoIHZhbHVlcyBmcm9tIGFuIGV4aXN0aW5nIHF1YXRlcm5pb25cbiAqXG4gKiBAcGFyYW0ge1JlYWRvbmx5UXVhdH0gYSBxdWF0ZXJuaW9uIHRvIGNsb25lXG4gKiBAcmV0dXJucyB7cXVhdH0gYSBuZXcgcXVhdGVybmlvblxuICogQGZ1bmN0aW9uXG4gKi9cblxuZXhwb3J0IHZhciBjbG9uZSA9IHZlYzQuY2xvbmU7XG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgcXVhdCBpbml0aWFsaXplZCB3aXRoIHRoZSBnaXZlbiB2YWx1ZXNcbiAqXG4gKiBAcGFyYW0ge051bWJlcn0geCBYIGNvbXBvbmVudFxuICogQHBhcmFtIHtOdW1iZXJ9IHkgWSBjb21wb25lbnRcbiAqIEBwYXJhbSB7TnVtYmVyfSB6IFogY29tcG9uZW50XG4gKiBAcGFyYW0ge051bWJlcn0gdyBXIGNvbXBvbmVudFxuICogQHJldHVybnMge3F1YXR9IGEgbmV3IHF1YXRlcm5pb25cbiAqIEBmdW5jdGlvblxuICovXG5cbmV4cG9ydCB2YXIgZnJvbVZhbHVlcyA9IHZlYzQuZnJvbVZhbHVlcztcbi8qKlxuICogQ29weSB0aGUgdmFsdWVzIGZyb20gb25lIHF1YXQgdG8gYW5vdGhlclxuICpcbiAqIEBwYXJhbSB7cXVhdH0gb3V0IHRoZSByZWNlaXZpbmcgcXVhdGVybmlvblxuICogQHBhcmFtIHtSZWFkb25seVF1YXR9IGEgdGhlIHNvdXJjZSBxdWF0ZXJuaW9uXG4gKiBAcmV0dXJucyB7cXVhdH0gb3V0XG4gKiBAZnVuY3Rpb25cbiAqL1xuXG5leHBvcnQgdmFyIGNvcHkgPSB2ZWM0LmNvcHk7XG4vKipcbiAqIFNldCB0aGUgY29tcG9uZW50cyBvZiBhIHF1YXQgdG8gdGhlIGdpdmVuIHZhbHVlc1xuICpcbiAqIEBwYXJhbSB7cXVhdH0gb3V0IHRoZSByZWNlaXZpbmcgcXVhdGVybmlvblxuICogQHBhcmFtIHtOdW1iZXJ9IHggWCBjb21wb25lbnRcbiAqIEBwYXJhbSB7TnVtYmVyfSB5IFkgY29tcG9uZW50XG4gKiBAcGFyYW0ge051bWJlcn0geiBaIGNvbXBvbmVudFxuICogQHBhcmFtIHtOdW1iZXJ9IHcgVyBjb21wb25lbnRcbiAqIEByZXR1cm5zIHtxdWF0fSBvdXRcbiAqIEBmdW5jdGlvblxuICovXG5cbmV4cG9ydCB2YXIgc2V0ID0gdmVjNC5zZXQ7XG4vKipcbiAqIEFkZHMgdHdvIHF1YXQnc1xuICpcbiAqIEBwYXJhbSB7cXVhdH0gb3V0IHRoZSByZWNlaXZpbmcgcXVhdGVybmlvblxuICogQHBhcmFtIHtSZWFkb25seVF1YXR9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7UmVhZG9ubHlRdWF0fSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge3F1YXR9IG91dFxuICogQGZ1bmN0aW9uXG4gKi9cblxuZXhwb3J0IHZhciBhZGQgPSB2ZWM0LmFkZDtcbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayBxdWF0Lm11bHRpcGx5fVxuICogQGZ1bmN0aW9uXG4gKi9cblxuZXhwb3J0IHZhciBtdWwgPSBtdWx0aXBseTtcbi8qKlxuICogU2NhbGVzIGEgcXVhdCBieSBhIHNjYWxhciBudW1iZXJcbiAqXG4gKiBAcGFyYW0ge3F1YXR9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHtSZWFkb25seVF1YXR9IGEgdGhlIHZlY3RvciB0byBzY2FsZVxuICogQHBhcmFtIHtOdW1iZXJ9IGIgYW1vdW50IHRvIHNjYWxlIHRoZSB2ZWN0b3IgYnlcbiAqIEByZXR1cm5zIHtxdWF0fSBvdXRcbiAqIEBmdW5jdGlvblxuICovXG5cbmV4cG9ydCB2YXIgc2NhbGUgPSB2ZWM0LnNjYWxlO1xuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSBkb3QgcHJvZHVjdCBvZiB0d28gcXVhdCdzXG4gKlxuICogQHBhcmFtIHtSZWFkb25seVF1YXR9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7UmVhZG9ubHlRdWF0fSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge051bWJlcn0gZG90IHByb2R1Y3Qgb2YgYSBhbmQgYlxuICogQGZ1bmN0aW9uXG4gKi9cblxuZXhwb3J0IHZhciBkb3QgPSB2ZWM0LmRvdDtcbi8qKlxuICogUGVyZm9ybXMgYSBsaW5lYXIgaW50ZXJwb2xhdGlvbiBiZXR3ZWVuIHR3byBxdWF0J3NcbiAqXG4gKiBAcGFyYW0ge3F1YXR9IG91dCB0aGUgcmVjZWl2aW5nIHF1YXRlcm5pb25cbiAqIEBwYXJhbSB7UmVhZG9ubHlRdWF0fSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge1JlYWRvbmx5UXVhdH0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEBwYXJhbSB7TnVtYmVyfSB0IGludGVycG9sYXRpb24gYW1vdW50LCBpbiB0aGUgcmFuZ2UgWzAtMV0sIGJldHdlZW4gdGhlIHR3byBpbnB1dHNcbiAqIEByZXR1cm5zIHtxdWF0fSBvdXRcbiAqIEBmdW5jdGlvblxuICovXG5cbmV4cG9ydCB2YXIgbGVycCA9IHZlYzQubGVycDtcbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgbGVuZ3RoIG9mIGEgcXVhdFxuICpcbiAqIEBwYXJhbSB7UmVhZG9ubHlRdWF0fSBhIHZlY3RvciB0byBjYWxjdWxhdGUgbGVuZ3RoIG9mXG4gKiBAcmV0dXJucyB7TnVtYmVyfSBsZW5ndGggb2YgYVxuICovXG5cbmV4cG9ydCB2YXIgbGVuZ3RoID0gdmVjNC5sZW5ndGg7XG4vKipcbiAqIEFsaWFzIGZvciB7QGxpbmsgcXVhdC5sZW5ndGh9XG4gKiBAZnVuY3Rpb25cbiAqL1xuXG5leHBvcnQgdmFyIGxlbiA9IGxlbmd0aDtcbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgc3F1YXJlZCBsZW5ndGggb2YgYSBxdWF0XG4gKlxuICogQHBhcmFtIHtSZWFkb25seVF1YXR9IGEgdmVjdG9yIHRvIGNhbGN1bGF0ZSBzcXVhcmVkIGxlbmd0aCBvZlxuICogQHJldHVybnMge051bWJlcn0gc3F1YXJlZCBsZW5ndGggb2YgYVxuICogQGZ1bmN0aW9uXG4gKi9cblxuZXhwb3J0IHZhciBzcXVhcmVkTGVuZ3RoID0gdmVjNC5zcXVhcmVkTGVuZ3RoO1xuLyoqXG4gKiBBbGlhcyBmb3Ige0BsaW5rIHF1YXQuc3F1YXJlZExlbmd0aH1cbiAqIEBmdW5jdGlvblxuICovXG5cbmV4cG9ydCB2YXIgc3FyTGVuID0gc3F1YXJlZExlbmd0aDtcbi8qKlxuICogTm9ybWFsaXplIGEgcXVhdFxuICpcbiAqIEBwYXJhbSB7cXVhdH0gb3V0IHRoZSByZWNlaXZpbmcgcXVhdGVybmlvblxuICogQHBhcmFtIHtSZWFkb25seVF1YXR9IGEgcXVhdGVybmlvbiB0byBub3JtYWxpemVcbiAqIEByZXR1cm5zIHtxdWF0fSBvdXRcbiAqIEBmdW5jdGlvblxuICovXG5cbmV4cG9ydCB2YXIgbm9ybWFsaXplID0gdmVjNC5ub3JtYWxpemU7XG4vKipcbiAqIFJldHVybnMgd2hldGhlciBvciBub3QgdGhlIHF1YXRlcm5pb25zIGhhdmUgZXhhY3RseSB0aGUgc2FtZSBlbGVtZW50cyBpbiB0aGUgc2FtZSBwb3NpdGlvbiAod2hlbiBjb21wYXJlZCB3aXRoID09PSlcbiAqXG4gKiBAcGFyYW0ge1JlYWRvbmx5UXVhdH0gYSBUaGUgZmlyc3QgcXVhdGVybmlvbi5cbiAqIEBwYXJhbSB7UmVhZG9ubHlRdWF0fSBiIFRoZSBzZWNvbmQgcXVhdGVybmlvbi5cbiAqIEByZXR1cm5zIHtCb29sZWFufSBUcnVlIGlmIHRoZSB2ZWN0b3JzIGFyZSBlcXVhbCwgZmFsc2Ugb3RoZXJ3aXNlLlxuICovXG5cbmV4cG9ydCB2YXIgZXhhY3RFcXVhbHMgPSB2ZWM0LmV4YWN0RXF1YWxzO1xuLyoqXG4gKiBSZXR1cm5zIHdoZXRoZXIgb3Igbm90IHRoZSBxdWF0ZXJuaW9ucyBoYXZlIGFwcHJveGltYXRlbHkgdGhlIHNhbWUgZWxlbWVudHMgaW4gdGhlIHNhbWUgcG9zaXRpb24uXG4gKlxuICogQHBhcmFtIHtSZWFkb25seVF1YXR9IGEgVGhlIGZpcnN0IHZlY3Rvci5cbiAqIEBwYXJhbSB7UmVhZG9ubHlRdWF0fSBiIFRoZSBzZWNvbmQgdmVjdG9yLlxuICogQHJldHVybnMge0Jvb2xlYW59IFRydWUgaWYgdGhlIHZlY3RvcnMgYXJlIGVxdWFsLCBmYWxzZSBvdGhlcndpc2UuXG4gKi9cblxuZXhwb3J0IHZhciBlcXVhbHMgPSB2ZWM0LmVxdWFscztcbi8qKlxuICogU2V0cyBhIHF1YXRlcm5pb24gdG8gcmVwcmVzZW50IHRoZSBzaG9ydGVzdCByb3RhdGlvbiBmcm9tIG9uZVxuICogdmVjdG9yIHRvIGFub3RoZXIuXG4gKlxuICogQm90aCB2ZWN0b3JzIGFyZSBhc3N1bWVkIHRvIGJlIHVuaXQgbGVuZ3RoLlxuICpcbiAqIEBwYXJhbSB7cXVhdH0gb3V0IHRoZSByZWNlaXZpbmcgcXVhdGVybmlvbi5cbiAqIEBwYXJhbSB7UmVhZG9ubHlWZWMzfSBhIHRoZSBpbml0aWFsIHZlY3RvclxuICogQHBhcmFtIHtSZWFkb25seVZlYzN9IGIgdGhlIGRlc3RpbmF0aW9uIHZlY3RvclxuICogQHJldHVybnMge3F1YXR9IG91dFxuICovXG5cbmV4cG9ydCB2YXIgcm90YXRpb25UbyA9IGZ1bmN0aW9uICgpIHtcbiAgdmFyIHRtcHZlYzMgPSB2ZWMzLmNyZWF0ZSgpO1xuICB2YXIgeFVuaXRWZWMzID0gdmVjMy5mcm9tVmFsdWVzKDEsIDAsIDApO1xuICB2YXIgeVVuaXRWZWMzID0gdmVjMy5mcm9tVmFsdWVzKDAsIDEsIDApO1xuICByZXR1cm4gZnVuY3Rpb24gKG91dCwgYSwgYikge1xuICAgIHZhciBkb3QgPSB2ZWMzLmRvdChhLCBiKTtcblxuICAgIGlmIChkb3QgPCAtMC45OTk5OTkpIHtcbiAgICAgIHZlYzMuY3Jvc3ModG1wdmVjMywgeFVuaXRWZWMzLCBhKTtcbiAgICAgIGlmICh2ZWMzLmxlbih0bXB2ZWMzKSA8IDAuMDAwMDAxKSB2ZWMzLmNyb3NzKHRtcHZlYzMsIHlVbml0VmVjMywgYSk7XG4gICAgICB2ZWMzLm5vcm1hbGl6ZSh0bXB2ZWMzLCB0bXB2ZWMzKTtcbiAgICAgIHNldEF4aXNBbmdsZShvdXQsIHRtcHZlYzMsIE1hdGguUEkpO1xuICAgICAgcmV0dXJuIG91dDtcbiAgICB9IGVsc2UgaWYgKGRvdCA+IDAuOTk5OTk5KSB7XG4gICAgICBvdXRbMF0gPSAwO1xuICAgICAgb3V0WzFdID0gMDtcbiAgICAgIG91dFsyXSA9IDA7XG4gICAgICBvdXRbM10gPSAxO1xuICAgICAgcmV0dXJuIG91dDtcbiAgICB9IGVsc2Uge1xuICAgICAgdmVjMy5jcm9zcyh0bXB2ZWMzLCBhLCBiKTtcbiAgICAgIG91dFswXSA9IHRtcHZlYzNbMF07XG4gICAgICBvdXRbMV0gPSB0bXB2ZWMzWzFdO1xuICAgICAgb3V0WzJdID0gdG1wdmVjM1syXTtcbiAgICAgIG91dFszXSA9IDEgKyBkb3Q7XG4gICAgICByZXR1cm4gbm9ybWFsaXplKG91dCwgb3V0KTtcbiAgICB9XG4gIH07XG59KCk7XG4vKipcbiAqIFBlcmZvcm1zIGEgc3BoZXJpY2FsIGxpbmVhciBpbnRlcnBvbGF0aW9uIHdpdGggdHdvIGNvbnRyb2wgcG9pbnRzXG4gKlxuICogQHBhcmFtIHtxdWF0fSBvdXQgdGhlIHJlY2VpdmluZyBxdWF0ZXJuaW9uXG4gKiBAcGFyYW0ge1JlYWRvbmx5UXVhdH0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHtSZWFkb25seVF1YXR9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcGFyYW0ge1JlYWRvbmx5UXVhdH0gYyB0aGUgdGhpcmQgb3BlcmFuZFxuICogQHBhcmFtIHtSZWFkb25seVF1YXR9IGQgdGhlIGZvdXJ0aCBvcGVyYW5kXG4gKiBAcGFyYW0ge051bWJlcn0gdCBpbnRlcnBvbGF0aW9uIGFtb3VudCwgaW4gdGhlIHJhbmdlIFswLTFdLCBiZXR3ZWVuIHRoZSB0d28gaW5wdXRzXG4gKiBAcmV0dXJucyB7cXVhdH0gb3V0XG4gKi9cblxuZXhwb3J0IHZhciBzcWxlcnAgPSBmdW5jdGlvbiAoKSB7XG4gIHZhciB0ZW1wMSA9IGNyZWF0ZSgpO1xuICB2YXIgdGVtcDIgPSBjcmVhdGUoKTtcbiAgcmV0dXJuIGZ1bmN0aW9uIChvdXQsIGEsIGIsIGMsIGQsIHQpIHtcbiAgICBzbGVycCh0ZW1wMSwgYSwgZCwgdCk7XG4gICAgc2xlcnAodGVtcDIsIGIsIGMsIHQpO1xuICAgIHNsZXJwKG91dCwgdGVtcDEsIHRlbXAyLCAyICogdCAqICgxIC0gdCkpO1xuICAgIHJldHVybiBvdXQ7XG4gIH07XG59KCk7XG4vKipcbiAqIFNldHMgdGhlIHNwZWNpZmllZCBxdWF0ZXJuaW9uIHdpdGggdmFsdWVzIGNvcnJlc3BvbmRpbmcgdG8gdGhlIGdpdmVuXG4gKiBheGVzLiBFYWNoIGF4aXMgaXMgYSB2ZWMzIGFuZCBpcyBleHBlY3RlZCB0byBiZSB1bml0IGxlbmd0aCBhbmRcbiAqIHBlcnBlbmRpY3VsYXIgdG8gYWxsIG90aGVyIHNwZWNpZmllZCBheGVzLlxuICpcbiAqIEBwYXJhbSB7UmVhZG9ubHlWZWMzfSB2aWV3ICB0aGUgdmVjdG9yIHJlcHJlc2VudGluZyB0aGUgdmlld2luZyBkaXJlY3Rpb25cbiAqIEBwYXJhbSB7UmVhZG9ubHlWZWMzfSByaWdodCB0aGUgdmVjdG9yIHJlcHJlc2VudGluZyB0aGUgbG9jYWwgXCJyaWdodFwiIGRpcmVjdGlvblxuICogQHBhcmFtIHtSZWFkb25seVZlYzN9IHVwICAgIHRoZSB2ZWN0b3IgcmVwcmVzZW50aW5nIHRoZSBsb2NhbCBcInVwXCIgZGlyZWN0aW9uXG4gKiBAcmV0dXJucyB7cXVhdH0gb3V0XG4gKi9cblxuZXhwb3J0IHZhciBzZXRBeGVzID0gZnVuY3Rpb24gKCkge1xuICB2YXIgbWF0ciA9IG1hdDMuY3JlYXRlKCk7XG4gIHJldHVybiBmdW5jdGlvbiAob3V0LCB2aWV3LCByaWdodCwgdXApIHtcbiAgICBtYXRyWzBdID0gcmlnaHRbMF07XG4gICAgbWF0clszXSA9IHJpZ2h0WzFdO1xuICAgIG1hdHJbNl0gPSByaWdodFsyXTtcbiAgICBtYXRyWzFdID0gdXBbMF07XG4gICAgbWF0cls0XSA9IHVwWzFdO1xuICAgIG1hdHJbN10gPSB1cFsyXTtcbiAgICBtYXRyWzJdID0gLXZpZXdbMF07XG4gICAgbWF0cls1XSA9IC12aWV3WzFdO1xuICAgIG1hdHJbOF0gPSAtdmlld1syXTtcbiAgICByZXR1cm4gbm9ybWFsaXplKG91dCwgZnJvbU1hdDMob3V0LCBtYXRyKSk7XG4gIH07XG59KCk7IiwiaW1wb3J0ICogYXMgZ2xNYXRyaXggZnJvbSBcIi4vY29tbW9uLmpzXCI7XG4vKipcbiAqIDQgRGltZW5zaW9uYWwgVmVjdG9yXG4gKiBAbW9kdWxlIHZlYzRcbiAqL1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcsIGVtcHR5IHZlYzRcbiAqXG4gKiBAcmV0dXJucyB7dmVjNH0gYSBuZXcgNEQgdmVjdG9yXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZSgpIHtcbiAgdmFyIG91dCA9IG5ldyBnbE1hdHJpeC5BUlJBWV9UWVBFKDQpO1xuXG4gIGlmIChnbE1hdHJpeC5BUlJBWV9UWVBFICE9IEZsb2F0MzJBcnJheSkge1xuICAgIG91dFswXSA9IDA7XG4gICAgb3V0WzFdID0gMDtcbiAgICBvdXRbMl0gPSAwO1xuICAgIG91dFszXSA9IDA7XG4gIH1cblxuICByZXR1cm4gb3V0O1xufVxuLyoqXG4gKiBDcmVhdGVzIGEgbmV3IHZlYzQgaW5pdGlhbGl6ZWQgd2l0aCB2YWx1ZXMgZnJvbSBhbiBleGlzdGluZyB2ZWN0b3JcbiAqXG4gKiBAcGFyYW0ge1JlYWRvbmx5VmVjNH0gYSB2ZWN0b3IgdG8gY2xvbmVcbiAqIEByZXR1cm5zIHt2ZWM0fSBhIG5ldyA0RCB2ZWN0b3JcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gY2xvbmUoYSkge1xuICB2YXIgb3V0ID0gbmV3IGdsTWF0cml4LkFSUkFZX1RZUEUoNCk7XG4gIG91dFswXSA9IGFbMF07XG4gIG91dFsxXSA9IGFbMV07XG4gIG91dFsyXSA9IGFbMl07XG4gIG91dFszXSA9IGFbM107XG4gIHJldHVybiBvdXQ7XG59XG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgdmVjNCBpbml0aWFsaXplZCB3aXRoIHRoZSBnaXZlbiB2YWx1ZXNcbiAqXG4gKiBAcGFyYW0ge051bWJlcn0geCBYIGNvbXBvbmVudFxuICogQHBhcmFtIHtOdW1iZXJ9IHkgWSBjb21wb25lbnRcbiAqIEBwYXJhbSB7TnVtYmVyfSB6IFogY29tcG9uZW50XG4gKiBAcGFyYW0ge051bWJlcn0gdyBXIGNvbXBvbmVudFxuICogQHJldHVybnMge3ZlYzR9IGEgbmV3IDREIHZlY3RvclxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBmcm9tVmFsdWVzKHgsIHksIHosIHcpIHtcbiAgdmFyIG91dCA9IG5ldyBnbE1hdHJpeC5BUlJBWV9UWVBFKDQpO1xuICBvdXRbMF0gPSB4O1xuICBvdXRbMV0gPSB5O1xuICBvdXRbMl0gPSB6O1xuICBvdXRbM10gPSB3O1xuICByZXR1cm4gb3V0O1xufVxuLyoqXG4gKiBDb3B5IHRoZSB2YWx1ZXMgZnJvbSBvbmUgdmVjNCB0byBhbm90aGVyXG4gKlxuICogQHBhcmFtIHt2ZWM0fSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7UmVhZG9ubHlWZWM0fSBhIHRoZSBzb3VyY2UgdmVjdG9yXG4gKiBAcmV0dXJucyB7dmVjNH0gb3V0XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGNvcHkob3V0LCBhKSB7XG4gIG91dFswXSA9IGFbMF07XG4gIG91dFsxXSA9IGFbMV07XG4gIG91dFsyXSA9IGFbMl07XG4gIG91dFszXSA9IGFbM107XG4gIHJldHVybiBvdXQ7XG59XG4vKipcbiAqIFNldCB0aGUgY29tcG9uZW50cyBvZiBhIHZlYzQgdG8gdGhlIGdpdmVuIHZhbHVlc1xuICpcbiAqIEBwYXJhbSB7dmVjNH0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge051bWJlcn0geCBYIGNvbXBvbmVudFxuICogQHBhcmFtIHtOdW1iZXJ9IHkgWSBjb21wb25lbnRcbiAqIEBwYXJhbSB7TnVtYmVyfSB6IFogY29tcG9uZW50XG4gKiBAcGFyYW0ge051bWJlcn0gdyBXIGNvbXBvbmVudFxuICogQHJldHVybnMge3ZlYzR9IG91dFxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBzZXQob3V0LCB4LCB5LCB6LCB3KSB7XG4gIG91dFswXSA9IHg7XG4gIG91dFsxXSA9IHk7XG4gIG91dFsyXSA9IHo7XG4gIG91dFszXSA9IHc7XG4gIHJldHVybiBvdXQ7XG59XG4vKipcbiAqIEFkZHMgdHdvIHZlYzQnc1xuICpcbiAqIEBwYXJhbSB7dmVjNH0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge1JlYWRvbmx5VmVjNH0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHtSZWFkb25seVZlYzR9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7dmVjNH0gb3V0XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGFkZChvdXQsIGEsIGIpIHtcbiAgb3V0WzBdID0gYVswXSArIGJbMF07XG4gIG91dFsxXSA9IGFbMV0gKyBiWzFdO1xuICBvdXRbMl0gPSBhWzJdICsgYlsyXTtcbiAgb3V0WzNdID0gYVszXSArIGJbM107XG4gIHJldHVybiBvdXQ7XG59XG4vKipcbiAqIFN1YnRyYWN0cyB2ZWN0b3IgYiBmcm9tIHZlY3RvciBhXG4gKlxuICogQHBhcmFtIHt2ZWM0fSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7UmVhZG9ubHlWZWM0fSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge1JlYWRvbmx5VmVjNH0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gc3VidHJhY3Qob3V0LCBhLCBiKSB7XG4gIG91dFswXSA9IGFbMF0gLSBiWzBdO1xuICBvdXRbMV0gPSBhWzFdIC0gYlsxXTtcbiAgb3V0WzJdID0gYVsyXSAtIGJbMl07XG4gIG91dFszXSA9IGFbM10gLSBiWzNdO1xuICByZXR1cm4gb3V0O1xufVxuLyoqXG4gKiBNdWx0aXBsaWVzIHR3byB2ZWM0J3NcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHtSZWFkb25seVZlYzR9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7UmVhZG9ubHlWZWM0fSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge3ZlYzR9IG91dFxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBtdWx0aXBseShvdXQsIGEsIGIpIHtcbiAgb3V0WzBdID0gYVswXSAqIGJbMF07XG4gIG91dFsxXSA9IGFbMV0gKiBiWzFdO1xuICBvdXRbMl0gPSBhWzJdICogYlsyXTtcbiAgb3V0WzNdID0gYVszXSAqIGJbM107XG4gIHJldHVybiBvdXQ7XG59XG4vKipcbiAqIERpdmlkZXMgdHdvIHZlYzQnc1xuICpcbiAqIEBwYXJhbSB7dmVjNH0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge1JlYWRvbmx5VmVjNH0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHtSZWFkb25seVZlYzR9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7dmVjNH0gb3V0XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGRpdmlkZShvdXQsIGEsIGIpIHtcbiAgb3V0WzBdID0gYVswXSAvIGJbMF07XG4gIG91dFsxXSA9IGFbMV0gLyBiWzFdO1xuICBvdXRbMl0gPSBhWzJdIC8gYlsyXTtcbiAgb3V0WzNdID0gYVszXSAvIGJbM107XG4gIHJldHVybiBvdXQ7XG59XG4vKipcbiAqIE1hdGguY2VpbCB0aGUgY29tcG9uZW50cyBvZiBhIHZlYzRcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHtSZWFkb25seVZlYzR9IGEgdmVjdG9yIHRvIGNlaWxcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gY2VpbChvdXQsIGEpIHtcbiAgb3V0WzBdID0gTWF0aC5jZWlsKGFbMF0pO1xuICBvdXRbMV0gPSBNYXRoLmNlaWwoYVsxXSk7XG4gIG91dFsyXSA9IE1hdGguY2VpbChhWzJdKTtcbiAgb3V0WzNdID0gTWF0aC5jZWlsKGFbM10pO1xuICByZXR1cm4gb3V0O1xufVxuLyoqXG4gKiBNYXRoLmZsb29yIHRoZSBjb21wb25lbnRzIG9mIGEgdmVjNFxuICpcbiAqIEBwYXJhbSB7dmVjNH0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge1JlYWRvbmx5VmVjNH0gYSB2ZWN0b3IgdG8gZmxvb3JcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gZmxvb3Iob3V0LCBhKSB7XG4gIG91dFswXSA9IE1hdGguZmxvb3IoYVswXSk7XG4gIG91dFsxXSA9IE1hdGguZmxvb3IoYVsxXSk7XG4gIG91dFsyXSA9IE1hdGguZmxvb3IoYVsyXSk7XG4gIG91dFszXSA9IE1hdGguZmxvb3IoYVszXSk7XG4gIHJldHVybiBvdXQ7XG59XG4vKipcbiAqIFJldHVybnMgdGhlIG1pbmltdW0gb2YgdHdvIHZlYzQnc1xuICpcbiAqIEBwYXJhbSB7dmVjNH0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge1JlYWRvbmx5VmVjNH0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHtSZWFkb25seVZlYzR9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7dmVjNH0gb3V0XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIG1pbihvdXQsIGEsIGIpIHtcbiAgb3V0WzBdID0gTWF0aC5taW4oYVswXSwgYlswXSk7XG4gIG91dFsxXSA9IE1hdGgubWluKGFbMV0sIGJbMV0pO1xuICBvdXRbMl0gPSBNYXRoLm1pbihhWzJdLCBiWzJdKTtcbiAgb3V0WzNdID0gTWF0aC5taW4oYVszXSwgYlszXSk7XG4gIHJldHVybiBvdXQ7XG59XG4vKipcbiAqIFJldHVybnMgdGhlIG1heGltdW0gb2YgdHdvIHZlYzQnc1xuICpcbiAqIEBwYXJhbSB7dmVjNH0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge1JlYWRvbmx5VmVjNH0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHtSZWFkb25seVZlYzR9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7dmVjNH0gb3V0XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIG1heChvdXQsIGEsIGIpIHtcbiAgb3V0WzBdID0gTWF0aC5tYXgoYVswXSwgYlswXSk7XG4gIG91dFsxXSA9IE1hdGgubWF4KGFbMV0sIGJbMV0pO1xuICBvdXRbMl0gPSBNYXRoLm1heChhWzJdLCBiWzJdKTtcbiAgb3V0WzNdID0gTWF0aC5tYXgoYVszXSwgYlszXSk7XG4gIHJldHVybiBvdXQ7XG59XG4vKipcbiAqIE1hdGgucm91bmQgdGhlIGNvbXBvbmVudHMgb2YgYSB2ZWM0XG4gKlxuICogQHBhcmFtIHt2ZWM0fSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7UmVhZG9ubHlWZWM0fSBhIHZlY3RvciB0byByb3VuZFxuICogQHJldHVybnMge3ZlYzR9IG91dFxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiByb3VuZChvdXQsIGEpIHtcbiAgb3V0WzBdID0gTWF0aC5yb3VuZChhWzBdKTtcbiAgb3V0WzFdID0gTWF0aC5yb3VuZChhWzFdKTtcbiAgb3V0WzJdID0gTWF0aC5yb3VuZChhWzJdKTtcbiAgb3V0WzNdID0gTWF0aC5yb3VuZChhWzNdKTtcbiAgcmV0dXJuIG91dDtcbn1cbi8qKlxuICogU2NhbGVzIGEgdmVjNCBieSBhIHNjYWxhciBudW1iZXJcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHtSZWFkb25seVZlYzR9IGEgdGhlIHZlY3RvciB0byBzY2FsZVxuICogQHBhcmFtIHtOdW1iZXJ9IGIgYW1vdW50IHRvIHNjYWxlIHRoZSB2ZWN0b3IgYnlcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gc2NhbGUob3V0LCBhLCBiKSB7XG4gIG91dFswXSA9IGFbMF0gKiBiO1xuICBvdXRbMV0gPSBhWzFdICogYjtcbiAgb3V0WzJdID0gYVsyXSAqIGI7XG4gIG91dFszXSA9IGFbM10gKiBiO1xuICByZXR1cm4gb3V0O1xufVxuLyoqXG4gKiBBZGRzIHR3byB2ZWM0J3MgYWZ0ZXIgc2NhbGluZyB0aGUgc2Vjb25kIG9wZXJhbmQgYnkgYSBzY2FsYXIgdmFsdWVcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHtSZWFkb25seVZlYzR9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7UmVhZG9ubHlWZWM0fSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHBhcmFtIHtOdW1iZXJ9IHNjYWxlIHRoZSBhbW91bnQgdG8gc2NhbGUgYiBieSBiZWZvcmUgYWRkaW5nXG4gKiBAcmV0dXJucyB7dmVjNH0gb3V0XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIHNjYWxlQW5kQWRkKG91dCwgYSwgYiwgc2NhbGUpIHtcbiAgb3V0WzBdID0gYVswXSArIGJbMF0gKiBzY2FsZTtcbiAgb3V0WzFdID0gYVsxXSArIGJbMV0gKiBzY2FsZTtcbiAgb3V0WzJdID0gYVsyXSArIGJbMl0gKiBzY2FsZTtcbiAgb3V0WzNdID0gYVszXSArIGJbM10gKiBzY2FsZTtcbiAgcmV0dXJuIG91dDtcbn1cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgZXVjbGlkaWFuIGRpc3RhbmNlIGJldHdlZW4gdHdvIHZlYzQnc1xuICpcbiAqIEBwYXJhbSB7UmVhZG9ubHlWZWM0fSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge1JlYWRvbmx5VmVjNH0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHtOdW1iZXJ9IGRpc3RhbmNlIGJldHdlZW4gYSBhbmQgYlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBkaXN0YW5jZShhLCBiKSB7XG4gIHZhciB4ID0gYlswXSAtIGFbMF07XG4gIHZhciB5ID0gYlsxXSAtIGFbMV07XG4gIHZhciB6ID0gYlsyXSAtIGFbMl07XG4gIHZhciB3ID0gYlszXSAtIGFbM107XG4gIHJldHVybiBNYXRoLmh5cG90KHgsIHksIHosIHcpO1xufVxuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSBzcXVhcmVkIGV1Y2xpZGlhbiBkaXN0YW5jZSBiZXR3ZWVuIHR3byB2ZWM0J3NcbiAqXG4gKiBAcGFyYW0ge1JlYWRvbmx5VmVjNH0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHtSZWFkb25seVZlYzR9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7TnVtYmVyfSBzcXVhcmVkIGRpc3RhbmNlIGJldHdlZW4gYSBhbmQgYlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBzcXVhcmVkRGlzdGFuY2UoYSwgYikge1xuICB2YXIgeCA9IGJbMF0gLSBhWzBdO1xuICB2YXIgeSA9IGJbMV0gLSBhWzFdO1xuICB2YXIgeiA9IGJbMl0gLSBhWzJdO1xuICB2YXIgdyA9IGJbM10gLSBhWzNdO1xuICByZXR1cm4geCAqIHggKyB5ICogeSArIHogKiB6ICsgdyAqIHc7XG59XG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIGxlbmd0aCBvZiBhIHZlYzRcbiAqXG4gKiBAcGFyYW0ge1JlYWRvbmx5VmVjNH0gYSB2ZWN0b3IgdG8gY2FsY3VsYXRlIGxlbmd0aCBvZlxuICogQHJldHVybnMge051bWJlcn0gbGVuZ3RoIG9mIGFcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gbGVuZ3RoKGEpIHtcbiAgdmFyIHggPSBhWzBdO1xuICB2YXIgeSA9IGFbMV07XG4gIHZhciB6ID0gYVsyXTtcbiAgdmFyIHcgPSBhWzNdO1xuICByZXR1cm4gTWF0aC5oeXBvdCh4LCB5LCB6LCB3KTtcbn1cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgc3F1YXJlZCBsZW5ndGggb2YgYSB2ZWM0XG4gKlxuICogQHBhcmFtIHtSZWFkb25seVZlYzR9IGEgdmVjdG9yIHRvIGNhbGN1bGF0ZSBzcXVhcmVkIGxlbmd0aCBvZlxuICogQHJldHVybnMge051bWJlcn0gc3F1YXJlZCBsZW5ndGggb2YgYVxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBzcXVhcmVkTGVuZ3RoKGEpIHtcbiAgdmFyIHggPSBhWzBdO1xuICB2YXIgeSA9IGFbMV07XG4gIHZhciB6ID0gYVsyXTtcbiAgdmFyIHcgPSBhWzNdO1xuICByZXR1cm4geCAqIHggKyB5ICogeSArIHogKiB6ICsgdyAqIHc7XG59XG4vKipcbiAqIE5lZ2F0ZXMgdGhlIGNvbXBvbmVudHMgb2YgYSB2ZWM0XG4gKlxuICogQHBhcmFtIHt2ZWM0fSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7UmVhZG9ubHlWZWM0fSBhIHZlY3RvciB0byBuZWdhdGVcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gbmVnYXRlKG91dCwgYSkge1xuICBvdXRbMF0gPSAtYVswXTtcbiAgb3V0WzFdID0gLWFbMV07XG4gIG91dFsyXSA9IC1hWzJdO1xuICBvdXRbM10gPSAtYVszXTtcbiAgcmV0dXJuIG91dDtcbn1cbi8qKlxuICogUmV0dXJucyB0aGUgaW52ZXJzZSBvZiB0aGUgY29tcG9uZW50cyBvZiBhIHZlYzRcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHtSZWFkb25seVZlYzR9IGEgdmVjdG9yIHRvIGludmVydFxuICogQHJldHVybnMge3ZlYzR9IG91dFxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBpbnZlcnNlKG91dCwgYSkge1xuICBvdXRbMF0gPSAxLjAgLyBhWzBdO1xuICBvdXRbMV0gPSAxLjAgLyBhWzFdO1xuICBvdXRbMl0gPSAxLjAgLyBhWzJdO1xuICBvdXRbM10gPSAxLjAgLyBhWzNdO1xuICByZXR1cm4gb3V0O1xufVxuLyoqXG4gKiBOb3JtYWxpemUgYSB2ZWM0XG4gKlxuICogQHBhcmFtIHt2ZWM0fSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7UmVhZG9ubHlWZWM0fSBhIHZlY3RvciB0byBub3JtYWxpemVcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gbm9ybWFsaXplKG91dCwgYSkge1xuICB2YXIgeCA9IGFbMF07XG4gIHZhciB5ID0gYVsxXTtcbiAgdmFyIHogPSBhWzJdO1xuICB2YXIgdyA9IGFbM107XG4gIHZhciBsZW4gPSB4ICogeCArIHkgKiB5ICsgeiAqIHogKyB3ICogdztcblxuICBpZiAobGVuID4gMCkge1xuICAgIGxlbiA9IDEgLyBNYXRoLnNxcnQobGVuKTtcbiAgfVxuXG4gIG91dFswXSA9IHggKiBsZW47XG4gIG91dFsxXSA9IHkgKiBsZW47XG4gIG91dFsyXSA9IHogKiBsZW47XG4gIG91dFszXSA9IHcgKiBsZW47XG4gIHJldHVybiBvdXQ7XG59XG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIGRvdCBwcm9kdWN0IG9mIHR3byB2ZWM0J3NcbiAqXG4gKiBAcGFyYW0ge1JlYWRvbmx5VmVjNH0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHtSZWFkb25seVZlYzR9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7TnVtYmVyfSBkb3QgcHJvZHVjdCBvZiBhIGFuZCBiXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGRvdChhLCBiKSB7XG4gIHJldHVybiBhWzBdICogYlswXSArIGFbMV0gKiBiWzFdICsgYVsyXSAqIGJbMl0gKyBhWzNdICogYlszXTtcbn1cbi8qKlxuICogUmV0dXJucyB0aGUgY3Jvc3MtcHJvZHVjdCBvZiB0aHJlZSB2ZWN0b3JzIGluIGEgNC1kaW1lbnNpb25hbCBzcGFjZVxuICpcbiAqIEBwYXJhbSB7UmVhZG9ubHlWZWM0fSByZXN1bHQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7UmVhZG9ubHlWZWM0fSBVIHRoZSBmaXJzdCB2ZWN0b3JcbiAqIEBwYXJhbSB7UmVhZG9ubHlWZWM0fSBWIHRoZSBzZWNvbmQgdmVjdG9yXG4gKiBAcGFyYW0ge1JlYWRvbmx5VmVjNH0gVyB0aGUgdGhpcmQgdmVjdG9yXG4gKiBAcmV0dXJucyB7dmVjNH0gcmVzdWx0XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGNyb3NzKG91dCwgdSwgdiwgdykge1xuICB2YXIgQSA9IHZbMF0gKiB3WzFdIC0gdlsxXSAqIHdbMF0sXG4gICAgICBCID0gdlswXSAqIHdbMl0gLSB2WzJdICogd1swXSxcbiAgICAgIEMgPSB2WzBdICogd1szXSAtIHZbM10gKiB3WzBdLFxuICAgICAgRCA9IHZbMV0gKiB3WzJdIC0gdlsyXSAqIHdbMV0sXG4gICAgICBFID0gdlsxXSAqIHdbM10gLSB2WzNdICogd1sxXSxcbiAgICAgIEYgPSB2WzJdICogd1szXSAtIHZbM10gKiB3WzJdO1xuICB2YXIgRyA9IHVbMF07XG4gIHZhciBIID0gdVsxXTtcbiAgdmFyIEkgPSB1WzJdO1xuICB2YXIgSiA9IHVbM107XG4gIG91dFswXSA9IEggKiBGIC0gSSAqIEUgKyBKICogRDtcbiAgb3V0WzFdID0gLShHICogRikgKyBJICogQyAtIEogKiBCO1xuICBvdXRbMl0gPSBHICogRSAtIEggKiBDICsgSiAqIEE7XG4gIG91dFszXSA9IC0oRyAqIEQpICsgSCAqIEIgLSBJICogQTtcbiAgcmV0dXJuIG91dDtcbn1cbi8qKlxuICogUGVyZm9ybXMgYSBsaW5lYXIgaW50ZXJwb2xhdGlvbiBiZXR3ZWVuIHR3byB2ZWM0J3NcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHtSZWFkb25seVZlYzR9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7UmVhZG9ubHlWZWM0fSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHBhcmFtIHtOdW1iZXJ9IHQgaW50ZXJwb2xhdGlvbiBhbW91bnQsIGluIHRoZSByYW5nZSBbMC0xXSwgYmV0d2VlbiB0aGUgdHdvIGlucHV0c1xuICogQHJldHVybnMge3ZlYzR9IG91dFxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBsZXJwKG91dCwgYSwgYiwgdCkge1xuICB2YXIgYXggPSBhWzBdO1xuICB2YXIgYXkgPSBhWzFdO1xuICB2YXIgYXogPSBhWzJdO1xuICB2YXIgYXcgPSBhWzNdO1xuICBvdXRbMF0gPSBheCArIHQgKiAoYlswXSAtIGF4KTtcbiAgb3V0WzFdID0gYXkgKyB0ICogKGJbMV0gLSBheSk7XG4gIG91dFsyXSA9IGF6ICsgdCAqIChiWzJdIC0gYXopO1xuICBvdXRbM10gPSBhdyArIHQgKiAoYlszXSAtIGF3KTtcbiAgcmV0dXJuIG91dDtcbn1cbi8qKlxuICogR2VuZXJhdGVzIGEgcmFuZG9tIHZlY3RvciB3aXRoIHRoZSBnaXZlbiBzY2FsZVxuICpcbiAqIEBwYXJhbSB7dmVjNH0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge051bWJlcn0gW3NjYWxlXSBMZW5ndGggb2YgdGhlIHJlc3VsdGluZyB2ZWN0b3IuIElmIG9tbWl0dGVkLCBhIHVuaXQgdmVjdG9yIHdpbGwgYmUgcmV0dXJuZWRcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gcmFuZG9tKG91dCwgc2NhbGUpIHtcbiAgc2NhbGUgPSBzY2FsZSB8fCAxLjA7IC8vIE1hcnNhZ2xpYSwgR2VvcmdlLiBDaG9vc2luZyBhIFBvaW50IGZyb20gdGhlIFN1cmZhY2Ugb2YgYVxuICAvLyBTcGhlcmUuIEFubi4gTWF0aC4gU3RhdGlzdC4gNDMgKDE5NzIpLCBuby4gMiwgNjQ1LS02NDYuXG4gIC8vIGh0dHA6Ly9wcm9qZWN0ZXVjbGlkLm9yZy9ldWNsaWQuYW9tcy8xMTc3NjkyNjQ0O1xuXG4gIHZhciB2MSwgdjIsIHYzLCB2NDtcbiAgdmFyIHMxLCBzMjtcblxuICBkbyB7XG4gICAgdjEgPSBnbE1hdHJpeC5SQU5ET00oKSAqIDIgLSAxO1xuICAgIHYyID0gZ2xNYXRyaXguUkFORE9NKCkgKiAyIC0gMTtcbiAgICBzMSA9IHYxICogdjEgKyB2MiAqIHYyO1xuICB9IHdoaWxlIChzMSA+PSAxKTtcblxuICBkbyB7XG4gICAgdjMgPSBnbE1hdHJpeC5SQU5ET00oKSAqIDIgLSAxO1xuICAgIHY0ID0gZ2xNYXRyaXguUkFORE9NKCkgKiAyIC0gMTtcbiAgICBzMiA9IHYzICogdjMgKyB2NCAqIHY0O1xuICB9IHdoaWxlIChzMiA+PSAxKTtcblxuICB2YXIgZCA9IE1hdGguc3FydCgoMSAtIHMxKSAvIHMyKTtcbiAgb3V0WzBdID0gc2NhbGUgKiB2MTtcbiAgb3V0WzFdID0gc2NhbGUgKiB2MjtcbiAgb3V0WzJdID0gc2NhbGUgKiB2MyAqIGQ7XG4gIG91dFszXSA9IHNjYWxlICogdjQgKiBkO1xuICByZXR1cm4gb3V0O1xufVxuLyoqXG4gKiBUcmFuc2Zvcm1zIHRoZSB2ZWM0IHdpdGggYSBtYXQ0LlxuICpcbiAqIEBwYXJhbSB7dmVjNH0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge1JlYWRvbmx5VmVjNH0gYSB0aGUgdmVjdG9yIHRvIHRyYW5zZm9ybVxuICogQHBhcmFtIHtSZWFkb25seU1hdDR9IG0gbWF0cml4IHRvIHRyYW5zZm9ybSB3aXRoXG4gKiBAcmV0dXJucyB7dmVjNH0gb3V0XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIHRyYW5zZm9ybU1hdDQob3V0LCBhLCBtKSB7XG4gIHZhciB4ID0gYVswXSxcbiAgICAgIHkgPSBhWzFdLFxuICAgICAgeiA9IGFbMl0sXG4gICAgICB3ID0gYVszXTtcbiAgb3V0WzBdID0gbVswXSAqIHggKyBtWzRdICogeSArIG1bOF0gKiB6ICsgbVsxMl0gKiB3O1xuICBvdXRbMV0gPSBtWzFdICogeCArIG1bNV0gKiB5ICsgbVs5XSAqIHogKyBtWzEzXSAqIHc7XG4gIG91dFsyXSA9IG1bMl0gKiB4ICsgbVs2XSAqIHkgKyBtWzEwXSAqIHogKyBtWzE0XSAqIHc7XG4gIG91dFszXSA9IG1bM10gKiB4ICsgbVs3XSAqIHkgKyBtWzExXSAqIHogKyBtWzE1XSAqIHc7XG4gIHJldHVybiBvdXQ7XG59XG4vKipcbiAqIFRyYW5zZm9ybXMgdGhlIHZlYzQgd2l0aCBhIHF1YXRcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHtSZWFkb25seVZlYzR9IGEgdGhlIHZlY3RvciB0byB0cmFuc2Zvcm1cbiAqIEBwYXJhbSB7UmVhZG9ubHlRdWF0fSBxIHF1YXRlcm5pb24gdG8gdHJhbnNmb3JtIHdpdGhcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gdHJhbnNmb3JtUXVhdChvdXQsIGEsIHEpIHtcbiAgdmFyIHggPSBhWzBdLFxuICAgICAgeSA9IGFbMV0sXG4gICAgICB6ID0gYVsyXTtcbiAgdmFyIHF4ID0gcVswXSxcbiAgICAgIHF5ID0gcVsxXSxcbiAgICAgIHF6ID0gcVsyXSxcbiAgICAgIHF3ID0gcVszXTsgLy8gY2FsY3VsYXRlIHF1YXQgKiB2ZWNcblxuICB2YXIgaXggPSBxdyAqIHggKyBxeSAqIHogLSBxeiAqIHk7XG4gIHZhciBpeSA9IHF3ICogeSArIHF6ICogeCAtIHF4ICogejtcbiAgdmFyIGl6ID0gcXcgKiB6ICsgcXggKiB5IC0gcXkgKiB4O1xuICB2YXIgaXcgPSAtcXggKiB4IC0gcXkgKiB5IC0gcXogKiB6OyAvLyBjYWxjdWxhdGUgcmVzdWx0ICogaW52ZXJzZSBxdWF0XG5cbiAgb3V0WzBdID0gaXggKiBxdyArIGl3ICogLXF4ICsgaXkgKiAtcXogLSBpeiAqIC1xeTtcbiAgb3V0WzFdID0gaXkgKiBxdyArIGl3ICogLXF5ICsgaXogKiAtcXggLSBpeCAqIC1xejtcbiAgb3V0WzJdID0gaXogKiBxdyArIGl3ICogLXF6ICsgaXggKiAtcXkgLSBpeSAqIC1xeDtcbiAgb3V0WzNdID0gYVszXTtcbiAgcmV0dXJuIG91dDtcbn1cbi8qKlxuICogU2V0IHRoZSBjb21wb25lbnRzIG9mIGEgdmVjNCB0byB6ZXJvXG4gKlxuICogQHBhcmFtIHt2ZWM0fSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gemVybyhvdXQpIHtcbiAgb3V0WzBdID0gMC4wO1xuICBvdXRbMV0gPSAwLjA7XG4gIG91dFsyXSA9IDAuMDtcbiAgb3V0WzNdID0gMC4wO1xuICByZXR1cm4gb3V0O1xufVxuLyoqXG4gKiBSZXR1cm5zIGEgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIGEgdmVjdG9yXG4gKlxuICogQHBhcmFtIHtSZWFkb25seVZlYzR9IGEgdmVjdG9yIHRvIHJlcHJlc2VudCBhcyBhIHN0cmluZ1xuICogQHJldHVybnMge1N0cmluZ30gc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIHRoZSB2ZWN0b3JcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gc3RyKGEpIHtcbiAgcmV0dXJuIFwidmVjNChcIiArIGFbMF0gKyBcIiwgXCIgKyBhWzFdICsgXCIsIFwiICsgYVsyXSArIFwiLCBcIiArIGFbM10gKyBcIilcIjtcbn1cbi8qKlxuICogUmV0dXJucyB3aGV0aGVyIG9yIG5vdCB0aGUgdmVjdG9ycyBoYXZlIGV4YWN0bHkgdGhlIHNhbWUgZWxlbWVudHMgaW4gdGhlIHNhbWUgcG9zaXRpb24gKHdoZW4gY29tcGFyZWQgd2l0aCA9PT0pXG4gKlxuICogQHBhcmFtIHtSZWFkb25seVZlYzR9IGEgVGhlIGZpcnN0IHZlY3Rvci5cbiAqIEBwYXJhbSB7UmVhZG9ubHlWZWM0fSBiIFRoZSBzZWNvbmQgdmVjdG9yLlxuICogQHJldHVybnMge0Jvb2xlYW59IFRydWUgaWYgdGhlIHZlY3RvcnMgYXJlIGVxdWFsLCBmYWxzZSBvdGhlcndpc2UuXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGV4YWN0RXF1YWxzKGEsIGIpIHtcbiAgcmV0dXJuIGFbMF0gPT09IGJbMF0gJiYgYVsxXSA9PT0gYlsxXSAmJiBhWzJdID09PSBiWzJdICYmIGFbM10gPT09IGJbM107XG59XG4vKipcbiAqIFJldHVybnMgd2hldGhlciBvciBub3QgdGhlIHZlY3RvcnMgaGF2ZSBhcHByb3hpbWF0ZWx5IHRoZSBzYW1lIGVsZW1lbnRzIGluIHRoZSBzYW1lIHBvc2l0aW9uLlxuICpcbiAqIEBwYXJhbSB7UmVhZG9ubHlWZWM0fSBhIFRoZSBmaXJzdCB2ZWN0b3IuXG4gKiBAcGFyYW0ge1JlYWRvbmx5VmVjNH0gYiBUaGUgc2Vjb25kIHZlY3Rvci5cbiAqIEByZXR1cm5zIHtCb29sZWFufSBUcnVlIGlmIHRoZSB2ZWN0b3JzIGFyZSBlcXVhbCwgZmFsc2Ugb3RoZXJ3aXNlLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBlcXVhbHMoYSwgYikge1xuICB2YXIgYTAgPSBhWzBdLFxuICAgICAgYTEgPSBhWzFdLFxuICAgICAgYTIgPSBhWzJdLFxuICAgICAgYTMgPSBhWzNdO1xuICB2YXIgYjAgPSBiWzBdLFxuICAgICAgYjEgPSBiWzFdLFxuICAgICAgYjIgPSBiWzJdLFxuICAgICAgYjMgPSBiWzNdO1xuICByZXR1cm4gTWF0aC5hYnMoYTAgLSBiMCkgPD0gZ2xNYXRyaXguRVBTSUxPTiAqIE1hdGgubWF4KDEuMCwgTWF0aC5hYnMoYTApLCBNYXRoLmFicyhiMCkpICYmIE1hdGguYWJzKGExIC0gYjEpIDw9IGdsTWF0cml4LkVQU0lMT04gKiBNYXRoLm1heCgxLjAsIE1hdGguYWJzKGExKSwgTWF0aC5hYnMoYjEpKSAmJiBNYXRoLmFicyhhMiAtIGIyKSA8PSBnbE1hdHJpeC5FUFNJTE9OICogTWF0aC5tYXgoMS4wLCBNYXRoLmFicyhhMiksIE1hdGguYWJzKGIyKSkgJiYgTWF0aC5hYnMoYTMgLSBiMykgPD0gZ2xNYXRyaXguRVBTSUxPTiAqIE1hdGgubWF4KDEuMCwgTWF0aC5hYnMoYTMpLCBNYXRoLmFicyhiMykpO1xufVxuLyoqXG4gKiBBbGlhcyBmb3Ige0BsaW5rIHZlYzQuc3VidHJhY3R9XG4gKiBAZnVuY3Rpb25cbiAqL1xuXG5leHBvcnQgdmFyIHN1YiA9IHN1YnRyYWN0O1xuLyoqXG4gKiBBbGlhcyBmb3Ige0BsaW5rIHZlYzQubXVsdGlwbHl9XG4gKiBAZnVuY3Rpb25cbiAqL1xuXG5leHBvcnQgdmFyIG11bCA9IG11bHRpcGx5O1xuLyoqXG4gKiBBbGlhcyBmb3Ige0BsaW5rIHZlYzQuZGl2aWRlfVxuICogQGZ1bmN0aW9uXG4gKi9cblxuZXhwb3J0IHZhciBkaXYgPSBkaXZpZGU7XG4vKipcbiAqIEFsaWFzIGZvciB7QGxpbmsgdmVjNC5kaXN0YW5jZX1cbiAqIEBmdW5jdGlvblxuICovXG5cbmV4cG9ydCB2YXIgZGlzdCA9IGRpc3RhbmNlO1xuLyoqXG4gKiBBbGlhcyBmb3Ige0BsaW5rIHZlYzQuc3F1YXJlZERpc3RhbmNlfVxuICogQGZ1bmN0aW9uXG4gKi9cblxuZXhwb3J0IHZhciBzcXJEaXN0ID0gc3F1YXJlZERpc3RhbmNlO1xuLyoqXG4gKiBBbGlhcyBmb3Ige0BsaW5rIHZlYzQubGVuZ3RofVxuICogQGZ1bmN0aW9uXG4gKi9cblxuZXhwb3J0IHZhciBsZW4gPSBsZW5ndGg7XG4vKipcbiAqIEFsaWFzIGZvciB7QGxpbmsgdmVjNC5zcXVhcmVkTGVuZ3RofVxuICogQGZ1bmN0aW9uXG4gKi9cblxuZXhwb3J0IHZhciBzcXJMZW4gPSBzcXVhcmVkTGVuZ3RoO1xuLyoqXG4gKiBQZXJmb3JtIHNvbWUgb3BlcmF0aW9uIG92ZXIgYW4gYXJyYXkgb2YgdmVjNHMuXG4gKlxuICogQHBhcmFtIHtBcnJheX0gYSB0aGUgYXJyYXkgb2YgdmVjdG9ycyB0byBpdGVyYXRlIG92ZXJcbiAqIEBwYXJhbSB7TnVtYmVyfSBzdHJpZGUgTnVtYmVyIG9mIGVsZW1lbnRzIGJldHdlZW4gdGhlIHN0YXJ0IG9mIGVhY2ggdmVjNC4gSWYgMCBhc3N1bWVzIHRpZ2h0bHkgcGFja2VkXG4gKiBAcGFyYW0ge051bWJlcn0gb2Zmc2V0IE51bWJlciBvZiBlbGVtZW50cyB0byBza2lwIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIGFycmF5XG4gKiBAcGFyYW0ge051bWJlcn0gY291bnQgTnVtYmVyIG9mIHZlYzRzIHRvIGl0ZXJhdGUgb3Zlci4gSWYgMCBpdGVyYXRlcyBvdmVyIGVudGlyZSBhcnJheVxuICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gRnVuY3Rpb24gdG8gY2FsbCBmb3IgZWFjaCB2ZWN0b3IgaW4gdGhlIGFycmF5XG4gKiBAcGFyYW0ge09iamVjdH0gW2FyZ10gYWRkaXRpb25hbCBhcmd1bWVudCB0byBwYXNzIHRvIGZuXG4gKiBAcmV0dXJucyB7QXJyYXl9IGFcbiAqIEBmdW5jdGlvblxuICovXG5cbmV4cG9ydCB2YXIgZm9yRWFjaCA9IGZ1bmN0aW9uICgpIHtcbiAgdmFyIHZlYyA9IGNyZWF0ZSgpO1xuICByZXR1cm4gZnVuY3Rpb24gKGEsIHN0cmlkZSwgb2Zmc2V0LCBjb3VudCwgZm4sIGFyZykge1xuICAgIHZhciBpLCBsO1xuXG4gICAgaWYgKCFzdHJpZGUpIHtcbiAgICAgIHN0cmlkZSA9IDQ7XG4gICAgfVxuXG4gICAgaWYgKCFvZmZzZXQpIHtcbiAgICAgIG9mZnNldCA9IDA7XG4gICAgfVxuXG4gICAgaWYgKGNvdW50KSB7XG4gICAgICBsID0gTWF0aC5taW4oY291bnQgKiBzdHJpZGUgKyBvZmZzZXQsIGEubGVuZ3RoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbCA9IGEubGVuZ3RoO1xuICAgIH1cblxuICAgIGZvciAoaSA9IG9mZnNldDsgaSA8IGw7IGkgKz0gc3RyaWRlKSB7XG4gICAgICB2ZWNbMF0gPSBhW2ldO1xuICAgICAgdmVjWzFdID0gYVtpICsgMV07XG4gICAgICB2ZWNbMl0gPSBhW2kgKyAyXTtcbiAgICAgIHZlY1szXSA9IGFbaSArIDNdO1xuICAgICAgZm4odmVjLCB2ZWMsIGFyZyk7XG4gICAgICBhW2ldID0gdmVjWzBdO1xuICAgICAgYVtpICsgMV0gPSB2ZWNbMV07XG4gICAgICBhW2kgKyAyXSA9IHZlY1syXTtcbiAgICAgIGFbaSArIDNdID0gdmVjWzNdO1xuICAgIH1cblxuICAgIHJldHVybiBhO1xuICB9O1xufSgpOyIsImltcG9ydCAqIGFzIGdsTWF0cml4IGZyb20gXCIuL2NvbW1vbi5qc1wiO1xuLyoqXG4gKiAzeDMgTWF0cml4XG4gKiBAbW9kdWxlIG1hdDNcbiAqL1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgaWRlbnRpdHkgbWF0M1xuICpcbiAqIEByZXR1cm5zIHttYXQzfSBhIG5ldyAzeDMgbWF0cml4XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZSgpIHtcbiAgdmFyIG91dCA9IG5ldyBnbE1hdHJpeC5BUlJBWV9UWVBFKDkpO1xuXG4gIGlmIChnbE1hdHJpeC5BUlJBWV9UWVBFICE9IEZsb2F0MzJBcnJheSkge1xuICAgIG91dFsxXSA9IDA7XG4gICAgb3V0WzJdID0gMDtcbiAgICBvdXRbM10gPSAwO1xuICAgIG91dFs1XSA9IDA7XG4gICAgb3V0WzZdID0gMDtcbiAgICBvdXRbN10gPSAwO1xuICB9XG5cbiAgb3V0WzBdID0gMTtcbiAgb3V0WzRdID0gMTtcbiAgb3V0WzhdID0gMTtcbiAgcmV0dXJuIG91dDtcbn1cbi8qKlxuICogQ29waWVzIHRoZSB1cHBlci1sZWZ0IDN4MyB2YWx1ZXMgaW50byB0aGUgZ2l2ZW4gbWF0My5cbiAqXG4gKiBAcGFyYW0ge21hdDN9IG91dCB0aGUgcmVjZWl2aW5nIDN4MyBtYXRyaXhcbiAqIEBwYXJhbSB7UmVhZG9ubHlNYXQ0fSBhICAgdGhlIHNvdXJjZSA0eDQgbWF0cml4XG4gKiBAcmV0dXJucyB7bWF0M30gb3V0XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGZyb21NYXQ0KG91dCwgYSkge1xuICBvdXRbMF0gPSBhWzBdO1xuICBvdXRbMV0gPSBhWzFdO1xuICBvdXRbMl0gPSBhWzJdO1xuICBvdXRbM10gPSBhWzRdO1xuICBvdXRbNF0gPSBhWzVdO1xuICBvdXRbNV0gPSBhWzZdO1xuICBvdXRbNl0gPSBhWzhdO1xuICBvdXRbN10gPSBhWzldO1xuICBvdXRbOF0gPSBhWzEwXTtcbiAgcmV0dXJuIG91dDtcbn1cbi8qKlxuICogQ3JlYXRlcyBhIG5ldyBtYXQzIGluaXRpYWxpemVkIHdpdGggdmFsdWVzIGZyb20gYW4gZXhpc3RpbmcgbWF0cml4XG4gKlxuICogQHBhcmFtIHtSZWFkb25seU1hdDN9IGEgbWF0cml4IHRvIGNsb25lXG4gKiBAcmV0dXJucyB7bWF0M30gYSBuZXcgM3gzIG1hdHJpeFxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBjbG9uZShhKSB7XG4gIHZhciBvdXQgPSBuZXcgZ2xNYXRyaXguQVJSQVlfVFlQRSg5KTtcbiAgb3V0WzBdID0gYVswXTtcbiAgb3V0WzFdID0gYVsxXTtcbiAgb3V0WzJdID0gYVsyXTtcbiAgb3V0WzNdID0gYVszXTtcbiAgb3V0WzRdID0gYVs0XTtcbiAgb3V0WzVdID0gYVs1XTtcbiAgb3V0WzZdID0gYVs2XTtcbiAgb3V0WzddID0gYVs3XTtcbiAgb3V0WzhdID0gYVs4XTtcbiAgcmV0dXJuIG91dDtcbn1cbi8qKlxuICogQ29weSB0aGUgdmFsdWVzIGZyb20gb25lIG1hdDMgdG8gYW5vdGhlclxuICpcbiAqIEBwYXJhbSB7bWF0M30gb3V0IHRoZSByZWNlaXZpbmcgbWF0cml4XG4gKiBAcGFyYW0ge1JlYWRvbmx5TWF0M30gYSB0aGUgc291cmNlIG1hdHJpeFxuICogQHJldHVybnMge21hdDN9IG91dFxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBjb3B5KG91dCwgYSkge1xuICBvdXRbMF0gPSBhWzBdO1xuICBvdXRbMV0gPSBhWzFdO1xuICBvdXRbMl0gPSBhWzJdO1xuICBvdXRbM10gPSBhWzNdO1xuICBvdXRbNF0gPSBhWzRdO1xuICBvdXRbNV0gPSBhWzVdO1xuICBvdXRbNl0gPSBhWzZdO1xuICBvdXRbN10gPSBhWzddO1xuICBvdXRbOF0gPSBhWzhdO1xuICByZXR1cm4gb3V0O1xufVxuLyoqXG4gKiBDcmVhdGUgYSBuZXcgbWF0MyB3aXRoIHRoZSBnaXZlbiB2YWx1ZXNcbiAqXG4gKiBAcGFyYW0ge051bWJlcn0gbTAwIENvbXBvbmVudCBpbiBjb2x1bW4gMCwgcm93IDAgcG9zaXRpb24gKGluZGV4IDApXG4gKiBAcGFyYW0ge051bWJlcn0gbTAxIENvbXBvbmVudCBpbiBjb2x1bW4gMCwgcm93IDEgcG9zaXRpb24gKGluZGV4IDEpXG4gKiBAcGFyYW0ge051bWJlcn0gbTAyIENvbXBvbmVudCBpbiBjb2x1bW4gMCwgcm93IDIgcG9zaXRpb24gKGluZGV4IDIpXG4gKiBAcGFyYW0ge051bWJlcn0gbTEwIENvbXBvbmVudCBpbiBjb2x1bW4gMSwgcm93IDAgcG9zaXRpb24gKGluZGV4IDMpXG4gKiBAcGFyYW0ge051bWJlcn0gbTExIENvbXBvbmVudCBpbiBjb2x1bW4gMSwgcm93IDEgcG9zaXRpb24gKGluZGV4IDQpXG4gKiBAcGFyYW0ge051bWJlcn0gbTEyIENvbXBvbmVudCBpbiBjb2x1bW4gMSwgcm93IDIgcG9zaXRpb24gKGluZGV4IDUpXG4gKiBAcGFyYW0ge051bWJlcn0gbTIwIENvbXBvbmVudCBpbiBjb2x1bW4gMiwgcm93IDAgcG9zaXRpb24gKGluZGV4IDYpXG4gKiBAcGFyYW0ge051bWJlcn0gbTIxIENvbXBvbmVudCBpbiBjb2x1bW4gMiwgcm93IDEgcG9zaXRpb24gKGluZGV4IDcpXG4gKiBAcGFyYW0ge051bWJlcn0gbTIyIENvbXBvbmVudCBpbiBjb2x1bW4gMiwgcm93IDIgcG9zaXRpb24gKGluZGV4IDgpXG4gKiBAcmV0dXJucyB7bWF0M30gQSBuZXcgbWF0M1xuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBmcm9tVmFsdWVzKG0wMCwgbTAxLCBtMDIsIG0xMCwgbTExLCBtMTIsIG0yMCwgbTIxLCBtMjIpIHtcbiAgdmFyIG91dCA9IG5ldyBnbE1hdHJpeC5BUlJBWV9UWVBFKDkpO1xuICBvdXRbMF0gPSBtMDA7XG4gIG91dFsxXSA9IG0wMTtcbiAgb3V0WzJdID0gbTAyO1xuICBvdXRbM10gPSBtMTA7XG4gIG91dFs0XSA9IG0xMTtcbiAgb3V0WzVdID0gbTEyO1xuICBvdXRbNl0gPSBtMjA7XG4gIG91dFs3XSA9IG0yMTtcbiAgb3V0WzhdID0gbTIyO1xuICByZXR1cm4gb3V0O1xufVxuLyoqXG4gKiBTZXQgdGhlIGNvbXBvbmVudHMgb2YgYSBtYXQzIHRvIHRoZSBnaXZlbiB2YWx1ZXNcbiAqXG4gKiBAcGFyYW0ge21hdDN9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHtOdW1iZXJ9IG0wMCBDb21wb25lbnQgaW4gY29sdW1uIDAsIHJvdyAwIHBvc2l0aW9uIChpbmRleCAwKVxuICogQHBhcmFtIHtOdW1iZXJ9IG0wMSBDb21wb25lbnQgaW4gY29sdW1uIDAsIHJvdyAxIHBvc2l0aW9uIChpbmRleCAxKVxuICogQHBhcmFtIHtOdW1iZXJ9IG0wMiBDb21wb25lbnQgaW4gY29sdW1uIDAsIHJvdyAyIHBvc2l0aW9uIChpbmRleCAyKVxuICogQHBhcmFtIHtOdW1iZXJ9IG0xMCBDb21wb25lbnQgaW4gY29sdW1uIDEsIHJvdyAwIHBvc2l0aW9uIChpbmRleCAzKVxuICogQHBhcmFtIHtOdW1iZXJ9IG0xMSBDb21wb25lbnQgaW4gY29sdW1uIDEsIHJvdyAxIHBvc2l0aW9uIChpbmRleCA0KVxuICogQHBhcmFtIHtOdW1iZXJ9IG0xMiBDb21wb25lbnQgaW4gY29sdW1uIDEsIHJvdyAyIHBvc2l0aW9uIChpbmRleCA1KVxuICogQHBhcmFtIHtOdW1iZXJ9IG0yMCBDb21wb25lbnQgaW4gY29sdW1uIDIsIHJvdyAwIHBvc2l0aW9uIChpbmRleCA2KVxuICogQHBhcmFtIHtOdW1iZXJ9IG0yMSBDb21wb25lbnQgaW4gY29sdW1uIDIsIHJvdyAxIHBvc2l0aW9uIChpbmRleCA3KVxuICogQHBhcmFtIHtOdW1iZXJ9IG0yMiBDb21wb25lbnQgaW4gY29sdW1uIDIsIHJvdyAyIHBvc2l0aW9uIChpbmRleCA4KVxuICogQHJldHVybnMge21hdDN9IG91dFxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBzZXQob3V0LCBtMDAsIG0wMSwgbTAyLCBtMTAsIG0xMSwgbTEyLCBtMjAsIG0yMSwgbTIyKSB7XG4gIG91dFswXSA9IG0wMDtcbiAgb3V0WzFdID0gbTAxO1xuICBvdXRbMl0gPSBtMDI7XG4gIG91dFszXSA9IG0xMDtcbiAgb3V0WzRdID0gbTExO1xuICBvdXRbNV0gPSBtMTI7XG4gIG91dFs2XSA9IG0yMDtcbiAgb3V0WzddID0gbTIxO1xuICBvdXRbOF0gPSBtMjI7XG4gIHJldHVybiBvdXQ7XG59XG4vKipcbiAqIFNldCBhIG1hdDMgdG8gdGhlIGlkZW50aXR5IG1hdHJpeFxuICpcbiAqIEBwYXJhbSB7bWF0M30gb3V0IHRoZSByZWNlaXZpbmcgbWF0cml4XG4gKiBAcmV0dXJucyB7bWF0M30gb3V0XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGlkZW50aXR5KG91dCkge1xuICBvdXRbMF0gPSAxO1xuICBvdXRbMV0gPSAwO1xuICBvdXRbMl0gPSAwO1xuICBvdXRbM10gPSAwO1xuICBvdXRbNF0gPSAxO1xuICBvdXRbNV0gPSAwO1xuICBvdXRbNl0gPSAwO1xuICBvdXRbN10gPSAwO1xuICBvdXRbOF0gPSAxO1xuICByZXR1cm4gb3V0O1xufVxuLyoqXG4gKiBUcmFuc3Bvc2UgdGhlIHZhbHVlcyBvZiBhIG1hdDNcbiAqXG4gKiBAcGFyYW0ge21hdDN9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHtSZWFkb25seU1hdDN9IGEgdGhlIHNvdXJjZSBtYXRyaXhcbiAqIEByZXR1cm5zIHttYXQzfSBvdXRcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gdHJhbnNwb3NlKG91dCwgYSkge1xuICAvLyBJZiB3ZSBhcmUgdHJhbnNwb3Npbmcgb3Vyc2VsdmVzIHdlIGNhbiBza2lwIGEgZmV3IHN0ZXBzIGJ1dCBoYXZlIHRvIGNhY2hlIHNvbWUgdmFsdWVzXG4gIGlmIChvdXQgPT09IGEpIHtcbiAgICB2YXIgYTAxID0gYVsxXSxcbiAgICAgICAgYTAyID0gYVsyXSxcbiAgICAgICAgYTEyID0gYVs1XTtcbiAgICBvdXRbMV0gPSBhWzNdO1xuICAgIG91dFsyXSA9IGFbNl07XG4gICAgb3V0WzNdID0gYTAxO1xuICAgIG91dFs1XSA9IGFbN107XG4gICAgb3V0WzZdID0gYTAyO1xuICAgIG91dFs3XSA9IGExMjtcbiAgfSBlbHNlIHtcbiAgICBvdXRbMF0gPSBhWzBdO1xuICAgIG91dFsxXSA9IGFbM107XG4gICAgb3V0WzJdID0gYVs2XTtcbiAgICBvdXRbM10gPSBhWzFdO1xuICAgIG91dFs0XSA9IGFbNF07XG4gICAgb3V0WzVdID0gYVs3XTtcbiAgICBvdXRbNl0gPSBhWzJdO1xuICAgIG91dFs3XSA9IGFbNV07XG4gICAgb3V0WzhdID0gYVs4XTtcbiAgfVxuXG4gIHJldHVybiBvdXQ7XG59XG4vKipcbiAqIEludmVydHMgYSBtYXQzXG4gKlxuICogQHBhcmFtIHttYXQzfSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7UmVhZG9ubHlNYXQzfSBhIHRoZSBzb3VyY2UgbWF0cml4XG4gKiBAcmV0dXJucyB7bWF0M30gb3V0XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGludmVydChvdXQsIGEpIHtcbiAgdmFyIGEwMCA9IGFbMF0sXG4gICAgICBhMDEgPSBhWzFdLFxuICAgICAgYTAyID0gYVsyXTtcbiAgdmFyIGExMCA9IGFbM10sXG4gICAgICBhMTEgPSBhWzRdLFxuICAgICAgYTEyID0gYVs1XTtcbiAgdmFyIGEyMCA9IGFbNl0sXG4gICAgICBhMjEgPSBhWzddLFxuICAgICAgYTIyID0gYVs4XTtcbiAgdmFyIGIwMSA9IGEyMiAqIGExMSAtIGExMiAqIGEyMTtcbiAgdmFyIGIxMSA9IC1hMjIgKiBhMTAgKyBhMTIgKiBhMjA7XG4gIHZhciBiMjEgPSBhMjEgKiBhMTAgLSBhMTEgKiBhMjA7IC8vIENhbGN1bGF0ZSB0aGUgZGV0ZXJtaW5hbnRcblxuICB2YXIgZGV0ID0gYTAwICogYjAxICsgYTAxICogYjExICsgYTAyICogYjIxO1xuXG4gIGlmICghZGV0KSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBkZXQgPSAxLjAgLyBkZXQ7XG4gIG91dFswXSA9IGIwMSAqIGRldDtcbiAgb3V0WzFdID0gKC1hMjIgKiBhMDEgKyBhMDIgKiBhMjEpICogZGV0O1xuICBvdXRbMl0gPSAoYTEyICogYTAxIC0gYTAyICogYTExKSAqIGRldDtcbiAgb3V0WzNdID0gYjExICogZGV0O1xuICBvdXRbNF0gPSAoYTIyICogYTAwIC0gYTAyICogYTIwKSAqIGRldDtcbiAgb3V0WzVdID0gKC1hMTIgKiBhMDAgKyBhMDIgKiBhMTApICogZGV0O1xuICBvdXRbNl0gPSBiMjEgKiBkZXQ7XG4gIG91dFs3XSA9ICgtYTIxICogYTAwICsgYTAxICogYTIwKSAqIGRldDtcbiAgb3V0WzhdID0gKGExMSAqIGEwMCAtIGEwMSAqIGExMCkgKiBkZXQ7XG4gIHJldHVybiBvdXQ7XG59XG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIGFkanVnYXRlIG9mIGEgbWF0M1xuICpcbiAqIEBwYXJhbSB7bWF0M30gb3V0IHRoZSByZWNlaXZpbmcgbWF0cml4XG4gKiBAcGFyYW0ge1JlYWRvbmx5TWF0M30gYSB0aGUgc291cmNlIG1hdHJpeFxuICogQHJldHVybnMge21hdDN9IG91dFxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBhZGpvaW50KG91dCwgYSkge1xuICB2YXIgYTAwID0gYVswXSxcbiAgICAgIGEwMSA9IGFbMV0sXG4gICAgICBhMDIgPSBhWzJdO1xuICB2YXIgYTEwID0gYVszXSxcbiAgICAgIGExMSA9IGFbNF0sXG4gICAgICBhMTIgPSBhWzVdO1xuICB2YXIgYTIwID0gYVs2XSxcbiAgICAgIGEyMSA9IGFbN10sXG4gICAgICBhMjIgPSBhWzhdO1xuICBvdXRbMF0gPSBhMTEgKiBhMjIgLSBhMTIgKiBhMjE7XG4gIG91dFsxXSA9IGEwMiAqIGEyMSAtIGEwMSAqIGEyMjtcbiAgb3V0WzJdID0gYTAxICogYTEyIC0gYTAyICogYTExO1xuICBvdXRbM10gPSBhMTIgKiBhMjAgLSBhMTAgKiBhMjI7XG4gIG91dFs0XSA9IGEwMCAqIGEyMiAtIGEwMiAqIGEyMDtcbiAgb3V0WzVdID0gYTAyICogYTEwIC0gYTAwICogYTEyO1xuICBvdXRbNl0gPSBhMTAgKiBhMjEgLSBhMTEgKiBhMjA7XG4gIG91dFs3XSA9IGEwMSAqIGEyMCAtIGEwMCAqIGEyMTtcbiAgb3V0WzhdID0gYTAwICogYTExIC0gYTAxICogYTEwO1xuICByZXR1cm4gb3V0O1xufVxuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSBkZXRlcm1pbmFudCBvZiBhIG1hdDNcbiAqXG4gKiBAcGFyYW0ge1JlYWRvbmx5TWF0M30gYSB0aGUgc291cmNlIG1hdHJpeFxuICogQHJldHVybnMge051bWJlcn0gZGV0ZXJtaW5hbnQgb2YgYVxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBkZXRlcm1pbmFudChhKSB7XG4gIHZhciBhMDAgPSBhWzBdLFxuICAgICAgYTAxID0gYVsxXSxcbiAgICAgIGEwMiA9IGFbMl07XG4gIHZhciBhMTAgPSBhWzNdLFxuICAgICAgYTExID0gYVs0XSxcbiAgICAgIGExMiA9IGFbNV07XG4gIHZhciBhMjAgPSBhWzZdLFxuICAgICAgYTIxID0gYVs3XSxcbiAgICAgIGEyMiA9IGFbOF07XG4gIHJldHVybiBhMDAgKiAoYTIyICogYTExIC0gYTEyICogYTIxKSArIGEwMSAqICgtYTIyICogYTEwICsgYTEyICogYTIwKSArIGEwMiAqIChhMjEgKiBhMTAgLSBhMTEgKiBhMjApO1xufVxuLyoqXG4gKiBNdWx0aXBsaWVzIHR3byBtYXQzJ3NcbiAqXG4gKiBAcGFyYW0ge21hdDN9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHtSZWFkb25seU1hdDN9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7UmVhZG9ubHlNYXQzfSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge21hdDN9IG91dFxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBtdWx0aXBseShvdXQsIGEsIGIpIHtcbiAgdmFyIGEwMCA9IGFbMF0sXG4gICAgICBhMDEgPSBhWzFdLFxuICAgICAgYTAyID0gYVsyXTtcbiAgdmFyIGExMCA9IGFbM10sXG4gICAgICBhMTEgPSBhWzRdLFxuICAgICAgYTEyID0gYVs1XTtcbiAgdmFyIGEyMCA9IGFbNl0sXG4gICAgICBhMjEgPSBhWzddLFxuICAgICAgYTIyID0gYVs4XTtcbiAgdmFyIGIwMCA9IGJbMF0sXG4gICAgICBiMDEgPSBiWzFdLFxuICAgICAgYjAyID0gYlsyXTtcbiAgdmFyIGIxMCA9IGJbM10sXG4gICAgICBiMTEgPSBiWzRdLFxuICAgICAgYjEyID0gYls1XTtcbiAgdmFyIGIyMCA9IGJbNl0sXG4gICAgICBiMjEgPSBiWzddLFxuICAgICAgYjIyID0gYls4XTtcbiAgb3V0WzBdID0gYjAwICogYTAwICsgYjAxICogYTEwICsgYjAyICogYTIwO1xuICBvdXRbMV0gPSBiMDAgKiBhMDEgKyBiMDEgKiBhMTEgKyBiMDIgKiBhMjE7XG4gIG91dFsyXSA9IGIwMCAqIGEwMiArIGIwMSAqIGExMiArIGIwMiAqIGEyMjtcbiAgb3V0WzNdID0gYjEwICogYTAwICsgYjExICogYTEwICsgYjEyICogYTIwO1xuICBvdXRbNF0gPSBiMTAgKiBhMDEgKyBiMTEgKiBhMTEgKyBiMTIgKiBhMjE7XG4gIG91dFs1XSA9IGIxMCAqIGEwMiArIGIxMSAqIGExMiArIGIxMiAqIGEyMjtcbiAgb3V0WzZdID0gYjIwICogYTAwICsgYjIxICogYTEwICsgYjIyICogYTIwO1xuICBvdXRbN10gPSBiMjAgKiBhMDEgKyBiMjEgKiBhMTEgKyBiMjIgKiBhMjE7XG4gIG91dFs4XSA9IGIyMCAqIGEwMiArIGIyMSAqIGExMiArIGIyMiAqIGEyMjtcbiAgcmV0dXJuIG91dDtcbn1cbi8qKlxuICogVHJhbnNsYXRlIGEgbWF0MyBieSB0aGUgZ2l2ZW4gdmVjdG9yXG4gKlxuICogQHBhcmFtIHttYXQzfSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7UmVhZG9ubHlNYXQzfSBhIHRoZSBtYXRyaXggdG8gdHJhbnNsYXRlXG4gKiBAcGFyYW0ge1JlYWRvbmx5VmVjMn0gdiB2ZWN0b3IgdG8gdHJhbnNsYXRlIGJ5XG4gKiBAcmV0dXJucyB7bWF0M30gb3V0XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIHRyYW5zbGF0ZShvdXQsIGEsIHYpIHtcbiAgdmFyIGEwMCA9IGFbMF0sXG4gICAgICBhMDEgPSBhWzFdLFxuICAgICAgYTAyID0gYVsyXSxcbiAgICAgIGExMCA9IGFbM10sXG4gICAgICBhMTEgPSBhWzRdLFxuICAgICAgYTEyID0gYVs1XSxcbiAgICAgIGEyMCA9IGFbNl0sXG4gICAgICBhMjEgPSBhWzddLFxuICAgICAgYTIyID0gYVs4XSxcbiAgICAgIHggPSB2WzBdLFxuICAgICAgeSA9IHZbMV07XG4gIG91dFswXSA9IGEwMDtcbiAgb3V0WzFdID0gYTAxO1xuICBvdXRbMl0gPSBhMDI7XG4gIG91dFszXSA9IGExMDtcbiAgb3V0WzRdID0gYTExO1xuICBvdXRbNV0gPSBhMTI7XG4gIG91dFs2XSA9IHggKiBhMDAgKyB5ICogYTEwICsgYTIwO1xuICBvdXRbN10gPSB4ICogYTAxICsgeSAqIGExMSArIGEyMTtcbiAgb3V0WzhdID0geCAqIGEwMiArIHkgKiBhMTIgKyBhMjI7XG4gIHJldHVybiBvdXQ7XG59XG4vKipcbiAqIFJvdGF0ZXMgYSBtYXQzIGJ5IHRoZSBnaXZlbiBhbmdsZVxuICpcbiAqIEBwYXJhbSB7bWF0M30gb3V0IHRoZSByZWNlaXZpbmcgbWF0cml4XG4gKiBAcGFyYW0ge1JlYWRvbmx5TWF0M30gYSB0aGUgbWF0cml4IHRvIHJvdGF0ZVxuICogQHBhcmFtIHtOdW1iZXJ9IHJhZCB0aGUgYW5nbGUgdG8gcm90YXRlIHRoZSBtYXRyaXggYnlcbiAqIEByZXR1cm5zIHttYXQzfSBvdXRcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gcm90YXRlKG91dCwgYSwgcmFkKSB7XG4gIHZhciBhMDAgPSBhWzBdLFxuICAgICAgYTAxID0gYVsxXSxcbiAgICAgIGEwMiA9IGFbMl0sXG4gICAgICBhMTAgPSBhWzNdLFxuICAgICAgYTExID0gYVs0XSxcbiAgICAgIGExMiA9IGFbNV0sXG4gICAgICBhMjAgPSBhWzZdLFxuICAgICAgYTIxID0gYVs3XSxcbiAgICAgIGEyMiA9IGFbOF0sXG4gICAgICBzID0gTWF0aC5zaW4ocmFkKSxcbiAgICAgIGMgPSBNYXRoLmNvcyhyYWQpO1xuICBvdXRbMF0gPSBjICogYTAwICsgcyAqIGExMDtcbiAgb3V0WzFdID0gYyAqIGEwMSArIHMgKiBhMTE7XG4gIG91dFsyXSA9IGMgKiBhMDIgKyBzICogYTEyO1xuICBvdXRbM10gPSBjICogYTEwIC0gcyAqIGEwMDtcbiAgb3V0WzRdID0gYyAqIGExMSAtIHMgKiBhMDE7XG4gIG91dFs1XSA9IGMgKiBhMTIgLSBzICogYTAyO1xuICBvdXRbNl0gPSBhMjA7XG4gIG91dFs3XSA9IGEyMTtcbiAgb3V0WzhdID0gYTIyO1xuICByZXR1cm4gb3V0O1xufVxuLyoqXG4gKiBTY2FsZXMgdGhlIG1hdDMgYnkgdGhlIGRpbWVuc2lvbnMgaW4gdGhlIGdpdmVuIHZlYzJcbiAqXG4gKiBAcGFyYW0ge21hdDN9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHtSZWFkb25seU1hdDN9IGEgdGhlIG1hdHJpeCB0byByb3RhdGVcbiAqIEBwYXJhbSB7UmVhZG9ubHlWZWMyfSB2IHRoZSB2ZWMyIHRvIHNjYWxlIHRoZSBtYXRyaXggYnlcbiAqIEByZXR1cm5zIHttYXQzfSBvdXRcbiAqKi9cblxuZXhwb3J0IGZ1bmN0aW9uIHNjYWxlKG91dCwgYSwgdikge1xuICB2YXIgeCA9IHZbMF0sXG4gICAgICB5ID0gdlsxXTtcbiAgb3V0WzBdID0geCAqIGFbMF07XG4gIG91dFsxXSA9IHggKiBhWzFdO1xuICBvdXRbMl0gPSB4ICogYVsyXTtcbiAgb3V0WzNdID0geSAqIGFbM107XG4gIG91dFs0XSA9IHkgKiBhWzRdO1xuICBvdXRbNV0gPSB5ICogYVs1XTtcbiAgb3V0WzZdID0gYVs2XTtcbiAgb3V0WzddID0gYVs3XTtcbiAgb3V0WzhdID0gYVs4XTtcbiAgcmV0dXJuIG91dDtcbn1cbi8qKlxuICogQ3JlYXRlcyBhIG1hdHJpeCBmcm9tIGEgdmVjdG9yIHRyYW5zbGF0aW9uXG4gKiBUaGlzIGlzIGVxdWl2YWxlbnQgdG8gKGJ1dCBtdWNoIGZhc3RlciB0aGFuKTpcbiAqXG4gKiAgICAgbWF0My5pZGVudGl0eShkZXN0KTtcbiAqICAgICBtYXQzLnRyYW5zbGF0ZShkZXN0LCBkZXN0LCB2ZWMpO1xuICpcbiAqIEBwYXJhbSB7bWF0M30gb3V0IG1hdDMgcmVjZWl2aW5nIG9wZXJhdGlvbiByZXN1bHRcbiAqIEBwYXJhbSB7UmVhZG9ubHlWZWMyfSB2IFRyYW5zbGF0aW9uIHZlY3RvclxuICogQHJldHVybnMge21hdDN9IG91dFxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBmcm9tVHJhbnNsYXRpb24ob3V0LCB2KSB7XG4gIG91dFswXSA9IDE7XG4gIG91dFsxXSA9IDA7XG4gIG91dFsyXSA9IDA7XG4gIG91dFszXSA9IDA7XG4gIG91dFs0XSA9IDE7XG4gIG91dFs1XSA9IDA7XG4gIG91dFs2XSA9IHZbMF07XG4gIG91dFs3XSA9IHZbMV07XG4gIG91dFs4XSA9IDE7XG4gIHJldHVybiBvdXQ7XG59XG4vKipcbiAqIENyZWF0ZXMgYSBtYXRyaXggZnJvbSBhIGdpdmVuIGFuZ2xlXG4gKiBUaGlzIGlzIGVxdWl2YWxlbnQgdG8gKGJ1dCBtdWNoIGZhc3RlciB0aGFuKTpcbiAqXG4gKiAgICAgbWF0My5pZGVudGl0eShkZXN0KTtcbiAqICAgICBtYXQzLnJvdGF0ZShkZXN0LCBkZXN0LCByYWQpO1xuICpcbiAqIEBwYXJhbSB7bWF0M30gb3V0IG1hdDMgcmVjZWl2aW5nIG9wZXJhdGlvbiByZXN1bHRcbiAqIEBwYXJhbSB7TnVtYmVyfSByYWQgdGhlIGFuZ2xlIHRvIHJvdGF0ZSB0aGUgbWF0cml4IGJ5XG4gKiBAcmV0dXJucyB7bWF0M30gb3V0XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGZyb21Sb3RhdGlvbihvdXQsIHJhZCkge1xuICB2YXIgcyA9IE1hdGguc2luKHJhZCksXG4gICAgICBjID0gTWF0aC5jb3MocmFkKTtcbiAgb3V0WzBdID0gYztcbiAgb3V0WzFdID0gcztcbiAgb3V0WzJdID0gMDtcbiAgb3V0WzNdID0gLXM7XG4gIG91dFs0XSA9IGM7XG4gIG91dFs1XSA9IDA7XG4gIG91dFs2XSA9IDA7XG4gIG91dFs3XSA9IDA7XG4gIG91dFs4XSA9IDE7XG4gIHJldHVybiBvdXQ7XG59XG4vKipcbiAqIENyZWF0ZXMgYSBtYXRyaXggZnJvbSBhIHZlY3RvciBzY2FsaW5nXG4gKiBUaGlzIGlzIGVxdWl2YWxlbnQgdG8gKGJ1dCBtdWNoIGZhc3RlciB0aGFuKTpcbiAqXG4gKiAgICAgbWF0My5pZGVudGl0eShkZXN0KTtcbiAqICAgICBtYXQzLnNjYWxlKGRlc3QsIGRlc3QsIHZlYyk7XG4gKlxuICogQHBhcmFtIHttYXQzfSBvdXQgbWF0MyByZWNlaXZpbmcgb3BlcmF0aW9uIHJlc3VsdFxuICogQHBhcmFtIHtSZWFkb25seVZlYzJ9IHYgU2NhbGluZyB2ZWN0b3JcbiAqIEByZXR1cm5zIHttYXQzfSBvdXRcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gZnJvbVNjYWxpbmcob3V0LCB2KSB7XG4gIG91dFswXSA9IHZbMF07XG4gIG91dFsxXSA9IDA7XG4gIG91dFsyXSA9IDA7XG4gIG91dFszXSA9IDA7XG4gIG91dFs0XSA9IHZbMV07XG4gIG91dFs1XSA9IDA7XG4gIG91dFs2XSA9IDA7XG4gIG91dFs3XSA9IDA7XG4gIG91dFs4XSA9IDE7XG4gIHJldHVybiBvdXQ7XG59XG4vKipcbiAqIENvcGllcyB0aGUgdmFsdWVzIGZyb20gYSBtYXQyZCBpbnRvIGEgbWF0M1xuICpcbiAqIEBwYXJhbSB7bWF0M30gb3V0IHRoZSByZWNlaXZpbmcgbWF0cml4XG4gKiBAcGFyYW0ge1JlYWRvbmx5TWF0MmR9IGEgdGhlIG1hdHJpeCB0byBjb3B5XG4gKiBAcmV0dXJucyB7bWF0M30gb3V0XG4gKiovXG5cbmV4cG9ydCBmdW5jdGlvbiBmcm9tTWF0MmQob3V0LCBhKSB7XG4gIG91dFswXSA9IGFbMF07XG4gIG91dFsxXSA9IGFbMV07XG4gIG91dFsyXSA9IDA7XG4gIG91dFszXSA9IGFbMl07XG4gIG91dFs0XSA9IGFbM107XG4gIG91dFs1XSA9IDA7XG4gIG91dFs2XSA9IGFbNF07XG4gIG91dFs3XSA9IGFbNV07XG4gIG91dFs4XSA9IDE7XG4gIHJldHVybiBvdXQ7XG59XG4vKipcbiAqIENhbGN1bGF0ZXMgYSAzeDMgbWF0cml4IGZyb20gdGhlIGdpdmVuIHF1YXRlcm5pb25cbiAqXG4gKiBAcGFyYW0ge21hdDN9IG91dCBtYXQzIHJlY2VpdmluZyBvcGVyYXRpb24gcmVzdWx0XG4gKiBAcGFyYW0ge1JlYWRvbmx5UXVhdH0gcSBRdWF0ZXJuaW9uIHRvIGNyZWF0ZSBtYXRyaXggZnJvbVxuICpcbiAqIEByZXR1cm5zIHttYXQzfSBvdXRcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gZnJvbVF1YXQob3V0LCBxKSB7XG4gIHZhciB4ID0gcVswXSxcbiAgICAgIHkgPSBxWzFdLFxuICAgICAgeiA9IHFbMl0sXG4gICAgICB3ID0gcVszXTtcbiAgdmFyIHgyID0geCArIHg7XG4gIHZhciB5MiA9IHkgKyB5O1xuICB2YXIgejIgPSB6ICsgejtcbiAgdmFyIHh4ID0geCAqIHgyO1xuICB2YXIgeXggPSB5ICogeDI7XG4gIHZhciB5eSA9IHkgKiB5MjtcbiAgdmFyIHp4ID0geiAqIHgyO1xuICB2YXIgenkgPSB6ICogeTI7XG4gIHZhciB6eiA9IHogKiB6MjtcbiAgdmFyIHd4ID0gdyAqIHgyO1xuICB2YXIgd3kgPSB3ICogeTI7XG4gIHZhciB3eiA9IHcgKiB6MjtcbiAgb3V0WzBdID0gMSAtIHl5IC0geno7XG4gIG91dFszXSA9IHl4IC0gd3o7XG4gIG91dFs2XSA9IHp4ICsgd3k7XG4gIG91dFsxXSA9IHl4ICsgd3o7XG4gIG91dFs0XSA9IDEgLSB4eCAtIHp6O1xuICBvdXRbN10gPSB6eSAtIHd4O1xuICBvdXRbMl0gPSB6eCAtIHd5O1xuICBvdXRbNV0gPSB6eSArIHd4O1xuICBvdXRbOF0gPSAxIC0geHggLSB5eTtcbiAgcmV0dXJuIG91dDtcbn1cbi8qKlxuICogQ2FsY3VsYXRlcyBhIDN4MyBub3JtYWwgbWF0cml4ICh0cmFuc3Bvc2UgaW52ZXJzZSkgZnJvbSB0aGUgNHg0IG1hdHJpeFxuICpcbiAqIEBwYXJhbSB7bWF0M30gb3V0IG1hdDMgcmVjZWl2aW5nIG9wZXJhdGlvbiByZXN1bHRcbiAqIEBwYXJhbSB7UmVhZG9ubHlNYXQ0fSBhIE1hdDQgdG8gZGVyaXZlIHRoZSBub3JtYWwgbWF0cml4IGZyb21cbiAqXG4gKiBAcmV0dXJucyB7bWF0M30gb3V0XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIG5vcm1hbEZyb21NYXQ0KG91dCwgYSkge1xuICB2YXIgYTAwID0gYVswXSxcbiAgICAgIGEwMSA9IGFbMV0sXG4gICAgICBhMDIgPSBhWzJdLFxuICAgICAgYTAzID0gYVszXTtcbiAgdmFyIGExMCA9IGFbNF0sXG4gICAgICBhMTEgPSBhWzVdLFxuICAgICAgYTEyID0gYVs2XSxcbiAgICAgIGExMyA9IGFbN107XG4gIHZhciBhMjAgPSBhWzhdLFxuICAgICAgYTIxID0gYVs5XSxcbiAgICAgIGEyMiA9IGFbMTBdLFxuICAgICAgYTIzID0gYVsxMV07XG4gIHZhciBhMzAgPSBhWzEyXSxcbiAgICAgIGEzMSA9IGFbMTNdLFxuICAgICAgYTMyID0gYVsxNF0sXG4gICAgICBhMzMgPSBhWzE1XTtcbiAgdmFyIGIwMCA9IGEwMCAqIGExMSAtIGEwMSAqIGExMDtcbiAgdmFyIGIwMSA9IGEwMCAqIGExMiAtIGEwMiAqIGExMDtcbiAgdmFyIGIwMiA9IGEwMCAqIGExMyAtIGEwMyAqIGExMDtcbiAgdmFyIGIwMyA9IGEwMSAqIGExMiAtIGEwMiAqIGExMTtcbiAgdmFyIGIwNCA9IGEwMSAqIGExMyAtIGEwMyAqIGExMTtcbiAgdmFyIGIwNSA9IGEwMiAqIGExMyAtIGEwMyAqIGExMjtcbiAgdmFyIGIwNiA9IGEyMCAqIGEzMSAtIGEyMSAqIGEzMDtcbiAgdmFyIGIwNyA9IGEyMCAqIGEzMiAtIGEyMiAqIGEzMDtcbiAgdmFyIGIwOCA9IGEyMCAqIGEzMyAtIGEyMyAqIGEzMDtcbiAgdmFyIGIwOSA9IGEyMSAqIGEzMiAtIGEyMiAqIGEzMTtcbiAgdmFyIGIxMCA9IGEyMSAqIGEzMyAtIGEyMyAqIGEzMTtcbiAgdmFyIGIxMSA9IGEyMiAqIGEzMyAtIGEyMyAqIGEzMjsgLy8gQ2FsY3VsYXRlIHRoZSBkZXRlcm1pbmFudFxuXG4gIHZhciBkZXQgPSBiMDAgKiBiMTEgLSBiMDEgKiBiMTAgKyBiMDIgKiBiMDkgKyBiMDMgKiBiMDggLSBiMDQgKiBiMDcgKyBiMDUgKiBiMDY7XG5cbiAgaWYgKCFkZXQpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGRldCA9IDEuMCAvIGRldDtcbiAgb3V0WzBdID0gKGExMSAqIGIxMSAtIGExMiAqIGIxMCArIGExMyAqIGIwOSkgKiBkZXQ7XG4gIG91dFsxXSA9IChhMTIgKiBiMDggLSBhMTAgKiBiMTEgLSBhMTMgKiBiMDcpICogZGV0O1xuICBvdXRbMl0gPSAoYTEwICogYjEwIC0gYTExICogYjA4ICsgYTEzICogYjA2KSAqIGRldDtcbiAgb3V0WzNdID0gKGEwMiAqIGIxMCAtIGEwMSAqIGIxMSAtIGEwMyAqIGIwOSkgKiBkZXQ7XG4gIG91dFs0XSA9IChhMDAgKiBiMTEgLSBhMDIgKiBiMDggKyBhMDMgKiBiMDcpICogZGV0O1xuICBvdXRbNV0gPSAoYTAxICogYjA4IC0gYTAwICogYjEwIC0gYTAzICogYjA2KSAqIGRldDtcbiAgb3V0WzZdID0gKGEzMSAqIGIwNSAtIGEzMiAqIGIwNCArIGEzMyAqIGIwMykgKiBkZXQ7XG4gIG91dFs3XSA9IChhMzIgKiBiMDIgLSBhMzAgKiBiMDUgLSBhMzMgKiBiMDEpICogZGV0O1xuICBvdXRbOF0gPSAoYTMwICogYjA0IC0gYTMxICogYjAyICsgYTMzICogYjAwKSAqIGRldDtcbiAgcmV0dXJuIG91dDtcbn1cbi8qKlxuICogR2VuZXJhdGVzIGEgMkQgcHJvamVjdGlvbiBtYXRyaXggd2l0aCB0aGUgZ2l2ZW4gYm91bmRzXG4gKlxuICogQHBhcmFtIHttYXQzfSBvdXQgbWF0MyBmcnVzdHVtIG1hdHJpeCB3aWxsIGJlIHdyaXR0ZW4gaW50b1xuICogQHBhcmFtIHtudW1iZXJ9IHdpZHRoIFdpZHRoIG9mIHlvdXIgZ2wgY29udGV4dFxuICogQHBhcmFtIHtudW1iZXJ9IGhlaWdodCBIZWlnaHQgb2YgZ2wgY29udGV4dFxuICogQHJldHVybnMge21hdDN9IG91dFxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBwcm9qZWN0aW9uKG91dCwgd2lkdGgsIGhlaWdodCkge1xuICBvdXRbMF0gPSAyIC8gd2lkdGg7XG4gIG91dFsxXSA9IDA7XG4gIG91dFsyXSA9IDA7XG4gIG91dFszXSA9IDA7XG4gIG91dFs0XSA9IC0yIC8gaGVpZ2h0O1xuICBvdXRbNV0gPSAwO1xuICBvdXRbNl0gPSAtMTtcbiAgb3V0WzddID0gMTtcbiAgb3V0WzhdID0gMTtcbiAgcmV0dXJuIG91dDtcbn1cbi8qKlxuICogUmV0dXJucyBhIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiBhIG1hdDNcbiAqXG4gKiBAcGFyYW0ge1JlYWRvbmx5TWF0M30gYSBtYXRyaXggdG8gcmVwcmVzZW50IGFzIGEgc3RyaW5nXG4gKiBAcmV0dXJucyB7U3RyaW5nfSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIG1hdHJpeFxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBzdHIoYSkge1xuICByZXR1cm4gXCJtYXQzKFwiICsgYVswXSArIFwiLCBcIiArIGFbMV0gKyBcIiwgXCIgKyBhWzJdICsgXCIsIFwiICsgYVszXSArIFwiLCBcIiArIGFbNF0gKyBcIiwgXCIgKyBhWzVdICsgXCIsIFwiICsgYVs2XSArIFwiLCBcIiArIGFbN10gKyBcIiwgXCIgKyBhWzhdICsgXCIpXCI7XG59XG4vKipcbiAqIFJldHVybnMgRnJvYmVuaXVzIG5vcm0gb2YgYSBtYXQzXG4gKlxuICogQHBhcmFtIHtSZWFkb25seU1hdDN9IGEgdGhlIG1hdHJpeCB0byBjYWxjdWxhdGUgRnJvYmVuaXVzIG5vcm0gb2ZcbiAqIEByZXR1cm5zIHtOdW1iZXJ9IEZyb2Jlbml1cyBub3JtXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGZyb2IoYSkge1xuICByZXR1cm4gTWF0aC5oeXBvdChhWzBdLCBhWzFdLCBhWzJdLCBhWzNdLCBhWzRdLCBhWzVdLCBhWzZdLCBhWzddLCBhWzhdKTtcbn1cbi8qKlxuICogQWRkcyB0d28gbWF0MydzXG4gKlxuICogQHBhcmFtIHttYXQzfSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7UmVhZG9ubHlNYXQzfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge1JlYWRvbmx5TWF0M30gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHttYXQzfSBvdXRcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gYWRkKG91dCwgYSwgYikge1xuICBvdXRbMF0gPSBhWzBdICsgYlswXTtcbiAgb3V0WzFdID0gYVsxXSArIGJbMV07XG4gIG91dFsyXSA9IGFbMl0gKyBiWzJdO1xuICBvdXRbM10gPSBhWzNdICsgYlszXTtcbiAgb3V0WzRdID0gYVs0XSArIGJbNF07XG4gIG91dFs1XSA9IGFbNV0gKyBiWzVdO1xuICBvdXRbNl0gPSBhWzZdICsgYls2XTtcbiAgb3V0WzddID0gYVs3XSArIGJbN107XG4gIG91dFs4XSA9IGFbOF0gKyBiWzhdO1xuICByZXR1cm4gb3V0O1xufVxuLyoqXG4gKiBTdWJ0cmFjdHMgbWF0cml4IGIgZnJvbSBtYXRyaXggYVxuICpcbiAqIEBwYXJhbSB7bWF0M30gb3V0IHRoZSByZWNlaXZpbmcgbWF0cml4XG4gKiBAcGFyYW0ge1JlYWRvbmx5TWF0M30gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHtSZWFkb25seU1hdDN9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7bWF0M30gb3V0XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIHN1YnRyYWN0KG91dCwgYSwgYikge1xuICBvdXRbMF0gPSBhWzBdIC0gYlswXTtcbiAgb3V0WzFdID0gYVsxXSAtIGJbMV07XG4gIG91dFsyXSA9IGFbMl0gLSBiWzJdO1xuICBvdXRbM10gPSBhWzNdIC0gYlszXTtcbiAgb3V0WzRdID0gYVs0XSAtIGJbNF07XG4gIG91dFs1XSA9IGFbNV0gLSBiWzVdO1xuICBvdXRbNl0gPSBhWzZdIC0gYls2XTtcbiAgb3V0WzddID0gYVs3XSAtIGJbN107XG4gIG91dFs4XSA9IGFbOF0gLSBiWzhdO1xuICByZXR1cm4gb3V0O1xufVxuLyoqXG4gKiBNdWx0aXBseSBlYWNoIGVsZW1lbnQgb2YgdGhlIG1hdHJpeCBieSBhIHNjYWxhci5cbiAqXG4gKiBAcGFyYW0ge21hdDN9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHtSZWFkb25seU1hdDN9IGEgdGhlIG1hdHJpeCB0byBzY2FsZVxuICogQHBhcmFtIHtOdW1iZXJ9IGIgYW1vdW50IHRvIHNjYWxlIHRoZSBtYXRyaXgncyBlbGVtZW50cyBieVxuICogQHJldHVybnMge21hdDN9IG91dFxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBtdWx0aXBseVNjYWxhcihvdXQsIGEsIGIpIHtcbiAgb3V0WzBdID0gYVswXSAqIGI7XG4gIG91dFsxXSA9IGFbMV0gKiBiO1xuICBvdXRbMl0gPSBhWzJdICogYjtcbiAgb3V0WzNdID0gYVszXSAqIGI7XG4gIG91dFs0XSA9IGFbNF0gKiBiO1xuICBvdXRbNV0gPSBhWzVdICogYjtcbiAgb3V0WzZdID0gYVs2XSAqIGI7XG4gIG91dFs3XSA9IGFbN10gKiBiO1xuICBvdXRbOF0gPSBhWzhdICogYjtcbiAgcmV0dXJuIG91dDtcbn1cbi8qKlxuICogQWRkcyB0d28gbWF0MydzIGFmdGVyIG11bHRpcGx5aW5nIGVhY2ggZWxlbWVudCBvZiB0aGUgc2Vjb25kIG9wZXJhbmQgYnkgYSBzY2FsYXIgdmFsdWUuXG4gKlxuICogQHBhcmFtIHttYXQzfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7UmVhZG9ubHlNYXQzfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge1JlYWRvbmx5TWF0M30gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEBwYXJhbSB7TnVtYmVyfSBzY2FsZSB0aGUgYW1vdW50IHRvIHNjYWxlIGIncyBlbGVtZW50cyBieSBiZWZvcmUgYWRkaW5nXG4gKiBAcmV0dXJucyB7bWF0M30gb3V0XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIG11bHRpcGx5U2NhbGFyQW5kQWRkKG91dCwgYSwgYiwgc2NhbGUpIHtcbiAgb3V0WzBdID0gYVswXSArIGJbMF0gKiBzY2FsZTtcbiAgb3V0WzFdID0gYVsxXSArIGJbMV0gKiBzY2FsZTtcbiAgb3V0WzJdID0gYVsyXSArIGJbMl0gKiBzY2FsZTtcbiAgb3V0WzNdID0gYVszXSArIGJbM10gKiBzY2FsZTtcbiAgb3V0WzRdID0gYVs0XSArIGJbNF0gKiBzY2FsZTtcbiAgb3V0WzVdID0gYVs1XSArIGJbNV0gKiBzY2FsZTtcbiAgb3V0WzZdID0gYVs2XSArIGJbNl0gKiBzY2FsZTtcbiAgb3V0WzddID0gYVs3XSArIGJbN10gKiBzY2FsZTtcbiAgb3V0WzhdID0gYVs4XSArIGJbOF0gKiBzY2FsZTtcbiAgcmV0dXJuIG91dDtcbn1cbi8qKlxuICogUmV0dXJucyB3aGV0aGVyIG9yIG5vdCB0aGUgbWF0cmljZXMgaGF2ZSBleGFjdGx5IHRoZSBzYW1lIGVsZW1lbnRzIGluIHRoZSBzYW1lIHBvc2l0aW9uICh3aGVuIGNvbXBhcmVkIHdpdGggPT09KVxuICpcbiAqIEBwYXJhbSB7UmVhZG9ubHlNYXQzfSBhIFRoZSBmaXJzdCBtYXRyaXguXG4gKiBAcGFyYW0ge1JlYWRvbmx5TWF0M30gYiBUaGUgc2Vjb25kIG1hdHJpeC5cbiAqIEByZXR1cm5zIHtCb29sZWFufSBUcnVlIGlmIHRoZSBtYXRyaWNlcyBhcmUgZXF1YWwsIGZhbHNlIG90aGVyd2lzZS5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gZXhhY3RFcXVhbHMoYSwgYikge1xuICByZXR1cm4gYVswXSA9PT0gYlswXSAmJiBhWzFdID09PSBiWzFdICYmIGFbMl0gPT09IGJbMl0gJiYgYVszXSA9PT0gYlszXSAmJiBhWzRdID09PSBiWzRdICYmIGFbNV0gPT09IGJbNV0gJiYgYVs2XSA9PT0gYls2XSAmJiBhWzddID09PSBiWzddICYmIGFbOF0gPT09IGJbOF07XG59XG4vKipcbiAqIFJldHVybnMgd2hldGhlciBvciBub3QgdGhlIG1hdHJpY2VzIGhhdmUgYXBwcm94aW1hdGVseSB0aGUgc2FtZSBlbGVtZW50cyBpbiB0aGUgc2FtZSBwb3NpdGlvbi5cbiAqXG4gKiBAcGFyYW0ge1JlYWRvbmx5TWF0M30gYSBUaGUgZmlyc3QgbWF0cml4LlxuICogQHBhcmFtIHtSZWFkb25seU1hdDN9IGIgVGhlIHNlY29uZCBtYXRyaXguXG4gKiBAcmV0dXJucyB7Qm9vbGVhbn0gVHJ1ZSBpZiB0aGUgbWF0cmljZXMgYXJlIGVxdWFsLCBmYWxzZSBvdGhlcndpc2UuXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGVxdWFscyhhLCBiKSB7XG4gIHZhciBhMCA9IGFbMF0sXG4gICAgICBhMSA9IGFbMV0sXG4gICAgICBhMiA9IGFbMl0sXG4gICAgICBhMyA9IGFbM10sXG4gICAgICBhNCA9IGFbNF0sXG4gICAgICBhNSA9IGFbNV0sXG4gICAgICBhNiA9IGFbNl0sXG4gICAgICBhNyA9IGFbN10sXG4gICAgICBhOCA9IGFbOF07XG4gIHZhciBiMCA9IGJbMF0sXG4gICAgICBiMSA9IGJbMV0sXG4gICAgICBiMiA9IGJbMl0sXG4gICAgICBiMyA9IGJbM10sXG4gICAgICBiNCA9IGJbNF0sXG4gICAgICBiNSA9IGJbNV0sXG4gICAgICBiNiA9IGJbNl0sXG4gICAgICBiNyA9IGJbN10sXG4gICAgICBiOCA9IGJbOF07XG4gIHJldHVybiBNYXRoLmFicyhhMCAtIGIwKSA8PSBnbE1hdHJpeC5FUFNJTE9OICogTWF0aC5tYXgoMS4wLCBNYXRoLmFicyhhMCksIE1hdGguYWJzKGIwKSkgJiYgTWF0aC5hYnMoYTEgLSBiMSkgPD0gZ2xNYXRyaXguRVBTSUxPTiAqIE1hdGgubWF4KDEuMCwgTWF0aC5hYnMoYTEpLCBNYXRoLmFicyhiMSkpICYmIE1hdGguYWJzKGEyIC0gYjIpIDw9IGdsTWF0cml4LkVQU0lMT04gKiBNYXRoLm1heCgxLjAsIE1hdGguYWJzKGEyKSwgTWF0aC5hYnMoYjIpKSAmJiBNYXRoLmFicyhhMyAtIGIzKSA8PSBnbE1hdHJpeC5FUFNJTE9OICogTWF0aC5tYXgoMS4wLCBNYXRoLmFicyhhMyksIE1hdGguYWJzKGIzKSkgJiYgTWF0aC5hYnMoYTQgLSBiNCkgPD0gZ2xNYXRyaXguRVBTSUxPTiAqIE1hdGgubWF4KDEuMCwgTWF0aC5hYnMoYTQpLCBNYXRoLmFicyhiNCkpICYmIE1hdGguYWJzKGE1IC0gYjUpIDw9IGdsTWF0cml4LkVQU0lMT04gKiBNYXRoLm1heCgxLjAsIE1hdGguYWJzKGE1KSwgTWF0aC5hYnMoYjUpKSAmJiBNYXRoLmFicyhhNiAtIGI2KSA8PSBnbE1hdHJpeC5FUFNJTE9OICogTWF0aC5tYXgoMS4wLCBNYXRoLmFicyhhNiksIE1hdGguYWJzKGI2KSkgJiYgTWF0aC5hYnMoYTcgLSBiNykgPD0gZ2xNYXRyaXguRVBTSUxPTiAqIE1hdGgubWF4KDEuMCwgTWF0aC5hYnMoYTcpLCBNYXRoLmFicyhiNykpICYmIE1hdGguYWJzKGE4IC0gYjgpIDw9IGdsTWF0cml4LkVQU0lMT04gKiBNYXRoLm1heCgxLjAsIE1hdGguYWJzKGE4KSwgTWF0aC5hYnMoYjgpKTtcbn1cbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayBtYXQzLm11bHRpcGx5fVxuICogQGZ1bmN0aW9uXG4gKi9cblxuZXhwb3J0IHZhciBtdWwgPSBtdWx0aXBseTtcbi8qKlxuICogQWxpYXMgZm9yIHtAbGluayBtYXQzLnN1YnRyYWN0fVxuICogQGZ1bmN0aW9uXG4gKi9cblxuZXhwb3J0IHZhciBzdWIgPSBzdWJ0cmFjdDsiLCJpbXBvcnQgeyB2ZWMzIH0gZnJvbSBcImdsLW1hdHJpeFwiO1xuXG4vLyBWZXJ0ZXggW3gsIHksIHpdXG50eXBlIFZlY3RvciA9IFtudW1iZXIsIG51bWJlciwgbnVtYmVyXTtcbi8vIFNvbWUgYWxpYXNlcyB3aGljaCBhcmUgdXNlZnVsIGZvciBkb2N1bWVudGF0aW9uXG4vLyBDb2xvciBbciwgZywgYl1cbnR5cGUgQ29sb3JWZWN0b3IgPSBWZWN0b3I7XG4vLyBQb2ludCAoeCwgeSwgeilcbnR5cGUgUG9pbnQgPSBWZWN0b3I7XG5cbmV4cG9ydCB0eXBlIE1hdGVyaWFsID0ge1xuICBhbWJpZW50OiBDb2xvclZlY3RvcjtcbiAgZGlmZnVzZTogQ29sb3JWZWN0b3I7XG4gIHNwZWN1bGFyOiBDb2xvclZlY3RvcjtcbiAgbjogbnVtYmVyO1xufTtcblxuZnVuY3Rpb24gcmdiKHI6IG51bWJlciwgZzogbnVtYmVyLCBiOiBudW1iZXIpOiBWZWN0b3Ige1xuICByZXR1cm4gW3IgLyAyNTUsIGcgLyAyNTUsIGIgLyAyNTVdO1xufVxuXG4vLyBEZXNjcmlwdGlvbiBvZiB0cmlhbmdsZSBKU09OLlxuLy9cbi8vIE5vdGU6IFRoZSBhcnJheXMgb2YgYGFtYmllbnRgLCBgZGlmZnVzZWAsIGBzcGVjdWxhcmAsIGFuZCBgdHJpYW5nbGVzYCBhbGxcbi8vIGhhdmUgdGhlIHNhbWUgbGVuZ3RoLlxuZXhwb3J0IHR5cGUgTW9kZWwgPSB7XG4gIG1hdGVyaWFsOiBNYXRlcmlhbDtcbiAgdmVydGljZXM6IEFycmF5PFBvaW50PjtcbiAgLy8gTnVtYmVycyBhcmUgaW50ZWdlciByZWZlcmVuY2VzIHRvIHZlcnRleGVzIHdpdGhpbiBgdmVydGljZXNgXG4gIHRyaWFuZ2xlczogQXJyYXk8W251bWJlciwgbnVtYmVyLCBudW1iZXJdPjtcbn07XG5cbi8vIENlbnRlciBtb2RlbCBvbiBvcmlnaW4uIFRoaXMgc2hvdWxkIGJlIGRvbmUgZm9yIGFsbCBtb2RlbHMgbm90IHRpZWQgdG9cbi8vIGFub3RoZXJcbmZ1bmN0aW9uIGNlbnRlcihtb2RlbDogTW9kZWwpOiBNb2RlbCB7XG4gIC8vIFByZXByb2Nlc3MgYWxsIHZlcnRleGVzIHNvIHRoZWlyIGNlbnRyb2lkIGlzIHRoZSBvcmlnaW5cbiAgbGV0IGNlbnRyb2lkID0gdmVjMy5jcmVhdGUoKTtcbiAgZm9yIChjb25zdCB2IG9mIG1vZGVsLnZlcnRpY2VzKSB7XG4gICAgdmVjMy5hZGQoY2VudHJvaWQsIGNlbnRyb2lkLCB2KTtcbiAgfVxuICB2ZWMzLnNjYWxlKGNlbnRyb2lkLCBjZW50cm9pZCwgMSAvIG1vZGVsLnZlcnRpY2VzLmxlbmd0aCk7XG4gIGZvciAoY29uc3QgdiBvZiBtb2RlbC52ZXJ0aWNlcykge1xuICAgIHZlYzMuc3VidHJhY3QodiwgdiwgY2VudHJvaWQpO1xuICB9XG4gIHJldHVybiBtb2RlbDtcbn1cblxuZnVuY3Rpb24gY3ViZShzaWRlTGVuOiBudW1iZXIsIG1hdGVyaWFsOiBNYXRlcmlhbCk6IE1vZGVsIHtcbiAgcmV0dXJuIGNlbnRlcih7XG4gICAgbWF0ZXJpYWw6IG1hdGVyaWFsLFxuICAgIHZlcnRpY2VzOiBbXG4gICAgICBbMCwgMCwgMF0sXG4gICAgICBbc2lkZUxlbiwgMCwgMF0sXG4gICAgICBbc2lkZUxlbiwgMCwgc2lkZUxlbl0sXG4gICAgICBbMCwgMCwgc2lkZUxlbl0sXG4gICAgICBbMCwgc2lkZUxlbiwgMF0sXG4gICAgICBbc2lkZUxlbiwgc2lkZUxlbiwgMF0sXG4gICAgICBbc2lkZUxlbiwgc2lkZUxlbiwgc2lkZUxlbl0sXG4gICAgICBbMCwgc2lkZUxlbiwgc2lkZUxlbl0sXG4gICAgXSxcbiAgICB0cmlhbmdsZXM6IFtcbiAgICAgIFswLCAxLCAyXSxcbiAgICAgIFsyLCAzLCAwXSxcbiAgICAgIFs0LCA1LCA2XSxcbiAgICAgIFs2LCA3LCA0XSxcbiAgICAgIFswLCAxLCA0XSxcbiAgICAgIFs0LCA1LCAxXSxcbiAgICAgIFsxLCAyLCA1XSxcbiAgICAgIFsyLCA1LCA2XSxcbiAgICAgIFsyLCAzLCA2XSxcbiAgICAgIFszLCA2LCA3XSxcbiAgICAgIFszLCAwLCA3XSxcbiAgICAgIFswLCA3LCA0XSxcbiAgICBdLFxuICB9KTtcbn1cblxuLy8gVGhpcyBtb2RpZmllcyBtb2RlbCBkaXJlY3RseVxuZnVuY3Rpb24gc2hpZnQobW9kZWw6IE1vZGVsLCB2ZWM6IFZlY3Rvcik6IE1vZGVsIHtcbiAgZm9yIChjb25zdCBpIGluIG1vZGVsLnZlcnRpY2VzKSB7XG4gICAgbW9kZWwudmVydGljZXNbaV1bMF0gKz0gdmVjWzBdO1xuICAgIG1vZGVsLnZlcnRpY2VzW2ldWzFdICs9IHZlY1sxXTtcbiAgICBtb2RlbC52ZXJ0aWNlc1tpXVsyXSArPSB2ZWNbMl07XG4gIH1cbiAgcmV0dXJuIG1vZGVsO1xufVxuXG5leHBvcnQgY29uc3QgU1VOX0NPTE9SOiBWZWN0b3IgPSByZ2IoMjUyLCAyMjksIDExMik7XG5leHBvcnQgY29uc3QgU1BBQ0VfQ09MT1I6IFZlY3RvciA9IHJnYigyOSwgMTcsIDUzKTtcblxuZXhwb3J0IGNvbnN0IFNVTl9TSURFX0xFTkdUSDogbnVtYmVyID0gMi4wO1xuZXhwb3J0IGNvbnN0IFNVTjogTW9kZWwgPSBjdWJlKFNVTl9TSURFX0xFTkdUSCwge1xuICBhbWJpZW50OiBTVU5fQ09MT1IsXG4gIGRpZmZ1c2U6IFswLjAsIDAuMCwgMC4wXSxcbiAgc3BlY3VsYXI6IFswLjAsIDAuMCwgMC4wXSxcbiAgbjogMTEsXG59KTtcblxuZXhwb3J0IGNvbnN0IERPVDogTW9kZWwgPSBjdWJlKDAuMSwge1xuICBhbWJpZW50OiBbMS4wLCAxLjAsIDEuMF0sXG4gIGRpZmZ1c2U6IFswLjAsIDAuMCwgMC4wXSxcbiAgc3BlY3VsYXI6IFswLjAsIDAuMCwgMC4wXSxcbiAgbjogMTEsXG59KTtcblxuZXhwb3J0IGNvbnN0IFNISVA6IE1vZGVsID0gY2VudGVyKHtcbiAgbWF0ZXJpYWw6IHtcbiAgICBhbWJpZW50OiBbMC4xMjUsIDAuMTI1LCAwLjEyNV0sXG4gICAgZGlmZnVzZTogWzAuMzI1LCAwLjMyNSwgMC4zMjVdLFxuICAgIHNwZWN1bGFyOiBbMC40NSwgMC40NSwgMC40NV0sXG4gICAgbjogMzEsXG4gIH0sXG4gIHZlcnRpY2VzOiBbXG4gICAgWzAuMCwgMC4wLCAwXSxcbiAgICBbMC4zLCAwLjYsIDBdLFxuICAgIFswLjYsIDAuMCwgMF0sXG4gICAgWzAuMywgMC4xNSwgMC4wOF0sXG4gICAgWzAuMywgMC4xNSwgLTAuMDhdLFxuICBdLFxuICB0cmlhbmdsZXM6IFtcbiAgICBbMCwgMSwgM10sXG4gICAgWzAsIDEsIDRdLFxuICAgIFswLCAzLCA0XSxcbiAgICBbMiwgMSwgM10sXG4gICAgWzIsIDEsIDRdLFxuICAgIFsyLCAzLCA0XSxcbiAgXSxcbn0pO1xuZXhwb3J0IGNvbnN0IFNISVBfTk9aWkxFOiB2ZWMzID0gU0hJUC52ZXJ0aWNlc1sxXTtcbmV4cG9ydCBjb25zdCBTSElQX0NPTExJU0lPTl9QT0lOVFM6IHZlYzNbXSA9IFNISVAudmVydGljZXMubWFwKCh2KSA9PiB2ZWMzLmZyb21WYWx1ZXMoLi4udikpO1xuXG5leHBvcnQgY29uc3QgU0hJUF9GTEFNRTogTW9kZWwgPSB7XG4gIG1hdGVyaWFsOiB7XG4gICAgYW1iaWVudDogcmdiKDIyNiwgODgsIDM0KSxcbiAgICBkaWZmdXNlOiBbMC4wLCAwLjAsIDAuMF0sXG4gICAgc3BlY3VsYXI6IFswLjAsIDAuMCwgMC4wXSxcbiAgICBuOiAxNyxcbiAgfSxcbiAgdmVydGljZXM6IFtcbiAgICBbNSAvIDMyLCAwLCAwXSxcbiAgICBbMCwgMCwgNSAvIDEyOF0sXG4gICAgWy01IC8gMzIsIDAsIDBdLFxuICAgIFswLCAwLCAtNSAvIDEyOF0sXG4gICAgWzAsIC0wLjQsIDBdLFxuICBdLFxuICB0cmlhbmdsZXM6IFtcbiAgICBbMCwgMSwgMl0sXG4gICAgWzIsIDMsIDBdLFxuICAgIFswLCAxLCA0XSxcbiAgICBbMSwgMiwgNF0sXG4gICAgWzIsIDMsIDRdLFxuICAgIFszLCAwLCA0XSxcbiAgXSxcbn07XG5cbmV4cG9ydCBjb25zdCBTSElQX0ZMQU1FX0FDQ0VOVDogTW9kZWwgPSB7XG4gIG1hdGVyaWFsOiB7XG4gICAgYW1iaWVudDogcmdiKDI1NSwgMjQ3LCAxMTApLFxuICAgIGRpZmZ1c2U6IFswLjAsIDAuMCwgMC4wXSxcbiAgICBzcGVjdWxhcjogWzAuMCwgMC4wLCAwLjBdLFxuICAgIG46IDE3LFxuICB9LFxuICB2ZXJ0aWNlczogW1xuICAgIFs0LjUgLyAzMiwgMCwgMF0sXG4gICAgWzAsIDAsIDYgLyAxMjhdLFxuICAgIFstNC41IC8gMzIsIDAsIDBdLFxuICAgIFswLCAwLCAtNiAvIDEyOF0sXG4gICAgWzAsIC0wLjM2LCAwXSxcbiAgXSxcbiAgdHJpYW5nbGVzOiBbXG4gICAgWzAsIDEsIDJdLFxuICAgIFsyLCAzLCAwXSxcbiAgICBbMCwgMSwgNF0sXG4gICAgWzEsIDIsIDRdLFxuICAgIFsyLCAzLCA0XSxcbiAgICBbMywgMCwgNF0sXG4gIF0sXG59O1xuXG5jb25zdCBSRVRJQ0xFX1M6IG51bWJlciA9IDAuMTtcbmNvbnN0IFJFVElDTEVfRElTVDogbnVtYmVyID0gMTA7XG5leHBvcnQgY29uc3QgU0hJUF9SRVRJQ0xFOiBNb2RlbCA9IHNoaWZ0KFxuICBjdWJlKFJFVElDTEVfUywge1xuICAgIGFtYmllbnQ6IHJnYigyNTUsIDI1NSwgMjU1KSxcbiAgICBkaWZmdXNlOiBbMC4wLCAwLjAsIDAuMF0sXG4gICAgc3BlY3VsYXI6IFswLjAsIDAuMCwgMC4wXSxcbiAgICBuOiAxMSxcbiAgfSksXG4gIFswLCBSRVRJQ0xFX0RJU1QsIDBdLFxuKTtcblxuZXhwb3J0IGNvbnN0IE1JU1NJTEU6IE1vZGVsID0gY2VudGVyKHtcbiAgbWF0ZXJpYWw6IHtcbiAgICBhbWJpZW50OiBbMS4wLCAwLjIsIDAuMl0sXG4gICAgZGlmZnVzZTogWzAuMCwgMC4wLCAwLjBdLFxuICAgIHNwZWN1bGFyOiBbMC4wLCAwLjAsIDAuMF0sXG4gICAgbjogMTEsXG4gIH0sXG4gIHZlcnRpY2VzOiBbXG4gICAgWzEgLyAzMiwgMC4wLCAwLjBdLFxuICAgIFswLjAsIDAuMCwgMSAvIDMyXSxcbiAgICBbLTEgLyAzMiwgMC4wLCAwLjBdLFxuICAgIFswLjAsIDAuMCwgLTEgLyAzMl0sXG4gICAgWzEgLyAzMiwgMC41LCAwLjBdLFxuICAgIFswLjAsIDAuNSwgMSAvIDMyXSxcbiAgICBbLTEgLyAzMiwgMC41LCAwLjBdLFxuICAgIFswLjAsIDAuNSwgLTEgLyAzMl0sXG4gIF0sXG4gIHRyaWFuZ2xlczogW1xuICAgIFswLCAxLCAyXSxcbiAgICBbMiwgMywgMF0sXG4gICAgWzQsIDUsIDZdLFxuICAgIFs2LCA3LCA0XSxcbiAgICBbMCwgMSwgNF0sXG4gICAgWzQsIDUsIDFdLFxuICAgIFsxLCAyLCA1XSxcbiAgICBbMiwgNSwgNl0sXG4gICAgWzIsIDMsIDZdLFxuICAgIFszLCA2LCA3XSxcbiAgICBbMywgMCwgN10sXG4gICAgWzAsIDcsIDRdLFxuICBdLFxufSk7XG5cbmV4cG9ydCBjb25zdCBBU1RFUk9JRF9DT0xPUjogVmVjdG9yID0gcmdiKDk5LCA3OCwgNjMpO1xuZXhwb3J0IGNvbnN0IEFTVEVST0lEX0RBTUFHRURfQ09MT1I6IFZlY3RvciA9IFsxLCAwLCAwXTtcblxuZnVuY3Rpb24gcmFuZGYobG86IG51bWJlciwgaGk6IG51bWJlcikge1xuICByZXR1cm4gKGhpIC0gbG8pICogTWF0aC5yYW5kb20oKSArIGxvO1xufVxuXG5leHBvcnQgY29uc3QgQVNURVJPSURfQU1CSUVOVF9TQ0FMQVI6IG51bWJlciA9IDAuNTtcbmV4cG9ydCBjb25zdCBBU1RFUk9JRF9ESUZGVVNFX1NDQUxBUjogbnVtYmVyID0gMS4wO1xuY29uc3QgQVNURVJPSURfTUFURVJJQUwgPSB7XG4gIGFtYmllbnQ6IDxWZWN0b3I+QVNURVJPSURfQ09MT1IubWFwKCh4KSA9PiB4ICogQVNURVJPSURfQU1CSUVOVF9TQ0FMQVIpLFxuICBkaWZmdXNlOiA8VmVjdG9yPkFTVEVST0lEX0NPTE9SLm1hcCgoeCkgPT4geCAqIEFTVEVST0lEX0RJRkZVU0VfU0NBTEFSKSxcbiAgc3BlY3VsYXI6IFswLjAsIDAuMCwgMC4wXSxcbiAgbjogMTEsXG59O1xuXG5leHBvcnQgZnVuY3Rpb24gcmFuZG9tQXN0ZXJvaWQocmFkaXVzOiBudW1iZXIpOiBbbnVtYmVyLCBNb2RlbF0ge1xuICBsZXQgc2lkZUxlbmd0aCA9IHJhZGl1cyAqICgyIC8gTWF0aC5zcXJ0KDMpKTtcbiAgbGV0IHRlbXBsYXRlID0gW1xuICAgIFswLCAwLCAwXSxcbiAgICBbc2lkZUxlbmd0aCwgMCwgMF0sXG4gICAgW3NpZGVMZW5ndGgsIDAsIHNpZGVMZW5ndGhdLFxuICAgIFswLCAwLCBzaWRlTGVuZ3RoXSxcbiAgICBbMCwgc2lkZUxlbmd0aCwgMF0sXG4gICAgW3NpZGVMZW5ndGgsIHNpZGVMZW5ndGgsIDBdLFxuICAgIFtzaWRlTGVuZ3RoLCBzaWRlTGVuZ3RoLCBzaWRlTGVuZ3RoXSxcbiAgICBbMCwgc2lkZUxlbmd0aCwgc2lkZUxlbmd0aF0sXG4gIF07XG5cbiAgbGV0IHZlcnRleGVzOiBWZWN0b3JbXSA9IHRlbXBsYXRlLm1hcCgodikgPT4ge1xuICAgIGxldCBkaXNwID0gdmVjMy5yYW5kb20odmVjMy5jcmVhdGUoKSwgcmFuZGYoMCwgc2lkZUxlbmd0aCAvIDIpKTtcbiAgICByZXR1cm4gW3ZbMF0gKyBkaXNwWzBdLCB2WzFdICsgZGlzcFsxXSwgdlsyXSArIGRpc3BbMl1dO1xuICB9KTtcblxuICBsZXQgYXN0ZXJvaWQgPSBjZW50ZXIoe1xuICAgIC8vIERlZXAgY2xvbmUgdGhlIG1hdGVyaWFsIHNpbmNlIHdlIG1vZGlmeSB0aGUgY29sb3IgbGF0ZXJcbiAgICBtYXRlcmlhbDogSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeShBU1RFUk9JRF9NQVRFUklBTCkpLFxuICAgIHZlcnRpY2VzOiB2ZXJ0ZXhlcyxcbiAgICB0cmlhbmdsZXM6IFtcbiAgICAgIFswLCAxLCAyXSxcbiAgICAgIFsyLCAzLCAwXSxcbiAgICAgIFs0LCA1LCA2XSxcbiAgICAgIFs2LCA3LCA0XSxcbiAgICAgIFswLCAxLCA0XSxcbiAgICAgIFs0LCA1LCAxXSxcbiAgICAgIFsxLCAyLCA1XSxcbiAgICAgIFsyLCA1LCA2XSxcbiAgICAgIFsyLCAzLCA2XSxcbiAgICAgIFszLCA2LCA3XSxcbiAgICAgIFszLCAwLCA3XSxcbiAgICAgIFswLCA3LCA0XSxcbiAgICBdLFxuICB9KTtcblxuICBsZXQgYXZnUmFkaXVzID0gMC4wO1xuICBmb3IgKGNvbnN0IHYgb2YgYXN0ZXJvaWQudmVydGljZXMpIHtcbiAgICBhdmdSYWRpdXMgKz0gTWF0aC5oeXBvdCguLi52KTtcbiAgfVxuICBhdmdSYWRpdXMgLz0gYXN0ZXJvaWQudmVydGljZXMubGVuZ3RoO1xuXG4gIHJldHVybiBbYXZnUmFkaXVzLCBhc3Rlcm9pZF07XG59XG4iLCJpbXBvcnQgeyB2ZWMzLCBtYXQ0IH0gZnJvbSBcImdsLW1hdHJpeFwiO1xuXG5pbXBvcnQgKiBhcyBtb2RlbHMgZnJvbSBcIi4vbW9kZWxzXCI7XG5pbXBvcnQgeyBNb2RlbCB9IGZyb20gXCIuL21vZGVsc1wiO1xuXG5leHBvcnQgY29uc3QgTlVNX1NVTlM6IG51bWJlciA9IDQ7XG5cbmV4cG9ydCBjb25zdCBGT0dfU1RBUlQgPSAyNDtcbmV4cG9ydCBjb25zdCBGT0dfRU5EID0gMzI7XG5leHBvcnQgY29uc3QgRk9HX0NPTE9SID0gbW9kZWxzLlNQQUNFX0NPTE9SO1xuXG5leHBvcnQgY2xhc3MgU2NlbmVPYmplY3Qge1xuICAvLyB0aGlzIGNvbnRhaW5zIHZlcnRleCBjb29yZGluYXRlcyBpbiB0cmlwbGVzXG4gIHB1YmxpYyB2ZXJ0ZXhQb3NCdWZmZXI6IFdlYkdMQnVmZmVyO1xuICAvLyB0aGlzIGNvbnRhaW5zIGluZGljZXMgaW50byB2ZXJ0ZXhCdWZmZXIgaW4gdHJpcGxlc1xuICBwdWJsaWMgdHJpYW5nbGVCdWZmZXI6IFdlYkdMQnVmZmVyO1xuICAvLyB0aGUgbnVtYmVyIG9mIGluZGljZXMgaW4gdGhlIHRyaWFuZ2xlIGJ1ZmZlclxuICBwdWJsaWMgdHJpYW5nbGVCdWZmZXJTaXplOiBudW1iZXI7XG4gIC8vIFRoZSBpbnB1dCBtb2RlbCB0aGlzIHNjZW5lIGNvbWVzIGZyb21cbiAgcHVibGljIG1vZGVsOiBNb2RlbDtcbiAgLy8gTW9kZWwgdHJhbnNmb3Jtc1xuICBwdWJsaWMgdmVydGV4VHJhbnNmb3JtOiBtYXQ0O1xuXG4gIGNvbnN0cnVjdG9yKGdsOiBXZWJHTFJlbmRlcmluZ0NvbnRleHQsIG1vZGVsOiBNb2RlbCwgdmVydGV4VHJhbnNmb3JtOiBtYXQ0ID0gbWF0NC5jcmVhdGUoKSkge1xuICAgIC8vIFNlbmQgdmVydGV4IHBvc2l0aW9ucyB0byB3ZWJnbFxuICAgIGxldCB2ZXJ0ZXhQb3NBcnJheSA9IG1vZGVsLnZlcnRpY2VzLmZsYXQoKTtcbiAgICBsZXQgdmVydGV4UG9zQnVmZmVyID0gZ2wuY3JlYXRlQnVmZmVyKCk7XG4gICAgaWYgKHZlcnRleFBvc0J1ZmZlciA9PSBudWxsKSB7XG4gICAgICB0aHJvdyBcImNvdWxkIG5vdCBjcmVhdGUgd2ViZ2wgYnVmZmVyXCI7XG4gICAgfVxuICAgIGdsLmJpbmRCdWZmZXIoZ2wuQVJSQVlfQlVGRkVSLCB2ZXJ0ZXhQb3NCdWZmZXIpO1xuICAgIGdsLmJ1ZmZlckRhdGEoZ2wuQVJSQVlfQlVGRkVSLCBuZXcgRmxvYXQzMkFycmF5KHZlcnRleFBvc0FycmF5KSwgZ2wuU1RBVElDX0RSQVcpO1xuXG4gICAgLy8gU2VuZCB0aGUgdHJpYW5nbGUgaW5kZXhlcyB0byB3ZWJnbFxuICAgIGxldCB0cmlhbmdsZUFycmF5ID0gbW9kZWwudHJpYW5nbGVzLmZsYXQoKTtcbiAgICBsZXQgdHJpYW5nbGVCdWZmZXIgPSBnbC5jcmVhdGVCdWZmZXIoKTtcbiAgICBpZiAodHJpYW5nbGVCdWZmZXIgPT0gbnVsbCkge1xuICAgICAgdGhyb3cgXCJjb3VsZCBub3QgY3JlYXRlIHdlYmdsIGJ1ZmZlclwiO1xuICAgIH1cbiAgICBnbC5iaW5kQnVmZmVyKGdsLkVMRU1FTlRfQVJSQVlfQlVGRkVSLCB0cmlhbmdsZUJ1ZmZlcik7XG4gICAgZ2wuYnVmZmVyRGF0YShnbC5FTEVNRU5UX0FSUkFZX0JVRkZFUiwgbmV3IFVpbnQxNkFycmF5KHRyaWFuZ2xlQXJyYXkpLCBnbC5TVEFUSUNfRFJBVyk7XG5cbiAgICB0aGlzLnZlcnRleFBvc0J1ZmZlciA9IHZlcnRleFBvc0J1ZmZlcjtcbiAgICB0aGlzLnRyaWFuZ2xlQnVmZmVyID0gdHJpYW5nbGVCdWZmZXI7XG4gICAgdGhpcy50cmlhbmdsZUJ1ZmZlclNpemUgPSB0cmlhbmdsZUFycmF5Lmxlbmd0aDtcbiAgICB0aGlzLm1vZGVsID0gbW9kZWw7XG4gICAgdGhpcy52ZXJ0ZXhUcmFuc2Zvcm0gPSB2ZXJ0ZXhUcmFuc2Zvcm07XG4gIH1cblxuICB0cmFuc2xhdGUodjogdmVjMykge1xuICAgIG1hdDQubXVsdGlwbHkoXG4gICAgICB0aGlzLnZlcnRleFRyYW5zZm9ybSxcbiAgICAgIG1hdDQuZnJvbVRyYW5zbGF0aW9uKG1hdDQuY3JlYXRlKCksIHYpLFxuICAgICAgdGhpcy52ZXJ0ZXhUcmFuc2Zvcm0sXG4gICAgKTtcbiAgfVxuXG4gIHJvdGF0ZShyYWRzOiBudW1iZXIpIHtcbiAgICBtYXQ0LnJvdGF0ZVoodGhpcy52ZXJ0ZXhUcmFuc2Zvcm0sIHRoaXMudmVydGV4VHJhbnNmb3JtLCByYWRzKTtcbiAgfVxuXG4gIHBvcygpOiB2ZWMzIHtcbiAgICByZXR1cm4gbWF0NC5nZXRUcmFuc2xhdGlvbih2ZWMzLmNyZWF0ZSgpLCB0aGlzLnZlcnRleFRyYW5zZm9ybSk7XG4gIH1cbn1cblxuY29uc3QgU0hBREVSX0FUVFJJQlVURVMgPSBbXCJhVmVydGV4UG9zXCJdO1xuY29uc3QgU0hBREVSX1VOSUZPUk1TID0gW1xuICBcInVWaWV3aW5nVHJhbnNmb3JtXCIsXG4gIFwidVBlcnNwZWN0aXZlVHJhbnNmb3JtXCIsXG4gIFwidVZlcnRleFRyYW5zZm9ybVwiLFxuICBcInVMaWdodHNcIixcbiAgXCJ1TnVtTGlnaHRzXCIsXG4gIFwidUV5ZVBvc1wiLFxuICBcInVGb2dcIixcblxuICBcInVNYXRlcmlhbC5hbWJpZW50XCIsXG4gIFwidU1hdGVyaWFsLmRpZmZ1c2VcIixcbiAgXCJ1TWF0ZXJpYWwuc3BlY3VsYXJcIixcbiAgXCJ1TWF0ZXJpYWwuc2hpbmVcIixcbl07XG5cbmV4cG9ydCB0eXBlIFNoYWRlckF0dHJpYnV0ZXMgPSB7XG4gIGF0dHJpYnM6IHtcbiAgICBhVmVydGV4UG9zOiBudW1iZXI7XG4gIH07XG4gIHVuaWZvcm1zOiB7XG4gICAgdVZpZXdpbmdUcmFuc2Zvcm06IFdlYkdMVW5pZm9ybUxvY2F0aW9uO1xuICAgIHVQZXJzcGVjdGl2ZVRyYW5zZm9ybTogV2ViR0xVbmlmb3JtTG9jYXRpb247XG4gICAgdVZlcnRleFRyYW5zZm9ybTogV2ViR0xVbmlmb3JtTG9jYXRpb247XG4gICAgdUxpZ2h0czogV2ViR0xVbmlmb3JtTG9jYXRpb247XG4gICAgdU51bUxpZ2h0czogV2ViR0xVbmlmb3JtTG9jYXRpb247XG4gICAgdUV5ZVBvczogV2ViR0xVbmlmb3JtTG9jYXRpb247XG4gICAgdUZvZzogV2ViR0xVbmlmb3JtTG9jYXRpb247XG5cbiAgICBcInVNYXRlcmlhbC5hbWJpZW50XCI6IFdlYkdMVW5pZm9ybUxvY2F0aW9uO1xuICAgIFwidU1hdGVyaWFsLmRpZmZ1c2VcIjogV2ViR0xVbmlmb3JtTG9jYXRpb247XG4gICAgXCJ1TWF0ZXJpYWwuc3BlY3VsYXJcIjogV2ViR0xVbmlmb3JtTG9jYXRpb247XG4gICAgXCJ1TWF0ZXJpYWwuc2hpbmVcIjogV2ViR0xVbmlmb3JtTG9jYXRpb247XG5cbiAgICB1U2FtcGxlcjogV2ViR0xVbmlmb3JtTG9jYXRpb247XG4gIH07XG59O1xuXG5leHBvcnQgZnVuY3Rpb24gaW5pdFdlYmdsKGNhbnZhczogSFRNTENhbnZhc0VsZW1lbnQpOiBXZWJHTFJlbmRlcmluZ0NvbnRleHQge1xuICBsZXQgZ2wgPSBjYW52YXMuZ2V0Q29udGV4dChcIndlYmdsXCIpO1xuICBpZiAoZ2wgPT0gbnVsbCkge1xuICAgIHRocm93IFwidW5hYmxlIHRvIGNyZWF0ZSBnbCBjb250ZXh0IC0tIGlzIHlvdXIgYnJvd3NlciBnbCByZWFkeT9cIjtcbiAgfVxuXG4gIC8vIHVzZSBtYXggd2hlbiB3ZSBjbGVhciB0aGUgZGVwdGggYnVmZmVyXG4gIGdsLmNsZWFyRGVwdGgoMS4wKTtcbiAgZ2wuY2xlYXJDb2xvciguLi5tb2RlbHMuU1BBQ0VfQ09MT1IsIDEpO1xuICAvLyB1c2UgaGlkZGVuIHN1cmZhY2UgcmVtb3ZhbCAod2l0aCB6YnVmZmVyaW5nKVxuICBnbC5lbmFibGUoZ2wuREVQVEhfVEVTVCk7XG5cbiAgLy8gV2UgbXVzdCBlbmFibGUgYmxlbmRpbmcgc28gdGhhdCB3ZSBzZWUgdGhlIG9iamVjdHMgYmVoaW5kIHVzXG5cbiAgcmV0dXJuIGdsO1xufVxuXG4vLyBzZXR1cCB0aGUgd2ViR0wgc2hhZGVyc1xuZXhwb3J0IGZ1bmN0aW9uIHNldHVwU2hhZGVycyhnbDogV2ViR0xSZW5kZXJpbmdDb250ZXh0KTogU2hhZGVyQXR0cmlidXRlcyB7XG4gIGdsLmdldEV4dGVuc2lvbihcIk9FU19zdGFuZGFyZF9kZXJpdmF0aXZlc1wiKTtcblxuICBsZXQgdlNoYWRlckNvZGUgPSBgXG5wcmVjaXNpb24gaGlnaHAgZmxvYXQ7XG5cbnVuaWZvcm0gbWF0NCB1Vmlld2luZ1RyYW5zZm9ybTtcbnVuaWZvcm0gbWF0NCB1UGVyc3BlY3RpdmVUcmFuc2Zvcm07XG5cbnVuaWZvcm0gbWF0NCB1VmVydGV4VHJhbnNmb3JtO1xuXG5hdHRyaWJ1dGUgdmVjMyBhVmVydGV4UG9zO1xudmFyeWluZyB2ZWM0IHZTdXJmYWNlUG9zO1xuXG52b2lkIG1haW4odm9pZCkge1xuICB2U3VyZmFjZVBvcyA9IHVWZXJ0ZXhUcmFuc2Zvcm0gKiB2ZWM0KGFWZXJ0ZXhQb3MsIDEuMCk7XG5cbiAgZ2xfUG9zaXRpb24gPSB1UGVyc3BlY3RpdmVUcmFuc2Zvcm0gKiB1Vmlld2luZ1RyYW5zZm9ybSAqIHZTdXJmYWNlUG9zO1xufVxuYDtcblxuICAvLyBjcmVhdGUgdmVydGV4IHNoYWRlclxuICBsZXQgdlNoYWRlciA9IGdsLmNyZWF0ZVNoYWRlcihnbC5WRVJURVhfU0hBREVSKTtcbiAgaWYgKHZTaGFkZXIgPT0gbnVsbCkge1xuICAgIHRocm93IFwiY291bGQgbm90IGNyZWF0ZSB3ZWJnbCBzaGFkZXJcIjtcbiAgfVxuICBnbC5zaGFkZXJTb3VyY2UodlNoYWRlciwgdlNoYWRlckNvZGUpO1xuICBnbC5jb21waWxlU2hhZGVyKHZTaGFkZXIpO1xuICBpZiAoIWdsLmdldFNoYWRlclBhcmFtZXRlcih2U2hhZGVyLCBnbC5DT01QSUxFX1NUQVRVUykpIHtcbiAgICB0aHJvdyBcImVycm9yIGR1cmluZyB2ZXJ0ZXggc2hhZGVyIGNvbXBpbGU6IFwiICsgZ2wuZ2V0U2hhZGVySW5mb0xvZyh2U2hhZGVyKTtcbiAgfVxuXG4gIGxldCBmU2hhZGVyQ29kZSA9IGBcbiNleHRlbnNpb24gR0xfT0VTX3N0YW5kYXJkX2Rlcml2YXRpdmVzIDogZW5hYmxlXG5cbnByZWNpc2lvbiBoaWdocCBmbG9hdDtcblxuY29uc3QgaW50IE5VTV9TVU5TID0gJHtOVU1fU1VOU307XG5jb25zdCBmbG9hdCBGT0dfU1RBUlQgPSAke0ZPR19TVEFSVC50b0ZpeGVkKDEwKX07XG5jb25zdCBmbG9hdCBGT0dfRU5EID0gJHtGT0dfRU5ELnRvRml4ZWQoMTApfTtcbmNvbnN0IHZlYzMgRk9HX0NPTE9SID0gdmVjMygke0ZPR19DT0xPUlswXX0sICR7Rk9HX0NPTE9SWzFdfSwgJHtGT0dfQ09MT1JbMl19KTtcblxudW5pZm9ybSB2ZWMzIHVMaWdodHNbTlVNX1NVTlNdO1xudW5pZm9ybSBpbnQgdU51bUxpZ2h0cztcbnVuaWZvcm0gdmVjMyB1RXllUG9zO1xudW5pZm9ybSBpbnQgdUZvZztcblxuc3RydWN0IE1hdGVyaWFsIHtcbiAgdmVjMyBhbWJpZW50O1xuICB2ZWMzIGRpZmZ1c2U7XG4gIHZlYzMgc3BlY3VsYXI7XG4gIGZsb2F0IHNoaW5lO1xufTtcblxudW5pZm9ybSBNYXRlcmlhbCB1TWF0ZXJpYWw7XG5cbnZhcnlpbmcgdmVjNCB2U3VyZmFjZVBvcztcblxuLy8gVGhlIGZ1bmN0aW9uIDEgLyAoMSArIDAuMDAyeF4zKSA9PSAwLjUgYXQgNy45MzdcbmZsb2F0IGF0dGVudWF0aW9uKGZsb2F0IHgpIHtcbiAgaWYgKHggPCA4LjApIHtcbiAgICByZXR1cm4gMS4wO1xuICB9IGVsc2Uge1xuICAgIHggLT0gOC4wO1xuICAgIGZsb2F0IGEgPSAxLjAgLyAoMS4wICsgMC4wNSp4ICsgMC4wMDQqeCp4KngpO1xuICAgIHJldHVybiBjbGFtcChhLCAwLjAsIDEuMCk7XG4gIH1cbn1cblxudm9pZCBtYWluKHZvaWQpIHtcbiAgdmVjMyBjb2xvciA9IHVNYXRlcmlhbC5hbWJpZW50O1xuXG4gIHZlYzMgdmlld1ZlY3RvciA9IG5vcm1hbGl6ZSh1RXllUG9zIC0gdlN1cmZhY2VQb3MueHl6KTtcbiAgdmVjMyBub3JtYWxWZWN0b3IgPSBub3JtYWxpemUoY3Jvc3MoXG4gICAgZEZkeCh2U3VyZmFjZVBvcy54eXopLFxuICAgIGRGZHkodlN1cmZhY2VQb3MueHl6KVxuICApKTtcblxuICBmb3IgKGludCBpID0gMDsgaSA8IE5VTV9TVU5TOyBpKyspIHtcbiAgICBpZiAoaSA+PSB1TnVtTGlnaHRzKSB7XG4gICAgICBicmVhaztcbiAgICB9XG5cbiAgICB2ZWMzIGxpZ2h0VmVjdG9yID0gbm9ybWFsaXplKHVMaWdodHNbaV0gLSB2U3VyZmFjZVBvcy54eXopO1xuICAgIHZlYzMgaGFsZlZlY3RvciA9IG5vcm1hbGl6ZSh2aWV3VmVjdG9yICsgbGlnaHRWZWN0b3IpO1xuXG4gICAgZmxvYXQgbGlnaHREaXN0ID0gbGVuZ3RoKHVMaWdodHNbaV0gLSB2U3VyZmFjZVBvcy54eXopO1xuICAgIGZsb2F0IGF0dGVuID0gYXR0ZW51YXRpb24obGlnaHREaXN0KTtcblxuICAgIHZlYzMgZGlmZnVzZSA9IGF0dGVuICogdU1hdGVyaWFsLmRpZmZ1c2UgKiBtYXgoMC4wLCBkb3Qobm9ybWFsVmVjdG9yLCBsaWdodFZlY3RvcikpO1xuICAgIHZlYzMgc3BlY3VsYXIgPSBhdHRlbiAqIHVNYXRlcmlhbC5zcGVjdWxhciAqIHBvdyhtYXgoMC4wLCBkb3Qobm9ybWFsVmVjdG9yLCBoYWxmVmVjdG9yKSksIHVNYXRlcmlhbC5zaGluZSk7XG4gICAgY29sb3IgKz0gZGlmZnVzZSArIHNwZWN1bGFyO1xuICB9XG5cbiAgZmxvYXQgZm9nRmFjdG9yID0gMC4wO1xuICBpZiAodUZvZyA9PSAxKSB7XG4gICAgZmxvYXQgZGlzdCA9IGxlbmd0aCh1RXllUG9zIC0gdlN1cmZhY2VQb3MueHl6KTtcbiAgICBmb2dGYWN0b3IgPSBtaW4oMS4wLCBtYXgoMC4wLCBkaXN0IC0gRk9HX1NUQVJUKSAvIChGT0dfRU5EIC0gRk9HX1NUQVJUKSk7XG4gIH1cblxuICBnbF9GcmFnQ29sb3IgPSB2ZWM0KG1peChjb2xvciwgRk9HX0NPTE9SLCBmb2dGYWN0b3IpLCAxLjApO1xufVxuYDtcblxuICAvLyBjcmVhdGUgZnJhZyBzaGFkZXJcbiAgbGV0IGZTaGFkZXIgPSBnbC5jcmVhdGVTaGFkZXIoZ2wuRlJBR01FTlRfU0hBREVSKTtcbiAgaWYgKGZTaGFkZXIgPT0gbnVsbCkge1xuICAgIHRocm93IFwiY291bGQgbm90IGNyZWF0ZSB3ZWJnbCBzaGFkZXJcIjtcbiAgfVxuICBnbC5zaGFkZXJTb3VyY2UoZlNoYWRlciwgZlNoYWRlckNvZGUpO1xuICBnbC5jb21waWxlU2hhZGVyKGZTaGFkZXIpO1xuICBpZiAoIWdsLmdldFNoYWRlclBhcmFtZXRlcihmU2hhZGVyLCBnbC5DT01QSUxFX1NUQVRVUykpIHtcbiAgICB0aHJvdyBcImVycm9yIGR1cmluZyBmcmFnbWVudCBzaGFkZXIgY29tcGlsZTogXCIgKyBnbC5nZXRTaGFkZXJJbmZvTG9nKGZTaGFkZXIpO1xuICB9XG5cbiAgLy8gY3JlYXRlIHRoZSBzaW5nbGUgc2hhZGVyIHByb2dyYW1cbiAgbGV0IHNoYWRlclByb2dyYW0gPSBnbC5jcmVhdGVQcm9ncmFtKCk7XG4gIGlmIChzaGFkZXJQcm9ncmFtID09IG51bGwpIHtcbiAgICB0aHJvdyBcImNvdWxkIG5vdCBjcmVhdGUgd2ViZ2wgcHJvZ3JhbVwiO1xuICB9XG4gIGdsLmF0dGFjaFNoYWRlcihzaGFkZXJQcm9ncmFtLCBmU2hhZGVyKTtcbiAgZ2wuYXR0YWNoU2hhZGVyKHNoYWRlclByb2dyYW0sIHZTaGFkZXIpO1xuICBnbC5saW5rUHJvZ3JhbShzaGFkZXJQcm9ncmFtKTtcblxuICBpZiAoIWdsLmdldFByb2dyYW1QYXJhbWV0ZXIoc2hhZGVyUHJvZ3JhbSwgZ2wuTElOS19TVEFUVVMpKSB7XG4gICAgdGhyb3cgXCJlcnJvciBkdXJpbmcgc2hhZGVyIHByb2dyYW0gbGlua2luZzogXCIgKyBnbC5nZXRQcm9ncmFtSW5mb0xvZyhzaGFkZXJQcm9ncmFtKTtcbiAgfVxuXG4gIGdsLnVzZVByb2dyYW0oc2hhZGVyUHJvZ3JhbSk7XG5cbiAgbGV0IHNoYWRlckF0dHJpYnV0ZXMgPSB7XG4gICAgYXR0cmliczoge30sXG4gICAgdW5pZm9ybXM6IHt9LFxuICB9O1xuXG4gIGZvciAoY29uc3QgbmFtZSBvZiBTSEFERVJfQVRUUklCVVRFUykge1xuICAgIGxldCBhdHRyaWIgPSBnbC5nZXRBdHRyaWJMb2NhdGlvbihzaGFkZXJQcm9ncmFtLCBuYW1lKTtcbiAgICBpZiAoYXR0cmliID09IC0xKSB7XG4gICAgICB0aHJvdyBgaW52YWxpZCBhdHRyaWJ1dGUgJHtuYW1lfWA7XG4gICAgfVxuICAgIGdsLmVuYWJsZVZlcnRleEF0dHJpYkFycmF5KGF0dHJpYik7XG4gICAgc2hhZGVyQXR0cmlidXRlcy5hdHRyaWJzW25hbWVdID0gYXR0cmliO1xuICB9XG5cbiAgZm9yIChjb25zdCBuYW1lIG9mIFNIQURFUl9VTklGT1JNUykge1xuICAgIGxldCB1bmlmb3JtID0gZ2wuZ2V0VW5pZm9ybUxvY2F0aW9uKHNoYWRlclByb2dyYW0sIG5hbWUpO1xuICAgIHNoYWRlckF0dHJpYnV0ZXMudW5pZm9ybXNbbmFtZV0gPSB1bmlmb3JtO1xuICB9XG5cbiAgcmV0dXJuIHNoYWRlckF0dHJpYnV0ZXMgYXMgU2hhZGVyQXR0cmlidXRlcztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDYW1lcmEge1xuICBleWU6IHZlYzM7XG4gIHZpZXdpbmdUcmFuc2Zvcm06IG1hdDQ7XG4gIHBlcnNwZWN0aXZlVHJhbnNmb3JtOiBtYXQ0O1xufVxuXG4vLyBUT0RPOiBKdXN0IHVzZSBhcnJheSByYXRoZXIgdGhhbiBpdGVyYWJsZT9cbmV4cG9ydCBmdW5jdGlvbiByZW5kZXIoXG4gIGdsOiBXZWJHTFJlbmRlcmluZ0NvbnRleHQsXG4gIGxpZ2h0czogSXRlcmFibGU8dmVjMz4sXG4gIG9iamVjdHM6IEl0ZXJhYmxlPFNjZW5lT2JqZWN0PixcbiAgZnJvbnRPYmplY3RzOiBJdGVyYWJsZTxTY2VuZU9iamVjdD4sXG4gIHNoYWRlckluZm86IFNoYWRlckF0dHJpYnV0ZXMsXG4gIGNhbWVyYTogQ2FtZXJhLFxuICBvcHRzPzoge1xuICAgIGZvZzogYm9vbGVhbjtcbiAgfSxcbikge1xuICBpZiAob3B0cyA9PSB1bmRlZmluZWQpIHtcbiAgICBvcHRzID0geyBmb2c6IHRydWUgfTtcbiAgfVxuXG4gIC8vIGNsZWFyIGZyYW1lL2RlcHRoIGJ1ZmZlcnNcbiAgZ2wuY2xlYXIoZ2wuQ09MT1JfQlVGRkVSX0JJVCB8IGdsLkRFUFRIX0JVRkZFUl9CSVQpO1xuXG4gIGZ1bmN0aW9uIGJpbmRCdWZmZXJUbyhidWZmZXI6IFdlYkdMQnVmZmVyLCBhdHRyaWI6IEdMdWludCwgc2l6ZTogbnVtYmVyKSB7XG4gICAgZ2wuYmluZEJ1ZmZlcihnbC5BUlJBWV9CVUZGRVIsIGJ1ZmZlcik7XG4gICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcihcbiAgICAgIGF0dHJpYixcbiAgICAgIHNpemUsIC8vIHNpemVcbiAgICAgIGdsLkZMT0FULCAvLyB0eXBlXG4gICAgICBmYWxzZSwgLy8gbm9ybWFsaXplZFxuICAgICAgMCwgLy8gc3RyaWRlXG4gICAgICAwLCAvLyBvZmZzZXRcbiAgICApO1xuICB9XG5cbiAgbGV0IGxpZ2h0c0FycjogbnVtYmVyW10gPSBbXTtcbiAgbGV0IG51bUxpZ2h0czogbnVtYmVyID0gMDtcbiAgZm9yIChsZXQgbGlnaHRQb3Mgb2YgbGlnaHRzKSB7XG4gICAgbGlnaHRzQXJyLnB1c2goLi4ubGlnaHRQb3MpO1xuICAgIG51bUxpZ2h0cyArPSAxO1xuICB9XG4gIGdsLnVuaWZvcm0zZnYoc2hhZGVySW5mby51bmlmb3Jtcy51TGlnaHRzLCBsaWdodHNBcnIpO1xuICBnbC51bmlmb3JtMWkoc2hhZGVySW5mby51bmlmb3Jtcy51TnVtTGlnaHRzLCBudW1MaWdodHMpO1xuXG4gIGdsLnVuaWZvcm0xaShzaGFkZXJJbmZvLnVuaWZvcm1zLnVGb2csIG9wdHMuZm9nID8gMSA6IDApO1xuXG4gIC8vIFRoZXNlIHVuaWZvcm1zIGRvbid0IGNoYW5nZSBhY3Jvc3MgdGhlIG1vZGVsc1xuICBnbC51bmlmb3JtM2Z2KHNoYWRlckluZm8udW5pZm9ybXMudUV5ZVBvcywgY2FtZXJhLmV5ZSk7XG5cbiAgZ2wudW5pZm9ybU1hdHJpeDRmdihzaGFkZXJJbmZvLnVuaWZvcm1zLnVWaWV3aW5nVHJhbnNmb3JtLCBmYWxzZSwgY2FtZXJhLnZpZXdpbmdUcmFuc2Zvcm0pO1xuICBnbC51bmlmb3JtTWF0cml4NGZ2KFxuICAgIHNoYWRlckluZm8udW5pZm9ybXMudVBlcnNwZWN0aXZlVHJhbnNmb3JtLFxuICAgIGZhbHNlLFxuICAgIGNhbWVyYS5wZXJzcGVjdGl2ZVRyYW5zZm9ybSxcbiAgKTtcblxuICBmdW5jdGlvbiBkcmF3T2JqZWN0KG9iajogU2NlbmVPYmplY3QpIHtcbiAgICBiaW5kQnVmZmVyVG8ob2JqLnZlcnRleFBvc0J1ZmZlciwgc2hhZGVySW5mby5hdHRyaWJzLmFWZXJ0ZXhQb3MsIDMpO1xuXG4gICAgZ2wudW5pZm9ybU1hdHJpeDRmdihzaGFkZXJJbmZvLnVuaWZvcm1zLnVWZXJ0ZXhUcmFuc2Zvcm0sIGZhbHNlLCBvYmoudmVydGV4VHJhbnNmb3JtKTtcblxuICAgIGxldCBtYXRlcmlhbCA9IG9iai5tb2RlbC5tYXRlcmlhbDtcbiAgICBnbC51bmlmb3JtM2Z2KHNoYWRlckluZm8udW5pZm9ybXNbXCJ1TWF0ZXJpYWwuYW1iaWVudFwiXSwgbWF0ZXJpYWwuYW1iaWVudCk7XG4gICAgZ2wudW5pZm9ybTNmdihzaGFkZXJJbmZvLnVuaWZvcm1zW1widU1hdGVyaWFsLmRpZmZ1c2VcIl0sIG1hdGVyaWFsLmRpZmZ1c2UpO1xuICAgIGdsLnVuaWZvcm0zZnYoc2hhZGVySW5mby51bmlmb3Jtc1tcInVNYXRlcmlhbC5zcGVjdWxhclwiXSwgbWF0ZXJpYWwuc3BlY3VsYXIpO1xuICAgIGdsLnVuaWZvcm0xZihzaGFkZXJJbmZvLnVuaWZvcm1zW1widU1hdGVyaWFsLnNoaW5lXCJdLCBtYXRlcmlhbC5uKTtcblxuICAgIGdsLmJpbmRCdWZmZXIoZ2wuRUxFTUVOVF9BUlJBWV9CVUZGRVIsIG9iai50cmlhbmdsZUJ1ZmZlcik7XG4gICAgZ2wuZHJhd0VsZW1lbnRzKGdsLlRSSUFOR0xFUywgb2JqLnRyaWFuZ2xlQnVmZmVyU2l6ZSwgZ2wuVU5TSUdORURfU0hPUlQsIDApO1xuICB9XG5cbiAgLy8gV2UgY2Fubm90IHVzZSBhbiBpdGVyYWJsZSByZXBlYXRlZGx5XG4gIGdsLmVuYWJsZShnbC5ERVBUSF9URVNUKTtcbiAgbGV0IG9iamVjdHNBcnIgPSBBcnJheS5mcm9tKG9iamVjdHMpO1xuICBmb3IgKGNvbnN0IG9iaiBvZiBvYmplY3RzQXJyKSB7XG4gICAgZHJhd09iamVjdChvYmopO1xuICB9XG5cbiAgZ2wuZGlzYWJsZShnbC5ERVBUSF9URVNUKTtcbiAgbGV0IGZyb250T2JqZWN0c0FyciA9IEFycmF5LmZyb20oZnJvbnRPYmplY3RzKTtcbiAgZnJvbnRPYmplY3RzQXJyLmZvckVhY2goZHJhd09iamVjdCk7XG59XG4iLCJleHBvcnQgY2xhc3MgRGVib3VuY2VyIHtcbiAgZGVib3VuY2VUaW1lOiBudW1iZXI7XG4gIGxhc3RDaGFuZ2U6IG51bWJlcjtcbiAgZ2V0VGltZTogKCkgPT4gbnVtYmVyO1xuXG4gIGNvbnN0cnVjdG9yKGdldFRpbWU6ICgpID0+IG51bWJlciwgZGVsYXlNczogbnVtYmVyKSB7XG4gICAgdGhpcy5nZXRUaW1lID0gZ2V0VGltZTtcbiAgICB0aGlzLmRlYm91bmNlVGltZSA9IGRlbGF5TXM7XG4gICAgdGhpcy5sYXN0Q2hhbmdlID0gLWRlbGF5TXM7XG4gIH1cblxuICByZXNldCgpIHtcbiAgICB0aGlzLmxhc3RDaGFuZ2UgPSAtdGhpcy5kZWJvdW5jZVRpbWU7XG4gIH1cblxuICBzZXQoKSB7XG4gICAgdGhpcy5sYXN0Q2hhbmdlID0gdGhpcy5nZXRUaW1lKCk7XG4gIH1cblxuICByZWFkeSgpIHtcbiAgICByZXR1cm4gdGhpcy5nZXRUaW1lKCkgLSB0aGlzLmxhc3RDaGFuZ2UgPj0gdGhpcy5kZWJvdW5jZVRpbWU7XG4gIH1cblxuICB0cnkoZjogKCkgPT4gdm9pZCkge1xuICAgIGxldCBub3cgPSB0aGlzLmdldFRpbWUoKTtcbiAgICBpZiAobm93IC0gdGhpcy5sYXN0Q2hhbmdlID49IHRoaXMuZGVib3VuY2VUaW1lKSB7XG4gICAgICBmKCk7XG4gICAgICB0aGlzLmxhc3RDaGFuZ2UgPSBub3c7XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBLZXlib2FyZCB7XG4gIHB1YmxpYyByZWFkb25seSBwcmVzc2VkOiBTZXQ8c3RyaW5nPjtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLnByZXNzZWQgPSBuZXcgU2V0KCk7XG4gIH1cblxuICByZWdpc3RlcigpIHtcbiAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKFwia2V5ZG93blwiLCAoZTogS2V5Ym9hcmRFdmVudCkgPT4ge1xuICAgICAgdGhpcy5wcmVzc2VkLmFkZChlLmNvZGUpO1xuICAgIH0pO1xuICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoXCJrZXl1cFwiLCAoZTogS2V5Ym9hcmRFdmVudCkgPT4ge1xuICAgICAgdGhpcy5wcmVzc2VkLmRlbGV0ZShlLmNvZGUpO1xuICAgIH0pO1xuICB9XG59XG4iLCIvLyBUT0RPOiBNYWtlIG11c2ljIHBsYXkgb24gc3RhcnRcbi8vIFRPRE86IEhhdmUgc291bmQgZWZmZWN0cyBhbmQgbXVzaWMgbXV0ZVxuaW1wb3J0IHsgcXVhdCwgdmVjMywgbWF0NCB9IGZyb20gXCJnbC1tYXRyaXhcIjtcblxuaW1wb3J0ICogYXMgbW9kZWxzIGZyb20gXCIuL21vZGVsc1wiO1xuaW1wb3J0ICogYXMgcmVuZGVyIGZyb20gXCIuL3JlbmRlclwiO1xuaW1wb3J0IHsgU2NlbmVPYmplY3QgfSBmcm9tIFwiLi9yZW5kZXJcIjtcbmltcG9ydCB7IERlYm91bmNlciwgS2V5Ym9hcmQgfSBmcm9tIFwiLi9pbnB1dHNcIjtcbmltcG9ydCB7IENhbWVyYSB9IGZyb20gXCIuL3JlbmRlclwiO1xuXG4vLyBUT0RPOiBUcnkgdG8gc3BsaXQgdXAgZGlmZmVyZW50IGxvb3BzIGludG8gZGlmZmVyZW50IGZpbGVzXG5cbnR5cGUgUmFuZ2UgPSBbbnVtYmVyLCBudW1iZXJdO1xuXG5mdW5jdGlvbiByYW5kZihsbzogbnVtYmVyLCBoaTogbnVtYmVyKSB7XG4gIHJldHVybiAoaGkgLSBsbykgKiBNYXRoLnJhbmRvbSgpICsgbG87XG59XG5cbmZ1bmN0aW9uIGNsYW1wKG46IG51bWJlciwgcmFuZ2U6IFJhbmdlKSB7XG4gIHJldHVybiBNYXRoLm1pbihyYW5nZVsxXSwgTWF0aC5tYXgocmFuZ2VbMF0sIG4pKTtcbn1cblxuZnVuY3Rpb24gaW50ZXJwb2xhdGUocG9zOiBudW1iZXIsIHJhbmdlOiBSYW5nZSkge1xuICByZXR1cm4gcG9zICogcmFuZ2VbMV0gKyAoMSAtIHBvcykgKiByYW5nZVswXTtcbn1cblxuZnVuY3Rpb24gZGVncmVlcyhyYWRzOiBudW1iZXIpIHtcbiAgcmV0dXJuIHJhZHMgKiAoTWF0aC5QSSAvIDE4MCk7XG59XG5cbi8vIEZpbmQgYSBwb3NpdGlvbiBpbiB0aGUgZ2l2ZW4gdW5pdCB2ZWN0b3IgZGlyZWN0aW9uXG5mdW5jdGlvbiByYW5kb21BcmMoZGlyZWN0aW9uOiB2ZWMzLCBhcmM6IG51bWJlcik6IHZlYzMge1xuICByZXR1cm4gcmFuZG9tQXJjUmFuZ2UoZGlyZWN0aW9uLCBbMCwgYXJjXSk7XG59XG5cbi8vIEZpbmQgYSBwb3NpdGlvbiBpbiB0aGUgZ2l2ZW4gdW5pdCB2ZWN0b3IgZGlyZWN0aW9uXG5mdW5jdGlvbiByYW5kb21BcmNSYW5nZShkaXJlY3Rpb246IHZlYzMsIGFyY1JhbmdlOiBSYW5nZSk6IHZlYzMge1xuICAvLyBUaGlzIGZhaWxzIGlmIGRpcmVjdGlvbiA9IFstMSwwLDBdIHNvIHdlIGhhdmUgdHdvIGFsdGVybmF0aXZlc1xuICBsZXQgcGVycGVuZGljdWxhciA9IHZlYzMuZnJvbVZhbHVlcyhkaXJlY3Rpb25bMF0gKyAxLCBkaXJlY3Rpb25bMV0sIGRpcmVjdGlvblsyXSk7XG4gIGlmIChNYXRoLmFicyhwZXJwZW5kaWN1bGFyWzBdKSA8IDAuMDEpIHtcbiAgICBwZXJwZW5kaWN1bGFyID0gdmVjMy5mcm9tVmFsdWVzKGRpcmVjdGlvblswXSwgZGlyZWN0aW9uWzFdICsgMSwgZGlyZWN0aW9uWzJdKTtcbiAgfVxuICB2ZWMzLmNyb3NzKHBlcnBlbmRpY3VsYXIsIGRpcmVjdGlvbiwgcGVycGVuZGljdWxhcik7XG4gIHZlYzMubm9ybWFsaXplKHBlcnBlbmRpY3VsYXIsIHBlcnBlbmRpY3VsYXIpO1xuXG4gIC8vIGxldCBhcmNWZWMgPSB2ZWMzLmNsb25lKGRpcmVjdGlvbik7XG4gIGxldCBhcmNWZWMgPSB2ZWMzLmNvcHkodmVjMy5jcmVhdGUoKSwgZGlyZWN0aW9uKTtcbiAgbGV0IGFuZ2xlT3V0ID0gbWF0NC5mcm9tUm90YXRpb24obWF0NC5jcmVhdGUoKSwgcmFuZGYoLi4uYXJjUmFuZ2UpLCBwZXJwZW5kaWN1bGFyKTtcbiAgbGV0IGFuZ2xlQXJvdW5kID0gbWF0NC5mcm9tUm90YXRpb24obWF0NC5jcmVhdGUoKSwgcmFuZGYoMCwgMiAqIE1hdGguUEkpLCBkaXJlY3Rpb24pO1xuICB2ZWMzLnRyYW5zZm9ybU1hdDQoYXJjVmVjLCBhcmNWZWMsIGFuZ2xlT3V0KTtcbiAgdmVjMy50cmFuc2Zvcm1NYXQ0KGFyY1ZlYywgYXJjVmVjLCBhbmdsZUFyb3VuZCk7XG5cbiAgcmV0dXJuIGFyY1ZlYztcbn1cblxuY29uc3QgU1BBV05fRElTVEFOQ0U6IG51bWJlciA9IHJlbmRlci5GT0dfRU5EICsgMTtcbmNvbnN0IERFU1BBV05fRElTVEFOQ0U6IG51bWJlciA9IFNQQVdOX0RJU1RBTkNFICsgMTtcblxuY29uc3QgTkVBUl9CT1VORDogbnVtYmVyID0gMSAvIDMyO1xuY29uc3QgVklFV19ESVNUQU5DRTogbnVtYmVyID0gMzI7XG5cbi8vIE51bWJlciBvZiB0aWNrcyB0byB3YWl0IGJlZm9yZSBnb2luZyB0byB0aGUgbmV4dCBsZXZlbCBhZnRlciB3aW5uaW5nIGEgbGV2ZWxcbmNvbnN0IExFVkVMX1dBSVRfVElDS1M6IG51bWJlciA9IDMwO1xuXG5jb25zdCBBU1RFUk9JRF9USUVSUzogbnVtYmVyID0gMjtcbnR5cGUgVGllcmVkPFQ+ID0gW1QsIFRdO1xuY29uc3QgQVNURVJPSURfUkFESVVTX1RJRVJTOiBUaWVyZWQ8UmFuZ2U+ID0gW1xuICBbMS40LCAxLjhdLFxuICBbMC42LCAwLjhdLFxuXTtcbmNvbnN0IEFTVEVST0lEX0hFQUxUSF9USUVSUzogVGllcmVkPG51bWJlcj4gPSBbMiwgMV07XG5jb25zdCBBU1RFUk9JRF9QT0lOVF9USUVSUzogVGllcmVkPG51bWJlcj4gPSBbMTAwLCA1MF07XG5jb25zdCBBU1RFUk9JRF9ST1RBVElPTl9TUEVFRDogUmFuZ2UgPSBbMC4wMDUsIDAuMV07XG5jb25zdCBBU1RFUk9JRF9TUExJVF9TUEVFRDogUmFuZ2UgPSBbMC4wMSwgMC4wOF07XG5jb25zdCBBU1RFUk9JRF9JTklUSUFMX1NQQVdOX0RJU1RBTkNFOiBSYW5nZSA9IFsxNiwgMzJdO1xuY29uc3QgQVNURVJPSURfU1BBV05fRElTVEFOQ0U6IG51bWJlciA9IFNQQVdOX0RJU1RBTkNFO1xuY29uc3QgQVNURVJPSURfREVTUEFXTl9ESVNUQU5DRTogbnVtYmVyID0gREVTUEFXTl9ESVNUQU5DRTtcbmNvbnN0IEFTVEVST0lEX1NQQVdOX0FSQzogbnVtYmVyID0gZGVncmVlcygxMjApO1xuY29uc3QgQVNURVJPSURfVkVMT0NJVFlfQVJDOiBudW1iZXIgPSBkZWdyZWVzKDQ1KTtcbi8vIEEgZnVkZ2UgZmFjdG9yIHRvIHR3ZWFrIHRoZSBhc3Rlcm9pZCBjb2xsaXNpb24gaW4gdGhlIHBsYXllcidzIGZhdm9yXG5jb25zdCBBU1RFUk9JRF9SQURJVVNfRlVER0VfRkFDVE9SOiBudW1iZXIgPSAwLjg1O1xuY29uc3QgQVNURVJPSURfREVOU0lUWTogbnVtYmVyID0gMS4wO1xuXG5jb25zdCBTVU5fSU5JVElBTF9TUEFXTl9ESVNUQU5DRTogUmFuZ2UgPSBbMTAsIDI4XTtcbmNvbnN0IFNVTl9TUEFXTl9ESVNUQU5DRTogbnVtYmVyID0gU1BBV05fRElTVEFOQ0U7XG5jb25zdCBTVU5fREVTUEFXTl9ESVNUQU5DRTogbnVtYmVyID0gREVTUEFXTl9ESVNUQU5DRTtcbi8vIDIuNSBkZWdyZWVzIGlzIGp1c3QgZW5vdWdoIHRvIGFsd2F5cyBsZXQgeW91IGRvZGdlIGJ1dCBmb3IgaXQgdG8gYmUgZGVhZGx5XG4vLyBpZiB5b3UncmUgbm90IHBheWluZyBhdHRlbnRpb25cbmNvbnN0IFNVTl9TUEFXTl9BUkM6IFJhbmdlID0gW2RlZ3JlZXMoMi41KSwgZGVncmVlcyg1MCldO1xuXG5jb25zdCBTSElQX01BWF9USFJVU1Q6IG51bWJlciA9IDAuMDAxO1xuY29uc3QgU0hJUF9USFJPVFRMRV9TUEVFRF9MSU1JVDogUmFuZ2UgPSBbLTEgLyA5LCAxIC8gMTVdO1xuY29uc3QgU0hJUF9GT1ZfREVHUkVFUzogUmFuZ2UgPSBbODAsIDg2XTtcbmNvbnN0IFNISVBfQ0FNRVJBX0NIQVNFX0ZBQ1RPUjogbnVtYmVyID0gMC42O1xuXG5jb25zdCBTSElQX1ZFTE9DSVRZX0VQU0lMT046IG51bWJlciA9IDFlLTEwO1xuY29uc3QgU0hJUF9ST1RBVElPTl9FUFNJTE9OOiBudW1iZXIgPSAxZS0xMDtcbmNvbnN0IFNISVBfUk9UQVRJT05fVE9QT1VUOiBudW1iZXIgPSAwLjAxO1xuY29uc3QgU0hJUF9ST1RBVElPTl9UT1BPVVRfU0NBTElORzogbnVtYmVyID0gMC45MjU7XG5cbmNvbnN0IFNISVBfTU9VU0VfVFVSTl9TUEVFRDogbnVtYmVyID0gMC4wMDAxO1xuY29uc3QgU0hJUF9HQU1FUEFEX1RVUk5fU1BFRUQ6IG51bWJlciA9IDAuMDAzO1xuY29uc3QgU0hJUF9ST0xMX1NQRUVEOiBudW1iZXIgPSBkZWdyZWVzKDAuMyk7XG5cbi8vIG51bWJlciBvZiB0aWNrcyBtb3ZpbmcgYXQgTUlTU0lMRV9TUEVFRCB0byB0cmF2ZWwgREVTUEFXTl9ESVNUQU5DRVxuY29uc3QgTUlTU0lMRV9ESVNUQU5DRTogbnVtYmVyID0gREVTUEFXTl9ESVNUQU5DRTtcbi8vIFRoaXMgc2hvdWxkIGJlIG5vdGFibHkgc21hbGxlciB0aGFuIHRoZSBhc3Rlcm9pZCByYWRpdXMgb3RoZXJ3aXNlIG1pc3NpbGVzXG4vLyBjYW4gcGhhc2UgdGhyb3VnaCBhc3Rlcm9pZHNcbi8vIFRPRE86IENoZWNrIG1pc3NpbGUgY29sbGlzaW9ucyBhdCBtdWx0aXBsZSBzdGVwcyB0byBlbnN1cmUgbWlzc2lsZXMgZG9uJ3Rcbi8vIFwicGhhc2UgdGhyb3VnaFwiIGFzdGVyb2lkc1xuY29uc3QgTUlTU0lMRV9TUEVFRDogbnVtYmVyID0gMS4wO1xuY29uc3QgTUlTU0lMRV9DT09MRE9XTl9USUNLUzogbnVtYmVyID0gMzA7XG5jb25zdCBNSVNTSUxFX0xJRkVfVElDS1M6IG51bWJlciA9IE1hdGgucm91bmQoTUlTU0lMRV9ESVNUQU5DRSAvIE1JU1NJTEVfU1BFRUQpO1xuY29uc3QgTUlTU0lMRV9NQVNTOiBudW1iZXIgPSAwLjM7XG5cbmNvbnN0IEZSRUNBTV9NT1VTRV9UVVJOX1NQRUVEOiBudW1iZXIgPSAwLjAwMjtcbmNvbnN0IEZSRUNBTV9ST0xMX1NQRUVEOiBudW1iZXIgPSAwLjAyO1xuY29uc3QgRlJFRUNBTV9ERUZBVUxUX01PVkVfU1BFRUQ6IG51bWJlciA9IDAuMDQ7XG5jb25zdCBGUkVFQ0FNX01PVkVfU1BFRURfSU5DUkVNRU5UOiBudW1iZXIgPSAwLjAwNTtcbmNvbnN0IEZSRUVDQU1fTkVBUl9CT1VORDogbnVtYmVyID0gMSAvIDMyO1xuY29uc3QgRlJFRUNBTV9GQVJfQk9VTkQ6IG51bWJlciA9IDY0O1xuXG5jb25zdCBNRU5VX05VTV9BU1RFUk9JRFM6IG51bWJlciA9IDY0O1xuLy8gV2UgZG9uJ3QgbGV0IHRoZSBhbmdsZSBiZSAwIG9yIGVsc2Ugd2UgZ2V0IGludGVyc2VjdGlvbnMgd2l0aCB1c1xuY29uc3QgTUVOVV9BU1RFUk9JRF9WRUxPQ0lUWV9BUkM6IFJhbmdlID0gW2RlZ3JlZXMoMyksIGRlZ3JlZXMoNDUpXTtcbmNvbnN0IE1FTlVfQVNURVJPSURfU1BBV05fQVJDOiBudW1iZXIgPSBkZWdyZWVzKDEyMCk7XG5jb25zdCBNRU5VX0FTVEVST0lEX1NQQVdOX0RJU1RBTkNFOiBudW1iZXIgPSBTUEFXTl9ESVNUQU5DRTtcbmNvbnN0IE1FTlVfQVNURVJPSURfU1BFRUQ6IFJhbmdlID0gWzAuMDEsIDAuMV07XG5cbmNvbnN0IERFQk9VTkNFX01TOiBudW1iZXIgPSAyMDA7XG5cbi8vIFRPRE86IE1ha2UgdGhlc2UgY29uZmlndXJhYmxlLCBhcyB3ZWxsIGFzIGRpcmVjdGlvblxuY29uc3QgQ09OVFJPTExFUl9YX0FYSVM6IG51bWJlciA9IDA7XG5jb25zdCBDT05UUk9MTEVSX1lfQVhJUzogbnVtYmVyID0gMTtcbmNvbnN0IERFQURaT05FOiBudW1iZXIgPSAwLjE1O1xuXG5mdW5jdGlvbiBhc3Rlcm9pZFNwZWVkKGxldmVsOiBudW1iZXIpOiBSYW5nZSB7XG4gIGxldCBzbG93ID0gMC4wMSArIGxldmVsICogMC4wMDU7XG4gIGxldCBmYXN0ID0gMC4wOSArIGxldmVsICogMC4wMztcbiAgcmV0dXJuIFtzbG93LCBmYXN0XTtcbn1cblxuZnVuY3Rpb24gbnVtQXN0ZXJvaWRzKGxldmVsOiBudW1iZXIpOiBUaWVyZWQ8bnVtYmVyPiB7XG4gIGxldCBiaWcgPSBNYXRoLnJvdW5kKCgxIC8gMikgKiBsZXZlbCAqIGxldmVsICsgOCAqIGxldmVsKTtcbiAgbGV0IHNtYWxsID0gTWF0aC5yb3VuZCgoMSAvIDgpICogbGV2ZWwgKiBsZXZlbCArIDQgKiBsZXZlbCArIDQpO1xuICByZXR1cm4gW2JpZywgc21hbGxdO1xufVxuXG4vLyBUT0RPOiBBY3R1YWxseSBtaXggdGhlIHZvbHVtZSBiZXR0ZXJcbmNvbnN0IE1JU1NJTEVfU0ZYOiBIVE1MQXVkaW9FbGVtZW50ID0gbmV3IEF1ZGlvKFwibWlzc2lsZS5tcDNcIik7XG5jb25zdCBNVVNJQzogSFRNTEF1ZGlvRWxlbWVudCA9IG5ldyBBdWRpbyhcIm11c2ljLndhdlwiKTtcbmNvbnN0IE1VU0lDX1ZPTFVNRTogbnVtYmVyID0gMS4wO1xuY29uc3QgU0ZYX1ZPTFVNRTogbnVtYmVyID0gMS4wO1xuTVVTSUMudm9sdW1lID0gTVVTSUNfVk9MVU1FICogMC43NTtcbk1VU0lDLmxvb3AgPSB0cnVlO1xuXG50eXBlIE1pc3NpbGUgPSB7XG4gIGJpcnRoOiBudW1iZXI7XG4gIHZlbG9jaXR5OiB2ZWMzO1xuICBvYmo6IFNjZW5lT2JqZWN0O1xufTtcblxuY2xhc3MgRWFzZWQge1xuICB3YW50OiBudW1iZXI7XG4gIGN1cnJlbnQ6IG51bWJlcjtcbiAgc3BlZWRMaW1pdDogUmFuZ2U7XG5cbiAgY29uc3RydWN0b3IodmFsdWU6IG51bWJlciwgc3BlZWRMaW1pdDogUmFuZ2UpIHtcbiAgICB0aGlzLndhbnQgPSB2YWx1ZTtcbiAgICB0aGlzLmN1cnJlbnQgPSB2YWx1ZTtcbiAgICB0aGlzLnNwZWVkTGltaXQgPSBzcGVlZExpbWl0O1xuICB9XG5cbiAgc2V0KHZhbHVlOiBudW1iZXIpIHtcbiAgICB0aGlzLndhbnQgPSB2YWx1ZTtcbiAgfVxuXG4gIGdldCgpIHtcbiAgICByZXR1cm4gdGhpcy5jdXJyZW50O1xuICB9XG5cbiAgc3RlcCgpIHtcbiAgICB0aGlzLmN1cnJlbnQgKz0gY2xhbXAodGhpcy53YW50IC0gdGhpcy5jdXJyZW50LCB0aGlzLnNwZWVkTGltaXQpO1xuICB9XG59XG5cbi8vIFRPRE86IEltcGxlbWVudCBhbiBhbW1vIG1lY2hhbmljXG5jbGFzcyBTaGlwIHtcbiAgdmVsb2NpdHk6IHZlYzM7XG5cbiAgb2JqOiBTY2VuZU9iamVjdDtcbiAgZmxhbWU6IFNjZW5lT2JqZWN0O1xuICBmbGFtZUFjY2VudDogU2NlbmVPYmplY3Q7XG4gIHJldGljbGU6IFNjZW5lT2JqZWN0O1xuXG4gIGxhc3RGaXJlZDogbnVtYmVyO1xuICB0aHJvdHRsZTogRWFzZWQ7XG5cbiAgd29ybGRSb3RhdGlvbjogcXVhdDtcblxuICBmb3J3YXJkOiB2ZWMzO1xuICB1cDogdmVjMztcbiAgcmlnaHQ6IHZlYzM7XG5cbiAgdGhydXN0ZXJTZng6IEhUTUxBdWRpb0VsZW1lbnQ7XG5cbiAgY29uc3RydWN0b3IoZ2w6IFdlYkdMUmVuZGVyaW5nQ29udGV4dCkge1xuICAgIHRoaXMudmVsb2NpdHkgPSB2ZWMzLmNyZWF0ZSgpO1xuICAgIHRoaXMub2JqID0gbmV3IFNjZW5lT2JqZWN0KGdsLCBtb2RlbHMuU0hJUCk7XG4gICAgdGhpcy5mbGFtZSA9IG5ldyBTY2VuZU9iamVjdChnbCwgbW9kZWxzLlNISVBfRkxBTUUpO1xuICAgIHRoaXMuZmxhbWVBY2NlbnQgPSBuZXcgU2NlbmVPYmplY3QoZ2wsIG1vZGVscy5TSElQX0ZMQU1FX0FDQ0VOVCk7XG4gICAgLy8gVGhlIGZsYW1lIGlzIGFsd2F5cyBieSB0aGUgZmxhbWUgYWNjZW50XG4gICAgdGhpcy5mbGFtZUFjY2VudC52ZXJ0ZXhUcmFuc2Zvcm0gPSB0aGlzLmZsYW1lLnZlcnRleFRyYW5zZm9ybTtcbiAgICB0aGlzLnJldGljbGUgPSBuZXcgU2NlbmVPYmplY3QoZ2wsIG1vZGVscy5TSElQX1JFVElDTEUpO1xuICAgIC8vIFRoZSByZXRpY2xlIG1vdmVzIHdpdGggdGhlIHNoaXBcbiAgICB0aGlzLnJldGljbGUudmVydGV4VHJhbnNmb3JtID0gdGhpcy5vYmoudmVydGV4VHJhbnNmb3JtO1xuXG4gICAgdGhpcy5sYXN0RmlyZWQgPSBOdW1iZXIuTkVHQVRJVkVfSU5GSU5JVFk7XG4gICAgdGhpcy50aHJvdHRsZSA9IG5ldyBFYXNlZCgwLCBTSElQX1RIUk9UVExFX1NQRUVEX0xJTUlUKTtcblxuICAgIHRoaXMud29ybGRSb3RhdGlvbiA9IHF1YXQuY3JlYXRlKCk7XG5cbiAgICB0aGlzLnVwID0gdmVjMy5mcm9tVmFsdWVzKDAsIDAsIC0xKTtcbiAgICB0aGlzLmZvcndhcmQgPSB2ZWMzLmZyb21WYWx1ZXMoMCwgMSwgMCk7XG4gICAgdGhpcy5yaWdodCA9IHZlYzMuZnJvbVZhbHVlcygtMSwgMCwgMCk7XG5cbiAgICB0aGlzLnRocnVzdGVyU2Z4ID0gbmV3IEF1ZGlvKFwidGhydXN0ZXIud2F2XCIpO1xuICAgIHRoaXMudGhydXN0ZXJTZngubG9vcCA9IHRydWU7XG4gIH1cblxuICAqb2JqZWN0cygpOiBJdGVyYWJsZTxTY2VuZU9iamVjdD4ge1xuICAgIHlpZWxkIHRoaXMub2JqO1xuICAgIGlmICh0aGlzLnRocm90dGxlLmdldCgpID4gMCkge1xuICAgICAgeWllbGQgdGhpcy5mbGFtZTtcbiAgICAgIHlpZWxkIHRoaXMuZmxhbWVBY2NlbnQ7XG4gICAgfVxuICB9XG5cbiAgc2V0VGhyb3R0bGUoYW1vdW50OiBudW1iZXIpIHtcbiAgICBpZiAoYW1vdW50ICE9IDApIHtcbiAgICAgIHRoaXMudGhydXN0ZXJTZngucGxheSgpO1xuICAgIH1cbiAgICB0aGlzLnRocm90dGxlLnNldChhbW91bnQpO1xuICB9XG5cbiAgcGl0Y2hVcChyYWRzOiBudW1iZXIpIHtcbiAgICB0aGlzLnJvdGF0ZShyYWRzLCB0aGlzLnJpZ2h0KTtcbiAgfVxuXG4gIHlhd0xlZnQocmFkczogbnVtYmVyKSB7XG4gICAgdGhpcy5yb3RhdGUocmFkcywgdGhpcy51cCk7XG4gIH1cblxuICByb2xsUmlnaHQocmFkczogbnVtYmVyKSB7XG4gICAgdGhpcy5yb3RhdGUocmFkcywgdGhpcy5mb3J3YXJkKTtcbiAgfVxuXG4gIHByaXZhdGUgcm90YXRlKHJhZHM6IG51bWJlciwgYWJvdXRXb3JsZDogdmVjMykge1xuICAgIGxldCB3b3JsZEltcHVsc2UgPSBxdWF0LnNldEF4aXNBbmdsZShxdWF0LmNyZWF0ZSgpLCBhYm91dFdvcmxkLCByYWRzKTtcbiAgICBxdWF0Lm11bHRpcGx5KHRoaXMud29ybGRSb3RhdGlvbiwgdGhpcy53b3JsZFJvdGF0aW9uLCB3b3JsZEltcHVsc2UpO1xuICB9XG5cbiAgY29sbGlzaW9uUG9pbnRzKCk6IHZlYzNbXSB7XG4gICAgcmV0dXJuIG1vZGVscy5TSElQX0NPTExJU0lPTl9QT0lOVFMubWFwKCh2KSA9PlxuICAgICAgdmVjMy50cmFuc2Zvcm1NYXQ0KHZlYzMuY3JlYXRlKCksIHYsIHRoaXMub2JqLnZlcnRleFRyYW5zZm9ybSksXG4gICAgKTtcbiAgfVxuXG4gIC8vIFRPRE86IE1heWJlIGJlIGEgZnJlZSBmdW5jdGlvblxuICB0cnlGaXJlKGdhbWU6IEdhbWUpIHtcbiAgICBpZiAoZ2FtZS5wbGF5LnRpY2tzIC0gdGhpcy5sYXN0RmlyZWQgPD0gTUlTU0lMRV9DT09MRE9XTl9USUNLUykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMubGFzdEZpcmVkID0gZ2FtZS5wbGF5LnRpY2tzO1xuICAgIGxldCBzZnggPSA8SFRNTEF1ZGlvRWxlbWVudD5NSVNTSUxFX1NGWC5jbG9uZU5vZGUoKTtcbiAgICAvLyBUT0RPOiBEbyBhY3R1YWwgYXVkaW8gbWl4aW5nXG4gICAgc2Z4LnZvbHVtZSA9IFNGWF9WT0xVTUUgKiAwLjE1O1xuICAgIHNmeC5wbGF5KCk7XG5cbiAgICBsZXQgbWlzc2lsZVZlbG9jaXR5ID0gdmVjMy5jcmVhdGUoKTtcbiAgICB2ZWMzLnNjYWxlQW5kQWRkKG1pc3NpbGVWZWxvY2l0eSwgdGhpcy52ZWxvY2l0eSwgdGhpcy5mb3J3YXJkLCBNSVNTSUxFX1NQRUVEKTtcbiAgICBsZXQgb2JqID0gbmV3IFNjZW5lT2JqZWN0KGdhbWUuZ2wsIG1vZGVscy5NSVNTSUxFKTtcbiAgICAvLyBXZSBkb24ndCBjYWxsIHRyYW5zbGF0ZSBiZWNhdXNlIHdlIHdhbnQgdG8gdHJhbnNsYXRlIGluIG1vZGVsXG4gICAgLy8gY29vcmRpbmF0ZXNcbiAgICBtYXQ0LnRyYW5zbGF0ZShvYmoudmVydGV4VHJhbnNmb3JtLCBvYmoudmVydGV4VHJhbnNmb3JtLCBtb2RlbHMuU0hJUF9OT1paTEUpO1xuICAgIG1hdDQubXVsdGlwbHkob2JqLnZlcnRleFRyYW5zZm9ybSwgdGhpcy5vYmoudmVydGV4VHJhbnNmb3JtLCBvYmoudmVydGV4VHJhbnNmb3JtKTtcblxuICAgIGdhbWUucGxheS5taXNzaWxlcy5wdXNoKHtcbiAgICAgIGJpcnRoOiBnYW1lLnBsYXkudGlja3MsXG4gICAgICB2ZWxvY2l0eTogbWlzc2lsZVZlbG9jaXR5LFxuICAgICAgb2JqOiBvYmosXG4gICAgfSk7XG4gIH1cblxuICBleWUoKTogdmVjMyB7XG4gICAgbGV0IGV5ZSA9IHRoaXMub2JqLnBvcygpO1xuICAgIHZlYzMuc2NhbGVBbmRBZGQoZXllLCBleWUsIHRoaXMuZm9yd2FyZCwgLTAuNjUpO1xuICAgIHZlYzMuc2NhbGVBbmRBZGQoZXllLCBleWUsIHRoaXMudXAsIDAuMyk7XG4gICAgcmV0dXJuIGV5ZTtcbiAgfVxuXG4gIGNhbWVyYShsYXN0UG9zOiB2ZWMzKTogcmVuZGVyLkNhbWVyYSB7XG4gICAgbGV0IGV5ZSA9IHRoaXMuZXllKCk7XG4gICAgbGV0IHRocm90dGxlID0gdGhpcy50aHJvdHRsZS5nZXQoKTtcbiAgICBsZXQgZm92ID0gaW50ZXJwb2xhdGUodGhyb3R0bGUgKiB0aHJvdHRsZSwgU0hJUF9GT1ZfREVHUkVFUyk7XG4gICAgdmVjMy5sZXJwKGV5ZSwgbGFzdFBvcywgZXllLCBTSElQX0NBTUVSQV9DSEFTRV9GQUNUT1IpO1xuXG4gICAgbGV0IHZpZXdpbmdUcmFuc2Zvcm0gPSBtYXQ0Lmxvb2tBdChcbiAgICAgIG1hdDQuY3JlYXRlKCksXG4gICAgICBleWUsIC8vIGV5ZVxuICAgICAgdmVjMy5hZGQodmVjMy5jcmVhdGUoKSwgZXllLCB0aGlzLmZvcndhcmQpLCAvLyBjZW50ZXJcbiAgICAgIHRoaXMudXAsIC8vIHVwXG4gICAgKTtcbiAgICBsZXQgcGVyc3BlY3RpdmVUcmFuc2Zvcm0gPSBtYXQ0LnBlcnNwZWN0aXZlKFxuICAgICAgbWF0NC5jcmVhdGUoKSxcbiAgICAgIGRlZ3JlZXMoZm92KSwgLy8gRk9WIHlcbiAgICAgIGNhbnZhcy53aWR0aCAvIGNhbnZhcy5oZWlnaHQsIC8vIGFzcGVjdCByYXRpbyAoVy9IKVxuICAgICAgTkVBUl9CT1VORCwgLy8gbmVhciBib3VuZFxuICAgICAgVklFV19ESVNUQU5DRSwgLy8gZmFyIGJvdW5kXG4gICAgKTtcblxuICAgIHJldHVybiB7XG4gICAgICBleWU6IGV5ZSxcbiAgICAgIHZpZXdpbmdUcmFuc2Zvcm06IHZpZXdpbmdUcmFuc2Zvcm0sXG4gICAgICBwZXJzcGVjdGl2ZVRyYW5zZm9ybTogcGVyc3BlY3RpdmVUcmFuc2Zvcm0sXG4gICAgfTtcbiAgfVxufVxuXG5jbGFzcyBBc3Rlcm9pZCB7XG4gIG9iajogU2NlbmVPYmplY3Q7XG4gIHZlbG9jaXR5OiB2ZWMzO1xuICByYWRpdXM6IG51bWJlcjtcbiAgdGllcjogbnVtYmVyO1xuICByb3RhdGlvbjogcXVhdDtcbiAgaGVhbHRoOiBudW1iZXI7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgZ2w6IFdlYkdMUmVuZGVyaW5nQ29udGV4dCxcbiAgICB0aWVyOiBudW1iZXIsXG4gICAgdmVsb2NpdHk6IHZlYzMsXG4gICAgb3B0PzogeyByYWRpdXM6IG51bWJlcjsgcm90YXRpb246IHF1YXQgfSxcbiAgKSB7XG4gICAgLy8gQ2xhbXAgdGhlIHJhZGl1cyB0byB0aGUgYWNjZXB0YWJsZSB2YWx1ZXNcbiAgICBsZXQgdGllclJhZGl1cyA9IEFTVEVST0lEX1JBRElVU19USUVSU1t0aWVyXTtcbiAgICBsZXQgcmFkaXVzID1cbiAgICAgIG9wdCAhPSB1bmRlZmluZWRcbiAgICAgICAgPyBNYXRoLm1pbih0aWVyUmFkaXVzWzFdLCBNYXRoLm1heCh0aWVyUmFkaXVzWzBdLCBvcHQucmFkaXVzKSlcbiAgICAgICAgOiByYW5kZiguLi50aWVyUmFkaXVzKTtcblxuICAgIGxldCBbYWN0dWFsUmFkaXVzLCBtb2RlbF0gPSBtb2RlbHMucmFuZG9tQXN0ZXJvaWQocmFkaXVzKTtcbiAgICB0aGlzLm9iaiA9IG5ldyBTY2VuZU9iamVjdChnbCwgbW9kZWwpO1xuICAgIHRoaXMucmFkaXVzID0gYWN0dWFsUmFkaXVzO1xuICAgIHRoaXMudGllciA9IHRpZXI7XG4gICAgdGhpcy5oZWFsdGggPSBBU1RFUk9JRF9IRUFMVEhfVElFUlNbdGllcl07XG4gICAgdGhpcy52ZWxvY2l0eSA9IHZlbG9jaXR5O1xuICAgIGlmIChvcHQgPT0gdW5kZWZpbmVkKSB7XG4gICAgICBsZXQgcmFkcyA9IHJhbmRmKC4uLkFTVEVST0lEX1JPVEFUSU9OX1NQRUVEKTtcbiAgICAgIGxldCByb3RhdGlvbkF4aXMgPSB2ZWMzLnJhbmRvbSh2ZWMzLmNyZWF0ZSgpKTtcbiAgICAgIHRoaXMucm90YXRpb24gPSBxdWF0LnNldEF4aXNBbmdsZShxdWF0LmNyZWF0ZSgpLCByb3RhdGlvbkF4aXMsIHJhZHMpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnJvdGF0aW9uID0gb3B0LnJvdGF0aW9uO1xuICAgIH1cbiAgfVxuXG4gIHNwbGl0KGdsOiBXZWJHTFJlbmRlcmluZ0NvbnRleHQpOiBbQXN0ZXJvaWQsIEFzdGVyb2lkXSB7XG4gICAgbGV0IGRpcmVjdGlvbiA9IHZlYzMucmFuZG9tKHZlYzMuY3JlYXRlKCkpO1xuICAgIGxldCBzcGVlZCA9IHJhbmRmKC4uLkFTVEVST0lEX1NQTElUX1NQRUVEKTtcblxuICAgIGxldCBsZWZ0VmVsb2NpdHkgPSB2ZWMzLnNjYWxlQW5kQWRkKHZlYzMuY3JlYXRlKCksIHRoaXMudmVsb2NpdHksIGRpcmVjdGlvbiwgc3BlZWQpO1xuICAgIGxldCBsZWZ0ID0gbmV3IEFzdGVyb2lkKGdsLCB0aGlzLnRpZXIgKyAxLCBsZWZ0VmVsb2NpdHksIHtcbiAgICAgIHJhZGl1czogdGhpcy5yYWRpdXMgLyAyLFxuICAgICAgcm90YXRpb246IHF1YXQuY2xvbmUodGhpcy5yb3RhdGlvbiksXG4gICAgfSk7XG4gICAgbGV0IHBvcyA9IHRoaXMub2JqLnBvcygpO1xuICAgIGxlZnQub2JqLnRyYW5zbGF0ZShwb3MpO1xuICAgIGxldCByaWdodFZlbG9jaXR5ID0gdmVjMy5zY2FsZUFuZEFkZCh2ZWMzLmNyZWF0ZSgpLCB0aGlzLnZlbG9jaXR5LCBkaXJlY3Rpb24sIC1zcGVlZCk7XG4gICAgbGV0IHJpZ2h0ID0gbmV3IEFzdGVyb2lkKGdsLCB0aGlzLnRpZXIgKyAxLCByaWdodFZlbG9jaXR5LCB7XG4gICAgICByYWRpdXM6IHRoaXMucmFkaXVzIC8gMixcbiAgICAgIHJvdGF0aW9uOiBxdWF0LmNsb25lKHRoaXMucm90YXRpb24pLFxuICAgIH0pO1xuICAgIHJpZ2h0Lm9iai50cmFuc2xhdGUocG9zKTtcblxuICAgIHJldHVybiBbbGVmdCwgcmlnaHRdO1xuICB9XG5cbiAgZGFtYWdlKCkge1xuICAgIHRoaXMuaGVhbHRoIC09IDE7XG5cbiAgICBsZXQgbWF0ZXJpYWwgPSB0aGlzLm9iai5tb2RlbC5tYXRlcmlhbDtcbiAgICBsZXQgaGVhbHRoUGVyY2VudCA9IHRoaXMuaGVhbHRoIC8gQVNURVJPSURfSEVBTFRIX1RJRVJTW3RoaXMudGllcl07XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCAzOyBpKyspIHtcbiAgICAgIGxldCBjb2xvciA9XG4gICAgICAgIG1vZGVscy5BU1RFUk9JRF9DT0xPUltpXSAqIGhlYWx0aFBlcmNlbnQgK1xuICAgICAgICBtb2RlbHMuQVNURVJPSURfREFNQUdFRF9DT0xPUltpXSAqICgxIC0gaGVhbHRoUGVyY2VudCk7XG4gICAgICBtYXRlcmlhbC5hbWJpZW50W2ldID0gY29sb3IgKiBtb2RlbHMuQVNURVJPSURfQU1CSUVOVF9TQ0FMQVI7XG4gICAgICBtYXRlcmlhbC5kaWZmdXNlW2ldID0gY29sb3IgKiBtb2RlbHMuQVNURVJPSURfRElGRlVTRV9TQ0FMQVI7XG4gICAgfVxuICB9XG59XG5cbi8vIFRPRE86IE1ha2Ugc3VuIGEgY2xhc3M/XG5mdW5jdGlvbiBzdW5Db250YWlucyhzdW46IFNjZW5lT2JqZWN0LCBwb2ludDogdmVjMyk6IGJvb2xlYW4ge1xuICBsZXQgY2VudGVyID0gc3VuLnBvcygpO1xuICByZXR1cm4gWzAsIDEsIDJdLmV2ZXJ5KFxuICAgIChpKSA9PlxuICAgICAgY2VudGVyW2ldIC0gbW9kZWxzLlNVTl9TSURFX0xFTkdUSCAvIDIgPD0gcG9pbnRbaV0gJiZcbiAgICAgIHBvaW50W2ldIDw9IGNlbnRlcltpXSArIG1vZGVscy5TVU5fU0lERV9MRU5HVEggLyAyLFxuICApO1xufVxuXG5lbnVtIEdhbWVNb2RlIHtcbiAgTWVudSxcbiAgUGF1c2UsXG4gIFBsYXksXG4gIEZyZWVjYW0sXG59XG5cbmV4cG9ydCB0eXBlIEdhbWUgPSB7XG4gIGdsOiBXZWJHTFJlbmRlcmluZ0NvbnRleHQ7XG4gIHNoYWRlckluZm86IHJlbmRlci5TaGFkZXJBdHRyaWJ1dGVzO1xuICBtb2RlOiBHYW1lTW9kZTtcbiAgaW5wdXRzOiB7XG4gICAga2V5Ym9hcmQ6IEtleWJvYXJkO1xuICAgIGdhbWVwYWQ6IG51bWJlcjtcbiAgICBwYXVzZURlYm91bmNlcjogRGVib3VuY2VyO1xuICAgIG1vdXNlRG93bjogYm9vbGVhbjtcbiAgfTtcbiAgcGxheToge1xuICAgIHNoaXA6IFNoaXA7XG4gICAgbWlzc2lsZXM6IE1pc3NpbGVbXTtcbiAgICB0aWVyZWRBc3Rlcm9pZHM6IFRpZXJlZDxBc3Rlcm9pZFtdPjtcbiAgICBudW1Bc3Rlcm9pZHM6IFRpZXJlZDxudW1iZXI+O1xuICAgIHN1bnM6IFNjZW5lT2JqZWN0W107XG4gICAgdGlja3M6IG51bWJlcjtcbiAgICBzY29yZTogbnVtYmVyO1xuICAgIGxhc3RDYW1lcmFQb3NpdGlvbjogdmVjMztcbiAgICBjYW1lcmE6IENhbWVyYTtcbiAgICBhc3Rlcm9pZFNwZWVkOiBSYW5nZTtcbiAgICBsZXZlbDogbnVtYmVyO1xuICAgIGxldmVsRmluaXNoZWRBdDogbnVsbCB8IG51bWJlcjtcbiAgfTtcbiAgZnJlZWNhbToge1xuICAgIGZyZWVjYW1Nb2RlRGVib3VuY2VyOiBEZWJvdW5jZXI7XG4gICAgZ2VuZXJhbERlYm91bmNlcjogRGVib3VuY2VyO1xuICAgIGNhbWVyYTogRnJlZUNhbWVyYTtcbiAgICBmb2c6IGJvb2xlYW47XG4gICAgc2hvd1NoaXBDb2xsaXNpb25zOiBib29sZWFuO1xuICB9O1xuICBtZW51OiB7XG4gICAgY2FtZXJhOiBGcmVlQ2FtZXJhO1xuICAgIGFzdGVyb2lkczogQXN0ZXJvaWRbXTtcbiAgICBzdW5zOiBTY2VuZU9iamVjdFtdO1xuICAgIG1vdmluZ0NhbWVyYTogYm9vbGVhbjtcbiAgICBtb3ZlTW9kZURlYm91bmNlcjogRGVib3VuY2VyO1xuICB9O1xufTtcblxuZnVuY3Rpb24gaW5pdEdhbWUoZ2w6IFdlYkdMUmVuZGVyaW5nQ29udGV4dCk6IEdhbWUge1xuICBsZXQga2V5Ym9hcmQgPSBuZXcgS2V5Ym9hcmQoKTtcbiAga2V5Ym9hcmQucmVnaXN0ZXIoKTtcbiAgbGV0IHNoaXAgPSBuZXcgU2hpcChnbCk7XG5cbiAgbGV0IGdhbWU6IEdhbWUgPSB7XG4gICAgZ2w6IGdsLFxuICAgIHNoYWRlckluZm86IHJlbmRlci5zZXR1cFNoYWRlcnMoZ2wpLFxuICAgIG1vZGU6IEdhbWVNb2RlLk1lbnUsXG4gICAgaW5wdXRzOiB7XG4gICAgICBrZXlib2FyZDoga2V5Ym9hcmQsXG4gICAgICAvLyBUT0RPOiBEb24ndCBoYXJkY29kZVxuICAgICAgZ2FtZXBhZDogMCxcbiAgICAgIHBhdXNlRGVib3VuY2VyOiBuZXcgRGVib3VuY2VyKERhdGUubm93LCBERUJPVU5DRV9NUyksXG4gICAgICBtb3VzZURvd246IGZhbHNlLFxuICAgIH0sXG4gICAgcGxheToge1xuICAgICAgc2hpcDogc2hpcCxcbiAgICAgIG1pc3NpbGVzOiBbXSxcbiAgICAgIHRpZXJlZEFzdGVyb2lkczogW1tdLCBbXV0sXG4gICAgICAvLyBUaGVzZSBnZXQgcmVhc3NpZ25lZCB3aGVuIHdlIHBsYXkgYSBsZXZlbFxuICAgICAgbnVtQXN0ZXJvaWRzOiBbMCwgMF0sXG4gICAgICBzdW5zOiBbXSxcbiAgICAgIHRpY2tzOiAwLFxuICAgICAgc2NvcmU6IDAsXG4gICAgICBsYXN0Q2FtZXJhUG9zaXRpb246IHNoaXAuZXllKCksXG4gICAgICBjYW1lcmE6IHNoaXAuY2FtZXJhKHNoaXAuZXllKCkpLFxuICAgICAgYXN0ZXJvaWRTcGVlZDogWzAsIDBdLFxuICAgICAgbGV2ZWw6IDAsXG4gICAgICBsZXZlbEZpbmlzaGVkQXQ6IG51bGwsXG4gICAgfSxcbiAgICBmcmVlY2FtOiB7XG4gICAgICBjYW1lcmE6IG5ldyBGcmVlQ2FtZXJhKHtcbiAgICAgICAgZXllOiB2ZWMzLmZyb21WYWx1ZXMoMCwgMCwgLTUpLFxuICAgICAgICBsb29rQXQ6IHZlYzMuZnJvbVZhbHVlcygwLCAwLCAxKSxcbiAgICAgICAgbG9va1VwOiB2ZWMzLmZyb21WYWx1ZXMoMCwgMSwgMCksXG4gICAgICAgIHdpZHRoOiBjYW52YXMud2lkdGgsXG4gICAgICAgIGhlaWdodDogY2FudmFzLmhlaWdodCxcbiAgICAgICAgZm92RGVncmVlczogU0hJUF9GT1ZfREVHUkVFU1swXSxcbiAgICAgICAgbmVhcjogRlJFRUNBTV9ORUFSX0JPVU5ELFxuICAgICAgICBmYXI6IEZSRUVDQU1fRkFSX0JPVU5ELFxuICAgICAgICBtb3ZlU3BlZWQ6IEZSRUVDQU1fREVGQVVMVF9NT1ZFX1NQRUVELFxuICAgICAgfSksXG4gICAgICBmcmVlY2FtTW9kZURlYm91bmNlcjogbmV3IERlYm91bmNlcihEYXRlLm5vdywgREVCT1VOQ0VfTVMpLFxuICAgICAgZ2VuZXJhbERlYm91bmNlcjogbmV3IERlYm91bmNlcihEYXRlLm5vdywgREVCT1VOQ0VfTVMpLFxuICAgICAgZm9nOiB0cnVlLFxuICAgICAgc2hvd1NoaXBDb2xsaXNpb25zOiBmYWxzZSxcbiAgICB9LFxuICAgIG1lbnU6IHtcbiAgICAgIGNhbWVyYTogbmV3IEZyZWVDYW1lcmEoe1xuICAgICAgICBleWU6IHZlYzMuZnJvbVZhbHVlcygwLCAwLCAwKSxcbiAgICAgICAgbG9va0F0OiB2ZWMzLmZyb21WYWx1ZXMoMCwgMCwgMSksXG4gICAgICAgIGxvb2tVcDogdmVjMy5mcm9tVmFsdWVzKDAsIDEsIDApLFxuICAgICAgICB3aWR0aDogY2FudmFzLndpZHRoLFxuICAgICAgICBoZWlnaHQ6IGNhbnZhcy5oZWlnaHQsXG4gICAgICAgIGZvdkRlZ3JlZXM6IFNISVBfRk9WX0RFR1JFRVNbMF0sXG4gICAgICAgIG5lYXI6IE5FQVJfQk9VTkQsXG4gICAgICAgIGZhcjogVklFV19ESVNUQU5DRSxcbiAgICAgICAgbW92ZVNwZWVkOiBGUkVFQ0FNX0RFRkFVTFRfTU9WRV9TUEVFRCxcbiAgICAgIH0pLFxuICAgICAgYXN0ZXJvaWRzOiBbXSxcbiAgICAgIHN1bnM6IFtdLFxuICAgICAgbW92aW5nQ2FtZXJhOiBmYWxzZSxcbiAgICAgIG1vdmVNb2RlRGVib3VuY2VyOiBuZXcgRGVib3VuY2VyKERhdGUubm93LCBERUJPVU5DRV9NUyksXG4gICAgfSxcbiAgfTtcblxuICAvLyBTZXQgdXAgbWVudVxuICBtZW51U2NlbmUoZ2FtZSk7XG5cbiAgcmV0dXJuIGdhbWU7XG59XG5cbmZ1bmN0aW9uKiBhbGxBc3Rlcm9pZHMoZ2FtZTogR2FtZSk6IEl0ZXJhYmxlPEFzdGVyb2lkPiB7XG4gIGZvciAoY29uc3QgdGllciBvZiBnYW1lLnBsYXkudGllcmVkQXN0ZXJvaWRzKSB7XG4gICAgeWllbGQqIHRpZXI7XG4gIH1cbn1cblxuZnVuY3Rpb24gbWVudVNjZW5lKGdhbWU6IEdhbWUpIHtcbiAgbGV0IGNhbWVyYSA9IGdhbWUubWVudS5jYW1lcmE7XG4gIGNhbWVyYS55YXdMZWZ0KGRlZ3JlZXMoLTMwKSk7XG4gIGNhbWVyYS5waXRjaFVwKGRlZ3JlZXMoLTIwKSk7XG4gIGxldCBzdW4gPSBuZXcgU2NlbmVPYmplY3QoZ2FtZS5nbCwgbW9kZWxzLlNVTik7XG4gIHN1bi50cmFuc2xhdGUodmVjMy5mcm9tVmFsdWVzKDMuNSwgLTQsIDEwKSk7XG4gIGdhbWUubWVudS5zdW5zLnB1c2goc3VuKTtcbiAgbGV0IGJhY2tsaWdodCA9IG5ldyBTY2VuZU9iamVjdChnYW1lLmdsLCBtb2RlbHMuU1VOKTtcbiAgYmFja2xpZ2h0LnRyYW5zbGF0ZSh2ZWMzLnNjYWxlQW5kQWRkKHZlYzMuY3JlYXRlKCksIGNhbWVyYS5leWUsIGNhbWVyYS5mb3J3YXJkLCAtNCkpO1xuICBnYW1lLm1lbnUuc3Vucy5wdXNoKGJhY2tsaWdodCk7XG59XG5cbmZ1bmN0aW9uKiBwbGF5T2JqZWN0cyhnYW1lOiBHYW1lKTogSXRlcmFibGU8U2NlbmVPYmplY3Q+IHtcbiAgeWllbGQqIGdhbWUucGxheS5zaGlwLm9iamVjdHMoKTtcbiAgaWYgKGdhbWUuZnJlZWNhbS5zaG93U2hpcENvbGxpc2lvbnMpIHtcbiAgICBmb3IgKGNvbnN0IHYgb2YgZ2FtZS5wbGF5LnNoaXAuY29sbGlzaW9uUG9pbnRzKCkpIHtcbiAgICAgIGxldCBvYmogPSBuZXcgU2NlbmVPYmplY3QoZ2FtZS5nbCwgbW9kZWxzLkRPVCk7XG4gICAgICBvYmoudHJhbnNsYXRlKHYpO1xuICAgICAgeWllbGQgb2JqO1xuICAgIH1cbiAgfVxuICBmb3IgKGNvbnN0IG0gb2YgZ2FtZS5wbGF5Lm1pc3NpbGVzKSB7XG4gICAgeWllbGQgbS5vYmo7XG4gIH1cbiAgZm9yIChjb25zdCBhIG9mIGFsbEFzdGVyb2lkcyhnYW1lKSkge1xuICAgIHlpZWxkIGEub2JqO1xuICB9XG4gIHlpZWxkKiBnYW1lLnBsYXkuc3Vucztcbn1cblxuZnVuY3Rpb24qIHBsYXlGcm9udE9iamVjdHMoZ2FtZTogR2FtZSk6IEl0ZXJhYmxlPFNjZW5lT2JqZWN0PiB7XG4gIHlpZWxkIGdhbWUucGxheS5zaGlwLnJldGljbGU7XG59XG5cbmZ1bmN0aW9uKiBwbGF5TGlnaHRzKGdhbWU6IEdhbWUpOiBJdGVyYWJsZTx2ZWMzPiB7XG4gIGZvciAoY29uc3Qgc3VuIG9mIGdhbWUucGxheS5zdW5zKSB7XG4gICAgeWllbGQgc3VuLnBvcygpO1xuICB9XG59XG5cbmZ1bmN0aW9uKiBtZW51T2JqZWN0cyhnYW1lOiBHYW1lKTogSXRlcmFibGU8U2NlbmVPYmplY3Q+IHtcbiAgZm9yIChjb25zdCBhIG9mIGdhbWUubWVudS5hc3Rlcm9pZHMpIHtcbiAgICB5aWVsZCBhLm9iajtcbiAgfVxuICB5aWVsZCogZ2FtZS5tZW51LnN1bnM7XG59XG5cbmZ1bmN0aW9uKiBtZW51TGlnaHRzKGdhbWU6IEdhbWUpOiBJdGVyYWJsZTx2ZWMzPiB7XG4gIGZvciAoY29uc3Qgc3VuIG9mIGdhbWUubWVudS5zdW5zKSB7XG4gICAgeWllbGQgc3VuLnBvcygpO1xuICB9XG59XG5cbi8vIFNjaGVkdWxlcyB0aGUgbmV4dCBmcmFtZSBiYXNlZCBvbiB0aGUgZ2FtZSBtb2RlXG5mdW5jdGlvbiBzY2hlZHVsZU5leHRGcmFtZShnYW1lOiBHYW1lKSB7XG4gIGlmIChnYW1lLm1vZGUgPT0gR2FtZU1vZGUuTWVudSkge1xuICAgIHJlcXVlc3RBbmltYXRpb25GcmFtZSgoKSA9PiBtZW51TG9vcChnYW1lKSk7XG4gIH0gZWxzZSBpZiAoZ2FtZS5tb2RlID09IEdhbWVNb2RlLlBhdXNlKSB7XG4gICAgcmVxdWVzdEFuaW1hdGlvbkZyYW1lKCgpID0+IHBhdXNlTG9vcChnYW1lKSk7XG4gIH0gZWxzZSBpZiAoZ2FtZS5tb2RlID09IEdhbWVNb2RlLlBsYXkpIHtcbiAgICByZXF1ZXN0QW5pbWF0aW9uRnJhbWUoKCkgPT4gcGxheUxvb3AoZ2FtZSkpO1xuICB9IGVsc2UgaWYgKGdhbWUubW9kZSA9PSBHYW1lTW9kZS5GcmVlY2FtKSB7XG4gICAgcmVxdWVzdEFuaW1hdGlvbkZyYW1lKCgpID0+IGRldkxvb3AoZ2FtZSkpO1xuICB9XG59XG5cbmZ1bmN0aW9uIHF1aXRHYW1lKGdhbWU6IEdhbWUpIHtcbiAgZGlzcGxheS50aW1lLmhpZGRlbiA9IHRydWU7XG4gIGRpc3BsYXkuc2NvcmUuaGlkZGVuID0gdHJ1ZTtcbiAgZGlzcGxheS5sZXZlbC5oaWRkZW4gPSB0cnVlO1xuXG4gIGRpc3BsYXkubWFpblRleHQuaW5uZXJIVE1MID0gXCJBc3Rlcm9pZHNcIjtcbiAgZGlzcGxheS5tYWluVGV4dC5oaWRkZW4gPSBmYWxzZTtcbiAgZGlzcGxheS5tZW51QnV0dG9uLmlubmVySFRNTCA9IFwiU3RhcnRcIjtcbiAgZGlzcGxheS5tZW51QnV0dG9uLmhpZGRlbiA9IGZhbHNlO1xuICBkaXNwbGF5Lm1lbnVCdXR0b24ub25jbGljayA9ICgpID0+IHtcbiAgICBwbGF5R2FtZShnYW1lLCAxKTtcbiAgfTtcbiAgZGlzcGxheS5tZW51QnV0dG9uMi5oaWRkZW4gPSB0cnVlO1xuXG4gIGdhbWUubW9kZSA9IEdhbWVNb2RlLk1lbnU7XG59XG5cbmZ1bmN0aW9uIGdhbWVPdmVyKGdhbWU6IEdhbWUpIHtcbiAgZGlzcGxheS50aW1lLmhpZGRlbiA9IGZhbHNlO1xuICBkaXNwbGF5LnNjb3JlLmhpZGRlbiA9IGZhbHNlO1xuICBkaXNwbGF5LmxldmVsLmhpZGRlbiA9IGZhbHNlO1xuXG4gIGRpc3BsYXkubWFpblRleHQuaW5uZXJIVE1MID0gXCJHYW1lIE92ZXJcIjtcbiAgZGlzcGxheS5tYWluVGV4dC5oaWRkZW4gPSBmYWxzZTtcbiAgZGlzcGxheS5tZW51QnV0dG9uLmlubmVySFRNTCA9IFwiUmVzdGFydFwiO1xuICBkaXNwbGF5Lm1lbnVCdXR0b24uaGlkZGVuID0gZmFsc2U7XG4gIGRpc3BsYXkubWVudUJ1dHRvbi5vbmNsaWNrID0gKCkgPT4ge1xuICAgIHBsYXlHYW1lKGdhbWUsIDEpO1xuICB9O1xuICBkaXNwbGF5Lm1lbnVCdXR0b24yLmlubmVySFRNTCA9IFwiUXVpdFwiO1xuICBkaXNwbGF5Lm1lbnVCdXR0b24yLmhpZGRlbiA9IGZhbHNlO1xuICBkaXNwbGF5Lm1lbnVCdXR0b24yLm9uY2xpY2sgPSAoKSA9PiB7XG4gICAgcXVpdEdhbWUoZ2FtZSk7XG4gIH07XG5cbiAgZ2FtZS5wbGF5LnNoaXAudGhydXN0ZXJTZngucGF1c2UoKTtcblxuICBkb2N1bWVudC5leGl0UG9pbnRlckxvY2soKTtcbiAgZ2FtZS5tb2RlID0gR2FtZU1vZGUuUGF1c2U7XG59XG5cbmZ1bmN0aW9uIHBhdXNlR2FtZShnYW1lOiBHYW1lKSB7XG4gIGRpc3BsYXkuc2NvcmUuaGlkZGVuID0gZmFsc2U7XG4gIGRpc3BsYXkudGltZS5oaWRkZW4gPSBmYWxzZTtcbiAgZGlzcGxheS5sZXZlbC5oaWRkZW4gPSBmYWxzZTtcblxuICBkaXNwbGF5Lm1haW5UZXh0LmlubmVySFRNTCA9IFwiUGF1c2VcIjtcbiAgZGlzcGxheS5tYWluVGV4dC5oaWRkZW4gPSBmYWxzZTtcbiAgZGlzcGxheS5tZW51QnV0dG9uLmlubmVySFRNTCA9IFwiVW5wYXVzZVwiO1xuICBkaXNwbGF5Lm1lbnVCdXR0b24uaGlkZGVuID0gZmFsc2U7XG4gIGRpc3BsYXkubWVudUJ1dHRvbi5vbmNsaWNrID0gKCkgPT4ge1xuICAgIHVucGF1c2VHYW1lKGdhbWUpO1xuICB9O1xuICBkaXNwbGF5Lm1lbnVCdXR0b24yLmlubmVySFRNTCA9IFwiUXVpdFwiO1xuICBkaXNwbGF5Lm1lbnVCdXR0b24yLmhpZGRlbiA9IGZhbHNlO1xuICBkaXNwbGF5Lm1lbnVCdXR0b24yLm9uY2xpY2sgPSAoKSA9PiB7XG4gICAgcXVpdEdhbWUoZ2FtZSk7XG4gIH07XG5cbiAgTVVTSUMucGF1c2UoKTtcbiAgZ2FtZS5wbGF5LnNoaXAudGhydXN0ZXJTZngucGF1c2UoKTtcblxuICBkb2N1bWVudC5leGl0UG9pbnRlckxvY2soKTtcbiAgZ2FtZS5tb2RlID0gR2FtZU1vZGUuUGF1c2U7XG59XG5cbmZ1bmN0aW9uIHVucGF1c2VHYW1lKGdhbWU6IEdhbWUpIHtcbiAgZGlzcGxheS50aW1lLmhpZGRlbiA9IGZhbHNlO1xuICBkaXNwbGF5LnNjb3JlLmhpZGRlbiA9IGZhbHNlO1xuICBkaXNwbGF5LmxldmVsLmhpZGRlbiA9IGZhbHNlO1xuXG4gIGRpc3BsYXkubWFpblRleHQuaGlkZGVuID0gdHJ1ZTtcbiAgZGlzcGxheS5tZW51QnV0dG9uLmhpZGRlbiA9IHRydWU7XG4gIGRpc3BsYXkubWVudUJ1dHRvbjIuaGlkZGVuID0gdHJ1ZTtcblxuICBNVVNJQy5wbGF5KCk7XG5cbiAgY2FudmFzLnJlcXVlc3RQb2ludGVyTG9jaygpO1xuICBnYW1lLm1vZGUgPSBHYW1lTW9kZS5QbGF5O1xufVxuXG5mdW5jdGlvbiBwbGF5R2FtZShnYW1lOiBHYW1lLCBsZXZlbDogbnVtYmVyKSB7XG4gIGRpc3BsYXkudGltZS5oaWRkZW4gPSBmYWxzZTtcbiAgZGlzcGxheS5zY29yZS5oaWRkZW4gPSBmYWxzZTtcbiAgZGlzcGxheS5sZXZlbC5oaWRkZW4gPSBmYWxzZTtcblxuICBkaXNwbGF5Lm1haW5UZXh0LmhpZGRlbiA9IHRydWU7XG4gIGRpc3BsYXkubWVudUJ1dHRvbi5oaWRkZW4gPSB0cnVlO1xuICBkaXNwbGF5Lm1lbnVCdXR0b24yLmhpZGRlbiA9IHRydWU7XG5cbiAgaWYgKGxldmVsID09IDEpIHtcbiAgICBNVVNJQy5wbGF5KCk7XG4gICAgTVVTSUMuY3VycmVudFRpbWUgPSAwLjA7XG4gIH1cblxuICBjYW52YXMucmVxdWVzdFBvaW50ZXJMb2NrKCk7XG4gIGdhbWUubW9kZSA9IEdhbWVNb2RlLlBsYXk7XG5cbiAgZ2FtZS5wbGF5LnNoaXAgPSBuZXcgU2hpcChnYW1lLmdsKTtcbiAgZ2FtZS5wbGF5Lm1pc3NpbGVzID0gW107XG4gIGdhbWUucGxheS50aWVyZWRBc3Rlcm9pZHMgPSBbW10sIFtdXTtcbiAgZ2FtZS5wbGF5Lm51bUFzdGVyb2lkcyA9IG51bUFzdGVyb2lkcyhsZXZlbCk7XG4gIGdhbWUucGxheS5hc3Rlcm9pZFNwZWVkID0gYXN0ZXJvaWRTcGVlZChsZXZlbCk7XG4gIGdhbWUucGxheS5zdW5zID0gW107XG4gIGdhbWUucGxheS5zY29yZSA9IDA7XG4gIGdhbWUucGxheS50aWNrcyA9IDA7XG4gIGdhbWUucGxheS5sYXN0Q2FtZXJhUG9zaXRpb24gPSBnYW1lLnBsYXkuc2hpcC5leWUoKTtcbiAgZ2FtZS5wbGF5LmNhbWVyYSA9IGdhbWUucGxheS5zaGlwLmNhbWVyYShnYW1lLnBsYXkuc2hpcC5leWUoKSk7XG4gIGdhbWUucGxheS5sZXZlbCA9IGxldmVsO1xuICBnYW1lLnBsYXkubGV2ZWxGaW5pc2hlZEF0ID0gbnVsbDtcbiAgdXBkYXRlU2NvcmUoZ2FtZSk7XG4gIHVwZGF0ZUNsb2NrKGdhbWUpO1xuICB1cGRhdGVMZXZlbChnYW1lKTtcblxuICBmb3IgKGNvbnN0IFt0aWVyLCBudW1Bc3Rlcm9pZHNdIG9mIGdhbWUucGxheS5udW1Bc3Rlcm9pZHMuZW50cmllcygpKSB7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW1Bc3Rlcm9pZHM7IGkrKykge1xuICAgICAgbGV0IHBvcyA9IHJhbmRvbUFyYyhnYW1lLnBsYXkuc2hpcC5mb3J3YXJkLCBBU1RFUk9JRF9TUEFXTl9BUkMpO1xuICAgICAgbGV0IHZlbG9jaXR5ID0gcmFuZG9tQXJjKHZlYzMuc2NhbGUodmVjMy5jcmVhdGUoKSwgcG9zLCAtMSksIEFTVEVST0lEX1ZFTE9DSVRZX0FSQyk7XG4gICAgICB2ZWMzLnNjYWxlKHBvcywgcG9zLCByYW5kZiguLi5BU1RFUk9JRF9JTklUSUFMX1NQQVdOX0RJU1RBTkNFKSk7XG4gICAgICB2ZWMzLnNjYWxlKHZlbG9jaXR5LCB2ZWxvY2l0eSwgcmFuZGYoLi4uZ2FtZS5wbGF5LmFzdGVyb2lkU3BlZWQpKTtcblxuICAgICAgbGV0IGFzdGVyb2lkID0gbmV3IEFzdGVyb2lkKGdhbWUuZ2wsIHRpZXIsIHZlbG9jaXR5KTtcbiAgICAgIGFzdGVyb2lkLnZlbG9jaXR5ID0gdmVsb2NpdHk7XG4gICAgICBhc3Rlcm9pZC5vYmoudHJhbnNsYXRlKHBvcyk7XG4gICAgICBnYW1lLnBsYXkudGllcmVkQXN0ZXJvaWRzW3RpZXJdLnB1c2goYXN0ZXJvaWQpO1xuICAgIH1cbiAgfVxuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgcmVuZGVyLk5VTV9TVU5TOyBpKyspIHtcbiAgICAvLyBUT0RPOiBFbnN1cmUgc3VucyBhcmVuJ3QgY2xvc2UgdG9nZXRoZXI/XG4gICAgbGV0IHN1biA9IG5ldyBTY2VuZU9iamVjdChnYW1lLmdsLCBtb2RlbHMuU1VOKTtcbiAgICBzdW4udHJhbnNsYXRlKHZlYzMucmFuZG9tKHZlYzMuY3JlYXRlKCksIHJhbmRmKC4uLlNVTl9JTklUSUFMX1NQQVdOX0RJU1RBTkNFKSkpO1xuICAgIGdhbWUucGxheS5zdW5zLnB1c2goc3VuKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBkZXZNb2RlKGdhbWU6IEdhbWUpIHtcbiAgZ2FtZS5mcmVlY2FtLmNhbWVyYS5zeW5jKGdhbWUucGxheS5zaGlwLCBnYW1lLnBsYXkuY2FtZXJhKTtcbiAgZ2FtZS5tb2RlID0gR2FtZU1vZGUuRnJlZWNhbTtcbn1cblxuZnVuY3Rpb24gdW5kZXZNb2RlKGdhbWU6IEdhbWUpIHtcbiAgZ2FtZS5tb2RlID0gR2FtZU1vZGUuUGxheTtcbn1cblxuZnVuY3Rpb24gY2hlY2tOZXh0TGV2ZWwoZ2FtZTogR2FtZSkge1xuICBpZiAoZ2FtZS5wbGF5LmxldmVsRmluaXNoZWRBdCAhPSBudWxsKSB7XG4gICAgLy8gV2UnZXZlIGZpbmlzaGVkIHRoZSBsZXZlbFxuICAgIGlmIChnYW1lLnBsYXkudGlja3MgLSBnYW1lLnBsYXkubGV2ZWxGaW5pc2hlZEF0IDwgTEVWRUxfV0FJVF9USUNLUykge1xuICAgICAgcmV0dXJuO1xuICAgIH0gZWxzZSB7XG4gICAgICBwbGF5R2FtZShnYW1lLCBnYW1lLnBsYXkubGV2ZWwgKyAxKTtcbiAgICB9XG4gIH1cblxuICBpZiAoZ2FtZS5wbGF5Lm51bUFzdGVyb2lkcy5ldmVyeSgobikgPT4gbiA9PSAwKSkge1xuICAgIGdhbWUucGxheS5sZXZlbEZpbmlzaGVkQXQgPSBnYW1lLnBsYXkudGlja3M7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIEZyZWVDYW1lcmEge1xuICBwdWJsaWMgZXllOiB2ZWMzO1xuICBwdWJsaWMgZm9yd2FyZDogdmVjMztcbiAgcHVibGljIHVwOiB2ZWMzO1xuICBwdWJsaWMgcmlnaHQ6IHZlYzM7XG5cbiAgcHVibGljIG1vdmVTcGVlZDogbnVtYmVyO1xuXG4gIHB1YmxpYyByZWFkb25seSB2aWV3aW5nVHJhbnNmb3JtOiBtYXQ0O1xuICBwdWJsaWMgcmVhZG9ubHkgcGVyc3BlY3RpdmVUcmFuc2Zvcm06IG1hdDQ7XG5cbiAgY29uc3RydWN0b3Ioe1xuICAgIGV5ZSxcbiAgICBsb29rQXQsXG4gICAgbG9va1VwLFxuICAgIHdpZHRoLFxuICAgIGhlaWdodCxcbiAgICBmb3ZEZWdyZWVzLFxuICAgIG5lYXIsXG4gICAgZmFyLFxuICAgIG1vdmVTcGVlZCxcbiAgfToge1xuICAgIGV5ZTogdmVjMztcbiAgICBsb29rQXQ6IHZlYzM7XG4gICAgbG9va1VwOiB2ZWMzO1xuICAgIHdpZHRoOiBudW1iZXI7XG4gICAgaGVpZ2h0OiBudW1iZXI7XG4gICAgZm92RGVncmVlczogbnVtYmVyO1xuICAgIG5lYXI6IG51bWJlcjtcbiAgICBmYXI6IG51bWJlcjtcbiAgICBtb3ZlU3BlZWQ6IG51bWJlcjtcbiAgfSkge1xuICAgIHRoaXMuZXllID0gZXllO1xuICAgIHRoaXMuZm9yd2FyZCA9IGxvb2tBdDtcbiAgICB0aGlzLnVwID0gbG9va1VwO1xuICAgIHRoaXMucmlnaHQgPSB2ZWMzLmNyb3NzKHZlYzMuY3JlYXRlKCksIGxvb2tBdCwgbG9va1VwKTtcblxuICAgIHRoaXMubW92ZVNwZWVkID0gbW92ZVNwZWVkO1xuXG4gICAgdGhpcy52aWV3aW5nVHJhbnNmb3JtID0gbWF0NC5jcmVhdGUoKTtcbiAgICB0aGlzLnBlcnNwZWN0aXZlVHJhbnNmb3JtID0gbWF0NC5jcmVhdGUoKTtcbiAgICB0aGlzLnJlZnJlc2hWaWV3KCk7XG4gICAgbWF0NC5wZXJzcGVjdGl2ZShcbiAgICAgIHRoaXMucGVyc3BlY3RpdmVUcmFuc2Zvcm0sXG4gICAgICBkZWdyZWVzKGZvdkRlZ3JlZXMpLCAvLyBGT1YgeVxuICAgICAgd2lkdGggLyBoZWlnaHQsIC8vIGFzcGVjdCByYXRpbyAoVy9IKVxuICAgICAgbmVhciwgLy8gbmVhciBib3VuZFxuICAgICAgZmFyLCAvLyBmYXIgYm91bmRcbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSByZWZyZXNoVmlldygpIHtcbiAgICBtYXQ0Lmxvb2tBdChcbiAgICAgIHRoaXMudmlld2luZ1RyYW5zZm9ybSxcbiAgICAgIHRoaXMuZXllLCAvLyBleWVcbiAgICAgIHZlYzMuYWRkKHZlYzMuY3JlYXRlKCksIHRoaXMuZXllLCB0aGlzLmZvcndhcmQpLCAvLyBjZW50ZXJcbiAgICAgIHRoaXMudXAsIC8vIHVwXG4gICAgKTtcbiAgfVxuXG4gIG1vdmUoZGlyZWN0aW9uOiB2ZWMzLCBkaXN0YW5jZTogbnVtYmVyKSB7XG4gICAgdmVjMy5zY2FsZUFuZEFkZCh0aGlzLmV5ZSwgdGhpcy5leWUsIGRpcmVjdGlvbiwgZGlzdGFuY2UpO1xuICAgIHRoaXMucmVmcmVzaFZpZXcoKTtcbiAgfVxuXG4gIHBpdGNoVXAocmFkczogbnVtYmVyKSB7XG4gICAgdGhpcy50cmFuc2Zvcm1WaWV3KG1hdDQuZnJvbVJvdGF0aW9uKG1hdDQuY3JlYXRlKCksIHJhZHMsIHRoaXMucmlnaHQpKTtcbiAgICB0aGlzLnJlZnJlc2hWaWV3KCk7XG4gIH1cblxuICB5YXdMZWZ0KHJhZHM6IG51bWJlcikge1xuICAgIHRoaXMudHJhbnNmb3JtVmlldyhtYXQ0LmZyb21Sb3RhdGlvbihtYXQ0LmNyZWF0ZSgpLCByYWRzLCB0aGlzLnVwKSk7XG4gICAgdGhpcy5yZWZyZXNoVmlldygpO1xuICB9XG5cbiAgcm9sbFJpZ2h0KHJhZHM6IG51bWJlcikge1xuICAgIHRoaXMudHJhbnNmb3JtVmlldyhtYXQ0LmZyb21Sb3RhdGlvbihtYXQ0LmNyZWF0ZSgpLCByYWRzLCB0aGlzLmZvcndhcmQpKTtcbiAgICB0aGlzLnJlZnJlc2hWaWV3KCk7XG4gIH1cblxuICBwcml2YXRlIHRyYW5zZm9ybVZpZXcodHJhbnNmb3JtOiBtYXQ0KSB7XG4gICAgdmVjMy50cmFuc2Zvcm1NYXQ0KHRoaXMuZm9yd2FyZCwgdGhpcy5mb3J3YXJkLCB0cmFuc2Zvcm0pO1xuICAgIHZlYzMudHJhbnNmb3JtTWF0NCh0aGlzLnVwLCB0aGlzLnVwLCB0cmFuc2Zvcm0pO1xuICAgIHZlYzMudHJhbnNmb3JtTWF0NCh0aGlzLnJpZ2h0LCB0aGlzLnJpZ2h0LCB0cmFuc2Zvcm0pO1xuICB9XG5cbiAgc3luYyhzaGlwOiBTaGlwLCBjYW06IENhbWVyYSkge1xuICAgIHZlYzMuY29weSh0aGlzLmZvcndhcmQsIHNoaXAuZm9yd2FyZCk7XG4gICAgdmVjMy5jb3B5KHRoaXMudXAsIHNoaXAudXApO1xuICAgIHZlYzMuY29weSh0aGlzLnJpZ2h0LCBzaGlwLnJpZ2h0KTtcbiAgICB2ZWMzLmNvcHkodGhpcy5leWUsIGNhbS5leWUpO1xuICAgIG1hdDQuY29weSh0aGlzLnZpZXdpbmdUcmFuc2Zvcm0sIGNhbS52aWV3aW5nVHJhbnNmb3JtKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBoYW5kbGVLZXlib2FyZChnYW1lOiBHYW1lKSB7XG4gIGxldCBrZXlib2FyZCA9IGdhbWUuaW5wdXRzLmtleWJvYXJkO1xuXG4gIGlmIChnYW1lLmlucHV0cy5tb3VzZURvd24pIHtcbiAgICBnYW1lLnBsYXkuc2hpcC50cnlGaXJlKGdhbWUpO1xuICB9XG5cbiAgaWYgKGtleWJvYXJkLnByZXNzZWQuaGFzKFwiS2V5UFwiKSkge1xuICAgIGdhbWUuaW5wdXRzLnBhdXNlRGVib3VuY2VyLnRyeSgoKSA9PiBwYXVzZUdhbWUoZ2FtZSkpO1xuICB9XG5cbiAgaWYgKGtleWJvYXJkLnByZXNzZWQuaGFzKFwiS2V5RVwiKSkge1xuICAgIGdhbWUucGxheS5zaGlwLnJvbGxSaWdodChTSElQX1JPTExfU1BFRUQpO1xuICB9XG4gIGlmIChrZXlib2FyZC5wcmVzc2VkLmhhcyhcIktleVFcIikpIHtcbiAgICBnYW1lLnBsYXkuc2hpcC5yb2xsUmlnaHQoLVNISVBfUk9MTF9TUEVFRCk7XG4gIH1cblxuICBpZiAoa2V5Ym9hcmQucHJlc3NlZC5oYXMoXCJLZXlXXCIpKSB7XG4gICAgZ2FtZS5wbGF5LnNoaXAuc2V0VGhyb3R0bGUoMS4wKTtcbiAgfSBlbHNlIHtcbiAgICBnYW1lLnBsYXkuc2hpcC5zZXRUaHJvdHRsZSgwLjApO1xuICB9XG5cbiAgaWYgKGtleWJvYXJkLnByZXNzZWQuaGFzKFwiU3BhY2VcIikpIHtcbiAgICBnYW1lLnBsYXkuc2hpcC50cnlGaXJlKGdhbWUpO1xuICB9XG59XG5cbmZ1bmN0aW9uIGhhbmRsZUdhbWVwYWQoZ2FtZTogR2FtZSkge1xuICBsZXQgZ2FtZXBhZCA9IG5hdmlnYXRvci5nZXRHYW1lcGFkcygpW2dhbWUuaW5wdXRzLmdhbWVwYWRdO1xuICBpZiAoZ2FtZXBhZCA9PSBudWxsKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgY29uc3QgUElUQ0hfQVhJUyA9IDE7XG4gIGNvbnN0IFlBV19BWElTID0gMDtcbiAgY29uc3QgUk9MTF9BWElTID0gMjtcbiAgY29uc3QgVEhST1RUTEVfVFJJR0dFUiA9IDc7XG4gIGNvbnN0IEJVVFRPTl9BID0gMDtcbiAgY29uc3QgQlVUVE9OX1IgPSA1O1xuXG4gIGdhbWUucGxheS5zaGlwLnBpdGNoVXAoU0hJUF9HQU1FUEFEX1RVUk5fU1BFRUQgKiBnYW1lcGFkLmF4ZXNbUElUQ0hfQVhJU10pO1xuICBnYW1lLnBsYXkuc2hpcC55YXdMZWZ0KC1TSElQX0dBTUVQQURfVFVSTl9TUEVFRCAqIGdhbWVwYWQuYXhlc1tZQVdfQVhJU10pO1xuICBnYW1lLnBsYXkuc2hpcC5yb2xsUmlnaHQoU0hJUF9HQU1FUEFEX1RVUk5fU1BFRUQgKiBnYW1lcGFkLmF4ZXNbUk9MTF9BWElTXSk7XG4gIGdhbWUucGxheS5zaGlwLnNldFRocm90dGxlKGdhbWVwYWQuYnV0dG9uc1tUSFJPVFRMRV9UUklHR0VSXS52YWx1ZSk7XG4gIGlmIChnYW1lcGFkLmJ1dHRvbnNbQlVUVE9OX1JdLnByZXNzZWQgfHwgZ2FtZXBhZC5idXR0b25zW0JVVFRPTl9BXS5wcmVzc2VkKSB7XG4gICAgZ2FtZS5wbGF5LnNoaXAudHJ5RmlyZShnYW1lKTtcbiAgfVxuXG4gIGNvbnNvbGUubG9nKGdhbWVwYWQpO1xufVxuXG5mdW5jdGlvbiBzcGF3blN1bnMoZ2FtZTogR2FtZSkge1xuICAvLyBUT0RPOiBNYWtlIHN1cmUgdGhlIHN1bnMgbmV2ZXIgYXBwZWFyIGNsb3NlIHRvZ2V0aGVyP1xuICB3aGlsZSAoZ2FtZS5wbGF5LnN1bnMubGVuZ3RoIDwgcmVuZGVyLk5VTV9TVU5TKSB7XG4gICAgbGV0IHN1biA9IG5ldyBTY2VuZU9iamVjdChnYW1lLmdsLCBtb2RlbHMuU1VOKTtcbiAgICBsZXQgcG9zOiB2ZWMzO1xuICAgIGlmICh2ZWMzLmxlbmd0aChnYW1lLnBsYXkuc2hpcC52ZWxvY2l0eSkgPCBTSElQX1ZFTE9DSVRZX0VQU0lMT04pIHtcbiAgICAgIHBvcyA9IHZlYzMucmFuZG9tKHZlYzMuY3JlYXRlKCkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgZGlyZWN0aW9uID0gdmVjMy5ub3JtYWxpemUodmVjMy5jcmVhdGUoKSwgZ2FtZS5wbGF5LnNoaXAudmVsb2NpdHkpO1xuICAgICAgcG9zID0gcmFuZG9tQXJjUmFuZ2UoZGlyZWN0aW9uLCBTVU5fU1BBV05fQVJDKTtcbiAgICB9XG4gICAgdmVjMy5zY2FsZUFuZEFkZChwb3MsIGdhbWUucGxheS5zaGlwLm9iai5wb3MoKSwgcG9zLCBTVU5fU1BBV05fRElTVEFOQ0UpO1xuICAgIHN1bi50cmFuc2xhdGUocG9zKTtcbiAgICBnYW1lLnBsYXkuc3Vucy5wdXNoKHN1bik7XG4gIH1cbn1cblxuLy8gTWFrZSB0aGUgb2JqZWN0IGFwcGVhciB2YWd1ZWx5IGluIHRoZSBkaXJlY3Rpb24gd2UncmUgZ29pbmdcbmZ1bmN0aW9uIHNwYXduTWVudUFzdGVyb2lkcyhnYW1lOiBHYW1lKSB7XG4gIGxldCBjYW1lcmEgPSBnYW1lLm1lbnUuY2FtZXJhO1xuICB3aGlsZSAoZ2FtZS5tZW51LmFzdGVyb2lkcy5sZW5ndGggPCBNRU5VX05VTV9BU1RFUk9JRFMpIHtcbiAgICBsZXQgcG9zID0gcmFuZG9tQXJjKGNhbWVyYS5mb3J3YXJkLCBNRU5VX0FTVEVST0lEX1NQQVdOX0FSQyk7XG4gICAgLy8gTm93IGdlbmVyYXRlIGEgdmVsb2NpdHkgYXJjIGluIHRoZSBvcHBvc2l0ZSBkaXJlY3Rpb25cbiAgICBsZXQgdmVsb2NpdHkgPSByYW5kb21BcmNSYW5nZSh2ZWMzLnNjYWxlKHZlYzMuY3JlYXRlKCksIHBvcywgLTEpLCBNRU5VX0FTVEVST0lEX1ZFTE9DSVRZX0FSQyk7XG4gICAgdmVjMy5zY2FsZUFuZEFkZChwb3MsIGNhbWVyYS5leWUsIHBvcywgTUVOVV9BU1RFUk9JRF9TUEFXTl9ESVNUQU5DRSk7XG4gICAgdmVjMy5zY2FsZSh2ZWxvY2l0eSwgdmVsb2NpdHksIHJhbmRmKC4uLk1FTlVfQVNURVJPSURfU1BFRUQpKTtcblxuICAgIGxldCBhc3Rlcm9pZCA9IG5ldyBBc3Rlcm9pZChnYW1lLmdsLCAxLCB2ZWxvY2l0eSk7XG4gICAgYXN0ZXJvaWQudmVsb2NpdHkgPSB2ZWxvY2l0eTtcbiAgICBhc3Rlcm9pZC5vYmoudHJhbnNsYXRlKHBvcyk7XG4gICAgZ2FtZS5tZW51LmFzdGVyb2lkcy5wdXNoKGFzdGVyb2lkKTtcbiAgfVxufVxuXG4vLyBNYWtlIHRoZSBvYmplY3QgYXBwZWFyIHZhZ3VlbHkgaW4gdGhlIGRpcmVjdGlvbiB3ZSdyZSBnb2luZ1xuZnVuY3Rpb24gZGVzcGF3bk1lbnVBc3Rlcm9pZHMoZ2FtZTogR2FtZSkge1xuICBsZXQgZGVhZEFzdGVyb2lkczogbnVtYmVyW10gPSBbXTtcbiAgZm9yIChjb25zdCBbYXN0ZXJvaWRJZCwgYXN0ZXJvaWRdIG9mIGdhbWUubWVudS5hc3Rlcm9pZHMuZW50cmllcygpKSB7XG4gICAgaWYgKHZlYzMuZGlzdGFuY2UoZ2FtZS5tZW51LmNhbWVyYS5leWUsIGFzdGVyb2lkLm9iai5wb3MoKSkgPiBBU1RFUk9JRF9ERVNQQVdOX0RJU1RBTkNFKSB7XG4gICAgICBkZWFkQXN0ZXJvaWRzLnB1c2goYXN0ZXJvaWRJZCk7XG4gICAgfVxuICB9XG4gIGZvciAobGV0IGkgPSBkZWFkQXN0ZXJvaWRzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgZ2FtZS5tZW51LmFzdGVyb2lkcy5zcGxpY2UoZGVhZEFzdGVyb2lkc1tpXSwgMSk7XG4gIH1cbn1cblxuLy8gTWFrZSB0aGUgb2JqZWN0IGFwcGVhciB2YWd1ZWx5IGluIHRoZSBkaXJlY3Rpb24gd2UncmUgZ29pbmdcbmZ1bmN0aW9uIHNwYXduQXN0ZXJvaWRzKGdhbWU6IEdhbWUpIHtcbiAgZm9yIChsZXQgdGllciA9IDA7IHRpZXIgPCBBU1RFUk9JRF9USUVSUzsgdGllcisrKSB7XG4gICAgd2hpbGUgKGdhbWUucGxheS50aWVyZWRBc3Rlcm9pZHNbdGllcl0ubGVuZ3RoIDwgZ2FtZS5wbGF5Lm51bUFzdGVyb2lkc1t0aWVyXSkge1xuICAgICAgbGV0IHBvcyA9IHJhbmRvbUFyYyhnYW1lLnBsYXkuc2hpcC5mb3J3YXJkLCBBU1RFUk9JRF9TUEFXTl9BUkMpO1xuICAgICAgLy8gTm93IGdlbmVyYXRlIGEgdmVsb2NpdHkgYXJjIGluIHRoZSBvcHBvc2l0ZSBkaXJlY3Rpb25cbiAgICAgIGxldCB2ZWxvY2l0eSA9IHJhbmRvbUFyYyhcbiAgICAgICAgdmVjMy5zY2FsZSh2ZWMzLmNyZWF0ZSgpLCBnYW1lLnBsYXkuc2hpcC5mb3J3YXJkLCAtMSksXG4gICAgICAgIEFTVEVST0lEX1ZFTE9DSVRZX0FSQyxcbiAgICAgICk7XG4gICAgICB2ZWMzLnNjYWxlQW5kQWRkKHBvcywgZ2FtZS5wbGF5LnNoaXAub2JqLnBvcygpLCBwb3MsIEFTVEVST0lEX1NQQVdOX0RJU1RBTkNFKTtcbiAgICAgIHZlYzMuc2NhbGUodmVsb2NpdHksIHZlbG9jaXR5LCByYW5kZiguLi5nYW1lLnBsYXkuYXN0ZXJvaWRTcGVlZCkpO1xuXG4gICAgICBsZXQgYXN0ZXJvaWQgPSBuZXcgQXN0ZXJvaWQoZ2FtZS5nbCwgdGllciwgdmVsb2NpdHkpO1xuICAgICAgYXN0ZXJvaWQudmVsb2NpdHkgPSB2ZWxvY2l0eTtcbiAgICAgIGFzdGVyb2lkLm9iai50cmFuc2xhdGUocG9zKTtcbiAgICAgIGdhbWUucGxheS50aWVyZWRBc3Rlcm9pZHNbdGllcl0ucHVzaChhc3Rlcm9pZCk7XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIGRlc3Bhd25TdW5zKGdhbWU6IEdhbWUpIHtcbiAgbGV0IGRlYWRTdW5zOiBudW1iZXJbXSA9IFtdO1xuICBmb3IgKGNvbnN0IFtzdW5JZCwgc3VuXSBvZiBnYW1lLnBsYXkuc3Vucy5lbnRyaWVzKCkpIHtcbiAgICBpZiAodmVjMy5kaXN0YW5jZShnYW1lLnBsYXkuc2hpcC5vYmoucG9zKCksIHN1bi5wb3MoKSkgPiBTVU5fREVTUEFXTl9ESVNUQU5DRSkge1xuICAgICAgZGVhZFN1bnMucHVzaChzdW5JZCk7XG4gICAgfVxuICB9XG4gIGZvciAobGV0IGkgPSBkZWFkU3Vucy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIGdhbWUucGxheS5zdW5zLnNwbGljZShkZWFkU3Vuc1tpXSwgMSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gZGVzcGF3bkFzdGVyb2lkcyhnYW1lOiBHYW1lKSB7XG4gIGxldCBkZWFkQXN0ZXJvaWRzOiBUaWVyZWQ8bnVtYmVyW10+ID0gW1tdLCBbXV07XG4gIGZvciAoY29uc3QgW3RpZXIsIGFzdGVyb2lkc10gb2YgZ2FtZS5wbGF5LnRpZXJlZEFzdGVyb2lkcy5lbnRyaWVzKCkpIHtcbiAgICBmb3IgKGNvbnN0IFthc3Rlcm9pZElkLCBhc3Rlcm9pZF0gb2YgYXN0ZXJvaWRzLmVudHJpZXMoKSkge1xuICAgICAgaWYgKHZlYzMuZGlzdGFuY2UoZ2FtZS5wbGF5LnNoaXAub2JqLnBvcygpLCBhc3Rlcm9pZC5vYmoucG9zKCkpID4gQVNURVJPSURfREVTUEFXTl9ESVNUQU5DRSkge1xuICAgICAgICBkZWFkQXN0ZXJvaWRzW3RpZXJdLnB1c2goYXN0ZXJvaWRJZCk7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIGZvciAoY29uc3QgW3RpZXIsIGRlYWRdIG9mIGRlYWRBc3Rlcm9pZHMuZW50cmllcygpKSB7XG4gICAgZm9yIChsZXQgaSA9IGRlYWQubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgIGdhbWUucGxheS50aWVyZWRBc3Rlcm9pZHNbdGllcl0uc3BsaWNlKGRlYWRbaV0sIDEpO1xuICAgIH1cbiAgfVxufVxuXG5mdW5jdGlvbiBkZXNwYXduTWlzc2lsZXMoZ2FtZTogR2FtZSkge1xuICAvLyBUT0RPOiBVc2UgYSBxdWV1ZSBvciBzb21ldGhpbmcgbW9yZSBlZmZpY2llbnQ/XG4gIHdoaWxlIChcbiAgICBnYW1lLnBsYXkubWlzc2lsZXMubGVuZ3RoID4gMCAmJlxuICAgIGdhbWUucGxheS50aWNrcyAtIGdhbWUucGxheS5taXNzaWxlc1swXS5iaXJ0aCA+IE1JU1NJTEVfTElGRV9USUNLU1xuICApIHtcbiAgICBnYW1lLnBsYXkubWlzc2lsZXMuc2hpZnQoKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBoYW5kbGVEZWFkQXN0ZXJvaWRzKGdhbWU6IEdhbWUpIHtcbiAgZm9yIChsZXQgdGllciA9IDA7IHRpZXIgPCBBU1RFUk9JRF9USUVSUzsgdGllcisrKSB7XG4gICAgZm9yIChsZXQgaSA9IGdhbWUucGxheS50aWVyZWRBc3Rlcm9pZHNbdGllcl0ubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgIGxldCBhc3Rlcm9pZCA9IGdhbWUucGxheS50aWVyZWRBc3Rlcm9pZHNbdGllcl1baV07XG4gICAgICBpZiAoYXN0ZXJvaWQuaGVhbHRoIDw9IDApIHtcbiAgICAgICAgaWYgKHRpZXIgKyAxIDwgQVNURVJPSURfVElFUlMpIHtcbiAgICAgICAgICBsZXQgY2hpbGRyZW4gPSBhc3Rlcm9pZC5zcGxpdChnYW1lLmdsKTtcbiAgICAgICAgICBnYW1lLnBsYXkudGllcmVkQXN0ZXJvaWRzW3RpZXIgKyAxXS5wdXNoKC4uLmNoaWxkcmVuKTtcbiAgICAgICAgICBnYW1lLnBsYXkubnVtQXN0ZXJvaWRzW3RpZXIgKyAxXSArPSBjaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgIH1cbiAgICAgICAgZ2FtZS5wbGF5LnRpZXJlZEFzdGVyb2lkc1t0aWVyXS5zcGxpY2UoaSwgMSk7XG4gICAgICAgIGdhbWUucGxheS5udW1Bc3Rlcm9pZHNbdGllcl0gLT0gMTtcbiAgICAgICAgZ2FtZS5wbGF5LnNjb3JlICs9IEFTVEVST0lEX1BPSU5UX1RJRVJTW3RpZXJdO1xuICAgICAgICB1cGRhdGVTY29yZShnYW1lKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gYWNjZWxlcmF0ZVNoaXAoZ2FtZTogR2FtZSkge1xuICB2ZWMzLnNjYWxlQW5kQWRkKFxuICAgIGdhbWUucGxheS5zaGlwLnZlbG9jaXR5LFxuICAgIGdhbWUucGxheS5zaGlwLnZlbG9jaXR5LFxuICAgIGdhbWUucGxheS5zaGlwLmZvcndhcmQsXG4gICAgU0hJUF9NQVhfVEhSVVNUICogZ2FtZS5wbGF5LnNoaXAudGhyb3R0bGUuZ2V0KCksXG4gICk7XG59XG5cbmZ1bmN0aW9uIHJlZnJlc2hUaHJvdHRsZShnYW1lOiBHYW1lKSB7XG4gIGxldCBzaGlwID0gZ2FtZS5wbGF5LnNoaXA7XG4gIHNoaXAudGhyb3R0bGUuc3RlcCgpO1xuICBsZXQgdGhyb3R0bGUgPSBzaGlwLnRocm90dGxlLmdldCgpO1xuXG4gIG1hdDQuc2NhbGUoc2hpcC5mbGFtZS52ZXJ0ZXhUcmFuc2Zvcm0sIHNoaXAub2JqLnZlcnRleFRyYW5zZm9ybSwgdmVjMy5mcm9tVmFsdWVzKDEsIHRocm90dGxlLCAxKSk7XG5cbiAgbGV0IHdpZ2dsZVVwID0gMC4wMDYgKiBNYXRoLnNpbigwLjcwNzEwNjc4MTE4NyAqIGdhbWUucGxheS50aWNrcyk7XG4gIGxldCB3aWdnbGVTaWRlID0gMC4wMDQgKiBNYXRoLnNpbigoMS42MTgwMyAvIDIpICogZ2FtZS5wbGF5LnRpY2tzKTtcbiAgLy8gbGV0IHdpZ2dsZVVwID0gcmFuZGYoLVdJR0dMRSwgV0lHR0xFKTtcbiAgLy8gbGV0IHdpZ2dsZVNpZGUgPSByYW5kZigtV0lHR0xFLCBXSUdHTEUpO1xuICBtYXQ0LnJvdGF0ZShcbiAgICBzaGlwLmZsYW1lLnZlcnRleFRyYW5zZm9ybSxcbiAgICBzaGlwLmZsYW1lLnZlcnRleFRyYW5zZm9ybSxcbiAgICB3aWdnbGVVcCxcbiAgICB2ZWMzLmZyb21WYWx1ZXMoMSwgMCwgMCksXG4gICk7XG4gIG1hdDQucm90YXRlKFxuICAgIHNoaXAuZmxhbWUudmVydGV4VHJhbnNmb3JtLFxuICAgIHNoaXAuZmxhbWUudmVydGV4VHJhbnNmb3JtLFxuICAgIHdpZ2dsZVNpZGUsXG4gICAgdmVjMy5mcm9tVmFsdWVzKDAsIDAsIDEpLFxuICApO1xuXG4gIHNoaXAudGhydXN0ZXJTZngudm9sdW1lID0gU0ZYX1ZPTFVNRSAqIHRocm90dGxlO1xufVxuXG5mdW5jdGlvbiByb3RhdGVTaGlwKGdhbWU6IEdhbWUpIHtcbiAgbGV0IHNoaXAgPSBnYW1lLnBsYXkuc2hpcDtcblxuICAvLyBJbiByYWRpYW5zIHBlciB0aWNrXG4gIGxldCB0dXJuU3BlZWQgPSBxdWF0LmdldEF4aXNBbmdsZSh2ZWMzLmNyZWF0ZSgpLCBzaGlwLndvcmxkUm90YXRpb24pO1xuICBsZXQgcm90YXRpb25GYWN0b3IgPVxuICAgIChNYXRoLmxvZyh0dXJuU3BlZWQpIC0gTWF0aC5sb2coU0hJUF9ST1RBVElPTl9FUFNJTE9OKSkgL1xuICAgIChNYXRoLmxvZyhTSElQX1JPVEFUSU9OX1RPUE9VVCkgLSBNYXRoLmxvZyhTSElQX1JPVEFUSU9OX0VQU0lMT04pKTtcbiAgcm90YXRpb25GYWN0b3IgPSBjbGFtcChyb3RhdGlvbkZhY3RvciwgWzAsIDFdKTtcbiAgY29uc3Qgc2NhbGVGYWN0b3IgPSByb3RhdGlvbkZhY3RvciAqIFNISVBfUk9UQVRJT05fVE9QT1VUX1NDQUxJTkc7XG4gIHF1YXQuc2NhbGUoc2hpcC53b3JsZFJvdGF0aW9uLCBzaGlwLndvcmxkUm90YXRpb24sIHNjYWxlRmFjdG9yKTtcbiAgcXVhdC5jYWxjdWxhdGVXKHNoaXAud29ybGRSb3RhdGlvbiwgc2hpcC53b3JsZFJvdGF0aW9uKTtcblxuICAvLyBSb3RhdGVcbiAgdmVjMy50cmFuc2Zvcm1RdWF0KHNoaXAuZm9yd2FyZCwgc2hpcC5mb3J3YXJkLCBzaGlwLndvcmxkUm90YXRpb24pO1xuICB2ZWMzLnRyYW5zZm9ybVF1YXQoc2hpcC51cCwgc2hpcC51cCwgc2hpcC53b3JsZFJvdGF0aW9uKTtcbiAgdmVjMy50cmFuc2Zvcm1RdWF0KHNoaXAucmlnaHQsIHNoaXAucmlnaHQsIHNoaXAud29ybGRSb3RhdGlvbik7XG5cbiAgbGV0IHBvcyA9IHNoaXAub2JqLnBvcygpO1xuICBzaGlwLm9iai50cmFuc2xhdGUodmVjMy5zY2FsZSh2ZWMzLmNyZWF0ZSgpLCBwb3MsIC0xKSk7XG4gIGxldCByb3QgPSBtYXQ0LmZyb21RdWF0KG1hdDQuY3JlYXRlKCksIHNoaXAud29ybGRSb3RhdGlvbik7XG4gIG1hdDQubXVsdGlwbHkoc2hpcC5vYmoudmVydGV4VHJhbnNmb3JtLCByb3QsIHNoaXAub2JqLnZlcnRleFRyYW5zZm9ybSk7XG4gIHNoaXAub2JqLnRyYW5zbGF0ZShwb3MpO1xufVxuXG5mdW5jdGlvbiBtb3ZlU2hpcChnYW1lOiBHYW1lKSB7XG4gIGdhbWUucGxheS5zaGlwLm9iai50cmFuc2xhdGUoZ2FtZS5wbGF5LnNoaXAudmVsb2NpdHkpO1xufVxuXG5mdW5jdGlvbiBtb3ZlTWlzc2lsZXMoZ2FtZTogR2FtZSkge1xuICBmb3IgKGNvbnN0IG1pc3NpbGUgb2YgZ2FtZS5wbGF5Lm1pc3NpbGVzKSB7XG4gICAgbWlzc2lsZS5vYmoudHJhbnNsYXRlKG1pc3NpbGUudmVsb2NpdHkpO1xuICB9XG59XG5cbmZ1bmN0aW9uIG1vdmVBc3Rlcm9pZHMoZ2FtZTogR2FtZSkge1xuICBmb3IgKGNvbnN0IGFzdGVyb2lkIG9mIGFsbEFzdGVyb2lkcyhnYW1lKSkge1xuICAgIGFzdGVyb2lkLm9iai50cmFuc2xhdGUoYXN0ZXJvaWQudmVsb2NpdHkpO1xuXG4gICAgbGV0IHBvcyA9IGFzdGVyb2lkLm9iai5wb3MoKTtcbiAgICBhc3Rlcm9pZC5vYmoudHJhbnNsYXRlKHZlYzMuc2NhbGUodmVjMy5jcmVhdGUoKSwgcG9zLCAtMSkpO1xuICAgIGxldCByb3QgPSBtYXQ0LmZyb21RdWF0KG1hdDQuY3JlYXRlKCksIGFzdGVyb2lkLnJvdGF0aW9uKTtcbiAgICBtYXQ0Lm11bHRpcGx5KGFzdGVyb2lkLm9iai52ZXJ0ZXhUcmFuc2Zvcm0sIHJvdCwgYXN0ZXJvaWQub2JqLnZlcnRleFRyYW5zZm9ybSk7XG4gICAgYXN0ZXJvaWQub2JqLnRyYW5zbGF0ZShwb3MpO1xuICB9XG59XG5cbmZ1bmN0aW9uIGNvbGxpZGVTaGlwQXN0ZXJvaWQoZ2FtZTogR2FtZSkge1xuICAvLyBUT0RPOiBEbyBtb3JlIGludGVsbGlnZW50IHRoaW5ncyBvbiBhIGxvc3MuIEFsc28gcHJvYmFibHkganVzdCBsb3dlclxuICAvLyBoZWFsdGggYW5kIGRvIGNlcnRhaW4gdGhpbmdzIHdoZW4gaGVhbHRoIGhpdHMgMCBjb2xsaXNpb25zIGJldHRlclxuICBmb3IgKGNvbnN0IGFzdGVyb2lkIG9mIGFsbEFzdGVyb2lkcyhnYW1lKSkge1xuICAgIC8vIFRPRE86IEFkZCBhc3Rlcm9pZCBtb21lbnR1bVxuICAgIGZvciAoY29uc3QgdiBvZiBnYW1lLnBsYXkuc2hpcC5jb2xsaXNpb25Qb2ludHMoKSkge1xuICAgICAgLy8gV2UgdXNlIGEgc2xpZ2h0bHkgc21hbGxlciByYWRpdXMgdG8gdGlsdCBlcnJvcnMgaW4gdGhlIHBsYXllcnMgZmF2b3JcbiAgICAgIGlmICh2ZWMzLmRpc3RhbmNlKGFzdGVyb2lkLm9iai5wb3MoKSwgdikgPD0gQVNURVJPSURfUkFESVVTX0ZVREdFX0ZBQ1RPUiAqIGFzdGVyb2lkLnJhZGl1cykge1xuICAgICAgICAvLyBUT0RPOiBBZGQgaGVhbHRoIGFuZCBjb2xsaXNpb25zXG4gICAgICAgIGdhbWVPdmVyKGdhbWUpO1xuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG5mdW5jdGlvbiBjb2xsaWRlU2hpcFN1bihnYW1lOiBHYW1lKSB7XG4gIGZvciAoY29uc3Qgc3VuIG9mIGdhbWUucGxheS5zdW5zKSB7XG4gICAgZm9yIChjb25zdCB2IG9mIGdhbWUucGxheS5zaGlwLmNvbGxpc2lvblBvaW50cygpKSB7XG4gICAgICBpZiAoc3VuQ29udGFpbnMoc3VuLCB2KSkge1xuICAgICAgICBnYW1lT3ZlcihnYW1lKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gY29sbGlkZU1pc3NpbGVBc3Rlcm9pZChnYW1lOiBHYW1lKSB7XG4gIGxldCBkZWFkTWlzc2lsZXM6IG51bWJlcltdID0gW107XG4gIGZvciAoY29uc3QgYXN0ZXJvaWQgb2YgYWxsQXN0ZXJvaWRzKGdhbWUpKSB7XG4gICAgZm9yIChjb25zdCBbbWlzc2lsZUlkLCBtaXNzaWxlXSBvZiBnYW1lLnBsYXkubWlzc2lsZXMuZW50cmllcygpKSB7XG4gICAgICBsZXQgZGlzdCA9IHZlYzMuZGlzdGFuY2UoYXN0ZXJvaWQub2JqLnBvcygpLCBtaXNzaWxlLm9iai5wb3MoKSk7XG4gICAgICBpZiAoZGlzdCA8PSBhc3Rlcm9pZC5yYWRpdXMpIHtcbiAgICAgICAgZGVhZE1pc3NpbGVzLnB1c2gobWlzc2lsZUlkKTtcbiAgICAgICAgYXN0ZXJvaWQuZGFtYWdlKCk7XG5cbiAgICAgICAgbGV0IGFzdGVyb2lkVm9sdW1lID0gKDQgLyAzKSAqIE1hdGguUEkgKiBhc3Rlcm9pZC5yYWRpdXMgKiogMztcbiAgICAgICAgbGV0IGFzdGVyb2lkTWFzcyA9IEFTVEVST0lEX0RFTlNJVFkgKiBhc3Rlcm9pZFZvbHVtZTtcbiAgICAgICAgbGV0IGFzdGVyb2lkUm90YXRpb25hbEluZXJ0aWEgPSAoMiAvIDUpICogYXN0ZXJvaWRNYXNzICogYXN0ZXJvaWQucmFkaXVzICoqIDI7XG5cbiAgICAgICAgLy8gVE9ETzogRmlndXJlIG91dCB3aGVyZSB0byBwdXQgdGhpcyBhbmQgaG93IHRvIGdlbmVyYWxpemUgdGhpc1xuICAgICAgICAvLyBiZWhhdmlvclxuICAgICAgICAvLyBUT0RPOiBBY2NvdW50IGZvciByb3RhdGlvblxuICAgICAgICBsZXQgbm9ybWFsID0gdmVjMy5zdWJ0cmFjdCh2ZWMzLmNyZWF0ZSgpLCBtaXNzaWxlLm9iai5wb3MoKSwgYXN0ZXJvaWQub2JqLnBvcygpKTtcbiAgICAgICAgbGV0IGNvbGxpc2lvblJhZGl1cyA9IHZlYzMubGVuZ3RoKG5vcm1hbCk7XG4gICAgICAgIHZlYzMubm9ybWFsaXplKG5vcm1hbCwgbm9ybWFsKTtcbiAgICAgICAgbGV0IG5vcm1hbFNwZWVkID0gTWF0aC5hYnModmVjMy5kb3Qobm9ybWFsLCBtaXNzaWxlLnZlbG9jaXR5KSk7XG5cbiAgICAgICAgbGV0IHBlcnBlbmRpY3VsYXJWZWxvY2l0eSA9IHZlYzMuc2NhbGVBbmRBZGQoXG4gICAgICAgICAgdmVjMy5jcmVhdGUoKSxcbiAgICAgICAgICBtaXNzaWxlLnZlbG9jaXR5LFxuICAgICAgICAgIG5vcm1hbCxcbiAgICAgICAgICAtbm9ybWFsU3BlZWQsXG4gICAgICAgICk7XG5cbiAgICAgICAgLy8gRGl2aWRpbmcgYnkgYXN0ZXJvaWQgbWFzcyBhY2NvdW50cyBmb3IgbW9tZW50dW1cbiAgICAgICAgdmVjMy5zY2FsZUFuZEFkZChcbiAgICAgICAgICBhc3Rlcm9pZC52ZWxvY2l0eSxcbiAgICAgICAgICBhc3Rlcm9pZC52ZWxvY2l0eSxcbiAgICAgICAgICBub3JtYWwsXG4gICAgICAgICAgLW5vcm1hbFNwZWVkICogKE1JU1NJTEVfTUFTUyAvIGFzdGVyb2lkTWFzcyksXG4gICAgICAgICk7XG5cbiAgICAgICAgbGV0IHJvdGF0aW9uQXhpcyA9IHZlYzMuY3Jvc3ModmVjMy5jcmVhdGUoKSwgbm9ybWFsLCBwZXJwZW5kaWN1bGFyVmVsb2NpdHkpO1xuICAgICAgICB2ZWMzLm5vcm1hbGl6ZShyb3RhdGlvbkF4aXMsIHJvdGF0aW9uQXhpcyk7XG4gICAgICAgIGxldCBtaXNzaWxlVG9ycXVlID0gY29sbGlzaW9uUmFkaXVzICogdmVjMy5sZW5ndGgocGVycGVuZGljdWxhclZlbG9jaXR5KSAqIE1JU1NJTEVfTUFTUztcbiAgICAgICAgbGV0IHJvdCA9IHF1YXQuc2V0QXhpc0FuZ2xlKFxuICAgICAgICAgIHF1YXQuY3JlYXRlKCksXG4gICAgICAgICAgcm90YXRpb25BeGlzLFxuICAgICAgICAgIG1pc3NpbGVUb3JxdWUgLyBhc3Rlcm9pZFJvdGF0aW9uYWxJbmVydGlhLFxuICAgICAgICApO1xuICAgICAgICBxdWF0Lm11bHRpcGx5KGFzdGVyb2lkLnJvdGF0aW9uLCBhc3Rlcm9pZC5yb3RhdGlvbiwgcm90KTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgZm9yIChsZXQgaSA9IGRlYWRNaXNzaWxlcy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIGdhbWUucGxheS5taXNzaWxlcy5zcGxpY2UoZGVhZE1pc3NpbGVzW2ldLCAxKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBjb2xsaWRlTWlzc2lsZVN1bihnYW1lOiBHYW1lKSB7XG4gIGxldCBkZWFkTWlzc2lsZXM6IG51bWJlcltdID0gW107XG4gIGZvciAoY29uc3Qgc3VuIG9mIGdhbWUucGxheS5zdW5zKSB7XG4gICAgZm9yIChjb25zdCBbbWlzc2lsZUlkLCBtaXNzaWxlXSBvZiBnYW1lLnBsYXkubWlzc2lsZXMuZW50cmllcygpKSB7XG4gICAgICBpZiAoc3VuQ29udGFpbnMoc3VuLCBtaXNzaWxlLm9iai5wb3MoKSkpIHtcbiAgICAgICAgZGVhZE1pc3NpbGVzLnB1c2gobWlzc2lsZUlkKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgZm9yIChsZXQgaSA9IGRlYWRNaXNzaWxlcy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIGdhbWUucGxheS5taXNzaWxlcy5zcGxpY2UoZGVhZE1pc3NpbGVzW2ldLCAxKTtcbiAgfVxufVxuXG5mdW5jdGlvbiB1cGRhdGVQbGF5Q2FtZXJhKGdhbWU6IEdhbWUpIHtcbiAgZ2FtZS5wbGF5LmNhbWVyYSA9IGdhbWUucGxheS5zaGlwLmNhbWVyYShnYW1lLnBsYXkubGFzdENhbWVyYVBvc2l0aW9uKTtcbiAgZ2FtZS5wbGF5Lmxhc3RDYW1lcmFQb3NpdGlvbiA9IGdhbWUucGxheS5zaGlwLmV5ZSgpO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVTY29yZShnYW1lOiBHYW1lKSB7XG4gIGRpc3BsYXkuc2NvcmUuaW5uZXJUZXh0ID0gYFNjb3JlOiAke2dhbWUucGxheS5zY29yZX1gO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVDbG9jayhnYW1lOiBHYW1lKSB7XG4gIGxldCB0b3RhbFNlY29uZHMgPSBNYXRoLmZsb29yKGdhbWUucGxheS50aWNrcyAvIDYwKTtcbiAgbGV0IG1pbnV0ZXMgPSBNYXRoLmZsb29yKHRvdGFsU2Vjb25kcyAvIDYwKTtcbiAgbGV0IHNlY29uZHMgPSB0b3RhbFNlY29uZHMgJSA2MDtcbiAgZGlzcGxheS50aW1lLmlubmVyVGV4dCA9IGBUaW1lOiAke21pbnV0ZXN9OiR7c2Vjb25kcy50b1N0cmluZygpLnBhZFN0YXJ0KDIsIFwiMFwiKX1gO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVMZXZlbChnYW1lOiBHYW1lKSB7XG4gIGRpc3BsYXkubGV2ZWwuaW5uZXJUZXh0ID0gYExldmVsOiAke2dhbWUucGxheS5sZXZlbH1gO1xufVxuXG5mdW5jdGlvbiBoYW5kbGVGcmVlY2FtTW92ZXMoa2V5Ym9hcmQ6IEtleWJvYXJkLCBjYW1lcmE6IEZyZWVDYW1lcmEpIHtcbiAgbGV0IGNhbU1vdmUgPSB2ZWMzLmNyZWF0ZSgpO1xuXG4gIC8vIENhbWVyYSBtb3ZlbWVudHNcbiAgaWYgKGtleWJvYXJkLnByZXNzZWQuaGFzKFwiS2V5QVwiKSkge1xuICAgIHZlYzMuc2NhbGVBbmRBZGQoY2FtTW92ZSwgY2FtTW92ZSwgY2FtZXJhLnJpZ2h0LCAtMSk7XG4gIH1cbiAgaWYgKGtleWJvYXJkLnByZXNzZWQuaGFzKFwiS2V5RFwiKSkge1xuICAgIHZlYzMuYWRkKGNhbU1vdmUsIGNhbU1vdmUsIGNhbWVyYS5yaWdodCk7XG4gIH1cbiAgaWYgKGtleWJvYXJkLnByZXNzZWQuaGFzKFwiS2V5V1wiKSkge1xuICAgIHZlYzMuYWRkKGNhbU1vdmUsIGNhbU1vdmUsIGNhbWVyYS5mb3J3YXJkKTtcbiAgfVxuICBpZiAoa2V5Ym9hcmQucHJlc3NlZC5oYXMoXCJLZXlTXCIpKSB7XG4gICAgdmVjMy5zY2FsZUFuZEFkZChjYW1Nb3ZlLCBjYW1Nb3ZlLCBjYW1lcmEuZm9yd2FyZCwgLTEpO1xuICB9XG4gIGlmIChrZXlib2FyZC5wcmVzc2VkLmhhcyhcIlNoaWZ0TGVmdFwiKSkge1xuICAgIHZlYzMuc2NhbGVBbmRBZGQoY2FtTW92ZSwgY2FtTW92ZSwgY2FtZXJhLnVwLCAtMSk7XG4gIH1cbiAgaWYgKGtleWJvYXJkLnByZXNzZWQuaGFzKFwiU3BhY2VcIikpIHtcbiAgICB2ZWMzLmFkZChjYW1Nb3ZlLCBjYW1Nb3ZlLCBjYW1lcmEudXApO1xuICB9XG5cbiAgaWYgKCF2ZWMzLmV4YWN0RXF1YWxzKGNhbU1vdmUsIHZlYzMuY3JlYXRlKCkpKSB7XG4gICAgdmVjMy5ub3JtYWxpemUoY2FtTW92ZSwgY2FtTW92ZSk7XG4gICAgY2FtZXJhLm1vdmUoY2FtTW92ZSwgY2FtZXJhLm1vdmVTcGVlZCk7XG4gIH1cblxuICBpZiAoa2V5Ym9hcmQucHJlc3NlZC5oYXMoXCJLZXlFXCIpKSB7XG4gICAgY2FtZXJhLnJvbGxSaWdodChGUkVDQU1fUk9MTF9TUEVFRCk7XG4gIH1cbiAgaWYgKGtleWJvYXJkLnByZXNzZWQuaGFzKFwiS2V5UVwiKSkge1xuICAgIGNhbWVyYS5yb2xsUmlnaHQoLUZSRUNBTV9ST0xMX1NQRUVEKTtcbiAgfVxuXG4gIGlmIChrZXlib2FyZC5wcmVzc2VkLmhhcyhcIkFycm93VXBcIikpIHtcbiAgICBjYW1lcmEubW92ZVNwZWVkICs9IEZSRUVDQU1fTU9WRV9TUEVFRF9JTkNSRU1FTlQ7XG4gIH1cbiAgaWYgKGtleWJvYXJkLnByZXNzZWQuaGFzKFwiQXJyb3dEb3duXCIpICYmIGNhbWVyYS5tb3ZlU3BlZWQgPiBGUkVFQ0FNX01PVkVfU1BFRURfSU5DUkVNRU5UKSB7XG4gICAgY2FtZXJhLm1vdmVTcGVlZCAtPSBGUkVFQ0FNX01PVkVfU1BFRURfSU5DUkVNRU5UO1xuICB9XG59XG5cbmZ1bmN0aW9uIGRldkxvb3AoZ2FtZTogR2FtZSkge1xuICBsZXQga2V5Ym9hcmQgPSBnYW1lLmlucHV0cy5rZXlib2FyZDtcblxuICBoYW5kbGVGcmVlY2FtTW92ZXMoa2V5Ym9hcmQsIGdhbWUuZnJlZWNhbS5jYW1lcmEpO1xuXG4gIGlmIChrZXlib2FyZC5wcmVzc2VkLmhhcyhcIkFycm93TGVmdFwiKSkge1xuICAgIGdhbWUuZnJlZWNhbS5nZW5lcmFsRGVib3VuY2VyLnRyeSgoKSA9PiB7XG4gICAgICBnYW1lLnBsYXkubGV2ZWwgPSBNYXRoLm1heCgxLCBnYW1lLnBsYXkubGV2ZWwgLSAxKTtcbiAgICAgIGdhbWUucGxheS5udW1Bc3Rlcm9pZHMgPSBudW1Bc3Rlcm9pZHMoZ2FtZS5wbGF5LmxldmVsKTtcbiAgICAgIHVwZGF0ZUxldmVsKGdhbWUpO1xuICAgIH0pO1xuICB9XG4gIGlmIChrZXlib2FyZC5wcmVzc2VkLmhhcyhcIkFycm93UmlnaHRcIikpIHtcbiAgICBnYW1lLmZyZWVjYW0uZ2VuZXJhbERlYm91bmNlci50cnkoKCkgPT4ge1xuICAgICAgZ2FtZS5wbGF5LmxldmVsICs9IDE7XG4gICAgICBnYW1lLnBsYXkubnVtQXN0ZXJvaWRzID0gbnVtQXN0ZXJvaWRzKGdhbWUucGxheS5sZXZlbCk7XG4gICAgICB1cGRhdGVMZXZlbChnYW1lKTtcbiAgICB9KTtcbiAgfVxuXG4gIGlmIChrZXlib2FyZC5wcmVzc2VkLmhhcyhcIktleUZcIikpIHtcbiAgICBnYW1lLmZyZWVjYW0uZ2VuZXJhbERlYm91bmNlci50cnkoKCkgPT4ge1xuICAgICAgZ2FtZS5mcmVlY2FtLmZvZyA9ICFnYW1lLmZyZWVjYW0uZm9nO1xuICAgIH0pO1xuICB9XG5cbiAgaWYgKGtleWJvYXJkLnByZXNzZWQuaGFzKFwiS2V5Q1wiKSkge1xuICAgIGdhbWUuZnJlZWNhbS5nZW5lcmFsRGVib3VuY2VyLnRyeSgoKSA9PiB7XG4gICAgICBnYW1lLmZyZWVjYW0uc2hvd1NoaXBDb2xsaXNpb25zID0gIWdhbWUuZnJlZWNhbS5zaG93U2hpcENvbGxpc2lvbnM7XG4gICAgfSk7XG4gIH1cblxuICBpZiAoa2V5Ym9hcmQucHJlc3NlZC5oYXMoXCJLZXlCXCIpKSB7XG4gICAgZ2FtZS5mcmVlY2FtLmZyZWVjYW1Nb2RlRGVib3VuY2VyLnRyeSgoKSA9PiB1bmRldk1vZGUoZ2FtZSkpO1xuICB9XG4gIHJlbmRlci5yZW5kZXIoXG4gICAgZ2FtZS5nbCxcbiAgICBwbGF5TGlnaHRzKGdhbWUpLFxuICAgIHBsYXlPYmplY3RzKGdhbWUpLFxuICAgIHBsYXlGcm9udE9iamVjdHMoZ2FtZSksXG4gICAgZ2FtZS5zaGFkZXJJbmZvLFxuICAgIGdhbWUuZnJlZWNhbS5jYW1lcmEsXG4gICAge1xuICAgICAgZm9nOiBnYW1lLmZyZWVjYW0uZm9nLFxuICAgIH0sXG4gICk7XG5cbiAgc2NoZWR1bGVOZXh0RnJhbWUoZ2FtZSk7XG59XG5cbmZ1bmN0aW9uIG1lbnVMb29wKGdhbWU6IEdhbWUpIHtcbiAgZGVzcGF3bk1lbnVBc3Rlcm9pZHMoZ2FtZSk7XG4gIHNwYXduTWVudUFzdGVyb2lkcyhnYW1lKTtcblxuICBmb3IgKGNvbnN0IGFzdGVyb2lkIG9mIGdhbWUubWVudS5hc3Rlcm9pZHMpIHtcbiAgICBhc3Rlcm9pZC5vYmoudHJhbnNsYXRlKGFzdGVyb2lkLnZlbG9jaXR5KTtcbiAgICBsZXQgcm90TWF0cml4ID0gbWF0NC5mcm9tUXVhdChtYXQ0LmNyZWF0ZSgpLCBhc3Rlcm9pZC5yb3RhdGlvbik7XG4gICAgbWF0NC5tdWx0aXBseShhc3Rlcm9pZC5vYmoudmVydGV4VHJhbnNmb3JtLCBhc3Rlcm9pZC5vYmoudmVydGV4VHJhbnNmb3JtLCByb3RNYXRyaXgpO1xuICB9XG5cbiAgaWYgKGdhbWUuaW5wdXRzLmtleWJvYXJkLnByZXNzZWQuaGFzKFwiS2V5QlwiKSkge1xuICAgIGdhbWUubWVudS5tb3ZlTW9kZURlYm91bmNlci50cnkoKCkgPT4ge1xuICAgICAgaWYgKGdhbWUubWVudS5tb3ZpbmdDYW1lcmEpIHtcbiAgICAgICAgZG9jdW1lbnQuZXhpdFBvaW50ZXJMb2NrKCk7XG4gICAgICAgIGdhbWUubWVudS5tb3ZpbmdDYW1lcmEgPSBmYWxzZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNhbnZhcy5yZXF1ZXN0UG9pbnRlckxvY2soKTtcbiAgICAgICAgZ2FtZS5tZW51Lm1vdmluZ0NhbWVyYSA9IHRydWU7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBpZiAoZ2FtZS5tZW51Lm1vdmluZ0NhbWVyYSkge1xuICAgIGhhbmRsZUZyZWVjYW1Nb3ZlcyhnYW1lLmlucHV0cy5rZXlib2FyZCwgZ2FtZS5tZW51LmNhbWVyYSk7XG4gIH1cblxuICByZW5kZXIucmVuZGVyKFxuICAgIGdhbWUuZ2wsXG4gICAgbWVudUxpZ2h0cyhnYW1lKSxcbiAgICBtZW51T2JqZWN0cyhnYW1lKSxcbiAgICBbXSxcbiAgICBnYW1lLnNoYWRlckluZm8sXG4gICAgZ2FtZS5tZW51LmNhbWVyYSxcbiAgKTtcblxuICBzY2hlZHVsZU5leHRGcmFtZShnYW1lKTtcbn1cblxuZnVuY3Rpb24gcGF1c2VMb29wKGdhbWU6IEdhbWUpIHtcbiAgaWYgKGdhbWUuaW5wdXRzLmtleWJvYXJkLnByZXNzZWQuaGFzKFwiS2V5UFwiKSkge1xuICAgIGdhbWUuaW5wdXRzLnBhdXNlRGVib3VuY2VyLnRyeSgoKSA9PiB1bnBhdXNlR2FtZShnYW1lKSk7XG4gIH1cblxuICByZW5kZXIucmVuZGVyKFxuICAgIGdhbWUuZ2wsXG4gICAgcGxheUxpZ2h0cyhnYW1lKSxcbiAgICBwbGF5T2JqZWN0cyhnYW1lKSxcbiAgICBwbGF5RnJvbnRPYmplY3RzKGdhbWUpLFxuICAgIGdhbWUuc2hhZGVySW5mbyxcbiAgICBnYW1lLnBsYXkuY2FtZXJhLFxuICApO1xuXG4gIHNjaGVkdWxlTmV4dEZyYW1lKGdhbWUpO1xufVxuXG5mdW5jdGlvbiBwbGF5TG9vcChnYW1lOiBHYW1lKSB7XG4gIGNoZWNrTmV4dExldmVsKGdhbWUpO1xuXG4gIGhhbmRsZUtleWJvYXJkKGdhbWUpO1xuICBoYW5kbGVHYW1lcGFkKGdhbWUpO1xuXG4gIC8vIERlc3Bhd24gZmFyIGF3YXkgb2JqZWN0c1xuICBkZXNwYXduU3VucyhnYW1lKTtcbiAgZGVzcGF3bkFzdGVyb2lkcyhnYW1lKTtcbiAgZGVzcGF3bk1pc3NpbGVzKGdhbWUpO1xuXG4gIC8vIEhhbmRsZSBuZXcgb2JqZWN0IGNyZWF0aW9uXG4gIHNwYXduU3VucyhnYW1lKTtcbiAgc3Bhd25Bc3Rlcm9pZHMoZ2FtZSk7XG5cbiAgLy8gSGFuZGxlIGNvbGxpc2lvbnNcbiAgY29sbGlkZU1pc3NpbGVTdW4oZ2FtZSk7XG4gIGNvbGxpZGVNaXNzaWxlQXN0ZXJvaWQoZ2FtZSk7XG5cbiAgLy8gRGVzdHJveSBvYmplY3RzXG4gIGhhbmRsZURlYWRBc3Rlcm9pZHMoZ2FtZSk7XG5cbiAgLy8gSGFuZGxlIGFjY2VsZXJhdGlvblxuICBhY2NlbGVyYXRlU2hpcChnYW1lKTtcblxuICAvLyBIYW5kbGUgdmVsb2NpdHlcbiAgbW92ZVNoaXAoZ2FtZSk7XG4gIG1vdmVNaXNzaWxlcyhnYW1lKTtcbiAgbW92ZUFzdGVyb2lkcyhnYW1lKTtcblxuICAvLyBQb3NzaWJseSBraWxsIHNoaXBcbiAgLy8gV2UgZG9uJ3Qgd2FudCB0byBraWxsIHRoZSBzaGlwIGlmIHdlJ3ZlIGZpbmlzaGVkIHRoZSBsZXZlbFxuICBpZiAoZ2FtZS5wbGF5LmxldmVsRmluaXNoZWRBdCA9PSBudWxsKSB7XG4gICAgY29sbGlkZVNoaXBBc3Rlcm9pZChnYW1lKTtcbiAgICBjb2xsaWRlU2hpcFN1bihnYW1lKTtcbiAgfVxuXG4gIHVwZGF0ZUNsb2NrKGdhbWUpO1xuXG4gIHVwZGF0ZVBsYXlDYW1lcmEoZ2FtZSk7XG5cbiAgLy8gU3luYyB0aGUgc2hpcCdzIG1vZGVsXG4gIHJlZnJlc2hUaHJvdHRsZShnYW1lKTtcbiAgcm90YXRlU2hpcChnYW1lKTtcblxuICBpZiAoZ2FtZS5pbnB1dHMua2V5Ym9hcmQucHJlc3NlZC5oYXMoXCJLZXlCXCIpKSB7XG4gICAgZ2FtZS5mcmVlY2FtLmZyZWVjYW1Nb2RlRGVib3VuY2VyLnRyeSgoKSA9PiBkZXZNb2RlKGdhbWUpKTtcbiAgfVxuXG4gIGdhbWUucGxheS50aWNrcyArPSAxO1xuICByZW5kZXIucmVuZGVyKFxuICAgIGdhbWUuZ2wsXG4gICAgcGxheUxpZ2h0cyhnYW1lKSxcbiAgICBwbGF5T2JqZWN0cyhnYW1lKSxcbiAgICBwbGF5RnJvbnRPYmplY3RzKGdhbWUpLFxuICAgIGdhbWUuc2hhZGVySW5mbyxcbiAgICBnYW1lLnBsYXkuY2FtZXJhLFxuICApO1xuXG4gIHNjaGVkdWxlTmV4dEZyYW1lKGdhbWUpO1xufVxuXG5jb25zdCBjYW52YXMgPSA8SFRNTENhbnZhc0VsZW1lbnQ+ZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoXCJnYW1lLWNhbnZhc1wiKTtcbi8vIFRPRE86IE1ha2UgdGhpcyBkeW5hbWljIGluc3RlYWQgb2YgaGFyZGNvZGluZyBjZXJ0YWluIHBvc2l0aW9ucy4gQWxzbyBtb3ZlXG4vLyB0byBcInRleHRcIiBtb2R1bGVcbmNvbnN0IGRpc3BsYXkgPSB7XG4gIHNjb3JlOiA8SFRNTEVsZW1lbnQ+ZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoXCJzY29yZS10ZXh0XCIpLFxuICB0aW1lOiA8SFRNTEVsZW1lbnQ+ZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoXCJ0aW1lLXRleHRcIiksXG4gIGxldmVsOiA8SFRNTEVsZW1lbnQ+ZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoXCJsZXZlbC10ZXh0XCIpLFxuICBtZW51QnV0dG9uOiA8SFRNTEJ1dHRvbkVsZW1lbnQ+ZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoXCJtZW51LWJ1dHRvblwiKSxcbiAgbWVudUJ1dHRvbjI6IDxIVE1MQnV0dG9uRWxlbWVudD5kb2N1bWVudC5nZXRFbGVtZW50QnlJZChcIm1lbnUtYnV0dG9uMlwiKSxcbiAgbWFpblRleHQ6IDxIVE1MRWxlbWVudD5kb2N1bWVudC5nZXRFbGVtZW50QnlJZChcIm1haW4tdGV4dFwiKSxcbn07XG5cbmZ1bmN0aW9uIG1haW4oKSB7XG4gIGxldCBnbCA9IHJlbmRlci5pbml0V2ViZ2woY2FudmFzKTtcbiAgbGV0IGdhbWUgPSBpbml0R2FtZShnbCk7XG5cbiAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoXCJibHVyXCIsICgpID0+IHtcbiAgICBpZiAoZ2FtZS5tb2RlID09IEdhbWVNb2RlLlBsYXkpIHtcbiAgICAgIHBhdXNlR2FtZShnYW1lKTtcbiAgICB9XG4gICAgTVVTSUMucGF1c2UoKTtcbiAgfSk7XG5cbiAgZGlzcGxheS5tZW51QnV0dG9uLm9uY2xpY2sgPSAoKSA9PiB7XG4gICAgcGxheUdhbWUoZ2FtZSwgMSk7XG4gIH07XG5cbiAgY2FudmFzLm9uY2xpY2sgPSAoKSA9PiB7XG4gICAgaWYgKGdhbWUubW9kZSA9PSBHYW1lTW9kZS5QbGF5IHx8IGdhbWUubW9kZSA9PSBHYW1lTW9kZS5GcmVlY2FtKSB7XG4gICAgICBjYW52YXMucmVxdWVzdFBvaW50ZXJMb2NrKCk7XG4gICAgfVxuICB9O1xuICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKFwicG9pbnRlcmxvY2tjaGFuZ2VcIiwgKCkgPT4ge1xuICAgIGlmIChkb2N1bWVudC5wb2ludGVyTG9ja0VsZW1lbnQgPT09IGNhbnZhcykge1xuICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihcIm1vdXNlbW92ZVwiLCB1cGRhdGVQb3NpdGlvbik7XG4gICAgfSBlbHNlIHtcbiAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJtb3VzZW1vdmVcIiwgdXBkYXRlUG9zaXRpb24pO1xuICAgIH1cbiAgfSk7XG4gIGZ1bmN0aW9uIHVwZGF0ZVBvc2l0aW9uKGU6IE1vdXNlRXZlbnQpIHtcbiAgICBpZiAoZ2FtZS5tb2RlID09IEdhbWVNb2RlLkZyZWVjYW0pIHtcbiAgICAgIGdhbWUuZnJlZWNhbS5jYW1lcmEueWF3TGVmdCgtRlJFQ0FNX01PVVNFX1RVUk5fU1BFRUQgKiBlLm1vdmVtZW50WCk7XG4gICAgICBnYW1lLmZyZWVjYW0uY2FtZXJhLnBpdGNoVXAoLUZSRUNBTV9NT1VTRV9UVVJOX1NQRUVEICogZS5tb3ZlbWVudFkpO1xuICAgIH0gZWxzZSBpZiAoZ2FtZS5tb2RlID09IEdhbWVNb2RlLlBsYXkpIHtcbiAgICAgIGdhbWUucGxheS5zaGlwLnlhd0xlZnQoLVNISVBfTU9VU0VfVFVSTl9TUEVFRCAqIGUubW92ZW1lbnRYKTtcbiAgICAgIGdhbWUucGxheS5zaGlwLnBpdGNoVXAoLVNISVBfTU9VU0VfVFVSTl9TUEVFRCAqIGUubW92ZW1lbnRZKTtcbiAgICB9IGVsc2UgaWYgKGdhbWUubW9kZSA9PSBHYW1lTW9kZS5NZW51KSB7XG4gICAgICBnYW1lLm1lbnUuY2FtZXJhLnlhd0xlZnQoLUZSRUNBTV9NT1VTRV9UVVJOX1NQRUVEICogZS5tb3ZlbWVudFgpO1xuICAgICAgZ2FtZS5tZW51LmNhbWVyYS5waXRjaFVwKC1GUkVDQU1fTU9VU0VfVFVSTl9TUEVFRCAqIGUubW92ZW1lbnRZKTtcbiAgICB9XG4gIH1cbiAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihcIm1vdXNlZG93blwiLCAoKSA9PiB7XG4gICAgZ2FtZS5pbnB1dHMubW91c2VEb3duID0gdHJ1ZTtcbiAgfSk7XG4gIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoXCJtb3VzZXVwXCIsICgpID0+IHtcbiAgICBnYW1lLmlucHV0cy5tb3VzZURvd24gPSBmYWxzZTtcbiAgfSk7XG5cbiAgc2NoZWR1bGVOZXh0RnJhbWUoZ2FtZSk7XG59XG5cbm1haW4oKTtcbiJdLCJuYW1lcyI6WyJfX3dlYnBhY2tfcmVxdWlyZV9fIiwiZXhwb3J0cyIsImRlZmluaXRpb24iLCJrZXkiLCJvIiwiT2JqZWN0IiwiZGVmaW5lUHJvcGVydHkiLCJlbnVtZXJhYmxlIiwiZ2V0Iiwib2JqIiwicHJvcCIsInByb3RvdHlwZSIsImhhc093blByb3BlcnR5IiwiY2FsbCIsIlN5bWJvbCIsInRvU3RyaW5nVGFnIiwidmFsdWUiLCJFUFNJTE9OIiwiQVJSQVlfVFlQRSIsIkZsb2F0MzJBcnJheSIsIkFycmF5IiwiUkFORE9NIiwiTWF0aCIsInJhbmRvbSIsImNyZWF0ZSIsIm91dCIsImNsb25lIiwiYSIsIngiLCJ5IiwieiIsImh5cG90IiwiZnJvbVZhbHVlcyIsImNvcHkiLCJzZXQiLCJhZGQiLCJiIiwic3VidHJhY3QiLCJtdWx0aXBseSIsImRpdmlkZSIsImNlaWwiLCJmbG9vciIsIm1pbiIsIm1heCIsInJvdW5kIiwic2NhbGUiLCJzY2FsZUFuZEFkZCIsImRpc3RhbmNlIiwic3F1YXJlZERpc3RhbmNlIiwic3F1YXJlZExlbmd0aCIsIm5lZ2F0ZSIsImludmVyc2UiLCJub3JtYWxpemUiLCJsZW4iLCJzcXJ0IiwiY3Jvc3MiLCJheCIsImF5IiwiYXoiLCJieCIsImJ5IiwiYnoiLCJsZXJwIiwidCIsImhlcm1pdGUiLCJjIiwiZCIsImZhY3RvclRpbWVzMiIsImZhY3RvcjEiLCJmYWN0b3IyIiwiZmFjdG9yMyIsImZhY3RvcjQiLCJiZXppZXIiLCJpbnZlcnNlRmFjdG9yIiwiaW52ZXJzZUZhY3RvclRpbWVzVHdvIiwiciIsIlBJIiwielNjYWxlIiwiY29zIiwic2luIiwidHJhbnNmb3JtTWF0NCIsIm0iLCJ3IiwidHJhbnNmb3JtTWF0MyIsInRyYW5zZm9ybVF1YXQiLCJxIiwicXgiLCJxeSIsInF6IiwicXciLCJ1dngiLCJ1dnkiLCJ1dnoiLCJ1dXZ4IiwidXV2eSIsInV1dnoiLCJ3MiIsInJvdGF0ZVgiLCJyYWQiLCJwIiwicm90YXRlWSIsInJvdGF0ZVoiLCJhbmdsZSIsIm1hZyIsImNvc2luZSIsImFjb3MiLCJ6ZXJvIiwic3RyIiwiZXhhY3RFcXVhbHMiLCJhMCIsImExIiwiYTIiLCJiMCIsImIxIiwiYjIiLCJhYnMiLCJpIiwiYXJndW1lbnRzIiwibGVuZ3RoIiwidmVjIiwic3ViIiwibXVsIiwiZGl2IiwiZGlzdCIsInNxckRpc3QiLCJzcXJMZW4iLCJmb3JFYWNoIiwic3RyaWRlIiwib2Zmc2V0IiwiY291bnQiLCJmbiIsImFyZyIsImwiLCJhMDAiLCJhMDEiLCJhMDIiLCJhMDMiLCJhMTAiLCJhMTEiLCJhMTIiLCJhMTMiLCJhMjAiLCJhMjEiLCJhMjIiLCJhMjMiLCJhMzAiLCJhMzEiLCJhMzIiLCJhMzMiLCJiMyIsInJvdGF0ZSIsImF4aXMiLCJzIiwiYjAwIiwiYjAxIiwiYjAyIiwiYjEwIiwiYjExIiwiYjEyIiwiYjIwIiwiYjIxIiwiYjIyIiwiZnJvbVJvdGF0aW9uIiwiZnJvbVF1YXQiLCJ4MiIsInkyIiwiejIiLCJ4eCIsInl4IiwieXkiLCJ6eCIsInp5IiwienoiLCJ3eCIsInd5Iiwid3oiLCJwZXJzcGVjdGl2ZSIsImZvdnkiLCJhc3BlY3QiLCJuZWFyIiwiZmFyIiwibmYiLCJmIiwidGFuIiwiSW5maW5pdHkiLCJsb29rQXQiLCJleWUiLCJjZW50ZXIiLCJ1cCIsIngwIiwieDEiLCJ5MCIsInkxIiwiejAiLCJ6MSIsImV5ZXgiLCJleWV5IiwiZXlleiIsInVweCIsInVweSIsInVweiIsImNlbnRlcngiLCJjZW50ZXJ5IiwiY2VudGVyeiIsImlkZW50aXR5Iiwic2V0QXhpc0FuZ2xlIiwiYXciLCJidyIsInJnYiIsImciLCJtb2RlbCIsImNlbnRyb2lkIiwidmVydGljZXMiLCJ2IiwiY3ViZSIsInNpZGVMZW4iLCJtYXRlcmlhbCIsInRyaWFuZ2xlcyIsIlNVTl9DT0xPUiIsIlNQQUNFX0NPTE9SIiwiU1VOIiwiYW1iaWVudCIsImRpZmZ1c2UiLCJzcGVjdWxhciIsIm4iLCJET1QiLCJTSElQIiwiU0hJUF9OT1paTEUiLCJTSElQX0NPTExJU0lPTl9QT0lOVFMiLCJtYXAiLCJTSElQX0ZMQU1FIiwiU0hJUF9GTEFNRV9BQ0NFTlQiLCJTSElQX1JFVElDTEUiLCJzaGlmdCIsIk1JU1NJTEUiLCJBU1RFUk9JRF9DT0xPUiIsIkFTVEVST0lEX0RBTUFHRURfQ09MT1IiLCJBU1RFUk9JRF9NQVRFUklBTCIsIkZPR19DT0xPUiIsImdsIiwidmVydGV4VHJhbnNmb3JtIiwidmVydGV4UG9zQXJyYXkiLCJmbGF0IiwidmVydGV4UG9zQnVmZmVyIiwiY3JlYXRlQnVmZmVyIiwiYmluZEJ1ZmZlciIsIkFSUkFZX0JVRkZFUiIsImJ1ZmZlckRhdGEiLCJTVEFUSUNfRFJBVyIsInRyaWFuZ2xlQXJyYXkiLCJ0cmlhbmdsZUJ1ZmZlciIsIkVMRU1FTlRfQVJSQVlfQlVGRkVSIiwiVWludDE2QXJyYXkiLCJ0aGlzIiwidHJpYW5nbGVCdWZmZXJTaXplIiwidHJhbnNsYXRlIiwicmFkcyIsInBvcyIsIm1hdCIsIlNIQURFUl9BVFRSSUJVVEVTIiwiU0hBREVSX1VOSUZPUk1TIiwic2V0dXBTaGFkZXJzIiwiZ2V0RXh0ZW5zaW9uIiwidlNoYWRlciIsImNyZWF0ZVNoYWRlciIsIlZFUlRFWF9TSEFERVIiLCJzaGFkZXJTb3VyY2UiLCJjb21waWxlU2hhZGVyIiwiZ2V0U2hhZGVyUGFyYW1ldGVyIiwiQ09NUElMRV9TVEFUVVMiLCJnZXRTaGFkZXJJbmZvTG9nIiwiZlNoYWRlckNvZGUiLCJ0b0ZpeGVkIiwiZlNoYWRlciIsIkZSQUdNRU5UX1NIQURFUiIsInNoYWRlclByb2dyYW0iLCJjcmVhdGVQcm9ncmFtIiwiYXR0YWNoU2hhZGVyIiwibGlua1Byb2dyYW0iLCJnZXRQcm9ncmFtUGFyYW1ldGVyIiwiTElOS19TVEFUVVMiLCJnZXRQcm9ncmFtSW5mb0xvZyIsInVzZVByb2dyYW0iLCJzaGFkZXJBdHRyaWJ1dGVzIiwiYXR0cmlicyIsInVuaWZvcm1zIiwiYXR0cmliIiwiZ2V0QXR0cmliTG9jYXRpb24iLCJlbmFibGVWZXJ0ZXhBdHRyaWJBcnJheSIsInVuaWZvcm0iLCJnZXRVbmlmb3JtTG9jYXRpb24iLCJyZW5kZXIiLCJsaWdodHMiLCJvYmplY3RzIiwiZnJvbnRPYmplY3RzIiwic2hhZGVySW5mbyIsImNhbWVyYSIsIm9wdHMiLCJ1bmRlZmluZWQiLCJmb2ciLCJjbGVhciIsIkNPTE9SX0JVRkZFUl9CSVQiLCJERVBUSF9CVUZGRVJfQklUIiwibGlnaHRzQXJyIiwibnVtTGlnaHRzIiwibGlnaHRQb3MiLCJwdXNoIiwiZHJhd09iamVjdCIsImJ1ZmZlciIsImFWZXJ0ZXhQb3MiLCJ2ZXJ0ZXhBdHRyaWJQb2ludGVyIiwiRkxPQVQiLCJ1bmlmb3JtTWF0cml4NGZ2IiwidVZlcnRleFRyYW5zZm9ybSIsInVuaWZvcm0zZnYiLCJ1bmlmb3JtMWYiLCJkcmF3RWxlbWVudHMiLCJUUklBTkdMRVMiLCJVTlNJR05FRF9TSE9SVCIsInVMaWdodHMiLCJ1bmlmb3JtMWkiLCJ1TnVtTGlnaHRzIiwidUZvZyIsInVFeWVQb3MiLCJ1Vmlld2luZ1RyYW5zZm9ybSIsInZpZXdpbmdUcmFuc2Zvcm0iLCJ1UGVyc3BlY3RpdmVUcmFuc2Zvcm0iLCJwZXJzcGVjdGl2ZVRyYW5zZm9ybSIsImVuYWJsZSIsIkRFUFRIX1RFU1QiLCJvYmplY3RzQXJyIiwiZnJvbSIsImRpc2FibGUiLCJnZXRUaW1lIiwiZGVsYXlNcyIsImRlYm91bmNlVGltZSIsImxhc3RDaGFuZ2UiLCJyZXNldCIsInJlYWR5IiwidHJ5Iiwibm93IiwicHJlc3NlZCIsIlNldCIsInJlZ2lzdGVyIiwiZG9jdW1lbnQiLCJhZGRFdmVudExpc3RlbmVyIiwiZSIsImNvZGUiLCJkZWxldGUiLCJsbyIsImhpIiwiY2xhbXAiLCJyYW5nZSIsImRlZ3JlZXMiLCJyYW5kb21BcmMiLCJkaXJlY3Rpb24iLCJhcmMiLCJyYW5kb21BcmNSYW5nZSIsImFyY1JhbmdlIiwicGVycGVuZGljdWxhciIsImFyY1ZlYyIsImFuZ2xlT3V0IiwiYW5nbGVBcm91bmQiLCJORUFSX0JPVU5EIiwiQVNURVJPSURfUkFESVVTX1RJRVJTIiwiQVNURVJPSURfSEVBTFRIX1RJRVJTIiwiQVNURVJPSURfUE9JTlRfVElFUlMiLCJBU1RFUk9JRF9ST1RBVElPTl9TUEVFRCIsIkFTVEVST0lEX1NQTElUX1NQRUVEIiwiQVNURVJPSURfSU5JVElBTF9TUEFXTl9ESVNUQU5DRSIsIkFTVEVST0lEX1NQQVdOX0FSQyIsIkFTVEVST0lEX1ZFTE9DSVRZX0FSQyIsIlNVTl9JTklUSUFMX1NQQVdOX0RJU1RBTkNFIiwiU1VOX1NQQVdOX0FSQyIsIlNISVBfVEhST1RUTEVfU1BFRURfTElNSVQiLCJTSElQX0ZPVl9ERUdSRUVTIiwiU0hJUF9ST0xMX1NQRUVEIiwiTUlTU0lMRV9MSUZFX1RJQ0tTIiwiTUlTU0lMRV9ESVNUQU5DRSIsIkZSRUVDQU1fTU9WRV9TUEVFRF9JTkNSRU1FTlQiLCJNRU5VX0FTVEVST0lEX1ZFTE9DSVRZX0FSQyIsIk1FTlVfQVNURVJPSURfU1BBV05fQVJDIiwiTUVOVV9BU1RFUk9JRF9TUEVFRCIsIkRFQk9VTkNFX01TIiwibnVtQXN0ZXJvaWRzIiwibGV2ZWwiLCJNSVNTSUxFX1NGWCIsIkF1ZGlvIiwiTVVTSUMiLCJ2b2x1bWUiLCJNVVNJQ19WT0xVTUUiLCJsb29wIiwiR2FtZU1vZGUiLCJzcGVlZExpbWl0Iiwid2FudCIsImN1cnJlbnQiLCJzdGVwIiwidmVsb2NpdHkiLCJTY2VuZU9iamVjdCIsImZsYW1lIiwiZmxhbWVBY2NlbnQiLCJyZXRpY2xlIiwibGFzdEZpcmVkIiwiTnVtYmVyIiwiTkVHQVRJVkVfSU5GSU5JVFkiLCJ0aHJvdHRsZSIsIkVhc2VkIiwid29ybGRSb3RhdGlvbiIsImZvcndhcmQiLCJyaWdodCIsInRocnVzdGVyU2Z4Iiwic2V0VGhyb3R0bGUiLCJhbW91bnQiLCJwbGF5IiwicGl0Y2hVcCIsInlhd0xlZnQiLCJyb2xsUmlnaHQiLCJhYm91dFdvcmxkIiwid29ybGRJbXB1bHNlIiwiY29sbGlzaW9uUG9pbnRzIiwidHJ5RmlyZSIsImdhbWUiLCJ0aWNrcyIsInNmeCIsImNsb25lTm9kZSIsIlNGWF9WT0xVTUUiLCJtaXNzaWxlVmVsb2NpdHkiLCJtaXNzaWxlcyIsImJpcnRoIiwibGFzdFBvcyIsImZvdiIsImNhbnZhcyIsIndpZHRoIiwiaGVpZ2h0IiwidGllciIsIm9wdCIsInRpZXJSYWRpdXMiLCJyYWRpdXMiLCJzaWRlTGVuZ3RoIiwidmVydGV4ZXMiLCJkaXNwIiwiYXN0ZXJvaWQiLCJKU09OIiwicGFyc2UiLCJzdHJpbmdpZnkiLCJhdmdSYWRpdXMiLCJhY3R1YWxSYWRpdXMiLCJoZWFsdGgiLCJyb3RhdGlvbkF4aXMiLCJyb3RhdGlvbiIsInNwbGl0Iiwic3BlZWQiLCJsZWZ0VmVsb2NpdHkiLCJsZWZ0IiwiQXN0ZXJvaWQiLCJyaWdodFZlbG9jaXR5IiwiZGFtYWdlIiwiaGVhbHRoUGVyY2VudCIsImNvbG9yIiwic3VuQ29udGFpbnMiLCJzdW4iLCJwb2ludCIsImV2ZXJ5IiwiYWxsQXN0ZXJvaWRzIiwidGllcmVkQXN0ZXJvaWRzIiwicGxheU9iamVjdHMiLCJzaGlwIiwiZnJlZWNhbSIsInNob3dTaGlwQ29sbGlzaW9ucyIsInN1bnMiLCJwbGF5RnJvbnRPYmplY3RzIiwicGxheUxpZ2h0cyIsInNjaGVkdWxlTmV4dEZyYW1lIiwibW9kZSIsIk1lbnUiLCJyZXF1ZXN0QW5pbWF0aW9uRnJhbWUiLCJkZWFkQXN0ZXJvaWRzIiwibWVudSIsImFzdGVyb2lkcyIsImVudHJpZXMiLCJhc3Rlcm9pZElkIiwiU1BBV05fRElTVEFOQ0UiLCJzcGxpY2UiLCJkZXNwYXduTWVudUFzdGVyb2lkcyIsInNwYXduTWVudUFzdGVyb2lkcyIsInJvdE1hdHJpeCIsImlucHV0cyIsImtleWJvYXJkIiwiaGFzIiwibW92ZU1vZGVEZWJvdW5jZXIiLCJtb3ZpbmdDYW1lcmEiLCJleGl0UG9pbnRlckxvY2siLCJyZXF1ZXN0UG9pbnRlckxvY2siLCJoYW5kbGVGcmVlY2FtTW92ZXMiLCJtZW51TGlnaHRzIiwibWVudU9iamVjdHMiLCJtZW51TG9vcCIsIlBhdXNlIiwicGF1c2VEZWJvdW5jZXIiLCJ1bnBhdXNlR2FtZSIsInBhdXNlTG9vcCIsIlBsYXkiLCJsZXZlbEZpbmlzaGVkQXQiLCJwbGF5R2FtZSIsImNoZWNrTmV4dExldmVsIiwibW91c2VEb3duIiwicGF1c2VHYW1lIiwiaGFuZGxlS2V5Ym9hcmQiLCJnYW1lcGFkIiwibmF2aWdhdG9yIiwiZ2V0R2FtZXBhZHMiLCJheGVzIiwiYnV0dG9ucyIsImNvbnNvbGUiLCJsb2ciLCJoYW5kbGVHYW1lcGFkIiwiZGVhZFN1bnMiLCJzdW5JZCIsImRlc3Bhd25TdW5zIiwiZGVhZCIsImRlc3Bhd25Bc3Rlcm9pZHMiLCJkZXNwYXduTWlzc2lsZXMiLCJzcGF3blN1bnMiLCJhc3Rlcm9pZFNwZWVkIiwic3Bhd25Bc3Rlcm9pZHMiLCJkZWFkTWlzc2lsZXMiLCJtaXNzaWxlSWQiLCJjb2xsaWRlTWlzc2lsZVN1biIsIm1pc3NpbGUiLCJhc3Rlcm9pZE1hc3MiLCJhc3Rlcm9pZFJvdGF0aW9uYWxJbmVydGlhIiwibm9ybWFsIiwiY29sbGlzaW9uUmFkaXVzIiwibm9ybWFsU3BlZWQiLCJwZXJwZW5kaWN1bGFyVmVsb2NpdHkiLCJtaXNzaWxlVG9ycXVlIiwicm90IiwiY29sbGlkZU1pc3NpbGVBc3Rlcm9pZCIsImNoaWxkcmVuIiwic2NvcmUiLCJ1cGRhdGVTY29yZSIsImhhbmRsZURlYWRBc3Rlcm9pZHMiLCJhY2NlbGVyYXRlU2hpcCIsIm1vdmVTaGlwIiwibW92ZU1pc3NpbGVzIiwibW92ZUFzdGVyb2lkcyIsImdhbWVPdmVyIiwiY29sbGlkZVNoaXBBc3Rlcm9pZCIsImNvbGxpZGVTaGlwU3VuIiwidXBkYXRlQ2xvY2siLCJsYXN0Q2FtZXJhUG9zaXRpb24iLCJ1cGRhdGVQbGF5Q2FtZXJhIiwid2lnZ2xlVXAiLCJ3aWdnbGVTaWRlIiwicmVmcmVzaFRocm90dGxlIiwib3V0X2F4aXMiLCJ0dXJuU3BlZWQiLCJyb3RhdGlvbkZhY3RvciIsInNjYWxlRmFjdG9yIiwicm90YXRlU2hpcCIsImZyZWVjYW1Nb2RlRGVib3VuY2VyIiwic3luYyIsIkZyZWVjYW0iLCJkZXZNb2RlIiwicGxheUxvb3AiLCJnZW5lcmFsRGVib3VuY2VyIiwidXBkYXRlTGV2ZWwiLCJ1bmRldk1vZGUiLCJkZXZMb29wIiwicXVpdEdhbWUiLCJkaXNwbGF5IiwidGltZSIsImhpZGRlbiIsIm1haW5UZXh0IiwiaW5uZXJIVE1MIiwibWVudUJ1dHRvbiIsIm9uY2xpY2siLCJtZW51QnV0dG9uMiIsInBhdXNlIiwiY3VycmVudFRpbWUiLCJTaGlwIiwibG9va1VwIiwiZm92RGVncmVlcyIsIm1vdmVTcGVlZCIsInJlZnJlc2hWaWV3IiwibW92ZSIsInRyYW5zZm9ybVZpZXciLCJ0cmFuc2Zvcm0iLCJjYW0iLCJpbm5lclRleHQiLCJ0b3RhbFNlY29uZHMiLCJtaW51dGVzIiwic2Vjb25kcyIsInRvU3RyaW5nIiwicGFkU3RhcnQiLCJjYW1Nb3ZlIiwiZ2V0RWxlbWVudEJ5SWQiLCJnZXRDb250ZXh0IiwiY2xlYXJEZXB0aCIsImNsZWFyQ29sb3IiLCJLZXlib2FyZCIsIkRlYm91bmNlciIsIkRhdGUiLCJGcmVlQ2FtZXJhIiwiYmFja2xpZ2h0IiwibWVudVNjZW5lIiwiaW5pdEdhbWUiLCJ1cGRhdGVQb3NpdGlvbiIsIm1vdmVtZW50WCIsIm1vdmVtZW50WSIsIndpbmRvdyIsInBvaW50ZXJMb2NrRWxlbWVudCIsInJlbW92ZUV2ZW50TGlzdGVuZXIiLCJtYWluIl0sInNvdXJjZVJvb3QiOiIifQ== \ No newline at end of file diff --git a/asteroids/index.html b/asteroids/index.html new file mode 100644 index 0000000..0cb458c --- /dev/null +++ b/asteroids/index.html @@ -0,0 +1 @@ +3D Asteroids

Asteroids

\ No newline at end of file diff --git a/asteroids/missile.mp3 b/asteroids/missile.mp3 new file mode 100644 index 0000000..78246d8 Binary files /dev/null and b/asteroids/missile.mp3 differ diff --git a/asteroids/music.wav b/asteroids/music.wav new file mode 100644 index 0000000..2a72914 Binary files /dev/null and b/asteroids/music.wav differ diff --git a/asteroids/thruster.wav b/asteroids/thruster.wav new file mode 100644 index 0000000..92b55bf Binary files /dev/null and b/asteroids/thruster.wav differ diff --git a/blog/index.html b/blog/index.html new file mode 100644 index 0000000..d614127 --- /dev/null +++ b/blog/index.html @@ -0,0 +1 @@ +Eli | Blog \ No newline at end of file diff --git a/blog/interviewees-t-test/index.html b/blog/interviewees-t-test/index.html new file mode 100644 index 0000000..d26b860 --- /dev/null +++ b/blog/interviewees-t-test/index.html @@ -0,0 +1,86 @@ +Eli | Interviewee's T-tests

Interviewee's T-tests

2024-10-17

I've been running a lot of coding interviews lately, especially for people coming directly from university. And it strikes me that many candidates will keep only a single informal test that they write and rewrite as they want to check things about their code.

This always sort of bothers me because when you delete a test the first time it passes, you lose the ability to catch regressions. But also because what a "test" is is so informal when you're rewriting the same piece of code over and over, many candidates don't really think about what exactly the goal is of any given test and won't comprehensively test their code.

The easy and practical way to avoid these pitfalls is to keep your old tests and copy-and-paste a new one instead of rewriting the same one over and over. But I'm going to propose a swaggier solution: the T test framework.

The test framework is called T because it's meant to be extremely short and easy to understand (plus it makes joke in the the title work). My hope is that you can read this post and then weeks later reproduce the test framework from memory and explain how it works in under a minute.

You can find the T framework for all the programming languages I feel comfortable doing interviews in—Rust, Python, and C—with their output below the code. But it should be easy to write versions in your programming language of choice.

Rust

fn test(name: &str, t: impl FnOnce() + std::panic::UnwindSafe) {
+    println!("=== {name}");
+    if std::panic::catch_unwind(t).is_ok() {
+        println!("=== PASS\n");
+    } else {
+        println!("=== FAIL\n");
+    }
+}
+
+fn main() {
+    test("failing", || {
+        assert!(false);
+    });
+    test("passing", || {
+        assert!(true);
+    });
+}
+
=== failing
+thread 'main' panicked at src/main.rs:12:9:
+assertion failed: false
+note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
+=== FAIL
+
+=== passing
+=== PASS
+

Python

import traceback
+
+def test(t):
+    print(f"=== {t.__name__}")
+    try:
+        t()
+        print("=== PASS\n")
+    except Exception as e:
+        traceback.print_exception(e)
+        print("=== FAIL\n")
+
+@test
+def failing():
+    assert False
+
+@test
+def passing():
+    assert True
+
=== failing
+Traceback (most recent call last):
+  File "/Users/eli.hunter/t.py", line 6, in test
+    t()
+  File "/Users/eli.hunter/t.py", line 14, in failing
+    assert False
+AssertionError
+=== FAIL
+
+=== passing
+=== PASS
+

C

#include <stdio.h>
+
+int failing() {
+    return 1;
+}
+
+int passing() {
+    return 0;
+}
+
+void test(char* name, int (*t) (void)) {
+    printf("=== %s\n", name);
+    int rtn = t();
+    if (rtn == 0) {
+        puts("=== PASS\n");
+    } else {
+        printf("returned %d\n", rtn);
+        puts("=== FAIL\n");
+    }
+}
+
+int main() {
+    test("failing", failing);
+    test("passing", passing);
+}
+
=== failing
+returned 1
+=== FAIL
+
+=== passing
+=== PASS
+
\ No newline at end of file diff --git a/blog/toothpaste-reviews-2020/index.html b/blog/toothpaste-reviews-2020/index.html new file mode 100644 index 0000000..96fbfb4 --- /dev/null +++ b/blog/toothpaste-reviews-2020/index.html @@ -0,0 +1 @@ +Eli | Toothpaste Reviews 2020

Toothpaste Reviews 2020

2020-09-07

For fun during quarantine I decided to go through my collection of travel-size toothpaste tubes to figure out which one is the best. This was back in late March, early April mind you. I was pretty bored with weeks of quarantine and definitely not adjusted to all the changes, so this was like a fun little game for myself I did. I kept individual notes on all the different toothpastes and ranked them individually.

When I told this to one of my friends they thought it was interesting and encouraged me to make it my first blog post. I think it's a cute enough idea and I've been wanting to start actually making some posts on my blog since I have a few draft posts around. Sadly I didn't think to take pictures of the toothpaste tubes as I was doing the reviews and I can't bring myself to take images from online at the risk of this seeming even remotely legitimate. I also don't include prices or links because I can't be bothered. Anyway, let's get into the ranking.

1. Crest Complete with Scope

Somewhat unsurprisingly, this is the toothpaste that I normally use, so obviously I'd like it. Compared to #2 (Crest Gum Detoxify), it has a slightly worse flavor and foaminess. But at a significant fraction of the price you still get a good-flavored paste that strikes a good balance between foam and paste.

2. Crest Gum Detoxify

At the price, you'd expect this toothpaste to be excellent, and you'd be right. It had the best texture and taste of any of the toothpastes I used and definitely left my mouth feeling the cleanest. It's just so expensive that I can't put it at first.

3. Colgate Clean Mint

This one reminded me a lot of #5 (Crest Cavity Protection Regular Paste) but better across the board. It tasted slightly stronger than it and had a noticeably more pleasant texture. Otherwise it's a pretty unremarkable toothpaste.

4. Listerine Essential Care Gel

This toothpaste (well, toothgel I guess?) surprised me the most of all the toothpastes I reviewed. It doesn't spread very well because it's a gel but the taste is incredibly pleasant and feels very clean. The taste is somewhere between Listerine mouthwash and regular crest toothpaste, leaving a very clean feel in your mouth. Also, once you get used to the gel aspect it actually spreads incredibly well, although it doesn't foam up as much as I prefer.

5. Crest Cavity Protection Regular Paste

Maybe it's because this is what I grew up with but this is exactly what comes to my mind when I think of toothpaste. It has a fairly weak mint flavor but is very agreeable. It spreads nicely and foams up pretty well. Yeah, it's what a toothpaste should do at a good price. I personally consider this the floor of good toothpastes.

6. Aquafresh Extreme Clean

Oh Aquafresh, I never used you before now and I'm glad. This was the hardest paste to spread (much worse than the gel above!) and hardly foamed at all once you actually got it all over your teach. The taste was the harshest mint I tried and didn't even leave your mouth feeling clean. It wasn't actively unpleasant to use but there are so many better options.

7. Crest 3D White

As a rule, I think whitening toothpastes and other products are a bad idea. Teeth aren't naturally perfectly white and there's no long term benefits to whitening them (that I know of). So whitening teeth is just superficial, expensive, and painful to me.

Crest 3D White toothpaste did nothing to change this for me. Every night brushing my teeth felt like punishment where I'd use a toothpaste that tasted, spread, and foamed like silt, leaving a somewhat dirty feeling in my mouth. Also, whenever I used it my teeth would burn a little. From talking to friends I think this is normal for whitening products, but I still don't want brushing my teeth to hurt. It was a bearable experience but made me not look forward to brushing my teeth even if they felt gross.

8. Kid's Crest Cavity Protection Sparkle Fun

Oh. My. God. This toothpaste was awful. I used it a few times as a kid during family vacations and the like, and I do not remember this toothpaste being So unpleasant. It foamed up so much and felt vaguely gritty I think from the glitter. The worst was the taste. All the others tasted like mint, which is what I've come to expect from a toothpaste. However, in an attempt to appeal to kids, this one tastes like bubblegum. I don't know whose idea it was to use a sugary food as a flavor for toothpaste but whenever I used this not only did it taste bad it also left a very dirty taste in my mouth, like I just ate candy. Using it as an adult was an awful experience, but from what I remember as a kid I actually liked it so maybe they're just hitting their target audience really well.

Raw Notes

Here is a literal transcription of my original notes from my phone.

  1. Crest Complete with Scope: A slightly worse Crest Gum Detoxify at a fraction of the price. My personal favorite.
  2. Crest Gum Detoxify: Pleasantly smooth and minty. Most expensive I tried but also best toothpaste I've ever used.
  3. Colgate Clean Mint: Slightly stronger mint than Crest's regular paste makes it slightly more pleasant. But otherwise unremarkable.
  4. Listerine Essential Care Gel: Doesn't spread very well because it's a gel. Taste is shockingly pleasant, somewhere between Listerine mouthwash and regular crest toothpaste. Leaves a very clean feel in your mouth.
  5. Crest Cavity Protection Regular Paste: Unremarkable and reasonably priced.
  6. Aquafresh Extreme Clean: Harsh taste and paste that doesn't spread or foam very well. Not unpleasant but took some getting used to.
  7. Crest 3D White: Tastes like clay and one of the more expensive toothpastes. Weird texture and vaguely burns after use. Unpleasant to use but bearable. Also teeth whitening is unnecessary IMO.
  8. Kid's Crest Cavity Protection Sparkle Fun: Foams up an absurd amount, vaguely gritty, tastes like awful bubble gum. Using it was an awful experience.
\ No newline at end of file diff --git a/elihunter173_resume.pdf b/elihunter173_resume.pdf new file mode 100644 index 0000000..fd661d5 Binary files /dev/null and b/elihunter173_resume.pdf differ diff --git a/favicon-128.png b/favicon-128.png new file mode 100644 index 0000000..4cf33d9 Binary files /dev/null and b/favicon-128.png differ diff --git a/favicon-180.png b/favicon-180.png new file mode 100644 index 0000000..4717864 Binary files /dev/null and b/favicon-180.png differ diff --git a/favicon-192.png b/favicon-192.png new file mode 100644 index 0000000..f54ccbd Binary files /dev/null and b/favicon-192.png differ diff --git a/favicon-32.png b/favicon-32.png new file mode 100644 index 0000000..72d7833 Binary files /dev/null and b/favicon-32.png differ diff --git a/index.html b/index.html new file mode 100644 index 0000000..a70f7b3 --- /dev/null +++ b/index.html @@ -0,0 +1 @@ +Eli \ No newline at end of file diff --git a/notes/index.html b/notes/index.html new file mode 100644 index 0000000..aca41d8 --- /dev/null +++ b/notes/index.html @@ -0,0 +1 @@ +Eli | Notes

NCSU Class Notes

Fall 2018

This was the semester before I settled on using markdown for notes, so I hand-wrote most of these notes but sadly didn't save them.

The other classes I took were: CH 101, E 101, E 115, EC 205, and MA 241.

Spring 2019

Fall 2019

Spring 2020

Fall 2020

Spring 2021

Fall 2021

Notes from Talks

Notes from talks and one-off presentations I attend.

Misc. Notes

Miscellaneous notes from online courses or other events.

\ No newline at end of file diff --git a/notes/nand2tetris/index.html b/notes/nand2tetris/index.html new file mode 100644 index 0000000..a21747d --- /dev/null +++ b/notes/nand2tetris/index.html @@ -0,0 +1 @@ +Eli | Nand2Tetris

Nand2Tetris

This course gradually builds a computer, using a custom architecture called Hack, which can run a functioning version of Tetris from first principles starting with NAND gates. The general flow is

  1. Create all logic gates out of NAND.
  2. Build an ALU (major part of CPU).
  3. Build registers and memory.
  4. Write some Hack programs in machine code.
  5. Use all previous chips to build an implementation of the Hack architecture.
  6. Create an assembler for Hack.
\ No newline at end of file diff --git a/notes/ncsu/1f/csc116/afs_tree.png b/notes/ncsu/1f/csc116/afs_tree.png new file mode 100644 index 0000000..cbf46de Binary files /dev/null and b/notes/ncsu/1f/csc116/afs_tree.png differ diff --git a/notes/ncsu/1f/csc116/index.html b/notes/ncsu/1f/csc116/index.html new file mode 100644 index 0000000..621aa9c --- /dev/null +++ b/notes/ncsu/1f/csc116/index.html @@ -0,0 +1,11 @@ +Eli | CSC 116: Introduction to Computing

CSC 116: Introduction to Computing

Instructor: Dr. Matthias Stallmann | Semester: Fall 2018

Table of Contents

These notes originate from before I settled on using markdown and (Neo)Vim for note-taking, so these are transcriptions from the original Google docs. I actually took way more notes in this class, but I seem to have misplaced most of them so here is what little I still have.

# Misc Shell Stuff

  • man COMMAND: Show the manual entry for that command.
  • Absolute Path: begins at root, starts with /
  • Relative Path: begins at current directory, doesn’t start with anything.
  • \: Escape character, allows for special characters to be encoded.
  • -: Single character / short flag.
  • --: Multiple character / long flag.
  • .: Current directory.
  • ..: Above directory.
  • ~: Home directory.

{{ figure(src="afs_tree.png, title="Simple Heap") }}

# Commands

  • pwd: print working directory
  • cd [DIRNAME]: Change directory to DIRNAME if specified. Otherwise home directory (~).
  • mkdir DIRNAME: Makes new empty directory.
  • rmdir DIRNAME: Removes directory. Fails if it is not already empty.
  • ls [PATH]: List contents of PATH if specified. Otherwise current directory.
    • -l: List contents in long form (exact size, permission access, last modified, etc).
    • -a: list ALL content (even hidden files/directories).
  • mv SOURCE DESTINATION: Move/rename file/directory to destination.
    • -n: No-clobber. Won't delete another file.
    • -i: Interactive. Asks before clobbering an old file.
  • cp PATH [PATH2 ...] DEST_PATH: Copy file/directory from path (and path2 ...) to DEST_PATH. If multiple paths are specified, DEST_PATH must be a directory.
    • -R/-r: recursive copy (copy directory and all subdirectories)
  • rm PATH: Remove file.
    • -i: Interactive. Asks for conformation.
    • -r: Recursive. Removes all files and child directories.
    • -f: Force. Ignore all failures and go ahead at all costs.
  • chmod PERMISSIONS PATH: Change the permissions of PATH. If PERMISSIONS is a 3-digit octal permission, then it sets the permissions. Otherwise, it modifies them based on the ugo+-rwx scheme.
  • diff FILE1 FILE2: Reports differences in FILE1 and FILE2. Doesn't display differences in binary files by default.
  • wc FILE: Find word count, line count, character count, of FILE.
  • more FILE: Scroll through the contents of FILE. This is called a pager.
    • q: Quit.
    • enter: See more.
    • space: Next page.
    • /pattern: Find pattern.
  • less filename: Scroll through the contents of FILE, with the ability to go up and down. This is a more advanced version of more.
    • Flags
      • -g: Highlight match of searched string.
      • -I: Use case insensitive searches.
      • -N: Show line numbers.
    • Keys
      • q: Quit.
      • space: Next page.
      • d: Next half page.
      • b: Previous page.
      • u: Previous half page.
      • v: Edit command.
      • <: First line.
      • >: Last line.
      • /: Forward search.
      • ?: Backward search.
  • cat [FILE1 ...]: Read and print file(s) as listed sequentially. It concatenates files! If given no files, it just forwards standard in (more on that later).
  • zip ZIPFILE FILE [FILE2 ...]: Zip compress FILE (and FILE2) and place them into ZIP_FILE, creating ZIPFILE if necessary.
    • -R: Recursive. Used for zipping directories.
  • unzip ZIPFILE: Unzips ZIPFILE and places its files in the current directory.
    • -d DIRNAME: Places unzipped files in destination dir.

# Andrew File System (AFS)

AFS uses an Access Control List (ACL) to control permissions to files and directories. It is an extended version of the UNIX permissions system, using the following permissions.

  • a (administer): Change the entries on the ACL
  • d (delete): Remove files and subdirectories from the directory or move them to other directories
  • i (insert): Add files or subdirectories to the directory by copying, moving or creating
  • k (lock): Set read locks or write locks on the files in the directory
  • l (lookup): List the files and subdirectories in the directory, stat the directory itself, and issue the fs listacl command to examine the directory's ACL
  • r (read): Read the contents of files in the directory; issue the ls -l command to stat the elements in the directory
  • w (write): Modify the contents of files in the directory, and issue the UNIX chmod command to change their mode bits

These are all subcommands of the root fs command. That is for a command listed as foo, you run fs foo. For more info read http://docs.openafs.org/Reference/1/

  • la [PATH]: List Access. Shows a list of all access permissions to current directory or specified directory.
  • sa PATH UNITY_ID ACCESS: Set Access. Sets access permissions to PATH for UNITY_ID.
  • lq PATH: List quota. Show how much space PATH is using versus your quota (total allowed).
  • mkm DIRPATH users.<UNITY_ID>.backup: Make Mount. Creates backup directory at DIRPATH containing a backup of UNITY_ID's home directory.
  • rmm dirname: Remove Mount. Removes mounted directory.

# Java Commands

  • javac FILENAME.java: Compile .java file into .class.
    • -d DIRNAME: places .class file into DIRNAME.
  • java FILENAME: Runs program with filename (no extension). There must be a .class file with that name in the classpath.
    • -cp dirname: Modifies the classpath. Basically, you specify the location of the class file.

# Javadoc

/**
+ * This is a Javadoc comment. You must use this
+ * for programs.
+ *
+ * @param paramName Use this to specify
+ * parameters.
+ *
+ * @author authorName Use to specify the author
+ * of the code.
+ */
+

# Git Commands

These are all subcommands of the root git command. That is for a command listed as foo, you run git foo.

  • clone URL [DIRNAME]: Clones git repository (repo) to the current directory or specified directory.
  • add PATH: Add changes to staging area for committing.
  • commit: Create a snapshot of the changes in the staging area and commit them to your current branch.
    • -m "MESSAGE": Specify message with commit. Otherwise opens up core.editor to edit commit message.
  • push [BRANCH]: Pushes most recent revision to remote repo. If you don't specify BRANCH then you're using the "upstream" branch, that is the branch on the server that your branch was made from. For this class it'll be master mostly.
  • status: Show status of current repostiroy. Lists files added, files modified but unadded, etc.
  • diff FILE: Show the differences between last commit and current status.
  • branch BRANCH: Create a new branch off your current branch.
    • -d: deletes existing branch
  • checkout BRANCH: Switch branches (and a whole bunch more).
    • -b: Creates branch and then switches to it.
  • log: Shows a log of recent commits.

## Configuration

Git has a bunch of configuration values that go in your git config file. We'll list the key nes for this class.

  • user.name: Name of user.
  • user.email: Email of user.
  • core.editor: Main editor for git commit messages and other things.

# Miscellaneous EOS Notes

These may or may not apply to all computers outside of EOS. Try and see what happens.

## Commands

  • script: Creates a log of every command executed and its output. Used for E115 assignments.
    • -f: Force log to begin immediately.
    • -a: Appends the log to a previous one.
  • clear: clears the screen
  • add: Show list of installable programs.
  • add PROGRAM: Add program to current session as command.
  • attach ABSOLUTE_PATH: Create shortcut at ABSOLUTE_PATH.
    • for E 115 use /ncsu/e115
  • last [USER]: Show everyone's last login or just USER's.
    • -l: Show only last login and logout.
  • write username: Send message to user.
  • who: Sees who is logged in.
  • passwd: changes password

## Shell Shortcuts

  • up: Previous command.
  • down: Next command.
  • ctrl + c: Stop command.
  • ctrl + z: Pause command.
  • fg: Reopens command.
  • tab: Autocomplete (iff unambiguous).
  • tab x2: Show all autocomplete options.
  • ";": Shows line has ended and allows multiple commands to be chained.
\ No newline at end of file diff --git a/notes/ncsu/1f/index.html b/notes/ncsu/1f/index.html new file mode 100644 index 0000000..1c7fbef --- /dev/null +++ b/notes/ncsu/1f/index.html @@ -0,0 +1 @@ +Zola

Welcome to Zola!

You're seeing this page because we couldn't find a template to render.

To modify this page, create a section.html file in the templates directory or install a theme.
You can find what variables are available in this template in the documentation.

\ No newline at end of file diff --git a/notes/ncsu/1s/csc216/abba_fsm.png b/notes/ncsu/1s/csc216/abba_fsm.png new file mode 100644 index 0000000..856d61f Binary files /dev/null and b/notes/ncsu/1s/csc216/abba_fsm.png differ diff --git a/notes/ncsu/1s/csc216/class_design.png b/notes/ncsu/1s/csc216/class_design.png new file mode 100644 index 0000000..a092835 Binary files /dev/null and b/notes/ncsu/1s/csc216/class_design.png differ diff --git a/notes/ncsu/1s/csc216/csc_216_lifecycle.png b/notes/ncsu/1s/csc216/csc_216_lifecycle.png new file mode 100644 index 0000000..abaac8f Binary files /dev/null and b/notes/ncsu/1s/csc216/csc_216_lifecycle.png differ diff --git a/notes/ncsu/1s/csc216/full_class_diagram.png b/notes/ncsu/1s/csc216/full_class_diagram.png new file mode 100644 index 0000000..31c6806 Binary files /dev/null and b/notes/ncsu/1s/csc216/full_class_diagram.png differ diff --git a/notes/ncsu/1s/csc216/index.html b/notes/ncsu/1s/csc216/index.html new file mode 100644 index 0000000..8a348bf --- /dev/null +++ b/notes/ncsu/1s/csc216/index.html @@ -0,0 +1,250 @@ +Eli | CSC 216: Intro to Software Engineering & Programming Concepts

CSC 216: Intro to Software Engineering & Programming Concepts

Instructor: Dr. Sarah Heckman | Semester: Spring 2019

Table of Contents

# Administrivia

## Grades

WeightComponentAdditional Info
12%Guided Projects
34%ProjectsTwo projects. 3% of each is part 1. 14% of each is part 2.
Guided Projects12
Labs15
Exam 112Exam 1 will cover material from approximately the first third of the course.
Exam 212Exam 2 will cover material from approximately the first two-thirds of the course.
Exam 315Exam 3 will cover all materials for the course.
  • Need >65% on exams to get a C or higher

## Lecture

  • Attendance: You must answer at least one of the Google form exercises per class.
    • If miss 4+ labs, -5 pt on final grade.
  • Instructor: Dr. Sarah Heckman (sesmith5)
  • Email: sarah_heckman@ncsu.edu
  • Web Page: https://people.engr.ncsu.edu/sesmith5/
  • Phone: 919-515-2042
  • Office Location: Engineering Building II, Room 2297
  • Office Hours: (See calendar for most up-to-date office hours)

## Lab

  • Name: Hanna Fernandez
  • Email: hfernan@ncsu.edu
  • Jenkins: go.ncsu.edu/jenkins-csc216-2
  • Attendance: Required.
    • Missing 4 labs will result in F
  • A lab grade may be dropped.

## Assignments

  • Projects:
    • Part 1: Design and black-box testing. Independent.
    • Part 2: Implementation and testing. Optionally independent.
  • Guided Projects:
    • There will be 3.
    • All independent.

## Academic Integrity

## Main Topics

  • Managing Complex Software: Software gets big. How do you handle it?
    • Tools: Eclipse :(
  • Test Driven Development: Writing tests first and then trying to make it so that your code passes those tests.
    • Tools: JUnit 4
  • Code Coverage: How much code is being tested
  • Static Analysis: Looks at the code itself.
    • Tools: Checkstyle, SpotBugs, PMD, EclEmma
  • Version Control: Manages source code across machines and tracks and merges changes.
    • Tools: Git
  • Continuous Integration: Whenever there is a change in the repository, test the code.
    • Tools: Jenkins

# Object Oriented Design (OO)

N.B. These are defined with reference to Java.

  • Procedural: Execute code without objects. Everything is simply a list of of things to run (i.e. a procedure!).
  • Object Oriented: We deal with objects, representations of real things, which can interact with other objects and classes in limited, controlled ways.
  • Method: A list of statements to run.
    • Static: A method which isn't connected to an object.
    • Non-static: A method which is connected to an object.
  • Class: A blueprint for an object. Has a list of methods and fields that each object should have, and it defines what each of those methods do (normally) and what type those fields are.
  • Object: An instance of a class. Takes up space in memory (well, most objects are really just reference objects) which defines the fields. It can leverage the methods it has given to it by the class to do stuff with its fields.
  • Reference Objects / Pointers: A much, much smaller bit of information that simply points to a place in memory. When you "copy" objects normally in Java, it just copies the reference object / the pointer

## FAQ

  • Why use abstract classes and interfaces? To promote code reuse and make sure that methods can be interacted with in a standard way. Abstract classes promise that there will be some functionality.
  • Why make the distinction? Because, in Java, you can only extend a single class but you can implement as many interfaces as you want.
  • How do you Javadoc abstract methods? Provide high-level guidance to what functionality is expected from this method.
  • How do you Javadoc interfaces? Provide similar comments like abstract classes, but even better because they are so broad.
  • Why use interfaces if you're just going to use it once? (A) It makes more sense. (B) It makes it easier for you to add more things in the future. (C) You might not be the only one who wants to use something like that.
  • Can you cast a parent to a child? Nope! Well, technically, yes but only if the child doesn't add anything on top of the parent. But, all children add at least a pointer to the parent.

## Vocabulary

  • Single Inheritance: A class can only inherit a single class or have a single parent.
    • Why? To prevent name space clashing (although this does have other solutions).
  • Polymorphism: Where you can treat multiple different types (of objects) as the same type.
    • This is normally visualized, in Java, as a hierarchy of classes, like a family tree.
  • Abstract Class: Classes that can have abstract methods.
    • Concrete children extends this abstract class but can only implement one.
    • Consider nouns.
  • Abstract Method: An exposed method in an abstract class (since it must be
  • implemented in a child).
  • Interfaces: Special classes that only describe abstract methods.
    • Concrete children implements this interface and can implement many.
    • All classes are public and abstract (because nothing else matters to outsiders).
  • Abstract classes and interfaces cannot be instantiated.
    • Abstract classes can specify constructors, however.
  • Delegation: The process of wrapping an Object so that it uses the Object's behaviors as its behaviors.

## Methods

  • Methods have a signature, which is their name and parameter types.
  • Parameters have a type and can be final.
  • Syntax: accessMod [static] ReturnType name([final] Type param1, [final] Type param2)

## Semantics

  • Value Semantics: This bit of data is dealt with directly. That is its actual information in memory.
  • Reference Semantics: This bit of data is interacted with by a reference object / pointer.
  • Dereferencing: Accessing the data or the method of an object.
    • Dot Notation: The process of accessing the methods of a reference.
      • e.g. reference.method(), reference.field

### Null Semantics

  • null: A built in value that does not refer to any object.
    • It cannot be dereferenced!
  • null can be passed, initialized, checked for, returned (for bad data), etc!

### Java Specifics/Oddities

  • Java uses reference semantics for all objects and value semantics for all primitives.
  • Implicit Parameter: this is an implied parameter in all methods of an object. It references the current object.
  • Default Values: All types have specific default values.
    • int = 0
    • double = 0.0
    • boolean = false
    • char = null (character)
    • Object = null (object)

### Invariants

  • Invariants: Things which you state are going to be always true. You must ensure it.
    • Java Invariants: If you override equals(), you should also override hashCode()
    • hashCode(): Hashes an objects

### Cloning

  • .clone(): Returns a shallow copy of a given object. This comes from interface Cloneable
  • What about deep copies?

## Composition and Delegation

  • Composition: A class has fields that are instances of other class(es).
  • Delegation: The course can call upon methods and other things of the objects it contains. Allows an object to not get too complex!
  • Abstraction: The process of separating ideas so you don't have to know everything! This is the beauty of OOD.
  • Encapsulation: Hide the plumbing or implementation details from the clients. They don't need to know and they might mess things up!
    • Ways: Make fields private so you can control what people do.

## Inheritance

  • Hierarchical. Allows specialization of broader class.
  • The super class (parent) is ignorant of the sub class (child)
  • Super class constructed first. That means that the sub class can override parts of the super class and a sub class has a pointer to its parent.
  • The sub class is an instance of the super class.
  • A child cannot modify the private variables of its parent.
    • However, it can modify protected variables. (But those are yuck!)
  • Everything in a hierarchy should define its own equals methods. Then, the child checks the parent's equality and then checks its specialization.

### Java Syntax

  • extends: Shows parent/superclass of child/subclass
  • super: References the parent/superclass of the current class.
  • A class can only extend one class.
public class SubClass extends SuperClass {
+  // This class has all of the (implemented)
+  // functionality of the super class
+}
+

### Usage

  • Children are clients of the parent and must use accessor/mutator methods to modify those fields.
  • A child can act as its parent. A parent can not act like its child.
  • If a child is acting as a parent, you cannot reference any of the child's (childish) things.

## Abstract Class

  • If you use interfaces or abstract classes to interact with someting, you can only interact with the methods present in those interfaces or abstract classes.
public abstract class Beer
+implements Drinkable, Brewable {
+
+  private String name;
+
+  public Beer(String name) {
+    this.name = name;
+  }
+
+  // Declare abstract methods
+  public abstract boolean
+  addIngredient(BeerIngredient i);
+  public abstract Collection<BeerIngredient>
+  getIngredients();
+
+  // Implement inherited methods
+  public void brew() {
+    System.out.println(
+      name + " is being brewed"
+    );
+  }
+
+  // I don't have to implement Drinkable because
+  // this is an abstract class
+}
+

## Interface

public interface Brewable {
+  void brew();
+}
+

## Nested Classes

  • Outer Class: A class that contains an inner class.
  • Inner Class: A class defined within another class.
  • Compiled Bytecode Class Names: OuterClass$InnerClass.class
  • In UML Diagrams:
    • Composition connector (black diamond)
    • Inner-class connector (white circle with black x)
  • Static Nested Class: A static class inside of an outer class.
    • These can only access the outer class's instance values.
  • To access parent outer explicitly use OuterClass.this.
  • To access public inner class, use OuterClass.InnerClass.

### Advantages

  • Encapsulation: Clients don't have to worry about them (if they're private)
  • Inner classes can change the instance fields of their outer class.
    • It cannot access the nested classes fields!

## Anonymous Objects

  • Anonymous Object: An object that is created with no reference to it.

## Anonymous Classes

  • Anonymous Classes: Creating a class in-line. A class that has no real name
    • Mostly used when creating an interface that implements some methods.
new Foo() {
+  public int someState;
+  public void doStuff() {
+    // Do things
+  }
+}
+

## Exceptions

  • Exception: A special object that represents an error or bad condition.
    • Unchecked Exception: Exception that doesn't have to be handled to be compiled.
    • Java Examples: InputMismatchException
    • For Java: extend RuntimeException
    • Checked Exception: Exception that must be handled to be compiled.
    • Java Examples: FileNotFoundException
    • For Java: extend Exception
    • Checked vs Unchecked is semi-arbitrarily decided by Java language developers.
  • throw: A keyword that throws an object that implements the Throwable interface.
  • throws: A keyword in the method header that states that the stated exception might be generated

### Try-Catch-Finally Blocks

  • Try: Statements that might throw exception.
    • Mandatory block.
  • Catch: Statements that handle exception.
    • Mandatory block.
  • Finally: Statements that always execute. Good place for closing resources.
    • Optional block.
  • Normal Flow: Specific exception, less specific exception, general exception
  • Multi-catch: Can catch a list of exceptions in a common catch block.
    • For Java 1.7+
  • Try-with-Resources: Declares one or more resources that must be closed. Essentially automatically closes resources when necessary. (Opened resources must implement Autoclosable)
    • Alternative to try.
    • For Java 1.7+
try {
+  // Do things
+} catch (ExceptionType name) {
+  // Handle errors
+}
+
try {
+  // Statements
+  // Exception thrown!
+  // Statements skipped
+} catch (UnmatchedExceptionType name) {
+  // Would handle exception, but doesn't go in
+  // here
+} catch (MatchedExceptionType name) {
+  // Handle thrown exception
+} catch (AlsoMatchedExceptionType name) {
+  // Would handle exception, but goes to first
+  // catch block.
+} finally {
+  // Statements here are always executed!
+}
+
try {
+  // Throws either Exception1 or Exception2,
+  // that need to be handled equally
+} catch (Exception1 | Exception2 name) {
+  // Handle exceptions
+}
+
try (File f = new File()) {
+  // May throw FileNotFoundException
+} catch (FileNotFoundException e) {
+  // Handle exception
+}
+// Resources automatically closed!
+

### Create Custom Exceptions

  • Don't go too crazy. They're generally not a very good idea.
    • If you can use a common Java exception, do!
  • Useful if you want to add more information or have a specific Exception that is not present in the Java exceptions library.
public class MyException extends Exception {
+  public MyException(String message) {
+    super(message);
+  }
+  public MyException() {
+    super("Exception message");
+  }
+}
+

## Errors

  • You rarely need to create errors.
  • Errors are fatal issues that are rarely encountered and should (almost) never be caught.
    • Java Examples: OutOfMemoryError

# (Java) Libraries

  • Libraries: A reusable collection of classes and pieces of software. Promotes code reuse, standard ways of doing things, efficient code, and focusing on what is really important for your project.
    • Examples: Java, Java Collections, JUnit, Apache
    • "It's a solved problem."
  • API: A list of instructions of how to interact with the software.
    • For this class, they are simple a series of webpages, created from Javadoc, that describe how to use our afternoon.
  • Installation of Libraries:
    • Add the JAR (Java ARchive) to your classpath.
  • Classpath: A set of locations that your Java Compiler and JVM will look at for code.
    • By default, your system PATH variable. However, you can update it with command line flags.
    • Eclipse does this automatically with your .project and .classpath files. This allows you to structure your projects like Eclipse expects and compile them easily within Eclipse.
    • In Eclipse, you add libraries to the build path on a per-project or a global scale.

## Library and Build Managers

  • Maven: Helps manage projects and libraries. Helps build.
  • Gradle: Like maven but different.
  • Ant: Helps manage projects and libraries.

## Java Iterators

Java collections can be iterated using a for-each loop.

for (Type item : container) {
+  // Do things
+}
+

This allows for more effiecient code, as you don't always have to pass through things multiple times. Instead, you can use an iterator which keeps track of its position and its value.

To make a class use iterators, you should implement Iterable<E>.

public class List<E> implements Iterable<E> {
+  // Stuff
+  public Iterator iterator() {
+    // Make iterator and stuff
+  }
+  public class Iterator<E> {
+    // Do stuff
+  }
+}
+

### API

  • hastNext() : boolean: Returns true if the Iterator can return another element.
  • next() : E: Returns the value of the next element. (This is also the thing the Iterator is currently on.)
  • remove(): Removes the current element under the Iterator.

## Limitations

  • Iterator is unidirectional.
  • Adding things while Iterating causes issues. (ConcurrentModificationException)

## Misc

  • Iterators keep track of their spots even if you remove stuff. If properly implemented.

## Java GUIs

  • Java GUI Libraries:
    • java.awt.*: Abstract Windowing Toolkit. The OG.
    • javax.swing.*: Java Extension Swing
    • Inherits from awt.
  • Components:
    • Frame: Top-level window with title and border.
    • Container: A thing that contains components.
    • Panel: A thing that can hold other components or panels.
    • Components: A thing that does a thing (e.g. buttons, text boxes).
    • Top-level containers: JFrame, JDialog, JApplet
    • General-purpose containers: JPanel, JScrollPane
    • Special-purpose containers: JRootPane, JLayeredPane
  • Layouts:
    • BorderLayout: The UI is divided into north, sound, east, west, and center.
    • FlowLayout: Components go from left to right and wrap when they run out of room.
    • BoxLayout: Components in row or column.
    • CardLayout: Components in a stack where only the top is shown.
    • GridLayout: Things are in a rectangular grid.
    • GridBagLayout: Things are in a rectangular grid and can span multiple grids.

GUIs are event-driven. That is, we wait for the user to interact with the GUI and they can do whatever they want. We can, however, restrict their access.

This means, even close buttons, don't truly close the program.

To create a GUI, try storyboarding and consider what your user needs to do. Draw a picture of your planned GUI and adjust it as you think about what a user must do with it. Try sectioning things off into logical blocks or creating a tree of components.

Generally, thinking about things as columns and rows is very helpful.

Java uses the event model to handle events in GUIs. This uses event objects that encapsulate the information required to handle the event; this includes the information entered, the type of action, and the source of the event (e.g. a button).

An event model uses events, handlers, and listeners. Events are things that the user has done or things that have occurred. Handlers are things that notify listeners when events have occurred. Listeners are things that take action given certain events. In Java, the event is an EventObject and a listener is an EventHandler. Because of this structure, we must register listeners to the handler.

To create listeners, you create an object that implements ActionListener. There are many ways to do this:

  • You could make your GUI implement ActionListener and then create a broad eventPerformed(ActionEvent) method that handles all events performed, using if statements.
    • Pros: Separates controller and view code.
    • Cons: God it's so fucking gross.
  • Create named ActionListener classes.
    • Pros: You can reuse code so much.
    • Cons: You have to write a ton of boilerplate and go across multiple classes.
  • Create anonymous ActionListeners with their specific code.
    • Pros: You don't get gross spaghetti code with tons of if statements.
    • Cons: It mixes controller and view code. It is harder to reuse things.
  • Create lambda expressions for handling events.
    • Pros: You don't have to write as much boilerplate as the anonymous class. You can also reuse some code.
    • Cons: It doesn't separate the controller and view code as much.

Low level events are interactions with the operating system, like key pressed. Semantic events are user-actions, like button clicks and text edits.

To handle low level events, it is recommended to use Java's *Adapter abstract classes. These make it easier to handle low level events and "convert" them to action events.

  • JButton:
    • .processEvent(): Takes in ActionEvent and takes action.
public class CSC216GUI extends JFrame
+implements ActionListener {
+
+  public CSC216GUI() {
+    // Setup
+    setTitle("CSC 216 GUI");
+    setSize(400, 400);
+    setLocation(600, 200);
+
+    // Create main container
+    Container c = getContentPane(
+      new BorderLayout()
+    );
+
+    // Components
+    JLabel lblCheer = new JLabel("Wolf!");
+    c.add(lblCheer, BorderLayout.NORTH);
+
+    JButton btnClick = new JButton("Click me!");
+    // Anonymous class
+    btnClick.addActionListener(
+      new ActionListener() {
+        void eventPerformed(ActionEvent e) {
+          System.out.println("Anonymous class");
+        }
+      }
+    );
+    // Lamda expression
+    btnClick.addActionListener(e -> {
+      System.out.println("Lambda expression")
+    });
+    // GUI is listener
+    btnClick.addActionListener(this);
+    c.add(btnClick, BorderLayout.SOUTH);
+
+    // so it actually closes
+    setDefaultCloseOperation(EXIT_ON_CLOSE);
+    // default is invisible :)
+    setVisible(true);
+  }
+
+  public void eventPerformed(ActionEvent e) {
+    System.out.println("GUI is listener");
+  }
+
+  public static void main(String[] args) {
+    CSC216 gui = new CSC216GUI();
+  }
+
+}
+

## ListIterator

A List specifically for lists. All linked lists are doubly linked lists. To support inserting in doubly linked lists, you need to make the first and last node actual nodes and not names for the boundary nodes (like what I said when I created Walker). ListIterator's think about being between two nodes.

  • Differences:
    • Can move forward and backward through the list (doubly linked).
    • Sits between two elements.
    • Can handle concurrent adding.

### ListIterator API

  • hasNext() : boolean: Returns true if the ListIterator can return the next element.
  • next() : E: Returns the next element.
  • nextIndex() : boolean: Returns the index of the next element.
  • hasPrevious() : boolean: Returns true if the ListIterator can return the previous element.
  • previous() : E: Returns the previous element.
  • previousIndex() : boolean: Returns the index of the previous element.
  • add(E): Inserts the specific element between the two elements the ListIterator is currently at.
  • remove(): Removes the element last returned by next() or previous().
  • set(E): Replaces the last element returned by next() or previous() using the given data.

### AbstractSequentialList

AbstractSequentialList is an abstract class is useful for creating lists. This implements almost everything except for listIterator() and size() because everything is done through ListIterator.

# Design Patterns

  • Design Pattern: A standard way to solve a specific problem
    • "It's a solved problem!"
    • Why? Because they help communication
  • Design patterns emerge.
  • Common Ones: Written by "The Gang of Four" and there are 23 written in a big book.

## Families

  • Creational: Process of object creation.
  • Structural: Composition of classes or objects.
  • Behavioral: Ways in which classes interact and distribute responsibility.
  • Concurrency: How to make code that is thread-safe and can run at the same time without breaking.

## Model-View-Controller (MVC)

  • What does it do? Separates the presentation of info from the working with the info.
  • Why?
    • You can hotplug the view and/or controller really easily!
    • You can debug issues more easily because you know what is failing.
  • Model: Contains data and the logic for maintaining that data.
  • View: Displays things to the user.
  • Controller: Handles and translates the data of the model for the view or
  • others.
  • Examples:
    • Java Swing Apps:
    • View and controller in the same class (very tightly coupled). (GUI class)
    • Web Apps:
    • View: HTML/XHTML + CSS.
    • Controller: GET and POST.
    • Model: Whatever backend underlies the project.

## Observer

You have a single object that you want to be able to notify any number of other objects about when it changes.

To do this, you make the single object you want to have other things observe extend Observable, which means it knows how to handle adding observers and notifiers. Then you have your observers extend Observer, which means they know how to handle being notified by an observable object.

Why would you do this? It allows you to decouple the thing your objects want to watch, meaning that it doesn't have to know about its listeners. This allows you to make easier to refactor to the higher level observers without breaking the observable.

This is commonly done in GUIs.

// In the Observable when something changes
+this.setChanged();
+notify();
+

## Singleton

A class controls the number of instances and the manner of creation of its instances.

Here, we will only ever use a singleton that manages one instance of itself.

Why do this? So outsiders only look at a single instance or controlled instance by the class.

## State Pattern

A way to implement FSMs with objects.

Essentially, you have a state object representing each state. The machine parses the input and calls the appropriate method on the current state object. That state object then acts and changes the parent state object as necessary.

# Design Suggestions

  • Don't implement functionality you don't know the clear use of.
  • Don't implement any functionality if its not in the requirements.
    • You should update the requirements, not implement what isn't there!
  • Limit class mutability as much as possible.
    • Omit mutators that have no use.
    • Limit object creation to the constructor.
  • Classes should be as cohesive as possible. They are a single level of abstraction
    • Should this class/object really know this?
  • Limit coupling. Make classes orthogonal
  • Design documents are persuasive papers.
  • Don't create a bunch of objects. It's inefficient.
  • Changing things is dangerous. Adding things is less.
  • Duplicating works is dumb.
    • One reason OO is useful.

# Software Engineering & Design

## Methods of Showing Design

  • UML (Unified Modeling Language) Diagram: Shows the interaction between different classes and objects.

  • CRC (Class, Responsibilities, Collaborators): Shows, on a per class basis, what each Object does and is responsible for.

    • Responsibilities: Behaviors
    • Collaborators: State, interacting classes
  • Software Design Models: A generalized approach to creating some piece of software.

    • Waterfall
    • Spiral
    • Iterative (Agile!)
  • Software Process Development Phases

    1. Requirements/Analysis
    2. Design
    3. Implementation/Code
    4. Testing
    5. Integration
    6. Maintenance
  • Software Artifacts: Any bit of documentation that is associated to the software.

  • Best Practices:

    • Design Practices
    • IDEs
    • Programming languages
    • Reviews and Inspections
    • Static Analysis
    • Testing Practices (diabolic testing)
    • Code Coverage
    • Version Control
    • Continuous Integration
    • Why use best practices?
    • Improve programmer productivity.
    • Reduce software faults and failures.
    • Support collaboration.

## Software Process

  • Goal of Design: Decide the software's structure and the hardware's configuration.
    • How will individual classes and software components work together?
  • Small Programs: ~10s classes/interfaces
  • Medium Programs: ~1000s classes/interfaces
  • General Design Flow:
    • What are the useful objects (candidate objects)?
    • What are the useful things objects should do (candidate behaviors)?
    • What are the useful things for each object to know (candidate state)?

### Requirements/Analysis

  • Goal: Understand customer requirements for the software system.
  • Difficult to get right because customers don't know what they want or how to communicate it.
  • Requirements often evolve.
  • Software Artifacts: Requirements documents, use cases, user stories.
    • CSC-216 uses "use cases".
    • Requirements Documents: Very formal "the system shall"
    • Use Cases: Grouped list of abilities of the system.
    • User Stories: A specific story about what a user is doing.

### Design

  • Goal: Decide the structure of the software and the hardware configurations that support it.
  • What am I designing for?
  • Software Artifacts: Design documents, class diagrams, UML diagrams.

### Implementation/Code

  • Goal: Translate requirements/design into concrete system.
  • Decide the implementation language (should be driven by how you designed).
  • Software Artifacts: Source code, bug database, config files, media, executables, source code repo

### Testing

  • Goal: Find errors in software.
  • Do this as quickly as possible!
  • Software Artifacts: Test code (test harnesses, scaffolding, etc.), bug database, test database, test inputs/outputs, documentation.

### Integration

  • Goal: Bring the software system together.
  • Individual programmers work together to bring all their parts together.
  • Software Artifacts: APIs, interfaces, integration documentation.

## Software Design Models

### Planned/Waterfall

  • A planned, step by step method of development

Waterfall Design Process

#### Pros

  • Allows workforce specialization
  • Great for known requirements.

#### Cons

  • Very hard to fix early issues.
  • Takes forever to deliver.

### Iterative/Agile Model

  • An iterative model that results in immediately useful products.

#### Pros

  • Allows for more interaction between developers and consumers, reducing the likelihood of misunderstanding.
  • Allows for more communication between developers reducing the risk of error, since they have to talk more between each iteration.

#### Cons

  • Scope Creep: The expectation of the software increasing.

## Task Planning

  • Task Planning: Assigning tasks in a logical way that optimizes the work people accomplish.
  • Tasks should be focused around deliverables.
    • Deliverables: Specific objects/things that must be turned in or delivered.
  • Tasks should have a time estimate attached to them
    • Ideal Time: The amount of time something should take ideally, no distractions, work 100% of time with 100% efficiency.
    • Elapsed Time: The amount of time it actually takes to do something.
  • Story Points: A relative, unit-less measure of time to express the size/difficulty of a task.

### Pros

  • Defines project scope
  • Illuminates project deliverables
    • What actually matters?
  • Accountability for teams
    • Reduce conflicts by identifying task owners
    • Increase leaderships

## Testing

  • Testing = Process to find faults. "The dynamic verification of the behavior of a program on a finite set of test cases, suitably selected from the usually infinite executions domain, against the expected behavior."
  • Write black box test cases first! That way you aren't biased.
  • Tips:
    • Really just try to mess things up.
    • Think about equivalence classes.
    • For white box tests, think about cyclomatic complexity.
  • Test code should be separate from source code.
  • Test code should be javadoc'd as well as source code.
  • Iterate between tests and coding

### Vocabulary

  • Fault A bug. An incorrect process, step, or data definition.
  • Verification: Evaluates whether the product is being built right.
    • White box testing. Code is known.
    • Test individual paths, correctly loops at boundaries, internal data structures, logical decisions are complete (handle true and false).
  • Validation: Evaluates whether the right product is being built.
    • Black box testing. Code is unknown.
    • Incorrect or missing functions, interface errors, errors in data structures, behavior or performance errors, initialization and termination errors.
  • Equivalence Classes: Chunks of input/output space that (should) all work identically. Pick a representative (middle!) value from these chunks.
    • This is part of the suitably selected part of testing.
  • Cyclomatic Complexity: The number of paths of execution that can be taken through a program (or at least an estimate of it).
    • Easy way to find: Number of decisions + 1 (not always correct!)

### Types of Testing

  • Unit: Tests a single bit of software (normally a method). Should be automated.
    • JUnit
  • Integration: Tests a small group of software units together (or integrated!). Should be automated.
    • JUnit
  • Functional/System: Tests a full, complete, integrated system / piece of software. Should be external.
  • Acceptance: Tests done by client to make sure that software works as expected.
  • Regression: A selective retesting of all other types of testing. This should always be (more or less) the same and should always be passed. DONE TO MAKE SURE THAT PROGRAM WORKS AS EXPECTED. Should be automated.
  • Beta: Tests done by a subset of consumers. They just use the software and see if they like it!

### Test Case Information

  • Unique Identifier
    • Black Box: Name of test in document.
    • White Box: Name of test method or specific assert.
  • Input into the program or program unit
    • Black Box: How the user runs and interacts with the program. Should be extremely specific.
    • White Box: Inputs to a method that set up the test.
  • Expected Results from the program or program unit
    • What you expect to get back, based off the requirements. Should be extremely specific.
  • Actual Results from the program or program unit
    • Black Box: What the user is shown.
    • White Box: Return values or state from other methods or objects.

### Code Coverage

  • Code Coverage: A measure of test case completeness.
    • Method Coverage: How many methods have been tested?
    • Statement Coverage: How many statements in each method have been tested?
    • Decision/Branch Coverage: How many decisions have been evaluated on their true and false path?
    • Condition Coverage: How many individual conditionals have been executed for both their true and false path? (EclEmma's Branch coverage)
  • If you have 100% statement coverage, you have 100% condition coverage
  • Coverage is not perfect and doesn't say that your test cases are strong.
  • 80-90% line/statement coverage is expected for each non-UI class.
    • Never stop testing.
    • Double check on Jenkins.
  • You can test coverage on non-whitebox tests too! :)

## Debugging

  • Eclipse can debug code!
  • Debugging lets you see code as it is running.
    • What line its executing.
    • The stacktrack.
    • The current data.
  • Breakpoints: Things you can insert from the gutter to stop/pause code execution when it reaches that line.
    • Allows you to walk through your code step by step.
  • Steps: How your program executes.
    • Step Over: Executes the next method as if it was a black box.
    • Step In: Executes a method by going into it.
    • Step Return: Goes to the return statement and finishes it.

## Analysis Types

  • Static Analysis: Evaluating the code without executing it.
  • Dynamic Analysis: Evaluating the code by executing it.
  • Looks for obvious problems or misuses of APIs, ignoring invariants, etc.
  • Issues:
    • False Positive: Reports bugs that program doesn't contain.
    • False Negative: Contains bugs that analyzer does not report.
  • Our Tools:
    • FindBugs: Finds subtle bugs.
    • CheckStyle: Make sure that code is properly constructed in correct style.
    • PMD: Finds more style issues and content issues.

## UML (Unified Modelling Language)

  • UML: Models OO software.
    • Converged from earlier standards (OMT, OOSE, Booch)
  • Use Case Diagrams: Models the interactions between use cases.
    • Ovals: Use case
    • Stick Figure: User (can be library, person, etc)
  • Class Diagram: Shows the interaction between different classes and objects. Static.
  • Sequence Diagram: Shows the flow of the program through different methods and classes through a specific scenario. Dynamic.
  • State Chart Diagram: Shows how models change state when performing a task.

### Class Diagrams

#### Class Attributes

  • Attributes: An instance variable (including static).
  • Form: visibility name : type
  • Visibilities:
    • + -- Public
    • # -- Protected
    • - -- Private
    • ~ -- Package (default)
    • / -- Derived
  • Static Attributes: Underlined

#### Class Operations/Methods

  • Operations: Actions that the class can perform.
  • Form: visibility name(parameters : types) : return_type
    • If return_type is void, omit it.
  • Visibilities:
    • + -- Public
    • # -- Protected
    • - -- Private
    • ~ -- Package (default)
  • Static Methods: Underlined.

#### Connectors

  • Connector: Any arrow that connects two classes
  • Generalization (is-a): Shows inheritance.
    • Interface Connector: Dashed arrow with triangular head points from concrete class to interface.
    • Abstract Class Connector: Solid arrow with triangular head points from concrete class to interface.
  • Composition (has-a): There are quite a few different ones!
    • Attributes: Small things (Strings, primitives), part of existing library, immutable value objects.
    • Dependency: A Class needs another Class to work, but doesn't have any fields that are one.
    • Shouldn't be included in CSC-216!
    • Connector: A dashed line.
    • Association: A Class knows about an instance of another Class, but they are somewhat independent.
    • Connector: A solid arrow with > head from the container (source) to the contained (target) with numbers (multiplicity) to show how many containers have how many contained.
    • Aggregation: The container class essentially just controls a group of those Classes. Unidirectional.
    • Connector: A line with a white diamond next to the aggregate class.
    • Composition: The container class controls every part of the contained. Unidirectional.
    • Connector: A line with a black diamond next to the container class.
  • Abstracts: Shows Classes that can't be directly instantiated. Italicized.
    • Implements: When a class implements an interfaces. Shown with dashed line with a white triangle head.
  • Interfaces: Shows interfaces. Depend on the particular instance.

Event Class

Wolf Scheduler Diagram

### Sequence Diagram

  • Message: Any piece of information or control that is passed between two classes. Solid arrow pointing to where the message went.
  • Return Message: The result of the sent message. Dashed arrow showing the message going back to where it was called from

### Tools for Creating UML Diagrams

  • Microsoft Visio
  • Commercial Eclipse Plugins
  • Violet UML (open source)
  • Dia (freeware)

# Algorithmic Efficiency

  • Big Idea: Generally, there is a trade off between runtime efficiency and size efficiency.

## Big O

  • Big O Notation: A way of showing the trend of worst, case running time of an algorithm.
  • You can specify specific cases and those will have different times, but then those are considered different algorithms.
  • Specific, common growth rates are shown at the bottom in a table.
NameBig O Notation
ConstantO(1)
LogarithmicO(log(N))
LinearO(N)
Log-LinearO(Nlog(N))
QuadraticO(N2)
ExponentialO(2N)

# Data Structures

## Stack

  • Stack: A collection of data that can only be accessed in a Last-In First-Out (LIFO) manner. That is, you can only access the newest element.

### Methods of Interaction

  • push: Adds an element at the top of the stack.
  • pop: Removes and returns the element at the top of the stack.
  • peek: Returns the element at the top of the stack.

### Usage

  • Can't do for-each style coding because you can't access the inner elements.
  • Instead do while not empty pop style.

### Uses

  • When using postfix (12+) or prefix (+12) notation, these can be stack evaluated.
    • For prefix notation, you push tokens onto the stack and, once you reach a function that takes N arguments, you push N more times and then pop $N
    • 1$ times (to remove the arguments and the operator), evaluate the function, and then push the result onto the stack.
    • For postfix notation, you push tokens onto the stack unless it is a function that takes N arguments. Then you pop N times, evaluate the arguments, and push the result onto the stack.

## Queue

  • Queue: A colleciton of data that can only be accessed in a First-In First-Out (FIFO) manner. That is, you can only access the oldest element.

### Methods of Interaction

  • enqueue: Adds an element at the back of the queue.
  • dequeue: Removes and returns the element at the front of the queue.
  • peek: Returns the element at the front of the queue.

## Trees

A tree is a directed, acyclic structure of linked nodes. These can be binary, heaped, and more.

Trees are inherently recursive and thus it is strongly recommended that you program recursively with it, especially traversal which is where you visit every node in the tree.

For traversals, you should probably draw a diagram to see what order and how you are traversing the tree.

Some uses of trees are representing the file structure using a filesystem tree, representing/implementing AI machines using decision trees, and compiling code using an abstract syntax tree / parse tree.

### Vocabulary

  • Directed means links are one-way.
  • Acyclic means no path crosses a node twice.
  • Balanced: The property of a tree being at or near its minimum height.
  • Tree Properties:
    • Height: The number of nodes between the current node and the lowest leaf node.
    • Really +1 the height of its child.
    • Depth: The number of nodes between the current node and the root node.
  • Types of Traversals:
    • Pre-order is where you process the branch, the left, then the right.
    • Start from the top and go down.
    • Post-order is where you process the left, the right, then branch.
    • Go to the bottom and then go up.
    • In-order is where you process the left, the branch, then the right.
    • If you draw the tree such that the distance between sibling nodes halves each level you go down, this is really easy.
  • Types of Nodes:
    • Branch nodes have a parent and a child.
    • Leafs have no children.
    • The root has no parent, and is the ancestor of all nodes. This can also be a branch or leaf.
  • Node Relations:
    • A parent is a node that points to the current node.
    • A child is a node that the current node points to.
    • A sibling is a node with a common parent of the child.

## Binary Search Tree

A binary tree is a tree where each branch only has two children.

A binary search tree is a binary tree that cannot contain duplicates where each branch is strictly greater than the max value in its left child's tree (and thus is greater than its left child) and strictly less than the min value in its right child's tree (and thus less than its right child) and each of its children are binary search trees.

A binary search tree has to take at most the height of the root node to find an element at a given element. This makes it important to try your best to keep the tree as close to its minimum height as possible (this means balanced). For balanced binary search trees, the efficiency is near O(log2(n)). For unbalanced binary search trees, the efficiency is near O(n).

### Adding Elements

  1. Start at the root as your branch.
  2. If the element is the same as the branch,
  3. Else if the branch is empty, insert the element there.
  4. Else if the element is less than the branch, add the element to the left side.
  5. Else if the element is greater than the branch, add the element to the right side.

In Java, it is recommended to do adds by reassigning your node with a function.

public void add(E element) {
+  this.root = add(overallRoot, value);
+}
+private Node add(Node branch, E element) {
+  if (branch == null) {
+    branch = new Node(element);
+  } else if (E < branch.data) {
+    // You'd really do compareTo here but it's
+    // hard to read
+    branch.left = add(branch.left, element);
+  } else {
+    branch.right = add(branch.right, element);
+  }
+}
+

### Getting Elements

  • Getting Minimum:
    1. If you don't have a left, return yourself.
    2. If you do, go left.
  • Getting Maximum:
    1. If you don't have a right, return yourself.
    2. If you do, go right.

### Removing Elements

  1. Find your appropriate node.
  2. If you have two children, set yourself to the min of the right tree (or max of the left tree).
  3. If you have one child, replace yourself with your child.
  4. If you have no children, kill yourself.

## Heaped Trees / Heaps

A heaped tree or heap is a tree which satisfies the heaping property, that is each node is either greater than or less than its children. If it has the prior, it is called a max heap because the root is the max element. If it has the latter, it is called a min heap because the root is the min element.

# Data Structure Modification

## Searching

How do you find things in data structures? One way is by arranging things in some natural order.

There are two categories, sorted and unsorted.

  • Sorted: Slower insertion/up-front. Faster retrieval/end.
  • Unsorted: Faster insertion/up-front. Slow retrieval/end.

There are many methods, each have trade-offs:

  • Sequential Search:
    • Definition: Start at element 0. If you are on the element you want, you found it. Otherwise, go to next element. At any time, if you are at the end, the list does not contain the element.
    • Efficiency: O(n)
    • Pros: Works for unsorted lists.
    • Cons: It's fairly slow.
  • Binary Search:
    • Definition: Locate target by selecting middle element, this is your pivot point. If your element should go before the pivot point, look only at that half. Likewise for your element after the pivot point. Select middle element of that half as your new pivot point. Recurse.
    • Efficiency: O(log2(n))
    • Pros: Is fast.
    • Cons: The list must be sorted.
// This is like java.util.Arrays#binarySearch
+private static int
+binarySearch(int[] list, int value, int min,
+             int max) {
+  if (min > max) {
+    // Missed element
+    return -1;
+    // java.util.Arrays#binarySearch(array,
+    // value) returns -(min + 1), or insertion
+    // point
+  } else {
+    // List not empty
+    int pivot = (min + max) / 2;
+    if (value < list[pivot]) {
+      //
+      binarySearch(list, value, min, pivot - 1);
+    } else if (value > list[pivot]) {
+      binarySearch(list, value, pivot + 1, max);
+    } else {
+      return pivot;
+    }
+  }
+}
+

## Sorting

Sorting is ordering items into their natural ordering. There are many different ways to do this, each with trade offs:

  • Bogo Sort:
    • Method: Shuffle and check if its sorted. Repeat until sorted.
    • Efficiency: O(n!).
  • Selection Sort:
    • Method: There are two parts of the list: the sorted and the unsorted; everything starts unsorted. Find the smallest value in the unsorted part and place it at the end of the sorted part.
    • Efficiency: O(n2).
  • Bubble Sort:
    • Method: Start on the first element. Compare the current element to the next, swapping them if they are not in the right order. Do this until you reach the end of the list. Do this until the list is completely sorted.
    • Efficiency: O(n2) but slower than selection sort due to doing more swaps.
  • Insertion Sort:
    • Method: There are two parts of the list: the sorted and the unsorted; everything starts unsorted. Take the first element in the list and insert it into the sorted part in sorted order. Do this until there is no unsorted part.
    • Efficiency: $O(n^2) but normally faster than selection sort because you do fewer comparisons.
  • Merge Sort:
    • Method: We already know how to merge two sorted lists (by having multiple read heads and taking the smallest value at any of the read heads). If our list is length 1, it is trivially sorted. If our list is unsorted, we split the list into a left and right half and merge sort those. Then we merge those two now sorted halves (each lists their own!). The list is now sorted.
    • Efficiency: O(nlog2(n))
  • Quick Sort:
    • Method: Pick a pivot element and split the list into two parts, either larger or smaller than the pivot. Sort those sub lists. The pivot goes right between these two sublists. The list is now sorted.
    • Efficiency: O(nlog2(n)) (can be worse with bad pivots).
    • It really matters what pivot you pick. There are different ways to do it:
    • Pick first. (good and easy if unsorted)
    • Pick randomly. (good on average)
    • Pick median of first, middle, and last. (great for sorted and reverse sorted elements)

# Finite State Machines

  • Finite State Machine: A system that can have only a fixed set of inputs, states, and transitions.
    • The state is held in memory.
  • Why use FSMs?: They can describe almost all systems easily. They are very easy to implement. They're also just interesting!
  • Guard: Something which must be true for a transition to occur.

## Diagrams

  • FSM Diagram:
    • State: A circle.
    • Final State: A double-layered circle.
    • Inputs: A letter or other identifier.
    • Transition: Arrows labeled with the input given.
  • Transition Tables: A tabular method of showing the possible states.
    • Inputs: Heading.
    • State: First Column.
    • Transition: Intersection between state's row and heading column.

## Examples

  • A vending machine modeled by a finite state machine:

Vending Machine Diagram

  • Compilation of code:

Pascal Real Constant Compiler

  • Substring Finding:

Simple Text Processing for 'abba'

  • Text Processing:

wc as a FSM

StateA-Za-z\nOther
01: ++wc, ++cc0: ++lc, ++cc0: ++cc
11: ++cc0: ++lc, ++cc0: ++cc

## While-Switch Idiom

  • While you have input, switch on your state, and then modify your state and other variables based off your given state and the input.
    • Switching on state doesn't really matter, but Dr. Heckman cares.
while you have input:
+  switch(STATE):
+    case STATE_0: ...
+    case STATE_1: ...
+    case STATE_2: ...
+    case STATE_3: ...
+
// Replicates wc functionality
+while ((next = br.read()) !=1) {
+  ch = (char) next;
+  switch (state) {
+    case 0:
+      if (ch == '\n') {
+        ++lc;
+        ++cc;
+      } else if (Character.isLetter(ch)) {
+        state = 1;
+        ++wc;
+        ++cc;
+      } else {
+        ++cc;
+      }
+      break;
+
+    case 1:
+      if (ch == '\n') {
+        state = 0;
+        ++lc;
+        ++cc;
+      } else if (Character.isLetter(ch)) {
+        ++cc;
+      } else {
+        state = 0;
+        ++cc;
+      }
+      break;
+
+    default:
+      System.out.println(
+        "Invalid state: " + state
+      );
+  }
+}
+

## Object Oriented Implementation

This only works for object-oriented paradigms.

Use the state pattern. This is useful if all your states have to handle all/most types of input.

This works with bounded recursive loops. (This is when a state has some data, which is formally illegal but simplifies implementation.)

## Functional Implementation

This only works with functional paradigms.

Instead of having objects that implement a common interface, you can have a set of functions that represent state. Each function knows how to handle an arbitrary input, parses it, and returns the appropriate state (function).

You set the current function to the call of the current function with the input.

StateFunction curr = defaultStateFunction
+while input:
+  // curr returns a StateFunction
+  curr = curr(input)
+

This does not work with bounded recursive loops.

# Recursion

  • Recursion: Defining something using itself.
  • Why use it?
    • It works better for some things. For example, some things are inherently
    • recursive.
    • Trees are inherently recursive (so are files).
    • Some searches are inherently recursive.
    • Some functional languages use only recursion. (e.g. Haskell, Scheme, etc.)
    • It can be mathematically proved to work much more easily through induction.
    • It's really elegant.
  • How do you write recursively?
    • You just treat the problem as if you've already solved a smaller but completely identical problem.
    • Try to break the problem into a smaller but identical problem.

## Verification Methods

  • Static Analysis (Static): Check for various style and general techniques.
  • Testing (Dynamic): Actually run your code and make sure it works.
  • Formal Analysis (Static): Mathematically prove this program calculates correctly (normally using discrete mathematics).
    • It is harder to prove that it does what the client whats for the given inputs.
    • You normally use mathematical induction.
    • Mathematically Induction? You use your basis step (base case) followed by inductive step (recursive).
    • You have to correctly identify the recursive/inductive step.

## Important Notes

  • Calling a function takes over the flow of control, unless you are using forking / multiprocessing / multithreading.
  • Sometimes recursive solutions are very inefficient if they need to calculate values repetitively or need to make several function calls for something trivial.

## Types of Recursive Functions

  • Linear/Trivial: The function only calls itself once. Can almost always be iterative.
    • Often O(n)
  • Branching: The function calls multiple instances of itself. Often must be recursive.
    • Sometimes O(n2)

## Creating a Recursive Solution

  • Base Case(s): A trivial example of the problem with a known solution.
    • Try to choose the cleanest, best, simplest base case.
  • Recursive Case: A more complex example that can be solved by solving a simpler version and then doing something with it.
  • Your function must have a size parameter, so that it can end. It should be decreasing (but not necessarily monotonically).
  • Check the size parameter, it it is small, solve the base case. If not, solve the recursive case.

## Public-Private Pairs in Recursive Methods/Functions

Sometimes you need more information to accumulate in a recursive method that always has the same default value. To do this, you create a public method that has only a restricted number of parameters. This public method then calls on the private method with the "default value".

This is essentially a workaround for not having true default values and also making sure your clients don't have to worry about that.

public void crawl(File f) {
+  crawl(File, "");
+}
+
+public void crawl(File f, String indent) {
+  System.out.println(f);
+  if (f.isDirectory()) {
+    for (File subfile : f.listFiles()) {
+      crawl(subfile, indent + "  ");
+    }
+  }
+}
+

## Using Control Flow as a Data Structure

Using recursion, you can use the method call stack as a data structure. How? You store a local variable in the method cal, call the method recursively, and then do something with the local variable after the recursive method completes.

// This only works with synchronous method calls
+void reverseLines(Scanner input) {
+  if (input.hasNextLine()) {
+    // "Push" something onto the "stack"
+    String line = input.nextLine();
+    // Add a new method to the call stack
+    reverseLines(input);
+    // "Pop" something from the "stack"
+    System.out.println(line);
+  }
+}
+
  • Cohesion: How much one class represents a single abstraction. (Allows for reuse!)
  • Coupling: The amount with which one program calls upon another.
    • Internal Coupling: One class modifying another's data.
    • Parameter Coupling: Using services provided by another class.
  • Encapsulation: A piece of software having a small, controlled, logical number of ways to interact with it.
  • Software Artifacts: Any documentation. Design documents, class diagrams, other UML diagrams.
  • Serialization: The process of saving a Java object's state to a file.
  • Deserialization: The process of reading a Java object's state from a file.

# Misc

## Horner's Rule

  • Horner's Rule: A method for parsing numbers as polynomials.
    • 1092=(((1)B+0)B+9)+2 where B is the given base
  • Why is Horner's rule useful? Because it can be used to convert ASCII into numbers, since ASCII digits are all consecutive in terms of value.
  • Summary: Read value, shift by base, repeat.
\ No newline at end of file diff --git a/notes/ncsu/1s/csc216/pascal_compiler_fsm.png b/notes/ncsu/1s/csc216/pascal_compiler_fsm.png new file mode 100644 index 0000000..ceba203 Binary files /dev/null and b/notes/ncsu/1s/csc216/pascal_compiler_fsm.png differ diff --git a/notes/ncsu/1s/csc216/vending_machine_fsm.png b/notes/ncsu/1s/csc216/vending_machine_fsm.png new file mode 100644 index 0000000..5f8fa2c Binary files /dev/null and b/notes/ncsu/1s/csc216/vending_machine_fsm.png differ diff --git a/notes/ncsu/1s/csc216/waterfall.png b/notes/ncsu/1s/csc216/waterfall.png new file mode 100644 index 0000000..4130ecf Binary files /dev/null and b/notes/ncsu/1s/csc216/waterfall.png differ diff --git a/notes/ncsu/1s/csc216/wc_fsm.png b/notes/ncsu/1s/csc216/wc_fsm.png new file mode 100644 index 0000000..b4d3f38 Binary files /dev/null and b/notes/ncsu/1s/csc216/wc_fsm.png differ diff --git a/notes/ncsu/1s/e102/ghg_emissions.png b/notes/ncsu/1s/e102/ghg_emissions.png new file mode 100644 index 0000000..eef4a3b Binary files /dev/null and b/notes/ncsu/1s/e102/ghg_emissions.png differ diff --git a/notes/ncsu/1s/e102/index.html b/notes/ncsu/1s/e102/index.html new file mode 100644 index 0000000..ae53d5d --- /dev/null +++ b/notes/ncsu/1s/e102/index.html @@ -0,0 +1 @@ +Eli | E 102: Engineering in the 21st Century

E 102: Engineering in the 21st Century

Instructor: Ms. Hailey Queen | Semester: Spring 2019

Table of Contents

# Administrivia

  • Goal of E-101: Show engineering as a profession, the design cycle, basic problem solving.
  • Goals of E-102: Specific the grand challenges engineers face, how engineers tackle those, and how those challenges impact history, politics, society, etc.
    • This is a GEP (interdisciplinary perspectives).
  • We only meet once a week on Thursday!
  • 1 Free absence allowed. After -5% per class (for unexcused)

## Professor

  • Name: Hailey Queen
  • Email: haqueen@ncsu.edu
  • Office hours on syllabus

## TA

  • Name: Lexi Kloeppel
  • Major: Chemical Engineering Major, Biomanufacturing Minor - Senior
  • Email: lrkloeppel@ncsu.edu
  • Takes care of absences

## Grades

WeightComponentDetails
5%ParticipationKahoot
15%HomeworkMoodle Assignments (14)
20%Midterm ExamIn class, closed notes
15%PaperBased on Grand Challenges
15%Team PosterBased on Grand Challenges
30%Final ExamComprehensive

# Grand Challenges

  • 14 Engineering Grand Challenges
  • Founded by National Academy of Engineers (NAE)
  • Created in 2008
  • National Academy of Engineers: A large body of engineers that helps set ethics standards, promote engineering concerns, and set goals (the Grand Challenges)
    • Established 1964
    • Members elected by current members based on research (~2000)
      • NC State has 14 :)
    • Part of National Academy of Sciences founded by Abraham Lincoln

## Categories

  • Health
    • Advance health informatics
    • Engineer better medicines
    • Reverse-engineer the brain
  • Security
    • Prevent nuclear terror
    • Secure cyberspace
  • Sustainability
    • Make solar energy affordable
    • Provide energy from fusion
    • Developer carbon sequestration methods
    • Manage the nitrogen cycle
    • Provide access to clean water
  • Joy of Living
    • Enhance virtual reality
    • Advance personalized learning
    • Engineer the tools for scientific discovery

## Enhancing Virtual Reality

Virtual reality is all about simulating reality so we can have more control in education, training, entertainment, and even more scenarios.

Currently, the main components are goggles/headsets, headphones/earbuds, and movement sensors. In the future, omnidirectional treadmills, touch simulators, and possibly other tools will become part of the standard VR toolset.

This has connections to [personalizing learning](#Advance Personalized Learning)

  • Important People:
    • Jaron Lanier

## Advance Personalized Learning

  • Big Ideas:
    • People are different
    • Motivation
    • Let students move at their own rate.
    • We collect more data to figure out how students learn, what they are learning, and how to better help them. (machine learning and data science???)
    • Get quick feedback from immediate assessment to send help people.
    • Figure out what students are interested in and use that to help keep them interesting.
  • Why is it important?
    • We need educated people for almost everything.
    • Our education system kinda sucks.
    • We have a shit ton of people drop out.
  • Connections:
    • Personalized Medicine: Using data.
    • Reverse Engineer the Brain: How does it work?
    • Enhancing Virtual Reality: Cool new way to teach!

## Carbon Sequestration

  • Chemical Engineering's most important and personal grand challenges.
  • Scrubber: Removes CO2 from gas.
    • Types: Wet gas scrubber.
  • US Expected Cost from Climate Change: 20$ trillion.
    • 2nd highest in the world.
  • Current Solutions: Shift energy sources, land management, carbon injection, biochar/biomass, rock storage.
  • Current Issues: Which solution should we do? God it's so expensive. No solution is very good so far.
    • Carbon Tax: Companies lobby against it because they don't want to spend it.

Greenhouse Gas Emissions Diagram

## Manage the Nitrogen Cycle

  • Sustainability: Maintaining balance of resource use in environment.
  • Things that Add Nitrogen to Ground: Legumes (nitrogen fixing root nodules), fertilizer, nitrifying bacteria.
  • Things that Remove Nitrogen from Ground: Denitrifying bacteria, soil leeching (water), plant roots.
  • How does nitrogen get added by humans? Primarily creating nitrogen based fertilizer and disrupting ecosystems (killing nitrogen providing legumes).
  • Why is the nitrogen cycle important? Because nitrous oxide is a very strong greenhouse gas and nitrogen can get into water (from runoff) and ruin aquatic ecosystems (fish kills, eutrophication, algal blooms).

Nitrogen Cycle Diagram

## Reverse-Engineering the Brain

  • Impacts:
    • Cure/help neurological diseases.
    • Advance computing.
    • Understanding humans.
    • Advances in prosthetics.

## Health Informations

  • Health Informations: The acquisition, management, and use of data in health and medical setting.
  • Very closely related with engineering better medicines. How can you create better medicine if you don't have info?

## Preventing Nuclear Terror

  • Currently, our "best" method of preventing nuclear terror is Mutually Assured
  • Destruction (MAD), which is a shit method.
  • Three parts to using nuclear weapons.
    • Obtaining nuclear materials - The hardest one.
      • Uranium 235, Plutonium 239 are used because they are fissile (can sustain chain reactions).
      • You get plutonium 239 from a breeder reactor (creates it) and uranium 235 from enrichment.
    • Obtaining a detonation method.
    • Delivering the weapons.
  • Solutions:
    • Systems for tracking nuclear materials and weapons.
    • Nuclear car wash.
    • Computer modeling of nuclear attacks to guide warning systems and clean up.

### Anantomy of Nuclear Weapons/Reactor

  • For a weapon to work, a reaction needs to be supercritical.
  • Subcritical: Not enough neutrons are released to sustain the reaction. Dies out.
  • Critical: Just enoug neutrons to release to sustain the reaction. Self sustains.
  • Supercritical: More neutrons are released than need to sustain the reaciton. Goes boom.
  • Types of Nuclear Assemblies / Detonators:
    • Gun type: A conventional explosive to the side of two nuclear pieces explodes and pushes the two pieces together. Can only be used for uranium
    • Implosion type: A conventional explosive surrounds the nuclear material and explodes, compressing the nuclear material. Can be used for everything.
  • Enriching uranium 235: You use mass separation. This is normally done now by gaseous centrifuging, since uranium 235 is lighter than normal uranium 239.
  • Breeding plutonium 239: Basically there is a series of nuclear processes that convert uranium 238 to plutonium 239.
    • Normal reactors create plutonium 240, which can't be used for nuclear weapons because it blows itself up before it goes supercritical.

## Restore Urban Infrastructure

  • Why security? Urban infrastructure impacts the safety/stability of society as a whole.
    • Think Flint, Michigan and the Hyatt Regency walkway collapse.
  • Issues:
    • US gets a D+ from the American Society of Civil Engineers
  • Why is it hard?
    • It's really expensive
    • It isn't sexy.
    • People don't see the benefit.

# Majors

## Biomedical Engineering

  • Focuses: biomaterials, biomechanical,

## Chemical Engineering

  • AKA: Process engineering.
  • Not always in manufaturing.
  • Often used as a spring board to medical/dental school.
  • 7 concentrations.
  • Research: Biofuels, biomolecular, complex fluids, nanoscience, polymers, engineering, computational, kinetics/electrochemical.

### Jobs

  • Traditional: Chemical processing, petroleum refining, paper production, synthetic materials, textiles, food processing, brewing.
  • Emerging: Pharmaceutical, nanotechnology, bioengineering, green engineering, microelectronics, alternative energy.
  • NC State pay after school: ~69,500$

## Industrial and System Engineering

  • Determine the most effective ways to use people, resources, information, energy, etc.
    • Quality, efficiency, cost
  • Essentially fancy management, planning, and HR
  • Relevant Fields: Management and planning of manufacturing, hospitals, and also Disney by some strange alchemy.

### Impacts

  • The moving assembly line
    • Effective use of labor resources
    • Increased speed
    • Increased quality
  • The widespread adoption of cars (boo!)
    • Model T: 93 Minutes and $290

## Material Science Engineering

  • Largest Users of Solar (by raw amount): China > Japan > Germany > US
  • Solar Energy ~1% of energy produced
  • Focus: Metals, ceramics, polymers, composites, microelectronics
  • "Making Stuff: Stronger, Smaller, Cleaner, and Smarter"

## Nuclear Engineering

  • Possible Fields: Energy, medicine, medical imaging, military, nuclear terror (politics).
  • Related Grand Challenges: Provide energy from fusion, engineer better medicines, reverse-engineer the brain, prevent nuclear terror, engineer the tools for discovery.

### Fusion

  • Method: Fuse tritium (formed from nuclear reaction Lithium) and deuterium.
  • Pros: Creates a lot of energy, extremely clean, very reliable, won't have runaway reactions.
  • Cons: It's really hard, like, really really hard.

### Fission

  • Pros: It creates a lot energy, it produces no carbon emissions, very reliable.
  • Cons: It's much cheaper, it can be unsafe, it can have runaway reactions.

### Medical Field

  • Single-Photon Emission Computerized Tomography (SPECT): A form of imaging that can better show brain-related issues.

## Paper Science and Engineering

  • Paper Science and Engineering: Specialization of chemical engineering.
  • In the College of Engineering and College of Natural Resources
  • Often double major in PSE and CHE
  • Lots of hands-on learning.

### Finances

  • Highest paid NC State Engineering major.
  • 50%-60% of students have a scholarship.

## Civil Engineering

  • Deals with design, construction, and maintenance of infrastructure.
  • 2nd oldest.
  • Subdisciplines:
    • Structural engineering
    • Transportation engineering
    • Geotechnical engineering
    • Construction engineering
    • Water resources and engineering
    • Environmental engineering
  • Size: 1000 undergraduates.
\ No newline at end of file diff --git a/notes/ncsu/1s/e102/nitrogen_cycle.png b/notes/ncsu/1s/e102/nitrogen_cycle.png new file mode 100644 index 0000000..1bb31a3 Binary files /dev/null and b/notes/ncsu/1s/e102/nitrogen_cycle.png differ diff --git a/notes/ncsu/1s/index.html b/notes/ncsu/1s/index.html new file mode 100644 index 0000000..1c7fbef --- /dev/null +++ b/notes/ncsu/1s/index.html @@ -0,0 +1 @@ +Zola

Welcome to Zola!

You're seeing this page because we couldn't find a template to render.

To modify this page, create a section.html file in the templates directory or install a theme.
You can find what variables are available in this template in the documentation.

\ No newline at end of file diff --git a/notes/ncsu/1s/ma225/index.html b/notes/ncsu/1s/ma225/index.html new file mode 100644 index 0000000..8291417 --- /dev/null +++ b/notes/ncsu/1s/ma225/index.html @@ -0,0 +1 @@ +Eli | MA 225: Foundations of Advanced Mathematics

MA 225: Foundations of Advanced Mathematics

Instructor: Dr. Fulp | Semester: Spring 2019

Table of Contents

Sadly I did not scan in my paper notes for this class, so all I have is this small cheatsheet.

# Vocabulary

  • Axiom: A statement simply accepted to be true.
  • Theorem: A statement proved to be true using the axioms.
  • Lemma: A small theorem used in a specific proof to make the proof cleaner/easier.
  • Proposition: A sentence with one of two truth values.
    • "The sky is blue."
    • "4 divides 5."
  • Universe (U): All possible elements within the realm of discussion.
  • Open Sentence: A propsoition dependent on a variable within the universe.
  • Universal Quantifier (): (x)P(x) is true iff the truth set of P(x) is U.
  • Existential Quantifier (): (x)P(x) is true iff the truth set of P(x) is non-empty.
  • Unique Quantifier (!): (!x)P(x) is true iff the truth set of P(x) contains only one value.
  • Set: A collection of unique elements that cannot contain itself. (Sets can be elements!)
  • Argot: The standard human language used to describe logical statements.

# Logical Equivalences

Let P, Q, and R be propositions about elements x in universe U. We write P(x) iff proposition P holds for some specific element xU. If we instead write simply P, we consider some specific element xU where P(x) holds.

  • Double Negation:
    • P¬(¬P)
  • Commutative Law:
    • PQQP
    • PQQP
  • Associative Law:
    • P(QR)(PQ)R
    • P(QR)(PQ)R
  • Distributive Law:
    • P(QR)(PQ)(PR)
    • P(QR)(PQ)(PR)
  • DeMorgan's Law:
    • ¬(PQ)¬P¬Q
    • ¬(PQ)¬P¬Q
  • Implication Properties:
    • PQ¬PQ
    • ¬(PQ)P¬Q
    • ¬(PQ)P¬Q
    • ¬(PQ)Q¬P
    • (PQ)(PQ)(QP)
    • P(PR)(PQ)R
    • P(PR)(PQ)(PR)
    • (PQ)R(PR)(QR)
    • Contraposition:
      • PQ¬Q¬P
  • Quantifiers and Negation: Normally, this would be written out in English instead of being symbolic. However, to avoid ambiguity, we write this symbolically.
    • ¬[(x)P(x)](x)[¬P(x)]
    • ¬[(x)P(x)](x)[¬P(x)]

# Set Equivalences

Let A and B be sets in some universe U.

  • Ac={xU:xA}
  • AB=AB=ABc
  • AB=BcAc
  • DeMorgan's Law:
    • (AUU)c=AU(Ac)
    • (AUU)c=AU(Ac)

# Argot of Logical Statements

Let P and Q be propositions.

  • PQ
    • P implies Q.
    • If P, then Q.
    • Q, if P.
    • P only if Q.
    • Q, when P.
    • Q whenever P.
    • P is sufficient for Q
    • Q is necessary for P.
    • Q is a necessary consequent of P.
  • PQ
    • P implies Q, and conversely.
    • P if and only if Q.
    • P iff Q.
    • P is equivalent to Q.
    • P is necessary and sufficient for Q.
\ No newline at end of file diff --git a/notes/ncsu/1s/ma242/index.html b/notes/ncsu/1s/ma242/index.html new file mode 100644 index 0000000..bd709c8 --- /dev/null +++ b/notes/ncsu/1s/ma242/index.html @@ -0,0 +1 @@ +Eli | MA 242: Calculus 3

MA 242: Calculus 3

Instructor: Ms. Leslie Kurtz | Semester: Spring 2019

Table of Contents

Sadly I did not scan in my paper notes for this class, so all I have is this small cheatsheet.

# Vector Property Equations

  • aT=rr||r||
  • aN=||r×r||||r||
  • K=||r×r||||r||3
  • T^=r||r||
  • B^=r×r||r×r||
  • N^=B^×T^
\ No newline at end of file diff --git a/notes/ncsu/1s/py205/index.html b/notes/ncsu/1s/py205/index.html new file mode 100644 index 0000000..5aacd29 --- /dev/null +++ b/notes/ncsu/1s/py205/index.html @@ -0,0 +1 @@ +Eli | PY 205: Physics I (Mechanics & Energy)

PY 205: Physics I (Mechanics & Energy)

Instructor: Dr. Kory Green | Semester: Spring 2019

Table of Contents

Sadly I did not scan in my paper notes for this class, so all I have is this small cheatsheet.

# Units

## Fundamental Units

DimensionSymbolSI Unit
LengthLmeter (m)
MassMkilogram (kg)
TimeTsecond (s)

## Derived Units

DimensionSI Unit
Areasquare meter (m2)
Volumecubic meter (m3)
Velocitymeters per second (m/s)
Accelerationmeters per second per second (m/s2)
ForceNewtons or (N=kgm/s2)
PressureNewtons per meter (N/m=kg/s2)

## SI Prefixes

Prefix10n
tera- (T)12
giga- (G)9
mega- (M)6
kilo- (k)3
centi- (c)-2
milli- (m)-3
micro- (μ)-6
nano- (n)-9
pico- (p)-12
fempto- (f)-15

# Kinematics

SymbolPropertySI Units
x or yPositionm
vVelocitym/s
aAccelerationm/s2
tTimes

## Equations

  • vf=vi+at
  • xf=xi+vit+12at2
  • v¯=vf+vi2
  • xf=xi+(vx,f+vx,i2)t
  • vf2=vi2+2a(xfxi)

## Constants

  • gearth=9.80m/s2

# Rotation

## Variables

SymbolPropertySI Units
θAngle/Angular Positionrad
ωAngular speedrad/s
αAngular accelerationrad/s2
τTorque (angular force)Nm
IMoment of inertiakgm2
rRadiusm
TPeriods
FFrequency1/s or Hz
vLinear velocitym/s
ac=arCentripetal/center-seeking accelerationm/s2
atTangential accelerationm/s2

## Equations

  • ω=2πT
  • v=2πrT
  • ac=v2r
  • T=2πrv
  • F=1T
  • τ=Iα
  • I=ICM+MD2 (Parallel Axis Theorem)
  • ωf=ωi+at
  • θf=θi+ωit+12αt2
  • ω¯=ωf+ωi2
  • θf=θi+(ωf+ωi2)t
  • ωf2=ωi2+2α(θfθi)

### Common Moments of Inertia

ShapeEquation
PointI=MR2
Rod attached in middleI=112MR2
Rod attached on endI=13MR2
Thin circular hoopI=MR2 and I=12MR2
Thin solid diskI=12MR2 and I=14MR2
Hollow sphereI=23MR2
Solid sphereI=25MR2

## Vocab

  • Lever/Moment Arm: The perpendicular distance between the axis of rotation and the application of force.
    • AKA: The part that matters.

# Newtonian Physics

## Principles

  • Archimede's Principle (for bouyancy): The bouyant force is the weight of the fluid displaced.

## Laws

  1. F=0a=0
  2. F=ma=ddt(mv)
  3. Equal and opposite reaction.

## Types of Forces

  • Contact: Objects must be touching to have an effect
    • Normal/Flex: Perpendicular to plane, prevents clipping.
    • Tension: From rope or rope-like objects.
    • Friction: Opposes motion of body against another.
    • Spring: Seeks equilibrium in springs.
    • Buoyant: Pushes things with/against gravity depending on density.
  • Field: Acts even without touching.
    • Gravitational: Pull all material objects together.
    • Electromagnetic: Pull/push magnetic things.

## Equations for Forces

Force TypeEquationNote
WeightW=mg=mGMbodyr2Assumes uniform gravitational field.
NormalN=FinsideThe force that prevents two bodies from intersecting.
SpringFsp=kxk is the unique spring constant.
BouyantB=ρfluidgVdispFor fully submered bodies, Vdisp=Vobj.

# Energy

## Vocabulary

  • Energy: The ability to do work.
  • Work: A measure of change of state and its associated difficulty in a system.

## Principles

  • Energy in a system is constant unless is receives some work external to the system or does some work external to the system.

## Variables

SymbolPropertySI Units
EEnergyJ
WWork / Change in EnergyJ
PPower / Rate of Change in EnergyJ/s or W
UPotential EnergyJ
UgGravitational Potential EnergyJ
UspSpring Potential EnergyJ
KEKinetic EnergyJ

## Equations

  • E=Fr
  • Ef=Ei+W
  • Wf=!f,dr

### Energy Equations

Energy TypeEquationsNotes
Potential Spring Energy (Us)12kx2
Potential Gravitational Energy (Ug)mghAssumes uniform gravitational field
Translational Kinetic Energy (KE)12mv2
Rotational Kinetic Energy (KE)12Iω2
\ No newline at end of file diff --git a/notes/ncsu/2f/csc230/aligned_struct.png b/notes/ncsu/2f/csc230/aligned_struct.png new file mode 100644 index 0000000..061ba74 Binary files /dev/null and b/notes/ncsu/2f/csc230/aligned_struct.png differ diff --git a/notes/ncsu/2f/csc230/copy_bits.png b/notes/ncsu/2f/csc230/copy_bits.png new file mode 100644 index 0000000..1041b59 Binary files /dev/null and b/notes/ncsu/2f/csc230/copy_bits.png differ diff --git a/notes/ncsu/2f/csc230/index.html b/notes/ncsu/2f/csc230/index.html new file mode 100644 index 0000000..76ab7cc --- /dev/null +++ b/notes/ncsu/2f/csc230/index.html @@ -0,0 +1,760 @@ +Eli | CSC 230: C & Software Tools

CSC 230: C & Software Tools

Instructor: Dr. Susan Balik | Semester: Fall 2019

Table of Contents

# Coding Style

We use Javadoc-style Doxygen comments.

We avoid magic numbers, instead using constants via preprocessor directives (#define VALUE_NAME <VALUE>).

Indent with soft tabs (i.e. spaces). One statement per line. End all lines with \n.

Avoid global variables because they're really unsafe and it's hard to track their modification.

# Compilation

Java uses cross-platform bytecode that the JVM will use on runtime to produce and run machine code. The JVM either uses a bytecode interpreter or Just-In-Time (JIT) compilation. JIT is faster.

C directly generates machine code.

  • Java
    • Cross platform bytecode binaries.
    • Can be easier to debug.
  • C
    • Produces faster code.

## Steps

The parts are split into a frontend and backend. Frontends deal with the language specifics. Backends deal with the architecture specifics. The middle speaks a standard language.

This let's the hardest parts (optimization) be handled in a repeatable way for different languages and architectures.

  • Frontend: preprocessing, lexical analysis, parsing, assembler.
  • Backend: code generation, assembler.

## Preprocessing

Goes in and processes all the preprocessor directives (lines that start with #) in the source code.

There are a bunch of different kinds of preprocessor directives:

  • #define MACRO_NAME(ARGS) MACRO_VALUE: Defines a macro with the given name, which textually expands to the macro value, textually replacing the given arguments.
  • #include <filename>: Copies the given filename in place of this. This first looks into the system directories and then looks in the current directory.
  • #include "filename": Does the same thing as the above, but looks in the current directory first and then looks into the system directories.

### Macros

C preprocessor macros are textual and unhygienic (meaning they can have name collisions). Because of this, you really should only use them for defining constants.

// Defining simple constants.
+#define SIZE 5
+

Macros do allow you to define multi-line functions. These functions are pass-by-name, where they have access to whatever names were present in the code at the time. (Make sure that you aren't using global variables here. Because of variable shadowing, this may not do what you expect.) Also, because of operator precedence, we should surround all variables in parentheses and the entire macro value in parentheses, if we're using multiple operators.

// Bad behavior!
+#define TIMES_TWO(x) x * 2
+// this expands to: 1 + 1 * 2 = 3
+TIMES_TWO(1 + 1);
+// Better behavior
+#define TIMES_TWO(x) ((x) * 2)
+

However, macros do allow for (very limited, very messy) generic programming.

// Generic Programming with Macros
+// Relying on operators working with types
+#define MAX(x, y) ((x) > (y) ? (x) : (y))
+// Taking an explicit type
+#define SWAP(x, y, type) { \
+  type tmp = x; \
+  x = y; \
+  y = tmp; \
+}
+

You can also control macro expansion using

  • #x: Puts quotes around the value x of the given argument. Useful for debugging sometimes.
  • x ## y: Puts quotes around the value x and y. Due to implicit string literal concatenation, these concatenate each other.

### Include Guard

## Lexical Analysis

Converts source code into tokens.

The C scanner / lexical analyzer is a maximal muncher. This means it goes as far as it can with its first guess whenever there is ambiguity.

## Parsing

Converts the string of tokens into an Abstract Syntax Tree (AST).

## Optimization

Analyzes, modifies, and makes the AST more efficient. This can run few to many times, depending on the compilation parameters.

## Code Generation

Converts the AST into a specific architecture's assembly instructions.

## Assembler

A specific architecture's assembler goes in and converts the assembly to machine code.

# Revision Control

Why do we need revision control? To coordinate work, allow faster conflict resolution, allow people to work on the same file at the same time, etc. Here's an example of revision control systems.

  • SCCS (Source Code Control System, 1972): Centralized
  • RCS (Revision Control System, 1982): Centralized
  • CVS (Concurrent Versioning System, 1990): Centralized
  • SVN (Subversion, 2000): Centralized
  • git (2005): Decentralized

Centralized version control has a single, authoritative server/repo. Everyone who checks out from the server just copies the files, with no local repo.

Decentralized version control means everyone has a clone of the server. Officially, there is no authoritative copy (although there is an agreed one).

# Debugging

  • GNU Debugger (gdb): A symbolic debugger for your program.
  • Valgrind: A dynamic analysis checker, ensuring that memory is properly allocated, initialized, and freed.

We use the GNU Debugger (gdb), for debugging. The GNU Debugger is a symbolic debugger, meaning you get to see and interact with the symbols associated with the memory addresses.

Since compilers normally don't store symbol information and other debugging info, you have to add that using the -g flag.

$ gcc -Wall -std=c99 -g filename.c -o filename
+$ gdb ./filename [args...]
+

## GDB Commands

These all have shortcuts and you can find more by running help in gdb.

  • break [procedureName]: Create breakpoint on procedure name.
  • break [lineNumber]: Create breakpoint on line number.
  • delete [breakpointNumber]: Delete breakpoint.
  • condition [breakpointNumber] [condition]: Make breakpoint conditional on condition.
  • set variable n = 25: Change the value of a variable.

### Inspecting Code

  • print [expression]: Print the value of the expression.
  • backtrace: Displace the stack trace.
  • up: Look at the variable values in the above stack trace (i.e. child).
  • down: Look at the variable values in the below stack trace (i.e. parent).
  • list: Look at source code surrounding current statement.
  • list [procedureName]: Look at code for procedure.

### Executing Code

  • run: Go! You can also do redirection.
  • continue: Go until next breakpoint.
  • next: Go to next statement.
  • step: Go to next statement, going into function calls.
  • until [lineNumber]: Run until you hit the line number.
  • finish: Go until the function exists.

## assert.h

Note: It is recommended to disable assertions in production code (by defining NDEBUG). It is recommended to not disable them during debugging and testing though. Normally, you write assert statements in your procedures to validate input.

C allows you to perform easy sanity checks using assert.h (such as bound checks). This provides an assert procedure, that asserts that some given boolean is true, otherwise is crashes the program and prints out information about the issue.

It is recommended that you include assert statements to catch errors during development and document assumptions. They can be trivially disabled during production compilation.

### Examples

A simple procedure with assert.

#include <assert.h>
+
+int f(int a, int b)
+{
+  assert( a != 0 && b > 0 );
+  ...
+}
+

Compiling.

# No debugging
+$ gcc -DNDEBUG -std=c99 -Wall ...
+# With debugging
+$ gcc -g -std=c99 -Wall ...
+

## Valgrind

Valgrind is a dynamic error detection tool. It runs your code in a VM using JIT compilation. It adds several error-checking instructions in your code. It can also use symbol information, so you should generally use -g to compile with symbolic debugging information.

Note: This causes significant overhead. 10-100x.

Valgrind has several tools, but you can only run one at a time.

By default, it uses memcheck, which checks for misuse of heap-allocated memory, out of bounds memory access for heap-allocated memory (not stack or static), and leaked memory (with --leak-check=full). There are options for this, such as --track-fds=yes that tracks file descriptors.

There's an experimental tool called exp-sgcheck that does static and global bounds checking. It uses heuristics and may return false positives and false negatives.

Note: Valgrind produces a lot of output. Most of it useful.

### Examples

# Compile your program with symbol information
+$ gcc -g -std=c99 –Wall program.c -o program
+
+# General usage
+$ valgrind valgrind-options ./program args
+
+# Example usage
+# You could --tool=toolname, but memcheck is
+# the default (and what we'll use)
+$ valgrind --leak-check=full ./program
+

## CPPCheck

CPPCheck (cppcheck) is a static analysis tool. It's not great, but it can catch un-obfuscated issues bound access.

# Types and Variables

## Standard/Fundamental Types

C has a fairly rich standard library of types, but it doesn't mandate much about actual sizes. That means the size is platform dependent. See limits.h for your platform's sizes.

We have integral values. For every type, there is a signed and unsigned version. By default things are signed.

  • long long: At least 64 bits or as large as long.
  • long: At least 64 bits or as large as int.
  • int: At least 32 bits or as large as short.
  • short: At least 16 bits or as large as char.
  • char: At least 8 bits.

We have real values.

  • long double: At least as large as double.
  • double: Double precision float.
  • float: Single precision float.

There's also a few "fake" or odd types.

  • _Bool: A "fake" type that is an integer underneath. Really, 0 is false (both integer and float) and anything else is true.
    • This has a strange name to preserve backwards compatibility.
    • If you include stdbool.h, you get the nice preprocessor constants of bool => _Bool, true => 1, and false => 0.
  • void: Nothing and anything.

## Making Variables

Variables have

  • Name: How the variable is accessed. Must be a legal identifier.
  • Type: How the contents of the variable's memory is organized (and thought about).
  • Scope: Where the variable can be used.
  • Storage Class: How the variable is stored and initialized.

C allows for variable shadowing. This just means you can declare a new variable of the same name in a narrower scope and you can only access the newer variable with the same name. This should generally be avoided.

## Literals

Literals are different from variables because they don't have a name, type, scope, or storage class (well, string literals have static storage).

The C compiler infers/coerces your literal to the type required.

Adjacent string literals are implicitly concatenated. This is most useful for multi-line strings.

### Integers

The compiler infers their type type by treating the number as the smallest type required to store the literal and then using its type promotion semantics.

You can specify the type of integers by appending

  • U for unsigned.
  • L for long.
  • LL for long long.

Integer literals that start with 0 are octal. Integer literals that start with 0x are hexadecimal.

### Floats

Floats are computerized scientific notation. They are split into a sign bit, mantissa, and exponent.

  • Sign Bit: A single bit at the beginning of a list
  • Mantissa: The value part of the number.
  • Exponent: Determines the order of magnitude.

Since, scientific notation mandates that the number before the decimal not be zero and binary is only 1s and 0s, we always know that floats start with a 0.

Unlike integers, floats cannot have overflow. However, they can have underflow. Since floats represent continuous fields as discrete values using "scientific notation", floats far from zero are fairly imprecise. This means that you can get "stuck" at certain high values because you cannot "jump past" the number, since they're so far apart.

### Strings

C is weird and annoying. A string is really just a null-terminated array of characters (i.e. unsigned bytes). Null terminated? Yeah, that just means that a \0 ends the array.

They can be encoded in any way but normally using ASCII or UTF-8 (or UTF-16 if you're Windows and hate yourself). Here we will use ASCII encoded strings.

Since strings are just arrays, you can iterate over them like arrays. However, you can also iterate over them using pointers until you reach a null character! IMO, this is more clear because it is more like a for each loop.

for (char *c = string; *c != '\0'; c++) {
+  // Using pointers. Means you can avoid array
+  // syntax.
+}
+for (int i = 0; string[i]; i++) {
+  // Using arrays, along with the null
+  // terminator (0) being falsey.
+}
+

## Type Promotion

In C, some integers are considered "more specific"/wider while others are "less specific"/narrower. Narrower numbers are automatically casted to the wider numbers. This is called type promotion and it follows the following graph.

Type Promotion Graph

Integers specifically have the concept of rank, which is basically the same thing as narrow vs wide. A int is a higher rank than a short. A int is the same rank as a int.

The following rules apply in the following order.

  1. A lower rank integer of a certain sign-ness is promoted to a higher rank integer of the same sign-ness.
  2. A lower rank unsigned integer is promoted to a higher rank signed integer (since they can fit). This occurs automatically when a same-rank signed and unsigned integer interact; they both get promoted to a higher rank signed.
  3. A same rank signed integer becomes a same rank unsigned integer if you can't promote them both.

These semantics are summed up by the following flow charts.

Integer Rank 1

Integer Rank 2

Integer Rank 3

## Operators

There's bunch of friends we get from Java, so I'll only cover the new ones.

The sizeof <TYPE> operator returns the number of bytes in a type. For integers, this is the special size_t type.

int bro = sizeof( int );
+

Since C has type promotion, you don't always need casting, but it helps the compiler and allows you to shrink types explicitly. You can always explicitly throw away values by casting to void.

// Convert long to short
+short a = (short) 123L;
+// Explicitly throw away return value
+(void) getchr();
+

# Standard Library

A great resource is http://www.cplusplus.com/.

## stdio.h

C uses streams for IO. A stream is just a stream of characters/bytes and is an abstraction of all input. There all three standard streams:

  • stdout (0): Normal, expected output.

  • stderr (2): Exceptional output.

  • stdin (1): Normal input.

  • int getchar(): Reads a single character from stdin as an int.

  • void putchr(int): Outputs a single character into stdout.

  • int printf(const *char, ...): Outputs a string into stdout using the format string followed by the arguments/values for the format specifers in the format string.

  • int scanf(const *char, ...): Outputs format string to stdout, pausing for input whenever it reaches an input specifier. It then tries to parse the input correctly and put it into the corresponding pointer in the arguments after the format string. The pointers are used in the order given. Returns number of successfully parsed values. This fails fast and matches greedily.

### File IO

stdio.h includes opaque FILE structs which are used to interact with file streams. These streams are only interacted with through procedures provided by stdio.h. The earlier standard streams are also provided as preprocessor macros that expand to specific FILE structs.

Most OSes limit the number of files a process can have. This is both practical and acts as a small stopgap for malpractice. In Linux, we can have 1024 open files (meaning Linux gives us 10 bits). In practice we can only have 1021 because of stdout, stderr, and stdin.

  • FILE *fopen(const char *filename, const char *mode): Returns a file pointer to the desired file.
  • int fclose(FILE *filestream): Closes the given file stream. This is important because file streams use buffering (aka caching) and the OS limits the number of files we can have.
  • int feof(FILE *stream): Returns true if EOF has been read by any file IO class. This is set by the reading functions.
    • You should generally not use this because it is error prone. Really, just think about what's happening.
  • int ferror(FILE *stream): Returns true if any operation on the file failed/errored. This is error is set whenever any operation fails. No future successful operations will overwrite this error flag.
  • void clearerr(FILE *stream): Clears the error flag from the file. Must be called manually, otherwise errors will never be cleared.
  • int fprintf(FILE *filestream, const char *format, ...): Like printf, except it prints into the given file stream.
  • int fscanf(FILE *filestream, const char *format, ...): Like scanf, except it scans from the given file stream.
  • int fgetc(FILE *stream): Like getchar but reads from the given file.
  • int getc(FILE *stream): Same as getc, but may be a macro.
  • int ungetc(int c, FILE *stream): Puts character c back onto the stream and clears the EOF flag. This works even for stdin.
    • You can't write EOF back.
    • This works because streams perform buffering. You can just write some values back to the buffer or scroll back the buffer one.
  • int put(FILE *stream): Same as putc, but may be a macro.
  • int fflush(FILE *stream): Flushes the buffer for the given file. All file IO in C is buffered by default. Returns EOF if failure and sets the error on the stream.
    • stdout normally flushes with new lines.
  • size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream): Read nmemb members, each with size size into the memory at ptr from file stream. Returns number of bytes read.
  • size_t fwrite(void *ptr, size_t size, size_t nmemb, FILE *stream): Same as fread except it writes to the file stream rather than reading.
  • int rewind(FILE *stream ): Restart the file pointer from the start.
    • If you're using this, you're probably doing something you shouldn't.
  • int fseek(FILE *stream, long offset, int whence): Seek to anywhere in the file. Offset can be positive or negative, depending on whence.
    • whence tells you with respect to what you're seeking. It can be:
      • SEEK_SET: Relative to start.
      • SEEK_CUR: Relative to current position.
      • SEEK_END: Relative to end of file.
    • This is best for binary data because text has inconsistent offsets cross platform, meaning it might "lie" to you.
  • long ftell(FILE *stream): Return current position in file from beginning.
  • int remove(const char *pathname): Remove file.
  • int rename(const char *old, const char *new): Rename file. Return EOF on failure.
  • FILE *mktemp(): Create temporary file.

#### Buffered File IO

Calls to the OS (required for writing/reading files) are costly, so C caches/buffers our desired input and output. When we fill up the buffer, we preform a single call to the OS. This is one reason why closing files is important. Closing a file flushes the buffer by preforming a call to the OS.

#### Binary File IO

You can open files in text mode or binary mode in C. On the common platform, they happen to be the same but this isn't generally true.

Text mode tries to hide some details of the file, such line termination. Meanwhile, binary mode gives you literally the bytes in the file.

#### Block File IO

Sometimes, reading character by character isn't very useful. We can instead read arbitrary blocks of binary data into any part of our program. This is useful for serialization and deserialization of arbitrary data types.

This can also provide a performance advantage.

#### File Open Modes

  • r: Read
  • rb: Read binary
  • wb: Write binary
  • w: Write
  • r+: Read and write
  • a: Append

## string.h

string.h is a standard library header file that provides useful procedures for using null-terminated strings:

  • int strlen(const char*): Get the number of characters in the string (excluding the null terminator).
    • Note: This should not be used for iteration, because it requires looping over the array multiple times.
  • char *strcpy(char *dest, const char* src): Copies the contents of src to dest, up to the first null character in src.
    • It is generally recommended not to use this.
    • Note: This does not check for dest being too small (because it can't), so you must assure this yourself (or use strncpy).
  • char *strncpy(char *dest, const char* src, int n): Copies the contents of src to dest, up to the first null character in src or the nth character in src, whichever comes first. This prevents overwriting memory.
    • If src is smaller than n, strncpy pads the rest of the characters with zero.
    • This does not put a null character at the end of the string if it runs out of space. To guarantee this, always set the last the last character in the buffer to null.
  • char *strcat(char *dest, const char *src): Appends the characters from src to dest (overwriting and replacing the null character on dest). This may write outside of the buffer and will not always put a null character on the end.
  • char *strncat(char *dest, const char *src, size_t n): Appends the characters from src to dest (overwriting and replacing the null character on dest), where the max length of dest is n. If appending the characters to dest would make it be longer than n, it stops and puts a null character at the end.
    • This always puts a null character at the end.
  • int strcmp(const char *s1, const char *s2): Compares s1 and s2 lexicographically.
    • Returns: < 0 when s1 < s2. 0 when s1 == s2. > 0 when s1 > s2.
  • int strncmp(const char *s1, const char *s2, size_t n): Compares s1 and s2 lexicographically, reading at most n characters from both strings.
    • This is only really useful when you don't have null terminate strings or you only want to compare the first few elements.
  • int sscanf(const char *str, const char *format, ...): Like scanf except reads from str as input. Unlike scanf and fscanf, this does not move the string forward (see str is const).
    • Has special format specifier %n. This writes a char *, holding the position where sscanf left.
  • int sprintf(char *str, const char *format, ...): Like printf except writes to str.
  • int snprintf(char *str, size_t size, const char *format, ...): Like sprintf except it writes at most size bytes including the null character to str. That is, size is the size of the string buffer.

We also have the following number parsing procedures. When these fail, they return 0, so they are not the best way to do this. Generally, you should prefer sscanf.

  • int atoi(const char*): Convert ASCII to integer.
  • float atoi(const char*): Convert ASCII to float.
  • double atoi(const char*): Convert ASCII to double.
  • long atol(const char*): Convert ASCII to long.

### Bounds Inconsistencies

Proceduren Behavior
strncpy()n is a number of characters to write padding with zeros if possible may not null terminate if there's no extra room.
strncmp()n is a maximum number of characters to compare will stop when we reach n, when there's a difference or either string ends (at null termination).
strncat()n is a maximum number of characters to append not counting the null terminator will always write a null terminator.
snprintf()n is a buffer capacity on the destination including the null terminator will always write a null terminator.

### scanf

Since we must manually allocate strings (using character arrays) in C and we are normally fairly lazy (very justifiably), we normally just allocate a large enough character array for usual input. For example,

// 100 will probably be enough, right? (No)
+char someString[100];
+scanf("%s", someString);
+

However, C does not bound check arrays, so scanf can and will write more characters than allowed to the array, if the user inputs more than expected. Using the previous example, if the user enters 100 characters, we'd be in trouble (because C adds null terminators, remember?).

To guard against this, we can provide scanf a length specifier.

char someString[100];
+// now we're safe!
+scanf("%99s", someString);
+

scanf also has some oddities with whitespace. Any whitespace in the specifier means gobble all whitespace possible.

// I won't match "2 + 2" but I will match "2+2"
+scanf("%d+%d", &a, &b);
+// I will match "2 + 2" and "2+2"
+scanf("%d + %d", &a, &b);
+

scanf also accept regex character classes, so that scanf only accepts things in that character class.

// I accept any upper case letters
+scanf("%[A-Z]", &string);
+// I accept anything but upper case letters
+scanf("%[^A-Z]", &string);
+

scanf allows us to capture but disregard things by placing a * after the %.

scanf("%*s %s", &onlyOneString);
+

### Memory Management

  • void* memcpy(void* dest, const void* src, size_t count): Copies count bytes from src to dest. Returns pointer to dest.
    • These must not overlap.
  • void *memmove(void *dest, const void *src, size_t n): Same as memcpy, but uses a small internal buffer to allow for overlapping regions.
  • void *memset(void *s, int c, size_t n): Set n bytes of memory from s to c.

## stdlib.h

stdlib.h is a giant trash can header file. Anything that doesn't fit well anywhere else gets thrown here.

### Random Numbers

C's random number generator is (generally) cryptographically secure, only if it has been securely seeded. By default, C's random number generator is not seeded at all.

  • int rand(): Generate random number from 0 to RAND_MAX.
  • RAND_MAX: Maximum number returned by rand.
  • void srand(unsigned int seed): Seed rand using the given seed. This must be done if you don't want the same numbers every time.
    • Normally, for non-cryptographic contexts, seeding it with the time is sufficient. Do this by doing void srand(time(NULL)).
      • time is in time.h.

### Environment Variables

C can really easily deal with environment variables (envar), but it can only do so locally to the program.

  • char *getenv(const char *varname): Get value of varname envar.
  • void setenv(const char *varname, const char *newValue, int overwrite): Set value of varname envar to the new value. Doesn't overwrite if overwrite is zero.

## stdarg.h

C implements variadic functions by providing a bunch of macros in stdarg.h. In C, your variadic function must take at least one non-variadic argument. You mark variadic arguments using ... as the last argument. The variadic arguments don't need to have a consistent type. C also does not store the type or length of the variadic arguments. Instead, you must essentially treat it like a state machine.

int printf(const char *fmt, ...);
+

To use variadic arguments, we must declare a va_list, and then use va_start(list) on it to initialize it. Then, we use va_arg(list, type), to try to extract a variable of the given type from the list. We then must call va_end(list) to end the list.

int addIntegers(int n, ...) {
+  va_list ap; // for argument pointer
+  va_start(ap, n);
+  int total = 0;
+  for (int i = 0; i < n; i++) {
+    total += va_arg(ap, int);
+  }
+  va_end(ap);
+  return total;
+}
+

### Knowing When to Stop

As mentioned earlier, C doesn't store the type or length of arguments. To handle this, you can accept some specifiers that you can count (e.g. how printf does it). You can use special final values (e.g. NULL). You can accept an argument specifying the number of arguments.

All of these are error prone and rely on you to trust the caller. Be prepared to fail.

## setjmp.h

setjmp.h is a way to implement exceptions using gotos that can jump across function boundaries (unlike C's normal gotos). However, it is more controlled because you can only jump back to a single marked location, and that marked location must handle different possibilities. It is debated on whether this is a good thing. It can be confusing and hard to track, but you choose! Sometimes it's good.

To use this, you first create a jmp_buf that stores your program's entire environment. You then switch on a setjmp, where each of the cases are the possible error codes. (Zero is the initial error code.) Then, the code in the zero case may call longjmp with an int code. This then jumps back to the setjmp where setjmp returns the given int code.

// May long jump
+int readValues(jmp_buf *eenv) {
+  int sum = 0;
+  int m, v;
+  while ((m = scanf("%d", &v)) == 1) {
+    sum += v;
+  }
+  if (m != EOF) {
+    longjmp(*eenv, 1);
+  }
+  return sum;
+}
+
+// Handles long jump
+int main() {
+  jmp_buf eenv;
+  if ( setjmp( eenv ) == 0 ) {
+    readValues(&eenv);
+  } else {
+    printf("Invalid input!\n");
+  }
+}
+

### Cleaning Up

In some cases, we may need to do cleanup of a function that may jump up. To handle this, we do a setjmp in that function and then, in the case of error, clean up and longjmp again. Yes, it's annoying, but welcome to long jump.

## errno.h

C handles errors by setting a "global int" called errno which is used to represent a bunch of different error conditions. It's not actually a global variable under the covers. It's a transparent preprocessor macro which has some special handling we won't get into.

Most errnos you will ever deal with are named, documented, and supported. Each errno has short messages describing then, which can be accessed through perror.

  • void perror(const char *s): Print an error message corresponding to the current error. Prefix it with s.
FILE *fp = fopen(“someFile.txt, “r”);
+if (fp == NULL) {
+  perror(“someFile.txt);
+  exit(1);
+}
+

## math.h

You have to tell the linker to search for a named library, if it isn't part of the standard C library. For math, you have to supply -lm at the end of the flags. This is because it is a linker flag (i.e. LDFLAGS), which must be put at the end of the command.

  • M_E: e.
  • M_PI: π.
  • M_SQRT2: 2.
  • sin(x): Sine in radians.
  • cos(x): Cosine in radians.
  • tan(x): Tangent in radians.
  • asin(x): Arcsine in radians.
  • acos(x): Arc-cosine in radians.
  • atan(x): Arctangent in radians.
  • atan2(y, x): Find angle θ that points from (0,0) to (x,y).
  • exp(x): ex.
  • exp2(x): 2x.
  • exp10(x): 10x.
  • log(x): ln(x).
  • log2(x): log2(x).
  • log10(x): log10(x).
  • pow(x, y): xy.
  • sqrt(x): x.
  • round(x): Nearest integer as double.
  • fabs(x): Absolute value.
  • floor(x): Floor.
  • ceil(x): Ceiling.
  • fmod(x, y): Floating point modulus.

# Memory Segmentation

Memory in C is segmented into the machine code, statically-allocated data, the heap, and the stack:

Memory Segmentation in C

An important note is that scope isn't the same as storage class. Storage class is an implementation/memory concept, while lifetime is a compiler/coding concept. So, for example, you can create static local variables. This isn't recommended though because it is confusing.

## Machine Code

The actual compiled procedures and statements that run your code.

## Static/Global Variables

Variables with static storage are initialized at start up (really at compile-time). If you don't initialize them, they have a zero value. If you do, they must be initialized to a constant expression.

Note: C isn't very smart with constant expressions. If a global variable A is set to a constant expression and global variable B is set to A. A is considered constant and B is not:

char globalC = 'a'; // Yes
+int globalI = 15 + (39 % 3); // Yes
+int globalJ = globalI + 1; // No
+

## Heap

Data from the heap is explicitly requested and is explicitly released.

## Stack

All local variables are initialized on the stack by default. Variables initialized on the stack must have a size known at compile-time. Otherwise, you must allocate it dynamically on the heap and store a reference/pointer to it.

# Pointers

In C, everything is passed by value. To get around always copying the data we care about, we use pointers and dereferencing. Creating diagrams where variable are nodes are your friend!

Pointers are simply memory addresses with a method of getting the value at that memory address. Really, pointers are to the start of a memory block and the type of the pointer determines the size of the block.

When declaring a pointer, the number of asterisks (*) describes how deep you have to go before you reach the given type. I personally think this is easiest to understand by postfixing the type with *, since it is distinct from dereferencing, but that isn't always standard.

int a; // just a int
+char *b; // pointer to a char
+float **c; // pointer to a pointer to a float
+

When using a declared pointer, you can use the dereference operator by prefixing the name by *. This says to follow the pointer to get the value of that memory address. (You technically could do this for any size_t, but that's unsafe and error-prone so C stops you.) This can be applied n times where n is the number of asterisks you used when declaring the pointer (i.e. how deep the pointer is).

When using any variable, you can use the address of operator by prefixing the name by &. This gets the address of the variable in memory. (You can't apply this multiple times because C doesn't implicitly declare a variable when using &, so there is no memory address to get for &&.)

Putting it all together.

int a = 5; // int 'a' with value 5.
+int *pa; // int pointer 'pa'.
+pa = &a; // make pa point to a.
+// Do the same but briefer
+int *pa = &a;
+
int a = 5; // int
+int *pa = &a; // int pointer
+int **ppa = &pa; // int double pointer
+
+*pa = **ppa + 1; // a = 6, *pa = 6, **ppa = 6
+

There also exists a special macro constant called NULL. This is just *0. This just means a pointer to memory address 0, which is either an invalid or protected segment of memory.

Wait a minute! You just said we can have pointers to invalid/protected segments of memory. We can also do pointer arithmetic to directly muck with pointers. Isn't this unsafe?

Yes! Trying to access an invalid segment of memory causes your OS to immediately terminate your program with a "segmentation fault". This is like the NullPointerException from Java except unrecoverable.

Note: Pointers in C do not follow type promotion semantics because they use type to determine how much memory they look at. For example, if you wanted to make a int* point to a char, the pointer would look for 4 bytes while the char only is 1 byte. (You can silence these with casting, but why would you want to?)

## Some Odd Syntax

It is important to realize that [] (arrays) have higher precedence than * when declaring. This means

// I am an array of 10 int pointers
+int *ap[ 10 ];
+// I think this is clearer here
+int* ap[10];
+

const is another type operator (like [] or *). This just says, don't let me change this value during it's lifetime. This has some non-obvious interactions with pointers. Most of the time, you'll just use const pointers to declare to users that you won't change the value.

// pointer to a const int
+int const * x = &a;
+// const pointer to a int
+int * const y = &b;
+// const pointer to a const int
+int const * const z = &c;
+

Hint: In general, you should read const and points backwards.

## Pointer Arithmetic

You can do integer arithmetic directly on pointers. When you add a number n to a pointer p, you're actually shifting the pointer over by n times the sizeof(*p). For example

// These are all play examples
+short *a = 0;
+a + 1; // shifts a over 2 bytes
+int *b = 0;
+b + 1; // shifts b over 4 bytes
+

Using this, you can really easily see that array notation is really syntactic sugar for pointer arithmetic, which means you can use array notation for any pointer! So,

int i;
+int a[10];
+a[i] == *(a + i);
+

Weirdly, this means you can also swap the array and the index because addition is commutative.

int i;
+int a[10];
+i[a] == a[i];
+

Why do we use arrays at all then? Well, static arrays have stronger type checking (can't change their length) and sizeof returns the number of bytes in the static array, rather than the number of bytes in the pointer.

## Pointer Iteration

You can use pointers to iterate over collections. This is generally more performant as you don't have to do integer arithmetic and incrementation every loop. Just incrementation.

However, this is generally pretty overkill because integer arithmetic is very cheap, and the compiler is very good. It also is a little harder to think about, so it's not recommended unless you have a good reason to do so.

int a[] = { 1, 4, 9, 16, 25 };
+int len = sizeof( a ) / sizeof( a[ 0 ] );
+// This points right after the array. This is
+// okay as long as we don't dereference it
+int *end = a + len;
+int sum = 0;
+for ( int *p = a; p < end; p++ ) {
+  sum += *p;
+}
+return sum;
+

## Void Pointers

Sometimes, you're lazy or can't know about what your pointer points to. To handle this, we use void pointers, which are just memory addresses that can point to anything. We receive void pointers from malloc, which we'll get later.

void *ptr; // We now have a void pointer
+

# Dynamic Allocation

For the stack, you must know how much memory you want to allocate at compile time so that the compiler will know where to put things without overwriting them. The stack also has limited size. As you can see, the stack is limited.

If you want more memory or to dynamically allocate your memory. You need to use the heap. However, you have to (mostly) manually manage this memory using malloc (memory allocate) and free (release allocated memory back to OS).

When you use malloc, you as for a certain number of bytes of memory and you will receive a pointer to the first address. If there is no memory, it returns NULL. When you use free, you simply provide the address to the first address you received from malloc. free knows how much memory to release because malloc and free track the memory used.

malloc and free are declared in stdlib.h with the following signature:

// stdlib.h
+// returns memory address
+void *malloc(size_t size);
+// returns `addr` to system allocator
+void free(void *addr);
+

A common usage of dynamic allocation is for large or variable length arrays. This is useful when you don't have enough space, can't know at compile time, or can't be bothered to make it known at compile time. For example,

#include <stdlib.h>
+// Allocate a dynamic array for 1000 integers
+// how they like to do it
+int *list = (int *) malloc(1000 * sizeof(int));
+// how I like to do it
+int *list = malloc(1000 * sizeof(*list));
+

## Dynamic Allocation Hazards

Dynamic allocation has a lot of issues. Taken together, we call these issues memory safety issues.

  • Segmentation Faults: We forget to check that malloc returns null. Your program will just crash.
  • Buffer Overflow: We try to write outside of our memory bounds. This may cause invalidation of important memory or cause you to read invalid memory.
  • Memory Leak: We forget to use free in certain cases. This causes your program to keep using more and more memory until you crash. You also get performance issues.
  • Mistaken frees: You free memory you didn't malloc.
  • Multiple frees: You free memory multiple times. You might invalidate memory management data structures. May allow that memory to be malloc'd twice.
  • Dangling Pointer / Use After free: You try to access memory after you free it. You'll either get garbage, old invalid data, or malicious code. Really hard to debug.
    • Set the given pointer to NULL to avoid! Then you just crash.

## Dynamic Allocation Benefits

Yes, dynamic allocation is more expensive, since you must call the OS. It's also hard to work with.

However, it does have benefits. You can store pointers to valid memory across multiple procedure calls. You can allocate larger things. You can allocate things not known at compile time.

A great usage of this is resizing arrays. This is basically the same as Java. You create some initial array. Then you can add, remove, and access things in it. When you run out of space, you create a new array that's larger, you copy everything from your old array into it, you update your pointer to point into the new memory, and then you free the old memory. It's a good idea to double the length of the array each time, because this gives us an amortized cost of O(1), since malloc is slow.

## Move and Copy

C has some convenience methods that allow you to more easily copy arbitrary memory:

  • void *memcpy(void *dest, void const *src, size_t n): Copy n bytes from src to dest, keeping them both.
  • void *memmove(void *dest, void const *src, size_t n): Copy n bytes from src to dest, freeing src.
    • A little more expensive than memcpy.
  • void *realloc(void *ptr, size_t size): Changes the size of the allocated memory address to the given size. It returns the address of the reallocated block.
    • When growing the array, it increases the size in place, if possible. If it can't, it finds where the memory can be allocated and then copies and moves everything over.
    • When shrinking the array, it decreases the size in place, discarding the data that doesn't fit.
    • You should always use the value it returns. Don't assume it will be the same.

# Managing Larger Projects

In C, to use variables and functions from other files, you must declare the variable and function prototype for the compiler to allow you to use the values. The linker will link the declarations in the object (*.o) files into a single executable.

To declare a variable without allocating it, you must use extern when declaring the variable.

// There exists some global named x. I don't
+// know where, but it's there and I want it.
+extern int x;
+

To declare a function, you just declare the function prototype.

// There exists some global procedure named f. I
+// don't know where, but it's there and I want
+// it.
+int f( x );
+

However, every file that uses these globals and functions declared in some file (say stuff.c) must have these exact same declarations to access parts of stuff.c. Manually declaring these dependencies is brittle and annoying. This lead us to header files and the #include preprocessor directive.

## Header Files

Header files are C files that contain only declarations of procedures and globals. Each source file (*.c) that exports some procedures or globals declares them in its corresponding header file (*.h). Users then #include the header files from the libraries they want to use.

How do these work? Well, #include just pastes the contents of the included file. This gives you the declarations of the header file, allowing you to use the declared items. When you compile the source file (*.c) into an object file (*.o), you have these external declarations that must (or at least should) be defined. Then, when you go to produce the executable, the linker takes your object file along with the object file (*.o) for your library, links the declarations in your object file to the definition/implementations in the library. It then produces an executable.

Note: It is a good practice for a source file to include its own header file. This detects disagreements with declaration and implementation and won't compile if there is one.

The linker then takes the object

If you put static in front of a global variable or procedure definition, you get internal linkage, meaning others can't use it.

# Compile main.c into main.o but don't link it.
+$ gcc -c main.c
+

# Goto

Goto is now considered bad, unsafe, and abstract-breaking. However, this is how machine code does branching, so we'll cover how C does it.

Any statement in C can be labeled with a label on its own line like so

label_name:
+printf("%s", "bro");
+
+// more code...
+
+goto label_name;
+

However, C does have a slightly muzzled goto. You can't goto another label in another procedure/function. You can, however, go to inner and outer code blocks.

# Side Effects

Side effects are just when some procedure modifies or manipulates a piece of data directly. This affects the caller sometimes in unexpected ways.

This a common source of bugs and is very difficult to fix efficiently in C. Commonly, the solution is just RTFM, which isn't great.

Side effects are hard to reason about because they are hard to notice and are strongly affected by performance and sequence points. Sequence points are essentially just where C finishes a statement. These are the following: ;, ,, &&, ||, ?.

# Procedure Evaluation

The C compiler matches the called procedure's name and its actual parameters with the formal parameters of the procedure.

  • Actual Parameters: Types of arguments passed in before types are promoted.

  • Formal Parameters: Types of parameters the procedure expects.

Procedures in C can only return one value, like Java. This is sad, but we get around it by taking in pointers which we fill with values normally.

## Procedure Declaration

We can declare functions, which helps the C compiler be aware of what procedures we have. This is a core part of a header file! (which we haven't gotten to yet). Function declarations look like the following:

// Declaration. Variable names are optional, but
+// good for documentation.
+int expunge( float x, long y );
+
+// Definition.
+int expunge( float x, long y )
+{
+  // do things
+}
+

## Variadic Procedure

You can also have variadic arguments via a few special procedures. A variadic function looks something like the following:

void printFloats( int n, ... );
+

We'll get more into this later.

## Performance Considerations

It is (somewhat) important to note that procedure calls aren't free (duh!). We have to transfer control to another procedure, by saving the parameters, allocating variables on the stack for the procedure, save the return address, jump to the procedure's address, do the things, clear the stack, and jump back to the caller.

In Java, we have procedures (there, methods) check for the validity of their arguments and complain when they are invalid. This is normally a fantastic idea; however, this does add additional overhead on calling procedures. If we want a performance boost, when can declare that the procedure shall have undefined behavior for invalid values and thus place the onus of validation on the caller. This is normally a bad idea, since they aren't that expensive and can remove a whole class of errors.

# Arrays

C arrays are syntactically similar to Java.

## Allocation

However, in C arrays are either allocated statically or dynamically. Statically allocated arrays must have a constant expression for their length (known at compile time) and because they are allocated on the stack. Dynamically allocated arrays can have a length only known at runtime, but must be allocated on the heap. (We store a pointer to the first element in the array.)

// Declare and allocate an array of length 10
+int a[10];
+// Declare and allocate an array of length 10.
+// Initialize array to zero.
+int a[10] = {};
+// Declare and allocate array and partially
+// initialize it.
+int a[10] = {1, 2, 3};
+// Declare and allocate an array large enough to
+// fit the given data.
+int a[] = {1, 2, 3};
+// Declare and allocate an array large enough to
+// fit the given data. Giving indexes. Elements
+// unspecified are zeroed.
+int a[] = {[3] = 1, 2, [6] = 3};
+// {0, 0, 0, 1, 2, 0, 3}
+

In Java, all arrays are dynamically allocated on the heap, but Java manages it behind the scenes.

## Multi-Dimensional Arrays

For multi-dimensional arrays, C uses the same syntax as Java.

// Declare and allocate 2D array with 3 rows and
+// 4 columns.
+int table[3][4];
+// Declare and allocate 2D array with 3 rows and
+// 4 columns. Initialize to zero.
+int table[3][4] = {};
+// Declare and allocate 2D array with 3 rows and
+// 4 columns. Initialize values.
+int table[3][4] = {
+  {0, 1, 4, 9},
+  {16, 25, 36, 49},
+  {64, 81, 100, 121 }
+};
+// Declare and allocate 2D array with 3 rows and
+// 4 columns. Partially initialize values. All
+// other values initialized to zero.
+int table[3][4] = {
+  {0, 1},
+  {16, 25, 36, 49},
+  {64}
+};
+// We also have the special indexing
+// initialization.
+

C can only infer the size of the outermost array. It cannot for any inner array. It does this because then you would have arrays to pointers, which we'd then have to individually initialize. This syntax is supposed to create a local block of memory. Having an array of pointers to another arrays would not be local. This isn't what what we'd expect, so we don't do it.

For some reason, C can only infer the size of the outer array. I haven't quite figured out why it doesn't take the max of the inferred size of the inner arrays. Maybe it's error prone?

C arranges multi-dimensional arrays in row-major order. Essentially, it arranges everything as a string, where the outer dimension is more significant than the inner. (This is only for statically allocated arrays!)

This method of memory allocation makes indexing faster. In Java, we have an array on the heap of pointers to other arrays on the heap.

### Unspecified Lengths

In C, you can have unspecified lengths for outer arrays, but you must have the length for the inner array, if you're initializing this. We'll get into this more in [Arrays are Just Pointers]. However, suffice it to say

### Limitations

Since the stack is only so, we can't create HUGE arrays on the stack (e.g. int[1000000]). To normal workaround is to either use the heap or to use a static lifetime array, so the compiler properly plans ahead.

## Variable Length Arrays

C99 began to allow for variable length arrays on the stack.

TODO: Write more.

## Arrays are Just Pointers

In C, arrays are just pointers with nice syntax for creating and pointer arithmetic. This is easiest to see with procedure parameters (e.g. int test[]). We don't know the size of the array because it's just a pointer!

Since we don't know the size of the array, we can't safely iterate over it. To account for this, we normally take length as a parameter.

Note: This requires us to trust the caller. This is another security issue.

### Inner Dimensions

You may be confused why we declare the inner dimension of an array in procedures. We don't strictly need to (Java doesn't), but this allows us to have faster, smaller, more local memory. The reason it allows this is because it means C doesn't make your array an array of pointers to arrays, but instead an array of statically allocated arrays.

This may be initially confusing, but realize that array syntax is just syntactic sugar for pointer syntax.

// array syntax
+void foo(int array[][3]);
+// pointer syntax, equivalent
+void foo(int (*array)[3]);
+

Now you should be able to more easily see that we need to know what our pointer points to. If we had int array[][], we'd really just have a double pointer (e.g. int **array). That is, we'd have an array that pointed to other arrays.

Sometimes this is what you want, sometimes not.

## Bounds Checking

Unlike almost every other language, C has no bounds checks for array access.

This basically means you can write or read memory on accident. This is called buffer overflows.

Sadly, bugs like this normally fail at some future point and cause security issues. Exploits using array bound checking issues are called stack smashing exploits. There are several static analysis tools (clang, fortify, etc.)

Worst case, these bugs arise as segmentation faults (trying to access memory forbidden by OS). Sometimes you also get a bus error.

# Function Pointers

Realize that procedures/functions are really just the address of the first instruction in the procedure. This means we can pass them around and call them! We just need some (type) semantics to make sure the compiler know what to do with args and to be (somewhat) safe.

Procedures/functions have a type based off of their parameters and their return value.

## Syntax

C has some pretty garbage syntax for function pointers IMO. This comes from it not having a function keyword.

Here's a quick breakdown of the syntax.

// Declare a variable called foo which is a
+// pointer to a function that takes in a pointer
+// to a character and returns an integer.
+int (*foo)(char*);
+
+// Declare a function that takes in a function
+// which takes a character and returns an
+// integer.
+void someFunc(int (*)(char*));
+
+// Declare an array of function pointers. Call
+// this array testList
+bool (*testList[10]) (int);
+

When we assign function pointers, we're technically supposed to use the & address of operator. And then, when we apply them, we should dereference them (*). For example,

int (*funcPtr)() = &func;
+// Apply it
+(*funcPtr)();
+

However, this is pretty garbage syntax for something that is unambiguous, since we can't do arithmetic on function pointers. Therefore, C allows us to not use those operators and instead do this:

int (*funcPtr)() = func;
+// Apply it
+funcPtr();
+

## Why?

Well, first off, it allows for basic, low level first class functions, which is rad. More practically, it allows for the strategy pattern, the chain of command pattern, and callbacks.

The strategy pattern is where we have a common function that takes a specific function that changes its behavior. Imagine we have a function that plays a game and takes in a strategy, which is itself a function. This allows for easier modification and more code reuse.

The chain of command pattern is where we apply a series of functions, taking the first successful output.

# Struct

Structs are what has made C last so long.

A struct is just a collection of heterogeneously typed, named fields stored contiguously. We access the field of a struct a using a.fieldName struct. We access the field of a struct pointer aPtr using aPtr->fieldName.

Structs have unspecified order within the struct. This is so that we can make platform-specific optimizations. For example, most architectures have some sort of "alignment" for their data (e.g. 2-byte alignment, 4-byte alignment). Data that is aligned is faster to access. Data that is not aligned is slower to access.

Poorly Aligned Struct, using given order

Well Aligned Struct, overriding given order

## Semantics

Like everything in C, structs are passed by value and allocated on the stack. However, you can have enormous structs. Therefore, we normally work with pointers to structs!

When working with struct *s you have the choice of using * with . to deference and get fields, or the nicer -> syntax (see [Pointers to Structs]).

When returning structs within procedures, you must be careful. If you return it by value, that might be slow but you'll be safe. If you return a pointer, make sure you won't get a dangling pointer (i.e. make sure that you malloc the struct and later free it in the caller).

## Syntax

### Named Structs

// Declare a struct
+struct StructName {
+  type name;
+  ...
+};
+
+// Declare example struct
+struct Person {
+  char name[ 12 ];
+  double height;
+  int age;
+};
+
+
+// Declare an uninitialized person struct
+struct Person p1;
+// Initialize the struct
+p1.height = 1.75;
+p1.age = 24;
+// Note that we can't do p1.name = "William"
+// because p1.name is an array and not a pointer
+strcpy(p1.name, "William");
+
+// Declare and initialize a struct
+struct Person p2 = { "William", 1.85, 27 };
+
+// More explicit initialization syntax
+struct Person p3 = {
+  .age = 33,
+  .name = "Agatha",
+  .height = 1.7
+};
+

### Anonymous Structs

We can declare anonymous structs by just not giving them a name. These are useful for global structs (like singletons) or one-time use structs. No other struct has the same type.

// Declare anonymous struct with an instance
+// named varName
+typedef struct {
+  type name;
+  ...
+} varName;
+
+// Typedef a struct. Basically assign the
+// anonymous struct type to the given. This is
+// hotly debated. I generally don't typedef
+// structs, but it doesn't matter much to me.
+typedef struct {
+  int foo;
+  char bar;
+} Example;
+

### Pointers to Structs

Since structs are passed by value, like everything in C, and structs can get large, we like to deal with struct *s. This means, to get a field on the struct *, we must first dereference it (duh). This looks like

// readStruct returns a pointer to an malloc'd
+// struct. We won't free that here.
+struct Person *p1 = readStruct();
+printf("%s\n", (*p1).name);
+

However, this gets really ugly with nested pointers, nested structs, and even basic things like this. Therefore, we invented -> syntax, which is just * and . combined. The above would like like

// readStruct returns a pointer to an malloc'd
+// struct. We won't free that here.
+struct Person *p1 = readStruct();
+printf("%s\n", p1->name);
+

# Typedef

Typedef is used by the compiler to create aliases for types (not actually defining new types!).

When to use typedef is debated. Generally, you should only do it when you have a good reason to. Otherwise, it can add more cognitive load to people keeping track of what your types are.

Note: A typedef only applies after the line on which the typedef occurred, for some reason.

## Syntax

// General Syntax. For types such as arrays, the
+// name must be mixed with the type because C
+// has annoying syntax.
+typedef TYPE IDENTIFIER;
+
+// "Complex" basic type. Generally not
+// recommended.
+typedef char Table[NUM_ROWS][NUM_COLS];
+
+// Pointer type. Strongly advised against.
+typedef char *str;
+
+// Anonymous enum.
+typedef enum { NAME1, NAME2 } ExampleEnum;
+
+// Anonymous struct.
+typedef struct {
+  int field1,
+  char field2,
+} ExampleStruct;
+
+// Function. Strongly recommended.
+typedef void *mallocLike(size_t size);
+

## Recommendations

First off, you should generally not use typedef a bunch. It is very weak in C because you can use the original type and the aliases type interchangeably, so it doesn't add much type safety. It also doesn't allow for any behaviors (like associated methods in Go). Additionally, people don't expect to see several typedefs in C code.

You should never typedef a pointer type. This adds an incredibly amount of cognitive load, since whether or not a value is a pointer changes both the semantics and the syntax of the type. For example, people could pass their type to a procedure and expect it to be passed by value (because it says it is), but then the procedure mutates their variable.

There are two strong cases for using typedef. When you have compiler flags which you want to change the types (using #ifdef) and when you have a complex, completely opaque type to the consumer (opaque means the user does not interact with it directly).

Using specific types is normally not necessary unless you have had issues with a specific architecture (don't do premature optimization!). If you do a typedef, then you only have one #ifdef, like

#ifdef SOME_PREPROCESSOR
+typedef Something uint16_t
+#else
+typedef Something uint32_t
+#endif
+

An example of a completely opaque type is FILE, where you only interact with it through accessor/mutator procedures. This simplifies the client code and allows you more flexibility with modifying the type.

// We declare the following anonymous struct to
+// have the name OpaqueStruct This means you can
+// use the type as OpaqueStruct instead of
+// struct OpaqueStruct.
+typedef struct {
+  int field1,
+  char field2,
+} OpaqueStruct;
+

# Data Structures

There are two main ways to keep data organized. You can either keep it all in one place (i.e. arrays and structs), or you can use links/pointers (i.e. linked data structures).

Linked List

Here's a quick comparison of the benefits two

  • Contiguous Memory:
    • Can use (pointer) arithmetic to quickly and randomly access any data.
    • Very simple for fixed-size data.
  • Linked Memory:
    • Easier to grow and add stuff to.
    • Doesn't require large, contiguous section of memory.
    • Are more intuitive for certain data structures (e.g. graphs)

## Linked List Example

// Create a struct with a useful short name and
+// long name
+typedef struct NodeStruct {
+  int value;
+  // We must use struct NodeStruct, because the
+  // typedef only applies after the typedef in
+  // the file
+  struct NodeStruct *next;
+} Node;
+
+Node *head = malloc(sizeof(Node));
+*head = (Node) {
+  .value = 1;
+  .next = NULL;
+}
+
+// Simple traversal, relying on next being NULL
+// at the end of the list and NULL being falsey
+for ( Node *n = head; n; n = n->next ) {
+  printf( "%d ", n->value );
+}
+printf( "\n" );
+

## Simple Object Orientation

In C, object orientation is achieved by having procedures that take the first parameter as a pointer to your type. Then, the procedure mutates it as you wish.

Note: This is actually how object orientation works for most languages. In fact, Some languages, such as Go, Rust, and Python, don't even hide this. Their method syntax is explicitly just syntactic sugar around this core feature. I prefer this way!

For example, suppose you have a type T and a procedure f. If you want f to mutate a variable of type T, have it accept T* as its first parameter. That is f(T*, ...).

Concretely,

// Use Node from earlier
+typedef struct {
+  Node *head;
+} List;
+
+void addValue(List *list, int val)
+{
+  Node *n = (Node *)malloc( sizeof( Node ) );
+  n->value = val;
+  n->next = list->head;
+  list->head = n;
+}
+

## Memory Management of Linked Structures

With linked structures, since we're doing dynamic allocation, you must be very careful that you don't leave anything dangling.

// Freeing a list iteratively
+while (head) {
+  Node *next = head->next;
+  free(head);
+  head = next;
+}
+
+// Freeing a list recursively
+void freeNode(Node *n) {
+  if (n->next) {
+    freeNode(n->next);
+  }
+  free(n);
+}
+

## Adding and Removing in Linked Lists

In Java, we had to do the really annoying special cases for removing at the front. However, because C allows us to use pointers more easily, we can get rid of that special case by "taking a step back" and using a pointer the current node we're on. We can then just mutate the thing we're pointing to.

You already know this and there's a great Computerphile video about it, so I won't talk to much about it.

https://www.youtube.com/watch?v=t5NszbIerYc

# Advanced Object Orientation

OOP in C is difficult, hard to read, hard to maintain, and overall not idiomatic. However, for educational purposes, it is good to see how object orientation can be / is done at a low level. We'll only talk about inheritance, constructors, destructors, methods, and single dispatch.

Inheritance is the hardest of these.

## Inheritance

For inheritance, C's type system actively fights us. To make it work, we can do multiple things. We can either have our subtyped struct have an instance of the superclass struct as the first element (bad) or we could have our subtype struct declare the same fields in the same order (worse).

Here, we'll only cover how to do single inheritance because multiple inheritance is very difficult because you need to do address manipulation.

For the safe-ish method, the way you use the subtype is by casting it to the supertype. Since C will put the first field at the start of the struct, when you cast it you still have a valid address. This also means you can upcast in the future as long as you're using pointers and not passing things by value.

For the unsafe method, the way you use the subtype is by casting it to the supertype and hope that the you remembered to declare the fields in the correct order and the compiler left them in the same order. Otherwise its the same.

## Constructors

Constructors are just procedures which dynamically

# Handling Binary Data

Sadly, C99 has no way of reading in binary, printing out binary, or writing binary literals.

## Little/Big Endianness

Differ architectures use differ byte orders for memory. This is because computer engineers disagree on which is better, because there's not much of a difference.

Little endian machines put the least significant byte first. Big endian machines put the most significant byte first; this is the way people normally write it.

int a = 3;
+// Little Endian: 03 00 00 00
+// Big Endian: 00 00 00 03
+

## Binary/Bitwise Operators

In C, there are many operators that operate on bits. All of the binary operators have equivalent assignment operators as you'd expect.

  • Bitwise OR x | y: 0b10 | 0b01 is 0b11.
    • Logical OR ||.
  • Bitwise AND x & y: 0b10 & 0b01 is 0b00.
    • Logical AND &&.
  • Bitwise NOT ~x: ~0b10 is 0b01.
    • Logical NOT !.
  • Bitwise XOR ^x: 0b110 ^ 0b100 is 0b010.
  • Left Shift x << n: Shifts the bits left by n, putting 0s in for the "walk off". 0b110 << 1 is 0b100.
  • Right Logical Shift x >> n: Shifts the bits right by n, putting 0s in for the "walk off". 0b011 >> 1 is 0b001. Applies only to unsigned integers.
  • Right Arithmetic Shift x >> n: Same as right logical shift, except that the "walk off" (on the left) is replaced with the sign bit. Applies only to signed integers.

0x1A < 5

## Bit Masking

Sometimes, we only care about certain bits. To get at these bits, we apply a mask. A mask is just a number with specific bits flipped based off of what you care about.

By ANDing the mask with the bits of interest, we keep only the bits that were 1 in the original bits, making everything else 0. This is called clearing selected bits.

// Clear bits 0 and 2
+bits = 0b0110
+mask = 0b1010
+bits & mask // 0b0010
+

By ORing the mask with the bits of interest, we keep only the bits that were 0 in the original bits, making everything else 1. This is called setting selected bits.

// Set bits 3 and 1
+bits = 0b0110
+mask = 0b1010
+bits | mask // 0b1110
+

By XORing the mask with the bits of interest, we invert all the bits of interest.

// Invert bits 3 and 1
+bits = 0b0110
+mask = 0b1010
+bits ^ mask // 0b1100
+

We can copy bit ranges by creating a mask of 1s with that range. We then AND the source with the mask, AND the destination with the inverse of the mask, and then OR those together.

Copying Bits

## Bit Fields / Packing

We can pack multiple smaller integers inside of a large integer by using masks and bit shifting for modification and access. This allows for less memory use at the cost of runtime (normally), since memory access that isn't along address boundaries is less efficient on most CPUs.

Integer Packing

You really shouldn't do this by hand if you do it at all. It's very easy to make mistakes and it makes simple operations much more tedious.

If you're going to do this, we can make the compiler handle this by using bit fields in structs. This makes the compiler handle all the shifting nonsense required for field access and modification. It also handles when the number of bit fields is longer than a single integer.

typedef struct {
+  unsigned short red;
+  unsigned short green;
+  unsigned char blue;
+  unsigned char alpha;
+} RegularColor;
+sizeof(RegularColor); // 6
+
+typedef struct {
+  unsigned short red : 9;
+  unsigned short green : 9;
+  unsigned char blue : 6;
+  unsigned char alpha : 6;
+} PackedColor;
+sizeof(PackedColor); // 4
+

In general, these act exactly like normal fields. However, you cannot access the address of the values, since they may not line up along address boundaries.

Note: This is generally a bad idea and unnecessary on most modern systems, since memory is cheap and its not very portable.

## 2's Complement

There's a fantastic video about this. This explains 2's complement in decimal.

We normally use 2's complement, rather than 1's complement. This is because 1's complement has a complicated "end around borrow" concept and a negative 0.

# Object Oriented / Component Design

Changing header files is expensive because that requires recompiling the client code and the library code. If we just change the library file, then we only need to recompile the library code, which is faster.

For that reason, you want your header file to be as minimal as possible, only making a library promise without exposing unnecessary implementation details. There are a few ways to do this.

## Abstract/Hidden Object

We completely hide the object in question. The library maintains a static singleton instance that isn't exposed in the header. The client can only interact with this library code using procedures which interact with this singleton instance behind the scenes. This is like project 3's wordlist!

This is generally okay, but it only allows us to have a single instance, so it's very inflexible.

## Incomplete Type / Abstract Data Type

In the header file, we can declare that certain types/structs exist without providing any fields on them. This means that clients can know that the library provides such objects, but can't see any of their fields. In other words, these objects are opaque to the client.

// Incomplete types in header
+typedef struct Node Node;
+
// Specific implementations in source
+typedef struct Node {
+  // Here we're storing any generic data using a
+  // void pointer and a size
+  size_t size;
+  void *data;
+  struct Node *next;
+}
+

This is a lot like how Java and other traditional object oriented languages work. However, they make it easier to use procedures that mutate the object by using method notation, which attaches the procedure to the namespace of a specific object. They also do a bunch of fancy single dispatch, polymorphism, inheritance, and all that jazz.

Note: This is an excellent trade off because it doesn't make either the library or the client code more complicated, but it does make the library significantly more flexible.

### Generic Abstract Data Types

Many times, we want a certain object to work with an entire family of objects. (You want containers to work with any contained data.) C has the garbage, OG way of doing this. To do this in C, you store a raw pointer and the number of bytes associated with that piece of data. Then, client code must provide the type either through function pointers that manipulate that data or using casting whenever they want to pull something out of the object.

Here's a complete example that is a set implemented using an unordered linked list.

#include "set.h"
+
+// An inner component of our actual data type,
+// Set
+struct Node {
+  void *val;
+  struct Node *next;
+};
+
+typedef bool eq_fn(void const *v1,
+                   void const *v2);
+
+// This is our actual data type this file deals
+// with
+typedef struct SetStruct {
+  // I can store any data, but I must know their
+  // size and how to compare the data
+  size_t vsize;
+  eq_fn same;
+  struct Node *head;
+} Set;
+
+Set *makeSet(size_t vsize, eq_fn same) {
+  Set *s = malloc(sizeof(Set)) ;
+  s->head = NULL;
+  s->vsize = vsize;
+  s->same = same;
+  return s;
+}
+

Note: This makes both the library and the client code more complicated with the benefit that it makes the library more flexible. This is generally seen as a reasonable fair trade off as it doesn't make the client code significantly more complicated, although it does make the library code significantly more complicated.

# Security & Safety

C has no training wheels. This makes it very powerful and efficient. However, it also makes it easy to introduce bugs and security exploits.

## Resource Leak

If you malloc something and return it in one path but not another, make sure that you free it in the other path.

/**
+  Read an entire block of data from fp.
+  @return Pointer to the block on success, or
+  NULL on failure
+*/
+char *getBlock( FILE *fp ) {
+  char *buf = (char *)malloc( BLOCK_SZ );
+  if (!buf) {
+    // Don't need to friend here.
+    return NULL;
+  }
+  if ( fread( buf, 1, BLOCK_SZ, fp )
+       != BLOCK_SZ ) {
+    free(buf); // MAKE SURE TO FREE HERE!!!
+    return NULL;
+  }
+  return buf;
+}
+

Likewise with file pointers.

bool getFile( char *name, int cap,
+              char *buffer ) {
+  FILE *fp = fopen( name, "r" );
+  if ( !fp ) {
+    return false;
+  }
+  int len = fread( buffer, 1, cap, fp );
+  fclose(fp); // MAKE SURE NOT TO FORGET HERE
+  return len > 0;
+}
+

## Input Validation

When you do input validation, it's better to whitelist rather than blacklist. Also, should you try to avoid taking in user input and pasting that into some sort of "eval" function.

The best way to validate inputs is by using an open-source library that validates and escapes things immediately.

C has a int system(const char*) procedure, that allows us to just run the given string as if it were a shell command, and returns its return code. You should never use this because it's slow and insecure. If you use it, make sure to completely and totally validate all input.

# Enums

C enums allow us to avoid using preprocessor macros. This lets us have more sophisticated scope rules.

C also automatically determines the optimal integer type for the enum in terms of size and speed.

// Simple enum
+enum Color { RED, GREEN, BLUE };
+enum Color c = RED;
+
+// Enum with specified values
+enum Mood {
+  HAPPY = 2,
+  AFRAID,
+  BORED = 0,
+  BLUE,
+  GLAD,
+};
+enum Mood m = HAPPY;
+

There are a few limits on enums. You can't have two enums in the same scope with the same value. Also, enums are literally just integers, so you can add them, use them as booleans, increment them, and all that nonsense. They are also printed as integers.

enum Color { red, green, blue };
+ // This won't work because `blue` is reused.
+enum Mood { happy, sad, blue };
+
+enum Mood m = happy;
+m++; // m == sad
+

## Enum Hack

Since enums are constant expressions and respect scope, we can use them as compile time constants if we're using a common name (e.g. SIZE).

// Okay, but doesn't respect scope
+#define SIZE 100
+struct Contact {
+  char name[ SIZE ];
+  char email[ SIZE ];
+};
+
+// Does respect scope, but a little hacky
+struct Contact {
+  enum { SIZE = 100 };
+  char name[ SIZE ];
+  char email[ SIZE ];
+}
+

# Unions

# Odd Keywords

C normally makes optimizations such as storing values to the register and not rereading memory. This is good because it's more performant. However, sometimes (e.g. when doing concurrency), that value might have changed. We use the volatile keyword to tell C to not do optimizations for this value.

# Testing & Profiling

Profiling is the process of figuring out what your program is spending its time and resources doing. You know what testing and coverage is.

## Test Coverage

In this class, we use gcov (GNU Coverage tool) to get test coverage. This requires we enable some features on compilation. -fprofile-arcs tracks branch coverage. -ftest-coverage tracks statement coverage.

## Profiling

In this class, we use gprof (GNU Profiler tool) to profile things.

## DIY Optimizations

Generally, you should not do these DIY code optimizations if they hurt readability. Most compilers are optimizing and will do this for you. A few exceptions are inlining simple functions, passing by const reference, and putting the most common conditions first.

# C++

We'll learning C++11. It has the following features.

  • Namespaces
  • Classes and objects.
  • Destructors.
  • Operate overloading.
  • Move Semantics: How to safely describe memory changes / ownership.
  • constexpr: Evaluate arbitrary expressions at compile time.
  • Range Based For Loops: Iterators.
  • Lambda Expressions.
  • Lambda Captures: Strongly documented closures.
  • nullptr: Essentially renamed NULL.
  • Templates: Allows you to define how to build a function given some arbitrary compile time values. Created for compile time generics.
    • Can be used for many other things.
  • C backwards compatibility.

Here's an overview of the terminology that differs from Java's terminology.

  • Base Class: Super(most) class.
  • Derived Class: Subclass.

## Hello World!

Notice how we use the bitshift operators? That's standard in C++! We overload the stream with nice-looking operators to give use new, easier syntax.

// So we get access to std::cout
+#include <iostream>
+
+int main() {
+  // Put the folowing string to the std::cout
+  // stream. std::cout is buffered stdout.
+  std::cout << "Hello, World!\n";
+
+  // Alternatively, use std::endl, the platform
+  // specific line terminator.
+  std::count << "Hello, World!" << std::endl;
+  // std::flush tells the buffered output to
+  // flush manually.
+  std::count << "Hello, World!" << '\n'
+    << std::flush;
+
+  // Generally, you shouldn't use std::endl or
+  // std::flush because generally the OS knows
+  // better when it should flush the buffer than
+  // you.
+}
+

## Namespaces

Namespace extensions

C++ defaults to searching in the current namespace (including any namespaces you're using). If it can't find the name you're looking for, then that's an error.

C++ has the scope resolution operation: ::. You put this after a namespace to get a name within the namespace.

int val = 3;
+void f() {
+  // Prints 3
+  std::cout << val;
+}
+
+namespace MyNamespace {
+  int val = -10;
+  void f() {
+    std::cout << "val: " << val << "\n";
+    std::cout << "global: " << ::val << "\n";
+  }
+}
+
+// ...
+
+// Call global f
+f();
+// Call f in MyNamespace
+MyNamespace::f();
+

## Using C Libraries

We can use C libraries easily in C++. The only difference is that they are in the std namespace and their header files get a makeover. Remove the .h and prepend the name with a c. We use namespaces because they're nice.

// Import stdio.h from C
+#include <cstdio>
+
+// Like a * import from other languages. Import
+// everything from std namespace into our
+// namespace. Use with care! (Or not at all.)
+using namespace std;
+
+int main() {
+  printf("Hello, within C!\n");
+}
+

## File IO

File IO is done using input streams (istreams) and output streams (ostreams). Specifically, it's done with a specialization of both of these streams, fstreams.

## RAII (Resource Acquisition Is Initialization)

RAII is a standard idiom in programming. It essentially says that all resources should have a constructor and destructor. The constructor is called at resource acquisition time. C++ itself automatically calls the destructor whenever your object goes out of scope. It guarantees that it calls this in all possible paths, even if your program crashes. You can manually call the destructor.

This is sometimes called SBRM (Scope Based Resource Management). It's the same thing.

This pattern means we don't need to worry about a lot of resources. For example, we don't need to close files when we're done with them. (Although it's not a bad idea.)

## References and Move Semantics

References are a safe abstraction around pointers that allows for additional optimizations, because we're guaranteed by the compiler the pointers are known to be identical.

Syntactically, we treat it as if we had the value itself. Essentially, it's just an alias for the other value. This means we can also assign to returned references, which is really cool.

// Takes a reference to a and b
+void swap(int &a, int &b) {
+  // notice how we're not dereferencing. It
+  // calls int's copy constructor
+  int tmp = a;
+  a = b;
+  b = temp;
+}
+
int &a = some[complicated]->object.thing;
+// ...
+cout << a << std::endl;
+a = 12;
+
int &lookup( char *name ) {
+  ...;
+}
+
+// ...
+
+// Assigning from reference
+int x = lookup( "mary" );
+// Assigning to reference
+lookup( "bob" ) = 35;
+
+// Notice how there's no pointer syntax!
+

## Templates

We want to define our functions to work with abstract data. How do we do that? In C++, we use templates!

Templates are compile time feature, where the compiler figures out all the different versions of your template you call and compile them all as separate functions.

## Default Parameters

The syntax is almost exactly what you think it would be!

void repeat(char const *str = "Good Evening",
+            int count = 10) {
+  for (int i = 0; i < count; i++) {
+    std::cout << str;
+  }
+}
+

## String Class

Strings are mutable character buffers wrapped in objects. You can treat them like primitives and they use copy semantics.

They also have array indexing overloaded, so you can treat them like char arrays!

string a = "123";
+string b = "xyz";
+string c;
+// copies a to c
+c = a;
+// makes c a copy of a and b concatenated
+c = a + b;
+
+// Compares the contents of a and b
+if (a == b) {
+  cout << "Hi!";
+}
+

### String IO

You can use streams (as earlier), but there's also a few helpful functions.

  • getline(istream &is, string &str): Reads a line from is into str, dynamically resizing str as necessary.

### String Methods

  • string substr(int pos, int len): Create a substring of len characters, starting at pos by copying the characters.
  • size_t find(string &str): Return starting index of the first occurrence of str. Returns string::npos if no matches are found.
  • insert(int pos, string &str): Insert str at position pos, displacing all characters on the right.
  • erase(int pos, int len): Remove len characters starting at pos, shifting all characters on the right.
  • char *c_str(): Return the underlying char array for the string.

## Standard Template Library (STL)

The standard template library in C++ is the standard library's collection framework. It's pretty big, so we won't cover them all.

### Vector

Vector is the simplest and most used container. It is in the <vector> header. It is like an ArrayList in Java, a resizable array of generic elements.

You can use the following to initialize vectors.

vector<int> iList( 10 );
+vector<short> sList( 20, -1 );
+

Vectors have the traditional mutation methods

Vectors support deep copying, just use simple a assignment.

### Iterators

C++11 has a for each loop.

// Value iteration. Generally lame.
+for (int v : container) {
+  count << v << endl;
+}
+// Reference iteration. Only do if you need
+// mutability.
+for (int &v : container) {
+  count << v << endl;
+}
+// Const reference iteration. Use most of the
+// time.
+for (const int &v : container) {
+  count << v << endl;
+}
+

## Memory Management

Like the malloc and free procedures in C, we have new and delete in C++.

## Classes and Structs

In C++, classes and structs are identical except that for classes, the default access is private, structs, the default access is public. Generally, however, we use structs just to be blobs of data and classes for, well, classes.

C++ has a lot of energy dedicated to making classes good. Here are a bunch of special member functions.

### Constructors

They are responsible to assigning values to the fields to the class. The memory for the object is already allocated by the time it runs.

class Person {
+  string name;
+  int age;
+
+  public:
+  Person(string name, int age) {
+    // Use the implicit this reference
+    // (generally preferred)
+    this->name = name;
+    // Use the scope resolution operator
+    Person::age = age;
+  }
+
+  ...;
+};
+

### Default Constructor

The default constructor is a parameterless constructor that gets call automatically when you allocate the object. This is important to assign the fields to their start / null values.

class SomeClass {
+public:
+  SomeClass() {
+    std::cout << "Hi!" << std::endl;
+  }
+}
+
+// calls default constructor
+SomeClass c;
+// calls default constructor
+SomeClass *cp = new SomeClass;
+// calls default constructor 5 times
+SomeClass c[5];
+

### Copy Constructor

The copy constructor is used whenever you pass an object by value (whether passing it to a function or assigning it to something else).

class List {
+public:
+  // other is what you want to copy. This must
+  // be a reference because otherwise you'd have
+  // to call the copy constructor to call the
+  // copy constructor.
+  List(const List &other) {
+    Node **ptr = &head;
+    for (Node *n = other.head; n; n = n->next) {
+      *ptr = new Node;
+      (*ptr)->val = n->val;
+      ptr = &((*ptr)->next);
+    }
+    // terminate the list
+    *ptr = NULL;
+  }
+};
+
+// Example usage
+List alist;
+alist.push(2);
+// Calls copy constructor
+List blist = alist;
+alist.push(3);
+alist.size() == 2;
+blist.size() == 3;
+

### Destructor

Destructors are called automatically when the object goes out of scope (allocated on the stack) or when delete is called manually. C++ will default to having a destructor that does nothing. This is not okay for objects that dynamically allocate things.

### Operator Overloading

All operator's are overloaded by defining a operatorSYMBOL member function. They only must accept a certain number of arguments, but their types are returns are not mandated.

They can be member functions or not.

### Suppressing Value Semantics (and others)

TODO:

It uses = delete after declaring the method.

### Friendship

If you want to access private elements of a class (or something) in a certain function defined outside of the class, you must declare it a friend, otherwise they cannot access the private elements.

In the following example, since we want ostream to be the left hand side, we must declare the overloaded operator as a non-member function. Since this wants to access a private member of List, this must be a friend.

class List {
+  // Allows this function's definition to access
+  // its private parts.
+  friend ostream &
+  operator<<(ostream &output, const List &lst);
+};
+
+// If you didn't declare this a friend earlier,
+// then this could not access lst.head.
+ostream &operator<<(ostream &output,
+                    const List &lst) {
+  for (List::Node *n = lst.head; n;
+       n = n->next) {
+    output << n->val << " ";
+  }
+  return output;
+}
+

## Headers in C++

In C++, it's a good idea to declare all public classes in a header file, for the same reason we do in C. This does require we use a different syntax for implementing because we have namespaces.

class List {
+  struct Node {
+    int val;
+    Node *next;
+  };
+  Node *head;
+public:
+  // It's not my job to declare this
+  static int x;
+
+  List();
+  List( const List & );
+  ~List();
+  ...;
+}
+
// list.c
+#include <iostream>
+
+#include "list.h"
+
+using namespace std;
+
+static int List::x = 5;
+
+List::List() {
+  head = NULL;
+}
+
+// Implementing copy constructor, destructor,
+// etc.
+

## Throwing

In C++, we can throw anything! We have the exact same try-catch system.

int f(int val) {
+  if (val <= 0) {
+    throw 42;
+  }
+  if ( val % 3 != 0 ) {
+    throw "That value isn't divisible by 3";
+  }
+  return val / 3;
+}
+
+// Calling code
+try {
+  int result = f( val );
+  cout << result << endl;
+} catch ( const char *str ) {
+  cout << "Error: " << str << endl;
+} catch ( int code ) {
+  cout << "Internal Error: " << code << endl;
+}
+

## Inheritance

We'll only cover public inheritance. You can look up private (and protected) inheritance.

As you know, the main reason to do inheritance is for abstraction (not code reuse!).

### Virtual Methods

Virtual functions are the way you tell the compiler you'd like to use single dispatch for that function.

### Const Methods

Const methods are member functions that are not allowed to mutate the object. You can only call const methods on const objects. You can call both const methods and non-const methods on non-const objects.

class EmailContact : public Contact {
+  char *email;
+public:
+  ...;
+  void print() const override {
+    // Print our name and our email.
+    cout << getName() << " " << email << endl;
+  }
+};
+
\ No newline at end of file diff --git a/notes/ncsu/2f/csc230/integer_packing.png b/notes/ncsu/2f/csc230/integer_packing.png new file mode 100644 index 0000000..593f538 Binary files /dev/null and b/notes/ncsu/2f/csc230/integer_packing.png differ diff --git a/notes/ncsu/2f/csc230/integer_rank1.png b/notes/ncsu/2f/csc230/integer_rank1.png new file mode 100644 index 0000000..1c55d6f Binary files /dev/null and b/notes/ncsu/2f/csc230/integer_rank1.png differ diff --git a/notes/ncsu/2f/csc230/integer_rank2.png b/notes/ncsu/2f/csc230/integer_rank2.png new file mode 100644 index 0000000..3a0ccf3 Binary files /dev/null and b/notes/ncsu/2f/csc230/integer_rank2.png differ diff --git a/notes/ncsu/2f/csc230/integer_rank3.png b/notes/ncsu/2f/csc230/integer_rank3.png new file mode 100644 index 0000000..de90d17 Binary files /dev/null and b/notes/ncsu/2f/csc230/integer_rank3.png differ diff --git a/notes/ncsu/2f/csc230/left_shift.png b/notes/ncsu/2f/csc230/left_shift.png new file mode 100644 index 0000000..c32db61 Binary files /dev/null and b/notes/ncsu/2f/csc230/left_shift.png differ diff --git a/notes/ncsu/2f/csc230/linked_list.png b/notes/ncsu/2f/csc230/linked_list.png new file mode 100644 index 0000000..380d7aa Binary files /dev/null and b/notes/ncsu/2f/csc230/linked_list.png differ diff --git a/notes/ncsu/2f/csc230/memory_segmentation.png b/notes/ncsu/2f/csc230/memory_segmentation.png new file mode 100644 index 0000000..68c7ee1 Binary files /dev/null and b/notes/ncsu/2f/csc230/memory_segmentation.png differ diff --git a/notes/ncsu/2f/csc230/misaligned_struct.png b/notes/ncsu/2f/csc230/misaligned_struct.png new file mode 100644 index 0000000..e4365be Binary files /dev/null and b/notes/ncsu/2f/csc230/misaligned_struct.png differ diff --git a/notes/ncsu/2f/csc230/type_promotion.png b/notes/ncsu/2f/csc230/type_promotion.png new file mode 100644 index 0000000..12cef29 Binary files /dev/null and b/notes/ncsu/2f/csc230/type_promotion.png differ diff --git a/notes/ncsu/2f/csc316/2_4_tree.png b/notes/ncsu/2f/csc316/2_4_tree.png new file mode 100644 index 0000000..61cea9e Binary files /dev/null and b/notes/ncsu/2f/csc316/2_4_tree.png differ diff --git a/notes/ncsu/2f/csc316/avl_h_derivation.png b/notes/ncsu/2f/csc316/avl_h_derivation.png new file mode 100644 index 0000000..b5e5741 Binary files /dev/null and b/notes/ncsu/2f/csc316/avl_h_derivation.png differ diff --git a/notes/ncsu/2f/csc316/balanced_bst.png b/notes/ncsu/2f/csc316/balanced_bst.png new file mode 100644 index 0000000..611d5fb Binary files /dev/null and b/notes/ncsu/2f/csc316/balanced_bst.png differ diff --git a/notes/ncsu/2f/csc316/balanced_quicksort.png b/notes/ncsu/2f/csc316/balanced_quicksort.png new file mode 100644 index 0000000..b1312ba Binary files /dev/null and b/notes/ncsu/2f/csc316/balanced_quicksort.png differ diff --git a/notes/ncsu/2f/csc316/bst_rotation.png b/notes/ncsu/2f/csc316/bst_rotation.png new file mode 100644 index 0000000..65e01a4 Binary files /dev/null and b/notes/ncsu/2f/csc316/bst_rotation.png differ diff --git a/notes/ncsu/2f/csc316/circular_array.png b/notes/ncsu/2f/csc316/circular_array.png new file mode 100644 index 0000000..60502d8 Binary files /dev/null and b/notes/ncsu/2f/csc316/circular_array.png differ diff --git a/notes/ncsu/2f/csc316/complete_binary_tree.png b/notes/ncsu/2f/csc316/complete_binary_tree.png new file mode 100644 index 0000000..6637e73 Binary files /dev/null and b/notes/ncsu/2f/csc316/complete_binary_tree.png differ diff --git a/notes/ncsu/2f/csc316/euler_tour.png b/notes/ncsu/2f/csc316/euler_tour.png new file mode 100644 index 0000000..ef5dc11 Binary files /dev/null and b/notes/ncsu/2f/csc316/euler_tour.png differ diff --git a/notes/ncsu/2f/csc316/golden_ratio_n_1.png b/notes/ncsu/2f/csc316/golden_ratio_n_1.png new file mode 100644 index 0000000..8fa9436 Binary files /dev/null and b/notes/ncsu/2f/csc316/golden_ratio_n_1.png differ diff --git a/notes/ncsu/2f/csc316/golden_ratio_n_2.png b/notes/ncsu/2f/csc316/golden_ratio_n_2.png new file mode 100644 index 0000000..958e9c6 Binary files /dev/null and b/notes/ncsu/2f/csc316/golden_ratio_n_2.png differ diff --git a/notes/ncsu/2f/csc316/golden_ratio_n_3.png b/notes/ncsu/2f/csc316/golden_ratio_n_3.png new file mode 100644 index 0000000..19ecd43 Binary files /dev/null and b/notes/ncsu/2f/csc316/golden_ratio_n_3.png differ diff --git a/notes/ncsu/2f/csc316/hash_table_coalesced_chaining.png b/notes/ncsu/2f/csc316/hash_table_coalesced_chaining.png new file mode 100644 index 0000000..8d12064 Binary files /dev/null and b/notes/ncsu/2f/csc316/hash_table_coalesced_chaining.png differ diff --git a/notes/ncsu/2f/csc316/hash_table_coalesced_chaining_cellar.png b/notes/ncsu/2f/csc316/hash_table_coalesced_chaining_cellar.png new file mode 100644 index 0000000..c8d2eab Binary files /dev/null and b/notes/ncsu/2f/csc316/hash_table_coalesced_chaining_cellar.png differ diff --git a/notes/ncsu/2f/csc316/hash_table_separate_chaining.png b/notes/ncsu/2f/csc316/hash_table_separate_chaining.png new file mode 100644 index 0000000..ca71909 Binary files /dev/null and b/notes/ncsu/2f/csc316/hash_table_separate_chaining.png differ diff --git a/notes/ncsu/2f/csc316/heap.png b/notes/ncsu/2f/csc316/heap.png new file mode 100644 index 0000000..223e28d Binary files /dev/null and b/notes/ncsu/2f/csc316/heap.png differ diff --git a/notes/ncsu/2f/csc316/heap_array.png b/notes/ncsu/2f/csc316/heap_array.png new file mode 100644 index 0000000..29c1bbb Binary files /dev/null and b/notes/ncsu/2f/csc316/heap_array.png differ diff --git a/notes/ncsu/2f/csc316/imbalanced_quicksort.png b/notes/ncsu/2f/csc316/imbalanced_quicksort.png new file mode 100644 index 0000000..96ee8b6 Binary files /dev/null and b/notes/ncsu/2f/csc316/imbalanced_quicksort.png differ diff --git a/notes/ncsu/2f/csc316/index.html b/notes/ncsu/2f/csc316/index.html new file mode 100644 index 0000000..f77e940 --- /dev/null +++ b/notes/ncsu/2f/csc316/index.html @@ -0,0 +1,67 @@ +Eli | CSC 316: Data Structures & Algorithms

CSC 316: Data Structures & Algorithms

Instructor: Dr. Jason King | Semester: Fall 2019

Table of Contents

# Terms

  • Problem: Question to answer.
  • Problem Specification: Specific description of problem parameters and solutions.
  • Parameters: The specific, current input to a problem. Parts of a problem that can change without changing the fundamental nature of the problem.
  • Solution: Description of the properties needed for the algorithm to have. Or, The actual solving algorithm.
  • Algorithm: A general, finite solution to a problem. Normally specified in pseudocode. Good algorithms are efficient, adaptable, and easy to implement.
    • Greedy Algorithm: Algorithm that tries to minimize/maximize as early as possible.
    • Brute Force Algorithm: Algorithm that just tries every possibility.
  • Pseudo-Code: A human-focused, informal, language-agnostic piece of pseudo-code.
  • Abstract Data Type: A way to model a data type using the possible operations that can be done on it. Like an interface/protocol!
  • Data Structure: Systematic way of organizing and accessing data. Abstract, but impact how computer memory is organized.
    • Deterministic Data Structures: Data structures where the same actions always produces the same results.
    • Probabilistic Data Structures: Data structures where the same actions do not always produces the same results.
  • Theory of Algorithms: Designing and analyzing computational procedures.
  • Complexity Theory: Classifying problems based on their runtime/difficulty. Sometimes proving you can't have an efficient implementation.

# Runtime Analysis

In this class, we just do theoretical analysis because real life is messy. Actual runtime depends on specific parameters of problem instance, what else was running on hardware, how program was written, language of program, how program was compiled, etc.

In this class, if you have multiple parameters for the asymptotic efficiency, specify them.

## Operational Analysis

Operational analysis analyzes the asymptotic growth rate of a single operation. There are the following asymptotic growth rates:

  • Big-Oh: Upper bound.
    • fO(g)c,n0n>n0f(n)g(n).
  • Big-Omega: Lower bound.
    • fΩ(g)c,n0n>n0f(n)g(n).
  • Big-Theta: Family or tight upper bound.
    • f(O(f)Ω(f)).

We use theoretical analysis of program runtime using arbitrary timestamps, characterizing algorithm runtime by the size of input. Why? So we can abstract our analysis to any software and hardware combo.

We use the RAM model of a computer. In the RAM model, our machine has a CPU, where all simple operations take a consistent constant time, and an arbitrary amount of RAM, where all accesses take a constant time.

Since doing a full blown analysis to get the proper function is painful, we normally do a fuzzy analysis to just get the Big-Oh class. This is done by looking at the "essential operation" (i.e. the operation we care about).

Since not all programs are a sequential list of instructions and instead branch, we take the branch that will cause more essential operations.

### Limit Test

If f(n) and g(n) are monotone increasing and positive, then, where result is limn(f(n)g(n)),

  • result=0fO(g). (i.e. g(n) grows faster.)
  • 0<result<fΘ(g). (i.e. f(n) and g(n) grow at the same rate.)
  • result=fΩ(g). (i.e. f(n) grows faster.)

## Amortized Analysis

Amortized analysis exists because operational analysis can be "too pessimistic". Amortized analysis attempts to analyze the average case of an algorithm in a formal way.

Note: You can only analyze average cost over a *series of operations.

The word "amortized" comes initially from business, where an amortized cost is a cost whose cost "decreases" due to saving money in the long term. Think of education.

  • Aggregate Cost: Total cost of a series of operations.
    • T(n) is aggregate cost for a sequence of n operations.
  • Amortized Cost: Average cost over a series of operations.
    • T(n)n is amortized cost. This is just the average cost!
    • You use this when you occasionally do a heavy operation that will make future operations faster (e.g. growing an array based list).

We still use our good old asymptotic growth rate friend (e.g. big-oh, big-omega, big-theta). This means T(n)=n2+nT(n)O(n2)T(n)nO(n).

Note: In this class, we are fairly fuzzy on the difference between aggregate cost and amortized cost. Sometimes we call them both amortized cost.

### Example

Let's see why we double lists (doubling strategy) instead of adding some constant (incremental strategy).

First, we analyze the incremental strategy.

We grow times n1c, where n is number of elements to add and c is how many elements we grow by.

T(n)=(c+1)+...+((n1)c+1) =ci=1n1i+n =c((n1)n2)+n =c(n2n2)+n.

This gives use T(n) O(n2), so the amortized cost T(n)n O(n).

We have shown the amortized cost is O(n).

Now, we analyze the doubling strategy.

We grow where 2c=nc=log2(n) times, where n is number of elements to add (to an empty list). c is the number of times we've grown the list.

T(n)=1+(1+1)+...+(2c1+2c1)

Note: We add the second number to account for how many additions we can do after we grow the list before we grow it again. =1+2i=0c12 =1+2(202c12) =1+2(2c1) =22c1 =22log2(n)1 =2n1. T(n)O(n). T(n)/n=21/nO(1).

## Experimental Analysis

You have to use the same hardware and software set up with little influence from other programs, temperature, etc. You must document your hardware.

This is beneficial in showing bad implementation problems.

### Graphing

When we make graphs, we use a log-log plot so it's easier to see polynomial growth rates, as they are transformed into lines. You can use whatever you want to graph things. R, Matlab, Excel, Google Sheets, etc.

y=axk. log(y)=klog(x)+log(a). Y=log(y). X=log(x). Y=kX+log(a).

To find the runtime of our graph, we plot a normalized collection of lines. We then make the lines intersect at a point by finding af(n)=ag(n) where g(n) is our normalized graph and f(n) is our actual runtime. We do this by choosing an arbitrary n and doing a=f(n)g(n).

## Analysis in This Class

In this class, we use the following set of steps to analyze an algorithm:

  1. Write an algorithm using pseudo-code, only using our ADT methods.
  2. Choose/identify your data structure implementations. If they are not specified, choose the most efficient one. Otherwise, use what they say.
  3. Analyze the algorithm.

# Algorithm Design

There are a few common designs:

  • Exhaustive Search: Examine all possibilities.
  • Divide and Conquer: Solve some original problem by decomposing it into smaller/easier problems and solving them recursively.
  • Greedy Approach: Optimize as early as possible.
  • Dynamic Problem: Solve small problems first and then save partial results and reuse them later in the larger problem.

# Pseudo-Code

We use a semi-standardized pseudo-code because we want to have an easy, common language to avoid regrade requests and complaints.

## Algorithm

Algorithm nameOfAlgorithm(param1, param2, ...)
+  Input
+    param1, description of param1, including
+      variables derived from / attached to
+      param1.
+    param2, ...
+  Output
+    Description of output
+
+  steps...
+

## For Loops

Arithmetic Iteration:

# start and end are inclusive
+for i <- 1 to n-1 do
+  if i = 2 then
+    i <- 3
+  print(i)
+

Collection Iteration:

# iteration through collection
+for each elem in List do
+  print(elem)
+

## If-Else

# start and end are inclusive
+if i = 2 then
+  print(i)
+else
+  print("Oh no")
+

# Iterative Algorithms

TODO: Integrate this with [Algorithm Analysis]

## Sorting Algorithms

Sorting algorithms can have the following properties:

  • Stable: Elements with the same key are sorted in the order they originally appeared.

### Comparison Based

Sort by making comparisons between pairs of elements. Analyze as number of comparisons. Normally efficient on small data sets with data that is almost sorted.

  • Bogo Sort: While the list isn't in order, shuffle the list.
    • O(???): Has unbounded running time.
  • Bubble Sort: Compare pairs of adjacent elements. If they are not in order, swap them. Repeat until no swaps are needed.
    • O(n2): Because you loop through the list n times. The worst case is a reversed list, when you have to reverse everything.
  • Insertion Sort: Split your list into two conceptual parts. The front is the sorted part and has no elements. The rest is the unsorted part. Take the first part of the unsorted part and insert it into the correct location of the sorted part.
    • O(n2): The worst scenario is when the list is in reversed order, since you have to do the maximum number of insertions each time. When this is the case, you have to do the familiar n+(n1)+(n2)+..., since you have to do n swaps at first, then n1 swaps, etc. Another way of doing this, difficult to find of this fuzzy worst case, is to find the worst case scenario for each loop.
  • Selection Sort: Split your list into two conceptual parts. The front is the sorted part and has no elements. The rest is the unsorted part. Find the smallest value in the unsorted part and select it to go at the end of the sorted part.
    • O(n2): You have to make n comparisons to find the first min. Then you have to make n1, then n2, ...

### Non-Comparison Based

Makes no direct comparisons between elements.

#### Counting Sort / Pigeonhole Sort

You count the number of instances of each key, putting the counts into another list with the counts ordered by key. You then take the cumsum of the sorted keys to find the ranges for each key. You then go through the list, finding the index using the key of the element to get the cumsummed count. You decrement the cumsummed count so you don't overwrite anything.

This is O(n+k) where n is number of elements in list and k is the range of the elements.

If you go through the list backwards, it is stable. Otherwise, it is unstable. However, here, we always go through the list forwards to differentiate it from radix sort, eve though they're basically identical.

#### Radix Sort

First, some names: N is the radix, B is a list of N buckets. w is the word size of integers (number of digits in things being sorted).

Basically, this is counting sort where you only consider a single digit at a time, slowly going through all digits. The counting sort version must be stable (processing the list in reverse).

This has O(wn) runtime because you are essentially running counting sort (O(n+k)) w times with a constant k.

You normally should go from least significant digit (LSD) to most significant digit (MSD), otherwise you will have less significant digit's overriding more significant digits.

Note: You could go from MSD to LSD, but then you must only sort within the digit buckets. You could do this in parallel though!

#### Heap Sort

In heap sort, you take advantage of the heap property, where the smallest element is always on top of the heap (for a min heap). Basically, you just insert all the elements you want to sort into a heap. Then, you remove everything from the heap and it's in sorted order because of the magic of heaps!

## Recursive Algorithms

Recursive algorithms are quite simply a base case and a recursive case. A base case is a special case for some certain (normally small) input. A recursive case is a general case that breaks the current case into (normally smaller) case(s) and calls itself.

You can find which case is the recursive case by finding all paths that call the algorithm again. Vice versa for the base case.

Because recursion, our T(n) function is also recursive. It again is set up into a base case and recursive case, specifically by input size.

T(n)=g(n);nd T(n)=aT(b)+f(n);n>d

  • g(n) is the number of essential operations (a.k.a. the runtime) of the base case.
  • f(n) is the number of essential operations (a.k.a. the runtime) of the recursive case.
  • d is the input size of the base case.
  • a is the number of recursive calls in the recursive case.
  • b is the new input size to a recursive call.

In this class, we look for T(n) (i.e. the actual runtime equation), not O(n).

### Analyzing

In CSC 216, we tried to find a closed-form (i.e. non-recursive form) by unfolding the recursive algorithm until we spotted a pattern. We then use this pattern to construct our closed-form solution. Do not simplify when creating the pattern.

Here, we will use a tree/levels method.

### Sorting Algorithms

Here, we only cover comparison based recursive sorting algorithms.

Again, because we're using comparison based algorithms, our essential operation is a comparison.

#### Merge Sort

Merge sort works by splitting up a list of elements into two halves, left and right. It then sorts those halves and merges them. If merge sort sees an empty list or a list with a single element, it declares it trivially sorted.

You already know the runtime is O(nlog(n)). Let's derive it! (On paper).

TODO: Add my paper notes to this.

#### Quick Sort

First, we pick a pivot. (There are many strategies!) Then, we create 3 lists: L (less than pivot), E (equal to pivot), G (greater than pivot). We then sort L and G. Then we concatenate L, E, G.

Quick sort produces imbalanced trees due to the selection of pivot. It is vital to have an effective pivot selection

Imbalanced Pivot

Balanced Pivot

As you can see intuitively, and we can theoretically prove, it is much more efficient to select the median (or near the median) of the element.

In face, picking the worst (min or max) each time is O(n2), while picking the best (median) each time is O(nlog(n)).

There are a few ways to pick a pivot:

  • Simple: Just pick the left or right.
  • Randomized: Pick a random pivot.
  • Heuristic: Pick the median of left, right, and middle. (Or some other elements!)

### Types of Recursion

There are a few types of recursion.

  • Tail Recursion: The final call is a recursive call to itself.
  • General Recursion: The final call is not a recursive call.

Tail recursion, outside of being epic, can be trivially converted into being iterative. This is good for efficiency because it means you don't have to store the last stack frame and can instead just replace your current stack frame with the new stack frame. This is called tail call optimization and doesn't just apply to tail recursion. Essentially, this just means you switch to a loop where your tail call becomes assigning the new values.

General recursion is much harder to convert to an iterative. Whenever you do a recursive call, you must put your current frame onto a stack (hence stack frame!), and then pop it out once you regain control flow.

As you can imagine, since tail recursion doesn't need a stack to store the context of every parent's call, it is vastly more memory and runtime efficient.

However, not every compiler performs tail call optimization because there can be other design considerations. For example, the JVM does not natively perform tail call optimization so it can properly report stack frames during an exception.

Note: You should probably keep your algorithm recursive because you get some extra guarantees on your algorithm (immutability safety). It also is often easier to understand.

# Indexed Lists

## Array Based / Contiguous Memory List

Array based lists are a solid chunk of memory, where adjacent in list means adjacent in memory. There are a few types:

  • Static Array-Based List: A array list with a constant size that can't grow.
    • Issues: You can waste memory if you allocate too much. You're screwed if you don't have enough space.
  • Dynamic Array-Based List: A array list that can copy itself into a new memory location to grow.
    • Issues: Sometimes you have to grow the array (O(n)!). The array doesn't shrink most of the time. Not actually that great for highly dynamic arrays, since they'll have to grow repeatedly.

How do we analyze the cost of adding to the end of an array based list? It's technically O(n) because you have to grow the array sometimes, but that's super pessimistic. So instead we use amortized cost to more properly represent the average case.

## Linked / Linked-Memory List

Elements can be scattered anywhere in memory. Each element keeps track of its value and then a pointer to the next value.

The way we navigate the list is by keeping track of a special head element and then following the pointers the appropriate number of times.

There are a few big families:

  • Singly-Linked List: The list is a chain where the nodes point to their successor. The final node points to nothing.
  • Circularly (Singly) Linked List: The list is a loop where the nodes point to their successor. The final node points to the first list.
  • Doubly-Linked List: The list is a string of nodes where the nodes point both to their successor and predecessor.

A few concepts they all share:

  • Dummy Node: A node with no information that sits at the end of (one side) of the list.

### Singly Linked List

### Circularly (Singly) Linked List

### Doubly Linked List

# Positional Lists

A type of list that allows us to interact with lists via positions/elements in the list instead of index.

Why do this? This is incredibly efficient (everything except search is O(n)). And, sometimes we really don't care that much about indexes, so it is nice to have a fast list. This also is an easy way to start learning how graphs work!

We will implement this as a doubly linked list with dummy nodes, since we have to regularly interact with elements either before or after a certain position and we don't want to be super careful about not missing previous elements.

# Stack

OperationDescription
pop()Removes and returns the element at the top of the stack.
top()Returns, but does not remove, the element at the top of the stack.
size()Returns the number of elements in the stack.
isEmpty()Returns true if the stack is empty; otherwise, returns false.

A stack has limited operations, where you can only access the top (peek), add to the top (push), or remove from the top (pop). Think of it as a Tower of Hanoi!

Visualization for Stack

Why use a stack? It's really easy to make an efficient implementation. We can also do a lot of interesting things (see stack machines).

## Array Based Stack

For traditional (i.e. non-circular) array based stacks, we want to push and pop from the end of the array. This allows us to push and pop in O(1) time since we don't have to do any shifts.

# Queue

OperationDescription
dequeue()Removes and returns the element at the front of the queue.
front()Returns, but does not remove, the element at the front of the queue.
size()Returns the number of elements in the queue.
isEmpty()Returns true if the queue is empty; otherwise, returns false.

Why use a queue? They are really easy to make an efficient implementation (i.e. O(1) for all operations). We can also do a lot of interesting things (see process schedulers).

## Singly Linked List

You want to dequeue at the head and enqueue at the tail, so you can do both in constant time. (You can enqueue in constant time at the head but dequeuing at the tail takes O(n).)

## Circular Buffer/Array

This is exactly my ArrayTapeList from last semester. You just treat the array as a circle and use modular arithmetic to get the indexes.

In this class, we assert that we always have one empty space. We also maintain front and rear where front is the index of the first element and rear is the space after the circular array. IMO, it would be easier if we maintained size.

Circular Array

You can enqueue/dequeue at either end equally efficiently, but here we will enqueue at rear and dequeue at front. This lines up well since rear is an empty space.

# Iterators

While they're not really their own data structure, they are a common language structure.

Iterators allow us to iterate over a collection in an abstract way. This is important because it allows data structures to implement their own method of iteration, allowing for more efficient iteration. The necessity for this over list.get(i) in a loop is easiest to see with linked lists. list.get(i) in a loop is O(n2) for linked lists while an iterator is O(n).

# Maps / Dictionaries / Associative Arrays

These have a bunch of names and are the most important data structure imo.

Maps are key value pairs, where you insert, retrieve, and interact with data in the structure using keys.

For some reason, we differentiate between dictionaries and maps. Here, dictionaries can have multiple values with the same key while maps cannot. We also change the method names.

## Dictionary ADT

This can have multiple values for a single key.
OperationDescription
insert(k, v)Inserts the given key-value entry into the dictionary
lookUp(k)Returns the value associated with the given key
delete(k, v)Removes and returns the given key-value entry from the dictionary
size()Returns the number of key-value entries in the dictionary
isEmpty()Returns true if the dictionary has no key-value entries

## Map ADT

This has a single value for a single key.
OperationDescription
put(k, v)Sets the value for the given key to be value, adding if necessary
get(k)Returns the value associated with the given key
remove(k)Removes the key from the map and return the previous value
size()Returns the number of key-value entries in the dictionary
isEmpty()Returns true if the dictionary has no key-value entries

## Unordered List Based Implementations

For unordered lists, we store a list key-value pairs (like a tuple!).

For both array based lists and linked lists:

  • Lookup is O(n) because we have to walk through every element in the worst case.
  • Put (with no duplicate keys) is O(n) because we have to walk through every element and then set the element or search through every element and then add at any arbitrary place (we assume addition is O(1)).
  • Remove is O(n) because we have to search through the list.

## Heuristic List Based Implementations

It really sucks that everything is O(n). Notice that we have better performance in general if the keys we care about are near where we search (here, we assume the first). To make this case more common, we can use some heuristics that work for any arbitrary element.

These heuristics tell us how to move an element after lookup.

Generally, we insert elements where we search first (normally the front).

The move to front (MTF) heuristic is when, after we look something up, we move that entry to the front. This is most common for linked lists. This is good because it can make drastic changes very quickly, so if a small subset of the keys in the list are normally looked up.

The transpose heuristic is when, after we look something up, we swap the entry with the previous. This is most common for array based lists.

## Search List

To improve lookup, we can keep a sorted array. This allows us to do binary search for lookup, meaning we have O(log(n)) look up. This does, however, make insertion and removal O(n) because we have to shift over elements.

This must be an array based list (or some list with random access).

## Skip List

A skip list is probabilistic due to its insertion algorithm and uses <2n space (yes, it's also O(n)). You can prove this quickly to yourself to see that each

We can approximate the performance of binary search using linked lists if we use a skip list.

A skip list consists of a list of h lists such that

S0S1S2...Sh

and

length(Si1)length(Si)/2

where each list starts and ends with two dummy nodes. And has about half the size of the previous (For integers, we normally just use and .) We arrange these as an ordered list (often viewed vertically) where the corresponding nodes are linked to the one before them, after them, above them, and below them. We call this a quad!

Skip List Diagram

A skip list uses far more memory than a normal list, because it holds duplicates of the elements (well, really duplicate pointers to the element). We also hold sentinel nodes on both side. You can see this below.

### Look Up in Skip List

The algorithm for lookup is, start at the top left. If the element to your right is equal to your element, you found it. If the element to your right is greater than your element, drop down and start over. If you can't drop down, give up.

You can see this emulates binary search because each step to the right skips about half the list.

### Removal in Skip List

The algorithm for removal is to first find the element. Once you find it, remove it and go down removing its "siblings" until you hit the bottom.

If you now have two top lists that are just the dummy nodes, remove them.

### Insertion in Skip List

Insertion in a skip list uses RNG (50/50 true vs false) to determine whether the inserted element should also be inserted into the list above.

Here, we say you flip a coin every time you insert at a level. If you get a tails, you insert into the next level. If you get a heads, you stop.

# Trees

A tree is directed, acyclic, and leveled. Directed means links have direction, acyclic means no path wraps around to the same node, and leveled means nodes have a single particular level.

We apply trees all over the space. Decision trees, abstract syntax trees, file systems, process trees, etc.

## Terms

Most of the terms we use to describe a tree are very simple.

  • Subtree: A tree within another tree.

### Parts of Tree

  • Node: A single element in the tree. Knows its data and its children.
  • Root: The single, top node in the tree. A node with no parents.
  • Leaf / External Node: A node with no children.
  • Branch: Any internal node that isn't a leaf.

### Relationships between Nodes

  • Parent: Single node above current node.
  • Child: One of possibly many nodes that are directly underneath your node.
  • Sibling: A child of your parent.
  • Ancestor: Your parent or your ancestor's parent.

### Shape of Tree

  • Height: Max level of any node in tree.
  • Depth / Level: Number of steps it takes to go from root to current node.

## ADT / Interface

OperationDescription
parent(p)Returns the parent of the given node p.
children(p)Returns a list of children of the given node p.
numChildren(p)Returns the number of children of the given node p.
isInternal(p)Returns true if the node has one or more children.
isLeaf(p)Returns true if the node has no children.
isRoot(p)Returns true if the node is the root of the tree (has no parent).
root()Returns the root of the tree.
size()Returns the number of entries in the tree.
isEmpty()Returns true if the tree is empty; otherwise, returns false.

## Traversal

Traversing a tree is the process of visiting every node in a tree. Visiting means performing some arbitrary action.

There is pre-order traversal, where you visit the current node and then its children. It has O(n) runtime, assuming the language has a O(1) stack.

Algorithm preOrder(node)
+  if node is null then
+    return
+  visit node
+  for each child of node do
+    preOrder(child)
+

There is post-order traversal, where you visit the node's children and then the node itself. It has O(n) runtime, assuming the language has a O(1) stack.

Algorithm postOrder(node)
+  if node is null then
+    return
+  for each child of node do
+    postOrder(child)
+  visit node
+

You can draw out a Euler tour to do the traversal for pre or post order traversals. You start on the left of the root. For pre-order, you traverse when you touch the left of a node. For the post-order, the right.

Euler Tour

You can also do level order traversals, where you process a level at a time left to right. It has O(n) runtime, assuming you use a O(1) queue.

Algorithm levelOrder(node)
+  Q <- new empty Queue
+  if v is null then
+    return
+
+  Q.enqueue(v)
+  while NOT Q.isEmpty() do
+    q <- Q.dequeue()
+    visit(q)
+    for each child of q do
+      Q.enqueue(child)
+

## Algorithms on Trees

Almost all algorithms on trees are essentially traversals, except we preform some important operation while visiting. This can help when breaking down unfamiliar algorithms.

## Building Trees from Traversals

We can use the pre-order and post-order traversals of a general tree to reconstruct it. Here, I'll assume the traversals are listed pre-order above post-order.

To do this, we take the root element (first node in pre-order or last node in post-order) out of the root element. Then we list the pre-order and post-order traversals without the root. The first node in the pre-order traversal is a child of the root. We then create a block from this child at the top left to the same node in the post-order traversal. All node in this block are children of the found child node. We then repeat ignoring this block to get the next child.

If we want to recreate the tree, we recurse for every child we find.

# Binary Trees

Binary trees are just trees where the nodes have a max of 2 children. Traditionally, these are ordered and we call one left and the other right.

## ADT / Interface

This has the same interface as a tree, plus the following.
OperationDescription
left(p)Returns the left child of the node p.
right(p)Returns the right child of the node p.
sibling(p)Returns the sibling of the node p.

## Traversals

We can, again, do everything a tree can do, but we can also do an in-order traversal. This is, again, O(1) assuming the language has a O(1) stack.

Algorithm inOrder(node)
+  if node is null then
+    return
+  inOrder(left(node))
+  visit node
+  inOrder(right(node))
+

## Special Binary Trees

We have a few special cases for binary trees that allow us to make some useful assumptions.

### Proper Binary Tree / Full Binary Tree / 2-tree

Every non-leaf node has two children.

This gives us count(leaves) = count(non-leaves) + 1.

Proper Binary Tree

### Perfect Binary Tree

A proper binary tree where all leaves have the same depth. This tree contains the most elements possible for the given height of the tree. Perfect trees have the most elements for their height h.

This gives us, for a tree with height h:

  • 2h+11 nodes.
  • 2h leaves.
  • 2h1 non-leaves / internal nodes.

Perfect Binary Tree

### Complete Binary Tree

A complete tree is an approximation of a perfect tree. All levels are filled except possibly the last level, which is filled from left to right. Complete trees have the least height among all binary trees with n nodes.

They have nodes 2hn<2h+1.

Complete Binary Tree

## Array Based Binary Tree

TODO

Array based implementation

# Binary Search Tree (BSTs)

Binary search trees are binary trees where for every interior (non-leaf) node N, left(N)<N<right(N). If there interior node has no left or right node, it is vacuously true. This is called the shape property.

Essentially, this means if you do an in order traversal of the tree you get a sorted list.

This means we can use trees for sorting and organization! This let's use search, insert, and manipulate trees using the binary search algorithm (O(logn)), giving us a fairly efficient data structure.

## Look Up

When you search through a binary search tree, the height determines how many searches you need to do in the worst case.

This should make sense since by looking up you're basically determining the path to find your element. In the worst case, your element is the lowest element (or between the lowest element and its in-order successor/predecessor), so you're having to compare for every node passed.

## Insertion

For insertion, we look search for the element. If we find it, we replace it's value with what we want. If we don't find it, we add it to where we ended up looking. (This relies on the fact that, when we search, we go to where the element "should" be.)

This means, in general, insertions increase the height of the tree.

## Removal

There are 3 cases you need to handle for removing a node N from BSTs:

  • children(N)=0: Just delete N.
  • children(N)=1: Replace N with its child only child.
  • children(N)=2: Replace N with the minimum from the right subtree (i.e. bottom left on right). We call this the in-order successor
    • We could also do max from the left subtree (i.e. bottom right on left, the in-order predecessor), but here we'll only be doing in-order successors because it makes grading easier.

This is basically a lookup (find the element to remove and find the lowest), so it has a runtime based off height.

## Runtime

In summary, where n is number of nodes in tree and h is height of tree:

  • Look Up: O(h)
  • Insertion: O(h)
  • Removal: O(h)

For balanced, complete trees, this means that everything is O(logn) because for complete trees O(h)=O(logn). (Because nlog2(h))

For unbalanced, non-complete trees, this means that everything is O(n) because O(h)=O(n).

This means the worst case performance for everything is O(n).

# Balanceable Binary Search Trees

As we just covered, BSTs are most efficient when they are balanced (e.g. almost complete). Therefore, we can get improved performance if we get try to keep a balanced tree.

Unbalanced BST

Balanced BST

It should be pretty easy to see that the only operations which can make a balanced tree unbalanced are get and put.

## Rotations

To maintain a tree as balanced, we must do rotations. A left rotation is where you take the left child L of a node N and make it so that L is a parent of N and N is the right child of L. Vice versa for right rotations.

Simple BST Rotation

We normally follow trinode restructuring. Where we have 3 important nodes, labeled "a", "b", and "c" in in-order traversal order. These are child, parent, and grand-parent (irrespectively). We try to make it so that "b" is the root, "a" is the left child, and "c" is the right child. This is useful because this is the simplest restructuring that reduces the height of the tree by one.

I strongly recommend visualizing these being moved and how the nodes and subtrees shift/disconnect.

Trinode Rotation #1

Trinode Rotation #2

Trinode Rotation #3

Trinode Rotation #4

## AVL Trees

This was invented by Georgy Adelson-Velsky and Evgenii Landis

AVL Trees have the following properties:

  • Height Balance Property: Where, for every node, its children's height differs by at most 1.

The lowest node which violates the height-balance property is the node that violates it. We find the nodes that violate the height-balance property by, after inserting or removing, going up and updating the heights. Once we find one that violates it, mark it. Then, chose its child with a larger height. Do this again; if its children have the same height, choose such that you form a "line". Make sure that you are labeling nodes correctly by their value. Now, you have "a", "b", and "c" (make sure that you have them labeled correctly)

For insertion, since you are only ever adding a leaf at possible a new level, you only have to do one rotation at most. For removal, you can potentially do many as you can be starting from high within the tree.

Intuitively, the AVL tree always makes the most conservative rotations possible.

Make sure you only do the trinode rotations from earlier.

### AVL Tree Performance

Temporarily, we'll use h since we haven't derived h in terms of n.

  • Lookup: O(h)
    • Trace Down: O(h)
  • Insert: O(h)
    • Trace Down: O(h)
    • Insert at Leaf: O(1)
    • Trace Up and Update Heights: O(h)
    • Restructure at most once: O(1)
      • Rotation: O(1)
  • Removal: O(h)
    • Trace Down: O(h)
    • Remove Node: O(1)
    • Trace Up and Update Heights: O(h)
    • Restructure as many h times: O(h)
      • Rotation: O(1)

Now, let's derive h in terms of n! We'll find the lowest n for a given h. We'll always make the left subtree larger to make analysis easier.

h and n Visualized

Since we defined the left subtree as always being the larger, let

  • n(h) be number of nodes in tree.
  • n(h1) be number of nodes in left subtree.
  • n(h2) be number of nodes in right subtree.

Given n(1)=1, n(2)=2,

n(h)=1+n(h1)+n(h2) n(h)>1+n(h2)+n(h2) Since we know n(h1)n(h2) n(h)>2n(h2)

Doing this recursively, we get n(h)>2n(h2) n(h)>4n(h4) n(h)>8n(h6)

You can probably see (and probably already knew), that this means

n(h)>2in(h2i) for i>0 and h2i1 (since we know)

## Splay Trees

Splay trees are trees which implement a splay operation, which reorganizes the tree. It does this by moving itself to be the root without breaking the binary search property (thing move to front heuristic). Every operation (lookUp, insert, delete) calls splay.

Note: Splay trees do not make any guarantees about the height of the tree (unlike AVL trees). This makes analysis significantly harder.

splay does this by doing repeated rotations (until the node is in sorted order). There are three cases:

  • p == tree.root(): Stop.
  • parent(p) == tree.root(): Perform zig.
  • p has parent u and grandparent w:
    • p and w are same direction children: Perform zig-zig. These are like trinode restructuring that go a "step too far".
    • p and w are opposite direction children: Perform zig-zig. These are just trinode restructring.

Right Rotation: 'Zig'

Left Rotation: 'Zig'

Right Rotation: 'Zig-Zig'

Left Rotation: 'Zig-Zig'

Right Heavy: 'Zig-Zag'

Left Heavy: 'Zig-Zag'

### Insertion

When we insert a node, we insert it like we would a binary search tree. We then splay the just inserted node.

### Removal

When we remove, we set the value of the node with its in-order successor's value (this can be itself if it has no in-order successor). We then remove the in-order successor's original node. Now, we splay the parent of the removed node.

### Look Up

When we look up a node, we splay the looked up node.

### Other Variations

Here, we use a variant of a splay tree called a "bottom up" splay tree. This means we insert into the bottom of the tree and then rotate as we go up. We could also do a "top down" splay tree, where we rotate as we go down.

### Why?

Moving everything might seem pointless / too much. They are most often used when locality matters. That is, if you want some node A, you might also be interested in its neighbors. A good example is looking for a book in a library.

### Runtime Analysis

TODO: re notate

The worst case scenario for a splay tree is where you insert keys in ascending or descending order. This yields a perfectly unbalanced tree (i.e. h=n).

  • Look Up: O(h)
    • Trace down: O(h)
    • Splay to the root: O(h)
  • Insert: O(h)
    • Trace Down: O(h)
    • Insert new leaf: O(1)
    • Splay to Root: O(h)
      • Because you need to do at most h splays.
  • Delete: O(h)
    • Trace Down: O(h)
    • Delete leaf: O(1)
    • Splay to Root: O(h)
      • Because you need to do at most h splays.

What makes splay trees annoying to analyze is that they have a worst case of O(h)=O(n) for everything. However, this is only in the case that you are operating on it only in ascending order, so it's misleading to say this. Therefore, we must use amortized analysis to get the average case.

We care mostly about how costly splaying is in a splay tree. This is because we do it at every operation.

First, let's define a bunch of variables:

  • Let T be a splay tree with n keys.
  • Let w be some node in T.
  • Let size(w) be the number of nodes in the subtree rooted as w.
    • size(w) = 1 + size(left(w)) + size(right(w)).
  • Let rank r(w)=log2(size(w)).

Rank is basically a measure of the balance of your tree. Lowering rank means better lookup. To analyze the runtime, let's break this down into scenarios and analyze the change in rank (Δr). Δr is, essentially, our "savings" from doing the rotation. This savings comes from us making the tree more balanced, so it is easier to look up in future.

#### Zig-Zig

Suppose we have nodes x, y, and z, that are being involved in a splay operation. Let r(w) be the rank after splaying.

Zig-Zig Rank Analysis

r(x)=r(z) r(y)r(x) r(x)r(y)

## 2-4 Trees

2-4 trees are actually a special type of [A-B Trees]. They can have more than 2 children.

Every inner node in a 2-4 tree has between 2 and 4 children and 1 and 3 children, respectively.

A 2-4 tree has the following properties:

  • All leaves have the same depth and contain 1, 2, or 3 keys.
    • That is, it's always a perfect tree!
  • An interior node can be:
    • A 2-node: 1 key and 2 children.
    • A 3-node: 2 key and 3 children.
    • A 4-node: 3 key and 4 children.
  • It is a search tree.
    • For 2-node, child[0] < keys[0] < child[1].
    • For 3-node, child[0] < keys[0] < child[1] < key[1] < child[2].
    • For 4-node, child[0] < keys[0] < child[1] < key[1] < child[2] < key[2] < child[3].
    • Essentially, it's sorted.

Types of Nodes in 2-4 Tree

To always maintain perfect balance it grows up.

### Look Up

Look up is fairly simple. We try to find what values we sit between in the current node, stopping if we find our node. If we don't find out node, we trace down to the node that is between the two nodes our value sits between. We then repeat.

### Insertion

Insertion starts by searching for your element, stopping when you find it or reach a leaf. You then insert the element into the leaf in correct order. Then, you check for overflow.

Overflow occurs when your node has 4 elements. To resolve this, split the node, pushing the 3rd up to the parent (in correct order) and put the 1st and 2nd in their own node and the 4rd in its own node. We then check the parent for overflow and repeat as necessary.

Note: We push 3rd up for consistency. You could just as easily push your 2nd up.

### Removal

Removal is the most complicated operation. When we remove, we search for the element we want to remove. If it is a leaf node, we just remove the element from the node. If it is an internal node, we replace the element with its in order successor and remove the in-order successor from its original node. We then check the node we just removed an element from for underflow.

Underflow occurs when your node has 0 elements. We have three ways to resolve this: deletion, transfer, or fusion.

  • Deletion: When the node is the root, we know the root is no longer necessary, since we only propagate removals up when we have a single child. (see fusion)
  • Transfer: When the node has at least one 3-node or 4-node sibling, it just rotates the adjacent child and parent around. (see image below)
  • Fusion: When the both node's siblings are 2-nodes, it must must fuse with its parent

## A-B Trees

A-B trees are multi-way search trees are a generalization of [2-4 Trees]. This should be easy to understand, since 2-4 was somewhat arbitrary.

A is the minimum number of children. B is the maximum number of trees.

## B Trees

B trees are a type of A-B tree with b=2a1. They only store data in the nodes.

B trees are best known for being used to efficiently access storage. This is great because accessing storage is incredibly expensive. The idea is you store the address that points to the next storage node. You then do searches to find where you should next access memory until you reach the final memory block.

They are great because they can be very wide, meaning we don't need several accesses to physical storage to reach the nodes that actually hold the data. Additionally, most of the time, starting access to storage access is the most expensive process. This means you can get a lot of data in a single access, another benefit.

## Red-Black Trees

A summary of the trees we've learned so far:

  • AVL Trees: Require O(logn) restructuring after deletion.
  • Splay Trees: Cannot guarantee O(logn) performance on any single operation because there are no guarantees about height.
  • 2-4 Trees: Require O(logn) split when inserting or O(logn) fusion when deleting.

Red-black trees have none of the above downsides, requiring only O(1) structural changes after insertion or deletion, making them more performant than any other tree we will learn. However, they are also the most complicated tree we will learn.

Note: Red-black trees are really a BST implementation of 2-4 trees. More on that later.

Red-Black Tree

### Properties of Red-Black Trees

  • Root Property: Root is black.
  • Leaf Property: Every leaf is black.
    • If you use dummy nodes, this becomes easier to see.
  • Red Property: The children of red nodes are black.
  • Depth/Black Property: All leaf nodes have the same number of black ancestors. ("black depth")
    • More generally, from any starting node N, all paths to the dummy leaf descendants contain the same number of black nodes.

These properties guarantee that the shortest path (all black) is no more than twice the length of the shortest path (alternating red and black). This is how we make our balance guarantee. In other words

h2d

### Connection to 2-4 Trees

Red-black trees are 2-4 trees because, given a red-black tree, we can construct a 2-4 tree. The inverse is not always true.

You do this by merging every red node with its parent, storing its entry in the parent and making all its children the children of the parent.

Red-Black Tree to 2-4 Tree

### Look Up

Look up in a red-black tree is the exact same as for a general BST.

Red-Black Tree Lookup

### Insertion

We start insertion using the traditional BST insertion operation. Then, we determine the color.

  • Inserting at Root: Black.
  • Otherwise: Red.

For free, this preserves:

  • Root property since we insert the root as black
  • Leaf property, since use use black dummy nodes.
  • Depth property, since we only care about black depth and we just inserted red.

This means the only property we may have violated is the red property. If the parent of the inserted node is black, we have not violated the red property. Otherwise, we have a double-red violation of the red property, which we must resolve.

#### Resolving Double-Red Violations

First off, names. Name the node we just inserted x, its parent y, its grandparent z, and its uncle s.

Resolving this violation is broken into two cases.

  • Case 1: s is black.
    • Recall that we already know y is red because we have a double-red violation and z is black by the red property.
  • Case 2: s is red.
    • Again, recall that y is red and z is black.

In case 1, we resolve this with a single (O(1)) trinode restructuring of x, y, and z. You then recolor whatever your b was (root of subtree after restructuring) to be black and your a and c red. This ensures that both sides follow the depth property, since the black z may no longer be the root, we want to make sure its previous descendants still follow the depth property. We have now resolved the issue and do not need to do any further checks.

In case 2, the double red may propagate, but we don't have to do any restructuring. This corresponds to a split in a 2-4 tree! (Although not always the 3rd element split we do.) To resolve this, we recolor y and s black (i.e. flip the color of the 2 levels above) and recolor z black, unless it is the root. We then check z for a double-red violation and resolve it accordingly.

Case 2 vs 2-4 Tree

Node: In the worst case, we must do O(h) recolorings in the worst case, where we always have case 2 violations. However, we consider this a trivial operation (i.e. not the essential operation).

### Removal

We start removal using the traditional BST removal operation. Recall that, for deleting internal nodes, we replace the value of a node with the value of its in-order successor and then we delete the in-order successor node.

If we removed a red node, we have finished, since black depth has not been changed.

If we removed a black node, we have violated the black depth property. We mark this by marking the dummy sentinel/NIL node as a double-black to account for the missing black ancestor.

### Resolving Double-Black Violations

First off, names. Name the double black node p, its parent z, its sibling y, and one of its siblings children (i.e. nephews) x (it doesn't matter which one).

TODO: Does it really not matter?

Resolving the violation is broken into two cases.

  • Case 1: y is black and has a red child x.
  • Case 2: y is black and both its children are black.
  • Case 2: y is red.

In case 1, we resolve this with a single (O(1)) trinode restructuring of x, y, and z. We then recolor a and c to black and b to be z's original color. Essentially, we just added a black depth to p, and then made sure that we didn't affect y's black depth. This corresponds to a transfer in a 2-4 tree.

Double-Black vs Transfer

In case 2, we recolor y from black to red and recolor z to black. If it already was black, make it double black and resolve that issue. (Unless it is the root, then just reduce it because then everything is reduced.) Basically, we just pushed the black up a level.

Double-Black When Red vs Fusion

Double-Black When Black vs Fusion

In case 3, we rotate y around z and recolor y to black and z to red. This doesn't actually improve anything directly, but it should get us one step closer. Now, you just try to resolve the double black again.

### Performance

  • Look Up: O(h)
    • Trace Down: O(h)
  • Insert: O(h)
    • Trace Down: O(h)
    • Insert new node: O(1)
    • Restructuring / Recoloring: O(h)
      • Case 1: O(1)
      • Case 2: O(h)
  • Remove: O(h)
    • Trace Down: O(h)
    • Remove node: O(1)
    • Restructuring / Recoloring: O(h)
      • Case 1: O(1)
      • Case 2: O(h)
      • Case 3: O(h)
        • Since it may lead to case 2.

#### Proofs

We want to reparameterize our runtimes to be in terms of n instead of h. To do this, we show that ninterior2d1 using a proof by induction.

In our base case, d=1 and ninterior=1. Therefore, ninterior2d1=201 holds.

Now, we split our inductive case into three cases, based off of the color of the children of the black node. This is easiest to see by converting the red black tree into a 2-4 tree and then analyzing the number of keys.

2-Node Equivalent

ninteriorn1+n2+1 2d2+2d2+1 22d2+1 2d1+1

3-Node Equivalent

ninteriorn1+n2+n3+2 2d2+2d2+2d2+1 32d2+2 2d1+2

4-Node Equivalent

ninteriorn1+n2+n3+n4+3 2d2+2d2+2d2+2d2+3 42d2+3 2d+3

In the smallest of these cases (case 1), we have ninterior2d1+1, which is greater than 2d1.

We have now proven that, for every red black tree,

ninterior2d1

Using h2dh2d and n2d1, we get

n2h21 log2nh21 h2log2n+1 h2log2n+2

Now, reparameterizing our runtimes, we get

O(h)=O(logn)

### Height

The proof for heights uses the known height of a 2-4 tree and making connections between red-black trees and 2-4 trees. This is an alternate way to prove runtime.

Let T be a red black tree of n entries with height h and black-depth d. Let T be the corresponding 2-4 tree of height h.

We know d=h+1 and hlog2n, from the connection between 2-4 trees and red-black trees. We know h2d, by the property of red-black trees. This gives us

h2d h2(h+1) h2(log2n+1)

This shows that the height of a red-black tree is O(logn).

### Red-Black Tree Summary

  • Insert:
    • Case 1: Sibling s of parent y is black.
      • Rotations: 2 (trinode restructuring).
      • Recolorings: Constant #.
    • Case 2: Sibling s of parent y is red.
      • Rotations: 0.
      • Recolorings: Constant #, but may propagate.
  • Delete:
    • Case 1: Sibling y of p is black and has a red child x.
      • Rotations: 2 (trinode restructuring).
      • Recolorings: Constant #.
    • Case 2: Sibling y of p is black and both of y's children are black.
      • Rotations: 0.
      • Recolorings: Constant #, then case 1 or 2.
    • Case 3: Sibling y of p is red.
      • Rotations: 1.
      • Recolorings: Constant #, then case 1 or 2.

# Hash Maps

Hash maps are great if you don't care about memory efficiency and do care a lot about runtime efficiency. We especially use them when key space (K) is huge (e.g. compiler symbol tables and IP addresses) and lookup and insertion is common, with few deletes, since deletion is more difficult.

Hash maps are expected to have O(1) runtime for all map functions. However, hash maps are fairly memory inefficient, due to maintaining a table much larger than the actual map.

## Idea

The idea is we have an array of size m and a hash function that that converts your elements into an integer from 0 to m1. This array holds lists of our given elements.

For insertion, you get the index of your new element by hashing it and then add your element at to the list at the given index.

For access, you get the index of your element by hashing it and then search for your element in the list at the given index.

For removal, you get the index of your element by hashing it and then remove your element from the list at the given index.

## Hash Function

Normally, your hash function is split up into two parts. You create a hash code, which can be arbitrarily large. Then, you compress it to be in the appropriate range (normally using modulus).

## Hash Code

There are a few different strategies. Here, we'll cover additive, polynomial, and cyclic-shift. For simplicity, we'll only be hashing strings, but you could easily extend this for other structured data.

### Additive

For a key of k=c0c1c2...cn1. Our hash function is

f(k)=i=0n1ci

This has the issue where there are a ton of collisions due to anagrams.

### Polynomial

For a key of k=c0c1c2...cn1. Our hash function is

f(k)=i=0n1ciri

Where r is some constant that has been optimized either mathematically or experimentally.

This might easier to show via accumulation

from functools import reduce
+def hasher(string):
+    reduce(
+        lambda acc, c: r * acc + ord(c),
+        string,
+    )
+

### Cyclic Shifting

This is the same as polynomial hashing, but instead of accumulating by multiplying the accumulator by r, we cycle the accumulator by n bits before we sum the current hash.

In practice, we can do the cycling using bit shifts.

from functools import reduce
+def rol(byte, n):
+    """Rotates `byte` left by n bits."""
+def hasher(string):
+    reduce(
+        lambda acc, c: rol(acc, n) + ord(c)
+        string,
+    )
+

A good value for n when hashing English words is 5. This was determined experimentally.

## Compression Function

A compression function takes some random integer f(k), which is the hash of key k, and returns an integer h(k) in the range 0..m1

There are a few different strategies. Here, we'll cover division, multiply-and-divide (MAD), and golden ratio method.

### Division Method

The division method is immediately obvious. It's what you think of. Just mod the numbers!

Given hash table of size m and a hash code f(k).

h(k)=mod(f(k),m)

#### Guidelines

Choosing m is very important and depends on your input space and your r (assuming you did polynomial hashing).

You should not choose m that evenly divides r1. Suppose m=r1.

h(ABC)=mod(f(ABC),r1) =mod(67r2+66r+65,r1) =mod(67((r1)2+2(r1)+1)+66((r1)+1)+65,r1) =mod((67(r1)+134+66)(r1)+67+66+65),r1) =mod(65+66+67,r1)

This basically means all anagrams will be identical, which is what we wanted to avoid by using polynomial hashing.

You should chose m to be prime because that avoids the issues above (with polynomial keys).

You should not chose m that divides rk±x for k=1,2 and x=1,2. Suppose m=r.

h(ABC)=mod(f(ABC),r) =mod(67r2+66r+65,r) =mod((67r+66)r+65,r) =mod(65,r)

This basically means all words that start with the same first letter will be identical.

### MAD Method (Multiply-And-Divide)

This method may eliminate some patterns in a set of hash codes due to being slightly more sophisticated.

h(k)=mod(αf(k)+β,m)

Where m is prime, α>0, and β0.

### Golden Ratio Method / Fibonacci Hashing

Has efficient compression for any m, not just primes.

In general, you divide your hash by the golden ratio. Then you take the fractional part and scale it by m to get the index. It's actually really intuitive! Don't get caught up in the symbols.

h(k)=mf(k)ϕ

Where x is the fractional part of x.

Note: Sometimes, in code, we prefer to multiply by the inverse of ϕ.

#### Why This is Good

This is generally the best compression method because it depends on all characters, meaning permutations are unlikely to collide.

This compression function has also been proven to evenly distribute keys, assuming evenly distributed key space. To throw out some bigs words, keys with small hamming distance in the key space are separated largely and randomly within the compression space.

An intuitive proof of this is that starting with n=1 gives you a fraction which is ϕ1. Going to n+1 falls into the segment of greatest length, dividing the segment by the golden ratio.

Golden Ratio with n=1

Golden Ratio with n=2

Golden Ratio with n=3

Note: This also has the benefit that if m=2i, you can calculate this very quickly on computers by performing some shortcuts using binary.

## Java's hashCode()

In Java, we compute the initial hash code (no compression), using the hashCode() method.

Java has the invariant that A.equals(B) necessarily implies A.hashCode() == B.hashCode(). However, the reverse is not necessarily true. Therefore, if you override equals(), you almost certainly need to override hashCode().

There exist the following guidelines/recommendations for implementing hashCode() in Java.

  • Store some constant nonzero value, say, 17, in an int variable called result.
  • For each field taken into account by the equals method
    • Compute an int hash code c for the field:
      • If the field is a boolean, compute (f ? 1 : 0).
      • If the field is a byte, char, short, or int, compute (int) f.
      • If the field is a long, compute (int) (f ^ (f >>> 32)).
      • If the field is a float, compute Float.floatToIntBits(f).
      • If the field is a double, compute Double.doubleToLongBits(f), and then hash the resulting long as above
      • If the field is an object reference and this class’s equals method compares the field by recursively invoking equals, recursively invoke hashCode on the field. If the value of the field is null, return 0 (or some other constant, but 0 is traditional)
      • If the field is an array, treat it as if each element were a separate field. That is, compute a hash code for each significant element by applying these rules recursively, and combine these values. If every element in an array field is significant, you can use one of the Arrays.hashCode methods added in Java 1.5.
    • Combine the hash code c computed in the previous step into result as follows:
      • result = 31 * result + c;
  • Return result.

# Hash Collision Resolution

We can't guarantee that we never have collisions. So, how do we tell our program where to look next?

There are two broad categories:

  • Chaining: Collided keys are linked together.
  • Open Addressing: Some algorithm determines how to search through the table.

Here's a quick comparison of the benefits of each.

  • Chaining: Removing is simple, requires more memory for small data.
  • Open Addressing: No dynamic memory management, more processor locality.

## Separate Chaining

### Standard Separate Chaining

Items are not stored in the buckets of the hash table. Instead, the buckets store pointers to a secondary map. (This means its a 2-level data structure.)

To use this, you hash your key, get the map at the hash, and then operate on that smaller map.

Separate Chaining

The advantages of this is that it's really easy to implement and has good performance. The disadvantages is that you need references and dynamic memory management.

### Coalesced Chaining

We consider coalesced chaining an example of separate chaining. It's actually a hybrid of open addressing and separate chaining!

The goal here is, like open addressing, to avoid dynamic memory management and pointers, but to maintain the benefits of chaining.

We do this by making our table contain entries which contain a piece of data and then a "next" pointer/index. We first insert the element directly into the table, with a no next. If we get a collision, we check the "next" and follow it. If it does not have a next, we start searching from the start of the table for an empty slot to insert into. If it does have a next, follow it and try to insert there and repeat as necessary.

As you can see, this means that our displaced keys (search from beginning to insert) take up space meant for our keys, since we just start from the front, causing more collisions.

Coalesced Hashing

### Coalesced Chaining with a Cellar

Coalesced chaining with a cellar is just coalesced chaining, except that our displaced keys initially go into a cellar meant exclusively for displaced keys. Whenever the cellar runs out of space, you just move outside of the cellar.

For good performance, make your cellar ~14% of m.

Coalesced Hashing with a Cellar

## Open Addressing

### Linear Probing

In linear probing, you store items directly into the hash table. If you get a collision during insertion, you look at the next index and try to insert there. For searching, you get the hash. You then look at that index. If the slot is empty, you've failed. If the slot isn't empty but you haven't found it, take some constant size step (normally one) and then check that slot.

### Double Hashing

Double hashing is the exact same as linear probing. However, instead of using a constant step size, you use some second hashing function to determine the step size.

Make sure the secondary hash is never 0.

## Performance

For hash tables, expected performance often depends on the load factor λ.

λ=nm

Where n is the number of items in the map and m is the number of items in the map.

We also consider the number of probes required in the map. This just means accesses. S(λ) is the average number of probes required by successful lookup. U(λ) is the same except for unsuccessful lookups.

Here's a quick breakdown of the performance. We won't derive these here. S is the average runtime of a successful lookup. U is the average runtime of an unsuccessful lookup. These all assume perfect hash functions (i.e. ones which evenly distribute everything.)

### Separate Chaining

S(λ)2+λ/2 U(λ)1+λ

### Linear Probing

S(λ)12(1+11λ) U(λ)12(1+1(1λ)2)

### Double Hashing

S(λ)1λln(11λ) U(λ)11λ

# Heap

Heaps are special binary trees that have the following properties:

  • Partial Order Property: Every node's child is either smaller than it (min heap) or larger than it (max heap). This has the result of making the smallest element in the heap on top, for a min heap, and the largest element in the heap on top, for a max heap.
    • Other people call this the heap property.
  • Complete Binary Tree Property: Heaps are always complete trees. Meaning they have the smallest height possible for their number of elements.
    • Therefore, h=log(n).

Simple Heap

The special thing about heaps is that all paths from root to leaf are in sorted order, in ascending order for a min heap and descending order for a max heap.

Additionally, we only interact with the root of the heap. That is, the largest or smallest element from the collection.

## Removing

When we remove the root of the heap, we the change value of the root with the value of one of the leaves and remove that leaf node. (Here, we pick the rightmost leaf.) Now we might have just violated the partial order property, so we perform a down heap on the root.

When performing a down heap, we swap the current node with its smallest child, until we are smaller than the smallest child (i.e. the partial order property is no longer violated).

## Insertion

When we insert into the heap, we insert into one of the leaves. Here, we insert into bottom level as far left as we can, to line up with remove.

When we do this, we may have just violated the partial order property. To resolve this, we perform an up heap on the node just inserted.

When performing an up heap, we swap the current node with its parent child, until we are larger than the parent. (i.e. the partial order property is no longer violated).

## Array Based Implementations

This may surprise you because we normally create trees using linked nodes. However, since heaps are complete trees, we don't waste as much memory with huge gaps, so it makes more sense to use an array. Also, if you look at an image, it makes a lot of sense.

Array Based Heap

As you can see, the array is just a level-order traversal of the tree! You can also see why we remove the bottommost rightmost; it's just size() - 1. You can also see why we insert into the bottommost leftmost empty position; its just size().

Finally, doing it this way doesn't make traditional up heaping or down heaping any harder.

# Priority Queue

Priority queues are a way to organize entries based off some priority. It is not related to queues whatsoever. This is used a lot in schedulers, packet routers, etc.

Here, we treat priority like a key. However, as you could probably guess, we allow multiple things of the same priority. We treat the object like a value.

Recall the total order relation's (i.e. ) properties:

  • Reflexive: kk
  • Antisymmetric: k1k2k2k1k1=k2
  • Transitive: k1k2k2k3k1k3

## ADT / Interface

OperationDescription
insert(k, v)Adds the entry with key K and value V to the priority queue
min()Returns, but does not remove, the entry with the smallest key
deleteMin()Removes and returns the entry with the smallest key
size()Returns the number of entries in the priority queue
isEmpty()Returns true if the priority queue is empty; otherwise, returns false

## List Based Implementations

List based implementations definitely are not the best. But they are simple to understand.

For sorted lists, whenever we insert an element, we insert it in sorted order. This yields O(n) insertion but O(1) removal.

For unsorted lists, whenever we remove an element, we make sure to remove the min element. This yields O(1) insertion but O(n) removal.

## Heap Based Implementations

Often, we implement priority queues using heaps. It should be pretty easy to see the parallel. You literally just create the concept of a custom "entry" containing your priority and data. Then, you just min/max on the heap using the entry.

# Adaptable Priority Queue

An adaptable heap is a more pragmatic, less perfect heap. Basically, this just allows you to remove arbitrary values and update priorities of values. Here, we also include updating the value of a node.

## ADT / Interface

This also supports all operations on a traditional priority queue.
OperationDescription
remove(e)Removes and returns entry e from the priority queue
replaceKey(e, k)Replaces the key of existing entry e
replaceValue(e, v)Replaces the value of the existing entry e

## Location-Aware Heap Implementation

We could search for elements in our heap whenever we want to operate on arbitrary elements. Alternatively, we can allow for instant access by making the entries in the heap know their index. This allows for random access, but it does mean we have to keep it updated.

# Sets

Sets are super simple. They are unordered, finite collections of elements without duplicates. They are just like mathematical sets. They're optimized for membership tests.

They're normally implemented like maps with no associated value. If you're literally wrapping existing maps, you either always insert null or the same thing as the key.

## ADT / Interface

OperationDescription
add(e)Adds the element e to the set (if e is not already present in the set).
remove(e)Removes and returns the element e from the set (if e is present in the set).
contains(e)Returns true if the set contains the element e; otherwise, returns false.
addAll(T)Updates the current set to also include all elements contained in the set T (also called “union”).
retainAll(T)Updates the current set to keep only those elements that are also elements in T (also called “intersection”).
removeAll(T)Updates the current set to remove any of the elements that are contained in T (also called “subtraction”).
size()Returns the number of elements in the set.
isEmpty()Returns true if the set contains no elements.

# Disjoint Sets

Disjoint sets are split into two main parts. There's the universe set, which holds all disjoint sets. There's the disjoint subsets / splits which partition the universal set.

If this sounds familiar, it should. These are covered in discrete mathematics when discussing how you partition a set. This is just a computer implementation.

For this class, each disjoint subset has a specific identifier element. We can pick these arbitrarily because its unimportant.

## ADT / Interface

These all return pointers to the sets/nodes.
OperationDescription
makeSet(e)Creates a disjoint set that contains the element e, then returns the position that identifies the set.
union(s, t)Merges the disjoint sets that contain positions s and t.
find(e)Returns the position of the identifier for the disjoint set that contains the element.

## Applications

Disjoint sets are useful in graph theory. If you have a set of nodes and graphs made up of subsets of those nodes, you can determine which graphs are combined by whether or not they have any intersection (i.e. if they're disjoint sets or not).

## Up-Tree Forest

Up-trees are just normal trees except that the links point to the parents (up) instead of to the children (down). We still call oldest parent the root!

A forest is just a set of disjoint trees.

Up-Tree Forest

We implement disjoint sets like this to have efficient find and union. To help us with this, we use linked general trees.

For us, each tree keeps track of its parent and its number of children (count) so that we can do a balanced union.

### makeSet

Just create a new tree node with its parent as itself. We do the weird parent thing to make implementation simpler?

### union

Find the root of both s and t. Call these rs and rt. Then, we need to merge the roots. We could do this arbitrarily by making one of them the parent. But for this class we use the heuristic by making the node with more successors (i.e. larger count) be the parent so that we stay roughly balanced.

### find

Take the node and then walk to its root.

We can do path compression find, where we update the parent pointer of everything along the path from the node to the parent to point to the parent. This effectively flattens the tree, making it faster in the future.

### Implementation Difficulties

Since up-trees only have parent pointers, its pretty difficult to individually access the elements, since you have an unknown number of required handles to get every element. (The number of handles required would be the number of leafs!)

#### Auxiliary Map

Along with your disjoint sets, you have another map that maps from the elements to the nodes. This requires more memory and everything.

#### Array Representation

If you can convert your elements to integers, you can store the parent index in the slot. For roots, you store the negative count.

Basically, this is just a hash table that points to the parent index of the hash table.

# Graphs

Simple Undirected Graph

Simple Directed Graph

Graphs are discussed using set-theoretic terms. Essentially, graphs are just sets of vertices and edges.

  • Graph: Set of vertices and edges.
    • Here we mean specifically undirected graph.
  • Digraph: Set of vertices and arcs.
    • Here we mean specifically directed graph.
  • Vertex: Node that can contain data.
  • Edge: Unordered pair of vertices.
    • To show they are unordered, we notate them u,v.
  • Arc: Ordered pair of vertices.
    • We normally call arcs edges.
    • To show they are ordered, we notate them (u,v).
  • Self Loop: Edge with the same vertex as both endpoints.
  • Incident Edges: All edges on a certain vertex.
  • Adjacent Vertices: Vertices connected by a single edge.
  • Degree: Number of connected edges on a vertex.
  • Complete Graph: Graph with edge between every distinct pair of vertices.

## Paths

Paths are fundamental to understanding and analyzing graph.

  • Path: A sequence of edges describing how to move through the graph.
  • Simple Path: A path where all vertices are distinct.
  • Cycle: A path that starts and ends on the same vertex, with no successive edges being identical. In other words, you can't forwards and then back.

## Subgraphs

  • Subgraph: Graph that is made up of only vertexes and edges of some other graph.
  • Spanning Subgraph: Graph that has all of the vertexes but not all of the vertexes of some other graph.

Many times, you can break up a graph into a smaller simpler graph. If you can prove/analyze properties of the smaller, simpler graph and then apply those to the parent graph, it makes your job simpler.

## Connections

It's often beneficial to think about how connected a graph is. This makes certain problems way easier to analyze.

For an undirected graph, we use the following terms

  • Connected Graph: From any vertex, it is possible to find a path to any other vertex.
  • Maximally Connected Graph: A connected graph where no path must be longer than 1.
  • Connected Component: Maximally connected subgraph.
    • In the most extreme case, this is a single vertex.

For a directed graph, we use the above terms when the connection may only go in one direction. We append the term strongly, when the relationship goes in both directions.

## Applications

Graphs are often used in networks and path planning. They can also be used for other things! In real life, vertices normally contain data and edges/arcs describe relations between bits of data.

## Properties Graphs

Here, graph is defined by set E of n edges and V of m vertices.

For an undirected graph, where deg(v) defines the degree of vertex v.

vVdeg(v)=2m mn(n1)2

For an directed graph, where indeg(v) defines the number of incoming arcs and outdeg(v) defines the number of outgoing arcs for vertex v.

vVindeg(v)=vVoutdeg(v)=m mn(n1)

## ADT / Interface

OperationDescription
.isDirected().Returns true if the graph is a directed graph. Otherwise returns false.
numVertices()Returns number of vertices in the graph.
vertices()Returns an iteration of all vertices in the graph.
numEdges()Returns the number of edges in the graph.
edges()Returns an iteration of all edges in the graph.
getEdge(u, v)Returns the edge that connects vertex u and vertex v; if no edge connects the two vertices, return null. For undirected graphs, getEdge(u,v) = getEdge(v,u).
endVertices(e)Returns the two endpoint vertices of edge e. For a directed graph, the first vertex is the source vertex and the second is the destination vertex.
opposite(v, e)Returns the other vertex of the edge, given an edge e incident to vertex v.
outDegree(v)Returns the number of outgoing edges from v.
inDegree(v)Returns the number of incoming edges to v.
outgoingEdges(v)Returns an iteration of all outgoing edges from vertex v.
incomingEdges(v)Returns an iteration of all incoming edges to vertex v.
insertVertex(x)Creates and returns a new Vertex storing element x.
insertEdge(u,v,x)Creates and returns a new Edge from vertex u to vertex v and stores element x.
removeVertex(v)Removes vertex v and all its incident edges from the graph.
removeEdge(e)Removes edge e from the graph.

# Graph Traversals

We've already seen traversals with trees. Remember that trees are just acyclic, connected graphs!

A graph traversal is a systematic way to visit all vertices v in graph G. These traversals are only possible if the graph is connected. (Duh!)

Graph traversals have many applications:

  • Garbage Collection: Given the references/names in your program, all pieces of memory should be connected. Unconnected pieces are garbage and should be freed.
  • Compute minimum spanning tree
  • Exploring/Moving Around Graph: Find optimal path from one vertex to another.
  • Determine Possibilities: Determine if graph is connected

## Types of Edges

Discovery edge

back edge

forward edge

cross edge

## Depth First Search (DFS)

DFS is like pre-order or post-order traversals for trees.

DFS for undirected graphs can only ever have discovery or back edges. DFS for directed graphs can have any edge. I won't prove that here, but it's pretty easy to see intuitively.

You keep a set of visited nodes. Then, whenever you visit a node, it marks it as visited and check all outgoing edges. For every outgoing edge, if the edge is to an unvisited node, mark it is a discovery edge recursively traverse that node. If the edge is to a visited node, mark it as a back, forward, or cross edge as appropriate.

Basically, go as deep as possible until you can't anymore. Then backtrack.

## Breadth First Search (BFS)

BFS is like level-order traversals for trees.

BFS for undirected graphs can only ever have discovery or cross edges. BFS for directed graphs can only ever have discovery, cross, or edges. I won't prove that here, but it's pretty easy to see intuitively.

## Transitive Closures

We can solve things more rapidly if we create a transitive closure or, basically, a graph of shortcuts.

Mathematically, for a graph G=(V,E), the transitive closure G=(V,E) is a graph that has all the same vertices and G has and edge (u,v) whenever G has a path from u to v.

If our edges have weights, these algorithm can also help us precompute the weights.

### Depth-First Search for Transitive Closures

We can construct a transitive closure by doing a depth first search on every vertex to find all vertices reachable by that vertex. Then we can link them.

Recall DFS has runtime of O(n+m). This algorithm has O(n(n+m)).

### Floyd-Warshall Algorithm for Transitive Closures

Note: In class, v1 is i, v2 is j, and v3 is j.

Floyd-Warshall's algorithm by checking every possible pair of vertices v1 and v2. If there's an edge between them, then we go through all other vertices v3 and find if v2 and v3 are connected by an edge. If v2 and v3 are connected, then we know we can go from v1 to v3. Add an edge between them if there isn't already one.

## Shortest Paths

Several times we'll want find the shortest path between two points. Mapping, network routing, etc.

To find the shortest path, we need some sort of weight for the edges.

### Floyd-Warshall Algorithm for Shortest Paths

### Dijkstra's Algorithm

  • Purpose: Find the shortest path from some vertex s to all other vertices. (This is called finding the single source shortest paths.)
    • The version we're taught it in class doesn't handle negative weights. If we were more liberal with what we checked, it probably would.
  • Methods: Dynamic programming, greedy.
  • Runtime: O((n+m)logn). O(mlogn) for connected graph since $m \ge n
    • 1$.

Dijkstra's algorithm uses an adaptable priority queue to keep track of what it wants to visit. It is a priority queue because it wants to check the closest/lightest path first. It is adaptable because the edge weights can update.

We start the algorithm by creating a priority queue containing vertexes with the weight for reaching that vertex from the starting vertex. Since we haven't discovered anything yet, everything except is except for the start which is 0.

Then, we start processing. First, we look at the lowest weight / easiest to reach vertex v in the priority queue. We then look at all of its neighboring vertexes vn. We compare the weight for reaching vn from v (weight(v)+weight(edge(v,vn))) with the current weight of vn. We then set the weight of vn to the minimum of those, updating the parent as appropriate. We then remove v from the priority queue and repeat until we've handled everything in the queue.

## Minimum Spanning Trees (MST)

A minimum spanning tree is a set of edges that connects all vertices with the lowest total weight of all edges.

Note: You can have multiple minimum spanning trees.

### Prim-Jarnik's Algorithm

  • Purpose: find the minimum spanning tree for some vertex.
  • Methods: Greedy.
  • Runtime: O((n+m)logn). O(mlogn) for connected graph since $m \ge n
    • 1$.

Prim-Jarnik's algorithm is very similar to Dijkstra's algorithm, except it's does minimum spanning trees.

You start with some arbitrary vertex and maintain a growing "cloud" of vertices by adding the lowest cost vertices to add new vertices.

We start the algorithm by creating a priority queue containing vertexes with the weight for reaching that vertex from the starting vertex. Since we haven't discovered anything yet, everything except is except for the start which is 0.

Now, consider the vertex with the lowest weight.

### Kruskal's Algorithm

  • Purpose: find the minimum spanning tree for some vertex.
  • Methods: Greedy.
  • Runtime: O(mlog(m)+mlog(n)+n). O(mlogm) for a connected graph. O(mlogn) since mn(n1)2 for an undirected graph and mn(n1) for a directed graph and logn2=O(logn).
    • We do O(mlogn) to show that Prim-Jarnik's Algorithm and Kruskal's algorithm theoretically have the same performance. Note: Your specific application does matter.

Kruskal's algorithm works by keeping a collection of edges and adding the next cheapest edge as long as it doesn't create a cycle.

You start by considering all edges in order of increasing weight. (Use a heap!) If adding the edge doesn't create a cycle with the edges you've already added, add it. Otherwise, skip it because you already have an edge connecting those for cheaper.

Note: An easy and efficient way to determine whether something would create a cycle is by maintaining a disjoint set of vertices.

## Graph Applications

### Biconnectivity

  • Biconnectivity: A measure of redundancy of a network.
  • Vertex-Disjoint Path: Two paths have the same start and end vertex but share no other vertexes.
  • Edge-Disjoint Path: Two paths have the same start and end vertex but share no edges.
  • Articulation Point / Cut-Vertex: A vertex in a connected graph that, if removed, makes the graph not connected.
    • Formally, given a MST, a vertex v is a cut-vertex if
      • It is the root and has more than one child.
      • It is not the root and has a child w such that no descendant of w reaches an ancestor and v.
  • Biconnected Graph: A connected graph that contains no cut-vertexes.
    • In other words, for every path between vi and vf, there exists at least two vertex-disjoint paths between vi and vf. (Hence the name!)

We'd like to measure how redundant our network is. Biconnectivity is a formal way to quantify redundancy.

The straightforward approach to find out if a connected graph is biconnected would be, starting from the initial graph, delete a single vertex/edge. Then run BFS/DFS to find out if the graph is still connected. Do this for every edge and node.

However, we can be more efficient by being clever with DFS.

TODO: Add the cleverness

### PageRank

PageRank handles finding the wanted node in the network given an ambiguous query. This was initially created for Google search by Larry Page. This is a very difficult problem for the following reasons:

  • Keywords are inexpressive.
  • There are multiple terms for the same concept. (Synonyms.)
  • There are multiple concepts for the same term. (Polysemy.)

The main idea of PageRank is that nodes that link to a lot of other nodes are important and that nodes that are linked to by a lot of other nodes are important.

PageRank is an iterative algorithm that runs until everything stabilizes. It starts out by assigning each node an equal importance (normally 1n). To find the next iteration, every node splits its importance between all of the nodes it links to, sending each one of them a fraction of its importance.

Note: The total weight never actually changes. It just gets redistributed.

This has a few issues:

  • How do we deal with dangling pages?
    • We normally deal with dangling pages by saying that they link to every node.
  • The Internet is huge. How do we speed it up?
    • We can decompose the graph into smaller graphs and run PageRank on them. Then do something to bring them all back together.
    • We can stop early. The precise values returned by PageRank don't normally matter. We only need to find the relative ordering.
  • This doesn't model things perfectly. What about random switches?
    • We normally add a damping factor. This damping factor is the probability that the user randomly switches webpages.

# P (Polynomial) vs NP (Non-Deterministic Polynomial)

  • Polynomial Time: Anything less than O(nlogn).
  • Non-Polynomial Time: Anything greater than or equal to O(nlogn).
  • P: Problems that have both polynomial time solutions and verifications.
  • NP: Problems that have a polynomial time verification, but it is unknown on whether they have a polynomial time solution.

The P vs NP problem asks, if there is a polynomial time algorithm to verify a solution, does that imply that there is a polynomial time algorithm to solve the problem? In other words, are all NP problems actually P problems.

Important! NP does not mean that a polynomial time solution does not exist. It just means we don't know if it exists.

How would you prove P = NP? The idea is you pick an NP-complete problem. The NP-complete problems are problems where we only know the solution using a brute force method. If you can prove that one of these is P, then you did it.

## Comparison Based Sorting Algorithms

We will motivate this discussion using comparison based sorting.

There does exist polynomial time solutions to sort a list (e.g. merge sort O(nlogn), bubble sort O(n2)). There also exists polynomial time verifications (check over every element in the list O(n)).

Is there a algorithm to solve faster than O(nlogn)? No. We can check this by forming a decision tree.

Sorting Decision Tree

The first level can have up to n children, all nodes in the next level can have n1 children, and so on. Thus the total number of nodes is nn1...1=n!. This means we know this means the height of the tree is at least log(n!). Since log(n!)log(n/2)n/2. This is Ω(nlogn).

We have shown that no solution can be faster than O(nlogn).

\ No newline at end of file diff --git a/notes/ncsu/2f/csc316/left_heavy_zig_zag.png b/notes/ncsu/2f/csc316/left_heavy_zig_zag.png new file mode 100644 index 0000000..f7ccb04 Binary files /dev/null and b/notes/ncsu/2f/csc316/left_heavy_zig_zag.png differ diff --git a/notes/ncsu/2f/csc316/left_zig.png b/notes/ncsu/2f/csc316/left_zig.png new file mode 100644 index 0000000..d1c959f Binary files /dev/null and b/notes/ncsu/2f/csc316/left_zig.png differ diff --git a/notes/ncsu/2f/csc316/left_zig_zig.png b/notes/ncsu/2f/csc316/left_zig_zig.png new file mode 100644 index 0000000..b708dd9 Binary files /dev/null and b/notes/ncsu/2f/csc316/left_zig_zig.png differ diff --git a/notes/ncsu/2f/csc316/perfect_binary_tree.png b/notes/ncsu/2f/csc316/perfect_binary_tree.png new file mode 100644 index 0000000..47c26d2 Binary files /dev/null and b/notes/ncsu/2f/csc316/perfect_binary_tree.png differ diff --git a/notes/ncsu/2f/csc316/proper_binary_tree.png b/notes/ncsu/2f/csc316/proper_binary_tree.png new file mode 100644 index 0000000..9d40748 Binary files /dev/null and b/notes/ncsu/2f/csc316/proper_binary_tree.png differ diff --git a/notes/ncsu/2f/csc316/red_black_2_node.png b/notes/ncsu/2f/csc316/red_black_2_node.png new file mode 100644 index 0000000..993e3a4 Binary files /dev/null and b/notes/ncsu/2f/csc316/red_black_2_node.png differ diff --git a/notes/ncsu/2f/csc316/red_black_3_node.png b/notes/ncsu/2f/csc316/red_black_3_node.png new file mode 100644 index 0000000..b89ef37 Binary files /dev/null and b/notes/ncsu/2f/csc316/red_black_3_node.png differ diff --git a/notes/ncsu/2f/csc316/red_black_4_node.png b/notes/ncsu/2f/csc316/red_black_4_node.png new file mode 100644 index 0000000..20cfa7a Binary files /dev/null and b/notes/ncsu/2f/csc316/red_black_4_node.png differ diff --git a/notes/ncsu/2f/csc316/red_black_case_2_vs_2_4.png b/notes/ncsu/2f/csc316/red_black_case_2_vs_2_4.png new file mode 100644 index 0000000..c9df543 Binary files /dev/null and b/notes/ncsu/2f/csc316/red_black_case_2_vs_2_4.png differ diff --git a/notes/ncsu/2f/csc316/red_black_double_black_fusion1.png b/notes/ncsu/2f/csc316/red_black_double_black_fusion1.png new file mode 100644 index 0000000..c44de61 Binary files /dev/null and b/notes/ncsu/2f/csc316/red_black_double_black_fusion1.png differ diff --git a/notes/ncsu/2f/csc316/red_black_double_black_fusion2.png b/notes/ncsu/2f/csc316/red_black_double_black_fusion2.png new file mode 100644 index 0000000..b5d8fcd Binary files /dev/null and b/notes/ncsu/2f/csc316/red_black_double_black_fusion2.png differ diff --git a/notes/ncsu/2f/csc316/red_black_double_black_transfer.png b/notes/ncsu/2f/csc316/red_black_double_black_transfer.png new file mode 100644 index 0000000..7a69060 Binary files /dev/null and b/notes/ncsu/2f/csc316/red_black_double_black_transfer.png differ diff --git a/notes/ncsu/2f/csc316/red_black_lookup.png b/notes/ncsu/2f/csc316/red_black_lookup.png new file mode 100644 index 0000000..49232a3 Binary files /dev/null and b/notes/ncsu/2f/csc316/red_black_lookup.png differ diff --git a/notes/ncsu/2f/csc316/red_black_to_2_4.png b/notes/ncsu/2f/csc316/red_black_to_2_4.png new file mode 100644 index 0000000..a0adc09 Binary files /dev/null and b/notes/ncsu/2f/csc316/red_black_to_2_4.png differ diff --git a/notes/ncsu/2f/csc316/red_black_tree.png b/notes/ncsu/2f/csc316/red_black_tree.png new file mode 100644 index 0000000..7ce15ca Binary files /dev/null and b/notes/ncsu/2f/csc316/red_black_tree.png differ diff --git a/notes/ncsu/2f/csc316/right_heavy_zig_zag.png b/notes/ncsu/2f/csc316/right_heavy_zig_zag.png new file mode 100644 index 0000000..72defc9 Binary files /dev/null and b/notes/ncsu/2f/csc316/right_heavy_zig_zag.png differ diff --git a/notes/ncsu/2f/csc316/right_zig.png b/notes/ncsu/2f/csc316/right_zig.png new file mode 100644 index 0000000..b42c4fc Binary files /dev/null and b/notes/ncsu/2f/csc316/right_zig.png differ diff --git a/notes/ncsu/2f/csc316/right_zig_zig.png b/notes/ncsu/2f/csc316/right_zig_zig.png new file mode 100644 index 0000000..591fda7 Binary files /dev/null and b/notes/ncsu/2f/csc316/right_zig_zig.png differ diff --git a/notes/ncsu/2f/csc316/simple_digraph.png b/notes/ncsu/2f/csc316/simple_digraph.png new file mode 100644 index 0000000..d55aeab Binary files /dev/null and b/notes/ncsu/2f/csc316/simple_digraph.png differ diff --git a/notes/ncsu/2f/csc316/simple_graph.png b/notes/ncsu/2f/csc316/simple_graph.png new file mode 100644 index 0000000..488d1f1 Binary files /dev/null and b/notes/ncsu/2f/csc316/simple_graph.png differ diff --git a/notes/ncsu/2f/csc316/skip_list.png b/notes/ncsu/2f/csc316/skip_list.png new file mode 100644 index 0000000..aabdea8 Binary files /dev/null and b/notes/ncsu/2f/csc316/skip_list.png differ diff --git a/notes/ncsu/2f/csc316/sorting_decision_tree.png b/notes/ncsu/2f/csc316/sorting_decision_tree.png new file mode 100644 index 0000000..c73fad2 Binary files /dev/null and b/notes/ncsu/2f/csc316/sorting_decision_tree.png differ diff --git a/notes/ncsu/2f/csc316/stack_view.png b/notes/ncsu/2f/csc316/stack_view.png new file mode 100644 index 0000000..f2c2a0b Binary files /dev/null and b/notes/ncsu/2f/csc316/stack_view.png differ diff --git a/notes/ncsu/2f/csc316/trinode_rotation1.png b/notes/ncsu/2f/csc316/trinode_rotation1.png new file mode 100644 index 0000000..ec38f8e Binary files /dev/null and b/notes/ncsu/2f/csc316/trinode_rotation1.png differ diff --git a/notes/ncsu/2f/csc316/trinode_rotation2.png b/notes/ncsu/2f/csc316/trinode_rotation2.png new file mode 100644 index 0000000..3fe9660 Binary files /dev/null and b/notes/ncsu/2f/csc316/trinode_rotation2.png differ diff --git a/notes/ncsu/2f/csc316/trinode_rotation3.png b/notes/ncsu/2f/csc316/trinode_rotation3.png new file mode 100644 index 0000000..cb46b4e Binary files /dev/null and b/notes/ncsu/2f/csc316/trinode_rotation3.png differ diff --git a/notes/ncsu/2f/csc316/trinode_rotation4.png b/notes/ncsu/2f/csc316/trinode_rotation4.png new file mode 100644 index 0000000..f9bd0c4 Binary files /dev/null and b/notes/ncsu/2f/csc316/trinode_rotation4.png differ diff --git a/notes/ncsu/2f/csc316/unbalanced_bst.png b/notes/ncsu/2f/csc316/unbalanced_bst.png new file mode 100644 index 0000000..a635744 Binary files /dev/null and b/notes/ncsu/2f/csc316/unbalanced_bst.png differ diff --git a/notes/ncsu/2f/csc316/up_tree_forest.png b/notes/ncsu/2f/csc316/up_tree_forest.png new file mode 100644 index 0000000..70e17c2 Binary files /dev/null and b/notes/ncsu/2f/csc316/up_tree_forest.png differ diff --git a/notes/ncsu/2f/csc316/zig_zig_analysis.png b/notes/ncsu/2f/csc316/zig_zig_analysis.png new file mode 100644 index 0000000..69a640d Binary files /dev/null and b/notes/ncsu/2f/csc316/zig_zig_analysis.png differ diff --git a/notes/ncsu/2f/index.html b/notes/ncsu/2f/index.html new file mode 100644 index 0000000..1c7fbef --- /dev/null +++ b/notes/ncsu/2f/index.html @@ -0,0 +1 @@ +Zola

Welcome to Zola!

You're seeing this page because we couldn't find a template to render.

To modify this page, create a section.html file in the templates directory or install a theme.
You can find what variables are available in this template in the documentation.

\ No newline at end of file diff --git a/notes/ncsu/2f/py208/index.html b/notes/ncsu/2f/py208/index.html new file mode 100644 index 0000000..60eab19 --- /dev/null +++ b/notes/ncsu/2f/py208/index.html @@ -0,0 +1 @@ +Eli | PY 208: Physics II (Electricity and Magnetism)

PY 208: Physics II (Electricity and Magnetism)

Instructor: Dr. Shuang Fang Lim | Semester: Fall 2019

Scanned PDF.

\ No newline at end of file diff --git a/notes/ncsu/2f/soc202/crude_divorce_rate.png b/notes/ncsu/2f/soc202/crude_divorce_rate.png new file mode 100644 index 0000000..1bb5161 Binary files /dev/null and b/notes/ncsu/2f/soc202/crude_divorce_rate.png differ diff --git a/notes/ncsu/2f/soc202/index.html b/notes/ncsu/2f/soc202/index.html new file mode 100644 index 0000000..0835d77 --- /dev/null +++ b/notes/ncsu/2f/soc202/index.html @@ -0,0 +1 @@ +Eli | SOC 202: Principles of Sociology

SOC 202: Principles of Sociology

Instructor: Thomas-Winfield, M.S. | Semester: Fall 2019

Table of Contents

# Administrivia

  • No final exam. Just a final semi-independent project.
  • Grades on Moodle.
  • No late work.
  • No more than 2 absences. 3 tardies = 1 absence.
  • Notes for day uploaded at start of class.

# Terms

  • Sociology: Science of human social behavior and individuals interaction with society.
  • Sociological Imagination/Perspective: Ability to see relation between individual lives and society at large. Specifically dealing with troubles and issues.
  • Diversity: Abstract concept of the variety of experiences of members in a group.
  • Positivism: The scientific method, where knowledge and inquiry is above all.
  • Ethnography: Study done using observation and interviews.

## Sociological Concepts

It is important to realize society changes people and people change society.

  • Social Interaction: Meaningful behavior involving 2+ people.
  • Social Structure: Organized pattern for relationships and institutions that make up a society. Common social forces of society.
  • Social Institutions: Organized system of social behaviors with a specific purpose. (e.g. marriage, government, family)
    • Unlike individual behavior, this cannot be directly observed.
  • Social Organization: Order established within social groups. A structured system/pattern of social relationships in a group of people. This makes society easier to understand.
    • Formal Social Organizations: Goal directed. Military, universities, hospitals.
    • Informal Social Organizations: Not goal directed. Friend groups, individual relationships, social groups.
  • Social Change: The change society experiences over time for any reason.
    • This can be motivated to attempt to cause significant transformation of behavior patterns, social institutions, and cultural values. This is called applied sociology normally.
  • Structural Effects: Pushes on individuals from society.
  • Cultural Capital: Skills, behaviors, and experiences that can change your lot (can benefit or harm you). Everyone has cultural capital but the type/quality of it depends. Examples include speech style, education, negotiation abilities, self advocacy, discipline.

### Societal Concepts

  • Issues: Largely felt troubles coming form a common origin in society. Hard to pinpoint specific cause.
    • Synonyms: Public Issues of Social Structure.
    • Parallel: Troubles.
  • Structure: Social systems that constrain actions of individuals.
    • Parallel: Agency.
  • Context: Setting for a society.
    • Parallel: Social Context
  • Macroscopic/Large-Scale Social Phenomena: Groups, organizations, cultures, society, the world, and the relationships among them.
    • Parallel Microscopic ...

### Individual Concepts

  • Troubles: Privately felt difficulties
    • Synonyms: Personal Troubles of Mileau (i.e. social setting of troubles)
    • Parallel: Issues.
    • Examples: Divorce (rate), student loan debt, unemployment (in recession/depression), obesity.
  • Agency: Capacity to act independently.
    • Parallel: Structure.
  • Social Context: Influence of society on individuals.
    • Parallel: Context.
  • Microscopic/Small-Scale Social Phenomena: Individuals and their thoughts and actions.
    • Parallel Macroscopic ...

# People

See page 19 of "Sociology: The Essentials, 9th ed." for a table. All people here discussed American society.

  • Alexis de Tocqueville (1805–1859): French man. "Tyranny of the majority".
  • Harriet Martineau (1802–1876): British woman. Wrote "Society in America (1937)".
  • Jane Addams (1860-1935): White woman. Leader in "settlement house movement" and other movements to help poor and immigrants.
  • Ida B. Wells-Barnett (1862–1931): Black woman; born a slave. Leader of anti-lynching movement and women's and black's rights.
  • W. E. B. DuBois (1868-1963): Black man. Founder of NAACP (National Association for the Advancement of Colored People).
  • C. Wright Mills (1916-1962): "Sociological imagination".

# Sociological Research

Broadly research involves a puzzle and idea.

  • Puzzle: Research Question
  • Idea: Hook or twist to research question. What makes your research unique.

Sociologists generally don't replicate a study unless a previous research study had questionable practices. (This is rationalized because of peer review) If there is replication, there tends to be a "twist" and researches themselves will recommend twists.

Sociological research tends to be split between quantitative and qualitative. Here's a broad overview:

  • Quantitative:
    • Deductive (theory/hypotheses to research)
    • Methods: surveys, polls, structured questionnaires, experiments (i.e. numerical data)
    • Asks: relate, effect, cause, impact
    • Broad
    • Generalizable
  • Qualitative:
    • Inductive (research to theory/hypotheses)
    • Methods: participant observation, focus groups, in-depth interviews (i.e. text-based data)
    • Asks “what” or “how”
    • Deep
    • Not generalizable

It is important to note that sociological research tends to have values that can impact their research (see positionality). This positionality is more impactful for qualitative research.

To try to combat positionality, sociologists (especially qualitative) tend to be very reflective, describing their position and history and how that may impact their research.

## Quantitative Research

Quantitative research seeks to create associations/correlations and uses hypotheses. Actual numbers and counts (of groups) are used; numbers are often hard to get, so we can be pretty liberal.

To show causality, sociologists only must only show the following to a reasonable person.

  • Correlation: We need to see them together.
  • Temporal Ordering: We need to know that our independent variable occurs before our dependent variable.
  • Non-Spuriousness: The relationship makes sense / isn't caused by anything else.

As you can see, sociologists are pretty liberal. Their requirements are sound in theory, but it's hard to prove non-spuriousness in practice without experiments, which we can't (normally) do because of ethics.

Quantitative research normally uses surveys, polls, structured questionnaires, experiments (i.e., numerical data).

Quantitative research tends to be easy to generalize.

### Examples

Does critical thinking ability relate to student achievement?

Is there a relationship between neighborhood type (e.g. residential, business district) and types of crimes committed (e.g. car theft, robbery)?

## Qualitative Research

Qualitative research seeks to understand individual people's perceptions of their experiences, what meaning people attribute to themselves, and the social processes that help form their lives.

There are no hypotheses and it is very individual and touchy-feely. It's a lot like case-studies except normal.

Qualitative research tends to be very exploratory, where people start with a central question that spawns sub-questions.

Normally works with symbolic interaction on the micro level.

Qualitative research normally uses participant observation, focus groups, in-depth interviews (i.e. text-based data)

Qualitative research tends to be hard to generalize.

### Examples

What are the experiences of minority students in predominantly white educational institutions?

How do parents discuss sex and sexuality with early adolescent girls and boys?

## Themes

  • (Social) Diversity: The variety of group experiences that come from social structure.
    • Group differences in opportunities
    • Shaping of social institutions by various factors.
  • (Social) Inequality: Ways social categories are differentially positioned with social goods (e.g. labor market, education, healthcare, political representation, etc.)
  • Globalization: Increased economic, political, and social connectedness and interdependence among societies around the world.
    • Pros: More access to goods and services, shared technology, etc.
    • Cons: Job displacement, pollution impacts, "deviant globalization" (terrorism, sex trafficking, black market, etc.)
    • Causes: Internet, container ships, airplanes.

## "Levels" of Study

  • Personal Level (micro): Studying individual people
    • Examples: symbolic interaction, family conflict, aging
  • Societal Level (macro): Examine whole semi-homogeneous group.
    • Examples: crime and law, poverty and wealth, social movements
  • Global Level (macro): Examine whole world.
    • Examples: war and peace, global economy
    • Increasingly similar to societal level.

## Ethics

Here are some examples of ethical controversies:

  • Philip Zimbardo: Stanford Prison Experiment (1971)
  • Federal Government: [Tuskegee Syphilis Study] (1932-1972)
  • Laud Humphreys': [Tearoom Trade Study] (1965-1968)
    • Issue: Men did not know they were being studied (no informed consent). He deceived the participants. Collected personal information on participants. Did follow up studies again deceiving the participants.
    • https://en.wikipedia.org/wiki/Tearoom_Trade
  • Mark Regnerus: Study on Same-Sex Parenting (2012)
    • Issue: Conflict of interest, funded by anti-LGBTQ groups. Had troublesome research practices.

As a reaction, we have the following informal ethical principles.

  • Respect for Persons: Treat individuals as autonomous people, protecting children and others with diminished-autonomy.
  • Beneficence: Minimize harm to studied individuals (and everyone) and maximize the benefits to studied individuals (and everyone)
  • Justice: Benefits and harms should be distributed justly/fairly equally

Also, every institution that does research on humans must have an institutional review board (IRB) that reviews research proposals, that apply common ethical standards. Researches cannot begin until the IRB approves.

### Common Ethical Standards

  • Achieve Valid Results: Your research is meant to get correct info.
  • Ensure Honesty and Openness: Scientists must disclose their methods and honest in presenting their finding.
  • Protect Research Participants:
    • Do no harm to participants.
    • Participants must be anonymous, unless explicitly waived with informed consent.
    • Benefits should outweigh risks.
  • Informed Consent:
    • Participants must know how and why the research is being done, unless them knowing prevents the study.

## Peer Review

All research must go through peer review process. The peer review process is when you send your paper to a board. They give you feedback and one of the following happens:

  • Your paper is rejected.
  • Your paper is temporarily rejected with feedback.
  • Your paper is accepted.

## Finding and Parsing Research

In this class, we will only look at peer-reviewed articles from NC State's database which were published by sociological journals.

You can search for you topic, filtering for only peer-reviewed articles, and then scour for one published by a journal. Or you can search in all for sociological journals. Then, pick the one you want, and go directly to the journal's website.

You can also use Google Scholar, find what you want, and then look for it on NC State's libraries.

When reading articles, always read the abstract first.

### Research Outline

  • Title and Author Information
  • Abstract
  • Introduction
  • Literature Review
    • Qualitative: State a grounded theory, which is what they're stating.
  • Hypotheses (Quantitative Articles Only)
  • Method
    • Quantitative: Independent variables, dependent variables, controls.
    • Qualitative: Demographics, interview process, recruitment strategies.
  • Analysis
    • Quantitative: What they did statistically.
    • Qualitative: How they thought about the results.
  • Results/Findings
    • Quantitative: Give descriptive statistics. State whether their hypothesis was supported. Show data. Don't interpret.
    • Qualitative: Provide examples and interpretations
  • Discussion/Conclusion
    • Quantitative: Where they interpret, elaborate, and say stuff about their findings. Talk about limitations. Suggestions for future research and policy.
    • Qualitative: What they think their interpretation/findings mean. Suggestions for future research and policy.
  • References
  • Appendix (e.g., interview questionnaire, survey example)

## Citations

When you summarize or paraphrase work, provide the author's names and year of publication.

Gender inequality... (West and Zimmerman 2009)

When directly quoting, include author's name, year of publication, and page numbers from work within directly after the quote.

Firebaugh argues "..." (Firebaugh 2008:50)

If you have works with several authors, you cite every author the first time and then just the first author "et al.".

# Purpose of Sociology

  • Scientific / Descriptivist View: Just describe and investigate society's structure.
  • Social Reform / Prescriptivist View: Take the results of research into society's relationship and use it to solve social problems.
  • Hybrid: You do both! How much? It's a spectrum.

# Debates

## Agency vs Structure

  • Do people act as free agents or as a social structure? It's hard to determine and seems to depend! I tend to think structure.

# Theories

Sociology theory arose during the 1800s because of and with industrialization and urbanization. (A lot of things were changing!)

## Social Construction of Reality Theory (SCT)

  • Social Construction: Social mechanism, phenomenon, and category created and developed by society. These are jointly constructed using shared assumptions about reality.
    • These do not strictly exists biologically (although are often linked).
    • Examples: Gender, race

How can you tell what is a social construction? There are examples of societies that have different social constructions or it is comprehensible that there exists a society with different social constructions.

How do we get these? Media, family, history, agriculture(!), etc.

Sociologists consider (our perception of) reality a social construction (i.e. social construction of reality theory) because we learn and comprehend a lot about reality via language and communication, which is a social construction. This is just a HOT way to say that you get biases from your culture/upbringing/society that you hold to be fundamental truths being constantly reaffirmed due to confirmation bias and self-fulfilling prophecies. (There is no reality! Hahaha.)

The concept of a shared social reality is said to be the commonly held social constructions in a group that helps form the basis of a society and hold them together.

### Examples

A poorer, more crime-heavy neighborhood gets randomly frisked and high levels of police surveillance. This neighborhood things police are a good thing. A richer, less crime-heavy neighborhood rarely gets bothered by police and only sees them when there is a severe issue. This neighborhood thinks police are a good thing.

We assume there are only two genders that are completely linked with sex. (Wait, I thought sex and gender are the same? Exactly! Sex is a physical thing; gender is a social thing.)

## Functionalism (Macro)

They are optimistic about inequality and believe it helps us.

The core assumption is that society is like a living organism. Each part has a function and purpose and society needs all parts to survive.

Belief that inequality/stratification is inevitable and functional for society because social inequality motivates people to fill different positions in society that are necessary.

  • Social Cohesion: Degree to which those in social system identify with it, feel bound to it, and are willing to cooperate in a society.
  • Social Facts: Social patterns external to individuals (e.g. customs).
  • Functions: Positive consequence of a structure. Help society.
    • Family: raise kids, provide micro support structure, help create and prolong society (values, language, etc.).
  • Dysfunctions: Negative consequence of a structure. Harm society.
    • Border Control: Can split families, harm innocent people (especially unfairly).

### People

  • Auguste Comte (1798–1857): French man. Pioneered "sociology" and "positivism".
  • Emile Durkheim (1858-1917): Jewish, French man. "[Functionalism]" and "[sui generis]" (society is greater than the sum of its part). Interested anti-Semitism unifying people.

## Conflict Theory (Macro)

They are pessimistic about inequality and believe it is inevitable and harms us. Basically, "If we could just solve inequality...".

This theory was brought around mostly because of capitalism and is focused mostly on the economy and capitalism. Focuses heavily on class struggle.

The belief that struggle over scare resources leads to inequality. Inequality leads to conflict and unequal power distribution, some dominating others.

Why wasn't Marx (and conflict theory) right?

  • It was, kinda.

  • Not just class/economics that separate people (e.g. racism).

  • Revolts are dangerous.

  • We have the "American Dream".

  • Globalization and technology is like WOAH. The online shopping, containerization, and the Internet has made a lot of the assumptions for a healthy market ABSURDLY more accurate.

  • Power: Ability to control others, events, and resources. General ability to make things happen.

  • (Social) Classes: Different groups of society, separated economically.

    • Capitalist (or Bourgeoisie): Rich large business owners. Oppressors.
    • Petty Bourgeoisie: Small business owners.
    • Proletariat (or Working Class): Workers. Oppressed.
    • Lumpenproletariat: Those discarded by capitalism (e.g. homeless).
  • Class Struggle: Capitalists driven to decrease wages of workers. Workers want high wages. This causes struggle.

  • Rationalization: Act of social structures becoming more direct and efficient.

    • Pros:
      • Fewer people need to work.
      • We have more stuff in less time.
      • Can have less human error.
    • Cons:
      • Fewer people have jobs.
      • Job displacement (altho only an issue in capitalism).
      • Stressful.
      • Environment can get hurt.
      • Less interaction with people.
      • People get comfortable being isolated.
    • Examples:
      • Consumers increasingly are doing more work (pumping gas, bagging groceries). "Consumer workers".

### People

  • Karl Marx (1818-1883):
    • Analyzed society economically.
  • Max Weber (Vay-Ber) (1864-1920):
    • Analyzed society and power with political, economic, and cultural (religious) dimensions.
    • Created "verstehen" (understanding social actions from those who do them).
    • Connected economy and religion, showing that protestant economies tend to be more successful (fluke?).
    • Created rationalization.

### Symbolic Interactionism (Micro)

Assumes that interaction and communication is extremely important.

Focuses on how people interact, the meaning of certain symbols/statements, and how those symbols/statements affect people.

## Dramaturgy (Instance of SCT)

Created by Goffman. Models social interaction as a drama/theater, with a front stage and a back stage. Where, during the front stage, we try to manage and manipulate others' impressions of us, while, during the back stage, we don't care.

  • Front Stage: When we're interacting with people.
  • Back Stage: When we're not interacting with other people.

This is similar to the looking glass self theory, where we always consider other people's impressions of you, which impacts your behavior.

# Socialization

  • Socialization: How an individual learns and accepts the way their society/group works. Lifelong process of learning the expectations, values, norms, and roles of a culture. How an individual learns their "place" in society.

Socialization is split into childhood / primary and adult socialization.

Primary socialization is how newborns and young children acquire language, identities, and culture (routines, norms, and values). This is chiefly responsible for transforming children into prepared adults (called anticipatory socialization). Parents and the family unit are responsible for this.

For the longest time, primary socialization was assumed to be one-direction, from parent to child. Recent research shows that this is two-directional. This is most easily seen by children of immigrants teaching and exposing their parents to the language and culture of their new home. Additionally with technology. This backflow is called reverse socialization.

Adult socialization occurs with peers (and also children). Generally, this is people slowly evolving in a changing society. The most common change is changing your "presentation of self". Adult socialization can also occur with resocialization, where people have to unlearn their old behaviors, norms, and culture and learn new ones. This occurs most in total institutions, which are closed off enclaves of culture (e.g. military and prison).

## Nature vs Nurture

Sociologists tend to believe nurture plays a very large role. They don't believe in "human nature" in general (i.e. women want to have children). They believe most human behavior is shaped strongly by socialization and the environment.

## Agents of Socialization

There are many things that socialize you. Here's a quick breakdown:

  • Family: Basic introduction into family and societal culture (i.e. tasks, rituals, beliefs, gender, social-class, etc.). There are noticeable class and racial differences.
  • Schools: Teachers have implicit biases and beliefs that their students are exposed to ("hidden curriculum"). Gender roles become more extreme here due to exposure to other people in the same age and the "hidden curriculum" (e.g. boys line up here, girls play with these toys, etc.).
  • Peers: Your peers beliefs amplify and affect your beliefs. Acting as an "echo chamber".
  • Media: Beliefs are spread widely and talked as though generally accepted.
  • Religion: Religions have their own culture, beliefs, and norms.

## Theories of Socialization

Here's a quick breakdown:

  • Psychoanalytic Theory:
    • Created by Sigmund Freud
    • Focuses on the unconscious.
    • Pretty wack, not really covered.
  • Social Learning Theory ("Role Modeling"):
    • Like "behaviorism" from sociology.
    • Says formation of identity is a learned both by modeling your actions and beliefs after others and by changing your beliefs and actions based on people's reactions to them.
    • Behavior exhibited by many people is more likely to be repeated.
    • Behavior that is positively reinforced is more likely to be repeated.
    • Sociologists use different terms from psychologists because ugh:
      • Positive Reinforcement: Good!
      • Negative Reinforcement: Bad!
  • Functionalism:
    • Socialization is how people are integrated into society and how society maintains stability.
    • Focus on social consensus and conformity.
  • Conflict Theory:
    • View socialization as a way to perpetuate the status quo.
    • People learn to accept the current system and their social status rather than challenge them.
  • Symbolic Interaction (SI) Theory:
    • Recall symbolic interaction theory focuses on the self and interactions between individuals.
    • Focuses on the concept of "self", which is socially built and reinforced.
    • There are many different SI theories.

### Symbolic Interaction (SI) Theories

  • Cooley's - The "Looking-Glass Self":
    • A lot like social learning theory. Explains that formation of self is a social process based on your interactions with other people.
    • The "looking-glass self" is our understanding of how other people perceive and judge us.
  • Mead's Theory of Socialization:
    • Argued that social roles are the basis of social interaction.
    • Argues identity emerged from the roles you play in the following stages:
      • Imitation Stage: Child copies the roles of others without understanding them.
        • Children cursing
      • Play Stage: Children take the roles of people in the environment, but only one at a time. Understand their roles relationships with other people.
        • Playing "House", "Cops and Robbers"
      • Game Stage: Children become capable of understanding and playing multiple roles. Children get a generalized other, which is the abstract composition of all your roles in every situation. Has two dimensions, the active, self-defining "I", the passive, defined "Me".

# Culture

Culture refers to

  • shared system of beliefs, knowledge, meanings, and symbols
  • shared forms of communication
  • set of values, beliefs, and practices

There are non-material parts of culture: norms, laws, customs, ideas, and beliefs. There are material parts of culture: money, technology, and houses.

Culture is learned, shared, common, and taken for granted.

Culture is made up of a few fundamental elements:

  • Values: Standards defining what is good, desirable, right, important, and vice versa.
  • Norms: Informal, unwritten rules that guide how people live. Sometimes combined with laws.
  • Laws: Codified rules that enforce how people live. Sometimes combined with norms.
  • Beliefs: Shared ideas believed collectively to be true.
  • Language: Actual, real language. Set of meaningful symbols allowing communication. Allows for the spreading and storage of culture.

## Norms

Norms are reinforced with sanctions, which can be either punishments, when norms are violated, or rewards, when norms are followed.

Mores are extremely important, heavily punished norms (tend to be laws). Folkways are unimportant norms that are not heavily punished.

## Different Culture within a Society

There can be many different cultures within a society! There is the dominant or mainstream culture, which is the culture of the most powerful group (also tends to be the largest). This mainstream culture tends to be considered the "most correct" or "most legitimate" that other subcultures do not have. Subcultures are any cultures within a society that are not the mainstream culture. They have to different from mainstream culture in some significant way, but they don't have to be totally incompatible. Any extreme, far-leaning political or religious groups can be categorized as subcultures. Some examples are Amish, LGTBQ+, and polyamorists. Counter-culture is similar to subculture except their culture tends to actively and vocally reject mainstream cultures and they can often impact/change mainstream culture. Examples include Alt-Right, Antifa, (old) LGBTQ+, and the civil rights movement.

In America, rich, politicians, and celebrities "define" the mainstream culture. This also tends to be white, upper-middle class culture in America.

## Analyzing Other Cultures

  • Ethnocentrism: Tendency to analyze other cultures using your own culture as a "normal standard".

  • Cultural Relativism: Belief that something can only be understood and judged in relation to the cultural context in which appears.

# Social Structure & Interaction

  • Society: A system of social interaction. Typically geographically based with interdependence among people.
  • Social Interaction: Behavior between people with a meaning. Helps form social bonds. Foundation of society.
  • Social Organization: Order established within social groups. A structured system/pattern of social relationships in a group of people. This makes society easier to understand.
    • Formal Social Organizations: Goal directed. Military, universities, hospitals.
    • Informal Social Organizations: Not goal directed. Friend groups, individual relationships, social groups.
  • Social Institution: Established, organized system of social behavior with a recognized purpose.
    • Great example of functionalism.
    • Examples: Family, education, religion, government, work, economy, sports, mass media.
  • Social Structure: Underlying pattern of interaction and social relationships. Can both enable and confine someone. Society is made up of social structures.
    • Examples: Social class (access to goods), economy, the government.
  • Status: Established position in social structure, carrying certain rank, value, and meaning.
    • Achieved Status: Attained through effort.
    • Ascribed Status: Assigned from the features of the person. Had from the moment of birth.
    • Master Status: The most dominant status that a person has. Generally overrides all other statuses.
  • Role: Behavior others expect from a person in a status.
    • Example: Police, students, professors, doctors, men, women.

People try to study society at two levels: macro and micro. Macro level studies an entire society, looking for large patterns, often simplifying certain things. Micro level focuses on individuals, analyzing patterns within a single person's life.

Why do we form a society? Well, there's a lot of reasons, but broadly we say it is necessary because of solidarity.

## (Durkheim's) Social Solidarity

  • Mechanical Solidarity:
    • Social cohesions from homogeneity of people.
    • Everyone plays similar roles (hunter-gatherer societies)
    • Social bonds based on common sentiments and morality.
    • Became less important as society grew.
    • I'm pretty sure this has never actually been important.
  • Organic Society
    • People specialize and play a variety of roles.
    • Unity is based on need of other people's specialties.
    • "Division of Labor"

## Interaction

Interaction occurs between a collection of interconnected social groups. In these groups, people communicate, have common goals/norms, and has a subject sense of "we".

Note: Categories, people with some common features, aren't necessarily social groups.

## Formal Organizations

There are broadly 3 categories

  • Normative Organizations: Voluntary organizations where people pursue goals they enjoy / find worthwhile.
    • Examples: service, civil rights, religious
  • Coercive Organizations: Largely involuntary organizations where people have a need to be there.
    • Examples: prison, hospital
  • Utilitarian Organization: Organizations people join for a specific purpose. They aren't intrinsically enjoyable.
    • Examples: companies, colleges

Often, social organizations become a bureaucracy, which is an example of rationalization. Bureaucracies organize individuals to be more efficient and are large and impersonal and large, but organize individuals.

### Ideal Type Bureaucracy

An ideal type bureaucracy is the ideal bureaucracy that satisfies the following; it would be the "most efficient" social organization/bureaucracy:

  • High degree of division of labor: Be more efficient.
  • Hierarchy of authority: Be more efficient.
  • Rules and regulations: Treat everyone equally.
  • Impersonal: Treat everyone equally.
  • Career ladders: Encourage people to work.
  • Efficiency: Be more efficient.

### Informal Structure of Bureaucracies

However, real bureaucracies are never ideal type because we're humans and we can't really be impersonal. This means bureaucracies have an informal structure, which are activities which violate/bypass the formal structure of the bureaucracy. For example, people preferring their friends or people from a certain group. This is what we call corruption.

### Problems with Bureaucracies

  • Ritualism: Excessive following of rules.
  • Alienation: When a person is mentally separated from the organization and its goals. People feel like they are just "cogs in a machine".
    • Issues: Increased turnover, tardiness, low satisfaction.
  • McDonaldization: Basically hyper-rationalization with a focus on the negative effects (e.g. impersonal structure).
    • As you could probably guess, this comes from McDonald's and the general fast food industry's philosophy being applied to other things.
    • Pros: Cheap, efficient, quick, consistent, wider range of goods to more people (cheap), people (normally) treated more equally, culture spreads easily.
    • Cons: Deskilling (workers are replaceable), impersonality, workers (normally) paid worse, consumer workers (e.g. self-checkout), worker burnout.
    • Main Dimensions:
      • Efficiency: Always do things the same, efficient way.
      • Calculability: Assess outcomes quantitatively.
      • Predictability: Encourage homogeneity.
      • Control: Replace human labor with more predictable things (e.g. machines) wherever possible.
    • Identified by Ritzer.

# Social Networks

  • Social Networks: The graph/network of relationships between people, where people are nodes and relationships are edges.
  • Social Capital: Resources available to people through their network.
    • "Embedded" in social networks.

Society is generally organized as a graph of "bubbles", where the bubbles have weak ties between then and strong ties within them.

  • Weak Ties: People you see / hang out with only occasionally. Very cheap.
  • Strong Ties: People you see / hang out with regularly. Very expensive.

For job searching, weak ties are more important because they are far more expansive and often have access to unique information and contacts.

## Network Exclusion

Often, particular groups of people are excluded, either intentionally or unintentionally. (This is called nepotism.) Why?

This can be due to intentional/explicit segregation or subconscious bias. However, most common is people in the network are similar, so they are more likely to have opportunities for networking (through people wanting to hang out). Additionally, if people don't already have a connection to a network, it is difficult to make those initial connections because no one knows you and you are likely to not have significant things in common, making it harder to make those connections and network.

Another difficulty is people don't always notice they're being excluded, so what can they do?

# Conformity

  • Conformity: When people do/think things they otherwise wouldn't because of group influences.

Generally, people conform to authority and group influences because they either want to fit in or feel less responsible for their actions because they are in a group. The responsibility issue is easiest seen with the Kitty Genovese case and the bystander effect.

Conformity can be both good and bad. We mostly talk about bad thought.

## Milgram Experiment

You should remember this from AP psychology. This is the experiment where the researcher commanded people to shock an individual. The people could "hear" the other person being shocked, but they couldn't see them (because they were recordings). The purpose of the experiment was to see how people will react/listen to authority. It was inspired by Nazi Germany.

85% of people gave the maximum voltage.

## Asch Conformity Experiment

There was a group of 5 people. Only one person (the final one) was an actual subject. They had to judge the length of lines. On certain questions, every confederate would give an incorrect answer vocally and then the subject answered vocally. Another variation was every confederate except one would give an incorrect answer vocally and then the subject answered vocally. Another variation was where every confederate gave an incorrect answer vocally and the subject answered on paper.

There were two main reasons people changed their answer: conflict avoidance or affecting their actual beliefs/views.

37% of the people gave the incorrect answer when every confederate gave the incorrect answer.

5% of the people gave the incorrect answer when every confederate gave the right answer but one gave the right answer.

## Kitty Genovese / Bystander Effect / Diffusion of Responsibility

You should remember Kitty Genovese from AP psychology. She was murdered and several people were aware of her being murder, but no one called the police. This was due to the bystander effect and also a fear of danger, from the murderer.

The bystander effect is the more people that witness an event, the less responsible each person feels. This means people are less likely to take action.

## Examples

  • Current American immigration camps
  • Me Too movement (both before and during)

# Inequality and Stratification

## Causes of Poverty

There are two main arguments for the cause of poverty: cultural and structural.

### Cultural

The culture of poverty argument or blaming the victim argument attributes the causes of poverty to the personal work values / irresponsibility of the poor. Broadly denounced.

### Structural

There are multiple parts, but broadly it attributes poverty to the forces in an economy and society. There are a 3 main parts.

  • Economic Restructuring: Recent changes in the economy have made things worse for working class.
    • Decline in manufacturing leads to worse jobs (e.g. service jobs)
    • Rise of globalization
  • Job Openings: Most newer jobs are low-paying.
  • Limited "Opportunity Structure": Not enough "good" or "appropriate" jobs for people.

## Stratification

Stratification is a fixed, hierarchical arrangement/ranking in society where people have different access to resources/power/perceived worth. Structured inequality. There are a variety of stratification systems:

  • Estate System: Feudalism, where people are bound to owners.
  • Caste System: Strict, hierarchical organization, where people are born into and bound to a specific caste for life.
  • Class System: Less-strict, hierarchical organization, where people can potentially change.

Social class is the social position of groups relative to the cultural, economic, and social resources. Essentially, a group of your life changes.

We cannot directly measure social class, instead we use some indicators:

  • Income
  • Occupational Prestige: How much do people respect your job
  • Educational Attainment
  • Sometimes also occupation and place of residence

Note: These do not strictly define class.

Status attainment is the process by which people gain a specific position in a stratification system. Socioeconomic status (SES) is commonly how we describe status, and it includes the above measures.

# Gender and Sexuality

  • Gender Socialization: Process by which people learn about the expectations and identities for your gender in society.
  • Femininities and Masculinities: Traits acquired during gender socialization.
    • It is plural because there are many different forms and traits within a society, based off ethnicity, age, social class, etc.
  • Homophobia: Negative attitudes towards non-straight people.
    • Homophobia is more prominent in men, as a way to discourage feminine traits in men.
  • Gender Identity: Person's definition or perception of themselves as a particular gender.
  • Transgender: People whose gender identity and/or gender presentation differs from the gender they were "assigned" at birth due to their sex.
    • May take hormones or surgery to change physical aspects of their physical sex.
    • Sometimes has different terms such as genderqueer, agender, and gender fluid.
    • Violence against transgender people is very high.
  • Intersex: Individuals who are born with both genitalia.
  • Sexual Identity: Internal sense of one's sexual self.
  • Sexual Orientation: Element of sexual identity referring to who you desire (fantasies), who you want to have sexual relations with (behaviors), and who you feel connected to (feeling).
    • We tend to simplify hugely. It's not a binary, but a spectrum.
  • Sexuality: Capacity to sexual feelings towards certain groups.
    • This tends to be organized as a continuum.
  • Asexuality: Lack of sexual attraction, desire, etc. Not just low sex drive.
    • Outside of the continuum.
  • Heterosexism/Heteronormativity: Belief that heterosexuality is superior to other sexual orientations.

In society, gender and sexuality are incredibly linked.

Recall that sociologists discuss the social construction of gender, where they draw a significant difference between sex and gender:

  • Sex: Biological male or female. Given by genetics.
    • Biological Determinism: Attributes gender differences to physical differences of the sexes.
  • Gender: Socially learned expectations, identities, and behaviors associated with each sex. A system of social practices that creates the gender categories.

## Theories of Gender

### Gender Performance

This theory is similar to the dramaturgy theory of social interaction applied to gender and sexuality.

This was created by West and Zimmerman in 1987 and onward.They argue that gender is interaction, a routine and standard of interaction which is shaped and evaluated by everyday interactions.

Basically, gender performance is about doing gender and receiving recognition of that gender. When you do gender, you reproduce the existing social order.

### Intersectionality

Intersectionality attempts to look at overlapping/intersecting social identities and how they create unique specific systems of oppression and discrimination. Essentially, you can't create overlapping buckets and expect the overlap to behave the same as the non-overlap.

This was coined by Kimberle Crenshaw in 1989.

The biggest example is analyzing the discrimination against women of color. You can get a more full analysis if you analyze the discrimination of women and the discrimination of people of color. Then, you synthesize this discrimination to understand discrimination against women of color.

### Hegemonic Masculinity

Hegemonic comes from hegemony.

This was created by R. W. Connell in 1995.

Hegemonic masculinity argues that there is a hegemonic masculinity that is the ideal vision of masculinity. This ideal vision of masculinity justifies the dominant position of men. Many men attempt to achieve hegemonic masculinity, but are disqualified for some reason. Men who cannot achieve this instead achieve subordinate masculinity. Examples of subordinate masculinity are gay men or men of color.

Hegemonic masculinity also argues that there is an emphasized femininity that is the ideal vision of femininity. It justifies the subordinate position of women. Likewise, women try to achieve emphasized femininity. Women who don't achieve these ideals are likewise seen as lesser than those who do.

Hegemonic masculinity says that, even if you have subordinate masculinity, you still benefit from it because of the subordination of women. It also argues that you can only analyze femininity and masculinity in relation to each other.

# Racial Inequality

Overall, race, ethnicity, and everything can be changed and are normally defined by the group in power. In other words, they are socially constructed.

  • Race: Distinct group in society based on some biological characteristics.
    • Almost entirely biological.
    • Examples: skin color, lip form, hair texture.
  • Ethnicity: Distinct, but not necessarily exclusive, group that is based on cultural similarities.
  • White: Light skinned people of European descent.
  • Whiteness: Construction of white race, white culture, and the system of privileges.
    • Early in America: White Anglo Saxon Protestants where white.
    • Now: Any western European (for the most part).
  • Prejudice: Beliefs about some group that is unlikely to change based on evidence.
    • Includes: racism, stereotyping, scapegoating
  • Discrimination: Actions which negatively impact some group. These are motivated by prejudices.

## Mass Incarceration

  • Mass Incarceration: Process by which people are placed in criminal justice system, branded as criminals and felons, locked up for extremely long periods of time, and then released and second-class citizens.
    • Began in the 1960s, when we changed from rehabilitation for drug addiction to punishment/imprisonment.
      • 1963-1993 incarceration rate increased independent of crime.
    • Marked by President Nixon's War on Drugs (1970s).
    • Disproportionately affects minorities (especially black) and men (with the intersection having it the worst).
  • Institutional Racism: Racism in the day-to-day operation of social institutions/structures, codified in the rules, policies, and practices of these institutions.
    • Basically, routine and unequal treatment.
    • Worse than individual racism because its widespread and better at prolonging itself.
    • Opioid Epidemic vs War on Drugs: The opioid epidemic is more focused on rehabilitation and affects whites more. The war on drugs was more focused on imprisonment and affected blacks more.
    • Education System: Black and Latino student bodies receive significantly less funding than whites.

Prisoners and felons become second-class citizens because they lose the right to vote, can no longer serve jury duty, and are legally discriminated against in employment and housing.

Mass incarceration is a race issue 1.5 million black men are "missing".

Michelle Alexander (2014) argues that mass incarceration is a system of racial and social control, which has ushered in the Negro problem of poverty. She argues prisons has been used a "solution" to this problem. She also argues that prison privatization has caused additional issues, where people profit off of imprisonment of people.

## Colorblind Racism

Bonilla-Silva (2009) attempted to explore the intent, methods, and analysis for current racial inequality. Basically, he argues that colorblindness is a new form of racism, where people ignore/fail to acknowledge real racial inequality. This causes people to not address the actual institutional racism. It also discounts the affect race has on people's lives.

This is often called the new Jim-Crow.

He split his analysis into four main causes for the modern racial inequality.

  • TODO

# Fighting Inequality

Why don't people resist inequality?

  • Current system is legitimized by certain ideologies. For example, equal opportunity.
  • People don't see realistic alternatives.
  • People don't realize that there is inequality.
  • People don't realize when they're causing inequality.
  • Even if you're resisting inequality successfully, it will take years to see any change.
  • People are depoliticized, meaning they feel powerless to change things and essentially give up or stop caring.
  • People derive benefits from the inequality.
  • Several people are still doing well with the status quo, so they are not motivated to change things. Middle class inertia.

# Family

## Divorce

  • Crude Divorce Rate: Relative to general population.
  • Refined Divorce Rate: Relative to unmarried women population.

Crude Divorce Rate

Refined Divorce Rate

Note: Several states stopped keeping track of marriage rates from 1998 to

As you can see, by in large divorce is more common than it used to be because of

  • Legality: No fault divorce laws make it so you don't have to prove a "breach of the marriage contract" (e.g. infidelity or abuse).
  • Societal Perspective: Divorce is not stigmatized.
  • Romantic Love Fades: People often marry when they're just in romantic love.
    • Companionate love is not tied to sexual passion and develops more gradually.
  • Rise of Individualism: People can feasibly live separately.
  • Feminism: Women are less economically dependent on men.
  • Stress of Marriages: Sharing finances is incredibly difficult, especially since women are more independent economically. Children exacerbate this because they're expensive.
    • Strongly impacted by the economy.

However, the divorce rate has decreased in recent years because of

  • Increased cohabitation before marriage, meaning people are more "experienced" by the time they marry in general.
  • People are waiting longer to get married in general, meaning they are more likely to find "the right person" or to be stuck.

# Work & the Economy

## Industrial Revolution

In the 1800s, the industrial revolution occurred. It has the following effects:

  • Skilled workers replaced by unskilled workers operating "skilled" machines.
  • Longer hours.
  • Lower pay because unskilled laborers.
  • Workers could be more easily replaced.
  • The rise of unions.

## Deindustrialization

Deindustrialization is the decline in manufacturing and the rise in service jobs. It was brought about by

  • Rise of Automation: Don't need unskilled workers at all anymore.
  • Globalization: More developed nations' workers had to compete with less developed nations' workers.
  • Rise of Consumerism: Cheaper goods led to higher demand.
  • Rise of Service Sector

## Dual Labor Market Theory

The market's jobs can be broadly split into two markets:

  • Primary Labor Market: High wage jobs with good benefits, good working conditions, opportunities for promotion, job protection, and due process.
    • More likely to be unionized and men and majority.
    • Examples: Engineering, law, medicine, executives.
  • Secondary Labor Market: Low wage jobs with poor benefits, high turnover, poor working conditions, and have little opportunity for advancement.
    • More likely to be women and minorities.
    • Examples: Service, retail, fast food jobs, grocery workers.

## Types of Capitalism

Capitalism is a fuzzy system that has a bunch of different effects and facets. Competitive capitalism is the ideal, but it leads to monopoly capitalism because the most competitive firm often purchases the less competitive firm or the less competitive firm goes out of business (and the less competitive firm's workers and customer often head to the more competitive firm).

  • Competitive Capitalism: Large number of small firms. No firm dominates.
  • Monopoly Capitalism: One or a few (oligopoly) huge cooperations dominate certain markets (can be one or many markets).

## Applications to the United States

C. Wright Mill' power elite theory says there there exists a power elite that controls a large amount of wealth, privilege, and political power. This power stretches across institutions: government, military, and economy. They are largely unified on their desire to maintain power, although they have some disagreements.

## Occupational Sex Segregation

This is a bit of gender and a bit of economy. Occupational sex segregation is where, in the same job, there are differences in how men and women are treated. There's a few explanations for this:

  • Neoclassical Explanation: Sex segregation in the workplace suggests men and women allocate different amount of effort between workplace and the household. Basically, says women put more effort into family.
    • Shown to not hold in recent years. It's not the "effort" but more the traits associated with the job (i.e. some jobs are "manly" and some are "womanly").
  • Women Sustain Disadvantage in the Workplace: Traditional ideologies are upheld in the workplace by employers ranking prospective employees on their potential productivity and their characteristics. Women are seen to be more likely to quit / be less productive because of children. Also, since most of these jobs are already male-dominated, the employers and current employees are more likely to highly rate men, since they are in their ingroup. This is an example of the old boys network.

One of the biggest effects of occupational sex segregation is in terms of pay and the gender wage gap. The pay gap comes from women generally being in lower paying jobs and women being paid less within the same job. Interestingly, previously female dominated jobs tend to be higher paid when they become male dominated.

This has led to the devaluation hypothesis which says that female dominated jobs are paid less because society devalues women's labor.

There's also the glass ceiling for women, which describes how women who enter male dominated fields tend to eventually hit a "ceiling" in their promotion, where they eventually are no longer promoted. There's also the glass escalator for men, which describes how men who enter female dominated fields tend to be more readily promoted into management.

Theres a concept of emotional labor, which is the management of your feelings and emotions for job. This puts a lot of stress on the individual and increases rate of depression and mental illness. Service and secondary labor market labor tends to be more emotional labor heavy. Women tend to have more service jobs, meaning they have a higher rate of depression and mental illness because of their jobs.

# Education

  • Meritocracy: System based on the ideology that all people have an equal chance of succeeding with hard work.
    • Requires people's background to be unrelated to mobility.
    • Idea: People succeed based off their own merit.
  • Tracking / Curriculum Differentiation: Separating students within schools according to some measure of ability.
    • Issues:
      • Lack of standardization.
      • Non-standardized tracking policies.
      • Race and class affect student placement.
      • Lack of mobility across tracks. (Working class students are often tracked into vocational education.)
      • Subjective / non-objective measures can be used (e.g. parents just asking).
    • This worsens educational inequality and segregation.
    • Basically, AG, AP, NCSSM, and the like.
  • Districting / Redlining: The process of explicitly or implicitly districting schools along race and income lines.
    • Worsens educational inequality especially by race and income.
  • Stereotype Threat: Individual has stress/fear of confirming negative stereotypes about their race / gender.

America strives to be a meritocracy. However, it is unequal with the following failures

  • Students with highest reading and math scores at end of high school are parents who have most education.
  • Asians and Whites are more likely than Blacks and Latinos to complete high school and attain higher education.
  • Women have better high school completion rates and are more likely to attain higher education.

## Coleman Report

James Coleman (1966) estimated how much schools differ in equality and found that achievement was most related to teacher quality, family background, and racial composition. He found that black children in integrated schools did better than those in non-integrated schools.

Coleman's report was against school redlining or segregation.

## Gender in Education

Women are more likely to be more educated. However, they receive less rewards. What gives?

  • Differential Reference Groups: Women compare themselves to other women, seeing that women can do well with high education.
  • Pollyanna Hypothesis: Women see gender inequality to be thing of past, so who gives a shit.
  • Social Powerlessness: Women go to college to get a rich man.
  • Sex-Role Socialization: Women tend to believe that their abilities are innate and unchangeable, but men tend to believe that can develop or improve their abilities with practice and effort. This
    • The evidence for this is that girls with higher IQ tend to give up more quickly than those with a low IQ.

# Lareau (2011) - Unequal Childhoods

In most cases of child care, social class trumps race, since race is something other people interpret while social class is something you feel.

## Parenting

You can sum up the difference in that broadly poor parents see their children as kids to provide for while rich parents see their children as growing adults to nurture. To use her terms:

  • Concerted Cultivation: The process by which middle class parents raise their children to interact with and question adults through many diverse, organized activities. Organized leisure activities controlled by parents to help a child develop.
  • Accomplishment of Natural Growth: The process by which poor parents raise their children by providing their necessities and making sure they are healthy and alive. Generally, they stay out of the child's social and emotional life; believing that it will unfold naturally.

Although this divide makes rich/middle-class parents sound strictly better, there are economic differences. Middle class parents don't have to worry about food, basic medicine, or how to keep your child healthy and alive as much.

Concerted cultivation tends to better prepare children for being adults but is more stressful.

Accomplishment of natural growth tends to lead to more relaxed children who are more capable of creating activities by themselves. The nature of poor parents also tends to make the children less trusting of and more apprehensive around authority.

This does cause issues though because schools encourage concerted cultivation, which causes dissonance or something for poor kids.

Our dominant set of cultural repertoires (or the way we think about something) for children tends to be that it is best to treat them like adults and to reason with them, but these change all the time. Rich parents also tend to change more quickly. Since rich parents adopt more quickly, they tend to be more in-line with the common body of education thought (i.e. schools). This gives the children and parents an advantage of being considered "better" by the school.

## Children

Rich children tend to have a sense of entitlement, where they believe that they deserve to manage their own time and have their opinions be heard. They tend to be better at expressing their wishes and manipulating adults to give them what they want. They tend to be worse about organizing their time and being considered subordinate to adults.

Poor children tend to have a sense of constrain, where they are unlikely to make special requests, tend to not resist authority figures (as much), and tend to disregard rules (e.g. encouraging/being proud of your kid "beating up" another kid).

Poor children tend to see their parents fail to change institutions / have them listen, while rich children tend to see their parents succeed.

# Rank (2011) - Rethinking American Poverty

Generally, America has viewed poverty as a personal failure. This means we broadly don't feel socially obligated to help them. This is seen by our lack of sympathy for working-age poor, but large(r) sympathy for old poor.

This refusal of reality allows us to reinforce our ideals: individualism and self-reliance, hard work pays off, and there are economic opportunities for all. This has also led to hyper-competitiveness, as people try to "improve" the system by just making everyone better. However, the real problem is lack of opportunity.

Additionally, things have been getting worse. Jobs are not as stable, health care benefits are worse, wages are stagnated, and many social welfare programs are being cut.

## Necessary Changes to Solve Poverty

  • Recognize that poverty indirectly affects everyone in society.
    • Poverty has a steep price (e.g. emergency room visits rather than yearly checkups, social programs, higher rate of doing crime)
    • Many Americans will experience poverty at some point (e.g. 66% on social welfare at some point, 60% in poverty for a year)
    • "Out of sight, out of mind" oftentimes with inner city or rural.
    • It's been getting worse.
  • Realize that the existence of poverty is a structural issue.
    • Caused by our economics and politics.
    • While there may be individual reasons for poverty (e.g. lack of education), these can also be structural issues. Also, this doesn't explain lack of opportunity in the first place. (That is, why do people have to lose?)
    • Economy has been producing more low-paying, part time, and no-benefits jobs.
      • 33% of jobs pay less than $11.50
    • Think of musical chairs analogy. Sure, the losers may have reasons for being slower (i.e. old or disabled), but why don't we have enough chairs?
  • Taking a more proactive approach towards preventing poverty, by viewing it as a moral injustice. This would prevent / make more abuses more difficult.
    • Examples of Abuses: burnout, pay cuts, reduction in benefits
    • In 1980, a CEO was paid 42 times that of an average worker. Now, it is 400 times.

## Stats

  • 50% of children will be on food stamps at some point in childhood.
  • Bottom 60% hold less than 1% of wealth.
  • 66% of counties where black children are growing up and considered high poverty.

# Rist (1970)

  • Goal: Understand how schools reproduce the class structure and divisions of society.
  • Methods: Longitudinal observational study. She started observing children in kindergarten. She went through to at least 2nd grade.

Her takeaways in kindergarten were that the teacher divided the class into three tables. Table 1, table 2, and table 3, with the following behaviors.

  • Table 1:
    • "Fast learners".
    • 0 smelled like urine.
    • More likely to be middle / upper class.
    • Had middle class cultural capital, like the teacher.
    • Learn directly from the teacher through her direct interactions with you.
    • Generally felt superior to table 2 and 3. Made fun of table 2 and 3.
  • Table 2:
    • "Slow learners".
    • 2 smelled like urine.
    • Learn through watching the teacher interact with table 1.
  • Table 3:
    • "Slow learners".
    • 5 smelled like urine.
    • Learn through watching the teacher interact with table 1.

For 1st and 2nd grade, the same division occurred, where students were unlikely to change their group. In 1st grade, these tables became tables A, B, and C respectively. In 2nd grade, these tables became the Tigers, Cardinals, and Clowns.

\ No newline at end of file diff --git a/notes/ncsu/2f/soc202/refined_divorce_rate.png b/notes/ncsu/2f/soc202/refined_divorce_rate.png new file mode 100644 index 0000000..a571e50 Binary files /dev/null and b/notes/ncsu/2f/soc202/refined_divorce_rate.png differ diff --git a/notes/ncsu/2f/st370/index.html b/notes/ncsu/2f/st370/index.html new file mode 100644 index 0000000..35675b1 --- /dev/null +++ b/notes/ncsu/2f/st370/index.html @@ -0,0 +1 @@ +Eli | ST 370: Probability & Statistics for Engineers

ST 370: Probability & Statistics for Engineers

Instructor: Dr. Paul Savariappan | Semester: Fall 2019

Scanned PDF.

\ No newline at end of file diff --git a/notes/ncsu/2s/csc236/index.html b/notes/ncsu/2s/csc236/index.html new file mode 100644 index 0000000..53971dd --- /dev/null +++ b/notes/ncsu/2s/csc236/index.html @@ -0,0 +1,252 @@ +Eli | CSC 236: Computer Architecture & Assembly

CSC 236: Computer Architecture & Assembly

Instructor: Dr. Vincent Freeh | Semester: Spring 2020

Table of Contents

# Views of System

There are two orthogonal views of a system, logical and physical. Logical is reasoning about function. Physical is reasoning about construction. This class attempts to analyze a computer using both. Logical view is also the architectural view.

# Number Systems

Computers, like us, use a positional number system. You already know this, so I won't go too deep into it, but basically to find the value v of some string of digits D in some radix r (or base), you do

v=diDdiri.

In this class, we will follow the math standard of postfixing a number with a subscript of the radix (or base) rather than the standard computer science prefix. For example, we write 1012 rather than 0b101.

## Unsigned Integers

Unsigned binary integers are pretty simple. All bits (or binary digits) are value digits.

We represent these without a + or .

### Overflows

What happens if we run out of bits after some operation? Well, we get an overflow! This means we lose the largest bit. Think about an odometer (or some other counter) rolling over.

Note: Most hardware detects overflows like this, but software doesn't always pay attention because not all platforms support it.

## Signed Integers

There are many representations for signed integers. The most common is two's complement, but there used to be a lot of diversity.

We represent these with a mandatory + or .

### Signed Magnitude

This was used by the Gemini program in NASA.

The MSB is the sign bit (0 is positive, 1 is negative), the rest is the magnitude. You choose the most significant bit normally because that gives the signed positive and unsigned numbers the same representation for most numbers.

0000 0111 == +7
+1000 0111 == -7
+

The rules for addition are:

  • If the signs are the sames, add the digits as if they were unsigned. The result has the sign of the operands.
  • If the magnitudes are different, subtract the digits of the smaller number from the digits of the larger number. The result has the sign of the larger number.
  • If the magnitudes are the same, the result is zero, either positive or negative.

Why isn't this used?

  • There is +0 (0000 0000) and 0 (1000 0000).
  • Arithmetic is complicated.

### One's Complement

This was used by the Apollo program, the PDP-1, and Univac 1100.

The MSB is the sign bit (0 is positive, 1 is negative). If the sign is negative, you invert the bits to get the positive version. This is really easy to do in hardware.

0000 0111 == +7
+1111 1000 == -7
+

The rules for addition are, to add the binary as if it was unsigned. Then you do an end around carry, where if you have a carry bit, you add one again.

 111
+  1110 # -1
++ 1110 # -1
+  ----
+  1100
+     1
+  ----
+  1101 # -2
+

Why is this good? Negation and addition is really quick and easy. The end around carry is simple in hardware.

Why isn't this used? It has a positive and negative zero, which have weird rules. End around carries aren't hard, but still something you have to consider.

### Two's Complement

This is used by almost all computers now.

The two's complement TC for a number with d bits is N+TC(N)=2d. We negate a number by taking the two's complement of it. In other words, we solve for TC(N) to get TC(N)=2dN. Solve for that in your done! Luckily, in hardware there is a very easy way to do this. You just flip the bits and add one. When looking at the binary as a person, you keep everything to the right of the first 1, including the 1, and flip everything to the left.

0000 0111 == +7
+1111 1001 == -7
+

The rules for addition are, just add the binary as if it was unsigned. That's it!

Two's Complement Wheel

Why is this used? It has the all the benefits of one's complement, but it only has a single 0. Nice!

How do you detect overflow? When summing numbers with like signs, the result should have the same sign. When summing numbers of different signs, they cannot overflow, since the magnitude is decreasing. In hardware, you just make sure the sign bit is the same as the carry-out bit.

# Multiplication and Division

Sadly, no one has found out a way to do signed and unsigned multiplication (and division) with the same instruction.

## Multiplication

Multiplication can get really big. x digits times y digits requires x+y digits. So, how do you multiply two words? It could give you a 32 bit back, in x86 we handle this by storing the result in a different place and potentially in two registers.

  • [i]mul byte: al * byte = ax
  • [i]mul word: ax * word = dx:ax

Note: mul is unsigned multiplication. imul is signed multiplication.

For performance reasons, we often to know whether we ended up needing more space than you were originally used (basically another digit). We store this information in the carry flag (CF), to tell you if the significant part of the solution outgrew your original data size. (CF=1 means it did outgrow. CF=0 means it did not.) This works because multiplication can never overflow.

Weirdly, you can't multiply by an immediate, only a register or memory value.

## Division

We often care about both the remainder and the quotient, so we store both the remainder and quotient.

  • [i]div byte: ax is the numerator, byte is the divisor. ah is the remainder, al the quotient.
  • [i]div word: dx:ax is the numerator, word is the divisor. dx is the remainder, ax the quotient.

Note: div is unsigned multiplication. idiv is signed multiplication.

Note: Status flags are not updated by divide.

If you want to convert a word into long / double word, you use the cwd instruction. This acts on ax.

You can get a divide overflow by not having enough space for the quotient. (You'll always have room for the remainder.) If you get a divide overflow (e.g. by dividing by zero or by dividing something large by something small), DOS interrupts your program and then terminates it. The way to get around this is normally either to check your division before you do it or to write an interrupt handler. You probably shouldn't do this.

We won't prove it here, but if the upper half of the digits of the denominator is less than that of the numerator, then the division will overflow. Otherwise, it won't. In other words, we want a large denominator to not overflow.

The sign of the quotient acts exactly like you think it would. For the remainder, you have to deal with negative remainders. Remember that the remainder is defined as quotient * divisor + remainder = value. For example, the remainder of 1/5 is 1 because the quotient would be 0.

# Computer Architecture

Modern computers follow the John von Neumann architecture, where there is memory, which holds instructions and data, and a processor, which executes instructions on data.

Note: Most of what a CPU has is actually a cache.

## Anatomy of Instructions

Instructions (and thus assembly) is made up of opcodes and operands. Opcodes define what operation you want to perform and operands define what data you are operating on.

Instructions are normally executed in a pipeline, where each step of the pipeline performs some different operation. Multiple instructions can be in the pipeline at once, allowing the CPU to execute "multiple things at once". However, sometimes the pipeline has "bubbles", where nothing is occupying that spot in the pipeline. This is due to conditional branching primarily. The hardware can get around this with speculative execution, where it takes a guess and either trashes the pipeline if it guessed wrong or executes as normal if it was right. (This isn't important for this class.) A standard, simple pipeline is fetch, decode, execute, and store.

Note: Modern Intel CPUs have complex instruction sets, but they have a "translator" that converts the instructions into CISC operations, which are actually executed.

There are two main "philosophies" on what instructions the hardware should provide and why.

### Complex Instruction Set Computer (CISC)

The hardware provides many functions natively, having many special instructions and many address modes. What was used primarily from the 1960s to 1990s. x86 is CISC.

Why is this no longer preferred? Instructions have variable size and variable execution time. This tends to make it slower and harder to decode.

### Reduced Instruction Set Computer (RISC)

The hardware provides few instructions natively, only having simple load and store from memory and the rest operating on registers.

Why is this now preferred? Instructions have fixed size and have fixed execution time. This makes it faster and easier to decode.

## Memory Technology

There are a bunch of different kinds of memory which are used at different times because of their different strengths and weaknesses.

  • SRAM (Static Ram): Fast, expensive, uses transistors. Used as part of CPU cache.
    • 6 transistors per bit.
    • Access Time: 5-10 ns.
    • ~$1000/GiB.
  • DRAM (Dynamic Ram): Slow, less expensive, capacitors. Used as part of main memory. Bunch of types.
    • 1 transistors and 1 capacitor per bit.
    • Access time: 50-150 ns.
    • ~$10/GiB.
    • Types:
      • EDO: Faster DRAM.
      • SDRAM: Synchronous DRAM.
      • DDR-SDRAM: Double Data Rate SDRAM.
      • RDRAM: Rambus DRAM.

There's also SCM (storage class memory), which is basically an SSD that is as fast as RAM.

## Anatomy of CPU

  • Registers: Data held within the CPU. Can be general purpose or contain CPU state.
    • Special Registers (x86):
      • Program Counter / Instruction Address Register (IAR): Address of next instruction. By default, it increments after every instruction.
  • Arithmetic Logic Unit (ALU): A chip containing circuits which do various operations, which the CPU can select.
    • Common Chips:
      • Add
      • Invert
      • Boolean Logic (AND, OR, etc.)
      • Multiply / Divide (less common)
  • Instruction Decode Unit (I Unit): Fetches opcode, updates IAR, finds effective address (locate data), sends control to E unit.
    • Address Mode: Instructions on how to determine effective address.
    • Effective Address: Actual location of data; provided by address mode.
  • Execution Unit (E Unit): Executes provided instruction.

## Memory Bus

The magic that makes the CPU and DRAM talk.

  • Address Bus (CPU -> Memory): Carries desired memory address from CPU to memory.
    • 64-bit computers "can" address 264 bytes, but most only implement 236.
  • Data Bus (CPU <-> Memory): Sends data to the CPU or to the memory, depending on read/write line.
  • Address Valid Line (CPU -> Memory): Must be set for memory to send data over data bus.
  • Read/Write Line (CPU -> Memory): Whether the CPU is writing to memory or the memory is sending to the CPU.
  • Clock Line (CPU -> Memory): Keeps CPU and memory in sync.

# History

DOS was less of an OS and more of a monitor. The processes it started had complete control of the computer. DOS would just ask you what you want.

## Software

There were three big players: IBM, Motorola, and Intel. IBM was the biggest and there were many others.

When the PC age came in, the biggest player IBM bought hardware from Intel and software from Microsoft. Why? It was far cheaper to do since IBM's hardware was focused on high-quality mainframes.

Motorola had a 16 bit 6800. They decided to make a huge redesign, the 68000, which was an extremely well designed 32 bit architecture. However, the software was incompatible.

Intel had a 16 bit 8080. They decided to make an incremental redesign, the 8086, which was a 32 bit architecture that could only support 20 bits of memory. However, the software was compatible. This ended up making it when. How did they make it work? They used memory segments / blocks to indirect the desired memory address from the actual physical address.

# Architecture Woes

Computers are complex things that grow and evolve over time. Here's a chronicle of some of disagreements and compromises that have been made throughout history.

## Memory Segments

Memory on the 8086 had 20 bit addresses. However, it only have 16 bit registers. To get around this, we added the concept of segments. Note: Memory segments were a hack to get around limitations.

Segments are 16 byte blocks of addresses, where each segment is a 16 bit number. We throw away the smallest 4 bits (or last hex digit). To get the actual address, you multiple the address of the segment by 16 (add a 0 to the right in hex) and add the offset.

# Data offset
+DS = 0x1234
+# Memory offset
+memory_address = 0x5678
+# Actual address
+DS + memory_address
+0x1234 * 0x10 + 0x5678
+0x12340 + 0x5678
+0x179b8
+

We have four different types of segments:

  • Data segment.
  • Code segment.
  • Stack segment.
  • Extra segment. (Exists only because we used 2 bits to address segments.)

Why is this bad? It's an extra thing we always have to do, which is slow. We didn't extend the amount of memory a process could have, so if you need that you need to determine what segment you want, where the segment you want is, and then load it in.

Note: This no longer exists anymore for the most part.

## Endianness

Endianness used to be incredibly important when we had 1 byte or otherwise small memory buses. It no longer matters as much, but we are still bound by the legacy decision.

Intel machines are little endian, meaning that the least significant byte is stored first in memory. The alternative is big endian, meaning the most significant byte is stored first in memory.

Why be little endian? When we get large values into the CPU from memory (i.e. more than one byte), the CPU expects the smallest byte first. To prevent jumping around, we store the bytes in memory such that we first see the smallest byte.

Note: This byte reversal only occurs in memory and not in the CPU.

# x86 Anatomy

## Registers

There are 4 general purpose registers in x86, and they are 16 bit (words). You can replace the x with an h to access only the upper half (more significant) half of the register; use l to use the lower half.

  • ax: Accumulator. Default for many operations.
  • bx: Base.
  • cx: Count.
  • dx: Data.

There are also a few special purpose registers in x86, also 16 bit registers.

  • SP: Stack pointer. Location of top of stack.
  • BP: Base pointer. Location of bottom of stack.
  • IP: Instruction pointer.
  • SI: Source index. For string operations.
  • DI: Destination index. For string operations.

## Status Flags / Condition Codes

All status flags give you status on the last operation performed. Except there are some that don't set the flags.

  • SF: Sign flag. 1 means negative. 0 means positive. This only looks at the most significant bit.
  • ZF: Zero flag. 1 means last operation was zero. 0 means last operation was not zero.
  • OF: Overflow flag. 1 means overflow. 0 means no overflow. It is set when the sign of the two incoming numbers are the same but the result is not.
    • Checks signed overflow.
  • CF: Carry flag. 1 means there was a carry. 0 means there was not.
    • Checks unsigned overflow.

# DOS Anatomy

DOS was written for the 8086, which could only address 1MiB of RAM. DOS further limits this to 640KiB for user programs, of this ~100KiB is used by DOS itself. The remaining 384KiB are reserved for the ROM, BIOS, and memory-mapped for IO.

The display happens to be assigned to addresses Bx xxx. To update the display, you just write to that part of memory and the hardware handles the rest.

# Assembly

Every line of assembly is like the following. You don't always have dest or source for an opcode. You can always have a label or comment, even if you don't have an opcode.

label:
+ opcode dest,source ;comment
+
  • label: An identifier that can be used for GOTOs (or other) later.
  • opcode Short, human-readable name for an instruction.
  • dest What the instruction operates on.
  • source What the instruction gets its data from.
  • comment A command. Completely ignored by assembler.

There are a few limitations / things you have to get right:

  • dest and source must be the same size.
  • You cannot have two memory references.

Note: In this class, every line needs a comment and you put block comments in front of sections.

You can also declare data in memory like the following.

varname (db|dw) value ; comment
+
  • varname: An identifier that can be used for later references.
    • Future references must be wrapped in square brackets (e.g. [varname]).
  • db: Declare data to be bytes.
  • dw: Declare data to be words (2 bytes).
  • value: An immediate value.

## Address Mode

The address mode describes how the machine should locate the value. Here's a list of ones:

  • Register Direct: Get value from address.
    • Can always be source and destination.
  • Immediate: Hard code a value into the binary and use that.
    • Can always be source but never destination.
  • Memory Direct: Get value from memory.
    • Can always be source and destination, unless memory direct is both source and destination.
  • List / Structure: You use a register (si, di, bx, or bp) to indirectly address some piece of memory.
    • Valid Combinations:
      • Base or index optionally with displacement.
      • Base and index optionally with displacement.
    • Default Segments: You can force the segment you want by prefixing the index with a certain segment register (i.e. cs:[si]).
      • Data Segment: si, di, bx.
      • Stack Segment: bp.

## Instructions / Opcodes

  • mov: Copies source into destination.
    • Cannot move immediate into segment register.
    • Cannot move between segment registers.
    • Does not set condition code.
  • add: dest += source.
  • sub: dest -= source.
    • Due to the way hardware implements subtraction (inverting and then adding), the carry flag "shouldn't" be set the way you expect. However, Intel engineers made it so it is set how you'd expect.
  • inc: Increments dest, without setting the carry flag. It doesn't set the carry flag because inc is most often used for iteration, so you may want to keep the carry information from a previous loop. It's also unlikely that you'll has signed overflow from incrementing.
  • cmp: dest - source, throwing away values but sets flags.
  • jmp: Unconditional jump to dest as an instruction address. This normally jumps to a label or an offset, which are things provided by the assembler.
    • Just slaps dest into the instruction pointer (IP).
  • Conditional Jumps: There a large collection of different opcodes that check all the different flags we have. To use them, you must first do some arithmetic (normally cmp) and then use the appropriate conditional jump. When the condition is true, they jump; otherwise, they fall through.
    • You can look on the class website (notes 6-16).
  • int: Triggers interrupt identified by dest. 21h is the dest for DOS syscalls. DOS looks for the syscall ID in ah and the arguments in al.
    • NOTE: All DOS syscalls may use ax register. This is actually the cause of the NT bug, which was when a bunch of assembly programs broke when NT started using the ax register for the write syscall and didn't previously.
  • loop: Decrement cx and jump if cx isn't zero. Preserves condition codes.
speed db ??? ; speed in mph (unsigned byte)
+
+; Go to trouble if speed is greather than 55mph
+cmp [speed],55 ; Check speed (speed - 55)
+ja trouble  ; ja because unsigned >
+

### Syscalls

DOS decided to make 21h be the interrupt for DOS syscalls. There are a bunch of syscalls, but all of them send/receive information via the al register and are identified in the ah register.

; Read character from stdin into al register
+mov ah,8
+int 21h
+; Write character to stdout
+mov ah,2
+mov al,'a'
+int 21h
+

## Immediates

The machine has no concept of negatives. Instead, it must be managed by the programmer.

Our assembly has no special marker for immediates. You just write a number. You can prepend the number with a - to mark it as two's complement negative. You can append the number with a h to mark it as hex.

If you have multiple immediates separated by commas, they become a list.

If you wrap a character with ', then it gets encoded to ASCII. If you wrap a string with ', then it gets encoded to ASCII as a list.

## Directives

Directives are commands to the assembler, not the machine. All directives in this class look like .name.

  • .model: What memory model for the assembler to use. For DOSBOX, we use .model small.
  • .8086: Only use 8086 instructions.
  • .stack: How many bytes for the stack segment to hold. For DOSBOX, we use .stack 256.
    • You could manually change the stack segment register, but that's more complicated.
  • .data: Marks start of data segment. This is where you can define the data as described earlier. Optional.
  • .code: Marks start of code segment. This is where you can define the instructions as described earlier. Technically optional, but why would you not want it?

## Casting

To down-cast numbers, you just throw away the bits. To up-cast unsigned numbers, you just put zeros in front. To up-cast signed numbers, you extend the sign bit.

The hardware doesn't provide a direct instruction for unsigned up-casting because is easy. Since signed up-casting is more difficult, there is an instruction to convert byte to word (cbw), but it only works on ax.

; Signed Up-Casting
+.data
+a db 255
+b db 1
+c dw 0
+.code
+ ; [c] = [a] + [b]
+ mov al, [a]
+ xor ah, ah
+ mov bl, [b]
+ xor bh, bh
+ add ax, bx
+ mov [c], ax
+
; Unsigned Up-Casting
+.data
+a db -1
+b db 2
+c dw 0
+.code
+ ; [c] = [a] + [b]
+ ; Cast [a] to word
+ mov al, [a]
+ cbw ; ax = FF FF
+ ; We shift [a] to bx since cbw only works on ax
+ mov bx, ax
+ ; Cast [b] to word
+ mov al, [b]
+ cbw
+ ; Add them
+ add ax, bx
+ mov [c], ax
+

## Basic Example

The first thing you do (normally) in your assembly program is set the data segment and sometimes the extra segment. The code segment and stack segment are set by the OS.

Identifiers that start with @ are "injected" into the code by the OS loader at load time.

Note: DOS makes 21h a syscall. The identifier for the desired syscall goes in ah and the return is in al.

.data
+a db 10
+b db 55
+c db 0
+
+.code
+start:
+  ; Set up the data segment (DS). We cannot move
+  ; immediates into segment registers per the
+  ; machine design.
+  mov ax, @data
+  mov ds, ax
+
+  ; C = A + B
+  mov al, [a]
+  add al, [b]
+  mov [c], al
+
+exit:
+  ; syscall: ah = service code: al = return code
+  ; 4c = terminate
+  ; 00 = 0 return code
+  mov ax, 4c00h
+  int 21h
+
+; Mark end of source code and give it address
+; of first instruction. This is not an
+; instruction, although it looks like it.
+end start
+

## Indirect Addressing

You can use the following registers as index/pointer registers. All others are invalid because of hardware limitations.

  • si: Source index. In data segment. Program data.
  • di: Destination index. In data segment. Program data.
  • bx: Base register. In data segment. Program data.
  • bp: Base pointer. In stack segment. Subroutine arguments.

Here's a quick example.

.data
+list dw ... ; Values to sum
+
+.code
+; let mut sum = 0;
+; for i in 0..9 { sum += list[i] }
+start:
+ ; set up data segment
+ mov ax, @data
+ mov ds, ax
+
+ xor ax, ax ; ax = 0
+ mov cx, 10 ; cx = 0
+ mov si, offset list  ; si = &list
+calc:
+ add ax, [si] ; ax += *si
+ add si, 2 ; si++ (because dw has a size of 2)
+ loop calc ; do { ... } while (--cx != 0)
+

You must be careful with how you compare indirect addresses with immediates (and anything else) because the assembler cannot tell whether you want to treat the indirect address as pointer to a byte or pointer to a word. (This ambiguity doesn't exist for using direct addresses with things of known size.) To get around this, you prefix the indexing with word ptr or byte ptr. This just tells the assembler what instruction to produce.

## Subroutines

Subroutines encompass procedures, functions, and methods.

Compilers has linkage conventions (or ABI), where they expect subroutines to be called in a certain way and to be set up in a certain way. You must write your subroutines or subroutine calls following these conventions if you want a high level language (HLL) to be able to call the subroutine or for you to be able to call a HLL's subroutines.

Why use subroutines? Subroutines are self-contained and reusable, which is great software development.

Why not use subroutines? Calling subroutines can be more expensive than just in-lining the subroutine and you have to develop conventions, which increases complexity. (Compilers can easily mitigate this.)

There's a few common protocols. They're mostly split up by different concerns that can be combined freely.

  • State Management:
    • Subroutine stores, the called subroutine saves and restores all registers it modifies except for its returns.
    • Caller stores, the caller of the subroutine saves all the registers it cares about and returns them.
    • Efficient but easy to mistake, the caller saves only the live registers that the subroutine modifies.
  • Parameter Passing:
    • Use registers, simple but limited.
    • Share global variables, incredibly hard to track. Do not use.
    • Pass on stack, highly recommended and used by most HLLs.

Since x86 is a CISC, it has a call and ret instructions. call pushes the next instruction's address onto the stack and jumps to the given label. ret pops a word word off of the stack and jumps to that as if it were the address of an instruction. (Normally you use call and then ret.)

Similarly, it has a push instruction which puts a value on the stack and updates the stack pointer (sp). You could do this manually, but it is slower.

### Multiple Files

As you know, programming everything in one file can get really annoying. However, when we have a subroutine defined in a separate file, how can the assembler find it when its assembling our file?

It can't! The trick is we have to say that the subroutine's label is external via extern <LABEL> in the main file and mark the labels as public <LABEL> in the subroutine file. When the assembler sees this, it will generate a symbol table and the linker will make sure that link all the object file's symbol table's together. If it can't find some symbols, it fails, but if it can find all the symbols then it properly links them all together.

; main.asm
+.model small
+.8086
+.stack 256
+
+extrn subroutine
+
+.data
+foo dw 8
+
+.code
+start:
+ mov ax, @data
+ mov ds, ax
+
+ mov cx, 10 ; Some personal data
+ mov ax, 6 ; Arguments
+ push cx ; Save cx
+ call subroutine
+ pop cx ; Recover cx
+
+exit:
+ mov ax, 4c00h
+ int 21h
+
+end start
+
; subroutine.asm
+.model small
+.8086
+; DON'T REDEFINE .stack
+
+public subroutine
+
+subroutine:
+ mov cx, 123 ; Trash cx
+ mov ax, 5 ; Return value
+ ret
+
+end ; NO START ROUTINE
+

### Putting Assembly and HLLs Together

To write assembly for a high level language (or a specific compiler), you have to conform to the language's API. This is because the compiler generates things in a certain way and the assembly needs to look like the compiler expects.

For C, subroutines are called by pushing arguments to the stack (in reverse order) and functions with name <name> become subroutines with name _<name> (i.e. they prefix the name with an underscore). Additionally, the callee is responsible for saving bp, si, di, ss, and ds while the caller is responsible for all others.

Why does C specify that you should push the arguments in reverse? It is because C functions can have variadic arguments.

For the subroutines to get the arguments off the stack, the subroutine has to look back into the stack. This is done by copying the stack pointer to the base pointer and looking up a known offset to the subroutine. If you're not pushing anything in your subroutine, you don't actually need to copy the stack pointer.

; int rc = asmprint('x', 5);
+main:
+  ; Push the arguments onto the stack. C does
+  ; this in the opposite order because it means
+  ; adding arguments
+  mov ax, 5
+  push ax
+  mov al, 120
+  push ax
+  ; Make the call
+  call _asmprint
+  ; Pop the arguments you pushed onto the stack
+  add sp, 4
+  ; Retrieve the return value, returned in ax
+  ; by convention
+  mov [rc], ax
+
+_asmprint:
+  push bp
+  mov bp, sp
+  ; 4 to skip the IP pushed by call
+  mov dl, [bp + 4]
+  ; 4 to skip the IP pushed by call
+  mov cx, [bp + 6]
+  mov ah, 2 ; Plan to read
+asmprint_loop:
+  int 21h
+  loop asmprint_loop
+
+  ; Set return value
+  mov ax, 0
+  pop bp
+  ; We'd have to pop stuff off the stack if we
+  ; had pushed
+  ret
+

Security Note: Whenever you make a call to a subroutine within a subroutine your arguments are visible to the subroutine.

Note: Since 64-bit Intel chips released 8 general purpose registers, C started passing arguments in these registers. It tried to put the first 6 arguments in the double word registers.

## Stack

On the 8086, the stack grows downwards and by units in words. The stack pointer (sp) points to the start of the stack, getting decremented by 2 whenever its pushed and incremented by 2 whenever its pushed.

If we want re-entrant code (i.e. the subroutine can be called as many times as you want concurrently), you aren't allowed to store any values explicitly in the data segment. (Imagine if you made a recursive call to a function that stores values in the data segment.) To get around this, you put local variables in the stack, at a certain offset down from the current stack frame (normally bp).

# Anatomy of Machine Code

Note: Use the table in the course notes for the test.

On the 8086, instructions are variable sized and can be 1 to 6 bytes. Here's the breakdown. Each block is a byte and the numbers within the bytes are bits. You don't need every byte for all instructions.

Anatomy of x86 Instruction

  • Code (1 byte): What is actually being executed. Always needed.
    • opcode: What to execute.
    • d: Data direction (0 = reg rc, 1 = reg dest).
    • w: Data size (0 = byte, 1 = word).
  • Addr (1 byte): Expands opcodes and describes operands. Needed for certain opcodes (see table).
    • mod: Mode.
    • reg: Register or special code.
    • r/m: Register/memory.
  • Disp (2 bytes): Memory offset for variables. Needed if you have a memory operand.
  • Data (2 bytes): Immediate data. Needed if you have an immediate operand. If you have byte immediate memory, only use the low byte.

Note: al is the byte accumulator. ax is the word accumulator.

# Boolean Algebra and Computer Hardware

There are certain bitwise operations that are atomic. That means that they can be used to construct every other operation (e.g. AND, OR, etc.), which can then be used to generate addition, subtraction, and everything! NAND is the standard atomic operation.

x86 has boolean instruction / bitwise operations:

  • not ax
  • and ax, bx
  • or ax, bx
  • xor ax, bx

x86 also has shifts, both left and right and both arithmetic and logical. Arithmetic fills in with the sign bit on the left. Logical always fills with zeros. Both of them shift the bit out into the carry. You should use arithmetic for signed numbers and logical for unsigned numbers.

  • shl ax: Shift logical left. Multiply by 2.
  • shr ax: Shift logical right. Divide by 2.
  • sal ax: Shift arithmetic left. (Actually same as logical left! Just clearer to people)
  • sar ax: Shift arithmetic right.

All shifts always round down, meaning sar -5 yields -3, because -5/2 is -2.5. This means constantly arithmetically shifting right a negative number will yield -1.

Similar to shifts are rotations. They are identical to shifts except that the bit shifted out is the same as the bit shifted in. The carry bits are still set the same. There is no arithmetic vs logical rotating. It's just rotating.

# ARM Assembly

ARM (Advanced RISC Machine) is designed and licensed by a British company ARM Holdings. They don't actually manufacture any chips, just design them and license out the designs.

ARM processors are widely in embedded contexts due to their low power usage. Because embedded systems can vary so widely, there are variants on ARM assembly designed to make certain tasks easier.

## General Design

ARM is a load and store machine. That is, all data processing is done in registers, so to manipulate memory variables you must load them into a register and then store them out once you're done.

All instructions are 32 bits in length and almost all instructions execute in a single cycle.

Instructions can be conditionally executed without jumps. That is, only perform this when this.

Instructions can optionally set the condition codes. It is up the developer / compiler to decide.

## Programming Model

Memory address space is 4 GiB (i.e. 32 bit address space) and there are three data sizes, listed below, that can both either be unsigned or signed two's complement. There are also 16 general purpose registers, 3 of which have special meaning (but can still be manipulated normally). There's an additional status register that stores the flag.

  • Data Sizes:
    • Byte: 8 bits.
    • Halfword: 16 bits.
    • Word: 32 bits.
  • Registers:
    • r0, ..., r12: General purpose.
    • r13 (SP): Stack pointer. (Same as in x86 terms.)
    • r14 (LR): Link register. Where the return address to a subroutine is stored. In x86 all return addresses are on the stack. In ARM return addresses can be put on the stack in software (and often are), but for the machine it has to be in LR.
    • r15 (PC): Program counter. (Instruction pointer in x86 terms.)
    • Status Register: Where execution flags are stored. Here's a brief listing. You can find more on the class website.
      • N: Sign. (0 = positive, 1 = negative)
      • Z: Zero. (0 = zero, 1 = not zero)
      • C: Carry.
        • On addition, this acts the same way as x86, where the carry flag is just the carry out of the addition.
        • On subtraction, this is the opposite of the x86. The borrow flag does not match real subtraction and instead matches the complementary addition.
      • V: Signed overflow. (0 = didn't occur, 1 = did occur)

## Instructions

### Load and Store

Loading and storing is done much differently than in x86, where it was just mov. Here's a list of some of the different operations. rd is the destination, rn is the first source, and rm is the second store. Almost every load has a corresponding store, except for loading constants of course.

Note: We only list ldr and str here. These operate on unsigned words. There are different versions of load and store with different suffixes that operate on halfwords, bytes, signed, etc.

  • Loads: Load a value into rd.
    • ldr rd, =var: Assigns address of variable.
    • ldr rd, =const: Assigns constant.
    • ldr rd, [rn]: Assigns value pointed to by rn.
    • ldr rd, [rn, rm]: Assigns value pointed to by rn + rm (sum of registers).
    • ldr rd, [rn, #n]: Assigns value pointed to by rn + #n (register with offset).
    • ldr rd, [rn], #n: Assigns value pointed to by rn and then post increment rn by #n. (Useful for iteration.)
  • Stores: Store the value of rd into something. The destination is the second operand.
    • str rd, [rn]: Store into memory pointed to by rn.
    • str rd, [rn, rm]: Store into memory pointed to by rn + rm (sum of registers).
    • str rd, [rn, #n]: Store into memory pointed to by rn + #n (register with offset).
    • str rd, [rn], #n: Store into memory pointed to by rn and then post increment rn by #n. (Useful for iteration.)

### Conditional Execution

In ARM, many instructions can be executed conditionally. To make an instruction conditionally executed in assembly, you must prefix your instruction's mnemonic with the conditional flag that you want.

; calc abs(r4)
+mov r0, #0 ; Set r0 to 0. Necessary to negate r4
+cmp r4, #0 ; Test value in r4
+submi r4, r0, r4 ; if neg, r4 = 0 - r4
+

You can look at the class notes to see what specific instructions can be executed conditionally and what the suffixes are for each condition code.

For instructions that can optionally set the condition codes (e.g. add, sub), you must suffix the instruction mnemonic with s if you want to update the condition codes. When you combine this suffix with conditional execution, you put the s after the conditional execution suffix.

Why would you want to do this? It improves performance for pipelined machines. In a pipelined machine, instruction execution is divided into stages where instructions are passed from stage to stage. This allows multiple instructions to be executing in parallel. In pipelined machines, conditional jumps cause "bubbles" in the pipeline, because you can't determine whether you should jump or not until that instruction has gone through the entire pipeline. This can be mitigated using speculative execution, but that still has a cost if you're wrong.

With conditional execution, there is no pipeline draining and much less pipeline "bubbles". Suppose we have a pipeline with 4 stages. If we did a conditional jump, we'd have a bubble of 4 instructions if we used a conditional jump. With conditional execution, we have a bubble of 1 instruction. (Well, really the instruction would just happen to be "wasted". We'd still work on it.) And we have no bubble at all if we actually execute the instruction.

Note: These pipeline bubbles occur when the machine starts the pipeline with something it didn't need and must subsequently "drain" the pipeline if it realizes it was wrong.

### Immediates

Immediates have some weird rules about them in ARM. Since all instructions are 32-bits and some bits are needed for the opcode, destination register, and other things, not all 32 bits of the instruction are available for immediates. In fact, only 12 bits are available.

To extend the range of immediates allowed, ARM splits up the space for immediates into 8 bits for the value and 4 bits the rotation amount. When accessing an immediate, the machine reads in the 8 bit value and then rotates it right (ROR) two times the rotation amount.

This means any 0-255 value can be generated with a rotation amount of 4. Any multiple of 4 less than 4255 can be generated using a rotation amount of F (i.e. 30), because rotating a 32 bit field 30 times right is equivalent to rotating left 2 times which is equivalent to multiplying by 4. These rules follow similarly for other rotation amounts. (It's kinda annoying to think about rotating right, so normally we just consider rotating left and convert the value.)

Why did they make it this complicated rule? It vastly extends the range of immediates allowed, means every immediate you want possible to create out of 2 immediates, is really easy to do in hardware, and assemblers and compilers had gotten sophisticated enough at the time of ARM to understand the rules.

Okay, well, how do assemblers handle this? If you do something like ldr r0, =999, the assembler will create a memory variable containing 999 and then convert that instruction into a load from memory. If you do something like add r2, r1, #999, you're just told you can't do that. Why doesn't the assembler handle this case? Because you need an additional instruction to handle this and if the assembler generated additional instructions from each machine instruction then it is no longer a one-to-one mapping, which is valuable for assembly.

### Subroutines

ARM provides several instructions for ergonomically dealing with subroutines. In general, storing the return address is called linking and jumping to different addresses is called branching.

  • bl label: Branch and link to label. Saves the next ip as lr and then sets pc to label.
    • Basically call from x86.
    • This can be conditionally executed.
  • stmdb sp!, {regs..., lr}: Store multiple decrement before use. The ! causes the stack pointer sp to be updated. It stores the registers in brackets on the stack and decrements the stack pointer before it is used.
    • Make sure that the link register lr is the return address.
  • ldmia sp!, {regs..., pc}: Loads multiple increment after use. The ! causes the stack pointer sp to be updated. It loads values off the stack into the registers in brackets and then increments the stack pointer after it is used.
    • Make sure that the program counter pc is the last address so we jump back to the link register.
main:
+  ldr r1, =n  ; r1 points to n
+  ldr r0, [r1]  ; r0 = n
+  bl sqrt  ; call subroutine
+
+sqrt:
+  stmdb sp!, {r1-r3, lr}  ; save r1-r3 and
+  ; link regiter
+
+  ; Trash the registers
+  ldr r1, =27
+  ldr r2, =11
+  ldr r3, =100
+  ; Load the hardcoded result
+  ldr r0, =25
+
+  ; restore r1-r3, load the pc with the original
+  ; link register
+  ldmia sp!, {r1-r3, pc}  ; 
+
+.data
+n: .word 625
+n: .word 0
+

### x86-like Instructions

These instructions have strong parallels to ones in x86, so we won't dedicate an entire section to each of them.

  • Move: Move is much more limited in ARM. It can only deal with registers and (limited) immediates. You'll generally don't want to use these because most assemblers only have the sophisticated immediate resolving for ldr. Also, you should rarely be copying registers around.
    • mov rd, rn: Copy rn into rd.
    • mov rd, #n: Move limited constant #n into rd.
  • Arithmetic: Unlike in x86, the destination doesn't need to be a source. In ARM, we can "save" the variables if we'd like.
    • add rd, rn, rm: rd = rn + rm.
    • add rd, rn, #n: rd = rn + #n.
    • sub rd, rn, rm: rd = rn - rm.
    • sub rd, rn, #n: rd = rn - #n.
    • cmp rd, rn: Calculates rd - rn and sets condition code.
    • cmp rd, #n: Calculates rd - #n and sets condition code.

## Data Format and Labels

Note: These are specifics of ARMSim syntax, but ARMSim syntax is closely related to other assembler's syntax (e.g. GNU Assembler), so this should be closely or direcly applicable.

In ARMSim, data declarations and label declarations both end in a colon. Here is some example data declarations

v1: .skip  4  ; Reserve 4 bytes
+v2: .word  1000  ; 32 bit word
+v3: .word  0x000003e8  ; hex
+v4: .hword 555  ; 16 bit half word
+v5: .byte  10  ; 8 bit byte
+v6: .byte  -10
+v7: .asciz "ABC"  ; Null-terminated ASCII string
+v8: .ascii "DEF"  ; ASCII string
+

Like in MASM, we can define immediate aliases (basically constant numbers) using the following syntax.

.equ SWI_Open, 0x66 ; Open syscall
+

Instead of using the .code directive to show that the instructions / program is starting, you use the .text directive, since code goes in the text section.

# Java Virtual Machine (JVM)

Somewhat surprisingly, people have written assemblers for the JVM, assembling your program to JVM bytecode. One example is Jasmin, although it is very old now. Why? It allows you to more easily test the security and capabilities of the JVM, since you don't have to the securities of the compiler.

Recall that Java was initially created for running on networked embedded devices (e.g. PDAs and VCRs). This is important for understanding the design of the JVM.

How do you execute JVM byte code? There are 4 main ways.

  • Interpreter: Reads the byte code and executes the corresponding machine code.
  • Naive JIT (Just-in-Time) Compiler: Whenever we call a method, compile it to machine code and execute.
  • Monitoring JIT Compiler: Start out interpreting monitor program activity. JIT compile the parts that are executed often or otherwise considered beneficial to compile.
  • Hardware: Some companies (e.g. AJILE) created hardware that actually targets JVM byte code as its machine code.

## Instruction Architecture

The JVM is a stack based architecture. That means only the push and pop operations actually have operands (their data) and everything else implicitly gets its data from popping things off the stack and pushing the results back onto the stack.

What is good about the JVM being a stack machine? It allows for compact instructions. It is agnostic to the registers of the machine. It allows for simpler interpreters.

What is bad about the JVM being a stack machine? It requires more instructions to do basic things. Some operations become more difficult.

The JVM uses variable length instructions.

The JVM is super-optimized for programs with 4 variables, optimized for 256 variables, and bad for up to 65536 variables. Why? The original purpose of Java was to be on embedded devices, which don't have programs with large amounts of data.

Wait, how do these optimizations work? Java stores all variables in a single local variable array, where variables are uniquely identified and referenced by an integer.

## The JVM and History of Caching

If you count what JVM instructions are normally executed, most are pushes and pops. In fact, there are far more pushes than pops because arithmetic operations have implicit 2 pops and 1 push that isn't counted. About 8% of instructions executed are branches/jumps (for variable checks and loops).

Looking at this information, it means a jump occurs about every 12 instructions (1/128), meaning most loops are about 12 instructions. This helped hardware designers know that caches are extremely beneficial because it means programs exhibit strong locality of reference, since programs that loop often execute the same instructions and work with contiguous arrays. This locality of reference means we can get cache hit rations of 90+%, meaning they are extremely valuable.

This should make sense to you as a programmer because most programs follow the pattern where they set up some data, loop for awhile, and then go on to another loop.

## JVM Calling Conventions

Since Java is a stack based architecture, we pass arguments to subroutines/functions on the stack is more difficult. This is because passing them on the stack would mean we can only load the arguments on top of the stack or we would have to pop them all off the stack and load them into local variables, which is inefficient.

To make this more efficient, the caller puts the arguments onto the stack and then the subroutine's local variables array is made to overlap with the arguments in the caller's stack, meaning the subroutine doesn't need to copy any of the arguments and instead gets them for free.

For returning variables, Java guarantees that functions will only return one thing and that it is on top of the stack.

# Microcode

On RISC machines, every instruction maps almost directly to an actual circuit. On CISC machines, many instructions map to a collection of hardwired instructions/circuits. The collection of hardwired instructions/circuits that makes up actual instructions is called microcode. Microcode is like the subroutines of CISC machine code.

Note: RISC designs are generally preferred over microcode currently because RISC instructions are easier to pipeline, avoids the overhead of microcode, and hardwired circuits can often achieve improved performance. Further, most programming is no longer done in assembly, so the ease of use of CISC ISAs is far less important. However, it still is important for implementations of CISC ISAs (e.g. x86) and is neat!

Why is microcode nice? It allows less complicated chips to implement more complicated instructions, that normally would only be possible on more expensive/complicated chips. Likewise, it allows machines to emulate other instruction sets. This capability was used by IBM in its S/360 compatible computer architecture.

Microcode can also enable performance improvements by rewriting code in microcode rather than machine code. How? The machine doesn't have to fetch or decode any machine code, since the microcode is stored in the CPU itself.

Why is microcode bad? Microcode is incredibly hard for a human to use and is incredibly powerful. Also, why bother have microcode when you could just have simpler machine code?

## x86 String Instructions

Text processing was at the time an extremely important use for computers (and still is to this day). Because of this Intel decided to make highly optimized machine code instructions for doing common string operations (compare, move, scan, load, and store). These instructions were written in hand-optimized microcode.

These operations were written generically enough that they also allowed numeric array manipulation.

# Interrupts and I/O

An interrupt is a signal to the CPU that allows it to asynchronous events. Every interrupt that triggers has a unique integer ID. The CPU contains (and the OS manages) an interrupt vector table, which maps from unique integer ID to a list of subroutines to call in response to the interrupt.

In general, a CPU handles an interrupt by preparing for a context switch (storing registers on stack) and then calls every interrupt handler in the interrupt vector table sequentially. When it is done, it goes back to where it was and restores its saved data.

Specific to the 8086, the CPU stores the flags, CS, and IP onto the stack. Then it loads the CS and IP and jumps to the loaded CS and IP, which then executes the interrupt handler. The interrupt handler then saves every register it modifiers, does what it needs to do, restores the registers, and calls iret (for interrupt return).

When an interrupt occurs, the CPU prepares for a context switch (by storing the registers onto the stack) and then goes to the interrupt vector table. It then calls the subroutine to handle the inter

Note: If an entry in the interrupt vector table is empty, then the interrupt triggers a "double fault", which is like the default interrupt handler and also the interrupt-within-an-interrupt handler.

## Security

In the early days of interrupts and interrupt handlers, there were several security vulnerabilities.

Interrupts allowed hackers to corrupt the operating system's code by modifying the stack to point in the middle of the operating system's code (arbitrary changes to SP and SI were allowed) and then trigger an interrupt causing the hardware to overwrite part of the operating system in memory. The operating system and hardware did have ways to stop the user from directly modifying the OS's code, but they had not thought to stop hardware interrupts from modifying it.

This security vulnerability was solved by having the OS have a safe stack space, which users couldn't modify. Hardware then used this safe stack space for context switching.

## I/O

There are there main ways to do input and output:

  • Programmer I/O (PIO): Very restrictive, byte oriented, hardly used anymore.
  • Memory Mapped I/O (MMIO): You reserve part of your address space to communicate with hardware devices. You then can read/write as if this were real memory, even though it is actually being mapped to another devices by the hardware.
    • Devices us a programmable interrupt adapter/controller, which pretends to be memory and triggers interrupts.
    • Example: VGA text buffer.
  • Direct Memory Access (DMA): High performance. Allows you to directly read and write memory on the device.
    • Used for things such as network cards and hard disks where performance is critical.

# Floating Point Numbers

The standard for representing floating point numbers in binary was originally set by IEEE 754-1985 in 1985. The most up to date version of the spec is IEEE 754-2008 from 2008.

Note: There are some complex rules around rounding and how to deal with infinity in the spec. For this class, we'll stick to the basic idea.

The standard specifies 3 precisions of floating point numbers.

  • Single precision: 32 bits.
  • Double precision: 64 bits.
  • Quadruple precision: 128 bits.

Every precision breaks the field into a sign, exponent, and significand as detailed below. Note: You always store the "normalized" form of the number, that is in ±n×10e, 1n<2.

  • Sign (1 bit)
  • Exponent: The exponent e in ±n×10e. This is stored biased so that you have to subtract the bias from the value to get the actual exponent e. (The bias is always half of the fields maximum value.) The maximum and minimum exponent is always reserved for special numbers (e.g. infinity).
    • Single Precision: 8 bits and 127 is the bias.
  • Significand: The fractional part of n. We only store the fractional part because we know that the bit before the decimal place will always be 1 because we store the normalized form of the number. (This is called the hidden bit.)

This has some pitfalls though!

We have a limited number of digits so we can have rounding error. In general, Single precision numbers can handle ~7-8 significant figures, with the exact precision depending on the number.

Since we are using binary fractional parts, not all seemingly simple fractions can be represented exactly. For example in binary 1/10 has infinitely many repeating digits. Of course π also has infinitely many repeating digits.

To handle the rounding error and imprecision that is associated with floating point, you establish a constant small value epsilon that represents an acceptable amount of error. Then, when you check for equality, you see if the difference between the numbers is less than epsilon.

Outside of the rounding errors, floating point number have some special numbers that use the reserved exponents.

  • ±0: Everything but sign bit is 0. Sign bit acts normally.
    • Because of the hidden bit, all zeros normally wouldn't actually be zero.
  • ±: Exponent is maxed and significand is 0. Sign bit acts normally.
  • NaN: Sign = 1, exponent is maxed, and significand is not zero.
    • All operations on NaN yield NaN.
    • Occurs when you do something invalid, like divide by zero.

Creating a NaN is an example of an exception, but there are others. Examples include overflow and underflow. However, these exceptions have default actions defined in the standard and it is common practice to accept the default action.

## Floating Pointer Coprocessor / Numeric Data Processor (NDP)

Historically, many computers did not have native floating point operations (instead emulating it in software) and those who did shelled out to a completely different chip in the system which would perform the operations. Nowadays, most consumer computers have the floating point coprocessor on the same chip as the main CPU, but it is still acts like a coprocessor.

Communication with the coprocessor is done via the floating point register stack. The top of the stack is called ST or stack top. The processor treats this as a pure stack, limiting you to the following operations.

  • fld dest: Load real. Push a real number onto the stack.
  • fst[bw] dest: Peek at the top of the stack.
  • fstp[bw] dest: Pop a real number off of the stack.
  • fadd: ST(1) + ST.
  • fsub: ST(1) - ST.
  • fmul: ST(1) * ST.
  • fdiv: ST(1) / ST.
  • fwait: Wait for NDP to complete store. Should be done after trying to read from the coprocessor.

The NDP has a status word, which provides information about its current state. Two of the bits, C3 and C0, show the comparison of ST(1) and ST.

  • ST(1) > ST: C3 = 0. C0 = 0.
  • ST(1) < ST: C3 = 0. C0 = 1.
  • ST(1) = ST: C3 = 1. C0 = 0.
  • ST(1) ? ST: C3 = 1. C0 = 1. This occurs when you cannot compare the numbers, for example of one of the numbers is NaN.

Neat! How do we use that? Well, if you move the high byte of the NDP status register into the low byte of the x86 status register, C3 corresponds to ZF and C0 corresponds to CF. This correspondence was done intentionally because then ja, jb, and je have their exact expected meaning.

# Computer Architecture Design

In general, shorter instructions are better (delivered faster and smaller binaries), fixed-length instructions are better (easier to decode), and instructions are all sized in full bytes (easier to address, no 12-bit instructions).

## Explicit vs Implicit Operands

One important decision is the number of explicit vs implicit operands an instruction has.

Consider four machines: M0 has no explicit operands, M1 has one, M2 has two, and M3 has three. Let's see how they calculate C = A + B.

M0 is normally called a stack machine. All operations push and pop things off the stack. Load/push and store/pop are the only exceptions and they have one operand.

push [A]
+push [B]
+add
+pop [C]
+

M1 is normally called accumulator machines because all loads load into the accumulator, all arithmetic uses the accumulator as a source and a destination, and all stores store the accumulator.

load [A]
+add [B]
+store [C]
+

M2 is (close to) what the 8086 is. Load and store have their two expected operands. All arithmetic uses one of the registers as both a source and destination.

mov [C], [A]
+add [C], [B]
+

M3 is (close to) what ARM is. You explicitly list all operands for all instructions.

add [C], [A], [B]
+

The 8086 is close to M2 because there are restrictions on what the operands can be (i.e. no memory to memory). ARM is close to M3 because there are restrictions on what the operands can be (i.e. only registers).

Let's pretend we have a machine with the following specs

  • Cycle Time: 1 us (1 MHz)
  • Memory Rate: 106 bytes/sec
  • Fetch Instruction: 1 us / byte
  • Decode Opcode: 1 us
  • Access Data: 1 us / operand
  • Execute: 2 us
  • Opcode: 1 byte
  • Operand: 2 bytes

This gives us the following table. Note: We leave off M0 because it requires memory addressing for some instructions but not others and thus complicates analysis.
PartM1M2M3
Fetch357
Decode111
Data123
Execute222
1 instr71013
C = A + B212013
instr / sec142,857100,00076,923

Notice something from this analysis. All machines have the exact same clock speed but execute different number of instructions per second. Further, the machine that executes instructions the fastest was the slowest to run our program while the machine that executes instructions the slowest was the fastest to run our program. Answering which machine is the fastest is extremely difficult and will depend on the program!

In general, to compare machines we need to know clock speed, instruction execution rate, capability of each instruction, and a specific task to perform (i.e. benchmark). Then, the time for the instruction is given by the following

time=instructionstaskcyclesinstrsecondscycle

Note: The benchmark must be fair (i.e. don't use benchmarks that are helped special capabilities) and accurate (i.e. be careful about the compiler being smarter than your synthetic benchmark by doing dead-code elimination, etc.).

## Caching

If we built RAM only using transistors (static RAM), it would be extremely efficient but extremely expensive. Instead we use much cheaper static RAM using transistors and capacitors. To get around the slow performance of dynamic RAM, we use a very small extremely efficient cache. Why does this work? Many programs exhibit locality of reference because of loops and most memory structures are nearby each other (e.g. arrays).

Note: Some page replacement algorithms exhibit Belady's Anomaly, where more cache reduces performance. Algorithms that don't exhibit this are called stack algorithms.

## Pipelining

Often instructions are executed in different independent stages (e.g. fetch, decode, execute). We can improve efficiency by always having an instruction in each of these stages. This is called pipelining.

In general, this is excellent for performance. However, it does have an issue with conditional branching. Namely, if you hit a branch you have to wait to execute the branch to find the next instruction. This is called having a bubble in the pipeline.

This can be mitigated using speculative execution, where you predict that the branch will / won't be executed. If you guess wrong, you have to drain the pipeline and it's just as bad as if you just waited. If you guessed right, then it's like you had no jump.

How do you predict whether or not you'll take the jump? You could use a global prediction from instructions executed. You could provide different instructions / a bit in the opcode that says whether this jump is likely to be taken or not and then have the compiler / programmer pick the appropriate one. You could dynamically keep track of whether that branch tends to be taken, but that incurs additional overhead and complexity.

This can also be mitigated by having hardware that can do the first few stages of the pipeline for the two different possible instructions, until you figure out which one you should have executed. That is, take both paths and clean it up afterwards. This is the best performance always, but it is also expensive.

This can also be mitigated by using a delayed branching architecture. That is, you say you will always execute the instruction immediately after a jump. This ensures that you will never drain the pipeline or guess incorrectly and thus improves performance. The key issue is that you need to find a instruction that will always be executed in both cases that you can insert into the delay slot. I personally am not convinced that this is better than just having "maybe yes" vs "maybe no" jumps, especially because it gets harder the longer your pipeline becomes since you get more and more delay slots. Some examples of programs that use this are MIPS and SPARC.

In general, longer pipelines tend to have a faster steady state (speed once pipeline is saturated) but slower latency (time it takes for pipeline to be saturated). They also tend to take longer to recover from bubbles in the pipeline. Since pipelines are drained reasonably regularly, latency is often important.

# Newer x86

Pentium processors and beyond are actually RISC machines that have a CISC frontend layered on top of them. Basically, they have a RISC microcode that actually does all the work. Then they have a CISC decode, that reads in the complex instructions and converts them into microcode that actually gets executed. Note: Some RISC-like instructions, such as adding two registers, are sent directly to the RISC core.

The Pentium did out-of-order instruction execution, more sophisticated speculative execution using dynamic branch prediction, and did superscalar execution.

Note: The Pentium 4 had a 20-stage pipeline, largely to allow it to pump up its clock rate, since that was (and still is) huge for marketing. This was the main motivation for Intel to have such complex and sophisticated branch prediction.

## Branch Prediction

The original Pentium 1's branch prediction algorithm was accurate on average 75% of the time. It's algorithm was the following pseudo-code.

# The 2 bit number is how many time's
+# we've seen the branch since we took it,
+# with 11 being the max.
+history = 2 bit history of jumps taken
+if branch not in history:
+  if branch goes forward:
+    don't take branch
+  else:
+    # It's probably a loop
+    take branch
+else:
+  if history[branch] != 11:
+    take branch
+  else:
+    don't take branch
+

This is clever because it allows us to be wrong once and still say we should jump again to properly handle nested loops.

## Reduced Operations

Every instruction is broken down into 1-4 reduced operations (ROPS), which specify with painful detail the steps required to perform the operation. If an instruction (e.g. a string instruction) cannot be broken down that far, it is passed to the microcode ROM.

These ROPS additionally have a speculative bit, that says whether the operation is being done speculatively, meaning you may have to trash your work. These ROPS are queued onto their appropriate unit (e.g. they need an integer ALU, floating point ALU, load store module, jxx module, etc.). Sometimes there's even multiple of these units for performance.

These ROPS have additional "scratch" registers which they can work with, which the programmer does not get access to.

Scheduling these ROPS on distinct units allows for out-of-order and parallel operation execution, which is what we want.

# Hardware Description Languages

Nowadays, most hardware is designed using a hardware description language, such as Verilog that produces the actual circuitry from the hardware description. This is advantageous because it means automated testing / verification of hardware correctness can be done and allows much easier and more rapid development of hardware.

Also, if the language is flexible / powerful enough, the programmer should lose little to no control over the design of the hardware and instead is empowered to make more powerful and complex designs.

\ No newline at end of file diff --git a/notes/ncsu/2s/csc236/machine_code_anatomy.png b/notes/ncsu/2s/csc236/machine_code_anatomy.png new file mode 100644 index 0000000..6eef135 Binary files /dev/null and b/notes/ncsu/2s/csc236/machine_code_anatomy.png differ diff --git a/notes/ncsu/2s/csc236/twos_complement.png b/notes/ncsu/2s/csc236/twos_complement.png new file mode 100644 index 0000000..50b4ddc Binary files /dev/null and b/notes/ncsu/2s/csc236/twos_complement.png differ diff --git a/notes/ncsu/2s/csc246/dynamic_linking.png b/notes/ncsu/2s/csc246/dynamic_linking.png new file mode 100644 index 0000000..b33e66f Binary files /dev/null and b/notes/ncsu/2s/csc246/dynamic_linking.png differ diff --git a/notes/ncsu/2s/csc246/dynamic_loading.png b/notes/ncsu/2s/csc246/dynamic_loading.png new file mode 100644 index 0000000..2cc5b10 Binary files /dev/null and b/notes/ncsu/2s/csc246/dynamic_loading.png differ diff --git a/notes/ncsu/2s/csc246/heirarchical_page_table.png b/notes/ncsu/2s/csc246/heirarchical_page_table.png new file mode 100644 index 0000000..9b9ddbc Binary files /dev/null and b/notes/ncsu/2s/csc246/heirarchical_page_table.png differ diff --git a/notes/ncsu/2s/csc246/index.html b/notes/ncsu/2s/csc246/index.html new file mode 100644 index 0000000..4d3d6f4 --- /dev/null +++ b/notes/ncsu/2s/csc246/index.html @@ -0,0 +1,267 @@ +Eli | CSC 246: Operating Systems

CSC 246: Operating Systems

Instructor: Dr. David Sturgil | Semester: Spring 2020

Table of Contents

# Terms

  • Operating System: Creates a layer of separation between hardware and application. A program that helps other programs run.
    • Virtualizes hardware, normally mandatory.
    • Provides system calls (syscalls).
  • Virtualization: Abstraction over underlying hardware, making it easier to use, share, and reason about. For example, UNIX's everything is a file abstraction.
  • System Calls: Requests the operating system to do something. This can be expensive (because of interrupts) and obtuse, so normally you call these through a library.

# Computer Architecture

In this class, we'll consider a simplified model of a computer because they're complex.

We also follow the Von Neumann architecture, which is the processor and memory model, where you put program in memory.

  • CPU: Processor executing your code.
  • CPU Cache: Tiny amount of incredibly fast memory your CPU uses. Amortizes cost of memory accesses.
    • Cache Hit: CPU finds what it wants in the cache.
    • Cache Miss: CPU does not find what it wants in the cache.
  • Memory: Volatile memory containing your working program and data.
  • Device Controllers: Control specific hardware, varies wildly depending on computer.
    • Includes persistent storage, such as disk controllers.

Simple Computer Architecture

## Storage Hierarchy

Sadly, we haven't found any storage device that is faster, cheaper, and larger than every other option. Because of this, we have to make engineering decisions to improve performance.

We usually do this by creating a storage hierarchy of memory going from small and fast to large and slow. We tend to use the smaller, faster memory cache to temporarily store data for the larger, slower memory backing store to try to get the best of both worlds.

## CPU Cache

Programs normally exhibit temporal locality, where they are likely to access things accessed recently, and spatial locality, where they are like to access things nearby things accessed recently.

Since we normally both read and write to the cache, the backing store may become out of date. To resolve this, we need a write-policy to keep them in step.

  • Write-through: The hardware automatically writes to the backing store (RAM) whenever the cache is written to.
  • Write-back: Whenever (a portion of) the cache is cleared / replaced, write it back to the backing store to get updates.

## Device Controllers

Here's a quick breakdown on how programs can access hardware.

  • System call: OS receives requests from application.
  • Command: OS makes requests to hardware.
  • Interrupts: OS is notified when hardware needs service.
  • Upcall: OS can notify application of events of interest.

Overview of Layers

### CPU to Device

Most device controllers have a few registers to communicate with the CPU.

  • Status registers: To check what it’s doing.
  • Data-in registers: To give it some data.
  • Data-out registers: To get some data back.
  • Control registers: To tell it what to do next.

That's cool and all, but how do you tell the CPU to use these? There's two main ways.

  • Port-Mapped I/O: Special CPU instructions for IO. Somewhat common on embedded systems with a set number of devices.
  • Memory-Mapped I/O: Computer hardware reserves a part of address space for devices. The CPU then accesses these as if they were just normal memory, but the hardware redirects the requests.

### Devices to CPU

There are a few ways for the device to tell the CPU about things, like completing a request or something.

  • Polling: The CPU must know to look at the status registers to check out the device. Can be inefficient if you're polling a ton.
  • Interrupts: Hardware supported system. The hardware fires off an interrupt and the CPU will automatically do jump to an interrupt handler.
    • Interrupt Handler: A subroutine that runs whenever an interrupt is fired. Can be arbitrarily long, but should be short to prevent latency spikes.
    • Interrupt Vector: List of addresses of subroutines to run when interrupt fires off.

Note: Interrupts are similar to CPU traps (exceptions) that occur whenever a bad instruction occurs, like divide-by-zero.

### Bulk IO

Some devices need to dump a lot of data into the computer. We normally do this using a direct memory access (DMA), which puts data from a device into the system's memory.

## Hardware Protection

### CPU

It can be dangerous to any program to run every operation provided by the hardware. Therefore, most hardware uses dual-mode operation where there are two modes:

  • Kernel Mode: Can access all instructions and all registers, privileged and unprivileged.
  • User Mode: Can only access unprivileged instructions and registers.

Note: Modern hardware often has more than just these two modes, but we won't talk about that here.

How do we switch modes? Normally, there are special instructions to switch to the appropriate mode. The kernel automatically switches back to user mode whenever it needs to, but how do you switch from user mode to kernel mode? The answer is system calls and interrupts.

Interrupts automatically switch to kernel mode at the start and switch to user mode (or whatever the old mode was) at the end.

System calls trigger a special trap on the CPU which goes into the appropriate system call.

How do we prevent user programs from preventing the OS to run? The normal solution is to have a timer interrupt, which fires at a countdown to allow the OS to take control of the CPU eventually.

### I/O & Device Controllers

If you use port-mapped IO, it's easy to do protection. Just make those special instructions privileged.

If you use memory-mapped IO, you have to use memory protection.

### Memory

Modern memory protection is very sophisticated. Here, we will use a simpler model that considers only a base register and a limit register. The base register stores the start of valid memory addresses. The limit register stores the size of the range. The hardware automatically checks these on all memory accesses.

Note: These registers are privileged registers, meaning only the kernel can change them.

Memory Protection

# OS Architecture

## Microkernel

Microkernels take the position that as little as possible should be put in the kernel / run in kernel mode. This means that parts of the OS that normally run in the kernel (e.g. device drivers and file systems) instead run in userspace as processes.

Why should we do this?

  • Easier to port to new machines (less code).
  • Less likely there will be bugs (less code).
  • Less code in kernel mode.
  • More extensible and modular. (Think about rclone mount and FUSE.)

Why shouldn't we do this?

  • Switching between kernel mode and user mode is expensive (interrupts).

## Monolithic Kernel

Monolithic kernels are the traditional design. It's where the kernel performs basically everything you'd expect an operating system to do.

Why should we do this?

  • It has higher performance because it switches less between kernel and user mode.
  • Kernels grow very naturally.
  • You can work around the disadvantages pretty easily (see next section).

Why shouldn't we do this?

  • Less extensible and modular.
  • Harder to port to new machines.

### Kernel Modules

A class of dynamically loadable parts of the kernel. These can be run in user mode or kernel mode once loaded.

There are often specific types or classes of kernel modules, in a object-oriented manner. Modules implement interfaces specified by these types and that allows the kernel to load them.

In Linux, these are .ko (kernel object) files.

## Boot Up

Operating systems can be huge. This means that they don't fit in a page of memory (basically a section of memory) and can't be trivially loaded by hardware. To mitigate this, we write small programs called bootloaders, which help load your operating system.

Here's a quick overview of the standard steps that occur whenever you turn on your computer. Different systems may have slight modifications, but the general process remains the same.

  1. Start running firmware at known address.
  2. Load bootloader from secondary storage.
  3. Bootloader copies kernel into memory ad begins execution.
  4. Kernel initializes necessary data structures (e.g. interrupt vectors).
  5. Kernel starts running init process (in user mode).

More modern computers can use EFI stubs, which (can) completely replace bootloaders. However, we won't cover that here.

# Inter-Process Communication (IPC)

There are many ways to do IPC. The two standard models involve either direct sharing of memory (or other hardware) or message passing, which is a fancy way to say copying memory or other things.

## Signals

The simplest is signals. They are mostly used to cancel, kill, or do something similar to the process. For example, CTRL-C sends SIGINT (interrupted), which tries to interrupt (and normally terminate) the process which received the signal.

This is hardly inter-process communication.

## Message Passing

This is easier to get right, but (theoretically) less performant.

Processes have independent mailboxes that can hold data. Other processes can copy messages / data into your mailbox by going through the operating system. Only you can read your mailbox. No other process can read or write to your mailbox.

There are two main ways to do this. Direct, where you send directly to a process, or indirect, where you send through a named communication channel (e.g. named pipes).

The kernel may temporarily copy data into its own memory while it waits to deliver. This is called buffering.

### Anonymous Pipes

  • #include <unistd.h>
  • pipe(int fds[2]): Create pipe with read end 0 and write end 1.
    • Use alphabetical order of read and write to remember the numbers. (Or just man pipe(3).)

Pipes are queues of bytes that don't respect message boundaries. You give it a 2-array of ints and it gives you two file descriptors, a read end 0 and write end 1.

Message boundaries? Basically, if you write 2 bytes, 5 bytes, and 3 bytes to a pipe, the other end will see just 10 bytes.

POSIX defines send and recv syscalls that can send and receive messages on pipes. However, you can also use read and write syscalls, and you'll normally want to.

You normally use pipes by calling pipe, forking, and then having one process close one end and the other process close the other end (to prevent the OS from mistakenly thinking that someone is still using the pipe). When all write ends of the pipe is closed, from the child exiting or manually closing the pipe, the read end of the pipe receives an EOF.

Note: If you max out the OS's buffer, the write syscall blocks.

### POSIX Message Queues

  • #include <mqueue.h>
  • mq_open(): Opens message queue. Give it a maximum message size and maximum number of messages to store.
  • mq_send(): Sends message across queue.
  • mq_receive(): Receives message from queue.
  • mq_close(): Stop using the message queue.
  • mq_unlink(): Destroys the message queue.

Message queues are named queues of bytes that respect message boundaries.

Message queues are identifiable by a unique name (starting with /) across completely separate processes on the machine. They have their own completely different syscalls, unlike files and pipes, i.e. you can't use read or write on them.

Message queues can live longer than the process that makes them and can exist without any process making them. To remove them, you must call mq_unlink to destroy the message queue.

If you want to create the message queue, but one already exists, you get an error through errno. If you want to hook up to an existing message queue, but one doesn't exist, you get an error through error through errno.

## Shared Memory

  • #include <sys/shm.h>
  • shmget() (Shared Memory Get): Create a shared memory identifier (int) for a section shared memory. This memory is automatically zeroed.
  • shmat() (Shared Memory Attach): Attach the shared memory to your address space, making it look like just another pointer. You can mark this memory as read-only (SHM_RDONLY), write-only, or read-write.
    • You can specify a memory address to attach to, but you probably shouldn't. shmdt() (Shared Memory Detach): Remove the shared memory at the given pointer from your address space, but don't delete the shared memory.
  • shmctl() (Shared Memory Control): Delete (or otherwise control) the shared memory given by the shared memory identifier (int).

This is hard to get right, but (theoretically) more performant.

There is a block of memory that both processes can read and write to. The operating system does very little control and trusts the programs to get it right.

This is accessed just like any other buffer because the OS maps the shared memory into your program's address space.

## Blocking

Whenever your program asks for something that the OS can't provide immediately, your process will block. (Assuming you're using a blocking system call.) When your process blocks, the OS puts your process into a waiting state, where it is not taking up (m)any resources. The OS will wake up your process when it gets what you asked for.

There are a few main blocking methods for IPC:

  • Blocking Receive.
  • Non-blocking Receive.
  • Blocking Send.
  • Non-blocking Send.
  • Rendezvous: Blocking send and receive, with no buffer.

### Buffering

Buffering is how we let non-blocking send work. The OS temporarily holds the data being shared while the receiver (ideally) catches up. This lets the sender not be slowed down.

### Busy Waiting

Busy waiting is when your program takes as much CPU time as it can to just wait for things. This is terrible. It's basically a poor man's blocking.

# Processes

There are a bunch of ways to handle parallelism / concurrency. We will cover processes right now.

Processes are separate programs identified by a PID (process identifier). They have separate, protected memory and (can) run on separate CPUs. Processes can only interfere with each other in controlled ways (e.g. shared memory, signals, pipes). Processes also have the concept of privilege, which we'll cover later.

## Syscalls

  • fork: Create a child process. Both the child and the parent run the same program with the same variables on the same line. On the parent fork returns the PID of the child. On the child, it returns 0.
  • wait: Wait for a child to terminate. If given a PID, it waits for that specific child. If not given a PID, it just waits for any one child.
    • Child termination forms a queue. Whenever you wait for a child, it pops that child off the queue, blocking if the queue is empty.

## Memory Layout

Processes has multiple sections of memory. They aren't really contiguous, but it's easy to visualize that way.

  • Text: Immutable data, can be shared.
  • Data: Mutable data, should not be shared.
  • Stack: Local variables, return addresses.
  • Heap: Dynamically allocated memory.

Memory Layout

## Process Organization

Process are normally organized into a process table, which is a list of all PCBs on the system. However, this is not very useful for scheduling.

To make scheduling more efficient, we keep scheduling queue(s), which is a list of PCBs for processes waiting. These queues are organized in various ways to make scheduling more efficient. Here's a few common ones.

  • Ready Queue: Ready to run.
  • Device Queue: Waiting on a specific device.

Process Queues

### Time Sharing

Whenever the OS does work, it may not switch back to the process that was previously running. The OS has a scheduler which it uses to determine what process to next run. They are incredibly complicated, so we will cover that later.

Switching between processes requires a context switch. A context switch is where the OS writes out all CPU registers (and other data) into memory and loads another process's saved data. It then executes the process whose data it just loaded.

This is great because it allows for processes to share! However, it is very expensive because processes keep track of a lot, for example:

  • PID.
  • Copies of program counter and other CPU registers.
  • Memory bounds.
  • Accounting information.
  • Resources in use (e.g. open files).
  • Pointers for linking PCBs into various lists.

Where does it store this info? The OS stores the info in a process control block, which is a block of memory that the OS sets aside for process information.

### Process State

This isn't related to the process control block we talked about earlier. Instead this deals with scheduling.

This state indicates how the OS should treat the process during scheduling. The specific design may be different, but this is the standard.

  • New: Created and can't be run yet.
  • Running: Executing instructions on a CPU.
  • Waiting: Process has requested I/O (or something else) and can't run until it's complete.
  • Ready: Process is runnable, but isn't on a CPU right now.
  • Terminated: Process has finished, still has a process ID, but isn't runnable.

Process Scheduling States

### Types of Processes

In terms of scheduling, it is useful to think about what the process spends most of its time doing. To help think about this we use a CPU-IO burst cycle, where programs switch between waiting on IO and using the CPU. CPU bound processes are programs that spend most of their time using the CPU. IO bound processes are programs that spend most of their time waiting for IO.

### Process Tree

POSIX organizes processes as a tree, where processes have a parent and a child. The root is called the init process and is what runs initially and forks off every other process.

There are many models on how parents and children operate. They can share everything or share nothing. POSIX is somewhere in between. The child can be can run the same program as the parent (POSIX fork) or run a completely different program (Windows CreateProcess).

Note: In POSIX, you use the exec* family of syscalls to replace the running process a different program. These system calls (if successful) never return.

What happens if the parent of a process dies? In POSIX the child keeps running normally, but the OS sends you a signal that your parent died. In other systems, there is cascading termination, where the the OS kills the child (and its children).

# Threads

Threads are like processes that are even more cooperative (but less so than coroutines). They share code, data, heap, and OS allocated resources (e.g. files). They have different CPU registers, positions in code, and stack.

Process Address Space Illustration

For performance reasons, we want to keep the per-thread state as little as possible to ensure that we can quickly switch between threads and start additional threads. In other words, we want to keep the thread control block tiny.

## POSIX Threads

  • #include <pthread.h>
  • pthread_create: Creates a new thread with a given start routine. This start routine is the lifetime of the program, like main. This can give the start routine some data.
  • pthread_join: Wait for the given thread to return / exit. This can return data by filling in a pointer.
  • pthread_exit: exit() but for a thread and returning abstract data.

A start routine returns a void * and accepts a single void *. This is used for input and output. Make sure that the argument and return have appropriate lifetimes. You should be very careful about giving/returning data between threads on the stack. In general, you'll want to heap allocate the argument and return.

## Java Threads

java.lang.Thread is how Java represents Threads. There are many different ways to tell Java what to run in the thread. You can subclass Thread and override its run method. Then when you start instances of this subclass, they run your run method. You can pass Thread itself a Runnable (either a subclass or a lambda expression). Then running that instance of Thread will run that Runnable.

Java's threads don't run immediately. Instead you must call start on them for them to start. You can then join on them.

You can also make a Thread a daemon, by calling setDaemon to it. This must be set before you start the thread. This makes it run in the background (and thus run the JVM in the background). Like a daemon!

Java does directly support arguments too threads or returning from threads. Instead, you must subclass Thread to add the arguments via a constructor and return the arguments by having attributes on the thread that you look at at the end.

## User-Level Threads / Coroutines / Green Threads

User-level threads are where you implement threading in userspace either by using a single thread / process or multiple without the kernel being aware that you are running multiple threads.

Using OS provided threads requires syscalls, which can be expensive. It's also not very portable because each OS tends to provide different interfaces. Because of this user-level threads can be quicker and more portable. Theoretically, user level threads can be even more cooperative too.

However, naive user-level threads have one huge issue: blocking. When a single one of your user-level threads makes a blocking syscall, the OS might block your entire thread, preventing all your other user-level threads to execute. There are many different ways to handle this. Go does this by creating a new blocking thread for each blocking syscall, so the kernel blocks that thread and not the one you were using.

## Thread Pools

A common way to get around the issues with context switching and the cost of creating threads is by creating a fixed size thread pool. You then split up your work not by threads but by units of work. Then the thread pool distributes the work among the finite number of threads.

## Thread Cancellation

How do you ask/tell a thread to die? If it dies at the wrong point, it might leave your data (which is shared by many threads) corrupted / inconsistent. There are two main ways.

  • Asynchronous Cancellation: Force a thread to right now.
  • Deferred Cancellation: Create cancellation points, where the thread checks whether it should still be running. Then the thread terminates gracefully.

## Contention

Threads can either run only within their process or run against other processes. Process contention scope is where the thread only competes for time against other threads within its process. System contention scope is the thread competes for time against all other processes on the system.

Note: pthreads let's us specify a thread's scope.

# CPU Scheduling

When does the CPU scheduler run? If your scheduler does the last two, it's called preemptive because it can forcefully interrupt a process.

  • Process terminates.
  • Process voluntarily yields the CPU.
  • Process blocks (syscall).
  • Another process finishes waiting (hardware interrupt). Preemption.
  • Process has had enough CPU time for now (timer interrupt). Preemption.

Once we pick a process, we need to do process dispatch via a dispatcher. This installs saved context, switches modes, and updates memory bounds. The time it takes to do this is called dispatch latency.

A CPU scheduler wants to min-max the following. However, notice that there is no globally optimal solutions for all cases. For example, minimizing response time requires more context switches, causing more context switches and decreased throughput.

  • CPU Utilization: How often is the CPU running a user process.
  • Throughput: How many processes (or CPU bursts) are finished per time unit.
  • Turnaround time: Time from when a job is submitted until its done.
    • Normally not great for benchmarking scheduler performance.
  • Waiting time: Time a process spend in the ready state.
  • Response time: Time from when a job becomes runnable to when it starts producing output.

Note: For measuring effectiveness, we normally measure waiting time, since that is due largely to the decisions of the scheduler.

## First-Come, First-Served (FCFS) Scheduling

This incredibly simple method of scheduling just runs processes in the order they arrive and runs them without preemption.

It is fast, taking constant time for inserting new processes and selecting new processes, and has reduced scheduling overhead by being non-preemptive.

FCFS schedulers exhibit the convoy effect, where you can have many processes that need short CPU bursts piled up behind a few that need a lot time.

## Shortest Job First (SJF) / Shortest Remaining Time First (SRTF) Scheduling

SJF/SRTF is a provably optimal scheduler in terms of waiting time (for non-preemptive and preemptive schedulers respectively). What SJF does is look at the jobs' burst time and schedule the job with the shortest burst time first. What SRTF does is look at the jobs' burst time and schedule the job with the smallest remaining time first; when a new job arrives, it interrupts the currently running one to put the one with the smallest remaining time back in.

They are virtually identical, but SJF is non-preemptive, which SRTF is preemptive.

Even though these are theoretically optimal for average waiting time, in practice they rely on us knowing (approximately) the running time of a process, which is unrealistic, and there's also a risk of starvation.

### Approximations of Running Time

There are several ways to estimate the time a CPU burst needs. Most of them involve statistical techniques using the process's previous CPU burst times.

One way is a simple average of your previous bursts. Another way is an exponential average of your previous bursts (weight the previous ones exponentially less).

The math for exponential average, where τ is the estimate burst time, b is the actual burst time, and α is some arbitrary constant (1 is more reactive, 0 is more smoothing)

τn+1=αb+(1α)τn

## Priority Scheduling

Priority scheduling gives every process a priority number. We then schedule things with a higher priority first. In pure priority scheduling (what we'll do in this class), we only look the priority of a process, ignoring time.

Priority scheduling is not inherently preemptive or non-preemptive.

Note: In this class, we consider smaller priority numbers to be higher priority to match POSIX.

In Linux, you can change the priority of your process by using the nice command. It ranges from -20 to 19, but regular users can't set negative priorities (which are higher).

## Round Robin (RR) Scheduling

Here, we chunk up time into time quantums (normally between 10-100ms) and then distribute these in a round-robin fashion. You maintain a ready queue of processes. Whenever you start a new time quantum, your program picks the first process of the ready queue. When you end a time quantum, the OS preempts the process, putting it on the back of the ready queue, and taking the next one off the queue. If your program blocks before its time quantum is done, the program just goes to the next time quantum early.

Why is this good? This bounds wait time to (n1)q. It makes CPU time very predictable, because you always get 1/n time, so it's like you processor is just n times lower. This means turnaround time is longer but response time is quicker.

How do you pick a good quantum? There's a trade-off between response time and overhead. The smaller your time quantum, the faster your response time but the more overhead (from context switches). The larger your time quantum, the slower your response time.

## Real-Time Scheduling

Real-time scheduling is when the scheduling of your program is a critical part of its correctness. As in, your operating system must guarantee that a process can run within say 5ms and let it run for say 10ms. Failure to do so would be a critical failure. These are called hard real time operating systems / schedulers.

Most general purpose operating system's do not meet hard real-time scheduling requirements, but they do try to meet soft real-time scheduling requirements, such as those required for multi-media programs. Soft real-time scheduling is where you're expected to respond quickly and keep vaguely in real time, but the value doesn't drop to zero if you fail to meet them.

This is done by designating processes as real time processes, giving them higher priority.

In Linux, regular users can't make their processes real time. However, to do this, you must use chrt.

## Multilevel Queue Scheduling

The idea of multilevel queue scheduling is that some categories of processes are more important. For example, batch jobs you want to run FCFS to minimize waiting time, but interactive jobs you want to run with RR to response time.

How do you determine which level queue a process should go in? You could have processes tell you, but processes can change and different OSes implement scheduling differently, so it's hard to do cross platform. We normally schedule this using feedback, where a process moves between the queues.

Feedback is based on aging or process behavior.

For example (aging), new processes may go into a RR queue with 8ms. Then going to 16ms RR queue. Then going to a FCFS queue. The idea is you bet that the process won't take much time, giving it a bit more time until it's done. This would give you a good balance of waiting time and response time.

## Multi-Processor CPU

Asymmetric multi-processing is where we treat specific cores differently. This is more common in heterogeneous multi-processor systems, where you have for example a specific core for sound processing. Symmetric multi-processing (SMP) is where we treat all cores equally. This is very common in homogeneous multi-processor systems.

Processes tend to run faster if they are repeatedly put on the same processor because of the cache. Soft processor affinity is where the OS tries to schedule processes on the same processors, but is willing to not. Hard processor affinity is where the OS mandates the processes are on the same processors; this is normally done via request.

## Linux Scheduler

Each CPU core has its own ready queue that it stores in a red-black tree sorted by virtual runtime. It is a work-stealing scheduler, meaning that a CPU can steal work from other cores if it runs out of work.

Virtual run time is the runtime of the program scaled by its niceness. Less nice processes get charged less for their time. More nice processes get charged more.

Per POSIX, Linux has 140 different priorities, with the first 100 for real-time processes.

# Synchronization

A race condition is when the correctness of your program depends on the order of execution of multiple threads/processes. This normally occurs because of non-atomic operations / memory getting changed unexpectedly, especially with shared memory.

Note: Having multiple threads read a piece of memory is okay. However, having one thread read/write a piece of memory and any other thread read (or write) that same memory is incorrect.

## Classic Synchronization Problems

There are a few standard problems that basically all computer scientists learn about.

### Bounded Buffer / Thread-safe Queue

A bounded buffer is a multi-producer, multi-consumer queue of elements. If you want to solve this just using semaphores, it would look something like this

sem emptyCount = BUFFER_SIZE;
+sem fullCount = 0;
+sem lock = 1;
+producer() {
+  while (true) {
+    Item it = makeSomething();
+    acquire(emptyCount); // emptyCount--
+    acquire(lock);
+    buffer[(first + num) % BUFFER_SIZE] = it;
+    num++;
+    release(lock);
+    release(fullCount); // fullCount++
+  }
+}
+consumer() {
+  while (true) {
+    acquire(fullCount); // fullCount--
+    acquire(lock);
+    Item it = buffer[first];
+    first = (first + 1) % BUFFER_SIZE;
+    num--;
+    release(lock);
+    release(emptyCount); // emptyCount++
+    consumeItem(it);
+  }
+}
+

### Dining Philosophers Problem

Imagine you have multiple philosophers sitting at a table. They each have a plate in front of them. Between each plate there is a single chopstick. All philosophers are sitting there thinking, looking up. Whenever they get hungry, they grab the chopstick on their left and then later on their right.

How do you prevent the Philosopher's from deadlocking? They deadlock when they all grab the chopstick on their left and thus no one can grab the on on their right.

Here's a quick list of the solutions, along with comments on them.

  • Keep an extra chopstick around: More resources aren't always available.
  • Only one at a time can eat: Horribly slow.
  • Only pick up a chopstick if you can get both: Might have starvation. Suppose the philosopher to your right starts eating and then the one to your left starts eating, alternating forever. You never get to eat.
  • Break the symmetry, make some pick left first and others right first: Works well and is reusable!

### Readers and Writers Problem

This issue is similar to the critical section problem solved with mutual exclusion. However, solving this problem allows for more concurrency.

Normally, it is safe for multiple threads to read concurrently. However, it is not safe for one thread to write while there is another thread looking/writing the memory. Formally, where nw is the number of writers and nr is the number of readers, it is safe if (nr=0 or nw=0) and nw1.

We now implement this using monitor pseudo-code. This implementation has an issue with starvation, where writers may starve because readers can get in if other people are reading but a writer cannot. We could fix it, but we don't here.

monitor ReadersWriters {
+  // Number of readers
+  int nr = 0;
+  // Number of writers
+  int nw = 0;
+
+  // Okay to read?
+  Condition readable;
+  // Okay to write?
+  Condition writable;
+
+  void lockReading() {
+    while (nw > 0) {
+      readable.wait();
+    }
+    nr++;
+    // Other readers waiting should know that
+    // it's safe to read. We do this because our
+    // pseudo-code doesn't use broadcast
+    readable.signal();
+  }
+  void unlockReading() {
+    nr--;
+    if (nr == 0) {
+      // Don't broadcast because we only want to
+      // wake up one writer.
+      writable.signal();
+    }
+  }
+
+  void lockWriting() {
+    while (nr > 0 || nw > 0) {
+      writable.wait();
+    }
+    nw++;
+  }
+  void unlockWriting() {
+    nw--;
+
+    // Wake a reader and a writer and let them
+    // race.
+    writable.signal();
+    // We don't have broadcast >:(
+    readable.signal();
+  }
+}
+

### Priority Inversion

Synchronization mechanisms can interfere with priority issues. Suppose you have some cheap low-priority job that acquires a lock. Then you have a medium-priority job that is very CPU intensive. Normally, the medium-priority job will run a lot more than the low priority job. However, suppose then a high-priority job comes along and tries to get the same lock the low-priority job got. Now the high-priority job is blocked by a low-priority job and will have to wait a long time!

How do we fix this? Normally, RTOS's (and possible normal OS's) will have the option for priority-inheritance, where the low-priority job will be promoted to the same level as the high-priority job while it is blocking that high-priority job.

## Synchronization Mechanisms

Most of the times with memory, you have a critical section problem, where you only have a single section (or a few) interacting with shared memory. To keep this memory safe from corruption, we put up guards around this critical section using various synchronization mechanisms (a.k.a. primitives).

Note: Ideally these critical sections are small and quick.

A good solution to the critical section problem should have the following properties:

  • Mutual Exclusion: We only want one thread in the critical section at a time.
  • Progress: Progress will always be made, you never wait forever.
  • Bounded Waiting: Can't starve a thread.

### Naive Synchronization

This example may look good, but it will allow multiple threads in if they both get past the while loop simultaneously and then set that they are inside.

bool inside[2] = {false, false};
+someThread0() {
+  while(true) {
+    while (inside[1]) {}
+    inside[0] = true;
+    // critical section
+    inside[0] = false;
+    // remainder section
+  }
+}
+someThread1() {
+  while(true) {
+    while (inside[0]) {}
+    inside[1] = true;
+    // critical section
+    inside[1] = false;
+    // remainder section
+  }
+}
+

This example solves the problem, but has the issue of deadlock, where they both say they want in and then wait for the other guy to finish.

bool wantIn[2] = {false, false};
+someThread0() {
+  while(true) {
+    wantIn[0] = true;
+    while (wantIn[1]) {}
+    // critical section
+    wantIn[0] = false;
+    // remainder section
+  }
+}
+someThread1() {
+  while(true) {
+    wantIn[1] = true;
+    while (wantIn[0]) {}
+    // critical section
+    wantIn[1] = false;
+    // remainder section
+  }
+}
+

We could try to resolve it by taking turns (strict alternation) and it works, but its generally a bad idea because its possible for the threads to not want to go through the critical section the same number of times and its also wasteful.

int turn = 0;
+someThread0() {
+  while(true) {
+    while (turn == 1) {}
+    // critical section
+    turn = 1;
+    // remainder section
+  }
+}
+someThread1() {
+  while(true) {
+    while (turn == 0) {}
+    // critical section
+    turn = 0;
+    // remainder section
+  }
+}
+

### Peterson's Algorithm

Combining strict alternation with wantIn. Essentially, it says "I want in, but I'll let you go first if its your turn." Most of the time turn isn't even looked at.

int turn = 0;
+someThread0() {
+  while(true) {
+    wantIn[0] = true;
+    turn = 1; // no, after you
+    while (wantIn[1] && turn == 1) {}
+    // critical section
+    wantIn[0] = false;
+    // remainder section
+  }
+}
+someThread1() {
+  while(true) {
+    wantIn[1] = true;
+    turn = 0; // no, after you
+    while (wantIn[0] && turn == 0) {}
+    // critical section
+    wantIn[1] = false;
+    // remainder section
+  }
+}
+

Note: This may not actually work anymore, since modern processors do not guarantee that memory writes occur in the same order appeared. This is because of performance. Because of this, we have various synchronization primitives.

### Counting Semaphores

Counting semaphores are conceptually counts of the number of threads that can be in the critical section at once. They can be naively implemented the following. However, most of the time semaphores are implemented by the OS and are much more efficient (e.g. they don't busy wait).

acquire(sem s) {
+  while (s <= 0) {}
+  s--;
+}
+release(sem s) {
+  s++;
+}
+

Here's how a semaphore would apply to our previous problem.

sem s = 1;
+someThread0() {
+  while(true) {
+    acquire(s);
+    // critical section
+    release(s);
+    // remainder section
+  }
+}
+someThread1() {
+  while(true) {
+    acquire(s);
+    // critical section
+    release(s);
+    // remainder section
+  }
+}
+

Note: In this class, we'll say you can't start semaphores at negative values. It varies across libraries.

### Binary Semaphore / Mutex

Binary semaphores and mutexes are similar and perform basically the exact same operation. Instead of having a count that gets decremented and incremented by acquire and release, you just have a boolean flag that either locks or unlocks.

They cover the most common pattern of using a counting semaphore, where you just want to have a single thread in a critical section.

### Atomic Operations / Spinlocks

Modern processors provide atomic operations and most libraries provider ways to access these ergonomically. Atomic operations are operations that will always run together and never have any instruction go in-between them and interfere / change things.

Most atomic operations have the mnemonic of test and set, where you do some check and then conditionally change the value.

Atomic operations can be used to implement spin-locks. Spin-locks are essentially good busy waiting, using atomic operations and normally yield after spinning for a bit.

## Monitors

Note: Monitors with condition variables are provably equivalent to semaphores.

Monitors are easy ways to wrap functions in locks. They ensure that anyone that wants to call this function first acquires the appropriate lock and releases it when they're done.

This prevents us from waiting within a monitor. For example, for the bounded buffer problem, we try to add things through the monitor and no one else has called it. How do we show we should also block?

The trick is condition variables. Condition variables are basically events that we can either signal as happening or wait to happen. When you wait on a condition variable, you give up your lock on the monitor and go into a queue of people waiting on that condition variable / event.

Note: Signaling on a condition variable where no one is waiting has no effect.

There are two different policies for how signaling works.

  • Signal and Wait: Whenever you signal, you wait for the thread you signaled to start and finish.
  • Signal and Continue: Whenever you signal, you continue running until you're done with the monitor. The one you woke up gets to run once you're done.
    • Most common!

We use C/Java like syntax for monitors.

monitor Maximizer {
+  // In some languages hasValC and hasVal might
+  // be able to be in the same
+  condition hasValC;
+  bool hasVal = false;
+
+  int largest;
+  void submitValue(int val) {
+    while (!hasVal || val > largest) {
+      largest = val;
+    }
+    // this only wakes a single thread / waiter
+    hasValC.signal();
+    hasVal = true;
+  }
+  int getLargest() {
+    if (!hasVal) {
+      hasValC.wait();
+      // tell anyone else waiting to wake up
+      hasValC.signal();
+    }
+    return largest;
+  }
+}
+
// Synchronized stack
+monitor IntStack {
+  condition nonEmpty;
+  Stack<Integer> stack = new Stack<>();
+  int popInt() {
+    // Must be while because suppose you have
+    // three threads A, B, C. B is waiting for
+    // something to be pushed. A just pushed
+    // something. Then C came in and popped
+    // after A pushed, without blocking. B then,
+    // having been woke up by A, wakes up and
+    // would try to pop from an empty stack
+    // (because C stole its element) if there
+    // was not a while loop.
+    while (stack.size() <= 0) {
+      nonEmpty.wait();
+    }
+    return stack.pop();
+  }
+  void pushInt(int v) {
+    stack.push(v);
+    nonEmpty.signal();
+  }
+}
+

## APIs

### semaphore.h

semaphore.h is the POSIX semaphore library. It doesn't work on Mac sadly, although they do compile, so that's cool. There are both named semaphores sem_open (return sem_t *) and anonymous semaphores sem_init (return sem_t). You must provide them initial values.

  • Type: sem_t.
  • Acquire: sem_wait.
  • Release: sem_post.

### pthread.h

Monitors are not primitives, but you can implement them via structs and functions.

  • Monitor: C has no monitor primitives. Instead you use mutexes.
    • Initialize: pthread_mutex_init(pthread_mutex_t *) or PTHREAD_MUTEX_INITIALIZE.
    • Enter Monitor: pthread_mutext_lock(pthread_mutext_t *).
    • Leave Monitor: pthread_mutext_unlock(pthread_mutext_t *).
  • Condition Variables: Luckily, condition variables are primitives, but they aren't restricted. This uses signal and continue semantics.
    • Initialize: pthread_cond_init(pthread_cond_t *) or PTHREAD_COND_INITIALIZE.
    • Wait: pthread_cond_wait(pthread_cond_t *, pthread_mutex_t *).
    • Signal: pthread_cond_signal(pthread_cond_t *).
    • Signal Everyone: pthread_cond_broadcast(pthread_cond_t *).

### Java's synchronized Keyword

In Java, every object can be used as a lock and any method can be a lock. The threads waiting for a lock on synchronized method is called the entry set and the JVM does not guarantee any order. The threads waiting for an object is called the wait set and the JVM does not guarantee any order.

Note: Even if you treat an object as a lock, other people may not. You should thus prefer using synchronized methods over using synchronized blocks on an individual object instance.

  • Monitor: You just put synchronized in a method's declaration and automatically you acquire the lock before you enter and automatically release the lock before you exit.
    • All synchronized methods on an object exclude each other. Meaning if you have synchronized a() and synchronized b(), you can't call both a and b at the same time.
  • Condition Variables: You call the appropriate methods on any Object. This uses signal and continue semantics.
    • Wait: this.wait(). This gives up the lock on this. This is why you don't want to create other objects just to wait on them, otherwise you wouldn't give up the lock on this.
    • Signal: this.notify(). Just moves someone from the wait set and into the entry set.
    • Signal Everyone: this.notifyAll(). Moves everyone from the wait set and into the entry set. This is more useful, since Java doesn't give us arbitrarily many condition variables. You just use while loops normally.

# Deadlock

A deadlock is a synchronization issue where you are prevented from making process. Formally, deadlock is when you have a set S of processes where every process in S is waiting to acquire a resource where the desired resource is held by another process in S.

We can help ourselves understand the issue using a resource allocation graph, where you use circles for processes and blocks for resources containing dots for an instance of that resource. Request edges are directed arrows from processes to resource blocks show desire (but not ownership) for instance. Assignment edges are directed arrows from resource dots to processes shows ownership.

Processes with request edges are generally blocked by the OS and the OS assigns resources to processes.

There are a few main ways of dealing with deadlock:

  • Prevent: Design for no deadlock.
  • Detect: Watch for deadlocks and do something to recover from deadlocks.
  • Avoid: Regulate process behavior so that they never reach deadlock, even though they theoretically good.
    • Think moves ahead in the game.
  • Ignore: Just hope for the best and let users deal with it! :)
    • What most OSes use! This is to avoid unnecessary overhead.

## Deadlock Prevention

There are four necessary conditions for a deadlock to occur. If you don't have all of these, you can't have a deadlock.

  • Mutual Exclusion: Some resources can only be used by one process at a time.
  • Hold and Wait: Processes can have some resources and ask for more.
  • No Preemption: OS gets a resource back only when a process is done with it.
  • Circular Wait: It's possible to build a cycle of processes.

Which condition can we prevent/remove?

  • Mutual Exclusion: The operating system generally doesn't use mutual exclusion of most resources. However, this isn't universally possible (e.g. for mutexes), so mutual exclusion is impractical to remove.
  • Hold and Wait: We could mandate that every process must request all resources at startup. However, this yields reduced resource utilization and possible starvation (because processes wait on things they hardly need or on things that others hardly need), so it is not very practical globally.
    • Remember the "you must pick up both chopsticks at once" for the dining philosophers problem.
  • Preemption: This actually isn't too bad and is done all over the place (e.g. in the CPU, in memory). The issue is that we have to remember the state where you left, but this isn't always possible because otherwise you might reach an invalid state or waste time.
  • Circular Wait: This is the most practical way to implement deadlock prevention. You do this by imposing a total ordering on all resource types, meaning you must ask for a lower number resource before you ask for a higher number resource. You can do this within your own processes, but it isn't always practical for the OS for the same reason as hold and wait.
    • This let's you choose the priority of the resource!

## Deadlock Detection

Unlike deadlock prevention, this does not prevent limit the ability of programs or limit resource utilization (until deadlock).

The pseudo-code for detecting deadlock is as follows:

While there's some process P where all of P's
+outstanding requests can be satisfied:
+  Remove all request and assignment edges for P
+  (to pretent P finishes without asking for
+  more).
+If any processes remain:
+  You have a deadlock.
+  Find cycle(s); the processes among them are
+  responsible for the deadlock.
+

Now, how do we resolve the deadlock? We have to kill a process. We could kill a resource hog, which frees up a bunch of resources, but potentially wastes a bunch of time; it also means that resource hogs tend to starve. We could kill the youngest process, which means we waste less energy.

Why don't OSes use this? It involves forcible killing of a process, meaning we wasted a bunch of time by killing an unfinished process. Also, this normally causes garbage-collector type pauses on our entire system, which isn't great.

## Deadlock Avoidance

Note: This is mostly safe state detection.

If done right, this doesn't limit the ability of programs, prevents deadlocks entirely, and can only somewhat limit resource utilization.

Often, this requires us to know the future (i.e. what the processes might request). Practically this is done by having the OS mandate that all processes stake claims on certain resources, meaning they may want to acquire them sometime in the future. If a process doesn't have a claim on a resource, it can't get an instance of it. Claims are denoted with dashed arrows on the resource allocation graph. Note: Claims are often denoted with a certain multiplicity.

This requires us define safe states and unsafe states. Safe states are where it is impossible to reach deadlock. Unsafe states are where it is possible to reach deadlock.

When now run a safe state detector whenever a request for a resource is made. This detector ensures that granting the resource keeps us in a safe state. The algorithm for the detector is called the banker's algorithm. It goes like this

  • Pretend like you granted the resource.
  • Turn all claim edges into request edges.
  • Run the deadlock detection algorithm.

# Memory

We will think about memory as a linearly addressable array of words (smallest addressable unit). Recall memory protection!

For simplicity in this class, we pretend as though memory is split into two sections: one for the resident operating system and the other for user programs. We will also pretend as that memory is allocated contiguously we with a base (start of memory) and limit (end of memory) registers.

We want our programs to not be dependent on where specifically they are loaded. How do we do this? We do this with specific address bindings. Address bindings describe how we choose the physical memory space the program will run in. There are a few main ways:

  • Compile Time: The compiler chooses the address when it builds. That is, the compiler generates absolute code.
  • Load Time: The memory address is set when the program starts running. That is, the compiler generates relocatable code.
  • Execution Time: The OS determines where the addresses should be as it starts executing.

## Linking

Linking is the process of taking relocatable code and putting it in a single location and hooking up all libraries. There are two main ways to do this: static linking and dynamic linking.

Static linking is essentially where the linker essentially copies and pastes all the relevant code into the final binary. This is simpler, but does result in larger executable binaries. It also doesn't allow for updates without recompiling your project.

Static Linking

Dynamic linking is essentially where the linker sets up symlinks to all the relevant code into the final binary. This is more complicated but results in smaller executable binaries and allows for updates without recompiling. Note: This doesn't necessarily save space in memory once they're loaded unless you can share copies in memory (especially if you only use the base and limit registers are we are assuming). This can leave you in "DLL hell", where your code suddenly breaks because of silent/undeclared incompatibilities or where you can't tell what version of the library you're getting.

This can be more sophisticated using stubs. Stubs are small little pretend functions that actually properly link whenever they are first called.

Dynamic Linking

## Loading

Loading is where you actually load the library into memory (instead of just putting it into the binary). There are two ways to do this again: static loading and dynamic loading.

Static loading is the most common. When the OS loads your program, it loads your entire program into memory including your libraries.

Dynamic loading is like dynamic linking for loading. In dynamic loading, your stubs not only link to the proper library when they are run but they also actually load/locate the library in memory when it is executed. Likewise, you have dynamically unload libraries when they are used. This can reduce your program's memory footprint significantly, especially if you use some large library only in one place of your program or only occasionally in your program. It can additionally reduce start up time by not loading all of your libraries at first.

Dynamic Loading

## Swapping

Swapping is the process of move your main memory into your backing store (normally disk). You may want to do this if your computer is running out of memory to run all of its processes.

When the OS detects that it will run out of memory, it will take a stopped process and move all of its memory to the backing store. Then, when that process wants to start, it swaps that memory back into main memory, potentially swapping something else to the backing store.

The biggest cost to swapping is transfer time, or the amount of time it takes to copy as process control block (PCB) to/from main memory.

Note: Modern OSes don't always do this for one complete process at a time.

Swapping

## Making Room for Memory

Maintaining memory is difficult, we need to

  • Maintain allocated regions,
  • Maintain unallocated regions,
  • Reclaim unused regions,
  • Efficiently allocate memory to minimize holes, and
  • Be quick.

Note: Maintaining memory is almost impossible for compile-time binding because those programs need to be loaded into an exact location. Load-time binding is much easier because they can fit anywhere as long as its contiguous.

There's a few main methods of figuring out what unused section / hole to allocate memory n words in. They each have strengths and weaknesses.

  • First-Fit: Walk down the list and chose the first hole that's as large as n.
  • Best-Fit: Find the smallest hole that's as large as n.
  • Next-Fit: ADS
    • Maintains good cache locality.
  • Worst-Fit: Find the largest hole.
    • This is good for storing holes in a heap.

As memory is allocated, we get small gaps in the memory between processes, too small to be useful. This is called external fragmentation. If you use first-fit memory allocation, on average about 50% of the memory you give out will be lost to external fragmentation.

Sometimes when processes ask for memory, you may give them more memory than they need. This is because it may be cheaper/simpler to not keep up with the little extra bit of unused memory. This is called internal fragmentation.

What if we have several allocated blocks that are not very tightly packed and we want to make them tightly packed? You can perform compaction by moving them without the process noticing. You have to be very careful with this because all pointers and memory addresses will become invalidated. To resolve this, you need execution time address binding, often with hardware support.

Hardware support? Yes! Instead of the process itself keeping actual addresses, they can keep addresses relative to some base/relocation register. Whenever the process uses an address, it is transparently mapped to an actual address by adding the value of the base/relocation register (or something more complex). Then the OS just needs to copy the memory and update the relocation register. This requires...

  • Logical/Virtual Addresses: What the user program thinks it runs on.
  • Physical Addresses: What address the memory is really at, meaningful to hardware.
  • Address Translation: Runtime conversion from logical to physical address (using relocation register).

Address translation is supported by the memory-management unit (MMU) and normally only applies in user-mode.

## Paged Memory

Our base and limit registers which we've been dealing with up until now have been fairly limited. Let's level them up using paged memory. This is a more sophisticated way of handling address translation. Paged memory isn't contiguous and is instead broken into multiple fixed-size blocks called pages. Process memory is split up into a sequence of pages physical memory is split into a sequence of page-sized frames.

Why differentiate between a page and a frame? Frames are empty places where you "hang" pages.

Paged Memory

Why do this? This virtually eliminates external fragmentation by having hardware make fragmentation "normal".

Pages are organized into frames using a page table. The page table stores frames indexed by page. Whenever the CPU wants to read memory, it looks up the frame using the index of the page and translates uses that to translate the virtual/logical address into a physical address.

Each process has its own page table and it is used by the CPU in user mode.

Here is the algorithm for doing paged memory address translation. Note: For performance reasons, the page size is (almost) always a power of two. That way we just translate the high order bits using a table lookup and keep the low order bits, instead of doing arithmetic.

class Process:
+    def __init__(self, page_size, page_table):
+        self.page_size = page_size
+        self.page_table = page_table
+
+    def translate_address(self, addr):
+        page_number = addr // self.page_size
+        frame = self.page_table[page_number]
+        offset = addr % self.page_size
+        return frame * self.page_size + offset
+

Logical Addresses

### Page Tables

How do we implement and store page tables? How big should they be? How do we tell the hardware where to look for the page table?

Currently, most page sizes are about 4 KiB. Modern hardware can support larger page tables, but this was common for 32 bit systems. That means, you'd have 12 bits for the addresses within a page and 20 bits for the page number. This means you'd have about 1 million entries in the page table, where each entry is at least 20 bits. Since 20 bits is a weird number, we normally give each entry 4 bytes (32 bits) because that makes it much easier to index into the table, so you don't have to multiply by a weird number (e.g. 3). This means the page table would take 4 MiB, with a lot of wasted space.

Note: The above calculations assume you're using a 32 bit system. On a 64 bit system, you'd likely have 8 byte page entries and possibly more bits for a page number.

Note: The size of the page numbers don't need to be the same size as the frame numbers. In other words, the physical address and logical address don't need to be the same size. This will allow you to either overcommit memory (what we do) or undercommit memory.

To help reduce the amount of wasted space, we use the extra space for other things. Here's a list of a few common uses:

  • Valid/Invalid bit: If the bit is valid, the CPU allows you to access the page. Otherwise, you can't.
    • Set by OS.
    • This is useful because it means the OS doesn't have to initialize all the memory you "have" and allows you to grow based off of what you use.
  • Read-Only bit: True if this process can't write it.
    • Set by OS.
  • Modified bit: Whenever a page is written to.
    • Set by hardware.
    • Useful for tracking whether or not we should copy out memory to disk if we're doing that.
  • Reference bit: Set by hardware whenever page is read/written (referenced).
    • Set by hardware.
    • This isn't set when you make an invalid read/write.
  • No-Execute bit: True if process can't execute code on the page. (Your stack is normally not executable.)
    • Set by hardware.
    • Used to help prevent buffer overflow, where people write arbitrary code into the stack and execute it.

We tell hardware what page we're using using the page table base register (PTBR). This can only be modified in kernel mode, as you'd expect. This is normally only switched during context switches by the OS.

### Paged Memory Tricks

Using paged memory allows us to do more clever things than just making memory allocation easier and reducing fragmentation. It allows us to do

  • Sparsely Populated Logical Address Space: We can give processes a way larger logical address space than physical address space, basically preventing the stack and heap to bump into each other.
  • Shared memory: Just given processes pages with shared frames. Useful for mutable shared memory or shared libraries.
  • Copy on write: Only copy things once there are actual changes.
    • Useful for efficient fork implementation! fork only copies the page table and sets the read-only bit on all pages. We set the read-only bit so the OS gets notified whenever the child tries to write to the page. Whenever they write, we actually copy the underlying frame and make both pages in both children writable.

### Page Table Caching

Pages can be incredibly expensive. It doubles the number of memory accesses, since you always need to look at the page table, and requires the additional step of address translation.

This can be mitigated using a translation look-aside buffer (TLB), which is a special cache for each CPU core that caches a subset of the page table. The TLB stores the page table rows using associative memory that allows for parallel search by page number. In other words, it's a hardware dictionary / map.

If you can't find the row you're looking for in the TLB, it is called a TLB miss and we have to look up the frame number in the page table. We then save the just read row into the TLB (sometimes with a few of the surroundings), removing another row (decided by hardware). If you can find what you want, it's called a TLB hit and you don't have to look at the page table.

Paging with TLB

Note: In class we normally treat the TLB as a write-back cache. It's also normally a write-back cache.

To measure the performance of the TLB, we have to consider the TLB Hit Ratio (α). Then, the effective access time is thitα+tmiss(1α). We can calculate thit and tmiss using the TLB lookup time (ttlb) and memory cycle time (tmemory) doing thit=ttlb+tmemory and tmiss=ttlb+2tmemory.

We want to maximize the TLB hit ratio so we get good performance. How do we do that? Using locality of reference or, in other words, putting everything close together so they fall mostly in the same pages.

Since the page table is different between processes, most OS's throw away the TLB every time there is a context switch, which means that after every context switch you start anew with the cache. This is one reason why context switches are so expensive and in-process context switches are cheap.

Alternatively, some hardware marks every TLB entry with a address-space identifier unique to the process and only allows the process with the correct identifier to access values of the TLB. This let's you preserve the TLB between switches.

### Making the Page Table Manageable

As we discussed earlier, if we naively implemented page tables with 220 entries at 4-bytes each, every process would have a 4MiB page table, which doesn't scale well, especially considering very few processes actually use it all.

#### Variable Page Table Size

Simplest.

Variable page table size just allows processes to have a smaller page table and only access certain possible pages. This is normally implemented using a page table length register (PTLR) that tells the hardware the length of the current page table and then the hardware checks the length on every access. This is saved and restored on context switch.

This makes growing page tables very problematic because you have to both find more memory for the frames and the larger page table.

#### Hierarchical Page Tables

By far most common.

This resolves the problem of finding contiguous memory regions for page tables the same way page tables do. A meta-page table! (Or a hierarchical page table.)

To implement this, we break up the page table into page-sized section. This means we can mark large sections of the page table as invalid and not allocate memory for them by invalidating a page in the outer page table. Then, we can easily grow the page table when we need to by allocating a page in memory for the page table (which then gets pages to fill itself in).

Note: Technically at full load, this takes up more memory than a naive implementation, but that almost never happens.

Note: Really, both the inner and outer page table are in the same frames that normal memory is placed in.

To do address translation, we split up our logical address into three parts (unlike the normal 2). The highest order bits are for the outer page table, the middle order bits are for the inner page table, and the low order bits for the final page offset.

We can actually have more than the 2 levels discussed here! The technique works for arbitrarily many until the top level table fits in a page.

With multi-level page tables, the TLB becomes increasingly important. This is because the TLB goes straight from page number (including outer and lower page number) to the frame number. Thus you can skip each of the levels and go straight to the frame number, saving two memory accesses (one for outer and one for inner page table).

Note: All page tables except for the outermost one are guaranteed to have the same page size because they fit as much as they can in a frame. You'd like it to work out perfectly so that the outermost page table has no wasted space.

#### Hashed Page Tables

Store the sparse mapping from page number to frame number as a hash table. To handle collisions, you use a linked list on every line of the hash table. Then the hardware just hashes the page number looks in the list for a match.

#### Inverted Page Table

Since we only have a limited number of frames that doesn't change between processes, if we build the table backwards, it can be much smaller. This has more complicated page lookup, but can have decreased storage overhead.

The reason this saves so much memory is because there are often fewer physical frames than logical pages and you only have a single shared page table for the entire machine. Because the page table has to be shared, you need to verify the PID of the process.

This would have a huge performance disadvantage if it weren't for the TLB.

#### Software Address Translation

For more complex address translation methods (e.g. hashed page tables), sometimes the hardware doesn't support address translation through anything but the TLB. If it tries to use a page number not in the TLB, it traps the OS and asks it to do the address translation and put the output in the TLB. This makes TLB misses way more complicated, but means you can make the page table more sophisticated.

## Virtual Memory

Previously we talked about swapping entire process's memory to secondary storage. This was extremely disruptive to the process, not very granular, and not particularly efficient, because we had to do so much at one time.

We can make this swapping more granular by only swapping a single page at a time. Here's some terms about that.

  • Page out: Copy a page from main memory to the backing store.
  • Page in: Copy a page from the backing store into main memory.
  • Memory resident: The page is in a frame in main memory.

What are some strategies to do this?

### Demand Paging

We move seldom-used pages to the backing store and bring a page into memory when processes try to access it. This means processes take much less physical memory.

This can be pure demand paging, where we don't even bother loading pages into memory until they're first used. This can save I/O at process startup and allows less physical memory per process, allowing more processes.

How do we know when we should page in a page when it isn't in memory? The trick is we mark the pages that aren't memory resident (on secondary storage) as invalid. Then when the process tries to access one of these pages, the hardware traps to the OS and we can figure out if the page actually exists but just in secondary storage.

While we are paging in the page a process asked for, we block the process on I/O (since paging in can take awhile!). When the OS is done paging in the page, the OS updates the process's page table and wakes up the process.

### Page Fault Efficiency

What if paging in requires we page out another page? In that case, we call it page replacement with a victim, where the victim page is the page that is being forcibly paged out. This means page faults / swapping pages can be really expensive because you have to read-in, write-out, and do other administrative work to do page replacement.

With this knowledge, we can create a formula for our effective access time (EAT), that is how long it takes to access memory on average, where 0p1.0 is the page fault rate. EAT = (1-p)*memory_access_time + p*(page_fault_overhead + page_out_time + page_in_time + fix_page_table + memory_access_time).

Normally, the amount of time it takes to handle a page fault is at least 5-6 orders of magnitude above the non-page fault memory access time. This means we really don't want to page fault.

We can't pick what memory the process's ask for, so the only thing that we can really control to keep our page fault rate low is who should be the victim. Note: We don't have long to think about this because you're the OS!

There are two main policies for picking the victim. Local page replacement policy means that a process will only ever replace one of its own pages. Global page replacement policy means that any page can be the victim when a process needs to replace a page.

### Page Replacement Algorithms

We test this similar to how we tested process scheduling algorithms. We'll make up a string of pages used by a "program" and see how various algorithms perform. The most thing we measure is the number of page faults.

Belady's anomaly occurs when more memory results in worse performance. It can occur at any level, not just swapping pages. Not all algorithms are subject to Belady's anomaly, but many are.

Algorithms that aren't subject to Belady's anomaly are called stack algorithms. Stack algorithms are algorithms where the set of pages you keep in memory is a subset of the set of pages you would have kept in memory if you had one more page. In other words, more memory always means you'll keep additional pages in memory but never chose to throw out memory that would have remained with fewer pages.

#### First-In-First-Out (FIFO) Page Replacement

Always pick the oldest page as the victim.

  • Pros:
    • Extremely easy and efficient to implement
    • Only requires work when a page fault occurs. (Normal memory access doesn't require updating anything.)
  • Cons:
    • Often we have long running processes that are important.
    • Really sucks when we access memory in repeated sequences.
    • More frames can yield more page faults. Belady's anomaly.

#### Optimal Page Replacement (OPT)

This algorithm is guaranteed to give you the fewest number of page faults for a given reference string.

OPT looks into the future by looking at the references after its current position in the reference string. It then picks the reference that won't be used for the longest time as the victim.

  • Pros:
    • Guaranteed to give you the fewest number of page faults.
  • Cons:
    • Requires you know the order of page requests that will occur in the future to be properly implemented.

To get around the knowing the future, we use heuristics based of previous behavior to predict the future.

#### Least Recently Used (LRU)

This is like a backward-looking approximation looking of OPT. The idea is that pages that have been used recently are likely to be used in the future.

To implement this, you'd probably either keep a timestamp on every memory reference and then replace the page with the oldest timestamp (okay in hot path, bad in cold path.) or you could keep a linked list and move the page to the front of the list (awful in hot path, okay in cold path.) Since this is hard to implement efficiently, we normally approximate it.

One way to approximate this is to use the hardware-set reference bit. The OS clears the bit every once in awhile to see get an idea on pages are being used most often. This leads us into the Second Chance algorithm.

#### Second Chance / Clock Algorithm

We keep a pointer to the next victim page. When we go to page-out / evict the victim, we check its reference bit. (We do this even when evicting uninitialized pages.) If its reference bit is set, we clear the bit and move to the next page. If the reference bit is set, it is your victim.

This is good because it is free in the hot path and cheap in the cold path.

This algorithm performs better under pressure because it is a better approximation to LRU the faster it cycles around. So, if it doesn't cycle around for a really long time, it basically just randomly picks a page to evict after moving the victim pointer around a lot and clearing a bunch of reference bits.

#### Least Frequently Used

This utilizes the reference bit like the second change algorithm does. Every once in awhile the OS goes in and checks the reference bits. If the bit is set, it increments the pages corresponding count and then clears the bit.

Then, when it needs to evict a page, it evicts the page with the smallest count.

This solution generally has a problem with over-valuing pages that are used intensively for a short period of time and then not used for a long period of time. We could however find a way to decrement the counter properly.

Note: Sometimes LRU is absolutely awful, even in fairly common places. Imagine you access pages in the same order, over and over, (e.g. iterating over a large array) and you have almost enough frames to hold them all. This would cause you to page fault over and over and over again. Because of this, some systems implement multiple page replacement algorithms, each with a priority. When a process starts it uses the highest priority one, but if that keeps failing then it switches to the next one, eventually even settling for random page replacement.

#### Additional Reference Bits

This is similar to least frequently used, but it keeps a history of the past few reference bits. To do this, every page has a reference register or reference integer. Periodically the OS goes in and right shifts all reference registers and bitwise ors the current reference bit with the most significant bit in the register. Then, when it's time to pick a register, it picks the one with the smallest count.

Here's an example

0011 1111  # used for awhile but not recently
+1100 0000  # idle for awhile but used recently
+1100 0110  # used recently and in past
+1111 1111  # used all the time
+

This is clever and not incredibly expensive, but it's still fairly expensive because it has to do the upkeep of occasionally checking. Since page faults don't happen that often, the additional upkeep and harder choosing process of this better algorithm normally isn't worthwhile.

### Enhanced Second Chance

This is just second chance except we prefer pages that have not been written to. We want to prefer this because it means paging out is cheaper, since we don't need to write the updated page into its copy in storage. To do this, we look at both the reference bit and the dirty bit.

The following table shows the priority of the enhanced second chance algorithm. It prefers the pages at the top. The reason we prefer dirty pages that haven't been recently used is because we consider the reference bit to say whether we'll need to page something back in in the future. If we page out a clean recently used page, we'll have to page it back in later at a cost of 1. If we page out a dirty not recently used page, it'll have a cost of 1 as well because we'll only need to page it out.
ReferenceDirty
00
01
10
11

How does it make its choice? As it scans forward, it acts like normal second chance but it will only accept clean pages. However, while it is scanning it remembers the state of other pages. If it scans everything and doesn't find a clean, unused page, it goes through its memory to settle for something else.

### Page Fault Tricks

You can do some things to reduce the cost of page faults.

One method is page buffering. To do this, you keep some frames free all the time. When a page fault occurs, you page your desired page into one of the available frames. Then, you later page out an idle page to maintain your buffer / pool of free frames. This is like paying in advance. You basically hope that some pages won't be missed and your disk will sometimes be free.

Page buffering also allows for minor page faults. That occurs when you need a page that hasn't been used since it was paged out onto disk. Since we didn't actually overwrite the contents of the page, we don't need to do any I/O and can just resurrect that old page. (We call "normal" page faults major page faults in this case!) This is kinda like the OS being caught thinking that a page wasn't used anymore.

Minor page faults also allow for smarted shared libraries. When the process first tries to access the shared library that it hasn't loaded into its page table, the OS probably can handle it using a minor page fault if any other process has the bit of the shared library loaded that we want.

### Thrashing

Thrashing occurs when a process doesn't have enough pages to do the work it requires. It starts to page fault a lot and exhibit low CPU utilization and abnormally high I/O utilization, leading to an extreme decrease in overall performance.

How do we tell the difference between many I/O bound processes and thrashing? Normally, you monitor the page fault rate. If page faults are where the majority of I/O is occurring, then you're most likely thrashing.

How do we mitigate thrashing? One way to mitigate thrashing is to implement local page replacement. That way one process's bad behavior (thrashing) doesn't spread to the entire rest of the system.

### Local Page Replacement

The most common way to allocate frames for an individual process is to do proportional allocation, where you give each process a number of frames proportional to its total memory size. However, this has an issue. Process's need a minimum number of frames or else they have the potential to stop making process, since one instruction can potentially require many frames at once if, for example, the instruction spans a frame, the source and destination are in separate frames, etc. Therefore, OSes that do proportional allocation have a minimum number of frames that they allocate to a process. They want to allocate more than this minimum in general though for good performance.

How do we quantify a processes page usage? We consider the process's working set or the pages it is actively using right now. If we want to measure the process's working set, we can count the most recent n references (say 1,000,000). If we can't keep the process's working set in memory, we'll have very poor performance. In general, processes that have a smaller working set will have better performance because they are less likely to page fault; processes that exhibit better locality of reference generally have better performance.

This working set can change though as the program executes, so the operating system should have a way to adjust its frame allocation policy for a process as it executes. We normally do this through heuristics, rather than actually keeping track of the process's working set. A standard heuristic to keep is the page fault rate of the process.

### Page Replacement in Linux 2.4

The kernel maintains the following lists of pages.

  • Active list: Pages that aren't (currently) candidates for replacement.
  • Inactive lists: Pages that would (probably) make good victims.
    • Clean list: Pages that are identical to a copy on the backing store.
    • Dirty list: Pages that are not (or at least might not be).

Every once in awhile, the kernel processes the active list like second change. If the page was referenced since it last checked, it increments the age. If it wasn't referenced and the age isn't 0, it halves the age. Otherwise, it moves the page to the appropriate inactive list.

Occasionally the kernel will clean pages on the dirty list (i.e. write them out to the backing store and move them to the clean list). Pages on the clean list are potential minor page faults and as such are checked before page faulting.

# GPU Programming & CUDA

CUDA is a framework for general purpose GPU programming. CUDA is nice because it helps factor our hardware differences across GPU models and mix CPU and GPU code.

CPUs have a few powerful processing elements that are independently controllable with large caches. GPUs meanwhile have many weak processing elements that are controlled in concert and each doing pretty much the same thing with small caches. That is, GPUs follow the SIMD or single instruction multiple data design.

Note: The cache of GPUs has a different idea of locality, because you want to consider pixels vertically and horizontally adjacent to be "local".

## Jobs on the GPU

In GPU programming, the CPU (or host) is in charge while the GPU (or device) does most of the work. The host executes the serial parts of the program, prepares jobs for the device, and requests and waits for jobs/grids to execute. The device actually does the work.

How do you run jobs on the GPU? You create a block of threads, each contains 10-100s threads, with shared memory and limited synchronization support (e.g. wait for everyone else to catch up). You can still have race conditions with shared memory and such like you would normally.

Because thread blocks have shared memory and synchronization support, there's a limit on how big they can be. To get around this, we organize blocks of threads into grids or jobs, where grids can be multi-dimensional. Each block has an index within its grid and each thread has an index within its block. It uses these indexes to determine what computations it's responsible for.

Why are they organized into grids? It allows us to better model the idea of graphics and images and also take advantage of GPUs different cache locality model. We won't take advantage of that here though.

Note: You want to break your kernel up to be as small as possible, even if you think doing multiple might be better. GPU processing elements are incredibly weak but they are incredibly parallel.

## CUDA Code

CUDA uses an extended version of the C language (.cu), with additional attributes to mark where the function will run, that way it can properly compile the code.

// b needs to be in host memory
+__host__ void someFunction(int a, char *b) {
+  // C code to run on the host (or CPU).
+}
+
+// d needs to be in device memory
+__device__ void otherFunction(int c, double *d)
+{
+  // C code to run on the device (or GPU).
+}
+

Each thread in a grid executes a kernel (no relation to OS kernel). A kernel is a function that runs on the device but can be called from the host.

// Define a kernel that will execute on the
+// device and be called from the host.
+__global__ void myKernel(int a, int *bList) {
+  // C code for the device to execute.
+}
+
+int main() {
+  // Call a kernel from the host, asking the
+  // device to execute. NOTE: bList must be in
+  // device memory
+  myKernel<<<blocksPerGrid, threadsPerBlock>>>
+  (a, bList);
+}
+

To compile CUDA code, you use nvcc. nvcc presents a similar CLI to gcc and clang. Once you compile the CUDA code, you execute it as you normally would.

## Memory

The GPU has memory which the CPU cannot address. Therefore, we cannot use our normal memory techniques (e.g. malloc). Luckily, CUDA provides calls that are similar to standard memory allocation calls.

  • cudaError_t cudaMalloc(void **memp, size_t size): Fill in memp with a pointer to the newly allocated block of size bytes.
    • Don't dereference the memory in the host!
  • cudaError_t cudaFree(void *mem): Free the memory returned by cudaMalloc.
  • cudaError_t cudaMemcpy(void *dest, const void *src, size_t size, enum cudaMemcpyKind dir): Copy memory between the CPU and GPU (either direction, specified by dir).
  • cudaError_t cudaDeviceReset(): Remove all device allocations.

## Things We Missed

CUDA has per-thread registers, per-thread local memory, per-grid global memory, and per-grid constant memory. It also has the __syncthreads() barrier within a block and atomic operations on shared memory.

# Distributed Systems

Benefits of distributed computing:

  • Resource sharing: Only need one machine with a certain resource.
  • Computational speedup: More hosts mean more power.
  • Reliability: Individual nodes can fail, but the system can still operate.
  • Communication: Mostly for humans.
  • Cost effectiveness: Multiple inexpensive devices are cheaper and easier to grow.

Building distributed operating systems are a lot like operating systems. It could transparently provide resources within the network and perform other tasks such as:

  • Data migration: Transparently move data as necessary.
  • Computation migration: Execute computational steps on host with needed resources.
  • Process migration: Move a whole program while it is running. (Load balancing, data access, etc.)

In general, distributed systems need the following properties:

  • Scalability: Gradually add resources.
  • Robustness: Tolerate failure of individual components.
  • Availability: High utilization.
  • Heterogeneity: Different types of hosts can cooperate. Differences can include different computational speeds, byte order, instruction sets, operating system, etc.

There have been a lot of work on distributed computing. Although there is still much work to be done, we have made some progress.

  • Operating systems provide easy access to the network.
  • Some distributed file systems do exist.
  • Map-reduce for distributed high performance computing has been successful.

## Shareable Network Interface

Much like we built a file system to both make using the storage device easier and making it so that multiple processes can use the storage device simultaneously, we build a network interface.

Here's a list of issues this network interface has to handle:

  • Indirect Connections: We aren't always connected directly to the host we want.
  • Unreliable Connections: Messages may be lost or delayed and links may fail.
  • Network Congestion: We're sharing the network with other machines on the network, so we have to be able to route messages even with antagonists / competing applications.
  • Changing Network Topology: Devices come online, offline, and switch networks all the time.

Normally, to handle all these concerns we split the concerns into layers, where each layer handles a particular set of concerns.

### Physical Layer

Decides how we will physically connect machines and how we will encode information (i.e. binary).

Part of Ethernet and part 802.11 (wireless) handles this.

Organizes data into fixed or variable length frames and makes routing decisions for local networks. Corrects errors introduced by physical layer (normally using information stored in message header).

The rest of Ethernet and 802.11 (wireless) handles this. Also modem.

### Network Layer

Organize data (frames) into variable-length packets. Adds additional header information concerning routing data across multiple connections.

The Internet Protocol (IP) handles this.

The Internet Protocol provides a best-effort packet delivery service. Each host is represented with a 32-bit IPv4 address (or 128-bit for IPv6). Each packet is stamped with a source and destination address. Basically, you dump a packet into the network and it tries its best to route it to the destination.

There is no error detection or correction for the payload (only for the headers). There is no attempt to avoid network congestion.

Congestion may cause packets to be dropped (or more rarely errors) or even duplicated. Retransmission to recover from lost packets may reorder packets (or more rarely routing machines).

Individual IP addresses have a structure that allows routers to know who would know more about the packet. They forward the packet to this node and it continues until it reaches the destination.

### Transport Layer

The transport layer provides useful application semantics on top of the network layer. It allows for process-to-process packet delivery (rather than host-to-host). Breaks (large) messages into packets and reassembles them on arrival. Creates the illusion of connections for clients, rather than just spurious packets/messages.

Examples include the Transmission Control Protocol (TCP) or User Datagram Protocol (UDP).

#### UDP

UDP is conceptually a very thin layer. You don't need to establish a connection first and messages may be lost. Conceptually, it is just a message queue that provides error detection within messages and port numbers to dispatch messages to the right process on the host.

Note: Individual messages are called datagrams.

Port numbers are 16-bit integers that uniquely identify processes on a host.

To use UDP, you choose a port number and then create a datagram socket for that port.

Why is UDP set up? UDP is very cheap to set up and because of that fast. For certain services where real-time performance is more important than never missing a message (e.g. streaming video), this trade off is worth it.

##### UDP in Java

You just use java.net.DatagramSocket and java.net.DatagramPacket. You create a DatagramSocket on a particular client. You create DatagramPackets, which have both data and a destination (i.e. IP and port), and have the socket send these packets to the given destination.

#### TCP

Whereas UDP was a message queue, TCP is a pipe. TCP has no message boundaries (instead just sending bytes) and guarantees that no bytes will be lost or received out of order. A connection must be established first and reliability (e.g. packet loss prevention) is achieved by using acknowledgement and a timeout, retransmitting in the case of failure. It also performs congestion control, where it will slow down the sender if the receivers network is congested / we're losing too many packets. It slows the sender down by periodically blocking the sender.

Where in UDP applications where peers, TCP follows a strict client-server model. The server selects a port, sets up a server socket with that port, then starts listening on that socket. A client then sets up a socket and then tries to connect with the server by sending a message to the server on that port. The server sends an acceptance of that request and then the client responds with an acknowledgement. At that point, the server sets up a new socket that is just connected to that client. Now the client's socket and the server's new socket act like a pipe.

The server gets a new socket to allow the server socket to keep listening for new connections.

##### TCP in Java

This requires java.net.ServerSocket and java.net.Socket. The client creates a Socket with the given host and port. The server creates a ServerSocket which is basically a factory for Sockets; the server repeatedly calls ServerSocket.accept to generate Sockets that correspond to individual client sockets.

### Application Layer

This is how your application actually communicates and is what you think about most. It includes things like HTTP, SSH, and DNS.

As the name implies, this is not the job of the OS.

## Remote Procedure Call (RPC)

Often, we don't structure our code as sends and receives. Instead, we think about code in terms of functions. RPC makes this possible. Essentially, you have some framework / library that can transparently send and receive network messages and make them look as though they were executed on the same host like a normal function (hence transparent).

This is normally done by having a server with a thin client-stub that exposes all functions the server can perform. This client-stub could even be auto-generated. Then, whenever you want to do an RPC call, you call the client-stub that makes a request to the server.

RPC could easily be implemented using UDP using one-off requests which should be faster (assuming everything works). However, this is dangerous because you don't know whether the request or the response got lost. In other words, you don't know whether your function was executed or not. To cope with that, we want idempotent functions or functions that don't have any additional affect after being called more than once. Alternatively, we could guarantee that call functions either zero or one times. That is, we don't retransmit requests.

## Structures for Distributed Applications

### Client-Server Model

One of the oldest and most widely used model of distributed applications is client-server. You have one server and many different clients. It is highly centralized.

We normally split up applications into layers. A common split is presentation logic, application logic, database logic, and database management system (DBMS). We can then decide where we put each layer. Where we want to put the layers depends on the structure of our application, but here's a list of some common named splits.

  • Host-based Processing: All layers on the server.
  • Server-based Processing: Presentation logic on client. All others on server.
  • Client-based Processing: Presentation, application, and (some) database logic on client. DBMS done by server.
  • Cooperative Processing: Presentation logic and some application logic on client. Some application logic on server and database logic and DBMS on server.
    • Shared computational load!
    • More complex to design.

### Peer-to-peer

There is no server. Everyone is a "client" and shares in part of the application logic.

Scales very well but often more complicated to design.

### Transactional

Model all application logic in terms of transactions. A users then just makes various transactions with the system and the system guarantees they are executed appropriately.

# Protection

For many computing scenarios we want to enforce a certain policy on how OS resources can be used and by who. For example, maybe we don't want everyone to be able to read certain files or maybe we want to restrict how much a certain group can print.

Normally, when implementing and designing protection solutions, we talk about access rights (rules) to the operations certain users can perform on given objects (resources). Note: Instead of saying users, we normally call the things with the access rights a protection domain because sometimes we deal with groups or programs or other things.

A good permissions system allows for many different types of permission policies and fine grain control.

## Access Rights

Some common access rights are read, write, execute, append, create, delete, list (for directories). There can be access rights specific to various objects, such as printing for a printer. However, this is often handled using the standard file system access rights. (For example, printing to a printer might be write permissions.)

Often we conditionally allow domains to give away access rights to other domains. We may add an additional access right for all normal ones, for example read* (read star). Here the star means that the domain can give that permission to other domains (limited copy) or transfer that star access right to another domain. However, another more often used technique is to consider certain domains the owner of the object. The owner can give away and revoke access rights as it sees fit.

Another trick that is sometimes used is the switch access right to a domain object. This is used to allow certain domains to temporarily switch to another domain and use its access rights. However, this leads to the confinement problem, where domains can switch to another domain which has access to things the original domain shouldn't have access to. Even worse, sometimes this switch right chain can be hard to find, it is even undecidable if you allow creation of domains and objects.

How do we record access rights?

### Access Matrix

One naive / easy way would be to use an access matrix, where every row in a protection domain, every column is an object, and the internal cells are the access rights of that domain.

This is extremely memory inefficient because matrices take a lot of memory and are very sparse. As such, it is very rarely used. However, it is easy to see.

### Access List

  • Easy to know who can use an object.
  • Easy to remove an object or revoke rights.
  • Hard to answer "What can I access?"
  • Most common in general.

Basically, you convert each column in the access matrix into a list. Every list is associated with an object and contains a series of entries, each containing a domain and its access rights. You omit empty spaces which allows for much less wasted space.

Each object keeps track of its individual access list (aka column).

### Capability List

  • Easy to know what a domain can access.
  • Hard to remove an object or revoke rights.
  • Hard to answer "Who can access this?"
  • Who manages the list??

A capability list is a lot like an access list except that it lists the rows. Every list is associated with a domain and contains a series of entries, each containing its object and its access right. You omit empty spaces which allows for much less wasted space.

Each domain keeps track of its individual capability list (aka row).

### Lock and Key

  • Hard to know who can access an object.
  • Hard to know what objects a domain can access.
  • Easy to revoke access rights.
  • Maybe more efficient to represent and give out access rights.

Lock and key is like a mixture of access list and capability list. Every domain contains a list of keys and every object contains a list of locks. Then, to find out what your access rights are, a domain matches its key with an objects lock. We're normally clever, having domains share keys with the same permissions and having objects use the same keys as other objects.

Note: it is permissible for a domain to have multiple keys to the same object with the same access rights. Basically, it's okay if you have multiple reasons for accessing an object.

This is good in general because it enables easier revoking of access rights, by having keys be reasons that a domain can access that resource. Then, you just revoke that key so you don't accidentally take aways a domain's permissions to an object when it had multiple reasons of using it.

Note: There are many different ways to convert an access matrix into a lock and key system.

Note: This is kinda how Unix group ownership works.

## Standard Unix Permissions

Every user has a unique user id. Every user is a member in multiple groups. Every group has a unique group id.

Permissions are associated with each object. Every object has an owner, group, and mode bits. There are three mode bits assigned to each of the three domains. They are read, write, and execute as the permissions mode bits and owner, group, and other as the domains.

For files, read, write, and execute mean exactly what you'd think. For directories, read means you can get a listing, write means you can add / delete files, and execute means you can see file attributes.

Your groups are kinda like a list of keys and the single group for an object is kinda like a single lock for that object. You have to squint a bit though.

There's also some extra bits beyond the mode bits we normally think about. There's the setuid bit which means pretend to be the owner while executing, the setgid bit which means pretend to be the group while executing, and the sticky bit which means keep this program in memory even when it's not running. The sticky bit used to be useful to keep commonly used programs in memory for efficiency, but it's not as important anymore because OS caching has improved and we have faster computers.

### Syscalls for Unix Permissions

  • fchmod(int fd, mode_t mode): Set mode bits of file.
  • fchown(int fd, uid_t owner, gid_t group): Set owner and group of file.
  • fstat(int fd, struct stat *buf): Fill in buf with information about the file.

## Permissions and Programs

Most programs are run with exactly the same permissions as you when running. In other words, the program is you.

Some security techniques such as sandboxing change this by running the program in a limited environment to help prevent trojan horses and other exploits. The principle behind sandboxing is called the principle of least privilege, which says we should only give programs exactly the permissions they need and no more. This helps prevent accidental breakages either from mistakes or malicious programs. You can do this in a Unix-y way using groups, but that is limited in terms of how many groups you can have.

To do this truly well, we'd like programs to have some way of dynamically changing their protection domain. That way, programs could start with as few permissions as possible and assign certain module / subprocesses of the program high permissions to allow them to do just what they want to do. For example, this would allow the init system to have very few permissions but spawn off higher permission processes.

### Permissions and Java

Java actually has an interesting concept of "trusted" code. By default, code from your hard drive is considered code, but it is possible that the JVM downloads code and starts executing it while it is running. In this case, it considers the downloaded code untrusted and doesn't allow it to do certain protected operations (e.g. opening arbitrary files).

This is enforced using stack inspection from the AccessController class. It has a checkPermissions method which introspects the stack to find out if we are allowed to do privileged code. It has the doPrivileged method, which only trusted code can execute and marks the current point in the stack as a point where a privileged operation was allowed.

\ No newline at end of file diff --git a/notes/ncsu/2s/csc246/logical_addresses.png b/notes/ncsu/2s/csc246/logical_addresses.png new file mode 100644 index 0000000..d477651 Binary files /dev/null and b/notes/ncsu/2s/csc246/logical_addresses.png differ diff --git a/notes/ncsu/2s/csc246/memory_protection.png b/notes/ncsu/2s/csc246/memory_protection.png new file mode 100644 index 0000000..d406062 Binary files /dev/null and b/notes/ncsu/2s/csc246/memory_protection.png differ diff --git a/notes/ncsu/2s/csc246/paged_memory.png b/notes/ncsu/2s/csc246/paged_memory.png new file mode 100644 index 0000000..accbdc0 Binary files /dev/null and b/notes/ncsu/2s/csc246/paged_memory.png differ diff --git a/notes/ncsu/2s/csc246/process_memory_layout.png b/notes/ncsu/2s/csc246/process_memory_layout.png new file mode 100644 index 0000000..5364ba2 Binary files /dev/null and b/notes/ncsu/2s/csc246/process_memory_layout.png differ diff --git a/notes/ncsu/2s/csc246/process_queues.png b/notes/ncsu/2s/csc246/process_queues.png new file mode 100644 index 0000000..f3b8cb2 Binary files /dev/null and b/notes/ncsu/2s/csc246/process_queues.png differ diff --git a/notes/ncsu/2s/csc246/process_scheduling_states.png b/notes/ncsu/2s/csc246/process_scheduling_states.png new file mode 100644 index 0000000..581c000 Binary files /dev/null and b/notes/ncsu/2s/csc246/process_scheduling_states.png differ diff --git a/notes/ncsu/2s/csc246/simple_computer_architecture.png b/notes/ncsu/2s/csc246/simple_computer_architecture.png new file mode 100644 index 0000000..777d026 Binary files /dev/null and b/notes/ncsu/2s/csc246/simple_computer_architecture.png differ diff --git a/notes/ncsu/2s/csc246/static_linking.png b/notes/ncsu/2s/csc246/static_linking.png new file mode 100644 index 0000000..40fc4e4 Binary files /dev/null and b/notes/ncsu/2s/csc246/static_linking.png differ diff --git a/notes/ncsu/2s/csc246/swapping.png b/notes/ncsu/2s/csc246/swapping.png new file mode 100644 index 0000000..27c1057 Binary files /dev/null and b/notes/ncsu/2s/csc246/swapping.png differ diff --git a/notes/ncsu/2s/csc246/switching_layers.png b/notes/ncsu/2s/csc246/switching_layers.png new file mode 100644 index 0000000..391a494 Binary files /dev/null and b/notes/ncsu/2s/csc246/switching_layers.png differ diff --git a/notes/ncsu/2s/csc246/thread_stacks.png b/notes/ncsu/2s/csc246/thread_stacks.png new file mode 100644 index 0000000..72f71b0 Binary files /dev/null and b/notes/ncsu/2s/csc246/thread_stacks.png differ diff --git a/notes/ncsu/2s/csc246/tlb.png b/notes/ncsu/2s/csc246/tlb.png new file mode 100644 index 0000000..8e1756a Binary files /dev/null and b/notes/ncsu/2s/csc246/tlb.png differ diff --git a/notes/ncsu/2s/csc333/index.html b/notes/ncsu/2s/csc333/index.html new file mode 100644 index 0000000..61edd43 --- /dev/null +++ b/notes/ncsu/2s/csc333/index.html @@ -0,0 +1 @@ +Eli | CSC 333: Automata, Grammars, and Computability

CSC 333: Automata, Grammars, and Computability

Instructor: Dr. Don Sheehy | Semester: Spring 2020

Scanned PDF.

\ No newline at end of file diff --git a/notes/ncsu/2s/index.html b/notes/ncsu/2s/index.html new file mode 100644 index 0000000..1c7fbef --- /dev/null +++ b/notes/ncsu/2s/index.html @@ -0,0 +1 @@ +Zola

Welcome to Zola!

You're seeing this page because we couldn't find a template to render.

To modify this page, create a section.html file in the templates directory or install a theme.
You can find what variables are available in this template in the documentation.

\ No newline at end of file diff --git a/notes/ncsu/2s/ma341/index.html b/notes/ncsu/2s/ma341/index.html new file mode 100644 index 0000000..5669e95 --- /dev/null +++ b/notes/ncsu/2s/ma341/index.html @@ -0,0 +1 @@ +Eli | MA 341: Applied Differential Equations I

MA 341: Applied Differential Equations I

Instructor: Mrs. Leslie Kurtz | Semester: Spring 2020

Scanned PDF.

\ No newline at end of file diff --git a/notes/ncsu/2s/ma405/index.html b/notes/ncsu/2s/ma405/index.html new file mode 100644 index 0000000..f53a240 --- /dev/null +++ b/notes/ncsu/2s/ma405/index.html @@ -0,0 +1 @@ +Eli | MA 405: Introduction to Linear Algebra

MA 405: Introduction to Linear Algebra

Instructor: Dr. Alina Duca | Semester: Spring 2020

Table of Contents

# Scanned Notes

Scanned PDF.

# Cheatsheet

Thruout this cheatsheet, I use Householder notation. That is, matrixes are denoted with capital English letters A,B,..., vectors are denoted with lowercase English letters a,b,..., and scalars are denoted with Greek letters α,β,....

## Vector Space Properties

We say a set V over field F with operations addition + and scalar multiplication is a vector space if and only if the following properties hold for all vectors u,v,wV and all scalars α,βF.

Note: A field is the scalars that make up vectors in V. Often F is the real numbers R.

  • Addition:
    • Closure: u+vV.
    • Commutativity: u+v=v+u.
    • Associativity: (u+v)+w=u+(v+w).
    • Identity: 0V such that u+0=u.
    • Additive Inverse: uV such that u+(u)=0.
  • Multiplication:
    • Closure: αuV.
    • Identity: 1F such that 1u=u.
  • Distributivity:
    • Vector Additive Distributivity: α(u+v)=(αu)+(αv).
    • Scalar Additive Distributivity: (α+β)u=(αu)+(βu).
    • Scalar Multiplicative Distributivity: (αβ)u=α(βu).
\ No newline at end of file diff --git a/notes/ncsu/3f/csc326/burndown_chart.png b/notes/ncsu/3f/csc326/burndown_chart.png new file mode 100644 index 0000000..c25d192 Binary files /dev/null and b/notes/ncsu/3f/csc326/burndown_chart.png differ diff --git a/notes/ncsu/3f/csc326/index.html b/notes/ncsu/3f/csc326/index.html new file mode 100644 index 0000000..41f305a --- /dev/null +++ b/notes/ncsu/3f/csc326/index.html @@ -0,0 +1,284 @@ +Eli | CSC 326: Software Engineering

CSC 326: Software Engineering

Instructor: Dr. Sarah Heckman | Semester: Fall 2020

Table of Contents

# Administrivia

WeightComponentAdditional Info
20%Onboarding (OBP)Aug 13 - Sept 30
40%Team Projects (TP)Sept 30 - Nov 11
40%Weekly QuizzesDuring the week. Can make 3 up.
  • No exams! Just quizzes. :)
  • Notify for absences, especially for lab.
  • Extra Credit: 2 of the following activities. Each activity gives you 1 point on your quiz average.
    • Software Engineering Research Study: In Piazza.
    • CSC Seminars.
  • Quizzes: Moodle.
  • Academic Integrity:
    • As long as you cite your sources for online resources, you're good.
    • Solo quizzes are open book and everything.

# Bugs & Issues

  • Fault: Underlying issue in the code/project. Caused by mistakes normally.
  • Error: Incorrect program state resulting from the execution of a fault. Doesn't necessarily cause failure.
  • Failure: Observable incorrect behavior.

When you run into a failure, you want to create a minimum reproducible example. This is a minimum number of steps / bit of code to reproduce the issue. You should try to generalize the issue as much as possible. That is find out exactly what kind of circumstances the issue occurs under and try to make it as generic as possible.

For our class we need a reproduction, isolation, and generalize section in our bug reports. Probably want to use GitHub template.

# Maven

Maven (mvn) builds projects by reading the project object model (POM) file pom.xml and executing a sequence of steps to reach a specified target. The POM can declare dependencies, custom profiles that apply a group of settings, build plugins that define custom targets and steps, and all that fun stuff!

Maven looks for dependencies in the repositories section of the pom.xml. By default it uses mvnrepository.com.

# CoffeeMaker Tools

To test the frontend, we use Selenium. Selenium is a browser automation tool meant to help test web frontends. It allows you to scrape the HTML DOM to find if elements exist and also manipulate the web browser by clicking on things or doing other normal user interactions programmatically. Selenium is built on top of JUnit so it makes tests easy to set up and run if you already use JUnit.

To do test, we use Cucumber, which uses the Gherkin. It believes that by making tests look closer to natural English makes it easier to write tests, especially for non-developer users.

# Requirements Engineering

  • Requirements: Definition of what the system should do.
  • Types of Requirements: In general, you want more functional requirements that non-functional requirements because they are easier to test and verify.
    • Functional Requirements: Something that the system must explicitly do.
    • Non-functional Requirements: User-visible parts of the system not directly related to what the program does. (e.g. usability, privacy, performance, security)
    • Constraints: Non user-visible constraints that restricts the development process. (e.g. deployment troubles, implementation language)
  • Requirements Elicitation: Process of getting the requirements.
  • Requirements Validation: Process of reviewing requirements with the stakeholder to ensure that they are:
    • Traceable: Ensure that you can see where each requirement comes from.
    • Non-prescriptive: Says nothing about how programmers will solve the problem.
    • Consistent Language
    • Testable
    • Concise
  • Stakeholders: People that care about the software system or want it.
  • Requirements Engineering: The process of having stakeholders and engineers communicate to form a set of requirements / required behaviors.
  • Business Case: The motivation behind the system and its requirements.
  • Language of Requirements, sorted from most important to least important: shall, should, may, shall.

Why do we care? The most common causes of software project failures is communications (requirements!) based. For example, incomplete requirements, lack of user involvement, unrealistic expectations, etc. Cost goes up in fixing/detecting as you go further into the project.

Requirements engineering has two parts: analysis and modeling. Analysis is understand user needs to create a system definition. Modelling is transforming the system's requirements into an actual software system.

## Requirements Elicitation

One of the most important parts of requirements elicitation is understanding why the system needs a certain behavior. It gives context to the requirements. This is called the business case.

In this class we will use a use-case style of requirements, which is a semi-formal way to document requirements. It's more formal than stories but less formal than requests for proposal.

## Use Cases

Use cases are written by the developers.

The way we build use cases is by listening to stories, which is a series of things that a specific user/actor should be able to do. The actor is a representative for a whole class of users. Normally for user stories we just follow the happy path (or the case with no errors). We do this by describing the preconditions and then the main flow of what the user does. There are sub-flows which are slight changes on the main flow or more descriptive descriptions of the flow. Then there are alternative flows which describe error conditions and error handling. The main flow should connect to alternative and sub-flows.

These user stories are collected to create a big picture where we combine all the user stories to understand all the things that the system should be able to do. This allows us to understand the value of the system.

We then can break up the system into slices which we can deliver and build incrementally and adapt as requirements and teams change.

## User-Stories

User-stories are an informal and highly collaborative form of software engineerings. (Agile!) Agile in general tries to embrace that requirements change by regularly delivering and collaborating with the stakeholders. They are written by the stakeholders.

In general user-stories should be of the form like "As an X, I want to do Y, so that I can Z."

Since user stories are so small, teams that use them often also use epics. Epics are larger changes that cannot be made in a single iteration and are broken down into a family of stories.

User stories should follow INVEST:

  • Investigate-able
  • Negotiable
  • Valuable
  • Estimate-able
    • If you cannot estimate due to lack of experience, run a spike where you just do a prototype except with an epic/edgy name.
  • Small: Small enough that it can be done in a single iteration.
  • Testable

There are many ways to organize stories. Kanban boards are a list of in-progress, done, and to-do tasks. You can also break them down differently.

## Traditional Requirements

Traditional requirements are very formal like government contracts.

# Testing

  • Closed / Black Box Tests: Concerned with requirements and validation, regardless of implementation.
  • Open / Glass / White Box Tests: Testing implementation
  • Types of Coverage:
    • Class
    • Method
    • Line
    • Statement
    • Branch: Individual branches in the control flow graph.
    • Clause: Parts of statements.
    • Path: How many unique paths are you taking through the control flow graph.
    • Requirements: No code at all! Just do you have test cases for your requirements.
  • Types of Testing:
    • Unit Testing: Test single bits of code. Normally a single function or component, linked to a very specific bit of the requirements or code.
    • Integration Testing: Test combinations of multiple components. Test multiple functions or classes. Helps catch things like "where will user input be sanitized?" or "where will errors be handled?"
    • Functional/System Tests: Test conducted on the entire system. Can be done manually or automated with tools like Selenium.
    • Acceptance Tests: Formal tests to determine whether the solution satisfies the acceptance criteria. Normally done by the customer (and in this case the teaching staff).
    • Regression Testing: Test things for specific functionality and run old tests on current code. Helps prevent breaking current functionality.
    • Selective Retesting: When you have a tests that take a long time to run, often you only want to run a small selection of them to give developers feedback more quickly.
    • Beta Testing: Unstructured testing by a subset of the users.

We care about test coverage here. Test coverage is a lot like lines of code. It can give you a ballpark idea, but it can't tell you about missing code and many bugs occur because of a single small line in a large function that can easily go untested. Test coverage can help you identify dead code or code that isn't required for your system. For example, why do I need this code?

There are two main approaches of development with testing. There is test driven development (TDD), where you iteratively write failing tests and code to pass said tests. This focuses heavily on unit tests. There is behavior driven development (BDD), where you look at the behavior of the system at a higher level. This is with the hope of having customers write some of the tests. In this class we use Cucumber for this.

To create tests, we consider equivalence classes and boundary values. For equivalence classes you divide up all possible inputs into sets of similar values and pick a semi-random representative from the set. For boundary values, you pick values that are right on the edges of your equivalence classes and test those.

## Control Flow Graphs

Control flow graphs are useful for code analysis, both in testing and compiling. Control flow graphs are composed of nodes, which are statements represented by squares in the visual, and branches, which are things like if, for, and while represented by diamonds in the visual.

We can compress a series of nodes with no branches into a basic block, which a series of statements where executing the first statement in the block ensures that the last one will be executed.

Using the formalism of a control flow graph and graph theory, we can make some assertions about how much testing we need to get branch, statement, or path coverage. In this case, branch coverage is executing all edges and statement coverage is executing all nodes. This is how static analysis tooling works!

# Design

One of software engineering's main goals is to create well designed software. However, unlike many other traditional engineering projects, software normally has no "physical" representation, or at least one that is useful. That means communication is really hard.

In this class we'll use UML because it's easy to grade, even though it's only used by ~30% of surveyed software developers in industry.

## UML Class Diagrams

Attributes are just listed in the class. They're the same as association except they're simpler value types or external types.

Association is where a class has a field of another class in your project. It is represented by a black arrow with an arrow head, labeled in the middle by the field name and on the head by the multiplicity of the field. You should also label the base of the arrow with

Aggregation is where one class contains another class. It's like a stronger version of association. The owned class can exist without the owning class. This is represented the same way as association except with a white diamond head.

Composition is where one class fully owns another class. It's like a super strong version of aggregation, where the owned class doesn't make since without the owning class. Normally this is an inner class. This is represented the same was as aggregation except with a filled black triangle head.

Generalization is how we show inheritance of types. It is show with a white triangle head with a solid line for class inheritance and a dashed line for interface inheritance.

For abstract methods of an interface or abstract base class is italicized.

## UML Sequence Diagrams

UML sequence diagrams let us model the dynamic execution of the program, as opposed to the static layout that class diagrams give you. Every class gets its own line. The flow of control goes down in time and changes lanes whenever we call a method of another class. When we change lanes, we draw a solid arrow labeled by the name of the called method. The line goes from the previously running line to the newly called object. The returns of methods are denoted using a dashed line labeled by both the name of the method returning and the returned value. When we create a new object, it's line appears. When we destroy an object, it's line disappears.

## UML State Diagrams

State Diagrams are a higher level representation of a finite state machine (FSM) where the entire state of the machine is represented by the FSM.

Every state is represented by a box or circle with the name of the state.

State diagrams follow the standard deterministic finite automata rules. There is one initial state but there can be multiple final states. Every state must be reachable from the initial state. Every state must have a path to the final state. States not shown are error states.

Every transition arrow has optionally a trigger, guard clause, and activity. The trigger is what causes the transition. A transition is only taken if the guard clause also holds though. The activity is what the application does on that trigger beyond just transition.

# REST APIs

REST (REpresentation State Transfer) is a way to interact with backend models, controllers, and services in a language agnostic, networked way.

Why use RESTful APIs? REST can work over the network which allows you to keep your proprietary code secret by hiding it behind the network. It's also the easiest way to distribute your application. Most personal computers have web browsers which are essentially giant JavaScript and rendering engines, so if you design your front-end in JavaScript (or WebAssembly!), then your application can be run without installing anything (kinda). However, JavaScript is slow and we often want to interact with some remote data. To get around this, we create a server in any language we want and interact with it over a REST API. Then we have a single server we control and can optimize as we want and share data with clients as they request.

Essentially, REST APIs (with a lot of work) can allow us to achieve the following desireable properties of service (e.g. social networks):

  • Performance: Appropriate component interactions.
  • Scalability: support large numbers of components and interactions among components.
  • Simplicity of interfaces.
  • Modifiability of components.
  • Visibility of communication between components by service agents.
  • Portability of components by moving program code with the data.
  • Reliability when failures within components, connectors, or data

Most REST APIs use HTTP as the transport protocol and serializes/deserializes data using JSON (sometimes XML, Protobuf, MessagePack, etc.).

HTTP requests have verbs (the type of request) and nouns (the resource requested). For example GET /recipes has the verb of GET and the noun of /recipes. It would return a JSON-formatted array of recipes, for example.

Some of the most common types of operations an application needs to make is called CRUD operations (create, read, update, delete). Each standard CRUD operation has its corresponding HTTP verbs.

  • GET: Retrieve record.
  • DELETE: Delete record.
  • POST: Create record.
  • PUT: Update record.

On top of normal HTTP nouns, we can add parameters to provide additional information. This is useful if the noun represents a function call and the parameters are the arguments to the function. For example, GET /dogs?color=red&state=running&location=park has the parameters color=red, state=running, and location=park.

## REST API Designer

REST APIs should never remove or change things without making a major version number change. This is to not break old clients. Since we often want to make breaking changes, it's good to include a major version number in the path (e.g. /api/v1/resource), so you can change the version number and then make breaking changes.

Since you (should) never remove or change things without making a major version number change, what you expose should be very well thought out. If you're not sure how things should be split, try to release or expose only a stable subset as you work on the final design.

As with any API, you should name things clearly and consistently and make sure that the user doesn't have to do checks that you (the server) could do.

In general for performance (and simplicity), REST APIs should be stateless and cacheable, so that you can improve performance with caches more easily and simplify the client server interactions.

If your API holds sensitive data, you should use standard authentication protocols like OAuth.

To make the API more performant, when you have infinite or extremely large data you should either stream partial responses (chunks) of data or provide some pagination where the client requests a certain page. The page doesn't have to be absolute. For example Discord's API for getting messages can get you n messages after the given message ID.

## HTTP Errors

  • 200: Okay.
  • 400: Bad request.
  • 404: Unknown path.
  • 500: Internal server error.

## Frameworks

Frameworks are meant to make creating applications easier by being a collection of opinionated defaults that help you easily set up your application.

Essentially, you are just "filling in the slots" provided by the framework. There's generally two ways to do this: black-box (compose objects) and white-box (inheritance), named such because in black-box you don't need to know how the bits of the framework work (as much) but with white-box you do.

There are several ways frameworks work, but the Spring framework we use extensively uses dependency injection (basically parameter passing). There are 4 main roles in the Spring framework.

  • Service: Any object that can be used.
  • Client: Any object that uses other objects.
  • Interfaces: How a client may use the services. Never treated as concrete, so there's no construction or extension by a client.
  • Injector: Constructs services and injects them into the client, possibly constructing the service as well.

Dependency injection is nice because it makes the code configurable using config files, meaning you can change behavior without having to recompile and helps create an isolated client. The downsides you get an explosion of types, hard to trace code, and complex links between classes.

# Architectural Patterns

Architectural patterns consist of component types that perform some function at runtime, a topological layout of components showing their relationships, and a set of connectors that facilitate communication.

We'll list broad families and individual styles within those architectural families but most systems are hybrid or combinations of different styles.

## Data Centered

Data centered architectures tend to have a centralized data store (that may be distributed) that communicates with many clients. This is good because it allows for easier backups and easier administration for the downside of somewhat harder to track errors.

This data centered architecture is broadly split into the repository model and the blackboard model. Of course, projects often straddle or use both of these models.

In the repository model, the central database is passive and the clients are active. Client's poll the repository for information and the repository. This makes it harder to update/change the repository but potentially reduce load on the repository. It is better for systems where data is less real-time and people request to see things rather than get notified to see things (e.g. YouTube, Google Drive, Spotify, Instagram, Reddit). This does mean that everyone must agree on a data-interchange format and the repository may be a bottleneck.

In the blackboard model, the central database is active and the clients are active. Essentially, it's a PUB/SUB (publish/subscribe) system where clients subscribe to updates and the central database pushes events to the clients. It is better for systems where you need to react immediately to things rather than request to view them (e.g. eBay, Slack, Discord, Weather Service Alerts). This is good for systems that are non-deterministic, but it does require complex infrastructure.

## Call and Return

In call and return you essentially just write a program like you would normally. You organize your code into a series of function calls or similar ideas.

There's the main program and subprogram split, which is literally just procedural code where you call functions to do things. It's easy to write and understand, but can get really messy.

There's the object-oriented design, which we know very well. You design the system using interfaces and each class fulfills the interface. Because of interfaces, you can get easier code reuse and potentially easier to understand code as you separate certain aspects of the code get abstracted away. It can also get really messy and hard to understand like main program and subprogram, but it can make it easier to understand.

There's the layered design, where we split to design into layers where (ideally) every layer can be swapped out for an equivalent layer and every layer communicates with a clean, abstract interface. This is incredibly common, with OS code vs userspace code, the networking stack, and good object oriented code. This is good because it's easy to understand and extend because every layer is independent and well encapsulated. This can be bad because structuring layers can be incredibly difficult, causing leaky abstractions that actually cause more harm than good. Also, performance may suffer because of all the layers.

## Data Flow

In data flow style architectures, you design your system as a pipeline from a data source to a data sink. It is good for systems that need to be distributed or parallelized.

There's pipe and filter where you model your program as a set of inputs and outputs where you do local transformations and filters on the data. This is good because it easily handles infinite data (incrementally) and parallelization. It's limited (intentionally) by not having knowledge of other filters and having no shared state. This is because all filters work at the same time. One example architecture of map-reduce where you represent your problem into an easily parallelizable map function that gets applied to every element and then a reduce section that is both associative and commutative (e.g. sum or union) so that it can also be executed in parallel. If the reduce part of not associative and commutative, then it may have to be done sequentially. This can be harder to write but is easier to parallelize and often more performant.

There's batch sequential where you sequentially transform data but split it into batches to process in parallel. It can be easier to write but harder to parallelize and potentially more buggy.

## Event Systems

For event systems there is explicit invocation where you request things to be executed to change and implicit invocation where something changes on the system and it executes a callback you provided.

# Human Computer Interaction (HCI)

HCI focuses on the human aspect of computer system. It tries to make systems ergonomic and easy to use intuitively.

Why is this important? If you're creating a system for people, it would be good if people can actually use it. If people can't use it or can't use it safely, then you are wasting time and putting lives at risk. Intuitive software also saves money in terms of support and training materials.

For example, Tesla's (early) autopilot systems allowed humans to pay too little attention for too long. This meant that when the system suddenly requested human input, people had to very quickly become re-adjusted to what is happening on the road, leading to overcorrections and crashes.

One of the most important ideas of HCI is the context for use. That is, what is going on around the user when they're using your software. Is it cold? Are they stressed out? In a hurry? etc.

We'll cover three main perspectives physical computing, cognitive computing, and social computing.

Physical computing tries to make things ergonomic with no distractions. So recognize the ambient sound and lighting that will be around the user. Understand where they'll be working. By considering that you can make your project more comfortable to use safely and effectively. Normally you consider anthropometrics, which is the shape, size, strength, etc. of the human body. Anthropometrics help you understand issues with posture and muscle strain.

Cognitive computing tries to understand what is going on in the persons mind. So are they old/young, disabled, stressed, hurried, etc. By understanding what they can understand and know you know how to make things less confusing to them. You normally try to remove cognitive noise. You try to understand people's mental models for how the system works and make the system operate as closely to that mental model or shape their mental model to be as close to the system as possible.

Social computing tries to understand how people communicate and what their prior relationships are. This can make your software less socially awkward and easier to use effectively. It can also help you know when to notify people to do things. How do you facilitate communication between people? If you don't consider this you can have communication difficulties. For example, plane crashes if the pilot and traffic control cannot communicate because of a sudden update.

How do you apply all those principles? Concept design is the process of white boarding or otherwise generating ideas and alternative solutions. We often talk about task flows, where you have three columns (or rows): what the user does, how the system should function, and them some space for notes.
UserSystemConsiderations for Design
1. Gather new contact details
2. Locate contact area in applicationCreate button on home pagePrimary action in the app so button should be front and center of Home page
3. Enter contact detailsText fields to enter contact detailsRequired fields: name, email, phone. Optional fields: address, birthday.
4. Save new contact detailsSave button and way to show user new contact has been created and savedCreation success means info is read only and presented in the UI

You can also create a wireframe of what the user interface should look like at a low-fidelity high level. This is meant to be easier to write than the corresponding code.

# Persistent Data / Databases

In CSC 216 we did simple serialization (e.g. XML, CSV, JSON, Java serialization, Python pickling, etc.). This is good for small data and for human interaction but are slow for edits small with respect to the whole data size.

However, when we want to constantly have out data be persistent and have high performance for small edits, a database can come in handy. They store data on the disk for persistence, but some also uses memory for performance.

The specific types of database we'll be talking about are relational databases.

Relational databases model data essentially like a collection spreadsheets or tables. These tables are managed by the RDBMS, which is a system optimized for inserting, updating, selecting, and deleting data in the database. CRUD operations! (Normally) each table represents a single class, the columns the fields of the class, and the rows the instances of the class. Many RDBMS (e.g. PostgreSQL, MySQL) use the Structured Query Language (SQL), which is a semi-standardized language for describing queries.

Note: In SQL databases, we normally use snake_case for column names.

Why do we use relational databases here? They are commonly used in industry and map nicely to objects. This mapping can be done systematically by an object relational mapping (ORM).

Note: If something can be (easily) calculated from data in the database, you shouldn't store it because that wastes space and allows data in the database to get out of sync. Using linear algebra terms you basically want a linearly independent set of columns (or a basis for the data you want!).

## Hibernate

In this class we'll use the Hibernate object relational mapping, which is an ORM framework that uses annotations and a config file hibernate.cfg.xml to support the connection between Java objects and persistent storage. Here's an annotated and simplified example from CoffeeMaker's hibernate.cfg.xml.

The SHORTENED link is: http://www.hibernate.org/dtd/hibernate‐configuration‐3.0.dtd. It is too large to fit attractively.

<?xml version="1.0" encoding="utf‐8"?>
+<!DOCTYPE hibernate‐configuration SYSTEM
+  "SHORTENED">
+<hibernate‐configuration>
+  <session‐factory>
+    <!--
+    Specifies the Hibernate dialect for the
+    version of MySQL
+    -->
+    <property name="hibernate.dialect">
+      org.hibernate.dialect.MySQL5Dialect
+    </property>
+    <!--
+    Drop and re‐create the database schema on
+    startup, useful because CoffeeMaker is a
+    toy.
+    -->
+    <property name="hibernate.hbm2ddl.auto">
+      create
+    </property>
+    <!--
+    Connection properties, specifies the DB
+    Drive (JDBC) and connection URL.
+    -->
+    <property
+      name="hibernate.connection.driver_class">
+      com.mysql.jdbc.Driver
+    </property>
+    <property name="hibernate.connection.url">
+      jdbc:mysql://localhost/coffeemaker
+    </property>
+
+    <!--
+    Ideally you'd create a user with minimal
+    privileges and a strong password for
+    security.
+    -->
+    <property
+      name="hibernate.connection.username">
+      root
+    </property>
+    <property
+      name="hibernate.connection.password">
+    </property>
+    <!--
+    JDBC connection pool (use the built‐in), and
+    size.
+    -->
+    <property
+      name="hibernate.connection.pool_size">
+      10
+    </property>
+    <!-- Echo all executed SQL to stdout -->
+    <property name="show_sql">true</property>
+
+    <!-- List of persistent classes -->
+    <mapping
+      class="coffee_maker.models.Recipe" />
+    <mapping
+      class="coffee_maker.models.Inventory" />
+  </session‐factory>
+</hibernate‐configuration>
+

Here is an annotated example of a plain Java class that uses Hibernate

@Entity
+@Table(name = "recipes")
+public class Recipe {
+  // The columns in the database. Primitives
+  // don't *need* to be boxed into their Object
+  // form. But `null` means that something
+  // doesn't exist, which is different from the
+  // zero value of the primitive. However, if
+  // you guarantee that the column always have a
+  // value then you can use the primitive.
+
+  @Override
+  @Id
+  @GeneratedValue(generator = "increment")
+  @GenericGenerator(
+    name = "increment",
+    strategy = "increment")
+  private Long id;
+  @NotNull
+  private String name;
+  @Min(0)
+  private Integer price;
+  @Min(0)
+  private Integer coffee;
+  @Min(0)
+  private Integer milk;
+
+  // Mark this as the primary key that is
+  // auto-incremented by 1 with each insert. The
+  // primary key must be unique and is fast to
+  // look up by.
+  public Long getId()
+    return id;
+  }
+
+  // getName, setName, getPrice, setPrice, ...
+}
+

Here is a simple interaction with the database to atomically save the object.

Note: If you open a connection to the database, you have to close the database connection, much like with files. Otherwise you can get denial of service by leaking connections. Sadly, Session does not implement AutoCloseable.

public void save() {
+  final Session session =
+    sessionFactory.openSession();
+  // Wrap the operation(s) in a transaction to
+  // make them atomic. Ideally you'd use a
+  // try-with-resources block, but the example
+  // in class didn't use that.
+  session.beginTransaction();
+  // CRUD operation
+  session.saveOfUpdate(this);
+  // Commit the transaction, actually making the
+  // changes.
+  session.getTransaction().commit();
+  // Close the session!!
+  session.close();
+}
+

## Database Testing

How do we test with databases tho? Good point, they're really complicated. We especially don't want to test on the production database because that could really mess things up.

To get around this, we use a test database and mocking. A test database is just your normal database except without any important data. Normally you wipe the test database at the start of every test run to keep the tests reproducible. We can also create a mock database, which vastly simplifies thing. We basically just hard-code data and create the minimal interface that we actually use. There are libraries that make this easier, like Mockito.

## Structured Query Language (SQL)

SQL is a declarative language, which means we just state what we want.

Most SQL databases are case insensitive. However, some of them are so normally we make keywords all UPPERCASE. SQL strings/characters use single quotes.

SQL supports a fairly large set of built-in data types, although you can extend this in some databases using plugins.

Here's an annotated example of the standard SQL you would run to create a database, make a table in it, and add some rows.

-- Create a database called coffeemaker
+CREATE SCHEMA coffeemaker;
+-- Start "using" the database, basically cd in
+-- it. (This is a MySQL thing.)
+USE coffeemaker;
+
+-- Create a table with the following fields
+CREATE TABLE recipes (
+  id BIGINT NOT NULL AUTO_INCREMENT,
+  -- 20 bytes pseudo-string
+  name VARCHAR(20) NOT NULL,
+  price INT,
+  coffee INT,
+  milk INT,
+  chocolate INT,
+  -- Specify the primary key. This is the thing
+  -- that is fastest to look up by and must be
+  -- unique for each row.
+  PRIMARY KEY (id)
+);
+
+-- Add a row into the 'recipes' table.
+INSERT INTO recipes
+(name, price, coffee, milk, sugar, chocolate)
+VALUES
+('Coffee', 50, 1, 1, 1, 0)
+;
+
+-- Select all the recipes and show them
+SELECT * FROM recipes;
+

Let's look a little more at those SELECT statements. SELECT statements are how you extract data from a database. They have the general form of

SELECT <cols> FROM <tables>
+WHERE <conditions>;
+

Some of the simplest types of queries are where you select multiple columns and filter by different columns. Here's annotated examples.

-- Select every column from the recipes table.
+SELECT * FROM recipes;
+
+-- Select the name column from the recipes
+-- table.
+SELECT name FROM recipes;
+
+-- Select the recipe name with an id of 1.
+SELECT name FROM recipes WHERE id = 1;
+
+-- Select recipes with at least one unit of
+-- coffee and one unit of milk.
+SELECT * FROM recipes
+WHERE coffee > 1 AND milk > 1;
+

As you can see above, * is the wildcard (matches everything). For comparisons, we use >, >=, <, <=, =, != (note one equals for equality). To check for null we use $columns IS NULL.

We can do more advanced queries by doing filtering, sorting, and aggregation.

-- Filter out all non-unique column combinations
+SELECT DISTINCT <columns> FROM <table>;
+
+-- Sort the columns by the <orderby columns>
+SELECT <columns> FROM <table>
+WHERE <conditions>
+ORDER BY <orderby columns>
+;
+
+-- Aggregate all columns by the groupby column
+-- and count the number of matches in that
+-- group.
+SELECT <columns>, COUNT(<groupby column>)
+FROM <table>
+WHERE <conditions>
+GROUP BY <groupby column>
+;
+

## Using Persistent Objects

When we want to reference rows in a table, we need the row's primary key. The primary key is a unique value (normally integer) which is the fastest way to look up something. We can insert this into other tables either as the direct value (gross! It's unchecked) or as a foreign key. When we use a foreign key, the database checks that the foreign key actually is a valid key in the table. It also does neat stuff with cascading deletes and the like. You can think of the foreign key as a reference to the row in the table or a restriction on the raw value.

Concretely, this is used if you want to have one class have a reference to another class. For example, consider the following two classes (sans annotations, IDs, etc.).

class User {
+  String name;
+}
+
+class Transaction {
+  User purchaser;
+  Integer cost;
+}
+

This would result in the following two tables, users and transactions respectively, where purchaser is a foreign key.
idname
1Eli
......
idpurchasercost
.........
2110
.........

Here's how you create a foreign key

CREATE TABLE transactions (
+  id BIGINT NOT NULL AUTO_INCREMENT,
+  purchase BIGINT,
+  paid INT,
+  -- id is OUR primary key
+  PRIMARY KEY (id),
+  -- Create a column called purchase which is a
+  -- foreign key referencing the recipes.id
+  -- column. If this foreign key references the
+  -- same key in multiple different tables we
+  -- can list them out after `REFERENCES`
+  FOREIGN KEY (purchase) REFERENCES recipes(id)
+);
+

As mentioned earlier, cascading deletes means that when we delete a row of a table then all the rows that reference that row get deleted as well.

What if we don't want that? Normally what we do then is we just mark the row as "hidden" or "deleted" but don't actually remove the data. Then the backend knows to just ignore those (e.g. by adding a WHERE clause that filters it).

Sweet! Now we know how to reference a single row in another table. What if we want to make it variadic? That is reference multiple rows in our row.

You can't! Well, kinda. What you do instead is create a join table that provides the many to many relationship. Then you reference a "collection id" on the join table in your referencing row and the join table has multiple rows that use that "collection id", each row mapping to one of the reference rows. That's a mouthful so here's an example.

transactions
idpaid
1175
250
3100
4190

transactions_recipes
transaction_idrecipe_id
11
12
21
33
42
43

recipes
idnamepricecoffeemilksugarchocolate
1Coffee502110
2Mocha752111
3Coffee1005000

As you can see, transaction 1 ordered recipe 1 and 2, transaction 2 recipe 1, transaction 3 recipe 3, transaction 4 recipe 2 and 3.

If we then wanted to join all rows in the tables where the recipe was ordered as part of a transaction, we would run the following query.

Note: This displays multiple rows when transactions have multiple recipes, but the recipe is identical.

SELECT *
+FROM
+  transactions AS t,
+  transactions_recipes AS tr,
+  recipes AS r
+WHERE
+  -- t.id is higher priority for sorting than
+  -- r.id
+  t.id = tr.transaction_id 
+  AND r.id = tr.recipe_id
+ORDER BY t.id, r.id
+;
+

Hibernate (and really JPA) uses many annotations to automate this, @OneToOne, @OneToMany, @ManyToOne, @ManyToMany, and @ElementCollection.

# Web Frontend

Web frontends fundamentally use HTML (Hypertext Markup Language) which is similar to XML (Extensible Markup Language) and CSS (Cascading Style Sheets) as a way for communicating the structure of documents/webpage. Since we want webpages to be able to modify themselves and be web apps (because browser wars and legacy!), the language JavaScript was created, which is a language which is designed to run in the browser and has a standard API for manipulating the DOM (Document Object Model) which is the programmatic representation of HTML documents.

## HTML

HTML tags are called DOM notes. You're probably somewhat familiar with it but here's an example. HTML includes a <head> and <body> sections. The head is where metadata (e.g. CSS, text encoding, page title). The body is the actual document explained.

<!DOCTYPE html>
+<html>
+<head>
+  <!-- Some comment -->
+  <title>Page Title</title>
+
+  <style>
+  /* Inline CSS! */
+  body {
+    background-color: powderblue;
+  }
+  p    {
+    color: red;
+  }
+  .some-class {
+    color: green;
+  }
+  </style>
+  <!-- External CSS! -->
+  <style href="css/styles.css"></style>
+
+  <script>
+  // Inline JavaScript!
+  console.log("Hello from JavaScript!");
+  </script>
+  <!-- External JavaScript! -->
+  <script src="js/foo.js"></script>
+</head>
+<body>
+  <h1 class="some-class">This is a Heading</h1>
+  <p>This is a paragraph.</p>
+</body>
+</html>
+

## CSS

CSS has tags, classes, and ids which are used to classify each DOM element (e.g. HTML tag). Every HTML tag can have a single id and multiple classes.

/* This applies to all divs */
+div {
+  color: red;
+}
+
+/*
+  This applies to any tag with
+  class="class-selector"
+*/
+.class-selector {
+  color: green;
+}
+
+/*
+  This applies to any tag with
+  id="id-selector"
+*/
+#id-selector {
+  color: blue;
+}
+

You might notice that in the above example that all those styles conflict with each other. What if we apply all of them at the same time? The id style would take precedence. Really, every style gets a specificity where a tag selector gets a weight of [0,0,0,1], class [0,0,1,0], id [0,1,0,0], and inline styling [1,0,0,0]. When we have multiple selectors apply, we get the winning style by picking the style with the highest specificity. When multiple tags apply (e.g. div.class-selector) we add them together. If any style has !important then it automatically wins. If multiple things are important then normal specificity rules apply but only for !important elements. For example, in the example below the text is blue because #id-selector wins.

<div id="id-selector" class="class-selector">
+  div text
+</div>
+

CSS is called cascading because in the following example "span text" would be red even though the span isn't directly colored. When things aren't directly styled they inherit from their parent.

<div id="id-selector" class="class-selector">
+  div text <span>span text</span>
+</div>
+

## JavaScript (+ AngularJS)

JavaScript is "the language of the browser". Browsers are essentially JavaScript engines that have a rendering engine that runs on HTML and CSS. This class won't focus on learning JavaScript specifically. It's a standard interpreted, imperative, multi-paradigm language with plenty of resources online, so if you're lost you should be able to easily find some online. Instead, we'll focus on learning AngularJS.

AngularJS (also called Angular version 1) is the deprecated version of the Angular web-frontend JavaScript framework. A framework is an opinionated library (or set of libraries) that helps control and handle the entire lifecycle and structure of a project. It intends to make things easier.

Why do we use the old version of the framework? Well, it was kinda new when this project's tech stack was last updated and Dr. Heckman is really busy. Also, stubbornly staying on old versions even though it makes you do more work is realistic to industry so there's that I guess...

TODO: Finish from the recording.

# Presentations

Presentations are an important part of communicating with management and other developers. As such, this will be our assignment for milestone 6 of the on-boarding project.

The general layout of a presentation is the classic organization that you've probably been taught since elementary school.

  • Introduction: Identify your purpose, thesis, POV / ask / desired action, and audience. Introduce your "story" if applicable.
  • Body: Build supporting points for your thesis.
  • Conclusion: Restate your purpose and POV. Do a short overview. Then conclude with any advice you have.

Visuals and text should be simple, readable, and be a "launch pad for discussion". Most importantly, think about the person who will have the hardest time reading the presentation. For example, "can the person in the back of class see this?" or "can someone watching this on their phone see this?". This includes increasing text size for code and browsers.

For our on-boarding project, we will do live (recorded) demos. For this, make sure to freeze your code (i.e. stop making changes), script your demos, and practice your demos. That way nothing surprising happens! Live demos are filled with peril, so please for the love of god make sure that it won't fail.

# Code Inspections/Review

Code inspection/review is the process of reviewing software artifacts by developers, managers, and/or customers for comment or approval. The purpose is to detect errors, ensure software meets requirements, and that everything is well designed.

There are a few big different types of inspections

  • Desk Check: Offline inspection done independently with findings (optionally) discussed at a meeting or directly with the member.
  • Checklist: A set of standards set by the team that a developer can review.
  • Structured Walkthrough: Done normally during a meeting. The developer walks the entire team through a section of code line by line.
  • Commit Inspection: Basically a desk check but via PRs and diffs and a focus on changed content.

The benefits of reviewing code include the following.

  • Promote Openness: People share knowledge which builds a culture of sharing knowledge and understanding everything.
  • Raises Standard: People expect good code.
  • Propel Teamwork: We have a standard way of communicating and resolving issues.
  • Promote Values: Values make it into checklists and are checked.
  • Frame Social Recognition: Trusted reviewers.

One of the most powerful things with standardization and improvement of processes is checklists (like ARC). They provide a standard list of things to think about and consider, insuring that all knowledge is shared and every requirement is checked every time.

There are several roles for inspection. These don't have to be set in stone but it is helpful to assign people individual work to help make the process smoother.

  • Author: Person who wrote it.
  • Inspectors: Everyone except author.
  • Moderator: Member of quality assurance team.
  • Scribe: Take notes during inspection of issues of interest.
  • Reader: Person who interprets artifact for inspectors.

Michael Fagan invented formal software inspections and as such the standard methodology he introduced is called the Fagan inspection. Fagan inspection is simple. It is there is individual review by all inspectors, where they mark all faults found, following the checklist, and track how much time they spent (less than 2 hours). Meanwhile the author prepares for questions. Then there is a review meeting where all inspectors and the author meet. The moderator calls the meeting and all inspectors go through all defects. The goal is not to correct defects because that takes time, it should be to give a course of action and trust that the author knows how to fix it. If necessary the author can ask questions after inspection. Inspection shouldn't last more than 2 hours and if it needs to then it should be split up.

The feedback should not be framed (either by the inspector or the author) as a personal attack because those are counterproductive. Also, style issues should not be the focus of the inspection. Possibly note it and definitely have an automated formatter.

The preparation component of inspection is incredibly important. At the start of a meeting, you should ask how long everyone spent on the individual portion of inspection. If most people did not do the preparation, you should consider cancelling the meeting.

What are the issues with code review? It's not effective for discovering bugs, the findings are normally too low level and don't find architectural issues, and developers normally don't like it. It's still effecting for knowledge transfer and ensuring requirements are met.

# Software Process Models

A software process model is a standard template with how to do software development.

Plan-driven process models have up-front, stable requirements. The cost of development is minimized by doing all planning up front. This is common for large, safety-critical projects, like aerospace and automotive projects. This allows for specialization.

In general, plan-driven process models encourage predictability, thorough documentation, and clear delineation of tasks. Normally companies even have specific people whose job it is to do process improvement.

Agile process models have changing requirements. Agile process models try to quickly and effectively incorporate changes to reduce the cost of requirements changing during work. This is common for app development

Note: These are loose divides because really everything is a spectrum from planning early to planning late.

## Models

## Plan Driven Process Models

The waterfall model is the classic plan-driven process model. It is extremely predictable in terms of cost and time. However, it doesn't consider risk or effectively adapt to changing requirements.

The spiral model is a modification of the waterfall model. Basically instead of doing planning all up front, you heavily plan and do risk-analysis of smaller prototypes. For example, first you try to get some requirements, do a small prototype, do risk analysis with that prototype. Then you start to plan heavier development, doing risk analysis again, and developing another more detailed prototype.

The personal software process (PSP) is a system of checklists, scripts, and templates to guide people through the "levels" of PSP. Basically you keep track of defects you introduce and how much time you spend on completing tasks to figure out what defects you normally introduce and how much time you spend so you can get better at estimation. This tends to improve quality but people struggle with detailed reporting and many people stop using it after awhile.

The team software process (TSP) is like PSP but extended to larger projects and teams. To do this it adds more scripts, more forms, and more roles. The idea is that by assigning everyone a task/part that they own you can improve accountability and quality.

The rational unified process (RUP) applies ""object-oriented principles"" and uses UML as a notation for some reason. It's extremely flexible and thus hard to define. That's really all we have to say.

## Agile Process Models

The agile processes (as a name) were kicked off by the "Agile Manifesto" which was published in February 2001. Basically it said

Individuals and interactions over process and tools. Working software over comprehensive documentation. Customer collaboration over contract negotiation. Responding to change over following a plan.

And then it listed the following 12 principles.

  • Our highest priority is to satisfy the customer through early and continuous delivery of valuable software.
  • Welcome changing requirements, even late in development. Agile processes harness change for the customer's competitive advantage.
  • Deliver working software frequently, from a couple of weeks to a couple of months, with a preference to the shorter timescale.
  • Business people and developers must work together daily throughout the project.
  • Build projects around motivated individuals. Give them the environment and support they need, and trust them to get the job done.
  • The most efficient and effective method of conveying information to and within a development team is face-to-face conversation.
  • Working software is the primary measure of progress.
  • Agile processes promote sustainable development. The sponsors, developers, and users should be able to maintain a constant pace indefinitely.
  • Continuous attention to technical excellence and good design enhances agility.
  • Simplicity, the art of maximizing the amount of work not done, is essential.
  • The best architectures, requirements, and designs emerge from self-organizing teams.
  • At regular intervals, the team reflects on how to become more effective, then tunes and adjusts its behavior accordingly.

The incremental model you get requirements, do some design, and then implement a feature. You do this iteratively to gradually fulfil more and more requirements. This still allow parallel work by having your design people designing requirements and requirements people getting newer requirements. The idea here is you don't redo any work but instead just keep adding to the project.

The iterative model is the most agile plan-driven model. It is essentially the incremental model except instead of adding on you redo things at the end of each increment. The idea is that this minimizes technical debt, which is just poor design decisions made to meet a deadline.

The LEAN model tries to do the following 9 things

  • Eliminate Waste: Prevent extra features, thrashing, and bureaucracy.
  • Create Knowledge: Do reviews
  • Build Quality In: Write tests and do CI.
  • Defer Commitment: Try to schedule irreversible decisions to the last responsible moment.
  • Deliver Fast: Try to cut down on things in-progress.
  • Respect People: Be accepting and congratulatory. Don't overwork people.
  • Improve the System: Make measurements of quality.

Extreme programming (XP) values pair programming, working together, incremental design, basically everything in agile. Work is organized into epics and stories. Epics are a collection of stories. Stories are informal requirements that say what a specific user wants to be able to do and why. These features/requirements should be able to implemented in a single sprint. A sprint is some measure of time, normally a weak.

TODO: Finish

# Planning & Project Management

Project management goes through three main phases:

  • Planning: Plan for releases, some design, schedule resources, etc.
  • Execution
  • Control: What went well what went less well?

For release planning, you need to understand the themes or high level epics you want to focus on, followed by a goal for you project, and your expected velocity. So if we want to get 240 story points and we get 30 story points done per iteration, it'll take 8 iterations (estimated) to do something.

Generally, when you're planning releases you either think about the release date or the release features. With features you determine the release date by the features included (velocity and story points). With dates you determine the features by the required release date. We'll be doing date focused release planning because, well, the class can only be so long.

A critical piece to planning is understanding your velocity/progress. A good way to track this is with burn-down charts, where you track the number of story points left at the end of every iteration. This lets you easily see your velocity (the slope), your progress (the hight), and whether or not you'll reach the deadline (estimated line).

Burndown Chart Example

There are two types of iterations we consider. A normal iteration and a stabilization iteration. A normal iteration adds features and fixes bugs. A stabilization iteration refactors code, documents code, removes old code, and does all that good stuff. A stabilization iteration earns no story points because fuck you; suffer with bad code; good code isn't Agile.

## Feature Based Roles

Often it is beneficial to split up tasks and their owners by roles. Roles categorize what aspect of the project is being worked on. This helps tasks both be more efficiently assigned and more efficiently worked on. There are a few different types of division:

  • User Role Division: Each developer implements a use case from the perspective of a certain user.
  • Specialization Roles: You specialize on QA, planning, team management, etc.
  • Feature-Based Roles: Split based on part of system, e.g. frontend, backend, and data entry.

Estimation is an important part of software development (and really just doing things in general). Ideal time is the amount of time it takes to do something with no distractions. Elapsed time is the amount of time it takes to do something in practice. Generally, we're pretty good for estimating ideal time but bad at elapsed time. A good rule of thumb is the multiply ideal time by 3-4.

Some teams use story points, which are just a unitless measures of how long it takes to do something. The actual value is meaningless but the relative amount is valuable. It allows you to compare how long tasks will take. A standard way to do things is assign an "average" task 5 points but really it depends on the team.

With story points, how do we assign them? There's a few ways.

  • Expert Opinion: Just use your gut feeling.
  • Planning Poker: You have a moderator read the description and the task. Then everyone silently selects a card for their estimate and present it. Then the person with the highest estimate justifies it and the person with the lowest estimate justifies it. Then everyone re-votes until they converge.
    • This is less about getting an estimate and more about sharing knowledge and coming to a common understand. They can help get a rough idea of how to implement things and design them.

One reason we do story points is to find velocity, which is how many points we do per week. This helps improve estimates for how many tasks a team can complete.

# Security & Privacy

  • Asset: People, property, and info under protection.
  • Threat: Source of attack.
  • Vulnerability: Weakness in protections. Latent, not necessarily exploited.
    • Like Fault.
  • Exploit/Attack: Concrete use of a vulnerability to breach protection.
    • Like Error.
  • Information Security:
    • Confidentiality: Not shared.
    • Integrity: Don't alter or destroy data.
    • Availability: Readily available to authorized users.
  • Authentication: Act of validating entity's identity.
  • Authorization: Act of checking whether the user is allowed to perform certain actions based on who they are.

Security is controlling what users can do and see, in other words it is the ability of the system to perform its function with confidentiality, integrity, or availability losses. Privacy is just controlling what others can see.

When we think about security, we don't just think about normal users making mistakes. We think about intelligent attackers actively trying to exploit your system.

## IEEE Top 10 Secure Design Principles

Below are the 10 principles, but our biggest ones (not listed below) are never trust single points of failure, never trust your user, never trust input, and never trust defaults (especially passwords).

Here are the real IEEE top 10 design principles for secure design.

Earn or give, but never assume trust. Ask how many permissions does this really need? How fine grained can I make permissions? Assume people are trying to exploit your system. Assume your users will make mistakes. Don't assume the server APIs will be called in your expected order. Don't expect the UI will actually restrict what the user sends to the server. (i.e. don't only add business logic on frontend.) Don't store secrets on the client side.

Use tamper‐proof authentication mechanisms. Use two-factor authentication or other systems.

Authorize after you authenticate. Ensure that the user really has the permissions required to do a particular action. This should be done before important actions.

Strict separation. Separate data your system works with and what your code does. Don't evaluate strings. Don't evaluate or do string concatenation with SQL queries. Ideally use prepared queries (see below). Don't provide too much error information (e.g. don't do a stack trace). Don't say whether your password or username was incorrect.

Prepared queries have a series of free variables represented by ?. These queries are compiled to a binary format and optimized by the database engine. This makes it faster to execute future queries using this. These ? variables can then be bound to concrete types. Strings here don't need to be escaped because the binary format ensures that strings and other variables are interpreted appropriately.

-- This query has 2 parameters, one for name and
+-- one for price.
+INSERT INTO products
+(name, price)
+VALUES
+(?, ?);
+

Explicitly validate ALL data. Validate multiple levels and especially whenever data crosses a trust boundary, for example when the user enters information or data comes from the API. You should have a safe list / whitelist and a block list / blacklist

Use cryptography correctly. Don't push your secrets to git repositories. Don't roll your own cryptographic libraries. Ensure you safely share keys and other security things.

Identify and handle sensitive data. Make sure that you trust the servers which you are storing information. Make sure that sensitive data is being encrypted (i.e. don't use plain text). Often we have different levels for the different types of information.

Always consider users. Make sure that your policies are reasonable for the average person to follow. That is, don't be annoying because then users will try to circumvent your policy.

Understand your attack surface. Your attack surface is the sum of all paths for data and commands into and out of the system. The fewer paths you have, the easier it is to secure them all. Close all ports possible. Restrict user privileges as much as possible.

Design flexible systems. Ensure that updates and changes to the system don't break security. For example, don't leak secrets when people change their password, don't leak secrets when components outside your control change, and don't leak secrets when someone updates their system.

## Cross-Site Scripting XSS

Cross site scripting occurs where user input somehow changes the HTML output (for other people) without sufficient cleaning. If this occurs, then a user could inject script tags into the HTML which other users will then load. This allows for basic things like vandalism of websites or even worse injection of JavaScript which can spoof fake input boxes (e.g. credit card number) or load some malware onto the client which just loaded the page. Here is an example of a XSS vulnerability.

page += String.format(
+  "<input name='creditcard' type='TEXT' "
+    + "value='%s'>",
+  request.getParameter("CC"));
+

This could insert.

'><script>
+  document.location='http://attacker.com/'
+<script'
+

## Threat Modeling

In order to secure systems, we need to understand what we need to secure. To help us this we have threat models which semi-formally describe how our system could be insecure.

We can do threat modeling with data flow diagrams which models all the nodes/actors in a system and how the data goes between them (and is validated). Often the graph is segmented by trust boundaries (for example our local server vs an unknown client).

One popular threat model is the STRIDE threat model which is an acronym for the following.

  • Spoofing: pretending to be someone else by using their credentials.
  • Tampering: malicious modification of data.
  • Repudiation: users deny an action because no proof that action happened.
  • Information Disclosure: exposing information to those that shouldn't have it.
  • Denial of Service: valid uses cannot access the system.
  • Elevation of Privilege: user gains privilege they shouldn't have.

The idea with the model is that these are the 6 main ways for security to be compromise. By looking at each one individually and how your system handles each of these kind of exploits, you can determine how you need to secure your system and what vulnerabilities exist. That is, you're finding the abuse cases which is the possible threats in your system. You can model these attacks using attack trees.

Normally when exploits or other security threats are found by cyber-security peoples, attack libraries are published illustrating how the attack works. This helps secure future systems.

Once we've identified these issues, how do we address them? There are 5 main ways.

  • Mitigate: what have similar software packages done to mitigate the threat, and how has that worked for them?
  • Eliminate: what software components are affected in eliminating the threat?
  • Transfer: will you need to transfer data or processes to another part of the system that is more trusted/secure?
  • Accept: outline the "acceptance criteria" that you will use to indicate the threat has been properly addressed.
  • Wait and See: be prepared if an attacker or other malicious user manages to find a way to exploit a vulnerability associated with the threat.

## Risk Management

A risk is a potential future harm. Often risk is unavoidable but it is still undesirable. As such we try to minimize the probability that a risk occurs. A risk is no longer a risk if it has happened.

How do we quantify risks? There are a few main ways: guess, take measurements, reason from first principles, listen to experts, and listen to experience.

Risk management is what we do to identify, address, and eliminate risks before they become significant threats or a major source of expense. We manage risks in two main ways: reactively and proactively. Reactive teams correct or fix the problem rapidly in response to a crisis (e.g. firefighters). Proactive teams try to prevent risks from becoming threats in the first place (e.g. national park service).

In order to mitigate risks, we can take the following actions.

  • Information Buying: Get more information by investing time to handle the risk. For example the risk of using new technology can be handled by using throw-away projects.
  • Contingency Plans: Make sure you know what to do if the risk happens.
  • Risk Reduction: Try to reduce the likelihood of the risk to occur. For example employ inspections to reduce the risk of losing information when someone leaves.
  • Risk Acceptance: Conciously accept that you will live with the risk and potential loss.
  • Risk Avoidance: Simply don't take the risky action. Often a lose-lose strategy because then you're not doing much.
  • Risk Protection: Buy insurance or use redundant systems. For example have more servers than you need.

## Privacy

Privacy is essentially the right to be left alone, so you can have private facts.

Here is the Better Buisiness Bureau's outline of what parts of a privacy policy there are.

  • Policy: what personal information is being collected on the site
  • Choice: what options the customer has about how/whether their data is collected and used
  • Access: how a customer can see what data has been collected and change/correct it if necessary
  • Security: state how any data that is collected is stored/protected
  • Redress: what customer can do if privacy policy is not met
  • Updates: how policy changes will be communicated

The Code of Fair Information Practices (FIPs) is a set of internationally recognized practices of addressing privacy of information about individuals. Essentially it says that you cannot keep secret personal data, a person must be able to find out what information is being stored about them, and a person's information can only be used for what they consent to.

The Children's Online Privacy Protection Act (COPPA) applies only to children under 13. It essentially requires additional protections, parental consent, and provides additional powers to the parent such as a way for parents to review information.

The Health Insurance Portability and Accountability Act (HIPAA) provides a standard for privacy and security of your protected health information (PHI). Further it provides a standardization of electronic data interchange of healthcare information. Protected health information is any information that can be used to identify the patient, including demographic, medical, and financial information in medical records.

EU General Data Protection Regulation (GDPR)

# Maintenance

Maintenance is the "long tail" of development. That is it's what you spend most of your time doing. There are four main types of maintenance we'll discuss.

Corrective maintenance tries to correct active faults. It is extremely difficult because you want to fix the bug without breaking anything else. This is made easier with good tests and clear design.

Perfective maintenance attempts to make the software better even when its not broken. Like looking at what features are used and make the unused features easier to use or otherwise better.

Adaptive maintenance is reactive changes that attempt to make the system still usable on a new environment. This can be because of changes of work policy, laws like the EU's GDPR, or operating system changes. Often adaptive maintenance is in response to bit rot, which is when software starts to break over time because of changes in its environment.

Preventative maintenance is active changes that attempt to make the system still usable in future environments. In essence, it is adaptive maintenance done ahead of time. You refactor things to make them easier to understand and maintain even when they aren't actively broken. Because you're not increasing/improving functionality, this is hard to sell to companies and managers.

What may effect the costs of maintenance? If you have lots of turnover, there is more maintenance effort. If you have contract based software developers, there may be little incentive to make maintenance easy.

How do we convince users to update? It's difficult. We need to balance user input and user annoyance. Updates that require user input are likely to be put off and can be annoying. However, on the flip-side forcibly updating software that causes disruptions to the user can be really annoying, for example Windows update suddenly restarting your computer. It's a balance to make your system as usable as possible.

# Software Engineering Economics

## Cost of Bugs

One of the main focuses of software engineering economics is to identify how expensive bugs/faults are.

In general the later you find and fix a bug the more expensive it is.

However, how do we actually determine what caused a fault? We do this with root cause analysis. Essentially, root cause analysis is where you keep asking "Why?" a fault occurred until you can no longer get a meaningful response. So for example for the fault that a server crashed.

  • Our server crashed. Why?
  • CPU usage spiked immediately before the crash. Why?
  • The program hit an infinite loop. Why?
  • A mistake by a developer. Why?
  • Because they did not sufficiently test their code.

# (Unconscious) Bias

Bias is incredibly important to understand as a member of the work force and especially if you manage other people. It is important because intrinsically we want everyone to be treated equally. If you don't care about people and instead only about profit, diverse teams also tend to perform better. It is also incredibly important because small biases can compound into huge effects, so we need to detect small biases.

First off, everyone is biased and not all bias is bad. For example, snakes being dangerous is a pretty good bias. However, in America white Americans are more likely to get a call back than black Americans, which is clearly a bad bias.

How do we eliminate this bias? We'll in particular be looking at hiring. A good way to do it is to eliminate names from resumes, have a checklist for what qualifications you want, and a script of what questions you will ask.

# Design Patterns

Design patterns are standard ways to structure your program to make it easier to maintain and understand. They also provide a standard language for communicating designs between developers.

  • Creational: How do we make an object?
  • Structural: How do we compose classes statically?
  • Behavioral: How do we manage the interactions within the system?

Here we'll talk about a few specific design patterns for in Java. These design patterns often apply to other languages, maybe with some changes, but some of these design patterns are irrelevant because of language features in other languages. Likewise, some languages need additional design patterns to cover up for features of the Java language.

The abstract factory design pattern is where you have an interface for a set of related objects that you want to create, for example styled GUI elements like scrollbars and window titles. Then you provide a concrete instance of this abstract factory (basically a vtable) to something that needs to create these elements. Then for example you could have a window system take in a factory for window elements. Then you use this factory to generate window elements. This allows you to dynamically change the styling.

The factory method design pattern is where your (super)class calls a method to construct an object satisfying an interface rather than a constructor for a specific implementation. That way your subclasses could override that method to change the object being constructed, which can be useful if they need to hide data into the object.

The visitor pattern is often used for data structures containing a fixed set of types. Basically you have an interface that describes all of the concrete types your data structure contains. Then you pass a concrete instance of this interface (basically a vtable) to your data structure. The data data structure gives you an iterator over something that can "accept" a visitor. Then you iterate over those elements repeatedly having them "accept" your visitor. Why do this? It makes it easy to add new operations. However, it makes it hard to add new classes.

This is useful because it gives you double-dispatch (limited multiple-dispatch) and "exhaustive matching". This is nice you're writing a compiler where you want to describe any action you run on the AST. Compared to an if-else chain this ensures that all instances are covered at compile time.

This is rendered somewhat obsolete if you have sum types and exhaustive matching, like Rust's enum and match, or if you have multiple-dispatch like Julia. Basically you just have an iterator that yields an enum. Then you iterate over that and match on the enum to determine what operation you want to do.

The observer pattern is basically a way to do publish-subscribe computing using object-oriented code. A subject contains a set of observers which it notifies whenever something happens. The observers satisfy a interface, normally called notify which accepts some data. Whenever the subject has an event happen (like a mouse button clicking), it iterates over the set of observers it has to notify them of the event. The subject also has methods for registering and de-registering observers.

# Configuration Management

In general, you should treat configuration of your systems as code, where assets are tracked in a VCS (e.g. git). However, you still need to keep secrets secret. This can be done by either factoring them out and having them manually entered or encrypted.

This is like what ARC does with provisioning!

Some tools that help you with this are Ansible, Puppet, Chef, and even more.

# Continuous Integration / Continuous Deployment

Continuous integration uses many ideas with configuration management. It is the practice of automatically building, testing, and analyzing your software in response to every software change done. This allows you to more easily detect issues quickly and more automatically redeploy and upgrade the software in production.

This builds off of configuration management because to automatically build, test, and deploy your software because you need a way to automatically set up the machine to run.

Most often CI/CD runs in a very dumb way. Basically it doesn't reuse things and just destroys and rebuilds everything every time. There is work being done on incremental builds, reusing artifacts, and caching. It's a hard problem tho.

# Microservices

Microservices are a technique to make applications easier to maintain, upgrade, and scale. They do this by splitting up your single monolithic process into several smaller processes, i.e. microservices.

The main reason you wouldn't want to use microservices is often you don't need the fault-tolerance or scalability of microservices. Also, microservices can make software harder to maintain (e.g. have to maintain an API that could often change) and it makes your software harder to deploy.

# Design Metrics

Design metrics are objective ways to measure the quality of software design. These are heuristics and aren't a "silver bullet". That is some designs are ranked wrongly low and others wrongly high. In general we'll be discussing metrics on Java or Java-like languages but these metrics can be generalized.

One of the most basic metrics is lines of code, where more lines of code means more maintenance. This isn't always correct because sometimes really low lines of code means things are "magic" or needlessly obfuscated. How do you count? People disagree but I generally think you should count comments, braces, and everything else, that is run wc -l on the source code. That's because lines of code isn't a perfect metric and making it simple is nice.

Another metric for Java-like languages is number of classes or for other languages number of modules. In general you want a moderate amount of classes/modules that way each class/module is reasonably well-focused but also not overly segmented. Similarly you can measure the number of methods in the class

You can measure the cyclomatic complexity which is the number of decision points plus 1.

In general you also want high cohesiveness of a class. That is you want each class to do/be a single thing. You can measure this by drawing a graph of methods where each method and field is a node and each method or field a method references gets a directed edge. Then you can see whether you get significant groupings or should otherwise split the class.

On the other hand you generally want low coupling of a class. That is you want your pieces of software to be as orthogonal/independent as possible. You can measure this in a fairly complicated way which I won't show here, but basically there's two types of coupling: afferent coupling, which is the number of classes that depends on this class/package, and efferent coupling, which is the number of classes that this class/package depends on.

# Performance & Monitoring

Performance is how (well) the system performs under load and monitoring is the process of measuring performance while the system is operating.

There are two big things to measure that are somewhat independent: thruput and latency. Thruput is how many requests the system can process per second. Latency is how long it takes to service a request.

Performance testing is the process of running tests explicitly to identify performance regressions and performance improvements. This let's you figure out if the system will be able to handle load in production.

To do good performance testing, you need to figure out the workload your system will undergo. Often the workload depends on the operations or things your software system does. If you can enumerate all possible operations and their frequency of use (i.e. create an operational profile), we can create better (performance) tests and also better determine where to focus your energy for fixing bugs and improving performance. To get these operational profiles, you often need to do monitoring of the system or talking clients / domain experts.

What issues exist with performance testing? One of the biggest is that applications don't run in isolation. There may be other applications or even your operating system that are taking up resources. In the extreme case this can make your tests flakey (which we experience with Jenkins).

How do we collect data from a system? In terms of performance and stability data, we can get temperatures and other data from the hardware; memory usage, swap usage, and other things from the operating system. If we have middleware (e.g. Nginx), you can get log data from that and likewise for the application itself. In terms of user experience (UX) logs, the system can log how users interact with it so like what operations they use, what buttons they click, etc.

One way to understand performance of a system is using a flame graph, which is a graph of stack frames in your system over time. That way you can see what functions take the longest, which helps you determine what functions you need to optimize. In certain cases it can also help you find specific issues in your system. For example maybe there are a bunch of recursive calls which can be seen by extremely tall flames.

Here are some examples of metrics for a specific service, e.g. an e-commerce website.

  • Availability Rate: % of time system is up.
  • Conversion Rate: % of customers that buy something of those who just looked. Can also be done for referrals and anything else similar.
  • Mean Time Between Failures: Average time service is available between failures.
  • Mean Time To Repair: Average time service is down when a repair occurs.
  • Incident Count: How many incidents (e.g. failures) occur per unit of time (e.g. week).
  • Actions Per Second: How often does a given action occur in your system? For example how many purchases, logins, sign-ups, etc, depending on your system.

How do operations manage failures? A good system to have is to have an incident management plan, which is a series of steps which occur whenever a failure is detected.

There's also a green-amber-red light system, where you categorize the state of the system using a 3 light system. Green is everything working. Amber is some non-critical modules are failing. Red is the system has completely failed.

\ No newline at end of file diff --git a/notes/ncsu/3f/csc412/ast_v_dag.png b/notes/ncsu/3f/csc412/ast_v_dag.png new file mode 100644 index 0000000..d631fab Binary files /dev/null and b/notes/ncsu/3f/csc412/ast_v_dag.png differ diff --git a/notes/ncsu/3f/csc412/frontend.png b/notes/ncsu/3f/csc412/frontend.png new file mode 100644 index 0000000..5d01539 Binary files /dev/null and b/notes/ncsu/3f/csc412/frontend.png differ diff --git a/notes/ncsu/3f/csc412/index.html b/notes/ncsu/3f/csc412/index.html new file mode 100644 index 0000000..4564a02 --- /dev/null +++ b/notes/ncsu/3f/csc412/index.html @@ -0,0 +1,475 @@ +Eli | CSC 412: Compiler Construction

CSC 412: Compiler Construction

Instructor: Dr. Xu Liu | Semester: Fall 2020

Table of Contents

# Administrivia

WeightComponentAdditional Info
30%Midterm
50%Project4 Projects (3 C/C++, 1 Python)
20%AssignmentsAll homework written.
  • TA: Abhijeet Krishnan
  • No final
  • Testing done in Virtual Computing Lab (VCL).
  • Projects may be different between 412 and 512.
  • Attendance: Required via Zoom. Need to email ahead of time if will be absent.
  • We do not discuss linking or assembling specifically here.

# Overview of Compilers

  • Compiler: Tool for analyzing and transforming high level programs into some executable form. Compilers often include optimizations to improve performance of the code.
  • Types of Compiler: Compilers are often categorized by similar properties.
    • Traditional: High-level to low-level (machine code, bytecode, hardware FPGA/ASIC).
      • C, C++, Rust
    • Source-to-source/Transpiler: Produce source code for a different similarly high-level language from another language.
      • Typescript, Moonscript.
    • Just-in-Time (JIT): Compiles at runtime often doing tracing or other performance-guided-optimizations.
      • Java (always uses bytecode but will JIT hot code)
    • Decompiler: Low-level to high-level.
    • Cross Compiler: Generate code for a machine different than the host running the compiler.
    • Binary Recompiler: Binary/machine-code to another binary/machine-code. Often useful for introducing tracing or other instructions.
  • Intermediate Representation: A low-level machine-code-like language that is architecture agnostic. Allows for easier optimizations and allows easier support for more languages and hosts.
    • Examples: GIMPLE (gcc's IR), LLVM IR.
  • Interpreter: Program that runs the source code directly. Or at least appears to do so; many interpreters do internal compilation. This is good because they are easy to write.
  • Activation Record: Stack frame.

Compilers normally go through the following steps: (front-end) preprocessing, lexical analysis, parsing, (middle-end) semantic analysis, IR conversion, code optimization, and (back-end) code generation.

One of the hardest parts of compilers is (user-friendly) error propagation. All parts can produce errors and the error chain can be very deep and complex.

## Three-Pass Compiler

Many compilers follow a three-pass system, with a front-end taking in source code and producing IR, middle-end taking in and producing IR, and back-end taking in IR and producing the final output.

The front-end lexes and parses the source code, producing an AST. It then does a bunch of analysis on the AST, such as type-checking. Then it produces IR. This class mostly covers front-end. It is normally O(n) or O(nlog(n))

The middle-end optimizes the IR a bunch. This is normally NPC (NP-Complete). This class does not touch the middle-end.

The back-end produces machine-code (or other output formats) from the IR. This is normally NPC (NP-Complete) because of register allocation. This class does some back-end.

# Front-end

The frontend first scans the code to produce tokens. Then parses the token stream to an AST. Then it does a bunch of analysis on the AST.

## Scanner

A scanner reads the raw text of the file and extracts the interesting tokens from it. This allows the parser to deal with higher-level tokens which makes it easier. It also allows handling error handling/reporting information to be more contained.

A scanner is the easiest part to implement normally and can even be done by a scanner generator. It can be done lazily (doesn't scan tokens until requested) or greedily (produces all tokens as soon as possible). A scanner generator takes descriptions of the tokens normally using regular expressions to generate a scanner.

I won't talk much about the theory here because CSC 333 was pretty extensive. But basically regular expressions are formally equivalent to finite automata (FA). Languages (i.e. sets of strings of symbols) recognized by finite automata are called FA and are closed under union , intersection , and Kleene star/closure which is 0 or more concatenations of strings from the language. We use ε to denote the empty string.

Note: We often insert a special EOF token at the end of the stream to make sure parsing end successfully.

Normally, reserved words or keywords (e.g. for) match all the rules for identifiers. To handle this, whenever we finish an identifier we see if the identifier is a reserved word / keyword and instead return a token for that keyword rather than a generic identifier token.

### Tokenizing

How do you split a series of characters into tokens? You could use the simple "I need a delimiter" rule (e.g. every token is separated by space), but often people want to write stuff like foo();. Also, sometimes you get code like this which can be surprisingly hard.

intv1=35+v33;
+

In general this is done by greedily finding the current word as long as it's legal. If you end in a legal state, then you just made a token and can return to the start state. If you end in an illegal state, then you have reached an error and report it.

### Types of Scanners

Fundamentally scanners run on DFAs. There are many way to build a DFA/scanner in code.

A table-driven scanner essentially just has a giant lookup table where your row is the current state and your column is the input. At every iteration, you look up in the table using your current state and your input to get the cell in the table which is your next state. This is somewhat memory inefficient (tables can be very big) but easy to code and maintain.

A direct-coded scanner is generally more efficient in terms of memory than the table-driven scanner and somewhat more efficient in terms of runtime. It can be less readable and somewhat harder to maintain though. In practice it's not that hard though. This is the kind of scanner you would make if you made one by hand. You read in a character, switch on the state, and then manually do the comparisons as you want.

### Scanner/DFA Optimization

To improve performance of DFAs (especially important for scanner generators), we normally use the following

  • RE to NFA: Build an NFA for each term, combine them all with ε-moves / ε-edges.
  • NFA to DFA: Build the simulation using subset construction.
  • DFA to Minimal DFA: Use Hopcroft's algorithm to minimize the number of states. Can reduce the number of states a LOT.
  • DFA to RE:
    • Why do this? It can give you a simpler RE.

Thompson's construction works by converting the 4 basic possible regular expression operators into an NFA, as shown below. This works on the AST of the parsed regular expressions.

Thompson's Construction

This however produces an extremely large and inefficient FA. However, it is always correct and we have algorithms to optimize them later.

## Parser

The cheif job of the parser is to product an abstract syntax tree (AST). To do this, the parser uses a formal grammer. Sometimes, finalizing the abstract syntax tree (e.g. in cases of overloading), we need to do context sensitive analysis (e.g. type analysis) that cannot be done by the parser.

### Grammars

Before we understand grammars, we need to understand their representation. We use Backus-Naur form. The Backus-Naur form describes a grammar as a set of productions, where a production is a mapping from a lefthand side to a righthand side with an arrow from left to right. There are non-terminal symbols, represented by a capital letters, called such because a valid string in a language cannot have a non-terminal symbol. There are terminal symbols, represented by lowercase letters, called such because there are a valid symbol in the alphabet.

We use a slightly modified version where we can use non-terminals with multiple letters in their names. To remain unambiguous, our multi-character non-terminals start with uppercase letters and have whitespace around them. Similarly, complex non-terminals (recognized by regular expressions) are wrapped in angle brackets < and >.

Every string s in the language recognized by a grammar has a derivation, that is a series of productions that can be applied, starting at the start symbol, to produce / arrive at s. The discovering of a derivation is called parsing.

For review, A regular grammar is a grammar where every production has at most one righthand non-terminal symbol and arbitrarily many lefthand terminal symbols. There can be no lefthand non-terminals and no righthand terminals.

# Not regular grammar
+S -> AB
+A -> aA | \e
+B -> bB | \e
+
+# Previous grammar rewritten to be regular
+A -> aA | B
+B -> bB | \e
+
+# Different no-variable grammar
+S -> ab | aabb | aaabbb
+

In context-free grammar you have a set of productions from a single non-terminal to a series of non-terminals or terminals. If you had multiple non-terminals and terminals on the left hand side, then it would be a context-sensitive grammar

# Recognizes a^nb^n. This is context-free.
+A -> aAb | \e
+# Recognizes a^nb^n n > 1. Also context-free
+A -> aAb | aabb
+
+# This is context-sensitive.
+AB -> ...
+

Parsers are normally driven by context-free grammars rather than context-sensitive grammars because they are easy to implement, easy for humans to understand, and fairly expressive. Basically they're a happy medium.

Grammars can be ambiguous, how can we formally classify that? We can't just say a grammar that has multiple possible derivations for a string because then if we have multiple non-terminals at a time then it has derivations depending on whether you derive the left or right first. To get around this, we say a grammar is an ambiguous grammar if it has multiple leftmost derivations (or equivalently multiple rightmost derivations), where a leftmost/rightmost derivation is where you always choose the leftmost or rightmost non-terminal symbol to expand respectively.

We do not want the grammars we design to be ambiguous because otherwise people will be surprised by our parser's behavior and there's a good chance that we will introduce bugs by accidentally switching from preferring one ambiguity to the other. Also, we often like to use our parser's grammar to produce an AST that we can then use to help analyze and execute the code. For example, we normally do a post-order walk of binary expressions (e.g. arithmetic) to determine which ones we should do first. Using a post-order walk ensures that expressions lower in the AST get executed first.

TODO: Get image from slide

This ambiguity typically occurs when defining arithmetic operations. A naive grammar for arithmetic would be

Expr -> Expr Op Expr
+Expr -> [id] | [num]
+Op -> + | - | * | /
+

However, this is ambiguous, which is a real problem if we want to embed order of operations in an AST. We can handle this in two main ways. Use some sort of precedence parsing, like Pratt parsing, where we give some numbers to our operators which then changes the parser to be unambiguous and take care of precedence. This can be easier to extend but harder to write initially. Alternatively, we can modify the grammar to take care of precedence. Ultimately it's up to a matter of preference. In this class we will modify the grammar. Here is arithmetic operations rewritten to take care of order of operations. You can give these names without numbers but that makes it harder to understand I think.

# Expr is human-friendly alias for the top level
+Expr -> L2
+L2 -> L2 + L1 | L1 - L1 | L1
+L1 -> L1 * L0 | L1 / L0 | L0
+L0 -> Atom
+# Atom is a human-friendly alias for the bottom
+# level
+Atom -> [id] | [num] | ( Expr )
+

But wait, isn't + and - still ambiguous? Nope! Notice that the left non-terminal side is the same level but the right non-terminal is at a lower level. This can have issues with left recursion, but this can again be trivially rewritten using something like

# Left recursive
+L1 -> L1 * L0
+# Not left recursive, uses {...} repetition.
+# Quoted symbols are not magical. Unquoted are
+# magic.
+L1 -> L0 { "*" L0 }
+

There are two ways of parsing we will discuss. There is top-down parsing, normally done with hand-coded recursive descent parsers. There is also bottom-up parsing, which normally uses a parser generator. There are many types such as LR(1) parsers, PEG parsers, etc.

### Top-Down Parsers

Top down parsers are called such because they first start at the start state and gradually get more and more specific. They start at the root of the parse tree and grow towards the leaves. They do this by picking a production and trying to match the input. However, if they pick the incorrect production, they may need to backtrack. Certain languages/grammars are designed such that it is always possible to pick the correct production. This is called predictive parsing.

We in general discuss recursive descent parsers as the classical top down parser. To create a recursive descent parser, you convert every production into a function that returns the AST node produced by the production. If the part of our production is a non-terminal, we call the production for it. If it is a terminal, check that the next token matches. If we have a repetition, like { expr }, we keep matching expr as much as we can. If we have an alternation, like a | b | c, we try each production in series until we get one that works. (As an optimization, we can match on the first token and switch directly to that production if we have enough data to prodict the correct production.) If we have an optinonal, like [ a ], we try to match a but if we fail we don't do anything.

Here is Rust-like pseudo-code for a recursive descent parser.

// A -> aA | bB
+// B -> bBc | c
+impl Parse for TokenStream {
+  fn A(&self) -> AstNode {
+    let node = AstNode::new();
+    match self.peek() {
+      'a' => {
+        node.push(self.next());
+        node.push(self.A());
+      }
+      'b' => {
+        node.push(self.next());
+        node.push(self.B());
+      }
+      _ => todo!("do real error handling"),
+    }
+    node
+  }
+}
+

Top down parsers have one big weakness. Left recursion. Left recursion is when you have a production like A -> A B. In this case, the leftmost symbol always generates itself and we cannot do any matching, instead just looping forever. To get around this, we "unroll" the left recursion into right recursion using repetition. So A -> A B would become A -> { B }. Basically, you make the non-left-recursive branch be its own thing at the start and make all the left-recursive branches be repetitions (with the left-recursion removed). Here's another annotated example.

# Left recursive!
+Fee -> Fee a | b
+
+# b was the only terminating branch so it
+# becomes the start. Fee a was the
+# non-terminating branch, so we repeat it.
+Fee -> b { a }
+
+# We could do this more formally with this. It's
+# identical to the above.
+Fee -> b Fee'
+Fee' -> a Fee' | \e
+

More formally, what we do is introduce a new non-terminal A for every left-recursive non-terminal A. The new A goes to the terminating branch of the old A and the new A goes to the A non-terminating old branch or the empty string ε. If that sounds confusing, read the following transformations. Basically, A is the formal way to do { ... }.

# Class left-recursive expression grammar
+Expr -> Expr + Term | Expr - Term | Term
+Term -> Term * Atom | Term / Atom | Atom
+
+# Rewritten not left-recursive expression
+# grammar
+Expr -> Term Expr'
+Expr' -> + Term Expr' | - Term | \e
+Term -> Atom Term'
+Term' -> * Atom | / Atom | \e
+

Not all left-recursion is obvious. We can have indirect left-recursion where you have to go through multiple steps initially. See the below example. The same algorithm works.

A -> B a
+B -> C b
+C -> A c | \e
+

Another less important weakness is it is impossible to "look-ahead" at tokens and make decisions based on that. Meaning that grammars like A -> aB | aC are impossible to parse with (formally) recursive descent parsers.

We would like to design grammars that can be parsed with recursive descent parsers. That is, we would like a predictive parser. For this to be possible, our grammar needs to LL(1) property. LL(1) means left-to-right scanning, leftmost derivation, one lookahead.

We define first(α) where αTNT as the set of symbols that are the first symbols in a string that derives from α. That is, xfirst(α) iff αxγ for some γ. We allow αT because αα.

We define follow(α) where αNT as the set of symbols that can occur immediately after α in a valid sequence.

We define first+(α) as first+(α)=first(α)follow(α)

A grammar LL(1) property of a grammar means that if we have rules Aα and Aβ both in the grammar, we would like first(α)first(β)=. This would mean that the grammar can look ahead a single token x. If xfirst(α) then pick α, if xfirst(β), then pick β, otherwise error.

Let's look at a non LL(1) grammar.

1. A -> aAb
+2. A -> bB
+3. A -> \e
+4. B -> b
+

Consider the string abbb. When doing recursive descent paring, we could get the following two tables
RuleSentential FormInput
A!abbb
1aAba!bbb
2abBba!bbb
RuleSentential FormInput
A!abbb
1aAba!bbb
3?aba!bbb

We can transform some (not all!) process is called left-factoring. Whenever you have an ambiguous choice, you factor out the first symbol which you have an ambiguous choice to a new common non-terminal. However, given a CFG doesn't meet the LL(1) condition, it is undecidable whether or not an equivalent an LL(1) grammar exists.

Here is an example of a language which has no LL(1) grammar.

L=an0bnan1b2n

Here is a CFG to recognize L

S -> A | B
+A -> aAb | a0b
+B -> aBbb | a1bb
+

You need an unbounded number of a characters before you can figure out whether to pick A or B. That is, if you say you only need n, I can give you a string that requires n+1.

Example: Is the following grammar an LL(1) grammar?

G -> M [num] "." [num]
+G -> N
+M -> "-"
+M -> \e
+N -> [num]
+

This is not an LL(1) grammar. first+(M)="-",[num] first+(N)=[num]. Means that first+(M)first+(N).

We can rewrite this grammar to be LL(1) as such

G -> "-" [num] "." [num]
+G -> [num] "." [num]
+D -> "." [num]
+D -> \e
+

Example: Convert the following grammar into an LL(1) grammar with no left-recursion.

G -> M N
+M -> a b
+M -> \e
+N -> N a
+N -> \e
+
+# Eliminate left recursion
+G -> M N
+M -> a b
+M -> \e
+N -> \e N'
+N' -> a N'
+N' -> \e
+# Simplify
+G -> M N
+G -> N
+M -> a b
+N -> a N
+N -> \e
+
+# Make LL(1)
+# Realize that M and N can both start with a.
+# Factor that out.
+G -> \e
+G -> a G'
+G' -> b N
+G' -> N
+N -> a N
+N -> \e
+
+# We're done!
+

Example: Let's apply our algorithm to show that not all grammars are LL(1). (Well, really to just give you the idea that not all are. We haven't shown our algorithm always works.)

G -> aAb | aBbb
+A -> aAb | 0
+B -> aBbb | 1
+
+# Factor out common a in G
+G -> a G1
+G1 -> Ab
+    | Bbb
+A -> aAb | 0
+B -> aBbb | 1
+# Simpler
+G -> a G1
+G1 -> aAbb
+    | 0b
+    | aBbbbb
+    | 1bb
+A -> aAb | 0
+B -> aBbb | 1
+
+# Factor out common a in G1
+G -> a G1
+G1 -> G2
+    | 0b
+    | 1bb
+G2 -> Abb
+    | Bbbbb
+A -> aAb | 0
+B -> aBbb | 1
+# Simpler
+G -> a G1
+G1 -> G2
+    | 0b
+    | 1bb
+G2 -> aAbbb
+    | 0bb
+    | aBbbbbbb
+    | 1bbbb
+A -> aAb | 0
+B -> aBbb | 1
+
+# Oh no, we have to factor out a common a again.
+# We're stuck in an infinite loop...
+

As we've gone over, here's the rough procedure for converting an LL(1) grammar into a recursive descent parser.

  1. Remove left recursion via intermediate rules / repetitions.
  2. Massage the grammar (removing empty / redundant rules).
  3. Do left-factoring until you get rid of all ambiguous rules. (You may have to massage the grammar to make it more obvious.)

#### Table-Based Recursive Descent Parser

If we're auto-generating a recursive descent parser, one of the easiest ways to do it is to encode your grammar as a giant token-production table because then all you have to do is write a table-driven parser which itself is pretty easy.

The table format is every row is a production to follow and the column is the token received. Then your parser keeps track of its current state/row/production, starting at the start state. It checks what the next token is and determines the next production to check.

class TableParser:
+  """Table driven parser in pseudo-python."""
+
+  def parse(self, tokens):
+    """
+    This is like a recursive descent parser
+    except we use a loop with a stack because,
+    well, that's exactly what recursion does but
+    we have to have generic code so it's easier
+    to loop like this. (Well, at least that's
+    what we say.)
+    """
+    # processing is the current non-terminal or
+    # terminal we're processing
+    processing = Stack()
+    processing.push(EOF)
+    while True:
+      want = processing.peek()
+      got = tokens.peek()
+      if want == EOF and want == EOF:
+        return AST
+      elif instanceof(Terminal, want):
+        if want == got:
+          processing.next()
+          tokens.next()
+        else:
+          raise Error(
+            f"expected {want}, got {got}"
+          )
+      else:
+        # A -> B1 B2 ... Bn
+        new_wants = self.table[want][got]
+        if new_wants is None:
+          raise Error(
+            f"unexpected token for {want}"
+          )
+        else:
+          processing.next()
+          # Push Bn ... B1
+          # This is so B1 is on top
+          for w in reversed(new_wants):
+            processing.push(w)
+

Many high-quality programming languages opt for hand-written parsers because, as you can see above, the error messages are lack-luster and it is hard to give higher quality error messages. Also, the code takes more memory and normally isn't faster.

### Bottom-Up Parsers

Bottom up parsers are called such because they start at the leaves gradually build up the abstract syntax tree. Bottom up parsers big weakness is that they do not have very good error reporting. However, they can parse more languages by their nature and they also require no changes to grammars to handle, for example, left-recursion and right-recursion elegantly.

We will be discussing LR(1) parsers as the class bottom-up parser. They are named similarly to LL(1). LR(1) means left-to-right scanning, rightmost derivation, one lookahead.

TODO: Watch lecture video

## Context Sensitive Analysis

This is where we do type checking and other semantic analysis, like undeclared variable usage.

For example, this is a type argument mismatch. A parser cannot identify this error so we don't call it a syntax error. Instead this is a semantic error.

void foo(int a);
+void main() {
+  foo("Hi");
+}
+

Similarly, this is use of an undeclared variable.

void main() {
+  printf("a %s", a);
+}
+

Why can't the parser detect semantic errors? Semantic errors often require depending on values, non-local information, and computed information.

There are two main approaches to doing semantic analysis: ad-hoc syntax-directed translation and attribute grammars.

### Ad-Hoc Syntax-Directed Translation

To do syntax-directed translation as we discuss here, you associate code with every single production. This code is run while you're parsing, running after every production is taken.

Often, computations require some initialization of data (e.g. allocating data). To do this formally we create a Init variable that derives to \e that does all initialization. For example, with determining the cost of executing a basic block. In practice though, we just add some initialization code at the start element. Something like this

Start -> Init BB
+Init -> \e  # cost = 0
+BB...  # cost += cost(...)
+

This could be done by a parser generator. Here's a concrete example using YACC.

# $$ refers to the attribute on the lhs
+# $n refers to the attribute on the nth element
+# of the rhs
+Assign -> Ident = Expr;  $$ <- COST(store) + $3
+Expr -> Expr + Term;  $$ <- $1 + COST(add) + $3
+

Because you are just associating code with productions, this is incredibly flexible. This does restrict the evaluation order to be whatever order you parse things in.

Often though if you're doing ad-hoc syntax-directed translation, you won't be using a parser generator because that makes it (generally) easier to write. Why would you ever not use a parser generator? Error messages. Error handling. Maintainability.

### Attribute Grammar

Another similar example is attribute grammars.

An attribute with additional semantic analysis code an attribute grammar. An attribute grammar is a normal CFG augmented with a set of rules. Every symbol in a derivation has a set of attributes (e.g. they're structs) and every production has a code snippet that describes how to compute a value for each attribute.

Here is an example using pseudo-code. It comes the decimal value of a signed binary number.

Number -> Sign List {
+  List.pos = 0
+  Number.val = if Sign.neg {
+    -List.val
+  } else {
+    List.val
+  }
+}
+
+Sign -> + { Sign.neg = false }
+Sign -> - { Sign.neg = true }
+
+List0 -> List1 Bit {
+  List1.pos = List0.pos + 1
+  Bit.pos = List0.pos
+  List0.val = List1.val + Bit.val
+}
+List0 -> Bit {
+  Bit.pos = List.pos
+  Bit.val = List.val
+}
+
+Bit -> 0 { Bit.val = 0 }
+Bit -> 1 { Bit.val = 2**Bit.pos }
+

We can make a graph of how the attributes are computed by an AST with a list of each nodes attributes. For every attribute, we draw an arrow from what the value depends on. For example, List1.pos = List0.pos + 1 means that List1.pos depends on List0.pos. This graph must be acyclic for all graphs, otherwise the computation would (possibly) never terminate.

One of the weaknesses(?) of attribute grammars is the lack of global variables.

## Type Checking

Type checking is a form of correctness verification. It helps statically prevent certain errors. Type checking is the process of determining whether type expressions conform to the type system, that is a collection on rules for types, of the language.

Some languages support type inference, which allows the developer to not define the type of a given variable and instead the compiler will infer it from context.

We call a language's type system sound if no runtime checking is necessary to ensure that the program experiences no type errors at runtime.

When we are type checking, we need to determine when two types are equivalent. There are two main ways to define this type equivalence: structural equivalence and name/nominal equivalence. Two types are structurally equivalent if their types have the same "shape". Two types are nominally equivalent if their types are lexically defined the same. In the below example v1 and v3 are structurally equivalent and v1 and v2 are nominally equivalent.

typedef struct { int a; int b; } X;
+typedef struct { int a; int b; } Y;
+X v1, v2;
+Y v3;
+

Some people think such strict type-checking / type-equivalence is annoying or needlessly restrictive. To make this easier certain languages support casts, which explicitly convert two types using essentially built-in conversion mechanisms, or coercions, which are like casts but implicit. If two types are structurally equivalent, the cast has no cost at runtime. If two types are not structurally equivalent, the compiler has to insert simple instructions to for example increase the width of the number. Depending on the languages semantics for casts and coercions, these can cause unexpected bugs or vulnerabilities. For example C will implicitly coerce numbers which may result in integer wraparound which introduces bugs or can even be insecurely optimized by the compiler (since integer wraparound is undefined).

How do we determine the type of expressions? We do this using type synthesis. Basically the compiler has a list of rules which it either has for built-ins (e.g. int + float -> float or int * int -> int) or determines from analyzing the source code. For example given a declaration like this

int write(char *s) {
+  // ...
+}
+

If the compiler would saw an expression like write(a), it would determine that a has type char * and would determine that the entire expression has type int.

### Polymorphism

Polymorphism is a really vague term that basically just means that a function or method or class can work with multiple different type.

One of the classic methods for doing polymorphism is dynamic dispatch with vtables. Java and Go use this with their interfaces and C++ does it with virtual methods. However, these polymorphic method still need to check their type. But this time we aren't just doing simple type equality because we can accept many different types. How do we handle this?

Normally, we use interfaces or abstract classes, or the generic name of subtyping. With interfaces or abstract classes we declare the behaviors that the given type must have to be used in place of those interfaces. Languages like Java and C++ use nominal subtyping, where the type must explicitly says it implements that abstract class, while languages like Go use structural subtyping, where the types must implement all the necessary methods. Then when we try to provide a concrete class to an abstract class our concrete class must be a subtype of the abstract class (in a way stated before). What if we want to assign an abstract class to another abstract class? Then the provided abstract class must be a subtype of the necessary abstract class. This is done using the same mechanisms where the given abstract class must explicitly implement/inherent from the necessary abstract class or must provide the necessary methods.

Note: All types are considered trivial subtypes of themselves.

There is also parametric polymorphism, which is the classic generics. Here you statically provide types to a function. This follows all the same subtyping requirements of inheritance. However, here all the subtyping is done at compile time so the language can guarantee more optimizations by not requiring vtables and dynamic dispatch.

With dynamic dispatch and especially deeply nested inheritance trees, the overhead necessary to call a virtual method can be very expensive as you have to follow many different points.

# Middle-end

Concerned with optimizations of the code. Often do multiple passes using different optimization methods because certain optimizations are more effective after another or benefit from running multiple times. Must not change the meaning of the code.

Core to the middle-end is the intermediate representation (IR) used. There are many IRs that exist that focus on certain things like ease of optimizing, ease of use, level of abstraction, speed of generation, etc. When designing or choosing an IR, you have to carefully design it to optimize it for your use case.

There are three main types of IRs:

  • Structural: Graph/Tree based code.
    • Rust's HIR.
  • Linear: Pseudo-assembly for an abstract machine.
    • LLVM IR.
  • Hybrid: Combination of structural and linear used.
    • Control-flow graph.

## Structural IR

The canonical structural IR is the abstract syntax tree (AST). This is where every node in your program gets a single node. It is the starting point of most other forms and even several optimizations, since it is directly what you get from the source code. It is like the parse tree except simplified to make it easier to use.

Similar to the AST, you can construct a directed acyclic graph (DAG), which is like a tree except branches can go down more than one level and multiple edges (arrows) can point to the same node. This is useful for identifying shared code/expressions, allowing for reducing code motion.

Tree vs DAG for Abstract Syntax

## Linear IR

Linear code tends to be much closer to machine code, often being designed (generally) as more heavily annotated, higher level assembly. They can make low level optimizations (e.g. register allocation) much easier but make analyzing higher level control flow more difficult.

There is stack machine code, which is mostly used for virtual machines because they are easy to implement. Every operation acts on a global stack except for push and pop. push pushes a new value from memory or immediate onto the stack. pop pops the top value from the stack and stores it into memory.

There is three address code which is like assembly except every operation can only have exactly 3 operands. For example r0 = r1 + r2 is a three address code but r0 = r1 + 2 * r2 is not (2 is an immediate and considered an address). This is essentially a generic assembly, because most real hardware have 1-3 operands per instruction, so this maps nicely.

There is static single assignment (SSA) form, which is actually the most popular linear form used in major compilers today. SSA means that every variable/register is written/set exactly once but can be read/used infinitely many times. This makes analyzing code flow and statement dependency very easy.

To make SSA work, we need to do renaming and ϕ functions. Renaming is the process of changing to the name of a variable whenever it is written/mutated. The ϕ function is conceptually like a union. It takes multiple different variables and returns one of them at runtime, meaning you can't determine which at compile time. If you have x2ϕ(x0,x1), then x2 depends on both x0 and x1.

## Hybrid IR

The control flow graph is a graph of how the code flows. You've probably studied it significantly in earlier classes, it's that graph that shows loops and logical branches like a graph. This is useful for higher level optimizations like combining loops, switching loops, and dead code elimination.

## LLVM Project

The LLVM project is a large project to produce high quality machine code for a wide range of architectures and wide range of languages. The LLVM project is a collection of optimizers on the LLVM IR (bundled into the opt binary), converting low quality IR to high quality IR, and then backends that produce machine code for various architectures (bundled into llc).

Then, new language designers simply need to emit LLVM IR (doesn't even need to be high quality) and suddenly their language will produce high quality machine for a wide variety of architectures. The core part of LLVM is the IR definition and the optimizers.

Since the LLVM project is a common project for academics who experiment with optimizations work on optimizations and has great industry support, it produces incredibly high quality machine code.

### LLVM IR

Here is the LLVM IR assembly language reference: https://llvm.org/docs/LangRef.html

The LLVM project uses static single assignment (SSA) IR called LLVM bitcode. It's call bitcode because normally tools use a binary format for efficiency and simplicity. There is also a human readable version that is kinda like RISC assembly code except with infinite registers, types, structs, an understanding of functions, and tons of instructions and annotations, like phi, align, global, etc. All of this makes LLVM IR easy to analyze and high level enough to be efficiently implemented on many machines.

Here are a bunch of examples of how some C code could compile to LLVM IR. These examples were cleaned up from examples with Clang 10 -emit-llvm -O1. You can play around with this on Godbolt Compiler Explorer.

#### Example 1

##### C
int square(int num) {
+  return num * num;
+}
+
##### LLVM
; %[name] is a register. You can give them any
+; name but compilers tend to produce just
+; incrementing numbers for simplicity. This is C
+; so it's name is mangled like it would be in
+; C++ or Rust.
+define i32 @square(i32 %num) {
+  %1 = alloca i32
+  store i32 %num, i32* %1
+  %2 = load i32* %1
+  %3 = load i32* %1
+  %4 = mul i32 %2, %3
+  ret i32 %4
+}
+

#### Example 2

##### C
int array[100];
+int x
+
+struct list {
+  int x;
+  struct list *next;
+};
+
##### LLVM
%struct.list = type { i32, %struct.list* }
+
+@array =
+  global [100 x i32] zeroinitializer, align 16
+@x = global i32 0, align 4
+

#### Example 3

##### C
int *ptr;
+ptr = ptr + 1;
+
##### LLVM
%ptr = alloca i32*
+%1 = load i32** %ptr
+%2 = getelementptr i32* %1, i64 1 ; add 1 to ptr
+; now %2 is the new pointer
+

#### Example 4

##### C
int max(int *x, int y) {
+  if (x && *x > y) {
+    return *x;
+  } else {
+    return y;
+  }
+}
+
##### LLVM
define i32 @max(i32* readonly %0, i32 %1) {
+; if (x && %4) {
+;   ...
+; } else {
+;   %7
+; }
+  %3 = icmp eq i32* %0, null
+  br i1 %3, label %7, label %4
+
+; if (... *x > y) {
+;   return *x;
+; } else {
+;   %7
+; }
+4:
+  ; t = *x
+  %5 = load i32, i32* %0, align 4
+  ; t > y
+  %6 = icmp sgt i32 %5, %1
+  ; return t or y
+  br il %6, label %8, label %7
+
+; return y
+7:
+  br label %8
+
+8:
+  ; if from 7, return y
+  ; if from 4, return t = *x
+  %9 = phi i32 [ %1, %7 ], [ %5, %4 ]
+  ret i32 %9
+}
+

Some things you can notice is that LLVM IR avoids explicitly representing the stack. This is to more easily support a wider range of machines. It uses alloca instead to represent the stack.

It also organizes code into functions with explicit arguments and return instructions. And then functions are organized into modules (by file). Every module is held in memory in a single large data structure. This allows for optimization on a large amount of the program. However, it is not possible to optimize across module (by the compiler). Instead it is done by the linker at link time, called link time optimization (LTO).

## Optimizations

There are several clever optimizations that people have thought up for compilers. There are way too many for us to go over extensively.

We structure code in basic blocks. If we recognize the connections between these basic blocks in the control flow diagram, we can eliminate dead code, remove unnecessary jump instructions, unlock future optimizations.

TODO: Get from 10/21

Constant propagation is the process of evaluating as much code at compile time as you can. Typically this is done by doing arithmetic on constants to result in a smaller simple constant, potentially removing expensive instructions. In the above example, we could simplify someNum() to just 147.3 which could then be inlined as a constant.

double someNum() {
+  int a = 3;
+  double b = 49.3;
+  return a * b;
+}
+

Strength reduction is the process of replacing expensive instructions with cheaper instructions. For example integer division by 32 can be simplified to a left shift by 5. In fact a lot of multiplications and divisions have extremely clever optimizations like that. If you're iterating over an array using an incrementing index, that can be optimized by a pointer which is just being incremented, replacing an increment, multiplication, and addition with a single addition every loop. Here's an example of a few.

// division replaced with left shift
+void division(int a) {
+  return a / 32;
+}
+void division(int a) {
+  return a >> 5;
+}
+
+// incrementing index replaced with pointer
+void arrayIndex(int arr[], size_t n) {
+  for (size_t i = 0; i < n; i++) {
+    arr[i] = 0;
+  }
+}
+void arrayIndex(int arr[], size_t n) {
+  int *end = arr + n;
+  int *p = arr;
+  // in asm p++ would be ptr += sizeof(*p)
+  for (; p != end; p++) {
+    *p = 0;
+  }
+}
+

Reducing code motion is where you take some identify some expression that is being repeatedly evaluated (e.g. in a loop). If that expression has no side effects and doesn't depend on any values changing in the loop, then you can evaluate that expression once and then store it in a temporary that you repeated reference. Here is an example.

// Calculate the nth prime, very expensive.
+size_t nthPrime(size_t n);
+
+// This technically evaluates nthPrime every
+// time, which is very expensive.
+void codeMotion(size_t n) {
+  for (size_t i = 0; i < nthPrime(n); i++) {
+    printf("%d\n", i);
+  }
+}
+// This code is equivalent and evaluate nthPrime
+// only once.
+void codeMotion(size_t n) {
+  size_t end = nthPrime(n)
+  for (size_t i = 0; i < end; i++) {
+    printf("%d\n", i);
+  }
+}
+

Loop unrolling is where you eliminate some jump instructions at the exchange of code bloat by duplicating the code within the loop multiple times. Below is C code with its unrolled version below. This isn't a great example because you don't really reduce the amount of instructions necessary or unlock auto-vectorization optimizations.

// rolled up loop
+void printNums(size_t n) {
+  for (size_t i = 0; i < n; i++) {
+    printf("%d\n", i);
+  }
+}
+
+// unrolled loop by 4
+void printNums(size_t n) {
+  size_t i = 0;
+  // Handle when n % 4 != 0
+  switch (n % 4) {
+  case 3:
+    printf("%d\n", i++)
+  case 2:
+    printf("%d\n", i++)
+  case 1:
+    printf("%d\n", i++)
+  case 0:
+  }
+  for (; i < n; i += 4) {
+    printf("%d\n", i);
+    printf("%d\n", i + 1);
+    printf("%d\n", i + 2);
+    printf("%d\n", i + 3);
+  }
+}
+

Loop unswitching is the process of extracting branches within a loop to outside of the loop. This changes the number of comparisons necessary to finish the loop from n to 1, which can make the loop way more efficient to run by itself by reducing the number of jumps and (in some cases) improving instruction cache locality. It can also unlock auto-vectorization. Here is an example of a loop and its unswitched version.

// original loop
+void printStuff(size_t n, bool a) {
+  for (size_t i = 0; i < n; i++) {
+    if (a) {
+      printf("a\n");
+    } else {
+      printf("b\n");
+    }
+  }
+}
+
+// unswitched loop
+void printNums(size_t n, bool a) {
+  if (a) {
+    for (size_t i = 0; i < n; i++) {
+      printf("a\n");
+    }
+  } else {
+    for (size_t i = 0; i < n; i++) {
+      printf("b\n");
+    }
+  }
+}
+

### Caches and Optimizations

TODO: Get from 10/21 lecture

False sharing is when two concurrently running processes continuously read and write memory from the same cache line, even when the memory that they're actually using is different. This is especially impactful when the two processes are running on different CPUs. This means that every time one process writes to the memory in the same cache line, it has to load it from the cache and invalidate the other processes memory. This means that when the other process next tries to write to that memory in the same cache line, it has to load it from memory and invalidate the other processes memory. This results in your processes continuously copying the cache line back and forth, thrashing memory and wasting a ton of time.

This example below results in false sharing (taken from Wikipedia), where sum_x needs to continually re-read x from main memory (instead of cache) even though inc_y's concurrent modification of y is irrelevant.

struct foo {
+  int x;
+  int y;
+};
+
+static struct foo f;
+
+// The two following functions are running
+// concurrently
+int sum_x(void) {
+  int s = 0;
+  for (int i = 0; i < 1000000; ++i) {
+    s += f.x;
+  }
+  return s;
+}
+
+void inc_y(void) {
+  for (int i = 0; i < 1000000; ++i) {
+    ++f.y;
+  }
+}
+

# Back-end

The back-end primarily has three responsibilities: instruction selection, instruction scheduling, and register allocation. Optimal register allocation is an NPC problem, so often we just use heuristics to ensure near-optimal solutions. This is similar to what we do for other optimizations.

As time goes on, hardware becomes more and more complex because they are no longer designed to be understood primarily by humans and instead to be primarily understood by compilers/computers. This can allow us to have higher performance computers for cheaper. Because of this, ISAs are getting increasingly complex. The compiler must understand this and produce high quality code, hiding these complexities from the programmer.

## Memory and Compilers

Compilers need to understand the memory layout of the machine they're running on. That way they can efficiently map the abstract memory model of the high level language to the hardware's memory.

A traditional C-like memory model (which is what most languages use) has a read-only code segment, a read-write static segment, a heap, and a stack. The code segment and static segment have a known size at compile time, but the heap and stack are growable and only known at runtime.

Normally, we put the read-only code segment at the lowest addresses. Immediately after that we have mutable memory in a static segment. These have a known size at compile time so we can put them directly next to each other. Then, to prevent the heap and stack from running into each other, we put the heap immediately after the static segment, having it grow to higher addresses, and we have the stack be at the highest addresses, having it grown down to lower addresses.

Having the stack and the heap really far apart used to be relevant when we didn't have paged memory and virtual addresses, so we really needed to ensure that the heap and the stack don't run into each other. Even as we have paged memory this is still useful so we can pretend that memory is a single flat address space without worrying about addresses collide.

## Procedure Abstraction

Functions are an incredibly common abstraction across languages and even in assembly. How do we efficiently implement this on a machine which doesn't have native support for procedures? First, to be able to call functions at all you need a calling convention. You could use the standard C calling convention, you could specify your own, or you could make your calling convention unspecified.

In general, to implement a procedure you have to perform the following steps:

  1. The callers stores program state before it calls the procedure. For example it pushes the instruction pointer to a known place and also stores the registers it cares about onto the stack.
  2. The caller jumps jumps to the address of the procedure it's calling.
  3. The called procedure stores all registers it uses that the calling convention tells it to store.
  4. The procedure does its work.
  5. The procedure reverts the registers it stored.
  6. The procedure jumps to the known instruction pointer location.
  7. The caller restores all the registers it stored onto the stack.

As you can see, this is fairly expensive but also incredibly common. As such many machines provide hardware interfaces to more efficiently call procedures.

In order to more easily organize the information and data local to each procedure, we create something call activation records (AR) or stack frames. These are application binary interface (ABI) dependent (i.e. machine dependent) information about each procedure call. It's exact structure depends on language and machine but often they contain the parameters for the function, the return address, and all the local data.

Stack Frame / Activation Record

Most languages put activation records on the stack (hence the name stack frame) because they are only used during the execution of the function. For some languages (like ML) put activation records on the heap because activation records may be used after the heap.

### Calling Conventions

To maintain activation records, the caller must go through a pre-call sequence and a post-return sequence. Likewise the callee needs to go through a standard prolog and a standard epilog

This standard sequence is calling the calling convention. It determines what registers need to be saved by the caller, what registers need to be saved by the callee, where arguments are stored, where return values are stored, where return addresses are stored, and all that fun stuff.

Here is some more information about the System V ABI for the Intel386 architecture. That is the C ABI for the Intel architectures. http://sco.com/developers/devspecs/abi386-4.pdf

## Instruction Selection

Instruction selection along with instruction scheduling and register allocation is one of the most important backend choices. For most machines, there are many different ways to perform a computation where the cost depends on the context. A classic example is that mov rax, 0 is the same as xor rax, rax.

Generally, the backend does this using a code generator with a set of rewrite rules. These rewrite rules describe all the ways the IR can be converted to a specific (series of) instructions. You normally do this by doing a post-order traversal / bottom-up walk of the tree to convert expressions into instructions. However, there are many matches for these rewrite rules for every expression, each with different costs. How do we do we find the lowest-cost match for each subtree?

One easy way is to compute all possible matches and choose the cheapest one. This can be absurdly expensive as your list of operations increases. There is also methods using dynamic programming.

## Instruction Scheduling

Instruction scheduling is the process of reordering instructions for optimal execution. This is necessary when / because instructions can take different number of cycles to complete and thus have different latencies. By reordering instructions you "hide" the latencies. Essentially you want to do as much as you can before you hit an instruction which depends on a previous instruction. You can also potentially reduce the number of necessary registers.

This may be unintuitive but consider the following example.

// W <- w * 2 * x * y * z
+
+// Schedule 1
+loadAl  r0, @w => r1        // 1
+add     r1, r1 => r1        // 4
+loadAl  r0, @x => r2        // 5
+mult    r1, r2 => r1        // 8
+loadAl  r0, @y => r2        // 9
+mult    r1, r2 => r1        // 12
+loadAl  r0, @z => r2        // 13
+add     r1, r2 => r1        // 16
+storeAl r1     => r0, @w    // 18
+// 21
+
+// Schedule 2
+loadAl  r0, @w => r1        // 1
+loadAl  r0, @x => r2        // 2
+loadAl  r0, @y => r3        // 3
+add     r1, r1 => r1        // 4
+add     r1, r2 => r1        // 5
+loadAl  r0, @z => r2        // 6
+mult    r1, r3 => r1        // 7
+mult    r1, r2 => r1        // 9
+storeAl r1     => r0, @w    // 11
+// 14
+

As you can see the schedule 2 took fewer cycles because it moved instructions that depends on previous instructions farther apart. This allows the machine to make more progress while the other instruction(s) it depends on are in flight.

Note that schedule 2 also uses more registers. In some cases thus it would be worse if it requires more cycles to spill the registers than it saves.

To help determine what instructions depend on each other, we build a dependence graph, which is a directed graph. Each node in the graph is an operation and every instruction's node has an arrow pointing directly to the instruction which depend on it / must occur after it. Often each node is annotated with the latency of the nodes plus all of its dependents.

There is a strategy to scheduling instructions called local list instruction scheduling. It is done as follows.

  1. Build a dependence graph G.
  2. Compute a priority function over the nodes in G. (The priority function determines the latency of the instruction.)

What are the weaknesses of this technique? We can't determine what branch will be taken, even which branch will be taken most of the time. We can't determine where a load or store will occur in memory, for example will most of the loads and stores of this variable be cache misses or cache hits? Those can hugely effect the latency of the instruction.

## Register Allocation

Register allocation is the process of deciding what data goes where in the machine.

A critical part of doing register allocation is determining the liveness of a variable. A variable is live between its definition and its last use, the range of these instructions / blocks is called its live range. Analysis of live ranges is way easier if you use static single assignment (SSA) form.

If you have more variables alive at some time than your machine has registers, then you won't be able to hold all of the values in registers and will have to spill some. A register spill is just when you store the contents of the variable into memory (e.g. on the stack).

We can transform register allocation into a graph coloring problem by using an interference graph. To create an interference graph, create a node for every variable (in SSA form). Whenever two variables are alive at the same time, connect them with an edge. Now we can transform register allocation into graph coloring by assigning each register a color and trying to minimize the number of colors k necessary to color the graph. If k is less than or equal to the number registers in your machine, then you're good. If k is greater than the number of registers in your machine, you need to find the optimal way to make the graph color-able using the number of registers in your machine. You modify the graph by introducing loads and stores, called register spills. You need to minimize the number of necessary spills as well.

Both of these problems (k-color-ability and minimizing the number of spills) is NP-Complete, essentially meaning they are extremely difficult. (Formally, there is no known way to solve the problems in polynomial time, and they are "as hard" as all other NP problems.)

One heuristic algorithm to perform register allocation is Chaitin's algorithm. It was actually the first register allocation algorithm that used graph coloring!

# Theoretical Stuff

## Chomsky's Hierarchy

Chomsky's hierarchy of languages/grammars is a way of categorizing grammars. A grammar G=(N,Σ,P,S) is a set of non-terminal symbols N, terminal symbols Σ, and productions P. One non-terminal SN is considered the start symbol. Productions αβP are rules that allow you to go from a sequence of lefthand side symbols $\alpha \in (N \cup \Sigmap)^totoasequenceofrighthandsymbols\beta \in (N \cup \Sigmap)^$. We can categorize grammars by the amount of restrictions placed on them. This allows us to categorize their computability.

  • Regular Grammar: A grammar where every production has at most one righthand non-terminal symbol and arbitrarily many lefthand terminal symbols. There can be no lefthand non-terminals and no righthand terminals. This is called a righthand grammar, but if we switch the left and right rules we get a lefthand grammar.
  • Context Free Grammar: A grammar where the lefthand side of productions is a single non-terminal and the righthand side is an arbitrary combination of terminals and non-terminals.
  • Context Sensitive Grammar: A grammar where the lefthand side of productions is an arbitrary combination of non-terminals but no terminals and the righthand side is an arbitrary combination of terminals and non-terminals.
  • Unrestricted Grammar: A grammar where the lefthand side of productions can have any arbitrary combination of terminal and non-terminals and the righthand side of productions can have again any arbitrary combinations.

Note: Technically these grammars are supersets of each other, but normally when we say a grammar is "context free" we mean that it is the minimal encompassing classification, that is it is not regular. Even though all regular grammars and context free grammars.

A regular grammar is guaranteed to be able to be parsed/validated in O(n) linear time by a finite automata (e.g. NFA). A context free grammar (CFG) can be computed in linear time by a pushdown automated (PDA).

Example: The following is a regular language recognized by the regular grammar below. L=an:nN

A -> aA | a
+

Example: The following is a context free language recognized by the context free grammar below. L=anbn:nN

A -> aAb | ab
+

Example: The following is a context sensitive language. L=anbncn:nN

# Performance Analysis

This stuff is research which the professor is working on. It's not incredibly relevant to constructing compilers but understanding performance and how to debug it is good for optimizations.

## DrCCTProf

CCT stands for calling context tree. DrCCTProf is developed by the professor's research group and examples and docs can be found in the slides.

In this class we will use DrCCTProf which is a binary analyzer that tracks instructions (operator and operands), registers (SIMD and general purpose), memory location, and storage locations of variable (register or memory). It is designed to efficiently allow for call path analysis, with ~2x overhead compared to the 100-1000x overhead of Valgrind.

It is built on DynamoRIO. DynamoRIO does dynamic binary instrumentation and is maintained by Google and is programmable using DynamoRIO clients, which are programmed by registering event handlers. It allows you to do things such as count the number of basic blocks executed during execution.

Compared to DynamoRIO, DrCCTProf provides a (slightly) nicer (undocumented) API for analyzing call path. It automatically builds a calling context tree and interns symbols (optionally). It builds the calling context tree to enable constant time querying of the call path because you just look up something from a tree instead of unwinding the stack.

### DrCCTProf Usage

The general usage is initialization, instrumentation, analysis, storage, and output.

  • Initialization: Open files and call into DynamoRIO to initialize.
  • Instrumentation: Instruct DrCCTProf about what things it should look at and what it should do when sees a certain thing (e.g. basic-block, instruction, etc.).
  • Analysis: Run the program with the instrumentation.
  • Storage: The instrumentation needs to efficiently store the memory either in DrCCTProf's Map<uint64_t, uint64_t> or shadow memory.
  • Output: Collect/aggregate all of the stored information and create output.

DrCCTProf outputs data in a format which is compatible to HPCToolkin, a Java GUI used to visualize the information more easily than the raw text output.

### Call Path Importance

To detect issues with generated code performance, we often need to know how the code was reached. That way we can detect redundant/inefficient code. For example, this basic block appeared twice in my execution trace, is that redundant code in code generation or am I duplicating work? Without the call path this is hard to determine.

It also allows detection of:

  • Memory Safety Issues: data races, out of bounds array access.
  • Performance Issues: False sharing detection (cache issues), etc.

### Data-centric DrCCTProf

By enabling data-centric detection in DrCCTProf, you keep track of every memory access and where it is allocated. That is, what call to malloc, is it on the stack, etc.

## DeadSpy

DeadSpy is a tool which can help analyze dead stores. Dead stores are memory writes with no intervening reads, so there are no effects of the write. The earlier write that does nothing is called the dead write and write that replaces that write is called the killing write.

DeadSpy, like DrCCTProf, analyzes machine code rather than the source code. This means it is a general purpose tool that works on many different languages (that compile to machine code).

Dead stores are most often caused by poor data structure choice, lack of design for performance (no restrict, dead writes in source code, etc.), overly aggressive compile optimizations, and TODO.

What we care the most about here is understanding why poor machine code generation occurs. We can detect when we're being too aggressive with compiler optimizations (sometimes compiler optimizations introduce issues if they are applied in unexpected ways) or if we're being too conservative.

\ No newline at end of file diff --git a/notes/ncsu/3f/csc412/stack_frame.png b/notes/ncsu/3f/csc412/stack_frame.png new file mode 100644 index 0000000..6d733f2 Binary files /dev/null and b/notes/ncsu/3f/csc412/stack_frame.png differ diff --git a/notes/ncsu/3f/csc412/thompsons_construction.png b/notes/ncsu/3f/csc412/thompsons_construction.png new file mode 100644 index 0000000..ed28b6e Binary files /dev/null and b/notes/ncsu/3f/csc412/thompsons_construction.png differ diff --git a/notes/ncsu/3f/index.html b/notes/ncsu/3f/index.html new file mode 100644 index 0000000..1c7fbef --- /dev/null +++ b/notes/ncsu/3f/index.html @@ -0,0 +1 @@ +Zola

Welcome to Zola!

You're seeing this page because we couldn't find a template to render.

To modify this page, create a section.html file in the templates directory or install a theme.
You can find what variables are available in this template in the documentation.

\ No newline at end of file diff --git a/notes/ncsu/3f/ma407/index.html b/notes/ncsu/3f/ma407/index.html new file mode 100644 index 0000000..975b5d7 --- /dev/null +++ b/notes/ncsu/3f/ma407/index.html @@ -0,0 +1 @@ +Eli | MA 407: Introduction to Modern Algebra

MA 407: Introduction to Modern Algebra

Instructor: Dr. Jo-Ann Cohen | Semester: Fall 2020

Scanned PDF.

\ No newline at end of file diff --git a/notes/ncsu/3f/ma520/index.html b/notes/ncsu/3f/ma520/index.html new file mode 100644 index 0000000..3dfcaa5 --- /dev/null +++ b/notes/ncsu/3f/ma520/index.html @@ -0,0 +1 @@ +Eli | MA 520: Linear Algebra

MA 520: Linear Algebra

Instructor: Dr. Bojko Bakalov | Semester: Fall 2020

Scanned PDF.

\ No newline at end of file diff --git a/notes/ncsu/3f/st421/index.html b/notes/ncsu/3f/st421/index.html new file mode 100644 index 0000000..056ef90 --- /dev/null +++ b/notes/ncsu/3f/st421/index.html @@ -0,0 +1 @@ +Eli | ST 421: Introduction to Mathematical Statistics

ST 421: Introduction to Mathematical Statistics

Instructor: Dr. Jonathan Duggins | Semester: Fall 2020

TODO: Include cheatsheet.

\ No newline at end of file diff --git a/notes/ncsu/3s/csc416/index.html b/notes/ncsu/3s/csc416/index.html new file mode 100644 index 0000000..6741cc0 --- /dev/null +++ b/notes/ncsu/3s/csc416/index.html @@ -0,0 +1 @@ +Eli | CSC 416: Introduction to Combinatorics

CSC 416: Introduction to Combinatorics

Instructor: Dr. Ernest Stitzinger | Semester: Spring 2021

Scanned PDF.

\ No newline at end of file diff --git a/notes/ncsu/3s/csc591/index.html b/notes/ncsu/3s/csc591/index.html new file mode 100644 index 0000000..b1630e5 --- /dev/null +++ b/notes/ncsu/3s/csc591/index.html @@ -0,0 +1 @@ +Eli | CSC 591: Special Topics in Computer Science: Computational Geometry

CSC 591: Special Topics in Computer Science: Computational Geometry

Instructor: Dr. Donald Sheehy | Semester: Spring 2021

Scanned PDF.

\ No newline at end of file diff --git a/notes/ncsu/3s/index.html b/notes/ncsu/3s/index.html new file mode 100644 index 0000000..1c7fbef --- /dev/null +++ b/notes/ncsu/3s/index.html @@ -0,0 +1 @@ +Zola

Welcome to Zola!

You're seeing this page because we couldn't find a template to render.

To modify this page, create a section.html file in the templates directory or install a theme.
You can find what variables are available in this template in the documentation.

\ No newline at end of file diff --git a/notes/ncsu/3s/ma402/index.html b/notes/ncsu/3s/ma402/index.html new file mode 100644 index 0000000..df75e52 --- /dev/null +++ b/notes/ncsu/3s/ma402/index.html @@ -0,0 +1 @@ +Eli | MA 402: Mathematics of Scientific Computing

MA 402: Mathematics of Scientific Computing

Instructor: Dr. Eric Hallman | Semester: Spring 2021

Scanned PDF.

\ No newline at end of file diff --git a/notes/ncsu/3s/ma425/index.html b/notes/ncsu/3s/ma425/index.html new file mode 100644 index 0000000..c3bee97 --- /dev/null +++ b/notes/ncsu/3s/ma425/index.html @@ -0,0 +1 @@ +Eli | MA 425: Mathematical Analysis I

MA 425: Mathematical Analysis I

Instructor: Dr. Stepan Paul | Semester: Spring 2021

Scanned PDF.

\ No newline at end of file diff --git a/notes/ncsu/4f/csc379/index.html b/notes/ncsu/4f/csc379/index.html new file mode 100644 index 0000000..16406cc --- /dev/null +++ b/notes/ncsu/4f/csc379/index.html @@ -0,0 +1 @@ +Eli | CSC 379: Ethics in Computing

CSC 379: Ethics in Computing

Instructor: Dr. David Wright | Semester: Fall 2021

Table of Contents

# Basics

Ethical theories are split into three general areas: meta-ethics, normative ethics, and applied ethics.

  • Ethical Principles
    • Beneficence: Do good to someone or a group.
    • Least Harm: Do not harm people.
    • Respect for Autonomy: Let people make their own choices.
    • Justice: People receive what they deserve in a sense.
  • Ethical Theories:
    • Deontological: Uses a set of rules to distinguish right from wrong. For example, "Don't lie. Don't steal. Don't cheat".
    • Utilitarian: Has the concept of a utility function, which may depend on the situation. Your goal is to maximize the utility function.
    • Rights: List of rights people have universally. You judge the ethics of a situation based on whether it respects or infringes on these rights.
    • Virtues: You think about about what a virtuous person would do.

Here are some frameworks for making decisions:

  • Consequentialist: Consider future effects.
  • Duty: Duties and obligations of situation.
  • Virtue: Consider character traits that motivate us.
\ No newline at end of file diff --git a/notes/ncsu/4f/csc461/index.html b/notes/ncsu/4f/csc461/index.html new file mode 100644 index 0000000..ca2dcb3 --- /dev/null +++ b/notes/ncsu/4f/csc461/index.html @@ -0,0 +1,6 @@ +Eli | CSC 461: Computer Graphics

CSC 461: Computer Graphics

Instructor: Dr. Ben Watson | Semester: Fall 2021

Table of Contents

# Administrivia

# History

  • Brunelleschi (1425): First to invent/define linear perspective.
  • Issac Newton (~1675): Discovered white light is a combo of light of all color. Created color wheel.
  • Thomas Young, Herman von Helmholtz, James Maxwell (1800s): Improved color theory and created first color photograph/display.
  • Ewald Hering (1800s): Theorized that human vision perception resulted in Newton's color wheel and opposing colors.
  • Leo Horwich & Dorothea Jameson (1950s): Found evidence for Haring's theory in the brain.
  • Pierre Bézier (1950s): Found an elegant mathematical way to describe arbitrary curves.
  • Jack Bresenham (1960s): Efficiently solved problem of representing sloped lines on rasterized 2D displays. That is, he used only integer addition and subtraction.
  • David Evans: Founded computer science department at University of Utah and hired Ivan Sutherland. Created early rasterization pipeline.
  • Ivan Sutherland (1960s): Developed first drawing program while grad student at MIT. Had undo and rubber-banding. Developed first head-mounted (augmented reality) display. Made famous computer graphics lab and University of Utah.
    • Many of the people below were in Sutherland's lab!
  • Henri Gouraud (1960s): Invented method of shading (Gouraud Shading) to make polygonal models appear smoother.
  • Ed Catmull (1900s): Invented z-buffering, texture mapping (to polygons), and new kind of surface.
  • Bui Tong Phong: Improved upon Gouraud shading by tweaking the algorithm to run on every pixel (now called Phong Shading). This was not feasible for high-performance use cases until recently.
  • Jim Blinn: Improved Phong shading (now called Blinn-Phong shading). Developed bump mapping and environment mapping.
  • Turner Whitted: NCSU student! Invented/improved ray tracing/casting, including handling of shadows, reflection, and refraction.
  • Jim Clarke (1980s): Developed methods of describing surface patches. Founded silicon graphics (hardware graphics company) and co-founded Netscape.

The Utah teapot is a teapot that was modeled by Martin Newell. It was the first realistic, somewhat complex model to see widespread use for testing objects. It's good because it casts shadows on itself, is immediately recognizable, and it doesn't need to be textured to look good. However, it's also not so complex as to be difficult to render or massive in size. It also got squished at some point!

# Ray Casting/Tracing

## History

Arthur Apple invented ray casting in 1968, that is following the light backwards by moving rays from the camera to other places.

A camera obscura, also known as a pinhole camera, is camera formed by allowing light to enter through a small pinhole in the surface. This requires there to be a large difference in brightness from the inside of the camera to the outside. Pinhole cameras are theorized to have first come up from pinhole cameras being naturally formed by tree foliage.

## Terms

Here are some terms for camera movement:

  • Dolly: Move forward/backward
  • Pedestal: Move up/down.
  • Truck: Move left/right.
  • Pitch: Look up/down.
  • Pan: Look left/right.
  • Roll: Rotate left/right.

Ray casting is a way of creating images from a specific perspective in a scene.

Any camera has the following properties:

  • Position: Point in 3D space where the camera sits.
  • Look-at Vector: Vector which points in the direction where the camera is looking. This defines pitch and pan.
  • Look-up Vector: Vector which points directly up relative to the camera. This defines roll.
  • Field of View (FOV): Number of degrees by which the sight vectors can deviate from the look-at vector. There can be a vertical and a horizontal FOV which changes the aspect ratio and corresponding camera's frustum.
  • Aspect Ratio (W:H): Ratio of the width of the viewable area to the height.

The camera's goal is determine what each pixel should be on the viewport. The viewport is a fictional surface some short distance away from the camera that fits within the frustum. This viewport has pixels and to fill in those pixels we cast rays from the camera to the pixel. Using those rays we fill in the color of the pixel.

We often have a near-clip plane which is some distance away from the camera before we starting casting rays and a far-clip plane which is where we stop casting rays (almost like they've hit fog). Inside these two planes we have a frustum which is like a 3D trapezoid.

Simple ray casters only don't deal with illumination because they only cast a single ray and don't consider how it may bounce off the surface. That is, they hit the surface and register that point.

For that you'd have to do ray tracing. Ray tracing logically continues the ray by allowing it to bounce off surfaces and only stop if it either goes too far or hits a light source. It further considers how the surfaces would impact the color or quality of the light. That is if you hit a white surface and then bounce off and hit a green light, the pixel will appear slightly green. This enables high quality shadows, reflection, and refraction.

A Cornell box is a standard test scene for computer graphics. You have a block with two different color walls on the left and right, a white background wall and ceiling, a ceiling with a hole in it to let light thru, and a colored object filling up most of the scene. This is particularly useful to test color bleeding, where colors reflect onto nearby objects and seem to "bleed" onto them.

## Math

When doing ray casting, you need to know what objects you're dealing with so you can do the correct math.

Often when doing computer graphics, we want to do bilinear interpolation (bi-lerp). That is, suppose you have a rectangle with some important properties at each corner (UL, UR, LL, LR). Bilinear interpolation gives you a way to calculate/interpolate the value of those properties at any point within the rectangle.

def bilerp(x, y):
+    # This assumes x and y are normalized from 0 to 1
+    above = x*UL + (1-x)*UR
+    below = x*LL + (1-x)*LR
+    return y*above + (1-y)*LR
+

### Finding Ray

To find the ray for a specific pixel, we need the location of the eye E and the projection window coordinates UL, UR, LL, and LR. (These stand for upper-left, upper-right, lower-left, and lower-right respectively.)

To find the coordinates of the pixel P, you do bilinear interpolation of the coordinates of UL, UR, LL, and LR using the pixel's x and y within screen space.

To define the ray's position at any time t, you use the position of the eye E and that of the pixel P, giving you R(t)=E+t(PE)=E+tD where D is the direction vector of the ray.

### Ellipsoid Collisions

Let S be a point. We say the point is on the surface of the ellipse if the following is true: |SCA|2=1. That is, S is the surface of the ellipse.

Now if you plug-in the equation of the ray into the ellipse equation and solve for t. That is you use this equation |R(t)CA|2=1 and solve for t you get the following at2+bt+c=0 where a=|DA|2, b=2(DAECA), c=|ECA|21.

Since this is just a quadratic, we can use the quadratic formula! t=b±b24ac2a

If we get one value of t, then we have just "grazed" the ellipse. If we have two values of t, then we've intersected it fully. If we have no values of t, then we've missed it entirely. You can just check the discriminant (b24ac). If it's positive, you've intersected (two solutions). If it's zero, you've grazed (one solution). If it's negative, you've missed (no solutions).

Now once you've found solution(s) for t, you pick the smaller t and plug it in to the ray equation R(t)=E+tD to find the intersection point.

### Triangle Collisions

A triangle is defined by three points A, B, and C. Our goal is to determine if the intersection point I exits and find it if it does.

To do this, we need to find the normal (vector) of triangle ABC N by doing N=BA×CA where BA and CA are vectors from B to A and C to A.

This vector N gives us a definition of the plane of triangle ABC: Nxx+Nyy+Nzz=d.

This gives us a test function for whether a point is on the surface of the triangle. That is, for all points S, we know NS=d.

However, there's an issue! We don't know what d is. To find d, we take a known point on the triangle (one of the vertexes) and solve for d. Let's use the first vertex A. We find which we can write in vector form as d=NA.

Now again like we did with ellipsoids, if you plug in the ray at time t R(t) as S into the previous equation and solve for t, you find the time at which the ray intersects the triangle. NR(t)=d.

Solving for T gives us the following equation t=dNEND. Notice that if ND=0, then the ray and the plane are parallel and there is no intersection. (Even if there are infinite intersections, we don't render them because that complicates the equation and we treat the triangle as infinitely thin.)

Now, to find I we plug in the solved for t (if it exists) into R(t).

Now that we have I, we need to determine if I is inside or outside the triangle. An easy way to do this is you know the point is on the inside of the triangle if and only if the point is on the same side of each edge. The way you know which side is by doing the following sign(N(IVi×Vi+1Vi)).

### Picking the Right Collisions

Now once you have all your collisions with all objects, you need to pick the first intersection you care about. You do this by picking the one with the smallest t which is greater than 1. We pick 1 because t=1 is when the ray intersects the view plane.

## Local Illumination

Local illumination is a method for determining the color a given ray should result in. We'll be discussing Phong shading and then Blinn-Phong shading.

Bui Tong Phong's illumination algorithm cares about 5 vectors when a ray hits the surface:

  • V (view): Vector from point to eye.
  • L (light): Vector from point to light.
  • N (normal): Vector normal to surface.
  • R (reflection): L reflected across the normal N.
    • We find R by finding the components of L which are parallel Lp and non-parallel Ln to N. We then define R=LpLn.
  • H (half): Vector halfway between V and L (just take the average).

Note that we expect all these vectors to be unit vectors (i.e. normalized).

There are three terms of Phong's model:

  • Ambient Cambient (color): Shadows. Approximates indirect light. Light that lights up everything including shadows.
  • Diffuse Cdiffuse (directional): Matte lighting. Follows Lambert's Law. Simulates how brightness of light on a surface depends on angle between the surface and light source. This emulate how light "grazing" the surface doesn't light it up much (low density of photons) but light directly hitting a surface is brighter (high density of photons)
  • Specular Cspecular (highlights): Bright spot. Depends on angle between eye and light source. This emulates mirror-like reflections.

You add all these terms together to get the color: C=Cambient+Cdiffuse+Cspecular.

To find the ambient lighting Cambient, you need 2 (arbitrary) variables Ka and La. Ka is the percentage of light that you see comes from ambient light (normally 5-10%). La is the color of the light source. This gives us the equation Cambient=KaLa.

Note that this simulation of a single ambient light source is crude because the ambient light comes from somewhere so it's color will be affected.

To find the diffuse lighting Cdiffuse, you need the vectors N and L and 2 arbitrary variables Kd and Ld. Again Kd is the percentage of light you see which comes from diffuse light and La is the color of the diffuse light. This gives us the equation Cdiffuse=KdLdmax(NL,0).

To find the specular lighting Cspecular, you need the vectors V and R along with an arbitrary integer n. As n get larger, the spot gets smaller as the light gets more focused. We know the light is a function of the angle between V and R, VR, which has a bell-curve / bump shape. Phong ended up using this function (VR)n. This function is arbitrary but works pretty well. We again have Ks as the percentage of light which comes from specular light and Ls which is the color of that light. This gives us the equation Cspecular=KsLs(NL)n.

Combining all these lights we get C=Cambient+Cdiffuse+Cspecular =KaLa+KdLdmax(NL,0)+KsLs(NL)n.

James Blinn improved the specular lighting part of the Phong shading model, making it the Blinn-Phong shading model. He observed that specular lighting really occurs more when N and H are close together. That is because real life surfaces are rough and have tons of little micro-bumps/facets and H describes where they point on average with what we can see. Therefore, when N and H are close the micro-bumps/facets will almost perfectly reflect the specular light to our eyes. That is instead of the light being a function of the angle between V and R, it is the angle between N and h, that is NH. This gives us a new equation for the specular color as Cspecular=KsLs(NH)n.

Now in Blinn-Phong shading we get C=Cambient+Cdiffuse+Cspecular =KaLa+KdLdmax(NL,0)+KsLs(NH)n.

## Ray Tracing

We will incrementally build ray tracing up from ray casting.

The first step is to consider shadows. To determine if a point is in shadow, whenever you find a collision cast a ray from it to the light source(s). If that ray collides with anything, then don't include the diffuse or specular light from the Blinn-Phong model.

Note: The following math might not be right.

Now for reflections, you have to find the reflection ray Rreflection. We find R by finding the components of V (the vector from collision to the eye) which are parallel Vp and non-parallel Vn to N and then define Rreflection=VpVn. This simplifies to the following where R, N, and V are normalized to unit vectors. Rreflection=2(NV)NV

Now, to handle the reflections we have a new coefficient Kreflection and find Creflection by recursively finding the color of the reflected ray. We keep track of how many bounces we've done for each level of recursion and stop after some set number of maximum reflections Mreflection.

We handle refraction similarly to reflections except we do different math to find the refraction ray Rrefraction. The math here comes from Snell's Law, which we won't cover in this class. This again introducing another color and coefficient Krefraction and Crefraction like with reflection (and all other colors). We similarly keep track of each level of recursion and stop after some set number of maximum refractions Mrefraction.

One issue with ray tracing is it only considers specular reflections. That is when you have a crisp clear reflection. It doesn't consider diffuse reflections, that is "color bleeding" style reflections.

Also, ray tracing is computationally intensive. One way to improve performance is the split the world into cubes recursively. Before we check for collisions of objects in the box, we determine if the ray collides with the box at all. We have the boxes recursively so we can hone in on the collided box(es) similar to how binary search works.

# Rasterization

Rasterization is an alternative method of rendering objects to ray casting. It is (especially was) the most common method of rendering 3D objects because of how cheap and hardware friendly it is. Sadly, rasterization is more complicated to understand and harder to add shadows, reflections, and refractions.

One important difference of rasterization is that you will be doing full shading on every single object in the model because, when we're doing shading, we don't know yet which object is closest. This gets worse the more triangles/objects you have stacked up. That is the depth complexity of the scene.

So why is rasterization faster? It's (relatively) easy to cut out unnecessary pixels for each object's pass which can save huge amounts of work because most objects only show up in a tiny number of pixels.

We can also do deferred shading, where our first pass is just to solve occlusion (i.e. figure out which objects are in front), saving a bunch of information, and then we do shading with this information.

Given a pixel in a triangle, how do you interpolate the values at the coordinates? You first find out how far along you are along two of the edges. Once you have that, you can do bilerp as normal. Find the value on the edge of your point to your left and right. Then you find where you are between your left and right points and do the weighted sum again.

The naive way to do this, using world coordinates, is called affine bilinear interpolation and results in morphing and skewed textures. We can resolve this using perspective interpolation

For perspective interpolation, you need to

  1. Perform perspective divide to go to 3d: [s/wt/w].
  2. Append the denominator: [s/wt/w1/w].
  3. Perform bilerp to point p including the denominator: [s/wpt/wp1/wp].
  4. Undo the divide: [sptp].

Note: OpenGL/WebGL automatically does this for us.

## Rasterization in OpenGL/WebGL

Instead of logically looping over pixels and then objects (image-order), you iterate over all objects and then pixels (object-order). However, most graphics APIs (e.g. OpenGL) handle this iteration for you.

A vertex shader takes all the objects in your scene (whose vertexes are 3D points) and outputs coordinates those vertexes should appear on the screen. In OpenGL, this is programmable and must produce output into gl_Position.

With these now projected vertexes and an index array describing the triangles, the rasterizer chops the triangles into pieces called fragments. These fragments are the pixels which intersect with the triangle. In OpenGL, this is not programmable.

Now, the fragment shader must color the fragments produced by the rasterizer. In OpenGL, this is programmable and must produce output into gl_FragColor.

Now, the compositor combines these fragments. In OpenGL, this is not programmable but is configurable. For example, the compositor may do hidden surface removal by ignore/removing pixels behind the frontmost one. There may also be transparency where you instead take averages.

# OpenGL/WebGL

Khronos is the group which maintains OpenGL and WebGL. WebGL is an web-based implementation of OpenGL.

OpenGL was born as Iris GL, which was a proprietary API owned by Silicon Graphics. In the 90s however, they decided to make it an open specification.

WebGL 1.0 was a descendant of OpenGL ES 2.0. WebGL 2.0 was released in 2018 and is a descendant of OpenGL ES 3.0.

For OpenGL, you need to know GLSL (Graphics Language Shader Language). GLSL code is compiled and executed by the GPU.

Vulkan, aka OpenGL Next 5.0, is a lower-level rework of a lot of OpenGL for the purpose of being more cross-platform and having better performance.

Metal is a MacOS based API similar to Vulkan. It was developed before Vulkan. Mantle is that for AMD. Direct3D is that for Windows.

## Usage

The process for rendering in WebGL is

  • Set up WebGl.
  • Load model.
  • Process model.
  • Render result.

See these rendering primitives in WeblGL: https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Constants#rendering_primitives

The vertex shader (programmed in GLSL) takes in attributes, per-vertex info like position and color; and uniforms, such as ambient light and perspective. It produces varyings, per-vertex values to be interpreted by fragment shader; gl_Position, the position of the vertex in clipping space; and gl_PointSize, the size of the point sprite.

The fragment shader takes in the varyings from the vertex shader and the same uniforms the vertex shader got. Then it outputs gl_FragColor, the color of the fragment which is used when only one render target is used; and gl_FragData[], fragment colors when multiple render targets are used.

How do we debug shaders? Keep them simple and correct, visualize debug values, possibly implement them in JavaScript. There's also some tools in the console. There's also an extension called WebGL insight.

OpenGL 2.0 removed matrix math. There's a useful library called glMatrix which re-implements the removed matrix code.

Here's a cheatsheet for WebGL 2.0: https://www.khronos.org/files/webgl20-reference-guide.pdf

# 3D Models

In this class, we prefer convex polygons because it makes it more simple to determine if we are inside the polygon or not.

We additional prefer to deal with triangles because they always define a plane. You can convert every polygon to triangles (i.e. triangulate the polygon) however.

If we have a complex surface, to convert it to a polygon we sample the surface at several points (at regular intervals) to define vertexes of the surface. We then connect the appropriate vertexes with edges to create the triangles.

After this, we have a minimally described 3D model. We often go further and add attributes to the model to describe its material(s) and how they reflect light.

We can also define vertex normals, which are normals pointing out from vertexes. These are included in attributes and are often used to shade the surface in a way to hide its facets / polygons.

# Transforms

We describe transforms of coordinates using matrixes. You can intuitively see how this works for rotation and scaling but it's not immediately clear how this works for translations.

The trick to make it work for translation is that we add an additional element to every vector, so we deal with vectors in R4 then our matrixes exist in R4×4 accordingly. These are called homogeneous coordinates.

A transformation matrix on homogeneous coordinates (R4×4) can intuitively be seen by a transformation matrix T with an offset vector o.

[To0001]

## Translation, Scaling, & Rotation

Let h be a homogeneous coordinate and define p to be the ordinary coordinate. This is specific to 3D ordinary coordinates, but a similar idea works in general. h=[xyzw]p=[xwywzw]

Here's an example of a translation

[100X010Y001Z0001][xyz1]=[x+X1y+Y1z+Z11]

Here's an example of a (one-dimensional) scaling [Sx0000Sy0000Sz00001][xyz1]=[xSxySyzSz1]

Here's an example of a rotation (around the x-axis) [10000cosθsinθ00sinθcosθ00001][xyz1]=[xcosθysinθzsinθy+cosθz1]

To compose transformations, we multiply their matrixes together. The rightmost one is applied first. The leftmost one is applied last.

All transformations are done relative to the origin. While this doesn't matter for translation, it does matter for rotation and scaling. To account for this, apply a translation to move one vertex to the origin, do your operation, and then apply the inverse translation to move that vertex back.

Composite rotations are confusing because earlier rotations changes the axis of rotation for future rotation. We can sidestep this issue by defining a rotation fully. That is, instead of composite rotations we define change of basis from one orthonormal basis to another. Intuitively, this is like applying a (complex) rotation to all 3 axes in unison.

To define a rotation around an axis, we change the basis of the current system so that the new y-axis is aligned with the rotation, then we apply a regular rotation about the y-axis, and finally apply the inverse change of basis, returning us to the original coordinate system.

Note: You can actually interpret all transformations as either changing the coordinate system or moving the object. It doesn't matter.

## Types of Transforms

  • Rigid Body: Translation or rotation. Preserves angles and lengths.
  • Affine: Rigid body or scale. Preserves parallelism.
  • Perspective: Does not preserve parallelism.

## Transforms & Normal Vectors

Just applying the transformations you make to a model's vectors to its normal vectors doesn't necessarily make sense. This works for uniform transformations, that is transformations which don't change the shape of the model. However, if you have something like a skew which modifies the shape of the object, then the normal vectors will be affected in weird ways.

Consider a rectangle which is made into a parallelogram by pushing the top to the right, that is the left and right side are skewed but the top and bottom remain parallel. If we were to apply this transformation to the normal vectors naively, then the normal vector of the top would become slanted but the normal vector of the right would remain unaffected. However, this is exactly what we don't want.

Suppose we have some model M with normals N and we want to apply transformation T to the model to get model M and normals N. The math to do this is M=TM N=(TT)1N.

This (TT)1 is how we handle the issue of normals changing in unintuitive ways.

# Projections

Using the standard viewing coordinates of an eye at the origin looking towards positive z, the projection of a point p=[x,y,z] is

p=[xyz] phomogeneous=[xyz1] Tproj=[1000010000100010] proj(phomogeneous)=Tprojphomogeneous=[xyzz] proj(p)=[x/zy/z1]

Notice that we are dividing by z in proj(p). This is the essence of projection. Farther away objects become smaller.

The way we do projection is we take our arbitrary viewing setup / eye, described by a set of 3 (orthogonal basis) x, y, and z vectors and a position/offset o. This gives us a viewing transform V, which transforms our viewing setup to the origin and converts the basis vectors into the standard normal basis.

V=[xyzo0001]

In WebGL this is mat4.lookAt(...).

Then we have our standard projection matrix P.

P=[1000010000100010]

In WebGL this is mat4.perspective(...) or mat4.frustrum(...).

Thus we get our complete projection transformation T that takes our viewing setup and converts any world coordinates into projection coordinates T=PV.

We're almost done but not quite. Our window is currently from -1 to 1 in both xand y. To fix this, we have to apply the following transformation

[w/20ox1h/2oy001]

In WebGL this is gl.viewport(...).

Note: Every model is defined with its own arbitrary origin. So to not have all of these models overlap, we have to first transform the model coordinates to world coordinates using that model's specific offset. These are done in WebGL using the using the standard mat4.{translate,scale,rotate}(...).

This gives us a final pipeline of:

  1. Model Coordinates
  • Modeling Transform
  1. World Coordinates
  • Viewing Transform
  1. Viewing Coordinates
  • Projection Transform
  1. Normalized Device Coordinates
  • Viewport Transform
  1. Device Coordinates

## Parallel vs Perspective Projections

For certain aesthetic or functional reasons, you might need to choose between parallel and perspective projections.

In parallel/orthographic projections, the eye is a plane and all view vectors are parallel. In perpsective projections, the eye is a point and no view vectors are parallel.

Perspective projection approaches perspective projection as you get farther and farther away.

# Hardware & The Graphics Pipeline

In OpenGL 3, there were two programmable shaders: the vertex shader and fragment shader. They are run in that order.

In OpenGL 3, they added a geometry shader between the vertex and fragment shader. And they were run in that order. The geometry shader is often unused because it forced a specific ordering on your fragments which slows down performance. Although WebGL is based off of OpenGL 3, it does not have the geometry shader.

In OpenGL 4, a tessellation shader was added. It takes high level surface specifications (e.g. spline patches) and then convert them to triangles. This is used to reduce the number of data passed in.

One reason that GPUs are fast is because of pipeline parallelism. That is they split the many steps needed to do rendering into steps and then do those steps on different things at the same time, instead of waiting for one shape to make it through the entire pipeline before starting the new one.

One disadvantage of pipelining is that it is almost impossible to balance loads, there is significant bandwidth use from transferring data from piece to piece, and likewise there is significant start-up and shut-down costs. It also cannot do cull optimization, where we skip certain steps if we discover they're unnecessary.

There is another optimization called SIMD parallelism. It applies a Single operation/Instruction to Multiple pieces of Data without moving the data. It is good because you don't have to transfer data from place to place like in a pipeline. You also don't have to balance loads because there is only a single place doing the work. However, it fails if you have one piece of data that has to do different operation (e.g. one vertex has to be clipped but not all). It also struggles to broadcast data to every piece of data it's acting on.

NIMD parallelism is what happens when you use both.

There is another part of GPUs called the compute shader. They allow the GPU to be used for general purpose computing, that is things that are not specifically graphics, for example machine learning.

# Shading

Shading is the process of determining the color of a piece of a polygon, called a fragment (triangle).

For shockingly long, we had no hardware support for dealing with fragments and their shading. There was only vertex transformations, and eventually some support for vertex lighting.

There are many different shading methods.

The simplest shading method is called flat (i.e. per-triangle) shading. Each triangle has its own normal and that normal is used for every fragment's pixel in the fragment shader. This results in sharp facets/edges between triangles, which we don't want in general.

There's another method called Gouraud (i.e. per-vertex) shading. The idea is you calculate the shading at each vertex using the vertex normals and then interpolate colors. This results in smoother colors but with the facets/edges still somewhat visible.

How do we get the vertex normal? If we're tessellating a patch we might be lucky enough to be able to directly calculate the normals. Otherwise, we can take the average of all the surrounding face normals.

Yet another method is called Phong (i.e. per-fragment) shading. The idea is you use the normal vectors at the vertex and interpolate the 3 vertex normals of the triangle your in, at your position. This results in much smoother shading with no obvious facets/edges, much better than even Gouraud shading. This was the first shading technique where specular highlights really looked good. Note that you must always re-normalize your interpolated normal vector in order to ensure it is always a unit vector, otherwise they might end up too short and result in weird/dim lighting because of that.

Note: Unlike Gouraud shading, Phong shading wasn't possible to do interactively until decades after his death once hardware caught up. This should make sense because with Gouraud shading, you're calculating very few colors and just doing basic interpolation to get the colors of every fragment. However, with Phong you're not only performing all the normal calculations but also interpolating vectors and normalizing them.

Note: In practice, you only want either Phong shading, because it's so smooth, or flat shading, for the aesthetic. Gouraud shading is just a less smooth smooth shading algorithm than Phong shading.

## Smooth Objects vs Non-smooth Objects

Sometimes, the smooth shading models of Gouraud and Phong shading look terrible, for example with sharply angled shapes or shapes that are not supposed to be smooth. Since these models try to smooth out edges, they can look wrong or with sharply angled shapes, very weird. For example, with a cube those shading models will shade the cube almost as if it were a super low-poly sphere.

# Texturing / Texture Mapping

Texture mapping is the process of adding colors to models. In its simplest form, you are just wrapping some 2D image around a surface.

This process can be extended with alpha which allows parts of the model to be partially or fully transparent. Likewise it can be extended with bump mapping, which allows texture mapping affect lighting calculations. There are also the techniques of shadow mapping and relief mapping.

What makes texture mapping possible is having a mathematically well-defined coordinate system for the surface of a model.

For clarity, we call the pixels in the texture texels and use u-v coordinates rather than x-y coordinates. Then, each vertex on a model gets a set of u-v coordinates describing what part of the texture should be mapped to it. Then, in the fragment shader, you get the interpolated u-v coordinate of your triangle's vertexes.

## Getting u-v Coordinates

Where do we get these u-v coordinates? If you're using spline patches, you get those "for free" by just defining the u-v coordinates for the corners of your patch.

If you aren't doing that, we can do a 2-stage approach. First, you map the texture to a simple shape logically containing that object in its center. Then, you map that simple shapes texture onto the object. You want the simple shape to as closely match the object's shape as possible.

If your object or texture is more complicated such that a 2-stage approach won't work, you have to manually build up the texture mapping. There are tools and techniques to make this easier. For example, you can break the object's surface into chunks and texture the chunks. These chunks' textures may then be stored separately or packed into a single image.

## Applying Textures

Given a u-v coordinate, how do we look up the color? This seems simple but is surprisingly difficult because your coordinates are unlikely to line up perfectly with a texel. Additionally, in screen space we are looking at simple pixels (i.e. squares), but due to perspective projection these might actually be notably skewed in texture space.

There's broadly two ways this can arise: magnification and minification. Magnification is when the pixel is smaller than the texel and you have to expand the texture. Minification is when the pixel spans multiple texels.

### Magnification: Nearest Neighbor vs Linear Interpolation

The two common ways to handle magnification, that is when your pixel falls within a texel, is either using nearest neighbor or linear interpolation. For nearest neighbor, you just pick the closest texel and use it exactly. This tends to be very fast but often looks bad with sharp lines and aliasing. Linear interpolation means you interpolate the color of the pixel from the neighboring texels. This is slower but often yields smoother, more attractive textures. Note: For certain styles, like pixel-art or pixelated styles, you want to use nearest neighbor to get sharp colors.

In OpenGL, you can pick between these two methods with glTexParameteri(...) by choosing either GL_NEAREST or GL_LINEAR.

Note: Generally, magnification is somewhat unsolved. That is we can't zoom in infinitely. We're limited by the quality of our imagery / textures.

### Minification: Mipmapping

Note: It feels like minification might only happen at a distance where the objects themselves seem very small so of course the pixels cover many texels. However, it's important to realize that minification also occurs when looking at things side-long / almost tangent to the surface because then again

For minification, we have the opposite issue where we have several texels within a single pixel. This has the issue of sharp edges tend to either get lost or even worse become spotty, as only some of the pixels pick the edge texel or none of them pick it strongly. This can be fixed with mipmapping. MIP is short for multum in parvo (i.e. many in a small place).

Logically, mipmapping is the process of averaging the values of all the texels within the pixel. However, this is difficult to do in real time, so instead mipmapping has pre-computed scaled down versions of the texture (normally two times scaling at each level). Each of these scales has a d value which describes how much of the texture a single texel takes up. So it is 1/642 for a 64 by 64 texture.

Then, at runtime you determine your pixels size in texture space d as a proportion of the texture, pick the appropriate texture scale, and then use that texture as normal. (You don't need to exactly know your pixel size, just an approximation.)

How do you pick the appropriate texture scale? You want to match the size of your texels to that of your pixels. So if your pixel takes up 1/322 of the pixel, you want to use the 32 by 32 version of the texture.

Of course you almost never line up exactly with a given scale, so you have to do something to figure that out. For trilinear mipmapping, you need to look at the two values of d you're straddling. Then, you find the color of your pixel in those two levels and do linear interpolation of those colors using your value of d and the two levels values of d. This results in a much smoother image with severe aliasing. It does result in things fading at a distance.

You can still have smoother images with less aliasing without things fading by using anisotropic filtering. This means you don't average over as much of the texture which leads to images still being sharp far away. Basically, this is just a better approximation of the size of the pixel in texture space.

## Wrapping

What happens if our texture coordinates exit the 0 to 1 range? There are three main ways: repeating, mirroring, and clamping. These should hopefully be intuitive by name. For repeating, you do mod and cycle the texture. For mirroring you start going down in coordinates. For clamping you just take either 0 or 1 if you're outside of the range.

Normally you won't really want to use clamping if you're expecting the texture coordinates to go far beyond the range. However, repeating and mirroring often times look very repetitive or plain.

## Lighting & Multi-texturing

Normally we'll want to either modulate or replace the color. For modulate, we use the Blinn-Phong illumination using the color of the texture as the material. Or alternatively, multiply the color from the texture by the color of the fragment after illumination. For replace, we simply set the color to be that of the texture.

Note: We multiply the color rather than averaging. This results in a much more intuitive and attractive combination.

You can also overlay textures (often pre-computed light textures) to improve the quality. You do the same strategy here as you would for modulating the color using the Blinn-Phong lighting model, just the lighting gotten from a pre-computed texture. This is called light mapping.

# Hidden Surface Removal

With rasterization, you don't get occlusion for free. That is, by default with rasterization you render and display all objects no matter if something is blocking them or not and the "winning" object (i.e. the one actually displayed) is just the one rendered last. Hidden surface removal is the process of hiding or not displaying the parts of the image you cannot see.

## Back-face Culling

One way to do partial hidden surface removal is back-face culling. For this, you simply don't render triangles which are occluded. This has the benefit on cutting down on the number of objects rendered.

How do we determine if a triangle is back-facing, that is should be culled? The simplest way is to take the dot product of the view vector (from collision to eye) and the normal vector of the collision. If it's negative, then the triangle is back-facing.

How do we know the normal vector of the triangle? The model could tell us. Alternatively, we could choose a convention so that we can tell the facing by the order of the triangle's vertexes. Typically, we say a triangle is facing you if the vertexes are winding counterclockwise and is facing away from you if they're clockwise.

Back-face culling is not a full solution to hidden surface however. For one, this does assume that we never want to see the back faces of a model. This is true for closed models but not for open ones. Additionally, this does not work if we have have occluded front-faces. For example consider looking at a torus/donut from the side, both the inside and outside of the donut are facing us but we only want to see the outside.

## Painters Algorithm

The painters algorithm renders objects in order of depth, from farthest to closet by sorting all the triangles by view depth (i.e. distance from eye) first before rendering. This naturally means that the farthest objects will be overwritten/occluded by the closest objects as desired.

This has a problem for intersecting polygons or polygons where neither one is clearly in front of the others, for example with cyclic relationships, like with the lid on a cardboard box. Also, sorting every single frame is somewhat slow.

Then if you try to sort by pixel it's even harder.

## Z-buffering

The most common technique to do this is called z-buffering. This is mostly implemented in hardware at this point, which is why it's so fast and common.

Logically, every single fragment has a z value and those with the closest z value (past the near clipping plane) are picked as the winning fragment to be rendered.

Implementation wise, you add a depth buffer or z-buffer, alongside the frame buffer, which is initialized with max z. Then, for every fragment you take their z value zfrag and compare it to the current value in the z-buffer. If it is lower/closer (and past the near clipping plane), you put that fragment's color to the frame buffer and update the z buffer with your zfrag

Pros: Z-buffering is really fast (linear) and you can render triangles in any order.

Cons: You have issues if the depth is identical where the winning object will be chosen arbitrarily, called z-fighting (a modelling issue, easy to avoid). This is especially bad if you have low-resolution depth information (e.g. with very far away objects). It's also inefficient with high depth complexity because you're gonna spend a lot of time rendering objects that will never be shown. Z-buffering also doesn't work well with transparency (naively).

## Binary Space Partition (BSP) Tree Depth Sort

Logically, a BSP is a data structure that allows us to efficiently (O(n)) traverse in either far to near order (for hidden surface removal that respects alpha) or near to far order (to limit overdraw). We will show a method of constructing a BSP which is O(nlog(n)). Note that a BSP is completely re-usable for any eye location in the set of objects.

To construct a binary space partition, choose an arbitrary polygon and make it the root. Then split the space into polygons in front of the root and those behind the root. If a polygon is on both sides then it must be split. The front is one side of the tree and the back is the other. Then you recurse to those subtrees.

Note: We can have heuristics that help us choose the root polygon to more evenly split the space to be more efficient. Tho sometimes bad partitions are inevitable. Consider for example a convex shape like a dodecahedron. No matter what face you choose, all of the faces are on the other side.

Also, notice that this doesn't work in the naive way of repeating cubes. This way is more efficient by respecting the geometry of the triangles.

To traverse a BSP, compare the eye to the root of the tree. Recurse towards the side nearer (or farther) the eye, output the current root polygon, and then recurse towards the side farther (or nearer) the eye.

Pros: Fast (O(n)) to traverse. Helps transparency and overdraw.

Cons: Slow (O(nlog(n))) to construct tree. Doesn't work well with dynamic scenes. Also, poor choices of roots (e.g. creates lots of splits, doesn't evenly split the area) yield poor performance.

# Displays

A vector display has no pixels. Instead, you have a stateful drawing head which you move (either drawing or not) using vectors. These are also called random displays since you can draw the display in any order. These predate raster displays. A modern example of vector displays are EKGs, pen plotters, and CNC routers.

A raster display has a regular scan that go over a regular array of pixels. Although modern displays don't actually require a physical scan over their pixels, we still do it for backwards compatibility reasons. Raster displays have become the most common kind of display. Let's go over their pros and cons.

Pros:

  • Raster displays allow the display update speed to be different than the image update speed (i.e. refresh rate != frame rate). This means your display won't flicker when drawing complex things.
  • Raster displays are significantly faster than vector displays.
  • Raster displays can fill in shapes easily, while vector displays can really only draw wireframes.
  • Raster displays can have much more complex colors more easily. Vector displays struggle significantly to do color.

Cons:

  • Raster displays have significant aliasing, especially with large pixels.

However, there are alternatives to both vector and raster displays. Most alternatives focus on having lower latency than current displays, driven primarily by video conferencing and virtual reality.

Plasma displays were invented in the 60s and most popular in the 80s and 90s. Their main benefit is they allow for partial updates, where you can update only the parts of the screen that have updated, rather than having to stream all the pixels all the time. They can do this because the display itself "remembers" what was displayed. They fell out of favor because they suffered from severe burn in, were expensive, and were generally outclassed by cheaper LCD screens or higher quality OLED screens.

High dynamic range (HDR) displays are displays with a significantly larger range of brightness, normally 5e4 to 1e5 cd/m2 instead of 5e2 to 1e3 cd/m2 (i.e. 4 more orders of magnitude). These are becoming commercially available today.

Near-eye light field displays are displays which are meant to be comfortable up close. Currently, virtual reality displays are fairly bulky in part due to the large lenses that must go in front of the display for them to be comfortable to look at. However, with near-eye light field displays, you can have a display roughly 1cm thick right against your eye that is still comfortable to look at. Nvidia has been doing research on this in particular. These work by having a micro-lense array that cover a traditional OLED array that presents several views of an image from slightly different angles. When close to your eye, we perceive this as a single image.

Since the same image must be rendered from several different views, this complicates rendering and makes rasterization in particular difficult. It also significantly reduces the perceived spatial resolution because you're essentially getting a smaller screen to render onto.

However, this does solve the vergence-accommodation conflict issue that affects current VR. Vergence is about stereoscopy and accommodation is about having one object (of your choice) in focus. So the conflict is where we have stereoscopic information but cannot independently focus on objects in the scene. This messes with our brain's depth sensing machinery and can cause nausea or headaches in users of VR as well as inaccurate depth perception.

# Images

## Transparency

Normally, to describe colors we use red-green-blue (RGB). However, this can be enhanced with transparency into red-green-blue-alpha (RGBA).

Suppose you have some fragment in front of an already colored buffer. To find the new color given some transparency α, you do $$\text{color}\text{new} = \alpha\text{color}\text{new} + (1-\alpha)\text{color}_\text{buf}$$

Notice that with this formulation, order matters! This is good because it's also what we'd naturally want.

Suppose you have a blue buffer b with a red r and green g fragment both with α=0.5. If you put red first Cr, then you get a redder color. If you put green first Cg, then you get a greener color. Cr=0.5r+0.5(0.5g+0.5b)=0.5r+0.25g+0.25b Cg=0.5g+0.5(0.5r+0.5b)=0.5g+0.25r+0.25b

This complicates rasterization because then we must sort by depth. That is, first you render all the opaque triangles with z-buffering. Then, render the transparent triangles from back to front. While rendering the triangles, turn off z-write and render the frontmost triangles (i.e. not occluded) without updating the z-buffer values.

## Frame Buffer

Raster displays have a frame buffer which is the raw image data of the image on the display. (This normally exists on the GPU.) To put images onto the display, you have to write the image data to the frame buffer. The display then displays out the content of the frame buffer while it is scanning.

This is part of what enables raster displays to separate display refresh rate from frame (update) rate.

However, this has a flaw: screen tearing. When the frame buffer updates in the middle of a display refresh, there are multiple frames being displayed at the same time. This is unattractive, so we want some way to synchronize display updates with frame buffer updates.

### Double Buffering / Vsync

The simplest way to do this through something called double buffering or vsync. Here, you have two buffers: the front buffer and the back buffer. The display only reads from the front buffer while the GPU reads from the back buffer. Then, we do a buffer swap when the is done displaying the front buffer (a so called vertical sync or vsync), we swap the buffers.

This method has one main issue: delay / latency. Your GPU has to wait for the display to finish displaying the frame (a vsync) before rendering the next frame.

We can mitigate this by triple buffering. In fact, you could go on and on forever to attempt to reduce tearing! This results in smoother motion at expense of increased latency.

### G-Sync / FreeSync

Another newer way to solve this issue is by flipping the relationship. That is, the GPU tells the monitor when to do another scan rather than the monitor telling the GPU when to render another frame. This results in no screen tearing and also less latency than double-buffering.

This was initially developed by Nvidia under the name G-Sync but there is an open alternative called FreeSync which was initially developed by AMD.

## Stenciling

Stenciling is a technique of clipping renders to only be inside a certain area or stencil. This is most often useful for reflections in rasterization.

Suppose you are looking at an object over a large reflective disk. A common way to render the reflection is by reflecting your viewport across the reflection plane and rendering the object again.

However, naively this would result in the object being visible outside of just the reflective disk. If we add a stencil of the shape of the reflective disk in our eyesight and only render the reflection within that stencil, then we see the reflection as desired.

This works by having a stencil buffer that you write into and check before outputting/rendering the color.

\ No newline at end of file diff --git a/notes/ncsu/4f/csc492/index.html b/notes/ncsu/4f/csc492/index.html new file mode 100644 index 0000000..81eb52d --- /dev/null +++ b/notes/ncsu/4f/csc492/index.html @@ -0,0 +1 @@ +Eli | CSC 492: Senior Design

CSC 492: Senior Design

Instructor: Ms. Margaret Heil | Semester: Fall 2021

Table of Contents

# Testing

Your project is expected to include a test plan which is documented with your written reports and updated with your oral reports.

They expect the reports to have two types of testing: unit testing and acceptance testing. Unit tests are small and automated. Acceptance tests test the whole system so you compare against the requirements. They are often complex enough that they're difficult or not worth it to automate, but that's not always the case.

It is beneficial to draft your test plan when you're doing your requirements.

Make sure your acceptance test plan is specific, you should fully describe everything and make it so it's impossible for someone to reasonably do something other than you intend. Make sure you create a test data set for your acceptance tests to you use. Your test data should be (relatively) small and understandable.

In OPR 1 we should report on test plan, test design.

\ No newline at end of file diff --git a/notes/ncsu/4f/index.html b/notes/ncsu/4f/index.html new file mode 100644 index 0000000..1c7fbef --- /dev/null +++ b/notes/ncsu/4f/index.html @@ -0,0 +1 @@ +Zola

Welcome to Zola!

You're seeing this page because we couldn't find a template to render.

To modify this page, create a section.html file in the templates directory or install a theme.
You can find what variables are available in this template in the documentation.

\ No newline at end of file diff --git a/notes/ncsu/4f/ma426/index.html b/notes/ncsu/4f/ma426/index.html new file mode 100644 index 0000000..19d2b40 --- /dev/null +++ b/notes/ncsu/4f/ma426/index.html @@ -0,0 +1 @@ +Eli | MA 426: Mathematical Analysis II \ No newline at end of file diff --git a/notes/ncsu/4f/ma450/index.html b/notes/ncsu/4f/ma450/index.html new file mode 100644 index 0000000..5a4e85c --- /dev/null +++ b/notes/ncsu/4f/ma450/index.html @@ -0,0 +1 @@ +Eli | MA 450: Methods of Applied Mathematics I

MA 450: Methods of Applied Mathematics I

Instructor: Dr. Mansoor Haider | Semester: Fall 2021

Scanned PDF.

\ No newline at end of file diff --git a/notes/ncsu/index.html b/notes/ncsu/index.html new file mode 100644 index 0000000..1c7fbef --- /dev/null +++ b/notes/ncsu/index.html @@ -0,0 +1 @@ +Zola

Welcome to Zola!

You're seeing this page because we couldn't find a template to render.

To modify this page, create a section.html file in the templates directory or install a theme.
You can find what variables are available in this template in the documentation.

\ No newline at end of file diff --git a/notes/talks/grad-apps/index.html b/notes/talks/grad-apps/index.html new file mode 100644 index 0000000..5d1b137 --- /dev/null +++ b/notes/talks/grad-apps/index.html @@ -0,0 +1 @@ +Eli | Preparing for Graduate School Applications

Preparing for Graduate School Applications

Speaker: Georgia Tech, Michigan, Northwestern, Ohio State, and Purdue | Date: 2021-10-14

Around January-March/April, try to visit campus!

Many universities normally have the final acceptance date as April 15th.

Do the leg work for finding teaching assistantships and research assistantships. It's not enough to just check the boxes.

Statement of purpose should vary based on the university. Talk about specific research that they are doing and perhaps even a specific professor. Talk about what you bring to the table. Speak about time as software team lead at aerial robotics club.

If you email a professor before you have an application or before you have even been accepted, you might be wasting your time. It's good to know the professors you want and do your research for your application because it looks good in your essays but a lot of professors don't really want to respond when someone hasn't even been accepted yet.

Give recommenders a "package". That is, tell them some information about what insight you want them to provide, what your goal is to do in grad school, and possibly even your resume or CV.

\ No newline at end of file diff --git a/notes/talks/index.html b/notes/talks/index.html new file mode 100644 index 0000000..1c7fbef --- /dev/null +++ b/notes/talks/index.html @@ -0,0 +1 @@ +Zola

Welcome to Zola!

You're seeing this page because we couldn't find a template to render.

To modify this page, create a section.html file in the templates directory or install a theme.
You can find what variables are available in this template in the documentation.

\ No newline at end of file diff --git a/notes/talks/notetaking/index.html b/notes/talks/notetaking/index.html new file mode 100644 index 0000000..dec4922 --- /dev/null +++ b/notes/talks/notetaking/index.html @@ -0,0 +1 @@ +Eli | Note-taking For the Things You Want to Remember Forever

Note-taking For the Things You Want to Remember Forever

Speaker: Dr. Sheehy | Date: 2021-09-24

Table of Contents

This lecture does not discuss class notes, paper notes, journaling. Instead, we're talking about notes for creating things and improving creativity.

The big picture is thinking about notetaking; the habits which inform the use of our notes; and the principles which inform our structure.

Here are names and misc things mentioned.

  • Tiago Forte's "Second Brain": System for taking notes.
  • Zettelkasten: Inspiration for Tiago Forte's "Second Brain". This was a physical system of notecards and links with notecards.
    • Andy Matuschak: English source for Zettelkasten.
    • Sönke Ahrens: Another writer.
  • Notational Velocity: Note taking app.
  • Atom Notes: Notational velocity for Atom.
  • Vim Notes: https://github.com/alok/notational-fzf-vim

Thinking About Notetaking

Think of brain as data structure where ...

  • Input: Reading, lectures.
  • Preprocessing: Note system.
  • Queries: Recall.
  • Application: Make something.

Think of yourself as three selfs: past self, current self, and future self.

You should think of future self in two ways: as a stranger and as yourself. As a stranger, you want to build the tools and take the notes to help a future you which has forgotten things. As yourself, you want to help yourself.

Aside: I enjoy writing notes like I'm talking to someone else because of this.

You can waste time even if you're doing something productive. For example, if you read something incredibly deep or learn a lot but don't take any notes. When you later forget that, your past self wasted your current self's time.

Habits

  • Atomic Notes: Every note should be small, focused, and standalone.
  • Start from Abundance: Takes lots of notes. Don't try to do a "heavy lift" where you do all the work at once. If you take lots of small notes, you can slowly build up to something large.
  • CODE: (From Tiago Forte)
    • C: Capture / Collect good ideas.
    • O: Organize information. We'll emphasize links of information.
    • D: Distill ideas. Think of as refactoring.
    • E: Express. Make stuff.
  • Play: Get comfortable exploring your notes and "having conversations with your past self".

Principles

  • Text files
  • Full text search
  • Easy to make and follow links
  • Fast note creation

A good bonus is having executable code.

\ No newline at end of file diff --git a/notes/talks/storing-sequences-in-searchable-form/index.html b/notes/talks/storing-sequences-in-searchable-form/index.html new file mode 100644 index 0000000..6866a81 --- /dev/null +++ b/notes/talks/storing-sequences-in-searchable-form/index.html @@ -0,0 +1 @@ +Eli | How to store massive sequence collections in a searchable form

How to store massive sequence collections in a searchable form

Speaker: Dominik Kempa | Date: 2020-03-11

Our goal is to compress sequential data in an (efficiently) searchable form.

The motivation is the Human Genome Project. It has produced 75 TiB of raw information but ~99% of all of that information is identical. Therefore traditional compression algorithms work extremely well, for example we can compress the raw data to about ~0.7 GiB with just zip. This form is not searchable.

There are other compression algorithms which are searchable however. You create an index and then compress that. This gives you a small searchable index.

Note: The compression indexes we'll be talking about only support full matches. Work is done on supporting any regular expression.

Index have the following properties:

  • Size: is how large the compressed algorithm is. Normally compressed indexes have size of O(c) or O(clogn) where c is the compressed size.
  • Functionality: is what kind of searches the index can support. Normally either plain access (weak) or full search (powerful).
  • Query Time: is how long the search takes. Normally the runtime for these "fast" indexes are O(logn) or O(log2n).

There are two main approaches for building these kind of indexes. There is offline, which constructs some query-able data structure to disk. This takes a lot of CPU and time but supports faster querying in general. There is online which queries more directly.

There are three main lossless compression types:

  • Statistical coding
  • Lempel-Ziv
  • Burrows-Wheeler transform

We are the least interested in statistical coding because it lacks an interesting property (that I didn't write down).

Interesting, Lempel-Ziv and Burrows-Wheeler compression types are equivalent up to O(logn) runtime scaling.

\ No newline at end of file diff --git a/projects/asteroids-3d/index.html b/projects/asteroids-3d/index.html new file mode 100644 index 0000000..dfdf408 --- /dev/null +++ b/projects/asteroids-3d/index.html @@ -0,0 +1 @@ +Eli | 3D Asteroids \ No newline at end of file diff --git a/projects/codie/example_discord.png b/projects/codie/example_discord.png new file mode 100644 index 0000000..1e1080b Binary files /dev/null and b/projects/codie/example_discord.png differ diff --git a/projects/codie/index.html b/projects/codie/index.html new file mode 100644 index 0000000..df603db --- /dev/null +++ b/projects/codie/index.html @@ -0,0 +1,11 @@ +Eli | Codie the Code Runner

Codie the Code Runner

Codie is a Discord bot I created for personal use within my friend groups to make sharing code-snippets with their output much easier to facilitate better conversations around code.

Why did I create Codie?

Before I made Codie, I often saw my friends and I sending snippets of code along with a screenshot or a copy of that code's output. This was frustrating both as someone sending code snippets because it involved opening separate apps and copy-pasting stuff and as someone reading code snippets because the snippets would be inconsistently formatted, sometimes as an image, sometimes as a code block, and sometimes as raw text.

So my idea was that if someone sends a message containing a normal fenced code block with a language annotation (Discord uses CommonMark-style language annotations) prefixed with some command (I used #!run), Codie would automatically run the code and reply with output of the program including stdout, stderr, and the exit status.

How does Codie work?

When you send a message for Codie to run, it looks something like this.

I can't believe this sorting algorithm works! #!run version=3.7 ```py
+def weirdsort(a):
+  for i in range(len(a)):
+    for j in range(len(a)):
+      if a[i] < a[j]:
+        a[i], a[j] = a[j], a[i]
+  return a
+
+print(weirdsort([5, 2, 3, 1, 4]))
+```
+

Aside: Check out Is this the simplest (and most surprising) sorting algorithm ever? for this sorting algorithm!

The first thing Codie does upon receiving a message like this (or really any message) is check if there is a #!run request, potentially with some options, followed by a fenced code block. And if there is, she extracts the language and the content from the code block and parses the options provided.

Without getting too deep into it, this is done using a regex to capture all the input from #!run to the code block, followed by a custom options subparser written with nom. We can get away with a regex to extract the code blocks because Discord only supports code blocks with exactly 3 backticks unlike CommonMark.

Once Codie has ensured the user has actually provided a valid run request with a language she recognizes and options she recognizes for that language, she matches this language and option pair with a Docker image, which she lazily builds if necessary.

The reason Codie uses Docker, beyond it being easy an easy way to set-up a wide variety of different language toolchains with different configurations, is for security.

Aside: Yes, I'm well aware that Docker isn't the most secure. See future work.

Codie tries her best to run all code she's given securely. This means code snippets should never be able to gain control, shutdown, or otherwise control the server that Codie is running on. But it also means that code snippets shouldn't be able to abuse the server's resources by running forever, slamming the server's network or CPU, or using resources in any other way that interferes with keeping the server online and healthy.

As such, the Docker containers Codie runs are locked down with no network access, a small amount of CPU time, a small amount of memory, and all code is run as the permission-less "nobody" user. Containers are also run with a 30 second timeout after which point they will be forcibly terminated and their resources cleaned up.

After the container finishes running or is terminated, Codie collects the stdout, stderr, and exit status of the code snippet using Docker logs and reports that to the user via a reply.

All put together, this is what sending the example message I used at the top actually looks like.

Actually Using Codie

Aside: You might have noticed both my message and Codie's message have been edited. Yes! Codie does support editing and re-running messages so you can fix typos or make other corrections.

Future Work

Currently, Codie is a private Discord bot that I only run on servers with my friends who I trust. In the future, I plan to make her publicly available. However, I am not confident in the security provided by Docker alone to run this publicly and will migrate to something like Firecracker before I make Codie publicly available.

\ No newline at end of file diff --git a/projects/dirbuf/graph1.svg b/projects/dirbuf/graph1.svg new file mode 100755 index 0000000..ef42e48 --- /dev/null +++ b/projects/dirbuf/graph1.svg @@ -0,0 +1,61 @@ + + +simple + + + +#3 + +#3 + + + +c + +c + + + +#3->c + + + + + +foo + +foo + + + +#3->foo + + + + + +#2 + +#2 + + + +b + +b + + + +#2->b + + + + + +#1 + +#1 + + + \ No newline at end of file diff --git a/projects/dirbuf/graph1a.svg b/projects/dirbuf/graph1a.svg new file mode 100755 index 0000000..d72192e --- /dev/null +++ b/projects/dirbuf/graph1a.svg @@ -0,0 +1,37 @@ + + +simple + + + +cₛ + +cₛ + + + +foo + +foo + + + +cₛ->foo + + + + + +bₛ + +bₛ + + + +a + +a + + + \ No newline at end of file diff --git a/projects/dirbuf/index.html b/projects/dirbuf/index.html new file mode 100644 index 0000000..37b98f1 --- /dev/null +++ b/projects/dirbuf/index.html @@ -0,0 +1,13 @@ +Eli | dirbuf.nvim

dirbuf.nvim

dirbuf.nvim is a file manager I created for Neovim. It was created with the idea of making creating, deleting, and moving files as easy as it is for text.

Why did I create dirbuf.nvim?

In 2020, every file manager plugin I could find used what I call a "command-style" of editing. That is if you want to create, copy, or delete a file, you have to press some specific keystroke, run a special command, or click a certain button to do that. In fact, every file manager I've seen uses this method except for vidir.

Side Note: I didn't actually learn about vidir until I had already implemented most of dirbuf.nvim and was researching dependency-resolution algorithms.

This method works and is fairly simple to implement, but I've encountered a number of issues with it: every plugin has a different set of mappings that often only loosely match default Vim keybindings, meaning you have to memorize more keybindings and remapping keys becomes more painful; input prompts often appear far from your cursor and the file your manipulating which results in a bumpier user experience; and you get a second-class editing experience where you can't use dot-repeating, macros, or other plugins to help you automate your change.

So my idea was that by creating a textual representation of a directory and handing that directly to the user to edit, you could get a for more native and intuitive experience. So creating a new line for a file would actually create a new file, renaming a directory on its line would actually rename the directory, and deleting a file's line would actually delete the file.

With this, you'd automatically work with whatever keybindings the users has, completely support any current and future text-editing plugins, and get one of the best batch renaming tools in the world with the full on-the-fly power of Neovim at your disposal.

How does dirbuf.nvim work?

From a user's perspective, dirbuf.nvim appears fairly simple. When you want to use dirbuf.nvim to make some changes, here's the sequence of events from your user-level perspective.

  1. You open a directory and get a text buffer containing a list of files, directories, symlinks, etc. in that directory.
  2. You make whatever edits you like to the directory buffer. Maybe you rename a few lines by editing their text, copy some others by copying their lines, delete a few few by deleting their lines, and make some new ones by creating new lines.
  3. You save the directory buffer to make your changes and then close the buffer.

By design, dirbuf.nvim is only active in steps 1 and 3. This is important because it means step 2, where all the edits happen, is a completely open box where the user can do whatever they want in any way they want, giving them the full power of Neovim and any plugins they have installed.

However, this means that whenever dirbuf.nvim wants to sync a directory buffer with the filesystem, it has to somehow figure out what changed between step 1 and step 3. So let's break down how dirbuf.nvim does this.

Step 1: Snapshotting & Displaying

In step 1, dirbuf.nvim scans the directory for filesystem entries. This gives us a list of what we call FStates, which are tables with a path, fname (the tail of the path), and an ftype ("file", "directory", "symlink", etc.).

dirbuf.nvim generates a unique id for each FState It then stores these FStates by their ID in a map. We use a map so we can easily lookup FStates in step 3. It then writes these FStates out to the directory buffer so the user can edit them.

So for example, given a file directory like this

.
+├── a
+├── b
+├── c
+└── d/
+

You get a directory buffer like this.

#00000001	a
+#00000002	b
+#00000003	c
+

Step 2: User Edits

Using our example from above, after several edits, the user ends up with the following directory buffer.

#00000002	b
+#00000003	c
+#00000003	foo
+bar/
+

We can see, after whatever edits the user did, the result is they deleted a, copied c to foo, deleted d/, and created bar.

Satisfied with these changes, they save the directory buffer or call :DirbufSync.

Step 3: Syncing

Now that the user has saved the directory buffer, dirbuf.nvim parses every line in the buffer into a FState. Any line with an ID is associated with the corresponding FState in the snapshot. Any line without an ID is considered a new entry.

This association or "linking" of parsed FStates with snapshotted FStates is a generalization of moving, copying, and deleting filesystem entries which allows dirbuf.nvim to figure out what the user "meant" by a series of changes. So if a snapshotted FState has no associated parsed FState, it's been deleted. If it has one linked FState, it's either been moved or left unchanged. And if it has multiple links, it's been either copied or copied and moved.

We can visualize these associations in the following diagram, using the earlier example with snapshotted FStates displayed by their ID. Note that we are intentionally leaving off the new entry of bar/.

Example FState Association Diagram

Dirbuf internally uses a data structure very similar to this FState association diagram called a change map. It makes a few tweaks to the FState association diagram to make it easier to convert to an efficient series of actions in future steps.

Namely, it doesn't store self-links, that is where we would associate an FState with itself, and instead sets stays flag to true, denoted here by subscript s. This prevents self-copies and allows us to easily identify cases where we can convert a copy to a move. The change map also identifies old entries by their filename rather than their ID, which makes dependent changes easier to identify.

Example Change Map

TODO: Discuss dependency resolution algorithm and future work

\ No newline at end of file diff --git a/projects/goofyglyphs/index.html b/projects/goofyglyphs/index.html new file mode 100644 index 0000000..e422f34 --- /dev/null +++ b/projects/goofyglyphs/index.html @@ -0,0 +1 @@ +Eli | Goofyglyphs (📜▶🤪)

Goofyglyphs (📜▶🤪)

Structure

Every clause in the emoji language follows the strict "Subject - Verb - Object/Destination" structure. Each part must be one emoji and all must be present for clause to be complete. Within a message, the same emoji refers to the same object/event; use identifiers to have multiple similar objects/events.

Example: I know you = "👈🧠👉".

You can also have exclamations, which are just a single emoji indicating the exclamation.

Example: It's raining = "🌧️".

Emoji Descriptors

Every emoji can have a description phrase associated with it. These phrases are placed after the emoji they describe and start with a single, special emoji indicating what kind descriptor it is.

  • ▶ (... ◀): Adjective phrase. This phrase contains a list of adjective-type emojis, followed by a ◀ to indicate the end of the adjective phrase. If you only have one adjective-type emoji, ◀ does not need to be specified.
    • Example: My dog ate a big round chicken = "🐕▶👈🍴🐔▶🆙⚪◀".
  • ⏩: Descriptive clause. Begins a new subject-verb-object clause which specifically describes the affected emoji.
    • Example: The dog, which I bought, makes me happy = "🐕⏩👈💳🐕😊👈"
  • 🚫: Negator. Negates emoji immediately following. This does not have any emojis in its descriptor phrase. "Not".
  • 0️⃣1️⃣2️⃣3️⃣4️⃣5️⃣6️⃣7️⃣8️⃣9️⃣🔟: Identifiers. Since emojis tend to refer to the same object/event, you can use identifiers to differentiate between similar objects/events.

The Substantive Emoji

The 🔼 emoji introduces a new subject-verb-object clause which itself acts where the 🔼 is placed.

  • Example: I wonder if fish swim like to sailboats (I'm thinking about whether fish swim similarly to boats) = "👈🤔🔼🏊▶🐟↔️❓🏊▶⛵"

Verb Modifiers

Verbs in particular can have modifiers. These modifiers are placed after the verb they affect, just like emoji descriptors.

  • ❓: Interrogator. Marks the verb-clause as a true-false question.
    • Example: "👉"
  • Tense Modifiers: These indicate the tense of the verb. If unspecified, then verbs are roughly present tense.
    • 🕘: Past. Something which did occur and has now finished.
      • Example: I used to want a meal = "👈🙏🕘🍽️"
    • 🕛: Present. Something which recently began occurring and is still occurring and will continue occurring.
      • Example: I currently want a meal = "👈🙏🕛🍽️"
    • 🕒: Future. Something which has not yet occurred but will later.
      • Example: I will want a meal = "👈🙏🕒🍽️"

Conjunctions

Conjunctions introduce new subject-verb-object clauses with a specific relation to the previous one.

  • ➕: Additional. The following clause exists in addition to the previous one. "And" or "But".
  • ➖: Optional. Either the following clause or the preceding clause are true, but not both. "Or" or "Either... Or".
  • ✖️: Causal. The following clause caused or motivated the earlier clause. "Because" or "Since".
  • ➗: Concessional. The following clause occurred in spite of the earlier one, explaining a reason the earlier one shouldn't have happened, can not follow a descriptive clause. "Although".

Vocabulary

Pronouns

  • 👈: 1st person.
  • 👉: 2nd person.
  • 👐: 3rd person.
  • 👇: Demonstrative pronoun (often followed by a descriptive clause), essentially can be used like a placeholder for a noun. This is essentially an unspecified object/event.

Common Vocabulary

  • ➡️: to be.
  • 🙏: to want/need/hope for; prayer.
  • ✊: to own/have; fist.
  • ✴️: to happen/occur; explosion.
  • 🗣️: to say/write/communicate; speaking/speech.
  • 🧠: to know/remember; knowledge/memory.

Changelog

  • 2022-04-05:
    • Changed ❓ from a clause modifier to a verb modifier. Removed clause modifier section.
    • Changed 👐 to from 1st person plural to 3rd person.
    • Add substantive emoji 🔼.
    • Change adjective phrase emoji from ➰ and ➿ to ▶️ and ◀️.
    • Change descriptive phrase emoji from 〰️ to ⏩.
  • 2021-12-26:
    • Changed descriptive clause emoji from 🔎 to 〰️.
    • Add adjective phrase ➰ (... ➿).
    • Classify descriptive clause emoji as emoji descriptor instead of a conjunction.
    • Remove integrator 🔗.
    • Add more examples and explain overall grammar more.
  • 2017: Initial version. History has since been lost since it was a Google Keep note on my phone for ~4 years.
\ No newline at end of file diff --git a/projects/index.html b/projects/index.html new file mode 100644 index 0000000..a400122 --- /dev/null +++ b/projects/index.html @@ -0,0 +1 @@ +Eli | Projects \ No newline at end of file diff --git a/projects/the-merp-experiment/index.html b/projects/the-merp-experiment/index.html new file mode 100644 index 0000000..b70919c --- /dev/null +++ b/projects/the-merp-experiment/index.html @@ -0,0 +1 @@ +Eli | The Merp Experiment \ No newline at end of file diff --git a/robots.txt b/robots.txt new file mode 100644 index 0000000..570de08 --- /dev/null +++ b/robots.txt @@ -0,0 +1,3 @@ +User-agent: * +Allow: / +Sitemap: https://elihunter173.com/sitemap.xml diff --git a/sitemap.xml b/sitemap.xml new file mode 100644 index 0000000..a5979e5 --- /dev/null +++ b/sitemap.xml @@ -0,0 +1,170 @@ + + + + https://elihunter173.com/ + + + https://elihunter173.com/blog/ + + + https://elihunter173.com/blog/interviewees-t-test/ + 2024-10-17 + + + https://elihunter173.com/blog/toothpaste-reviews-2020/ + 2020-09-07 + + + https://elihunter173.com/notes/ + + + https://elihunter173.com/notes/nand2tetris/ + + + https://elihunter173.com/notes/ncsu/ + + + https://elihunter173.com/notes/ncsu/1f/ + + + https://elihunter173.com/notes/ncsu/1f/csc116/ + + + https://elihunter173.com/notes/ncsu/1s/ + + + https://elihunter173.com/notes/ncsu/1s/csc216/ + + + https://elihunter173.com/notes/ncsu/1s/e102/ + + + https://elihunter173.com/notes/ncsu/1s/ma225/ + + + https://elihunter173.com/notes/ncsu/1s/ma242/ + + + https://elihunter173.com/notes/ncsu/1s/py205/ + + + https://elihunter173.com/notes/ncsu/2f/ + + + https://elihunter173.com/notes/ncsu/2f/csc230/ + + + https://elihunter173.com/notes/ncsu/2f/csc316/ + + + https://elihunter173.com/notes/ncsu/2f/py208/ + + + https://elihunter173.com/notes/ncsu/2f/soc202/ + + + https://elihunter173.com/notes/ncsu/2f/st370/ + + + https://elihunter173.com/notes/ncsu/2s/ + + + https://elihunter173.com/notes/ncsu/2s/csc236/ + + + https://elihunter173.com/notes/ncsu/2s/csc246/ + + + https://elihunter173.com/notes/ncsu/2s/csc333/ + + + https://elihunter173.com/notes/ncsu/2s/ma341/ + + + https://elihunter173.com/notes/ncsu/2s/ma405/ + + + https://elihunter173.com/notes/ncsu/3f/ + + + https://elihunter173.com/notes/ncsu/3f/csc326/ + + + https://elihunter173.com/notes/ncsu/3f/csc412/ + + + https://elihunter173.com/notes/ncsu/3f/ma407/ + + + https://elihunter173.com/notes/ncsu/3f/ma520/ + + + https://elihunter173.com/notes/ncsu/3f/st421/ + + + https://elihunter173.com/notes/ncsu/3s/ + + + https://elihunter173.com/notes/ncsu/3s/csc416/ + + + https://elihunter173.com/notes/ncsu/3s/csc591/ + + + https://elihunter173.com/notes/ncsu/3s/ma402/ + + + https://elihunter173.com/notes/ncsu/3s/ma425/ + + + https://elihunter173.com/notes/ncsu/4f/ + + + https://elihunter173.com/notes/ncsu/4f/csc379/ + + + https://elihunter173.com/notes/ncsu/4f/csc461/ + + + https://elihunter173.com/notes/ncsu/4f/csc492/ + + + https://elihunter173.com/notes/ncsu/4f/ma426/ + + + https://elihunter173.com/notes/ncsu/4f/ma450/ + + + https://elihunter173.com/notes/talks/ + + + https://elihunter173.com/notes/talks/grad-apps/ + 2021-10-14 + + + https://elihunter173.com/notes/talks/notetaking/ + 2021-09-24 + + + https://elihunter173.com/notes/talks/storing-sequences-in-searchable-form/ + 2020-03-11 + + + https://elihunter173.com/projects/ + + + https://elihunter173.com/projects/asteroids-3d/ + + + https://elihunter173.com/projects/codie/ + + + https://elihunter173.com/projects/dirbuf/ + + + https://elihunter173.com/projects/goofyglyphs/ + + + https://elihunter173.com/projects/the-merp-experiment/ + + diff --git a/styles.css b/styles.css new file mode 100644 index 0000000..8c734c3 --- /dev/null +++ b/styles.css @@ -0,0 +1 @@ +@import url("syntax-dark.css") (prefers-color-scheme: dark);@import url("syntax-light.css") (prefers-color-scheme: light);body{font-family:sans-serif;max-width:50rem;margin:0 auto 6rem;padding:0 1rem}img{max-width:100%}@media (prefers-color-scheme: dark){body{background-color:#121212;color:#fff}a{color:#58a6ff}a:visited{color:#cc76a4}a:active{color:#ff0000}}h1.title{font-size:2rem;margin-top:0.25rem;margin-bottom:0.5rem}pre{padding:0.5rem;outline:0.15rem solid;overflow-x:auto}code:not(pre *){padding:0.15em 0.3em;border-radius:4px}@media (prefers-color-scheme: light){code:not(pre *){background-color:rgba(175,184,193,0.2)}}@media (prefers-color-scheme: dark){code:not(pre *){background-color:rgba(94,100,110,0.4)}}table{display:block;max-width:100%;overflow-x:auto}table{border-collapse:collapse}th,td{border:1px solid;padding:0.25em}figure{text-align:center;margin:auto 0}figure figcaption{font-size:1.15rem;font-weight:bold}mjx-container[display="true"]{display:inline-grid;max-width:100%;overflow-x:auto;overflow-y:visible}nav{display:flex;align-items:baseline}nav ul{margin-left:auto;list-style:none}nav ul li{display:inline;margin-left:0.75em}video{width:100%} diff --git a/syntax-dark.css b/syntax-dark.css new file mode 100644 index 0000000..79f7045 --- /dev/null +++ b/syntax-dark.css @@ -0,0 +1,188 @@ +/* + * theme "gruvbox" generated by syntect + */ + +.z-code { + color: #fdf4c1; + background-color: #282828; +} + +.z-punctuation.z-definition.z-tag { + color: #83a598; +} +.z-punctuation.z-definition.z-entity { + color: #d3869b; +} +.z-constant { + color: #d3869b; +} +.z-constant.z-character.z-escape { + color: #b8bb26; +} +.z-constant.z-other { + color: #fdf4c1; +} +.z-entity { + color: #8ec07c; +} +.z-keyword.z-operator.z-comparison, .z-keyword.z-operator, .z-keyword.z-operator.z-symbolic, .z-keyword.z-operator.z-string, .z-keyword.z-operator.z-assignment, .z-keyword.z-operator.z-arithmetic, .z-keyword.z-operator.z-class, .z-keyword.z-operator.z-key, .z-keyword.z-operator.z-logical { + color: #fe8019; +} +.z-keyword, .z-keyword.z-operator.z-new, .z-keyword.z-other, .z-keyword.z-control { + color: #fa5c4b; +} +.z-storage { + color: #fa5c4b; +} +.z-string, .z-string.z-unquoted.z-heredoc .z-string { + color: #b8bb26; +} +.z-comment { + color: #928374; +font-style: italic; +} +.z-string.z-regexp .z-constant.z-character.z-escape { + color: #b8bb26; +} +.z-support { + color: #fabd2f; +} +.z-variable { + color: #fdf4c1; +} +.z-variable.z-language { + color: #fdf4c1; +} +.z-meta.z-function-call { + color: #fdf4c1; +} +.z-invalid { + color: #fdf4c1; + background-color: #932b1e; +} +.z-text .z-source, .z-string.z-unquoted.z-heredoc, .z-source .z-source { + color: #fdf4c1; +} +.z-string.z-quoted .z-source { + color: #b8bb26; +} +.z-string { + color: #b8bb26; +} +.z-support.z-constant { + color: #fabd2f; +} +.z-support.z-class { + color: #8ec07c; +} +.z-entity.z-name.z-tag { + color: #8ec07c; +font-weight: bold; +} +.z-meta.z-tag, .z-meta.z-tag .z-entity { + color: #8ec07c; +} +.z-constant.z-other.z-color.z-rgb-value { + color: #83a598; +} +.z-meta.z-selector.z-css .z-entity.z-name.z-tag { + color: #fa5c4b; +} +.z-meta.z-selector.z-css, .z-entity.z-other.z-attribute-name.z-id { + color: #b8bb26; +} +.z-meta.z-selector.z-css .z-entity.z-other.z-attribute-name.z-class { + color: #b8bb26; +} +.z-support.z-type.z-property-name.z-css { + color: #8ec07c; +} +.z-meta.z-preprocessor.z-at-rule .z-keyword.z-control.z-at-rule { + color: #fabd2f; +} +.z-meta.z-property-value .z-constant { + color: #fabd2f; +} +.z-meta.z-property-value .z-support.z-constant.z-named-color.z-css { + color: #fe8019; +} +.z-meta.z-constructor.z-argument.z-css { + color: #fabd2f; +} +.z-meta.z-diff, .z-meta.z-diff.z-header { + color: #83a598; +} +.z-markup.z-deleted { + color: #fa5c4b; +} +.z-markup.z-changed { + color: #fabd2f; +} +.z-markup.z-inserted { + color: #8ec07c; +} +.z-markup.z-bold { +font-weight: bold; +} +.z-markup.z-italic { +font-style: italic; +} +.z-markup.z-heading { + color: #8ec07c; +font-weight: bold; +} +.z-entity.z-name.z-type.z-class.z-php { + color: #8ec07c; +} +.z-keyword.z-other.z-phpdoc { + color: #928374; +} +.z-constant.z-numeric.z-css, .z-keyword.z-other.z-unit.z-css { + color: #d3869b; +} +.z-punctuation.z-definition.z-entity.z-css { + color: #b8bb26; +} +.z-variable.z-language.z-js { + color: #fabd2f; +} +.z-string.z-unquoted.z-label.z-js { + color: #fdf4c1; +} +.z-constant.z-other.z-table-name.z-sql { + color: #b8bb26; +} +.z-constant.z-other.z-database-name.z-sql { + color: #b8bb26; +} +.z-storage.z-type.z-dired.z-item.z-directory, .z-dired.z-item.z-directory { + color: #8ec07c; +} +.z-orgmode.z-link { + color: #fabd2f; +font-style: underline; +} +.z-orgmode.z-page { + color: #b8bb26; +} +.z-orgmode.z-break { + color: #d3869b; +} +.z-orgmode.z-headline { + color: #8ec07c; +} +.z-orgmode.z-tack { + color: #fabd2f; +} +.z-orgmode.z-follow_up { + color: #fabd2f; +} +.z-orgmode.z-checkbox { + color: #fabd2f; +} +.z-orgmode.z-checkbox.z-summary { + color: #fabd2f; +} +.z-orgmode.z-tags { + color: #fa5c4b; +} diff --git a/syntax-light.css b/syntax-light.css new file mode 100644 index 0000000..dfd37a8 --- /dev/null +++ b/syntax-light.css @@ -0,0 +1,192 @@ +/* + * theme "gruvbox" generated by syntect + */ + +.z-code { + color: #282828; + background-color: #fcf0ca; +} + +.z-punctuation.z-definition.z-tag { + color: #076678; +} +.z-punctuation.z-definition.z-entity { + color: #8f3f71; +} +.z-constant { + color: #8f3f71; +} +.z-constant.z-character.z-escape { + color: #79740e; +} +.z-constant.z-other { + color: #282828; +} +.z-entity { + color: #407959; +} +.z-keyword.z-operator.z-comparison, .z-keyword.z-operator, .z-keyword.z-operator.z-symbolic, .z-keyword.z-operator.z-string, .z-keyword.z-operator.z-assignment, .z-keyword.z-operator.z-arithmetic, .z-keyword.z-operator.z-class, .z-keyword.z-operator.z-key, .z-keyword.z-operator.z-logical { + color: #b23c15; +} +.z-keyword, .z-keyword.z-operator.z-new, .z-keyword.z-other, .z-keyword.z-control { + color: #9d0006; +} +.z-storage { + color: #9d0006; +} +.z-string, .z-string.z-unquoted.z-heredoc .z-string { + color: #79740e; +} +.z-comment { + color: #928374; +font-style: italic; +} +.z-string.z-regexp .z-constant.z-character.z-escape { + color: #79740e; +} +.z-support { + color: #b57614; +} +.z-variable { + color: #282828; +} +.z-variable.z-language { + color: #282828; +} +.z-meta.z-function-call { + color: #282828; +} +.z-invalid { + color: #282828; + background-color: #932b1e; +} +.z-text .z-source, .z-string.z-unquoted.z-heredoc, .z-source .z-source { + color: #282828; +} +.z-string.z-quoted .z-source { + color: #79740e; +} +.z-string { + color: #79740e; +} +.z-support.z-constant { + color: #b57614; +} +.z-support.z-class { + color: #407959; +} +.z-entity.z-name.z-tag { + color: #407959; +font-weight: bold; +} +.z-meta.z-tag, .z-meta.z-tag .z-entity { + color: #407959; +} +.z-constant.z-other.z-color.z-rgb-value { + color: #076678; +} +.z-meta.z-selector.z-css .z-entity.z-name.z-tag { + color: #9d0006; +} +.z-meta.z-selector.z-css, .z-entity.z-other.z-attribute-name.z-id { + color: #79740e; +} +.z-meta.z-selector.z-css .z-entity.z-other.z-attribute-name.z-class { + color: #79740e; +} +.z-support.z-type.z-property-name.z-css { + color: #407959; +} +.z-meta.z-preprocessor.z-at-rule .z-keyword.z-control.z-at-rule { + color: #b57614; +} +.z-meta.z-property-value .z-constant { + color: #b57614; +} +.z-meta.z-property-value .z-support.z-constant.z-named-color.z-css { + color: #b23c15; +} +.z-meta.z-constructor.z-argument.z-css { + color: #b57614; +} +.z-meta.z-diff, .z-meta.z-diff.z-header { + color: #282828; + background-color: #076678; +} +.z-markup.z-deleted { + color: #282828; + background-color: #9d0006; +} +.z-markup.z-changed { + color: #282828; + background-color: #b57614; +} +.z-markup.z-inserted { + color: #282828; + background-color: #407959; +} +.z-markup.z-bold { +font-weight: bold; +} +.z-markup.z-italic { +font-style: italic; +} +.z-markup.z-heading { + color: #407959; +font-weight: bold; +} +.z-entity.z-name.z-type.z-class.z-php { + color: #407959; +} +.z-keyword.z-other.z-phpdoc { + color: #928374; +} +.z-constant.z-numeric.z-css, .z-keyword.z-other.z-unit.z-css { + color: #8f3f71; +} +.z-punctuation.z-definition.z-entity.z-css { + color: #79740e; +} +.z-variable.z-language.z-js { + color: #b57614; +} +.z-string.z-unquoted.z-label.z-js { + color: #282828; +} +.z-constant.z-other.z-table-name.z-sql { + color: #79740e; +} +.z-constant.z-other.z-database-name.z-sql { + color: #79740e; +} +.z-storage.z-type.z-dired.z-item.z-directory, .z-dired.z-item.z-directory { + color: #407959; +} +.z-orgmode.z-link { + color: #b57614; +font-style: underline; +} +.z-orgmode.z-page { + color: #79740e; +} +.z-orgmode.z-break { + color: #8f3f71; +} +.z-orgmode.z-headline { + color: #407959; +} +.z-orgmode.z-tack { + color: #b57614; +} +.z-orgmode.z-follow_up { + color: #b57614; +} +.z-orgmode.z-checkbox { + color: #b57614; +} +.z-orgmode.z-checkbox.z-summary { + color: #b57614; +} +.z-orgmode.z-tags { + color: #9d0006; +} diff --git a/the-merp-experiment/assets/buildzone.png b/the-merp-experiment/assets/buildzone.png new file mode 100644 index 0000000..b70b773 Binary files /dev/null and b/the-merp-experiment/assets/buildzone.png differ diff --git a/the-merp-experiment/assets/factory.png b/the-merp-experiment/assets/factory.png new file mode 100644 index 0000000..62d54d3 Binary files /dev/null and b/the-merp-experiment/assets/factory.png differ diff --git a/the-merp-experiment/assets/gym.png b/the-merp-experiment/assets/gym.png new file mode 100644 index 0000000..1af64ef Binary files /dev/null and b/the-merp-experiment/assets/gym.png differ diff --git a/the-merp-experiment/assets/house.png b/the-merp-experiment/assets/house.png new file mode 100644 index 0000000..95d23a7 Binary files /dev/null and b/the-merp-experiment/assets/house.png differ diff --git a/the-merp-experiment/assets/merp.png b/the-merp-experiment/assets/merp.png new file mode 100644 index 0000000..2322cb0 Binary files /dev/null and b/the-merp-experiment/assets/merp.png differ diff --git a/the-merp-experiment/assets/pile.png b/the-merp-experiment/assets/pile.png new file mode 100644 index 0000000..728f389 Binary files /dev/null and b/the-merp-experiment/assets/pile.png differ diff --git a/the-merp-experiment/assets/road.png b/the-merp-experiment/assets/road.png new file mode 100644 index 0000000..b215ef7 Binary files /dev/null and b/the-merp-experiment/assets/road.png differ diff --git a/the-merp-experiment/assets/road_2way_atlas.png b/the-merp-experiment/assets/road_2way_atlas.png new file mode 100644 index 0000000..0b9494c Binary files /dev/null and b/the-merp-experiment/assets/road_2way_atlas.png differ diff --git a/the-merp-experiment/assets/road_one_way.png b/the-merp-experiment/assets/road_one_way.png new file mode 100644 index 0000000..0f99145 Binary files /dev/null and b/the-merp-experiment/assets/road_one_way.png differ diff --git a/the-merp-experiment/game.js b/the-merp-experiment/game.js new file mode 100644 index 0000000..28491fd --- /dev/null +++ b/the-merp-experiment/game.js @@ -0,0 +1,1941 @@ +const lAudioContext = (typeof AudioContext !== 'undefined' ? AudioContext : (typeof webkitAudioContext !== 'undefined' ? webkitAudioContext : undefined)); +let wasm; + +const heap = new Array(128).fill(undefined); + +heap.push(undefined, null, true, false); + +function getObject(idx) { return heap[idx]; } + +let heap_next = heap.length; + +function dropObject(idx) { + if (idx < 132) return; + heap[idx] = heap_next; + heap_next = idx; +} + +function takeObject(idx) { + const ret = getObject(idx); + dropObject(idx); + return ret; +} + +function addHeapObject(obj) { + if (heap_next === heap.length) heap.push(heap.length + 1); + const idx = heap_next; + heap_next = heap[idx]; + + heap[idx] = obj; + return idx; +} + +const cachedTextDecoder = (typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }) : { decode: () => { throw Error('TextDecoder not available') } } ); + +if (typeof TextDecoder !== 'undefined') { cachedTextDecoder.decode(); }; + +let cachedUint8Memory0 = null; + +function getUint8Memory0() { + if (cachedUint8Memory0 === null || cachedUint8Memory0.byteLength === 0) { + cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer); + } + return cachedUint8Memory0; +} + +function getStringFromWasm0(ptr, len) { + ptr = ptr >>> 0; + return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len)); +} + +function isLikeNone(x) { + return x === undefined || x === null; +} + +let cachedFloat64Memory0 = null; + +function getFloat64Memory0() { + if (cachedFloat64Memory0 === null || cachedFloat64Memory0.byteLength === 0) { + cachedFloat64Memory0 = new Float64Array(wasm.memory.buffer); + } + return cachedFloat64Memory0; +} + +let cachedInt32Memory0 = null; + +function getInt32Memory0() { + if (cachedInt32Memory0 === null || cachedInt32Memory0.byteLength === 0) { + cachedInt32Memory0 = new Int32Array(wasm.memory.buffer); + } + return cachedInt32Memory0; +} + +let WASM_VECTOR_LEN = 0; + +const cachedTextEncoder = (typeof TextEncoder !== 'undefined' ? new TextEncoder('utf-8') : { encode: () => { throw Error('TextEncoder not available') } } ); + +const encodeString = (typeof cachedTextEncoder.encodeInto === 'function' + ? function (arg, view) { + return cachedTextEncoder.encodeInto(arg, view); +} + : function (arg, view) { + const buf = cachedTextEncoder.encode(arg); + view.set(buf); + return { + read: arg.length, + written: buf.length + }; +}); + +function passStringToWasm0(arg, malloc, realloc) { + + if (realloc === undefined) { + const buf = cachedTextEncoder.encode(arg); + const ptr = malloc(buf.length, 1) >>> 0; + getUint8Memory0().subarray(ptr, ptr + buf.length).set(buf); + WASM_VECTOR_LEN = buf.length; + return ptr; + } + + let len = arg.length; + let ptr = malloc(len, 1) >>> 0; + + const mem = getUint8Memory0(); + + let offset = 0; + + for (; offset < len; offset++) { + const code = arg.charCodeAt(offset); + if (code > 0x7F) break; + mem[ptr + offset] = code; + } + + if (offset !== len) { + if (offset !== 0) { + arg = arg.slice(offset); + } + ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0; + const view = getUint8Memory0().subarray(ptr + offset, ptr + len); + const ret = encodeString(arg, view); + + offset += ret.written; + } + + WASM_VECTOR_LEN = offset; + return ptr; +} + +function debugString(val) { + // primitive types + const type = typeof val; + if (type == 'number' || type == 'boolean' || val == null) { + return `${val}`; + } + if (type == 'string') { + return `"${val}"`; + } + if (type == 'symbol') { + const description = val.description; + if (description == null) { + return 'Symbol'; + } else { + return `Symbol(${description})`; + } + } + if (type == 'function') { + const name = val.name; + if (typeof name == 'string' && name.length > 0) { + return `Function(${name})`; + } else { + return 'Function'; + } + } + // objects + if (Array.isArray(val)) { + const length = val.length; + let debug = '['; + if (length > 0) { + debug += debugString(val[0]); + } + for(let i = 1; i < length; i++) { + debug += ', ' + debugString(val[i]); + } + debug += ']'; + return debug; + } + // Test for built-in + const builtInMatches = /\[object ([^\]]+)\]/.exec(toString.call(val)); + let className; + if (builtInMatches.length > 1) { + className = builtInMatches[1]; + } else { + // Failed to match the standard '[object ClassName]' + return toString.call(val); + } + if (className == 'Object') { + // we're a user defined class or Object + // JSON.stringify avoids problems with cycles, and is generally much + // easier than looping through ownProperties of `val`. + try { + return 'Object(' + JSON.stringify(val) + ')'; + } catch (_) { + return 'Object'; + } + } + // errors + if (val instanceof Error) { + return `${val.name}: ${val.message}\n${val.stack}`; + } + // TODO we could test for more things here, like `Set`s and `Map`s. + return className; +} + +function makeMutClosure(arg0, arg1, dtor, f) { + const state = { a: arg0, b: arg1, cnt: 1, dtor }; + const real = (...args) => { + // First up with a closure we increment the internal reference + // count. This ensures that the Rust closure environment won't + // be deallocated while we're invoking it. + state.cnt++; + const a = state.a; + state.a = 0; + try { + return f(a, state.b, ...args); + } finally { + if (--state.cnt === 0) { + wasm.__wbindgen_export_2.get(state.dtor)(a, state.b); + + } else { + state.a = a; + } + } + }; + real.original = state; + + return real; +} +function __wbg_adapter_34(arg0, arg1) { + wasm._dyn_core__ops__function__FnMut_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h574b8bde9eb27d24(arg0, arg1); +} + +function __wbg_adapter_37(arg0, arg1, arg2) { + wasm._dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h355f9fc06797d336(arg0, arg1, addHeapObject(arg2)); +} + +function __wbg_adapter_52(arg0, arg1) { + wasm._dyn_core__ops__function__FnMut_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h444aca3444dce197(arg0, arg1); +} + +function __wbg_adapter_55(arg0, arg1, arg2) { + wasm._dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h9eebc0e84eded97e(arg0, arg1, addHeapObject(arg2)); +} + +function __wbg_adapter_58(arg0, arg1, arg2) { + wasm._dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h84b111d3460d60c9(arg0, arg1, addHeapObject(arg2)); +} + +function handleError(f, args) { + try { + return f.apply(this, args); + } catch (e) { + wasm.__wbindgen_exn_store(addHeapObject(e)); + } +} + +let cachedFloat32Memory0 = null; + +function getFloat32Memory0() { + if (cachedFloat32Memory0 === null || cachedFloat32Memory0.byteLength === 0) { + cachedFloat32Memory0 = new Float32Array(wasm.memory.buffer); + } + return cachedFloat32Memory0; +} + +function getArrayF32FromWasm0(ptr, len) { + ptr = ptr >>> 0; + return getFloat32Memory0().subarray(ptr / 4, ptr / 4 + len); +} + +function getArrayI32FromWasm0(ptr, len) { + ptr = ptr >>> 0; + return getInt32Memory0().subarray(ptr / 4, ptr / 4 + len); +} + +let cachedUint32Memory0 = null; + +function getUint32Memory0() { + if (cachedUint32Memory0 === null || cachedUint32Memory0.byteLength === 0) { + cachedUint32Memory0 = new Uint32Array(wasm.memory.buffer); + } + return cachedUint32Memory0; +} + +function getArrayU32FromWasm0(ptr, len) { + ptr = ptr >>> 0; + return getUint32Memory0().subarray(ptr / 4, ptr / 4 + len); +} + +async function __wbg_load(module, imports) { + if (typeof Response === 'function' && module instanceof Response) { + if (typeof WebAssembly.instantiateStreaming === 'function') { + try { + return await WebAssembly.instantiateStreaming(module, imports); + + } catch (e) { + if (module.headers.get('Content-Type') != 'application/wasm') { + console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e); + + } else { + throw e; + } + } + } + + const bytes = await module.arrayBuffer(); + return await WebAssembly.instantiate(bytes, imports); + + } else { + const instance = await WebAssembly.instantiate(module, imports); + + if (instance instanceof WebAssembly.Instance) { + return { instance, module }; + + } else { + return instance; + } + } +} + +function __wbg_get_imports() { + const imports = {}; + imports.wbg = {}; + imports.wbg.__wbindgen_cb_drop = function(arg0) { + const obj = takeObject(arg0).original; + if (obj.cnt-- == 1) { + obj.a = 0; + return true; + } + const ret = false; + return ret; + }; + imports.wbg.__wbindgen_object_drop_ref = function(arg0) { + takeObject(arg0); + }; + imports.wbg.__wbg_stringify_e1b19966d964d242 = function() { return handleError(function (arg0) { + const ret = JSON.stringify(getObject(arg0)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_fetch_1f9eb1a6c5433fb7 = function(arg0, arg1, arg2) { + const ret = getObject(arg0).fetch(getStringFromWasm0(arg1, arg2)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_instanceof_Response_4c3b1446206114d1 = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof Response; + } catch (_) { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_status_d6d47ad2837621eb = function(arg0) { + const ret = getObject(arg0).status; + return ret; + }; + imports.wbg.__wbg_arrayBuffer_5b2688e3dd873fed = function() { return handleError(function (arg0) { + const ret = getObject(arg0).arrayBuffer(); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_new_8f67e318f15d7254 = function(arg0) { + const ret = new Uint8Array(getObject(arg0)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_mark_40e050a77cc39fea = function(arg0, arg1) { + performance.mark(getStringFromWasm0(arg0, arg1)); + }; + imports.wbg.__wbg_log_c9486ca5d8e2cbe8 = function(arg0, arg1) { + let deferred0_0; + let deferred0_1; + try { + deferred0_0 = arg0; + deferred0_1 = arg1; + console.log(getStringFromWasm0(arg0, arg1)); + } finally { + wasm.__wbindgen_free(deferred0_0, deferred0_1, 1); + } + }; + imports.wbg.__wbg_log_aba5996d9bde071f = function(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) { + let deferred0_0; + let deferred0_1; + try { + deferred0_0 = arg0; + deferred0_1 = arg1; + console.log(getStringFromWasm0(arg0, arg1), getStringFromWasm0(arg2, arg3), getStringFromWasm0(arg4, arg5), getStringFromWasm0(arg6, arg7)); + } finally { + wasm.__wbindgen_free(deferred0_0, deferred0_1, 1); + } + }; + imports.wbg.__wbg_width_cfc58d9656d60465 = function(arg0) { + const ret = getObject(arg0).width; + return ret; + }; + imports.wbg.__wbg_height_1ba9072bd4001d19 = function(arg0) { + const ret = getObject(arg0).height; + return ret; + }; + imports.wbg.__wbg_matchMedia_7fbd33cb577fe4ad = function() { return handleError(function (arg0, arg1, arg2) { + const ret = getObject(arg0).matchMedia(getStringFromWasm0(arg1, arg2)); + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_matches_4cc0ff05af669dc3 = function(arg0) { + const ret = getObject(arg0).matches; + return ret; + }; + imports.wbg.__wbg_document_d609202d16c38224 = function(arg0) { + const ret = getObject(arg0).document; + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_querySelector_c72dce5ac4b6bc3e = function() { return handleError(function (arg0, arg1, arg2) { + const ret = getObject(arg0).querySelector(getStringFromWasm0(arg1, arg2)); + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_instanceof_HtmlCanvasElement_fba0ac991170cc00 = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof HTMLCanvasElement; + } catch (_) { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_body_64abc9aba1891e91 = function(arg0) { + const ret = getObject(arg0).body; + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_appendChild_d30e6b83791d04c0 = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg0).appendChild(getObject(arg1)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_addEventListener_9bf60ea8a362e5e4 = function() { return handleError(function (arg0, arg1, arg2, arg3) { + getObject(arg0).addEventListener(getStringFromWasm0(arg1, arg2), getObject(arg3)); + }, arguments) }; + imports.wbg.__wbg_parentElement_72e144c2e8d9e0b5 = function(arg0) { + const ret = getObject(arg0).parentElement; + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_getBoundingClientRect_4167ccfa40cf88fc = function(arg0) { + const ret = getObject(arg0).getBoundingClientRect(); + return addHeapObject(ret); + }; + imports.wbg.__wbg_width_1ccae8ab185a4192 = function(arg0) { + const ret = getObject(arg0).width; + return ret; + }; + imports.wbg.__wbg_height_415b4e67932f43c9 = function(arg0) { + const ret = getObject(arg0).height; + return ret; + }; + imports.wbg.__wbg_requestAnimationFrame_74309aadebde12fa = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg0).requestAnimationFrame(getObject(arg1)); + return ret; + }, arguments) }; + imports.wbg.__wbg_setTimeout_06458eba2b40711c = function() { return handleError(function (arg0, arg1, arg2) { + const ret = getObject(arg0).setTimeout(getObject(arg1), arg2); + return ret; + }, arguments) }; + imports.wbg.__wbg_stopPropagation_b7a931152e09c2ab = function(arg0) { + getObject(arg0).stopPropagation(); + }; + imports.wbg.__wbg_cancelBubble_976cfdf7ac449a6c = function(arg0) { + const ret = getObject(arg0).cancelBubble; + return ret; + }; + imports.wbg.__wbg_matches_9502c0f8ac0be969 = function(arg0) { + const ret = getObject(arg0).matches; + return ret; + }; + imports.wbg.__wbg_preventDefault_7f821f72e7c6b5d4 = function(arg0) { + getObject(arg0).preventDefault(); + }; + imports.wbg.__wbindgen_object_clone_ref = function(arg0) { + const ret = getObject(arg0); + return addHeapObject(ret); + }; + imports.wbg.__wbg_new_9fb8d994e1c0aaac = function() { + const ret = new Object(); + return addHeapObject(ret); + }; + imports.wbg.__wbg_target_52ddf6955f636bf5 = function(arg0) { + const ret = getObject(arg0).target; + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_is_ff7acd231c75c0e4 = function(arg0, arg1) { + const ret = Object.is(getObject(arg0), getObject(arg1)); + return ret; + }; + imports.wbg.__wbg_offsetX_e8c2e5379a90ae29 = function(arg0) { + const ret = getObject(arg0).offsetX; + return ret; + }; + imports.wbg.__wbg_offsetY_b8587366f6d36a25 = function(arg0) { + const ret = getObject(arg0).offsetY; + return ret; + }; + imports.wbg.__wbg_movementX_0a37286f5ab0f3d1 = function(arg0) { + const ret = getObject(arg0).movementX; + return ret; + }; + imports.wbg.__wbg_movementY_e32c630fded47131 = function(arg0) { + const ret = getObject(arg0).movementY; + return ret; + }; + imports.wbg.__wbg_requestFullscreen_3c582ffcaaffe1fd = function() { return handleError(function (arg0) { + getObject(arg0).requestFullscreen(); + }, arguments) }; + imports.wbg.__wbg_buttons_45faa2de9fb9d23b = function(arg0) { + const ret = getObject(arg0).buttons; + return ret; + }; + imports.wbg.__wbg_keyCode_48fe24f81bbcf215 = function(arg0) { + const ret = getObject(arg0).keyCode; + return ret; + }; + imports.wbg.__wbg_charCode_702eeeb047f6dad2 = function(arg0) { + const ret = getObject(arg0).charCode; + return ret; + }; + imports.wbg.__wbg_pointerType_07ad77393049c448 = function(arg0, arg1) { + const ret = getObject(arg1).pointerType; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_pointerId_32f8345c9e0f0ed8 = function(arg0) { + const ret = getObject(arg0).pointerId; + return ret; + }; + imports.wbg.__wbg_key_cf8022c18f47869e = function(arg0, arg1) { + const ret = getObject(arg1).key; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_ctrlKey_977280484bcead08 = function(arg0) { + const ret = getObject(arg0).ctrlKey; + return ret; + }; + imports.wbg.__wbg_altKey_bf16cace6fb79198 = function(arg0) { + const ret = getObject(arg0).altKey; + return ret; + }; + imports.wbg.__wbg_getModifierState_bdeffc8dda44d6dd = function(arg0, arg1, arg2) { + const ret = getObject(arg0).getModifierState(getStringFromWasm0(arg1, arg2)); + return ret; + }; + imports.wbg.__wbg_clientX_1a01963cb1caa614 = function(arg0) { + const ret = getObject(arg0).clientX; + return ret; + }; + imports.wbg.__wbg_clientY_c370190d4150fba9 = function(arg0) { + const ret = getObject(arg0).clientY; + return ret; + }; + imports.wbg.__wbg_pressure_b9f7c7decc59eb11 = function(arg0) { + const ret = getObject(arg0).pressure; + return ret; + }; + imports.wbg.__wbg_setPointerCapture_ba1b525b85454761 = function() { return handleError(function (arg0, arg1) { + getObject(arg0).setPointerCapture(arg1); + }, arguments) }; + imports.wbg.__wbg_removeEventListener_70ee8cc1640c97d7 = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).removeEventListener(getStringFromWasm0(arg1, arg2), getObject(arg3), getObject(arg4)); + }, arguments) }; + imports.wbg.__wbindgen_string_new = function(arg0, arg1) { + const ret = getStringFromWasm0(arg0, arg1); + return addHeapObject(ret); + }; + imports.wbg.__wbg_error_cd2ee9c1f33e07e2 = function(arg0, arg1) { + console.error(getObject(arg0), getObject(arg1)); + }; + imports.wbg.__wbg_addEventListener_374cbfd2bbc19ccf = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).addEventListener(getStringFromWasm0(arg1, arg2), getObject(arg3), getObject(arg4)); + }, arguments) }; + imports.wbg.__wbg_new_abda76e883ba8a5f = function() { + const ret = new Error(); + return addHeapObject(ret); + }; + imports.wbg.__wbg_stack_658279fe44541cf6 = function(arg0, arg1) { + const ret = getObject(arg1).stack; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_error_f851667af71bcfc6 = function(arg0, arg1) { + let deferred0_0; + let deferred0_1; + try { + deferred0_0 = arg0; + deferred0_1 = arg1; + console.error(getStringFromWasm0(arg0, arg1)); + } finally { + wasm.__wbindgen_free(deferred0_0, deferred0_1, 1); + } + }; + imports.wbg.__wbg_resume_61e2f63e5d5444cd = function() { return handleError(function (arg0) { + const ret = getObject(arg0).resume(); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_close_b87bff143de234d5 = function() { return handleError(function (arg0) { + const ret = getObject(arg0).close(); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_eval_0b93354704a20351 = function() { return handleError(function (arg0, arg1) { + const ret = eval(getStringFromWasm0(arg0, arg1)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbindgen_boolean_get = function(arg0) { + const v = getObject(arg0); + const ret = typeof(v) === 'boolean' ? (v ? 1 : 0) : 2; + return ret; + }; + imports.wbg.__wbg_crypto_58f13aa23ffcb166 = function(arg0) { + const ret = getObject(arg0).crypto; + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_is_object = function(arg0) { + const val = getObject(arg0); + const ret = typeof(val) === 'object' && val !== null; + return ret; + }; + imports.wbg.__wbg_process_5b786e71d465a513 = function(arg0) { + const ret = getObject(arg0).process; + return addHeapObject(ret); + }; + imports.wbg.__wbg_versions_c2ab80650590b6a2 = function(arg0) { + const ret = getObject(arg0).versions; + return addHeapObject(ret); + }; + imports.wbg.__wbg_node_523d7bd03ef69fba = function(arg0) { + const ret = getObject(arg0).node; + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_is_string = function(arg0) { + const ret = typeof(getObject(arg0)) === 'string'; + return ret; + }; + imports.wbg.__wbg_require_2784e593a4674877 = function() { return handleError(function () { + const ret = module.require; + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbindgen_is_function = function(arg0) { + const ret = typeof(getObject(arg0)) === 'function'; + return ret; + }; + imports.wbg.__wbg_call_5da1969d7cd31ccd = function() { return handleError(function (arg0, arg1, arg2) { + const ret = getObject(arg0).call(getObject(arg1), getObject(arg2)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_msCrypto_abcb1295e768d1f2 = function(arg0) { + const ret = getObject(arg0).msCrypto; + return addHeapObject(ret); + }; + imports.wbg.__wbg_newwithlength_6c2df9e2f3028c43 = function(arg0) { + const ret = new Uint8Array(arg0 >>> 0); + return addHeapObject(ret); + }; + imports.wbg.__wbg_subarray_2e940e41c0f5a1d9 = function(arg0, arg1, arg2) { + const ret = getObject(arg0).subarray(arg1 >>> 0, arg2 >>> 0); + return addHeapObject(ret); + }; + imports.wbg.__wbg_getRandomValues_504510b5564925af = function() { return handleError(function (arg0, arg1) { + getObject(arg0).getRandomValues(getObject(arg1)); + }, arguments) }; + imports.wbg.__wbg_randomFillSync_a0d98aa11c81fe89 = function() { return handleError(function (arg0, arg1) { + getObject(arg0).randomFillSync(takeObject(arg1)); + }, arguments) }; + imports.wbg.__wbg_now_096aa89623f72d50 = function() { + const ret = Date.now(); + return ret; + }; + imports.wbg.__wbg_connected_b7635f1ca65b9aed = function(arg0) { + const ret = getObject(arg0).connected; + return ret; + }; + imports.wbg.__wbg_instanceof_DomException_b6a266bb8c76af9e = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof DOMException; + } catch (_) { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbindgen_number_get = function(arg0, arg1) { + const obj = getObject(arg1); + const ret = typeof(obj) === 'number' ? obj : undefined; + getFloat64Memory0()[arg0 / 8 + 1] = isLikeNone(ret) ? 0 : ret; + getInt32Memory0()[arg0 / 4 + 0] = !isLikeNone(ret); + }; + imports.wbg.__wbg_pressed_e69db502a61fa2d8 = function(arg0) { + const ret = getObject(arg0).pressed; + return ret; + }; + imports.wbg.__wbg_value_06cba5b7a5b72e36 = function(arg0) { + const ret = getObject(arg0).value; + return ret; + }; + imports.wbg.__wbindgen_is_null = function(arg0) { + const ret = getObject(arg0) === null; + return ret; + }; + imports.wbg.__wbg_id_5dc2c54ac7e4e03d = function(arg0, arg1) { + const ret = getObject(arg1).id; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_buttons_db34e12152ea40cb = function(arg0) { + const ret = getObject(arg0).buttons; + return addHeapObject(ret); + }; + imports.wbg.__wbg_length_1009b1af0c481d7b = function(arg0) { + const ret = getObject(arg0).length; + return ret; + }; + imports.wbg.__wbg_axes_d0d77b474ee9ca9b = function(arg0) { + const ret = getObject(arg0).axes; + return addHeapObject(ret); + }; + imports.wbg.__wbg_mapping_f5c841b5e4d3469b = function(arg0) { + const ret = getObject(arg0).mapping; + return addHeapObject(ret); + }; + imports.wbg.__wbg_get_f01601b5a68d10e3 = function(arg0, arg1) { + const ret = getObject(arg0)[arg1 >>> 0]; + return addHeapObject(ret); + }; + imports.wbg.__wbg_isSecureContext_4d5c40709f7f7559 = function(arg0) { + const ret = getObject(arg0).isSecureContext; + return ret; + }; + imports.wbg.__wbg_navigator_96ba491902f8f083 = function(arg0) { + const ret = getObject(arg0).navigator; + return addHeapObject(ret); + }; + imports.wbg.__wbg_getGamepads_d4130931a826d504 = function() { return handleError(function (arg0) { + const ret = getObject(arg0).getGamepads(); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_index_6b2865fd145fa48d = function(arg0) { + const ret = getObject(arg0).index; + return ret; + }; + imports.wbg.__wbg_message_3915f683795a43d9 = function(arg0, arg1) { + const ret = getObject(arg1).message; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_getExtension_b32d1f4b44a2464b = function() { return handleError(function (arg0, arg1, arg2) { + const ret = getObject(arg0).getExtension(getStringFromWasm0(arg1, arg2)); + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_getSupportedExtensions_24ca3063e6cb52dc = function(arg0) { + const ret = getObject(arg0).getSupportedExtensions(); + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_getParameter_92e1c06daec0a5db = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg0).getParameter(arg1 >>> 0); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbindgen_string_get = function(arg0, arg1) { + const obj = getObject(arg1); + const ret = typeof(obj) === 'string' ? obj : undefined; + var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + var len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_texSubImage2D_009f28c178ac0ef3 = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) { + getObject(arg0).texSubImage2D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7 >>> 0, arg8 >>> 0, getObject(arg9)); + }, arguments) }; + imports.wbg.__wbg_texSubImage2D_09f65ee13c9715c2 = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) { + getObject(arg0).texSubImage2D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7 >>> 0, arg8 >>> 0, getObject(arg9)); + }, arguments) }; + imports.wbg.__wbg_texSubImage2D_586bd03abd8b9645 = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) { + getObject(arg0).texSubImage2D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7 >>> 0, arg8 >>> 0, getObject(arg9)); + }, arguments) }; + imports.wbg.__wbg_texSubImage3D_b3b3c1e1aaaa99a9 = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11) { + getObject(arg0).texSubImage3D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 >>> 0, arg10 >>> 0, getObject(arg11)); + }, arguments) }; + imports.wbg.__wbg_texSubImage3D_1629275aaeddba7f = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11) { + getObject(arg0).texSubImage3D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 >>> 0, arg10 >>> 0, getObject(arg11)); + }, arguments) }; + imports.wbg.__wbg_texSubImage3D_55f32eefc1c80c07 = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11) { + getObject(arg0).texSubImage3D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 >>> 0, arg10 >>> 0, getObject(arg11)); + }, arguments) }; + imports.wbg.__wbg_framebufferTextureMultiviewOVR_6ec7a85f3367d20e = function(arg0, arg1, arg2, arg3, arg4, arg5, arg6) { + getObject(arg0).framebufferTextureMultiviewOVR(arg1 >>> 0, arg2 >>> 0, getObject(arg3), arg4, arg5, arg6); + }; + imports.wbg.__wbg_bindFramebuffer_33174ee82d938627 = function(arg0, arg1, arg2) { + getObject(arg0).bindFramebuffer(arg1 >>> 0, getObject(arg2)); + }; + imports.wbg.__wbg_bindFramebuffer_80ab0501951cc2c3 = function(arg0, arg1, arg2) { + getObject(arg0).bindFramebuffer(arg1 >>> 0, getObject(arg2)); + }; + imports.wbg.__wbg_getSupportedProfiles_25ed88a41293cb71 = function(arg0) { + const ret = getObject(arg0).getSupportedProfiles(); + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_new_ffc6d4d085022169 = function() { + const ret = new Array(); + return addHeapObject(ret); + }; + imports.wbg.__wbg_includes_cafdff20dd66763c = function(arg0, arg1, arg2) { + const ret = getObject(arg0).includes(getObject(arg1), arg2); + return ret; + }; + imports.wbg.__wbg_createFramebuffer_1b0ce659f44b2562 = function(arg0) { + const ret = getObject(arg0).createFramebuffer(); + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_createFramebuffer_66918f52f84fb0a9 = function(arg0) { + const ret = getObject(arg0).createFramebuffer(); + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_createQuery_3a315cf1eec44e3d = function(arg0) { + const ret = getObject(arg0).createQuery(); + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_createRenderbuffer_cd7b8379638f7c64 = function(arg0) { + const ret = getObject(arg0).createRenderbuffer(); + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_createRenderbuffer_6d6e37cbb502ca33 = function(arg0) { + const ret = getObject(arg0).createRenderbuffer(); + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_createSampler_3a2ddaedd95dc2c5 = function(arg0) { + const ret = getObject(arg0).createSampler(); + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_createShader_25391a4dceb30291 = function(arg0, arg1) { + const ret = getObject(arg0).createShader(arg1 >>> 0); + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_createShader_a56f470ffa1c92a5 = function(arg0, arg1) { + const ret = getObject(arg0).createShader(arg1 >>> 0); + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_createTexture_fc71efc6d11fdbcb = function(arg0) { + const ret = getObject(arg0).createTexture(); + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_createTexture_0a5d95233724c9fb = function(arg0) { + const ret = getObject(arg0).createTexture(); + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_deleteShader_c10a3e2a689f8115 = function(arg0, arg1) { + getObject(arg0).deleteShader(getObject(arg1)); + }; + imports.wbg.__wbg_deleteShader_40389978f329df9f = function(arg0, arg1) { + getObject(arg0).deleteShader(getObject(arg1)); + }; + imports.wbg.__wbg_shaderSource_8581035b723a56a7 = function(arg0, arg1, arg2, arg3) { + getObject(arg0).shaderSource(getObject(arg1), getStringFromWasm0(arg2, arg3)); + }; + imports.wbg.__wbg_shaderSource_f58b7f19ccf7f292 = function(arg0, arg1, arg2, arg3) { + getObject(arg0).shaderSource(getObject(arg1), getStringFromWasm0(arg2, arg3)); + }; + imports.wbg.__wbg_compileShader_df38c9b4d109df2c = function(arg0, arg1) { + getObject(arg0).compileShader(getObject(arg1)); + }; + imports.wbg.__wbg_compileShader_710b082356f5014b = function(arg0, arg1) { + getObject(arg0).compileShader(getObject(arg1)); + }; + imports.wbg.__wbg_getShaderParameter_d5af258ca8110f13 = function(arg0, arg1, arg2) { + const ret = getObject(arg0).getShaderParameter(getObject(arg1), arg2 >>> 0); + return addHeapObject(ret); + }; + imports.wbg.__wbg_getShaderParameter_033044aa2910ba65 = function(arg0, arg1, arg2) { + const ret = getObject(arg0).getShaderParameter(getObject(arg1), arg2 >>> 0); + return addHeapObject(ret); + }; + imports.wbg.__wbg_createProgram_76ddcf5596a96a1a = function(arg0) { + const ret = getObject(arg0).createProgram(); + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_createProgram_36349c11c5d787f1 = function(arg0) { + const ret = getObject(arg0).createProgram(); + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_deleteProgram_ffe51c2159e56aeb = function(arg0, arg1) { + getObject(arg0).deleteProgram(getObject(arg1)); + }; + imports.wbg.__wbg_deleteProgram_100d1c04b7f0f6ee = function(arg0, arg1) { + getObject(arg0).deleteProgram(getObject(arg1)); + }; + imports.wbg.__wbg_attachShader_289e2f1d24149257 = function(arg0, arg1, arg2) { + getObject(arg0).attachShader(getObject(arg1), getObject(arg2)); + }; + imports.wbg.__wbg_attachShader_184a61d345c20d42 = function(arg0, arg1, arg2) { + getObject(arg0).attachShader(getObject(arg1), getObject(arg2)); + }; + imports.wbg.__wbg_linkProgram_1ab5d0990c565f87 = function(arg0, arg1) { + getObject(arg0).linkProgram(getObject(arg1)); + }; + imports.wbg.__wbg_linkProgram_79a9e7719a86a93e = function(arg0, arg1) { + getObject(arg0).linkProgram(getObject(arg1)); + }; + imports.wbg.__wbg_getProgramParameter_ac16a850d3f251f3 = function(arg0, arg1, arg2) { + const ret = getObject(arg0).getProgramParameter(getObject(arg1), arg2 >>> 0); + return addHeapObject(ret); + }; + imports.wbg.__wbg_getProgramParameter_69a29687a127f713 = function(arg0, arg1, arg2) { + const ret = getObject(arg0).getProgramParameter(getObject(arg1), arg2 >>> 0); + return addHeapObject(ret); + }; + imports.wbg.__wbg_getActiveUniform_f9072bcc7895dac1 = function(arg0, arg1, arg2) { + const ret = getObject(arg0).getActiveUniform(getObject(arg1), arg2 >>> 0); + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_size_5818c0d8de7ee6ea = function(arg0) { + const ret = getObject(arg0).size; + return ret; + }; + imports.wbg.__wbg_type_a25c4f950b3b3797 = function(arg0) { + const ret = getObject(arg0).type; + return ret; + }; + imports.wbg.__wbg_name_89f5e0e88ec3b968 = function(arg0, arg1) { + const ret = getObject(arg1).name; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_getActiveUniform_4f96fab0067ee961 = function(arg0, arg1, arg2) { + const ret = getObject(arg0).getActiveUniform(getObject(arg1), arg2 >>> 0); + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_useProgram_45855699f032d49a = function(arg0, arg1) { + getObject(arg0).useProgram(getObject(arg1)); + }; + imports.wbg.__wbg_useProgram_667ebfb0fb0de4c0 = function(arg0, arg1) { + getObject(arg0).useProgram(getObject(arg1)); + }; + imports.wbg.__wbg_createBuffer_993ecd2e92aabe3c = function(arg0) { + const ret = getObject(arg0).createBuffer(); + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_createBuffer_210de590ff501232 = function(arg0) { + const ret = getObject(arg0).createBuffer(); + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_bindBuffer_a0055fe364603e72 = function(arg0, arg1, arg2) { + getObject(arg0).bindBuffer(arg1 >>> 0, getObject(arg2)); + }; + imports.wbg.__wbg_bindBuffer_c71ed62c7c21bed0 = function(arg0, arg1, arg2) { + getObject(arg0).bindBuffer(arg1 >>> 0, getObject(arg2)); + }; + imports.wbg.__wbg_bindBufferRange_d9f0a9fc3adda248 = function(arg0, arg1, arg2, arg3, arg4, arg5) { + getObject(arg0).bindBufferRange(arg1 >>> 0, arg2 >>> 0, getObject(arg3), arg4, arg5); + }; + imports.wbg.__wbg_bindRenderbuffer_248119e9b6532f19 = function(arg0, arg1, arg2) { + getObject(arg0).bindRenderbuffer(arg1 >>> 0, getObject(arg2)); + }; + imports.wbg.__wbg_bindRenderbuffer_0c7738e79a575fdb = function(arg0, arg1, arg2) { + getObject(arg0).bindRenderbuffer(arg1 >>> 0, getObject(arg2)); + }; + imports.wbg.__wbg_blitFramebuffer_df3bca038546840e = function(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10) { + getObject(arg0).blitFramebuffer(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 >>> 0, arg10 >>> 0); + }; + imports.wbg.__wbg_createVertexArrayOES_528c4cd10c985d11 = function(arg0) { + const ret = getObject(arg0).createVertexArrayOES(); + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_createVertexArray_7466a685c3b93a65 = function(arg0) { + const ret = getObject(arg0).createVertexArray(); + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_deleteVertexArray_56114a4faffe5e22 = function(arg0, arg1) { + getObject(arg0).deleteVertexArray(getObject(arg1)); + }; + imports.wbg.__wbg_deleteVertexArrayOES_09c67a658698d158 = function(arg0, arg1) { + getObject(arg0).deleteVertexArrayOES(getObject(arg1)); + }; + imports.wbg.__wbg_bindVertexArray_7b37e9d04dfd27d9 = function(arg0, arg1) { + getObject(arg0).bindVertexArray(getObject(arg1)); + }; + imports.wbg.__wbg_bindVertexArrayOES_d0c90ddc7c6360d2 = function(arg0, arg1) { + getObject(arg0).bindVertexArrayOES(getObject(arg1)); + }; + imports.wbg.__wbg_pixelStorei_48bb580e625ac760 = function(arg0, arg1, arg2) { + getObject(arg0).pixelStorei(arg1 >>> 0, arg2); + }; + imports.wbg.__wbg_pixelStorei_b4b6c5d89e9b5f96 = function(arg0, arg1, arg2) { + getObject(arg0).pixelStorei(arg1 >>> 0, arg2); + }; + imports.wbg.__wbg_bufferData_9f6454cde4211a84 = function(arg0, arg1, arg2, arg3) { + getObject(arg0).bufferData(arg1 >>> 0, arg2, arg3 >>> 0); + }; + imports.wbg.__wbg_bufferData_7afee98828aad464 = function(arg0, arg1, arg2, arg3) { + getObject(arg0).bufferData(arg1 >>> 0, arg2, arg3 >>> 0); + }; + imports.wbg.__wbg_bufferData_11f5ff31cb447750 = function(arg0, arg1, arg2, arg3) { + getObject(arg0).bufferData(arg1 >>> 0, getObject(arg2), arg3 >>> 0); + }; + imports.wbg.__wbg_bufferData_a05a44a5492e757f = function(arg0, arg1, arg2, arg3) { + getObject(arg0).bufferData(arg1 >>> 0, getObject(arg2), arg3 >>> 0); + }; + imports.wbg.__wbg_bufferSubData_361bebad2e19dbcf = function(arg0, arg1, arg2, arg3) { + getObject(arg0).bufferSubData(arg1 >>> 0, arg2, getObject(arg3)); + }; + imports.wbg.__wbg_bufferSubData_07b03f17d75b6db7 = function(arg0, arg1, arg2, arg3) { + getObject(arg0).bufferSubData(arg1 >>> 0, arg2, getObject(arg3)); + }; + imports.wbg.__wbg_getBufferSubData_3d5a446fc6edc0d6 = function(arg0, arg1, arg2, arg3) { + getObject(arg0).getBufferSubData(arg1 >>> 0, arg2, getObject(arg3)); + }; + imports.wbg.__wbg_clearBufferiv_e26fb1758242f7f4 = function(arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).clearBufferiv(arg1 >>> 0, arg2, getArrayI32FromWasm0(arg3, arg4)); + }; + imports.wbg.__wbg_clearBufferuiv_75891c672ddef82a = function(arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).clearBufferuiv(arg1 >>> 0, arg2, getArrayU32FromWasm0(arg3, arg4)); + }; + imports.wbg.__wbg_clearBufferfv_ddf1d2c0a5f293c5 = function(arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).clearBufferfv(arg1 >>> 0, arg2, getArrayF32FromWasm0(arg3, arg4)); + }; + imports.wbg.__wbg_clearBufferfi_d57bee264d59476a = function(arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).clearBufferfi(arg1 >>> 0, arg2, arg3, arg4); + }; + imports.wbg.__wbg_clientWaitSync_31956a1ff24ab2d7 = function(arg0, arg1, arg2, arg3) { + const ret = getObject(arg0).clientWaitSync(getObject(arg1), arg2 >>> 0, arg3 >>> 0); + return ret; + }; + imports.wbg.__wbg_copyBufferSubData_926f5ccd6e693b1f = function(arg0, arg1, arg2, arg3, arg4, arg5) { + getObject(arg0).copyBufferSubData(arg1 >>> 0, arg2 >>> 0, arg3, arg4, arg5); + }; + imports.wbg.__wbg_copyTexSubImage2D_66766abee23288ff = function(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) { + getObject(arg0).copyTexSubImage2D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7, arg8); + }; + imports.wbg.__wbg_copyTexSubImage2D_bc4fe74768b6add0 = function(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) { + getObject(arg0).copyTexSubImage2D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7, arg8); + }; + imports.wbg.__wbg_copyTexSubImage3D_d694f427199991b8 = function(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) { + getObject(arg0).copyTexSubImage3D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); + }; + imports.wbg.__wbg_deleteBuffer_f4994a64cdd473a3 = function(arg0, arg1) { + getObject(arg0).deleteBuffer(getObject(arg1)); + }; + imports.wbg.__wbg_deleteBuffer_3129e4f30c465a14 = function(arg0, arg1) { + getObject(arg0).deleteBuffer(getObject(arg1)); + }; + imports.wbg.__wbg_deleteFramebuffer_2cc015c1b281e8a1 = function(arg0, arg1) { + getObject(arg0).deleteFramebuffer(getObject(arg1)); + }; + imports.wbg.__wbg_deleteFramebuffer_33112863fa4f3eb0 = function(arg0, arg1) { + getObject(arg0).deleteFramebuffer(getObject(arg1)); + }; + imports.wbg.__wbg_deleteQuery_d51a96512c6c3f3f = function(arg0, arg1) { + getObject(arg0).deleteQuery(getObject(arg1)); + }; + imports.wbg.__wbg_deleteRenderbuffer_80239f946eea133d = function(arg0, arg1) { + getObject(arg0).deleteRenderbuffer(getObject(arg1)); + }; + imports.wbg.__wbg_deleteRenderbuffer_5229b7175bb0b009 = function(arg0, arg1) { + getObject(arg0).deleteRenderbuffer(getObject(arg1)); + }; + imports.wbg.__wbg_deleteSampler_e33ef80c17eb0896 = function(arg0, arg1) { + getObject(arg0).deleteSampler(getObject(arg1)); + }; + imports.wbg.__wbg_deleteSync_3e63862ea7783216 = function(arg0, arg1) { + getObject(arg0).deleteSync(getObject(arg1)); + }; + imports.wbg.__wbg_deleteTexture_b8458a96b71a0a04 = function(arg0, arg1) { + getObject(arg0).deleteTexture(getObject(arg1)); + }; + imports.wbg.__wbg_deleteTexture_ad998c535ddaaf67 = function(arg0, arg1) { + getObject(arg0).deleteTexture(getObject(arg1)); + }; + imports.wbg.__wbg_disable_8938e1da156fa7d9 = function(arg0, arg1) { + getObject(arg0).disable(arg1 >>> 0); + }; + imports.wbg.__wbg_disable_483aff0769a6f791 = function(arg0, arg1) { + getObject(arg0).disable(arg1 >>> 0); + }; + imports.wbg.__wbg_disableVertexAttribArray_b196e82af1f9e794 = function(arg0, arg1) { + getObject(arg0).disableVertexAttribArray(arg1 >>> 0); + }; + imports.wbg.__wbg_disableVertexAttribArray_0c9e77abfba9ee15 = function(arg0, arg1) { + getObject(arg0).disableVertexAttribArray(arg1 >>> 0); + }; + imports.wbg.__wbg_drawArrays_4ae5359a7c3c5279 = function(arg0, arg1, arg2, arg3) { + getObject(arg0).drawArrays(arg1 >>> 0, arg2, arg3); + }; + imports.wbg.__wbg_drawArrays_ac75b6b4a565dfde = function(arg0, arg1, arg2, arg3) { + getObject(arg0).drawArrays(arg1 >>> 0, arg2, arg3); + }; + imports.wbg.__wbg_drawArraysInstancedANGLE_efcd706fccb1a8f0 = function(arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).drawArraysInstancedANGLE(arg1 >>> 0, arg2, arg3, arg4); + }; + imports.wbg.__wbg_drawArraysInstanced_f7080bf0ad1d976e = function(arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).drawArraysInstanced(arg1 >>> 0, arg2, arg3, arg4); + }; + imports.wbg.__wbindgen_number_new = function(arg0) { + const ret = arg0; + return addHeapObject(ret); + }; + imports.wbg.__wbg_push_901f3914205d44de = function(arg0, arg1) { + const ret = getObject(arg0).push(getObject(arg1)); + return ret; + }; + imports.wbg.__wbg_of_c36972ad824ef061 = function(arg0) { + const ret = Array.of(getObject(arg0)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_drawBuffersWEBGL_7b1f12f2ee6598f5 = function(arg0, arg1) { + getObject(arg0).drawBuffersWEBGL(getObject(arg1)); + }; + imports.wbg.__wbg_drawBuffers_770b4e7949774930 = function(arg0, arg1) { + getObject(arg0).drawBuffers(getObject(arg1)); + }; + imports.wbg.__wbg_drawElementsInstancedANGLE_924b2ff704a740e7 = function(arg0, arg1, arg2, arg3, arg4, arg5) { + getObject(arg0).drawElementsInstancedANGLE(arg1 >>> 0, arg2, arg3 >>> 0, arg4, arg5); + }; + imports.wbg.__wbg_drawElementsInstanced_1f828577186777cb = function(arg0, arg1, arg2, arg3, arg4, arg5) { + getObject(arg0).drawElementsInstanced(arg1 >>> 0, arg2, arg3 >>> 0, arg4, arg5); + }; + imports.wbg.__wbg_enable_e39f53a946b9e3a0 = function(arg0, arg1) { + getObject(arg0).enable(arg1 >>> 0); + }; + imports.wbg.__wbg_enable_c5caba1636ec3c96 = function(arg0, arg1) { + getObject(arg0).enable(arg1 >>> 0); + }; + imports.wbg.__wbg_enableVertexAttribArray_f8678d164c294659 = function(arg0, arg1) { + getObject(arg0).enableVertexAttribArray(arg1 >>> 0); + }; + imports.wbg.__wbg_enableVertexAttribArray_0424d3842911d8b6 = function(arg0, arg1) { + getObject(arg0).enableVertexAttribArray(arg1 >>> 0); + }; + imports.wbg.__wbg_framebufferRenderbuffer_6b4d1a1c53ccc57d = function(arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).framebufferRenderbuffer(arg1 >>> 0, arg2 >>> 0, arg3 >>> 0, getObject(arg4)); + }; + imports.wbg.__wbg_framebufferRenderbuffer_09dddaeb9b013985 = function(arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).framebufferRenderbuffer(arg1 >>> 0, arg2 >>> 0, arg3 >>> 0, getObject(arg4)); + }; + imports.wbg.__wbg_framebufferTexture2D_f8b0567baae853d2 = function(arg0, arg1, arg2, arg3, arg4, arg5) { + getObject(arg0).framebufferTexture2D(arg1 >>> 0, arg2 >>> 0, arg3 >>> 0, getObject(arg4), arg5); + }; + imports.wbg.__wbg_framebufferTexture2D_8d99f62eee2d1757 = function(arg0, arg1, arg2, arg3, arg4, arg5) { + getObject(arg0).framebufferTexture2D(arg1 >>> 0, arg2 >>> 0, arg3 >>> 0, getObject(arg4), arg5); + }; + imports.wbg.__wbg_framebufferTextureLayer_3776751a08a004cd = function(arg0, arg1, arg2, arg3, arg4, arg5) { + getObject(arg0).framebufferTextureLayer(arg1 >>> 0, arg2 >>> 0, getObject(arg3), arg4, arg5); + }; + imports.wbg.__wbg_frontFace_70a1886745b75bc9 = function(arg0, arg1) { + getObject(arg0).frontFace(arg1 >>> 0); + }; + imports.wbg.__wbg_frontFace_a08d3e57a0667c73 = function(arg0, arg1) { + getObject(arg0).frontFace(arg1 >>> 0); + }; + imports.wbg.__wbg_getParameter_fedfba9017d5fbcd = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg0).getParameter(arg1 >>> 0); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_getIndexedParameter_498208e84138d6d0 = function() { return handleError(function (arg0, arg1, arg2) { + const ret = getObject(arg0).getIndexedParameter(arg1 >>> 0, arg2 >>> 0); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_getUniformLocation_29cc1018d110f9f0 = function(arg0, arg1, arg2, arg3) { + const ret = getObject(arg0).getUniformLocation(getObject(arg1), getStringFromWasm0(arg2, arg3)); + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_getUniformLocation_50b6838495678a49 = function(arg0, arg1, arg2, arg3) { + const ret = getObject(arg0).getUniformLocation(getObject(arg1), getStringFromWasm0(arg2, arg3)); + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_getSyncParameter_268f427e8d9f123e = function(arg0, arg1, arg2) { + const ret = getObject(arg0).getSyncParameter(getObject(arg1), arg2 >>> 0); + return addHeapObject(ret); + }; + imports.wbg.__wbg_renderbufferStorage_fcb8aee479a5dd50 = function(arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).renderbufferStorage(arg1 >>> 0, arg2 >>> 0, arg3, arg4); + }; + imports.wbg.__wbg_renderbufferStorage_14a5ac06c7f68729 = function(arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).renderbufferStorage(arg1 >>> 0, arg2 >>> 0, arg3, arg4); + }; + imports.wbg.__wbg_renderbufferStorageMultisample_77d1555e1b4be5d5 = function(arg0, arg1, arg2, arg3, arg4, arg5) { + getObject(arg0).renderbufferStorageMultisample(arg1 >>> 0, arg2, arg3 >>> 0, arg4, arg5); + }; + imports.wbg.__wbg_samplerParameterf_726502cef2fc6dff = function(arg0, arg1, arg2, arg3) { + getObject(arg0).samplerParameterf(getObject(arg1), arg2 >>> 0, arg3); + }; + imports.wbg.__wbg_samplerParameteri_d0f51895de24bcbb = function(arg0, arg1, arg2, arg3) { + getObject(arg0).samplerParameteri(getObject(arg1), arg2 >>> 0, arg3); + }; + imports.wbg.__wbg_texStorage2D_612a56ff2dc6ac9e = function(arg0, arg1, arg2, arg3, arg4, arg5) { + getObject(arg0).texStorage2D(arg1 >>> 0, arg2, arg3 >>> 0, arg4, arg5); + }; + imports.wbg.__wbg_texStorage3D_102ea8c301d9573e = function(arg0, arg1, arg2, arg3, arg4, arg5, arg6) { + getObject(arg0).texStorage3D(arg1 >>> 0, arg2, arg3 >>> 0, arg4, arg5, arg6); + }; + imports.wbg.__wbg_uniform1i_59bbe75ef84036ac = function(arg0, arg1, arg2) { + getObject(arg0).uniform1i(getObject(arg1), arg2); + }; + imports.wbg.__wbg_uniform1i_a949331c579124f5 = function(arg0, arg1, arg2) { + getObject(arg0).uniform1i(getObject(arg1), arg2); + }; + imports.wbg.__wbg_uniform2iv_5a9f8821b3d44adb = function(arg0, arg1, arg2, arg3) { + getObject(arg0).uniform2iv(getObject(arg1), getArrayI32FromWasm0(arg2, arg3)); + }; + imports.wbg.__wbg_uniform2iv_c44d289b86e7b9c0 = function(arg0, arg1, arg2, arg3) { + getObject(arg0).uniform2iv(getObject(arg1), getArrayI32FromWasm0(arg2, arg3)); + }; + imports.wbg.__wbg_uniform3iv_482ad890ad013578 = function(arg0, arg1, arg2, arg3) { + getObject(arg0).uniform3iv(getObject(arg1), getArrayI32FromWasm0(arg2, arg3)); + }; + imports.wbg.__wbg_uniform3iv_d92618b7fac63d5f = function(arg0, arg1, arg2, arg3) { + getObject(arg0).uniform3iv(getObject(arg1), getArrayI32FromWasm0(arg2, arg3)); + }; + imports.wbg.__wbg_uniform4iv_6b5d31657261615b = function(arg0, arg1, arg2, arg3) { + getObject(arg0).uniform4iv(getObject(arg1), getArrayI32FromWasm0(arg2, arg3)); + }; + imports.wbg.__wbg_uniform4iv_7b54b6a063120eb2 = function(arg0, arg1, arg2, arg3) { + getObject(arg0).uniform4iv(getObject(arg1), getArrayI32FromWasm0(arg2, arg3)); + }; + imports.wbg.__wbg_uniform1f_97c947ddb8aeacf8 = function(arg0, arg1, arg2) { + getObject(arg0).uniform1f(getObject(arg1), arg2); + }; + imports.wbg.__wbg_uniform1f_0c8a4e0444282098 = function(arg0, arg1, arg2) { + getObject(arg0).uniform1f(getObject(arg1), arg2); + }; + imports.wbg.__wbg_uniform4f_83cd1c05881edfde = function(arg0, arg1, arg2, arg3, arg4, arg5) { + getObject(arg0).uniform4f(getObject(arg1), arg2, arg3, arg4, arg5); + }; + imports.wbg.__wbg_uniform4f_998813a169b13f40 = function(arg0, arg1, arg2, arg3, arg4, arg5) { + getObject(arg0).uniform4f(getObject(arg1), arg2, arg3, arg4, arg5); + }; + imports.wbg.__wbg_uniform2fv_dee4625f08f7518e = function(arg0, arg1, arg2, arg3) { + getObject(arg0).uniform2fv(getObject(arg1), getArrayF32FromWasm0(arg2, arg3)); + }; + imports.wbg.__wbg_uniform2fv_c9bafe596aaa6f96 = function(arg0, arg1, arg2, arg3) { + getObject(arg0).uniform2fv(getObject(arg1), getArrayF32FromWasm0(arg2, arg3)); + }; + imports.wbg.__wbg_uniform3fv_38d48a2561b89815 = function(arg0, arg1, arg2, arg3) { + getObject(arg0).uniform3fv(getObject(arg1), getArrayF32FromWasm0(arg2, arg3)); + }; + imports.wbg.__wbg_uniform3fv_7c6cc849b0150aaa = function(arg0, arg1, arg2, arg3) { + getObject(arg0).uniform3fv(getObject(arg1), getArrayF32FromWasm0(arg2, arg3)); + }; + imports.wbg.__wbg_uniform4fv_85d4d7ef22366b93 = function(arg0, arg1, arg2, arg3) { + getObject(arg0).uniform4fv(getObject(arg1), getArrayF32FromWasm0(arg2, arg3)); + }; + imports.wbg.__wbg_uniform4fv_4aa6ac4f94369a8f = function(arg0, arg1, arg2, arg3) { + getObject(arg0).uniform4fv(getObject(arg1), getArrayF32FromWasm0(arg2, arg3)); + }; + imports.wbg.__wbg_uniformMatrix2fv_0ec0bb00ca04ae0f = function(arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).uniformMatrix2fv(getObject(arg1), arg2 !== 0, getArrayF32FromWasm0(arg3, arg4)); + }; + imports.wbg.__wbg_uniformMatrix2fv_aaecec3c7496646f = function(arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).uniformMatrix2fv(getObject(arg1), arg2 !== 0, getArrayF32FromWasm0(arg3, arg4)); + }; + imports.wbg.__wbg_uniformMatrix3fv_6c6cf9285fa50932 = function(arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).uniformMatrix3fv(getObject(arg1), arg2 !== 0, getArrayF32FromWasm0(arg3, arg4)); + }; + imports.wbg.__wbg_uniformMatrix3fv_8ebebb0a689c27ea = function(arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).uniformMatrix3fv(getObject(arg1), arg2 !== 0, getArrayF32FromWasm0(arg3, arg4)); + }; + imports.wbg.__wbg_uniformMatrix4fv_47822ae94c519f11 = function(arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).uniformMatrix4fv(getObject(arg1), arg2 !== 0, getArrayF32FromWasm0(arg3, arg4)); + }; + imports.wbg.__wbg_uniformMatrix4fv_674d03cda2d50ccc = function(arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).uniformMatrix4fv(getObject(arg1), arg2 !== 0, getArrayF32FromWasm0(arg3, arg4)); + }; + imports.wbg.__wbg_cullFace_f7631a823163010d = function(arg0, arg1) { + getObject(arg0).cullFace(arg1 >>> 0); + }; + imports.wbg.__wbg_cullFace_d2f78f39007f1d5d = function(arg0, arg1) { + getObject(arg0).cullFace(arg1 >>> 0); + }; + imports.wbg.__wbg_colorMask_ee95cb90b5399c1d = function(arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).colorMask(arg1 !== 0, arg2 !== 0, arg3 !== 0, arg4 !== 0); + }; + imports.wbg.__wbg_colorMask_048d9f7d86363300 = function(arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).colorMask(arg1 !== 0, arg2 !== 0, arg3 !== 0, arg4 !== 0); + }; + imports.wbg.__wbg_depthMask_b520fa172dc50fdd = function(arg0, arg1) { + getObject(arg0).depthMask(arg1 !== 0); + }; + imports.wbg.__wbg_depthMask_03551bf1079ca4f3 = function(arg0, arg1) { + getObject(arg0).depthMask(arg1 !== 0); + }; + imports.wbg.__wbg_blendColor_bf0aca4480ec191b = function(arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).blendColor(arg1, arg2, arg3, arg4); + }; + imports.wbg.__wbg_blendColor_bd7597cf4f926625 = function(arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).blendColor(arg1, arg2, arg3, arg4); + }; + imports.wbg.__wbg_invalidateFramebuffer_233280f8e97054a6 = function() { return handleError(function (arg0, arg1, arg2) { + getObject(arg0).invalidateFramebuffer(arg1 >>> 0, getObject(arg2)); + }, arguments) }; + imports.wbg.__wbg_polygonOffset_784d0bd354450685 = function(arg0, arg1, arg2) { + getObject(arg0).polygonOffset(arg1, arg2); + }; + imports.wbg.__wbg_polygonOffset_f7ac1393deab0d93 = function(arg0, arg1, arg2) { + getObject(arg0).polygonOffset(arg1, arg2); + }; + imports.wbg.__wbg_bindTexture_ba764bb08be120f7 = function(arg0, arg1, arg2) { + getObject(arg0).bindTexture(arg1 >>> 0, getObject(arg2)); + }; + imports.wbg.__wbg_bindTexture_df13ba7e7ee5d984 = function(arg0, arg1, arg2) { + getObject(arg0).bindTexture(arg1 >>> 0, getObject(arg2)); + }; + imports.wbg.__wbg_bindSampler_d6c4782741c69639 = function(arg0, arg1, arg2) { + getObject(arg0).bindSampler(arg1 >>> 0, getObject(arg2)); + }; + imports.wbg.__wbg_activeTexture_123afbbc8970fe31 = function(arg0, arg1) { + getObject(arg0).activeTexture(arg1 >>> 0); + }; + imports.wbg.__wbg_activeTexture_713ce7d3e753740f = function(arg0, arg1) { + getObject(arg0).activeTexture(arg1 >>> 0); + }; + imports.wbg.__wbg_fenceSync_88242349a578d268 = function(arg0, arg1, arg2) { + const ret = getObject(arg0).fenceSync(arg1 >>> 0, arg2 >>> 0); + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_texParameteri_fba016345d388fd9 = function(arg0, arg1, arg2, arg3) { + getObject(arg0).texParameteri(arg1 >>> 0, arg2 >>> 0, arg3); + }; + imports.wbg.__wbg_texParameteri_31d32c2b86548f8e = function(arg0, arg1, arg2, arg3) { + getObject(arg0).texParameteri(arg1 >>> 0, arg2 >>> 0, arg3); + }; + imports.wbg.__wbg_texSubImage2D_1b4def2ea95bfb31 = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) { + getObject(arg0).texSubImage2D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7 >>> 0, arg8 >>> 0, getObject(arg9)); + }, arguments) }; + imports.wbg.__wbg_texSubImage2D_be9f61a79f57b819 = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) { + getObject(arg0).texSubImage2D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7 >>> 0, arg8 >>> 0, getObject(arg9)); + }, arguments) }; + imports.wbg.__wbg_texSubImage2D_8694c2fdf6ffae77 = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) { + getObject(arg0).texSubImage2D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7 >>> 0, arg8 >>> 0, arg9); + }, arguments) }; + imports.wbg.__wbg_compressedTexSubImage2D_6ab7ed818e5e4070 = function(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) { + getObject(arg0).compressedTexSubImage2D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7 >>> 0, getObject(arg8)); + }; + imports.wbg.__wbg_compressedTexSubImage2D_bc2325e36c328ef3 = function(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) { + getObject(arg0).compressedTexSubImage2D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7 >>> 0, arg8, arg9); + }; + imports.wbg.__wbg_compressedTexSubImage2D_b9e80ce57234bf68 = function(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) { + getObject(arg0).compressedTexSubImage2D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7 >>> 0, getObject(arg8)); + }; + imports.wbg.__wbg_texSubImage3D_c81838d3b14e2574 = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11) { + getObject(arg0).texSubImage3D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 >>> 0, arg10 >>> 0, arg11); + }, arguments) }; + imports.wbg.__wbg_texSubImage3D_4491b14dacde659b = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11) { + getObject(arg0).texSubImage3D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 >>> 0, arg10 >>> 0, getObject(arg11)); + }, arguments) }; + imports.wbg.__wbg_compressedTexSubImage3D_e237c5dd8b328f82 = function(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11) { + getObject(arg0).compressedTexSubImage3D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 >>> 0, arg10, arg11); + }; + imports.wbg.__wbg_compressedTexSubImage3D_fa81691b7cb3b7e4 = function(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10) { + getObject(arg0).compressedTexSubImage3D(arg1 >>> 0, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 >>> 0, getObject(arg10)); + }; + imports.wbg.__wbg_depthFunc_4706c33c9966db3b = function(arg0, arg1) { + getObject(arg0).depthFunc(arg1 >>> 0); + }; + imports.wbg.__wbg_depthFunc_aa8fdb5bf66ce5dc = function(arg0, arg1) { + getObject(arg0).depthFunc(arg1 >>> 0); + }; + imports.wbg.__wbg_depthRange_2d0d6f020c3d5566 = function(arg0, arg1, arg2) { + getObject(arg0).depthRange(arg1, arg2); + }; + imports.wbg.__wbg_depthRange_ded9f852ad909448 = function(arg0, arg1, arg2) { + getObject(arg0).depthRange(arg1, arg2); + }; + imports.wbg.__wbg_scissor_6691dacd4ecb8e80 = function(arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).scissor(arg1, arg2, arg3, arg4); + }; + imports.wbg.__wbg_scissor_c1bf95c48721deac = function(arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).scissor(arg1, arg2, arg3, arg4); + }; + imports.wbg.__wbg_vertexAttribDivisorANGLE_c01f8657d1933822 = function(arg0, arg1, arg2) { + getObject(arg0).vertexAttribDivisorANGLE(arg1 >>> 0, arg2 >>> 0); + }; + imports.wbg.__wbg_vertexAttribDivisor_938fb64827607dbe = function(arg0, arg1, arg2) { + getObject(arg0).vertexAttribDivisor(arg1 >>> 0, arg2 >>> 0); + }; + imports.wbg.__wbg_vertexAttribPointer_1241d48b9272fc9d = function(arg0, arg1, arg2, arg3, arg4, arg5, arg6) { + getObject(arg0).vertexAttribPointer(arg1 >>> 0, arg2, arg3 >>> 0, arg4 !== 0, arg5, arg6); + }; + imports.wbg.__wbg_vertexAttribPointer_7be57c972fbee1d0 = function(arg0, arg1, arg2, arg3, arg4, arg5, arg6) { + getObject(arg0).vertexAttribPointer(arg1 >>> 0, arg2, arg3 >>> 0, arg4 !== 0, arg5, arg6); + }; + imports.wbg.__wbg_vertexAttribIPointer_12bfde6cf8b7b821 = function(arg0, arg1, arg2, arg3, arg4, arg5) { + getObject(arg0).vertexAttribIPointer(arg1 >>> 0, arg2, arg3 >>> 0, arg4, arg5); + }; + imports.wbg.__wbg_viewport_2464c396536924a3 = function(arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).viewport(arg1, arg2, arg3, arg4); + }; + imports.wbg.__wbg_viewport_146f8499414eebc9 = function(arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).viewport(arg1, arg2, arg3, arg4); + }; + imports.wbg.__wbg_blendFunc_3edf09b56fbb3ffd = function(arg0, arg1, arg2) { + getObject(arg0).blendFunc(arg1 >>> 0, arg2 >>> 0); + }; + imports.wbg.__wbg_blendFunc_f148dd374b130586 = function(arg0, arg1, arg2) { + getObject(arg0).blendFunc(arg1 >>> 0, arg2 >>> 0); + }; + imports.wbg.__wbg_blendFuncSeparate_c3c9b0213697920c = function(arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).blendFuncSeparate(arg1 >>> 0, arg2 >>> 0, arg3 >>> 0, arg4 >>> 0); + }; + imports.wbg.__wbg_blendFuncSeparate_285a70ec8276ccab = function(arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).blendFuncSeparate(arg1 >>> 0, arg2 >>> 0, arg3 >>> 0, arg4 >>> 0); + }; + imports.wbg.__wbg_blendEquation_b53426d0d37db246 = function(arg0, arg1) { + getObject(arg0).blendEquation(arg1 >>> 0); + }; + imports.wbg.__wbg_blendEquation_e933afa2d360ea3b = function(arg0, arg1) { + getObject(arg0).blendEquation(arg1 >>> 0); + }; + imports.wbg.__wbg_blendEquationSeparate_68fd537772dc05eb = function(arg0, arg1, arg2) { + getObject(arg0).blendEquationSeparate(arg1 >>> 0, arg2 >>> 0); + }; + imports.wbg.__wbg_blendEquationSeparate_821c15a65234ac9e = function(arg0, arg1, arg2) { + getObject(arg0).blendEquationSeparate(arg1 >>> 0, arg2 >>> 0); + }; + imports.wbg.__wbg_stencilFuncSeparate_3b5e111c83147417 = function(arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).stencilFuncSeparate(arg1 >>> 0, arg2 >>> 0, arg3, arg4 >>> 0); + }; + imports.wbg.__wbg_stencilFuncSeparate_639e870ff536309e = function(arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).stencilFuncSeparate(arg1 >>> 0, arg2 >>> 0, arg3, arg4 >>> 0); + }; + imports.wbg.__wbg_stencilMask_3d9c0a4e72ab96ea = function(arg0, arg1) { + getObject(arg0).stencilMask(arg1 >>> 0); + }; + imports.wbg.__wbg_stencilMask_9a8f03321c1dea66 = function(arg0, arg1) { + getObject(arg0).stencilMask(arg1 >>> 0); + }; + imports.wbg.__wbg_stencilMaskSeparate_ef23e92802d8f995 = function(arg0, arg1, arg2) { + getObject(arg0).stencilMaskSeparate(arg1 >>> 0, arg2 >>> 0); + }; + imports.wbg.__wbg_stencilMaskSeparate_a5a7c370cd12a043 = function(arg0, arg1, arg2) { + getObject(arg0).stencilMaskSeparate(arg1 >>> 0, arg2 >>> 0); + }; + imports.wbg.__wbg_stencilOpSeparate_62ee06a95a1f36a4 = function(arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).stencilOpSeparate(arg1 >>> 0, arg2 >>> 0, arg3 >>> 0, arg4 >>> 0); + }; + imports.wbg.__wbg_stencilOpSeparate_497a2305c23d697a = function(arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).stencilOpSeparate(arg1 >>> 0, arg2 >>> 0, arg3 >>> 0, arg4 >>> 0); + }; + imports.wbg.__wbg_getUniformBlockIndex_bdf0666cfd18218e = function(arg0, arg1, arg2, arg3) { + const ret = getObject(arg0).getUniformBlockIndex(getObject(arg1), getStringFromWasm0(arg2, arg3)); + return ret; + }; + imports.wbg.__wbg_uniformBlockBinding_efdd3c56716c6289 = function(arg0, arg1, arg2, arg3) { + getObject(arg0).uniformBlockBinding(getObject(arg1), arg2 >>> 0, arg3 >>> 0); + }; + imports.wbg.__wbg_readBuffer_908a6eccf79eb471 = function(arg0, arg1) { + getObject(arg0).readBuffer(arg1 >>> 0); + }; + imports.wbg.__wbg_readPixels_d3c0e1ee54deb785 = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) { + getObject(arg0).readPixels(arg1, arg2, arg3, arg4, arg5 >>> 0, arg6 >>> 0, arg7); + }, arguments) }; + imports.wbg.__wbg_readPixels_1324fe35287c6abc = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) { + getObject(arg0).readPixels(arg1, arg2, arg3, arg4, arg5 >>> 0, arg6 >>> 0, getObject(arg7)); + }, arguments) }; + imports.wbg.__wbg_readPixels_070533492e105754 = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) { + getObject(arg0).readPixels(arg1, arg2, arg3, arg4, arg5 >>> 0, arg6 >>> 0, getObject(arg7)); + }, arguments) }; + imports.wbg.__wbg_beginQuery_91a71d14184dc3b1 = function(arg0, arg1, arg2) { + getObject(arg0).beginQuery(arg1 >>> 0, getObject(arg2)); + }; + imports.wbg.__wbg_endQuery_7f4678342575164a = function(arg0, arg1) { + getObject(arg0).endQuery(arg1 >>> 0); + }; + imports.wbg.__wbg_getQueryParameter_55ea7685196c2812 = function(arg0, arg1, arg2) { + const ret = getObject(arg0).getQueryParameter(getObject(arg1), arg2 >>> 0); + return addHeapObject(ret); + }; + imports.wbg.__wbg_get_7b48513de5dc5ea4 = function() { return handleError(function (arg0, arg1) { + const ret = Reflect.get(getObject(arg0), getObject(arg1)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_now_b724952e890dc703 = function(arg0) { + const ret = getObject(arg0).now(); + return ret; + }; + imports.wbg.__wbg_self_f0e34d89f33b99fd = function() { return handleError(function () { + const ret = self.self; + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_window_d3b084224f4774d7 = function() { return handleError(function () { + const ret = window.window; + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_globalThis_9caa27ff917c6860 = function() { return handleError(function () { + const ret = globalThis.globalThis; + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_global_35dfdd59a4da3e74 = function() { return handleError(function () { + const ret = global.global; + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbindgen_is_undefined = function(arg0) { + const ret = getObject(arg0) === undefined; + return ret; + }; + imports.wbg.__wbg_newnoargs_c62ea9419c21fbac = function(arg0, arg1) { + const ret = new Function(getStringFromWasm0(arg0, arg1)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_call_90c26b09837aba1c = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg0).call(getObject(arg1)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_resolve_6e1c6553a82f85b7 = function(arg0) { + const ret = Promise.resolve(getObject(arg0)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_then_3ab08cd4fbb91ae9 = function(arg0, arg1) { + const ret = getObject(arg0).then(getObject(arg1)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_then_8371cc12cfedc5a2 = function(arg0, arg1, arg2) { + const ret = getObject(arg0).then(getObject(arg1), getObject(arg2)); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_memory = function() { + const ret = wasm.memory; + return addHeapObject(ret); + }; + imports.wbg.__wbg_buffer_a448f833075b71ba = function(arg0) { + const ret = getObject(arg0).buffer; + return addHeapObject(ret); + }; + imports.wbg.__wbg_newwithbyteoffsetandlength_b2f5b737836be06b = function(arg0, arg1, arg2) { + const ret = new Int8Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0); + return addHeapObject(ret); + }; + imports.wbg.__wbg_newwithbyteoffsetandlength_c370f7b5f8986669 = function(arg0, arg1, arg2) { + const ret = new Int16Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0); + return addHeapObject(ret); + }; + imports.wbg.__wbg_newwithbyteoffsetandlength_be0a0b31d480f4b2 = function(arg0, arg1, arg2) { + const ret = new Int32Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0); + return addHeapObject(ret); + }; + imports.wbg.__wbg_newwithbyteoffsetandlength_d0482f893617af71 = function(arg0, arg1, arg2) { + const ret = new Uint8Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0); + return addHeapObject(ret); + }; + imports.wbg.__wbg_set_2357bf09366ee480 = function(arg0, arg1, arg2) { + getObject(arg0).set(getObject(arg1), arg2 >>> 0); + }; + imports.wbg.__wbg_length_1d25fa9e4ac21ce7 = function(arg0) { + const ret = getObject(arg0).length; + return ret; + }; + imports.wbg.__wbg_newwithbyteoffsetandlength_099217381c451830 = function(arg0, arg1, arg2) { + const ret = new Uint16Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0); + return addHeapObject(ret); + }; + imports.wbg.__wbg_newwithbyteoffsetandlength_7a23ee7b263abe07 = function(arg0, arg1, arg2) { + const ret = new Uint32Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0); + return addHeapObject(ret); + }; + imports.wbg.__wbg_newwithbyteoffsetandlength_fa811509d2a67254 = function(arg0, arg1, arg2) { + const ret = new Float32Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0); + return addHeapObject(ret); + }; + imports.wbg.__wbg_set_759f75cd92b612d2 = function() { return handleError(function (arg0, arg1, arg2) { + const ret = Reflect.set(getObject(arg0), getObject(arg1), getObject(arg2)); + return ret; + }, arguments) }; + imports.wbg.__wbg_newwithcontextoptions_b8f7091a3a364b0f = function() { return handleError(function (arg0) { + const ret = new lAudioContext(getObject(arg0)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_destination_4d44007f7d08d71b = function(arg0) { + const ret = getObject(arg0).destination; + return addHeapObject(ret); + }; + imports.wbg.__wbg_maxChannelCount_652279e4d267be9f = function(arg0) { + const ret = getObject(arg0).maxChannelCount; + return ret; + }; + imports.wbg.__wbg_setchannelCount_12bf2f57feba3188 = function(arg0, arg1) { + getObject(arg0).channelCount = arg1 >>> 0; + }; + imports.wbg.__wbg_createBuffer_444ba95ef8d4d0ff = function() { return handleError(function (arg0, arg1, arg2, arg3) { + const ret = getObject(arg0).createBuffer(arg1 >>> 0, arg2 >>> 0, arg3); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_currentTime_d2be936586614ff4 = function(arg0) { + const ret = getObject(arg0).currentTime; + return ret; + }; + imports.wbg.__wbg_createBufferSource_2900236a9a0ed333 = function() { return handleError(function (arg0) { + const ret = getObject(arg0).createBufferSource(); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_setbuffer_fcb9ea4265b72e7f = function(arg0, arg1) { + getObject(arg0).buffer = getObject(arg1); + }; + imports.wbg.__wbg_connect_7374783233c39eda = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg0).connect(getObject(arg1)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_setonended_7d1552abbde0045d = function(arg0, arg1) { + getObject(arg0).onended = getObject(arg1); + }; + imports.wbg.__wbg_start_88b66d1c6c29149b = function() { return handleError(function (arg0, arg1) { + getObject(arg0).start(arg1); + }, arguments) }; + imports.wbg.__wbg_copyToChannel_f1e42af1b32c01bb = function() { return handleError(function (arg0, arg1, arg2, arg3) { + getObject(arg0).copyToChannel(getArrayF32FromWasm0(arg1, arg2), arg3); + }, arguments) }; + imports.wbg.__wbg_measure_aa7a73f17813f708 = function() { return handleError(function (arg0, arg1, arg2, arg3) { + let deferred0_0; + let deferred0_1; + let deferred1_0; + let deferred1_1; + try { + deferred0_0 = arg0; + deferred0_1 = arg1; + deferred1_0 = arg2; + deferred1_1 = arg3; + performance.measure(getStringFromWasm0(arg0, arg1), getStringFromWasm0(arg2, arg3)); + } finally { + wasm.__wbindgen_free(deferred0_0, deferred0_1, 1); + wasm.__wbindgen_free(deferred1_0, deferred1_1, 1); + } + }, arguments) }; + imports.wbg.__wbindgen_debug_string = function(arg0, arg1) { + const ret = debugString(getObject(arg1)); + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbindgen_throw = function(arg0, arg1) { + throw new Error(getStringFromWasm0(arg0, arg1)); + }; + imports.wbg.__wbg_queueMicrotask_adae4bc085237231 = function(arg0) { + const ret = getObject(arg0).queueMicrotask; + return addHeapObject(ret); + }; + imports.wbg.__wbg_queueMicrotask_4d890031a6a5a50c = function(arg0) { + queueMicrotask(getObject(arg0)); + }; + imports.wbg.__wbg_instanceof_WebGl2RenderingContext_2a0a9b7be3acc66a = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof WebGL2RenderingContext; + } catch (_) { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_getProgramInfoLog_5caeb981d27a790c = function(arg0, arg1, arg2) { + const ret = getObject(arg1).getProgramInfoLog(getObject(arg2)); + var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + var len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_getShaderInfoLog_e78ccbd4507b9d0c = function(arg0, arg1, arg2) { + const ret = getObject(arg1).getShaderInfoLog(getObject(arg2)); + var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + var len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_instanceof_Window_3e5cd1f48c152d01 = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof Window; + } catch (_) { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_innerWidth_e5d865919c14bdf9 = function() { return handleError(function (arg0) { + const ret = getObject(arg0).innerWidth; + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_innerHeight_5e414ce6ae3fd139 = function() { return handleError(function (arg0) { + const ret = getObject(arg0).innerHeight; + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_devicePixelRatio_964a528c661f5575 = function(arg0) { + const ret = getObject(arg0).devicePixelRatio; + return ret; + }; + imports.wbg.__wbg_open_1526872b77d837c5 = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { + const ret = getObject(arg0).open(getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4)); + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_get_644791d4d61a5f69 = function(arg0, arg1, arg2) { + const ret = getObject(arg0)[getStringFromWasm0(arg1, arg2)]; + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_cancelAnimationFrame_cb9c6f65eaa83d76 = function() { return handleError(function (arg0, arg1) { + getObject(arg0).cancelAnimationFrame(arg1); + }, arguments) }; + imports.wbg.__wbg_clearTimeout_0f534a4b1fb4773d = function(arg0, arg1) { + getObject(arg0).clearTimeout(arg1); + }; + imports.wbg.__wbg_fullscreenElement_ebc349686c5a66a1 = function(arg0) { + const ret = getObject(arg0).fullscreenElement; + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_createElement_fdd5c113cb84539e = function() { return handleError(function (arg0, arg1, arg2) { + const ret = getObject(arg0).createElement(getStringFromWasm0(arg1, arg2)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_exitFullscreen_b5d53ae882b17a5c = function(arg0) { + getObject(arg0).exitFullscreen(); + }; + imports.wbg.__wbg_exitPointerLock_7fdf96663e773b31 = function(arg0) { + getObject(arg0).exitPointerLock(); + }; + imports.wbg.__wbg_requestPointerLock_1a4ef1990ed6cc1b = function(arg0) { + getObject(arg0).requestPointerLock(); + }; + imports.wbg.__wbg_setAttribute_e7b72a5e7cfcb5a3 = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).setAttribute(getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4)); + }, arguments) }; + imports.wbg.__wbg_getProgramInfoLog_99334d62bea10332 = function(arg0, arg1, arg2) { + const ret = getObject(arg1).getProgramInfoLog(getObject(arg2)); + var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + var len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_getShaderInfoLog_207d91c9201acffa = function(arg0, arg1, arg2) { + const ret = getObject(arg1).getShaderInfoLog(getObject(arg2)); + var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + var len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_style_97c680a5cbdf49cd = function(arg0) { + const ret = getObject(arg0).style; + return addHeapObject(ret); + }; + imports.wbg.__wbg_setProperty_ecf331459a4d3891 = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).setProperty(getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4)); + }, arguments) }; + imports.wbg.__wbg_width_87fb7beca76ecb6a = function(arg0) { + const ret = getObject(arg0).width; + return ret; + }; + imports.wbg.__wbg_setwidth_a04b04d18cb81715 = function(arg0, arg1) { + getObject(arg0).width = arg1 >>> 0; + }; + imports.wbg.__wbg_height_0fb9764a1a78e3f6 = function(arg0) { + const ret = getObject(arg0).height; + return ret; + }; + imports.wbg.__wbg_setheight_ae3c51b7555bd27d = function(arg0, arg1) { + getObject(arg0).height = arg1 >>> 0; + }; + imports.wbg.__wbg_x_dedc0183b8cf9e44 = function(arg0) { + const ret = getObject(arg0).x; + return ret; + }; + imports.wbg.__wbg_y_07982b620f686fbd = function(arg0) { + const ret = getObject(arg0).y; + return ret; + }; + imports.wbg.__wbg_width_eb7805903efd7fd3 = function(arg0) { + const ret = getObject(arg0).width; + return ret; + }; + imports.wbg.__wbg_height_aac6bd5616201da3 = function(arg0) { + const ret = getObject(arg0).height; + return ret; + }; + imports.wbg.__wbg_addListener_265dcc33d68a7574 = function() { return handleError(function (arg0, arg1) { + getObject(arg0).addListener(getObject(arg1)); + }, arguments) }; + imports.wbg.__wbg_removeListener_03d5c1013266db90 = function() { return handleError(function (arg0, arg1) { + getObject(arg0).removeListener(getObject(arg1)); + }, arguments) }; + imports.wbg.__wbg_ctrlKey_643b17aaac67db50 = function(arg0) { + const ret = getObject(arg0).ctrlKey; + return ret; + }; + imports.wbg.__wbg_shiftKey_8fb7301f56e7e01c = function(arg0) { + const ret = getObject(arg0).shiftKey; + return ret; + }; + imports.wbg.__wbg_altKey_c6c2a7e797d9a669 = function(arg0) { + const ret = getObject(arg0).altKey; + return ret; + }; + imports.wbg.__wbg_metaKey_2a8dbd51a3f59e9c = function(arg0) { + const ret = getObject(arg0).metaKey; + return ret; + }; + imports.wbg.__wbg_button_cd87b6dabbde9631 = function(arg0) { + const ret = getObject(arg0).button; + return ret; + }; + imports.wbg.__wbg_setwidth_7591ce24118fd14a = function(arg0, arg1) { + getObject(arg0).width = arg1 >>> 0; + }; + imports.wbg.__wbg_setheight_f7ae862183d88bd5 = function(arg0, arg1) { + getObject(arg0).height = arg1 >>> 0; + }; + imports.wbg.__wbg_getContext_52cc019050c5f7bd = function() { return handleError(function (arg0, arg1, arg2, arg3) { + const ret = getObject(arg0).getContext(getStringFromWasm0(arg1, arg2), getObject(arg3)); + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_videoWidth_ca6d86a1026278ad = function(arg0) { + const ret = getObject(arg0).videoWidth; + return ret; + }; + imports.wbg.__wbg_videoHeight_55466ec3a1cae41c = function(arg0) { + const ret = getObject(arg0).videoHeight; + return ret; + }; + imports.wbg.__wbg_shiftKey_55894418ec38c771 = function(arg0) { + const ret = getObject(arg0).shiftKey; + return ret; + }; + imports.wbg.__wbg_metaKey_16606958d932a374 = function(arg0) { + const ret = getObject(arg0).metaKey; + return ret; + }; + imports.wbg.__wbg_code_878e76a4ddb70157 = function(arg0, arg1) { + const ret = getObject(arg1).code; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_deltaX_03d8f6dcd2e14b63 = function(arg0) { + const ret = getObject(arg0).deltaX; + return ret; + }; + imports.wbg.__wbg_deltaY_7d9a7eb25f83e193 = function(arg0) { + const ret = getObject(arg0).deltaY; + return ret; + }; + imports.wbg.__wbg_deltaMode_5f43eb63f3077df7 = function(arg0) { + const ret = getObject(arg0).deltaMode; + return ret; + }; + imports.wbg.__wbindgen_closure_wrapper4600 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 3641, __wbg_adapter_34); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_closure_wrapper67219 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 50750, __wbg_adapter_37); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_closure_wrapper67221 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 50750, __wbg_adapter_37); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_closure_wrapper67223 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 50751, __wbg_adapter_37); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_closure_wrapper67225 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 50750, __wbg_adapter_37); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_closure_wrapper67227 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 50750, __wbg_adapter_37); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_closure_wrapper67229 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 50750, __wbg_adapter_37); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_closure_wrapper67231 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 50750, __wbg_adapter_37); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_closure_wrapper78009 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 53839, __wbg_adapter_52); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_closure_wrapper79563 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 54125, __wbg_adapter_55); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_closure_wrapper83612 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 55165, __wbg_adapter_58); + return addHeapObject(ret); + }; + + return imports; +} + +function __wbg_init_memory(imports, maybe_memory) { + +} + +function __wbg_finalize_init(instance, module) { + wasm = instance.exports; + __wbg_init.__wbindgen_wasm_module = module; + cachedFloat32Memory0 = null; + cachedFloat64Memory0 = null; + cachedInt32Memory0 = null; + cachedUint32Memory0 = null; + cachedUint8Memory0 = null; + + wasm.__wbindgen_start(); + return wasm; +} + +function initSync(module) { + if (wasm !== undefined) return wasm; + + const imports = __wbg_get_imports(); + + __wbg_init_memory(imports); + + if (!(module instanceof WebAssembly.Module)) { + module = new WebAssembly.Module(module); + } + + const instance = new WebAssembly.Instance(module, imports); + + return __wbg_finalize_init(instance, module); +} + +async function __wbg_init(input) { + if (wasm !== undefined) return wasm; + + if (typeof input === 'undefined') { + input = new URL('game_bg.wasm', import.meta.url); + } + const imports = __wbg_get_imports(); + + if (typeof input === 'string' || (typeof Request === 'function' && input instanceof Request) || (typeof URL === 'function' && input instanceof URL)) { + input = fetch(input); + } + + __wbg_init_memory(imports); + + const { instance, module } = await __wbg_load(await input, imports); + + return __wbg_finalize_init(instance, module); +} + +export { initSync } +export default __wbg_init; diff --git a/the-merp-experiment/game_bg.wasm b/the-merp-experiment/game_bg.wasm new file mode 100644 index 0000000..95b9b56 Binary files /dev/null and b/the-merp-experiment/game_bg.wasm differ diff --git a/the-merp-experiment/index.html b/the-merp-experiment/index.html new file mode 100644 index 0000000..7e3481a --- /dev/null +++ b/the-merp-experiment/index.html @@ -0,0 +1,6 @@ + \ No newline at end of file