sequenceserver 3.1.2 → 3.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/sequenceserver/blast/tasks.rb +1 -1
- data/lib/sequenceserver/routes.rb +1 -1
- data/lib/sequenceserver/version.rb +1 -1
- data/lib/sequenceserver.rb +1 -1
- data/public/css/app.min.css +1 -1
- data/public/css/sequenceserver.css +0 -18
- data/public/css/sequenceserver.min.css +2 -2
- data/public/js/alignment_exporter.js +16 -28
- data/public/js/cloud_share_modal.js +42 -42
- data/public/js/form.js +12 -10
- data/public/js/grapher.js +4 -4
- data/public/js/hit.js +3 -3
- data/public/js/hits.js +276 -0
- data/public/js/jquery_world.js +1 -1
- data/public/js/mailto.js +1 -3
- data/public/js/null_plugins/report_plugins.js +1 -0
- data/public/js/options.js +2 -6
- data/public/js/query.js +1 -1
- data/public/js/report.js +68 -252
- data/public/js/report_root.js +7 -5
- data/public/js/search.js +28 -11
- data/public/js/sequence.js +158 -158
- data/public/js/sequence_modal.js +28 -36
- data/public/js/sidebar.js +7 -6
- data/public/js/tests/alignment_exporter.spec.js +38 -0
- data/public/js/tests/cloud_share_modal.spec.js +75 -0
- data/public/js/tests/report.spec.js +37 -15
- data/public/packages/jquery-ui@1.13.3.js +19070 -0
- data/public/sequenceserver-report.min.js +3 -2481
- data/public/sequenceserver-report.min.js.LICENSE.txt +300 -0
- data/public/sequenceserver-report.min.js.map +1 -0
- data/public/sequenceserver-search.min.js +3 -2382
- data/public/sequenceserver-search.min.js.LICENSE.txt +292 -0
- data/public/sequenceserver-search.min.js.map +1 -0
- data/views/layout.erb +3 -7
- data/views/search.erb +1 -1
- data/views/search_layout.erb +1 -1
- metadata +11 -5
- data/public/config.js +0 -147
- data/public/packages/jquery-ui@1.11.4.js +0 -16624
    
        data/public/js/sequence.js
    CHANGED
    
    | @@ -9,78 +9,78 @@ require = (function e(t, n, r) { function s(o, u) { if (!n[o]) { if (!t[o]) { va | |
| 9 9 | 
             
                 * THIS FILE HAS BEEN MODIFIED FROM THE ORIGINAL
         | 
| 10 10 | 
             
                 * (https://github.com/ljgarcia/biojs-vis-sequence/blob/master/lib/index.js).
         | 
| 11 11 | 
             
                 *
         | 
| 12 | 
            -
                 * Sequence component | 
| 13 | 
            -
                 * | 
| 12 | 
            +
                 * Sequence component
         | 
| 13 | 
            +
                 *
         | 
| 14 14 | 
             
                 * @class
         | 
| 15 15 | 
             
                 * @extends Biojs
         | 
| 16 | 
            -
                 * | 
| 16 | 
            +
                 *
         | 
| 17 17 | 
             
                 * @author <a href="mailto:johncar@gmail.com">John Gomez</a>, <a href="mailto:secevalliv@gmail.com">Jose Villaveces</a>
         | 
| 18 18 | 
             
                 * @version 1.0.0
         | 
| 19 19 | 
             
                 * @category 3
         | 
| 20 | 
            -
                 * | 
| 20 | 
            +
                 *
         | 
| 21 21 | 
             
                 * @requires <a href='http://blog.jquery.com/2011/09/12/jquery-1-6-4-released/'>jQuery Core 1.6.4</a>
         | 
| 22 22 | 
             
                 * @dependency <script language="JavaScript" type="text/javascript" src="../biojs/dependencies/jquery/jquery-1.4.2.min.js"></script>
         | 
| 23 | 
            -
                 * | 
| 23 | 
            +
                 *
         | 
| 24 24 | 
             
                 * @requires <a href='http://jqueryui.com/download'>jQuery UI 1.8.16</a>
         | 
| 25 25 | 
             
                 * @dependency <script language="JavaScript" type="text/javascript" src="../biojs/dependencies/jquery/jquery-ui-1.8.2.custom.min.js"></script>
         | 
| 26 26 | 
             
                 *
         | 
| 27 27 | 
             
                 * @requires <a href='Biojs.Tooltip.css'>Biojs.Tooltip</a>
         | 
| 28 28 | 
             
                 * @dependency <script language="JavaScript" type="text/javascript" src="src/Biojs.Tooltip.js"></script>
         | 
| 29 | 
            -
                 * | 
| 29 | 
            +
                 *
         | 
| 30 30 | 
             
                 * @param {Object} options An object with the options for Sequence component.
         | 
| 31 | 
            -
                 * | 
| 32 | 
            -
                 * @option {string} target | 
| 31 | 
            +
                 *
         | 
| 32 | 
            +
                 * @option {string} target
         | 
| 33 33 | 
             
                 *    Identifier of the DIV tag where the component should be displayed.
         | 
| 34 | 
            -
                 * | 
| 35 | 
            -
                 * @option {string} sequence | 
| 34 | 
            +
                 *
         | 
| 35 | 
            +
                 * @option {string} sequence
         | 
| 36 36 | 
             
                 *    The sequence to be displayed.
         | 
| 37 | 
            -
                 * | 
| 38 | 
            -
                 * @option {string} [id] | 
| 37 | 
            +
                 *
         | 
| 38 | 
            +
                 * @option {string} [id]
         | 
| 39 39 | 
             
                 *    Sequence identifier if apply.
         | 
| 40 | 
            -
                 * | 
| 41 | 
            -
                 * @option {string} [format="FASTA"] | 
| 40 | 
            +
                 *
         | 
| 41 | 
            +
                 * @option {string} [format="FASTA"]
         | 
| 42 42 | 
             
                 *    The display format for the sequence representation.
         | 
| 43 | 
            -
                 * | 
| 44 | 
            -
                 * @option {Object[]} [highlights] | 
| 45 | 
            -
                 * 	  For highlighting multiple regions. | 
| 46 | 
            -
                 *    <pre class="brush: js" title="Syntax:"> | 
| 43 | 
            +
                 *
         | 
| 44 | 
            +
                 * @option {Object[]} [highlights]
         | 
| 45 | 
            +
                 * 	  For highlighting multiple regions.
         | 
| 46 | 
            +
                 *    <pre class="brush: js" title="Syntax:">
         | 
| 47 47 | 
             
                 *    [
         | 
| 48 48 | 
             
                 *    	// Highlight aminoacids from 'start' to 'end' of the current strand using the specified 'color' (optional) and 'background' (optional).
         | 
| 49 | 
            -
                 *    	{ start: <startVal1>, end: <endVal1> [, id:<idVal1>] [, color: <HTMLColor>] [, background: <HTMLColor>]}, | 
| 49 | 
            +
                 *    	{ start: <startVal1>, end: <endVal1> [, id:<idVal1>] [, color: <HTMLColor>] [, background: <HTMLColor>]},
         | 
| 50 50 | 
             
                 *    	//
         | 
| 51 51 | 
             
                 *    	// Any others highlights
         | 
| 52 | 
            -
                 *    	..., | 
| 53 | 
            -
                 *    	// | 
| 52 | 
            +
                 *    	...,
         | 
| 53 | 
            +
                 *    	//
         | 
| 54 54 | 
             
                 *    	{ start: <startValN>, end: <endValN> [, id:<idValN>] [, color: <HTMLColor>] [, background: <HTMLColor>]}
         | 
| 55 55 | 
             
                 *    ]</pre>
         | 
| 56 | 
            -
                 * | 
| 57 | 
            -
                 * <pre class="brush: js" title="Example:"> | 
| 56 | 
            +
                 *
         | 
| 57 | 
            +
                 * <pre class="brush: js" title="Example:">
         | 
| 58 58 | 
             
                 * highlights : [
         | 
| 59 59 | 
             
                 * 		{ start:30, end:42, color:"white", background:"green", id:"spin1" },
         | 
| 60 | 
            -
                 *		{ start:139, end:140 }, | 
| 60 | 
            +
                 *		{ start:139, end:140 },
         | 
| 61 61 | 
             
                 *		{ start:631, end:633, color:"white", background:"blue" }
         | 
| 62 62 | 
             
                 *	]
         | 
| 63 63 | 
             
                 * </pre>
         | 
| 64 | 
            -
                 * | 
| 65 | 
            -
                 * @option {Object} [columns={size:40,spacedEach:10}] | 
| 64 | 
            +
                 *
         | 
| 65 | 
            +
                 * @option {Object} [columns={size:40,spacedEach:10}]
         | 
| 66 66 | 
             
                 * 	  Options for displaying the columns. Syntax: { size: <numCols>, spacedEach: <numCols>}
         | 
| 67 | 
            -
                 * | 
| 68 | 
            -
                 * @option {Object} [selection] | 
| 67 | 
            +
                 *
         | 
| 68 | 
            +
                 * @option {Object} [selection]
         | 
| 69 69 | 
             
                 * 	  Positions for the current selected region. Syntax: { start: <startValue>, end: <endValue>}
         | 
| 70 | 
            -
                 * | 
| 71 | 
            -
                 * @option {Object[]} [annotations] | 
| 70 | 
            +
                 *
         | 
| 71 | 
            +
                 * @option {Object[]} [annotations]
         | 
| 72 72 | 
             
                 *    Set of overlapping annotations. Must be an array of objects following the syntax:
         | 
| 73 73 | 
             
                 *     		<pre class="brush: js" title="Syntax:">
         | 
| 74 | 
            -
                 *            [ | 
| 74 | 
            +
                 *            [
         | 
| 75 75 | 
             
                 *              // An annotation:
         | 
| 76 | 
            -
                 *              { name: <name>, | 
| 77 | 
            -
                 *                html: <message>, | 
| 78 | 
            -
                 *                color: <color_code>, | 
| 79 | 
            -
                 *                regions: [{ start: <startVal1>, end: <endVal1> color: <HTMLColor>}, ...,{ start: <startValN>, end: <endValN>, color: <HTMLColor>}] | 
| 80 | 
            -
                 *              }, | 
| 81 | 
            -
                 * | 
| 76 | 
            +
                 *              { name: <name>,
         | 
| 77 | 
            +
                 *                html: <message>,
         | 
| 78 | 
            +
                 *                color: <color_code>,
         | 
| 79 | 
            +
                 *                regions: [{ start: <startVal1>, end: <endVal1> color: <HTMLColor>}, ...,{ start: <startValN>, end: <endValN>, color: <HTMLColor>}]
         | 
| 80 | 
            +
                 *              },
         | 
| 81 | 
            +
                 *
         | 
| 82 82 | 
             
                 *              // ...
         | 
| 83 | 
            -
                 *              // more annotations here | 
| 83 | 
            +
                 *              // more annotations here
         | 
| 84 84 | 
             
                 *              // ...
         | 
| 85 85 | 
             
                 *            ]
         | 
| 86 86 | 
             
                 *    		 </pre>
         | 
| @@ -92,19 +92,19 @@ require = (function e(t, n, r) { function s(o, u) { if (!n[o]) { if (!t[o]) { va | |
| 92 92 | 
             
                 *        <li><b>regions</b> array of objects defining the intervals which belongs to the annotation.</li>
         | 
| 93 93 | 
             
                 *        <li><b>regions[i].start</b> is the starting character for the i-th interval.</li>
         | 
| 94 94 | 
             
                 *        <li><b>regions[i].end</b> is the ending character for the i-th interval.</li>
         | 
| 95 | 
            -
                 *        <li><b>regions[i].color</b> is an optional color for the i-th interval. | 
| 96 | 
            -
                 *      </ul> | 
| 97 | 
            -
                 * | 
| 98 | 
            -
                 * @option {Object} [formatOptions={title:true, footer:true}] | 
| 95 | 
            +
                 *        <li><b>regions[i].color</b> is an optional color for the i-th interval.
         | 
| 96 | 
            +
                 *      </ul>
         | 
| 97 | 
            +
                 *
         | 
| 98 | 
            +
                 * @option {Object} [formatOptions={title:true, footer:true}]
         | 
| 99 99 | 
             
                 * 	  Options for displaying the title. by now just affecting the CODATA format.
         | 
| 100 | 
            -
                 *    <pre class="brush: js" title="Syntax:"> | 
| 100 | 
            +
                 *    <pre class="brush: js" title="Syntax:">
         | 
| 101 101 | 
             
                 * 		formatOptions : {
         | 
| 102 102 | 
             
                 * 			title:false,
         | 
| 103 103 | 
             
                 * 			footer:false
         | 
| 104 104 | 
             
                 * 		}
         | 
| 105 105 | 
             
                 *    </pre>
         | 
| 106 | 
            -
                 * | 
| 107 | 
            -
                 * @example | 
| 106 | 
            +
                 *
         | 
| 107 | 
            +
                 * @example
         | 
| 108 108 | 
             
                 * var theSequence = "METLCQRLNVCQDKILTHYENDSTDLRDHIDYWKHMRLECAIYYKAREMGFKHINHQVVPTLAVSKNKALQAIELQLTLETIYNSQYSNEKWTLQDVSLEVYLTAPTGCIKKHGYTVEVQFDGDICNTMHYTNWTHIYICEEAojs SVTVVEGQVDYYGLYYVHEGIRTYFVQFKDDAEKYSKNKVWEVHAGGQVILCPTSVFSSNEVSSPEIIRQHLANHPAATHTKAVALGTEETQTTIQRPRSEPDTGNPCHTTKLLHRDSVDSAPILTAFNSSHKGRINCNSNTTPIVHLKGDANTLKCLRYRFKKHCTLYTAVSSTWHWTGHNVKHKSAIVTLTYDSEWQRDQFLSQVKIPKTITVSTGFMSI";
         | 
| 109 109 | 
             
                 * var mySequence = new Sequence({
         | 
| 110 110 | 
             
                 * 		sequence : theSequence,
         | 
| @@ -112,14 +112,14 @@ require = (function e(t, n, r) { function s(o, u) { if (!n[o]) { if (!t[o]) { va | |
| 112 112 | 
             
                 * 		format : 'CODATA',
         | 
| 113 113 | 
             
                 * 		id : 'P918283',
         | 
| 114 114 | 
             
                 * 		annotations: [
         | 
| 115 | 
            -
                 *        { name:"CATH", | 
| 116 | 
            -
                 * 	  		color:"#F0F020", | 
| 117 | 
            -
                 * 	  		html: "Using color code #F0F020 ", | 
| 115 | 
            +
                 *        { name:"CATH",
         | 
| 116 | 
            +
                 * 	  		color:"#F0F020",
         | 
| 117 | 
            +
                 * 	  		html: "Using color code #F0F020 ",
         | 
| 118 118 | 
             
                 * 	  		regions: [{start: 122, end: 135}]
         | 
| 119 119 | 
             
                 * 		  },
         | 
| 120 | 
            -
                 *        { name:"TEST", | 
| 121 | 
            -
                 *          html:"<br> Example of <b>HTML</b>", | 
| 122 | 
            -
                 *          color:"green", | 
| 120 | 
            +
                 *        { name:"TEST",
         | 
| 121 | 
            +
                 *          html:"<br> Example of <b>HTML</b>",
         | 
| 122 | 
            +
                 *          color:"green",
         | 
| 123 123 | 
             
                 *          regions: [
         | 
| 124 124 | 
             
                 *            {start: 285, end: 292},
         | 
| 125 125 | 
             
                 *            {start: 293, end: 314, color: "#2E4988"}]
         | 
| @@ -127,11 +127,11 @@ require = (function e(t, n, r) { function s(o, u) { if (!n[o]) { if (!t[o]) { va | |
| 127 127 | 
             
                 *      ],
         | 
| 128 128 | 
             
                 *      highlights : [
         | 
| 129 129 | 
             
                 *      	{ start:30, end:42, color:"white", background:"green", id:"spin1" },
         | 
| 130 | 
            -
                 *      	{ start:139, end:140 }, | 
| 130 | 
            +
                 *      	{ start:139, end:140 },
         | 
| 131 131 | 
             
                 *      	{ start:631, end:633, color:"white", background:"blue" }
         | 
| 132 132 | 
             
                 *      ]
         | 
| 133 | 
            -
                 * }); | 
| 134 | 
            -
                 * | 
| 133 | 
            +
                 * });
         | 
| 134 | 
            +
                 *
         | 
| 135 135 | 
             
                 */
         | 
| 136 136 |  | 
| 137 137 | 
             
                    var Class = require('js-class');
         | 
| @@ -162,8 +162,9 @@ require = (function e(t, n, r) { function s(o, u) { if (!n[o]) { if (!t[o]) { va | |
| 162 162 | 
             
                                // legacy: copy target id
         | 
| 163 163 | 
             
                                this.opt.target = this._container[0].id;
         | 
| 164 164 |  | 
| 165 | 
            -
                                // Lazy initialization | 
| 165 | 
            +
                                // Lazy initialization
         | 
| 166 166 | 
             
                                this._container.ready(function () {
         | 
| 167 | 
            +
                                    this._ready = false;
         | 
| 167 168 | 
             
                                    self._initialize();
         | 
| 168 169 | 
             
                                });
         | 
| 169 170 | 
             
                            },
         | 
| @@ -184,7 +185,7 @@ require = (function e(t, n, r) { function s(o, u) { if (!n[o]) { if (!t[o]) { va | |
| 184 185 | 
             
                                annotations: [],
         | 
| 185 186 | 
             
                                sequenceUrl: 'http://www.ebi.ac.uk/das-srv/uniprot/das/uniprot/sequence',
         | 
| 186 187 |  | 
| 187 | 
            -
                                // Styles | 
| 188 | 
            +
                                // Styles
         | 
| 188 189 | 
             
                                selectionColor: 'Yellow',
         | 
| 189 190 | 
             
                                selectionFontColor: 'black',
         | 
| 190 191 | 
             
                                highlightFontColor: 'red',
         | 
| @@ -209,13 +210,13 @@ require = (function e(t, n, r) { function s(o, u) { if (!n[o]) { if (!t[o]) { va | |
| 209 210 | 
             
                       * @eventData {string} type The name of the event.
         | 
| 210 211 | 
             
                       * @eventData {int} start A number indicating the start of the selection.
         | 
| 211 212 | 
             
                       * @eventData {int} end A number indicating the ending of selection.
         | 
| 212 | 
            -
                       * @example | 
| 213 | 
            +
                       * @example
         | 
| 213 214 | 
             
                       * mySequence.onSelectionChanged(
         | 
| 214 215 | 
             
                       *    function( objEvent ) {
         | 
| 215 216 | 
             
                       *       alert("Selected: " + objEvent.start + ", " + objEvent.end );
         | 
| 216 217 | 
             
                       *    }
         | 
| 217 | 
            -
                       * ); | 
| 218 | 
            -
                       * | 
| 218 | 
            +
                       * );
         | 
| 219 | 
            +
                       *
         | 
| 219 220 | 
             
                       * */
         | 
| 220 221 | 
             
                                'onSelectionChanged',
         | 
| 221 222 |  | 
| @@ -227,14 +228,14 @@ require = (function e(t, n, r) { function s(o, u) { if (!n[o]) { if (!t[o]) { va | |
| 227 228 | 
             
                       * @eventData {string} type The name of the event.
         | 
| 228 229 | 
             
                       * @eventData {int} start A number indicating the start of the selection.
         | 
| 229 230 | 
             
                       * @eventData {int} end A number indicating the ending of selection.
         | 
| 230 | 
            -
                       * @example | 
| 231 | 
            +
                       * @example
         | 
| 231 232 | 
             
                       * mySequence.onSelectionChange(
         | 
| 232 233 | 
             
                       *    function( objEvent ) {
         | 
| 233 234 | 
             
                       *       alert("Selection in progress: " + objEvent.start + ", " + objEvent.end );
         | 
| 234 235 | 
             
                       *    }
         | 
| 235 | 
            -
                       * ); | 
| 236 | 
            -
                       * | 
| 237 | 
            -
                       * | 
| 236 | 
            +
                       * );
         | 
| 237 | 
            +
                       *
         | 
| 238 | 
            +
                       *
         | 
| 238 239 | 
             
                       * */
         | 
| 239 240 | 
             
                                'onSelectionChange',
         | 
| 240 241 |  | 
| @@ -246,13 +247,13 @@ require = (function e(t, n, r) { function s(o, u) { if (!n[o]) { if (!t[o]) { va | |
| 246 247 | 
             
                       * @eventData {string} type The name of the event.
         | 
| 247 248 | 
             
                       * @eventData {string} name The name of the selected annotation.
         | 
| 248 249 | 
             
                       * @eventData {int} pos A number indicating the position of the selected amino acid.
         | 
| 249 | 
            -
                       * @example | 
| 250 | 
            +
                       * @example
         | 
| 250 251 | 
             
                       * mySequence.onAnnotationClicked(
         | 
| 251 252 | 
             
                       *    function( objEvent ) {
         | 
| 252 253 | 
             
                       *       alert("Clicked " + objEvent.name + " on position " + objEvent.pos );
         | 
| 253 254 | 
             
                       *    }
         | 
| 254 | 
            -
                       * ); | 
| 255 | 
            -
                       * | 
| 255 | 
            +
                       * );
         | 
| 256 | 
            +
                       *
         | 
| 256 257 | 
             
                       * */
         | 
| 257 258 | 
             
                                'onAnnotationClicked'
         | 
| 258 259 | 
             
                            ],
         | 
| @@ -283,7 +284,7 @@ require = (function e(t, n, r) { function s(o, u) { if (!n[o]) { if (!t[o]) { va | |
| 283 284 | 
             
                                // DIV for the sequence
         | 
| 284 285 | 
             
                                this._contentDiv = jQuery('<div/>').appendTo(this._container);
         | 
| 285 286 |  | 
| 286 | 
            -
                                // Initialize highlighting | 
| 287 | 
            +
                                // Initialize highlighting
         | 
| 287 288 | 
             
                                this._highlights = this.opt.highlights;
         | 
| 288 289 |  | 
| 289 290 | 
             
                                // Initialize annotations
         | 
| @@ -315,6 +316,7 @@ require = (function e(t, n, r) { function s(o, u) { if (!n[o]) { if (!t[o]) { va | |
| 315 316 | 
             
                                    this.clearSequence('No sequence available', '../biojs/css/images/warning_icon.png');
         | 
| 316 317 | 
             
                                }
         | 
| 317 318 |  | 
| 319 | 
            +
                                this._ready = true;
         | 
| 318 320 | 
             
                            },
         | 
| 319 321 |  | 
| 320 322 |  | 
| @@ -322,10 +324,10 @@ require = (function e(t, n, r) { function s(o, u) { if (!n[o]) { if (!t[o]) { va | |
| 322 324 | 
             
                     * Shows the columns indicated by the indexes array.
         | 
| 323 325 | 
             
                     * @param {string} seq The sequence strand.
         | 
| 324 326 | 
             
                     * @param {string} [identifier] Sequence identifier.
         | 
| 325 | 
            -
                     * | 
| 326 | 
            -
                     * @example | 
| 327 | 
            +
                     *
         | 
| 328 | 
            +
                     * @example
         | 
| 327 329 | 
             
                     * mySequence.setSequence("P99999");
         | 
| 328 | 
            -
                     * | 
| 330 | 
            +
                     *
         | 
| 329 331 | 
             
                     */
         | 
| 330 332 | 
             
                            setSequence: function (seq, identifier) {
         | 
| 331 333 |  | 
| @@ -353,23 +355,18 @@ require = (function e(t, n, r) { function s(o, u) { if (!n[o]) { if (!t[o]) { va | |
| 353 355 | 
             
                                jQuery.ajax({
         | 
| 354 356 | 
             
                                    url: self.opt.sequenceUrl,
         | 
| 355 357 | 
             
                                    dataType: 'xml',
         | 
| 356 | 
            -
                                    data: { segment: accession } | 
| 357 | 
            -
             | 
| 358 | 
            -
             | 
| 359 | 
            -
             | 
| 360 | 
            -
             | 
| 361 | 
            -
             | 
| 362 | 
            -
             | 
| 363 | 
            -
                                         | 
| 364 | 
            -
                                            console.log('Error decoding response data: ' + e.message);
         | 
| 365 | 
            -
                                            self.clearSequence('No sequence available', '../biojs/css/images/warning_icon.png');
         | 
| 366 | 
            -
                                        }
         | 
| 367 | 
            -
             | 
| 368 | 
            -
                                    },
         | 
| 369 | 
            -
                                    error: function (jqXHR, textStatus, errorThrown) {
         | 
| 370 | 
            -
                                        console.log('Error decoding response data: ' + textStatus);
         | 
| 371 | 
            -
                                        self.clearSequence('Error requesting the sequence to the server ' + this.url, '../biojs/css/images/warning_icon.png');
         | 
| 358 | 
            +
                                    data: { segment: accession }
         | 
| 359 | 
            +
                                }).done(function(xml) {
         | 
| 360 | 
            +
                                    try {
         | 
| 361 | 
            +
                                        var sequenceNode = jQuery(xml).find('SEQUENCE:first');
         | 
| 362 | 
            +
                                        self.setSequence(sequenceNode.text(), sequenceNode.attr('id'), sequenceNode.attr('label'));
         | 
| 363 | 
            +
                                    } catch (e) {
         | 
| 364 | 
            +
                                        console.log('Error decoding response data: ' + e.message);
         | 
| 365 | 
            +
                                        self.clearSequence('No sequence available', '../biojs/css/images/warning_icon.png');
         | 
| 372 366 | 
             
                                    }
         | 
| 367 | 
            +
                                }).fail(function(jqXHR, textStatus, errorThrown) {
         | 
| 368 | 
            +
                                    console.log('Error requesting the sequence: ' + textStatus);
         | 
| 369 | 
            +
                                    self.clearSequence('Error requesting the sequence to the server ' + this.url, '../biojs/css/images/warning_icon.png');
         | 
| 373 370 | 
             
                                });
         | 
| 374 371 | 
             
                            },
         | 
| 375 372 |  | 
| @@ -377,10 +374,10 @@ require = (function e(t, n, r) { function s(o, u) { if (!n[o]) { if (!t[o]) { va | |
| 377 374 | 
             
                   * Shows the columns indicated by the indexes array.
         | 
| 378 375 | 
             
                   * @param {string} [showMessage] Message to be showed.
         | 
| 379 376 | 
             
                   * @param {string} [icon] Icon to be showed a side of the message
         | 
| 380 | 
            -
                   * | 
| 381 | 
            -
                   * @example | 
| 377 | 
            +
                   *
         | 
| 378 | 
            +
                   * @example
         | 
| 382 379 | 
             
                   * mySequence.clearSequence("No sequence available", "../biojs/css/images/warning_icon.png");
         | 
| 383 | 
            -
                   * | 
| 380 | 
            +
                   *
         | 
| 384 381 | 
             
                   */
         | 
| 385 382 | 
             
                            clearSequence: function (showMessage, icon) {
         | 
| 386 383 |  | 
| @@ -414,9 +411,9 @@ require = (function e(t, n, r) { function s(o, u) { if (!n[o]) { if (!t[o]) { va | |
| 414 411 | 
             
                      * Set the current selection in the sequence causing the event {@link Sequence#onSelectionChanged}
         | 
| 415 412 | 
             
                      *
         | 
| 416 413 | 
             
                      * @example
         | 
| 417 | 
            -
                      * // set selection from the position 100 to 150 | 
| 414 | 
            +
                      * // set selection from the position 100 to 150
         | 
| 418 415 | 
             
                      * mySequence.setSelection(100, 150);
         | 
| 419 | 
            -
                      * | 
| 416 | 
            +
                      *
         | 
| 420 417 | 
             
                      * @param {int} start The starting character of the selection.
         | 
| 421 418 | 
             
                      * @param {int} end The ending character of the selection
         | 
| 422 419 | 
             
                      */
         | 
| @@ -440,6 +437,7 @@ require = (function e(t, n, r) { function s(o, u) { if (!n[o]) { if (!t[o]) { va | |
| 440 437 | 
             
                            _buildFormatSelector: function () {
         | 
| 441 438 | 
             
                                var self = this;
         | 
| 442 439 |  | 
| 440 | 
            +
                                console.log('build format selector container', this._container);
         | 
| 443 441 | 
             
                                this._headerDiv = jQuery('<div></div>').appendTo(this._container);
         | 
| 444 442 | 
             
                                this._headerDiv.append('Format: ');
         | 
| 445 443 |  | 
| @@ -465,11 +463,11 @@ require = (function e(t, n, r) { function s(o, u) { if (!n[o]) { if (!t[o]) { va | |
| 465 463 | 
             
                      * @example
         | 
| 466 464 | 
             
                      * // highlight the characters within the position 100 to 150, included.
         | 
| 467 465 | 
             
                      * mySequence.addHighlight( { "start": 100, "end": 150, "color": "white", "background": "red", "id": "aaa" } );
         | 
| 468 | 
            -
                      * | 
| 466 | 
            +
                      *
         | 
| 469 467 | 
             
                      * @param {Object} h The highlight defined as follows:
         | 
| 470 | 
            -
                      * | 
| 471 | 
            -
                      * | 
| 472 | 
            -
                      * @return {int} representing the id of the highlight on the internal array. Returns -1 on failure | 
| 468 | 
            +
                      *
         | 
| 469 | 
            +
                      *
         | 
| 470 | 
            +
                      * @return {int} representing the id of the highlight on the internal array. Returns -1 on failure
         | 
| 473 471 | 
             
                      */
         | 
| 474 472 | 
             
                            addHighlight: function (h) {
         | 
| 475 473 | 
             
                                var id = '-1';
         | 
| @@ -492,14 +490,17 @@ require = (function e(t, n, r) { function s(o, u) { if (!n[o]) { if (!t[o]) { va | |
| 492 490 |  | 
| 493 491 | 
             
                                return id;
         | 
| 494 492 | 
             
                            },
         | 
| 495 | 
            -
                            /* | 
| 493 | 
            +
                            /*
         | 
| 496 494 | 
             
                       * Function: Sequence._applyHighlight
         | 
| 497 495 | 
             
                       * Purpose:  Apply the specified color and background to a region between 'start' and 'end'.
         | 
| 498 496 | 
             
                       * Returns:  -
         | 
| 499 | 
            -
                       * Inputs: highlight -> {Object} An object containing the fields start (int), end (int), | 
| 497 | 
            +
                       * Inputs: highlight -> {Object} An object containing the fields start (int), end (int),
         | 
| 500 498 | 
             
                       * 						color (HTML color string) and background (HTML color string).
         | 
| 501 499 | 
             
                       */
         | 
| 502 500 | 
             
                            _applyHighlight: function (highlight) {
         | 
| 501 | 
            +
                                var zindex = 0,
         | 
| 502 | 
            +
                                    z = 0,
         | 
| 503 | 
            +
                                    o = 0;
         | 
| 503 504 | 
             
                                var seq = this._contentDiv.find('.sequence');
         | 
| 504 505 | 
             
                                for (var i = highlight.start - 1; i < highlight.end; i++) {
         | 
| 505 506 | 
             
                                    zindex = jQuery(seq[i]).css('z-index');
         | 
| @@ -521,7 +522,7 @@ require = (function e(t, n, r) { function s(o, u) { if (!n[o]) { if (!t[o]) { va | |
| 521 522 | 
             
                                        .addClass('highlighted');
         | 
| 522 523 | 
             
                                }
         | 
| 523 524 | 
             
                            },
         | 
| 524 | 
            -
                            /* | 
| 525 | 
            +
                            /*
         | 
| 525 526 | 
             
                       * Function: Sequence._applyHighlights
         | 
| 526 527 | 
             
                       * Purpose:  Apply the specified highlights.
         | 
| 527 528 | 
             
                       * Returns:  -
         | 
| @@ -532,7 +533,7 @@ require = (function e(t, n, r) { function s(o, u) { if (!n[o]) { if (!t[o]) { va | |
| 532 533 | 
             
                                    this._applyHighlight(highlights[i]);
         | 
| 533 534 | 
             
                                }
         | 
| 534 535 | 
             
                            },
         | 
| 535 | 
            -
                            /* | 
| 536 | 
            +
                            /*
         | 
| 536 537 | 
             
                       * Function: Sequence._restoreHighlights
         | 
| 537 538 | 
             
                       * Purpose:  Repaint the highlights in the specified region.
         | 
| 538 539 | 
             
                       * Returns:  -
         | 
| @@ -563,10 +564,10 @@ require = (function e(t, n, r) { function s(o, u) { if (!n[o]) { if (!t[o]) { va | |
| 563 564 | 
             
                                    }
         | 
| 564 565 | 
             
                                }
         | 
| 565 566 | 
             
                            },
         | 
| 566 | 
            -
                            /* | 
| 567 | 
            +
                            /*
         | 
| 567 568 | 
             
                       * Function: Sequence._restoreSelection
         | 
| 568 | 
            -
                       * Purpose:  Repaint the current selection in the specified region. | 
| 569 | 
            -
                       * 			 It is used in the case of any highlight do overriding of the current selection. | 
| 569 | 
            +
                       * Purpose:  Repaint the current selection in the specified region.
         | 
| 570 | 
            +
                       * 			 It is used in the case of any highlight do overriding of the current selection.
         | 
| 570 571 | 
             
                       * Returns:  -
         | 
| 571 572 | 
             
                       * Inputs: start -> {int} Start of the region to be restored.
         | 
| 572 573 | 
             
                       * 		   end -> {int} End of the region to be restored.
         | 
| @@ -594,7 +595,7 @@ require = (function e(t, n, r) { function s(o, u) { if (!n[o]) { if (!t[o]) { va | |
| 594 595 | 
             
                      * @example
         | 
| 595 596 | 
             
                      * // Clear the highlighted characters within the position 100 to 150, included.
         | 
| 596 597 | 
             
                      * mySequence.removeHighlight("spin1");
         | 
| 597 | 
            -
                      * | 
| 598 | 
            +
                      *
         | 
| 598 599 | 
             
                      * @param {string} id The id of the highlight on the internal array. This value is returned by method highlight.
         | 
| 599 600 | 
             
                      */
         | 
| 600 601 | 
             
                            removeHighlight: function (id) {
         | 
| @@ -631,7 +632,7 @@ require = (function e(t, n, r) { function s(o, u) { if (!n[o]) { if (!t[o]) { va | |
| 631 632 | 
             
                      * @example
         | 
| 632 633 | 
             
                      * // Set format to 'FASTA'.
         | 
| 633 634 | 
             
                      * mySequence.setFormat('FASTA');
         | 
| 634 | 
            -
                      * | 
| 635 | 
            +
                      *
         | 
| 635 636 | 
             
                      * @param {string} format The format for the sequence to be displayed.
         | 
| 636 637 | 
             
                      */
         | 
| 637 638 | 
             
                            setFormat: function (format) {
         | 
| @@ -655,7 +656,7 @@ require = (function e(t, n, r) { function s(o, u) { if (!n[o]) { if (!t[o]) { va | |
| 655 656 | 
             
                      * @example
         | 
| 656 657 | 
             
                      * // Set the number of columns to 70.
         | 
| 657 658 | 
             
                      * mySequence.setNumCols(70);
         | 
| 658 | 
            -
                      * | 
| 659 | 
            +
                      *
         | 
| 659 660 | 
             
                      * @param {int} numCols The number of columns.
         | 
| 660 661 | 
             
                      */
         | 
| 661 662 | 
             
                            setNumCols: function (numCols) {
         | 
| @@ -665,7 +666,7 @@ require = (function e(t, n, r) { function s(o, u) { if (!n[o]) { if (!t[o]) { va | |
| 665 666 |  | 
| 666 667 | 
             
                            /**
         | 
| 667 668 | 
             
                      * Set the visibility of the drop-down list of formats.
         | 
| 668 | 
            -
                      * | 
| 669 | 
            +
                      *
         | 
| 669 670 | 
             
                      * @param {boolean} visible true: show; false: hide.
         | 
| 670 671 | 
             
                      */
         | 
| 671 672 | 
             
                            formatSelectorVisible: function (visible) {
         | 
| @@ -682,7 +683,7 @@ require = (function e(t, n, r) { function s(o, u) { if (!n[o]) { if (!t[o]) { va | |
| 682 683 | 
             
                      * @example
         | 
| 683 684 | 
             
                      * // Shows the format selector.
         | 
| 684 685 | 
             
                      * mySequence.showFormatSelector();
         | 
| 685 | 
            -
                      * | 
| 686 | 
            +
                      *
         | 
| 686 687 | 
             
                      */
         | 
| 687 688 | 
             
                            showFormatSelector: function () {
         | 
| 688 689 | 
             
                                this._headerDiv.show();
         | 
| @@ -690,11 +691,11 @@ require = (function e(t, n, r) { function s(o, u) { if (!n[o]) { if (!t[o]) { va | |
| 690 691 |  | 
| 691 692 | 
             
                            /**
         | 
| 692 693 | 
             
                      * This is similar to a {Biojs.Protein3D#formatSelectorVisible} with the 'false' argument.
         | 
| 693 | 
            -
                      * | 
| 694 | 
            +
                      *
         | 
| 694 695 | 
             
                      * @example
         | 
| 695 696 | 
             
                      * // Hides the format selector.
         | 
| 696 697 | 
             
                      * mySequence.hideFormatSelector();
         | 
| 697 | 
            -
                      * | 
| 698 | 
            +
                      *
         | 
| 698 699 | 
             
                      */
         | 
| 699 700 | 
             
                            hideFormatSelector: function () {
         | 
| 700 701 | 
             
                                this._headerDiv.hide();
         | 
| @@ -702,7 +703,7 @@ require = (function e(t, n, r) { function s(o, u) { if (!n[o]) { if (!t[o]) { va | |
| 702 703 |  | 
| 703 704 | 
             
                            /**
         | 
| 704 705 | 
             
                      * Hides the whole component.
         | 
| 705 | 
            -
                      * | 
| 706 | 
            +
                      *
         | 
| 706 707 | 
             
                      */
         | 
| 707 708 | 
             
                            hide: function () {
         | 
| 708 709 | 
             
                                this._headerDiv.hide();
         | 
| @@ -711,15 +712,15 @@ require = (function e(t, n, r) { function s(o, u) { if (!n[o]) { if (!t[o]) { va | |
| 711 712 |  | 
| 712 713 | 
             
                            /**
         | 
| 713 714 | 
             
                      * Shows the whole component.
         | 
| 714 | 
            -
                      * | 
| 715 | 
            +
                      *
         | 
| 715 716 | 
             
                      */
         | 
| 716 717 | 
             
                            show: function () {
         | 
| 717 718 | 
             
                                this._headerDiv.show();
         | 
| 718 719 | 
             
                                this._contentDiv.show();
         | 
| 719 720 | 
             
                            },
         | 
| 720 | 
            -
                            /* | 
| 721 | 
            +
                            /*
         | 
| 721 722 | 
             
                       * Function: Sequence._setSelection
         | 
| 722 | 
            -
                       * Purpose:  Update the current selection. | 
| 723 | 
            +
                       * Purpose:  Update the current selection.
         | 
| 723 724 | 
             
                       * Returns:  -
         | 
| 724 725 | 
             
                       * Inputs: start -> {int} Start of the region to be selected.
         | 
| 725 726 | 
             
                       * 		   end -> {int} End of the region to be selected.
         | 
| @@ -757,9 +758,9 @@ require = (function e(t, n, r) { function s(o, u) { if (!n[o]) { if (!t[o]) { va | |
| 757 758 | 
             
                                current.end = end;
         | 
| 758 759 | 
             
                            },
         | 
| 759 760 |  | 
| 760 | 
            -
                            /* | 
| 761 | 
            +
                            /*
         | 
| 761 762 | 
             
                       * Function: Sequence._repaintSelection
         | 
| 762 | 
            -
                       * Purpose:  Repaint the whole current selection. | 
| 763 | 
            +
                       * Purpose:  Repaint the whole current selection.
         | 
| 763 764 | 
             
                       * Returns:  -
         | 
| 764 765 | 
             
                       * Inputs: -
         | 
| 765 766 | 
             
                       */
         | 
| @@ -769,9 +770,9 @@ require = (function e(t, n, r) { function s(o, u) { if (!n[o]) { if (!t[o]) { va | |
| 769 770 | 
             
                                this._setSelection(s.start, s.end);
         | 
| 770 771 | 
             
                            },
         | 
| 771 772 |  | 
| 772 | 
            -
                            /* | 
| 773 | 
            +
                            /*
         | 
| 773 774 | 
             
                       * Function: Sequence._redraw
         | 
| 774 | 
            -
                       * Purpose:  Repaint the current sequence. | 
| 775 | 
            +
                       * Purpose:  Repaint the current sequence.
         | 
| 775 776 | 
             
                       * Returns:  -
         | 
| 776 777 | 
             
                       * Inputs: -
         | 
| 777 778 | 
             
                       */
         | 
| @@ -783,7 +784,7 @@ require = (function e(t, n, r) { function s(o, u) { if (!n[o]) { if (!t[o]) { va | |
| 783 784 | 
             
                                //this._contentDiv.text('');
         | 
| 784 785 | 
             
                                this._contentDiv.children().remove();
         | 
| 785 786 |  | 
| 786 | 
            -
                                // Rebuild the spans of the sequence | 
| 787 | 
            +
                                // Rebuild the spans of the sequence
         | 
| 787 788 | 
             
                                // according to format
         | 
| 788 789 | 
             
                                if (this.opt.format == 'RAW') {
         | 
| 789 790 | 
             
                                    this._drawRaw();
         | 
| @@ -801,9 +802,9 @@ require = (function e(t, n, r) { function s(o, u) { if (!n[o]) { if (!t[o]) { va | |
| 801 802 | 
             
                                this._repaintSelection();
         | 
| 802 803 | 
             
                                this._addSpanEvents();
         | 
| 803 804 | 
             
                            },
         | 
| 804 | 
            -
                            /* | 
| 805 | 
            +
                            /*
         | 
| 805 806 | 
             
                       * Function: Sequence._drawFasta
         | 
| 806 | 
            -
                       * Purpose:  Repaint the current sequence using FASTA format. | 
| 807 | 
            +
                       * Purpose:  Repaint the current sequence using FASTA format.
         | 
| 807 808 | 
             
                       * Returns:  -
         | 
| 808 809 | 
             
                       * Inputs: -
         | 
| 809 810 | 
             
                       */
         | 
| @@ -832,9 +833,9 @@ require = (function e(t, n, r) { function s(o, u) { if (!n[o]) { if (!t[o]) { va | |
| 832 833 |  | 
| 833 834 | 
             
                                this._drawAnnotations(opt);
         | 
| 834 835 | 
             
                            },
         | 
| 835 | 
            -
                            /* | 
| 836 | 
            +
                            /*
         | 
| 836 837 | 
             
                       * Function: Sequence._drawCodata
         | 
| 837 | 
            -
                       * Purpose:  Repaint the current sequence using CODATA format. | 
| 838 | 
            +
                       * Purpose:  Repaint the current sequence using CODATA format.
         | 
| 838 839 | 
             
                       * Returns:  -
         | 
| 839 840 | 
             
                       * Inputs: -
         | 
| 840 841 | 
             
                       */
         | 
| @@ -884,11 +885,11 @@ require = (function e(t, n, r) { function s(o, u) { if (!n[o]) { if (!t[o]) { va | |
| 884 885 |  | 
| 885 886 | 
             
                                this._drawAnnotations(opt);
         | 
| 886 887 | 
             
                            },
         | 
| 887 | 
            -
                            /* | 
| 888 | 
            +
                            /*
         | 
| 888 889 | 
             
                       * Function: Sequence._drawAnnotations
         | 
| 889 | 
            -
                       * Purpose:  Paint the annotations on the sequence. | 
| 890 | 
            +
                       * Purpose:  Paint the annotations on the sequence.
         | 
| 890 891 | 
             
                       * Returns:  -
         | 
| 891 | 
            -
                       * Inputs: settings -> {object} | 
| 892 | 
            +
                       * Inputs: settings -> {object}
         | 
| 892 893 | 
             
                       */
         | 
| 893 894 | 
             
                            _drawAnnotations: function (settings) {
         | 
| 894 895 |  | 
| @@ -961,9 +962,9 @@ require = (function e(t, n, r) { function s(o, u) { if (!n[o]) { if (!t[o]) { va | |
| 961 962 | 
             
                                });
         | 
| 962 963 |  | 
| 963 964 | 
             
                            },
         | 
| 964 | 
            -
                            /* | 
| 965 | 
            +
                            /*
         | 
| 965 966 | 
             
                     * Function: Sequence._getAnnotationString
         | 
| 966 | 
            -
                     * Purpose:  Get the annotation text message for the tooltip | 
| 967 | 
            +
                     * Purpose:  Get the annotation text message for the tooltip
         | 
| 967 968 | 
             
                     * Returns:  {string} Annotation text for the annotation
         | 
| 968 969 | 
             
                     * Inputs:   id -> {int} index of the internal annotation array
         | 
| 969 970 | 
             
                     */
         | 
| @@ -972,12 +973,12 @@ require = (function e(t, n, r) { function s(o, u) { if (!n[o]) { if (!t[o]) { va | |
| 972 973 | 
             
                                return annotation.name + '<br/>' + ((annotation.html) ? annotation.html : '');
         | 
| 973 974 | 
             
                            },
         | 
| 974 975 |  | 
| 975 | 
            -
                            /* | 
| 976 | 
            +
                            /*
         | 
| 976 977 | 
             
                     * Function: Sequence._getHTMLRowAnnot
         | 
| 977 978 | 
             
                     * Purpose:  Build an annotation
         | 
| 978 979 | 
             
                     * Returns:  HTML of the annotation
         | 
| 979 980 | 
             
                     * Inputs:   currentPos -> {int}
         | 
| 980 | 
            -
                     * 			 annotation -> {Object} | 
| 981 | 
            +
                     * 			 annotation -> {Object}
         | 
| 981 982 | 
             
                     *  		 settings -> {Object}
         | 
| 982 983 | 
             
                     */
         | 
| 983 984 | 
             
                            _getHTMLRowAnnot: function (currentPos, annotation, settings) {
         | 
| @@ -1030,9 +1031,9 @@ require = (function e(t, n, r) { function s(o, u) { if (!n[o]) { if (!t[o]) { va | |
| 1030 1031 |  | 
| 1031 1032 | 
             
                                return (str.indexOf('span') == -1) ? '' : str;
         | 
| 1032 1033 | 
             
                            },
         | 
| 1033 | 
            -
                            /* | 
| 1034 | 
            +
                            /*
         | 
| 1034 1035 | 
             
                     * Function: Sequence._drawRaw
         | 
| 1035 | 
            -
                     * Purpose:  Repaint the current sequence using RAW format. | 
| 1036 | 
            +
                     * Purpose:  Repaint the current sequence using RAW format.
         | 
| 1036 1037 | 
             
                     * Returns:  -
         | 
| 1037 1038 | 
             
                     * Inputs: -
         | 
| 1038 1039 | 
             
                     */
         | 
| @@ -1059,9 +1060,9 @@ require = (function e(t, n, r) { function s(o, u) { if (!n[o]) { if (!t[o]) { va | |
| 1059 1060 |  | 
| 1060 1061 | 
             
                                this._drawAnnotations(opt);
         | 
| 1061 1062 | 
             
                            },
         | 
| 1062 | 
            -
                            /* | 
| 1063 | 
            +
                            /*
         | 
| 1063 1064 | 
             
                       * Function: Sequence._drawPride
         | 
| 1064 | 
            -
                       * Purpose:  Repaint the current sequence using PRIDE format. | 
| 1065 | 
            +
                       * Purpose:  Repaint the current sequence using PRIDE format.
         | 
| 1065 1066 | 
             
                       * Returns:  -
         | 
| 1066 1067 | 
             
                       * Inputs: -
         | 
| 1067 1068 | 
             
                       */
         | 
| @@ -1087,9 +1088,9 @@ require = (function e(t, n, r) { function s(o, u) { if (!n[o]) { if (!t[o]) { va | |
| 1087 1088 | 
             
                                this._drawSequence(seq, opt);
         | 
| 1088 1089 | 
             
                                this._drawAnnotations(opt);
         | 
| 1089 1090 | 
             
                            },
         | 
| 1090 | 
            -
                            /* | 
| 1091 | 
            +
                            /*
         | 
| 1091 1092 | 
             
                       * Function: Sequence._drawSequence
         | 
| 1092 | 
            -
                       * Purpose:  Repaint the current sequence using CUSTOM format. | 
| 1093 | 
            +
                       * Purpose:  Repaint the current sequence using CUSTOM format.
         | 
| 1093 1094 | 
             
                       * Returns:  -
         | 
| 1094 1095 | 
             
                       * Inputs:   a -> {char[]} a The sequence strand.
         | 
| 1095 1096 | 
             
                       * 			 opt -> {Object} opt The CUSTOM format.
         | 
| @@ -1216,11 +1217,11 @@ require = (function e(t, n, r) { function s(o, u) { if (!n[o]) { if (!t[o]) { va | |
| 1216 1217 |  | 
| 1217 1218 | 
             
                                return str;
         | 
| 1218 1219 | 
             
                            },
         | 
| 1219 | 
            -
                            /* | 
| 1220 | 
            +
                            /*
         | 
| 1220 1221 | 
             
                       * Function: Sequence._formatIndex
         | 
| 1221 1222 | 
             
                       * Purpose:  Build the HTML corresponding to counting numbers (top, left, right) in the strand.
         | 
| 1222 1223 | 
             
                       * Returns:  -
         | 
| 1223 | 
            -
                       * Inputs:   number -> {int} The number | 
| 1224 | 
            +
                       * Inputs:   number -> {int} The number
         | 
| 1224 1225 | 
             
                       * 			 size -> {int} Number of bins to suit the number.
         | 
| 1225 1226 | 
             
                       * 			 fillingChar -> {char} Character to be used for filling out blank bins.
         | 
| 1226 1227 | 
             
                       * 			 alignLeft -> {bool} Tell if aligned to the left.
         | 
| @@ -1241,7 +1242,7 @@ require = (function e(t, n, r) { function s(o, u) { if (!n[o]) { if (!t[o]) { va | |
| 1241 1242 | 
             
                                }
         | 
| 1242 1243 | 
             
                                return str;
         | 
| 1243 1244 | 
             
                            },
         | 
| 1244 | 
            -
                            /* | 
| 1245 | 
            +
                            /*
         | 
| 1245 1246 | 
             
                       * Function: Sequence._addSpanEvents
         | 
| 1246 1247 | 
             
                       * Purpose:  Add the event handlers to the strand.
         | 
| 1247 1248 | 
             
                       * Returns:  -
         | 
| @@ -1313,7 +1314,7 @@ require = (function e(t, n, r) { function s(o, u) { if (!n[o]) { if (!t[o]) { va | |
| 1313 1314 | 
             
                                })
         | 
| 1314 1315 | 
             
                                    .css('cursor', 'pointer');
         | 
| 1315 1316 | 
             
                            },
         | 
| 1316 | 
            -
                            /* | 
| 1317 | 
            +
                            /*
         | 
| 1317 1318 | 
             
                       * Function: Sequence._addTooltip
         | 
| 1318 1319 | 
             
                       * Purpose:  Add a tooltip around the target DOM element provided as argument
         | 
| 1319 1320 | 
             
                       * Returns:  -
         | 
| @@ -1349,22 +1350,22 @@ require = (function e(t, n, r) { function s(o, u) { if (!n[o]) { if (!t[o]) { va | |
| 1349 1350 |  | 
| 1350 1351 | 
             
                            /**
         | 
| 1351 1352 | 
             
                      * Annotate a set of intervals provided in the argument.
         | 
| 1352 | 
            -
                      * | 
| 1353 | 
            +
                      *
         | 
| 1353 1354 | 
             
                      * @example
         | 
| 1354 1355 | 
             
                      * // Annotations using regions with different colors.
         | 
| 1355 1356 | 
             
                      * mySequence.addAnnotation({
         | 
| 1356 | 
            -
                    *    name:"UNIPROT", | 
| 1357 | 
            -
                    *    html:"<br> Example of <b>HTML</b>", | 
| 1358 | 
            -
                    *    color:"green", | 
| 1357 | 
            +
                    *    name:"UNIPROT",
         | 
| 1358 | 
            +
                    *    html:"<br> Example of <b>HTML</b>",
         | 
| 1359 | 
            +
                    *    color:"green",
         | 
| 1359 1360 | 
             
                    *    regions: [
         | 
| 1360 1361 | 
             
                    *       {start: 540, end: 560},
         | 
| 1361 | 
            -
                    *       {start: 561, end:580, color: "#FFA010"}, | 
| 1362 | 
            -
                    *       {start: 581, end:590, color: "red"}, | 
| 1362 | 
            +
                    *       {start: 561, end:580, color: "#FFA010"},
         | 
| 1363 | 
            +
                    *       {start: 581, end:590, color: "red"},
         | 
| 1363 1364 | 
             
                    *       {start: 690, end:710}]
         | 
| 1364 1365 | 
             
                    * });
         | 
| 1365 | 
            -
                    * | 
| 1366 | 
            -
                      * | 
| 1367 | 
            -
                      * @param {Object} annotation The intervals belonging to the same annotation. | 
| 1366 | 
            +
                    *
         | 
| 1367 | 
            +
                      *
         | 
| 1368 | 
            +
                      * @param {Object} annotation The intervals belonging to the same annotation.
         | 
| 1368 1369 | 
             
                      * Syntax: { name: <value>, color: <HTMLColorCode>, html: <HTMLString>, regions: [{ start: <startVal1>, end: <endVal1>}, ...,  { start: <startValN>, end: <endValN>}] }
         | 
| 1369 1370 | 
             
                      */
         | 
| 1370 1371 | 
             
                            addAnnotation: function (annotation) {
         | 
| @@ -1374,13 +1375,13 @@ require = (function e(t, n, r) { function s(o, u) { if (!n[o]) { if (!t[o]) { va | |
| 1374 1375 |  | 
| 1375 1376 | 
             
                            /**
         | 
| 1376 1377 | 
             
                      * Removes an annotation by means of its name.
         | 
| 1377 | 
            -
                      * | 
| 1378 | 
            -
                      * @example | 
| 1378 | 
            +
                      *
         | 
| 1379 | 
            +
                      * @example
         | 
| 1379 1380 | 
             
                      * // Remove the UNIPROT annotation.
         | 
| 1380 | 
            -
                      * mySequence.removeAnnotation('UNIPROT'); | 
| 1381 | 
            -
                      * | 
| 1381 | 
            +
                      * mySequence.removeAnnotation('UNIPROT');
         | 
| 1382 | 
            +
                      *
         | 
| 1382 1383 | 
             
                      * @param {string} name The name of the annotation to be removed.
         | 
| 1383 | 
            -
                      * | 
| 1384 | 
            +
                      *
         | 
| 1384 1385 | 
             
                      */
         | 
| 1385 1386 | 
             
                            removeAnnotation: function (name) {
         | 
| 1386 1387 | 
             
                                for (var i = 0; i < this._annotations.length; i++) {
         | 
| @@ -1393,10 +1394,10 @@ require = (function e(t, n, r) { function s(o, u) { if (!n[o]) { if (!t[o]) { va | |
| 1393 1394 | 
             
                            },
         | 
| 1394 1395 | 
             
                            /**
         | 
| 1395 1396 | 
             
                      * Removes all the current annotations.
         | 
| 1396 | 
            -
                      * | 
| 1397 | 
            -
                      * @example | 
| 1398 | 
            -
                      * mySequence.removeAllAnnotations(); | 
| 1399 | 
            -
                      * | 
| 1397 | 
            +
                      *
         | 
| 1398 | 
            +
                      * @example
         | 
| 1399 | 
            +
                      * mySequence.removeAllAnnotations();
         | 
| 1400 | 
            +
                      *
         | 
| 1400 1401 | 
             
                      */
         | 
| 1401 1402 | 
             
                            removeAllAnnotations: function () {
         | 
| 1402 1403 | 
             
                                this._annotations = [];
         | 
| @@ -2454,4 +2455,3 @@ require = (function e(t, n, r) { function s(o, u) { if (!n[o]) { if (!t[o]) { va | |
| 2454 2455 |  | 
| 2455 2456 | 
             
                }, { './lib/index': 1 }]
         | 
| 2456 2457 | 
             
            }, {}, ['biojs-vis-sequence']);
         | 
| 2457 | 
            -
            //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCIvVXNlcnMvcHJpeWFtL3NlcXVlbmNlc2VydmVyL25vZGVfbW9kdWxlcy9iaW9qcy12aXMtc2VxdWVuY2UvbGliL2luZGV4LmpzIiwiL1VzZXJzL3ByaXlhbS9zZXF1ZW5jZXNlcnZlci9ub2RlX21vZHVsZXMvYmlvanMtdmlzLXNlcXVlbmNlL25vZGVfbW9kdWxlcy9iaW9qcy1ldmVudHMvaW5kZXguanMiLCIvVXNlcnMvcHJpeWFtL3NlcXVlbmNlc2VydmVyL25vZGVfbW9kdWxlcy9iaW9qcy12aXMtc2VxdWVuY2Uvbm9kZV9tb2R1bGVzL2Jpb2pzLWV2ZW50cy9ub2RlX21vZHVsZXMvYmFja2JvbmUtZXZlbnRzLXN0YW5kYWxvbmUvYmFja2JvbmUtZXZlbnRzLXN0YW5kYWxvbmUuanMiLCIvVXNlcnMvcHJpeWFtL3NlcXVlbmNlc2VydmVyL25vZGVfbW9kdWxlcy9iaW9qcy12aXMtc2VxdWVuY2Uvbm9kZV9tb2R1bGVzL2Jpb2pzLWV2ZW50cy9ub2RlX21vZHVsZXMvYmFja2JvbmUtZXZlbnRzLXN0YW5kYWxvbmUvaW5kZXguanMiLCIvVXNlcnMvcHJpeWFtL3NlcXVlbmNlc2VydmVyL25vZGVfbW9kdWxlcy9iaW9qcy12aXMtc2VxdWVuY2Uvbm9kZV9tb2R1bGVzL2Jpb2pzLWlvLWZhc3RhL2xpYi9nZW5lcmljX3JlYWRlci5qcyIsIi9Vc2Vycy9wcml5YW0vc2VxdWVuY2VzZXJ2ZXIvbm9kZV9tb2R1bGVzL2Jpb2pzLXZpcy1zZXF1ZW5jZS9ub2RlX21vZHVsZXMvYmlvanMtaW8tZmFzdGEvbGliL3BhcnNlci5qcyIsIi9Vc2Vycy9wcml5YW0vc2VxdWVuY2VzZXJ2ZXIvbm9kZV9tb2R1bGVzL2Jpb2pzLXZpcy1zZXF1ZW5jZS9ub2RlX21vZHVsZXMvYmlvanMtaW8tZmFzdGEvbGliL3N0cmluZ3MuanMiLCIvVXNlcnMvcHJpeWFtL3NlcXVlbmNlc2VydmVyL25vZGVfbW9kdWxlcy9iaW9qcy12aXMtc2VxdWVuY2Uvbm9kZV9tb2R1bGVzL2Jpb2pzLWlvLWZhc3RhL2xpYi91dGlscy5qcyIsIi9Vc2Vycy9wcml5YW0vc2VxdWVuY2VzZXJ2ZXIvbm9kZV9tb2R1bGVzL2Jpb2pzLXZpcy1zZXF1ZW5jZS9ub2RlX21vZHVsZXMvYmlvanMtaW8tZmFzdGEvbGliL3dyaXRlci5qcyIsIi9Vc2Vycy9wcml5YW0vc2VxdWVuY2VzZXJ2ZXIvbm9kZV9tb2R1bGVzL2Jpb2pzLXZpcy1zZXF1ZW5jZS9ub2RlX21vZHVsZXMvYmlvanMtaW8tZmFzdGEvbm9kZV9tb2R1bGVzL2Jpb2pzLW1vZGVsL3NyYy9pbmRleC5qcyIsIi9Vc2Vycy9wcml5YW0vc2VxdWVuY2VzZXJ2ZXIvbm9kZV9tb2R1bGVzL2Jpb2pzLXZpcy1zZXF1ZW5jZS9ub2RlX21vZHVsZXMvYmlvanMtaW8tZmFzdGEvbm9kZV9tb2R1bGVzL2Jpb2pzLW1vZGVsL3NyYy9zZXEuanMiLCIvVXNlcnMvcHJpeWFtL3NlcXVlbmNlc2VydmVyL25vZGVfbW9kdWxlcy9iaW9qcy12aXMtc2VxdWVuY2Uvbm9kZV9tb2R1bGVzL2Jpb2pzLWlvLWZhc3RhL25vZGVfbW9kdWxlcy9uZXRzL2luZGV4LmpzIiwiL1VzZXJzL3ByaXlhbS9zZXF1ZW5jZXNlcnZlci9ub2RlX21vZHVsZXMvYmlvanMtdmlzLXNlcXVlbmNlL25vZGVfbW9kdWxlcy9iaW9qcy1pby1mYXN0YS9ub2RlX21vZHVsZXMvbmV0cy9ub2RlX21vZHVsZXMveGhyL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2Jpb2pzLWlvLWZhc3RhL25vZGVfbW9kdWxlcy9uZXRzL25vZGVfbW9kdWxlcy94aHIvbm9kZV9tb2R1bGVzL2dsb2JhbC93aW5kb3cuanMiLCIvVXNlcnMvcHJpeWFtL3NlcXVlbmNlc2VydmVyL25vZGVfbW9kdWxlcy9iaW9qcy12aXMtc2VxdWVuY2Uvbm9kZV9tb2R1bGVzL2Jpb2pzLWlvLWZhc3RhL25vZGVfbW9kdWxlcy9uZXRzL25vZGVfbW9kdWxlcy94aHIvbm9kZV9tb2R1bGVzL29uY2Uvb25jZS5qcyIsIi9Vc2Vycy9wcml5YW0vc2VxdWVuY2VzZXJ2ZXIvbm9kZV9tb2R1bGVzL2Jpb2pzLXZpcy1zZXF1ZW5jZS9ub2RlX21vZHVsZXMvYmlvanMtaW8tZmFzdGEvbm9kZV9tb2R1bGVzL25ldHMvbm9kZV9tb2R1bGVzL3hoci9ub2RlX21vZHVsZXMvcGFyc2UtaGVhZGVycy9ub2RlX21vZHVsZXMvZm9yLWVhY2gvaW5kZXguanMiLCIvVXNlcnMvcHJpeWFtL3NlcXVlbmNlc2VydmVyL25vZGVfbW9kdWxlcy9iaW9qcy12aXMtc2VxdWVuY2Uvbm9kZV9tb2R1bGVzL2Jpb2pzLWlvLWZhc3RhL25vZGVfbW9kdWxlcy9uZXRzL25vZGVfbW9kdWxlcy94aHIvbm9kZV9tb2R1bGVzL3BhcnNlLWhlYWRlcnMvbm9kZV9tb2R1bGVzL2Zvci1lYWNoL25vZGVfbW9kdWxlcy9pcy1mdW5jdGlvbi9pbmRleC5qcyIsIi9Vc2Vycy9wcml5YW0vc2VxdWVuY2VzZXJ2ZXIvbm9kZV9tb2R1bGVzL2Jpb2pzLXZpcy1zZXF1ZW5jZS9ub2RlX21vZHVsZXMvYmlvanMtaW8tZmFzdGEvbm9kZV9tb2R1bGVzL25ldHMvbm9kZV9tb2R1bGVzL3hoci9ub2RlX21vZHVsZXMvcGFyc2UtaGVhZGVycy9ub2RlX21vZHVsZXMvdHJpbS9pbmRleC5qcyIsIi9Vc2Vycy9wcml5YW0vc2VxdWVuY2VzZXJ2ZXIvbm9kZV9tb2R1bGVzL2Jpb2pzLXZpcy1zZXF1ZW5jZS9ub2RlX21vZHVsZXMvYmlvanMtaW8tZmFzdGEvbm9kZV9tb2R1bGVzL25ldHMvbm9kZV9tb2R1bGVzL3hoci9ub2RlX21vZHVsZXMvcGFyc2UtaGVhZGVycy9wYXJzZS1oZWFkZXJzLmpzIiwiL1VzZXJzL3ByaXlhbS9zZXF1ZW5jZXNlcnZlci9ub2RlX21vZHVsZXMvYmlvanMtdmlzLXNlcXVlbmNlL25vZGVfbW9kdWxlcy9qcXVlcnktYnJvd3Nlci1wbHVnaW4vaW5kZXguanMiLCIvVXNlcnMvcHJpeWFtL3NlcXVlbmNlc2VydmVyL25vZGVfbW9kdWxlcy9iaW9qcy12aXMtc2VxdWVuY2Uvbm9kZV9tb2R1bGVzL2pxdWVyeS1icm93c2VyLXBsdWdpbi9qcXVlcnkuYnJvd3Nlci5qcyIsIm5vZGVfbW9kdWxlcy9qcy1jbGFzcy9jbGFzcy5qcyIsIi9Vc2Vycy9wcml5YW0vc2VxdWVuY2VzZXJ2ZXIvbm9kZV9tb2R1bGVzL2Jpb2pzLXZpcy1zZXF1ZW5jZS9ub2RlX21vZHVsZXMvYmlvanMtaW8tZmFzdGEvbGliL2luZGV4LmpzIiwiLi9pbmRleC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzc1Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDclJBO0FBQ0E7O0FDREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25EQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxQkE7QUFDQTs7QUNEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNOQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNOQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FDakxBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDVEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDZkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlCQTtBQUNBOztBQ0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FDOUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQ2hJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ0pBO0FBQ0EiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbiBlKHQsbixyKXtmdW5jdGlvbiBzKG8sdSl7aWYoIW5bb10pe2lmKCF0W29dKXt2YXIgYT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2lmKCF1JiZhKXJldHVybiBhKG8sITApO2lmKGkpcmV0dXJuIGkobywhMCk7dmFyIGY9bmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitvK1wiJ1wiKTt0aHJvdyBmLmNvZGU9XCJNT0RVTEVfTk9UX0ZPVU5EXCIsZn12YXIgbD1uW29dPXtleHBvcnRzOnt9fTt0W29dWzBdLmNhbGwobC5leHBvcnRzLGZ1bmN0aW9uKGUpe3ZhciBuPXRbb11bMV1bZV07cmV0dXJuIHMobj9uOmUpfSxsLGwuZXhwb3J0cyxlLHQsbixyKX1yZXR1cm4gbltvXS5leHBvcnRzfXZhciBpPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7Zm9yKHZhciBvPTA7bzxyLmxlbmd0aDtvKyspcyhyW29dKTtyZXR1cm4gc30pIiwiLy8gbGVnYWN5ISFcbiQuYnJvd3NlciA9IHJlcXVpcmUoXCJqcXVlcnktYnJvd3Nlci1wbHVnaW5cIik7XG5cbi8qKiBcbiAqIFNlcXVlbmNlIGNvbXBvbmVudCBcbiAqIFxuICogQGNsYXNzXG4gKiBAZXh0ZW5kcyBCaW9qc1xuICogXG4gKiBAYXV0aG9yIDxhIGhyZWY9XCJtYWlsdG86am9obmNhckBnbWFpbC5jb21cIj5Kb2huIEdvbWV6PC9hPiwgPGEgaHJlZj1cIm1haWx0bzpzZWNldmFsbGl2QGdtYWlsLmNvbVwiPkpvc2UgVmlsbGF2ZWNlczwvYT5cbiAqIEB2ZXJzaW9uIDEuMC4wXG4gKiBAY2F0ZWdvcnkgM1xuICogXG4gKiBAcmVxdWlyZXMgPGEgaHJlZj0naHR0cDovL2Jsb2cuanF1ZXJ5LmNvbS8yMDExLzA5LzEyL2pxdWVyeS0xLTYtNC1yZWxlYXNlZC8nPmpRdWVyeSBDb3JlIDEuNi40PC9hPlxuICogQGRlcGVuZGVuY3kgPHNjcmlwdCBsYW5ndWFnZT1cIkphdmFTY3JpcHRcIiB0eXBlPVwidGV4dC9qYXZhc2NyaXB0XCIgc3JjPVwiLi4vYmlvanMvZGVwZW5kZW5jaWVzL2pxdWVyeS9qcXVlcnktMS40LjIubWluLmpzXCI+PC9zY3JpcHQ+XG4gKiBcbiAqIEByZXF1aXJlcyA8YSBocmVmPSdodHRwOi8vanF1ZXJ5dWkuY29tL2Rvd25sb2FkJz5qUXVlcnkgVUkgMS44LjE2PC9hPlxuICogQGRlcGVuZGVuY3kgPHNjcmlwdCBsYW5ndWFnZT1cIkphdmFTY3JpcHRcIiB0eXBlPVwidGV4dC9qYXZhc2NyaXB0XCIgc3JjPVwiLi4vYmlvanMvZGVwZW5kZW5jaWVzL2pxdWVyeS9qcXVlcnktdWktMS44LjIuY3VzdG9tLm1pbi5qc1wiPjwvc2NyaXB0PlxuICpcbiAqIEByZXF1aXJlcyA8YSBocmVmPSdCaW9qcy5Ub29sdGlwLmNzcyc+QmlvanMuVG9vbHRpcDwvYT5cbiAqIEBkZXBlbmRlbmN5IDxzY3JpcHQgbGFuZ3VhZ2U9XCJKYXZhU2NyaXB0XCIgdHlwZT1cInRleHQvamF2YXNjcmlwdFwiIHNyYz1cInNyYy9CaW9qcy5Ub29sdGlwLmpzXCI+PC9zY3JpcHQ+XG4gKiBcbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIEFuIG9iamVjdCB3aXRoIHRoZSBvcHRpb25zIGZvciBTZXF1ZW5jZSBjb21wb25lbnQuXG4gKiAgICBcbiAqIEBvcHRpb24ge3N0cmluZ30gdGFyZ2V0IFxuICogICAgSWRlbnRpZmllciBvZiB0aGUgRElWIHRhZyB3aGVyZSB0aGUgY29tcG9uZW50IHNob3VsZCBiZSBkaXNwbGF5ZWQuXG4gKiAgICBcbiAqIEBvcHRpb24ge3N0cmluZ30gc2VxdWVuY2UgXG4gKiAgICBUaGUgc2VxdWVuY2UgdG8gYmUgZGlzcGxheWVkLlxuICogICAgXG4gKiBAb3B0aW9uIHtzdHJpbmd9IFtpZF0gXG4gKiAgICBTZXF1ZW5jZSBpZGVudGlmaWVyIGlmIGFwcGx5LlxuICogICAgXG4gKiBAb3B0aW9uIHtzdHJpbmd9IFtmb3JtYXQ9XCJGQVNUQVwiXSBcbiAqICAgIFRoZSBkaXNwbGF5IGZvcm1hdCBmb3IgdGhlIHNlcXVlbmNlIHJlcHJlc2VudGF0aW9uLlxuICogICAgXG4gKiBAb3B0aW9uIHtPYmplY3RbXX0gW2hpZ2hsaWdodHNdIFxuICogXHQgIEZvciBoaWdobGlnaHRpbmcgbXVsdGlwbGUgcmVnaW9ucy4gXG4gKiAgICA8cHJlIGNsYXNzPVwiYnJ1c2g6IGpzXCIgdGl0bGU9XCJTeW50YXg6XCI+IFxuICogICAgW1xuICogICAgXHQvLyBIaWdobGlnaHQgYW1pbm9hY2lkcyBmcm9tICdzdGFydCcgdG8gJ2VuZCcgb2YgdGhlIGN1cnJlbnQgc3RyYW5kIHVzaW5nIHRoZSBzcGVjaWZpZWQgJ2NvbG9yJyAob3B0aW9uYWwpIGFuZCAnYmFja2dyb3VuZCcgKG9wdGlvbmFsKS5cbiAqICAgIFx0eyBzdGFydDogJmx0O3N0YXJ0VmFsMSZndDssIGVuZDogJmx0O2VuZFZhbDEmZ3Q7IFssIGlkOiZsdDtpZFZhbDEmZ3Q7XSBbLCBjb2xvcjogJmx0O0hUTUxDb2xvciZndDtdIFssIGJhY2tncm91bmQ6ICZsdDtIVE1MQ29sb3ImZ3Q7XX0sIFxuICogICAgXHQvL1xuICogICAgXHQvLyBBbnkgb3RoZXJzIGhpZ2hsaWdodHNcbiAqICAgIFx0Li4uLCAgXG4gKiAgICBcdC8vIFxuICogICAgXHR7IHN0YXJ0OiAmbHQ7c3RhcnRWYWxOJmd0OywgZW5kOiAmbHQ7ZW5kVmFsTiZndDsgWywgaWQ6Jmx0O2lkVmFsTiZndDtdIFssIGNvbG9yOiAmbHQ7SFRNTENvbG9yJmd0O10gWywgYmFja2dyb3VuZDogJmx0O0hUTUxDb2xvciZndDtdfVxuICogICAgXTwvcHJlPlxuICogXG4gKiA8cHJlIGNsYXNzPVwiYnJ1c2g6IGpzXCIgdGl0bGU9XCJFeGFtcGxlOlwiPiBcbiAqIGhpZ2hsaWdodHMgOiBbXG4gKiBcdFx0eyBzdGFydDozMCwgZW5kOjQyLCBjb2xvcjpcIndoaXRlXCIsIGJhY2tncm91bmQ6XCJncmVlblwiLCBpZDpcInNwaW4xXCIgfSxcbiAqXHRcdHsgc3RhcnQ6MTM5LCBlbmQ6MTQwIH0sIFxuICpcdFx0eyBzdGFydDo2MzEsIGVuZDo2MzMsIGNvbG9yOlwid2hpdGVcIiwgYmFja2dyb3VuZDpcImJsdWVcIiB9XG4gKlx0XVxuICogPC9wcmU+XG4gKiBcbiAqIEBvcHRpb24ge09iamVjdH0gW2NvbHVtbnM9e3NpemU6NDAsc3BhY2VkRWFjaDoxMH1dIFxuICogXHQgIE9wdGlvbnMgZm9yIGRpc3BsYXlpbmcgdGhlIGNvbHVtbnMuIFN5bnRheDogeyBzaXplOiAmbHQ7bnVtQ29scyZndDssIHNwYWNlZEVhY2g6ICZsdDtudW1Db2xzJmd0O31cbiAqIFxuICogQG9wdGlvbiB7T2JqZWN0fSBbc2VsZWN0aW9uXSBcbiAqIFx0ICBQb3NpdGlvbnMgZm9yIHRoZSBjdXJyZW50IHNlbGVjdGVkIHJlZ2lvbi4gU3ludGF4OiB7IHN0YXJ0OiAmbHQ7c3RhcnRWYWx1ZSZndDssIGVuZDogJmx0O2VuZFZhbHVlJmd0O31cbiAqIFxuICogQG9wdGlvbiB7T2JqZWN0W119IFthbm5vdGF0aW9uc10gXG4gKiAgICBTZXQgb2Ygb3ZlcmxhcHBpbmcgYW5ub3RhdGlvbnMuIE11c3QgYmUgYW4gYXJyYXkgb2Ygb2JqZWN0cyBmb2xsb3dpbmcgdGhlIHN5bnRheDpcbiAqICAgICBcdFx0PHByZSBjbGFzcz1cImJydXNoOiBqc1wiIHRpdGxlPVwiU3ludGF4OlwiPlxuICogICAgICAgICAgICBbIFxuICogICAgICAgICAgICAgIC8vIEFuIGFubm90YXRpb246XG4gKiAgICAgICAgICAgICAgeyBuYW1lOiAmbHQ7bmFtZSZndDssIFxuICogICAgICAgICAgICAgICAgaHRtbDogJmx0O21lc3NhZ2UmZ3Q7LCBcbiAqICAgICAgICAgICAgICAgIGNvbG9yOiAmbHQ7Y29sb3JfY29kZSZndDssIFxuICogICAgICAgICAgICAgICAgcmVnaW9uczogW3sgc3RhcnQ6ICZsdDtzdGFydFZhbDEmZ3Q7LCBlbmQ6ICZsdDtlbmRWYWwxJmd0OyBjb2xvcjogJmx0O0hUTUxDb2xvciZndDt9LCAuLi4seyBzdGFydDogJmx0O3N0YXJ0VmFsTiZndDssIGVuZDogJmx0O2VuZFZhbE4mZ3Q7LCBjb2xvcjogJmx0O0hUTUxDb2xvciZndDt9XSBcbiAqICAgICAgICAgICAgICB9LCBcbiAqICAgICAgICAgICAgICBcbiAqICAgICAgICAgICAgICAvLyAuLi5cbiAqICAgICAgICAgICAgICAvLyBtb3JlIGFubm90YXRpb25zIGhlcmUgXG4gKiAgICAgICAgICAgICAgLy8gLi4uXG4gKiAgICAgICAgICAgIF1cbiAqICAgIFx0XHQgPC9wcmU+XG4gKiAgICB3aGVyZTpcbiAqICAgICAgPHVsPlxuICogICAgICAgIDxsaT48Yj5uYW1lPC9iPiBpcyB0aGUgdW5pcXVlIG5hbWUgZm9yIHRoZSBhbm5vdGF0aW9uPC9saT5cbiAqICAgICAgICA8bGk+PGI+aHRtbDwvYj4gaXMgdGhlIG1lc3NhZ2UgKGNhbiBiZSBIVE1MKSB0byBiZSBkaXNwbGF5ZWQgaW4gdGhlIHRvb2wgdGlwLjwvbGk+XG4gKiAgICAgICAgPGxpPjxiPmNvbG9yPC9iPiBpcyB0aGUgZGVmYXVsdCBIVE1MIGNvbG9yIGNvZGUgZm9yIGFsbCB0aGUgcmVnaW9ucy48L2xpPlxuICogICAgICAgIDxsaT48Yj5yZWdpb25zPC9iPiBhcnJheSBvZiBvYmplY3RzIGRlZmluaW5nIHRoZSBpbnRlcnZhbHMgd2hpY2ggYmVsb25ncyB0byB0aGUgYW5ub3RhdGlvbi48L2xpPlxuICogICAgICAgIDxsaT48Yj5yZWdpb25zW2ldLnN0YXJ0PC9iPiBpcyB0aGUgc3RhcnRpbmcgY2hhcmFjdGVyIGZvciB0aGUgaS10aCBpbnRlcnZhbC48L2xpPlxuICogICAgICAgIDxsaT48Yj5yZWdpb25zW2ldLmVuZDwvYj4gaXMgdGhlIGVuZGluZyBjaGFyYWN0ZXIgZm9yIHRoZSBpLXRoIGludGVydmFsLjwvbGk+XG4gKiAgICAgICAgPGxpPjxiPnJlZ2lvbnNbaV0uY29sb3I8L2I+IGlzIGFuIG9wdGlvbmFsIGNvbG9yIGZvciB0aGUgaS10aCBpbnRlcnZhbC4gICBcbiAqICAgICAgPC91bD4gXG4gKiAgICAgIFxuICogQG9wdGlvbiB7T2JqZWN0fSBbZm9ybWF0T3B0aW9ucz17dGl0bGU6dHJ1ZSwgZm9vdGVyOnRydWV9XSBcbiAqIFx0ICBPcHRpb25zIGZvciBkaXNwbGF5aW5nIHRoZSB0aXRsZS4gYnkgbm93IGp1c3QgYWZmZWN0aW5nIHRoZSBDT0RBVEEgZm9ybWF0LlxuICogICAgPHByZSBjbGFzcz1cImJydXNoOiBqc1wiIHRpdGxlPVwiU3ludGF4OlwiPiBcbiAqIFx0XHRmb3JtYXRPcHRpb25zIDoge1xuICogXHRcdFx0dGl0bGU6ZmFsc2UsXG4gKiBcdFx0XHRmb290ZXI6ZmFsc2VcbiAqIFx0XHR9XG4gKiAgICA8L3ByZT5cbiAqICAgIFxuICogQGV4YW1wbGUgXG4gKiB2YXIgdGhlU2VxdWVuY2UgPSBcIk1FVExDUVJMTlZDUURLSUxUSFlFTkRTVERMUkRISURZV0tITVJMRUNBSVlZS0FSRU1HRktISU5IUVZWUFRMQVZTS05LQUxRQUlFTFFMVExFVElZTlNRWVNORUtXVExRRFZTTEVWWUxUQVBUR0NJS0tIR1lUVkVWUUZER0RJQ05UTUhZVE5XVEhJWUlDRUVBb2pzIFNWVFZWRUdRVkRZWUdMWVlWSEVHSVJUWUZWUUZLRERBRUtZU0tOS1ZXRVZIQUdHUVZJTENQVFNWRlNTTkVWU1NQRUlJUlFITEFOSFBBQVRIVEtBVkFMR1RFRVRRVFRJUVJQUlNFUERUR05QQ0hUVEtMTEhSRFNWRFNBUElMVEFGTlNTSEtHUklOQ05TTlRUUElWSExLR0RBTlRMS0NMUllSRktLSENUTFlUQVZTU1RXSFdUR0hOVktIS1NBSVZUTFRZRFNFV1FSRFFGTFNRVktJUEtUSVRWU1RHRk1TSVwiO1xuICogdmFyIG15U2VxdWVuY2UgPSBuZXcgU2VxdWVuY2Uoe1xuICogXHRcdHNlcXVlbmNlIDogdGhlU2VxdWVuY2UsXG4gKiBcdFx0dGFyZ2V0IDogXCJZb3VyT3duRGl2SWRcIixcbiAqIFx0XHRmb3JtYXQgOiAnQ09EQVRBJyxcbiAqIFx0XHRpZCA6ICdQOTE4MjgzJyxcbiAqIFx0XHRhbm5vdGF0aW9uczogW1xuICogICAgICAgIHsgbmFtZTpcIkNBVEhcIiwgXG4gKiBcdCAgXHRcdGNvbG9yOlwiI0YwRjAyMFwiLCBcbiAqIFx0ICBcdFx0aHRtbDogXCJVc2luZyBjb2xvciBjb2RlICNGMEYwMjAgXCIsIFxuICogXHQgIFx0XHRyZWdpb25zOiBbe3N0YXJ0OiAxMjIsIGVuZDogMTM1fV1cbiAqIFx0XHQgIH0sXG4gKiAgICAgICAgeyBuYW1lOlwiVEVTVFwiLCBcbiAqICAgICAgICAgIGh0bWw6XCImbHQ7YnImZ3Q7IEV4YW1wbGUgb2YgJmx0O2ImZ3Q7SFRNTCZsdDsvYiZndDtcIiwgXG4gKiAgICAgICAgICBjb2xvcjpcImdyZWVuXCIsIFxuICogICAgICAgICAgcmVnaW9uczogW1xuICogICAgICAgICAgICB7c3RhcnQ6IDI4NSwgZW5kOiAyOTJ9LFxuICogICAgICAgICAgICB7c3RhcnQ6IDI5MywgZW5kOiAzMTQsIGNvbG9yOiBcIiMyRTQ5ODhcIn1dXG4gKiAgICAgICAgfVxuICogICAgICBdLFxuICogICAgICBoaWdobGlnaHRzIDogW1xuICogICAgICBcdHsgc3RhcnQ6MzAsIGVuZDo0MiwgY29sb3I6XCJ3aGl0ZVwiLCBiYWNrZ3JvdW5kOlwiZ3JlZW5cIiwgaWQ6XCJzcGluMVwiIH0sXG4gKiAgICAgIFx0eyBzdGFydDoxMzksIGVuZDoxNDAgfSwgXG4gKiAgICAgIFx0eyBzdGFydDo2MzEsIGVuZDo2MzMsIGNvbG9yOlwid2hpdGVcIiwgYmFja2dyb3VuZDpcImJsdWVcIiB9XG4gKiAgICAgIF1cbiAqIH0pO1x0XG4gKiBcbiAqL1xuXG52YXIgQ2xhc3MgPSByZXF1aXJlKCdqcy1jbGFzcycpO1xuXG52YXIgRVZUX09OX1NFTEVDVElPTl9DSEFOR0U9IFwib25TZWxlY3Rpb25DaGFuZ2VcIjtcbnZhciBFVlRfT05fU0VMRUNUSU9OX0NIQU5HRUQ9IFwib25TZWxlY3Rpb25DaGFuZ2VkXCI7XG52YXIgRVZUX09OX0FOTk9UQVRJT05fQ0xJQ0tFRD0gXCJvbkFubm90YXRpb25DbGlja2VkXCI7XG5cblNlcXVlbmNlID0gQ2xhc3MoXG4vKiogQGxlbmRzIFNlcXVlbmNlIyAqL1xue1x0XG5cdGNvbnN0cnVjdG9yOiBmdW5jdGlvbiAob3B0aW9ucykge1xuXHRcdHZhciBzZWxmID0gdGhpcztcblxuICAgIHRoaXMub3B0ID0galF1ZXJ5LmV4dGVuZCh0aGlzLm9wdCxvcHRpb25zKTtcblxuICAgIHRoaXMuX2NvbnRhaW5lciA9IGpRdWVyeSh0aGlzLm9wdC50YXJnZXQgKTtcbiAgICBcbiAgICAvLyBsZWdhY3kgc3VwcG9ydCAodGFyZ2V0IGlkIHdpdGhvdXQgJyMnKVxuICAgIGlmKHRoaXMuX2NvbnRhaW5lci5sZW5ndGggPT0gMCl7XG4gICAgICB0aGlzLl9jb250YWluZXIgPSBqUXVlcnkoIFwiI1wiICsgdGhpcy5vcHQudGFyZ2V0IClcbiAgICB9XG5cbiAgICBpZih0aGlzLl9jb250YWluZXIubGVuZ3RoID09IDApe1xuICAgICAgY29uc29sZS5sb2coXCJlbXB0eSB0YXJnZXQgY29udGFpbmVyXCIpO1xuICAgIH1cblxuICAgIC8vIGxlZ2FjeTogY29weSB0YXJnZXQgaWRcbiAgICB0aGlzLm9wdC50YXJnZXQgPSB0aGlzLl9jb250YWluZXJbMF0uaWQ7XG5cdFx0XG5cdFx0Ly8gTGF6eSBpbml0aWFsaXphdGlvbiBcblx0XHR0aGlzLl9jb250YWluZXIucmVhZHkoZnVuY3Rpb24oKSB7XG5cdFx0XHRzZWxmLl9pbml0aWFsaXplKCk7XG5cdFx0fSk7XG5cdH0sXG5cdFxuXHQvKipcblx0ICogRGVmYXVsdCB2YWx1ZXMgZm9yIHRoZSBvcHRpb25zXG5cdCAqIEBuYW1lIFNlcXVlbmNlLW9wdFxuXHQgKi9cblx0b3B0IDoge1xuXHRcdFxuXHRcdHNlcXVlbmNlIDogXCJcIixcblx0XHRpZCA6IFwiXCIsXG5cdFx0dGFyZ2V0IDogXCJcIixcblx0XHRmb3JtYXQgOiBcIkZBU1RBXCIsXG5cdFx0c2VsZWN0aW9uOiB7IHN0YXJ0OiAwLCBlbmQ6IDAgfSxcblx0XHRjb2x1bW5zOiB7IHNpemU6IDM1LCBzcGFjZWRFYWNoOiAxMCB9LFxuXHRcdGhpZ2hsaWdodHMgOiBbXSxcblx0XHRhbm5vdGF0aW9uczogW10sXG5cdFx0c2VxdWVuY2VVcmw6ICdodHRwOi8vd3d3LmViaS5hYy51ay9kYXMtc3J2L3VuaXByb3QvZGFzL3VuaXByb3Qvc2VxdWVuY2UnLFxuXHRcdFxuXHRcdC8vIFN0eWxlcyBcblx0XHRzZWxlY3Rpb25Db2xvciA6ICdZZWxsb3cnLFxuXHRcdHNlbGVjdGlvbkZvbnRDb2xvciA6ICdibGFjaycsXG5cdFx0aGlnaGxpZ2h0Rm9udENvbG9yIDogJ3JlZCcsXG5cdFx0aGlnaGxpZ2h0QmFja2dyb3VuZENvbG9yIDogJ3doaXRlJyxcblx0XHRmb250RmFtaWx5OiAnXCJBbmRhbGUgbW9ub1wiLCBjb3VyaWVyLCBtb25vc3BhY2UnLFxuXHRcdGZvbnRTaXplOiAnMTJweCcsXG5cdFx0Zm9udENvbG9yIDogJ2luaGVyaXQnLFxuXHRcdGJhY2tncm91bmRDb2xvciA6ICdpbmhlcml0Jyxcblx0XHR3aWR0aDogdW5kZWZpbmVkLFxuXHRcdGhlaWdodDogdW5kZWZpbmVkLFxuXHRcdGZvcm1hdFNlbGVjdG9yVmlzaWJsZTogdHJ1ZVxuXHR9LFxuXHRcblx0LyoqXG5cdCAqIEFycmF5IGNvbnRhaW5pbmcgdGhlIHN1cHBvcnRlZCBldmVudCBuYW1lc1xuXHQgKiBAbmFtZSBTZXF1ZW5jZS1ldmVudFR5cGVzXG5cdCAqL1xuXHRldmVudFR5cGVzIDogW1xuXHRcdC8qKlxuXHRcdCAqIEBuYW1lIFNlcXVlbmNlI29uU2VsZWN0aW9uQ2hhbmdlZFxuXHRcdCAqIEBldmVudFxuXHRcdCAqIEBwYXJhbSB7ZnVuY3Rpb259IGFjdGlvblBlcmZvcm1lZCBBbiBmdW5jdGlvbiB3aGljaCByZWNlaXZlcyBhbiB7QGxpbmsgQmlvanMuRXZlbnR9IG9iamVjdCBhcyBhcmd1bWVudC5cblx0XHQgKiBAZXZlbnREYXRhIHtPYmplY3R9IHNvdXJjZSBUaGUgY29tcG9uZW50IHdoaWNoIGRpZCB0cmlnZ2VyZWQgdGhlIGV2ZW50LlxuXHRcdCAqIEBldmVudERhdGEge3N0cmluZ30gdHlwZSBUaGUgbmFtZSBvZiB0aGUgZXZlbnQuXG5cdFx0ICogQGV2ZW50RGF0YSB7aW50fSBzdGFydCBBIG51bWJlciBpbmRpY2F0aW5nIHRoZSBzdGFydCBvZiB0aGUgc2VsZWN0aW9uLlxuXHRcdCAqIEBldmVudERhdGEge2ludH0gZW5kIEEgbnVtYmVyIGluZGljYXRpbmcgdGhlIGVuZGluZyBvZiBzZWxlY3Rpb24uXG5cdFx0ICogQGV4YW1wbGUgXG5cdFx0ICogbXlTZXF1ZW5jZS5vblNlbGVjdGlvbkNoYW5nZWQoXG5cdFx0ICogICAgZnVuY3Rpb24oIG9iakV2ZW50ICkge1xuXHRcdCAqICAgICAgIGFsZXJ0KFwiU2VsZWN0ZWQ6IFwiICsgb2JqRXZlbnQuc3RhcnQgKyBcIiwgXCIgKyBvYmpFdmVudC5lbmQgKTtcblx0XHQgKiAgICB9XG5cdFx0ICogKTsgXG5cdFx0ICogXG5cdFx0ICogKi9cblx0XHRcIm9uU2VsZWN0aW9uQ2hhbmdlZFwiLFxuXHRcdFxuXHRcdC8qKlxuXHRcdCAqIEBuYW1lIFNlcXVlbmNlI29uU2VsZWN0aW9uQ2hhbmdlXG5cdFx0ICogQGV2ZW50XG5cdFx0ICogQHBhcmFtIHtmdW5jdGlvbn0gYWN0aW9uUGVyZm9ybWVkIEFuIGZ1bmN0aW9uIHdoaWNoIHJlY2VpdmVzIGFuIHtAbGluayBCaW9qcy5FdmVudH0gb2JqZWN0IGFzIGFyZ3VtZW50LlxuXHRcdCAqIEBldmVudERhdGEge09iamVjdH0gc291cmNlIFRoZSBjb21wb25lbnQgd2hpY2ggZGlkIHRyaWdnZXJlZCB0aGUgZXZlbnQuXG5cdFx0ICogQGV2ZW50RGF0YSB7c3RyaW5nfSB0eXBlIFRoZSBuYW1lIG9mIHRoZSBldmVudC5cblx0XHQgKiBAZXZlbnREYXRhIHtpbnR9IHN0YXJ0IEEgbnVtYmVyIGluZGljYXRpbmcgdGhlIHN0YXJ0IG9mIHRoZSBzZWxlY3Rpb24uXG5cdFx0ICogQGV2ZW50RGF0YSB7aW50fSBlbmQgQSBudW1iZXIgaW5kaWNhdGluZyB0aGUgZW5kaW5nIG9mIHNlbGVjdGlvbi5cblx0XHQgKiBAZXhhbXBsZSBcblx0XHQgKiBteVNlcXVlbmNlLm9uU2VsZWN0aW9uQ2hhbmdlKFxuXHRcdCAqICAgIGZ1bmN0aW9uKCBvYmpFdmVudCApIHtcblx0XHQgKiAgICAgICBhbGVydChcIlNlbGVjdGlvbiBpbiBwcm9ncmVzczogXCIgKyBvYmpFdmVudC5zdGFydCArIFwiLCBcIiArIG9iakV2ZW50LmVuZCApO1xuXHRcdCAqICAgIH1cblx0XHQgKiApOyAgXG5cdFx0ICogXG5cdFx0ICogXG5cdFx0ICogKi9cblx0XHRcIm9uU2VsZWN0aW9uQ2hhbmdlXCIsXG5cdFx0XG5cdFx0LyoqXG5cdFx0ICogQG5hbWUgU2VxdWVuY2Ujb25Bbm5vdGF0aW9uQ2xpY2tlZFxuXHRcdCAqIEBldmVudFxuXHRcdCAqIEBwYXJhbSB7ZnVuY3Rpb259IGFjdGlvblBlcmZvcm1lZCBBbiBmdW5jdGlvbiB3aGljaCByZWNlaXZlcyBhbiB7QGxpbmsgQmlvanMuRXZlbnR9IG9iamVjdCBhcyBhcmd1bWVudC5cblx0XHQgKiBAZXZlbnREYXRhIHtPYmplY3R9IHNvdXJjZSBUaGUgY29tcG9uZW50IHdoaWNoIGRpZCB0cmlnZ2VyZWQgdGhlIGV2ZW50LlxuXHRcdCAqIEBldmVudERhdGEge3N0cmluZ30gdHlwZSBUaGUgbmFtZSBvZiB0aGUgZXZlbnQuXG5cdFx0ICogQGV2ZW50RGF0YSB7c3RyaW5nfSBuYW1lIFRoZSBuYW1lIG9mIHRoZSBzZWxlY3RlZCBhbm5vdGF0aW9uLlxuXHRcdCAqIEBldmVudERhdGEge2ludH0gcG9zIEEgbnVtYmVyIGluZGljYXRpbmcgdGhlIHBvc2l0aW9uIG9mIHRoZSBzZWxlY3RlZCBhbWlubyBhY2lkLlxuXHRcdCAqIEBleGFtcGxlIFxuXHRcdCAqIG15U2VxdWVuY2Uub25Bbm5vdGF0aW9uQ2xpY2tlZChcblx0XHQgKiAgICBmdW5jdGlvbiggb2JqRXZlbnQgKSB7XG5cdFx0ICogICAgICAgYWxlcnQoXCJDbGlja2VkIFwiICsgb2JqRXZlbnQubmFtZSArIFwiIG9uIHBvc2l0aW9uIFwiICsgb2JqRXZlbnQucG9zICk7XG5cdFx0ICogICAgfVxuXHRcdCAqICk7ICBcblx0XHQgKiBcblx0XHQgKiAqL1xuXHRcdFwib25Bbm5vdGF0aW9uQ2xpY2tlZFwiXG5cdF0sXG5cbiAgZ2V0SWQgOiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMub3B0LmlkO1xuICB9LFxuXG5cdC8vIGludGVybmFsIG1lbWJlcnNcblx0X2hlYWRlckRpdiA6IG51bGwsXG5cdF9jb250ZW50RGl2IDogbnVsbCxcblx0XG5cdC8vIE1ldGhvZHNcblxuXHRfaW5pdGlhbGl6ZTogZnVuY3Rpb24gKCkge1xuXHRcdFxuXHRcdGlmICggdGhpcy5vcHQud2lkdGggIT09IHVuZGVmaW5lZCApIHtcblx0XHRcdHRoaXMuX2NvbnRhaW5lci53aWR0aCggdGhpcy5vcHQud2lkdGggKTtcblx0XHR9XG5cdFx0XG5cdFx0aWYgKCB0aGlzLm9wdC5oZWlnaHQgIT09IHVuZGVmaW5lZCApIHtcblx0XHRcdHRoaXMuX2NvbnRhaW5lci5oZWlnaHQoIHRoaXMub3B0LmhlaWdodCApO1xuXHRcdH1cblx0XHRcblx0XHQvLyBEaXNhYmxlIHRleHQgc2VsZWN0aW9uXG5cdFx0XG5cdFx0dGhpcy5fY29udGFpbmVyLmNzcyh7XG5cdFx0XHQnLW1vei11c2VyLXNlbGVjdCc6J25vbmUnLFxuXHRcdFx0Jy13ZWJraXQtdXNlci1zZWxlY3QnOidub25lJyxcblx0XHRcdCd1c2VyLXNlbGVjdCc6J25vbmUnXG4gICAgICAgIH0pO1xuXHRcdFxuXHRcdC8vIERJViBmb3IgdGhlIGZvcm1hdCBzZWxlY3RvclxuXHRcdHRoaXMuX2J1aWxkRm9ybWF0U2VsZWN0b3IoKTtcblx0XHRcblx0XHQvLyBESVYgZm9yIHRoZSBzZXF1ZW5jZVxuXHRcdHRoaXMuX2NvbnRlbnREaXYgPSBqUXVlcnkoJzxkaXY+PC9kaXY+JykuYXBwZW5kVG8odGhpcy5fY29udGFpbmVyKTtcblx0XHR0aGlzLl9jb250ZW50RGl2LmNzcyh7XG5cdFx0XHRcdCdmb250LWZhbWlseSc6IHRoaXMub3B0LmZvbnRGYW1pbHksXG5cdFx0XHRcdCdmb250LXNpemUnOiB0aGlzLm9wdC5mb250U2l6ZSxcblx0XHRcdFx0J3RleHQtYWxpZ24nOiAnbGVmdCdcblx0XHRcdH0pO1xuXHRcdFxuXHRcdC8vIEluaXRpYWxpemUgaGlnaGxpZ2h0aW5nIFxuXHRcdHRoaXMuX2hpZ2hsaWdodHMgPSB0aGlzLm9wdC5oaWdobGlnaHRzO1xuXHRcdFxuXHRcdC8vIEluaXRpYWxpemUgYW5ub3RhdGlvbnNcblx0XHR0aGlzLl9hbm5vdGF0aW9ucyA9IHRoaXMub3B0LmFubm90YXRpb25zO1xuXHRcdFxuXHRcdC8vSW5pdGlhbGl6ZSB0b29sdGlwXG5cdFx0dmFyIHRvb2x0aXAgPSBcInNlcXVlbmNlVGlwXCIgKyB0aGlzLm9wdC50YXJnZXQgO1xuXHRcdGpRdWVyeSgnPGRpdiBpZD1cIicgKyB0b29sdGlwICsgJ1wiPjwvZGl2PicpIFxuXHQgICAgICAgIC5jc3Moe1x0XG5cdCAgICAgICAgXHQncG9zaXRpb24nOiBcImFic29sdXRlXCIsXG5cdCAgICAgICAgXHQnei1pbmRleCc6IFwiOTk5OTk5XCIsXG5cdCAgICAgICAgXHQnY29sb3InOiBcIiNmZmZcIixcblx0ICAgICAgICBcdCdmb250LXNpemUnOiBcIjEycHhcIixcblx0ICAgICAgICBcdCd3aWR0aCc6IFwiYXV0b1wiLFxuXHQgICAgICAgIFx0J2Rpc3BsYXknOiAnbm9uZSdcblx0ICAgICAgICB9KVxuXHQgICAgICAgIC5hZGRDbGFzcyhcInRvb2x0aXBcIilcblx0ICAgICAgICAuYXBwZW5kVG8oXCJib2R5XCIpXG5cdCAgICAgICAgLmhpZGUoKTtcblx0XHR0aGlzLm9wdC5fdG9vbHRpcCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRvb2x0aXApO1xuXG5cdFx0aWYgKCAodGhpcy5vcHQuc2VxdWVuY2UpICkge1xuXHRcdFx0dGhpcy5fcmVkcmF3KCk7XG5cdFx0XHRcblx0XHR9IGVsc2UgaWYgKCAgKHRoaXMub3B0LmlkKSApIHtcblx0XHRcdHRoaXMuX3JlcXVlc3RTZXF1ZW5jZSggdGhpcy5vcHQuaWQgKTtcblx0XHRcdFxuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLmNsZWFyU2VxdWVuY2UoXCJObyBzZXF1ZW5jZSBhdmFpbGFibGVcIiwgXCIuLi9iaW9qcy9jc3MvaW1hZ2VzL3dhcm5pbmdfaWNvbi5wbmdcIik7XG5cdFx0fVxuXHRcdFxuXHR9LFxuXHRcblx0XG5cdC8qKlxuXHQgKiBTaG93cyB0aGUgY29sdW1ucyBpbmRpY2F0ZWQgYnkgdGhlIGluZGV4ZXMgYXJyYXkuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBzZXEgVGhlIHNlcXVlbmNlIHN0cmFuZC5cblx0ICogQHBhcmFtIHtzdHJpbmd9IFtpZGVudGlmaWVyXSBTZXF1ZW5jZSBpZGVudGlmaWVyLlxuXHQgKiBcblx0ICogQGV4YW1wbGUgXG5cdCAqIG15U2VxdWVuY2Uuc2V0U2VxdWVuY2UoXCJQOTk5OTlcIik7XG5cdCAqIFxuXHQgKi9cbiAgICBzZXRTZXF1ZW5jZTogZnVuY3Rpb24gKCBzZXEsIGlkZW50aWZpZXIgKSB7XG5cbiAgICBcdGlmICggc2VxLm1hdGNoKC9eKFtBLU4sUi1aXVswLTldW0EtWl1bQS1aLCAwLTldW0EtWiwgMC05XVswLTldKXwoW08sUCxRXVswLTldW0EtWiwgMC05XVtBLVosIDAtOV1bQS1aLCAwLTldWzAtOV0pKFxcLlxcZCspPyQvaSkgKSB7XG4gICAgXHRcdHRoaXMuX3JlcXVlc3RTZXF1ZW5jZSggYXJndW1lbnRzWzBdICk7XG4gICAgXHRcdFxuICAgIFx0fSBlbHNlIHtcbiAgICBcdFx0dGhpcy5vcHQuc2VxdWVuY2UgPSBzZXE7XG4gICAgICAgIFx0dGhpcy5vcHQuaWQgPSBpZGVudGlmaWVyOyBcbiAgICAgICAgXHR0aGlzLl9oaWdobGlnaHRzID0gW107XG4gICAgXHRcdHRoaXMuX2hpZ2hsaWdodHNDb3VudCA9IDA7XG4gICAgXHRcdHRoaXMub3B0LnNlbGVjdGlvbiA9IHsgc3RhcnQ6IDAsIGVuZDogMCB9O1xuICAgIFx0XHR0aGlzLl9hbm5vdGF0aW9ucyA9IFtdO1xuICAgIFx0XHRcbiAgICBcdFx0dGhpcy5fY29udGVudERpdi5jaGlsZHJlbigpLnJlbW92ZSgpO1xuICAgIFx0XHR0aGlzLl9yZWRyYXcoKTtcbiAgICBcdH1cbiAgICB9LFxuICAgIFxuICAgIF9yZXF1ZXN0U2VxdWVuY2U6IGZ1bmN0aW9uICggYWNjZXNzaW9uICkge1xuXHRcdHZhciBzZWxmID0gdGhpcztcbiAgICBcdFxuICAgIFx0Y29uc29sZS5sb2coXCJSZXF1ZXN0aW5nIHNlcXVlbmNlIGZvcjogXCIgKyBhY2Nlc3Npb24gKTtcblxuXHRcdGpRdWVyeS5hamF4KHsgXG5cdFx0XHR1cmw6IHNlbGYub3B0LnNlcXVlbmNlVXJsLFxuXHRcdFx0ZGF0YVR5cGU6IFwieG1sXCIsXG5cdFx0XHRkYXRhOiB7IHNlZ21lbnQ6IGFjY2Vzc2lvbiB9LFxuXHRcdFx0c3VjY2VzczogZnVuY3Rpb24gKCB4bWwgICkge1xuXHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdFxuXHRcdFx0XHRcdHZhciBzZXF1ZW5jZU5vZGUgPSBqUXVlcnkoeG1sKS5maW5kKCdTRVFVRU5DRTpmaXJzdCcpO1xuXHRcdFx0XHRcdHNlbGYuc2V0U2VxdWVuY2UoIHNlcXVlbmNlTm9kZS50ZXh0KCksIHNlcXVlbmNlTm9kZS5hdHRyKFwiaWRcIiksIHNlcXVlbmNlTm9kZS5hdHRyKFwibGFiZWxcIikgKTtcblx0XHRcdFx0XHRcblx0XHRcdFx0fSBjYXRjaCAoZSkge1xuXHRcdFx0XHRcdGNvbnNvbGUubG9nKFwiRXJyb3IgZGVjb2RpbmcgcmVzcG9uc2UgZGF0YTogXCIgKyBlLm1lc3NhZ2UgKTtcblx0XHRcdFx0XHRzZWxmLmNsZWFyU2VxdWVuY2UoXCJObyBzZXF1ZW5jZSBhdmFpbGFibGVcIiwgXCIuLi9iaW9qcy9jc3MvaW1hZ2VzL3dhcm5pbmdfaWNvbi5wbmdcIik7XG5cdFx0XHRcdH1cblxuXHRcdFx0fSxcblx0XHRcdGVycm9yOiBmdW5jdGlvbiAoanFYSFIsIHRleHRTdGF0dXMsIGVycm9yVGhyb3duKSB7XG5cdFx0XHRcdGNvbnNvbGUubG9nKFwiRXJyb3IgZGVjb2RpbmcgcmVzcG9uc2UgZGF0YTogXCIgKyB0ZXh0U3RhdHVzICk7XG5cdFx0XHRcdHNlbGYuY2xlYXJTZXF1ZW5jZShcIkVycm9yIHJlcXVlc3RpbmcgdGhlIHNlcXVlbmNlIHRvIHRoZSBzZXJ2ZXIgXCIgKyB0aGlzLnVybCAsIFwiLi4vYmlvanMvY3NzL2ltYWdlcy93YXJuaW5nX2ljb24ucG5nXCIpO1xuXHRcdFx0fVxuXHRcdH0pO1xuICAgIH0sXG5cdFxuICAgIC8qKlxuXHQgKiBTaG93cyB0aGUgY29sdW1ucyBpbmRpY2F0ZWQgYnkgdGhlIGluZGV4ZXMgYXJyYXkuXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBbc2hvd01lc3NhZ2VdIE1lc3NhZ2UgdG8gYmUgc2hvd2VkLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gW2ljb25dIEljb24gdG8gYmUgc2hvd2VkIGEgc2lkZSBvZiB0aGUgbWVzc2FnZVxuXHQgKiBcblx0ICogQGV4YW1wbGUgXG5cdCAqIG15U2VxdWVuY2UuY2xlYXJTZXF1ZW5jZShcIk5vIHNlcXVlbmNlIGF2YWlsYWJsZVwiLCBcIi4uL2Jpb2pzL2Nzcy9pbWFnZXMvd2FybmluZ19pY29uLnBuZ1wiKTtcblx0ICogXG5cdCAqL1xuICAgIGNsZWFyU2VxdWVuY2U6IGZ1bmN0aW9uICggc2hvd01lc3NhZ2UsIGljb24gKSB7XG4gICAgXHRcbiAgICBcdHZhciBtZXNzYWdlID0gdW5kZWZpbmVkO1xuICAgIFx0XHRcbiAgICBcdHRoaXMub3B0LnNlcXVlbmNlID0gXCJcIjtcbiAgICBcdHRoaXMub3B0LmlkID0gXCJcIjsgXG4gICAgXHR0aGlzLl9oaWdobGlnaHRzID0gW107XG5cdFx0dGhpcy5faGlnaGxpZ2h0c0NvdW50ID0gMDtcblx0XHR0aGlzLm9wdC5zZWxlY3Rpb24gPSB7IHN0YXJ0OiAwLCBlbmQ6IDAgfTtcblx0XHR0aGlzLl9hbm5vdGF0aW9ucyA9IFtdO1xuXHRcdHRoaXMuX2NvbnRlbnREaXYuY2hpbGRyZW4oKS5yZW1vdmUoKTtcblx0XHRcblx0XHR0aGlzLl9oZWFkZXJEaXYuaGlkZSgpO1xuXHRcdFxuXHRcdGlmICggdW5kZWZpbmVkICE9PSBzaG93TWVzc2FnZSApIHtcblx0XHRcdG1lc3NhZ2UgPSBqUXVlcnkoJzxkaXY+JyArIHNob3dNZXNzYWdlICsgJzwvZGl2PicpXG5cdFx0XHRcdC5hcHBlbmRUbyh0aGlzLl9jb250ZW50RGl2KVxuXHRcdFx0XHQuYWRkQ2xhc3MoXCJtZXNzYWdlXCIpO1xuXHRcdFx0XG5cdFx0XHRpZiAoIHVuZGVmaW5lZCAhPT0gaWNvbiApIHtcblx0XHRcdFx0bWVzc2FnZS5jc3Moe1xuXHRcdFx0XHRcdCdiYWNrZ3JvdW5kJzogJ3RyYW5zcGFyZW50IHVybChcIicgKyBpY29uICsgJ1wiKSBuby1yZXBlYXQgY2VudGVyIGxlZnQnLFxuXHRcdFx0XHRcdCdwYWRkaW5nLWxlZnQnOiAnMjBweCdcblx0XHRcdFx0fSk7XG5cdFx0XHR9XG5cdFx0fVxuICAgIH0sXG5cdFxuXHQvKipcbiAgICAqIFNldCB0aGUgY3VycmVudCBzZWxlY3Rpb24gaW4gdGhlIHNlcXVlbmNlIGNhdXNpbmcgdGhlIGV2ZW50IHtAbGluayBTZXF1ZW5jZSNvblNlbGVjdGlvbkNoYW5nZWR9XG4gICAgKlxuICAgICogQGV4YW1wbGVcbiAgICAqIC8vIHNldCBzZWxlY3Rpb24gZnJvbSB0aGUgcG9zaXRpb24gMTAwIHRvIDE1MCBcbiAgICAqIG15U2VxdWVuY2Uuc2V0U2VsZWN0aW9uKDEwMCwgMTUwKTtcbiAgICAqIFxuICAgICogQHBhcmFtIHtpbnR9IHN0YXJ0IFRoZSBzdGFydGluZyBjaGFyYWN0ZXIgb2YgdGhlIHNlbGVjdGlvbi5cbiAgICAqIEBwYXJhbSB7aW50fSBlbmQgVGhlIGVuZGluZyBjaGFyYWN0ZXIgb2YgdGhlIHNlbGVjdGlvblxuICAgICovXG5cdHNldFNlbGVjdGlvbiA6IGZ1bmN0aW9uKHN0YXJ0LCBlbmQpIHtcblx0XHRpZihzdGFydCA+IGVuZCkge1xuXHRcdFx0dmFyIGF1eCA9IGVuZDtcblx0XHRcdGVuZCA9IHN0YXJ0O1xuXHRcdFx0c3RhcnQgPSBhdXg7XG5cblx0XHR9XG5cblx0XHRpZihzdGFydCAhPSB0aGlzLm9wdC5zZWxlY3Rpb24uc3RhcnQgfHwgZW5kICE9IHRoaXMub3B0LnNlbGVjdGlvbi5lbmQpIHtcblx0XHRcdHRoaXMuX3NldFNlbGVjdGlvbihzdGFydCwgZW5kKTtcblx0XHRcdHRoaXMudHJpZ2dlcihcblx0XHRcdFx0XHRFVlRfT05fU0VMRUNUSU9OX0NIQU5HRUQsIFxuXHRcdFx0XHRcdHsgXCJzdGFydFwiIDogc3RhcnQsIFwiZW5kXCIgOiBlbmQgfVxuXHRcdFx0KTtcblx0XHR9XG5cdH0sXG5cdFxuXHRfYnVpbGRGb3JtYXRTZWxlY3RvcjogZnVuY3Rpb24gKCkge1xuXHRcdHZhciBzZWxmID0gdGhpcztcblx0XHRcblx0XHR0aGlzLl9oZWFkZXJEaXYgPSBqUXVlcnkoJzxkaXY+PC9kaXY+JykuYXBwZW5kVG8odGhpcy5fY29udGFpbmVyKTtcblx0XHR0aGlzLl9oZWFkZXJEaXYuY3NzKHtcblx0XHRcdCdmb250LWZhbWlseSc6ICdcIkhldmVsdGljYSBOZXVlXCIsIEFyaWFsLCBcInNhbnMgc2VyaWZcIicsXG5cdFx0XHQnZm9udC1zaXplJzogJzE0cHgnXHRcblx0XHR9KS5hcHBlbmQoJ0Zvcm1hdDogJyk7XG5cdFx0XG5cdFx0dGhpcy5fZm9ybWF0U2VsZWN0b3IgPSBqUXVlcnkoJzxzZWxlY3Q+ICcrXG5cdFx0XHRcdCc8b3B0aW9uIHZhbHVlPVwiRkFTVEFcIj5GQVNUQTwvb3B0aW9uPicrXG5cdFx0XHRcdCc8b3B0aW9uIHZhbHVlPVwiQ09EQVRBXCI+Q09EQVRBPC9vcHRpb24+Jytcblx0XHRcdFx0JzxvcHRpb24gdmFsdWU9XCJQUklERVwiPlBSSURFPC9vcHRpb24+Jytcblx0XHRcdFx0JzxvcHRpb24gdmFsdWU9XCJSQVdcIj5SQVc8L29wdGlvbj48L3NlbGVjdD4nKS5hcHBlbmRUbyhzZWxmLl9oZWFkZXJEaXYpO1xuXG5cdFx0dGhpcy5fZm9ybWF0U2VsZWN0b3IuY2hhbmdlKGZ1bmN0aW9uKGUpIHtcblx0XHRcdHNlbGYub3B0LmZvcm1hdCA9IGpRdWVyeSh0aGlzKS52YWwoKTtcblx0XHRcdHNlbGYuX3JlZHJhdygpO1xuXHRcdH0pO1xuXHRcdFxuXHRcdHRoaXMuX2Zvcm1hdFNlbGVjdG9yLnZhbChzZWxmLm9wdC5mb3JtYXQpO1x0XG5cdFx0XG5cdFx0dGhpcy5mb3JtYXRTZWxlY3RvclZpc2libGUoIHRoaXMub3B0LmZvcm1hdFNlbGVjdG9yVmlzaWJsZSApO1xuXHR9LFxuXHRcblx0LyoqXG4gICAgKiBIaWdobGlnaHRzIGEgcmVnaW9uIHVzaW5nIHRoZSBmb250IGNvbG9yIGRlZmluZWQgaW4ge0Jpb2pzLlByb3RlaW4zRCNoaWdobGlnaHRGb250Q29sb3J9IGJ5IGRlZmF1bHQgaXMgcmVkLlxuICAgICpcbiAgICAqIEBkZXByZWNhdGVkIHVzZSBhZGRIaWdobGlnaHQgaW5zdGVhZC5cbiAgICAqIFxuICAgICogQHBhcmFtIHtpbnR9IHN0YXJ0IFRoZSBzdGFydGluZyBjaGFyYWN0ZXIgb2YgdGhlIGhpZ2hsaWdodGluZy5cbiAgICAqIEBwYXJhbSB7aW50fSBlbmQgVGhlIGVuZGluZyBjaGFyYWN0ZXIgb2YgdGhlIGhpZ2hsaWdodGluZy5cbiAgICAqIEBwYXJhbSB7c3RyaW5nfSBbY29sb3JdIEhUTUwgY29sb3IgY29kZS5cbiAgICAqIEBwYXJhbSB7c3RyaW5nfSBbYmFja2dyb3VuZF0gSFRNTCBjb2xvciBjb2RlLlxuICAgICogQHBhcmFtIHtzdHJpbmd9IFtpZF0gQ3VzdG9tIGlkZW50aWZpZXIuXG4gICAgKiBcbiAgICAqIEByZXR1cm4ge2ludH0gcmVwcmVzZW50aW5nIHRoZSBpZCBvZiB0aGUgaGlnaGxpZ2h0IG9uIHRoZSBpbnRlcm5hbCBhcnJheS4gUmV0dXJucyAtMSBvbiBmYWlsdXJlICBcbiAgICAqL1xuXHRoaWdobGlnaHQgOiBmdW5jdGlvbiAoc3RhcnQsIGVuZCwgY29sb3IsIGJhY2tncm91bmQsIGlkICkge1xuXHRcdHJldHVybiB0aGlzLmFkZEhpZ2hsaWdodCh7IFwic3RhcnRcIjogc3RhcnQsIFwiZW5kXCI6IGVuZCwgXCJjb2xvclwiOiBjb2xvciwgXCJiYWNrZ3JvdW5kXCI6IGJhY2tncm91bmQsIFwiaWRcIjogaWQgfSk7XG5cdH0sXG5cdFxuXHQvKipcbiAgICAqIEhpZ2hsaWdodHMgYSByZWdpb24gdXNpbmcgdGhlIGZvbnQgY29sb3IgZGVmaW5lZCBpbiB7U2VxdWVuY2UjaGlnaGxpZ2h0Rm9udENvbG9yfSBieSBkZWZhdWx0IGlzIHJlZC5cbiAgICAqXG4gICAgKiBAZXhhbXBsZVxuICAgICogLy8gaGlnaGxpZ2h0IHRoZSBjaGFyYWN0ZXJzIHdpdGhpbiB0aGUgcG9zaXRpb24gMTAwIHRvIDE1MCwgaW5jbHVkZWQuXG4gICAgKiBteVNlcXVlbmNlLmFkZEhpZ2hsaWdodCggeyBcInN0YXJ0XCI6IDEwMCwgXCJlbmRcIjogMTUwLCBcImNvbG9yXCI6IFwid2hpdGVcIiwgXCJiYWNrZ3JvdW5kXCI6IFwicmVkXCIsIFwiaWRcIjogXCJhYWFcIiB9ICk7XG4gICAgKiBcbiAgICAqIEBwYXJhbSB7T2JqZWN0fSBoIFRoZSBoaWdobGlnaHQgZGVmaW5lZCBhcyBmb2xsb3dzOlxuICAgICogXHRcbiAgICAqIFxuICAgICogQHJldHVybiB7aW50fSByZXByZXNlbnRpbmcgdGhlIGlkIG9mIHRoZSBoaWdobGlnaHQgb24gdGhlIGludGVybmFsIGFycmF5LiBSZXR1cm5zIC0xIG9uIGZhaWx1cmUgIFxuICAgICovXG5cdGFkZEhpZ2hsaWdodCA6IGZ1bmN0aW9uICggaCApIHtcblx0XHR2YXIgaWQgPSAnLTEnO1xuXHRcdHZhciBjb2xvciA9IFwiXCI7XG5cdFx0dmFyIGJhY2tncm91bmQgPSBcIlwiO1xuXHRcdHZhciBoaWdobGlnaHQgPSB7fTtcblx0XHRcblx0XHRpZiAoIGggaW5zdGFuY2VvZiBPYmplY3QgJiYgaC5zdGFydCA8PSBoLmVuZCApIHtcblx0XHRcdFxuXHRcdFx0Y29sb3IgPSAoIFwic3RyaW5nXCIgPT0gdHlwZW9mIGguY29sb3IgKT8gaC5jb2xvciA6IHRoaXMub3B0LmhpZ2hsaWdodEZvbnRDb2xvcjtcblx0XHRcdGJhY2tncm91bmQgPSAoIFwic3RyaW5nXCIgPT0gdHlwZW9mIGguYmFja2dyb3VuZCApPyBoLmJhY2tncm91bmQgOiB0aGlzLm9wdC5oaWdobGlnaHRCYWNrZ3JvdW5kQ29sb3I7XG5cdFx0XHRpZCA9ICggXCJzdHJpbmdcIiA9PSB0eXBlb2YgaC5pZCApPyBoLmlkIDogKG5ldyBOdW1iZXIodGhpcy5faGlnaGxpZ2h0c0NvdW50KyspKS50b1N0cmluZygpO1xuXHRcdFx0XG5cdFx0XHRoaWdobGlnaHQgPSB7IFwic3RhcnRcIjogaC5zdGFydCwgXCJlbmRcIjogaC5lbmQsIFwiY29sb3JcIjogY29sb3IsIFwiYmFja2dyb3VuZFwiOiBiYWNrZ3JvdW5kLCBcImlkXCI6IGlkIH07XG5cdFx0XHRcblx0XHRcdHRoaXMuX2hpZ2hsaWdodHMucHVzaChoaWdobGlnaHQpO1xuXHRcdFx0dGhpcy5fYXBwbHlIaWdobGlnaHQoaGlnaGxpZ2h0KTtcblx0XHRcdHRoaXMuX3Jlc3RvcmVTZWxlY3Rpb24oaC5zdGFydCxoLmVuZCk7XG5cdFx0fSBcblx0XHRcblx0XHRyZXR1cm4gaWQ7XG5cdH0sXG5cdC8qIFxuICAgICAqIEZ1bmN0aW9uOiBTZXF1ZW5jZS5fYXBwbHlIaWdobGlnaHRcbiAgICAgKiBQdXJwb3NlOiAgQXBwbHkgdGhlIHNwZWNpZmllZCBjb2xvciBhbmQgYmFja2dyb3VuZCB0byBhIHJlZ2lvbiBiZXR3ZWVuICdzdGFydCcgYW5kICdlbmQnLlxuICAgICAqIFJldHVybnM6ICAtXG4gICAgICogSW5wdXRzOiBoaWdobGlnaHQgLT4ge09iamVjdH0gQW4gb2JqZWN0IGNvbnRhaW5pbmcgdGhlIGZpZWxkcyBzdGFydCAoaW50KSwgZW5kIChpbnQpLCBcbiAgICAgKiBcdFx0XHRcdFx0XHRjb2xvciAoSFRNTCBjb2xvciBzdHJpbmcpIGFuZCBiYWNrZ3JvdW5kIChIVE1MIGNvbG9yIHN0cmluZykuXG4gICAgICovXG5cdF9hcHBseUhpZ2hsaWdodDogZnVuY3Rpb24gKCBoaWdobGlnaHQgKSB7XHRcdFxuXHRcdHZhciBzZXEgPSB0aGlzLl9jb250ZW50RGl2LmZpbmQoJy5zZXF1ZW5jZScpO1xuXHRcdGZvciAoIHZhciBpID0gaGlnaGxpZ2h0LnN0YXJ0IC0gMTsgaSA8IGhpZ2hsaWdodC5lbmQ7IGkrKyApe1xuXHRcdFx0emluZGV4ID0galF1ZXJ5KHNlcVtpXSkuY3NzKFwiei1pbmRleFwiKTtcblx0XHRcdGlmICh6aW5kZXg9PVwiYXV0b1wiKXtcblx0XHRcdFx0IHogPSAxO1xuXHRcdFx0XHQgbyA9IDE7XG5cdFx0XHQgfVxuXHRcdFx0IGVsc2V7XG5cdFx0XHRcdCB6ID0gMDtcblx0XHRcdFx0IG8gPSAwLjU7XG5cdFx0XHQgfVxuXHRcdFx0alF1ZXJ5KHNlcVtpXSlcblx0XHRcdFx0LmNzcyh7IFxuXHRcdFx0XHRcdFwiY29sb3JcIjogaGlnaGxpZ2h0LmNvbG9yLFxuXHRcdFx0XHRcdFwiYmFja2dyb3VuZC1jb2xvclwiOiBoaWdobGlnaHQuYmFja2dyb3VuZCxcblx0XHRcdFx0XHRcInotaW5kZXhcIjogeixcblx0XHRcdFx0XHRcIm9wYWNpdHlcIjogb1xuXHRcdFx0XHRcdH0pXG5cdFx0XHRcdC5hZGRDbGFzcyhcImhpZ2hsaWdodGVkXCIpO1xuXHRcdH1cblx0fSxcblx0LyogXG4gICAgICogRnVuY3Rpb246IFNlcXVlbmNlLl9hcHBseUhpZ2hsaWdodHNcbiAgICAgKiBQdXJwb3NlOiAgQXBwbHkgdGhlIHNwZWNpZmllZCBoaWdobGlnaHRzLlxuICAgICAqIFJldHVybnM6ICAtXG4gICAgICogSW5wdXRzOiBoaWdobGlnaHRzIC0+IHtPYmplY3RbXX0gQW4gYXJyYXkgY29udGFpbmluZyB0aGUgaGlnaGxpZ2h0cyB0byBiZSBhcHBsaWVkLlxuICAgICAqL1xuXHRfYXBwbHlIaWdobGlnaHRzOiBmdW5jdGlvbiAoIGhpZ2hsaWdodHMgKSB7XG5cdFx0Zm9yICggdmFyIGkgaW4gaGlnaGxpZ2h0cyApIHtcblx0XHRcdHRoaXMuX2FwcGx5SGlnaGxpZ2h0KGhpZ2hsaWdodHNbaV0pO1xuXHRcdH1cblx0fSxcblx0LyogXG4gICAgICogRnVuY3Rpb246IFNlcXVlbmNlLl9yZXN0b3JlSGlnaGxpZ2h0c1xuICAgICAqIFB1cnBvc2U6ICBSZXBhaW50IHRoZSBoaWdobGlnaHRzIGluIHRoZSBzcGVjaWZpZWQgcmVnaW9uLlxuICAgICAqIFJldHVybnM6ICAtXG4gICAgICogSW5wdXRzOiBzdGFydCAtPiB7aW50fSBTdGFydCBvZiB0aGUgcmVnaW9uIHRvIGJlIHJlc3RvcmVkLlxuICAgICAqIFx0XHQgICBlbmQgLT4ge2ludH0gRW5kIG9mIHRoZSByZWdpb24gdG8gYmUgcmVzdG9yZWQuXG4gICAgICovXG5cdF9yZXN0b3JlSGlnaGxpZ2h0czogZnVuY3Rpb24gKCBzdGFydCwgZW5kICkge1xuXHRcdHZhciBoID0gdGhpcy5faGlnaGxpZ2h0cztcblx0XHQvLyBwYWludCB0aGUgcmVnaW9uIHVzaW5nIGRlZmF1bHQgYmxhbmsgc2V0dGluZ3Ncblx0XHR0aGlzLl9hcHBseUhpZ2hsaWdodCh7XG5cdFx0XHRcInN0YXJ0XCI6IHN0YXJ0LCBcblx0XHRcdFwiZW5kXCI6IGVuZCwgXG5cdFx0XHRcImNvbG9yXCI6IHRoaXMub3B0LmZvbnRDb2xvciwgXG5cdFx0XHRcImJhY2tncm91bmRcIjogdGhpcy5vcHQuYmFja2dyb3VuZENvbG9yIFxuXHRcdH0pO1xuXHRcdC8vIHJlc3RvcmUgaGlnaGxpZ2h0cyBpbiB0aGF0IHJlZ2lvblxuXHRcdGZvciAoIHZhciBpIGluIGggKSB7XG5cdFx0XHQvLyBpbnRlcnZhbCBpbnRlcnNlY3RzIHdpdGggaGlnaGxpZ2h0IGkgP1xuXHRcdFx0aWYgKCAhKCBoW2ldLnN0YXJ0ID4gZW5kIHx8IGhbaV0uZW5kIDwgc3RhcnQgKSApIHtcblx0XHRcdFx0YSA9ICggaFtpXS5zdGFydCA8IHN0YXJ0ICkgPyBzdGFydCA6IGhbaV0uc3RhcnQ7XG5cdFx0XHRcdGIgPSAoIGhbaV0uZW5kID4gZW5kICkgPyBlbmQgOiBoW2ldLmVuZDtcblx0XHRcdFx0dGhpcy5fYXBwbHlIaWdobGlnaHQoe1xuXHRcdFx0XHRcdFwic3RhcnRcIjogYSwgXG5cdFx0XHRcdFx0XCJlbmRcIjogYiwgXG5cdFx0XHRcdFx0XCJjb2xvclwiOiBoW2ldLmNvbG9yLCBcblx0XHRcdFx0XHRcImJhY2tncm91bmRcIjogaFtpXS5iYWNrZ3JvdW5kIFxuXHRcdFx0XHR9KTtcblx0XHRcdH1cblx0XHR9XG5cdH0sXG5cdC8qIFxuICAgICAqIEZ1bmN0aW9uOiBTZXF1ZW5jZS5fcmVzdG9yZVNlbGVjdGlvblxuICAgICAqIFB1cnBvc2U6ICBSZXBhaW50IHRoZSBjdXJyZW50IHNlbGVjdGlvbiBpbiB0aGUgc3BlY2lmaWVkIHJlZ2lvbi4gXG4gICAgICogXHRcdFx0IEl0IGlzIHVzZWQgaW4gdGhlIGNhc2Ugb2YgYW55IGhpZ2hsaWdodCBkbyBvdmVycmlkaW5nIG9mIHRoZSBjdXJyZW50IHNlbGVjdGlvbi4gXG4gICAgICogUmV0dXJuczogIC1cbiAgICAgKiBJbnB1dHM6IHN0YXJ0IC0+IHtpbnR9IFN0YXJ0IG9mIHRoZSByZWdpb24gdG8gYmUgcmVzdG9yZWQuXG4gICAgICogXHRcdCAgIGVuZCAtPiB7aW50fSBFbmQgb2YgdGhlIHJlZ2lvbiB0byBiZSByZXN0b3JlZC5cbiAgICAgKi9cblx0X3Jlc3RvcmVTZWxlY3Rpb246IGZ1bmN0aW9uICggc3RhcnQsIGVuZCApIHtcblx0XHR2YXIgc2VsID0gdGhpcy5vcHQuc2VsZWN0aW9uO1xuXHRcdC8vIGludGVydmFsIGludGVyc2VjdHMgd2l0aCBjdXJyZW50IHNlbGVjdGlvbiA/XG5cdFx0Ly8gcmVzdG9yZSBzZWxlY3Rpb25cblx0XHRpZiAoICEoIHN0YXJ0ID4gc2VsLmVuZCB8fCBlbmQgPCBzZWwuc3RhcnQgKSApIHtcblx0XHRcdGEgPSAoIHN0YXJ0IDwgc2VsLnN0YXJ0ICkgPyBzZWwuc3RhcnQgOiBzdGFydDtcblx0XHRcdGIgPSAoIGVuZCA+IHNlbC5lbmQgKSA/IHNlbC5lbmQgOiBlbmQ7XG5cdFx0XHRcblx0XHRcdHRoaXMuX2FwcGx5SGlnaGxpZ2h0KHtcblx0XHRcdFx0XCJzdGFydFwiOiBhLCBcblx0XHRcdFx0XCJlbmRcIjogYiwgXG5cdFx0XHRcdFwiY29sb3JcIjogdGhpcy5vcHQuc2VsZWN0aW9uRm9udENvbG9yLCBcblx0XHRcdFx0XCJiYWNrZ3JvdW5kXCI6IHRoaXMub3B0LnNlbGVjdGlvbkNvbG9yLFxuXHRcdFx0fSk7XG5cdFx0fVxuXHR9LFxuXHRcblx0LyoqXG4gICAgKiBDbGVhciBhIGhpZ2hsaWdodGVkIHJlZ2lvbiB1c2luZy5cbiAgICAqXG4gICAgKiBAZGVwcmVjYXRlZCB1c2UgcmVtb3ZlSGlnaGxpZ2h0IGluc3RlYWQuXG4gICAgKiBcbiAgICAqIEBwYXJhbSB7aW50fSBpZCBUaGUgaWQgb2YgdGhlIGhpZ2hsaWdodCBvbiB0aGUgaW50ZXJuYWwgYXJyYXkuIFRoaXMgdmFsdWUgaXMgcmV0dXJuZWQgYnkgbWV0aG9kIGhpZ2hsaWdodC5cbiAgICAqL1xuXHR1bkhpZ2hsaWdodCA6IGZ1bmN0aW9uIChpZCkge1x0XG5cdFx0dGhpcy5yZW1vdmVIaWdobGlnaHQoaWQpO1xuXHR9LFxuXHRcblx0LyoqXG4gICAgKiBSZW1vdmUgYSBoaWdobGlnaHQuXG4gICAgKlxuICAgICogQGV4YW1wbGVcbiAgICAqIC8vIENsZWFyIHRoZSBoaWdobGlnaHRlZCBjaGFyYWN0ZXJzIHdpdGhpbiB0aGUgcG9zaXRpb24gMTAwIHRvIDE1MCwgaW5jbHVkZWQuXG4gICAgKiBteVNlcXVlbmNlLnJlbW92ZUhpZ2hsaWdodChcInNwaW4xXCIpO1xuICAgICogXG4gICAgKiBAcGFyYW0ge3N0cmluZ30gaWQgVGhlIGlkIG9mIHRoZSBoaWdobGlnaHQgb24gdGhlIGludGVybmFsIGFycmF5LiBUaGlzIHZhbHVlIGlzIHJldHVybmVkIGJ5IG1ldGhvZCBoaWdobGlnaHQuXG4gICAgKi9cblx0cmVtb3ZlSGlnaGxpZ2h0IDogZnVuY3Rpb24gKGlkKSB7XHRcblx0XHR2YXIgaCA9IHRoaXMuX2hpZ2hsaWdodHM7XG5cdFx0Zm9yICggaSBpbiBoICkge1xuXHRcdFx0aWYgKCBoW2ldLmlkID09IGlkICkge1xuXHRcdFx0XHRzdGFydCA9IGhbaV0uc3RhcnQ7XG5cdFx0XHRcdGVuZCA9IGhbaV0uZW5kO1xuXHRcdFx0XHRoLnNwbGljZShpLDEpO1xuXHRcdFx0XHRcblx0XHRcdFx0dGhpcy5fcmVzdG9yZUhpZ2hsaWdodHMoc3RhcnQsZW5kKTtcblx0XHRcdFx0dGhpcy5fcmVzdG9yZVNlbGVjdGlvbihzdGFydCxlbmQpO1xuXHRcdFx0XHRcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHR9XG5cdFx0fVxuXHR9LFxuXHRcblx0LyoqXG4gICAgKiBDbGVhciB0aGUgaGlnaGxpZ2h0cyBvZiB3aG9sZSBzZXF1ZW5jZS5cbiAgICAqIEBkZXByZWNhdGVkIHVzZSByZW1vdmVBbGxIaWdobGlnaHRzIGluc3RlYWQuXG4gICAgKi9cblx0dW5IaWdobGlnaHRBbGwgOiBmdW5jdGlvbiAoKSB7XG5cdFx0dGhpcy5yZW1vdmVBbGxIaWdobGlnaHRzKCk7XG5cdH0sXG5cdFxuXHQvKipcbiAgICAqIFJlbW92ZSBhbGwgdGhlIGhpZ2hsaWdodHMgb2Ygd2hvbGUgc2VxdWVuY2UuXG4gICAgKlxuICAgICogQGV4YW1wbGVcbiAgICAqIG15U2VxdWVuY2UucmVtb3ZlQWxsSGlnaGxpZ2h0cygpO1xuICAgICovXG5cdHJlbW92ZUFsbEhpZ2hsaWdodHMgOiBmdW5jdGlvbiAoKSB7XG5cdFx0dGhpcy5faGlnaGxpZ2h0cyA9IFtdO1xuXHRcdHRoaXMuX3Jlc3RvcmVIaWdobGlnaHRzKDEsdGhpcy5vcHQuc2VxdWVuY2UubGVuZ3RoKTtcblx0XHR0aGlzLl9yZXN0b3JlU2VsZWN0aW9uKDEsdGhpcy5vcHQuc2VxdWVuY2UubGVuZ3RoKTtcblx0fSxcblx0XG5cdC8qKlxuICAgICogQ2hhbmdlcyB0aGUgY3VycmVudCBkaXNwbGF5aW5nIGZvcm1hdCBvZiB0aGUgc2VxdWVuY2UuXG4gICAgKlxuICAgICogQGV4YW1wbGVcbiAgICAqIC8vIFNldCBmb3JtYXQgdG8gJ0ZBU1RBJy5cbiAgICAqIG15U2VxdWVuY2Uuc2V0Rm9ybWF0KCdGQVNUQScpO1xuICAgICogXG4gICAgKiBAcGFyYW0ge3N0cmluZ30gZm9ybWF0IFRoZSBmb3JtYXQgZm9yIHRoZSBzZXF1ZW5jZSB0byBiZSBkaXNwbGF5ZWQuXG4gICAgKi9cblx0c2V0Rm9ybWF0IDogZnVuY3Rpb24oZm9ybWF0KSB7XG5cdFx0aWYgKCB0aGlzLm9wdC5mb3JtYXQgIT0gZm9ybWF0LnRvVXBwZXJDYXNlKCkgKSB7XG5cdFx0XHR0aGlzLm9wdC5mb3JtYXQgPSBmb3JtYXQudG9VcHBlckNhc2UoKTtcblx0XHRcdHRoaXMuX3JlZHJhdygpO1xuXHRcdH1cblxuXHRcdHZhciBzZWxmID0gdGhpcztcblx0XHQvLyBDaGFuZ2VzIHRoZSBvcHRpb24gaW4gdGhlIGNvbWJvIGJveFxuXHRcdHRoaXMuX2hlYWRlckRpdi5maW5kKCdvcHRpb24nKS5lYWNoKGZ1bmN0aW9uKCkge1xuXHRcdFx0aWYoalF1ZXJ5KHRoaXMpLnZhbCgpID09IHNlbGYub3B0LmZvcm1hdC50b1VwcGVyQ2FzZSgpKSB7XG5cdFx0XHRcdGpRdWVyeSh0aGlzKS5hdHRyKCdzZWxlY3RlZCcsICdzZWxlY3RlZCcpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9LFxuXHRcblx0LyoqXG4gICAgKiBDaGFuZ2VzIHRoZSBjdXJyZW50IG51bWJlciBvZiBjb2x1bW5zIGluIHRoZSBkaXNwbGF5ZWQgc2VxdWVuY2UuXG4gICAgKlxuICAgICogQGV4YW1wbGVcbiAgICAqIC8vIFNldCB0aGUgbnVtYmVyIG9mIGNvbHVtbnMgdG8gNzAuXG4gICAgKiBteVNlcXVlbmNlLnNldE51bUNvbHMoNzApO1xuICAgICogXG4gICAgKiBAcGFyYW0ge2ludH0gbnVtQ29scyBUaGUgbnVtYmVyIG9mIGNvbHVtbnMuXG4gICAgKi9cblx0c2V0TnVtQ29scyA6IGZ1bmN0aW9uKG51bUNvbHMpIHtcblx0XHR0aGlzLm9wdC5jb2x1bW5zLnNpemUgPSBudW1Db2xzO1xuXHRcdHRoaXMuX3JlZHJhdygpO1xuXHR9LFxuXHRcblx0LyoqXG4gICAgKiBTZXQgdGhlIHZpc2liaWxpdHkgb2YgdGhlIGRyb3AtZG93biBsaXN0IG9mIGZvcm1hdHMuXG4gICAgKiBcbiAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gdmlzaWJsZSB0cnVlOiBzaG93OyBmYWxzZTogaGlkZS5cbiAgICAqL1xuXHRmb3JtYXRTZWxlY3RvclZpc2libGUgOiBmdW5jdGlvbiAodmlzaWJsZSl7XG5cdFx0aWYgKHZpc2libGUpIHtcblx0XHRcdHRoaXMuX2hlYWRlckRpdi5zaG93KCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMuX2hlYWRlckRpdi5oaWRlKCk7XG5cdFx0fVxuXHR9LFxuXHRcblx0LyoqXG4gICAgKiBUaGlzIGlzIHNpbWlsYXIgdG8gYSB7QmlvanMuUHJvdGVpbjNEI2Zvcm1hdFNlbGVjdG9yVmlzaWJsZX0gd2l0aCB0aGUgJ3RydWUnIGFyZ3VtZW50LlxuICAgICpcbiAgICAqIEBleGFtcGxlXG4gICAgKiAvLyBTaG93cyB0aGUgZm9ybWF0IHNlbGVjdG9yLlxuICAgICogbXlTZXF1ZW5jZS5zaG93Rm9ybWF0U2VsZWN0b3IoKTtcbiAgICAqIFxuICAgICovXG5cdHNob3dGb3JtYXRTZWxlY3RvciA6IGZ1bmN0aW9uKCkge1xuXHRcdHRoaXMuX2hlYWRlckRpdi5zaG93KCk7XG5cdH0sXG5cdFxuXHQvKipcbiAgICAqIFRoaXMgaXMgc2ltaWxhciB0byBhIHtCaW9qcy5Qcm90ZWluM0QjZm9ybWF0U2VsZWN0b3JWaXNpYmxlfSB3aXRoIHRoZSAnZmFsc2UnIGFyZ3VtZW50LlxuICAgICogXG4gICAgKiBAZXhhbXBsZVxuICAgICogLy8gSGlkZXMgdGhlIGZvcm1hdCBzZWxlY3Rvci5cbiAgICAqIG15U2VxdWVuY2UuaGlkZUZvcm1hdFNlbGVjdG9yKCk7XG4gICAgKiBcbiAgICAqL1xuXHRoaWRlRm9ybWF0U2VsZWN0b3IgOiBmdW5jdGlvbigpIHtcblx0XHR0aGlzLl9oZWFkZXJEaXYuaGlkZSgpO1xuXHR9LFxuXHRcblx0LyoqXG4gICAgKiBIaWRlcyB0aGUgd2hvbGUgY29tcG9uZW50LlxuICAgICogXG4gICAgKi9cblx0aGlkZSA6IGZ1bmN0aW9uICgpIHtcblx0XHR0aGlzLl9oZWFkZXJEaXYuaGlkZSgpO1xuXHRcdHRoaXMuX2NvbnRlbnREaXYuaGlkZSgpO1xuXHR9LFxuXG5cdC8qKlxuICAgICogU2hvd3MgdGhlIHdob2xlIGNvbXBvbmVudC5cbiAgICAqIFxuICAgICovXG5cdHNob3cgOiBmdW5jdGlvbiAoKSB7XG5cdFx0dGhpcy5faGVhZGVyRGl2LnNob3coKTtcblx0XHR0aGlzLl9jb250ZW50RGl2LnNob3coKTtcblx0fSxcblx0LyogXG4gICAgICogRnVuY3Rpb246IFNlcXVlbmNlLl9zZXRTZWxlY3Rpb25cbiAgICAgKiBQdXJwb3NlOiAgVXBkYXRlIHRoZSBjdXJyZW50IHNlbGVjdGlvbi4gXG4gICAgICogUmV0dXJuczogIC1cbiAgICAgKiBJbnB1dHM6IHN0YXJ0IC0+IHtpbnR9IFN0YXJ0IG9mIHRoZSByZWdpb24gdG8gYmUgc2VsZWN0ZWQuXG4gICAgICogXHRcdCAgIGVuZCAtPiB7aW50fSBFbmQgb2YgdGhlIHJlZ2lvbiB0byBiZSBzZWxlY3RlZC5cbiAgICAgKi9cblx0X3NldFNlbGVjdGlvbiA6IGZ1bmN0aW9uKHN0YXJ0LCBlbmQpIHtcblx0XHQvL2FsZXJ0KFwiYWRzYXNcIik7XG5cdFx0XG5cdFx0dmFyIGN1cnJlbnQgPSB0aGlzLm9wdC5zZWxlY3Rpb247XG5cdFx0dmFyIGNoYW5nZSA9IHt9O1xuXHRcdFxuXHRcdC8vIFdoaWNoIGlzIHRoZSBjaGFuZ2Ugb24gc2VsZWN0aW9uP1xuXHRcdGlmICggY3VycmVudC5zdGFydCA9PSBzdGFydCApIHtcblx0XHRcdC8vIGZvcndhcmQ/XG5cdFx0XHRpZiAoIGN1cnJlbnQuZW5kIDwgZW5kICkge1xuXHRcdFx0XHRjaGFuZ2Uuc3RhcnQgPSBjdXJyZW50LmVuZDtcblx0XHRcdFx0Y2hhbmdlLmVuZCA9IGVuZDtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHRoaXMuX3Jlc3RvcmVIaWdobGlnaHRzKGVuZCsxLCBjdXJyZW50LmVuZCk7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIGlmICggY3VycmVudC5lbmQgPT0gZW5kICkge1xuXHRcdFx0Ly8gZm9yd2FyZD9cblx0XHRcdGlmICggY3VycmVudC5zdGFydCA+IHN0YXJ0ICkge1xuXHRcdFx0XHRjaGFuZ2Uuc3RhcnQgPSBzdGFydDtcblx0XHRcdFx0Y2hhbmdlLmVuZCA9IGN1cnJlbnQuc3RhcnQ7XHRcdFx0XHRcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHRoaXMuX3Jlc3RvcmVIaWdobGlnaHRzKGN1cnJlbnQuc3RhcnQsIHN0YXJ0LTEpO1xuXHRcdFx0fVxuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLl9yZXN0b3JlSGlnaGxpZ2h0cyhjdXJyZW50LnN0YXJ0LCBjdXJyZW50LmVuZCk7XG5cdFx0XHRjaGFuZ2Uuc3RhcnQgPSBzdGFydDtcblx0XHRcdGNoYW5nZS5lbmQgPSBlbmQ7XG5cdFx0fVxuXG5cdFx0Y3VycmVudC5zdGFydCA9IHN0YXJ0O1xuXHRcdGN1cnJlbnQuZW5kID0gZW5kO1xuXG5cdFx0aWYgKCBjaGFuZ2Uuc3RhcnQgIT0gdW5kZWZpbmVkICkge1xuXHRcdFx0dGhpcy5fYXBwbHlIaWdobGlnaHQoe1xuXHRcdFx0XHRcInN0YXJ0XCI6IGNoYW5nZS5zdGFydCwgXG5cdFx0XHRcdFwiZW5kXCI6IGNoYW5nZS5lbmQsIFxuXHRcdFx0XHRcImNvbG9yXCI6IHRoaXMub3B0LnNlbGVjdGlvbkZvbnRDb2xvciwgXG5cdFx0XHRcdFwiYmFja2dyb3VuZFwiOiB0aGlzLm9wdC5zZWxlY3Rpb25Db2xvciBcblx0XHRcdH0pO1xuXHRcdH1cblx0XHRcblx0fSxcblx0XG5cdC8qIFxuICAgICAqIEZ1bmN0aW9uOiBTZXF1ZW5jZS5fcmVwYWludFNlbGVjdGlvblxuICAgICAqIFB1cnBvc2U6ICBSZXBhaW50IHRoZSB3aG9sZSBjdXJyZW50IHNlbGVjdGlvbi4gXG4gICAgICogUmV0dXJuczogIC1cbiAgICAgKiBJbnB1dHM6IC1cbiAgICAgKi9cblx0X3JlcGFpbnRTZWxlY3Rpb246IGZ1bmN0aW9uKCl7XG5cdFx0dmFyIHMgPSB0aGlzLm9wdC5zZWxlY3Rpb247XG5cdFx0dGhpcy5fc2V0U2VsZWN0aW9uKDAsMCk7XG5cdFx0dGhpcy5fc2V0U2VsZWN0aW9uKHMuc3RhcnQscy5lbmQpO1xuXHR9LFxuXHRcblx0LyogXG4gICAgICogRnVuY3Rpb246IFNlcXVlbmNlLl9yZWRyYXdcbiAgICAgKiBQdXJwb3NlOiAgUmVwYWludCB0aGUgY3VycmVudCBzZXF1ZW5jZS4gXG4gICAgICogUmV0dXJuczogIC1cbiAgICAgKiBJbnB1dHM6IC1cbiAgICAgKi9cblx0X3JlZHJhdyA6IGZ1bmN0aW9uKCkge1xuXHRcdHZhciBpID0gMDtcdFxuXHRcdHZhciBzZWxmID0gdGhpcztcblx0XHRcblx0XHQvLyBSZXNldCB0aGUgY29udGVudFxuXHRcdC8vdGhpcy5fY29udGVudERpdi50ZXh0KCcnKTtcblx0XHR0aGlzLl9jb250ZW50RGl2LmNoaWxkcmVuKCkucmVtb3ZlKCk7XG5cdFx0XG5cdFx0Ly8gUmVidWlsZCB0aGUgc3BhbnMgb2YgdGhlIHNlcXVlbmNlIFxuXHRcdC8vIGFjY29yZGluZyB0byBmb3JtYXRcblx0XHRpZih0aGlzLm9wdC5mb3JtYXQgPT0gJ1JBVycpIHtcblx0XHRcdHRoaXMuX2RyYXdSYXcoKTtcblx0XHR9IGVsc2UgaWYodGhpcy5vcHQuZm9ybWF0ID09ICdDT0RBVEEnKSB7XG5cdFx0XHR0aGlzLl9kcmF3Q29kYXRhKCk7XG5cdFx0fSBlbHNlIGlmICh0aGlzLm9wdC5mb3JtYXQgPT0gJ0ZBU1RBJyl7XG5cdFx0XHR0aGlzLl9kcmF3RmFzdGEoKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhpcy5vcHQuZm9ybWF0ID0gJ1BSSURFJztcblx0XHRcdHRoaXMuX2RyYXdQcmlkZSgpO1xuXHRcdH1cblx0XHRcblx0XHQvLyBSZXN0b3JlIHRoZSBoaWdobGlnaHRlZCByZWdpb25zXG5cdFx0dGhpcy5fYXBwbHlIaWdobGlnaHRzKHRoaXMuX2hpZ2hsaWdodHMpO1xuXHRcdHRoaXMuX3JlcGFpbnRTZWxlY3Rpb24oKTtcblx0XHR0aGlzLl9hZGRTcGFuRXZlbnRzKCk7XG5cdH0sXG5cdC8qIFxuICAgICAqIEZ1bmN0aW9uOiBTZXF1ZW5jZS5fZHJhd0Zhc3RhXG4gICAgICogUHVycG9zZTogIFJlcGFpbnQgdGhlIGN1cnJlbnQgc2VxdWVuY2UgdXNpbmcgRkFTVEEgZm9ybWF0LiAgXG4gICAgICogUmV0dXJuczogIC1cbiAgICAgKiBJbnB1dHM6IC1cbiAgICAgKi9cblx0X2RyYXdGYXN0YSA6IGZ1bmN0aW9uKCkge1xuXHRcdHZhciBzZWxmID0gdGhpcztcblx0XHR2YXIgYSA9IHRoaXMub3B0LnNlcXVlbmNlLnRvVXBwZXJDYXNlKCkuc3BsaXQoJycpO1xuXHRcdHZhciBwcmUgPSBqUXVlcnkoJzxwcmU+PC9wcmU+JykuYXBwZW5kVG8odGhpcy5fY29udGVudERpdik7XG5cblx0XHR2YXIgaSA9IDE7XG5cdFx0dmFyIGFyciA9IFtdO1xuXHQgICAgdmFyIHN0ciA9ICc+JyArIHRoaXMub3B0LmlkICsgJyAnICsgYS5sZW5ndGggKyAnIGJwPGJyLz4nO1xuXHRcdFxuXHRcdC8qIENvcnJlY3QgY29sdW1uIHNpemUgaW4gY2FzZSB0aGUgc2VxdWVuY2UgaXMgYXMgc21hbGwgcGVwdGlkZSAqL1xuXHRcdHZhciBudW1Db2xzID0gdGhpcy5vcHQuY29sdW1ucy5zaXplO1xuXHRcdGlmICggdGhpcy5vcHQuc2VxdWVuY2UubGVuZ3RoIDwgdGhpcy5vcHQuY29sdW1ucy5zaXplICkge1xuXHRcdFx0bnVtQ29scyA9IHRoaXMub3B0LnNlcXVlbmNlLmxlbmd0aDtcdFxuXHRcdH1cblx0XHRcblx0ICAgIHZhciBvcHQgPSB7XG5cdFx0XHRudW1Db2xzOiBudW1Db2xzLFxuXHRcdCAgICBudW1Db2xzRm9yU3BhY2U6IDBcblx0XHR9O1xuXG5cdFx0c3RyICs9IHRoaXMuX2RyYXdTZXF1ZW5jZShhLCBvcHQpO1xuXHRcdHByZS5odG1sKHN0cik7XG5cdFx0XG5cdFx0dGhpcy5fZHJhd0Fubm90YXRpb25zKG9wdCk7XG5cdH0sXG5cdC8qIFxuICAgICAqIEZ1bmN0aW9uOiBTZXF1ZW5jZS5fZHJhd0NvZGF0YVxuICAgICAqIFB1cnBvc2U6ICBSZXBhaW50IHRoZSBjdXJyZW50IHNlcXVlbmNlIHVzaW5nIENPREFUQSBmb3JtYXQuICBcbiAgICAgKiBSZXR1cm5zOiAgLVxuICAgICAqIElucHV0czogLVxuICAgICAqL1xuXHRfZHJhd0NvZGF0YSA6IGZ1bmN0aW9uKCkge1xuXHRcdFxuXHRcdHZhciBzZWxmID0gdGhpcztcblx0XHR2YXIgYSA9IHRoaXMub3B0LnNlcXVlbmNlLnRvVXBwZXJDYXNlKCkuc3BsaXQoJycpO1xuXHRcdHZhciBwcmUgPSBqUXVlcnkoJzxwcmUgc3R5bGU9XCJ3aGl0ZS1zcGFjZTpwcmVcIj48L3ByZT4nKS5hcHBlbmRUbyh0aGlzLl9jb250ZW50RGl2KTtcblxuXHRcdHZhciBpID0gMDtcblx0XHR2YXIgc3RyID0gJ0VOVFJZICAgICAgICAgICAnICsgdGhpcy5vcHQuaWQgKyAnPGJyLz4nO1xuXHRcdHN0ciArPSAnU0VRVUVOQ0U8YnIvPic7XG5cdFx0aWYgKCB0aGlzLm9wdC5mb3JtYXRPcHRpb25zICE9PSB1bmRlZmluZWQgKXtcblx0XHRcdGlmKHRoaXMub3B0LmZvcm1hdE9wdGlvbnMudGl0bGUgIT09IHVuZGVmaW5lZCApe1xuXHRcdFx0XHRpZiAodGhpcy5vcHQuZm9ybWF0T3B0aW9ucy50aXRsZSA9PSBmYWxzZSkge1xuXHRcdFx0XHRcdHN0ciA9ICcnO1xuXHRcdFx0XHR9XHRcdFx0XG5cdFx0XHR9XG5cdFx0fSBcblx0XHRcblx0XHQvKiBDb3JyZWN0IGNvbHVtbiBzaXplIGluIGNhc2UgdGhlIHNlcXVlbmNlIGlzIGFzIHNtYWxsIHBlcHRpZGUgKi9cblx0XHR2YXIgbnVtQ29scyA9IHRoaXMub3B0LmNvbHVtbnMuc2l6ZTtcblx0XHRpZiAoIHRoaXMub3B0LnNlcXVlbmNlLmxlbmd0aCA8IHRoaXMub3B0LmNvbHVtbnMuc2l6ZSApIHtcblx0XHRcdG51bUNvbHMgPSB0aGlzLm9wdC5zZXF1ZW5jZS5sZW5ndGg7XHRcblx0XHR9XG5cdFx0XG5cdFx0dmFyIG9wdCA9IHtcblx0XHRcdFx0bnVtTGVmdDogdHJ1ZSxcblx0XHRcdFx0bnVtTGVmdFNpemU6IDcsXG5cdFx0XHRcdG51bUxlZnRQYWQ6JyAnLFxuXHRcdFx0XHRudW1Ub3A6IHRydWUsXG5cdFx0XHRcdG51bVRvcEVhY2g6IDUsXG5cdFx0XHRcdG51bUNvbHM6IG51bUNvbHMsXG5cdFx0XHQgICAgbnVtQ29sc0ZvclNwYWNlOiAwLFxuXHRcdFx0ICAgIHNwYWNlQmV0d2VlbkNoYXJzOiB0cnVlXG5cdFx0fTtcblx0XHRcblx0XHRzdHIgKz0gdGhpcy5fZHJhd1NlcXVlbmNlKGEsIG9wdCk7XG5cdFx0XG5cdFx0dmFyIGZvb3RlciA9ICc8YnIvPi8vLyc7XG5cdFx0aWYgKHRoaXMub3B0LmZvcm1hdE9wdGlvbnMgIT09IHVuZGVmaW5lZCkge1xuXHRcdFx0aWYgKHRoaXMub3B0LmZvcm1hdE9wdGlvbnMuZm9vdGVyICE9PSB1bmRlZmluZWQpIHtcblx0XHRcdFx0aWYgKHRoaXMub3B0LmZvcm1hdE9wdGlvbnMuZm9vdGVyID09IGZhbHNlKSB7XG5cdFx0XHRcdFx0Zm9vdGVyID0gJyc7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdFx0c3RyICs9IGZvb3Rlcjtcblx0XHRwcmUuaHRtbChzdHIpO1xuXHRcdFxuXHRcdHRoaXMuX2RyYXdBbm5vdGF0aW9ucyhvcHQpO1xuXHR9LFxuXHQvKiBcbiAgICAgKiBGdW5jdGlvbjogU2VxdWVuY2UuX2RyYXdBbm5vdGF0aW9uc1xuICAgICAqIFB1cnBvc2U6ICBQYWludCB0aGUgYW5ub3RhdGlvbnMgb24gdGhlIHNlcXVlbmNlLiAgXG4gICAgICogUmV0dXJuczogIC1cbiAgICAgKiBJbnB1dHM6IHNldHRpbmdzIC0+IHtvYmplY3R9IFxuICAgICAqL1xuICAgIF9kcmF3QW5ub3RhdGlvbnM6IGZ1bmN0aW9uICggc2V0dGluZ3MgKXsgXG4gICAgXHRcbiAgICBcdHZhciBzZWxmID0gdGhpcztcbiAgICBcdHZhciBhID0gdGhpcy5vcHQuc2VxdWVuY2UudG9Mb3dlckNhc2UoKS5zcGxpdCgnJyk7ICAgIFx0XG4gICAgXHR2YXIgYW5ub3RhdGlvbnMgPSB0aGlzLl9hbm5vdGF0aW9ucztcbiAgICBcdHZhciBsZWZ0U3BhY2VzID0gJyc7XG4gICAgXHR2YXIgcm93ID0gJyc7XG4gICAgXHR2YXIgYW5ub3QgPSAnJztcbiAgICBcdFxuICAgIFx0Ly8gSW5kZXggYXQgdGhlIGxlZnQ/XG5cdFx0aWYgKCBzZXR0aW5ncy5udW1MZWZ0ICkge1xuXHRcdFx0bGVmdFNwYWNlcyArPSB0aGlzLl9mb3JtYXRJbmRleCgnICcsIHNldHRpbmdzLm51bUxlZnRTaXplKzIsICcgJyk7XG5cdFx0fVxuXG5cdFx0Zm9yICggdmFyIGkgPSAwOyBpIDwgYS5sZW5ndGg7IGkgKz0gc2V0dGluZ3MubnVtQ29scyApe1xuXHRcdFx0cm93ID0gJyc7XG5cdFx0XHRmb3IgKCB2YXIga2V5IGluIGFubm90YXRpb25zICl7XG5cdFx0XHRcdGFubm90YXRpb25zW2tleV0uaWQgPSB0aGlzLmdldElkKCkgKyBcIl9cIiArIGtleTtcblx0XHRcdFx0YW5ub3QgPSB0aGlzLl9nZXRIVE1MUm93QW5ub3QoaSsxLCBhbm5vdGF0aW9uc1trZXldLCBzZXR0aW5ncyk7XHRcdFx0XHRcblx0XHRcdFx0aWYgKGFubm90Lmxlbmd0aCA+IDApIHtcblx0XHRcdFx0XHRyb3cgKz0gJzxici8+Jztcblx0XHRcdFx0XHRyb3cgKz0gbGVmdFNwYWNlcztcblx0XHRcdFx0XHRyb3cgKz0gYW5ub3Q7XG5cdFx0XHRcdFx0cm93ICs9ICc8YnIvPic7XG5cdFx0XHRcdH0gXG5cdFx0XHR9XG5cdFx0XHRcblx0XHRcdHZhciBudW1Db2xzID0gc2V0dGluZ3MubnVtQ29scztcblx0XHRcdHZhciBjaGFyUmVtYWluaW5nID0gYS5sZW5ndGgtaTtcblx0XHRcdGlmKGNoYXJSZW1haW5pbmcgPCBudW1Db2xzKXtcblx0XHRcdFx0bnVtQ29sc1x0PSBjaGFyUmVtYWluaW5nO1xuXHRcdFx0fVxuXHRcdFx0XG5cdFx0XHRpZiAoIHNldHRpbmdzLm51bVJpZ2h0ICkge1xuXHRcdFx0XHRqUXVlcnkocm93KS5pbnNlcnRBZnRlcignZGl2Iycrc2VsZi5vcHQudGFyZ2V0KycgZGl2IHByZSBzcGFuI251bVJpZ2h0XycgKyB0aGlzLmdldElkKCkgKyAnXycgKyAoaSArIG51bUNvbHMpICk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRqUXVlcnkocm93KS5pbnNlcnRBZnRlcignZGl2Iycrc2VsZi5vcHQudGFyZ2V0KycgZGl2IHByZSBzcGFuIycrIHRoaXMuZ2V0SWQoKSArICdfJyArIChpICsgbnVtQ29scykgKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0XG5cdFx0Ly8gYWRkIHRvb2wgdGlwcyBhbmQgYmFja2dyb3VuZCcgY29sb3JpbmcgZWZmZWN0XG5cdFx0alF1ZXJ5KHRoaXMuX2NvbnRlbnREaXYpLmZpbmQoJy5hbm5vdGF0aW9uJykuZWFjaCggZnVuY3Rpb24oKXtcblx0XHRcdHNlbGYuX2FkZFRvb2xUaXAoIHRoaXMsIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRyZXR1cm4gc2VsZi5fZ2V0QW5ub3RhdGlvblN0cmluZyggalF1ZXJ5KHRoaXMpLmF0dHIoXCJpZFwiKSApO1xuXHRcdFx0fSk7XG5cdFx0XHRcblx0XHRcdGpRdWVyeSh0aGlzKS5tb3VzZW92ZXIoZnVuY3Rpb24oZSkge1xuXHRcdFx0XHRqUXVlcnkoJy5hbm5vdGF0aW9uLicralF1ZXJ5KGUudGFyZ2V0KS5hdHRyKFwiaWRcIikpLmVhY2goZnVuY3Rpb24oKXtcblx0XHRcdFx0XHRqUXVlcnkodGhpcykuY3NzKFwiYmFja2dyb3VuZC1jb2xvclwiLCBqUXVlcnkodGhpcykuYXR0cihcImNvbG9yXCIpICk7XG5cdFx0XHRcdH0pO1xuXHRcdCAgICB9KS5tb3VzZW91dChmdW5jdGlvbigpIHtcblx0XHQgICAgXHRqUXVlcnkoJy5hbm5vdGF0aW9uJykuY3NzKFwiYmFja2dyb3VuZC1jb2xvclwiLCBcInRyYW5zcGFyZW50XCIpOyBcblx0XHQgICAgXHRcblx0XHQgICAgfSkuY2xpY2soZnVuY3Rpb24oZSkge1xuXHRcdCAgICBcdFx0dmFyIG5hbWUgPSB1bmRlZmluZWQ7XG5cdFx0ICAgIFx0XHR2YXIgaWQgPSBqUXVlcnkoZS50YXJnZXQpLmF0dHIoXCJpZFwiKTtcblx0XHQgICAgXHRcdGZvcih2YXIgaSA9MDsgaSA8IHNlbGYuX2Fubm90YXRpb25zLmxlbmd0aDtpKyspe1xuICAgICAgICAgICAgICBpZihzZWxmLl9hbm5vdGF0aW9uc1tpXS5pZCA9PSBpZCl7XG4gICAgICAgICAgICAgICAgbmFtZSA9IHNlbGYuX2Fubm90YXRpb25zW2ldLm5hbWU7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblx0XHQgICAgXHRzZWxmLnRyaWdnZXIoIEVWVF9PTl9BTk5PVEFUSU9OX0NMSUNLRUQsIHtcblx0ICAgIFx0XHRcIm5hbWVcIjogbmFtZSxcblx0XHQgICAgXHRcdC8vXCJwb3NcIjogcGFyc2VJbnQoIGpRdWVyeShlLnRhcmdldCkuYXR0cihcInBvc1wiKSApXG5cdFx0ICAgIFx0fSk7XG5cdFx0ICAgIH0pO1xuXHRcdFx0XG5cdFx0fSk7XG5cbiAgICB9LFxuICAgIC8qIFxuICAgICAqIEZ1bmN0aW9uOiBTZXF1ZW5jZS5fZ2V0QW5ub3RhdGlvblN0cmluZ1xuICAgICAqIFB1cnBvc2U6ICBHZXQgdGhlIGFubm90YXRpb24gdGV4dCBtZXNzYWdlIGZvciB0aGUgdG9vbHRpcCBcbiAgICAgKiBSZXR1cm5zOiAge3N0cmluZ30gQW5ub3RhdGlvbiB0ZXh0IGZvciB0aGUgYW5ub3RhdGlvblxuICAgICAqIElucHV0czogICBpZCAtPiB7aW50fSBpbmRleCBvZiB0aGUgaW50ZXJuYWwgYW5ub3RhdGlvbiBhcnJheVxuICAgICAqL1xuICAgIF9nZXRBbm5vdGF0aW9uU3RyaW5nOiBmdW5jdGlvbiAoIGlkICkge1xuXHRcdHZhciBhbm5vdGF0aW9uID0gdGhpcy5fYW5ub3RhdGlvbnNbaWQuc3Vic3RyKGlkLmluZGV4T2YoXCJfXCIpICsgMSldO1xuXHRcdHJldHVybiBhbm5vdGF0aW9uLm5hbWUgKyBcIjxici8+XCIgKyAoKGFubm90YXRpb24uaHRtbCk/IGFubm90YXRpb24uaHRtbCA6ICcnKTtcbiAgICB9LFxuICAgIFxuICAgIC8qIFxuICAgICAqIEZ1bmN0aW9uOiBTZXF1ZW5jZS5fZ2V0SFRNTFJvd0Fubm90XG4gICAgICogUHVycG9zZTogIEJ1aWxkIGFuIGFubm90YXRpb25cbiAgICAgKiBSZXR1cm5zOiAgSFRNTCBvZiB0aGUgYW5ub3RhdGlvblxuICAgICAqIElucHV0czogICBjdXJyZW50UG9zIC0+IHtpbnR9XG4gICAgICogXHRcdFx0IGFubm90YXRpb24gLT4ge09iamVjdH0gXG4gICAgICogIFx0XHQgc2V0dGluZ3MgLT4ge09iamVjdH1cbiAgICAgKi9cbiAgICBfZ2V0SFRNTFJvd0Fubm90IDogZnVuY3Rpb24gKGN1cnJlbnRQb3MsIGFubm90YXRpb24sIHNldHRpbmdzKSB7XG4gICAgXHR2YXIgc3R5bGVCZWdpbiA9ICdib3JkZXItbGVmdDoxcHggc29saWQ7IGJvcmRlci1ib3R0b206MXB4IHNvbGlkOyBib3JkZXItY29sb3I6JztcbiAgICBcdHZhciBzdHlsZU9uID0gJ2JvcmRlci1ib3R0b206MXB4IHNvbGlkOyBib3JkZXItY29sb3I6JztcbiAgICBcdHZhciBzdHlsZUVuZCA9ICdib3JkZXItYm90dG9tOjFweCBzb2xpZDsgYm9yZGVyLXJpZ2h0OjFweCBzb2xpZDsgYm9yZGVyLWNvbG9yOic7XG5cdFx0dmFyIHN0eWxlQmVnaW5BbmRFbmQgPSAnYm9yZGVyLWxlZnQ6MXB4IHNvbGlkOyBib3JkZXItcmlnaHQ6MXB4IHNvbGlkOyBib3JkZXItYm90dG9tOjFweCBzb2xpZDsgYm9yZGVyLWNvbG9yOic7XG4gICAgXHRcbiAgICBcdHZhciByb3cgPSBbXTtcbiAgICBcdHZhciBlbmQgPSAoY3VycmVudFBvcyArIHNldHRpbmdzLm51bUNvbHMpO1xuICAgIFx0dmFyIHNwYWNlQmV0d2VlbkNoYXJzID0gKHNldHRpbmdzLnNwYWNlQmV0d2VlbkNoYXJzKT8gJyAnIDogJyc7ICAgIFx0XG4gICAgXHR2YXIgZGVmYXVsdENvbG9yID0gYW5ub3RhdGlvbi5jb2xvcjtcbiAgICBcdHZhciBpZCA9IGFubm90YXRpb24uaWQ7XG4gICAgXHRmb3IgKCB2YXIgcG9zPWN1cnJlbnRQb3M7IHBvcyA8IGVuZCA7IHBvcysrICkge1xuXHRcdFx0Ly8gcmVnaW9uc1xuXHRcdFx0Zm9yICggdmFyIHIgaW4gYW5ub3RhdGlvbi5yZWdpb25zICkge1xuXHRcdFx0XHRyZWdpb24gPSBhbm5vdGF0aW9uLnJlZ2lvbnNbcl07XG5cdFx0XHRcdFxuXHRcdFx0XHRzcGFjZUFmdGVyID0gJyc7XG5cdFx0XHRcdHNwYWNlQWZ0ZXIgKz0gKHBvcyAlIHNldHRpbmdzLm51bUNvbHNGb3JTcGFjZSA9PSAwICk/ICcgJyA6ICcnO1xuXHRcdFx0XHRzcGFjZUFmdGVyICs9IHNwYWNlQmV0d2VlbkNoYXJzO1xuXHRcdFx0XHRcblx0XHRcdFx0Y29sb3IgPSAoKHJlZ2lvbi5jb2xvcik/IHJlZ2lvbi5jb2xvciA6IGRlZmF1bHRDb2xvcik7XG5cdFx0XHRcdGRhdGEgPSAnY2xhc3M9XCJhbm5vdGF0aW9uICcraWQrJ1wiIGlkPVwiJytpZCsnXCIgY29sb3I9XCInK2NvbG9yKydcIiBwb3M9XCInK3BvcysnXCInO1xuXHRcdFx0XHRcblx0XHRcdFx0aWYgKCBwb3MgPT0gcmVnaW9uLnN0YXJ0ICYmIHBvcyA9PSByZWdpb24uZW5kKSB7XG5cdFx0XHRcdFx0cm93W3Bvc10gPSAnPHNwYW4gc3R5bGU9XCInK3N0eWxlQmVnaW5BbmRFbmQrY29sb3IrJ1wiICcrZGF0YSsnPiAnO1xuXHRcdFx0XHRcdHJvd1twb3NdICs9IHNwYWNlQWZ0ZXI7XG5cdFx0XHRcdFx0cm93W3Bvc10gKz0gJzwvc3Bhbj4nO1xuXHRcdFx0XHR9IGVsc2UgaWYgKCBwb3MgPT0gcmVnaW9uLnN0YXJ0ICkge1xuXHRcdFx0XHRcdHJvd1twb3NdID0gJzxzcGFuIHN0eWxlPVwiJytzdHlsZUJlZ2luK2NvbG9yKydcIiAnK2RhdGErJz4gJztcblx0XHRcdFx0XHRyb3dbcG9zXSArPSBzcGFjZUFmdGVyO1xuXHRcdFx0XHRcdHJvd1twb3NdICs9ICc8L3NwYW4+Jztcblx0XHRcdFx0fSBlbHNlIGlmICggcG9zID09IHJlZ2lvbi5lbmQgKSB7XG5cdFx0XHRcdFx0cm93W3Bvc10gPSAnPHNwYW4gc3R5bGU9XCInK3N0eWxlRW5kK2NvbG9yKycgXCIgJytkYXRhKyc+ICc7XG5cdFx0XHRcdFx0Ly9yb3dbcG9zXSArPSBzcGFjZUFmdGVyO1xuXHRcdFx0XHRcdHJvd1twb3NdICs9ICc8L3NwYW4+Jztcblx0XHRcdFx0fSBlbHNlIGlmICggcG9zID4gcmVnaW9uLnN0YXJ0ICYmIHBvcyA8IHJlZ2lvbi5lbmQgKSB7XG5cdFx0XHRcdFx0cm93W3Bvc10gPSAnPHNwYW4gc3R5bGU9XCInK3N0eWxlT24rY29sb3IrJ1wiICcrZGF0YSsnPiAnO1xuXHRcdFx0XHRcdHJvd1twb3NdICs9IHNwYWNlQWZ0ZXI7XG5cdFx0XHRcdFx0cm93W3Bvc10gKz0gJzwvc3Bhbj4nO1xuXHRcdFx0XHR9IGVsc2UgaWYgKCFyb3dbcG9zXSkge1xuXHRcdFx0XHRcdHJvd1twb3NdID0gJyAnO1xuXHRcdFx0XHRcdHJvd1twb3NdICs9IHNwYWNlQWZ0ZXI7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cbiAgICAgICBcdHZhciBzdHIgPSByb3cuam9pbihcIlwiKTtcbiAgICBcdFxuICAgIFx0cmV0dXJuICggc3RyLmluZGV4T2YoXCJzcGFuXCIpID09IC0xICk/IFwiXCIgOiBzdHI7XG4gICAgfSxcbiAgICAvKiBcbiAgICAgKiBGdW5jdGlvbjogU2VxdWVuY2UuX2RyYXdSYXdcbiAgICAgKiBQdXJwb3NlOiAgUmVwYWludCB0aGUgY3VycmVudCBzZXF1ZW5jZSB1c2luZyBSQVcgZm9ybWF0LiAgXG4gICAgICogUmV0dXJuczogIC1cbiAgICAgKiBJbnB1dHM6IC1cbiAgICAgKi9cblx0X2RyYXdSYXcgOiBmdW5jdGlvbigpIHtcblx0XHR2YXIgc2VsZiA9IHRoaXM7XG5cdFx0dmFyIGEgPSB0aGlzLm9wdC5zZXF1ZW5jZS50b0xvd2VyQ2FzZSgpLnNwbGl0KCcnKTtcblx0XHR2YXIgaSA9IDA7XG5cdFx0dmFyIGFyciA9IFtdO1xuXHRcdHZhciBwcmUgPSBqUXVlcnkoJzxwcmU+PC9wcmU+JykuYXBwZW5kVG8odGhpcy5fY29udGVudERpdik7XG5cdFx0XG5cdFx0LyogQ29ycmVjdCBjb2x1bW4gc2l6ZSBpbiBjYXNlIHRoZSBzZXF1ZW5jZSBpcyBhcyBzbWFsbCBwZXB0aWRlICovXG5cdFx0dmFyIG51bUNvbHMgPSB0aGlzLm9wdC5jb2x1bW5zLnNpemU7XG5cdFx0aWYgKCB0aGlzLm9wdC5zZXF1ZW5jZS5sZW5ndGggPCB0aGlzLm9wdC5jb2x1bW5zLnNpemUgKSB7XG5cdFx0XHRudW1Db2xzID0gdGhpcy5vcHQuc2VxdWVuY2UubGVuZ3RoO1x0XG5cdFx0fVxuXG5cdFx0dmFyIG9wdCA9IHtcblx0XHRcdG51bUNvbHM6IG51bUNvbHNcblx0XHR9O1xuXHRcdFxuXHRcdHByZS5odG1sKFxuXHRcdFx0dGhpcy5fZHJhd1NlcXVlbmNlKGEsIG9wdClcblx0XHQpO1xuXHRcdFxuXHRcdHRoaXMuX2RyYXdBbm5vdGF0aW9ucyhvcHQpO1xuXHR9LFxuXHQvKiBcbiAgICAgKiBGdW5jdGlvbjogU2VxdWVuY2UuX2RyYXdQcmlkZVxuICAgICAqIFB1cnBvc2U6ICBSZXBhaW50IHRoZSBjdXJyZW50IHNlcXVlbmNlIHVzaW5nIFBSSURFIGZvcm1hdC4gIFxuICAgICAqIFJldHVybnM6ICAtXG4gICAgICogSW5wdXRzOiAtXG4gICAgICovXG5cdF9kcmF3UHJpZGUgOiBmdW5jdGlvbigpIHtcblx0XHR2YXIgc2VsZiA9IHRoaXM7XG5cdFx0dmFyIGEgPSB0aGlzLm9wdC5zZXF1ZW5jZS50b1VwcGVyQ2FzZSgpLnNwbGl0KCcnKTtcblx0XHR2YXIgcHJlID0galF1ZXJ5KCc8cHJlPjwvcHJlPicpLmFwcGVuZFRvKHRoaXMuX2NvbnRlbnREaXYpO1xuXHRcdFxuXHRcdC8qIENvcnJlY3QgY29sdW1uIHNpemUgaW4gY2FzZSB0aGUgc2VxdWVuY2UgaXMgYXMgc21hbGwgcGVwdGlkZSAqL1xuXHRcdHZhciBudW1Db2xzID0gdGhpcy5vcHQuY29sdW1ucy5zaXplO1xuXHRcdGlmICggdGhpcy5vcHQuc2VxdWVuY2UubGVuZ3RoIDwgdGhpcy5vcHQuY29sdW1ucy5zaXplICkge1xuXHRcdFx0bnVtQ29scyA9IHRoaXMub3B0LnNlcXVlbmNlLmxlbmd0aDtcdFxuXHRcdH1cblx0XG5cdFx0b3B0ID0ge1xuXHRcdFx0bnVtTGVmdDogdHJ1ZSxcblx0XHRcdG51bUxlZnRTaXplOiA1LFxuXHRcdFx0bnVtTGVmdFBhZDonMCcsXG5cdFx0XHRudW1SaWdodDogdHJ1ZSxcblx0XHRcdG51bVJpZ2h0U2l6ZTogNSxcblx0XHRcdG51bVJpZ2h0UGFkOiAnMCcsXG5cdFx0XHRudW1Db2xzOiBudW1Db2xzLFxuXHRcdCAgICBudW1Db2xzRm9yU3BhY2U6IHNlbGYub3B0LmNvbHVtbnMuc3BhY2VkRWFjaFxuXHRcdH07XG5cdFx0XG5cdFx0cHJlLmh0bWwoXG5cdFx0XHR0aGlzLl9kcmF3U2VxdWVuY2UoYSwgb3B0KVxuXHRcdCk7XG5cdFx0XG5cdFx0dGhpcy5fZHJhd0Fubm90YXRpb25zKG9wdCk7XG5cdH0sXG5cdC8qIFxuICAgICAqIEZ1bmN0aW9uOiBTZXF1ZW5jZS5fZHJhd1NlcXVlbmNlXG4gICAgICogUHVycG9zZTogIFJlcGFpbnQgdGhlIGN1cnJlbnQgc2VxdWVuY2UgdXNpbmcgQ1VTVE9NIGZvcm1hdC4gIFxuICAgICAqIFJldHVybnM6ICAtXG4gICAgICogSW5wdXRzOiAgIGEgLT4ge2NoYXJbXX0gYSBUaGUgc2VxdWVuY2Ugc3RyYW5kLlxuICAgICAqIFx0XHRcdCBvcHQgLT4ge09iamVjdH0gb3B0IFRoZSBDVVNUT00gZm9ybWF0LlxuICAgICAqL1xuXHRfZHJhd1NlcXVlbmNlIDogZnVuY3Rpb24oYSwgb3B0KSB7XG5cdFx0dmFyIHN0ciA9ICcnO1xuXG5cdFx0dmFyIHNwYWNlU3R5bGUgPSAgXCJ3aGl0ZS1zcGFjZTogcHJlO1wiO1xuXHRcdFxuXHRcdC8vIEluZGV4IGF0IHRvcD9cblx0XHRpZiggb3B0Lm51bVRvcCApXG5cdFx0e1xuXHRcdFx0c3RyICs9ICc8c3BhbiBzdHlsZT1cIicrc3BhY2VTdHlsZSsnXCIgY2xhc3M9XCJudW1Ub3BcIj4nXG5cdFx0XHR2YXIgc2l6ZSA9IChvcHQuc3BhY2VCZXR3ZWVuQ2hhcnMpPyBvcHQubnVtVG9wRWFjaCoyOiBvcHQubnVtVG9wRWFjaDtcblx0XHRcdFxuXHRcdFx0aWYgKG9wdC5udW1MZWZ0KSB7XG5cdFx0XHRcdHN0ciArPSB0aGlzLl9mb3JtYXRJbmRleCgnICcsIG9wdC5udW1MZWZ0U2l6ZSwgJyAnKTtcblx0XHRcdH1cblx0XHRcdFxuXHRcdFx0c3RyICs9IHRoaXMuX2Zvcm1hdEluZGV4KCcgJywgc2l6ZSwgJyAnKTtcblx0XHRcdFxuXHRcdFx0Zm9yKHZhciB4ID0gb3B0Lm51bVRvcEVhY2g7IHggPCBvcHQubnVtQ29sczsgeCArPSBvcHQubnVtVG9wRWFjaCkge1xuXHRcdFx0XHRzdHIgKz0gdGhpcy5fZm9ybWF0SW5kZXgoeCwgc2l6ZSwgJyAnLCB0cnVlKTtcblx0XHRcdH1cblx0XHRcdHN0ciArPSAnPC9zcGFuPjxici8+J1xuXHRcdH1cblx0XHRcblx0XHRcblx0XHQvLyBJbmRleCBhdCB0aGUgbGVmdD9cblx0XHRpZiAob3B0Lm51bUxlZnQpIHtcblx0XHRcdHN0ciArPSB0aGlzLl9mb3JtYXRJbmRleCgxLCBvcHQubnVtTGVmdFNpemUsIG9wdC5udW1MZWZ0UGFkKTtcblx0XHRcdHN0ciArPSAnICAnO1xuXHRcdH1cblxuXHRcdHZhciBqPTE7XG5cdFx0Zm9yICh2YXIgaT0xOyBpIDw9IGEubGVuZ3RoOyBpKyspIHtcblxuXHRcdFx0aWYoIGkgJSBvcHQubnVtQ29scyA9PSAwKSB7XHRcblx0XHRcdFx0c3RyICs9ICc8c3BhbiBjbGFzcz1cInNlcXVlbmNlXCIgaWQ9XCInICsgdGhpcy5nZXRJZCgpICsgJ18nICsgaSArICdcIj4nICsgYVtpLTFdICsgJzwvc3Bhbj4nO1xuXHRcdFx0XHRcblx0XHRcdFx0aWYgKG9wdC5udW1SaWdodCkge1xuXHRcdFx0XHRcdHN0ciArPSAnPHNwYW4gc3R5bGU9XCInK3NwYWNlU3R5bGUrJ1wiIGlkPVwibnVtUmlnaHRfJyArIHRoaXMuZ2V0SWQoKSArICdfJyArIGkgKyAnXCI+Jztcblx0XHRcdFx0XHRzdHIgKz0gJyAgJztcblx0XHRcdFx0XHRzdHIgKz0gdGhpcy5fZm9ybWF0SW5kZXgoaSwgb3B0Lm51bVJpZ2h0U2l6ZSwgb3B0Lm51bVJpZ2h0UGFkKTtcdFxuXHRcdFx0XHRcdHN0ciArPSAnPC9zcGFuPic7XG5cdFx0XHRcdH1cblx0XHRcdFx0XG5cdFx0XHRcdHN0ciArPSAnPGJyLz4nO1xuXHRcdFx0XHRcblx0XHRcdFx0dmFyIGFhUmVtYWluaW5nID0gYS5sZW5ndGggLSBpO1xuXHRcdFx0XHRpZiAob3B0Lm51bUxlZnQgJiYgYWFSZW1haW5pbmcgPiAwKSB7XG5cdFx0XHRcdFx0c3RyICs9ICc8c3BhbiBpZD1cIm51bUxlZnRfJyArIHRoaXMuZ2V0SWQoKSArICdfJyArIGkgKyAnXCI+Jztcblx0XHRcdFx0XHRzdHIgKz0gdGhpcy5fZm9ybWF0SW5kZXgoaSsxLCBvcHQubnVtTGVmdFNpemUsIG9wdC5udW1MZWZ0UGFkKTtcblx0XHRcdFx0XHRzdHIgKz0gJyAgJztcblx0XHRcdFx0XHRzdHIgKz0gJzwvc3Bhbj4nO1xuXHRcdFx0XHR9XG5cdFx0XHRcdFxuXHRcdFx0XHRqID0gMTtcblx0XHRcdFx0XG5cdFx0XHR9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHN0ciArPSAnPHNwYW4gY2xhc3M9XCJzZXF1ZW5jZVwiIHN0eWxlPVwiJytzcGFjZVN0eWxlKydcIiBpZD1cIicgKyB0aGlzLmdldElkKCkgKyAnXycgKyBpICsgJ1wiPicgKyBhW2ktMV07XG5cdFx0XHRcdHN0ciArPSAoIGogJSBvcHQubnVtQ29sc0ZvclNwYWNlID09IDApPyAnICcgOiAnJztcblx0XHRcdFx0c3RyICs9IChvcHQuc3BhY2VCZXR3ZWVuQ2hhcnMpPyAnICcgOiAnJztcblx0XHRcdFx0c3RyICs9ICc8L3NwYW4+Jztcblx0XHRcdFx0aisrO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRcblx0XHRzdHIgKz0gJzxici8+J1x0XG5cdFx0XHRcblx0XHRpZiAoalF1ZXJ5LmJyb3dzZXIubXNpZSkge1xuXHRcdFx0c3RyID0gXCI8cHJlPlwiICsgc3RyICsgXCI8L3ByZT5cIjtcblx0XHR9XHRcblx0XHRcdFxuXHRcdHJldHVybiBzdHI7XG5cdH0sXG5cdC8qIFxuICAgICAqIEZ1bmN0aW9uOiBTZXF1ZW5jZS5fZm9ybWF0SW5kZXhcbiAgICAgKiBQdXJwb3NlOiAgQnVpbGQgdGhlIEhUTUwgY29ycmVzcG9uZGluZyB0byBjb3VudGluZyBudW1iZXJzICh0b3AsIGxlZnQsIHJpZ2h0KSBpbiB0aGUgc3RyYW5kLlxuICAgICAqIFJldHVybnM6ICAtXG4gICAgICogSW5wdXRzOiAgIG51bWJlciAtPiB7aW50fSBUaGUgbnVtYmVyIFxuICAgICAqIFx0XHRcdCBzaXplIC0+IHtpbnR9IE51bWJlciBvZiBiaW5zIHRvIHN1aXQgdGhlIG51bWJlci5cbiAgICAgKiBcdFx0XHQgZmlsbGluZ0NoYXIgLT4ge2NoYXJ9IENoYXJhY3RlciB0byBiZSB1c2VkIGZvciBmaWxsaW5nIG91dCBibGFuayBiaW5zLlxuICAgICAqIFx0XHRcdCBhbGlnbkxlZnQgLT4ge2Jvb2x9IFRlbGwgaWYgYWxpZ25lZCB0byB0aGUgbGVmdC5cbiAgICAgKi9cblx0X2Zvcm1hdEluZGV4IDogZnVuY3Rpb24oIG51bWJlciwgc2l6ZSwgZmlsbGluZ0NoYXIsIGFsaWduTGVmdCkge1xuXHRcdHZhciBzdHIgPSBudW1iZXIudG9TdHJpbmcoKTtcblx0XHR2YXIgZmlsbGluZyA9ICcnO1xuXHRcdHZhciBwYWRkaW5nID0gc2l6ZSAtIHN0ci5sZW5ndGg7XHRcblx0XHRpZiAoIHBhZGRpbmcgPiAwICkge1xuXHRcdFx0d2hpbGUgKCBwYWRkaW5nLS0gPiAwICkge1xuXHRcdFx0XHRmaWxsaW5nICs9IChcIjxzcGFuPlwiK2ZpbGxpbmdDaGFyK1wiPC9zcGFuPlwiKTtcblx0XHRcdH1cblx0XHRcdGlmIChhbGlnbkxlZnQpe1xuXHRcdFx0XHRzdHIgPSBudW1iZXIrZmlsbGluZztcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHN0ciA9IGZpbGxpbmcrbnVtYmVyO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRyZXR1cm4gc3RyO1xuXHR9LFxuXHQvKiBcbiAgICAgKiBGdW5jdGlvbjogU2VxdWVuY2UuX2FkZFNwYW5FdmVudHNcbiAgICAgKiBQdXJwb3NlOiAgQWRkIHRoZSBldmVudCBoYW5kbGVycyB0byB0aGUgc3RyYW5kLlxuICAgICAqIFJldHVybnM6ICAtXG4gICAgICogSW5wdXRzOiAgIC1cbiAgICAgKi9cblx0X2FkZFNwYW5FdmVudHMgOiBmdW5jdGlvbigpIHtcblx0XHR2YXIgc2VsZiA9IHRoaXM7XG5cdFx0dmFyIGlzTW91c2VEb3duID0gZmFsc2U7XG5cdFx0dmFyIGN1cnJlbnRQb3M7XG5cblx0XHRzZWxmLl9jb250ZW50RGl2LmZpbmQoJy5zZXF1ZW5jZScpLmVhY2goIGZ1bmN0aW9uICgpIHtcdFxuXHRcdFx0XG5cdFx0XHQvLyBSZWdpc3RlciB0aGUgc3RhcnRpbmcgcG9zaXRpb25cblx0XHRcdGpRdWVyeSh0aGlzKS5tb3VzZWRvd24oZnVuY3Rpb24oKSB7XG5cdFx0XHRcdHZhciBpZCA9IGpRdWVyeSh0aGlzKS5hdHRyKCdpZCcpO1xuXHRcdFx0XHRjdXJyZW50UG9zID0gcGFyc2VJbnQoaWQuc3Vic3RyKGlkLmluZGV4T2YoXCJfXCIpICsgMSkpO1xuXHRcdFx0XHRjbGlja1BvcyA9IGN1cnJlbnRQb3M7XG5cdFx0XHRcdHNlbGYuX3NldFNlbGVjdGlvbihjbGlja1BvcyxjdXJyZW50UG9zKTtcblx0XHRcdFx0aXNNb3VzZURvd24gPSB0cnVlO1xuXHRcdFx0XHRcblx0XHRcdFx0Ly8gU2VsZWN0aW9uIGlzIGhhcHBlbmluZywgcmFpc2UgYW4gZXZlbnRcblx0XHRcdFx0c2VsZi50cmlnZ2VyKFxuXHRcdFx0XHRcdEVWVF9PTl9TRUxFQ1RJT05fQ0hBTkdFLCBcblx0XHRcdFx0XHR7IFxuXHRcdFx0XHRcdFx0XCJzdGFydFwiIDogc2VsZi5vcHQuc2VsZWN0aW9uLnN0YXJ0LCBcblx0XHRcdFx0XHRcdFwiZW5kXCIgOiBzZWxmLm9wdC5zZWxlY3Rpb24uZW5kIFxuXHRcdFx0XHRcdH1cblx0XHRcdFx0KTtcblx0XHRcdFxuXHRcdFx0fSkubW91c2VvdmVyKGZ1bmN0aW9uKCkge1xuXHRcdFx0XHQvLyBVcGRhdGUgc2VsZWN0aW9uXG5cdFx0XHRcdC8vIFNob3cgdG9vbHRpcCBjb250YWluaW5nIHRoZSBwb3NpdGlvblxuXHRcdFx0XHR2YXIgaWQgPSBqUXVlcnkodGhpcykuYXR0cignaWQnKTtcblx0XHRcdFx0Y3VycmVudFBvcyA9IHBhcnNlSW50KGlkLnN1YnN0cihpZC5pbmRleE9mKFwiX1wiKSArIDEpKTtcblx0XHRcdFx0XG5cdFx0XHRcdGlmKGlzTW91c2VEb3duKSB7XG5cdFx0XHRcdFx0aWYoIGN1cnJlbnRQb3MgPiBjbGlja1BvcyApIHtcblx0XHRcdFx0XHRcdHNlbGYuX3NldFNlbGVjdGlvbihjbGlja1BvcywgY3VycmVudFBvcyk7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdHNlbGYuX3NldFNlbGVjdGlvbihjdXJyZW50UG9zLCBjbGlja1Bvcyk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFxuXHRcdFx0XHRcdC8vIFNlbGVjdGlvbiBpcyBoYXBwZW5pbmcsIHJhaXNlIGFuIGV2ZW50XG5cdFx0XHRcdFx0c2VsZi50cmlnZ2VyKCBFVlRfT05fU0VMRUNUSU9OX0NIQU5HRSwgeyBcblx0XHRcdFx0XHRcdFwic3RhcnRcIiA6IHNlbGYub3B0LnNlbGVjdGlvbi5zdGFydCwgXG5cdFx0XHRcdFx0XHRcImVuZFwiIDogc2VsZi5vcHQuc2VsZWN0aW9uLmVuZCBcblx0XHRcdFx0XHR9KTtcblx0XHRcdFx0fSBcblx0XHRcdFx0XG5cdFx0XHR9KS5tb3VzZXVwKGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRpc01vdXNlRG93biA9IGZhbHNlO1xuXHRcdFx0XHQvLyBTZWxlY3Rpb24gaXMgZG9uZSwgcmFpc2UgYW4gZXZlbnRcblx0XHRcdFx0c2VsZi50cmlnZ2VyKCBFVlRfT05fU0VMRUNUSU9OX0NIQU5HRUQsIHsgXG5cdFx0XHRcdFx0XCJzdGFydFwiIDogc2VsZi5vcHQuc2VsZWN0aW9uLnN0YXJ0LCBcblx0XHRcdFx0XHRcImVuZFwiIDogc2VsZi5vcHQuc2VsZWN0aW9uLmVuZCBcblx0XHRcdFx0fSk7XG5cdFx0XHR9KTtcblx0XHRcdFxuXHRcdFx0Ly8gQWRkIGEgdG9vbHRpcCBmb3IgdGhpcyBzZXF1ZW5jZSBiYXNlLlxuXHRcdFx0c2VsZi5fYWRkVG9vbFRpcC5jYWxsKCBzZWxmLCB0aGlzLCBmdW5jdGlvbiggKSB7XG5cdFx0XHRcdGlmIChpc01vdXNlRG93bikge1xuXHQgICAgIFx0XHRcdHJldHVybiBcIltcIiArIHNlbGYub3B0LnNlbGVjdGlvbi5zdGFydCArXCIsIFwiICsgc2VsZi5vcHQuc2VsZWN0aW9uLmVuZCArIFwiXVwiO1xuXHQgICAgIFx0XHR9IGVsc2Uge1xuXHQgICAgIFx0XHRcdHJldHVybiBjdXJyZW50UG9zO1xuXHQgICAgIFx0XHR9XG5cdFx0XHR9KTtcblx0XHRcdFxuXHRcdH0pXG5cdFx0LmNzcygnY3Vyc29yJywgJ3BvaW50ZXInKTtcblx0fSxcblx0LyogXG4gICAgICogRnVuY3Rpb246IFNlcXVlbmNlLl9hZGRUb29sdGlwXG4gICAgICogUHVycG9zZTogIEFkZCBhIHRvb2x0aXAgYXJvdW5kIHRoZSB0YXJnZXQgRE9NIGVsZW1lbnQgcHJvdmlkZWQgYXMgYXJndW1lbnRcbiAgICAgKiBSZXR1cm5zOiAgLVxuICAgICAqIElucHV0czogICB0YXJnZXQgLT4ge0VsZW1lbnR9IERPTSBlbGVtZW50IHdpY2ggaXMgdGhlIHRhcmdldGVkIGZvY3VzIGZvciB0aGUgdG9vbHRpcC5cbiAgICAgKiBcdFx0XHQgY2JHZXRNZXNzYWdlRnVuY3Rpb24gLT4ge2Z1bmN0aW9ufSBBIGNhbGxiYWNrIGZ1bmN0aW9uIHdpY2ggcmV0dXJucyB0aGUgbWVzc2FnZSB0byBiZSBkaXNwbGF5ZWQgaW4gdGhlIHRpcC5cbiAgICAgKi9cblx0X2FkZFRvb2xUaXAgOiBmdW5jdGlvbiAoIHRhcmdldCwgY2JHZXRNZXNzYWdlRnVuY3Rpb24gKSB7XG5cdFx0XG4gXHRcdHZhciB0aXBJZCA9IHRoaXMub3B0Ll90b29sdGlwO1xuXHRcdFxuXHRcdGpRdWVyeSh0YXJnZXQpLm1vdXNlb3ZlcihmdW5jdGlvbihlKSB7XG5cdFx0XHRcblx0IFx0XHR2YXIgb2Zmc2V0ID0galF1ZXJ5KGUudGFyZ2V0KS5vZmZzZXQoKTtcblxuXHRcdFx0aWYgKCAhIGpRdWVyeSggdGlwSWQgKS5pcygnOnZpc2libGUnKSApIHtcblx0XHQgICAgICAgIGpRdWVyeSggdGlwSWQgKSBcblx0XHQgICAgICAgIFx0LmNzcyh7XG5cdFx0ICAgICAgICBcdFx0J2JhY2tncm91bmQtY29sb3InOiBcIiMwMDBcIixcblx0XHQgICAgICAgIFx0XHQncGFkZGluZyc6IFwiM3B4IDEwcHggM3B4IDEwcHhcIixcblx0XHQgICAgICAgIFx0XHQndG9wJzogb2Zmc2V0LnRvcCArIGpRdWVyeShlLnRhcmdldCkuaGVpZ2h0KCkgKyBcInB4XCIsXG5cdFx0ICAgICAgICBcdFx0J2xlZnQnOiBvZmZzZXQubGVmdCArIGpRdWVyeShlLnRhcmdldCkud2lkdGgoKSArIFwicHhcIlxuXHRcdCAgICAgICAgXHR9KVxuXHRcdFx0ICAgICAgICAuYW5pbWF0ZSgge29wYWNpdHk6ICcwLjg1J30sIDEwKVxuXHRcdFx0ICAgICAgICAuaHRtbCggY2JHZXRNZXNzYWdlRnVuY3Rpb24uY2FsbCggdGFyZ2V0ICkgKVxuXHRcdFx0ICAgICAgICAuc2hvdygpO1xuXHRcdFx0fVxuXG5cdCAgICB9KS5tb3VzZW91dChmdW5jdGlvbigpIHtcblx0ICAgICAgICAvL1JlbW92ZSB0aGUgYXBwZW5kZWQgdG9vbHRpcCB0ZW1wbGF0ZVxuXHQgICAgICAgIGpRdWVyeSggdGlwSWQgKS5oaWRlKCk7XHQgICAgICAgICBcblx0ICAgIH0pO1xuXHR9LFxuXHRcbiAgIC8qKlxuICAgICogQW5ub3RhdGUgYSBzZXQgb2YgaW50ZXJ2YWxzIHByb3ZpZGVkIGluIHRoZSBhcmd1bWVudC5cblx0KiBcblx0KiBAZGVwcmVjYXRlZCBVc2UgYWRkQW5ub3RhdGlvbigpIGluc3RlYWQuXG4gICAgKiBcbiAgICAqIEBwYXJhbSB7T2JqZWN0fSBhbm5vdGF0aW9uIFRoZSBpbnRlcnZhbHMgYmVsb25naW5nIHRvIHRoZSBzYW1lIGFubm90YXRpb24uIFxuICAgICogU3ludGF4OiB7IG5hbWU6ICZsdDt2YWx1ZSZndDssIGNvbG9yOiAmbHQ7SFRNTENvbG9yQ29kZSZndDssIGh0bWw6ICZsdDtIVE1MU3RyaW5nJmd0OywgcmVnaW9uczogW3sgc3RhcnQ6ICZsdDtzdGFydFZhbDEmZ3Q7LCBlbmQ6ICZsdDtlbmRWYWwxJmd0O30sIC4uLiwgIHsgc3RhcnQ6ICZsdDtzdGFydFZhbE4mZ3Q7LCBlbmQ6ICZsdDtlbmRWYWxOJmd0O31dIH1cbiAgICAqL1xuXHRzZXRBbm5vdGF0aW9uOiBmdW5jdGlvbiAoIGFubm90YXRpb24gKSB7XG5cdFx0dGhpcy5hZGRBbm5vdGF0aW9uKGFubm90YXRpb24pO1xuXHR9LFxuXHRcblx0LyoqXG4gICAgKiBBbm5vdGF0ZSBhIHNldCBvZiBpbnRlcnZhbHMgcHJvdmlkZWQgaW4gdGhlIGFyZ3VtZW50LlxuICAgICogXG4gICAgKiBAZXhhbXBsZVxuICAgICogLy8gQW5ub3RhdGlvbnMgdXNpbmcgcmVnaW9ucyB3aXRoIGRpZmZlcmVudCBjb2xvcnMuXG4gICAgKiBteVNlcXVlbmNlLmFkZEFubm90YXRpb24oe1xuXHQqICAgIG5hbWU6XCJVTklQUk9UXCIsIFxuXHQqICAgIGh0bWw6XCImbHQ7YnImZ3Q7IEV4YW1wbGUgb2YgJmx0O2ImZ3Q7SFRNTCZsdDsvYiZndDtcIiwgXG5cdCogICAgY29sb3I6XCJncmVlblwiLCBcblx0KiAgICByZWdpb25zOiBbXG5cdCogICAgICAge3N0YXJ0OiA1NDAsIGVuZDogNTYwfSxcblx0KiAgICAgICB7c3RhcnQ6IDU2MSwgZW5kOjU4MCwgY29sb3I6IFwiI0ZGQTAxMFwifSwgXG5cdCogICAgICAge3N0YXJ0OiA1ODEsIGVuZDo1OTAsIGNvbG9yOiBcInJlZFwifSwgXG5cdCogICAgICAge3N0YXJ0OiA2OTAsIGVuZDo3MTB9XVxuXHQqIH0pO1xuXHQqIFxuICAgICogXG4gICAgKiBAcGFyYW0ge09iamVjdH0gYW5ub3RhdGlvbiBUaGUgaW50ZXJ2YWxzIGJlbG9uZ2luZyB0byB0aGUgc2FtZSBhbm5vdGF0aW9uLiBcbiAgICAqIFN5bnRheDogeyBuYW1lOiAmbHQ7dmFsdWUmZ3Q7LCBjb2xvcjogJmx0O0hUTUxDb2xvckNvZGUmZ3Q7LCBodG1sOiAmbHQ7SFRNTFN0cmluZyZndDssIHJlZ2lvbnM6IFt7IHN0YXJ0OiAmbHQ7c3RhcnRWYWwxJmd0OywgZW5kOiAmbHQ7ZW5kVmFsMSZndDt9LCAuLi4sICB7IHN0YXJ0OiAmbHQ7c3RhcnRWYWxOJmd0OywgZW5kOiAmbHQ7ZW5kVmFsTiZndDt9XSB9XG4gICAgKi9cblx0YWRkQW5ub3RhdGlvbjogZnVuY3Rpb24gKCBhbm5vdGF0aW9uICkge1xuXHRcdHRoaXMuX2Fubm90YXRpb25zLnB1c2goYW5ub3RhdGlvbik7XG5cdFx0dGhpcy5fcmVkcmF3KCk7XG5cdH0sXG5cdFxuXHQvKipcbiAgICAqIFJlbW92ZXMgYW4gYW5ub3RhdGlvbiBieSBtZWFucyBvZiBpdHMgbmFtZS5cbiAgICAqIFxuICAgICogQGV4YW1wbGUgXG4gICAgKiAvLyBSZW1vdmUgdGhlIFVOSVBST1QgYW5ub3RhdGlvbi5cbiAgICAqIG15U2VxdWVuY2UucmVtb3ZlQW5ub3RhdGlvbignVU5JUFJPVCcpOyBcbiAgICAqIFxuICAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgVGhlIG5hbWUgb2YgdGhlIGFubm90YXRpb24gdG8gYmUgcmVtb3ZlZC5cbiAgICAqIFxuICAgICovXG5cdHJlbW92ZUFubm90YXRpb246IGZ1bmN0aW9uICggbmFtZSApIHtcblx0XHRmb3IgKHZhciBpPTA7IGkgPCB0aGlzLl9hbm5vdGF0aW9ucy5sZW5ndGggOyBpKysgKXtcblx0XHRcdGlmKG5hbWUgIT0gdGhpcy5fYW5ub3RhdGlvbnNbaV0ubmFtZSl7XG5cdFx0XHRcdHRoaXMuX2Fubm90YXRpb25zLnNwbGljZShpLDEpO1xuXHRcdFx0XHR0aGlzLl9yZWRyYXcoKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHR9XG5cdFx0fVxuXHR9LFxuXHQvKipcbiAgICAqIFJlbW92ZXMgYWxsIHRoZSBjdXJyZW50IGFubm90YXRpb25zLlxuICAgICogXG4gICAgKiBAZXhhbXBsZSBcbiAgICAqIG15U2VxdWVuY2UucmVtb3ZlQWxsQW5ub3RhdGlvbnMoKTsgXG4gICAgKiBcbiAgICAqL1xuXHRyZW1vdmVBbGxBbm5vdGF0aW9uczogZnVuY3Rpb24gKCkge1xuXHRcdHRoaXMuX2Fubm90YXRpb25zID0gW107XG5cdFx0dGhpcy5fcmVkcmF3KCk7XG5cdH0sXG5cblx0XG59KTtcblxucmVxdWlyZShcImJpb2pzLWV2ZW50c1wiKS5taXhpbihTZXF1ZW5jZS5wcm90b3R5cGUpO1xubW9kdWxlLmV4cG9ydHMgPSBTZXF1ZW5jZTtcbiIsInZhciBldmVudHMgPSByZXF1aXJlKFwiYmFja2JvbmUtZXZlbnRzLXN0YW5kYWxvbmVcIik7XG5cbmV2ZW50cy5vbkFsbCA9IGZ1bmN0aW9uKGNhbGxiYWNrLGNvbnRleHQpe1xuICB0aGlzLm9uKFwiYWxsXCIsIGNhbGxiYWNrLGNvbnRleHQpO1xuICByZXR1cm4gdGhpcztcbn07XG5cbi8vIE1peGluIHV0aWxpdHlcbmV2ZW50cy5vbGRNaXhpbiA9IGV2ZW50cy5taXhpbjtcbmV2ZW50cy5taXhpbiA9IGZ1bmN0aW9uKHByb3RvKSB7XG4gIGV2ZW50cy5vbGRNaXhpbihwcm90byk7XG4gIC8vIGFkZCBjdXN0b20gb25BbGxcbiAgdmFyIGV4cG9ydHMgPSBbJ29uQWxsJ107XG4gIGZvcih2YXIgaT0wOyBpIDwgZXhwb3J0cy5sZW5ndGg7aSsrKXtcbiAgICB2YXIgbmFtZSA9IGV4cG9ydHNbaV07XG4gICAgcHJvdG9bbmFtZV0gPSB0aGlzW25hbWVdO1xuICB9XG4gIHJldHVybiBwcm90bztcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gZXZlbnRzO1xuIiwiLyoqXG4gKiBTdGFuZGFsb25lIGV4dHJhY3Rpb24gb2YgQmFja2JvbmUuRXZlbnRzLCBubyBleHRlcm5hbCBkZXBlbmRlbmN5IHJlcXVpcmVkLlxuICogRGVncmFkZXMgbmljZWx5IHdoZW4gQmFja29uZS91bmRlcnNjb3JlIGFyZSBhbHJlYWR5IGF2YWlsYWJsZSBpbiB0aGUgY3VycmVudFxuICogZ2xvYmFsIGNvbnRleHQuXG4gKlxuICogTm90ZSB0aGF0IGRvY3Mgc3VnZ2VzdCB0byB1c2UgdW5kZXJzY29yZSdzIGBfLmV4dGVuZCgpYCBtZXRob2QgdG8gYWRkIEV2ZW50c1xuICogc3VwcG9ydCB0byBzb21lIGdpdmVuIG9iamVjdC4gQSBgbWl4aW4oKWAgbWV0aG9kIGhhcyBiZWVuIGFkZGVkIHRvIHRoZSBFdmVudHNcbiAqIHByb3RvdHlwZSB0byBhdm9pZCB1c2luZyB1bmRlcnNjb3JlIGZvciB0aGF0IHNvbGUgcHVycG9zZTpcbiAqXG4gKiAgICAgdmFyIG15RXZlbnRFbWl0dGVyID0gQmFja2JvbmVFdmVudHMubWl4aW4oe30pO1xuICpcbiAqIE9yIGZvciBhIGZ1bmN0aW9uIGNvbnN0cnVjdG9yOlxuICpcbiAqICAgICBmdW5jdGlvbiBNeUNvbnN0cnVjdG9yKCl7fVxuICogICAgIE15Q29uc3RydWN0b3IucHJvdG90eXBlLmZvbyA9IGZ1bmN0aW9uKCl7fVxuICogICAgIEJhY2tib25lRXZlbnRzLm1peGluKE15Q29uc3RydWN0b3IucHJvdG90eXBlKTtcbiAqXG4gKiAoYykgMjAwOS0yMDEzIEplcmVteSBBc2hrZW5hcywgRG9jdW1lbnRDbG91ZCBJbmMuXG4gKiAoYykgMjAxMyBOaWNvbGFzIFBlcnJpYXVsdFxuICovXG4vKiBnbG9iYWwgZXhwb3J0czp0cnVlLCBkZWZpbmUsIG1vZHVsZSAqL1xuKGZ1bmN0aW9uKCkge1xuICB2YXIgcm9vdCA9IHRoaXMsXG4gICAgICBicmVha2VyID0ge30sXG4gICAgICBuYXRpdmVGb3JFYWNoID0gQXJyYXkucHJvdG90eXBlLmZvckVhY2gsXG4gICAgICBoYXNPd25Qcm9wZXJ0eSA9IE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHksXG4gICAgICBzbGljZSA9IEFycmF5LnByb3RvdHlwZS5zbGljZSxcbiAgICAgIGlkQ291bnRlciA9IDA7XG5cbiAgLy8gUmV0dXJucyBhIHBhcnRpYWwgaW1wbGVtZW50YXRpb24gbWF0Y2hpbmcgdGhlIG1pbmltYWwgQVBJIHN1YnNldCByZXF1aXJlZFxuICAvLyBieSBCYWNrYm9uZS5FdmVudHNcbiAgZnVuY3Rpb24gbWluaXNjb3JlKCkge1xuICAgIHJldHVybiB7XG4gICAgICBrZXlzOiBPYmplY3Qua2V5cyB8fCBmdW5jdGlvbiAob2JqKSB7XG4gICAgICAgIGlmICh0eXBlb2Ygb2JqICE9PSBcIm9iamVjdFwiICYmIHR5cGVvZiBvYmogIT09IFwiZnVuY3Rpb25cIiB8fCBvYmogPT09IG51bGwpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwia2V5cygpIGNhbGxlZCBvbiBhIG5vbi1vYmplY3RcIik7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGtleSwga2V5cyA9IFtdO1xuICAgICAgICBmb3IgKGtleSBpbiBvYmopIHtcbiAgICAgICAgICBpZiAob2JqLmhhc093blByb3BlcnR5KGtleSkpIHtcbiAgICAgICAgICAgIGtleXNba2V5cy5sZW5ndGhdID0ga2V5O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4ga2V5cztcbiAgICAgIH0sXG5cbiAgICAgIHVuaXF1ZUlkOiBmdW5jdGlvbihwcmVmaXgpIHtcbiAgICAgICAgdmFyIGlkID0gKytpZENvdW50ZXIgKyAnJztcbiAgICAgICAgcmV0dXJuIHByZWZpeCA/IHByZWZpeCArIGlkIDogaWQ7XG4gICAgICB9LFxuXG4gICAgICBoYXM6IGZ1bmN0aW9uKG9iaiwga2V5KSB7XG4gICAgICAgIHJldHVybiBoYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwga2V5KTtcbiAgICAgIH0sXG5cbiAgICAgIGVhY2g6IGZ1bmN0aW9uKG9iaiwgaXRlcmF0b3IsIGNvbnRleHQpIHtcbiAgICAgICAgaWYgKG9iaiA9PSBudWxsKSByZXR1cm47XG4gICAgICAgIGlmIChuYXRpdmVGb3JFYWNoICYmIG9iai5mb3JFYWNoID09PSBuYXRpdmVGb3JFYWNoKSB7XG4gICAgICAgICAgb2JqLmZvckVhY2goaXRlcmF0b3IsIGNvbnRleHQpO1xuICAgICAgICB9IGVsc2UgaWYgKG9iai5sZW5ndGggPT09ICtvYmoubGVuZ3RoKSB7XG4gICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGwgPSBvYmoubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgICAgICAgICBpZiAoaXRlcmF0b3IuY2FsbChjb250ZXh0LCBvYmpbaV0sIGksIG9iaikgPT09IGJyZWFrZXIpIHJldHVybjtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZm9yICh2YXIga2V5IGluIG9iaikge1xuICAgICAgICAgICAgaWYgKHRoaXMuaGFzKG9iaiwga2V5KSkge1xuICAgICAgICAgICAgICBpZiAoaXRlcmF0b3IuY2FsbChjb250ZXh0LCBvYmpba2V5XSwga2V5LCBvYmopID09PSBicmVha2VyKSByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9LFxuXG4gICAgICBvbmNlOiBmdW5jdGlvbihmdW5jKSB7XG4gICAgICAgIHZhciByYW4gPSBmYWxzZSwgbWVtbztcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgICAgIGlmIChyYW4pIHJldHVybiBtZW1vO1xuICAgICAgICAgIHJhbiA9IHRydWU7XG4gICAgICAgICAgbWVtbyA9IGZ1bmMuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgICBmdW5jID0gbnVsbDtcbiAgICAgICAgICByZXR1cm4gbWVtbztcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICB9O1xuICB9XG5cbiAgdmFyIF8gPSBtaW5pc2NvcmUoKSwgRXZlbnRzO1xuXG4gIC8vIEJhY2tib25lLkV2ZW50c1xuICAvLyAtLS0tLS0tLS0tLS0tLS1cblxuICAvLyBBIG1vZHVsZSB0aGF0IGNhbiBiZSBtaXhlZCBpbiB0byAqYW55IG9iamVjdCogaW4gb3JkZXIgdG8gcHJvdmlkZSBpdCB3aXRoXG4gIC8vIGN1c3RvbSBldmVudHMuIFlvdSBtYXkgYmluZCB3aXRoIGBvbmAgb3IgcmVtb3ZlIHdpdGggYG9mZmAgY2FsbGJhY2tcbiAgLy8gZnVuY3Rpb25zIHRvIGFuIGV2ZW50OyBgdHJpZ2dlcmAtaW5nIGFuIGV2ZW50IGZpcmVzIGFsbCBjYWxsYmFja3MgaW5cbiAgLy8gc3VjY2Vzc2lvbi5cbiAgLy9cbiAgLy8gICAgIHZhciBvYmplY3QgPSB7fTtcbiAgLy8gICAgIF8uZXh0ZW5kKG9iamVjdCwgQmFja2JvbmUuRXZlbnRzKTtcbiAgLy8gICAgIG9iamVjdC5vbignZXhwYW5kJywgZnVuY3Rpb24oKXsgYWxlcnQoJ2V4cGFuZGVkJyk7IH0pO1xuICAvLyAgICAgb2JqZWN0LnRyaWdnZXIoJ2V4cGFuZCcpO1xuICAvL1xuICBFdmVudHMgPSB7XG5cbiAgICAvLyBCaW5kIGFuIGV2ZW50IHRvIGEgYGNhbGxiYWNrYCBmdW5jdGlvbi4gUGFzc2luZyBgXCJhbGxcImAgd2lsbCBiaW5kXG4gICAgLy8gdGhlIGNhbGxiYWNrIHRvIGFsbCBldmVudHMgZmlyZWQuXG4gICAgb246IGZ1bmN0aW9uKG5hbWUsIGNhbGxiYWNrLCBjb250ZXh0KSB7XG4gICAgICBpZiAoIWV2ZW50c0FwaSh0aGlzLCAnb24nLCBuYW1lLCBbY2FsbGJhY2ssIGNvbnRleHRdKSB8fCAhY2FsbGJhY2spIHJldHVybiB0aGlzO1xuICAgICAgdGhpcy5fZXZlbnRzIHx8ICh0aGlzLl9ldmVudHMgPSB7fSk7XG4gICAgICB2YXIgZXZlbnRzID0gdGhpcy5fZXZlbnRzW25hbWVdIHx8ICh0aGlzLl9ldmVudHNbbmFtZV0gPSBbXSk7XG4gICAgICBldmVudHMucHVzaCh7Y2FsbGJhY2s6IGNhbGxiYWNrLCBjb250ZXh0OiBjb250ZXh0LCBjdHg6IGNvbnRleHQgfHwgdGhpc30pO1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIC8vIEJpbmQgYW4gZXZlbnQgdG8gb25seSBiZSB0cmlnZ2VyZWQgYSBzaW5nbGUgdGltZS4gQWZ0ZXIgdGhlIGZpcnN0IHRpbWVcbiAgICAvLyB0aGUgY2FsbGJhY2sgaXMgaW52b2tlZCwgaXQgd2lsbCBiZSByZW1vdmVkLlxuICAgIG9uY2U6IGZ1bmN0aW9uKG5hbWUsIGNhbGxiYWNrLCBjb250ZXh0KSB7XG4gICAgICBpZiAoIWV2ZW50c0FwaSh0aGlzLCAnb25jZScsIG5hbWUsIFtjYWxsYmFjaywgY29udGV4dF0pIHx8ICFjYWxsYmFjaykgcmV0dXJuIHRoaXM7XG4gICAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgICB2YXIgb25jZSA9IF8ub25jZShmdW5jdGlvbigpIHtcbiAgICAgICAgc2VsZi5vZmYobmFtZSwgb25jZSk7XG4gICAgICAgIGNhbGxiYWNrLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICB9KTtcbiAgICAgIG9uY2UuX2NhbGxiYWNrID0gY2FsbGJhY2s7XG4gICAgICByZXR1cm4gdGhpcy5vbihuYW1lLCBvbmNlLCBjb250ZXh0KTtcbiAgICB9LFxuXG4gICAgLy8gUmVtb3ZlIG9uZSBvciBtYW55IGNhbGxiYWNrcy4gSWYgYGNvbnRleHRgIGlzIG51bGwsIHJlbW92ZXMgYWxsXG4gICAgLy8gY2FsbGJhY2tzIHdpdGggdGhhdCBmdW5jdGlvbi4gSWYgYGNhbGxiYWNrYCBpcyBudWxsLCByZW1vdmVzIGFsbFxuICAgIC8vIGNhbGxiYWNrcyBmb3IgdGhlIGV2ZW50LiBJZiBgbmFtZWAgaXMgbnVsbCwgcmVtb3ZlcyBhbGwgYm91bmRcbiAgICAvLyBjYWxsYmFja3MgZm9yIGFsbCBldmVudHMuXG4gICAgb2ZmOiBmdW5jdGlvbihuYW1lLCBjYWxsYmFjaywgY29udGV4dCkge1xuICAgICAgdmFyIHJldGFpbiwgZXYsIGV2ZW50cywgbmFtZXMsIGksIGwsIGosIGs7XG4gICAgICBpZiAoIXRoaXMuX2V2ZW50cyB8fCAhZXZlbnRzQXBpKHRoaXMsICdvZmYnLCBuYW1lLCBbY2FsbGJhY2ssIGNvbnRleHRdKSkgcmV0dXJuIHRoaXM7XG4gICAgICBpZiAoIW5hbWUgJiYgIWNhbGxiYWNrICYmICFjb250ZXh0KSB7XG4gICAgICAgIHRoaXMuX2V2ZW50cyA9IHt9O1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgIH1cblxuICAgICAgbmFtZXMgPSBuYW1lID8gW25hbWVdIDogXy5rZXlzKHRoaXMuX2V2ZW50cyk7XG4gICAgICBmb3IgKGkgPSAwLCBsID0gbmFtZXMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgICAgIG5hbWUgPSBuYW1lc1tpXTtcbiAgICAgICAgaWYgKGV2ZW50cyA9IHRoaXMuX2V2ZW50c1tuYW1lXSkge1xuICAgICAgICAgIHRoaXMuX2V2ZW50c1tuYW1lXSA9IHJldGFpbiA9IFtdO1xuICAgICAgICAgIGlmIChjYWxsYmFjayB8fCBjb250ZXh0KSB7XG4gICAgICAgICAgICBmb3IgKGogPSAwLCBrID0gZXZlbnRzLmxlbmd0aDsgaiA8IGs7IGorKykge1xuICAgICAgICAgICAgICBldiA9IGV2ZW50c1tqXTtcbiAgICAgICAgICAgICAgaWYgKChjYWxsYmFjayAmJiBjYWxsYmFjayAhPT0gZXYuY2FsbGJhY2sgJiYgY2FsbGJhY2sgIT09IGV2LmNhbGxiYWNrLl9jYWxsYmFjaykgfHxcbiAgICAgICAgICAgICAgICAgIChjb250ZXh0ICYmIGNvbnRleHQgIT09IGV2LmNvbnRleHQpKSB7XG4gICAgICAgICAgICAgICAgcmV0YWluLnB1c2goZXYpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICghcmV0YWluLmxlbmd0aCkgZGVsZXRlIHRoaXMuX2V2ZW50c1tuYW1lXTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLy8gVHJpZ2dlciBvbmUgb3IgbWFueSBldmVudHMsIGZpcmluZyBhbGwgYm91bmQgY2FsbGJhY2tzLiBDYWxsYmFja3MgYXJlXG4gICAgLy8gcGFzc2VkIHRoZSBzYW1lIGFyZ3VtZW50cyBhcyBgdHJpZ2dlcmAgaXMsIGFwYXJ0IGZyb20gdGhlIGV2ZW50IG5hbWVcbiAgICAvLyAodW5sZXNzIHlvdSdyZSBsaXN0ZW5pbmcgb24gYFwiYWxsXCJgLCB3aGljaCB3aWxsIGNhdXNlIHlvdXIgY2FsbGJhY2sgdG9cbiAgICAvLyByZWNlaXZlIHRoZSB0cnVlIG5hbWUgb2YgdGhlIGV2ZW50IGFzIHRoZSBmaXJzdCBhcmd1bWVudCkuXG4gICAgdHJpZ2dlcjogZnVuY3Rpb24obmFtZSkge1xuICAgICAgaWYgKCF0aGlzLl9ldmVudHMpIHJldHVybiB0aGlzO1xuICAgICAgdmFyIGFyZ3MgPSBzbGljZS5jYWxsKGFyZ3VtZW50cywgMSk7XG4gICAgICBpZiAoIWV2ZW50c0FwaSh0aGlzLCAndHJpZ2dlcicsIG5hbWUsIGFyZ3MpKSByZXR1cm4gdGhpcztcbiAgICAgIHZhciBldmVudHMgPSB0aGlzLl9ldmVudHNbbmFtZV07XG4gICAgICB2YXIgYWxsRXZlbnRzID0gdGhpcy5fZXZlbnRzLmFsbDtcbiAgICAgIGlmIChldmVudHMpIHRyaWdnZXJFdmVudHMoZXZlbnRzLCBhcmdzKTtcbiAgICAgIGlmIChhbGxFdmVudHMpIHRyaWdnZXJFdmVudHMoYWxsRXZlbnRzLCBhcmd1bWVudHMpO1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIC8vIFRlbGwgdGhpcyBvYmplY3QgdG8gc3RvcCBsaXN0ZW5pbmcgdG8gZWl0aGVyIHNwZWNpZmljIGV2ZW50cyAuLi4gb3JcbiAgICAvLyB0byBldmVyeSBvYmplY3QgaXQncyBjdXJyZW50bHkgbGlzdGVuaW5nIHRvLlxuICAgIHN0b3BMaXN0ZW5pbmc6IGZ1bmN0aW9uKG9iaiwgbmFtZSwgY2FsbGJhY2spIHtcbiAgICAgIHZhciBsaXN0ZW5lcnMgPSB0aGlzLl9saXN0ZW5lcnM7XG4gICAgICBpZiAoIWxpc3RlbmVycykgcmV0dXJuIHRoaXM7XG4gICAgICB2YXIgZGVsZXRlTGlzdGVuZXIgPSAhbmFtZSAmJiAhY2FsbGJhY2s7XG4gICAgICBpZiAodHlwZW9mIG5hbWUgPT09ICdvYmplY3QnKSBjYWxsYmFjayA9IHRoaXM7XG4gICAgICBpZiAob2JqKSAobGlzdGVuZXJzID0ge30pW29iai5fbGlzdGVuZXJJZF0gPSBvYmo7XG4gICAgICBmb3IgKHZhciBpZCBpbiBsaXN0ZW5lcnMpIHtcbiAgICAgICAgbGlzdGVuZXJzW2lkXS5vZmYobmFtZSwgY2FsbGJhY2ssIHRoaXMpO1xuICAgICAgICBpZiAoZGVsZXRlTGlzdGVuZXIpIGRlbGV0ZSB0aGlzLl9saXN0ZW5lcnNbaWRdO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gIH07XG5cbiAgLy8gUmVndWxhciBleHByZXNzaW9uIHVzZWQgdG8gc3BsaXQgZXZlbnQgc3RyaW5ncy5cbiAgdmFyIGV2ZW50U3BsaXR0ZXIgPSAvXFxzKy87XG5cbiAgLy8gSW1wbGVtZW50IGZhbmN5IGZlYXR1cmVzIG9mIHRoZSBFdmVudHMgQVBJIHN1Y2ggYXMgbXVsdGlwbGUgZXZlbnRcbiAgLy8gbmFtZXMgYFwiY2hhbmdlIGJsdXJcImAgYW5kIGpRdWVyeS1zdHlsZSBldmVudCBtYXBzIGB7Y2hhbmdlOiBhY3Rpb259YFxuICAvLyBpbiB0ZXJtcyBvZiB0aGUgZXhpc3RpbmcgQVBJLlxuICB2YXIgZXZlbnRzQXBpID0gZnVuY3Rpb24ob2JqLCBhY3Rpb24sIG5hbWUsIHJlc3QpIHtcbiAgICBpZiAoIW5hbWUpIHJldHVybiB0cnVlO1xuXG4gICAgLy8gSGFuZGxlIGV2ZW50IG1hcHMuXG4gICAgaWYgKHR5cGVvZiBuYW1lID09PSAnb2JqZWN0Jykge1xuICAgICAgZm9yICh2YXIga2V5IGluIG5hbWUpIHtcbiAgICAgICAgb2JqW2FjdGlvbl0uYXBwbHkob2JqLCBba2V5LCBuYW1lW2tleV1dLmNvbmNhdChyZXN0KSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgLy8gSGFuZGxlIHNwYWNlIHNlcGFyYXRlZCBldmVudCBuYW1lcy5cbiAgICBpZiAoZXZlbnRTcGxpdHRlci50ZXN0KG5hbWUpKSB7XG4gICAgICB2YXIgbmFtZXMgPSBuYW1lLnNwbGl0KGV2ZW50U3BsaXR0ZXIpO1xuICAgICAgZm9yICh2YXIgaSA9IDAsIGwgPSBuYW1lcy5sZW5ndGg7IGkgPCBsOyBpKyspIHtcbiAgICAgICAgb2JqW2FjdGlvbl0uYXBwbHkob2JqLCBbbmFtZXNbaV1dLmNvbmNhdChyZXN0KSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG5cbiAgLy8gQSBkaWZmaWN1bHQtdG8tYmVsaWV2ZSwgYnV0IG9wdGltaXplZCBpbnRlcm5hbCBkaXNwYXRjaCBmdW5jdGlvbiBmb3JcbiAgLy8gdHJpZ2dlcmluZyBldmVudHMuIFRyaWVzIHRvIGtlZXAgdGhlIHVzdWFsIGNhc2VzIHNwZWVkeSAobW9zdCBpbnRlcm5hbFxuICAvLyBCYWNrYm9uZSBldmVudHMgaGF2ZSAzIGFyZ3VtZW50cykuXG4gIHZhciB0cmlnZ2VyRXZlbnRzID0gZnVuY3Rpb24oZXZlbnRzLCBhcmdzKSB7XG4gICAgdmFyIGV2LCBpID0gLTEsIGwgPSBldmVudHMubGVuZ3RoLCBhMSA9IGFyZ3NbMF0sIGEyID0gYXJnc1sxXSwgYTMgPSBhcmdzWzJdO1xuICAgIHN3aXRjaCAoYXJncy5sZW5ndGgpIHtcbiAgICAgIGNhc2UgMDogd2hpbGUgKCsraSA8IGwpIChldiA9IGV2ZW50c1tpXSkuY2FsbGJhY2suY2FsbChldi5jdHgpOyByZXR1cm47XG4gICAgICBjYXNlIDE6IHdoaWxlICgrK2kgPCBsKSAoZXYgPSBldmVudHNbaV0pLmNhbGxiYWNrLmNhbGwoZXYuY3R4LCBhMSk7IHJldHVybjtcbiAgICAgIGNhc2UgMjogd2hpbGUgKCsraSA8IGwpIChldiA9IGV2ZW50c1tpXSkuY2FsbGJhY2suY2FsbChldi5jdHgsIGExLCBhMik7IHJldHVybjtcbiAgICAgIGNhc2UgMzogd2hpbGUgKCsraSA8IGwpIChldiA9IGV2ZW50c1tpXSkuY2FsbGJhY2suY2FsbChldi5jdHgsIGExLCBhMiwgYTMpOyByZXR1cm47XG4gICAgICBkZWZhdWx0OiB3aGlsZSAoKytpIDwgbCkgKGV2ID0gZXZlbnRzW2ldKS5jYWxsYmFjay5hcHBseShldi5jdHgsIGFyZ3MpO1xuICAgIH1cbiAgfTtcblxuICB2YXIgbGlzdGVuTWV0aG9kcyA9IHtsaXN0ZW5UbzogJ29uJywgbGlzdGVuVG9PbmNlOiAnb25jZSd9O1xuXG4gIC8vIEludmVyc2lvbi1vZi1jb250cm9sIHZlcnNpb25zIG9mIGBvbmAgYW5kIGBvbmNlYC4gVGVsbCAqdGhpcyogb2JqZWN0IHRvXG4gIC8vIGxpc3RlbiB0byBhbiBldmVudCBpbiBhbm90aGVyIG9iamVjdCAuLi4ga2VlcGluZyB0cmFjayBvZiB3aGF0IGl0J3NcbiAgLy8gbGlzdGVuaW5nIHRvLlxuICBfLmVhY2gobGlzdGVuTWV0aG9kcywgZnVuY3Rpb24oaW1wbGVtZW50YXRpb24sIG1ldGhvZCkge1xuICAgIEV2ZW50c1ttZXRob2RdID0gZnVuY3Rpb24ob2JqLCBuYW1lLCBjYWxsYmFjaykge1xuICAgICAgdmFyIGxpc3RlbmVycyA9IHRoaXMuX2xpc3RlbmVycyB8fCAodGhpcy5fbGlzdGVuZXJzID0ge30pO1xuICAgICAgdmFyIGlkID0gb2JqLl9saXN0ZW5lcklkIHx8IChvYmouX2xpc3RlbmVySWQgPSBfLnVuaXF1ZUlkKCdsJykpO1xuICAgICAgbGlzdGVuZXJzW2lkXSA9IG9iajtcbiAgICAgIGlmICh0eXBlb2YgbmFtZSA9PT0gJ29iamVjdCcpIGNhbGxiYWNrID0gdGhpcztcbiAgICAgIG9ialtpbXBsZW1lbnRhdGlvbl0obmFtZSwgY2FsbGJhY2ssIHRoaXMpO1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgfSk7XG5cbiAgLy8gQWxpYXNlcyBmb3IgYmFja3dhcmRzIGNvbXBhdGliaWxpdHkuXG4gIEV2ZW50cy5iaW5kICAgPSBFdmVudHMub247XG4gIEV2ZW50cy51bmJpbmQgPSBFdmVudHMub2ZmO1xuXG4gIC8vIE1peGluIHV0aWxpdHlcbiAgRXZlbnRzLm1peGluID0gZnVuY3Rpb24ocHJvdG8pIHtcbiAgICB2YXIgZXhwb3J0cyA9IFsnb24nLCAnb25jZScsICdvZmYnLCAndHJpZ2dlcicsICdzdG9wTGlzdGVuaW5nJywgJ2xpc3RlblRvJyxcbiAgICAgICAgICAgICAgICAgICAnbGlzdGVuVG9PbmNlJywgJ2JpbmQnLCAndW5iaW5kJ107XG4gICAgXy5lYWNoKGV4cG9ydHMsIGZ1bmN0aW9uKG5hbWUpIHtcbiAgICAgIHByb3RvW25hbWVdID0gdGhpc1tuYW1lXTtcbiAgICB9LCB0aGlzKTtcbiAgICByZXR1cm4gcHJvdG87XG4gIH07XG5cbiAgLy8gRXhwb3J0IEV2ZW50cyBhcyBCYWNrYm9uZUV2ZW50cyBkZXBlbmRpbmcgb24gY3VycmVudCBjb250ZXh0XG4gIGlmICh0eXBlb2YgZGVmaW5lID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICBkZWZpbmUoZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gRXZlbnRzO1xuICAgIH0pO1xuICB9IGVsc2UgaWYgKHR5cGVvZiBleHBvcnRzICE9PSAndW5kZWZpbmVkJykge1xuICAgIGlmICh0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJyAmJiBtb2R1bGUuZXhwb3J0cykge1xuICAgICAgZXhwb3J0cyA9IG1vZHVsZS5leHBvcnRzID0gRXZlbnRzO1xuICAgIH1cbiAgICBleHBvcnRzLkJhY2tib25lRXZlbnRzID0gRXZlbnRzO1xuICB9IGVsc2Uge1xuICAgIHJvb3QuQmFja2JvbmVFdmVudHMgPSBFdmVudHM7XG4gIH1cbn0pKHRoaXMpO1xuIiwibW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuL2JhY2tib25lLWV2ZW50cy1zdGFuZGFsb25lJyk7XG4iLCIvLyBHZW5lcmF0ZWQgYnkgQ29mZmVlU2NyaXB0IDEuOC4wXG52YXIgR2VuZXJpY1JlYWRlciwgeGhyO1xuXG54aHIgPSByZXF1aXJlKCduZXRzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gR2VuZXJpY1JlYWRlciA9IChmdW5jdGlvbigpIHtcbiAgZnVuY3Rpb24gR2VuZXJpY1JlYWRlcigpIHt9XG5cbiAgR2VuZXJpY1JlYWRlci5yZWFkID0gZnVuY3Rpb24odXJsLCBjYWxsYmFjaykge1xuICAgIHZhciBvbnJldDtcbiAgICBvbnJldCA9IChmdW5jdGlvbihfdGhpcykge1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKGVyciwgcmVzcG9uc2UsIHRleHQpIHtcbiAgICAgICAgcmV0dXJuIF90aGlzLl9vblJldHJpZXZhbCh0ZXh0LCBjYWxsYmFjayk7XG4gICAgICB9O1xuICAgIH0pKHRoaXMpO1xuICAgIHJldHVybiB4aHIodXJsLCBvbnJldCk7XG4gIH07XG5cbiAgR2VuZXJpY1JlYWRlci5fb25SZXRyaWV2YWwgPSBmdW5jdGlvbih0ZXh0LCBjYWxsYmFjaykge1xuICAgIHZhciByVGV4dDtcbiAgICByVGV4dCA9IHRoaXMucGFyc2UodGV4dCk7XG4gICAgcmV0dXJuIGNhbGxiYWNrKHJUZXh0KTtcbiAgfTtcblxuICByZXR1cm4gR2VuZXJpY1JlYWRlcjtcblxufSkoKTtcbiIsIi8vIEdlbmVyYXRlZCBieSBDb2ZmZWVTY3JpcHQgMS44LjBcbnZhciBGYXN0YSwgR2VuZXJpY1JlYWRlciwgU2VxLCBTdHIsXG4gIF9faGFzUHJvcCA9IHt9Lmhhc093blByb3BlcnR5LFxuICBfX2V4dGVuZHMgPSBmdW5jdGlvbihjaGlsZCwgcGFyZW50KSB7IGZvciAodmFyIGtleSBpbiBwYXJlbnQpIHsgaWYgKF9faGFzUHJvcC5jYWxsKHBhcmVudCwga2V5KSkgY2hpbGRba2V5XSA9IHBhcmVudFtrZXldOyB9IGZ1bmN0aW9uIGN0b3IoKSB7IHRoaXMuY29uc3RydWN0b3IgPSBjaGlsZDsgfSBjdG9yLnByb3RvdHlwZSA9IHBhcmVudC5wcm90b3R5cGU7IGNoaWxkLnByb3RvdHlwZSA9IG5ldyBjdG9yKCk7IGNoaWxkLl9fc3VwZXJfXyA9IHBhcmVudC5wcm90b3R5cGU7IHJldHVybiBjaGlsZDsgfTtcblxuU3RyID0gcmVxdWlyZShcIi4vc3RyaW5nc1wiKTtcblxuR2VuZXJpY1JlYWRlciA9IHJlcXVpcmUoXCIuL2dlbmVyaWNfcmVhZGVyXCIpO1xuXG5TZXEgPSByZXF1aXJlKFwiYmlvanMtbW9kZWxcIikuc2VxO1xuXG5tb2R1bGUuZXhwb3J0cyA9IEZhc3RhID0gKGZ1bmN0aW9uKF9zdXBlcikge1xuICBfX2V4dGVuZHMoRmFzdGEsIF9zdXBlcik7XG5cbiAgZnVuY3Rpb24gRmFzdGEoKSB7XG4gICAgcmV0dXJuIEZhc3RhLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICB9XG5cbiAgRmFzdGEucGFyc2UgPSBmdW5jdGlvbih0ZXh0KSB7XG4gICAgdmFyIGN1cnJlbnRTZXEsIGRhdGFiYXNlLCBkYXRhYmFzZUlELCBpZGVudGlmaWVycywgaywgbGFiZWwsIGxpbmUsIHNlcXMsIF9pLCBfbGVuO1xuICAgIHNlcXMgPSBbXTtcbiAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHRleHQpICE9PSAnW29iamVjdCBBcnJheV0nKSB7XG4gICAgICB0ZXh0ID0gdGV4dC5zcGxpdChcIlxcblwiKTtcbiAgICB9XG4gICAgZm9yIChfaSA9IDAsIF9sZW4gPSB0ZXh0Lmxlbmd0aDsgX2kgPCBfbGVuOyBfaSsrKSB7XG4gICAgICBsaW5lID0gdGV4dFtfaV07XG4gICAgICBpZiAobGluZVswXSA9PT0gXCI+XCIgfHwgbGluZVswXSA9PT0gXCI7XCIpIHtcbiAgICAgICAgbGFiZWwgPSBsaW5lLnNsaWNlKDEpO1xuICAgICAgICBjdXJyZW50U2VxID0gbmV3IFNlcShcIlwiLCBsYWJlbCwgc2Vxcy5sZW5ndGgpO1xuICAgICAgICBzZXFzLnB1c2goY3VycmVudFNlcSk7XG4gICAgICAgIGlmIChTdHIuY29udGFpbnMoXCJ8XCIsIGxpbmUpKSB7XG4gICAgICAgICAgaWRlbnRpZmllcnMgPSBsYWJlbC5zcGxpdChcInxcIik7XG4gICAgICAgICAgayA9IDE7XG4gICAgICAgICAgd2hpbGUgKGsgPCBpZGVudGlmaWVycy5sZW5ndGgpIHtcbiAgICAgICAgICAgIGRhdGFiYXNlID0gaWRlbnRpZmllcnNba107XG4gICAgICAgICAgICBkYXRhYmFzZUlEID0gaWRlbnRpZmllcnNbayArIDFdO1xuICAgICAgICAgICAgY3VycmVudFNlcS5tZXRhW2RhdGFiYXNlXSA9IGRhdGFiYXNlSUQ7XG4gICAgICAgICAgICBrICs9IDI7XG4gICAgICAgICAgfVxuICAgICAgICAgIGN1cnJlbnRTZXEubmFtZSA9IGlkZW50aWZpZXJzW2lkZW50aWZpZXJzLmxlbmd0aCAtIDFdO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjdXJyZW50U2VxLnNlcSArPSBsaW5lO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gc2VxcztcbiAgfTtcblxuICByZXR1cm4gRmFzdGE7XG5cbn0pKEdlbmVyaWNSZWFkZXIpO1xuIiwiLy8gR2VuZXJhdGVkIGJ5IENvZmZlZVNjcmlwdCAxLjguMFxudmFyIHN0cmluZ3M7XG5cbnN0cmluZ3MgPSB7XG4gIGNvbnRhaW5zOiBmdW5jdGlvbih0ZXh0LCBzZWFyY2gpIHtcbiAgICByZXR1cm4gJycuaW5kZXhPZi5jYWxsKHRleHQsIHNlYXJjaCwgMCkgIT09IC0xO1xuICB9XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IHN0cmluZ3M7XG4iLCIvLyBHZW5lcmF0ZWQgYnkgQ29mZmVlU2NyaXB0IDEuOC4wXG52YXIgVXRpbHM7XG5cblV0aWxzID0ge307XG5cblV0aWxzLnNwbGl0TkNoYXJzID0gZnVuY3Rpb24odHh0LCBudW0pIHtcbiAgdmFyIGksIHJlc3VsdCwgX2ksIF9yZWY7XG4gIHJlc3VsdCA9IFtdO1xuICBmb3IgKGkgPSBfaSA9IDAsIF9yZWYgPSB0eHQubGVuZ3RoIC0gMTsgbnVtID4gMCA/IF9pIDw9IF9yZWYgOiBfaSA+PSBfcmVmOyBpID0gX2kgKz0gbnVtKSB7XG4gICAgcmVzdWx0LnB1c2godHh0LnN1YnN0cihpLCBudW0pKTtcbiAgfVxuICByZXR1cm4gcmVzdWx0O1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBVdGlscztcbiIsIi8vIEdlbmVyYXRlZCBieSBDb2ZmZWVTY3JpcHQgMS44LjBcbnZhciBGYXN0YUV4cG9ydGVyLCBVdGlscztcblxuVXRpbHMgPSByZXF1aXJlKFwiLi91dGlsc1wiKTtcblxubW9kdWxlLmV4cG9ydHMgPSBGYXN0YUV4cG9ydGVyID0gKGZ1bmN0aW9uKCkge1xuICBmdW5jdGlvbiBGYXN0YUV4cG9ydGVyKCkge31cblxuICBGYXN0YUV4cG9ydGVyW1wiZXhwb3J0XCJdID0gZnVuY3Rpb24oc2VxcywgYWNjZXNzKSB7XG4gICAgdmFyIHNlcSwgdGV4dCwgX2ksIF9sZW47XG4gICAgdGV4dCA9IFwiXCI7XG4gICAgZm9yIChfaSA9IDAsIF9sZW4gPSBzZXFzLmxlbmd0aDsgX2kgPCBfbGVuOyBfaSsrKSB7XG4gICAgICBzZXEgPSBzZXFzW19pXTtcbiAgICAgIGlmIChhY2Nlc3MgIT0gbnVsbCkge1xuICAgICAgICBzZXEgPSBhY2Nlc3Moc2VxKTtcbiAgICAgIH1cbiAgICAgIHRleHQgKz0gXCI+XCIgKyBzZXEubmFtZSArIFwiXFxuXCI7XG4gICAgICB0ZXh0ICs9IChVdGlscy5zcGxpdE5DaGFycyhzZXEuc2VxLCA4MCkpLmpvaW4oXCJcXG5cIik7XG4gICAgICB0ZXh0ICs9IFwiXFxuXCI7XG4gICAgfVxuICAgIHJldHVybiB0ZXh0O1xuICB9O1xuXG4gIHJldHVybiBGYXN0YUV4cG9ydGVyO1xuXG59KSgpO1xuIiwibW9kdWxlLmV4cG9ydHMuc2VxID0gcmVxdWlyZShcIi4vc2VxXCIpO1xuIiwibW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihzZXEsIG5hbWUsIGlkKSB7XG4gICAgdGhpcy5zZXEgPSBzZXE7XG4gICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgICB0aGlzLmlkID0gaWQ7XG4gICAgdGhpcy5tZXRhID0ge307XG59O1xuIiwidmFyIHJlcSA9IHJlcXVpcmUoJ3JlcXVlc3QnKVxuXG5tb2R1bGUuZXhwb3J0cyA9IE5ldHNcblxuZnVuY3Rpb24gTmV0cyh1cmksIG9wdHMsIGNiKSB7XG4gIHJlcSh1cmksIG9wdHMsIGNiKVxufSIsInZhciB3aW5kb3cgPSByZXF1aXJlKFwiZ2xvYmFsL3dpbmRvd1wiKVxudmFyIG9uY2UgPSByZXF1aXJlKFwib25jZVwiKVxudmFyIHBhcnNlSGVhZGVycyA9IHJlcXVpcmUoJ3BhcnNlLWhlYWRlcnMnKVxuXG52YXIgbWVzc2FnZXMgPSB7XG4gICAgXCIwXCI6IFwiSW50ZXJuYWwgWE1MSHR0cFJlcXVlc3QgRXJyb3JcIixcbiAgICBcIjRcIjogXCI0eHggQ2xpZW50IEVycm9yXCIsXG4gICAgXCI1XCI6IFwiNXh4IFNlcnZlciBFcnJvclwiXG59XG5cbnZhciBYSFIgPSB3aW5kb3cuWE1MSHR0cFJlcXVlc3QgfHwgbm9vcFxudmFyIFhEUiA9IFwid2l0aENyZWRlbnRpYWxzXCIgaW4gKG5ldyBYSFIoKSkgPyBYSFIgOiB3aW5kb3cuWERvbWFpblJlcXVlc3RcblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVYSFJcblxuZnVuY3Rpb24gY3JlYXRlWEhSKG9wdGlvbnMsIGNhbGxiYWNrKSB7XG4gICAgaWYgKHR5cGVvZiBvcHRpb25zID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgIG9wdGlvbnMgPSB7IHVyaTogb3B0aW9ucyB9XG4gICAgfVxuXG4gICAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge31cbiAgICBjYWxsYmFjayA9IG9uY2UoY2FsbGJhY2spXG5cbiAgICB2YXIgeGhyID0gb3B0aW9ucy54aHIgfHwgbnVsbFxuXG4gICAgaWYgKCF4aHIpIHtcbiAgICAgICAgaWYgKG9wdGlvbnMuY29ycyB8fCBvcHRpb25zLnVzZVhEUikge1xuICAgICAgICAgICAgeGhyID0gbmV3IFhEUigpXG4gICAgICAgIH1lbHNle1xuICAgICAgICAgICAgeGhyID0gbmV3IFhIUigpXG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgdXJpID0geGhyLnVybCA9IG9wdGlvbnMudXJpIHx8IG9wdGlvbnMudXJsXG4gICAgdmFyIG1ldGhvZCA9IHhoci5tZXRob2QgPSBvcHRpb25zLm1ldGhvZCB8fCBcIkdFVFwiXG4gICAgdmFyIGJvZHkgPSBvcHRpb25zLmJvZHkgfHwgb3B0aW9ucy5kYXRhXG4gICAgdmFyIGhlYWRlcnMgPSB4aHIuaGVhZGVycyA9IG9wdGlvbnMuaGVhZGVycyB8fCB7fVxuICAgIHZhciBzeW5jID0gISFvcHRpb25zLnN5bmNcbiAgICB2YXIgaXNKc29uID0gZmFsc2VcbiAgICB2YXIga2V5XG4gICAgdmFyIGxvYWQgPSBvcHRpb25zLnJlc3BvbnNlID8gbG9hZFJlc3BvbnNlIDogbG9hZFhoclxuXG4gICAgaWYgKFwianNvblwiIGluIG9wdGlvbnMpIHtcbiAgICAgICAgaXNKc29uID0gdHJ1ZVxuICAgICAgICBoZWFkZXJzW1wiQWNjZXB0XCJdID0gXCJhcHBsaWNhdGlvbi9qc29uXCJcbiAgICAgICAgaWYgKG1ldGhvZCAhPT0gXCJHRVRcIiAmJiBtZXRob2QgIT09IFwiSEVBRFwiKSB7XG4gICAgICAgICAgICBoZWFkZXJzW1wiQ29udGVudC1UeXBlXCJdID0gXCJhcHBsaWNhdGlvbi9qc29uXCJcbiAgICAgICAgICAgIGJvZHkgPSBKU09OLnN0cmluZ2lmeShvcHRpb25zLmpzb24pXG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB4aHIub25yZWFkeXN0YXRlY2hhbmdlID0gcmVhZHlzdGF0ZWNoYW5nZVxuICAgIHhoci5vbmxvYWQgPSBsb2FkXG4gICAgeGhyLm9uZXJyb3IgPSBlcnJvclxuICAgIC8vIElFOSBtdXN0IGhhdmUgb25wcm9ncmVzcyBiZSBzZXQgdG8gYSB1bmlxdWUgZnVuY3Rpb24uXG4gICAgeGhyLm9ucHJvZ3Jlc3MgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIElFIG11c3QgZGllXG4gICAgfVxuICAgIC8vIGhhdGUgSUVcbiAgICB4aHIub250aW1lb3V0ID0gbm9vcFxuICAgIHhoci5vcGVuKG1ldGhvZCwgdXJpLCAhc3luYylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vYmFja3dhcmQgY29tcGF0aWJpbGl0eVxuICAgIGlmIChvcHRpb25zLndpdGhDcmVkZW50aWFscyB8fCAob3B0aW9ucy5jb3JzICYmIG9wdGlvbnMud2l0aENyZWRlbnRpYWxzICE9PSBmYWxzZSkpIHtcbiAgICAgICAgeGhyLndpdGhDcmVkZW50aWFscyA9IHRydWVcbiAgICB9XG5cbiAgICAvLyBDYW5ub3Qgc2V0IHRpbWVvdXQgd2l0aCBzeW5jIHJlcXVlc3RcbiAgICBpZiAoIXN5bmMpIHtcbiAgICAgICAgeGhyLnRpbWVvdXQgPSBcInRpbWVvdXRcIiBpbiBvcHRpb25zID8gb3B0aW9ucy50aW1lb3V0IDogNTAwMFxuICAgIH1cblxuICAgIGlmICh4aHIuc2V0UmVxdWVzdEhlYWRlcikge1xuICAgICAgICBmb3Ioa2V5IGluIGhlYWRlcnMpe1xuICAgICAgICAgICAgaWYoaGVhZGVycy5oYXNPd25Qcm9wZXJ0eShrZXkpKXtcbiAgICAgICAgICAgICAgICB4aHIuc2V0UmVxdWVzdEhlYWRlcihrZXksIGhlYWRlcnNba2V5XSlcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0gZWxzZSBpZiAob3B0aW9ucy5oZWFkZXJzKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIkhlYWRlcnMgY2Fubm90IGJlIHNldCBvbiBhbiBYRG9tYWluUmVxdWVzdCBvYmplY3RcIilcbiAgICB9XG5cbiAgICBpZiAoXCJyZXNwb25zZVR5cGVcIiBpbiBvcHRpb25zKSB7XG4gICAgICAgIHhoci5yZXNwb25zZVR5cGUgPSBvcHRpb25zLnJlc3BvbnNlVHlwZVxuICAgIH1cbiAgICBcbiAgICBpZiAoXCJiZWZvcmVTZW5kXCIgaW4gb3B0aW9ucyAmJiBcbiAgICAgICAgdHlwZW9mIG9wdGlvbnMuYmVmb3JlU2VuZCA9PT0gXCJmdW5jdGlvblwiXG4gICAgKSB7XG4gICAgICAgIG9wdGlvbnMuYmVmb3JlU2VuZCh4aHIpXG4gICAgfVxuXG4gICAgeGhyLnNlbmQoYm9keSlcblxuICAgIHJldHVybiB4aHJcblxuICAgIGZ1bmN0aW9uIHJlYWR5c3RhdGVjaGFuZ2UoKSB7XG4gICAgICAgIGlmICh4aHIucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgbG9hZCgpXG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXRCb2R5KCkge1xuICAgICAgICAvLyBDaHJvbWUgd2l0aCByZXF1ZXN0VHlwZT1ibG9iIHRocm93cyBlcnJvcnMgYXJyb3VuZCB3aGVuIGV2ZW4gdGVzdGluZyBhY2Nlc3MgdG8gcmVzcG9uc2VUZXh0XG4gICAgICAgIHZhciBib2R5ID0gbnVsbFxuXG4gICAgICAgIGlmICh4aHIucmVzcG9uc2UpIHtcbiAgICAgICAgICAgIGJvZHkgPSB4aHIucmVzcG9uc2VcbiAgICAgICAgfSBlbHNlIGlmICh4aHIucmVzcG9uc2VUeXBlID09PSAndGV4dCcgfHwgIXhoci5yZXNwb25zZVR5cGUpIHtcbiAgICAgICAgICAgIGJvZHkgPSB4aHIucmVzcG9uc2VUZXh0IHx8IHhoci5yZXNwb25zZVhNTFxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGlzSnNvbikge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBib2R5ID0gSlNPTi5wYXJzZShib2R5KVxuICAgICAgICAgICAgfSBjYXRjaCAoZSkge31cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBib2R5XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0U3RhdHVzQ29kZSgpIHtcbiAgICAgICAgcmV0dXJuIHhoci5zdGF0dXMgPT09IDEyMjMgPyAyMDQgOiB4aHIuc3RhdHVzXG4gICAgfVxuXG4gICAgLy8gaWYgd2UncmUgZ2V0dGluZyBhIG5vbmUtb2sgc3RhdHVzQ29kZSwgYnVpbGQgJiByZXR1cm4gYW4gZXJyb3JcbiAgICBmdW5jdGlvbiBlcnJvckZyb21TdGF0dXNDb2RlKHN0YXR1cywgYm9keSkge1xuICAgICAgICB2YXIgZXJyb3IgPSBudWxsXG4gICAgICAgIGlmIChzdGF0dXMgPT09IDAgfHwgKHN0YXR1cyA+PSA0MDAgJiYgc3RhdHVzIDwgNjAwKSkge1xuICAgICAgICAgICAgdmFyIG1lc3NhZ2UgPSAodHlwZW9mIGJvZHkgPT09IFwic3RyaW5nXCIgPyBib2R5IDogZmFsc2UpIHx8XG4gICAgICAgICAgICAgICAgbWVzc2FnZXNbU3RyaW5nKHN0YXR1cykuY2hhckF0KDApXVxuICAgICAgICAgICAgZXJyb3IgPSBuZXcgRXJyb3IobWVzc2FnZSlcbiAgICAgICAgICAgIGVycm9yLnN0YXR1c0NvZGUgPSBzdGF0dXNcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBlcnJvclxuICAgIH1cblxuICAgIC8vIHdpbGwgbG9hZCB0aGUgZGF0YSAmIHByb2Nlc3MgdGhlIHJlc3BvbnNlIGluIGEgc3BlY2lhbCByZXNwb25zZSBvYmplY3RcbiAgICBmdW5jdGlvbiBsb2FkUmVzcG9uc2UoKSB7XG4gICAgICAgIHZhciBzdGF0dXMgPSBnZXRTdGF0dXNDb2RlKClcbiAgICAgICAgdmFyIGJvZHkgPSBnZXRCb2R5KClcbiAgICAgICAgdmFyIGVycm9yID0gZXJyb3JGcm9tU3RhdHVzQ29kZShzdGF0dXMsIGJvZHkpXG4gICAgICAgIHZhciByZXNwb25zZSA9IHtcbiAgICAgICAgICAgIGJvZHk6IGJvZHksXG4gICAgICAgICAgICBzdGF0dXNDb2RlOiBzdGF0dXMsXG4gICAgICAgICAgICBzdGF0dXNUZXh0OiB4aHIuc3RhdHVzVGV4dCxcbiAgICAgICAgICAgIHJhdzogeGhyXG4gICAgICAgIH1cbiAgICAgICAgaWYoeGhyLmdldEFsbFJlc3BvbnNlSGVhZGVycyl7IC8vcmVtZW1iZXIgeGhyIGNhbiBpbiBmYWN0IGJlIFhEUiBmb3IgQ09SUyBpbiBJRVxuICAgICAgICAgICAgcmVzcG9uc2UuaGVhZGVycyA9IHBhcnNlSGVhZGVycyh4aHIuZ2V0QWxsUmVzcG9uc2VIZWFkZXJzKCkpXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXNwb25zZS5oZWFkZXJzID0ge31cbiAgICAgICAgfVxuXG4gICAgICAgIGNhbGxiYWNrKGVycm9yLCByZXNwb25zZSwgcmVzcG9uc2UuYm9keSlcbiAgICB9XG5cbiAgICAvLyB3aWxsIGxvYWQgdGhlIGRhdGEgYW5kIGFkZCBzb21lIHJlc3BvbnNlIHByb3BlcnRpZXMgdG8gdGhlIHNvdXJjZSB4aHJcbiAgICAvLyBhbmQgdGhlbiByZXNwb25kIHdpdGggdGhhdFxuICAgIGZ1bmN0aW9uIGxvYWRYaHIoKSB7XG4gICAgICAgIHZhciBzdGF0dXMgPSBnZXRTdGF0dXNDb2RlKClcbiAgICAgICAgdmFyIGVycm9yID0gZXJyb3JGcm9tU3RhdHVzQ29kZShzdGF0dXMpXG5cbiAgICAgICAgeGhyLnN0YXR1cyA9IHhoci5zdGF0dXNDb2RlID0gc3RhdHVzXG4gICAgICAgIHhoci5ib2R5ID0gZ2V0Qm9keSgpXG4gICAgICAgIHhoci5oZWFkZXJzID0gcGFyc2VIZWFkZXJzKHhoci5nZXRBbGxSZXNwb25zZUhlYWRlcnMoKSlcblxuICAgICAgICBjYWxsYmFjayhlcnJvciwgeGhyLCB4aHIuYm9keSlcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBlcnJvcihldnQpIHtcbiAgICAgICAgY2FsbGJhY2soZXZ0LCB4aHIpXG4gICAgfVxufVxuXG5cbmZ1bmN0aW9uIG5vb3AoKSB7fVxuIiwiaWYgKHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICBtb2R1bGUuZXhwb3J0cyA9IHdpbmRvdztcbn0gZWxzZSBpZiAodHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIikge1xuICAgIG1vZHVsZS5leHBvcnRzID0gZ2xvYmFsO1xufSBlbHNlIGlmICh0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIil7XG4gICAgbW9kdWxlLmV4cG9ydHMgPSBzZWxmO1xufSBlbHNlIHtcbiAgICBtb2R1bGUuZXhwb3J0cyA9IHt9O1xufVxuIiwibW9kdWxlLmV4cG9ydHMgPSBvbmNlXG5cbm9uY2UucHJvdG8gPSBvbmNlKGZ1bmN0aW9uICgpIHtcbiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEZ1bmN0aW9uLnByb3RvdHlwZSwgJ29uY2UnLCB7XG4gICAgdmFsdWU6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiBvbmNlKHRoaXMpXG4gICAgfSxcbiAgICBjb25maWd1cmFibGU6IHRydWVcbiAgfSlcbn0pXG5cbmZ1bmN0aW9uIG9uY2UgKGZuKSB7XG4gIHZhciBjYWxsZWQgPSBmYWxzZVxuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIGlmIChjYWxsZWQpIHJldHVyblxuICAgIGNhbGxlZCA9IHRydWVcbiAgICByZXR1cm4gZm4uYXBwbHkodGhpcywgYXJndW1lbnRzKVxuICB9XG59XG4iLCJ2YXIgaXNGdW5jdGlvbiA9IHJlcXVpcmUoJ2lzLWZ1bmN0aW9uJylcblxubW9kdWxlLmV4cG9ydHMgPSBmb3JFYWNoXG5cbnZhciB0b1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmdcbnZhciBoYXNPd25Qcm9wZXJ0eSA9IE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHlcblxuZnVuY3Rpb24gZm9yRWFjaChsaXN0LCBpdGVyYXRvciwgY29udGV4dCkge1xuICAgIGlmICghaXNGdW5jdGlvbihpdGVyYXRvcikpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignaXRlcmF0b3IgbXVzdCBiZSBhIGZ1bmN0aW9uJylcbiAgICB9XG5cbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA8IDMpIHtcbiAgICAgICAgY29udGV4dCA9IHRoaXNcbiAgICB9XG4gICAgXG4gICAgaWYgKHRvU3RyaW5nLmNhbGwobGlzdCkgPT09ICdbb2JqZWN0IEFycmF5XScpXG4gICAgICAgIGZvckVhY2hBcnJheShsaXN0LCBpdGVyYXRvciwgY29udGV4dClcbiAgICBlbHNlIGlmICh0eXBlb2YgbGlzdCA9PT0gJ3N0cmluZycpXG4gICAgICAgIGZvckVhY2hTdHJpbmcobGlzdCwgaXRlcmF0b3IsIGNvbnRleHQpXG4gICAgZWxzZVxuICAgICAgICBmb3JFYWNoT2JqZWN0KGxpc3QsIGl0ZXJhdG9yLCBjb250ZXh0KVxufVxuXG5mdW5jdGlvbiBmb3JFYWNoQXJyYXkoYXJyYXksIGl0ZXJhdG9yLCBjb250ZXh0KSB7XG4gICAgZm9yICh2YXIgaSA9IDAsIGxlbiA9IGFycmF5Lmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgIGlmIChoYXNPd25Qcm9wZXJ0eS5jYWxsKGFycmF5LCBpKSkge1xuICAgICAgICAgICAgaXRlcmF0b3IuY2FsbChjb250ZXh0LCBhcnJheVtpXSwgaSwgYXJyYXkpXG4gICAgICAgIH1cbiAgICB9XG59XG5cbmZ1bmN0aW9uIGZvckVhY2hTdHJpbmcoc3RyaW5nLCBpdGVyYXRvciwgY29udGV4dCkge1xuICAgIGZvciAodmFyIGkgPSAwLCBsZW4gPSBzdHJpbmcubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgLy8gbm8gc3VjaCB0aGluZyBhcyBhIHNwYXJzZSBzdHJpbmcuXG4gICAgICAgIGl0ZXJhdG9yLmNhbGwoY29udGV4dCwgc3RyaW5nLmNoYXJBdChpKSwgaSwgc3RyaW5nKVxuICAgIH1cbn1cblxuZnVuY3Rpb24gZm9yRWFjaE9iamVjdChvYmplY3QsIGl0ZXJhdG9yLCBjb250ZXh0KSB7XG4gICAgZm9yICh2YXIgayBpbiBvYmplY3QpIHtcbiAgICAgICAgaWYgKGhhc093blByb3BlcnR5LmNhbGwob2JqZWN0LCBrKSkge1xuICAgICAgICAgICAgaXRlcmF0b3IuY2FsbChjb250ZXh0LCBvYmplY3Rba10sIGssIG9iamVjdClcbiAgICAgICAgfVxuICAgIH1cbn1cbiIsIm1vZHVsZS5leHBvcnRzID0gaXNGdW5jdGlvblxuXG52YXIgdG9TdHJpbmcgPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nXG5cbmZ1bmN0aW9uIGlzRnVuY3Rpb24gKGZuKSB7XG4gIHZhciBzdHJpbmcgPSB0b1N0cmluZy5jYWxsKGZuKVxuICByZXR1cm4gc3RyaW5nID09PSAnW29iamVjdCBGdW5jdGlvbl0nIHx8XG4gICAgKHR5cGVvZiBmbiA9PT0gJ2Z1bmN0aW9uJyAmJiBzdHJpbmcgIT09ICdbb2JqZWN0IFJlZ0V4cF0nKSB8fFxuICAgICh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJyAmJlxuICAgICAvLyBJRTggYW5kIGJlbG93XG4gICAgIChmbiA9PT0gd2luZG93LnNldFRpbWVvdXQgfHxcbiAgICAgIGZuID09PSB3aW5kb3cuYWxlcnQgfHxcbiAgICAgIGZuID09PSB3aW5kb3cuY29uZmlybSB8fFxuICAgICAgZm4gPT09IHdpbmRvdy5wcm9tcHQpKVxufTtcbiIsIlxuZXhwb3J0cyA9IG1vZHVsZS5leHBvcnRzID0gdHJpbTtcblxuZnVuY3Rpb24gdHJpbShzdHIpe1xuICByZXR1cm4gc3RyLnJlcGxhY2UoL15cXHMqfFxccyokL2csICcnKTtcbn1cblxuZXhwb3J0cy5sZWZ0ID0gZnVuY3Rpb24oc3RyKXtcbiAgcmV0dXJuIHN0ci5yZXBsYWNlKC9eXFxzKi8sICcnKTtcbn07XG5cbmV4cG9ydHMucmlnaHQgPSBmdW5jdGlvbihzdHIpe1xuICByZXR1cm4gc3RyLnJlcGxhY2UoL1xccyokLywgJycpO1xufTtcbiIsInZhciB0cmltID0gcmVxdWlyZSgndHJpbScpXG4gICwgZm9yRWFjaCA9IHJlcXVpcmUoJ2Zvci1lYWNoJylcbiAgLCBpc0FycmF5ID0gZnVuY3Rpb24oYXJnKSB7XG4gICAgICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGFyZykgPT09ICdbb2JqZWN0IEFycmF5XSc7XG4gICAgfVxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChoZWFkZXJzKSB7XG4gIGlmICghaGVhZGVycylcbiAgICByZXR1cm4ge31cblxuICB2YXIgcmVzdWx0ID0ge31cblxuICBmb3JFYWNoKFxuICAgICAgdHJpbShoZWFkZXJzKS5zcGxpdCgnXFxuJylcbiAgICAsIGZ1bmN0aW9uIChyb3cpIHtcbiAgICAgICAgdmFyIGluZGV4ID0gcm93LmluZGV4T2YoJzonKVxuICAgICAgICAgICwga2V5ID0gdHJpbShyb3cuc2xpY2UoMCwgaW5kZXgpKS50b0xvd2VyQ2FzZSgpXG4gICAgICAgICAgLCB2YWx1ZSA9IHRyaW0ocm93LnNsaWNlKGluZGV4ICsgMSkpXG5cbiAgICAgICAgaWYgKHR5cGVvZihyZXN1bHRba2V5XSkgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgcmVzdWx0W2tleV0gPSB2YWx1ZVxuICAgICAgICB9IGVsc2UgaWYgKGlzQXJyYXkocmVzdWx0W2tleV0pKSB7XG4gICAgICAgICAgcmVzdWx0W2tleV0ucHVzaCh2YWx1ZSlcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXN1bHRba2V5XSA9IFsgcmVzdWx0W2tleV0sIHZhbHVlIF1cbiAgICAgICAgfVxuICAgICAgfVxuICApXG5cbiAgcmV0dXJuIHJlc3VsdFxufSIsIm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi9qcXVlcnkuYnJvd3NlcicpO1xuIiwiLyohXG4gKiBqUXVlcnkgQnJvd3NlciBQbHVnaW4gdjAuMC42XG4gKiBodHRwczovL2dpdGh1Yi5jb20vZ2FiY2ViL2pxdWVyeS1icm93c2VyLXBsdWdpblxuICpcbiAqIE9yaWdpbmFsIGpxdWVyeS1icm93c2VyIGNvZGUgQ29weXJpZ2h0IDIwMDUsIDIwMTMgalF1ZXJ5IEZvdW5kYXRpb24sIEluYy4gYW5kIG90aGVyIGNvbnRyaWJ1dG9yc1xuICogaHR0cDovL2pxdWVyeS5vcmcvbGljZW5zZVxuICpcbiAqIE1vZGlmaWNhdGlvbnMgQ29weXJpZ2h0IDIwMTMgR2FicmllbCBDZWJyaWFuXG4gKiBodHRwczovL2dpdGh1Yi5jb20vZ2FiY2ViXG4gKlxuICogUmVsZWFzZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlXG4gKlxuICogRGF0ZTogMjAxMy0wNy0yOVQxNzoyMzoyNy0wNzowMFxuICovXG5cblxudmFyIG1hdGNoZWQsIGJyb3dzZXI7XG5cbnZhciB1YU1hdGNoID0gZnVuY3Rpb24oIHVhICkge1xuICB1YSA9IHVhLnRvTG93ZXJDYXNlKCk7XG5cbiAgdmFyIG1hdGNoID0gLyhvcHIpW1xcL10oW1xcdy5dKykvLmV4ZWMoIHVhICkgfHxcbiAgICAvKGNocm9tZSlbIFxcL10oW1xcdy5dKykvLmV4ZWMoIHVhICkgfHxcbiAgICAvKHZlcnNpb24pWyBcXC9dKFtcXHcuXSspLiooc2FmYXJpKVsgXFwvXShbXFx3Ll0rKS8uZXhlYyggdWEgKSB8fFxuICAgIC8od2Via2l0KVsgXFwvXShbXFx3Ll0rKS8uZXhlYyggdWEgKSB8fFxuICAgIC8ob3BlcmEpKD86Lip2ZXJzaW9ufClbIFxcL10oW1xcdy5dKykvLmV4ZWMoIHVhICkgfHxcbiAgICAvKG1zaWUpIChbXFx3Ll0rKS8uZXhlYyggdWEgKSB8fFxuICAgIHVhLmluZGV4T2YoXCJ0cmlkZW50XCIpID49IDAgJiYgLyhydikoPzo6fCApKFtcXHcuXSspLy5leGVjKCB1YSApIHx8XG4gICAgdWEuaW5kZXhPZihcImNvbXBhdGlibGVcIikgPCAwICYmIC8obW96aWxsYSkoPzouKj8gcnY6KFtcXHcuXSspfCkvLmV4ZWMoIHVhICkgfHxcbiAgICBbXTtcblxuICB2YXIgcGxhdGZvcm1fbWF0Y2ggPSAvKGlwYWQpLy5leGVjKCB1YSApIHx8XG4gICAgLyhpcGhvbmUpLy5leGVjKCB1YSApIHx8XG4gICAgLyhhbmRyb2lkKS8uZXhlYyggdWEgKSB8fFxuICAgIC8od2luZG93cyBwaG9uZSkvLmV4ZWMoIHVhICkgfHxcbiAgICAvKHdpbikvLmV4ZWMoIHVhICkgfHxcbiAgICAvKG1hYykvLmV4ZWMoIHVhICkgfHxcbiAgICAvKGxpbnV4KS8uZXhlYyggdWEgKSB8fFxuICAgIC8oY3JvcykvaS5leGVjKCB1YSApIHx8XG4gICAgW107XG5cbiAgcmV0dXJuIHtcbiAgICBicm93c2VyOiBtYXRjaFsgMyBdIHx8IG1hdGNoWyAxIF0gfHwgXCJcIixcbiAgICB2ZXJzaW9uOiBtYXRjaFsgMiBdIHx8IFwiMFwiLFxuICAgIHBsYXRmb3JtOiBwbGF0Zm9ybV9tYXRjaFsgMCBdIHx8IFwiXCJcbiAgfTtcbn07XG5cbm1hdGNoZWQgPSB1YU1hdGNoKCB3aW5kb3cubmF2aWdhdG9yLnVzZXJBZ2VudCApO1xuYnJvd3NlciA9IHt9O1xuYnJvd3Nlci51YU1hdGNoID0gdWFNYXRjaDtcblxuaWYgKCBtYXRjaGVkLmJyb3dzZXIgKSB7XG4gIGJyb3dzZXJbIG1hdGNoZWQuYnJvd3NlciBdID0gdHJ1ZTtcbiAgYnJvd3Nlci52ZXJzaW9uID0gbWF0Y2hlZC52ZXJzaW9uO1xuICBicm93c2VyLnZlcnNpb25OdW1iZXIgPSBwYXJzZUludChtYXRjaGVkLnZlcnNpb24pO1xufVxuXG5pZiAoIG1hdGNoZWQucGxhdGZvcm0gKSB7XG4gIGJyb3dzZXJbIG1hdGNoZWQucGxhdGZvcm0gXSA9IHRydWU7XG59XG5cbi8vIFRoZXNlIGFyZSBhbGwgY29uc2lkZXJlZCBtb2JpbGUgcGxhdGZvcm1zLCBtZWFuaW5nIHRoZXkgcnVuIGEgbW9iaWxlIGJyb3dzZXJcbmlmICggYnJvd3Nlci5hbmRyb2lkIHx8IGJyb3dzZXIuaXBhZCB8fCBicm93c2VyLmlwaG9uZSB8fCBicm93c2VyWyBcIndpbmRvd3MgcGhvbmVcIiBdICkge1xuICBicm93c2VyLm1vYmlsZSA9IHRydWU7XG59XG5cbi8vIFRoZXNlIGFyZSBhbGwgY29uc2lkZXJlZCBkZXNrdG9wIHBsYXRmb3JtcywgbWVhbmluZyB0aGV5IHJ1biBhIGRlc2t0b3AgYnJvd3NlclxuaWYgKCBicm93c2VyLmNyb3MgfHwgYnJvd3Nlci5tYWMgfHwgYnJvd3Nlci5saW51eCB8fCBicm93c2VyLndpbiApIHtcbiAgYnJvd3Nlci5kZXNrdG9wID0gdHJ1ZTtcbn1cblxuLy8gQ2hyb21lLCBPcGVyYSAxNSsgYW5kIFNhZmFyaSBhcmUgd2Via2l0IGJhc2VkIGJyb3dzZXJzXG5pZiAoIGJyb3dzZXIuY2hyb21lIHx8IGJyb3dzZXIub3ByIHx8IGJyb3dzZXIuc2FmYXJpICkge1xuICBicm93c2VyLndlYmtpdCA9IHRydWU7XG59XG5cbi8vIElFMTEgaGFzIGEgbmV3IHRva2VuIHNvIHdlIHdpbGwgYXNzaWduIGl0IG1zaWUgdG8gYXZvaWQgYnJlYWtpbmcgY2hhbmdlc1xuaWYgKCBicm93c2VyLnJ2IClcbntcbiAgdmFyIGllID0gXCJtc2llXCI7XG5cbiAgbWF0Y2hlZC5icm93c2VyID0gaWU7XG4gIGJyb3dzZXJbaWVdID0gdHJ1ZTtcbn1cblxuLy8gT3BlcmEgMTUrIGFyZSBpZGVudGlmaWVkIGFzIG9wclxuaWYgKCBicm93c2VyLm9wciApXG57XG4gIHZhciBvcGVyYSA9IFwib3BlcmFcIjtcblxuICBtYXRjaGVkLmJyb3dzZXIgPSBvcGVyYTtcbiAgYnJvd3NlcltvcGVyYV0gPSB0cnVlO1xufVxuXG4vLyBTdG9jayBBbmRyb2lkIGJyb3dzZXJzIGFyZSBtYXJrZWQgYXMgU2FmYXJpIG9uIEFuZHJvaWQuXG5pZiAoIGJyb3dzZXIuc2FmYXJpICYmIGJyb3dzZXIuYW5kcm9pZCApXG57XG4gIHZhciBhbmRyb2lkID0gXCJhbmRyb2lkXCI7XG5cbiAgbWF0Y2hlZC5icm93c2VyID0gYW5kcm9pZDtcbiAgYnJvd3NlclthbmRyb2lkXSA9IHRydWU7XG59XG5cbi8vIEFzc2lnbiB0aGUgbmFtZSBhbmQgcGxhdGZvcm0gdmFyaWFibGVcbmJyb3dzZXIubmFtZSA9IG1hdGNoZWQuYnJvd3NlcjtcbmJyb3dzZXIucGxhdGZvcm0gPSBtYXRjaGVkLnBsYXRmb3JtO1xuXG5cbm1vZHVsZS5leHBvcnRzID0gYnJvd3NlcjtcbiIsIi8qKiBAcHJlc2VydmUgaHR0cDovL2dpdGh1Yi5jb20vZWFzZXdheS9qcy1jbGFzcyAqL1xuXG4vLyBDbGFzcyBEZWZpbml0aW9uIHVzaW5nIEVDTUE1IHByb3RvdHlwZSBjaGFpblxuXG5mdW5jdGlvbiBpbmhlcml0KGRlc3QsIHNyYywgbm9QYXJlbnQpIHtcbiAgICB3aGlsZSAoc3JjICYmIHNyYyAhPT0gT2JqZWN0LnByb3RvdHlwZSkge1xuICAgICAgICBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyhzcmMpLmZvckVhY2goZnVuY3Rpb24gKG5hbWUpIHtcbiAgICAgICAgICAgIGlmIChuYW1lICE9ICcuY2xhc3MnICYmICFkZXN0Lmhhc093blByb3BlcnR5KG5hbWUpKSB7XG4gICAgICAgICAgICAgICAgdmFyIGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHNyYywgbmFtZSk7XG4gICAgICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGRlc3QsIG5hbWUsIGRlc2MpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgaWYgKG5vUGFyZW50KSB7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBzcmMgPSBzcmMuX19wcm90b19fO1xuICAgIH1cbiAgICByZXR1cm4gZGVzdDtcbn1cblxudmFyIENsYXNzID0gZnVuY3Rpb24gKGJhc2UsIHByb3RvLCBvcHRpb25zKSB7XG4gICAgaWYgKHR5cGVvZihiYXNlKSAhPSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIG9wdGlvbnMgPSBwcm90bztcbiAgICAgICAgcHJvdG8gPSBiYXNlO1xuICAgICAgICBiYXNlID0gT2JqZWN0O1xuICAgIH1cbiAgICBpZiAoIXByb3RvKSB7XG4gICAgICAgIHByb3RvID0ge307XG4gICAgfVxuICAgIGlmICghb3B0aW9ucykge1xuICAgICAgICBvcHRpb25zID0ge307XG4gICAgfVxuICAgIFxuICAgIHZhciBtZXRhID0ge1xuICAgICAgICBuYW1lOiBvcHRpb25zLm5hbWUsXG4gICAgICAgIGJhc2U6IGJhc2UsXG4gICAgICAgIGltcGxlbWVudHM6IFtdXG4gICAgfVxuICAgIHZhciBjbGFzc1Byb3RvID0gQ2xhc3MuY2xvbmUocHJvdG8pO1xuICAgIGlmIChvcHRpb25zLmltcGxlbWVudHMpIHtcbiAgICAgICAgKEFycmF5LmlzQXJyYXkob3B0aW9ucy5pbXBsZW1lbnRzKSA/IG9wdGlvbnMuaW1wbGVtZW50cyA6IFtvcHRpb25zLmltcGxlbWVudHNdKVxuICAgICAgICAgICAgLmZvckVhY2goZnVuY3Rpb24gKGltcGxlbWVudGVkVHlwZSkge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YoaW1wbGVtZW50ZWRUeXBlKSA9PSAnZnVuY3Rpb24nICYmIGltcGxlbWVudGVkVHlwZS5wcm90b3R5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgbWV0YS5pbXBsZW1lbnRzLnB1c2goaW1wbGVtZW50ZWRUeXBlKTtcbiAgICAgICAgICAgICAgICAgICAgQ2xhc3MuZXh0ZW5kKGNsYXNzUHJvdG8sIGltcGxlbWVudGVkVHlwZS5wcm90b3R5cGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgIH1cbiAgICBjbGFzc1Byb3RvLl9fcHJvdG9fXyA9IGJhc2UucHJvdG90eXBlO1xuICAgIHZhciB0aGVDbGFzcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHR5cGVvZih0aGlzLmNvbnN0cnVjdG9yKSA9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICB0aGlzLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIG1ldGEudHlwZSA9IHRoZUNsYXNzO1xuICAgIHRoZUNsYXNzLnByb3RvdHlwZSA9IGNsYXNzUHJvdG87XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoZUNsYXNzLCAnLmNsYXNzLm1ldGEnLCB7IHZhbHVlOiBtZXRhLCBlbnVtZXJhYmxlOiBmYWxzZSwgY29uZmlndXJhYmxlOiBmYWxzZSwgd3JpdGFibGU6IGZhbHNlIH0pO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShjbGFzc1Byb3RvLCAnLmNsYXNzJywgeyB2YWx1ZTogdGhlQ2xhc3MsIGVudW1lcmFibGU6IGZhbHNlLCBjb25maWd1cmFibGU6IGZhbHNlLCB3cml0YWJsZTogZmFsc2UgfSk7XG4gICAgaWYgKG9wdGlvbnMuc3RhdGljcykge1xuICAgICAgICBDbGFzcy5leHRlbmQodGhlQ2xhc3MsIG9wdGlvbnMuc3RhdGljcyk7XG4gICAgfVxuICAgIHJldHVybiB0aGVDbGFzcztcbn07XG5cbkNsYXNzLmV4dGVuZCA9IGluaGVyaXQ7XG5cbkNsYXNzLmNsb25lID0gZnVuY3Rpb24gKG9iamVjdCkge1xuICAgIHJldHVybiBpbmhlcml0KHt9LCBvYmplY3QpO1xufTtcblxuZnVuY3Rpb24gZmluZFR5cGUobWV0YSwgdHlwZSkge1xuICAgIHdoaWxlIChtZXRhKSB7XG4gICAgICAgIGlmIChtZXRhLnR5cGUucHJvdG90eXBlID09PSB0eXBlLnByb3RvdHlwZSkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgZm9yICh2YXIgaSBpbiBtZXRhLmltcGxlbWVudHMpIHtcbiAgICAgICAgICAgIHZhciBpbXBsVHlwZSA9IG1ldGEuaW1wbGVtZW50c1tpXTtcbiAgICAgICAgICAgIHZhciBpbXBsTWV0YSA9IGltcGxUeXBlWycuY2xhc3MubWV0YSddO1xuICAgICAgICAgICAgaWYgKGltcGxNZXRhKSB7XG4gICAgICAgICAgICAgICAgaWYgKGZpbmRUeXBlKGltcGxNZXRhLCB0eXBlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIHByb3RvID0gaW1wbFR5cGUucHJvdG90eXBlOyBwcm90bzsgcHJvdG8gPSBwcm90by5fX3Byb3RvX18pIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3RvID09PSB0eXBlLnByb3RvdHlwZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgbWV0YSA9IG1ldGEuYmFzZSA/IG1ldGEuYmFzZVsnLmNsYXNzLm1ldGEnXSA6IHVuZGVmaW5lZDtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xufVxuXG52YXIgQ2hlY2tlciA9IENsYXNzKHtcbiAgICBjb25zdHJ1Y3RvcjogZnVuY3Rpb24gKG9iamVjdCkge1xuICAgICAgICB0aGlzLm9iamVjdCA9IG9iamVjdDtcbiAgICB9LFxuICAgIFxuICAgIHR5cGVPZjogZnVuY3Rpb24gKHR5cGUpIHtcbiAgICAgICAgaWYgKHRoaXMub2JqZWN0IGluc3RhbmNlb2YgdHlwZSkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIG1ldGEgPSBDbGFzcy50eXBlSW5mbyh0aGlzLm9iamVjdCk7XG4gICAgICAgIHJldHVybiBtZXRhICYmIGZpbmRUeXBlKG1ldGEsIHR5cGUpO1xuICAgIH1cbn0pO1xuXG4vLyBhbGlhc2VzXG5DaGVja2VyLnByb3RvdHlwZS5hID0gQ2hlY2tlci5wcm90b3R5cGUudHlwZU9mO1xuQ2hlY2tlci5wcm90b3R5cGUuYW4gPSBDaGVja2VyLnByb3RvdHlwZS50eXBlT2Y7XG5cbkNsYXNzLmlzID0gZnVuY3Rpb24gKG9iamVjdCkge1xuICAgIHJldHVybiBuZXcgQ2hlY2tlcihvYmplY3QpO1xufTtcblxuQ2xhc3MudHlwZUluZm8gPSBmdW5jdGlvbiAob2JqZWN0KSB7XG4gICAgdmFyIHRoZUNsYXNzID0gb2JqZWN0Ll9fcHJvdG9fX1snLmNsYXNzJ107XG4gICAgcmV0dXJuIHRoZUNsYXNzID8gdGhlQ2xhc3NbJy5jbGFzcy5tZXRhJ10gOiB1bmRlZmluZWQ7XG59O1xuXG5DbGFzcy5WRVJTSU9OID0gWzAsIDAsIDJdO1xuXG5pZiAobW9kdWxlKSB7XG4gICAgbW9kdWxlLmV4cG9ydHMgPSBDbGFzcztcbn0gZWxzZSB7XG4gICAgZ2xvYmFsLkNsYXNzID0gQ2xhc3M7ICAgLy8gZm9yIGJyb3dzZXJcbn0iLCIvLyBHZW5lcmF0ZWQgYnkgQ29mZmVlU2NyaXB0IDEuOC4wXG5tb2R1bGUuZXhwb3J0cy5wYXJzZSA9IHJlcXVpcmUoXCIuL3BhcnNlclwiKTtcblxubW9kdWxlLmV4cG9ydHMud3JpdGVyID0gcmVxdWlyZShcIi4vd3JpdGVyXCIpO1xuIiwibW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKFwiLi9saWIvaW5kZXhcIik7XG4iXX0=
         |