ngx-chiptan
Version:
Angular component to renders chiptan flicker code.
142 lines • 19.8 kB
JavaScript
/*
Copyright (c) 2010–2012
Lars-Dominik Braun <lars@6xq.net>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
export function flickerCode(newcode) {
let code = newcode.toUpperCase().replace(/[^a-fA-F0-9]/g, '');
const toHex = (n, minlen) => {
let s = n.toString(16).toUpperCase();
while (s.length < minlen) {
s = '0' + s;
}
return s;
};
const quersumme = (n) => {
let q = 0;
while (n != 0) {
q += n % 10;
n = Math.floor(n / 10);
}
return q;
};
const getPayload = () => {
let i = 0;
let payload = '';
let len = parseInt(code.slice(0, 2), 16);
i += 2;
while (i < code.length - 2) {
i += 1;
len = parseInt(code.slice(i, i + 1), 16);
i += 1;
payload += code.slice(i, i + len * 2);
i += len * 2;
}
return payload;
};
const checksum = () => {
const len = code.length / 2 - 1;
code = toHex(len, 2) + code.substr(2);
const luhndata = getPayload();
let luhnsum = 0;
for (let i = 0; i < luhndata.length; i += 2) {
luhnsum += (1 * parseInt(luhndata[i], 16)) + quersumme(2 * parseInt(luhndata[i + 1], 16));
}
luhnsum = (10 - (luhnsum % 10)) % 10;
code = code.substr(0, code.length - 2) + toHex(luhnsum, 1) + code.substr(code.length - 1);
let xorsum = 0;
for (let i = 0; i < code.length - 2; i++) {
xorsum ^= parseInt(code[i], 16);
}
code = code.substr(0, code.length - 1) + toHex(xorsum, 1);
};
this.getCode = () => code;
checksum();
}
export function flickerCanvas(width, height, bgColor, barColor) {
let code, halfbyteid, clock, bitarray, canvas, ctx;
this.reset = () => {
halfbyteid = 0;
clock = 1;
};
const setup = () => {
const bits = new Object();
bits['0'] = [0, 0, 0, 0, 0];
bits['1'] = [0, 1, 0, 0, 0];
bits['2'] = [0, 0, 1, 0, 0];
bits['3'] = [0, 1, 1, 0, 0];
bits['4'] = [0, 0, 0, 1, 0];
bits['5'] = [0, 1, 0, 1, 0];
bits['6'] = [0, 0, 1, 1, 0];
bits['7'] = [0, 1, 1, 1, 0];
bits['8'] = [0, 0, 0, 0, 1];
bits['9'] = [0, 1, 0, 0, 1];
bits['A'] = [0, 0, 1, 0, 1];
bits['B'] = [0, 1, 1, 0, 1];
bits['C'] = [0, 0, 0, 1, 1];
bits['D'] = [0, 1, 0, 1, 1];
bits['E'] = [0, 0, 1, 1, 1];
bits['F'] = [0, 1, 1, 1, 1];
code = '0FFF' + code;
bitarray = [];
for (let i = 0; i < code.length; i += 2) {
bitarray[i] = bits[code[i + 1]];
bitarray[i + 1] = bits[code[i]];
}
};
const createCanvas = (width, height, bgColor, barColor) => {
canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
if (canvas.getContext) {
ctx = canvas.getContext('2d');
}
ctx.fillStyle = bgColor;
ctx.fillRect(0, 0, canvas.width, canvas.height);
};
this.step = () => {
const margin = 7;
const barwidth = canvas.width / 5;
bitarray[halfbyteid][0] = clock;
for (let i = 0; i < 5; i++) {
if (bitarray[halfbyteid][i] == 1) {
ctx.fillStyle = barColor;
}
else {
ctx.fillStyle = bgColor;
}
ctx.fillRect(i * barwidth + margin, margin, barwidth - 2 * margin, canvas.height - 2 * margin);
}
clock--;
if (clock < 0) {
clock = 1;
halfbyteid++;
if (halfbyteid >= bitarray.length) {
halfbyteid = 0;
}
}
return 0;
};
this.getCanvas = () => canvas;
this.setCode = newcode => {
code = newcode.getCode();
setup();
this.reset();
};
createCanvas(width, height, bgColor, barColor);
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmxpY2tlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1jaGlwdGFuL3NyYy9saWIvZmxpY2tlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQTs7Ozs7Ozs7Ozs7Ozs7Ozs7O0VBa0JFO0FBRUYsTUFBTSxVQUFVLFdBQVcsQ0FBQyxPQUFPO0lBQ2pDLElBQUksSUFBSSxHQUFHLE9BQU8sQ0FBQyxXQUFXLEVBQUUsQ0FBQyxPQUFPLENBQUMsZUFBZSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBRTlELE1BQU0sS0FBSyxHQUFHLENBQUMsQ0FBQyxFQUFFLE1BQU0sRUFBRSxFQUFFO1FBQzFCLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDckMsT0FBTyxDQUFDLENBQUMsTUFBTSxHQUFHLE1BQU0sRUFBRTtZQUN4QixDQUFDLEdBQUcsR0FBRyxHQUFHLENBQUMsQ0FBQztTQUNiO1FBRUQsT0FBTyxDQUFDLENBQUM7SUFDWCxDQUFDLENBQUE7SUFFRCxNQUFNLFNBQVMsR0FBRyxDQUFDLENBQUMsRUFBRSxFQUFFO1FBQ3RCLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNWLE9BQU8sQ0FBQyxJQUFJLENBQUMsRUFBRTtZQUNiLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO1lBQ1osQ0FBQyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDO1NBQ3hCO1FBRUQsT0FBTyxDQUFDLENBQUM7SUFDWCxDQUFDLENBQUE7SUFFRCxNQUFNLFVBQVUsR0FBRyxHQUFHLEVBQUU7UUFDdEIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ1YsSUFBSSxPQUFPLEdBQUcsRUFBRSxDQUFDO1FBRWpCLElBQUksR0FBRyxHQUFHLFFBQVEsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMs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LENBQUM7SUFFRixNQUFNLEtBQUssR0FBRyxHQUFHLEVBQUU7UUFDakIsTUFBTSxJQUFJLEdBQUcsSUFBSSxNQUFNLEVBQUUsQ0FBQztRQUMxQixJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDNUIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQzVCLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUM1QixJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDNUIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQzVCLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUM1QixJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDNUIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQzVCLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUM1QixJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDNUIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQzVCLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUM1QixJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDNUIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQzVCLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUM1QixJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFFNUIsSUFBSSxHQUFHLE1BQU0sR0FBRyxJQUFJLENBQUM7UUFFckIsUUFBUSxHQUFHLEVBQUUsQ0FBQztRQUNkLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsSUFBSSxDQUFDLEVBQUU7WUFDdkMsUUFBUSxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxHQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDOUIsUUFBUSxDQUFDLENBQUMsR0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7U0FDL0I7SUFDSCxDQUFDLENBQUM7SUFFRixNQUFNLFlBQVksR0FBRyxDQUFDLEtBQUssRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxFQUFFO1FBQ3hELE1BQU0sR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQzFDLE1BQU0sQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO1FBQ3JCLE1BQU0sQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO1FBQ3ZCLElBQUksTUFBTSxDQUFDLFVBQVUsRUFBRTtZQUNyQixHQUFHLEdBQUcsTUFBTSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQztTQUMvQjtRQUVELEdBQUcsQ0FBQyxTQUFTLEdBQUcsT0FBTyxDQUFDO1FBQ3hCLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxNQUFNLENBQUMsS0FBSyxFQUFFLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUNsRCxDQUFDLENBQUE7SUFFRCxJQUFJLENBQUMsSUFBSSxHQUFHLEdBQUcsRUFBRTtRQUNmLE1BQU0sTUFBTSxHQUFHLENBQUMsQ0FBQztRQUNqQixNQUFNLFFBQVEsR0FBRyxNQUFNLENBQUMsS0FBSyxHQUFHLENBQUMsQ0FBQztRQUVsQyxRQUFRLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsS0FBSyxDQUFDO1FBRWhDLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUU7WUFDMUIsSUFBSSxRQUFRLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFO2dCQUNoQyxHQUFHLENBQUMsU0FBUyxHQUFHLFFBQVEsQ0FBQzthQUMxQjtpQkFBTTtnQkFDTCxHQUFHLENBQUMsU0FBUyxHQUFHLE9BQU8sQ0FBQzthQUN6QjtZQUNELEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQyxHQUFHLFFBQVEsR0FBRyxNQUFNLEVBQUUsTUFBTSxFQUFFLFFBQVEsR0FBRyxDQUFDLEdBQUcsTUFBTSxFQUFFLE1BQU0sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxDQUFDO1NBQ2hHO1FBRUQsS0FBSyxFQUFFLENBQUM7UUFDUixJQUFJLEtBQUssR0FBRyxDQUFDLEVBQUU7WUFDYixLQUFLLEdBQUcsQ0FBQyxDQUFDO1lBRVYsVUFBVSxFQUFFLENBQUM7WUFDYixJQUFJLFVBQVUsSUFBSSxRQUFRLENBQUMsTUFBTSxFQUFFO2dCQUNqQyxVQUFVLEdBQUcsQ0FBQyxDQUFDO2FBQ2hCO1NBRUY7UUFFRCxPQUFPLENBQUMsQ0FBQztJQUNYLENBQUMsQ0FBQTtJQUVELElBQUksQ0FBQyxTQUFTLEdBQUcsR0FBRyxFQUFFLENBQUMsTUFBTSxDQUFDO0lBRTlCLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDLEVBQUU7UUFDdkIsSUFBSSxHQUFHLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUN6QixLQUFLLEVBQUUsQ0FBQztRQUNSLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUNmLENBQUMsQ0FBQTtJQUVELFlBQVksQ0FBQyxLQUFLLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxRQUFRLENBQUMsQ0FBQztBQUNqRCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiXHJcbi8qXHJcbkNvcHlyaWdodCAoYykgMjAxMOKAkzIwMTJcclxuICAgIExhcnMtRG9taW5payBCcmF1biA8bGFyc0A2eHEubmV0PlxyXG5QZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYSBjb3B5XHJcbm9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvIGRlYWxcclxuaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0c1xyXG50byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsXHJcbmNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpc1xyXG5mdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOlxyXG5UaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZCBpblxyXG5hbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cclxuVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUlxyXG5JTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSxcclxuRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFXHJcbkFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVJcclxuTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSxcclxuT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTlxyXG5USEUgU09GVFdBUkUuXHJcbiovXHJcblxyXG5leHBvcnQgZnVuY3Rpb24gZmxpY2tlckNvZGUobmV3Y29kZSkge1xyXG4gIGxldCBjb2RlID0gbmV3Y29kZS50b1VwcGVyQ2FzZSgpLnJlcGxhY2UoL1teYS1mQS1GMC05XS9nLCAnJyk7XHJcblxyXG4gIGNvbnN0IHRvSGV4ID0gKG4sIG1pbmxlbikgPT4ge1xyXG4gICAgbGV0IHMgPSBuLnRvU3RyaW5nKDE2KS50b1VwcGVyQ2FzZSgpO1xyXG4gICAgd2hpbGUgKHMubGVuZ3RoIDwgbWlubGVuKSB7XHJcbiAgICAgIHMgPSAnMCcgKyBzO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBzO1xyXG4gIH1cclxuXHJcbiAgY29uc3QgcXVlcnN1bW1lID0gKG4pID0+IHtcclxuICAgIGxldCBxID0gMDtcclxuICAgIHdoaWxlIChuICE9IDApIHtcclxuICAgICAgcSArPSBuICUgMTA7XHJcbiAgICAgIG4gPSBNYXRoLmZsb29yKG4gLyAxMCk7XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIHE7XHJcbiAgfVxyXG5cclxuICBjb25zdCBnZXRQYXlsb2FkID0gKCkgPT4ge1xyXG4gICAgbGV0IGkgPSAwO1xyXG4gICAgbGV0IHBheWxvYWQgPSAnJztcclxuXHJcbiAgICBsZXQgbGVuID0gcGFyc2VJbnQoY29kZS5zbGljZSgwLCAyKSwgMTYpO1xyXG4gICAgaSArPSAyO1xyXG4gICAgd2hpbGUgKGkgPCBjb2RlLmxlbmd0aCAtIDIpIHtcclxuICAgICAgaSArPSAxO1xyXG4gICAgICBsZW4gPSBwYXJzZUludChjb2RlLnNsaWNlKGksIGkgKyAxKSwgMTYpO1xyXG4gICAgICBpICs9IDE7XHJcbiAgICAgIHBheWxvYWQgKz0gY29kZS5zbGljZShpLCBpKyBsZW4gKiAyKTtcclxuICAgICAgaSArPSBsZW4gKiAyO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBwYXlsb2FkO1xyXG4gIH1cclxuXHJcbiAgY29uc3QgY2hlY2tzdW0gPSAoKSA9PiB7XHJcbiAgICBjb25zdCBsZW4gPSBjb2RlLmxlbmd0aCAvIDIgLSAxO1xyXG4gICAgY29kZSA9IHRvSGV4KGxlbiwgMikgKyBjb2RlLnN1YnN0cigyKTtcclxuXHJcbiAgICBjb25zdCBsdWhuZGF0YSA9IGdldFBheWxvYWQoKTtcclxuICAgIGxldCBsdWhuc3VtID0gMDtcclxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbHVobmRhdGEubGVuZ3RoOyBpICs9IDIpIHtcclxuICAgICAgbHVobnN1bSArPSAoMSAqIHBhcnNlSW50KGx1aG5kYXRhW2ldLCAxNikpICsgcXVlcnN1bW1lKDIgKiBwYXJzZUludChsdWhuZGF0YVtpICsgMV0sIDE2KSk7XHJcbiAgICB9XHJcbiAgICBsdWhuc3VtID0gKDEwIC0gKGx1aG5zdW0gJSAxMCkpICUgMTA7XHJcbiAgICBjb2RlID0gY29kZS5zdWJzdHIoMCwgY29kZS5sZW5ndGggLSAyKSArIHRvSGV4KGx1aG5zdW0sIDEpICsgY29kZS5zdWJzdHIoY29kZS5sZW5ndGggLSAxKTtcclxuXHJcbiAgICBsZXQgeG9yc3VtID0gMDtcclxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY29kZS5sZW5ndGggLSAyOyBpKyspIHtcclxuICAgICAgeG9yc3VtIF49IHBhcnNlSW50KGNvZGVbaV0sIDE2KTtcclxuICAgIH1cclxuXHJcbiAgICBjb2RlID0gY29kZS5zdWJzdHIoMCwgY29kZS5sZW5ndGgtMSkgKyB0b0hleCh4b3JzdW0sIDEpO1xyXG4gIH1cclxuXHJcbiAgdGhpcy5nZXRDb2RlID0gKCkgPT4gY29kZTtcclxuXHJcbiAgY2hlY2tzdW0oKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIGZsaWNrZXJDYW52YXMod2lkdGgsIGhlaWdodCwgYmdDb2xvciwgYmFyQ29sb3IpIHtcclxuICBsZXQgY29kZSwgaGFsZmJ5dGVpZCwgY2xvY2ssIGJpdGFycmF5LCBjYW52YXMsIGN0eDtcclxuXHJcbiAgdGhpcy5yZXNldCA9ICgpID0+IHtcclxuICAgIGhhbGZieXRlaWQgPSAwO1xyXG4gICAgY2xvY2sgPSAxO1xyXG4gIH07XHJcblxyXG4gIGNvbnN0IHNldHVwID0gKCkgPT4ge1xyXG4gICAgY29uc3QgYml0cyA9IG5ldyBPYmplY3QoKTtcclxuICAgIGJpdHNbJzAnXSA9IFswLCAwLCAwLCAwLCAwXTtcclxuICAgIGJpdHNbJzEnXSA9IFswLCAxLCAwLCAwLCAwXTtcclxuICAgIGJpdHNbJzInXSA9IFswLCAwLCAxLCAwLCAwXTtcclxuICAgIGJpdHNbJzMnXSA9IFswLCAxLCAxLCAwLCAwXTtcclxuICAgIGJpdHNbJzQnXSA9IFswLCAwLCAwLCAxLCAwXTtcclxuICAgIGJpdHNbJzUnXSA9IFswLCAxLCAwLCAxLCAwXTtcclxuICAgIGJpdHNbJzYnXSA9IFswLCAwLCAxLCAxLCAwXTtcclxuICAgIGJpdHNbJzcnXSA9IFswLCAxLCAxLCAxLCAwXTtcclxuICAgIGJpdHNbJzgnXSA9IFswLCAwLCAwLCAwLCAxXTtcclxuICAgIGJpdHNbJzknXSA9IFswLCAxLCAwLCAwLCAxXTtcclxuICAgIGJpdHNbJ0EnXSA9IFswLCAwLCAxLCAwLCAxXTtcclxuICAgIGJpdHNbJ0InXSA9IFswLCAxLCAxLCAwLCAxXTtcclxuICAgIGJpdHNbJ0MnXSA9IFswLCAwLCAwLCAxLCAxXTtcclxuICAgIGJpdHNbJ0QnXSA9IFswLCAxLCAwLCAxLCAxXTtcclxuICAgIGJpdHNbJ0UnXSA9IFswLCAwLCAxLCAxLCAxXTtcclxuICAgIGJpdHNbJ0YnXSA9IFswLCAxLCAxLCAxLCAxXTtcclxuXHJcbiAgICBjb2RlID0gJzBGRkYnICsgY29kZTtcclxuXHJcbiAgICBiaXRhcnJheSA9IFtdO1xyXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjb2RlLmxlbmd0aDsgaSArPSAyKSB7XHJcbiAgICAgIGJpdGFycmF5W2ldID0gYml0c1tjb2RlW2krMV1dO1xyXG4gICAgICBiaXRhcnJheVtpKzFdID0gYml0c1tjb2RlW2ldXTtcclxuICAgIH1cclxuICB9O1xyXG5cclxuICBjb25zdCBjcmVhdGVDYW52YXMgPSAod2lkdGgsIGhlaWdodCwgYmdDb2xvciwgYmFyQ29sb3IpID0+IHtcclxuICAgIGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xyXG4gICAgY2FudmFzLndpZHRoID0gd2lkdGg7XHJcbiAgICBjYW52YXMuaGVpZ2h0ID0gaGVpZ2h0O1xyXG4gICAgaWYgKGNhbnZhcy5nZXRDb250ZXh0KSB7XHJcbiAgICAgIGN0eCA9IGNhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xyXG4gICAgfVxyXG5cclxuICAgIGN0eC5maWxsU3R5bGUgPSBiZ0NvbG9yO1xyXG4gICAgY3R4LmZpbGxSZWN0KDAsIDAsIGNhbnZhcy53aWR0aCwgY2FudmFzLmhlaWdodCk7XHJcbiAgfVxyXG5cclxuICB0aGlzLnN0ZXAgPSAoKSA9PiB7XHJcbiAgICBjb25zdCBtYXJnaW4gPSA3O1xyXG4gICAgY29uc3QgYmFyd2lkdGggPSBjYW52YXMud2lkdGggLyA1O1xyXG5cclxuICAgIGJpdGFycmF5W2hhbGZieXRlaWRdWzBdID0gY2xvY2s7XHJcblxyXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCA1OyBpKyspIHtcclxuICAgICAgaWYgKGJpdGFycmF5W2hhbGZieXRlaWRdW2ldID09IDEpIHtcclxuICAgICAgICBjdHguZmlsbFN0eWxlID0gYmFyQ29sb3I7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgY3R4LmZpbGxTdHlsZSA9IGJnQ29sb3I7XHJcbiAgICAgIH1cclxuICAgICAgY3R4LmZpbGxSZWN0KGkgKiBiYXJ3aWR0aCArIG1hcmdpbiwgbWFyZ2luLCBiYXJ3aWR0aCAtIDIgKiBtYXJnaW4sIGNhbnZhcy5oZWlnaHQgLSAyICogbWFyZ2luKTtcclxuICAgIH1cclxuXHJcbiAgICBjbG9jay0tO1xyXG4gICAgaWYgKGNsb2NrIDwgMCkge1xyXG4gICAgICBjbG9jayA9IDE7XHJcblxyXG4gICAgICBoYWxmYnl0ZWlkKys7XHJcbiAgICAgIGlmIChoYWxmYnl0ZWlkID49IGJpdGFycmF5Lmxlbmd0aCkge1xyXG4gICAgICAgIGhhbGZieXRlaWQgPSAwO1xyXG4gICAgICB9XHJcblxyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiAwO1xyXG4gIH1cclxuXHJcbiAgdGhpcy5nZXRDYW52YXMgPSAoKSA9PiBjYW52YXM7XHJcblxyXG4gIHRoaXMuc2V0Q29kZSA9IG5ld2NvZGUgPT4ge1xyXG4gICAgY29kZSA9IG5ld2NvZGUuZ2V0Q29kZSgpO1xyXG4gICAgc2V0dXAoKTtcclxuICAgIHRoaXMucmVzZXQoKTtcclxuICB9XHJcblxyXG4gIGNyZWF0ZUNhbnZhcyh3aWR0aCwgaGVpZ2h0LCBiZ0NvbG9yLCBiYXJDb2xvcik7XHJcbn1cclxuIl19