{"version":3,"file":"pulseplot.umd.cjs","sources":["../lib/autorange.js","../lib/utils.js","../lib/dropzone.js","../lib/hexbuffer.js","../lib/histogram.js","../lib/bitbuffer.js","../lib/slicer.js","../lib/builder.js","../lib/rfraw.js","../lib/broadlinkrm.js","../lib/pulseplot.js","../lib/demos.js"],"sourcesContent":["/**\n    Determine divisor and SI prefix.\n\n    @author Christian W. Zuckschwerdt <zany@triq.net>\n    @copyright Christian W. Zuckschwerdt, 2019\n    @license\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 2 of the License, or\n    (at your option) any later version.\n*/\n\nconst autoranges = [\n    { name: 'yotta', scale: 1e24, prefix: 'Y' },\n    { name: 'zetta', scale: 1e21, prefix: 'Z' },\n    { name: 'exa', scale: 1e18, prefix: 'E' },\n    { name: 'peta', scale: 1e15, prefix: 'P' },\n    { name: 'tera', scale: 1e12, prefix: 'T' },\n    { name: 'giga', scale: 1e9, prefix: 'G' },\n    { name: 'mega', scale: 1e6, prefix: 'M' },\n    { name: 'kilo', scale: 1e3, prefix: 'k' },\n    { name: '', scale: 1e0, prefix: '' },\n    { name: 'milli', scale: 1e-3, prefix: 'm' },\n    { name: 'micro', scale: 1e-6, prefix: 'µ' },\n    { name: 'nano', scale: 1e-9, prefix: 'n' },\n    { name: 'pico', scale: 1e-12, prefix: 'p' },\n    { name: 'femto', scale: 1e-15, prefix: 'f' },\n    { name: 'atto', scale: 1e-18, prefix: 'a' },\n    { name: 'zepto', scale: 1e-21, prefix: 'z' },\n    { name: 'yocto', scale: 1e-24, prefix: 'y' },\n];\n\n/** Determine divisor and SI prefix. */\nfunction autorange(num, min_int = 10.0) {\n    if (num == 0.0)\n        return autoranges[8];\n\n    num = num / min_int;\n    for (let i = 0; i < autoranges.length; ++i) {\n        if (num >= autoranges[i].scale)\n            return autoranges[i];\n    }\n    return autoranges[autoranges.length - 1];\n}\n\nexport { autorange };\n\nconst autoranges_time = [\n    { name: 'year', scale: 31557513, prefix: 'Y' },\n    { name: 'month', scale: 2635200, prefix: 'M' },\n    { name: 'day', scale: 86400, prefix: 'D' },\n    { name: 'hour', scale: 3600, prefix: 'h' },\n    { name: 'minute', scale: 60, prefix: 'm' },\n    { name: 'second', scale: 1e0, prefix: 's' },\n    { name: 'milli', scale: 1e-3, prefix: 'ms' },\n    { name: 'micro', scale: 1e-6, prefix: 'µs' },\n    { name: 'nano', scale: 1e-9, prefix: 'ns' },\n    { name: 'pico', scale: 1e-12, prefix: 'ps' },\n    { name: 'femto', scale: 1e-15, prefix: 'fs' },\n    { name: 'atto', scale: 1e-18, prefix: 'as' },\n    { name: 'zepto', scale: 1e-21, prefix: 'zs' },\n    { name: 'yocto', scale: 1e-24, prefix: 'ys' },\n];\n\n/** Determine SI divisor or Sexagesimal multiplier and suffix. */\nfunction autorange_time(num, min_int = 10.0) {\n    if (num == 0.0)\n        return autoranges_time[8];\n\n    num = num / min_int;\n    for (let i = 0; i < autoranges_time.length; ++i) {\n        if (num >= autoranges_time[i].scale)\n            return autoranges_time[i];\n    }\n    return autoranges_time[autoranges_time.length - 1];\n}\n\nexport { autorange_time };\n","/**\n    @file Various utils.\n\n    @author Christian W. Zuckschwerdt <zany@triq.net>\n    @copyright Christian W. Zuckschwerdt, 2019\n    @license\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 2 of the License, or\n    (at your option) any later version.\n*/\n\n/** Returns element or expands selector. */\nexport function selector(elementOrSelector) {\n    if (!elementOrSelector) {\n        return elementOrSelector\n    } else if (typeof elementOrSelector === 'string') {\n        return document.querySelector(elementOrSelector)\n    } else {\n        return elementOrSelector // instanceof Element\n    }\n}\n\n/** Returns array or expands key. */\nexport function lookup(table, arrayOrKey) {\n    if (!arrayOrKey)\n        return arrayOrKey\n    if (typeof arrayOrKey !== 'string')\n        return arrayOrKey\n    if (table[arrayOrKey])\n        return table[arrayOrKey]\n    const match = arrayOrKey.toLowerCase()\n    for (let key in table)\n        if (key.toLowerCase() == match)\n            return table[key]\n    for (let key in table)\n        if (key.toLowerCase().startsWith(match))\n            return table[key]\n    return null\n}\n\n/** Strips HTML tags. */\nexport function strip(html) {\n    var doc = new DOMParser().parseFromString(html, 'text/html');\n    return doc.body.textContent || '';\n}\n","/**\n    @file DropZone JS.\n\n    @author Christian W. Zuckschwerdt <zany@triq.net>\n    @copyright Christian W. Zuckschwerdt, 2019\n    @license\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 2 of the License, or\n    (at your option) any later version.\n*/\n\n/*eslint no-console: \"off\"*/\n\nimport { selector } from './utils.js'\n\nexport class DropZone {\n    constructor(elementOrSelector, fileLoader) {\n        elementOrSelector = elementOrSelector || '#dropZone'\n        elementOrSelector = selector(elementOrSelector)\n\n        // https://css-tricks.com/drag-and-drop-file-uploading/\n        this.dropZone = elementOrSelector\n        this.fileLoader = fileLoader\n        this.inputEls = []\n        this.dragEnteredEls = []\n\n        window.addEventListener('dragenter', this)\n        window.addEventListener('dragleave', this)\n        window.addEventListener('dropleave', this)\n\n        const events = ['dragenter', 'dragover', 'dragleave', 'drop']\n        events.forEach(evt => this.dropZone.addEventListener(evt, this, false))\n    }\n\n    addInput(elementOrSelector) {\n        elementOrSelector = elementOrSelector || '#inputfile'\n        elementOrSelector = selector(elementOrSelector)\n\n        elementOrSelector.addEventListener('change', this, false)\n        this.inputEls.push(elementOrSelector)\n    }\n\n    destroy() {\n        window.removeEventListener('dragenter', this, false)\n        window.removeEventListener('dragleave', this, false)\n        window.removeEventListener('dropleave', this, false)\n\n        const events = ['dragenter', 'dragover', 'dragleave', 'drop']\n        events.forEach(evt => this.dropZone.removeEventListener(evt, this, false))\n\n        for (let el of this.inputEls) {\n            el.removeEventListener('change', this, false)\n        }\n    }\n\n    allowDrag(e) {\n        // ...Test that the item being dragged is a valid one\n        e.dataTransfer.dropEffect = 'copy'\n        e.preventDefault()\n    }\n\n    handleDrop(e) {\n        e.preventDefault()\n        this.handleFileSelect(e)\n    }\n\n    // https://www.html5rocks.com/en/tutorials/file/dndfiles/\n    handleFileSelect(evt) {\n        evt.stopPropagation()\n        evt.preventDefault()\n\n        //const files = evt.dataTransfer.files // FileList object.\n        //const files = evt.target.files // FileList object\n        const files = ('dataTransfer' in evt) ? evt.dataTransfer.files : evt.target.files\n\n        // files is a FileList of File objects. List some properties.\n        for (let i = 0, file; (file = files[i]); i++) {\n            // output some info right away?\n\n            // Blob.arrayBuffer() promise isn't generally supported\n            // use older FileReader.readAsArrayBuffer()\n            const reader = new FileReader()\n\n            // Closure to capture the file information.\n            reader.onload = (e) => {\n                // Process data\n                file['fileBuffer'] = e.target.result\n                //console.log(file.name)\n\n                this.fileLoader(file)\n            }\n\n            // Read in the image file as a data URL.\n            reader.readAsArrayBuffer(file)\n        }\n    }\n\n    // events\n\n    handleEvent(e) {\n        const handler = e.type\n        if (typeof this[handler] === 'function') {\n            e.preventDefault()\n            return this[handler](e)\n        }\n    }\n\n    dragenter(e) {\n        this.dragEnteredEls.push(e.target)\n\n        document.documentElement.classList.add('dragdrop')\n        this.dropZone.classList.add('active')\n    }\n\n    dragover(e) {\n        this.dropZone.classList.add('hover')\n        this.allowDrag(e)\n    }\n\n    dragleave(e) {\n        const index = this.dragEnteredEls.indexOf(e.target)\n        if (index > -1) {\n            this.dragEnteredEls.splice(index, 1)\n        }\n        if (this.dragEnteredEls.indexOf(this.dropZone) < 0) {\n            this.dropZone.classList.remove('hover')\n        }\n        if (this.dragEnteredEls.length === 0) {\n            document.documentElement.classList.remove('dragdrop')\n            this.dropZone.classList.remove('active')\n        }\n    }\n\n    dropleave() {\n        this.dragEnteredEls.splice(0)\n        this.dropZone.classList.remove('hover')\n        this.dropZone.classList.remove('active')\n        document.documentElement.classList.remove('dragdrop')\n    }\n\n    drop(e) {\n        const event = new Event('dropleave')\n        window.dispatchEvent(event)\n\n        this.handleDrop(e)\n    }\n\n    change(e) {\n        this.handleFileSelect(e)\n    }\n}\n","/**\n    @file Hexbuffer JS.\n\n    @author Christian W. Zuckschwerdt <zany@triq.net>\n    @copyright Christian W. Zuckschwerdt, 2020\n    @license\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 2 of the License, or\n    (at your option) any later version.\n*/\n\nfunction dec2hex(i, w = 2) {\n    i = Math.round(i)\n    return (i + 0x10000).toString(16).substr(-w).toUpperCase()\n}\n\nexport class Hexbuffer {\n    constructor(line = '') {\n        this.fromString(line)\n    }\n    fromString(s) {\n        this.line = s.replace(/\\s/g, '')\n        this.index = 0\n    }\n\n    hasNibble() {\n        return this.index + 1 <= this.line.length\n    }\n    hasByte() {\n        return this.index + 2 <= this.line.length\n    }\n    hasWord() {\n        return this.index + 4 <= this.line.length\n    }\n\n    peekNibble() {\n        return parseInt(this.line.substr(this.index, 1), 16)\n    }\n    peekByte() {\n        return parseInt(this.line.substr(this.index, 2), 16)\n    }\n    peekWord() {\n        return parseInt(this.line.substr(this.index, 4), 16)\n    }\n\n    getNibble() {\n        const r = parseInt(this.line.substr(this.index, 1), 16)\n        this.index += 1\n        return r\n    }\n    getByte() {\n        const r = parseInt(this.line.substr(this.index, 2), 16)\n        this.index += 2\n        return r\n    }\n    getWord() {\n        const r = parseInt(this.line.substr(this.index, 4), 16)\n        this.index += 4\n        return r\n    }\n\n    pushNibble(v) {\n        this.line += dec2hex(v, 1)\n    }\n    pushByte(v) {\n        this.line += dec2hex(v, 2)\n    }\n    pushWord(v) {\n        this.line += dec2hex(v, 4)\n    }\n}\n","/**\n    @file Histogram JS.\n\n    @author Christian W. Zuckschwerdt <zany@triq.net>\n    @copyright Christian W. Zuckschwerdt, 2020\n    @license\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 2 of the License, or\n    (at your option) any later version.\n*/\n\nimport { Hexbuffer } from './hexbuffer.js'\n\n/*eslint no-console: \"off\"*/\n\nconst max_hist_bins = 16\n\n/// Histogram data for single bin\nclass Bin {\n    constructor(num) {\n        if (typeof num !== 'undefined') {\n            this.count = 1\n            this.sum = num\n            this.mean = num\n            this.devi = 0\n            this.min = num\n            this.max = num\n        } else {\n            this.count = 0\n            this.sum = 0\n            this.mean = null\n            this.devi = 0\n            this.min = null\n            this.max = null\n        }\n    }\n    add(num) {\n        this.count++\n        this.sum += num\n        this.mean = this.sum / this.count\n        this.min = this.min === null ? num : Math.min(num, this.min)\n        this.max = this.max === null ? num : Math.max(num, this.max)\n        this.devi = (this.max - this.min) / 2\n    }\n    fuse(bin) {\n        this.count += bin.count\n        this.sum += bin.sum\n        this.mean = this.sum / this.count\n        this.min = Math.min(this.min, bin.min)\n        this.max = Math.max(this.max, bin.max)\n        this.devi = (this.max - this.min) / 2\n    }\n    contains(num) {\n        return num >= this.min && num <= this.max\n    }\n}\n\n/// Histogram data for all bins\nexport class Histogram {\n    constructor(data, tolerance = 0.2) {\n        this.bins = []\n        this.histogram_sum(data, tolerance)\n    }\n\n    get length() {\n        return this.bins.length\n    }\n\n    /// Generate a histogram (unsorted)\n    histogram_sum(data, tolerance = 0.2) {\n        const len = data.length\n        for (let n = 0; n < len; ++n) {\n            // Search for match in existing bins\n            let bin\n            for (bin = 0; bin < this.bins.length; ++bin) {\n                const bn = data[n]\n                const bm = this.bins[bin].mean\n                if (Math.abs(bn - bm) < (tolerance * Math.max(bn, bm))) {\n                    this.bins[bin].add(data[n])\n                    break // Match found! Data added to existing bin\n                }\n            }\n            // No match found? Add new bin\n            if (bin == this.bins.length && bin < max_hist_bins) {\n                this.bins.push(new Bin(data[n]))\n            }\n        }\n    }\n\n    /// Delete bin from histogram\n    delete_bin(index) {\n        this.bins.splice(index, 1)\n    }\n\n    /// Swap two bins in histogram\n    swap_bins(index1, index2) {\n        if ((index1 < this.bins.length) && (index2 < this.bins.length)) { // Avoid out of bounds\n            const tempbin = this.bins[index1]\n            this.bins[index1] = this.bins[index2]\n            this.bins[index2] = tempbin\n        }\n    }\n\n    /// Sort histogram with mean value (order lowest to highest)\n    sort_mean() {\n        if (this.bins.length < 2) return // Avoid underflow\n        // Compare all bins (bubble sort)\n        for (let n = 0; n < this.bins.length - 1; ++n) {\n            for (let m = n + 1; m < this.bins.length; ++m) {\n                if (this.bins[m].mean < this.bins[n].mean) {\n                    this.swap_bins(m, n)\n                }\n            }\n        }\n    }\n\n    /// Sort histogram with count value (order lowest to highest)\n    sort_count() {\n        if (this.bins.length < 2) return // Avoid underflow\n        // Compare all bins (bubble sort)\n        for (let n = 0; n < this.bins.length - 1; ++n) {\n            for (let m = n + 1; m < this.bins.length; ++m) {\n                if (this.bins[m].count < this.bins[n].count) {\n                    this.swap_bins(m, n)\n                }\n            }\n        }\n    }\n\n    /// Fuse histogram bins with means within tolerance\n    fuse_bins(tolerance = 0.2) {\n        if (this.bins.length < 2) return // Avoid underflow\n        // Compare all bins\n        for (let n = 0; n < this.bins.length - 1; ++n) {\n            for (let m = n + 1; m < this.bins.length; ++m) {\n                const bn = this.bins[n].mean\n                const bm = this.bins[m].mean\n                // if within tolerance\n                if (Math.abs(bn - bm) < (tolerance * Math.max(bn, bm))) {\n                    // Fuse data for bin[n] and bin[m]\n                    this.bins[n].fuse(this.bins[m])\n                    // Delete bin[m]\n                    this.delete_bin(m)\n                    m-- // Compare new bin in same place!\n                }\n            }\n        }\n    }\n\n    /// Trim zero-width bins\n    trim_bins(tolerance = 0) {\n        for (let n = 0; n < this.bins.length; ++n) {\n            // if within tolerance\n            if (this.bins[n].mean <= tolerance) {\n                // Delete bin[n]\n                this.delete_bin(n)\n            }\n        }\n    }\n\n    /// Find bin index\n    find_bin_index(width) {\n        for (let n = 0; n < this.bins.length; ++n) {\n            if (this.bins[n].contains(width)) {\n                return n\n            }\n        }\n        return -1\n    }\n\n    /// Print a histogram\n    console_print() {\n        for (let n = 0; n < this.bins.length; ++n) {\n            const b = this.bins[n]\n            console.log(`[${n}] ${b.count} × ${b.mean.toFixed(1)} ±${b.devi.toFixed(1)} µs [${b.min};${b.max}]`)\n        }\n    }\n\n    string_print(separator = ', ') {\n        let ret = []\n        for (let n = 0; n < this.bins.length; ++n) {\n            const b = this.bins[n]\n            ret.push(`${b.count}× ${b.mean.toFixed(1)} <small>±${b.devi.toFixed(1)}</small> µs`)\n        }\n        return ret.join(separator)\n    }\n\n}\n\nexport class Analyzer {\n    constructor(data, tolerance = 0.2) {\n        this.analyse_pulses(data, tolerance)\n        this.create_rfraw(data)\n    }\n\n    /// Create histograms from pulse data\n    analyse_pulses(data, messages, tolerance = 0.2) {\n        // Generate pulse/gap/period data\n        this.pulses = []\n        this.gaps = []\n        this.periods = []\n        this.pulse_sum = 0\n        this.gap_sum = 0\n        // Leave out last gap (end)\n        for (let j = 0; j < data.length - 2; j += 2) {\n            const m = data[j] // mark\n            const s = data[j + 1] // space\n            this.pulses.push(m)\n            this.gaps.push(s)\n            this.periods.push(m + s)\n            this.pulse_sum += m\n            this.gap_sum += s\n        }\n        const m = data[data.length - 2] // last mark\n        //const s = data[data.length - 1] // last space\n        this.pulses.push(m)\n        this.pulse_sum += m\n        //this.gap_sum += s\n        this.pulse_gap_ratio = this.pulse_sum / this.gap_sum\n        this.pulse_gap_skew = this.pulse_gap_ratio - 1\n\n        // Generate statistics\n        this.hist_pulses = new Histogram(this.pulses, tolerance)\n        this.hist_gaps = new Histogram(this.gaps, tolerance)\n        this.hist_periods = new Histogram(this.periods, tolerance)\n        this.hist_timings = new Histogram(data, tolerance)\n\n        // Trim zero-width bins\n        this.hist_pulses.trim_bins(tolerance)\n        this.hist_gaps.trim_bins(tolerance)\n        this.hist_periods.trim_bins(tolerance)\n        this.hist_timings.trim_bins(tolerance)\n\n        // Fuse overlapping bins\n        this.hist_pulses.fuse_bins(tolerance)\n        this.hist_gaps.fuse_bins(tolerance)\n        this.hist_periods.fuse_bins(tolerance)\n        this.hist_timings.fuse_bins(tolerance)\n    }\n\n    guess() {\n        const pulses = this.hist_pulses\n        const gaps = this.hist_gaps\n        const periods = this.hist_periods\n        pulses.sort_mean() // Easier to work with sorted data\n        gaps.sort_mean()\n        if (pulses.bins.length > 0 && pulses.bins[0].mean == 0) {\n            pulses.delete_bin(0) // Remove FSK initial zero-bin\n        }\n        //if (pulses.bins[0].mean <= 9 && pulses.bins[0].count <= 2) {\n        //    pulses.delete_bin(0) // Remove stray pulses\n        //}\n\n        // Attempt to find a matching modulation\n        //console.log(`${pulses.length} ${gaps.length} ${periods.length}`)\n        if (this.pulses.length == 1) {\n            return {\n                name: 'Single pulse detected. Probably Frequency Shift Keying or just noise...',\n            }\n        }\n        else if (pulses.length == 1 && gaps.length == 1) {\n            return {\n                name: 'Un-modulated signal. Maybe a preamble...',\n            }\n        }\n        else if (pulses.length == 1 && gaps.length > 1) {\n            return {\n                name: 'Pulse Position Modulation with fixed pulse width',\n                modulation: 'PPM',\n                short: gaps.bins[0].mean,\n                long: gaps.bins[1].mean,\n                gap: gaps.bins[1].max * 1.2, // Set limit above next lower gap\n                reset: gaps.bins[gaps.length - 1].max * 1.2, // Set limit above biggest gap\n            }\n        }\n        else if (pulses.length == 2 && gaps.length == 1) {\n            const short = pulses.bins[0].mean\n            const long = pulses.bins[1].mean\n            return {\n                name: 'Pulse Width Modulation with fixed gap',\n                modulation: 'PWM',\n                short: short,\n                long: long,\n                tolerance: (long - short) * 0.4,\n                reset: gaps.bins[gaps.length - 1].max * 1.2, // Set limit above biggest gap\n            }\n        }\n        else if (pulses.length == 2 && gaps.length == 2 && periods.length == 1) {\n            const short = pulses.bins[0].mean\n            const long = pulses.bins[1].mean\n            return {\n                name: 'Pulse Width Modulation with fixed period',\n                modulation: 'PWM',\n                short: short,\n                long: long,\n                tolerance: (long - short) * 0.4,\n                reset: gaps.bins[gaps.length - 1].max * 1.2, // Set limit above biggest gap\n            }\n        }\n        else if (pulses.length == 2 && gaps.length == 2 && periods.length == 3) {\n            const short = pulses.bins[0].mean\n            return {\n                name: 'Manchester coding (PCM)',\n                modulation: 'MC',\n                short: short, // Assume shortest pulse is half period\n                long: short, // Not used\n                reset: gaps.bins[gaps.length - 1].max * 1.2, // Set limit above biggest gap\n            }\n        }\n        else if (pulses.length == 2 && gaps.length >= 3) {\n            const short = pulses.bins[0].mean\n            const long = pulses.bins[1].mean\n            return {\n                name: 'Pulse Width Modulation with multiple packets',\n                modulation: 'PWM',\n                short: short,\n                long: long,\n                gap: gaps.bins[1].max * 1.2, // Set limit above second gap\n                tolerance: (long - short) * 0.4,\n                reset: gaps.bins[gaps.length - 1].max * 1.2, // Set limit above biggest gap\n            }\n        }\n        else if ((pulses.length >= 3 && gaps.length >= 3)\n            && (Math.abs(pulses.bins[1].mean - 2 * pulses.bins[0].mean) <= pulses.bins[0].mean / 8) // Pulses are multiples of shortest pulse\n            && (Math.abs(pulses.bins[2].mean - 3 * pulses.bins[0].mean) <= pulses.bins[0].mean / 8)\n            && (Math.abs(gaps.bins[0].mean - pulses.bins[0].mean) <= pulses.bins[0].mean / 8) // Gaps are multiples of shortest pulse\n            && (Math.abs(gaps.bins[1].mean - 2 * pulses.bins[0].mean) <= pulses.bins[0].mean / 8)\n            && (Math.abs(gaps.bins[2].mean - 3 * pulses.bins[0].mean) <= pulses.bins[0].mean / 8)) {\n            return {\n                name: 'Pulse Code Modulation (Not Return to Zero)',\n                modulation: 'PCM',\n                short: pulses.bins[0].mean, // Shortest pulse is bit width\n                long: pulses.bins[0].mean, // Bit period equal to pulse length (NRZ)\n                reset: pulses.bins[0].mean * 1024, // No limit to run of zeros...\n            }\n        }\n        else if (pulses.length == 3) {\n            // Re-sort to find lowest pulse count index (is probably delimiter)\n            pulses.sort_count()\n            const p1 = pulses.bins[1].mean\n            const p2 = pulses.bins[2].mean\n            const short = p1 < p2 ? p1 : p2 // Set to shorter pulse width\n            const long = p1 < p2 ? p2 : p1 // Set to longer pulse width\n            return {\n                name: 'Pulse Width Modulation with sync/delimiter',\n                modulation: 'PWM',\n                short: short,\n                long: long,\n                sync: pulses.bins[0].mean, // Set to lowest count pulse width\n                reset: gaps.bins[gaps.length - 1].max * 1.2, // Set limit above biggest gap\n            }\n        }\n        else {\n            return {\n                name: 'No clue...',\n            }\n        }\n    }\n\n    create_rfraw(data) {\n        const timings = this.hist_timings\n\n        if (timings.bins.length < 1) {\n            return ''\n        }\n        if (timings.bins.length > 8) {\n            return ''\n        }\n        if (data.length > 494) {\n            return ''\n        }\n\n        let raw = new Hexbuffer()\n\n        for (let b of timings.bins) {\n            raw.pushWord(b.mean)\n        }\n\n        for (let j = 0; j < data.length - 1; j += 2) {\n            const m = data[j] // mark\n            const s = data[j + 1] // space\n\n            const mi = timings.find_bin_index(m)\n            if (mi >= 0) {\n                raw.pushNibble(mi | 8)\n            } else if (m == 0) {\n                // skip 0-length, otherwise error on invalid bucket index\n            } else {\n                console.error('RfRaw encoding mark bucket not found:', m, mi);\n            }\n\n            const si = timings.find_bin_index(s)\n            if (si >= 0) {\n                raw.pushNibble(si)\n            } else if (s == 0) {\n                // skip 0-length, otherwise error on invalid bucket index\n            } else {\n                console.error('RfRaw encoding space bucket not found:', s, si);\n            }\n        }\n        // Pad buffer to full bytes by adding some space if needed\n        if (raw.line.length % 2) {\n            raw.pushNibble(0)\n        }\n\n        raw.pushByte(0x55)\n\n        let raw0 = new Hexbuffer()\n        raw0.pushByte(0xaa)\n        raw0.pushByte(0xb0)\n        raw0.pushByte(2 + raw.line.length / 2 - 1)\n        raw0.pushByte(timings.bins.length)\n        raw0.pushByte(1) // repeats\n\n        let raw1 = new Hexbuffer()\n        raw1.pushByte(0xaa)\n        raw1.pushByte(0xb1)\n        raw1.pushByte(timings.bins.length)\n\n        this.rfrawB0 = raw0.line + raw.line\n        this.rfrawB1 = raw1.line + raw.line\n    }\n\n    console_log() {\n        const guess = this.guess()\n        console.log('Analyzing pulses...')\n        console.log(`Total count: ${this.pulses.length}`)\n        console.log('Pulse width distribution:')\n        this.hist_pulses.console_print()\n        console.log('Gap width distribution:')\n        this.hist_gaps.console_print()\n        console.log('Pulse period distribution:')\n        this.hist_periods.console_print()\n        console.log('Pulse timing distribution:')\n        this.hist_timings.console_print()\n        console.log(`DC bias (Pulse/Gap skew): ${(this.pulse_gap_skew * 100).toFixed(1)}`)\n        console.log('Guessing modulation:')\n        console.log(guess)\n    }\n\n    print_plain(messages) {\n        const guess = this.guess()\n        messages.innerHTML = `\n        <div>Pulses: ${this.hist_pulses.string_print()}</div>\n        <div>Gaps: ${this.hist_gaps.string_print()}</div>\n        <div>Periods: ${this.hist_periods.string_print()}</div>\n        <div>Timings: ${this.hist_timings.string_print()}</div>\n        <div>${guess.name}</div>\n        `\n    }\n\n/*\nconst locale = new Intl.NumberFormat().resolvedOptions().locale\nconst formatter = new Intl.NumberFormat(locale, {\n    style: 'percent',\n    signDisplay: 'exceptZero',\n    maximumFractionDigits: 1,\n})\nformatter.format(0.5)\n*/\n    print(timings, messages) {\n        const guess = this.guess()\n        if (timings) {\n            timings.innerHTML = `<table>\n            <tr><th>Pulses</th><td>${this.hist_pulses.string_print('</td><td>')}</td></tr>\n            <tr><th>Gaps</th><td>${this.hist_gaps.string_print('</td><td>')}</td></tr>\n            <tr><th>Periods</th><td>${this.hist_periods.string_print('</td><td>')}</td></tr>\n            <tr><th>Timings</th><td>${this.hist_timings.string_print('</td><td>')}</td></tr>\n            </table>\n            `\n        }\n        if (messages) {\n            messages.innerHTML = `\n            <div><small>DC bias (Pulse/Gap skew): ${(this.pulse_gap_skew * 100).toFixed(1)}%</small><br>\n            Guessing modulation: <strong>${guess.name}</strong><br>\n            modulation: <strong>${guess.modulation}</strong>\n            short: <strong>${guess.short ? guess.short.toFixed(1) : '-'}</strong>\n            long: <strong>${guess.long ? guess.long.toFixed(1) : '-'}</strong>\n            sync: <strong>${guess.sync ? guess.sync.toFixed(1) : '-'}</strong>\n            gap: <strong>${guess.gap ? guess.gap.toFixed(1) : '-'}</strong>\n            reset: <strong>${guess.reset ? guess.reset.toFixed(1) : '-'}</strong><br>\n            <small>RfRaw (rx): <strong>${this.rfrawB1 ? this.rfrawB1 : '-'}</strong></small><br>\n            <small>RfRaw (tx): <strong>${this.rfrawB0 ? this.rfrawB0 : '-'}</strong></small>\n            </div>\n            `\n        }\n    }\n}\n","/**\n    @file Bitbuffer JS.\n\n    @author Christian W. Zuckschwerdt <zany@triq.net>\n    @copyright Christian W. Zuckschwerdt, 2020\n    @license\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 2 of the License, or\n    (at your option) any later version.\n*/\n\n//function dec2hex(i) {\n//    return (i + 0x100).toString(16).substr(-2).toUpperCase()\n//}\n\nexport class Bitbuffer {\n    constructor(bytes = [], len = 0) {\n        if (Array.isArray(bytes)) {\n            this.bytes = bytes\n            this.len = len || bytes.length * 8\n        } else {\n            this.fromString(bytes)\n        }\n    }\n    fromString(s) {\n        this.bytes = []\n        this.len = 0\n        let len = -1\n        s = s.trim()\n        // parse length\n        if (s.startsWith('{')) {\n            const end = s.indexOf('}')\n            if (end < 0) return\n            len = parseInt(s.slice(1), 10)\n            s = s.slice(end + 1)\n        }\n        // skip 0x prefix\n        if (s.startsWith('0x')) {\n            s = s.slice(2)\n        }\n        // parse nibbles\n        for (let c of s) {\n            const n = parseInt(c, 16)\n            this.pushNibble(n)\n        }\n        // set length if given\n        if (len >= 0)\n            this.len = len\n    }\n    pushZero() {\n        this.push(0)\n    }\n    pushOne() {\n        this.push(1)\n    }\n    pushSymbol(s) {\n        if (s == '0')\n            this.push(0)\n        else if (s == '1')\n            this.push(1)\n    }\n    push(bit) {\n        bit = bit ? 0x80 : 0\n        this.bytes[~~(this.len / 8)] |= bit >> (this.len % 8)\n        this.len += 1\n    }\n    pushNibble(n) {\n        for (let j = 3; j >= 0; --j) {\n            this.push((n >> j) & 1)\n        }\n    }\n    pushByte(n) {\n        for (let j = 7; j >= 0; --j) {\n            this.push((n >> j) & 1)\n        }\n    }\n    pushBreak() {\n        const b = ~~((this.len + 7) / 8)\n        this.bytes[b] = -1\n        this.len = (b + 1) * 8\n    }\n    toBitArray() {\n        let bits = []\n        for (let j = 0; j < this.len; ++j) {\n            const byte = this.bytes[~~(j / 8)] || 0\n            const bit = (byte >> (7 - (j % 8))) & 1\n            bits.push(bit)\n        }\n        return bits\n    }\n    toHexString() {\n        let s = `{${this.len}}`\n        for (let j = 0; j < this.len; j += 8) {\n            const b = this.bytes[~~(j / 8)] || 0\n            if (b < 0) {\n                s += ' / '\n            } else {\n                s += ' '\n                s += (b >> 4).toString(16).toUpperCase()\n                if (j + 4 < this.len)\n                    s += (b & 0xf).toString(16).toUpperCase()\n            }\n        }\n        return s\n    }\n}\n","/**\n    @file Pulse Slicer JS.\n\n    @author Christian W. Zuckschwerdt <zany@triq.net>\n    @copyright Christian W. Zuckschwerdt, 2020\n    @license\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 2 of the License, or\n    (at your option) any later version.\n*/\n\nimport { Bitbuffer } from './bitbuffer.js'\n\nexport function sliceGuess(pulses, guess) {\n    if (guess.modulation == 'PCM')\n        return slicePCM(pulses, guess)\n\n    else if (guess.modulation == 'MC')\n        return sliceMC(pulses, guess)\n\n    else if (guess.modulation == 'PPM')\n        return slicePPM(pulses, guess)\n\n    else if (guess.modulation == 'PWM')\n        return slicePWM(pulses, guess)\n\n    else if (guess.modulation == 'DM')\n        return sliceDM(pulses, guess)\n\n    else if (guess.modulation == 'NRZI')\n        return sliceNRZI(pulses, guess)\n\n    else if (guess.modulation == 'CMI')\n        return sliceCMI(pulses, guess)\n\n    else if (guess.modulation == 'PIWM')\n        return slicePIWM(pulses, guess)\n\n    else\n        return []\n}\n\n// returned hints array contains triples of start,end,symbol\n\n/// Pulse-code modulation (PCM)\n/// https://en.wikipedia.org/wiki/Pulse-code_modulation\n/// either NRZ or RZ\nexport function slicePCM(pulses, guess) {\n    if (!guess.long || guess.long == guess.short) {\n        return sliceNRZ(pulses, guess)\n    } else {\n        return sliceRZ(pulses, guess)\n    }\n}\n\n/// NRZ(L) NRZL Non-return-to-zero level\n/// https://en.wikipedia.org/wiki/Non-return-to-zero\nexport function sliceNRZ(pulses, guess) {\n    const short = guess.short\n    const gap = guess.gap\n\n    const bits = new Bitbuffer()\n    let hints = []\n\n    let x = 0\n    for (let j = 0; j < pulses.length; j += 1) {\n        const symbol = 1 - j % 2 // even: 1, odd: 0\n        const w = pulses[j] // mark or space\n        if (gap && w > gap) {\n            bits.pushBreak()\n        } else {\n            const cnt = ~~(w / short + 0.5)\n            for (let k = 0; k < cnt; ++k) {\n                hints.push([x + w / cnt * k, x + w / cnt * (k + 1), symbol])\n                bits.push(symbol)\n            }\n        }\n        x += w\n    }\n\n    return { hints, bits }\n}\n\n/// Return-to-zero level\n/// https://en.wikipedia.org/wiki/Return-to-zero\nexport function sliceRZ(pulses, guess) {\n    const short = guess.short\n    const long = guess.long\n    const gap = guess.gap\n\n    const shortl = short * 0.5\n    const shortu = short * 1.5\n\n    const bits = new Bitbuffer()\n    let hints = []\n\n    let x = 0\n    for (let j = 0; j < pulses.length; j += 2) {\n        const m = pulses[j] // mark\n        const s = pulses[j + 1] // space\n        if (m < shortl || m > shortu) {\n            bits.pushBreak()\n            x += m + s\n            continue\n        }\n        let onew = m * long / short // estimate the 1-bit width\n        let zs = s + m - onew // estimate 0-bits width\n        if (zs < long / 2) {\n            onew = m + s // no 0-bits\n            zs = 0\n        }\n        hints.push([x, x + onew, '1'])\n        bits.pushOne()\n        x += onew\n        if (gap && s > gap) {\n            bits.pushBreak()\n            x += zs\n            continue\n        }\n        const cnt = ~~(zs / long + 0.5)\n        for (let k = 0; k < cnt; ++k) {\n            hints.push([x + zs * k / cnt, x + zs * (k + 1) / cnt, '0'])\n            bits.pushZero()\n        }\n        x += zs\n    }\n\n    return { hints, bits }\n}\n\n/// Pulse-position modulation (PPM)\n/// https://en.wikipedia.org/wiki/Pulse-position_modulation\nexport function slicePPM(pulses, guess) {\n    const short = guess.short\n    const long = guess.long\n    const sync = guess.sync\n    const gap = guess.gap\n\n    const shortl = short * 0.5\n    const shortu = short * 1.5\n    const longl = long * 0.5\n    const longu = long * 1.5\n    const syncl = sync * 0.5\n    const syncu = sync * 1.5\n\n    const bits = new Bitbuffer()\n    let hints = []\n\n    let x = 0\n    for (let j = 0; j < pulses.length; j += 2) {\n        const m = pulses[j] // mark\n        const s = pulses[j + 1] // space\n        const x0 = x\n        x += m + s\n        if (s > shortl && s < shortu) {\n            hints.push([x0, x, '1'])\n            bits.pushOne()\n        } else if (s > longl && s < longu) {\n            hints.push([x0, x, '0'])\n            bits.pushZero()\n        } else if (s > syncl && s < syncu) {\n            hints.push([x0, x, 'X'])\n            bits.pushBreak()\n        } else if (gap && s > gap) {\n            bits.pushBreak()\n        }\n    }\n\n    return { hints, bits }\n}\n\n/// Pulse-width modulation (PWM)\n/// https://en.wikipedia.org/wiki/Pulse-width_modulation\nexport function slicePWM(pulses, guess) {\n    const short = guess.short\n    const long = guess.long\n    const sync = guess.sync\n    const gap = guess.gap\n\n    const shortl = short * 0.5\n    const shortu = short * 1.5\n    const longl = long * 0.5\n    const longu = long * 1.5\n    const syncl = sync * 0.5\n    const syncu = sync * 1.5\n\n    const bits = new Bitbuffer()\n    let hints = []\n\n    let x = 0\n    for (let j = 0; j < pulses.length; j += 2) {\n        const m = pulses[j] // mark\n        const s = pulses[j + 1] // space\n\n        const x0 = x\n        let x1 = x + m + s\n        // break on gaps\n        if (s > gap)\n            x1 = x + m + gap\n        x += m + s\n\n        if (m > shortl && m < shortu) {\n            hints.push([x0, x1, '1'])\n            bits.pushOne()\n        } else if (m > longl && m < longu) {\n            hints.push([x0, x1, '0'])\n            bits.pushZero()\n        } else if (m > syncl && m < syncu) {\n            hints.push([x0, x1, 'X'])\n            bits.pushBreak()\n        }\n        if (gap && s > gap) {\n            bits.pushBreak()\n        }\n    }\n\n    return { hints, bits }\n}\n\n/// get Manchester alignment, 1 if we are at the start of a bit, 0 if we are in the middle\nfunction manchesterAligned(pulses, offset, short) {\n    for (let j = offset; j < pulses.length; j += 2) {\n        const mw = pulses[j] // mark\n        const cw = ~~(mw / short + 0.5)\n        if (cw > 1) return 0 // middle\n        const sw = pulses[j + 1] // space\n        const sc = ~~(sw / short + 0.5)\n        if (sc > 1) return 1 // start\n    }\n    // warning, no alignment found\n    return 0\n}\n\n/// Manchester code (MC)\n/// https://en.wikipedia.org/wiki/Manchester_code\nexport function sliceMC(pulses, guess) {\n    const short = guess.short\n    const bits = new Bitbuffer()\n    let hints = []\n\n    // Manchester align string by finding the position of the first long pulse or gap\n    let aligned = manchesterAligned(pulses, 0, short)\n\n    let x = 0\n    let x1 = 0\n    for (let j = 0; j < pulses.length; j += 2) {\n        const mark = pulses[j] // mark\n        const mcnt = ~~(mark / short + 0.5)\n        const space = pulses[j + 1] // space\n        const scnt = ~~(space / short + 0.5)\n\n        if (mcnt == 1) {\n            if (!aligned) {\n                hints.push([x1, x + mark, '0'])\n                bits.pushZero()\n                x1 = x + mark\n            }\n            else { // aligned\n                x1 = x\n            }\n            aligned = !aligned\n        }\n        else if (mcnt == 2) {\n            if (!aligned) {\n                hints.push([x1, x + mark / 2, '0'])\n                bits.pushZero()\n                x1 = x + mark / 2\n            }\n            else { // aligned\n                // error\n                bits.pushBreak()\n                x1 = x + mark / 2\n            }\n            aligned = false\n        }\n        else if (mcnt > 2) {\n            if (!aligned) {\n                hints.push([x1, x + mark / mcnt, '0'])\n                bits.pushZero()\n                x1 = x + mark - mark / mcnt\n            }\n            else { // aligned\n                // error\n                x1 = x + mark - mark / mcnt\n            }\n            bits.pushBreak()\n            aligned = manchesterAligned(pulses, j + 1, short)\n        }\n\n        if (scnt == 1) {\n            if (!aligned) {\n                hints.push([x1, x + mark + space, '1'])\n                bits.pushOne()\n                x1 = x + mark + space\n            }\n            else { // aligned\n                x1 = x + mark\n            }\n            aligned = !aligned\n        }\n        else if (scnt == 2) {\n            if (!aligned) {\n                hints.push([x1, x + mark + space / 2, '1'])\n                bits.pushOne()\n                x1 = x + mark + space / 2\n            }\n            else { // aligned\n                // error\n                bits.pushBreak()\n                x1 = x + mark + space / 2\n            }\n            aligned = false\n        }\n        else if (scnt > 2) {\n            if (!aligned) {\n                hints.push([x1, x + mark + space / scnt, '1'])\n                bits.pushOne()\n                x1 = x + mark + space - space / scnt\n            }\n            else { // aligned\n                // error\n                x1 = x + mark + space - space / scnt\n            }\n            bits.pushBreak()\n            aligned = manchesterAligned(pulses, j + 1, short)\n        }\n\n        x += mark + space\n    }\n\n    return { hints, bits }\n}\n\n/// Differential Manchester Encoding (DM) aka Biphase Mark Code (CC)\n/// https://en.wikipedia.org/wiki/Differential_Manchester_encoding\nexport function sliceDM(pulses, guess) {\n    const short = guess.short\n    const bits = new Bitbuffer()\n    let hints = []\n\n    let x = 0\n    let x1 = null\n    for (let j = 0; j < pulses.length; j += 2) {\n        const mark = pulses[j] // mark\n        const mcnt = ~~(mark / short + 0.5)\n        const space = pulses[j + 1] // space\n        const scnt = ~~(space / short + 0.5)\n\n        if (!x1 && mcnt == 1 && scnt == 1) {\n            hints.push([x, x + mark + space, '0'])\n            bits.pushZero()\n        }\n        else if (mcnt == 1 && scnt == 1) {\n            hints.push([x1, x + mark, '0'])\n            bits.pushZero()\n            x1 = x + mark\n        }\n        else if (x1 && mcnt == 1 && scnt == 2) {\n            hints.push([x1, x + mark, '0'])\n            bits.pushZero()\n            hints.push([x + mark, x + mark + space, '1'])\n            bits.pushOne()\n            x1 = null\n        }\n        else if (mcnt == 2 && scnt == 1) {\n            hints.push([x, x + mark, '1'])\n            bits.pushOne()\n            x1 = x + mark\n        }\n        else if (mcnt == 2 && scnt == 2) {\n            hints.push([x, x + mark, '1'])\n            bits.pushOne()\n            hints.push([x + mark, x + mark + space, '1'])\n            bits.pushOne()\n        }\n        else if (!x1 && mcnt == 1) {\n            // error\n            hints.push([x, x + mark + short, '0'])\n            bits.pushZero()\n            bits.pushBreak()\n        }\n        else if (!x1 && mcnt == 2) {\n            // error\n            hints.push([x, x + mark, '1'])\n            bits.pushOne()\n            bits.pushBreak()\n        }\n        else {\n            // error (!x1 && mcnt == 1 && scnt == 2)\n            if (x1) {\n                hints.push([x1, x1 + short * 2, '0'])\n                bits.pushZero()\n            }\n            x1 = null\n            bits.pushBreak()\n        }\n        x += mark + space\n    }\n\n    return { hints, bits }\n}\n\n/// Non-return-to-zero, inverted (NRZI) https://en.wikipedia.org/wiki/Non-return-to-zero#NRZI\n/// NRZ(I) \tNRZI \tNon-return-to-zero inverted \tRefers to either an NRZ(M) or NRZ(S) code.\n/// NRZ(M) \tNRZM \tNon-return-to-zero mark \tSerializer mapping {0: constant, 1: toggle}.\n/// NRZ(S) \tNRZS \tNon-return-to-zero space \tSerializer mapping {0: toggle, 1: constant}.\n/// A 1 is transmitted as a transition, and a 0 is transmitted as no transition.\nexport function sliceNRZI(pulses, guess) {\n    const short = guess.short\n    const bits = new Bitbuffer()\n    let hints = []\n\n    let x = 0\n    let x1 = 0\n    for (let j = 0; j < pulses.length; j += 1) {\n        const w = pulses[j] // mark or space\n        const cnt = ~~(w / short + 0.5)\n        // every edge is a 1, don't use the first edge\n        if (x1) {\n            hints.push([x1, x + short / 2, '1'])\n            bits.pushOne()\n        }\n        x1 = x + short / 2\n        // count minus one amounts of 0\n        for (let k = 1; k < cnt; ++k) {\n            hints.push([x1, x1 + w / cnt, '0'])\n            bits.pushZero()\n            x1 += w / cnt\n\n        }\n        x += w\n    }\n\n    return { hints, bits }\n}\n\n/// Coded Mark Inversion (CMI) https://en.wikipedia.org/wiki/Coded_mark_inversion\n/// encodes zero bits as a half bit time of zero followed by a half bit time of one,\n/// and one bits are encoded as a full bit time of a constant level,\n/// the level used for one bits alternates each time one is coded.\nexport function sliceCMI(pulses, guess) {\n    const short = guess.short\n    const bits = new Bitbuffer()\n    let hints = []\n\n    let x = 0\n    let x1 = null\n    for (let j = 0; j < pulses.length; j += 2) {\n        const mark = pulses[j] // mark\n        const mcnt = ~~(mark / short + 0.5)\n        const space = pulses[j + 1] // space\n        const scnt = ~~(space / short + 0.5)\n\n        if (mcnt == 1 && scnt == 1) {\n            if (!x1) x1 = x - mark // first bit\n            hints.push([x1, x + mark, '0'])\n            bits.pushZero()\n            x1 = x + mark\n        }\n        else if (mcnt == 1 && scnt == 2) {\n            if (!x1) x1 = x - mark // first bit\n            hints.push([x1, x + mark, '0'])\n            bits.pushZero()\n            x1 = x + mark + space\n            hints.push([x + mark, x1, '1'])\n            bits.pushOne()\n        }\n        else if (mcnt == 1 && scnt == 3) {\n            if (!x1) x1 = x - mark // first bit\n            hints.push([x1, x + mark, '0'])\n            bits.pushZero()\n            x1 = x + mark + space * 2 / 3\n            hints.push([x + mark, x1, '1'])\n            bits.pushOne()\n        }\n        else if (mcnt == 2 && scnt == 1) {\n            hints.push([x1, x + mark, '1'])\n            bits.pushOne()\n            x1 = x + mark\n        }\n        else if (mcnt == 2 && scnt == 2) {\n            hints.push([x1, x + mark, '1'])\n            bits.pushOne()\n            x1 = x + mark + space\n            hints.push([x + mark, x1, '1'])\n            bits.pushOne()\n        }\n        else if (mcnt == 2 && scnt == 3) {\n            hints.push([x1, x + mark, '1'])\n            bits.pushOne()\n            x1 = x + mark + space * 2 / 3\n            hints.push([x + mark, x1, '1'])\n            bits.pushOne()\n        }\n        else if (mcnt == 3 && scnt == 1) {\n            hints.push([x1, x + mark / 3, '0'])\n            bits.pushZero()\n            hints.push([x + mark / 3, x + mark, '1'])\n            bits.pushOne()\n            x1 = x + mark\n        }\n        else if (mcnt == 3 && scnt == 2) {\n            hints.push([x1, x + mark / 3, '0'])\n            bits.pushZero()\n            hints.push([x + mark / 3, x + mark, '1'])\n            bits.pushOne()\n            x1 = x + mark + space\n            hints.push([x + mark, x1, '1'])\n            bits.pushOne()\n        }\n        else if (mcnt == 3 && scnt == 3) {\n            hints.push([x1, x + mark / 3, '0'])\n            bits.pushZero()\n            hints.push([x, x + mark / 3, '1'])\n            bits.pushOne()\n            hints.push([x + mark / 3, x + mark, '1'])\n            bits.pushOne()\n            hints.push([x + mark, x + mark + space * 3 / 2, '1'])\n            bits.pushOne()\n            x1 = x + mark + space * 3 / 2\n        }\n        else if (mcnt == 1) { // last zero\n            hints.push([x1, x + mark, '0'])\n            bits.pushZero()\n            bits.pushBreak()\n            x1 = x + mark\n        }\n        else if (mcnt == 2) { // last one\n            hints.push([x1, x + mark, '1'])\n            bits.pushOne()\n            bits.pushBreak()\n            x1 = x + mark\n        }\n        else {\n            // error\n            bits.pushBreak()\n        }\n        x += mark + space\n    }\n\n    return { hints, bits }\n}\n\n/// Pulse-Interval-Width Modulation (PIWM)\n/// Exotic differential coding\nexport function slicePIWM(pulses, guess) {\n    const short = guess.short\n    const bits = new Bitbuffer()\n    let hints = []\n\n    let x = 0\n    for (let j = 0; j < pulses.length; j += 1) {\n        const w = pulses[j] // mark or space\n        const cnt = ~~(w / short + 0.5)\n\n        if (cnt == 1) {\n            hints.push([x, x + w, '1'])\n            bits.pushOne()\n        }\n        else if (cnt == 2) {\n            hints.push([x, x + w, '0'])\n            bits.pushZero()\n        } else {\n            // error\n            bits.pushBreak()\n        }\n        x += w\n    }\n\n    return { hints, bits }\n}\n","/**\n    @file Pulse Builder JS.\n\n    @author Christian W. Zuckschwerdt <zany@triq.net>\n    @copyright Christian W. Zuckschwerdt, 2020\n    @license\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 2 of the License, or\n    (at your option) any later version.\n*/\n\n/*eslint no-console: \"off\"*/\n\nimport { Bitbuffer } from './bitbuffer.js'\n\nfunction parsePulseString(pulseStr) {\n    if (Array.isArray(pulseStr)) {\n        return pulseStr\n    }\n    let pulses = pulseStr.split(/\\D/).map(x => parseInt(x, 10))\n    return pulses\n}\n\nexport class PulseBuilder {\n    constructor(args) {\n        Object.assign(this, args)\n        this.build()\n    }\n\n    build() {\n        this.pulses = []\n        // warmup\n        if (this.warmup_raw) {\n            this.addRaw(this, this.warmup_raw)\n        }\n        const repeat = this.repeat || 1\n        for (let j = 0; j < repeat; ++j) {\n            // packet gap\n            if (this.gap && j > 0) {\n                this.pulses.push(0) // mark\n                this.pulses.push(this.gap) // space\n            }\n            // preamble\n            if (this.preamble) {\n                const bits = new Bitbuffer(this.preamble)\n                this.addCode(this, bits)\n            }\n            if (this.preamble_raw) {\n                this.addRaw(this, this.preamble_raw)\n            }\n            // sync raw\n            if (this.sync_raw) {\n                this.addRaw(this, this.sync_raw)\n            }\n            // syncword\n            if (this.syncword) {\n                const bits = new Bitbuffer(this.syncword)\n                this.addCode(this, bits)\n            }\n            // payload\n            const bits = new Bitbuffer(this.payload)\n            this.addCode(this, bits)\n            // postamble\n            if (this.postamble) {\n                const bits = new Bitbuffer(this.postamble)\n                this.addCode(this, bits)\n            }\n            if (this.postamble_raw) {\n                this.addRaw(this, this.postamble_raw)\n            }\n        }\n        this.coalesce()\n\n        // jitter\n        if (this.jitter) {\n            this.addJitter(this)\n        }\n        return this\n    }\n\n    addCode(arg, bits) {\n        if (arg.modulation == 'PCM')\n            this.buildPCM(arg, bits)\n        else if (arg.modulation == 'MC')\n            this.buildMC(arg, bits)\n        else if (arg.modulation == 'PPM')\n            this.buildPPM(arg, bits)\n        else if (arg.modulation == 'PWM')\n            this.buildPWM(arg, bits)\n        else if (arg.modulation == 'DM')\n            this.buildDM(arg, bits)\n        else if (arg.modulation == 'NRZI')\n            this.buildNRZI(arg, bits)\n        else if (arg.modulation == 'CMI')\n            this.buildCMI(arg, bits)\n        else if (arg.modulation == 'PIWM')\n            this.buildPIWM(arg, bits)\n        else\n            console.log('Unknown modulation!')\n        return arg\n    }\n\n    addRaw(arg, pulses) {\n        pulses = parsePulseString(pulses)\n        // ensure even (mark/space) count\n        if (pulses.length % 2)\n            pulses.push(0)\n        arg.pulses = arg.pulses.concat(pulses)\n        return arg\n    }\n\n    coalesce() {\n        let pulses = []\n\n        let pulse = 0\n        for (let j = 0; j < this.pulses.length; j += 2) {\n            const m = this.pulses[j] || 0 // mark\n            const s = this.pulses[j + 1] || 0 // space\n            if (!m && !s) {\n                // skip nulls\n            }\n            else if (!pulse && !m && pulses.length) {\n                // no pulse, append to last\n                pulses[pulses.length - 1] += ~~s\n            }\n            else if (!s) {\n                // no space, buffer\n                pulse += m\n            }\n            else {\n                pulses.push(~~(m + pulse))\n                pulses.push(~~(s))\n                pulse = 0\n            }\n        }\n        // flush buffered pulse\n        if (pulse) {\n            pulses.push(~~pulse)\n            pulses.push(0)\n        }\n\n        this.pulses = pulses\n        return this\n    }\n\n    addJitter(arg) {\n        const jitter = arg.jitter\n        let pulses = []\n\n        for (let j = 0; j < arg.pulses.length; ++j) {\n            const w = arg.pulses[j] // mark or space\n            if (w == 0) {\n                pulses.push(w) // keep empty pulses\n            } else if (jitter < 1) {\n                // relative jitter\n                const s = Math.random() * 2 * jitter + 1 - jitter\n                pulses.push(~~(w * s))\n            } else {\n                // absolute jitter\n                const s = Math.random() * 2 * jitter - jitter\n                pulses.push(~~(w + s))\n            }\n        }\n\n        arg.pulses = pulses\n        return arg\n    }\n\n    // returned hints array contains triples of start,end,symbol\n\n    /// Pulse-code modulation (PCM)\n    /// https://en.wikipedia.org/wiki/Pulse-code_modulation\n    /// either NRZ or RZ\n    buildPCM(arg, bits) {\n        if (!arg.long || arg.long == arg.short) {\n            return this.buildNRZ(arg, bits)\n        } else {\n            return this.buildRZ(arg, bits)\n        }\n    }\n\n\n    /// NRZ(L) NRZL Non-return-to-zero level\n    /// https://en.wikipedia.org/wiki/Non-return-to-zero\n    buildNRZ(arg, bits) {\n        // TODO: wip\n        const short = arg.short\n        let pulses = arg.pulses\n\n        const bit = bits.toBitArray()\n        for (let j = 0; j < bit.length; ++j) {\n            if (bit[j]) {\n                pulses.push(short)\n                pulses.push(0)\n            }\n            else {\n                pulses.push(0)\n                pulses.push(short)\n            }\n        }\n\n        return arg\n    }\n\n    /// Return-to-zero level\n    /// https://en.wikipedia.org/wiki/Return-to-zero\n    buildRZ(arg, bits) {\n        // TODO: wip\n        const short = arg.short\n        const long = arg.long\n        const short_gap = long - short\n        let pulses = arg.pulses\n\n        const bit = bits.toBitArray()\n        for (let j = 0; j < bit.length; ++j) {\n            if (bit[j]) {\n                pulses.push(short)\n                pulses.push(short_gap)\n            }\n            else {\n                pulses.push(0)\n                pulses.push(long)\n            }\n        }\n\n        return arg\n    }\n\n    /// Pulse-position modulation (PPM)\n    /// https://en.wikipedia.org/wiki/Pulse-position_modulation\n    buildPPM(arg, bits) {\n        const pulse = arg.pulse || ~~(arg.short / 3)\n        const short = arg.short\n        const long = arg.long\n\n        let pulses = arg.pulses\n\n        const bit = bits.toBitArray()\n        for (let j = 0; j < bit.length; ++j) {\n            pulses.push(pulse) // mark\n            if (bit[j]) {\n                pulses.push(short) // space\n            } else {\n                pulses.push(long) // space\n            }\n        }\n\n        return arg\n    }\n\n    /// Pulse-width modulation (PWM)\n    /// https://en.wikipedia.org/wiki/Pulse-width_modulation\n    buildPWM(arg, bits) {\n        const short = arg.short\n        const long = arg.long\n        const short_gap = arg.short_gap || arg.long\n        const long_gap = arg.long_gap || arg.short\n\n        let pulses = arg.pulses\n\n        const bit = bits.toBitArray()\n        for (let j = 0; j < bit.length; ++j) {\n            if (bit[j]) {\n                pulses.push(short) // mark\n                pulses.push(short_gap) // space\n            } else {\n                pulses.push(long) // mark\n                pulses.push(long_gap) // space\n            }\n        }\n\n        return arg\n    }\n\n    /// Manchester code (MC)\n    /// https://en.wikipedia.org/wiki/Manchester_code\n    buildMC(arg, bits) {\n        const short = arg.short\n        let pulses = arg.pulses\n\n        const bit = bits.toBitArray()\n        for (let j = 0; j < bit.length; ++j) {\n            if (bit[j]) {\n                pulses.push(short) // mark\n                pulses.push(short) // space\n            } else {\n                pulses.push(0) // mark\n                pulses.push(short) // space\n                pulses.push(short) // mark\n                pulses.push(0) // space\n            }\n        }\n\n        return arg\n    }\n\n    /// Differential Manchester Encoding (DM) aka Biphase Mark Code (CC)\n    /// https://en.wikipedia.org/wiki/Differential_Manchester_encoding\n    buildDM(arg, bits) {\n        const short = arg.short\n        let pulses = arg.pulses\n\n        const bit = bits.toBitArray()\n        let state = false\n        for (let j = 0; j < bit.length; ++j) {\n            const b = bit[j]\n            if (!b && !state) {\n                pulses.push(short) // mark\n                pulses.push(short) // space\n            } else if (!b && state) {\n                pulses.push(0) // mark\n                pulses.push(short) // space\n                pulses.push(short) // mark\n                pulses.push(0) // space\n            } else if (b && !state) {\n                pulses.push(short * 2) // mark\n                pulses.push(0) // space\n                state = !state\n            } else if (b && state) {\n                pulses.push(0) // mark\n                pulses.push(short * 2) // space\n                state = !state\n            }\n        }\n\n        return arg\n    }\n\n    /// Non-return-to-zero, inverted (NRZI) https://en.wikipedia.org/wiki/Non-return-to-zero#NRZI\n    /// NRZ(I) \tNRZI \tNon-return-to-zero inverted \tRefers to either an NRZ(M) or NRZ(S) code.\n    /// NRZ(M) \tNRZM \tNon-return-to-zero mark \tSerializer mapping {0: constant, 1: toggle}.\n    /// NRZ(S) \tNRZS \tNon-return-to-zero space \tSerializer mapping {0: toggle, 1: constant}.\n    /// A 1 is transmitted as a transition, and a 0 is transmitted as no transition.\n    buildNRZI(arg, bits) {\n        // TODO: wip\n        const short = arg.short\n        let pulses = arg.pulses\n\n        const bit = bits.toBitArray()\n        let state = !bit[0] // force an edge at start\n        for (let j = 0; j < bit.length; ++j) {\n            if (bit[j]) {\n                state = !state\n            }\n            if (state) {\n                pulses.push(short) // mark\n                pulses.push(0) // space\n            } else {\n                pulses.push(0) // mark\n                pulses.push(short) // space\n            }\n        }\n\n        return arg\n    }\n\n    /// Coded Mark Inversion (CMI) https://en.wikipedia.org/wiki/Coded_mark_inversion\n    /// encodes zero bits as a half bit time of zero followed by a half bit time of one,\n    /// and one bits are encoded as a full bit time of a constant level,\n    /// the level used for one bits alternates each time one is coded.\n    buildCMI(arg, bits) {\n        const short = arg.short\n        let pulses = arg.pulses\n\n        const bit = bits.toBitArray()\n        let state = false\n        for (let j = 0; j < bit.length; ++j) {\n            if (!bit[j]) {\n                pulses.push(0) // mark\n                pulses.push(short) // space\n                pulses.push(short) // mark\n                pulses.push(0) // space\n            } else if (!state) {\n                pulses.push(short * 2) // mark\n                pulses.push(0) // space\n                state = !state\n            } else { // if (state)\n                pulses.push(0) // mark\n                pulses.push(short * 2) // space\n                state = !state\n            }\n        }\n\n        return arg\n    }\n\n    /// Pulse-Interval-Width Modulation (PIWM)\n    /// Exotic differential coding\n    buildPIWM(arg, bits) {\n        const short = arg.short\n        let pulses = arg.pulses\n\n        const bit = bits.toBitArray()\n        for (let j = 0; j < bit.length; ++j) {\n            if (bit[j]) {\n                pulses.push(short) // mark or space\n            } else {\n                pulses.push(short * 2) // mark or space\n            }\n        }\n        // add a long trailing space if the bit count was uneven\n        if (bit.length % 2) {\n            pulses.push(short * 3) // space\n        }\n\n        return arg\n    }\n}","/**\n    @file RfRaw JS.\n\n    @author Christian W. Zuckschwerdt <zany@triq.net>\n    @copyright Christian W. Zuckschwerdt, 2020\n    @license\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 2 of the License, or\n    (at your option) any later version.\n*/\n\nimport { Hexbuffer } from './hexbuffer.js'\n\nexport class RfRaw {\n    static isRfRaw(line) {\n        return line.trim().startsWith('AA')\n    }\n    static getPulses(line) {\n        let pulses = []\n        // split codes on '+' or space between '55 AAB'\n        line = line.replace(/5\\s*5[+\\s]+A\\s*A\\s*B/g, '55;AAB')\n        const codes = line.split(';')\n        for (let code of codes) {\n            const p = RfRaw.getCodePulses(code)\n            pulses = pulses.concat(p)\n        }\n        return pulses\n    }\n    static getCodePulses(line) {\n        // AA B1 04 017C 046A 0BCC 2378 3818190908181908190909090908190819081818190909091A 55\n        console.log('parsing rfraw data: ', line)\n        let pulses = []\n        const buf = new Hexbuffer(line)\n\n        const sync = buf.getByte()\n        if (sync != 0xaa) {\n            return pulses\n        }\n\n        const fmt = buf.getByte()\n        let len\n        let buckets\n        let repeats\n        if (fmt == 0xb1) {\n            // s.a. https://github.com/Portisch/RF-Bridge-EFM8BB1/wiki/Decode-0xB1-sniffed-data\n            buckets = buf.getByte()\n        }\n        else if (fmt == 0xb0) {\n            // s.a. https://github.com/Portisch/RF-Bridge-EFM8BB1/wiki/0xB0\n            len = buf.getByte()\n            buckets = buf.getByte()\n            repeats = buf.getByte()\n        }\n        else {\n            return pulses\n        }\n\n        let bucket = []\n        for (let b = 0; b < buckets; ++b) {\n            bucket[b] = buf.getWord()\n        }\n        console.log(`buckets: ${buckets} (len ${len} repeats ${repeats}): `, bucket)\n        let v3format = false\n        const bufSafe = buf.index\n        while (buf.hasNibble()) {\n            const n = buf.getNibble()\n            if (n > 7) {\n                v3format = true\n                break\n            }\n        }\n        buf.index = bufSafe\n        console.log('RfRaw v3 format: ', v3format)\n\n        if (!v3format) {\n            pulses.push(0) // rfraw starts with a gap\n            while (buf.hasNibble()) {\n                if (buf.peekByte() == 0x55) break // sync end\n                const b = buf.getNibble()\n                if (b > buckets) break // error\n                pulses.push(bucket[b])\n            }\n            pulses.push(0) // rfraw ends with a pulse\n\n            if (repeats)\n                return new Array(repeats).fill(pulses).flat()\n            return pulses\n        }\n\n        let dataHigh = true\n        while (buf.hasNibble()) {\n            if (buf.peekByte() == 0x55) break // sync end\n            const n = buf.getNibble()\n            const b = n & 7\n            if (b > buckets) break // error\n            if (n & 8) {\n                if (!dataHigh)\n                    pulses.push(0)\n                pulses.push(bucket[b])\n                dataHigh = false\n            }\n            else {\n                if (dataHigh)\n                    pulses.push(0)\n                pulses.push(bucket[b])\n                dataHigh = true\n            }\n        }\n        if (!dataHigh)\n            pulses.push(0) // add last gap\n\n        if (repeats)\n            return new Array(repeats).fill(pulses).flat()\n        return pulses\n    }\n}\n","/**\n    @file BroadlinkRM JS.\n\n    @author Christian W. Zuckschwerdt <zany@triq.net>\n    @copyright Christian W. Zuckschwerdt, 2025\n    @license\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 2 of the License, or\n    (at your option) any later version.\n*/\n\nexport class BroadlinkRM {\n    static isBroadlinkRM(line) {\n        try {\n            bin = atob(line)\n        } catch (error) {\n            return false // Not base64\n        }\n\n        if (bin.length < 4) {\n            return false // Invalid data header\n        }\n\n        const codeType = bin.charCodeAt(0)\n        if (codeType == 0xb2 || codeType == 0xb1) {\n            return true // 433 MHz\n        } else if (codeType == 0xd7) {\n            return true // 315 MHz\n        } else if (codeType == 0x26) {\n            return false // IR code\n        } else {\n            return false // Unknown code type\n        }\n    }\n\n    static decodeData(line) {\n        let data = {\n            pulses: [],\n            frequency: 0,\n            repeats: 0,\n            errors: \"\",\n        }\n\n        let bin = \"\"\n        try {\n            bin = atob(line)\n        } catch (error) {\n            data.errors = 'Invalid Base64'\n            console.warn(data.errors)\n            return data\n        }\n\n        if (bin.length < 4) {\n            data.errors = 'Invalid data header'\n            console.warn(data.errors)\n            return data\n        }\n\n        const codeType = bin.charCodeAt(0)\n        if (codeType == 0xb2 || codeType == 0xb1) {\n            data.frequency = 433920000 // 433 MHz\n        } else if (codeType == 0xd7) {\n            data.frequency = 315000000 // 315 MHz\n        } else if (codeType == 0x26 /* IR code */) {\n            data.errors = 'Unsupported code type'\n            console.warn(data.errors, codeType)\n            return data\n        } else {\n            data.errors = `Invalid code type (${codeType.toString(16)})`\n            console.warn(data.errors, codeType)\n            return data\n        }\n\n        data.repeats = bin.charCodeAt(1)\n\n        let dataLen = bin.charCodeAt(2) | (bin.charCodeAt(3) << 8)  // big endian\n        if (dataLen + 2 != bin.length) {\n            data.errors = 'Code length mismatch'\n            console.warn(data.errors)\n        }\n\n        for (let i = 4; i < bin.length; i++) {\n            let pulse = bin.charCodeAt(i);\n            if (pulse == 0) {\n                pulse = bin.charCodeAt(++i) | (bin.charCodeAt(++i) << 8) // big endian\n            }\n            data.pulses.push(pulse)\n        }\n\n        return data\n    }\n}\n","/**\n    @file Pulse Data Viewer JS.\n\n    @author Christian W. Zuckschwerdt <zany@triq.net>\n    @copyright Christian W. Zuckschwerdt, 2020\n    @license\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 2 of the License, or\n    (at your option) any later version.\n*/\n\n/*eslint no-console: \"off\"*/\n\nimport { autorange, autorange_time } from './autorange.js'\n\nimport { selector, lookup, strip } from './utils.js'\n\nimport { DropZone } from './dropzone.js'\n\nimport { Analyzer } from './histogram.js'\nimport { sliceGuess } from './slicer.js'\nimport { PulseBuilder } from './builder.js'\nimport { RfRaw } from './rfraw.js'\nimport { BroadlinkRM } from './broadlinkrm.js'\n\n\nfunction readFile(file) {\n    return new Promise((resolve, reject) => {\n        var reader = new FileReader()\n        reader.onerror = () => {\n            reject(reader.error)\n        }\n        reader.onload = () => {\n            resolve(reader.result)\n        }\n        reader.readAsText(file)\n    })\n}\n\n\n// Check for the various File API support.\nif (window.File && window.FileReader && window.FileList && window.Blob) {\n    // Great success! All the File APIs are supported.\n} else {\n    alert('The File APIs are not fully supported in this browser.')\n}\n\n\nlet resizeTimer\n\nwindow.addEventListener('resize', function () {\n\n    clearTimeout(resizeTimer)\n    resizeTimer = setTimeout(function () {\n\n        // Dispatch the event.\n        const event = new Event('debouncedResize')\n        window.dispatchEvent(event)\n\n    }, 250)\n\n}, false)\n\n\n/**\n    Possible slicer values.\n    @readonly\n    @enum {string}\n*/\nconst Slicers = {\n    PCM: 'PCM',\n    PWM: 'PWM',\n    PPM: 'PPM',\n    MC: 'MC',\n    DM: 'DM',\n    NRZI: 'NRZI',\n    CMI: 'CMI',\n    PIWM: 'PIWM',\n}\n\n/**\n    Possible coding values.\n    @readonly\n    @enum {string}\n*/\nconst Codings = {\n    ManchesterGET: 'Manchester-GET',\n    ManchesterIEEE: 'Manchester-IEEE',\n    DifferentialManchester: 'Differential-Manchester',\n}\n\nconst slicerOptions = [\n    { text: 'off', value: '' },\n    { text: 'PCM', value: 'PCM' },\n    { text: 'PWM', value: 'PWM' },\n    { text: 'PPM', value: 'PPM' },\n    { text: 'MC', value: 'MC' },\n    { text: 'DM', value: 'DM' },\n    { text: 'NRZI', value: 'NRZI' },\n    { text: 'CMI', value: 'CMI' },\n    { text: 'PIWM', value: 'PIWM' },\n]\n\nconst codingOptions = [\n    { text: 'off', value: '' },\n    { text: 'Manchester G.E.Thomas', value: 'ManchesterGET' },\n    { text: 'Manchester IEEE', value: 'ManchesterIEEE' },\n    { text: 'Differential Manchester', value: 'DifferentialManchester' },\n]\n\nexport { Pulseplot }\n\n/**\n    The main Pulseplot class.\n*/\nclass Pulseplot {\n    /**\n        Get all possible slicer options.\n    */\n    static get slicerOptions() {\n        return slicerOptions\n    }\n    /**\n        Get all possible coding options.\n    */\n    static get codingOptions() {\n        return codingOptions\n    }\n\n    /**\n        Initialize a new Pulseplot.\n\n        @param {Object} options\n        @param {number} [options.width=0] - canvas width in px, 0 = auto\n        @param {number} [options.height=150] - canvas height in px\n        @param {number} [options.yHi=50] - Marks y-height\n        @param {number} [options.yLo=100] - Spaces y-height\n        @param {number} [options.yHintLo=115] - Hints y-bottom\n        @param {number} [options.yHintHi=35] - Hints y-top\n        @param {number} [options.yHintText=125] - Hints text y-offset\n        @param {number} [options.scroll=0] - Initial scroll offset\n        @param {number} [options.zoom=1] - Initial zoom factor\n        @param {boolean} [options.unlockable=false] - Enable unlockable\n        @param {boolean} [options.scrollzoom=false] - Enable scrollZoom\n        @param {Slicers} [options.slicer] - Slicer to apply, unset = auto\n        @param {string|Object} options.parent - Container element or selector\n        @param {string|Object} [options.renderInfo] - Info element or selector\n        @param {string|Object} [options.theme] - Theme name or options, see {@link setTheme}\n    */\n    constructor(options = {}) {\n        this.constrain = {\n            histogram: value => parseInt(value, 10) || 0,\n            slicer: value => lookup(Slicers, value) || '',\n            coding: value => lookup(Codings, value) || '',\n        }\n        const defaults = {\n            width: 0, // 0 = auto\n            scroll: 0,\n            zoom: 1,\n        }\n        this.setTheme(options.theme)\n        const heights = this.heightDefaults(options.height)\n        options = Object.assign({}, defaults, heights, options)\n\n        this.tag = Math.random().toString().substring(2) // unique instance tag\n        this.parent = selector(options.parent)\n        this.data = options.data || {}\n        this.width = options.width || this.parent.clientWidth\n        this.height = options.height\n        this.yHi = options.yHi\n        this.yLo = options.yLo\n        this.yHintLo = options.yHintLo\n        this.yHintHi = options.yHintHi\n        this.yHintText = options.yHintText\n        this.scroll = options.scroll\n        this.zoom = options.zoom\n        this.slicer = options.slicer\n        this.renderInfo = options.renderInfo\n        this.opts = options\n\n        if (options.data)\n            this.setData(options.data, options.fileinfo)\n        if (options.unlockable)\n            this.enableUnlockable()\n        if (options.scrollzoom)\n            this.enableScrollZoom()\n\n        if (window.ResizeObserver) {\n            // currently only with recent Edge, Firefox, Chrome, Opera\n            this.resizeObserver = new ResizeObserver(() => {\n                this.redrawCanvas()\n            })\n            this.resizeObserver.observe(this.parent)\n        } else {\n            // won't detect layout changes though\n            window.addEventListener('debouncedResize', this, false)\n        }\n    }\n\n    /**\n        Set a color theme.\n\n        @param {string|Object} options - Theme name or theme options\n        @param {string} [options.hiStroke='#3c3'] - Mark stroke color\n        @param {string} [options.hiFill='rgba(51,204,51,0.1)'] - Mark fill color\n        @param {number} [options.hiLine=3] - Mark line width\n        @param {number[]} [options.hiDash=[]] - Mark dash\n        @param {string} [options.loStroke='#c33'] - Space stroke color\n        @param {string} [options.loFill='rgba(204,204,204,0.1)'] - Space fill color\n        @param {number} [options.loLine=3] - Space line width\n        @param {number[]} [options.loDash=[]] - Space dash\n        @param {string} [options.edgeStroke='#ccc'] - Edges stroke color\n        @param {number} [options.edgeLine=1] - Edges line width\n        @param {number[]} [options.edgeDash=[]] - Edge dash\n        @param {string} [options.textFill='#666'] - Texts color\n        @param {string} [options.dotFill='#999'] - Dots color\n        @param {string} [options.hintStroke='#aaf'] - Hints stroke color\n        @param {number[]} [options.hintDash=[3, 2]] - Hints dash\n        @param {number} [options.hintLine=1] - Hints line width\n        @param {string} [options.hintAltStroke='#f99'] - Error hints stroke color\n        @param {number[]} [options.hintAltDash=[3, 2]] - Error hints dash\n        @param {number} [options.hintAltLine=3] - Error hints line width\n        @param {string} [options.hintFill='#448'] - Hints text color\n        @param {string} [options.timeLabelFill='#333'] - Time label text color\n        @param {string} [options.timeMinorFill='#CCC'] - Time minor tick color\n        @param {string} [options.timeMajorFill='#666'] - Time major tick color\n        @param {string} [options.font='10px sans-serif'] - Text font\n    */\n    setTheme(options) {\n        let defaults = {\n            hiStroke: '#3c3',\n            hiFill: 'rgba(51,204,51,0.1)',\n            hiLine: 3,\n            hiDash: [],\n            loStroke: '#c33',\n            loFill: 'rgba(204,204,204,0.1)',\n            loLine: 3,\n            loDash: [],\n            edgeStroke: '#ccc',\n            edgeLine: 1,\n            edgeDash: [],\n            textFill: '#666',\n            dotFill: '#999',\n            hintStroke: '#aaf',\n            hintDash: [3, 2],\n            hintLine: 1,\n            hintAltStroke: '#f99',\n            hintAltDash: [3, 2],\n            hintAltLine: 3,\n            hintFill: '#448',\n            timeLabelFill: '#333',\n            timeMinorFill: '#CCC',\n            timeMajorFill: '#666',\n            font: '10px sans-serif',\n        }\n        const themes = {}\n        themes.dark = {\n            hiStroke: '#b0b',\n            hiFill: 'rgba(191,0,191,0.2)',\n            hiLine: 3,\n            hiDash: [],\n            loStroke: '#27c',\n            loFill: 'rgba(102,102,102,0.2)',\n            loLine: 3,\n            loDash: [],\n            edgeStroke: '#555',\n            edgeLine: 1,\n            edgeDash: [],\n            textFill: '#ccc',\n            dotFill: '#555',\n            hintStroke: '#555',\n            hintDash: [3, 2],\n            hintLine: 1,\n            hintAltStroke: '#c55',\n            hintAltDash: [3, 2],\n            hintAltLine: 3,\n            hintFill: '#ccc',\n            timeLabelFill: '#DDD',\n            timeMinorFill: '#666',\n            timeMajorFill: '#999',\n            font: '10px sans-serif',\n        }\n        if (typeof options === 'string' && themes[options]) defaults = themes[options]\n        this.theme = Object.assign({}, defaults, options)\n        return this.redrawCanvas()\n    }\n\n    /**\n        Get all height options based on total height value.\n        @param {number} [height=120] - Total height\n        @returns {Object} - All height option defaults\n    */\n    heightDefaults(height = 120) {\n        const textHeight = parseInt(this.theme.font, 10) || 10\n        const timeHeight = 22 + ~~(height / 10)\n        const hintHeight = 1 + ~~(height / 10)\n        let defaults = {\n            height,\n            yHi: timeHeight + hintHeight,\n            yLo: height - textHeight - hintHeight,\n            yHintLo: height - textHeight,\n            yHintHi: timeHeight,\n            yHintText: height,\n        }\n        return defaults\n    }\n\n    /**\n        Enables mouse and touch scroll zoom on double click.\n    */\n    enableUnlockable() {\n        if (this.unlockable)\n            return\n        this.unlockable = true\n        const canvas = this.canvasNode\n        const events = ['dblclick']\n        events.forEach(evt => canvas.addEventListener(evt, this, false))\n    }\n\n    /**\n        Disables mouse and touch scroll zoom on double click.\n    */\n    disableUnlockable() {\n        if (!this.unlockable)\n            return\n        this.unlockable = false\n        const canvas = this.canvasNode\n        const events = ['dblclick']\n        events.forEach(evt => canvas.removeEventListener(evt, this, false))\n    }\n\n    /**\n        Enables mouse and touch scroll zoom.\n    */\n    enableScrollZoom() {\n        if (this.unlocked)\n            return\n        this.unlocked = true\n        const canvas = this.canvasNode\n        let events = ['mousedown', 'mousemove', 'mouseup', 'wheel']\n        if (!this.unlockable) {\n            events.push('dblclick')\n        }\n        if ('ontouchstart' in window) {\n            events = events.concat('touchstart', 'touchmove', 'touchend')\n        }\n        events.forEach(evt => canvas.addEventListener(evt, this, false))\n    }\n\n    /**\n        Disables mouse and touch scroll zoom.\n    */\n    disableScrollZoom() {\n        if (!this.unlocked)\n            return\n        this.unlocked = false\n        const canvas = this.canvasNode\n        let events = ['mousedown', 'mousemove', 'mouseup', 'wheel']\n        if (!this.unlockable) {\n            events.push('dblclick')\n        }\n        if ('ontouchstart' in window) {\n            events = events.concat('touchstart', 'touchmove', 'touchend')\n        }\n        events.forEach(evt => canvas.removeEventListener(evt, this, false))\n    }\n\n    /**\n        Release all event handlers and resources.\n    */\n    destroy() {\n        // this.dropZone?.destroy() // if we had optional chaining\n        this.dropZone ? this.dropZone.destroy() : null\n        // this.resizeObserver?.disconnect() // if we had optional chaining\n        this.resizeObserver ? this.resizeObserver.disconnect() : null\n        window.removeEventListener('debouncedResize', this, false)\n        this.disableScrollZoom()\n    }\n\n    createDropZone(elementOrSelector) {\n        elementOrSelector = elementOrSelector || this.parent.getElementsByClassName('dropzone')[0]\n        const fileLoader = this.setData.bind(this)\n        this.dropZone = new DropZone(elementOrSelector, fileLoader)\n    }\n\n    setSlicer(params) {\n        if (params && params.modulation) {\n            this.slicer = params\n        } else if (this.data && this.data.modulation) {\n            this.slicer = this.data\n        } else {\n            this.slicer = this.guess\n        }\n\n        if (!this.data.pulses || !this.data.pulses.length) return\n\n        const slice = sliceGuess(this.data.pulses, this.slicer)\n        this.data.hints = slice.hints\n        this.data.bits = slice.bits\n        if (slice.bits) {\n            const timings = this.timingsNode\n            const messages = this.messagesNode\n            this.analyzer.print(timings, messages)\n            console.log(slice.bits.toHexString())\n            if (messages) {\n                messages.innerHTML += `<div>Bits: <strong>${slice.bits.toHexString()}</strong></div>`\n            }\n        }\n\n        this.redrawCanvas()\n    }\n\n    /**\n        Set an option on the Pulseplot to some value.\n        @param {string} opt - Option name, see {@link #new_Pulseplot_new new}\n        @param {Object} value - The new value for the option\n    */\n    setOption(opt, value) {\n        this[opt] = this.constrain[opt](value)\n        return this.processData()\n    }\n\n    /**\n        Set a number of options on the Pulseplot to some values.\n        @param {Object} opts - A key/value object of options to set, see {@link #new_Pulseplot_new new}\n    */\n    setOptions(opts) {\n        for (let opt in opts) {\n            this[opt] = this.constrain[opt](opts[opt])\n        }\n        return this.processData()\n    }\n\n    /**\n        Set new data on the Pulseplot.\n        @param {string|Object} filedata - A URL string or File data object of `{ fileBuffer: ArrayBuffer, name: string, size: number, type: string }`\n    */\n    setData(data, fileinfo) {\n/*\n        let promise;\n        // handle if the arg is a url\n        if (typeof filedata === 'string') {\n            promise = loadUrl(filedata);\n        } else {\n            promise = Promise.resolve(filedata);\n        }\n\n        return promise\n            .then(filedata => {\n                this.fileinfo = filedata;\n                return this.processData();\n            })\n*/\n        if (data instanceof Blob) { // also File\n            readFile(data).then(text => {\n                this.data = this.parseData(text, data)\n                this.processData()\n            })\n        } else if (Array.isArray(data)) {\n            this.data = { pulses: data }\n            this.processData()\n        } else if (typeof data === 'string') {\n            // if startsWith \"http\" or \"/\" then readUrl...\n            this.data = this.parseData(data, fileinfo)\n            this.processData()\n        } else if (data.pulses) {\n            this.data = data\n            this.processData()\n        } else {\n            this.data = new PulseBuilder(data)\n            this.processData()\n        }\n    }\n\n    parseData(text, fileinfo = {}) {\n        let data = {\n            name: fileinfo.name || null,\n            type: fileinfo.type || null,\n            size: fileinfo.size || text.length,\n            lastModifiedDate: fileinfo.lastModifiedDate, // use lastModifiedDate only on IE\n            lastModified: fileinfo.lastModified,\n            pulses: [],\n            format: 'OOK',\n            rate: 250000,\n            scale: 1, // 1us\n        }\n\n        const lines = text.split('\\n')\n        for (let line of lines) {\n            if (!line) continue\n            if (line.startsWith(';timescale')) {\n                data.timescale = line.slice(11)\n                const s = parseFloat(data.timescale)\n                if (data.timescale.endsWith('ns'))\n                    data.scale = s * 1e-3\n                else if (data.timescale.endsWith('us'))\n                    data.scale = s\n                else if (data.timescale.endsWith('ms'))\n                    data.scale = s * 1e3\n                else if (data.timescale.endsWith('s'))\n                    data.scale = s * 1e6\n            }\n            if (line.startsWith(';created')) data.created = line.slice(9)\n            if (line.startsWith(';ook')) data.format = 'OOK'\n            if (line.startsWith(';fsk')) data.format = 'FSK'\n            if (line.startsWith(';freq1')) data.freq1 = line.slice(7)\n            if (line.startsWith(';freq2')) data.freq2 = line.slice(7)\n            if (line.startsWith(';samplerate')) data.rate = line.slice(12)\n            if (line.startsWith(';centerfreq')) data.centerfreq = line.slice(12)\n            if (line.startsWith(';sampledepth')) data.sampledepth = line.slice(13)\n            if (line.startsWith(';range')) data.range = line.slice(7)\n            if (line.startsWith(';rssi')) data.rssi = line.slice(6)\n            if (line.startsWith(';snr')) data.snr = line.slice(5)\n            if (line.startsWith(';noise')) data.noise = line.slice(7)\n            if (line.startsWith(';slicer')) data.slicer = line.slice(8)\n            if (line.startsWith(';')) continue\n\n            if (RfRaw.isRfRaw(line)) {\n                const pulses = RfRaw.getPulses(line)\n                data.pulses = data.pulses.concat(pulses)\n                continue\n            }\n            if (BroadlinkRM.isBroadlinkRM(line)) {\n                const decoded = BroadlinkRM.decodeData(line)\n                data.pulses = data.pulses.concat(decoded.pulses)\n                continue\n            }\n\n            const fields = line.split(' ')\n            for (let field of fields) {\n                if (field.length) {\n                    const n = parseInt(field, 10)\n                    data.pulses.push(n * data.scale)\n                }\n            }\n        }\n        data.freq1 = parseFloat(data.freq1)\n        data.freq2 = parseFloat(data.freq2)\n        data.rate = parseFloat(data.rate)\n        data.centerfreq = data.centerfreq && parseFloat(data.centerfreq)\n        data.sampledepth = data.sampledepth && parseFloat(data.sampledepth)\n        data.range = data.range && parseFloat(data.range)\n        data.rssi = data.rssi && parseFloat(data.rssi)\n        data.snr = data.snr && parseFloat(data.snr)\n        data.noise = data.noise && parseFloat(data.noise)\n\n        if (data.slicer) {\n            const args = data.slicer.split(':')\n            data.modulation = args[0]\n            data.short = args[1] && parseFloat(args[1])\n            data.long = args[2] && parseFloat(args[2])\n            data.sync = args[3] && parseFloat(args[3])\n            data.gap = args[4] && parseFloat(args[4])\n        }\n        //console.log(JSON.stringify(data))\n        return data\n    }\n\n    get canvasNode() {\n        return this.parent.getElementsByClassName('pulseplot-canvas')[0] || this.parent.getElementsByTagName('canvas')[0]\n    }\n\n    get fileinfoNode() {\n        return this.parent. getElementsByClassName('pulseplot-fileinfo')[0] || this.parent. getElementsByClassName('fileinfo')[0]\n    }\n\n    get timingsNode() {\n        return this.parent.getElementsByClassName('pulseplot-timings')[0]\n    }\n\n    get messagesNode() {\n        return this.parent.getElementsByClassName('pulseplot-messages')[0]\n    }\n\n    buildInfo() {\n        if (!this.renderInfo && !this.fileinfoNode) {\n            return\n        }\n\n        const data = this.data || {}\n        const sampleFormat = data.format\n        const sampleRate = data.rate\n        const rate_scale = autorange(sampleRate, 10.0)\n        const width_secs = data.width / 1000000\n        const width_scale = autorange_time(width_secs, 10.0)\n        const sampleCount = data.width / 1000000 * sampleRate\n        const pulses = data.pulses || []\n\n        const lastModified = data.lastModifiedDate || new Date(data.lastModified || 0) // use lastModifiedDate only on IE\n\n        const infos = []\n        infos.push({ text: 'File name', value: strip(data.name) })\n        infos.push({ text: 'File type', value: data.type || 'n/a' })\n        infos.push({ text: 'File size', value: `${data.size} bytes` })\n        infos.push({ text: 'Last modified', value: lastModified.toISOString() })\n        infos.push({ text: 'Sample format', value: sampleFormat })\n        infos.push({ text: 'No. of samples', value: `${sampleCount.toFixed(0)} S` })\n        if (sampleRate > 1)\n            infos.push({ text: 'Sample rate', value: `${sampleRate / rate_scale.scale}${rate_scale.prefix}` })\n        infos.push({ text: 'No. of pulses', value: `${pulses.length / 2} ×` })\n        if (sampleRate > 1)\n            infos.push({ text: 'Length (time)', value: `${(width_secs / width_scale.scale).toFixed(2)} ${width_scale.prefix}` })\n\n        if (this.renderInfo) {\n            this.renderInfo(infos)\n        } else {\n            let text = ''\n            for (let item of infos) {\n                text += `<span title=\"${item.text}\">${item.value}</span>`\n            }\n            const info = this.fileinfoNode\n            info.innerHTML = text\n        }\n    }\n\n    // events\n\n    handleEvent(e) {\n        //console.log(e.type)\n        const handler = e.type\n        if (typeof this[handler] === 'function') {\n            return this[handler](e)\n        }\n    }\n\n    wheel(e) {\n        //console.log(e)\n        // scroll (x)\n        let refresh = false\n        if (e.deltaX) {\n            this.scroll += e.deltaX * 10\n            refresh = true\n        }\n\n        // zoom (y)\n        const zoomMin = 0.5\n        const zoomMax = this.data.width / this.width * 10\n\n        let zoom\n        if (e.deltaY < 0) {\n            zoom = this.zoom * (1 + e.deltaY * -0.2) // zoom in\n        } else {\n            zoom = this.zoom / (1 + e.deltaY * 0.2) // zoom out\n        }\n        if (zoom < zoomMin) zoom = zoomMin\n        if (zoom > zoomMax) zoom = zoomMax\n        // apply and fix scroll\n        if (this.zoom != zoom) {\n            this.scroll = (this.scroll + e.layerX) / this.zoom * zoom - e.layerX\n            this.zoom = zoom\n            refresh = true\n        }\n\n        //console.log(`${e.deltaX}, ${e.deltaY} at ${e.layerX}, ${e.layerY}: ${this.scroll} x ${this.zoom}`)\n        if (refresh) this.redrawCanvas()\n        //clientX, clientY\n        //layerX, layerY\n        //pageX, pageY\n        //x, y\n        e.preventDefault()\n    }\n\n    dblclick(e) {\n        if (this.unlockable && !this.unlocked) {\n            this.enableScrollZoom()\n        }\n        else if (this.unlockable && this.unlocked) {\n            this.disableScrollZoom()\n        }\n        else if (this.zoom != 1 || this.scroll != 0) {\n            this.scroll = 0\n            this.zoom = 1\n            this.redrawCanvas()\n        }\n        e.preventDefault()\n    }\n\n    mousedown(e) {\n        this.dragX = e.offsetX\n        this.dragY = e.offsetY\n        this.dragOrig = this.scroll\n        this.isDrag = true\n        e.preventDefault()\n    }\n\n    mouseup(e) {\n        this.isDrag = false\n        e.preventDefault()\n    }\n\n    mousemove(e) {\n        if (!this.isDrag) return\n        this.redrawScroll(this.dragX - e.offsetX, this.dragY - e.offsetY)\n        e.stopPropagation()\n        e.preventDefault()\n    }\n\n    touchstart(e) {\n        // single touch or start of a drag\n        // touch events don't have offsetX, offsetY\n        const clientRect = e.target.getBoundingClientRect()\n\n        const t = e.targetTouches[0]\n        const offsetX = t.clientX - clientRect.left\n        const offsetY = t.clientY - clientRect.top\n\n        this.dragX = offsetX\n        this.dragY = offsetY\n        this.dragOrig = this.scroll\n        this.isDrag = true\n\n        if (e.targetTouches.length > 1)\n            e.preventDefault(); // don't allow multitouches\n    }\n\n    touchcancel(e) {\n        if (e.targetTouches.length < 1) {\n            this.isDrag = false\n            this.dragZoom = false\n        }\n    }\n\n    touchend(e) {\n        if (e.targetTouches.length < 1) {\n            this.isDrag = false\n            this.dragZoom = false\n        }\n    }\n\n    touchmove(e) {\n        // touch events don't have offsetX, offsetY\n        const clientRect = e.target.getBoundingClientRect()\n\n        let t1 = e.targetTouches[0]\n        if (!this.dragZoom && e.targetTouches.length == 1) {\n            // scroll\n            const offsetX = t1.clientX - clientRect.left\n            const offsetY = t1.clientY - clientRect.top\n\n            this.redrawScroll(this.dragX - offsetX, this.dragY - offsetY)\n        }\n        else if (e.targetTouches.length == 2) {\n            // zoom\n            this.isDrag = false\n            const t2 = e.targetTouches[1]\n            const dist = t1.clientX < t2.clientX ? t2.clientX - t1.clientX : t1.clientX - t2.clientX\n            if (!this.dragZoom) {\n                this.dragZoom = this.zoom\n                this.dragDist = dist\n            }\n            const pinchOrig = (t1.clientX + t2.clientX) / 2\n            const pinchDist = dist / this.dragDist\n            const zoom = this.dragZoom * pinchDist\n            this.scroll = (this.scroll + pinchOrig) / this.zoom * zoom - pinchOrig\n            this.zoom = zoom\n\n            this.redrawCanvas()\n            e.preventDefault()\n        }\n\n        e.stopPropagation()\n    }\n\n    debouncedResize() {\n        this.width = this.opts.width || this.parent.clientWidth\n        //this.width = this.opts.width || document.documentElement.clientWidth\n        this.drawCanvas()\n    }\n\n    // drawing\n\n    processData() {\n        if (!this.data.pulses || !this.data.pulses.length) return\n\n        let width = 0\n        for (let j = 0; j < this.data.pulses.length; ++j) {\n            width += this.data.pulses[j]\n        }\n        this.data.width = width\n\n        // Run analyzer\n        const timings = this.timingsNode\n        const messages = this.messagesNode\n        const analyzer = new Analyzer(this.data.pulses)\n        analyzer.console_log()\n        analyzer.print(timings, messages)\n        this.analyzer = analyzer\n        this.guess = analyzer.guess()\n\n        // populate hints\n        if (this.slicer) {\n            // already set, skip\n        } else if (this.data.modulation) {\n            this.slicer = this.data\n        } else {\n            this.slicer = this.guess\n        }\n        const slice = sliceGuess(this.data.pulses, this.slicer)\n        this.data.hints = slice.hints\n        this.data.bits = slice.bits\n        if (slice.bits) {\n            console.log(slice.bits.toHexString())\n            if (messages) {\n                messages.innerHTML += `<div>Bits: <strong>${slice.bits.toHexString()}</strong></div>`\n            }\n        }\n\n        this.buildInfo()\n\n        this.drawCanvas()\n    }\n\n    redrawScroll(x/*, y*/) {\n        //console.log(`scroll ${x}, ${y}`)\n        this.scroll = this.dragOrig + x\n        // TODO: Y for zoom\n        this.redrawCanvas()\n    }\n\n    redrawCanvas() {\n        window.requestAnimationFrame(this.drawCanvas.bind(this))\n    }\n\n    drawCanvas() {\n        this.width = this.opts.width || this.parent.clientWidth\n        //this.width = this.opts.width || document.documentElement.clientWidth\n        const width = this.width\n        const height = this.height\n\n        const canvas = this.canvasNode\n        canvas.width = width\n        canvas.height = height\n        //canvas.style.width = canvas.width + 'px'\n        //canvas.parentNode.style.width = canvas.width + 'px'\n        //canvas.style.height = canvas.height + 'px'\n        const ctx = canvas.getContext('2d')\n\n        const scroll = -this.scroll\n        const scale = width * this.zoom / this.data.width\n        const yHi = this.yHi + 0.5\n        const yLo = this.yLo + 0.5\n\n        // time axis\n        ctx.font = this.theme.font\n        const textMeasure = ctx.measureText('8')\n        const fontX = textMeasure.width\n        const fontY = textMeasure.actualBoundingBoxAscent +  textMeasure.actualBoundingBoxDescent\n\n        const total_time = this.data.width / 1000000 / this.zoom\n        const time_offset = scroll / width * total_time\n        const time_scale = autorange(total_time, 10.0)\n        const total_time_scaled = total_time / time_scale.scale\n        const time_offset_scaled = time_offset / time_scale.scale\n\n        ctx.fillStyle = this.theme.timeLabelFill\n        ctx.fillText(`t[${time_scale.prefix}s]`, 32, fontY)\n\n        // extra info\n        if (this.data.time)\n            ctx.fillText(`${this.data.time}`, 100, fontY)\n        if (this.data.format || this.data.mod)\n            ctx.fillText(`${(this.data.format || this.data.mod).toUpperCase()}`, 300, fontY)\n        if (this.data.pulses)\n            ctx.fillText(`${this.data.pulses.length / 2} pulses`, 330, fontY)\n        const rate_Hz = this.data.rate_Hz || this.data.samplerate_Hz || this.data.rate || this.data.samplerate\n        if (rate_Hz) {\n            const scale = autorange(rate_Hz, 10.0)\n            ctx.fillText(`${rate_Hz / scale.scale} ${scale.prefix}Hz`, 400, fontY)\n        }\n        const freq_Hz = this.data.freq_Hz || this.data.centerfreq_Hz || this.data.centerfreq\n        const freq1_Hz = this.data.freq1_Hz || this.data.freq1\n        if (freq1_Hz) {\n            const scale = autorange(freq1_Hz, 10.0)\n            ctx.fillText(`${(freq1_Hz / scale.scale).toFixed(3)} ${scale.prefix}Hz`, 500, fontY)\n        }\n        if (freq_Hz && freq1_Hz) {\n            ctx.fillStyle = this.theme.timeMinorFill\n            ctx.fillRect(700, ~~(fontY / 2), 100, 1)\n            ctx.fillStyle = this.theme.timeLabelFill\n\n            const fr = (freq1_Hz - this.data.freq_Hz) * 100 / rate_Hz + 50\n            ctx.lineWidth = this.theme.hiLine\n            ctx.strokeStyle = this.theme.hiStroke\n            ctx.beginPath()\n            ctx.moveTo(700 + fr, 0)\n            ctx.lineTo(700 + fr, fontY)\n            ctx.stroke()\n        }\n        const freq2_Hz = this.data.freq2_Hz || this.data.freq2\n        if (freq2_Hz) {\n            const scale = autorange(freq2_Hz, 10.0)\n            ctx.fillText(`${(freq2_Hz / scale.scale).toFixed(3)} ${scale.prefix}Hz`, 600, fontY)\n        }\n        if (freq_Hz && freq2_Hz) {\n            const fr = (freq2_Hz - this.data.freq_Hz) * 100 / rate_Hz + 50\n            ctx.lineWidth = this.theme.loLine\n            ctx.strokeStyle = this.theme.loStroke\n            ctx.beginPath()\n            ctx.moveTo(700 + fr, 0)\n            ctx.lineTo(700 + fr, fontY)\n            ctx.stroke()\n        }\n        const range_dB = this.data.range_dB || this.data.range || 66\n        const rssi_dB = this.data.rssi_dB || this.data.rssi\n        const snr_dB = this.data.snr_dB || this.data.snr\n        const noise_dB = this.data.noise_dB || this.data.noise\n        if (rssi_dB && snr_dB && noise_dB) {\n            ctx.lineWidth = 1\n            ctx.strokeStyle = this.theme.loStroke\n            ctx.beginPath()\n            ctx.moveTo(900, fontY)\n            ctx.lineTo(1000, fontY)\n            ctx.stroke()\n\n            ctx.lineWidth = this.theme.hiLine\n            ctx.strokeStyle = this.theme.hiStroke\n            ctx.beginPath()\n            ctx.moveTo(1000 + noise_dB * 100 / range_dB, fontY)\n            ctx.lineTo(1000 + rssi_dB * 100 / range_dB, fontY)\n            ctx.stroke()\n\n            ctx.fillText(`RSSI ${noise_dB.toFixed(1)} ${snr_dB.toFixed(1)} ${rssi_dB.toFixed(1)} dB`, 900, fontY)\n        }\n\n        // want a time marker for about every 85 pixels\n        const num_time_markers = width / 85\n        let time_markers_step = total_time_scaled / num_time_markers\n        // round to 5\n        time_markers_step = ~~(time_markers_step / 5) * 5\n        if (time_markers_step < 1.0) time_markers_step = 1.0\n\n        const time_per_pixel = width / total_time_scaled\n        //console.log({ time_offset_scaled, total_time_scaled, time_markers_step, time_per_pixel })\n\n        const y = 18\n        ctx.fillStyle = this.theme.timeMinorFill\n        for (let t = time_offset_scaled; t < total_time_scaled; t += time_markers_step / 5) {\n            if (t >= total_time_scaled - time_markers_step)\n                t = total_time_scaled\n            const x = ~~(t * time_per_pixel)\n            ctx.fillRect(x, y + 10, 1, 5)\n        }\n\n        ctx.fillStyle = this.theme.timeMajorFill\n        for (let t = time_offset_scaled; t < total_time_scaled; t += time_markers_step) {\n            if (t >= total_time_scaled - time_markers_step)\n                t = total_time_scaled\n            const x = ~~(t * time_per_pixel)\n            ctx.fillRect(x, y + 5, 1, 10)\n\n            const label = (t - time_offset_scaled).toFixed(0)\n            let x1 = x - 3 * label.length\n            if (t >= total_time_scaled)\n                x1 = x - 6 * fontX\n            //ctx.fillText(`${t.toFixed(0)}${time_scale.prefix}s`, x1, 18)\n            ctx.fillText(label, x1, 20)\n        }\n\n        // hints\n        ctx.lineWidth = this.theme.hintLine\n        ctx.strokeStyle = this.theme.hintStroke\n        ctx.setLineDash(this.theme.hintDash)\n        ctx.beginPath()\n        let xp // previous hint (end)\n        for (let j = 0; this.data.hints && j < this.data.hints.length; j += 1) {\n            const hint = this.data.hints[j]\n            const x0 = hint[0] * scale + scroll // start pos\n            const x1 = hint[1] * scale + scroll // end pos\n            if (xp != x0 && x0 >= 0 && x0 < width) {\n                ctx.moveTo(~~x0 - 0.5, this.yHintLo - 0.5)\n                ctx.lineTo(~~x0 - 0.5, this.yHintHi + 0.5)\n            }\n            if (x1 >= 0 && x1 < width) {\n                ctx.moveTo(~~x1 - 0.5, this.yHintLo - 0.5)\n                ctx.lineTo(~~x1 - 0.5, this.yHintHi + 0.5)\n            }\n            xp = x1\n        }\n        ctx.stroke()\n        ctx.setLineDash([])\n\n        // alt (error) hints\n        ctx.lineWidth = this.theme.hintAltLine\n        ctx.strokeStyle = this.theme.hintAltStroke\n        ctx.setLineDash(this.theme.hintAltDash)\n        ctx.beginPath()\n        xp = null // previous hint (end)\n        for (let j = 0; this.data.hints && j < this.data.hints.length; j += 1) {\n            const hint = this.data.hints[j]\n            const x0 = hint[0] * scale + scroll // start pos\n            const x1 = hint[1] * scale + scroll // end pos\n            if (xp != x0) {\n                if (xp && xp >= 0 && xp < width) {\n                    ctx.moveTo(~~xp - 0.5, this.yHintLo - 0.5)\n                    ctx.lineTo(~~xp - 0.5, this.yHintHi + 0.5)\n                }\n                if (x0 >= 0 && x0 < width) {\n                    ctx.moveTo(~~x0 - 0.5, this.yHintLo - 0.5)\n                    ctx.lineTo(~~x0 - 0.5, this.yHintHi + 0.5)\n                }\n            }\n            xp = x1\n        }\n        ctx.stroke()\n        ctx.setLineDash([])\n\n        // hints text\n        ctx.fillStyle = this.theme.hintFill\n        ctx.beginPath()\n        for (let j = 0; this.data.hints && j < this.data.hints.length; j += 1) {\n            const hint = this.data.hints[j]\n            const x0 = hint[0] * scale + scroll // start pos\n            const x1 = hint[1] * scale + scroll // end pos\n            const t = hint[2] // text\n            const w = x1 - x0\n            if (w > fontX) {\n                const xt = x0 + w / 2\n                if (xt >= 0 && xt < width)\n                    ctx.fillText(t, xt - 5, this.yHintText)\n            }\n        }\n        ctx.stroke()\n\n        if (!this.data.pulses || !this.data.pulses.length) return\n\n        // marks\n        let x = scroll\n        ctx.lineWidth = this.theme.hiLine\n        ctx.strokeStyle = this.theme.hiStroke\n        ctx.setLineDash(this.theme.hiDash)\n        ctx.fillStyle = this.theme.hiFill\n        ctx.beginPath()\n        for (let j = 0; j < this.data.pulses.length; j += 2) {\n            const x0 = x\n            x += this.data.pulses[j] * scale // mark\n            if ((x0 >= 0 && x0 < width) || (x >= 0 && x < width) || (x0 < 0 && x > width)) {\n                ctx.fillRect(~~x0, yHi, ~~(x - x0), yLo - yHi)\n                ctx.moveTo(~~x0 - 1, yHi)\n                ctx.lineTo(~~x + 0, yHi)\n            }\n            x += this.data.pulses[j + 1] * scale // space\n        }\n        ctx.stroke()\n\n        // spaces\n        x = scroll\n        ctx.lineWidth = this.theme.loLine\n        ctx.strokeStyle = this.theme.loStroke\n        ctx.setLineDash(this.theme.loDash)\n        ctx.fillStyle = this.theme.loFill\n        ctx.beginPath()\n        for (let j = 0; j < this.data.pulses.length; j += 2) {\n            x += this.data.pulses[j] * scale // mark\n            const x0 = x\n            x += this.data.pulses[j + 1] * scale // space\n            if ((x0 >= 0 && x0 < width) || (x >= 0 && x < width) || (x0 < 0 && x > width)) {\n                ctx.fillRect(~~x0, yHi, ~~(x - x0), yLo - yHi)\n                ctx.moveTo(~~x0 - 1, yLo)\n                ctx.lineTo(~~x + 0, yLo)\n            }\n        }\n        ctx.stroke()\n\n        // edges\n        x = scroll\n        ctx.lineWidth = this.theme.edgeLine\n        ctx.strokeStyle = this.theme.edgeStroke\n        ctx.setLineDash(this.theme.edgeDash)\n        ctx.beginPath()\n        for (let j = 0; j < this.data.pulses.length; j += 1) {\n            if (x >= 0 && x < width) {\n                ctx.moveTo(~~x - 0.5, yLo - 0.5)\n                ctx.lineTo(~~x - 0.5, yHi + 0.5)\n            }\n            x += this.data.pulses[j] * scale // mark or space\n        }\n        ctx.stroke()\n\n        // text\n        x = scroll\n        ctx.fillStyle = this.theme.textFill\n        const textY = yHi + (yLo - yHi + fontY) / 2\n        for (let j = 0; j < this.data.pulses.length; j += 1) {\n            const p = this.data.pulses[j] // mark or space\n            const w = p * scale\n            if (w > 30) {\n                const x0 = x + w / 2\n                if (x0 >= 0 && x0 < width)\n                    ctx.fillText(p, x0 - 10, textY)\n            }\n            x += w\n        }\n\n        // dots\n        const rate = 1000000 / this.data.rate * scale\n        x = scroll\n        if (rate > 2) {\n            const dotW = rate > 4 ? 2 : 1\n            ctx.fillStyle = this.theme.dotFill\n            for (let j = 0; j < this.data.pulses.length; j += 2) {\n                const mark = this.data.pulses[j] * scale // mark\n                for (let k = 0; k < mark - rate; k += rate) {\n                    const x0 = ~~(x + k)\n                    if (x0 >= 0 && x0 < width)\n                        ctx.fillRect(x0, yHi + 0.5, dotW, 3)\n                }\n                x += mark\n                const space = this.data.pulses[j + 1] * scale // space\n                for (let k = 0; k < space - rate; k += rate) {\n                    const x0 = ~~(x + k)\n                    if (x0 >= 0 && x0 < width)\n                        ctx.fillRect(x0, yLo - 3.5, dotW, 3)\n                }\n                x += space\n            }\n        }\n    }\n}\n","export function getDemos() {\n    let demos = []\n    for (let key in Demos) {\n        const demo = Demos[key]\n        demos.push({title: demo.name, key: key, value: demo})\n    }\n    return demos\n}\n\nexport const Demos = {\n    thgr221_mc: {\n        name: 'THGR221 MC',\n        format: 'OOK',\n        rate: 250000,\n        timescale: '1us',\n        modulation: 'MC',\n        warmup_raw: false,\n        preamble: 'fffffe',\n        preamble_raw: false,\n        syncword: false,\n        sync_raw: false,\n        payload: 'be28512a95880d82e453fffffebe28512a95880d82e453fffffebe28512a95880d82e452',\n        payload_invert: false,\n        postamble: false,\n        postamble_raw: false,\n        short: 500,\n        gap: 0,\n        repeat: 1,\n        jitter: 5,\n    },\n    vailant_dm: {\n        name: 'Vailant DM',\n        format: 'OOK',\n        rate: 250000,\n        timescale: '1us',\n        modulation: 'DM',\n        warmup_raw: false,\n        preamble: false,\n        preamble_raw: false,\n        syncword: false,\n        sync_raw: false,\n        payload: '{130}ffff814990fffbfffffed2ff4136807fc', // last byte is only 2 bits\n        //payload: [0xff, 0xff, 0x81, 0x49, 0x90, 0xff, 0xfb, 0xff, 0xff, 0xfe, 0xd2, 0xff, 0x41, 0x36, 0x80, 0x7f, 0xc0], // last byte is only 2 bits\n        //payload: [0xff, 0xff, 0x81, 0x49, 0x90, 0xff, 0xfb, 0xff, 0x7f, 0xfe, 0xd2, 0xff, 0x41, 0x76, 0x80, 0x7f, 0xc0], // last byte is only 2 bits\n        payload_invert: false,\n        postamble: false,\n        postamble_raw: [0, 16764],\n        short: 830,\n        gap: 0,\n        repeat: 2,\n        jitter: 10,\n    },\n    fody_pcm: {\n        name: 'Fody PCM (NRZ)',\n        format: 'FSK',\n        rate: 250000,\n        timescale: '1us',\n        modulation: 'PCM',\n        warmup_raw: false,\n        preamble: '00aaaaaaaaaa',\n        preamble_raw: false,\n        syncword: '2dd4',\n        sync_raw: false,\n        payload: 'f4f5edffffffffffedc8ffffff0b0a12000000000012370000000000',\n        payload_invert: false,\n        postamble: false,\n        postamble_raw: false,\n        short: 488,\n        long: false,\n        gap: 0,\n        repeat: 1,\n        jitter: 4,\n    },\n    pcm_rz: {\n        name: 'PCM (RZ) test',\n        format: 'OOK',\n        rate: 250000,\n        timescale: '1us',\n        modulation: 'PCM',\n        warmup_raw: false,\n        preamble: 'aaaaaaa9',\n        preamble_raw: false,\n        syncword: false,\n        sync_raw: false,\n        payload: 'a0ff',\n        payload_invert: false,\n        postamble: false,\n        postamble_raw: false,\n        short: 500,\n        long: 1000,\n        gap: 0,\n        repeat: 1,\n        jitter: 10,\n    },\n    proove_ppm: {\n        name: 'Proove PPM',\n        format: 'OOK',\n        rate: 250000,\n        timescale: '1us',\n        modulation: 'PPM',\n        warmup_raw: false,\n        preamble: false,\n        preamble_raw: [280, 2600],\n        syncword: false,\n        sync_raw: false,\n        payload: '59A6A9AA66666955',\n        payload_invert: false,\n        postamble: false,\n        postamble_raw: false,\n        pulse: 260,\n        short: 270,\n        long: 1300,\n        gap: 10000,\n        repeat: 15,\n        jitter: 0.05,\n    },\n    bresser3ch_pwm: {\n        name: 'Bresser-3ch PWM',\n        format: 'OOK',\n        rate: 250000,\n        timescale: '1us',\n        modulation: 'PWM',\n        warmup_raw: false,\n        preamble: false,\n        preamble_raw: [750, 700, 750, 700, 750, 700, 750, 700],\n        syncword: false,\n        sync_raw: false,\n        payload: 'e8d9f3bf76',\n        payload_invert: false,\n        postamble: false,\n        postamble_raw: false,\n        short: 260,\n        long: 500,\n        sync: 750,\n        short_gap: 470,\n        long_gap: 227,\n        gap: 1000,\n        repeat: 15,\n        jitter: 0.05,\n    },\n    pwm_fixedgap: {\n        name: 'PWM (fixed gap) test',\n        format: 'OOK',\n        rate: 250000,\n        timescale: '1us',\n        modulation: 'PWM',\n        warmup_raw: false,\n        preamble: 'aaaaaaa9',\n        preamble_raw: false,\n        syncword: false,\n        sync_raw: false,\n        payload: 'a0ff',\n        payload_invert: false,\n        postamble: false,\n        postamble_raw: false,\n        short: 500,\n        long: 1000,\n        short_gap: 500,\n        long_gap: 500,\n        gap: 0,\n        repeat: 1,\n        jitter: 0.05,\n    },\n    klimalogg_nrzi: {\n        name: 'Klimalogg NRZI',\n        format: 'OOK',\n        rate: 250000,\n        timescale: '1us',\n        modulation: 'NRZI',\n        warmup_raw: false,\n        preamble: '067ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe',\n        preamble_raw: false,\n        syncword: false,\n        sync_raw: false,\n        payload: '619fe6600fffc3c333fcffcff30fffc3ffffc33333fcffffffffff8007e0',\n        payload_invert: false,\n        postamble: false,\n        postamble_raw: [0, 10000],\n        short: 12,\n        long: false,\n        gap: 0,\n        repeat: 1,\n        jitter: 2,\n    },\n}\n"],"names":["autoranges","autorange","num","min_int","i","autoranges_time","autorange_time","selector","elementOrSelector","lookup","table","arrayOrKey","match","key","strip","html","doc","DropZone","fileLoader","evt","el","e","files","file","reader","handler","index","event","dec2hex","w","Hexbuffer","line","s","r","v","max_hist_bins","Bin","bin","Histogram","data","tolerance","len","n","bn","bm","index1","index2","tempbin","m","width","b","separator","ret","Analyzer","messages","j","pulses","gaps","periods","short","long","p1","p2","timings","raw","mi","si","raw0","raw1","guess","Bitbuffer","bytes","end","c","bit","bits","sliceGuess","slicePCM","sliceMC","slicePPM","slicePWM","sliceDM","sliceNRZI","sliceCMI","slicePIWM","sliceNRZ","sliceRZ","gap","hints","x","symbol","cnt","k","shortl","shortu","onew","zs","sync","longl","longu","syncl","syncu","x0","x1","manchesterAligned","offset","aligned","mark","mcnt","space","scnt","parsePulseString","pulseStr","PulseBuilder","args","repeat","arg","pulse","jitter","short_gap","long_gap","state","RfRaw","codes","code","p","buf","fmt","buckets","repeats","bucket","v3format","bufSafe","dataHigh","BroadlinkRM","codeType","readFile","resolve","reject","resizeTimer","Slicers","Codings","slicerOptions","codingOptions","Pulseplot","options","value","defaults","heights","themes","height","textHeight","timeHeight","hintHeight","canvas","events","params","slice","opt","opts","fileinfo","text","lines","decoded","fields","field","sampleFormat","sampleRate","rate_scale","width_secs","width_scale","sampleCount","lastModified","infos","item","info","refresh","zoomMin","zoomMax","zoom","clientRect","t","offsetX","offsetY","t1","t2","dist","pinchOrig","pinchDist","analyzer","ctx","scroll","scale","yHi","yLo","textMeasure","fontX","fontY","total_time","time_offset","time_scale","total_time_scaled","time_offset_scaled","rate_Hz","freq_Hz","freq1_Hz","fr","freq2_Hz","range_dB","rssi_dB","snr_dB","noise_dB","num_time_markers","time_markers_step","time_per_pixel","y","label","xp","hint","xt","textY","rate","dotW","getDemos","demos","Demos","demo"],"mappings":"iOAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAYA,MAAMA,EAAa,CACf,CAAE,KAAM,QAAS,MAAO,KAAM,OAAQ,GAAK,EAC3C,CAAE,KAAM,QAAS,MAAO,KAAM,OAAQ,GAAK,EAC3C,CAAE,KAAM,MAAO,MAAO,KAAM,OAAQ,GAAK,EACzC,CAAE,KAAM,OAAQ,MAAO,KAAM,OAAQ,GAAK,EAC1C,CAAE,KAAM,OAAQ,MAAO,KAAM,OAAQ,GAAK,EAC1C,CAAE,KAAM,OAAQ,MAAO,IAAK,OAAQ,GAAK,EACzC,CAAE,KAAM,OAAQ,MAAO,IAAK,OAAQ,GAAK,EACzC,CAAE,KAAM,OAAQ,MAAO,IAAK,OAAQ,GAAK,EACzC,CAAE,KAAM,GAAI,MAAO,EAAK,OAAQ,EAAI,EACpC,CAAE,KAAM,QAAS,MAAO,KAAM,OAAQ,GAAK,EAC3C,CAAE,KAAM,QAAS,MAAO,KAAM,OAAQ,GAAK,EAC3C,CAAE,KAAM,OAAQ,MAAO,KAAM,OAAQ,GAAK,EAC1C,CAAE,KAAM,OAAQ,MAAO,MAAO,OAAQ,GAAK,EAC3C,CAAE,KAAM,QAAS,MAAO,MAAO,OAAQ,GAAK,EAC5C,CAAE,KAAM,OAAQ,MAAO,MAAO,OAAQ,GAAK,EAC3C,CAAE,KAAM,QAAS,MAAO,MAAO,OAAQ,GAAK,EAC5C,CAAE,KAAM,QAAS,MAAO,MAAO,OAAQ,GAAK,CAChD,EAGA,SAASC,EAAUC,EAAKC,EAAU,GAAM,CACpC,GAAID,GAAO,EACP,OAAOF,EAAW,CAAC,EAEvBE,EAAMA,EAAMC,EACZ,QAASC,EAAI,EAAGA,EAAIJ,EAAW,OAAQ,EAAEI,EACrC,GAAIF,GAAOF,EAAWI,CAAC,EAAE,MACrB,OAAOJ,EAAWI,CAAC,EAE3B,OAAOJ,EAAWA,EAAW,OAAS,CAAC,CAC3C,CAIA,MAAMK,EAAkB,CACpB,CAAE,KAAM,OAAQ,MAAO,SAAU,OAAQ,GAAK,EAC9C,CAAE,KAAM,QAAS,MAAO,QAAS,OAAQ,GAAK,EAC9C,CAAE,KAAM,MAAO,MAAO,MAAO,OAAQ,GAAK,EAC1C,CAAE,KAAM,OAAQ,MAAO,KAAM,OAAQ,GAAK,EAC1C,CAAE,KAAM,SAAU,MAAO,GAAI,OAAQ,GAAK,EAC1C,CAAE,KAAM,SAAU,MAAO,EAAK,OAAQ,GAAK,EAC3C,CAAE,KAAM,QAAS,MAAO,KAAM,OAAQ,IAAM,EAC5C,CAAE,KAAM,QAAS,MAAO,KAAM,OAAQ,IAAM,EAC5C,CAAE,KAAM,OAAQ,MAAO,KAAM,OAAQ,IAAM,EAC3C,CAAE,KAAM,OAAQ,MAAO,MAAO,OAAQ,IAAM,EAC5C,CAAE,KAAM,QAAS,MAAO,MAAO,OAAQ,IAAM,EAC7C,CAAE,KAAM,OAAQ,MAAO,MAAO,OAAQ,IAAM,EAC5C,CAAE,KAAM,QAAS,MAAO,MAAO,OAAQ,IAAM,EAC7C,CAAE,KAAM,QAAS,MAAO,MAAO,OAAQ,IAAM,CACjD,EAGA,SAASC,GAAeJ,EAAKC,EAAU,GAAM,CACzC,GAAID,GAAO,EACP,OAAOG,EAAgB,CAAC,EAE5BH,EAAMA,EAAMC,EACZ,QAASC,EAAI,EAAGA,EAAIC,EAAgB,OAAQ,EAAED,EAC1C,GAAIF,GAAOG,EAAgBD,CAAC,EAAE,MAC1B,OAAOC,EAAgBD,CAAC,EAEhC,OAAOC,EAAgBA,EAAgB,OAAS,CAAC,CACrD,CC3EA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAaO,SAASE,EAASC,EAAmB,CACxC,OAAKA,IAEM,OAAOA,GAAsB,SAC7B,SAAS,cAAcA,CAAiB,EAExCA,EAEf,CAGO,SAASC,EAAOC,EAAOC,EAAY,CAGtC,GAFI,CAACA,GAED,OAAOA,GAAe,SACtB,OAAOA,EACX,GAAID,EAAMC,CAAU,EAChB,OAAOD,EAAMC,CAAU,EAC3B,MAAMC,EAAQD,EAAW,YAAW,EACpC,QAASE,KAAOH,EACZ,GAAIG,EAAI,YAAW,GAAMD,EACrB,OAAOF,EAAMG,CAAG,EACxB,QAASA,KAAOH,EACZ,GAAIG,EAAI,cAAc,WAAWD,CAAK,EAClC,OAAOF,EAAMG,CAAG,EACxB,OAAO,IACX,CAGO,SAASC,GAAMC,EAAM,CACxB,IAAIC,EAAM,IAAI,UAAS,EAAG,gBAAgBD,EAAM,WAAW,EAC3D,OAAOC,EAAI,KAAK,aAAe,EACnC,CC7CA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAgBO,MAAMC,CAAS,CAClB,YAAYT,EAAmBU,EAAY,CACvCV,EAAoBA,GAAqB,YACzCA,EAAoBD,EAASC,CAAiB,EAG9C,KAAK,SAAWA,EAChB,KAAK,WAAaU,EAClB,KAAK,SAAW,CAAA,EAChB,KAAK,eAAiB,CAAA,EAEtB,OAAO,iBAAiB,YAAa,IAAI,EACzC,OAAO,iBAAiB,YAAa,IAAI,EACzC,OAAO,iBAAiB,YAAa,IAAI,EAE1B,CAAC,YAAa,WAAY,YAAa,MAAM,EACrD,QAAQC,GAAO,KAAK,SAAS,iBAAiBA,EAAK,KAAM,EAAK,CAAC,CAC9E,CAEI,SAASX,EAAmB,CACxBA,EAAoBA,GAAqB,aACzCA,EAAoBD,EAASC,CAAiB,EAE9CA,EAAkB,iBAAiB,SAAU,KAAM,EAAK,EACxD,KAAK,SAAS,KAAKA,CAAiB,CAC5C,CAEI,SAAU,CACN,OAAO,oBAAoB,YAAa,KAAM,EAAK,EACnD,OAAO,oBAAoB,YAAa,KAAM,EAAK,EACnD,OAAO,oBAAoB,YAAa,KAAM,EAAK,EAEpC,CAAC,YAAa,WAAY,YAAa,MAAM,EACrD,QAAQW,GAAO,KAAK,SAAS,oBAAoBA,EAAK,KAAM,EAAK,CAAC,EAEzE,QAASC,KAAM,KAAK,SAChBA,EAAG,oBAAoB,SAAU,KAAM,EAAK,CAExD,CAEI,UAAUC,EAAG,CAETA,EAAE,aAAa,WAAa,OAC5BA,EAAE,eAAc,CACxB,CAEI,WAAWA,EAAG,CACVA,EAAE,eAAc,EAChB,KAAK,iBAAiBA,CAAC,CAC/B,CAGI,iBAAiBF,EAAK,CAClBA,EAAI,gBAAe,EACnBA,EAAI,eAAc,EAIlB,MAAMG,EAAS,iBAAkBH,EAAOA,EAAI,aAAa,MAAQA,EAAI,OAAO,MAG5E,QAASf,EAAI,EAAGmB,EAAOA,EAAOD,EAAMlB,CAAC,EAAIA,IAAK,CAK1C,MAAMoB,EAAS,IAAI,WAGnBA,EAAO,OAAUH,GAAM,CAEnBE,EAAK,WAAgBF,EAAE,OAAO,OAG9B,KAAK,WAAWE,CAAI,CACpC,EAGYC,EAAO,kBAAkBD,CAAI,CACzC,CACA,CAII,YAAYF,EAAG,CACX,MAAMI,EAAUJ,EAAE,KAClB,GAAI,OAAO,KAAKI,CAAO,GAAM,WACzB,OAAAJ,EAAE,eAAc,EACT,KAAKI,CAAO,EAAEJ,CAAC,CAElC,CAEI,UAAUA,EAAG,CACT,KAAK,eAAe,KAAKA,EAAE,MAAM,EAEjC,SAAS,gBAAgB,UAAU,IAAI,UAAU,EACjD,KAAK,SAAS,UAAU,IAAI,QAAQ,CAC5C,CAEI,SAASA,EAAG,CACR,KAAK,SAAS,UAAU,IAAI,OAAO,EACnC,KAAK,UAAUA,CAAC,CACxB,CAEI,UAAUA,EAAG,CACT,MAAMK,EAAQ,KAAK,eAAe,QAAQL,EAAE,MAAM,EAC9CK,EAAQ,IACR,KAAK,eAAe,OAAOA,EAAO,CAAC,EAEnC,KAAK,eAAe,QAAQ,KAAK,QAAQ,EAAI,GAC7C,KAAK,SAAS,UAAU,OAAO,OAAO,EAEtC,KAAK,eAAe,SAAW,IAC/B,SAAS,gBAAgB,UAAU,OAAO,UAAU,EACpD,KAAK,SAAS,UAAU,OAAO,QAAQ,EAEnD,CAEI,WAAY,CACR,KAAK,eAAe,OAAO,CAAC,EAC5B,KAAK,SAAS,UAAU,OAAO,OAAO,EACtC,KAAK,SAAS,UAAU,OAAO,QAAQ,EACvC,SAAS,gBAAgB,UAAU,OAAO,UAAU,CAC5D,CAEI,KAAKL,EAAG,CACJ,MAAMM,EAAQ,IAAI,MAAM,WAAW,EACnC,OAAO,cAAcA,CAAK,EAE1B,KAAK,WAAWN,CAAC,CACzB,CAEI,OAAOA,EAAG,CACN,KAAK,iBAAiBA,CAAC,CAC/B,CACA,CCvJA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAYA,SAASO,EAAQxB,EAAGyB,EAAI,EAAG,CACvB,OAAAzB,EAAI,KAAK,MAAMA,CAAC,GACRA,EAAI,OAAS,SAAS,EAAE,EAAE,OAAO,CAACyB,CAAC,EAAE,YAAW,CAC5D,CAEO,MAAMC,CAAU,CACnB,YAAYC,EAAO,GAAI,CACnB,KAAK,WAAWA,CAAI,CAC5B,CACI,WAAWC,EAAG,CACV,KAAK,KAAOA,EAAE,QAAQ,MAAO,EAAE,EAC/B,KAAK,MAAQ,CACrB,CAEI,WAAY,CACR,OAAO,KAAK,MAAQ,GAAK,KAAK,KAAK,MAC3C,CACI,SAAU,CACN,OAAO,KAAK,MAAQ,GAAK,KAAK,KAAK,MAC3C,CACI,SAAU,CACN,OAAO,KAAK,MAAQ,GAAK,KAAK,KAAK,MAC3C,CAEI,YAAa,CACT,OAAO,SAAS,KAAK,KAAK,OAAO,KAAK,MAAO,CAAC,EAAG,EAAE,CAC3D,CACI,UAAW,CACP,OAAO,SAAS,KAAK,KAAK,OAAO,KAAK,MAAO,CAAC,EAAG,EAAE,CAC3D,CACI,UAAW,CACP,OAAO,SAAS,KAAK,KAAK,OAAO,KAAK,MAAO,CAAC,EAAG,EAAE,CAC3D,CAEI,WAAY,CACR,MAAMC,EAAI,SAAS,KAAK,KAAK,OAAO,KAAK,MAAO,CAAC,EAAG,EAAE,EACtD,YAAK,OAAS,EACPA,CACf,CACI,SAAU,CACN,MAAMA,EAAI,SAAS,KAAK,KAAK,OAAO,KAAK,MAAO,CAAC,EAAG,EAAE,EACtD,YAAK,OAAS,EACPA,CACf,CACI,SAAU,CACN,MAAMA,EAAI,SAAS,KAAK,KAAK,OAAO,KAAK,MAAO,CAAC,EAAG,EAAE,EACtD,YAAK,OAAS,EACPA,CACf,CAEI,WAAWC,EAAG,CACV,KAAK,MAAQN,EAAQM,EAAG,CAAC,CACjC,CACI,SAASA,EAAG,CACR,KAAK,MAAQN,EAAQM,EAAG,CAAC,CACjC,CACI,SAASA,EAAG,CACR,KAAK,MAAQN,EAAQM,EAAG,CAAC,CACjC,CACA,CCvEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAgBA,MAAMC,GAAgB,GAGtB,MAAMC,EAAI,CACN,YAAYlC,EAAK,CACT,OAAOA,EAAQ,KACf,KAAK,MAAQ,EACb,KAAK,IAAMA,EACX,KAAK,KAAOA,EACZ,KAAK,KAAO,EACZ,KAAK,IAAMA,EACX,KAAK,IAAMA,IAEX,KAAK,MAAQ,EACb,KAAK,IAAM,EACX,KAAK,KAAO,KACZ,KAAK,KAAO,EACZ,KAAK,IAAM,KACX,KAAK,IAAM,KAEvB,CACI,IAAIA,EAAK,CACL,KAAK,QACL,KAAK,KAAOA,EACZ,KAAK,KAAO,KAAK,IAAM,KAAK,MAC5B,KAAK,IAAM,KAAK,MAAQ,KAAOA,EAAM,KAAK,IAAIA,EAAK,KAAK,GAAG,EAC3D,KAAK,IAAM,KAAK,MAAQ,KAAOA,EAAM,KAAK,IAAIA,EAAK,KAAK,GAAG,EAC3D,KAAK,MAAQ,KAAK,IAAM,KAAK,KAAO,CAC5C,CACI,KAAKmC,EAAK,CACN,KAAK,OAASA,EAAI,MAClB,KAAK,KAAOA,EAAI,IAChB,KAAK,KAAO,KAAK,IAAM,KAAK,MAC5B,KAAK,IAAM,KAAK,IAAI,KAAK,IAAKA,EAAI,GAAG,EACrC,KAAK,IAAM,KAAK,IAAI,KAAK,IAAKA,EAAI,GAAG,EACrC,KAAK,MAAQ,KAAK,IAAM,KAAK,KAAO,CAC5C,CACI,SAASnC,EAAK,CACV,OAAOA,GAAO,KAAK,KAAOA,GAAO,KAAK,GAC9C,CACA,CAGO,MAAMoC,CAAU,CACnB,YAAYC,EAAMC,EAAY,GAAK,CAC/B,KAAK,KAAO,CAAA,EACZ,KAAK,cAAcD,EAAMC,CAAS,CAC1C,CAEI,IAAI,QAAS,CACT,OAAO,KAAK,KAAK,MACzB,CAGI,cAAcD,EAAMC,EAAY,GAAK,CACjC,MAAMC,EAAMF,EAAK,OACjB,QAASG,EAAI,EAAGA,EAAID,EAAK,EAAEC,EAAG,CAE1B,IAAIL,EACJ,IAAKA,EAAM,EAAGA,EAAM,KAAK,KAAK,OAAQ,EAAEA,EAAK,CACzC,MAAMM,EAAKJ,EAAKG,CAAC,EACXE,EAAK,KAAK,KAAKP,CAAG,EAAE,KAC1B,GAAI,KAAK,IAAIM,EAAKC,CAAE,EAAKJ,EAAY,KAAK,IAAIG,EAAIC,CAAE,EAAI,CACpD,KAAK,KAAKP,CAAG,EAAE,IAAIE,EAAKG,CAAC,CAAC,EAC1B,KACpB,CACA,CAEgBL,GAAO,KAAK,KAAK,QAAUA,EAAMF,IACjC,KAAK,KAAK,KAAK,IAAIC,GAAIG,EAAKG,CAAC,CAAC,CAAC,CAE/C,CACA,CAGI,WAAWhB,EAAO,CACd,KAAK,KAAK,OAAOA,EAAO,CAAC,CACjC,CAGI,UAAUmB,EAAQC,EAAQ,CACtB,GAAKD,EAAS,KAAK,KAAK,QAAYC,EAAS,KAAK,KAAK,OAAS,CAC5D,MAAMC,EAAU,KAAK,KAAKF,CAAM,EAChC,KAAK,KAAKA,CAAM,EAAI,KAAK,KAAKC,CAAM,EACpC,KAAK,KAAKA,CAAM,EAAIC,CAChC,CACA,CAGI,WAAY,CACR,GAAI,OAAK,KAAK,OAAS,GAEvB,QAASL,EAAI,EAAGA,EAAI,KAAK,KAAK,OAAS,EAAG,EAAEA,EACxC,QAASM,EAAIN,EAAI,EAAGM,EAAI,KAAK,KAAK,OAAQ,EAAEA,EACpC,KAAK,KAAKA,CAAC,EAAE,KAAO,KAAK,KAAKN,CAAC,EAAE,MACjC,KAAK,UAAUM,EAAGN,CAAC,CAIvC,CAGI,YAAa,CACT,GAAI,OAAK,KAAK,OAAS,GAEvB,QAASA,EAAI,EAAGA,EAAI,KAAK,KAAK,OAAS,EAAG,EAAEA,EACxC,QAASM,EAAIN,EAAI,EAAGM,EAAI,KAAK,KAAK,OAAQ,EAAEA,EACpC,KAAK,KAAKA,CAAC,EAAE,MAAQ,KAAK,KAAKN,CAAC,EAAE,OAClC,KAAK,UAAUM,EAAGN,CAAC,CAIvC,CAGI,UAAUF,EAAY,GAAK,CACvB,GAAI,OAAK,KAAK,OAAS,GAEvB,QAASE,EAAI,EAAGA,EAAI,KAAK,KAAK,OAAS,EAAG,EAAEA,EACxC,QAASM,EAAIN,EAAI,EAAGM,EAAI,KAAK,KAAK,OAAQ,EAAEA,EAAG,CAC3C,MAAML,EAAK,KAAK,KAAKD,CAAC,EAAE,KAClBE,EAAK,KAAK,KAAKI,CAAC,EAAE,KAEpB,KAAK,IAAIL,EAAKC,CAAE,EAAKJ,EAAY,KAAK,IAAIG,EAAIC,CAAE,IAEhD,KAAK,KAAKF,CAAC,EAAE,KAAK,KAAK,KAAKM,CAAC,CAAC,EAE9B,KAAK,WAAWA,CAAC,EACjBA,IAEpB,CAEA,CAGI,UAAUR,EAAY,EAAG,CACrB,QAASE,EAAI,EAAGA,EAAI,KAAK,KAAK,OAAQ,EAAEA,EAEhC,KAAK,KAAKA,CAAC,EAAE,MAAQF,GAErB,KAAK,WAAWE,CAAC,CAGjC,CAGI,eAAeO,EAAO,CAClB,QAASP,EAAI,EAAGA,EAAI,KAAK,KAAK,OAAQ,EAAEA,EACpC,GAAI,KAAK,KAAKA,CAAC,EAAE,SAASO,CAAK,EAC3B,OAAOP,EAGf,MAAO,EACf,CAGI,eAAgB,CACZ,QAASA,EAAI,EAAGA,EAAI,KAAK,KAAK,OAAQ,EAAEA,EAAG,CACvC,MAAMQ,EAAI,KAAK,KAAKR,CAAC,EACrB,QAAQ,IAAI,IAAIA,CAAC,KAAKQ,EAAE,KAAK,MAAMA,EAAE,KAAK,QAAQ,CAAC,CAAC,KAAKA,EAAE,KAAK,QAAQ,CAAC,CAAC,QAAQA,EAAE,GAAG,IAAIA,EAAE,GAAG,GAAG,CAC/G,CACA,CAEI,aAAaC,EAAY,KAAM,CAC3B,IAAIC,EAAM,CAAA,EACV,QAASV,EAAI,EAAGA,EAAI,KAAK,KAAK,OAAQ,EAAEA,EAAG,CACvC,MAAMQ,EAAI,KAAK,KAAKR,CAAC,EACrBU,EAAI,KAAK,GAAGF,EAAE,KAAK,KAAKA,EAAE,KAAK,QAAQ,CAAC,CAAC,YAAYA,EAAE,KAAK,QAAQ,CAAC,CAAC,aAAa,CAC/F,CACQ,OAAOE,EAAI,KAAKD,CAAS,CACjC,CAEA,CAEO,MAAME,EAAS,CAClB,YAAYd,EAAMC,EAAY,GAAK,CAC/B,KAAK,eAAeD,EAAMC,CAAS,EACnC,KAAK,aAAaD,CAAI,CAC9B,CAGI,eAAeA,EAAMe,EAAUd,EAAY,GAAK,CAE5C,KAAK,OAAS,CAAA,EACd,KAAK,KAAO,CAAA,EACZ,KAAK,QAAU,CAAA,EACf,KAAK,UAAY,EACjB,KAAK,QAAU,EAEf,QAASe,EAAI,EAAGA,EAAIhB,EAAK,OAAS,EAAGgB,GAAK,EAAG,CACzC,MAAMP,EAAIT,EAAKgB,CAAC,EACVvB,EAAIO,EAAKgB,EAAI,CAAC,EACpB,KAAK,OAAO,KAAKP,CAAC,EAClB,KAAK,KAAK,KAAKhB,CAAC,EAChB,KAAK,QAAQ,KAAKgB,EAAIhB,CAAC,EACvB,KAAK,WAAagB,EAClB,KAAK,SAAWhB,CAC5B,CACQ,MAAMgB,EAAIT,EAAKA,EAAK,OAAS,CAAC,EAE9B,KAAK,OAAO,KAAKS,CAAC,EAClB,KAAK,WAAaA,EAElB,KAAK,gBAAkB,KAAK,UAAY,KAAK,QAC7C,KAAK,eAAiB,KAAK,gBAAkB,EAG7C,KAAK,YAAc,IAAIV,EAAU,KAAK,OAAQE,CAAS,EACvD,KAAK,UAAY,IAAIF,EAAU,KAAK,KAAME,CAAS,EACnD,KAAK,aAAe,IAAIF,EAAU,KAAK,QAASE,CAAS,EACzD,KAAK,aAAe,IAAIF,EAAUC,EAAMC,CAAS,EAGjD,KAAK,YAAY,UAAUA,CAAS,EACpC,KAAK,UAAU,UAAUA,CAAS,EAClC,KAAK,aAAa,UAAUA,CAAS,EACrC,KAAK,aAAa,UAAUA,CAAS,EAGrC,KAAK,YAAY,UAAUA,CAAS,EACpC,KAAK,UAAU,UAAUA,CAAS,EAClC,KAAK,aAAa,UAAUA,CAAS,EACrC,KAAK,aAAa,UAAUA,CAAS,CAC7C,CAEI,OAAQ,CACJ,MAAMgB,EAAS,KAAK,YACdC,EAAO,KAAK,UACZC,EAAU,KAAK,aAYrB,GAXAF,EAAO,UAAW,EAClBC,EAAK,UAAS,EACVD,EAAO,KAAK,OAAS,GAAKA,EAAO,KAAK,CAAC,EAAE,MAAQ,GACjDA,EAAO,WAAW,CAAC,EAQnB,KAAK,OAAO,QAAU,EACtB,MAAO,CACH,KAAM,yEACtB,EAEa,GAAIA,EAAO,QAAU,GAAKC,EAAK,QAAU,EAC1C,MAAO,CACH,KAAM,0CACtB,EAEa,GAAID,EAAO,QAAU,GAAKC,EAAK,OAAS,EACzC,MAAO,CACH,KAAM,mDACN,WAAY,MACZ,MAAOA,EAAK,KAAK,CAAC,EAAE,KACpB,KAAMA,EAAK,KAAK,CAAC,EAAE,KACnB,IAAKA,EAAK,KAAK,CAAC,EAAE,IAAM,IACxB,MAAOA,EAAK,KAAKA,EAAK,OAAS,CAAC,EAAE,IAAM,GACxD,EAEa,GAAID,EAAO,QAAU,GAAKC,EAAK,QAAU,EAAG,CAC7C,MAAME,EAAQH,EAAO,KAAK,CAAC,EAAE,KACvBI,EAAOJ,EAAO,KAAK,CAAC,EAAE,KAC5B,MAAO,CACH,KAAM,wCACN,WAAY,MACZ,MAAOG,EACP,KAAMC,EACN,WAAYA,EAAOD,GAAS,GAC5B,MAAOF,EAAK,KAAKA,EAAK,OAAS,CAAC,EAAE,IAAM,GACxD,CACA,SACiBD,EAAO,QAAU,GAAKC,EAAK,QAAU,GAAKC,EAAQ,QAAU,EAAG,CACpE,MAAMC,EAAQH,EAAO,KAAK,CAAC,EAAE,KACvBI,EAAOJ,EAAO,KAAK,CAAC,EAAE,KAC5B,MAAO,CACH,KAAM,2CACN,WAAY,MACZ,MAAOG,EACP,KAAMC,EACN,WAAYA,EAAOD,GAAS,GAC5B,MAAOF,EAAK,KAAKA,EAAK,OAAS,CAAC,EAAE,IAAM,GACxD,CACA,SACiBD,EAAO,QAAU,GAAKC,EAAK,QAAU,GAAKC,EAAQ,QAAU,EAAG,CACpE,MAAMC,EAAQH,EAAO,KAAK,CAAC,EAAE,KAC7B,MAAO,CACH,KAAM,0BACN,WAAY,KACZ,MAAOG,EACP,KAAMA,EACN,MAAOF,EAAK,KAAKA,EAAK,OAAS,CAAC,EAAE,IAAM,GACxD,CACA,SACiBD,EAAO,QAAU,GAAKC,EAAK,QAAU,EAAG,CAC7C,MAAME,EAAQH,EAAO,KAAK,CAAC,EAAE,KACvBI,EAAOJ,EAAO,KAAK,CAAC,EAAE,KAC5B,MAAO,CACH,KAAM,+CACN,WAAY,MACZ,MAAOG,EACP,KAAMC,EACN,IAAKH,EAAK,KAAK,CAAC,EAAE,IAAM,IACxB,WAAYG,EAAOD,GAAS,GAC5B,MAAOF,EAAK,KAAKA,EAAK,OAAS,CAAC,EAAE,IAAM,GACxD,CACA,KACa,IAAKD,EAAO,QAAU,GAAKC,EAAK,QAAU,GACvC,KAAK,IAAID,EAAO,KAAK,CAAC,EAAE,KAAO,EAAIA,EAAO,KAAK,CAAC,EAAE,IAAI,GAAKA,EAAO,KAAK,CAAC,EAAE,KAAO,GACjF,KAAK,IAAIA,EAAO,KAAK,CAAC,EAAE,KAAO,EAAIA,EAAO,KAAK,CAAC,EAAE,IAAI,GAAKA,EAAO,KAAK,CAAC,EAAE,KAAO,GACjF,KAAK,IAAIC,EAAK,KAAK,CAAC,EAAE,KAAOD,EAAO,KAAK,CAAC,EAAE,IAAI,GAAKA,EAAO,KAAK,CAAC,EAAE,KAAO,GAC3E,KAAK,IAAIC,EAAK,KAAK,CAAC,EAAE,KAAO,EAAID,EAAO,KAAK,CAAC,EAAE,IAAI,GAAKA,EAAO,KAAK,CAAC,EAAE,KAAO,GAC/E,KAAK,IAAIC,EAAK,KAAK,CAAC,EAAE,KAAO,EAAID,EAAO,KAAK,CAAC,EAAE,IAAI,GAAKA,EAAO,KAAK,CAAC,EAAE,KAAO,EACnF,MAAO,CACH,KAAM,6CACN,WAAY,MACZ,MAAOA,EAAO,KAAK,CAAC,EAAE,KACtB,KAAMA,EAAO,KAAK,CAAC,EAAE,KACrB,MAAOA,EAAO,KAAK,CAAC,EAAE,KAAO,IAC7C,EAEa,GAAIA,EAAO,QAAU,EAAG,CAEzBA,EAAO,WAAU,EACjB,MAAMK,EAAKL,EAAO,KAAK,CAAC,EAAE,KACpBM,EAAKN,EAAO,KAAK,CAAC,EAAE,KACpBG,EAAQE,EAAKC,EAAKD,EAAKC,EACvBF,EAAOC,EAAKC,EAAKA,EAAKD,EAC5B,MAAO,CACH,KAAM,6CACN,WAAY,MACZ,MAAOF,EACP,KAAMC,EACN,KAAMJ,EAAO,KAAK,CAAC,EAAE,KACrB,MAAOC,EAAK,KAAKA,EAAK,OAAS,CAAC,EAAE,IAAM,GACxD,CACA,KAEY,OAAO,CACH,KAAM,YACtB,EAEA,CAEI,aAAalB,EAAM,CACf,MAAMwB,EAAU,KAAK,aAQrB,GANIA,EAAQ,KAAK,OAAS,GAGtBA,EAAQ,KAAK,OAAS,GAGtBxB,EAAK,OAAS,IACd,MAAO,GAGX,IAAIyB,EAAM,IAAIlC,EAEd,QAASoB,KAAKa,EAAQ,KAClBC,EAAI,SAASd,EAAE,IAAI,EAGvB,QAASK,EAAI,EAAGA,EAAIhB,EAAK,OAAS,EAAGgB,GAAK,EAAG,CACzC,MAAMP,EAAIT,EAAKgB,CAAC,EACVvB,EAAIO,EAAKgB,EAAI,CAAC,EAEdU,EAAKF,EAAQ,eAAef,CAAC,EAC/BiB,GAAM,EACND,EAAI,WAAWC,EAAK,CAAC,EACdjB,GAAK,GAGZ,QAAQ,MAAM,wCAAyCA,EAAGiB,CAAE,EAGhE,MAAMC,EAAKH,EAAQ,eAAe/B,CAAC,EAC/BkC,GAAM,EACNF,EAAI,WAAWE,CAAE,EACVlC,GAAK,GAGZ,QAAQ,MAAM,yCAA0CA,EAAGkC,CAAE,CAE7E,CAEYF,EAAI,KAAK,OAAS,GAClBA,EAAI,WAAW,CAAC,EAGpBA,EAAI,SAAS,EAAI,EAEjB,IAAIG,EAAO,IAAIrC,EACfqC,EAAK,SAAS,GAAI,EAClBA,EAAK,SAAS,GAAI,EAClBA,EAAK,SAAS,EAAIH,EAAI,KAAK,OAAS,EAAI,CAAC,EACzCG,EAAK,SAASJ,EAAQ,KAAK,MAAM,EACjCI,EAAK,SAAS,CAAC,EAEf,IAAIC,EAAO,IAAItC,EACfsC,EAAK,SAAS,GAAI,EAClBA,EAAK,SAAS,GAAI,EAClBA,EAAK,SAASL,EAAQ,KAAK,MAAM,EAEjC,KAAK,QAAUI,EAAK,KAAOH,EAAI,KAC/B,KAAK,QAAUI,EAAK,KAAOJ,EAAI,IACvC,CAEI,aAAc,CACV,MAAMK,EAAQ,KAAK,MAAK,EACxB,QAAQ,IAAI,qBAAqB,EACjC,QAAQ,IAAI,gBAAgB,KAAK,OAAO,MAAM,EAAE,EAChD,QAAQ,IAAI,2BAA2B,EACvC,KAAK,YAAY,cAAa,EAC9B,QAAQ,IAAI,yBAAyB,EACrC,KAAK,UAAU,cAAa,EAC5B,QAAQ,IAAI,4BAA4B,EACxC,KAAK,aAAa,cAAa,EAC/B,QAAQ,IAAI,4BAA4B,EACxC,KAAK,aAAa,cAAa,EAC/B,QAAQ,IAAI,8BAA8B,KAAK,eAAiB,KAAK,QAAQ,CAAC,CAAC,EAAE,EACjF,QAAQ,IAAI,sBAAsB,EAClC,QAAQ,IAAIA,CAAK,CACzB,CAEI,YAAYf,EAAU,CAClB,MAAMe,EAAQ,KAAK,MAAK,EACxBf,EAAS,UAAY;AAAA,uBACN,KAAK,YAAY,cAAc;AAAA,qBACjC,KAAK,UAAU,cAAc;AAAA,wBAC1B,KAAK,aAAa,cAAc;AAAA,wBAChC,KAAK,aAAa,cAAc;AAAA,eACzCe,EAAM,IAAI;AAAA,SAEzB,CAWI,MAAMN,EAAST,EAAU,CACrB,MAAMe,EAAQ,KAAK,MAAK,EACpBN,IACAA,EAAQ,UAAY;AAAA,qCACK,KAAK,YAAY,aAAa,WAAW,CAAC;AAAA,mCAC5C,KAAK,UAAU,aAAa,WAAW,CAAC;AAAA,sCACrC,KAAK,aAAa,aAAa,WAAW,CAAC;AAAA,sCAC3C,KAAK,aAAa,aAAa,WAAW,CAAC;AAAA;AAAA,eAIrET,IACAA,EAAS,UAAY;AAAA,qDACoB,KAAK,eAAiB,KAAK,QAAQ,CAAC,CAAC;AAAA,2CAC/Ce,EAAM,IAAI;AAAA,kCACnBA,EAAM,UAAU;AAAA,6BACrBA,EAAM,MAAQA,EAAM,MAAM,QAAQ,CAAC,EAAI,GAAG;AAAA,4BAC3CA,EAAM,KAAOA,EAAM,KAAK,QAAQ,CAAC,EAAI,GAAG;AAAA,4BACxCA,EAAM,KAAOA,EAAM,KAAK,QAAQ,CAAC,EAAI,GAAG;AAAA,2BACzCA,EAAM,IAAMA,EAAM,IAAI,QAAQ,CAAC,EAAI,GAAG;AAAA,6BACpCA,EAAM,MAAQA,EAAM,MAAM,QAAQ,CAAC,EAAI,GAAG;AAAA,yCAC9B,KAAK,QAAU,KAAK,QAAU,GAAG;AAAA,yCACjC,KAAK,QAAU,KAAK,QAAU,GAAG;AAAA;AAAA,cAI1E,CACA,CCxeA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAgBO,MAAMC,CAAU,CACnB,YAAYC,EAAQ,GAAI9B,EAAM,EAAG,CACzB,MAAM,QAAQ8B,CAAK,GACnB,KAAK,MAAQA,EACb,KAAK,IAAM9B,GAAO8B,EAAM,OAAS,GAEjC,KAAK,WAAWA,CAAK,CAEjC,CACI,WAAWvC,EAAG,CACV,KAAK,MAAQ,CAAA,EACb,KAAK,IAAM,EACX,IAAIS,EAAM,GAGV,GAFAT,EAAIA,EAAE,KAAI,EAENA,EAAE,WAAW,GAAG,EAAG,CACnB,MAAMwC,EAAMxC,EAAE,QAAQ,GAAG,EACzB,GAAIwC,EAAM,EAAG,OACb/B,EAAM,SAAST,EAAE,MAAM,CAAC,EAAG,EAAE,EAC7BA,EAAIA,EAAE,MAAMwC,EAAM,CAAC,CAC/B,CAEYxC,EAAE,WAAW,IAAI,IACjBA,EAAIA,EAAE,MAAM,CAAC,GAGjB,QAASyC,KAAKzC,EAAG,CACb,MAAMU,EAAI,SAAS+B,EAAG,EAAE,EACxB,KAAK,WAAW/B,CAAC,CAC7B,CAEYD,GAAO,IACP,KAAK,IAAMA,EACvB,CACI,UAAW,CACP,KAAK,KAAK,CAAC,CACnB,CACI,SAAU,CACN,KAAK,KAAK,CAAC,CACnB,CACI,WAAWT,EAAG,CACNA,GAAK,IACL,KAAK,KAAK,CAAC,EACNA,GAAK,KACV,KAAK,KAAK,CAAC,CACvB,CACI,KAAK0C,EAAK,CACNA,EAAMA,EAAM,IAAO,EACnB,KAAK,MAAM,CAAC,EAAE,KAAK,IAAM,EAAE,GAAKA,GAAQ,KAAK,IAAM,EACnD,KAAK,KAAO,CACpB,CACI,WAAWhC,EAAG,CACV,QAASa,EAAI,EAAGA,GAAK,EAAG,EAAEA,EACtB,KAAK,KAAMb,GAAKa,EAAK,CAAC,CAElC,CACI,SAASb,EAAG,CACR,QAASa,EAAI,EAAGA,GAAK,EAAG,EAAEA,EACtB,KAAK,KAAMb,GAAKa,EAAK,CAAC,CAElC,CACI,WAAY,CACR,MAAML,EAAI,CAAC,GAAG,KAAK,IAAM,GAAK,GAC9B,KAAK,MAAMA,CAAC,EAAI,GAChB,KAAK,KAAOA,EAAI,GAAK,CAC7B,CACI,YAAa,CACT,IAAIyB,EAAO,CAAA,EACX,QAASpB,EAAI,EAAGA,EAAI,KAAK,IAAK,EAAEA,EAAG,CAE/B,MAAMmB,GADO,KAAK,MAAM,CAAC,EAAEnB,EAAI,EAAE,GAAK,IAChB,EAAKA,EAAI,EAAO,EACtCoB,EAAK,KAAKD,CAAG,CACzB,CACQ,OAAOC,CACf,CACI,aAAc,CACV,IAAI3C,EAAI,IAAI,KAAK,GAAG,IACpB,QAASuB,EAAI,EAAGA,EAAI,KAAK,IAAKA,GAAK,EAAG,CAClC,MAAML,EAAI,KAAK,MAAM,CAAC,EAAEK,EAAI,EAAE,GAAK,EAC/BL,EAAI,EACJlB,GAAK,OAELA,GAAK,IACLA,IAAMkB,GAAK,GAAG,SAAS,EAAE,EAAE,YAAW,EAClCK,EAAI,EAAI,KAAK,MACbvB,IAAMkB,EAAI,IAAK,SAAS,EAAE,EAAE,YAAW,GAE3D,CACQ,OAAOlB,CACf,CACA,CC1GA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAcO,SAAS4C,EAAWpB,EAAQa,EAAO,CACtC,OAAIA,EAAM,YAAc,MACbQ,GAASrB,EAAQa,CAAK,EAExBA,EAAM,YAAc,KAClBS,GAAQtB,EAAQa,CAAK,EAEvBA,EAAM,YAAc,MAClBU,GAASvB,EAAQa,CAAK,EAExBA,EAAM,YAAc,MAClBW,GAASxB,EAAQa,CAAK,EAExBA,EAAM,YAAc,KAClBY,GAAQzB,EAAQa,CAAK,EAEvBA,EAAM,YAAc,OAClBa,GAAU1B,EAAQa,CAAK,EAEzBA,EAAM,YAAc,MAClBc,GAAS3B,EAAQa,CAAK,EAExBA,EAAM,YAAc,OAClBe,GAAU5B,EAAQa,CAAK,EAGvB,CAAA,CACf,CAOO,SAASQ,GAASrB,EAAQa,EAAO,CACpC,MAAI,CAACA,EAAM,MAAQA,EAAM,MAAQA,EAAM,MAC5BgB,GAAS7B,EAAQa,CAAK,EAEtBiB,GAAQ9B,EAAQa,CAAK,CAEpC,CAIO,SAASgB,GAAS7B,EAAQa,EAAO,CACpC,MAAMV,EAAQU,EAAM,MACdkB,EAAMlB,EAAM,IAEZM,EAAO,IAAIL,EACjB,IAAIkB,EAAQ,CAAA,EAERC,EAAI,EACR,QAASlC,EAAI,EAAGA,EAAIC,EAAO,OAAQD,GAAK,EAAG,CACvC,MAAMmC,EAAS,EAAInC,EAAI,EACjB1B,EAAI2B,EAAOD,CAAC,EAClB,GAAIgC,GAAO1D,EAAI0D,EACXZ,EAAK,UAAS,MACX,CACH,MAAMgB,EAAM,CAAC,EAAE9D,EAAI8B,EAAQ,IAC3B,QAASiC,EAAI,EAAGA,EAAID,EAAK,EAAEC,EACvBJ,EAAM,KAAK,CAACC,EAAI5D,EAAI8D,EAAMC,EAAGH,EAAI5D,EAAI8D,GAAOC,EAAI,GAAIF,CAAM,CAAC,EAC3Df,EAAK,KAAKe,CAAM,CAEhC,CACQD,GAAK5D,CACb,CAEI,MAAO,CAAE,MAAA2D,EAAO,KAAAb,CAAI,CACxB,CAIO,SAASW,GAAQ9B,EAAQa,EAAO,CACnC,MAAMV,EAAQU,EAAM,MACdT,EAAOS,EAAM,KACbkB,EAAMlB,EAAM,IAEZwB,EAASlC,EAAQ,GACjBmC,EAASnC,EAAQ,IAEjBgB,EAAO,IAAIL,EACjB,IAAIkB,EAAQ,CAAA,EAERC,EAAI,EACR,QAASlC,EAAI,EAAGA,EAAIC,EAAO,OAAQD,GAAK,EAAG,CACvC,MAAMP,EAAIQ,EAAOD,CAAC,EACZvB,EAAIwB,EAAOD,EAAI,CAAC,EACtB,GAAIP,EAAI6C,GAAU7C,EAAI8C,EAAQ,CAC1BnB,EAAK,UAAS,EACdc,GAAKzC,EAAIhB,EACT,QACZ,CACQ,IAAI+D,EAAO/C,EAAIY,EAAOD,EAClBqC,EAAKhE,EAAIgB,EAAI+C,EAQjB,GAPIC,EAAKpC,EAAO,IACZmC,EAAO/C,EAAIhB,EACXgE,EAAK,GAETR,EAAM,KAAK,CAACC,EAAGA,EAAIM,EAAM,GAAG,CAAC,EAC7BpB,EAAK,QAAO,EACZc,GAAKM,EACDR,GAAOvD,EAAIuD,EAAK,CAChBZ,EAAK,UAAS,EACdc,GAAKO,EACL,QACZ,CACQ,MAAML,EAAM,CAAC,EAAEK,EAAKpC,EAAO,IAC3B,QAASgC,EAAI,EAAGA,EAAID,EAAK,EAAEC,EACvBJ,EAAM,KAAK,CAACC,EAAIO,EAAKJ,EAAID,EAAKF,EAAIO,GAAMJ,EAAI,GAAKD,EAAK,GAAG,CAAC,EAC1DhB,EAAK,SAAQ,EAEjBc,GAAKO,CACb,CAEI,MAAO,CAAE,MAAAR,EAAO,KAAAb,CAAI,CACxB,CAIO,SAASI,GAASvB,EAAQa,EAAO,CACpC,MAAMV,EAAQU,EAAM,MACdT,EAAOS,EAAM,KACb4B,EAAO5B,EAAM,KACbkB,EAAMlB,EAAM,IAEZwB,EAASlC,EAAQ,GACjBmC,EAASnC,EAAQ,IACjBuC,EAAQtC,EAAO,GACfuC,EAAQvC,EAAO,IACfwC,EAAQH,EAAO,GACfI,EAAQJ,EAAO,IAEftB,EAAO,IAAIL,EACjB,IAAIkB,EAAQ,CAAA,EAERC,EAAI,EACR,QAASlC,EAAI,EAAGA,EAAIC,EAAO,OAAQD,GAAK,EAAG,CACvC,MAAMP,EAAIQ,EAAOD,CAAC,EACZvB,EAAIwB,EAAOD,EAAI,CAAC,EAChB+C,EAAKb,EACXA,GAAKzC,EAAIhB,EACLA,EAAI6D,GAAU7D,EAAI8D,GAClBN,EAAM,KAAK,CAACc,EAAIb,EAAG,GAAG,CAAC,EACvBd,EAAK,QAAO,GACL3C,EAAIkE,GAASlE,EAAImE,GACxBX,EAAM,KAAK,CAACc,EAAIb,EAAG,GAAG,CAAC,EACvBd,EAAK,SAAQ,GACN3C,EAAIoE,GAASpE,EAAIqE,GACxBb,EAAM,KAAK,CAACc,EAAIb,EAAG,GAAG,CAAC,EACvBd,EAAK,UAAS,GACPY,GAAOvD,EAAIuD,GAClBZ,EAAK,UAAS,CAE1B,CAEI,MAAO,CAAE,MAAAa,EAAO,KAAAb,CAAI,CACxB,CAIO,SAASK,GAASxB,EAAQa,EAAO,CACpC,MAAMV,EAAQU,EAAM,MACdT,EAAOS,EAAM,KACb4B,EAAO5B,EAAM,KACbkB,EAAMlB,EAAM,IAEZwB,EAASlC,EAAQ,GACjBmC,EAASnC,EAAQ,IACjBuC,EAAQtC,EAAO,GACfuC,EAAQvC,EAAO,IACfwC,EAAQH,EAAO,GACfI,EAAQJ,EAAO,IAEftB,EAAO,IAAIL,EACjB,IAAIkB,EAAQ,CAAA,EAERC,EAAI,EACR,QAASlC,EAAI,EAAGA,EAAIC,EAAO,OAAQD,GAAK,EAAG,CACvC,MAAMP,EAAIQ,EAAOD,CAAC,EACZvB,EAAIwB,EAAOD,EAAI,CAAC,EAEhB+C,EAAKb,EACX,IAAIc,EAAKd,EAAIzC,EAAIhB,EAEbA,EAAIuD,IACJgB,EAAKd,EAAIzC,EAAIuC,GACjBE,GAAKzC,EAAIhB,EAELgB,EAAI6C,GAAU7C,EAAI8C,GAClBN,EAAM,KAAK,CAACc,EAAIC,EAAI,GAAG,CAAC,EACxB5B,EAAK,QAAO,GACL3B,EAAIkD,GAASlD,EAAImD,GACxBX,EAAM,KAAK,CAACc,EAAIC,EAAI,GAAG,CAAC,EACxB5B,EAAK,SAAQ,GACN3B,EAAIoD,GAASpD,EAAIqD,IACxBb,EAAM,KAAK,CAACc,EAAIC,EAAI,GAAG,CAAC,EACxB5B,EAAK,UAAS,GAEdY,GAAOvD,EAAIuD,GACXZ,EAAK,UAAS,CAE1B,CAEI,MAAO,CAAE,MAAAa,EAAO,KAAAb,CAAI,CACxB,CAGA,SAAS6B,EAAkBhD,EAAQiD,EAAQ9C,EAAO,CAC9C,QAASJ,EAAIkD,EAAQlD,EAAIC,EAAO,OAAQD,GAAK,EAAG,CAG5C,GADW,CAAC,EADDC,EAAOD,CAAC,EACAI,EAAQ,IAClB,EAAG,MAAO,GAGnB,GADW,CAAC,EADDH,EAAOD,EAAI,CAAC,EACJI,EAAQ,IAClB,EAAG,MAAO,EAC3B,CAEI,MAAO,EACX,CAIO,SAASmB,GAAQtB,EAAQa,EAAO,CACnC,MAAMV,EAAQU,EAAM,MACdM,EAAO,IAAIL,EACjB,IAAIkB,EAAQ,CAAA,EAGRkB,EAAUF,EAAkBhD,EAAQ,EAAGG,CAAK,EAE5C8B,EAAI,EACJc,EAAK,EACT,QAAShD,EAAI,EAAGA,EAAIC,EAAO,OAAQD,GAAK,EAAG,CACvC,MAAMoD,EAAOnD,EAAOD,CAAC,EACfqD,EAAO,CAAC,EAAED,EAAOhD,EAAQ,IACzBkD,EAAQrD,EAAOD,EAAI,CAAC,EACpBuD,EAAO,CAAC,EAAED,EAAQlD,EAAQ,IAE5BiD,GAAQ,GACHF,EAMDH,EAAKd,GALLD,EAAM,KAAK,CAACe,EAAId,EAAIkB,EAAM,GAAG,CAAC,EAC9BhC,EAAK,SAAQ,EACb4B,EAAKd,EAAIkB,GAKbD,EAAU,CAACA,GAENE,GAAQ,GACRF,GAOD/B,EAAK,UAAS,EACd4B,EAAKd,EAAIkB,EAAO,IAPhBnB,EAAM,KAAK,CAACe,EAAId,EAAIkB,EAAO,EAAG,GAAG,CAAC,EAClChC,EAAK,SAAQ,EACb4B,EAAKd,EAAIkB,EAAO,GAOpBD,EAAU,IAELE,EAAO,IACPF,IACDlB,EAAM,KAAK,CAACe,EAAId,EAAIkB,EAAOC,EAAM,GAAG,CAAC,EACrCjC,EAAK,SAAQ,GACb4B,EAAKd,EAAIkB,EAAOA,EAAOC,EAM3BjC,EAAK,UAAS,EACd+B,EAAUF,EAAkBhD,EAAQD,EAAI,EAAGI,CAAK,GAGhDmD,GAAQ,GACHJ,EAMDH,EAAKd,EAAIkB,GALTnB,EAAM,KAAK,CAACe,EAAId,EAAIkB,EAAOE,EAAO,GAAG,CAAC,EACtClC,EAAK,QAAO,EACZ4B,EAAKd,EAAIkB,EAAOE,GAKpBH,EAAU,CAACA,GAENI,GAAQ,GACRJ,GAOD/B,EAAK,UAAS,EACd4B,EAAKd,EAAIkB,EAAOE,EAAQ,IAPxBrB,EAAM,KAAK,CAACe,EAAId,EAAIkB,EAAOE,EAAQ,EAAG,GAAG,CAAC,EAC1ClC,EAAK,QAAO,EACZ4B,EAAKd,EAAIkB,EAAOE,EAAQ,GAO5BH,EAAU,IAELI,EAAO,IACPJ,IACDlB,EAAM,KAAK,CAACe,EAAId,EAAIkB,EAAOE,EAAQC,EAAM,GAAG,CAAC,EAC7CnC,EAAK,QAAO,GACZ4B,EAAKd,EAAIkB,EAAOE,EAAQA,EAAQC,EAMpCnC,EAAK,UAAS,EACd+B,EAAUF,EAAkBhD,EAAQD,EAAI,EAAGI,CAAK,GAGpD8B,GAAKkB,EAAOE,CACpB,CAEI,MAAO,CAAE,MAAArB,EAAO,KAAAb,CAAI,CACxB,CAIO,SAASM,GAAQzB,EAAQa,EAAO,CACnC,MAAMV,EAAQU,EAAM,MACdM,EAAO,IAAIL,EACjB,IAAIkB,EAAQ,CAAA,EAERC,EAAI,EACJc,EAAK,KACT,QAAShD,EAAI,EAAGA,EAAIC,EAAO,OAAQD,GAAK,EAAG,CACvC,MAAMoD,EAAOnD,EAAOD,CAAC,EACfqD,EAAO,CAAC,EAAED,EAAOhD,EAAQ,IACzBkD,EAAQrD,EAAOD,EAAI,CAAC,EACpBuD,EAAO,CAAC,EAAED,EAAQlD,EAAQ,IAE5B,CAAC4C,GAAMK,GAAQ,GAAKE,GAAQ,GAC5BtB,EAAM,KAAK,CAACC,EAAGA,EAAIkB,EAAOE,EAAO,GAAG,CAAC,EACrClC,EAAK,SAAQ,GAERiC,GAAQ,GAAKE,GAAQ,GAC1BtB,EAAM,KAAK,CAACe,EAAId,EAAIkB,EAAM,GAAG,CAAC,EAC9BhC,EAAK,SAAQ,EACb4B,EAAKd,EAAIkB,GAEJJ,GAAMK,GAAQ,GAAKE,GAAQ,GAChCtB,EAAM,KAAK,CAACe,EAAId,EAAIkB,EAAM,GAAG,CAAC,EAC9BhC,EAAK,SAAQ,EACba,EAAM,KAAK,CAACC,EAAIkB,EAAMlB,EAAIkB,EAAOE,EAAO,GAAG,CAAC,EAC5ClC,EAAK,QAAO,EACZ4B,EAAK,MAEAK,GAAQ,GAAKE,GAAQ,GAC1BtB,EAAM,KAAK,CAACC,EAAGA,EAAIkB,EAAM,GAAG,CAAC,EAC7BhC,EAAK,QAAO,EACZ4B,EAAKd,EAAIkB,GAEJC,GAAQ,GAAKE,GAAQ,GAC1BtB,EAAM,KAAK,CAACC,EAAGA,EAAIkB,EAAM,GAAG,CAAC,EAC7BhC,EAAK,QAAO,EACZa,EAAM,KAAK,CAACC,EAAIkB,EAAMlB,EAAIkB,EAAOE,EAAO,GAAG,CAAC,EAC5ClC,EAAK,QAAO,GAEP,CAAC4B,GAAMK,GAAQ,GAEpBpB,EAAM,KAAK,CAACC,EAAGA,EAAIkB,EAAOhD,EAAO,GAAG,CAAC,EACrCgB,EAAK,SAAQ,EACbA,EAAK,UAAS,GAET,CAAC4B,GAAMK,GAAQ,GAEpBpB,EAAM,KAAK,CAACC,EAAGA,EAAIkB,EAAM,GAAG,CAAC,EAC7BhC,EAAK,QAAO,EACZA,EAAK,UAAS,IAIV4B,IACAf,EAAM,KAAK,CAACe,EAAIA,EAAK5C,EAAQ,EAAG,GAAG,CAAC,EACpCgB,EAAK,SAAQ,GAEjB4B,EAAK,KACL5B,EAAK,UAAS,GAElBc,GAAKkB,EAAOE,CACpB,CAEI,MAAO,CAAE,MAAArB,EAAO,KAAAb,CAAI,CACxB,CAOO,SAASO,GAAU1B,EAAQa,EAAO,CACrC,MAAMV,EAAQU,EAAM,MACdM,EAAO,IAAIL,EACjB,IAAIkB,EAAQ,CAAA,EAERC,EAAI,EACJc,EAAK,EACT,QAAShD,EAAI,EAAGA,EAAIC,EAAO,OAAQD,GAAK,EAAG,CACvC,MAAM1B,EAAI2B,EAAOD,CAAC,EACZoC,EAAM,CAAC,EAAE9D,EAAI8B,EAAQ,IAEvB4C,IACAf,EAAM,KAAK,CAACe,EAAId,EAAI9B,EAAQ,EAAG,GAAG,CAAC,EACnCgB,EAAK,QAAO,GAEhB4B,EAAKd,EAAI9B,EAAQ,EAEjB,QAASiC,EAAI,EAAGA,EAAID,EAAK,EAAEC,EACvBJ,EAAM,KAAK,CAACe,EAAIA,EAAK1E,EAAI8D,EAAK,GAAG,CAAC,EAClChB,EAAK,SAAQ,EACb4B,GAAM1E,EAAI8D,EAGdF,GAAK5D,CACb,CAEI,MAAO,CAAE,MAAA2D,EAAO,KAAAb,CAAI,CACxB,CAMO,SAASQ,GAAS3B,EAAQa,EAAO,CACpC,MAAMV,EAAQU,EAAM,MACdM,EAAO,IAAIL,EACjB,IAAIkB,EAAQ,CAAA,EAERC,EAAI,EACJc,EAAK,KACT,QAAShD,EAAI,EAAGA,EAAIC,EAAO,OAAQD,GAAK,EAAG,CACvC,MAAMoD,EAAOnD,EAAOD,CAAC,EACfqD,EAAO,CAAC,EAAED,EAAOhD,EAAQ,IACzBkD,EAAQrD,EAAOD,EAAI,CAAC,EACpBuD,EAAO,CAAC,EAAED,EAAQlD,EAAQ,IAE5BiD,GAAQ,GAAKE,GAAQ,GAChBP,IAAIA,EAAKd,EAAIkB,GAClBnB,EAAM,KAAK,CAACe,EAAId,EAAIkB,EAAM,GAAG,CAAC,EAC9BhC,EAAK,SAAQ,EACb4B,EAAKd,EAAIkB,GAEJC,GAAQ,GAAKE,GAAQ,GACrBP,IAAIA,EAAKd,EAAIkB,GAClBnB,EAAM,KAAK,CAACe,EAAId,EAAIkB,EAAM,GAAG,CAAC,EAC9BhC,EAAK,SAAQ,EACb4B,EAAKd,EAAIkB,EAAOE,EAChBrB,EAAM,KAAK,CAACC,EAAIkB,EAAMJ,EAAI,GAAG,CAAC,EAC9B5B,EAAK,QAAO,GAEPiC,GAAQ,GAAKE,GAAQ,GACrBP,IAAIA,EAAKd,EAAIkB,GAClBnB,EAAM,KAAK,CAACe,EAAId,EAAIkB,EAAM,GAAG,CAAC,EAC9BhC,EAAK,SAAQ,EACb4B,EAAKd,EAAIkB,EAAOE,EAAQ,EAAI,EAC5BrB,EAAM,KAAK,CAACC,EAAIkB,EAAMJ,EAAI,GAAG,CAAC,EAC9B5B,EAAK,QAAO,GAEPiC,GAAQ,GAAKE,GAAQ,GAC1BtB,EAAM,KAAK,CAACe,EAAId,EAAIkB,EAAM,GAAG,CAAC,EAC9BhC,EAAK,QAAO,EACZ4B,EAAKd,EAAIkB,GAEJC,GAAQ,GAAKE,GAAQ,GAC1BtB,EAAM,KAAK,CAACe,EAAId,EAAIkB,EAAM,GAAG,CAAC,EAC9BhC,EAAK,QAAO,EACZ4B,EAAKd,EAAIkB,EAAOE,EAChBrB,EAAM,KAAK,CAACC,EAAIkB,EAAMJ,EAAI,GAAG,CAAC,EAC9B5B,EAAK,QAAO,GAEPiC,GAAQ,GAAKE,GAAQ,GAC1BtB,EAAM,KAAK,CAACe,EAAId,EAAIkB,EAAM,GAAG,CAAC,EAC9BhC,EAAK,QAAO,EACZ4B,EAAKd,EAAIkB,EAAOE,EAAQ,EAAI,EAC5BrB,EAAM,KAAK,CAACC,EAAIkB,EAAMJ,EAAI,GAAG,CAAC,EAC9B5B,EAAK,QAAO,GAEPiC,GAAQ,GAAKE,GAAQ,GAC1BtB,EAAM,KAAK,CAACe,EAAId,EAAIkB,EAAO,EAAG,GAAG,CAAC,EAClChC,EAAK,SAAQ,EACba,EAAM,KAAK,CAACC,EAAIkB,EAAO,EAAGlB,EAAIkB,EAAM,GAAG,CAAC,EACxChC,EAAK,QAAO,EACZ4B,EAAKd,EAAIkB,GAEJC,GAAQ,GAAKE,GAAQ,GAC1BtB,EAAM,KAAK,CAACe,EAAId,EAAIkB,EAAO,EAAG,GAAG,CAAC,EAClChC,EAAK,SAAQ,EACba,EAAM,KAAK,CAACC,EAAIkB,EAAO,EAAGlB,EAAIkB,EAAM,GAAG,CAAC,EACxChC,EAAK,QAAO,EACZ4B,EAAKd,EAAIkB,EAAOE,EAChBrB,EAAM,KAAK,CAACC,EAAIkB,EAAMJ,EAAI,GAAG,CAAC,EAC9B5B,EAAK,QAAO,GAEPiC,GAAQ,GAAKE,GAAQ,GAC1BtB,EAAM,KAAK,CAACe,EAAId,EAAIkB,EAAO,EAAG,GAAG,CAAC,EAClChC,EAAK,SAAQ,EACba,EAAM,KAAK,CAACC,EAAGA,EAAIkB,EAAO,EAAG,GAAG,CAAC,EACjChC,EAAK,QAAO,EACZa,EAAM,KAAK,CAACC,EAAIkB,EAAO,EAAGlB,EAAIkB,EAAM,GAAG,CAAC,EACxChC,EAAK,QAAO,EACZa,EAAM,KAAK,CAACC,EAAIkB,EAAMlB,EAAIkB,EAAOE,EAAQ,EAAI,EAAG,GAAG,CAAC,EACpDlC,EAAK,QAAO,EACZ4B,EAAKd,EAAIkB,EAAOE,EAAQ,EAAI,GAEvBD,GAAQ,GACbpB,EAAM,KAAK,CAACe,EAAId,EAAIkB,EAAM,GAAG,CAAC,EAC9BhC,EAAK,SAAQ,EACbA,EAAK,UAAS,EACd4B,EAAKd,EAAIkB,GAEJC,GAAQ,GACbpB,EAAM,KAAK,CAACe,EAAId,EAAIkB,EAAM,GAAG,CAAC,EAC9BhC,EAAK,QAAO,EACZA,EAAK,UAAS,EACd4B,EAAKd,EAAIkB,GAIThC,EAAK,UAAS,EAElBc,GAAKkB,EAAOE,CACpB,CAEI,MAAO,CAAE,MAAArB,EAAO,KAAAb,CAAI,CACxB,CAIO,SAASS,GAAU5B,EAAQa,EAAO,CACrC,MAAMV,EAAQU,EAAM,MACdM,EAAO,IAAIL,EACjB,IAAIkB,EAAQ,CAAA,EAERC,EAAI,EACR,QAASlC,EAAI,EAAGA,EAAIC,EAAO,OAAQD,GAAK,EAAG,CACvC,MAAM1B,EAAI2B,EAAOD,CAAC,EACZoC,EAAM,CAAC,EAAE9D,EAAI8B,EAAQ,IAEvBgC,GAAO,GACPH,EAAM,KAAK,CAACC,EAAGA,EAAI5D,EAAG,GAAG,CAAC,EAC1B8C,EAAK,QAAO,GAEPgB,GAAO,GACZH,EAAM,KAAK,CAACC,EAAGA,EAAI5D,EAAG,GAAG,CAAC,EAC1B8C,EAAK,SAAQ,GAGbA,EAAK,UAAS,EAElBc,GAAK5D,CACb,CAEI,MAAO,CAAE,MAAA2D,EAAO,KAAAb,CAAI,CACxB,CC3jBA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAgBA,SAASoC,GAAiBC,EAAU,CAChC,OAAI,MAAM,QAAQA,CAAQ,EACfA,EAEEA,EAAS,MAAM,IAAI,EAAE,IAAIvB,GAAK,SAASA,EAAG,EAAE,CAAC,CAE9D,CAEO,MAAMwB,EAAa,CACtB,YAAYC,EAAM,CACd,OAAO,OAAO,KAAMA,CAAI,EACxB,KAAK,MAAK,CAClB,CAEI,OAAQ,CACJ,KAAK,OAAS,CAAA,EAEV,KAAK,YACL,KAAK,OAAO,KAAM,KAAK,UAAU,EAErC,MAAMC,EAAS,KAAK,QAAU,EAC9B,QAAS5D,EAAI,EAAGA,EAAI4D,EAAQ,EAAE5D,EAAG,CAO7B,GALI,KAAK,KAAOA,EAAI,IAChB,KAAK,OAAO,KAAK,CAAC,EAClB,KAAK,OAAO,KAAK,KAAK,GAAG,GAGzB,KAAK,SAAU,CACf,MAAMoB,EAAO,IAAIL,EAAU,KAAK,QAAQ,EACxC,KAAK,QAAQ,KAAMK,CAAI,CACvC,CASY,GARI,KAAK,cACL,KAAK,OAAO,KAAM,KAAK,YAAY,EAGnC,KAAK,UACL,KAAK,OAAO,KAAM,KAAK,QAAQ,EAG/B,KAAK,SAAU,CACf,MAAMA,EAAO,IAAIL,EAAU,KAAK,QAAQ,EACxC,KAAK,QAAQ,KAAMK,CAAI,CACvC,CAEY,MAAMA,EAAO,IAAIL,EAAU,KAAK,OAAO,EAGvC,GAFA,KAAK,QAAQ,KAAMK,CAAI,EAEnB,KAAK,UAAW,CAChB,MAAMA,EAAO,IAAIL,EAAU,KAAK,SAAS,EACzC,KAAK,QAAQ,KAAMK,CAAI,CACvC,CACgB,KAAK,eACL,KAAK,OAAO,KAAM,KAAK,aAAa,CAEpD,CACQ,YAAK,SAAQ,EAGT,KAAK,QACL,KAAK,UAAU,IAAI,EAEhB,IACf,CAEI,QAAQyC,EAAKzC,EAAM,CACf,OAAIyC,EAAI,YAAc,MAClB,KAAK,SAASA,EAAKzC,CAAI,EAClByC,EAAI,YAAc,KACvB,KAAK,QAAQA,EAAKzC,CAAI,EACjByC,EAAI,YAAc,MACvB,KAAK,SAASA,EAAKzC,CAAI,EAClByC,EAAI,YAAc,MACvB,KAAK,SAASA,EAAKzC,CAAI,EAClByC,EAAI,YAAc,KACvB,KAAK,QAAQA,EAAKzC,CAAI,EACjByC,EAAI,YAAc,OACvB,KAAK,UAAUA,EAAKzC,CAAI,EACnByC,EAAI,YAAc,MACvB,KAAK,SAASA,EAAKzC,CAAI,EAClByC,EAAI,YAAc,OACvB,KAAK,UAAUA,EAAKzC,CAAI,EAExB,QAAQ,IAAI,qBAAqB,EAC9ByC,CACf,CAEI,OAAOA,EAAK5D,EAAQ,CAChB,OAAAA,EAASuD,GAAiBvD,CAAM,EAE5BA,EAAO,OAAS,GAChBA,EAAO,KAAK,CAAC,EACjB4D,EAAI,OAASA,EAAI,OAAO,OAAO5D,CAAM,EAC9B4D,CACf,CAEI,UAAW,CACP,IAAI5D,EAAS,CAAA,EAET6D,EAAQ,EACZ,QAAS9D,EAAI,EAAGA,EAAI,KAAK,OAAO,OAAQA,GAAK,EAAG,CAC5C,MAAMP,EAAI,KAAK,OAAOO,CAAC,GAAK,EACtBvB,EAAI,KAAK,OAAOuB,EAAI,CAAC,GAAK,EAC5B,CAACP,GAAK,CAAChB,IAGF,CAACqF,GAAS,CAACrE,GAAKQ,EAAO,OAE5BA,EAAOA,EAAO,OAAS,CAAC,GAAK,CAAC,CAACxB,EAEzBA,GAKNwB,EAAO,KAAK,CAAC,EAAER,EAAIqE,EAAM,EACzB7D,EAAO,KAAK,CAAC,CAAExB,CAAE,EACjBqF,EAAQ,GALRA,GAASrE,EAOzB,CAEQ,OAAIqE,IACA7D,EAAO,KAAK,CAAC,CAAC6D,CAAK,EACnB7D,EAAO,KAAK,CAAC,GAGjB,KAAK,OAASA,EACP,IACf,CAEI,UAAU4D,EAAK,CACX,MAAME,EAASF,EAAI,OACnB,IAAI5D,EAAS,CAAA,EAEb,QAASD,EAAI,EAAGA,EAAI6D,EAAI,OAAO,OAAQ,EAAE7D,EAAG,CACxC,MAAM1B,EAAIuF,EAAI,OAAO7D,CAAC,EACtB,GAAI1B,GAAK,EACL2B,EAAO,KAAK3B,CAAC,UACNyF,EAAS,EAAG,CAEnB,MAAMtF,EAAI,KAAK,OAAQ,EAAG,EAAIsF,EAAS,EAAIA,EAC3C9D,EAAO,KAAK,CAAC,EAAE3B,EAAIG,EAAE,CACrC,KAAmB,CAEH,MAAMA,EAAI,KAAK,OAAM,EAAK,EAAIsF,EAASA,EACvC9D,EAAO,KAAK,CAAC,EAAE3B,EAAIG,EAAE,CACrC,CACA,CAEQ,OAAAoF,EAAI,OAAS5D,EACN4D,CACf,CAOI,SAASA,EAAKzC,EAAM,CAChB,MAAI,CAACyC,EAAI,MAAQA,EAAI,MAAQA,EAAI,MACtB,KAAK,SAASA,EAAKzC,CAAI,EAEvB,KAAK,QAAQyC,EAAKzC,CAAI,CAEzC,CAKI,SAASyC,EAAKzC,EAAM,CAEhB,MAAMhB,EAAQyD,EAAI,MAClB,IAAI5D,EAAS4D,EAAI,OAEjB,MAAM1C,EAAMC,EAAK,WAAU,EAC3B,QAASpB,EAAI,EAAGA,EAAImB,EAAI,OAAQ,EAAEnB,EAC1BmB,EAAInB,CAAC,GACLC,EAAO,KAAKG,CAAK,EACjBH,EAAO,KAAK,CAAC,IAGbA,EAAO,KAAK,CAAC,EACbA,EAAO,KAAKG,CAAK,GAIzB,OAAOyD,CACf,CAII,QAAQA,EAAKzC,EAAM,CAEf,MAAMhB,EAAQyD,EAAI,MACZxD,EAAOwD,EAAI,KACXG,EAAY3D,EAAOD,EACzB,IAAIH,EAAS4D,EAAI,OAEjB,MAAM1C,EAAMC,EAAK,WAAU,EAC3B,QAASpB,EAAI,EAAGA,EAAImB,EAAI,OAAQ,EAAEnB,EAC1BmB,EAAInB,CAAC,GACLC,EAAO,KAAKG,CAAK,EACjBH,EAAO,KAAK+D,CAAS,IAGrB/D,EAAO,KAAK,CAAC,EACbA,EAAO,KAAKI,CAAI,GAIxB,OAAOwD,CACf,CAII,SAASA,EAAKzC,EAAM,CAChB,MAAM0C,EAAQD,EAAI,OAAS,CAAC,EAAEA,EAAI,MAAQ,GACpCzD,EAAQyD,EAAI,MACZxD,EAAOwD,EAAI,KAEjB,IAAI5D,EAAS4D,EAAI,OAEjB,MAAM1C,EAAMC,EAAK,WAAU,EAC3B,QAASpB,EAAI,EAAGA,EAAImB,EAAI,OAAQ,EAAEnB,EAC9BC,EAAO,KAAK6D,CAAK,EACb3C,EAAInB,CAAC,EACLC,EAAO,KAAKG,CAAK,EAEjBH,EAAO,KAAKI,CAAI,EAIxB,OAAOwD,CACf,CAII,SAASA,EAAKzC,EAAM,CAChB,MAAMhB,EAAQyD,EAAI,MACZxD,EAAOwD,EAAI,KACXG,EAAYH,EAAI,WAAaA,EAAI,KACjCI,EAAWJ,EAAI,UAAYA,EAAI,MAErC,IAAI5D,EAAS4D,EAAI,OAEjB,MAAM1C,EAAMC,EAAK,WAAU,EAC3B,QAASpB,EAAI,EAAGA,EAAImB,EAAI,OAAQ,EAAEnB,EAC1BmB,EAAInB,CAAC,GACLC,EAAO,KAAKG,CAAK,EACjBH,EAAO,KAAK+D,CAAS,IAErB/D,EAAO,KAAKI,CAAI,EAChBJ,EAAO,KAAKgE,CAAQ,GAI5B,OAAOJ,CACf,CAII,QAAQA,EAAKzC,EAAM,CACf,MAAMhB,EAAQyD,EAAI,MAClB,IAAI5D,EAAS4D,EAAI,OAEjB,MAAM1C,EAAMC,EAAK,WAAU,EAC3B,QAASpB,EAAI,EAAGA,EAAImB,EAAI,OAAQ,EAAEnB,EAC1BmB,EAAInB,CAAC,GACLC,EAAO,KAAKG,CAAK,EACjBH,EAAO,KAAKG,CAAK,IAEjBH,EAAO,KAAK,CAAC,EACbA,EAAO,KAAKG,CAAK,EACjBH,EAAO,KAAKG,CAAK,EACjBH,EAAO,KAAK,CAAC,GAIrB,OAAO4D,CACf,CAII,QAAQA,EAAKzC,EAAM,CACf,MAAMhB,EAAQyD,EAAI,MAClB,IAAI5D,EAAS4D,EAAI,OAEjB,MAAM1C,EAAMC,EAAK,WAAU,EAC3B,IAAI8C,EAAQ,GACZ,QAASlE,EAAI,EAAGA,EAAImB,EAAI,OAAQ,EAAEnB,EAAG,CACjC,MAAML,EAAIwB,EAAInB,CAAC,EACX,CAACL,GAAK,CAACuE,GACPjE,EAAO,KAAKG,CAAK,EACjBH,EAAO,KAAKG,CAAK,GACV,CAACT,GAAKuE,GACbjE,EAAO,KAAK,CAAC,EACbA,EAAO,KAAKG,CAAK,EACjBH,EAAO,KAAKG,CAAK,EACjBH,EAAO,KAAK,CAAC,GACNN,GAAK,CAACuE,GACbjE,EAAO,KAAKG,EAAQ,CAAC,EACrBH,EAAO,KAAK,CAAC,EACbiE,EAAQ,CAACA,GACFvE,GAAKuE,IACZjE,EAAO,KAAK,CAAC,EACbA,EAAO,KAAKG,EAAQ,CAAC,EACrB8D,EAAQ,CAACA,EAEzB,CAEQ,OAAOL,CACf,CAOI,UAAUA,EAAKzC,EAAM,CAEjB,MAAMhB,EAAQyD,EAAI,MAClB,IAAI5D,EAAS4D,EAAI,OAEjB,MAAM1C,EAAMC,EAAK,WAAU,EAC3B,IAAI8C,EAAQ,CAAC/C,EAAI,CAAC,EAClB,QAASnB,EAAI,EAAGA,EAAImB,EAAI,OAAQ,EAAEnB,EAC1BmB,EAAInB,CAAC,IACLkE,EAAQ,CAACA,GAETA,GACAjE,EAAO,KAAKG,CAAK,EACjBH,EAAO,KAAK,CAAC,IAEbA,EAAO,KAAK,CAAC,EACbA,EAAO,KAAKG,CAAK,GAIzB,OAAOyD,CACf,CAMI,SAASA,EAAKzC,EAAM,CAChB,MAAMhB,EAAQyD,EAAI,MAClB,IAAI5D,EAAS4D,EAAI,OAEjB,MAAM1C,EAAMC,EAAK,WAAU,EAC3B,IAAI8C,EAAQ,GACZ,QAASlE,EAAI,EAAGA,EAAImB,EAAI,OAAQ,EAAEnB,EACzBmB,EAAInB,CAAC,EAKEkE,GAKRjE,EAAO,KAAK,CAAC,EACbA,EAAO,KAAKG,EAAQ,CAAC,EACrB8D,EAAQ,CAACA,IANTjE,EAAO,KAAKG,EAAQ,CAAC,EACrBH,EAAO,KAAK,CAAC,EACbiE,EAAQ,CAACA,IAPTjE,EAAO,KAAK,CAAC,EACbA,EAAO,KAAKG,CAAK,EACjBH,EAAO,KAAKG,CAAK,EACjBH,EAAO,KAAK,CAAC,GAYrB,OAAO4D,CACf,CAII,UAAUA,EAAKzC,EAAM,CACjB,MAAMhB,EAAQyD,EAAI,MAClB,IAAI5D,EAAS4D,EAAI,OAEjB,MAAM1C,EAAMC,EAAK,WAAU,EAC3B,QAASpB,EAAI,EAAGA,EAAImB,EAAI,OAAQ,EAAEnB,EAC1BmB,EAAInB,CAAC,EACLC,EAAO,KAAKG,CAAK,EAEjBH,EAAO,KAAKG,EAAQ,CAAC,EAI7B,OAAIe,EAAI,OAAS,GACblB,EAAO,KAAKG,EAAQ,CAAC,EAGlByD,CACf,CACA,CCxZA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAcO,MAAMM,CAAM,CACf,OAAO,QAAQ3F,EAAM,CACjB,OAAOA,EAAK,OAAO,WAAW,IAAI,CAC1C,CACI,OAAO,UAAUA,EAAM,CACnB,IAAIyB,EAAS,CAAA,EAEbzB,EAAOA,EAAK,QAAQ,wBAAyB,QAAQ,EACrD,MAAM4F,EAAQ5F,EAAK,MAAM,GAAG,EAC5B,QAAS6F,KAAQD,EAAO,CACpB,MAAME,EAAIH,EAAM,cAAcE,CAAI,EAClCpE,EAASA,EAAO,OAAOqE,CAAC,CACpC,CACQ,OAAOrE,CACf,CACI,OAAO,cAAczB,EAAM,CAEvB,QAAQ,IAAI,uBAAwBA,CAAI,EACxC,IAAIyB,EAAS,CAAA,EACb,MAAMsE,EAAM,IAAIhG,EAAUC,CAAI,EAG9B,GADa+F,EAAI,QAAO,GACZ,IACR,OAAOtE,EAGX,MAAMuE,EAAMD,EAAI,QAAO,EACvB,IAAIrF,EACAuF,EACAC,EACJ,GAAIF,GAAO,IAEPC,EAAUF,EAAI,QAAO,UAEhBC,GAAO,IAEZtF,EAAMqF,EAAI,QAAO,EACjBE,EAAUF,EAAI,QAAO,EACrBG,EAAUH,EAAI,QAAO,MAGrB,QAAOtE,EAGX,IAAI0E,EAAS,CAAA,EACb,QAAShF,EAAI,EAAGA,EAAI8E,EAAS,EAAE9E,EAC3BgF,EAAOhF,CAAC,EAAI4E,EAAI,QAAO,EAE3B,QAAQ,IAAI,YAAYE,CAAO,SAASvF,CAAG,YAAYwF,CAAO,MAAOC,CAAM,EAC3E,IAAIC,EAAW,GACf,MAAMC,EAAUN,EAAI,MACpB,KAAOA,EAAI,aAEP,GADUA,EAAI,UAAS,EACf,EAAG,CACPK,EAAW,GACX,KAChB,CAKQ,GAHAL,EAAI,MAAQM,EACZ,QAAQ,IAAI,oBAAqBD,CAAQ,EAErC,CAACA,EAAU,CAEX,IADA3E,EAAO,KAAK,CAAC,EACNsE,EAAI,aACHA,EAAI,YAAc,IADF,CAEpB,MAAM5E,EAAI4E,EAAI,UAAS,EACvB,GAAI5E,EAAI8E,EAAS,MACjBxE,EAAO,KAAK0E,EAAOhF,CAAC,CAAC,CACrC,CAGY,OAFAM,EAAO,KAAK,CAAC,EAETyE,EACO,IAAI,MAAMA,CAAO,EAAE,KAAKzE,CAAM,EAAE,KAAI,EACxCA,CACnB,CAEQ,IAAI6E,EAAW,GACf,KAAOP,EAAI,aACHA,EAAI,YAAc,IADF,CAEpB,MAAMpF,EAAIoF,EAAI,UAAS,EACjB,EAAIpF,EAAI,EACd,GAAI,EAAIsF,EAAS,MACbtF,EAAI,GACC2F,GACD7E,EAAO,KAAK,CAAC,EACjBA,EAAO,KAAK0E,EAAO,CAAC,CAAC,EACrBG,EAAW,KAGPA,GACA7E,EAAO,KAAK,CAAC,EACjBA,EAAO,KAAK0E,EAAO,CAAC,CAAC,EACrBG,EAAW,GAE3B,CAIQ,OAHKA,GACD7E,EAAO,KAAK,CAAC,EAEbyE,EACO,IAAI,MAAMA,CAAO,EAAE,KAAKzE,CAAM,EAAE,KAAI,EACxCA,CACf,CACA,CCpHA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAYO,MAAM8E,CAAY,CACrB,OAAO,cAAcvG,EAAM,CACvB,GAAI,CACA,IAAM,KAAKA,CAAI,CAClB,MAAe,CACZ,MAAO,EACnB,CAEQ,GAAI,IAAI,OAAS,EACb,MAAO,GAGX,MAAMwG,EAAW,IAAI,WAAW,CAAC,EACjC,OAAIA,GAAY,KAAQA,GAAY,KAEzBA,GAAY,IADZ,IAGAA,GAAY,GACZ,GAInB,CAEI,OAAO,WAAWxG,EAAM,CACpB,IAAIQ,EAAO,CACP,OAAQ,CAAE,EACV,UAAW,EACX,QAAS,EACT,OAAQ,EACpB,EAEYF,EAAM,GACV,GAAI,CACAA,EAAM,KAAKN,CAAI,CAClB,MAAe,CACZ,OAAAQ,EAAK,OAAS,iBACd,QAAQ,KAAKA,EAAK,MAAM,EACjBA,CACnB,CAEQ,GAAIF,EAAI,OAAS,EACb,OAAAE,EAAK,OAAS,sBACd,QAAQ,KAAKA,EAAK,MAAM,EACjBA,EAGX,MAAMgG,EAAWlG,EAAI,WAAW,CAAC,EACjC,GAAIkG,GAAY,KAAQA,GAAY,IAChChG,EAAK,UAAY,gBACVgG,GAAY,IACnBhG,EAAK,UAAY,UACd,QAAIgG,GAAY,IACnBhG,EAAK,OAAS,wBACd,QAAQ,KAAKA,EAAK,OAAQgG,CAAQ,EAC3BhG,IAEPA,EAAK,OAAS,sBAAsBgG,EAAS,SAAS,EAAE,CAAC,IACzD,QAAQ,KAAKhG,EAAK,OAAQgG,CAAQ,EAC3BhG,GAGXA,EAAK,QAAUF,EAAI,WAAW,CAAC,GAEjBA,EAAI,WAAW,CAAC,EAAKA,EAAI,WAAW,CAAC,GAAK,GAC1C,GAAKA,EAAI,SACnBE,EAAK,OAAS,uBACd,QAAQ,KAAKA,EAAK,MAAM,GAG5B,QAASnC,EAAI,EAAGA,EAAIiC,EAAI,OAAQjC,IAAK,CACjC,IAAIiH,EAAQhF,EAAI,WAAWjC,CAAC,EACxBiH,GAAS,IACTA,EAAQhF,EAAI,WAAW,EAAEjC,CAAC,EAAKiC,EAAI,WAAW,EAAEjC,CAAC,GAAK,GAE1DmC,EAAK,OAAO,KAAK8E,CAAK,CAClC,CAEQ,OAAO9E,CACf,CACA,CC5FA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MA2BA,SAASiG,GAASjH,EAAM,CACpB,OAAO,IAAI,QAAQ,CAACkH,EAASC,IAAW,CACpC,IAAIlH,EAAS,IAAI,WACjBA,EAAO,QAAU,IAAM,CACnBkH,EAAOlH,EAAO,KAAK,CAC/B,EACQA,EAAO,OAAS,IAAM,CAClBiH,EAAQjH,EAAO,MAAM,CACjC,EACQA,EAAO,WAAWD,CAAI,CACzB,CAAA,CACL,CAII,OAAO,MAAQ,OAAO,YAAc,OAAO,UAAY,OAAO,MAG9D,MAAM,wDAAwD,EAIlE,IAAIoH,EAEJ,OAAO,iBAAiB,SAAU,UAAY,CAE1C,aAAaA,CAAW,EACxBA,EAAc,WAAW,UAAY,CAGjC,MAAMhH,EAAQ,IAAI,MAAM,iBAAiB,EACzC,OAAO,cAAcA,CAAK,CAElC,EAAO,GAAG,CAEV,EAAG,EAAK,EAQR,MAAMiH,GAAU,CACZ,IAAK,MACL,IAAK,MACL,IAAK,MACL,GAAI,KACJ,GAAI,KACJ,KAAM,OACN,IAAK,MACL,KAAM,MACV,EAOMC,GAAU,CACZ,cAAe,iBACf,eAAgB,kBAChB,uBAAwB,yBAC5B,EAEMC,GAAgB,CAClB,CAAE,KAAM,MAAO,MAAO,EAAI,EAC1B,CAAE,KAAM,MAAO,MAAO,KAAO,EAC7B,CAAE,KAAM,MAAO,MAAO,KAAO,EAC7B,CAAE,KAAM,MAAO,MAAO,KAAO,EAC7B,CAAE,KAAM,KAAM,MAAO,IAAM,EAC3B,CAAE,KAAM,KAAM,MAAO,IAAM,EAC3B,CAAE,KAAM,OAAQ,MAAO,MAAQ,EAC/B,CAAE,KAAM,MAAO,MAAO,KAAO,EAC7B,CAAE,KAAM,OAAQ,MAAO,MAAQ,CACnC,EAEMC,GAAgB,CAClB,CAAE,KAAM,MAAO,MAAO,EAAI,EAC1B,CAAE,KAAM,wBAAyB,MAAO,eAAiB,EACzD,CAAE,KAAM,kBAAmB,MAAO,gBAAkB,EACpD,CAAE,KAAM,0BAA2B,MAAO,wBAA0B,CACxE,EAOA,MAAMC,EAAU,CAIZ,WAAW,eAAgB,CACvB,OAAOF,EACf,CAII,WAAW,eAAgB,CACvB,OAAOC,EACf,CAsBI,YAAYE,EAAU,GAAI,CACtB,KAAK,UAAY,CACb,UAAWC,GAAS,SAASA,EAAO,EAAE,GAAK,EAC3C,OAAQA,GAASzI,EAAOmI,GAASM,CAAK,GAAK,GAC3C,OAAQA,GAASzI,EAAOoI,GAASK,CAAK,GAAK,EACvD,EACQ,MAAMC,EAAW,CACb,MAAO,EACP,OAAQ,EACR,KAAM,CAClB,EACQ,KAAK,SAASF,EAAQ,KAAK,EAC3B,MAAMG,EAAU,KAAK,eAAeH,EAAQ,MAAM,EAClDA,EAAU,OAAO,OAAO,CAAE,EAAEE,EAAUC,EAASH,CAAO,EAEtD,KAAK,IAAM,KAAK,OAAQ,EAAC,SAAU,EAAC,UAAU,CAAC,EAC/C,KAAK,OAAS1I,EAAS0I,EAAQ,MAAM,EACrC,KAAK,KAAOA,EAAQ,MAAQ,CAAA,EAC5B,KAAK,MAAQA,EAAQ,OAAS,KAAK,OAAO,YAC1C,KAAK,OAASA,EAAQ,OACtB,KAAK,IAAMA,EAAQ,IACnB,KAAK,IAAMA,EAAQ,IACnB,KAAK,QAAUA,EAAQ,QACvB,KAAK,QAAUA,EAAQ,QACvB,KAAK,UAAYA,EAAQ,UACzB,KAAK,OAASA,EAAQ,OACtB,KAAK,KAAOA,EAAQ,KACpB,KAAK,OAASA,EAAQ,OACtB,KAAK,WAAaA,EAAQ,WAC1B,KAAK,KAAOA,EAERA,EAAQ,MACR,KAAK,QAAQA,EAAQ,KAAMA,EAAQ,QAAQ,EAC3CA,EAAQ,YACR,KAAK,iBAAgB,EACrBA,EAAQ,YACR,KAAK,iBAAgB,EAErB,OAAO,gBAEP,KAAK,eAAiB,IAAI,eAAe,IAAM,CAC3C,KAAK,aAAY,CACpB,CAAA,EACD,KAAK,eAAe,QAAQ,KAAK,MAAM,GAGvC,OAAO,iBAAiB,kBAAmB,KAAM,EAAK,CAElE,CA+BI,SAASA,EAAS,CACd,IAAIE,EAAW,CACX,SAAU,OACV,OAAQ,sBACR,OAAQ,EACR,OAAQ,CAAE,EACV,SAAU,OACV,OAAQ,wBACR,OAAQ,EACR,OAAQ,CAAE,EACV,WAAY,OACZ,SAAU,EACV,SAAU,CAAE,EACZ,SAAU,OACV,QAAS,OACT,WAAY,OACZ,SAAU,CAAC,EAAG,CAAC,EACf,SAAU,EACV,cAAe,OACf,YAAa,CAAC,EAAG,CAAC,EAClB,YAAa,EACb,SAAU,OACV,cAAe,OACf,cAAe,OACf,cAAe,OACf,KAAM,iBAClB,EACQ,MAAME,EAAS,CAAA,EACf,OAAAA,EAAO,KAAO,CACV,SAAU,OACV,OAAQ,sBACR,OAAQ,EACR,OAAQ,CAAE,EACV,SAAU,OACV,OAAQ,wBACR,OAAQ,EACR,OAAQ,CAAE,EACV,WAAY,OACZ,SAAU,EACV,SAAU,CAAE,EACZ,SAAU,OACV,QAAS,OACT,WAAY,OACZ,SAAU,CAAC,EAAG,CAAC,EACf,SAAU,EACV,cAAe,OACf,YAAa,CAAC,EAAG,CAAC,EAClB,YAAa,EACb,SAAU,OACV,cAAe,OACf,cAAe,OACf,cAAe,OACf,KAAM,iBAClB,EACY,OAAOJ,GAAY,UAAYI,EAAOJ,CAAO,IAAGE,EAAWE,EAAOJ,CAAO,GAC7E,KAAK,MAAQ,OAAO,OAAO,CAAE,EAAEE,EAAUF,CAAO,EACzC,KAAK,aAAY,CAChC,CAOI,eAAeK,EAAS,IAAK,CACzB,MAAMC,EAAa,SAAS,KAAK,MAAM,KAAM,EAAE,GAAK,GAC9CC,EAAa,GAAK,CAAC,EAAEF,EAAS,IAC9BG,EAAa,EAAI,CAAC,EAAEH,EAAS,IASnC,MARe,CACX,OAAAA,EACA,IAAKE,EAAaC,EAClB,IAAKH,EAASC,EAAaE,EAC3B,QAASH,EAASC,EAClB,QAASC,EACT,UAAWF,CACvB,CAEA,CAKI,kBAAmB,CACf,GAAI,KAAK,WACL,OACJ,KAAK,WAAa,GAClB,MAAMI,EAAS,KAAK,WACL,CAAC,UAAU,EACnB,QAAQvI,GAAOuI,EAAO,iBAAiBvI,EAAK,KAAM,EAAK,CAAC,CACvE,CAKI,mBAAoB,CAChB,GAAI,CAAC,KAAK,WACN,OACJ,KAAK,WAAa,GAClB,MAAMuI,EAAS,KAAK,WACL,CAAC,UAAU,EACnB,QAAQvI,GAAOuI,EAAO,oBAAoBvI,EAAK,KAAM,EAAK,CAAC,CAC1E,CAKI,kBAAmB,CACf,GAAI,KAAK,SACL,OACJ,KAAK,SAAW,GAChB,MAAMuI,EAAS,KAAK,WACpB,IAAIC,EAAS,CAAC,YAAa,YAAa,UAAW,OAAO,EACrD,KAAK,YACNA,EAAO,KAAK,UAAU,EAEtB,iBAAkB,SAClBA,EAASA,EAAO,OAAO,aAAc,YAAa,UAAU,GAEhEA,EAAO,QAAQxI,GAAOuI,EAAO,iBAAiBvI,EAAK,KAAM,EAAK,CAAC,CACvE,CAKI,mBAAoB,CAChB,GAAI,CAAC,KAAK,SACN,OACJ,KAAK,SAAW,GAChB,MAAMuI,EAAS,KAAK,WACpB,IAAIC,EAAS,CAAC,YAAa,YAAa,UAAW,OAAO,EACrD,KAAK,YACNA,EAAO,KAAK,UAAU,EAEtB,iBAAkB,SAClBA,EAASA,EAAO,OAAO,aAAc,YAAa,UAAU,GAEhEA,EAAO,QAAQxI,GAAOuI,EAAO,oBAAoBvI,EAAK,KAAM,EAAK,CAAC,CAC1E,CAKI,SAAU,CAEN,KAAK,UAAW,KAAK,SAAS,QAAO,EAErC,KAAK,gBAAiB,KAAK,eAAe,WAAU,EACpD,OAAO,oBAAoB,kBAAmB,KAAM,EAAK,EACzD,KAAK,kBAAiB,CAC9B,CAEI,eAAeX,EAAmB,CAC9BA,EAAoBA,GAAqB,KAAK,OAAO,uBAAuB,UAAU,EAAE,CAAC,EACzF,MAAMU,EAAa,KAAK,QAAQ,KAAK,IAAI,EACzC,KAAK,SAAW,IAAID,EAAST,EAAmBU,CAAU,CAClE,CAEI,UAAU0I,EAAQ,CASd,GARIA,GAAUA,EAAO,WACjB,KAAK,OAASA,EACP,KAAK,MAAQ,KAAK,KAAK,WAC9B,KAAK,OAAS,KAAK,KAEnB,KAAK,OAAS,KAAK,MAGnB,CAAC,KAAK,KAAK,QAAU,CAAC,KAAK,KAAK,OAAO,OAAQ,OAEnD,MAAMC,EAAQjF,EAAW,KAAK,KAAK,OAAQ,KAAK,MAAM,EAGtD,GAFA,KAAK,KAAK,MAAQiF,EAAM,MACxB,KAAK,KAAK,KAAOA,EAAM,KACnBA,EAAM,KAAM,CACZ,MAAM9F,EAAU,KAAK,YACfT,EAAW,KAAK,aACtB,KAAK,SAAS,MAAMS,EAAST,CAAQ,EACrC,QAAQ,IAAIuG,EAAM,KAAK,YAAa,CAAA,EAChCvG,IACAA,EAAS,WAAa,sBAAsBuG,EAAM,KAAK,YAAW,CAAE,kBAEpF,CAEQ,KAAK,aAAY,CACzB,CAOI,UAAUC,EAAKZ,EAAO,CAClB,YAAKY,CAAG,EAAI,KAAK,UAAUA,CAAG,EAAEZ,CAAK,EAC9B,KAAK,YAAW,CAC/B,CAMI,WAAWa,EAAM,CACb,QAASD,KAAOC,EACZ,KAAKD,CAAG,EAAI,KAAK,UAAUA,CAAG,EAAEC,EAAKD,CAAG,CAAC,EAE7C,OAAO,KAAK,YAAW,CAC/B,CAMI,QAAQvH,EAAMyH,EAAU,CAgBhBzH,aAAgB,KAChBiG,GAASjG,CAAI,EAAE,KAAK0H,GAAQ,CACxB,KAAK,KAAO,KAAK,UAAUA,EAAM1H,CAAI,EACrC,KAAK,YAAW,CACnB,CAAA,EACM,MAAM,QAAQA,CAAI,GACzB,KAAK,KAAO,CAAE,OAAQA,CAAI,EAC1B,KAAK,YAAW,GACT,OAAOA,GAAS,UAEvB,KAAK,KAAO,KAAK,UAAUA,EAAMyH,CAAQ,EACzC,KAAK,YAAW,GACTzH,EAAK,QACZ,KAAK,KAAOA,EACZ,KAAK,YAAW,IAEhB,KAAK,KAAO,IAAI0E,GAAa1E,CAAI,EACjC,KAAK,YAAW,EAE5B,CAEI,UAAU0H,EAAMD,EAAW,GAAI,CAC3B,IAAIzH,EAAO,CACP,KAAMyH,EAAS,MAAQ,KACvB,KAAMA,EAAS,MAAQ,KACvB,KAAMA,EAAS,MAAQC,EAAK,OAC5B,iBAAkBD,EAAS,iBAC3B,aAAcA,EAAS,aACvB,OAAQ,CAAE,EACV,OAAQ,MACR,KAAM,KACN,MAAO,CACnB,EAEQ,MAAME,EAAQD,EAAK,MAAM;AAAA,CAAI,EAC7B,QAASlI,KAAQmI,EAAO,CACpB,GAAI,CAACnI,EAAM,SACX,GAAIA,EAAK,WAAW,YAAY,EAAG,CAC/BQ,EAAK,UAAYR,EAAK,MAAM,EAAE,EAC9B,MAAMC,EAAI,WAAWO,EAAK,SAAS,EAC/BA,EAAK,UAAU,SAAS,IAAI,EAC5BA,EAAK,MAAQP,EAAI,KACZO,EAAK,UAAU,SAAS,IAAI,EACjCA,EAAK,MAAQP,EACRO,EAAK,UAAU,SAAS,IAAI,EACjCA,EAAK,MAAQP,EAAI,IACZO,EAAK,UAAU,SAAS,GAAG,IAChCA,EAAK,MAAQP,EAAI,IACrC,CAcY,GAbID,EAAK,WAAW,UAAU,IAAGQ,EAAK,QAAUR,EAAK,MAAM,CAAC,GACxDA,EAAK,WAAW,MAAM,IAAGQ,EAAK,OAAS,OACvCR,EAAK,WAAW,MAAM,IAAGQ,EAAK,OAAS,OACvCR,EAAK,WAAW,QAAQ,IAAGQ,EAAK,MAAQR,EAAK,MAAM,CAAC,GACpDA,EAAK,WAAW,QAAQ,IAAGQ,EAAK,MAAQR,EAAK,MAAM,CAAC,GACpDA,EAAK,WAAW,aAAa,IAAGQ,EAAK,KAAOR,EAAK,MAAM,EAAE,GACzDA,EAAK,WAAW,aAAa,IAAGQ,EAAK,WAAaR,EAAK,MAAM,EAAE,GAC/DA,EAAK,WAAW,cAAc,IAAGQ,EAAK,YAAcR,EAAK,MAAM,EAAE,GACjEA,EAAK,WAAW,QAAQ,IAAGQ,EAAK,MAAQR,EAAK,MAAM,CAAC,GACpDA,EAAK,WAAW,OAAO,IAAGQ,EAAK,KAAOR,EAAK,MAAM,CAAC,GAClDA,EAAK,WAAW,MAAM,IAAGQ,EAAK,IAAMR,EAAK,MAAM,CAAC,GAChDA,EAAK,WAAW,QAAQ,IAAGQ,EAAK,MAAQR,EAAK,MAAM,CAAC,GACpDA,EAAK,WAAW,SAAS,IAAGQ,EAAK,OAASR,EAAK,MAAM,CAAC,GACtDA,EAAK,WAAW,GAAG,EAAG,SAE1B,GAAI2F,EAAM,QAAQ3F,CAAI,EAAG,CACrB,MAAMyB,EAASkE,EAAM,UAAU3F,CAAI,EACnCQ,EAAK,OAASA,EAAK,OAAO,OAAOiB,CAAM,EACvC,QAChB,CACY,GAAI8E,EAAY,cAAcvG,CAAI,EAAG,CACjC,MAAMoI,EAAU7B,EAAY,WAAWvG,CAAI,EAC3CQ,EAAK,OAASA,EAAK,OAAO,OAAO4H,EAAQ,MAAM,EAC/C,QAChB,CAEY,MAAMC,EAASrI,EAAK,MAAM,GAAG,EAC7B,QAASsI,KAASD,EACd,GAAIC,EAAM,OAAQ,CACd,MAAM3H,EAAI,SAAS2H,EAAO,EAAE,EAC5B9H,EAAK,OAAO,KAAKG,EAAIH,EAAK,KAAK,CACnD,CAEA,CAWQ,GAVAA,EAAK,MAAQ,WAAWA,EAAK,KAAK,EAClCA,EAAK,MAAQ,WAAWA,EAAK,KAAK,EAClCA,EAAK,KAAO,WAAWA,EAAK,IAAI,EAChCA,EAAK,WAAaA,EAAK,YAAc,WAAWA,EAAK,UAAU,EAC/DA,EAAK,YAAcA,EAAK,aAAe,WAAWA,EAAK,WAAW,EAClEA,EAAK,MAAQA,EAAK,OAAS,WAAWA,EAAK,KAAK,EAChDA,EAAK,KAAOA,EAAK,MAAQ,WAAWA,EAAK,IAAI,EAC7CA,EAAK,IAAMA,EAAK,KAAO,WAAWA,EAAK,GAAG,EAC1CA,EAAK,MAAQA,EAAK,OAAS,WAAWA,EAAK,KAAK,EAE5CA,EAAK,OAAQ,CACb,MAAM2E,EAAO3E,EAAK,OAAO,MAAM,GAAG,EAClCA,EAAK,WAAa2E,EAAK,CAAC,EACxB3E,EAAK,MAAQ2E,EAAK,CAAC,GAAK,WAAWA,EAAK,CAAC,CAAC,EAC1C3E,EAAK,KAAO2E,EAAK,CAAC,GAAK,WAAWA,EAAK,CAAC,CAAC,EACzC3E,EAAK,KAAO2E,EAAK,CAAC,GAAK,WAAWA,EAAK,CAAC,CAAC,EACzC3E,EAAK,IAAM2E,EAAK,CAAC,GAAK,WAAWA,EAAK,CAAC,CAAC,CACpD,CAEQ,OAAO3E,CACf,CAEI,IAAI,YAAa,CACb,OAAO,KAAK,OAAO,uBAAuB,kBAAkB,EAAE,CAAC,GAAK,KAAK,OAAO,qBAAqB,QAAQ,EAAE,CAAC,CACxH,CAEI,IAAI,cAAe,CACf,OAAO,KAAK,OAAQ,uBAAuB,oBAAoB,EAAE,CAAC,GAAK,KAAK,OAAQ,uBAAuB,UAAU,EAAE,CAAC,CAChI,CAEI,IAAI,aAAc,CACd,OAAO,KAAK,OAAO,uBAAuB,mBAAmB,EAAE,CAAC,CACxE,CAEI,IAAI,cAAe,CACf,OAAO,KAAK,OAAO,uBAAuB,oBAAoB,EAAE,CAAC,CACzE,CAEI,WAAY,CACR,GAAI,CAAC,KAAK,YAAc,CAAC,KAAK,aAC1B,OAGJ,MAAMA,EAAO,KAAK,MAAQ,CAAA,EACpB+H,EAAe/H,EAAK,OACpBgI,EAAahI,EAAK,KAClBiI,EAAavK,EAAUsK,EAAY,EAAI,EACvCE,EAAalI,EAAK,MAAQ,IAC1BmI,EAAcpK,GAAemK,EAAY,EAAI,EAC7CE,EAAcpI,EAAK,MAAQ,IAAUgI,EACrC/G,EAASjB,EAAK,QAAU,CAAA,EAExBqI,EAAerI,EAAK,kBAAoB,IAAI,KAAKA,EAAK,cAAgB,CAAC,EAEvEsI,EAAQ,CAAA,EAad,GAZAA,EAAM,KAAK,CAAE,KAAM,YAAa,MAAO/J,GAAMyB,EAAK,IAAI,CAAG,CAAA,EACzDsI,EAAM,KAAK,CAAE,KAAM,YAAa,MAAOtI,EAAK,MAAQ,KAAO,CAAA,EAC3DsI,EAAM,KAAK,CAAE,KAAM,YAAa,MAAO,GAAGtI,EAAK,IAAI,QAAU,CAAA,EAC7DsI,EAAM,KAAK,CAAE,KAAM,gBAAiB,MAAOD,EAAa,aAAe,CAAA,EACvEC,EAAM,KAAK,CAAE,KAAM,gBAAiB,MAAOP,CAAc,CAAA,EACzDO,EAAM,KAAK,CAAE,KAAM,iBAAkB,MAAO,GAAGF,EAAY,QAAQ,CAAC,CAAC,IAAM,CAAA,EACvEJ,EAAa,GACbM,EAAM,KAAK,CAAE,KAAM,cAAe,MAAO,GAAGN,EAAaC,EAAW,KAAK,GAAGA,EAAW,MAAM,EAAI,CAAA,EACrGK,EAAM,KAAK,CAAE,KAAM,gBAAiB,MAAO,GAAGrH,EAAO,OAAS,CAAC,IAAM,CAAA,EACjE+G,EAAa,GACbM,EAAM,KAAK,CAAE,KAAM,gBAAiB,MAAO,IAAIJ,EAAaC,EAAY,OAAO,QAAQ,CAAC,CAAC,IAAIA,EAAY,MAAM,EAAI,CAAA,EAEnH,KAAK,WACL,KAAK,WAAWG,CAAK,MAClB,CACH,IAAIZ,EAAO,GACX,QAASa,KAAQD,EACbZ,GAAQ,gBAAgBa,EAAK,IAAI,KAAKA,EAAK,KAAK,UAEpD,MAAMC,EAAO,KAAK,aAClBA,EAAK,UAAYd,CAC7B,CACA,CAII,YAAY5I,EAAG,CAEX,MAAMI,EAAUJ,EAAE,KAClB,GAAI,OAAO,KAAKI,CAAO,GAAM,WACzB,OAAO,KAAKA,CAAO,EAAEJ,CAAC,CAElC,CAEI,MAAMA,EAAG,CAGL,IAAI2J,EAAU,GACV3J,EAAE,SACF,KAAK,QAAUA,EAAE,OAAS,GAC1B2J,EAAU,IAId,MAAMC,EAAU,GACVC,EAAU,KAAK,KAAK,MAAQ,KAAK,MAAQ,GAE/C,IAAIC,EACA9J,EAAE,OAAS,EACX8J,EAAO,KAAK,MAAQ,EAAI9J,EAAE,OAAS,KAEnC8J,EAAO,KAAK,MAAQ,EAAI9J,EAAE,OAAS,IAEnC8J,EAAOF,IAASE,EAAOF,GACvBE,EAAOD,IAASC,EAAOD,GAEvB,KAAK,MAAQC,IACb,KAAK,QAAU,KAAK,OAAS9J,EAAE,QAAU,KAAK,KAAO8J,EAAO9J,EAAE,OAC9D,KAAK,KAAO8J,EACZH,EAAU,IAIVA,GAAS,KAAK,aAAY,EAK9B3J,EAAE,eAAc,CACxB,CAEI,SAASA,EAAG,CACJ,KAAK,YAAc,CAAC,KAAK,SACzB,KAAK,iBAAgB,EAEhB,KAAK,YAAc,KAAK,SAC7B,KAAK,kBAAiB,GAEjB,KAAK,MAAQ,GAAK,KAAK,QAAU,KACtC,KAAK,OAAS,EACd,KAAK,KAAO,EACZ,KAAK,aAAY,GAErBA,EAAE,eAAc,CACxB,CAEI,UAAUA,EAAG,CACT,KAAK,MAAQA,EAAE,QACf,KAAK,MAAQA,EAAE,QACf,KAAK,SAAW,KAAK,OACrB,KAAK,OAAS,GACdA,EAAE,eAAc,CACxB,CAEI,QAAQA,EAAG,CACP,KAAK,OAAS,GACdA,EAAE,eAAc,CACxB,CAEI,UAAUA,EAAG,CACJ,KAAK,SACV,KAAK,aAAa,KAAK,MAAQA,EAAE,QAAS,KAAK,MAAQA,EAAE,OAAO,EAChEA,EAAE,gBAAe,EACjBA,EAAE,eAAc,EACxB,CAEI,WAAWA,EAAG,CAGV,MAAM+J,EAAa/J,EAAE,OAAO,sBAAqB,EAE3CgK,EAAIhK,EAAE,cAAc,CAAC,EACrBiK,EAAUD,EAAE,QAAUD,EAAW,KACjCG,EAAUF,EAAE,QAAUD,EAAW,IAEvC,KAAK,MAAQE,EACb,KAAK,MAAQC,EACb,KAAK,SAAW,KAAK,OACrB,KAAK,OAAS,GAEVlK,EAAE,cAAc,OAAS,GACzBA,EAAE,eAAc,CAC5B,CAEI,YAAYA,EAAG,CACPA,EAAE,cAAc,OAAS,IACzB,KAAK,OAAS,GACd,KAAK,SAAW,GAE5B,CAEI,SAASA,EAAG,CACJA,EAAE,cAAc,OAAS,IACzB,KAAK,OAAS,GACd,KAAK,SAAW,GAE5B,CAEI,UAAUA,EAAG,CAET,MAAM+J,EAAa/J,EAAE,OAAO,sBAAqB,EAEjD,IAAImK,EAAKnK,EAAE,cAAc,CAAC,EAC1B,GAAI,CAAC,KAAK,UAAYA,EAAE,cAAc,QAAU,EAAG,CAE/C,MAAMiK,EAAUE,EAAG,QAAUJ,EAAW,KAClCG,EAAUC,EAAG,QAAUJ,EAAW,IAExC,KAAK,aAAa,KAAK,MAAQE,EAAS,KAAK,MAAQC,CAAO,CACxE,SACiBlK,EAAE,cAAc,QAAU,EAAG,CAElC,KAAK,OAAS,GACd,MAAMoK,EAAKpK,EAAE,cAAc,CAAC,EACtBqK,EAAOF,EAAG,QAAUC,EAAG,QAAUA,EAAG,QAAUD,EAAG,QAAUA,EAAG,QAAUC,EAAG,QAC5E,KAAK,WACN,KAAK,SAAW,KAAK,KACrB,KAAK,SAAWC,GAEpB,MAAMC,GAAaH,EAAG,QAAUC,EAAG,SAAW,EACxCG,EAAYF,EAAO,KAAK,SACxBP,EAAO,KAAK,SAAWS,EAC7B,KAAK,QAAU,KAAK,OAASD,GAAa,KAAK,KAAOR,EAAOQ,EAC7D,KAAK,KAAOR,EAEZ,KAAK,aAAY,EACjB9J,EAAE,eAAc,CAC5B,CAEQA,EAAE,gBAAe,CACzB,CAEI,iBAAkB,CACd,KAAK,MAAQ,KAAK,KAAK,OAAS,KAAK,OAAO,YAE5C,KAAK,WAAU,CACvB,CAII,aAAc,CACV,GAAI,CAAC,KAAK,KAAK,QAAU,CAAC,KAAK,KAAK,OAAO,OAAQ,OAEnD,IAAI4B,EAAQ,EACZ,QAASM,EAAI,EAAGA,EAAI,KAAK,KAAK,OAAO,OAAQ,EAAEA,EAC3CN,GAAS,KAAK,KAAK,OAAOM,CAAC,EAE/B,KAAK,KAAK,MAAQN,EAGlB,MAAMc,EAAU,KAAK,YACfT,EAAW,KAAK,aAChBuI,EAAW,IAAIxI,GAAS,KAAK,KAAK,MAAM,EAC9CwI,EAAS,YAAW,EACpBA,EAAS,MAAM9H,EAAST,CAAQ,EAChC,KAAK,SAAWuI,EAChB,KAAK,MAAQA,EAAS,MAAK,EAGvB,KAAK,SAEE,KAAK,KAAK,WACjB,KAAK,OAAS,KAAK,KAEnB,KAAK,OAAS,KAAK,OAEvB,MAAMhC,EAAQjF,EAAW,KAAK,KAAK,OAAQ,KAAK,MAAM,EACtD,KAAK,KAAK,MAAQiF,EAAM,MACxB,KAAK,KAAK,KAAOA,EAAM,KACnBA,EAAM,OACN,QAAQ,IAAIA,EAAM,KAAK,YAAa,CAAA,EAChCvG,IACAA,EAAS,WAAa,sBAAsBuG,EAAM,KAAK,YAAW,CAAE,oBAI5E,KAAK,UAAS,EAEd,KAAK,WAAU,CACvB,CAEI,aAAapE,EAAU,CAEnB,KAAK,OAAS,KAAK,SAAWA,EAE9B,KAAK,aAAY,CACzB,CAEI,cAAe,CACX,OAAO,sBAAsB,KAAK,WAAW,KAAK,IAAI,CAAC,CAC/D,CAEI,YAAa,CACT,KAAK,MAAQ,KAAK,KAAK,OAAS,KAAK,OAAO,YAE5C,MAAMxC,EAAQ,KAAK,MACbqG,EAAS,KAAK,OAEdI,EAAS,KAAK,WACpBA,EAAO,MAAQzG,EACfyG,EAAO,OAASJ,EAIhB,MAAMwC,EAAMpC,EAAO,WAAW,IAAI,EAE5BqC,EAAS,CAAC,KAAK,OACfC,EAAQ/I,EAAQ,KAAK,KAAO,KAAK,KAAK,MACtCgJ,EAAM,KAAK,IAAM,GACjBC,EAAM,KAAK,IAAM,GAGvBJ,EAAI,KAAO,KAAK,MAAM,KACtB,MAAMK,EAAcL,EAAI,YAAY,GAAG,EACjCM,EAAQD,EAAY,MACpBE,EAAQF,EAAY,wBAA2BA,EAAY,yBAE3DG,EAAa,KAAK,KAAK,MAAQ,IAAU,KAAK,KAC9CC,EAAcR,EAAS9I,EAAQqJ,EAC/BE,EAAavM,EAAUqM,EAAY,EAAI,EACvCG,EAAoBH,EAAaE,EAAW,MAC5CE,EAAqBH,EAAcC,EAAW,MAEpDV,EAAI,UAAY,KAAK,MAAM,cAC3BA,EAAI,SAAS,KAAKU,EAAW,MAAM,KAAM,GAAIH,CAAK,EAG9C,KAAK,KAAK,MACVP,EAAI,SAAS,GAAG,KAAK,KAAK,IAAI,GAAI,IAAKO,CAAK,GAC5C,KAAK,KAAK,QAAU,KAAK,KAAK,MAC9BP,EAAI,SAAS,IAAI,KAAK,KAAK,QAAU,KAAK,KAAK,KAAK,YAAa,CAAA,GAAI,IAAKO,CAAK,EAC/E,KAAK,KAAK,QACVP,EAAI,SAAS,GAAG,KAAK,KAAK,OAAO,OAAS,CAAC,UAAW,IAAKO,CAAK,EACpE,MAAMM,EAAU,KAAK,KAAK,SAAW,KAAK,KAAK,eAAiB,KAAK,KAAK,MAAQ,KAAK,KAAK,WAC5F,GAAIA,EAAS,CACT,MAAMX,EAAQ/L,EAAU0M,EAAS,EAAI,EACrCb,EAAI,SAAS,GAAGa,EAAUX,EAAM,KAAK,IAAIA,EAAM,MAAM,KAAM,IAAKK,CAAK,CACjF,CACQ,MAAMO,EAAU,KAAK,KAAK,SAAW,KAAK,KAAK,eAAiB,KAAK,KAAK,WACpEC,EAAW,KAAK,KAAK,UAAY,KAAK,KAAK,MACjD,GAAIA,EAAU,CACV,MAAMb,EAAQ/L,EAAU4M,EAAU,EAAI,EACtCf,EAAI,SAAS,IAAIe,EAAWb,EAAM,OAAO,QAAQ,CAAC,CAAC,IAAIA,EAAM,MAAM,KAAM,IAAKK,CAAK,CAC/F,CACQ,GAAIO,GAAWC,EAAU,CACrBf,EAAI,UAAY,KAAK,MAAM,cAC3BA,EAAI,SAAS,IAAK,CAAC,EAAEO,EAAQ,GAAI,IAAK,CAAC,EACvCP,EAAI,UAAY,KAAK,MAAM,cAE3B,MAAMgB,GAAMD,EAAW,KAAK,KAAK,SAAW,IAAMF,EAAU,GAC5Db,EAAI,UAAY,KAAK,MAAM,OAC3BA,EAAI,YAAc,KAAK,MAAM,SAC7BA,EAAI,UAAS,EACbA,EAAI,OAAO,IAAMgB,EAAI,CAAC,EACtBhB,EAAI,OAAO,IAAMgB,EAAIT,CAAK,EAC1BP,EAAI,OAAM,CACtB,CACQ,MAAMiB,EAAW,KAAK,KAAK,UAAY,KAAK,KAAK,MACjD,GAAIA,EAAU,CACV,MAAMf,EAAQ/L,EAAU8M,EAAU,EAAI,EACtCjB,EAAI,SAAS,IAAIiB,EAAWf,EAAM,OAAO,QAAQ,CAAC,CAAC,IAAIA,EAAM,MAAM,KAAM,IAAKK,CAAK,CAC/F,CACQ,GAAIO,GAAWG,EAAU,CACrB,MAAMD,GAAMC,EAAW,KAAK,KAAK,SAAW,IAAMJ,EAAU,GAC5Db,EAAI,UAAY,KAAK,MAAM,OAC3BA,EAAI,YAAc,KAAK,MAAM,SAC7BA,EAAI,UAAS,EACbA,EAAI,OAAO,IAAMgB,EAAI,CAAC,EACtBhB,EAAI,OAAO,IAAMgB,EAAIT,CAAK,EAC1BP,EAAI,OAAM,CACtB,CACQ,MAAMkB,EAAW,KAAK,KAAK,UAAY,KAAK,KAAK,OAAS,GACpDC,EAAU,KAAK,KAAK,SAAW,KAAK,KAAK,KACzCC,EAAS,KAAK,KAAK,QAAU,KAAK,KAAK,IACvCC,EAAW,KAAK,KAAK,UAAY,KAAK,KAAK,MAC7CF,GAAWC,GAAUC,IACrBrB,EAAI,UAAY,EAChBA,EAAI,YAAc,KAAK,MAAM,SAC7BA,EAAI,UAAS,EACbA,EAAI,OAAO,IAAKO,CAAK,EACrBP,EAAI,OAAO,IAAMO,CAAK,EACtBP,EAAI,OAAM,EAEVA,EAAI,UAAY,KAAK,MAAM,OAC3BA,EAAI,YAAc,KAAK,MAAM,SAC7BA,EAAI,UAAS,EACbA,EAAI,OAAO,IAAOqB,EAAW,IAAMH,EAAUX,CAAK,EAClDP,EAAI,OAAO,IAAOmB,EAAU,IAAMD,EAAUX,CAAK,EACjDP,EAAI,OAAM,EAEVA,EAAI,SAAS,QAAQqB,EAAS,QAAQ,CAAC,CAAC,IAAID,EAAO,QAAQ,CAAC,CAAC,IAAID,EAAQ,QAAQ,CAAC,CAAC,MAAO,IAAKZ,CAAK,GAIxG,MAAMe,GAAmBnK,EAAQ,GACjC,IAAIoK,EAAoBZ,EAAoBW,GAE5CC,EAAoB,CAAC,EAAEA,EAAoB,GAAK,EAC5CA,EAAoB,IAAKA,EAAoB,GAEjD,MAAMC,EAAiBrK,EAAQwJ,EAGzBc,GAAI,GACVzB,EAAI,UAAY,KAAK,MAAM,cAC3B,QAAST,EAAIqB,EAAoBrB,EAAIoB,EAAmBpB,GAAKgC,EAAoB,EAAG,CAC5EhC,GAAKoB,EAAoBY,IACzBhC,EAAIoB,GACR,MAAMhH,EAAI,CAAC,EAAE4F,EAAIiC,GACjBxB,EAAI,SAASrG,EAAG8H,GAAI,GAAI,EAAG,CAAC,CACxC,CAEQzB,EAAI,UAAY,KAAK,MAAM,cAC3B,QAAST,EAAIqB,EAAoBrB,EAAIoB,EAAmBpB,GAAKgC,EAAmB,CACxEhC,GAAKoB,EAAoBY,IACzBhC,EAAIoB,GACR,MAAMhH,EAAI,CAAC,EAAE4F,EAAIiC,GACjBxB,EAAI,SAASrG,EAAG8H,GAAI,EAAG,EAAG,EAAE,EAE5B,MAAMC,GAASnC,EAAIqB,GAAoB,QAAQ,CAAC,EAChD,IAAInG,EAAKd,EAAI,EAAI+H,EAAM,OACnBnC,GAAKoB,IACLlG,EAAKd,EAAI,EAAI2G,GAEjBN,EAAI,SAAS0B,EAAOjH,EAAI,EAAE,CACtC,CAGQuF,EAAI,UAAY,KAAK,MAAM,SAC3BA,EAAI,YAAc,KAAK,MAAM,WAC7BA,EAAI,YAAY,KAAK,MAAM,QAAQ,EACnCA,EAAI,UAAS,EACb,IAAI2B,EACJ,QAASlK,EAAI,EAAG,KAAK,KAAK,OAASA,EAAI,KAAK,KAAK,MAAM,OAAQA,GAAK,EAAG,CACnE,MAAMmK,EAAO,KAAK,KAAK,MAAMnK,CAAC,EACxB+C,EAAKoH,EAAK,CAAC,EAAI1B,EAAQD,EACvBxF,EAAKmH,EAAK,CAAC,EAAI1B,EAAQD,EACzB0B,GAAMnH,GAAMA,GAAM,GAAKA,EAAKrD,IAC5B6I,EAAI,OAAO,CAAC,CAACxF,EAAK,GAAK,KAAK,QAAU,EAAG,EACzCwF,EAAI,OAAO,CAAC,CAACxF,EAAK,GAAK,KAAK,QAAU,EAAG,GAEzCC,GAAM,GAAKA,EAAKtD,IAChB6I,EAAI,OAAO,CAAC,CAACvF,EAAK,GAAK,KAAK,QAAU,EAAG,EACzCuF,EAAI,OAAO,CAAC,CAACvF,EAAK,GAAK,KAAK,QAAU,EAAG,GAE7CkH,EAAKlH,CACjB,CACQuF,EAAI,OAAM,EACVA,EAAI,YAAY,CAAE,CAAA,EAGlBA,EAAI,UAAY,KAAK,MAAM,YAC3BA,EAAI,YAAc,KAAK,MAAM,cAC7BA,EAAI,YAAY,KAAK,MAAM,WAAW,EACtCA,EAAI,UAAS,EACb2B,EAAK,KACL,QAASlK,EAAI,EAAG,KAAK,KAAK,OAASA,EAAI,KAAK,KAAK,MAAM,OAAQA,GAAK,EAAG,CACnE,MAAMmK,EAAO,KAAK,KAAK,MAAMnK,CAAC,EACxB+C,EAAKoH,EAAK,CAAC,EAAI1B,EAAQD,EACvBxF,EAAKmH,EAAK,CAAC,EAAI1B,EAAQD,EACzB0B,GAAMnH,IACFmH,GAAMA,GAAM,GAAKA,EAAKxK,IACtB6I,EAAI,OAAO,CAAC,CAAC2B,EAAK,GAAK,KAAK,QAAU,EAAG,EACzC3B,EAAI,OAAO,CAAC,CAAC2B,EAAK,GAAK,KAAK,QAAU,EAAG,GAEzCnH,GAAM,GAAKA,EAAKrD,IAChB6I,EAAI,OAAO,CAAC,CAACxF,EAAK,GAAK,KAAK,QAAU,EAAG,EACzCwF,EAAI,OAAO,CAAC,CAACxF,EAAK,GAAK,KAAK,QAAU,EAAG,IAGjDmH,EAAKlH,CACjB,CACQuF,EAAI,OAAM,EACVA,EAAI,YAAY,CAAE,CAAA,EAGlBA,EAAI,UAAY,KAAK,MAAM,SAC3BA,EAAI,UAAS,EACb,QAASvI,EAAI,EAAG,KAAK,KAAK,OAASA,EAAI,KAAK,KAAK,MAAM,OAAQA,GAAK,EAAG,CACnE,MAAMmK,EAAO,KAAK,KAAK,MAAMnK,CAAC,EACxB+C,EAAKoH,EAAK,CAAC,EAAI1B,EAAQD,EACvBxF,EAAKmH,EAAK,CAAC,EAAI1B,EAAQD,EACvBV,EAAIqC,EAAK,CAAC,EACV7L,EAAI0E,EAAKD,EACf,GAAIzE,EAAIuK,EAAO,CACX,MAAMuB,EAAKrH,EAAKzE,EAAI,EAChB8L,GAAM,GAAKA,EAAK1K,GAChB6I,EAAI,SAAST,EAAGsC,EAAK,EAAG,KAAK,SAAS,CAC1D,CACA,CAGQ,GAFA7B,EAAI,OAAM,EAEN,CAAC,KAAK,KAAK,QAAU,CAAC,KAAK,KAAK,OAAO,OAAQ,OAGnD,IAAIrG,EAAIsG,EACRD,EAAI,UAAY,KAAK,MAAM,OAC3BA,EAAI,YAAc,KAAK,MAAM,SAC7BA,EAAI,YAAY,KAAK,MAAM,MAAM,EACjCA,EAAI,UAAY,KAAK,MAAM,OAC3BA,EAAI,UAAS,EACb,QAASvI,EAAI,EAAGA,EAAI,KAAK,KAAK,OAAO,OAAQA,GAAK,EAAG,CACjD,MAAM+C,EAAKb,EACXA,GAAK,KAAK,KAAK,OAAOlC,CAAC,EAAIyI,GACtB1F,GAAM,GAAKA,EAAKrD,GAAWwC,GAAK,GAAKA,EAAIxC,GAAWqD,EAAK,GAAKb,EAAIxC,KACnE6I,EAAI,SAAS,CAAC,CAACxF,EAAI2F,EAAK,CAAC,EAAExG,EAAIa,GAAK4F,EAAMD,CAAG,EAC7CH,EAAI,OAAO,CAAC,CAACxF,EAAK,EAAG2F,CAAG,EACxBH,EAAI,OAAO,CAAC,CAACrG,EAAI,EAAGwG,CAAG,GAE3BxG,GAAK,KAAK,KAAK,OAAOlC,EAAI,CAAC,EAAIyI,CAC3C,CACQF,EAAI,OAAM,EAGVrG,EAAIsG,EACJD,EAAI,UAAY,KAAK,MAAM,OAC3BA,EAAI,YAAc,KAAK,MAAM,SAC7BA,EAAI,YAAY,KAAK,MAAM,MAAM,EACjCA,EAAI,UAAY,KAAK,MAAM,OAC3BA,EAAI,UAAS,EACb,QAASvI,EAAI,EAAGA,EAAI,KAAK,KAAK,OAAO,OAAQA,GAAK,EAAG,CACjDkC,GAAK,KAAK,KAAK,OAAOlC,CAAC,EAAIyI,EAC3B,MAAM1F,EAAKb,EACXA,GAAK,KAAK,KAAK,OAAOlC,EAAI,CAAC,EAAIyI,GAC1B1F,GAAM,GAAKA,EAAKrD,GAAWwC,GAAK,GAAKA,EAAIxC,GAAWqD,EAAK,GAAKb,EAAIxC,KACnE6I,EAAI,SAAS,CAAC,CAACxF,EAAI2F,EAAK,CAAC,EAAExG,EAAIa,GAAK4F,EAAMD,CAAG,EAC7CH,EAAI,OAAO,CAAC,CAACxF,EAAK,EAAG4F,CAAG,EACxBJ,EAAI,OAAO,CAAC,CAACrG,EAAI,EAAGyG,CAAG,EAEvC,CACQJ,EAAI,OAAM,EAGVrG,EAAIsG,EACJD,EAAI,UAAY,KAAK,MAAM,SAC3BA,EAAI,YAAc,KAAK,MAAM,WAC7BA,EAAI,YAAY,KAAK,MAAM,QAAQ,EACnCA,EAAI,UAAS,EACb,QAASvI,EAAI,EAAGA,EAAI,KAAK,KAAK,OAAO,OAAQA,GAAK,EAC1CkC,GAAK,GAAKA,EAAIxC,IACd6I,EAAI,OAAO,CAAC,CAACrG,EAAI,GAAKyG,EAAM,EAAG,EAC/BJ,EAAI,OAAO,CAAC,CAACrG,EAAI,GAAKwG,EAAM,EAAG,GAEnCxG,GAAK,KAAK,KAAK,OAAOlC,CAAC,EAAIyI,EAE/BF,EAAI,OAAM,EAGVrG,EAAIsG,EACJD,EAAI,UAAY,KAAK,MAAM,SAC3B,MAAM8B,GAAQ3B,GAAOC,EAAMD,EAAMI,GAAS,EAC1C,QAAS9I,EAAI,EAAGA,EAAI,KAAK,KAAK,OAAO,OAAQA,GAAK,EAAG,CACjD,MAAMsE,EAAI,KAAK,KAAK,OAAOtE,CAAC,EACtB,EAAIsE,EAAImE,EACd,GAAI,EAAI,GAAI,CACR,MAAM1F,EAAKb,EAAI,EAAI,EACfa,GAAM,GAAKA,EAAKrD,GAChB6I,EAAI,SAASjE,EAAGvB,EAAK,GAAIsH,EAAK,CAClD,CACYnI,GAAK,CACjB,CAGQ,MAAMoI,EAAO,IAAU,KAAK,KAAK,KAAO7B,EAExC,GADAvG,EAAIsG,EACA8B,EAAO,EAAG,CACV,MAAMC,EAAOD,EAAO,EAAI,EAAI,EAC5B/B,EAAI,UAAY,KAAK,MAAM,QAC3B,QAASvI,EAAI,EAAGA,EAAI,KAAK,KAAK,OAAO,OAAQA,GAAK,EAAG,CACjD,MAAMoD,EAAO,KAAK,KAAK,OAAOpD,CAAC,EAAIyI,EACnC,QAASpG,EAAI,EAAGA,EAAIe,EAAOkH,EAAMjI,GAAKiI,EAAM,CACxC,MAAMvH,EAAK,CAAC,EAAEb,EAAIG,GACdU,GAAM,GAAKA,EAAKrD,GAChB6I,EAAI,SAASxF,EAAI2F,EAAM,GAAK6B,EAAM,CAAC,CAC3D,CACgBrI,GAAKkB,EACL,MAAME,EAAQ,KAAK,KAAK,OAAOtD,EAAI,CAAC,EAAIyI,EACxC,QAASpG,EAAI,EAAGA,EAAIiB,EAAQgH,EAAMjI,GAAKiI,EAAM,CACzC,MAAMvH,EAAK,CAAC,EAAEb,EAAIG,GACdU,GAAM,GAAKA,EAAKrD,GAChB6I,EAAI,SAASxF,EAAI4F,EAAM,IAAK4B,EAAM,CAAC,CAC3D,CACgBrI,GAAKoB,CACrB,CACA,CACA,CACA,CC9lCO,SAASkH,IAAW,CACvB,IAAIC,EAAQ,CAAA,EACZ,QAASnN,KAAOoN,EAAO,CACnB,MAAMC,EAAOD,EAAMpN,CAAG,EACtBmN,EAAM,KAAK,CAAC,MAAOE,EAAK,KAAM,IAAKrN,EAAK,MAAOqN,CAAI,CAAC,CAC5D,CACI,OAAOF,CACX,CAEO,MAAMC,EAAQ,CACjB,WAAY,CACR,KAAM,aACN,OAAQ,MACR,KAAM,KACN,UAAW,MACX,WAAY,KACZ,WAAY,GACZ,SAAU,SACV,aAAc,GACd,SAAU,GACV,SAAU,GACV,QAAS,2EACT,eAAgB,GAChB,UAAW,GACX,cAAe,GACf,MAAO,IACP,IAAK,EACL,OAAQ,EACR,OAAQ,CACX,EACD,WAAY,CACR,KAAM,aACN,OAAQ,MACR,KAAM,KACN,UAAW,MACX,WAAY,KACZ,WAAY,GACZ,SAAU,GACV,aAAc,GACd,SAAU,GACV,SAAU,GACV,QAAS,yCAGT,eAAgB,GAChB,UAAW,GACX,cAAe,CAAC,EAAG,KAAK,EACxB,MAAO,IACP,IAAK,EACL,OAAQ,EACR,OAAQ,EACX,EACD,SAAU,CACN,KAAM,iBACN,OAAQ,MACR,KAAM,KACN,UAAW,MACX,WAAY,MACZ,WAAY,GACZ,SAAU,eACV,aAAc,GACd,SAAU,OACV,SAAU,GACV,QAAS,2DACT,eAAgB,GAChB,UAAW,GACX,cAAe,GACf,MAAO,IACP,KAAM,GACN,IAAK,EACL,OAAQ,EACR,OAAQ,CACX,EACD,OAAQ,CACJ,KAAM,gBACN,OAAQ,MACR,KAAM,KACN,UAAW,MACX,WAAY,MACZ,WAAY,GACZ,SAAU,WACV,aAAc,GACd,SAAU,GACV,SAAU,GACV,QAAS,OACT,eAAgB,GAChB,UAAW,GACX,cAAe,GACf,MAAO,IACP,KAAM,IACN,IAAK,EACL,OAAQ,EACR,OAAQ,EACX,EACD,WAAY,CACR,KAAM,aACN,OAAQ,MACR,KAAM,KACN,UAAW,MACX,WAAY,MACZ,WAAY,GACZ,SAAU,GACV,aAAc,CAAC,IAAK,IAAI,EACxB,SAAU,GACV,SAAU,GACV,QAAS,mBACT,eAAgB,GAChB,UAAW,GACX,cAAe,GACf,MAAO,IACP,MAAO,IACP,KAAM,KACN,IAAK,IACL,OAAQ,GACR,OAAQ,GACX,EACD,eAAgB,CACZ,KAAM,kBACN,OAAQ,MACR,KAAM,KACN,UAAW,MACX,WAAY,MACZ,WAAY,GACZ,SAAU,GACV,aAAc,CAAC,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,GAAG,EACrD,SAAU,GACV,SAAU,GACV,QAAS,aACT,eAAgB,GAChB,UAAW,GACX,cAAe,GACf,MAAO,IACP,KAAM,IACN,KAAM,IACN,UAAW,IACX,SAAU,IACV,IAAK,IACL,OAAQ,GACR,OAAQ,GACX,EACD,aAAc,CACV,KAAM,uBACN,OAAQ,MACR,KAAM,KACN,UAAW,MACX,WAAY,MACZ,WAAY,GACZ,SAAU,WACV,aAAc,GACd,SAAU,GACV,SAAU,GACV,QAAS,OACT,eAAgB,GAChB,UAAW,GACX,cAAe,GACf,MAAO,IACP,KAAM,IACN,UAAW,IACX,SAAU,IACV,IAAK,EACL,OAAQ,EACR,OAAQ,GACX,EACD,eAAgB,CACZ,KAAM,iBACN,OAAQ,MACR,KAAM,KACN,UAAW,MACX,WAAY,OACZ,WAAY,GACZ,SAAU,uFACV,aAAc,GACd,SAAU,GACV,SAAU,GACV,QAAS,+DACT,eAAgB,GAChB,UAAW,GACX,cAAe,CAAC,EAAG,GAAK,EACxB,MAAO,GACP,KAAM,GACN,IAAK,EACL,OAAQ,EACR,OAAQ,CACX,CACL"}