{"id":1882,"date":"2026-04-10T17:05:03","date_gmt":"2026-04-10T15:05:03","guid":{"rendered":"https:\/\/cad-kompass.de\/?p=1882"},"modified":"2026-06-26T17:41:55","modified_gmt":"2026-06-26T15:41:55","slug":"dgm-tin-explainer","status":"publish","type":"post","link":"https:\/\/cad-kompass.de\/?p=1882","title":{"rendered":"DGM TIN Explainer"},"content":{"rendered":"\n<!--\n    (c) CAD-Kompass. Alle Rechte vorbehalten.\n    TIN-Explainer \u2013 Interaktive Delaunay-Triangulation\n-->\n<style>\n    .tin-box {\n        --tin-primary: #3f5f75;\n        --tin-primary-dark: #2c4a5e;\n        --tin-primary-deep: #1e3548;\n        --tin-ink: #1e293b;\n        --tin-text: #334155;\n        --tin-muted: #64748b;\n        --tin-border: #c8d6e0;\n        --tin-surface: #f7f9fb;\n        background: var(--tin-surface);\n        border: 3px solid var(--tin-primary);\n        border-radius: 8px;\n        margin: 28px 0;\n        overflow: hidden;\n        font-family: inherit;\n        color: var(--tin-text);\n        line-height: 1.6;\n    }\n    .tin-header {\n        background: linear-gradient(135deg, var(--tin-primary-deep) 0%, var(--tin-primary-dark) 100%);\n        padding: 14px 24px 12px;\n        position: relative;\n    }\n    .tin-header::after {\n        content: '';\n        position: absolute;\n        bottom: 0; left: 0; right: 0;\n        height: 3px;\n        background: repeating-linear-gradient(90deg, var(--tin-primary) 0px, var(--tin-primary) 8px, transparent 8px, transparent 12px);\n    }\n    .tin-box .tin-title { font-size: 1.15rem; font-weight: 700; color: #fff; margin: 0; padding: 0; }\n    .tin-box .tin-desc { font-size: 0.85rem; color: rgba(255,255,255,0.65); margin: 4px 0 0; }\n    .tin-privacy { background: #e8f5e9; color: #2e7d32; font-size: 0.8rem; padding: 6px 24px; border-bottom: 1px solid #c8e6c9; }\n    .tin-body { padding: 16px 24px 20px; }\n    .tin-controls { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 12px; align-items: center; }\n    .tin-btn { padding: 5px 12px; border: 2px solid var(--tin-primary); border-radius: 6px; background: #fff; color: var(--tin-primary); font-size: 0.82rem; font-family: inherit; cursor: pointer; transition: background 0.15s, color 0.15s; }\n    .tin-btn:hover { background: var(--tin-primary); color: #fff; }\n    .tin-btn.tin-active { background: var(--tin-primary); color: #fff; }\n    .tin-btn:disabled { opacity: 0.35; cursor: default; pointer-events: none; }\n    .tin-btn-icon { padding: 5px 8px; font-size: 0.92rem; line-height: 1; }\n    .tin-mode-group { display: flex; gap: 0; }\n    .tin-mode-group .tin-btn { border-radius: 0; }\n    .tin-mode-group .tin-btn:first-child { border-radius: 6px 0 0 6px; }\n    .tin-mode-group .tin-btn:last-child { border-radius: 0 6px 6px 0; }\n    .tin-separator { width: 1px; height: 24px; background: var(--tin-border); margin: 0 4px; }\n    .tin-canvas-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }\n    .tin-canvas-wrap { position: relative; pointer-events: auto; }\n    .tin-box, .tin-body, .tin-canvas-row { pointer-events: auto; }\n    .tin-canvas-label { font-size: 0.75rem; font-weight: 700; color: var(--tin-primary); text-transform: uppercase; letter-spacing: 0.06em; margin-bottom: 4px; }\n    .tin-canvas-wrap canvas { width: 100% !important; height: auto !important; aspect-ratio: 4 \/ 3; max-width: 100%; border: 2px solid var(--tin-border); border-radius: 6px; display: block; background: #fff; touch-action: none; pointer-events: auto; -webkit-user-select: none; user-select: none; position: relative; z-index: 1; }\n    .tin-canvas-hint { font-size: 0.78rem; color: var(--tin-muted); margin-top: 5px; min-height: 1.5em; }\n    .tin-stats { font-size: 0.78rem; color: var(--tin-muted); margin-top: 4px; }\n    .tin-stats span { margin-right: 12px; }\n    .tin-legend { display: flex; gap: 12px; flex-wrap: wrap; font-size: 0.78rem; color: var(--tin-muted); margin-top: 4px; }\n    .tin-legend-item { display: flex; align-items: center; gap: 4px; }\n    .tin-legend-dot { width: 9px; height: 9px; border-radius: 50%; display: inline-block; }\n    .tin-legend-line { width: 14px; height: 3px; display: inline-block; }\n    .tin-info-row { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-top: 14px; }\n    .tin-info-box { border-left: 3px solid var(--tin-primary); background: #fff; padding: 10px 14px; border-radius: 0 6px 6px 0; }\n    .tin-info-box h3 { font-size: 0.82rem; font-weight: 700; color: var(--tin-ink); margin: 0 0 4px; }\n    .tin-info-box p { font-size: 0.78rem; margin: 0; color: var(--tin-text); line-height: 1.5; }\n    .tin-context-menu { display: none; position: absolute; background: #fff; border: 1px solid var(--tin-border); border-radius: 6px; box-shadow: 0 4px 12px rgba(0,0,0,0.15); z-index: 100; overflow: hidden; min-width: 180px; }\n    .tin-context-item { padding: 8px 14px; font-size: 0.82rem; font-family: inherit; color: var(--tin-text); cursor: pointer; border: none; background: none; width: 100%; text-align: left; display: block; }\n    .tin-context-item:hover { background: var(--tin-surface); color: var(--tin-primary); }\n    .tin-context-sep { height: 1px; background: var(--tin-border); margin: 2px 0; }\n    .tin-tooltip { display: none; position: absolute; background: rgba(30,41,59,0.92); color: #fff; font-size: 0.73rem; padding: 5px 9px; border-radius: 4px; pointer-events: none; z-index: 50; line-height: 1.4; white-space: nowrap; font-family: inherit; }\n    .tin-z-edit { position: absolute; z-index: 60; background: #fff; border: 2px solid var(--tin-primary); border-radius: 4px; padding: 3px 6px; font-size: 0.85rem; font-family: inherit; width: 70px; text-align: center; box-shadow: 0 2px 8px rgba(0,0,0,0.18); display: none; }\n    .tin-3d-views { display: flex; gap: 0; margin-left: auto; }\n    .tin-3d-views .tin-btn { border-radius: 0; }\n    .tin-3d-views .tin-btn:first-child { border-radius: 6px 0 0 6px; }\n    .tin-3d-views .tin-btn:last-child { border-radius: 0 6px 6px 0; }\n    \/* 3D Orbit-Slider Layout \u2014 Canvas bleibt exakt wie 2D *\/\n    .tin-3d-orbit { display: flex; gap: 0; align-items: stretch; }\n    .tin-3d-orbit-canvas { flex: 1; min-width: 0; }\n    .tin-3d-orbit-canvas canvas { width: 100% !important; height: auto !important; aspect-ratio: 4 \/ 3; max-width: 100%; border: 2px solid var(--tin-border); border-radius: 6px 0 6px 6px; display: block; background: #fff; touch-action: none; pointer-events: auto; -webkit-user-select: none; user-select: none; position: relative; z-index: 1; }\n    .tin-3d-orbit-v { width: 28px; display: flex; flex-direction: column; align-items: center; padding: 2px 0; background: linear-gradient(180deg, #e8eff5 0%, #f0f5fa 100%); border: 2px solid var(--tin-border); border-left: none; border-radius: 0 6px 6px 0; }\n    .tin-3d-orbit-v .tin-orbit-icon { font-size: 0.6rem; color: var(--tin-primary); opacity: 0.7; line-height: 1; padding: 2px 0 3px; user-select: none; }\n    .tin-3d-orbit-h { display: flex; align-items: center; gap: 0; margin-top: -1px; }\n    .tin-3d-orbit-h .tin-orbit-icon { font-size: 0.6rem; color: var(--tin-primary); opacity: 0.7; width: 20px; text-align: center; user-select: none; flex-shrink: 0; }\n    \/* Custom Range Slider \u2014 horizontal *\/\n    .tin-orbit-range-h { -webkit-appearance: none; appearance: none; flex: 1; height: 22px; background: transparent; cursor: pointer; margin: 0; padding: 0; }\n    .tin-orbit-range-h::-webkit-slider-runnable-track { height: 6px; border-radius: 3px; background: linear-gradient(90deg, var(--tin-primary), #7ba3bb, var(--tin-primary)); border: 1px solid var(--tin-border); }\n    .tin-orbit-range-h::-webkit-slider-thumb { -webkit-appearance: none; width: 16px; height: 16px; margin-top: -6px; border-radius: 50%; background: radial-gradient(circle at 40% 35%, #fff 0%, var(--tin-primary) 100%); border: 2px solid var(--tin-primary-dark); box-shadow: 0 1px 4px rgba(30,53,72,0.35); cursor: grab; transition: box-shadow 0.15s; }\n    .tin-orbit-range-h::-webkit-slider-thumb:active { cursor: grabbing; box-shadow: 0 0 0 4px rgba(63,95,117,0.18), 0 1px 4px rgba(30,53,72,0.35); }\n    .tin-orbit-range-h::-moz-range-track { height: 6px; border-radius: 3px; background: linear-gradient(90deg, var(--tin-primary), #7ba3bb, var(--tin-primary)); border: 1px solid var(--tin-border); }\n    .tin-orbit-range-h::-moz-range-thumb { width: 14px; height: 14px; border-radius: 50%; background: radial-gradient(circle at 40% 35%, #fff 0%, var(--tin-primary) 100%); border: 2px solid var(--tin-primary-dark); box-shadow: 0 1px 4px rgba(30,53,72,0.35); cursor: grab; }\n    \/* Custom Range Slider \u2014 vertikal *\/\n    .tin-orbit-range-v { -webkit-appearance: none; appearance: none; writing-mode: vertical-lr; direction: rtl; flex: 1; width: 22px; min-height: 0; background: transparent; cursor: pointer; margin: 0; padding: 0; }\n    .tin-orbit-range-v::-webkit-slider-runnable-track { width: 6px; border-radius: 3px; background: linear-gradient(180deg, var(--tin-primary), #7ba3bb, var(--tin-primary)); border: 1px solid var(--tin-border); }\n    .tin-orbit-range-v::-webkit-slider-thumb { -webkit-appearance: none; width: 16px; height: 16px; margin-left: -6px; border-radius: 50%; background: radial-gradient(circle at 40% 35%, #fff 0%, var(--tin-primary) 100%); border: 2px solid var(--tin-primary-dark); box-shadow: 0 1px 4px rgba(30,53,72,0.35); cursor: grab; transition: box-shadow 0.15s; }\n    .tin-orbit-range-v::-webkit-slider-thumb:active { cursor: grabbing; box-shadow: 0 0 0 4px rgba(63,95,117,0.18), 0 1px 4px rgba(30,53,72,0.35); }\n    .tin-orbit-range-v::-moz-range-track { width: 6px; border-radius: 3px; background: linear-gradient(180deg, var(--tin-primary), #7ba3bb, var(--tin-primary)); border: 1px solid var(--tin-border); }\n    .tin-orbit-range-v::-moz-range-thumb { width: 14px; height: 14px; border-radius: 50%; background: radial-gradient(circle at 40% 35%, #fff 0%, var(--tin-primary) 100%); border: 2px solid var(--tin-primary-dark); box-shadow: 0 1px 4px rgba(30,53,72,0.35); cursor: grab; }\n    @media (max-width: 900px) {\n        .tin-canvas-row { grid-template-columns: 1fr; }\n        .tin-info-row { grid-template-columns: 1fr; }\n        .tin-body { padding: 12px; }\n    }\n<\/style>\n\n<div class=\"tin-box\">\n    <div class=\"tin-header\">\n        <div class=\"tin-title\">TIN-Explainer \u2014 Interaktive Delaunay-Triangulation<\/div>\n        <div class=\"tin-desc\">Punkte setzen, Bruchkanten definieren, Dreiecksvermaschung verstehen<\/div>\n    <\/div>\n    <div class=\"tin-privacy\">Dieses Tool arbeitet vollst\u00e4ndig in deinem Browser. Keine Daten werden \u00fcbertragen.<\/div>\n    <div class=\"tin-body\">\n        <div class=\"tin-controls\">\n            <div class=\"tin-mode-group\">\n                <button class=\"tin-btn tin-active\" id=\"tinModePoint\" data-tin-mode=\"point\">Punkte setzen<\/button>\n                <button class=\"tin-btn\" id=\"tinModeEdge\" data-tin-mode=\"edge\">Bruchkante<\/button>\n            <\/div>\n            <div class=\"tin-mode-group\">\n                <button class=\"tin-btn tin-active\" id=\"tinViewWire\" data-tin-view=\"wire\">Drahtgitter<\/button>\n                <button class=\"tin-btn\" id=\"tinViewHeight\" data-tin-view=\"height\">H\u00f6henfarben<\/button>\n                <button class=\"tin-btn\" id=\"tinViewSlope\" data-tin-view=\"slope\">Neigung<\/button>\n                <button class=\"tin-btn\" id=\"tinViewContour\" data-tin-view=\"contour\">H\u00f6henlinien<\/button>\n            <\/div>\n            <div class=\"tin-separator\"><\/div>\n            <button class=\"tin-btn tin-btn-icon\" id=\"tinBtnUndo\" data-tin-action=\"undo\" disabled title=\"R\u00fcckg\u00e4ngig (Strg+Z)\">\u21a9<\/button>\n            <button class=\"tin-btn tin-btn-icon\" id=\"tinBtnRedo\" data-tin-action=\"redo\" disabled title=\"Wiederherstellen (Strg+Y)\">\u21aa<\/button>\n            <label style=\"display:flex;align-items:center;gap:4px;font-size:0.82rem;color:#3f5f75;cursor:pointer;\">\n                <input type=\"checkbox\" id=\"tinCircumToggle\" style=\"accent-color:#3f5f75\"> Umkreise\n            <\/label>\n            <div class=\"tin-separator\"><\/div>\n            <button class=\"tin-btn\" data-tin-action=\"reset\">Zur\u00fccksetzen<\/button>\n            <button class=\"tin-btn tin-btn-icon\" data-tin-action=\"export\" title=\"Als PNG speichern\">\ud83d\udcf7<\/button>\n            <div class=\"tin-3d-views\">\n                <button class=\"tin-btn\" data-tin-cam=\"0,1.50\">Oben<\/button>\n                <button class=\"tin-btn\" data-tin-cam=\"0,0.08\">Vorne<\/button>\n                <button class=\"tin-btn\" data-tin-cam=\"3.14,0.08\">Hinten<\/button>\n                <button class=\"tin-btn\" data-tin-cam=\"-1.57,0.08\">Links<\/button>\n                <button class=\"tin-btn\" data-tin-cam=\"1.57,0.08\">Rechts<\/button>\n                <button class=\"tin-btn\" data-tin-cam=\"-0.6,0.65\">ISO \u2197<\/button>\n                <button class=\"tin-btn\" data-tin-cam=\"0.97,0.65\">ISO \u2198<\/button>\n                <button class=\"tin-btn\" data-tin-cam=\"2.54,0.65\">ISO \u2199<\/button>\n                <button class=\"tin-btn\" data-tin-cam=\"-2.17,0.65\">ISO \u2196<\/button>\n            <\/div>\n        <\/div>\n\n        <div class=\"tin-canvas-row\">\n            <div class=\"tin-canvas-wrap\" id=\"tinWrap2D\">\n                <div class=\"tin-canvas-label\">2D-Draufsicht (Lageplan)<\/div>\n                <canvas id=\"tinCanvas2D\" width=\"480\" height=\"360\"><\/canvas>\n                <div class=\"tin-tooltip\" id=\"tinTooltip\"><\/div>\n                <div class=\"tin-context-menu\" id=\"tinContextMenu\"><\/div>\n                <input type=\"number\" class=\"tin-z-edit\" id=\"tinZEdit\" step=\"0.1\">\n                <div class=\"tin-canvas-hint\" id=\"tinHint\">Klicke um Punkte zu setzen. Doppelklick auf einen Punkt \u2192 H\u00f6he \u00e4ndern. Rechtsklick \u2192 L\u00f6schen.<\/div>\n                <div class=\"tin-stats\" id=\"tinStats\"><\/div>\n                <div class=\"tin-legend\">\n                    <span class=\"tin-legend-item\"><span class=\"tin-legend-dot\" style=\"background:#2563eb\"><\/span> Messpunkt<\/span>\n                    <span class=\"tin-legend-item\"><span class=\"tin-legend-line\" style=\"background:#e11d48\"><\/span> Bruchkante<\/span>\n                    <span class=\"tin-legend-item\"><span class=\"tin-legend-line\" style=\"background:#94a3b8\"><\/span> TIN-Kante<\/span>\n                <\/div>\n            <\/div>\n            <div class=\"tin-canvas-wrap\" id=\"tinWrap3D\">\n                <div class=\"tin-canvas-label\">3D-Ansicht <span style=\"font-weight:400;text-transform:none;letter-spacing:0\">(Ziehen zum Drehen)<\/span><\/div>\n                <div class=\"tin-3d-orbit\">\n                    <div class=\"tin-3d-orbit-canvas\">\n                        <canvas id=\"tinCanvas3D\" width=\"480\" height=\"360\"><\/canvas>\n                        <div class=\"tin-3d-orbit-h\">\n                            <span class=\"tin-orbit-icon\">\u2194<\/span>\n                            <input type=\"range\" class=\"tin-orbit-range-h\" id=\"tinSliderAz\" min=\"0\" max=\"360\" value=\"214\" title=\"Horizontale Drehung (Azimut)\">\n                        <\/div>\n                    <\/div>\n                    <div class=\"tin-3d-orbit-v\">\n                        <span class=\"tin-orbit-icon\">\u2195<\/span>\n                        <input type=\"range\" class=\"tin-orbit-range-v\" id=\"tinSliderEl\" min=\"0\" max=\"360\" value=\"37\" title=\"Vertikale Neigung (Elevation)\">\n                    <\/div>\n                <\/div>\n                <div class=\"tin-canvas-hint\" style=\"text-align:right\">H\u00f6hen\u00fcberh\u00f6hung: <input type=\"range\" id=\"tinZScale\" min=\"5\" max=\"40\" value=\"18\" style=\"width:80px;vertical-align:middle;accent-color:#3f5f75\"> <span id=\"tinZScaleVal\">1.8\u00d7<\/span><\/div>\n            <\/div>\n        <\/div>\n\n        <div class=\"tin-info-row\">\n            <div class=\"tin-info-box\">\n                <h3>Was ist Delaunay?<\/h3>\n                <p>Die Delaunay-Triangulation verbindet Punkte so zu Dreiecken, dass kein Punkt innerhalb des Umkreises eines Dreiecks liegt. Das ergibt gleichm\u00e4\u00dfige Dreiecke \u2014 ideal f\u00fcr Gel\u00e4ndemodelle.<\/p>\n            <\/div>\n            <div class=\"tin-info-box\">\n                <h3>Warum Bruchkanten?<\/h3>\n                <p>Bruchkanten erzwingen Kanten im Dreiecksnetz entlang von B\u00f6schungen, Bordsteinen oder Gew\u00e4ssern. Ohne sie gl\u00e4ttet die Triangulation \u00fcber Gel\u00e4ndespr\u00fcnge hinweg.<\/p>\n            <\/div>\n            <div class=\"tin-info-box\">\n                <h3>Was sind TIN-Dreiecke?<\/h3>\n                <p>Ein TIN (Triangulated Irregular Network) besteht aus unregelm\u00e4\u00dfig verteilten Punkten mit H\u00f6henwerten. Jedes Dreieck beschreibt eine ebene Fl\u00e4che \u2014 zusammen bilden sie das Gel\u00e4ndemodell.<\/p>\n            <\/div>\n        <\/div>\n    <\/div>\n<\/div>\n\n<script>eval(decodeURIComponent(escape(atob(\"CiAgICAoZnVuY3Rpb24oKSB7CiAgICAgICAgLyogPT09PT0gRGVsYXVuYXRvciAoTWFwYm94LCBJU0MgTGljZW5zZSkgPT09PT0gKi8KICAgICAgICBmdW5jdGlvbiBEZWxhdW5hdG9yKGNvb3JkcykgewogICAgICAgICAgICB2YXIgbiA9IGNvb3Jkcy5sZW5ndGggPj4gMTsKICAgICAgICAgICAgaWYgKG4gPCAzKSByZXR1cm4geyB0cmlhbmdsZXM6IFtdLCBoYWxmZWRnZXM6IFtdLCBodWxsOiBbXSB9OwogICAgICAgICAgICB2YXIgaWRzID0gbmV3IFVpbnQzMkFycmF5KG4pLCBkaXN0cyA9IG5ldyBGbG9hdDY0QXJyYXkobik7CiAgICAgICAgICAgIHZhciBtaW5YID0gSW5maW5pdHksIG1pblkgPSBJbmZpbml0eSwgbWF4WCA9IC1JbmZpbml0eSwgbWF4WSA9IC1JbmZpbml0eTsKICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBuOyBpKyspIHsKICAgICAgICAgICAgICAgIHZhciB4ID0gY29vcmRzWzIqaV0sIHkgPSBjb29yZHNbMippKzFdOwogICAgICAgICAgICAgICAgaWYgKHggPCBtaW5YKSBtaW5YID0geDsgaWYgKHkgPCBtaW5ZKSBtaW5ZID0geTsKICAgICAgICAgICAgICAgIGlmICh4ID4gbWF4WCkgbWF4WCA9IHg7IGlmICh5ID4gbWF4WSkgbWF4WSA9IHk7CiAgICAgICAgICAgICAgICBpZHNbaV0gPSBpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHZhciBjeCA9IChtaW5YK21heFgpLzIsIGN5ID0gKG1pblkrbWF4WSkvMjsKICAgICAgICAgICAgdmFyIGkwPTAsIGkxPTAsIGkyPTAsIG1pbkRpc3Q9SW5maW5pdHk7CiAgICAgICAgICAgIGZvciAoaT0wO2k8bjtpKyspe3ZhciBkPWRzdChjeCxjeSxjb29yZHNbMippXSxjb29yZHNbMippKzFdKTtpZihkPG1pbkRpc3Qpe2kwPWk7bWluRGlzdD1kO319CiAgICAgICAgICAgIHZhciBpMHg9Y29vcmRzWzIqaTBdLGkweT1jb29yZHNbMippMCsxXTsgbWluRGlzdD1JbmZpbml0eTsKICAgICAgICAgICAgZm9yKGk9MDtpPG47aSsrKXtpZihpPT09aTApY29udGludWU7ZD1kc3QoaTB4LGkweSxjb29yZHNbMippXSxjb29yZHNbMippKzFdKTtpZihkPG1pbkRpc3QmJmQ+MCl7aTE9aTttaW5EaXN0PWQ7fX0KICAgICAgICAgICAgdmFyIGkxeD1jb29yZHNbMippMV0saTF5PWNvb3Jkc1syKmkxKzFdLG1pblI9SW5maW5pdHk7CiAgICAgICAgICAgIGZvcihpPTA7aTxuO2krKyl7aWYoaT09PWkwfHxpPT09aTEpY29udGludWU7dmFyIHI9Y3JhZChpMHgsaTB5LGkxeCxpMXksY29vcmRzWzIqaV0sY29vcmRzWzIqaSsxXSk7aWYocjxtaW5SKXtpMj1pO21pblI9cjt9fQogICAgICAgICAgICB2YXIgaTJ4PWNvb3Jkc1syKmkyXSxpMnk9Y29vcmRzWzIqaTIrMV07CiAgICAgICAgICAgIGlmKG1pblI9PT1JbmZpbml0eSlyZXR1cm57dHJpYW5nbGVzOltdLGhhbGZlZGdlczpbXSxodWxsOltdfTsKICAgICAgICAgICAgaWYob3JpKGkweCxpMHksaTF4LGkxeSxpMngsaTJ5KTwwKXt2YXIgdG1wPWkxO2kxPWkyO2kyPXRtcDt0bXA9aTF4O2kxeD1pMng7aTJ4PXRtcDt0bXA9aTF5O2kxeT1pMnk7aTJ5PXRtcDt9CiAgICAgICAgICAgIHZhciBjdHI9Y2N0cihpMHgsaTB5LGkxeCxpMXksaTJ4LGkyeSk7Y3g9Y3RyLng7Y3k9Y3RyLnk7CiAgICAgICAgICAgIGZvcihpPTA7aTxuO2krKylkaXN0c1tpXT1kc3QoY29vcmRzWzIqaV0sY29vcmRzWzIqaSsxXSxjeCxjeSk7CiAgICAgICAgICAgIHFzb3J0KGlkcyxkaXN0cywwLG4tMSk7CiAgICAgICAgICAgIHZhciBtYXhUcmk9TWF0aC5tYXgoMipuLTUsMCksdHJpYW5nbGVzPW5ldyBVaW50MzJBcnJheShtYXhUcmkqMyksaGFsZmVkZ2VzPW5ldyBJbnQzMkFycmF5KG1heFRyaSozKTsKICAgICAgICAgICAgaGFsZmVkZ2VzLmZpbGwoLTEpOwogICAgICAgICAgICB2YXIgaGFzaFNpemU9TWF0aC5jZWlsKE1hdGguc3FydChuKSksaHVsbEhhc2g9bmV3IEludDMyQXJyYXkoaGFzaFNpemUpLmZpbGwoLTEpOwogICAgICAgICAgICB2YXIgaHVsbFByZXY9bmV3IFVpbnQzMkFycmF5KG4pLGh1bGxOZXh0PW5ldyBVaW50MzJBcnJheShuKSxodWxsVHJpPW5ldyBVaW50MzJBcnJheShuKSxodWxsU3RhcnQ9aTA7CiAgICAgICAgICAgIHZhciB0cmlDb3VudD0wOwogICAgICAgICAgICBmdW5jdGlvbiBhZGRUcmkoaTAsaTEsaTIsYSxiLGMpe3ZhciB0PXRyaUNvdW50O3RyaWFuZ2xlc1t0XT1pMDt0cmlhbmdsZXNbdCsxXT1pMTt0cmlhbmdsZXNbdCsyXT1pMjtoYWxmZWRnZXNbdF09YTtoYWxmZWRnZXNbdCsxXT1iO2hhbGZlZGdlc1t0KzJdPWM7aWYoYSE9PS0xKWhhbGZlZGdlc1thXT10O2lmKGIhPT0tMSloYWxmZWRnZXNbYl09dCsxO2lmKGMhPT0tMSloYWxmZWRnZXNbY109dCsyO3RyaUNvdW50Kz0zO3JldHVybiB0O30KICAgICAgICAgICAgZnVuY3Rpb24gbGVnYWxpemUoYSl7dmFyIGI9aGFsZmVkZ2VzW2FdO2lmKGI9PT0tMSlyZXR1cm4gYTt2YXIgYTA9YS1hJTMsYjA9Yi1iJTM7dmFyIGFsPWEwKyhhKzEpJTMsYXI9YTArKGErMiklMyxibD1iMCsoYisyKSUzLGJyPWIwKyhiKzEpJTM7dmFyIHAwPXRyaWFuZ2xlc1thcl0scHI9dHJpYW5nbGVzW2FdLHBsPXRyaWFuZ2xlc1thbF0scDE9dHJpYW5nbGVzW2JsXTtpZihpbkNpcihjb29yZHNbMipwMF0sY29vcmRzWzIqcDArMV0sY29vcmRzWzIqcHJdLGNvb3Jkc1syKnByKzFdLGNvb3Jkc1syKnBsXSxjb29yZHNbMipwbCsxXSxjb29yZHNbMipwMV0sY29vcmRzWzIqcDErMV0pKXt0cmlhbmdsZXNbYV09cDE7dHJpYW5nbGVzW2JdPXAwO3ZhciBoYmw9aGFsZmVkZ2VzW2JsXSxoYXI9aGFsZmVkZ2VzW2FyXTtpZihoYmw9PT0tMSl7dmFyIGU9aHVsbFN0YXJ0O2Rve2lmKGh1bGxUcmlbZV09PT1ibCl7aHVsbFRyaVtlXT1hO2JyZWFrO31lPWh1bGxQcmV2W2VdO313aGlsZShlIT09aHVsbFN0YXJ0KTt9aGFsZmVkZ2VzW2FdPWhibDtpZihoYmwhPT0tMSloYWxmZWRnZXNbaGJsXT1hO2hhbGZlZGdlc1tiXT1oYXI7aWYoaGFyIT09LTEpaGFsZmVkZ2VzW2hhcl09YjtoYWxmZWRnZXNbYXJdPWJsO2hhbGZlZGdlc1tibF09YXI7bGVnYWxpemUoYSk7cmV0dXJuIGxlZ2FsaXplKGJyKTt9cmV0dXJuIGE7fQogICAgICAgICAgICBmdW5jdGlvbiBoayh4LHkpe3JldHVybiBNYXRoLmZsb29yKHBBbmcoeC1jeCx5LWN5KSpoYXNoU2l6ZSklaGFzaFNpemU7fQogICAgICAgICAgICBhZGRUcmkoaTAsaTEsaTIsLTEsLTEsLTEpOwogICAgICAgICAgICBodWxsTmV4dFtpMF09aHVsbFByZXZbaTJdPWkxO2h1bGxOZXh0W2kxXT1odWxsUHJldltpMF09aTI7aHVsbE5leHRbaTJdPWh1bGxQcmV2W2kxXT1pMDsKICAgICAgICAgICAgaHVsbFRyaVtpMF09MDtodWxsVHJpW2kxXT0xO2h1bGxUcmlbaTJdPTI7CiAgICAgICAgICAgIGh1bGxIYXNoW2hrKGkweCxpMHkpXT1pMDtodWxsSGFzaFtoayhpMXgsaTF5KV09aTE7aHVsbEhhc2hbaGsoaTJ4LGkyeSldPWkyOwogICAgICAgICAgICB2YXIgeHAseXA7CiAgICAgICAgICAgIGZvcih2YXIgaz0wO2s8aWRzLmxlbmd0aDtrKyspe2k9aWRzW2tdO3g9Y29vcmRzWzIqaV07eT1jb29yZHNbMippKzFdO2lmKGs+MCYmTWF0aC5hYnMoeC14cCk8PTFlLTEwJiZNYXRoLmFicyh5LXlwKTw9MWUtMTApY29udGludWU7eHA9eDt5cD15O2lmKGk9PT1pMHx8aT09PWkxfHxpPT09aTIpY29udGludWU7dmFyIHN0YXJ0PTAsa2V5PWhrKHgseSk7Zm9yKHZhciBqPTA7ajxoYXNoU2l6ZTtqKyspe3N0YXJ0PWh1bGxIYXNoWyhrZXkraiklaGFzaFNpemVdO2lmKHN0YXJ0IT09LTEmJnN0YXJ0IT09aHVsbE5leHRbc3RhcnRdKWJyZWFrO31zdGFydD1odWxsUHJldltzdGFydF07dmFyIGU9c3RhcnQscTt3aGlsZShxPWh1bGxOZXh0W2VdLG9yaSh4LHksY29vcmRzWzIqZV0sY29vcmRzWzIqZSsxXSxjb29yZHNbMipxXSxjb29yZHNbMipxKzFdKT49MCl7ZT1xO2lmKGU9PT1zdGFydCl7ZT0tMTticmVhazt9fWlmKGU9PT0tMSljb250aW51ZTt2YXIgdD1hZGRUcmkoZSxpLGh1bGxOZXh0W2VdLC0xLC0xLGh1bGxUcmlbZV0pO2h1bGxUcmlbaV09bGVnYWxpemUodCsyKTtodWxsVHJpW2VdPXQ7dmFyIG5leHQ9aHVsbE5leHRbZV07d2hpbGUocT1odWxsTmV4dFtuZXh0XSxvcmkoeCx5LGNvb3Jkc1syKm5leHRdLGNvb3Jkc1syKm5leHQrMV0sY29vcmRzWzIqcV0sY29vcmRzWzIqcSsxXSk8MCl7dD1hZGRUcmkobmV4dCxpLHEsaHVsbFRyaVtpXSwtMSxodWxsVHJpW25leHRdKTtodWxsVHJpW2ldPWxlZ2FsaXplKHQrMik7aHVsbE5leHRbbmV4dF09bmV4dDtuZXh0PXE7fWlmKGU9PT1zdGFydCl7d2hpbGUocT1odWxsUHJldltlXSxvcmkoeCx5LGNvb3Jkc1syKnFdLGNvb3Jkc1syKnErMV0sY29vcmRzWzIqZV0sY29vcmRzWzIqZSsxXSk8MCl7dD1hZGRUcmkocSxpLGUsLTEsaHVsbFRyaVtlXSxodWxsVHJpW3FdKTtsZWdhbGl6ZSh0KzIpO2h1bGxUcmlbcV09dDtodWxsTmV4dFtlXT1lO2U9cTt9fWh1bGxTdGFydD1odWxsUHJldltpXT1lO2h1bGxOZXh0W2VdPWh1bGxQcmV2W25leHRdPWk7aHVsbE5leHRbaV09bmV4dDtodWxsSGFzaFtoayh4LHkpXT1pO2h1bGxIYXNoW2hrKGNvb3Jkc1syKmVdLGNvb3Jkc1syKmUrMV0pXT1lO30KICAgICAgICAgICAgdmFyIGh1bGw9W107IGU9aHVsbFN0YXJ0OyBkb3todWxsLnB1c2goZSk7ZT1odWxsTmV4dFtlXTt9d2hpbGUoZSE9PWh1bGxTdGFydCk7CiAgICAgICAgICAgIHJldHVybnt0cmlhbmdsZXM6dHJpYW5nbGVzLnN1YmFycmF5KDAsdHJpQ291bnQpLGhhbGZlZGdlczpoYWxmZWRnZXMuc3ViYXJyYXkoMCx0cmlDb3VudCksaHVsbDpodWxsfTsKICAgICAgICB9CiAgICAgICAgZnVuY3Rpb24gZHN0KGEsYixjLGQpe3ZhciB4PWEtYyx5PWItZDtyZXR1cm4geCp4K3kqeTt9CiAgICAgICAgZnVuY3Rpb24gb3JpKHB4LHB5LHF4LHF5LHJ4LHJ5KXtyZXR1cm4ocXktcHkpKihyeC1xeCktKHF4LXB4KSoocnktcXkpO30KICAgICAgICBmdW5jdGlvbiBpbkNpcihheCxheSxieCxieSxjeCxjeSxweCxweSl7dmFyIGR4PWF4LXB4LGR5PWF5LXB5LGV4PWJ4LXB4LGV5PWJ5LXB5LGZ4PWN4LXB4LGZ5PWN5LXB5LGFwPWR4KmR4K2R5KmR5LGJwPWV4KmV4K2V5KmV5LGNwPWZ4KmZ4K2Z5KmZ5O3JldHVybiBkeCooZXkqY3AtYnAqZnkpLWR5KihleCpjcC1icCpmeCkrYXAqKGV4KmZ5LWV5KmZ4KTwwO30KICAgICAgICBmdW5jdGlvbiBjcmFkKGF4LGF5LGJ4LGJ5LGN4LGN5KXt2YXIgZHg9YngtYXgsZHk9YnktYXksZXg9Y3gtYXgsZXk9Y3ktYXksYmw9ZHgqZHgrZHkqZHksY2w9ZXgqZXgrZXkqZXksZD1keCpleS1keSpleDtpZihNYXRoLmFicyhkKTwxZS0xMClyZXR1cm4gSW5maW5pdHk7ZD0wLjUvZDt2YXIgeD0oZXkqYmwtZHkqY2wpKmQseT0oZHgqY2wtZXgqYmwpKmQ7cmV0dXJuIHgqeCt5Knk7fQogICAgICAgIGZ1bmN0aW9uIGNjdHIoYXgsYXksYngsYnksY3gsY3kpe3ZhciBkeD1ieC1heCxkeT1ieS1heSxleD1jeC1heCxleT1jeS1heSxibD1keCpkeCtkeSpkeSxjbD1leCpleCtleSpleSxkPTAuNS8oZHgqZXktZHkqZXgpO3JldHVybnt4OmF4KyhleSpibC1keSpjbCkqZCx5OmF5KyhkeCpjbC1leCpibCkqZH07fQogICAgICAgIGZ1bmN0aW9uIHBBbmcoZHgsZHkpe3ZhciBwPWR4LyhNYXRoLmFicyhkeCkrTWF0aC5hYnMoZHkpKTtyZXR1cm4oZHk+MD8zLXA6MStwKS80O30KICAgICAgICBmdW5jdGlvbiBxc29ydChpZHMsZCxsLHIpe2lmKHItbDw9MjApe2Zvcih2YXIgaT1sKzE7aTw9cjtpKyspe3ZhciB0PWlkc1tpXSx0ZD1kW3RdLGo9aS0xO3doaWxlKGo+PWwmJmRbaWRzW2pdXT50ZCl7aWRzW2orMV09aWRzW2pdO2otLTt9aWRzW2orMV09dDt9cmV0dXJuO312YXIgbT0obCtyKT4+MSxpPWwrMSxqPXI7c3coaWRzLG0saSk7aWYoZFtpZHNbbF1dPmRbaWRzW3JdXSlzdyhpZHMsbCxyKTtpZihkW2lkc1tpXV0+ZFtpZHNbcl1dKXN3KGlkcyxpLHIpO2lmKGRbaWRzW2xdXT5kW2lkc1tpXV0pc3coaWRzLGwsaSk7dmFyIHQ9aWRzW2ldLHRkPWRbdF07d2hpbGUodHJ1ZSl7ZG8gaSsrO3doaWxlKGRbaWRzW2ldXTx0ZCk7ZG8gai0tO3doaWxlKGRbaWRzW2pdXT50ZCk7aWYoajxpKWJyZWFrO3N3KGlkcyxpLGopO31pZHNbbCsxXT1pZHNbal07aWRzW2pdPXQ7aWYoci1pKzE+PWotbCl7cXNvcnQoaWRzLGQsaSxyKTtxc29ydChpZHMsZCxsLGotMSk7fWVsc2V7cXNvcnQoaWRzLGQsbCxqLTEpO3Fzb3J0KGlkcyxkLGkscik7fX0KICAgICAgICBmdW5jdGlvbiBzdyhhLGksail7dmFyIHQ9YVtpXTthW2ldPWFbal07YVtqXT10O30KICAgICAgICAvKiA9PT09PSBBbndlbmR1bmcgPT09PT0gKi8KICAgICAgICB2YXIgVyA9IDQ4MCwgSCA9IDM2MDsKICAgICAgICB2YXIgYzJkID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3RpbkNhbnZhczJEJyk7CiAgICAgICAgdmFyIGMzZCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd0aW5DYW52YXMzRCcpOwogICAgICAgIHZhciBkcHIgPSB3aW5kb3cuZGV2aWNlUGl4ZWxSYXRpbyB8fCAxOwogICAgICAgIGMyZC53aWR0aCA9IFcqZHByOyBjMmQuaGVpZ2h0ID0gSCpkcHI7IGMzZC53aWR0aCA9IFcqZHByOyBjM2QuaGVpZ2h0ID0gSCpkcHI7CiAgICAgICAgdmFyIHgyID0gYzJkLmdldENvbnRleHQoJzJkJyk7IHZhciB4MyA9IGMzZC5nZXRDb250ZXh0KCcyZCcpOwogICAgICAgIHgyLnNjYWxlKGRwcixkcHIpOyB4My5zY2FsZShkcHIsZHByKTsKICAgICAgICB2YXIgcHRzID0gW107ICAgICAgICAgICAvKiBbe3gseSx6fV0gKi8KICAgICAgICB2YXIgY29uID0gW107ICAgICAgICAgICAvKiBbW2ksal1dIGNvbnN0cmFpbnRzICovCiAgICAgICAgdmFyIG1vZGUgPSAncG9pbnQnOwogICAgICAgIHZhciB2aWV3TW9kZSA9ICd3aXJlJzsKICAgICAgICB2YXIgZWRnZUZpcnN0ID0gLTE7CiAgICAgICAgdmFyIHRyaSA9IG51bGw7ICAgICAgICAgLyogRGVsYXVuYXRvciByZXN1bHQgKi8KICAgICAgICB2YXIgc2hvd0NpcmN1bSA9IGZhbHNlOwogICAgICAgIHZhciBob3ZlclRyaSA9IC0xOwogICAgICAgIHZhciBkcmFnSWR4ID0gLTEsIGlzRHJhZyA9IGZhbHNlLCBkaWREcmFnID0gZmFsc2U7CiAgICAgICAgdmFyIHRQdHMgPSBbXSwgdENvbiA9IFtdOyAgLyogRXJ3ZWl0ZXJ0OiBwdHMgKyBTdGVpbmVyLVB1bmt0ZSBhdWYgQnJ1Y2hrYW50ZW4gKi8KICAgICAgICAvKiBVbmRvICovCiAgICAgICAgdmFyIGhpc3QgPSBbXSwgaGlzdFBvcyA9IC0xOwogICAgICAgIGZ1bmN0aW9uIHNhdmVIKCl7aGlzdFBvcysrO2hpc3QubGVuZ3RoPWhpc3RQb3M7aGlzdC5wdXNoKEpTT04uc3RyaW5naWZ5KHtwOnB0cyxjOmNvbn0pKTtpZihoaXN0Lmxlbmd0aD4zMCl7aGlzdC5zaGlmdCgpO2hpc3RQb3MtLTt9dXBkVW5kb0J0bigpO30KICAgICAgICBmdW5jdGlvbiB1cGRVbmRvQnRuKCl7ZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3RpbkJ0blVuZG8nKS5kaXNhYmxlZD1oaXN0UG9zPD0wO2RvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd0aW5CdG5SZWRvJykuZGlzYWJsZWQ9aGlzdFBvcz49aGlzdC5sZW5ndGgtMTt9CiAgICAgICAgd2luZG93LnRpblVuZG89ZnVuY3Rpb24oKXtpZihoaXN0UG9zPD0wKXJldHVybjtoaXN0UG9zLS07dmFyIHM9SlNPTi5wYXJzZShoaXN0W2hpc3RQb3NdKTtwdHM9cy5wO2Nvbj1zLmM7ZWRnZUZpcnN0PS0xO2RvVHJpKCk7dXBkVW5kb0J0bigpO307CiAgICAgICAgd2luZG93LnRpblJlZG89ZnVuY3Rpb24oKXtpZihoaXN0UG9zPj1oaXN0Lmxlbmd0aC0xKXJldHVybjtoaXN0UG9zKys7dmFyIHM9SlNPTi5wYXJzZShoaXN0W2hpc3RQb3NdKTtwdHM9cy5wO2Nvbj1zLmM7ZWRnZUZpcnN0PS0xO2RvVHJpKCk7dXBkVW5kb0J0bigpO307CiAgICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigna2V5ZG93bicsZnVuY3Rpb24oZSl7aWYoKGUuY3RybEtleXx8ZS5tZXRhS2V5KSYmZS5rZXk9PT0neicmJiFlLnNoaWZ0S2V5KXtlLnByZXZlbnREZWZhdWx0KCk7dGluVW5kbygpO31lbHNlIGlmKChlLmN0cmxLZXl8fGUubWV0YUtleSkmJihlLmtleT09PSd5J3x8KGUua2V5PT09J3onJiZlLnNoaWZ0S2V5KSkpe2UucHJldmVudERlZmF1bHQoKTt0aW5SZWRvKCk7fX0pOwogICAgICAgIHNhdmVIKCk7CiAgICAgICAgLyogM0QgS2FtZXJhICovCiAgICAgICAgdmFyIGNhbSA9IHsgYXo6IDAuNiwgZWw6IDAuNjUgfTsKICAgICAgICB2YXIgY2FtM0RyYWcgPSBmYWxzZSwgY2FtM0xhc3QgPSB7eDowLHk6MH07CiAgICAgICAgLyogSGlsZnNmdW5rdGlvbmVuICovCiAgICAgICAgZnVuY3Rpb24gZ3AoY3YsIGUpIHsgdmFyIHI9Y3YuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7IHJldHVybiB7eDooZS5jbGllbnRYLXIubGVmdCkqKFcvci53aWR0aCksIHk6KGUuY2xpZW50WS1yLnRvcCkqKEgvci5oZWlnaHQpfTsgfQogICAgICAgIGZ1bmN0aW9uIG5lYXJQdChweCxweSx0aHIpIHsgdmFyIGI9LTEsYmQ9dGhyKnRocjsgZm9yKHZhciBpPTA7aTxwdHMubGVuZ3RoO2krKyl7dmFyIGR4PXB0c1tpXS54LXB4LGR5PXB0c1tpXS55LXB5LGQ9ZHgqZHgrZHkqZHk7aWYoZDxiZCl7YmQ9ZDtiPWk7fX0gcmV0dXJuIGI7IH0KICAgICAgICBmdW5jdGlvbiBuZWFyQ29uKHB4LHB5LHRocikgeyB2YXIgYmk9LTEsYmQ9dGhyKnRocjsgZm9yKHZhciBpPTA7aTxjb24ubGVuZ3RoO2krKyl7dmFyIGE9Y29uW2ldWzBdLGI9Y29uW2ldWzFdO2lmKGE+PXB0cy5sZW5ndGh8fGI+PXB0cy5sZW5ndGgpY29udGludWU7dmFyIGF4PXB0c1thXS54LGF5PXB0c1thXS55LGJ4PXB0c1tiXS54LGJ5PXB0c1tiXS55LGR4PWJ4LWF4LGR5PWJ5LWF5LGwyPWR4KmR4K2R5KmR5O2lmKCFsMiljb250aW51ZTt2YXIgdD1NYXRoLm1heCgwLE1hdGgubWluKDEsKChweC1heCkqZHgrKHB5LWF5KSpkeSkvbDIpKSxjeD1heCt0KmR4LGN5PWF5K3QqZHksZDI9KHB4LWN4KSoocHgtY3gpKyhweS1jeSkqKHB5LWN5KTtpZihkMjxiZCl7YmQ9ZDI7Ymk9aTt9fSByZXR1cm4gYmk7IH0KICAgICAgICBmdW5jdGlvbiB0cmlBdChweCxweSl7aWYoIXRyaSlyZXR1cm4gLTE7dmFyIHQ9dHJpLnRyaWFuZ2xlcztmb3IodmFyIGk9MDtpPHQubGVuZ3RoO2krPTMpe3ZhciBwMD10UHRzW3RbaV1dLHAxPXRQdHNbdFtpKzFdXSxwMj10UHRzW3RbaSsyXV07dmFyIGQxPShweC1wMS54KSoocDAueS1wMS55KS0ocDAueC1wMS54KSoocHktcDEueSksZDI9KHB4LXAyLngpKihwMS55LXAyLnkpLShwMS54LXAyLngpKihweS1wMi55KSxkMz0ocHgtcDAueCkqKHAyLnktcDAueSktKHAyLngtcDAueCkqKHB5LXAwLnkpO2lmKCEoKGQxPDB8fGQyPDB8fGQzPDApJiYoZDE+MHx8ZDI+MHx8ZDM+MCkpKXJldHVybiBpLzM7fXJldHVybiAtMTt9CiAgICAgICAgLyogVHJpYW5ndWxpZXJ1bmc6IFN0ZWluZXItUHVua3RlIGVudGxhbmcgQnJ1Y2hrYW50ZW4gKyBDYXZpdHktUmUtVHJpYW5ndWxhdGlvbi4KICAgICAgICAgICBTdGVpbmVyLVB1bmt0ZSB2ZXJiZXNzZXJuIGRpZSBOZXR6cXVhbGl0w6R0IG5haGUgQnJ1Y2hrYW50ZW4uCiAgICAgICAgICAgZW5mQ29uKCkgZXJ6d2luZ3QgZGFuYWNoIGplZGUgZmVobGVuZGUgS2FudGUgcGVyIEthdml0w6R0cy1OZXV2ZXJtYXNjaHVuZy4gKi8KICAgICAgICBmdW5jdGlvbiBkb1RyaSgpIHsKICAgICAgICAgICAgaWYocHRzLmxlbmd0aDwzKXt0cmk9bnVsbDt0UHRzPXB0cy5zbGljZSgpO3RDb249Y29uLnNsaWNlKCk7ZHJhd0FsbCgpO3JldHVybjt9CiAgICAgICAgICAgIC8qIEVyd2VpdGVydGUgUHVua3RtZW5nZSBhdWZiYXVlbjogVXNlci1QdW5rdGUgKyBTdGVpbmVyICovCiAgICAgICAgICAgIHRQdHM9W107CiAgICAgICAgICAgIGZvcih2YXIgaT0wO2k8cHRzLmxlbmd0aDtpKyspIHRQdHMucHVzaCh7eDpwdHNbaV0ueCx5OnB0c1tpXS55LHo6cHRzW2ldLnp9KTsKICAgICAgICAgICAgdENvbj1bXTsKICAgICAgICAgICAgZm9yKHZhciBjaT0wO2NpPGNvbi5sZW5ndGg7Y2krKyl7CiAgICAgICAgICAgICAgICB2YXIgYT1jb25bY2ldWzBdLGI9Y29uW2NpXVsxXTsKICAgICAgICAgICAgICAgIGlmKGE+PXB0cy5sZW5ndGh8fGI+PXB0cy5sZW5ndGgpe3RDb24ucHVzaChbYSxiXSk7Y29udGludWU7fQogICAgICAgICAgICAgICAgdmFyIGR4PXB0c1tiXS54LXB0c1thXS54LGR5PXB0c1tiXS55LXB0c1thXS55OwogICAgICAgICAgICAgICAgdmFyIGRpc3Q9TWF0aC5zcXJ0KGR4KmR4K2R5KmR5KTsKICAgICAgICAgICAgICAgIHZhciBuU3ViPU1hdGgubWF4KDEsTWF0aC5jZWlsKGRpc3QvMTUpKTsKICAgICAgICAgICAgICAgIHZhciBwcmV2PWE7CiAgICAgICAgICAgICAgICBmb3IodmFyIHM9MTtzPG5TdWI7cysrKXsKICAgICAgICAgICAgICAgICAgICB2YXIgdD1zL25TdWI7CiAgICAgICAgICAgICAgICAgICAgdFB0cy5wdXNoKHt4OnB0c1thXS54K3QqZHgsIHk6cHRzW2FdLnkrdCpkeSwgejpwdHNbYV0ueit0KihwdHNbYl0uei1wdHNbYV0ueil9KTsKICAgICAgICAgICAgICAgICAgICB0Q29uLnB1c2goW3ByZXYsdFB0cy5sZW5ndGgtMV0pOwogICAgICAgICAgICAgICAgICAgIHByZXY9dFB0cy5sZW5ndGgtMTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHRDb24ucHVzaChbcHJldixiXSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdmFyIGNvPW5ldyBGbG9hdDY0QXJyYXkodFB0cy5sZW5ndGgqMik7CiAgICAgICAgICAgIGZvcih2YXIgaT0wO2k8dFB0cy5sZW5ndGg7aSsrKXtjb1syKmldPXRQdHNbaV0ueDtjb1syKmkrMV09dFB0c1tpXS55O30KICAgICAgICAgICAgdHJpPURlbGF1bmF0b3IoY28pOyBlbmZDb24oKTsgZHJhd0FsbCgpOwogICAgICAgIH0KICAgICAgICBmdW5jdGlvbiBzZWdYKGF4LGF5LGJ4LGJ5LGN4LGN5LGR4LGR5KXt2YXIgZDE9b3JpKGF4LGF5LGJ4LGJ5LGN4LGN5KSxkMj1vcmkoYXgsYXksYngsYnksZHgsZHkpLGQzPW9yaShjeCxjeSxkeCxkeSxheCxheSksZDQ9b3JpKGN4LGN5LGR4LGR5LGJ4LGJ5KTtyZXR1cm4oKGQxPjAmJmQyPDApfHwoZDE8MCYmZDI+MCkpJiYoKGQzPjAmJmQ0PDApfHwoZDM8MCYmZDQ+MCkpO30KICAgICAgICAvKiA9PT09PSBDb25zdHJhaW50LUVuZm9yY2VtZW50OiBDYXZpdHktUmUtVHJpYW5ndWxhdGlvbiA9PT09PQogICAgICAgICAgIEbDvHIgamVkZSBCcnVjaGthbnRlLCBkaWUgbmljaHQgYWxzIEthbnRlIGV4aXN0aWVydDoKICAgICAgICAgICAxLiBBbGxlIGtyZXV6ZW5kZW4gRHJlaWVja2UgZmluZGVuIHVuZCBlbnRmZXJuZW4KICAgICAgICAgICAyLiBSYW5kcG9seWdvbiBkZXIgS2F2aXTDpHQgYXVmYmF1ZW4KICAgICAgICAgICAzLiBBbiBkZW4gQnJ1Y2hrYW50ZW4tRW5kcHVua3RlbiBpbiB6d2VpIFRlaWxwb2x5Z29uZSBzcGFsdGVuCiAgICAgICAgICAgNC4gSmVkZXMgVGVpbHBvbHlnb24gcGVyIEVhci1DbGlwcGluZyBuZXUgdHJpYW5ndWxpZXJlbgogICAgICAgICAgIOKGkiBHYXJhbnRpZXJ0LCBkYXNzIGRpZSBCcnVjaGthbnRlIGFscyBLYW50ZSBleGlzdGllcnQuICovCiAgICAgICAgZnVuY3Rpb24gZW5mQ29uKCl7CiAgICAgICAgICAgIGlmKCF0cml8fCF0Q29uLmxlbmd0aClyZXR1cm47CiAgICAgICAgICAgIHZhciBucD10UHRzLmxlbmd0aDsKICAgICAgICAgICAgLyogRHJlaWVja3NsaXN0ZSBhdWZiYXVlbiAodmVyw6RuZGVybGljaCkgKi8KICAgICAgICAgICAgdmFyIHRyaXM9W107CiAgICAgICAgICAgIGZvcih2YXIgaT0wO2k8dHJpLnRyaWFuZ2xlcy5sZW5ndGg7aSs9MykKICAgICAgICAgICAgICAgIHRyaXMucHVzaChbdHJpLnRyaWFuZ2xlc1tpXSx0cmkudHJpYW5nbGVzW2krMV0sdHJpLnRyaWFuZ2xlc1tpKzJdXSk7CiAgICAgICAgICAgIGZvcih2YXIgY2k9MDtjaTx0Q29uLmxlbmd0aDtjaSsrKXsKICAgICAgICAgICAgICAgIHZhciBjYT10Q29uW2NpXVswXSxjYj10Q29uW2NpXVsxXTsKICAgICAgICAgICAgICAgIGlmKGNhPj1ucHx8Y2I+PW5wKWNvbnRpbnVlOwogICAgICAgICAgICAgICAgaWYoaGFzRWRnZSh0cmlzLGNhLGNiKSljb250aW51ZTsKICAgICAgICAgICAgICAgIHRyaXM9aW5zZXJ0Q29uKHRyaXMsY2EsY2IpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIC8qIFp1csO8Y2tzY2hyZWliZW4gKi8KICAgICAgICAgICAgdHJpLnRyaWFuZ2xlcz1uZXcgVWludDMyQXJyYXkodHJpcy5sZW5ndGgqMyk7CiAgICAgICAgICAgIGZvcih2YXIgaT0wO2k8dHJpcy5sZW5ndGg7aSsrKXsKICAgICAgICAgICAgICAgIHRyaS50cmlhbmdsZXNbaSozXT10cmlzW2ldWzBdOwogICAgICAgICAgICAgICAgdHJpLnRyaWFuZ2xlc1tpKjMrMV09dHJpc1tpXVsxXTsKICAgICAgICAgICAgICAgIHRyaS50cmlhbmdsZXNbaSozKzJdPXRyaXNbaV1bMl07CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgZnVuY3Rpb24gaGFzRWRnZSh0cmlzLGEsYil7CiAgICAgICAgICAgIGZvcih2YXIgaT0wO2k8dHJpcy5sZW5ndGg7aSsrKXt2YXIgdD10cmlzW2ldOwogICAgICAgICAgICAgICAgZm9yKHZhciBqPTA7ajwzO2orKykKICAgICAgICAgICAgICAgICAgICBpZigodFtqXT09PWEmJnRbKGorMSklM109PT1iKXx8KHRbal09PT1iJiZ0WyhqKzEpJTNdPT09YSkpcmV0dXJuIHRydWU7CiAgICAgICAgICAgIH1yZXR1cm4gZmFsc2U7CiAgICAgICAgfQogICAgICAgIGZ1bmN0aW9uIGluc2VydENvbih0cmlzLGNhLGNiKXsKICAgICAgICAgICAgdmFyIHBheD10UHRzW2NhXS54LHBheT10UHRzW2NhXS55LHBieD10UHRzW2NiXS54LHBieT10UHRzW2NiXS55OwogICAgICAgICAgICAvKiAxLiBBbGxlIERyZWllY2tlIGZpbmRlbiwgZGVyZW4gS2FudGVuIGRhcyBTZWdtZW50IGNhLWNiIGVjaHQgc2NobmVpZGVuICovCiAgICAgICAgICAgIHZhciBybT17fTsKICAgICAgICAgICAgZm9yKHZhciBpPTA7aTx0cmlzLmxlbmd0aDtpKyspe3ZhciB0PXRyaXNbaV07CiAgICAgICAgICAgICAgICB2YXIgZWQ9W1t0WzBdLHRbMV1dLFt0WzFdLHRbMl1dLFt0WzJdLHRbMF1dXTsKICAgICAgICAgICAgICAgIGZvcih2YXIgaj0wO2o8MztqKyspewogICAgICAgICAgICAgICAgICAgIHZhciBlYT1lZFtqXVswXSxlYj1lZFtqXVsxXTsKICAgICAgICAgICAgICAgICAgICBpZihlYT09PWNhfHxlYT09PWNifHxlYj09PWNhfHxlYj09PWNiKWNvbnRpbnVlOwogICAgICAgICAgICAgICAgICAgIGlmKHNlZ1gocGF4LHBheSxwYngscGJ5LHRQdHNbZWFdLngsdFB0c1tlYV0ueSx0UHRzW2ViXS54LHRQdHNbZWJdLnkpKXtybVtpXT10cnVlO2JyZWFrO30KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICBpZighT2JqZWN0LmtleXMocm0pLmxlbmd0aClyZXR1cm4gdHJpczsKICAgICAgICAgICAgLyogMi4gUmFuZGthbnRlbiBkZXIgS2F2aXTDpHQ6IEthbnRlbiBkaWUgbnVyIDHDlyBpbiBlbnRmZXJudGVuIERyZWllY2tlbiB2b3Jrb21tZW4gKi8KICAgICAgICAgICAgdmFyIGVjPXt9OwogICAgICAgICAgICBmb3IodmFyIGkgaW4gcm0pe3ZhciB0PXRyaXNbaV07CiAgICAgICAgICAgICAgICB2YXIgZWQ9W1t0WzBdLHRbMV1dLFt0WzFdLHRbMl1dLFt0WzJdLHRbMF1dXTsKICAgICAgICAgICAgICAgIGZvcih2YXIgaj0wO2o8MztqKyspewogICAgICAgICAgICAgICAgICAgIHZhciBrZXk9TWF0aC5taW4oZWRbal1bMF0sZWRbal1bMV0pKyctJytNYXRoLm1heChlZFtqXVswXSxlZFtqXVsxXSk7CiAgICAgICAgICAgICAgICAgICAgZWNba2V5XT0oZWNba2V5XXx8MCkrMTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICAvKiBHZXJpY2h0ZXRlIFJhbmRrYW50ZW4gKHVtZ2VkcmVodCDihpIgS2F2aXTDpHQgaW5uZW4pICovCiAgICAgICAgICAgIHZhciBiRWRnZXM9W107CiAgICAgICAgICAgIGZvcih2YXIgaSBpbiBybSl7dmFyIHQ9dHJpc1tpXTsKICAgICAgICAgICAgICAgIHZhciBlZD1bW3RbMF0sdFsxXV0sW3RbMV0sdFsyXV0sW3RbMl0sdFswXV1dOwogICAgICAgICAgICAgICAgZm9yKHZhciBqPTA7ajwzO2orKyl7CiAgICAgICAgICAgICAgICAgICAgdmFyIGtleT1NYXRoLm1pbihlZFtqXVswXSxlZFtqXVsxXSkrJy0nK01hdGgubWF4KGVkW2pdWzBdLGVkW2pdWzFdKTsKICAgICAgICAgICAgICAgICAgICBpZihlY1trZXldPT09MSliRWRnZXMucHVzaChbZWRbal1bMV0sZWRbal1bMF1dKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICAvKiAzLiBSYW5kcG9seWdvbiB2ZXJrZXR0ZW4gKi8KICAgICAgICAgICAgdmFyIG54dD17fTsKICAgICAgICAgICAgZm9yKHZhciBpPTA7aTxiRWRnZXMubGVuZ3RoO2krKylueHRbYkVkZ2VzW2ldWzBdXT1iRWRnZXNbaV1bMV07CiAgICAgICAgICAgIHZhciBzdGFydD1iRWRnZXNbMF1bMF0scG9seT1bc3RhcnRdLGN1cj1ueHRbc3RhcnRdLHNhZmU9NTAwOwogICAgICAgICAgICB3aGlsZShjdXIhPT11bmRlZmluZWQmJmN1ciE9PXN0YXJ0JiYoc2FmZS0tKT4wKXtwb2x5LnB1c2goY3VyKTtjdXI9bnh0W2N1cl07fQogICAgICAgICAgICB2YXIgaWE9cG9seS5pbmRleE9mKGNhKSxpYj1wb2x5LmluZGV4T2YoY2IpOwogICAgICAgICAgICBpZihpYT09PS0xfHxpYj09PS0xKXJldHVybiB0cmlzOyAvKiBGYWxsYmFjazogbmljaHQgw6RuZGVybiAqLwogICAgICAgICAgICAvKiA0LiBJbiB6d2VpIFRlaWxwb2x5Z29uZSBzcGFsdGVuICovCiAgICAgICAgICAgIHZhciBuPXBvbHkubGVuZ3RoLHAxPVtdLHAyPVtdOwogICAgICAgICAgICBmb3IodmFyIGlkeD1pYTs7KXtwMS5wdXNoKHBvbHlbaWR4XSk7aWYoaWR4PT09aWIpYnJlYWs7aWR4PShpZHgrMSklbjt9CiAgICAgICAgICAgIGZvcih2YXIgaWR4PWliOzspe3AyLnB1c2gocG9seVtpZHhdKTtpZihpZHg9PT1pYSlicmVhaztpZHg9KGlkeCsxKSVuO30KICAgICAgICAgICAgLyogNS4gRWFyLUNsaXBwaW5nIGbDvHIgamVkZXMgVGVpbHBvbHlnb24gKi8KICAgICAgICAgICAgdmFyIG5ld1Q9W107CiAgICAgICAgICAgIGlmKHAxLmxlbmd0aD49MyllYXJDbGlwKHAxLG5ld1QpOwogICAgICAgICAgICBpZihwMi5sZW5ndGg+PTMpZWFyQ2xpcChwMixuZXdUKTsKICAgICAgICAgICAgLyogQWx0ZSBEcmVpZWNrZSByYXVzLCBuZXVlIHJlaW4gKi8KICAgICAgICAgICAgdmFyIHJlcz1bXTsKICAgICAgICAgICAgZm9yKHZhciBpPTA7aTx0cmlzLmxlbmd0aDtpKyspaWYoIXJtW2ldKXJlcy5wdXNoKHRyaXNbaV0pOwogICAgICAgICAgICBmb3IodmFyIGk9MDtpPG5ld1QubGVuZ3RoO2krKylyZXMucHVzaChuZXdUW2ldKTsKICAgICAgICAgICAgcmV0dXJuIHJlczsKICAgICAgICB9CiAgICAgICAgLyogRWFyLUNsaXBwaW5nLVRyaWFuZ3VsYXRpb24gZsO8ciBlaW5mYWNoZSBQb2x5Z29uZSAqLwogICAgICAgIGZ1bmN0aW9uIGVhckNsaXAocG9seSxvdXQpewogICAgICAgICAgICBpZihwb2x5Lmxlbmd0aDwzKXJldHVybjsKICAgICAgICAgICAgdmFyIGFyZWE9MDsKICAgICAgICAgICAgZm9yKHZhciBpPTA7aTxwb2x5Lmxlbmd0aDtpKyspe3ZhciBqPShpKzEpJXBvbHkubGVuZ3RoOwogICAgICAgICAgICAgICAgYXJlYSs9dFB0c1twb2x5W2ldXS54KnRQdHNbcG9seVtqXV0ueS10UHRzW3BvbHlbal1dLngqdFB0c1twb2x5W2ldXS55O30KICAgICAgICAgICAgdmFyIGNjdz1hcmVhPjA7CiAgICAgICAgICAgIHZhciByZW09cG9seS5zbGljZSgpLHNhZmU9cmVtLmxlbmd0aCpyZW0ubGVuZ3RoOwogICAgICAgICAgICB3aGlsZShyZW0ubGVuZ3RoPjMmJihzYWZlLS0pPjApewogICAgICAgICAgICAgICAgdmFyIGZvdW5kPWZhbHNlOwogICAgICAgICAgICAgICAgZm9yKHZhciBpPTA7aTxyZW0ubGVuZ3RoO2krKyl7CiAgICAgICAgICAgICAgICAgICAgdmFyIHByZXY9KGkrcmVtLmxlbmd0aC0xKSVyZW0ubGVuZ3RoLG5leHQ9KGkrMSklcmVtLmxlbmd0aDsKICAgICAgICAgICAgICAgICAgICB2YXIgYT1yZW1bcHJldl0sYj1yZW1baV0sYz1yZW1bbmV4dF07CiAgICAgICAgICAgICAgICAgICAgdmFyIGNyb3NzPW9yaSh0UHRzW2FdLngsdFB0c1thXS55LHRQdHNbYl0ueCx0UHRzW2JdLnksdFB0c1tjXS54LHRQdHNbY10ueSk7CiAgICAgICAgICAgICAgICAgICAgaWYoY2N3P2Nyb3NzPD0wOmNyb3NzPj0wKWNvbnRpbnVlOyAvKiBuaWNodCBrb252ZXgg4oaSIGtlaW4gT2hyICovCiAgICAgICAgICAgICAgICAgICAgdmFyIG9rPXRydWU7CiAgICAgICAgICAgICAgICAgICAgZm9yKHZhciBqPTA7ajxyZW0ubGVuZ3RoO2orKyl7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmKGo9PT1wcmV2fHxqPT09aXx8aj09PW5leHQpY29udGludWU7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmKHB0SW5UcmkyKHJlbVtqXSxhLGIsYykpe29rPWZhbHNlO2JyZWFrO30KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgaWYoIW9rKWNvbnRpbnVlOwogICAgICAgICAgICAgICAgICAgIG91dC5wdXNoKFthLGIsY10pO3JlbS5zcGxpY2UoaSwxKTtmb3VuZD10cnVlO2JyZWFrOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaWYoIWZvdW5kKWJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmKHJlbS5sZW5ndGg9PT0zKW91dC5wdXNoKFtyZW1bMF0scmVtWzFdLHJlbVsyXV0pOwogICAgICAgIH0KICAgICAgICBmdW5jdGlvbiBwdEluVHJpMihwLGEsYixjKXsKICAgICAgICAgICAgdmFyIHB4PXRQdHNbcF0ueCxweT10UHRzW3BdLnk7CiAgICAgICAgICAgIHZhciBkMT1vcmkodFB0c1thXS54LHRQdHNbYV0ueSx0UHRzW2JdLngsdFB0c1tiXS55LHB4LHB5KTsKICAgICAgICAgICAgdmFyIGQyPW9yaSh0UHRzW2JdLngsdFB0c1tiXS55LHRQdHNbY10ueCx0UHRzW2NdLnkscHgscHkpOwogICAgICAgICAgICB2YXIgZDM9b3JpKHRQdHNbY10ueCx0UHRzW2NdLnksdFB0c1thXS54LHRQdHNbYV0ueSxweCxweSk7CiAgICAgICAgICAgIHJldHVybiAhKCgoZDE8MCl8fChkMjwwKXx8KGQzPDApKSYmKChkMT4wKXx8KGQyPjApfHwoZDM+MCkpKTsKICAgICAgICB9CiAgICAgICAgLyogRmFyYmVuICovCiAgICAgICAgZnVuY3Rpb24gelJhbmdlKCl7dmFyIG1uPUluZmluaXR5LG14PS1JbmZpbml0eSxycD10UHRzLmxlbmd0aD90UHRzOnB0cztmb3IodmFyIGk9MDtpPHJwLmxlbmd0aDtpKyspe2lmKHJwW2ldLno8bW4pbW49cnBbaV0uejtpZihycFtpXS56Pm14KW14PXJwW2ldLno7fXJldHVybnttaW46bW4sbWF4Om14LHJhbmdlOk1hdGgubWF4KG14LW1uLDEpfTt9CiAgICAgICAgZnVuY3Rpb24gaENvbCh6LHpyKXt2YXIgdD0oei16ci5taW4pL3pyLnJhbmdlO2lmKHQ8MC4zMylyZXR1cm4gbGVycChbNDAsODAsMTYwXSxbNjAsMTgwLDEyMF0sdC8wLjMzKTtpZih0PDAuNjYpcmV0dXJuIGxlcnAoWzYwLDE4MCwxMjBdLFsyMDAsMTgwLDYwXSwodC0wLjMzKS8wLjMzKTtyZXR1cm4gbGVycChbMjAwLDE4MCw2MF0sWzE0MCw4MCw0MF0sKHQtMC42NikvMC4zNCk7fQogICAgICAgIGZ1bmN0aW9uIHNDb2woaTAsaTEsaTIsenIpe3ZhciBycD10UHRzLmxlbmd0aD90UHRzOnB0czt2YXIgcj16ci5yYW5nZXx8MTt2YXIgZD1NYXRoLm1heChNYXRoLmFicyhycFtpMF0uei1ycFtpMV0ueiksTWF0aC5hYnMocnBbaTFdLnotcnBbaTJdLnopLE1hdGguYWJzKHJwW2kwXS56LXJwW2kyXS56KSkvcjtyZXR1cm4gbGVycChbNjAsMTgwLDYwXSxbMjIwLDQwLDQwXSxNYXRoLm1pbihkKjMsMSkpO30KICAgICAgICBmdW5jdGlvbiBsZXJwKGEsYix0KXt0PU1hdGgubWF4KDAsTWF0aC5taW4oMSx0KSk7cmV0dXJuJ3JnYignK01hdGgucm91bmQoYVswXSsoYlswXS1hWzBdKSp0KSsnLCcrTWF0aC5yb3VuZChhWzFdKyhiWzFdLWFbMV0pKnQpKycsJytNYXRoLnJvdW5kKGFbMl0rKGJbMl0tYVsyXSkqdCkrJyknO30KICAgICAgICAvKiBBdXRvLUjDtmhlOiBNaXR0ZSBob2NoLCBSYW5kIG5pZWRyaWcg4oCUIHNpbXVsaWVydCBuYXTDvHJsaWNoZXMgR2Vsw6RuZGUgKi8KICAgICAgICBmdW5jdGlvbiBhdXRvWihweCxweSl7CiAgICAgICAgICAgIHZhciBjeD1XLzIsY3k9SC8yOwogICAgICAgICAgICB2YXIgZHg9KHB4LWN4KS9jeCwgZHk9KHB5LWN5KS9jeTsKICAgICAgICAgICAgdmFyIGRpc3Q9TWF0aC5zcXJ0KGR4KmR4K2R5KmR5KTsgLyogMCA9IE1pdHRlLCB+MS40ID0gRWNrZSAqLwogICAgICAgICAgICB2YXIgYmFzZT0xMDArOCooMS1NYXRoLm1pbihkaXN0LDEuMikpOyAvKiAxMDAgYW0gUmFuZCwgMTA4IGluIGRlciBNaXR0ZSAqLwogICAgICAgICAgICB2YXIgbm9pc2U9KE1hdGguc2luKHB4KjAuMDUpKk1hdGguY29zKHB5KjAuMDcpK01hdGguc2luKHB4KjAuMDMrcHkqMC4wNCkpKjEuNTsKICAgICAgICAgICAgcmV0dXJuIE1hdGgucm91bmQoKGJhc2Urbm9pc2UpKjEwKS8xMDsKICAgICAgICB9CiAgICAgICAgLyogMkQgWmVpY2huZW4gKi8KICAgICAgICBmdW5jdGlvbiBkcmF3MkQoKXsKICAgICAgICAgICAgeDIuc2F2ZSgpOyB4Mi5jbGVhclJlY3QoMCwwLFcsSCk7CiAgICAgICAgICAgIGlmKCF0cml8fCF0cmkudHJpYW5nbGVzLmxlbmd0aCl7eDIucmVzdG9yZSgpO2RyYXdQdHMyRCgpO3JldHVybjt9CiAgICAgICAgICAgIHZhciB0PXRyaS50cmlhbmdsZXMsIHpyPXpSYW5nZSgpLCBycD10UHRzOwogICAgICAgICAgICAvKiBGw7xsbHVuZyAqLwogICAgICAgICAgICBpZih2aWV3TW9kZSE9PSd3aXJlJyYmdmlld01vZGUhPT0nY29udG91cicpewogICAgICAgICAgICAgICAgZm9yKHZhciBpPTA7aTx0Lmxlbmd0aDtpKz0zKXsKICAgICAgICAgICAgICAgICAgICB2YXIgcDA9cnBbdFtpXV0scDE9cnBbdFtpKzFdXSxwMj1ycFt0W2krMl1dOwogICAgICAgICAgICAgICAgICAgIHgyLmJlZ2luUGF0aCgpO3gyLm1vdmVUbyhwMC54LHAwLnkpO3gyLmxpbmVUbyhwMS54LHAxLnkpO3gyLmxpbmVUbyhwMi54LHAyLnkpO3gyLmNsb3NlUGF0aCgpOwogICAgICAgICAgICAgICAgICAgIHgyLmZpbGxTdHlsZT12aWV3TW9kZT09PSdoZWlnaHQnP2hDb2woKHAwLnorcDEueitwMi56KS8zLHpyKTpzQ29sKHRbaV0sdFtpKzFdLHRbaSsyXSx6cik7CiAgICAgICAgICAgICAgICAgICAgeDIuZ2xvYmFsQWxwaGE9MC41NTt4Mi5maWxsKCk7eDIuZ2xvYmFsQWxwaGE9MTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICAvKiBIb3ZlciAqLwogICAgICAgICAgICBpZihob3ZlclRyaT49MCYmaG92ZXJUcmkqMzx0Lmxlbmd0aCl7CiAgICAgICAgICAgICAgICB2YXIgaGk9aG92ZXJUcmkqMyxwMD1ycFt0W2hpXV0scDE9cnBbdFtoaSsxXV0scDI9cnBbdFtoaSsyXV07CiAgICAgICAgICAgICAgICB4Mi5iZWdpblBhdGgoKTt4Mi5tb3ZlVG8ocDAueCxwMC55KTt4Mi5saW5lVG8ocDEueCxwMS55KTt4Mi5saW5lVG8ocDIueCxwMi55KTt4Mi5jbG9zZVBhdGgoKTsKICAgICAgICAgICAgICAgIHgyLmZpbGxTdHlsZT0nIzNmNWY3NSc7eDIuZ2xvYmFsQWxwaGE9MC4xMjt4Mi5maWxsKCk7eDIuZ2xvYmFsQWxwaGE9MTsKICAgICAgICAgICAgfQogICAgICAgICAgICAvKiBLYW50ZW4g4oCUIHRDb24gZW50aMOkbHQgZGllIFN0ZWluZXItU2VnbWVudGUgKi8KICAgICAgICAgICAgdmFyIGNzPXt9O2Zvcih2YXIgYz0wO2M8dENvbi5sZW5ndGg7YysrKXt2YXIgaz1NYXRoLm1pbih0Q29uW2NdWzBdLHRDb25bY11bMV0pKyctJytNYXRoLm1heCh0Q29uW2NdWzBdLHRDb25bY11bMV0pO2NzW2tdPXRydWU7fQogICAgICAgICAgICB4Mi5saW5lV2lkdGg9MS4yO3gyLnN0cm9rZVN0eWxlPScjOTRhM2I4JzsKICAgICAgICAgICAgZm9yKHZhciBpPTA7aTx0Lmxlbmd0aDtpKz0zKWZvcih2YXIgaj0wO2o8MztqKyspe3ZhciBhPXRbaStqXSxiPXRbaSsoaisxKSUzXTtpZihjc1tNYXRoLm1pbihhLGIpKyctJytNYXRoLm1heChhLGIpXSljb250aW51ZTt4Mi5iZWdpblBhdGgoKTt4Mi5tb3ZlVG8ocnBbYV0ueCxycFthXS55KTt4Mi5saW5lVG8ocnBbYl0ueCxycFtiXS55KTt4Mi5zdHJva2UoKTt9CiAgICAgICAgICAgIC8qIEJydWNoa2FudGVuICovCiAgICAgICAgICAgIHgyLmxpbmVXaWR0aD0zO3gyLnN0cm9rZVN0eWxlPScjZTExZDQ4JzsKICAgICAgICAgICAgZm9yKHZhciBjPTA7Yzxjb24ubGVuZ3RoO2MrKyl7dmFyIGE9Y29uW2NdWzBdLGI9Y29uW2NdWzFdO2lmKGE8cHRzLmxlbmd0aCYmYjxwdHMubGVuZ3RoKXt4Mi5iZWdpblBhdGgoKTt4Mi5tb3ZlVG8ocHRzW2FdLngscHRzW2FdLnkpO3gyLmxpbmVUbyhwdHNbYl0ueCxwdHNbYl0ueSk7eDIuc3Ryb2tlKCk7fX0KICAgICAgICAgICAgLyogSMO2aGVubGluaWVuICovCiAgICAgICAgICAgIGlmKHZpZXdNb2RlPT09J2NvbnRvdXInKSBkcmF3Q29udG91cih4Mix6cik7CiAgICAgICAgICAgIC8qIFVta3JlaXNlICovCiAgICAgICAgICAgIGlmKHNob3dDaXJjdW0pIGRyYXdDaXJjKHgyKTsKICAgICAgICAgICAgeDIucmVzdG9yZSgpOwogICAgICAgICAgICBkcmF3UHRzMkQoKTsKICAgICAgICB9CiAgICAgICAgZnVuY3Rpb24gZHJhd1B0czJEKCl7CiAgICAgICAgICAgIGZvcih2YXIgaT0wO2k8cHRzLmxlbmd0aDtpKyspewogICAgICAgICAgICAgICAgeDIuYmVnaW5QYXRoKCk7eDIuYXJjKHB0c1tpXS54LHB0c1tpXS55LDYsMCxNYXRoLlBJKjIpOwogICAgICAgICAgICAgICAgeDIuZmlsbFN0eWxlPShlZGdlRmlyc3Q9PT1pKT8nI2UxMWQ0OCc6KGRyYWdJZHg9PT1pPycjMWQ0ZWQ4JzonIzI1NjNlYicpOwogICAgICAgICAgICAgICAgeDIuZmlsbCgpO3gyLmxpbmVXaWR0aD0yO3gyLnN0cm9rZVN0eWxlPScjZmZmJzt4Mi5zdHJva2UoKTsKICAgICAgICAgICAgICAgIC8qIFotTGFiZWwgKi8KICAgICAgICAgICAgICAgIHgyLmZpbGxTdHlsZT0nIzFlMjkzYic7eDIuZm9udD0nYm9sZCA5cHggc2Fucy1zZXJpZic7eDIudGV4dEFsaWduPSdjZW50ZXInOwogICAgICAgICAgICAgICAgeDIuZmlsbFRleHQoTWF0aC5yb3VuZChwdHNbaV0ueikscHRzW2ldLngscHRzW2ldLnktMTApOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGZ1bmN0aW9uIGRyYXdDb250b3VyKGN0eCx6cil7CiAgICAgICAgICAgIGlmKCF0cmkpcmV0dXJuO3ZhciB0PXRyaS50cmlhbmdsZXMscnA9dFB0czsKICAgICAgICAgICAgdmFyIGludGVydmFsPSh6ci5yYW5nZSkvMTA7IGlmKGludGVydmFsPDEpaW50ZXJ2YWw9MTsKICAgICAgICAgICAgY3R4LnNhdmUoKTsKICAgICAgICAgICAgZm9yKHZhciBsZXY9TWF0aC5jZWlsKHpyLm1pbi9pbnRlcnZhbCkqaW50ZXJ2YWw7bGV2PD16ci5tYXg7bGV2Kz1pbnRlcnZhbCl7CiAgICAgICAgICAgICAgICB2YXIgbWFqb3I9TWF0aC5yb3VuZChsZXYvaW50ZXJ2YWwpJTU9PT0wOwogICAgICAgICAgICAgICAgY3R4LmxpbmVXaWR0aD1tYWpvcj8xLjg6MC44O2N0eC5zdHJva2VTdHlsZT1tYWpvcj8nIzJjNGE1ZSc6JyM2NDc0OGInO2N0eC5nbG9iYWxBbHBoYT1tYWpvcj8wLjc6MC40OwogICAgICAgICAgICAgICAgY3R4LmJlZ2luUGF0aCgpOwogICAgICAgICAgICAgICAgZm9yKHZhciBpPTA7aTx0Lmxlbmd0aDtpKz0zKXsKICAgICAgICAgICAgICAgICAgICB2YXIgdnM9W3JwW3RbaV1dLHJwW3RbaSsxXV0scnBbdFtpKzJdXV0sY3I9W107CiAgICAgICAgICAgICAgICAgICAgZm9yKHZhciBqPTA7ajwzO2orKyl7dmFyIHZhPXZzW2pdLHZiPXZzWyhqKzEpJTNdOwogICAgICAgICAgICAgICAgICAgICAgICBpZigodmEuejw9bGV2JiZ2Yi56Pmxldil8fCh2Yi56PD1sZXYmJnZhLno+bGV2KSl7dmFyIHR0PShsZXYtdmEueikvKHZiLnotdmEueik7Y3IucHVzaCh7eDp2YS54K3R0Kih2Yi54LXZhLngpLHk6dmEueSt0dCoodmIueS12YS55KX0pO319CiAgICAgICAgICAgICAgICAgICAgaWYoY3IubGVuZ3RoPT09Mil7Y3R4Lm1vdmVUbyhjclswXS54LGNyWzBdLnkpO2N0eC5saW5lVG8oY3JbMV0ueCxjclsxXS55KTt9CiAgICAgICAgICAgICAgICB9Y3R4LnN0cm9rZSgpOwogICAgICAgICAgICB9Y3R4LnJlc3RvcmUoKTsKICAgICAgICB9CiAgICAgICAgZnVuY3Rpb24gZHJhd0NpcmMoY3R4KXsKICAgICAgICAgICAgaWYoIXRyaSlyZXR1cm47dmFyIHQ9dHJpLnRyaWFuZ2xlcyxycD10UHRzOwogICAgICAgICAgICBjdHguc2F2ZSgpO2N0eC5zZXRMaW5lRGFzaChbNCw0XSk7Y3R4LmxpbmVXaWR0aD0xO2N0eC5zdHJva2VTdHlsZT0nIzNmNWY3NSc7CiAgICAgICAgICAgIHZhciBzaT1ob3ZlclRyaT49MD9ob3ZlclRyaSozOjAsZWk9aG92ZXJUcmk+PTA\/aG92ZXJUcmkqMyszOnQubGVuZ3RoOwogICAgICAgICAgICBmb3IodmFyIGk9c2k7aTxlaTtpKz0zKXsKICAgICAgICAgICAgICAgIHZhciBwMD1ycFt0W2ldXSxwMT1ycFt0W2krMV1dLHAyPXJwW3RbaSsyXV07CiAgICAgICAgICAgICAgICB2YXIgZGV0PTIqKChwMC54LXAyLngpKihwMS55LXAyLnkpLShwMS54LXAyLngpKihwMC55LXAyLnkpKTtpZihNYXRoLmFicyhkZXQpPDFlLTEwKWNvbnRpbnVlOwogICAgICAgICAgICAgICAgdmFyIGN0PWNjdHIocDAueCxwMC55LHAxLngscDEueSxwMi54LHAyLnkpLHI9TWF0aC5zcXJ0KGRzdChjdC54LGN0LnkscDAueCxwMC55KSk7CiAgICAgICAgICAgICAgICBjdHguZ2xvYmFsQWxwaGE9KGhvdmVyVHJpPj0wJiZpPT09aG92ZXJUcmkqMyk\/MC42OjAuMjsKICAgICAgICAgICAgICAgIGN0eC5iZWdpblBhdGgoKTtjdHguYXJjKGN0LngsY3QueSxyLDAsTWF0aC5QSSoyKTtjdHguc3Ryb2tlKCk7CiAgICAgICAgICAgIH1jdHgucmVzdG9yZSgpOwogICAgICAgIH0KICAgICAgICAvKiAzRCBaZWljaG5lbiAqLwogICAgICAgIGZ1bmN0aW9uIGRyYXczRCgpewogICAgICAgICAgICB4My5zYXZlKCk7eDMuY2xlYXJSZWN0KDAsMCxXLEgpOwogICAgICAgICAgICBpZighdHJpfHwhdHJpLnRyaWFuZ2xlcy5sZW5ndGgpe3gzLmZpbGxTdHlsZT0nIzY0NzQ4Yic7eDMuZm9udD0nMTNweCBzYW5zLXNlcmlmJzt4My50ZXh0QWxpZ249J2NlbnRlcic7eDMuZmlsbFRleHQoJ01pbmRlc3RlbnMgMyBQdW5rdGUgZsO8ciAzRC1BbnNpY2h0JyxXLzIsSC8yKTt4My5yZXN0b3JlKCk7cmV0dXJuO30KICAgICAgICAgICAgdmFyIHQ9dHJpLnRyaWFuZ2xlcyx6cj16UmFuZ2UoKTsKICAgICAgICAgICAgdmFyIHpzPXBhcnNlRmxvYXQoZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3RpblpTY2FsZScpLnZhbHVlKS8xMDsKICAgICAgICAgICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3RpblpTY2FsZVZhbCcpLnRleHRDb250ZW50PXpzLnRvRml4ZWQoMSkrJ8OXJzsKICAgICAgICAgICAgLyogUHJvamVrdGlvbiAqLwogICAgICAgICAgICB2YXIgY3g9Vy8yLGN5PUgvMjsKICAgICAgICAgICAgdmFyIGNhPU1hdGguY29zKGNhbS5heiksc2E9TWF0aC5zaW4oY2FtLmF6KSxjZT1NYXRoLmNvcyhjYW0uZWwpLHNlPU1hdGguc2luKGNhbS5lbCk7CiAgICAgICAgICAgIHZhciB6bWlkPSh6ci5taW4renIubWF4KS8yOwogICAgICAgICAgICB2YXIgc2M9TWF0aC5taW4oVyxIKSowLjAwMjg7CiAgICAgICAgICAgIC8qIEF1dG8tU2thbGllcnVuZzogWi1CZXJlaWNoIHNvbGwgfjI1JSBkZXIgWFktQXVzZGVobnVuZyBlbnRzcHJlY2hlbiAqLwogICAgICAgICAgICB2YXIgcnA9dFB0cyx4TWluPUluZmluaXR5LHhNYXg9LUluZmluaXR5LHlNaW49SW5maW5pdHkseU1heD0tSW5maW5pdHk7CiAgICAgICAgICAgIGZvcih2YXIgaT0wO2k8cnAubGVuZ3RoO2krKyl7aWYocnBbaV0ueDx4TWluKXhNaW49cnBbaV0ueDtpZihycFtpXS54PnhNYXgpeE1heD1ycFtpXS54O2lmKHJwW2ldLnk8eU1pbil5TWluPXJwW2ldLnk7aWYocnBbaV0ueT55TWF4KXlNYXg9cnBbaV0ueTt9CiAgICAgICAgICAgIHZhciB4eUV4dD1NYXRoLm1heCh4TWF4LXhNaW4seU1heC15TWluLDEpOwogICAgICAgICAgICB2YXIgYXV0b1oyPSh6ci5yYW5nZT4wLjAwMSk\/eHlFeHQvenIucmFuZ2UqMC4yNToxOwogICAgICAgICAgICBmdW5jdGlvbiBwcm9qKHApewogICAgICAgICAgICAgICAgdmFyIHB4PShwLngtY3gpLHB5PS0ocC55LWN5KSxwej0ocC56LXptaWQpKnpzKmF1dG9aMjsKICAgICAgICAgICAgICAgIHZhciByeD1weCpjYS1weSpzYSwgcnk9cHgqc2ErcHkqY2E7CiAgICAgICAgICAgICAgICB2YXIgZnk9cnkqY2UrcHoqc2UsIGZ6PXJ5KnNlLXB6KmNlOwogICAgICAgICAgICAgICAgcmV0dXJue3g6Vy8yK3J4KnNjLHk6SC8yLWZ5KnNjLGQ6Znp9OwogICAgICAgICAgICB9CiAgICAgICAgICAgIC8qIERyZWllY2tlIHNvcnRpZXJlbiAoUGFpbnRlcidzIEFsZ29yaXRobSkgKi8KICAgICAgICAgICAgdmFyIHRyaXM9W107CiAgICAgICAgICAgIGZvcih2YXIgaT0wO2k8dC5sZW5ndGg7aSs9Myl7CiAgICAgICAgICAgICAgICB2YXIgcDA9cHJvaihycFt0W2ldXSkscDE9cHJvaihycFt0W2krMV1dKSxwMj1wcm9qKHJwW3RbaSsyXV0pOwogICAgICAgICAgICAgICAgdHJpcy5wdXNoKHtwOltwMCxwMSxwMl0saTppLGQ6KHAwLmQrcDEuZCtwMi5kKS8zfSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdHJpcy5zb3J0KGZ1bmN0aW9uKGEsYil7cmV0dXJuIGEuZC1iLmQ7fSk7CiAgICAgICAgICAgIC8qIFplaWNobmVuICovCiAgICAgICAgICAgIHZhciBjcz17fTtmb3IodmFyIGM9MDtjPHRDb24ubGVuZ3RoO2MrKyl7Y3NbTWF0aC5taW4odENvbltjXVswXSx0Q29uW2NdWzFdKSsnLScrTWF0aC5tYXgodENvbltjXVswXSx0Q29uW2NdWzFdKV09dHJ1ZTt9CiAgICAgICAgICAgIGZvcih2YXIgaT0wO2k8dHJpcy5sZW5ndGg7aSsrKXsKICAgICAgICAgICAgICAgIHZhciB0cj10cmlzW2ldLHBwPXRyLnAsdGk9dHIuaTsKICAgICAgICAgICAgICAgIHgzLmJlZ2luUGF0aCgpO3gzLm1vdmVUbyhwcFswXS54LHBwWzBdLnkpO3gzLmxpbmVUbyhwcFsxXS54LHBwWzFdLnkpO3gzLmxpbmVUbyhwcFsyXS54LHBwWzJdLnkpO3gzLmNsb3NlUGF0aCgpOwogICAgICAgICAgICAgICAgLyogRsO8bGx1bmcgaW1tZXIgbWl0IEjDtmhlbmZhcmJlbiBpbiAzRCAqLwogICAgICAgICAgICAgICAgeDMuZmlsbFN0eWxlPWhDb2woKHJwW3RbdGldXS56K3JwW3RbdGkrMV1dLnorcnBbdFt0aSsyXV0ueikvMyx6cik7CiAgICAgICAgICAgICAgICB4My5nbG9iYWxBbHBoYT0wLjg7eDMuZmlsbCgpO3gzLmdsb2JhbEFscGhhPTE7CiAgICAgICAgICAgICAgICAvKiBLYW50ZW4gKi8KICAgICAgICAgICAgICAgIHgzLmxpbmVXaWR0aD0wLjg7eDMuc3Ryb2tlU3R5bGU9J3JnYmEoMzAsNTMsNzIsMC4zKSc7eDMuc3Ryb2tlKCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgLyogQnJ1Y2hrYW50ZW4gaW4gM0QgKi8KICAgICAgICAgICAgeDMubGluZVdpZHRoPTIuNTt4My5zdHJva2VTdHlsZT0nI2UxMWQ0OCc7CiAgICAgICAgICAgIGZvcih2YXIgYz0wO2M8Y29uLmxlbmd0aDtjKyspewogICAgICAgICAgICAgICAgdmFyIGE9Y29uW2NdWzBdLGI9Y29uW2NdWzFdO2lmKGE+PXB0cy5sZW5ndGh8fGI+PXB0cy5sZW5ndGgpY29udGludWU7CiAgICAgICAgICAgICAgICB2YXIgcGE9cHJvaihwdHNbYV0pLHBiPXByb2oocHRzW2JdKTsKICAgICAgICAgICAgICAgIHgzLmJlZ2luUGF0aCgpO3gzLm1vdmVUbyhwYS54LHBhLnkpO3gzLmxpbmVUbyhwYi54LHBiLnkpO3gzLnN0cm9rZSgpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIC8qIFB1bmt0ZSBpbiAzRCAqLwogICAgICAgICAgICBmb3IodmFyIGk9MDtpPHB0cy5sZW5ndGg7aSsrKXsKICAgICAgICAgICAgICAgIHZhciBwcD1wcm9qKHB0c1tpXSk7CiAgICAgICAgICAgICAgICB4My5iZWdpblBhdGgoKTt4My5hcmMocHAueCxwcC55LDQsMCxNYXRoLlBJKjIpOwogICAgICAgICAgICAgICAgeDMuZmlsbFN0eWxlPScjMjU2M2ViJzt4My5maWxsKCk7eDMubGluZVdpZHRoPTEuNTt4My5zdHJva2VTdHlsZT0nI2ZmZic7eDMuc3Ryb2tlKCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgLyogVmlld0N1YmUgKi8KICAgICAgICAgICAgZHJhd1ZpZXdDdWJlKHgzKTsKICAgICAgICAgICAgeDMucmVzdG9yZSgpOwogICAgICAgIH0KICAgICAgICAvKiA9PT09PSBWaWV3Q3ViZSA9PT09PSAqLwogICAgICAgIGZ1bmN0aW9uIGRyYXdWaWV3Q3ViZShjdHgpewogICAgICAgICAgICB2YXIgc3o9MzgsIG14PVctc3otMTIsIG15PXN6KzEyOwogICAgICAgICAgICB2YXIgY2E9TWF0aC5jb3MoY2FtLmF6KSxzYT1NYXRoLnNpbihjYW0uYXopLGNlPU1hdGguY29zKGNhbS5lbCksc2U9TWF0aC5zaW4oY2FtLmVsKTsKICAgICAgICAgICAgdmFyIHM9c3oqMC40ODsKICAgICAgICAgICAgLyogOCBFY2twdW5rdGUgWy0xLi4xXcKzICBYPWxpbmtzL3JlY2h0cywgWT12b3JuZS9oaW50ZW4sIFo9b2Jlbi91bnRlbiAqLwogICAgICAgICAgICB2YXIgdmVydHM9W1stMSwtMSwtMV0sWzEsLTEsLTFdLFsxLDEsLTFdLFstMSwxLC0xXSwKICAgICAgICAgICAgICAgICAgICAgICBbLTEsLTEsIDFdLFsxLC0xLCAxXSxbMSwxLCAxXSxbLTEsMSwgMV1dOwogICAgICAgICAgICBmdW5jdGlvbiBwaih2KXsKICAgICAgICAgICAgICAgIHZhciBweD12WzBdKnMscHk9dlsxXSpzLHB6PXZbMl0qczsKICAgICAgICAgICAgICAgIHZhciByeD1weCpjYS1weSpzYSwgcnk9cHgqc2ErcHkqY2E7CiAgICAgICAgICAgICAgICB2YXIgZnk9cnkqY2UrcHoqc2UsIGZ6PXJ5KnNlLXB6KmNlOwogICAgICAgICAgICAgICAgcmV0dXJue3g6bXgrcngsIHk6bXktZnksIGQ6Znp9OwogICAgICAgICAgICB9CiAgICAgICAgICAgIHZhciBwdj1bXTtmb3IodmFyIGk9MDtpPDg7aSsrKXB2LnB1c2gocGoodmVydHNbaV0pKTsKICAgICAgICAgICAgLyogNiBGbMOkY2hlbjogaWR4KDQgRWNrcHVua3RlKSwgTGFiZWwsIEZhcmJlLCBLYW1lcmEtWmllbCAoYXosZWwpICovCiAgICAgICAgICAgIHZhciBmYWNlcz1bCiAgICAgICAgICAgICAgICB7aWR4OlswLDEsMiwzXSxsYmw6J1YnLCBjOicjZGJlNGVkJyxhejowLCAgICBlbDowLjA4fSwgICAgLyogVm9ybmUgIFk9LTEgKi8KICAgICAgICAgICAgICAgIHtpZHg6WzUsNCw3LDZdLGxibDonSCcsIGM6JyNkYmU0ZWQnLGF6Ok1hdGguUEksZWw6MC4wOH0sICAvKiBIaW50ZW4gWT0rMSAqLwogICAgICAgICAgICAgICAge2lkeDpbNCwwLDMsN10sbGJsOidMJywgYzonI2UwZGJlOCcsYXo6LTEuNTcsIGVsOjAuMDh9LCAgIC8qIExpbmtzICBYPS0xICovCiAgICAgICAgICAgICAgICB7aWR4OlsxLDUsNiwyXSxsYmw6J1InLCBjOicjZTBkYmU4JyxhejoxLjU3LCAgZWw6MC4wOH0sICAgLyogUmVjaHRzIFg9KzEgKi8KICAgICAgICAgICAgICAgIHtpZHg6WzAsMSw1LDRdLGxibDonJywgIGM6JyNkNGQ0ZDQnLGF6OjAsICAgICBlbDotMC4zNX0sICAvKiBVbnRlbiAgWj0tMSAqLwogICAgICAgICAgICAgICAge2lkeDpbMywyLDYsN10sbGJsOidPYicsYzonI2U4ZWVkOCcsYXo6MCwgICAgIGVsOjEuNTB9ICAgIC8qIE9iZW4gICBaPSsxICovCiAgICAgICAgICAgIF07CiAgICAgICAgICAgIC8qIFRpZWZlbnNvcnRpZXJ1bmcgKi8KICAgICAgICAgICAgdmFyIHNmPVtdOwogICAgICAgICAgICBmb3IodmFyIGY9MDtmPGZhY2VzLmxlbmd0aDtmKyspewogICAgICAgICAgICAgICAgdmFyIGZjPWZhY2VzW2ZdLGQ9MDsKICAgICAgICAgICAgICAgIGZvcih2YXIgaj0wO2o8NDtqKyspZCs9cHZbZmMuaWR4W2pdXS5kOwogICAgICAgICAgICAgICAgc2YucHVzaCh7ZjpmYyxkOmQvNH0pOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHNmLnNvcnQoZnVuY3Rpb24oYSxiKXtyZXR1cm4gYS5kLWIuZDt9KTsKICAgICAgICAgICAgLyogWmVpY2huZW4gKyBLbGljay1EYXRlbiBzYW1tZWxuICovCiAgICAgICAgICAgIHZjRmFjZXM9W107CiAgICAgICAgICAgIGN0eC5zYXZlKCk7CiAgICAgICAgICAgIGZvcih2YXIgaT0wO2k8c2YubGVuZ3RoO2krKyl7CiAgICAgICAgICAgICAgICB2YXIgZmM9c2ZbaV0uZiwgaXg9ZmMuaWR4OwogICAgICAgICAgICAgICAgdmFyIHFwdHM9W107CiAgICAgICAgICAgICAgICBjdHguYmVnaW5QYXRoKCk7CiAgICAgICAgICAgICAgICBjdHgubW92ZVRvKHB2W2l4WzBdXS54LHB2W2l4WzBdXS55KTtxcHRzLnB1c2goe3g6cHZbaXhbMF1dLngseTpwdltpeFswXV0ueX0pOwogICAgICAgICAgICAgICAgZm9yKHZhciBqPTE7ajw0O2orKyl7Y3R4LmxpbmVUbyhwdltpeFtqXV0ueCxwdltpeFtqXV0ueSk7cXB0cy5wdXNoKHt4OnB2W2l4W2pdXS54LHk6cHZbaXhbal1dLnl9KTt9CiAgICAgICAgICAgICAgICBjdHguY2xvc2VQYXRoKCk7CiAgICAgICAgICAgICAgICBjdHguZmlsbFN0eWxlPWZjLmM7Y3R4Lmdsb2JhbEFscGhhPTAuOTI7Y3R4LmZpbGwoKTsKICAgICAgICAgICAgICAgIGN0eC5saW5lV2lkdGg9MTtjdHguc3Ryb2tlU3R5bGU9JyMzZjVmNzUnO2N0eC5nbG9iYWxBbHBoYT0wLjQ1O2N0eC5zdHJva2UoKTsKICAgICAgICAgICAgICAgIC8qIExhYmVsICovCiAgICAgICAgICAgICAgICBpZihmYy5sYmwpewogICAgICAgICAgICAgICAgICAgIGN0eC5nbG9iYWxBbHBoYT0wLjc1O2N0eC5maWxsU3R5bGU9JyMxZTM1NDgnO2N0eC5mb250PSdib2xkIDlweCBzYW5zLXNlcmlmJztjdHgudGV4dEFsaWduPSdjZW50ZXInO2N0eC50ZXh0QmFzZWxpbmU9J21pZGRsZSc7CiAgICAgICAgICAgICAgICAgICAgdmFyIGN4Mj0wLGN5Mj0wO2Zvcih2YXIgaj0wO2o8NDtqKyspe2N4Mis9cHZbaXhbal1dLng7Y3kyKz1wdltpeFtqXV0ueTt9CiAgICAgICAgICAgICAgICAgICAgY3R4LmZpbGxUZXh0KGZjLmxibCxjeDIvNCxjeTIvNCk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB2Y0ZhY2VzLnB1c2goe3B0czpxcHRzLGF6OmZjLmF6LGVsOmZjLmVsfSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY3R4LnJlc3RvcmUoKTsKICAgICAgICB9CiAgICAgICAgZnVuY3Rpb24gZHJhd0FsbCgpe2RyYXcyRCgpO2RyYXczRCgpO3VwZFN0YXRzKCk7fQogICAgICAgIHdpbmRvdy50aW5EcmF3PWRyYXdBbGw7CiAgICAgICAgZnVuY3Rpb24gdXBkU3RhdHMoKXsKICAgICAgICAgICAgdmFyIHRjPXRyaT90cmkudHJpYW5nbGVzLmxlbmd0aC8zOjA7CiAgICAgICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd0aW5TdGF0cycpLmlubmVySFRNTD0nPHNwYW4+UHVua3RlOiAnK3B0cy5sZW5ndGgrJzwvc3Bhbj48c3Bhbj5EcmVpZWNrZTogJyt0YysnPC9zcGFuPjxzcGFuPkJydWNoa2FudGVuOiAnK2Nvbi5sZW5ndGgrJzwvc3Bhbj4nOwogICAgICAgICAgICB2YXIgaGludD1kb2N1bWVudC5nZXRFbGVtZW50QnlJZCgndGluSGludCcpOwogICAgICAgICAgICBpZihtb2RlPT09J2VkZ2UnJiZlZGdlRmlyc3QhPT0tMSloaW50LnRleHRDb250ZW50PSdLbGlja2UgYXVmIGVpbmVuIHp3ZWl0ZW4gUHVua3QsIHVtIGRpZSBCcnVjaGthbnRlIGFienVzY2hsaWXDn2VuLic7CiAgICAgICAgICAgIGVsc2UgaWYobW9kZT09PSdlZGdlJyloaW50LnRleHRDb250ZW50PSdLbGlja2UgYXVmIGVpbmVuIFB1bmt0IChvZGVyIHNldHplIGVpbmVuIG5ldWVuKSwgdW0gZWluZSBCcnVjaGthbnRlIHp1IGJlZ2lubmVuLic7CiAgICAgICAgICAgIGVsc2UgaGludC50ZXh0Q29udGVudD0nS2xpY2tlIHVtIFB1bmt0ZSB6dSBzZXR6ZW4uIERvcHBlbGtsaWNrIGF1ZiBQdW5rdCBcdTIxOTIgSFx1MDBmNmhlIFx1MDBlNG5kZXJuLiBSZWNodHNrbGljayBcdTIxOTIgTFx1MDBmNnNjaGVuLic7CiAgICAgICAgfQogICAgICAgIC8qID09PT09IDJEIEV2ZW50cyA9PT09PSAqLwogICAgICAgIGMyZC5zdHlsZS5jdXJzb3I9J2Nyb3NzaGFpcic7CiAgICAgICAgYzJkLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsZnVuY3Rpb24oZSl7CiAgICAgICAgICAgIGlmKGUuYnV0dG9uIT09MClyZXR1cm47dmFyIHA9Z3AoYzJkLGUpO2Nsb3NlQ3R4KCk7CiAgICAgICAgICAgIGlmKG1vZGU9PT0ncG9pbnQnKXt2YXIgbj1uZWFyUHQocC54LHAueSwxNCk7aWYobiE9PS0xKXtkcmFnSWR4PW47aXNEcmFnPXRydWU7ZGlkRHJhZz1mYWxzZTtjMmQuc3R5bGUuY3Vyc29yPSdncmFiYmluZyc7cmV0dXJuO319CiAgICAgICAgfSk7CiAgICAgICAgYzJkLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsZnVuY3Rpb24oZSl7CiAgICAgICAgICAgIHZhciBwPWdwKGMyZCxlKTsKICAgICAgICAgICAgaWYoaXNEcmFnJiZkcmFnSWR4IT09LTEpe3B0c1tkcmFnSWR4XS54PU1hdGgubWF4KDAsTWF0aC5taW4oVyxwLngpKTtwdHNbZHJhZ0lkeF0ueT1NYXRoLm1heCgwLE1hdGgubWluKEgscC55KSk7ZGlkRHJhZz10cnVlO2RvVHJpKCk7cmV0dXJuO30KICAgICAgICAgICAgaWYobW9kZT09PSdwb2ludCcpe2MyZC5zdHlsZS5jdXJzb3I9bmVhclB0KHAueCxwLnksMTQpIT09LTE\/J2dyYWInOidjcm9zc2hhaXInO30KICAgICAgICAgICAgdmFyIG5oPXRyaUF0KHAueCxwLnkpO2lmKG5oIT09aG92ZXJUcmkpe2hvdmVyVHJpPW5oO2RyYXcyRCgpO30KICAgICAgICAgICAgdXBkVGlwKGUscCk7CiAgICAgICAgfSk7CiAgICAgICAgYzJkLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLGZ1bmN0aW9uKCl7aWYoaXNEcmFnKXtpZihkaWREcmFnKXNhdmVIKCk7aXNEcmFnPWZhbHNlO2RyYWdJZHg9LTE7YzJkLnN0eWxlLmN1cnNvcj0nY3Jvc3NoYWlyJztzZXRUaW1lb3V0KGZ1bmN0aW9uKCl7ZGlkRHJhZz1mYWxzZTt9LDApO319KTsKICAgICAgICBjMmQuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLGZ1bmN0aW9uKGUpewogICAgICAgICAgICBpZihkaWREcmFnKXJldHVybjt2YXIgcD1ncChjMmQsZSk7CiAgICAgICAgICAgIGlmKG1vZGU9PT0ncG9pbnQnKXtpZihuZWFyUHQocC54LHAueSwxNCkhPT0tMSlyZXR1cm47cHRzLnB1c2goe3g6cC54LHk6cC55LHo6YXV0b1oocC54LHAueSl9KTtlZGdlRmlyc3Q9LTE7ZG9UcmkoKTtzYXZlSCgpO30KICAgICAgICAgICAgZWxzZSBpZihtb2RlPT09J2VkZ2UnKXt2YXIgbj1uZWFyUHQocC54LHAueSwyMCk7aWYobj09PS0xKXtwdHMucHVzaCh7eDpwLngseTpwLnksejphdXRvWihwLngscC55KX0pO249cHRzLmxlbmd0aC0xO2RvVHJpKCk7fQogICAgICAgICAgICAgICAgaWYoZWRnZUZpcnN0PT09LTEpe2VkZ2VGaXJzdD1uO2RyYXcyRCgpO31lbHNle2lmKGVkZ2VGaXJzdCE9PW4pY29uLnB1c2goW2VkZ2VGaXJzdCxuXSk7ZWRnZUZpcnN0PS0xO2RvVHJpKCk7c2F2ZUgoKTt9fQogICAgICAgIH0pOwogICAgICAgIGMyZC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZWxlYXZlJyxmdW5jdGlvbigpe2lmKGlzRHJhZyl7aXNEcmFnPWZhbHNlO2RyYWdJZHg9LTE7ZGlkRHJhZz1mYWxzZTt9aG92ZXJUcmk9LTE7aGlkZVRpcCgpO2RyYXcyRCgpO30pOwogICAgICAgIC8qIERvcHBlbGtsaWNrOiBIw7ZoZSDDpG5kZXJuICovCiAgICAgICAgdmFyIHpFZGl0ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3RpblpFZGl0Jyk7CiAgICAgICAgdmFyIHpFZGl0SWR4ID0gLTE7CiAgICAgICAgYzJkLmFkZEV2ZW50TGlzdGVuZXIoJ2RibGNsaWNrJyxmdW5jdGlvbihlKXsKICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpOwogICAgICAgICAgICB2YXIgcD1ncChjMmQsZSksIG5wPW5lYXJQdChwLngscC55LDE0KTsKICAgICAgICAgICAgaWYobnA9PT0tMSkgcmV0dXJuOwogICAgICAgICAgICBvcGVuWkVkaXQobnAsIGUpOwogICAgICAgIH0pOwogICAgICAgIGZ1bmN0aW9uIG9wZW5aRWRpdChpZHgsIGUpewogICAgICAgICAgICB6RWRpdElkeCA9IGlkeDsKICAgICAgICAgICAgekVkaXQudmFsdWUgPSBwdHNbaWR4XS56OwogICAgICAgICAgICB2YXIgd3IgPSBjMmQucGFyZW50RWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTsKICAgICAgICAgICAgekVkaXQuc3R5bGUubGVmdCA9IChlLmNsaWVudFggLSB3ci5sZWZ0IC0gMzUpICsgJ3B4JzsKICAgICAgICAgICAgekVkaXQuc3R5bGUudG9wID0gKGUuY2xpZW50WSAtIHdyLnRvcCAtIDM1KSArICdweCc7CiAgICAgICAgICAgIHpFZGl0LnN0eWxlLmRpc3BsYXkgPSAnYmxvY2snOwogICAgICAgICAgICB6RWRpdC5mb2N1cygpOwogICAgICAgICAgICB6RWRpdC5zZWxlY3QoKTsKICAgICAgICB9CiAgICAgICAgZnVuY3Rpb24gY2xvc2VaRWRpdChhcHBseSl7CiAgICAgICAgICAgIGlmKHpFZGl0SWR4IT09LTEgJiYgYXBwbHkpewogICAgICAgICAgICAgICAgdmFyIHYgPSBwYXJzZUZsb2F0KHpFZGl0LnZhbHVlKTsKICAgICAgICAgICAgICAgIGlmKCFpc05hTih2KSl7IHB0c1t6RWRpdElkeF0ueiA9IHY7IGRvVHJpKCk7IHNhdmVIKCk7IH0KICAgICAgICAgICAgfQogICAgICAgICAgICB6RWRpdElkeCA9IC0xOwogICAgICAgICAgICB6RWRpdC5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnOwogICAgICAgIH0KICAgICAgICB6RWRpdC5hZGRFdmVudExpc3RlbmVyKCdrZXlkb3duJyxmdW5jdGlvbihlKXsKICAgICAgICAgICAgaWYoZS5rZXk9PT0nRW50ZXInKXtlLnByZXZlbnREZWZhdWx0KCk7Y2xvc2VaRWRpdCh0cnVlKTt9CiAgICAgICAgICAgIGVsc2UgaWYoZS5rZXk9PT0nRXNjYXBlJyl7Y2xvc2VaRWRpdChmYWxzZSk7fQogICAgICAgIH0pOwogICAgICAgIHpFZGl0LmFkZEV2ZW50TGlzdGVuZXIoJ2JsdXInLGZ1bmN0aW9uKCl7Y2xvc2VaRWRpdCh0cnVlKTt9KTsKICAgICAgICAvKiBLb250ZXh0bWVuw7wgKi8KICAgICAgICB2YXIgY3R4TT1kb2N1bWVudC5nZXRFbGVtZW50QnlJZCgndGluQ29udGV4dE1lbnUnKTsKICAgICAgICBmdW5jdGlvbiBjbG9zZUN0eCgpe2N0eE0uc3R5bGUuZGlzcGxheT0nbm9uZSc7fQogICAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJyxjbG9zZUN0eCk7CiAgICAgICAgYzJkLmFkZEV2ZW50TGlzdGVuZXIoJ2NvbnRleHRtZW51JyxmdW5jdGlvbihlKXsKICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO3ZhciBwPWdwKGMyZCxlKSxucD1uZWFyUHQocC54LHAueSwxNCksbmM9bmVhckNvbihwLngscC55LDgpOwogICAgICAgICAgICBpZihucD09PS0xJiZuYz09PS0xKXJldHVybjsKICAgICAgICAgICAgdmFyIGh0bWw9Jyc7CiAgICAgICAgICAgIGlmKG5wIT09LTEpe2h0bWwrPSc8YnV0dG9uIGNsYXNzPSJ0aW4tY29udGV4dC1pdGVtIiBkYXRhLWE9ImV6IiBkYXRhLWk9IicrbnArJyI+SMO2aGUgw6RuZGVybiAoWjogJytwdHNbbnBdLnoudG9GaXhlZCgxKSsnKTwvYnV0dG9uPic7CiAgICAgICAgICAgICAgICBodG1sKz0nPGRpdiBjbGFzcz0idGluLWNvbnRleHQtc2VwIj48L2Rpdj4nOwogICAgICAgICAgICAgICAgaHRtbCs9JzxidXR0b24gY2xhc3M9InRpbi1jb250ZXh0LWl0ZW0iIGRhdGEtYT0iZHAiIGRhdGEtaT0iJytucCsnIj5QdW5rdCBlbnRmZXJuZW48L2J1dHRvbj4nOwogICAgICAgICAgICAgICAgdmFyIGhjPWZhbHNlO2Zvcih2YXIgaT0wO2k8Y29uLmxlbmd0aDtpKyspaWYoY29uW2ldWzBdPT09bnB8fGNvbltpXVsxXT09PW5wKXtoYz10cnVlO2JyZWFrO30KICAgICAgICAgICAgICAgIGlmKGhjKWh0bWwrPSc8YnV0dG9uIGNsYXNzPSJ0aW4tY29udGV4dC1pdGVtIiBkYXRhLWE9ImRwZSIgZGF0YS1pPSInK25wKyciPlB1bmt0ICsgQnJ1Y2hrYW50ZW4gZW50ZmVybmVuPC9idXR0b24+Jzt9CiAgICAgICAgICAgIGlmKG5jIT09LTEpe2lmKGh0bWwpaHRtbCs9JzxkaXYgY2xhc3M9InRpbi1jb250ZXh0LXNlcCI+PC9kaXY+JztodG1sKz0nPGJ1dHRvbiBjbGFzcz0idGluLWNvbnRleHQtaXRlbSIgZGF0YS1hPSJkYyIgZGF0YS1pPSInK25jKyciPkJydWNoa2FudGUgZW50ZmVybmVuPC9idXR0b24+Jzt9CiAgICAgICAgICAgIGN0eE0uaW5uZXJIVE1MPWh0bWw7Y3R4TS5zdHlsZS5kaXNwbGF5PSdibG9jayc7CiAgICAgICAgICAgIHZhciB3cj1jMmQucGFyZW50RWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtjdHhNLnN0eWxlLmxlZnQ9KGUuY2xpZW50WC13ci5sZWZ0KSsncHgnO2N0eE0uc3R5bGUudG9wPShlLmNsaWVudFktd3IudG9wKSsncHgnOwogICAgICAgICAgICBjdHhNLnF1ZXJ5U2VsZWN0b3JBbGwoJy50aW4tY29udGV4dC1pdGVtJykuZm9yRWFjaChmdW5jdGlvbihiKXtiLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJyxmdW5jdGlvbihldil7ZXYuc3RvcFByb3BhZ2F0aW9uKCk7dmFyIGE9dGhpcy5kYXRhc2V0LmEsaWR4PSt0aGlzLmRhdGFzZXQuaTsKICAgICAgICAgICAgICAgIGlmKGE9PT0nZXonKXsvKiBIw7ZoZSDDpG5kZXJuIOKAlCBGYWtlLUV2ZW50IGbDvHIgUG9zaXRpb24gKi92YXIgcj1jMmQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkscHQ9cHRzW2lkeF07b3BlblpFZGl0KGlkeCx7Y2xpZW50WDpyLmxlZnQrcHQueCooci53aWR0aC9XKSxjbGllbnRZOnIudG9wK3B0LnkqKHIuaGVpZ2h0L0gpfSk7fQogICAgICAgICAgICAgICAgZWxzZSBpZihhPT09J2RwJylkZWxQdChpZHgsZmFsc2UpO2Vsc2UgaWYoYT09PSdkcGUnKWRlbFB0KGlkeCx0cnVlKTtlbHNlIGlmKGE9PT0nZGMnKXtjb24uc3BsaWNlKGlkeCwxKTtkb1RyaSgpO3NhdmVIKCk7fWNsb3NlQ3R4KCk7fSk7fSk7CiAgICAgICAgfSk7CiAgICAgICAgZnVuY3Rpb24gZGVsUHQoaWR4LHdpdGhDb24pewogICAgICAgICAgICBpZih3aXRoQ29uKWNvbj1jb24uZmlsdGVyKGZ1bmN0aW9uKGMpe3JldHVybiBjWzBdIT09aWR4JiZjWzFdIT09aWR4O30pOwogICAgICAgICAgICBmb3IodmFyIGk9Y29uLmxlbmd0aC0xO2k+PTA7aS0tKXtpZihjb25baV1bMF09PT1pZHh8fGNvbltpXVsxXT09PWlkeCljb24uc3BsaWNlKGksMSk7ZWxzZXtpZihjb25baV1bMF0+aWR4KWNvbltpXVswXS0tO2lmKGNvbltpXVsxXT5pZHgpY29uW2ldWzFdLS07fX0KICAgICAgICAgICAgcHRzLnNwbGljZShpZHgsMSk7ZWRnZUZpcnN0PS0xO2RvVHJpKCk7c2F2ZUgoKTsKICAgICAgICB9CiAgICAgICAgLyogVG9vbHRpcCAqLwogICAgICAgIHZhciB0aXA9ZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3RpblRvb2x0aXAnKTsKICAgICAgICBmdW5jdGlvbiB1cGRUaXAoZSxwKXsKICAgICAgICAgICAgaWYoaXNEcmFnKXtoaWRlVGlwKCk7cmV0dXJuO30KICAgICAgICAgICAgdmFyIG5wPW5lYXJQdChwLngscC55LDE0KTsKICAgICAgICAgICAgaWYobnAhPT0tMSl7dGlwLmlubmVySFRNTD0nPGI+UHVua3QgJysobnArMSkrJzwvYj48YnI+WDogJytNYXRoLnJvdW5kKHB0c1tucF0ueCkrJyBZOiAnK01hdGgucm91bmQocHRzW25wXS55KSsnIDxiPlo6ICcrcHRzW25wXS56LnRvRml4ZWQoMSkrJzwvYj4nO3Nob3dUaXAoZSk7cmV0dXJuO30KICAgICAgICAgICAgaWYoaG92ZXJUcmk+PTAmJnRyaSl7dmFyIHQ9dHJpLnRyaWFuZ2xlcyxpPWhvdmVyVHJpKjMscDA9dFB0c1t0W2ldXSxwMT10UHRzW3RbaSsxXV0scDI9dFB0c1t0W2krMl1dOwogICAgICAgICAgICAgICAgdmFyIGFyZWE9TWF0aC5hYnMoKHAxLngtcDAueCkqKHAyLnktcDAueSktKHAyLngtcDAueCkqKHAxLnktcDAueSkpLzI7CiAgICAgICAgICAgICAgICB2YXIgZHo9TWF0aC5tYXgocDAueixwMS56LHAyLnopLU1hdGgubWluKHAwLnoscDEueixwMi56KTsKICAgICAgICAgICAgICAgIHRpcC5pbm5lckhUTUw9JzxiPkRyZWllY2s8L2I+PGJyPkZsw6RjaGU6ICcrYXJlYS50b0ZpeGVkKDApKycgcHjCsjxicj7OlFo6ICcrZHoudG9GaXhlZCgxKTtzaG93VGlwKGUpO3JldHVybjt9CiAgICAgICAgICAgIGhpZGVUaXAoKTsKICAgICAgICB9CiAgICAgICAgZnVuY3Rpb24gc2hvd1RpcChlKXt2YXIgcj1jMmQucGFyZW50RWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTt0aXAuc3R5bGUuZGlzcGxheT0nYmxvY2snO3RpcC5zdHlsZS5sZWZ0PShlLmNsaWVudFgtci5sZWZ0KzE0KSsncHgnO3RpcC5zdHlsZS50b3A9KGUuY2xpZW50WS1yLnRvcC0xMCkrJ3B4Jzt9CiAgICAgICAgZnVuY3Rpb24gaGlkZVRpcCgpe3RpcC5zdHlsZS5kaXNwbGF5PSdub25lJzt9CiAgICAgICAgLyogPT09PT0gM0QgRXZlbnRzIChPcmJpdCkgPT09PT0gKi8KICAgICAgICBjM2Quc3R5bGUuY3Vyc29yPSdncmFiJzsKICAgICAgICAvKiBWaWV3Q3ViZS1LbGljazogRmzDpGNoZSBlcmtlbm5lbiDihpIgS2FtZXJhIHNldHplbiAqLwogICAgICAgIHZhciB2Y0ZhY2VzPW51bGw7IC8qIHdpcmQgdm9uIGRyYXdWaWV3Q3ViZSBiZWbDvGxsdCAqLwogICAgICAgIGMzZC5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsZnVuY3Rpb24oZSl7CiAgICAgICAgICAgIGlmKGRpZERyYWczZClyZXR1cm47CiAgICAgICAgICAgIHZhciByPWMzZC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKSxweD1lLmNsaWVudFgtci5sZWZ0LHB5PWUuY2xpZW50WS1yLnRvcDsKICAgICAgICAgICAgaWYoIXZjRmFjZXMpcmV0dXJuOwogICAgICAgICAgICAvKiBWb24gdm9ybmUgKGxldHp0ZSBnZXplaWNobmV0ZSA9IG9iZXJzdGUpIG5hY2ggaGludGVuIHByw7xmZW4gKi8KICAgICAgICAgICAgZm9yKHZhciBpPXZjRmFjZXMubGVuZ3RoLTE7aT49MDtpLS0pewogICAgICAgICAgICAgICAgdmFyIGY9dmNGYWNlc1tpXTsKICAgICAgICAgICAgICAgIGlmKHB0SW5RdWFkKHB4LHB5LGYucHRzKSl7CiAgICAgICAgICAgICAgICAgICAgdGluU2V0Q2FtKGYuYXosZi5lbCk7cmV0dXJuOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfSk7CiAgICAgICAgZnVuY3Rpb24gcHRJblF1YWQocHgscHkscSl7CiAgICAgICAgICAgIC8qIFB1bmt0LWluLVBvbHlnb24gdmlhIHJheSBjYXN0aW5nIChyb2J1c3QgYmVpIGJlbGllYmlnZXIgV2luZHVuZykgKi8KICAgICAgICAgICAgdmFyIGluc2lkZT1mYWxzZTsKICAgICAgICAgICAgZm9yKHZhciBpPTAsaj0zO2k8NDtqPWkrKyl7CiAgICAgICAgICAgICAgICB2YXIgeWk9cVtpXS55LHlqPXFbal0ueTsKICAgICAgICAgICAgICAgIGlmKCh5aT5weSkhPT0oeWo+cHkpJiZweDwocVtqXS54LXFbaV0ueCkqKHB5LXlpKS8oeWoteWkpK3FbaV0ueClpbnNpZGU9IWluc2lkZTsKICAgICAgICAgICAgfXJldHVybiBpbnNpZGU7CiAgICAgICAgfQogICAgICAgIHZhciBkaWREcmFnM2Q9ZmFsc2U7CiAgICAgICAgYzNkLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsZnVuY3Rpb24oZSl7aWYoZS5idXR0b249PT0wKXtlLnByZXZlbnREZWZhdWx0KCk7Y2FtM0RyYWc9dHJ1ZTtkaWREcmFnM2Q9ZmFsc2U7Y2FtM0xhc3Q9e3g6ZS5jbGllbnRYLHk6ZS5jbGllbnRZfTtjM2Quc3R5bGUuY3Vyc29yPSdncmFiYmluZyc7fX0pOwogICAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLGZ1bmN0aW9uKGUpe2lmKCFjYW0zRHJhZylyZXR1cm47dmFyIGR4PWUuY2xpZW50WC1jYW0zTGFzdC54LGR5PWUuY2xpZW50WS1jYW0zTGFzdC55O2lmKE1hdGguYWJzKGR4KT4yfHxNYXRoLmFicyhkeSk+MilkaWREcmFnM2Q9dHJ1ZTtjYW0uYXotPWR4KjAuMDA4O2NhbS5lbD1jYW0uZWwrZHkqMC4wMDg7Y2FtM0xhc3Q9e3g6ZS5jbGllbnRYLHk6ZS5jbGllbnRZfTtzeW5jU2xpZGVycygpO2RyYXczRCgpO30pOwogICAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtb3VzZXVwJyxmdW5jdGlvbigpe2lmKGNhbTNEcmFnKXtjYW0zRHJhZz1mYWxzZTtjM2Quc3R5bGUuY3Vyc29yPSdncmFiJztzZXRUaW1lb3V0KGZ1bmN0aW9uKCl7ZGlkRHJhZzNkPWZhbHNlO30sMCk7fX0pOwogICAgICAgIC8qID09PT09IFN0ZXVlcnVuZyA9PT09PSAqLwogICAgICAgIHdpbmRvdy50aW5TZXRNb2RlPWZ1bmN0aW9uKG0pe21vZGU9bTtlZGdlRmlyc3Q9LTE7ZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3Rpbk1vZGVQb2ludCcpLmNsYXNzTGlzdC50b2dnbGUoJ3Rpbi1hY3RpdmUnLG09PT0ncG9pbnQnKTtkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgndGluTW9kZUVkZ2UnKS5jbGFzc0xpc3QudG9nZ2xlKCd0aW4tYWN0aXZlJyxtPT09J2VkZ2UnKTtkcmF3MkQoKTt9OwogICAgICAgIHdpbmRvdy50aW5TZXRWaWV3PWZ1bmN0aW9uKHYpe3ZpZXdNb2RlPXY7Wyd3aXJlJywnaGVpZ2h0Jywnc2xvcGUnLCdjb250b3VyJ10uZm9yRWFjaChmdW5jdGlvbihrKXtkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgndGluVmlldycray5jaGFyQXQoMCkudG9VcHBlckNhc2UoKStrLnNsaWNlKDEpKS5jbGFzc0xpc3QudG9nZ2xlKCd0aW4tYWN0aXZlJyx2PT09ayk7fSk7ZHJhd0FsbCgpO307CiAgICAgICAgd2luZG93LnRpblRvZ2dsZUNpcmN1bT1mdW5jdGlvbigpe3Nob3dDaXJjdW09ZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3RpbkNpcmN1bVRvZ2dsZScpLmNoZWNrZWQ7ZHJhdzJEKCk7fTsKICAgICAgICAvKiBTbGlkZXIg4oaUIEthbWVyYSBTeW5jICovCiAgICAgICAgdmFyIHNsQXo9ZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3RpblNsaWRlckF6Jyksc2xFbD1kb2N1bWVudC5nZXRFbGVtZW50QnlJZCgndGluU2xpZGVyRWwnKTsKICAgICAgICBmdW5jdGlvbiBzeW5jU2xpZGVycygpewogICAgICAgICAgICAvKiBhei9lbCAocmFkKSDihpIgU2xpZGVyICgwLTM2MMKwKSwgbm9ybWFsaXNpZXJ0IGF1ZiAwLi4yz4AgKi8KICAgICAgICAgICAgdmFyIGFkPSgoY2FtLmF6KjE4MC9NYXRoLlBJKSUzNjArMzYwKSUzNjA7CiAgICAgICAgICAgIHZhciBlZD0oKGNhbS5lbCoxODAvTWF0aC5QSSklMzYwKzM2MCklMzYwOwogICAgICAgICAgICBzbEF6LnZhbHVlPU1hdGgucm91bmQoYWQpOwogICAgICAgICAgICBzbEVsLnZhbHVlPU1hdGgucm91bmQoZWQpOwogICAgICAgIH0KICAgICAgICB3aW5kb3cudGluU2xpZGVyQ2FtPWZ1bmN0aW9uKCl7CiAgICAgICAgICAgIGNhbS5hej1wYXJzZUZsb2F0KHNsQXoudmFsdWUpKk1hdGguUEkvMTgwOwogICAgICAgICAgICBjYW0uZWw9cGFyc2VGbG9hdChzbEVsLnZhbHVlKSpNYXRoLlBJLzE4MDsKICAgICAgICAgICAgZHJhdzNEKCk7CiAgICAgICAgfTsKICAgICAgICB3aW5kb3cudGluU2V0Q2FtPWZ1bmN0aW9uKGF6LGVsKXtjYW0uYXo9YXo7Y2FtLmVsPWVsO3N5bmNTbGlkZXJzKCk7ZHJhdzNEKCk7fTsKICAgICAgICB3aW5kb3cudGluUmVzZXQ9ZnVuY3Rpb24oKXtwdHM9W107Y29uPVtdO3RQdHM9W107dENvbj1bXTtlZGdlRmlyc3Q9LTE7dHJpPW51bGw7aG92ZXJUcmk9LTE7ZHJhZ0lkeD0tMTtpc0RyYWc9ZmFsc2U7ZHJhd0FsbCgpO3NhdmVIKCk7fTsKICAgICAgICAvKiBQTkcgRXhwb3J0ICovCiAgICAgICAgd2luZG93LnRpbkV4cG9ydFBORz1mdW5jdGlvbigpewogICAgICAgICAgICAvKiBCZWlkZSBDYW52YXNlcyBuZWJlbmVpbmFuZGVyIGluIGVpbiBCaWxkICovCiAgICAgICAgICAgIHZhciBleHA9ZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJyk7ZXhwLndpZHRoPShXKjIrMjApKmRwcjtleHAuaGVpZ2h0PUgqZHByOwogICAgICAgICAgICB2YXIgZXg9ZXhwLmdldENvbnRleHQoJzJkJyk7CiAgICAgICAgICAgIGV4LmRyYXdJbWFnZShjMmQsMCwwLFcqZHByLEgqZHByKTsKICAgICAgICAgICAgZXguZHJhd0ltYWdlKGMzZCwoVysyMCkqZHByLDAsVypkcHIsSCpkcHIpOwogICAgICAgICAgICB2YXIgbGluaz1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCdhJyk7bGluay5kb3dubG9hZD0ndGluLXRyaWFuZ3VsYXRpb24ucG5nJztsaW5rLmhyZWY9ZXhwLnRvRGF0YVVSTCgnaW1hZ2UvcG5nJyk7bGluay5jbGljaygpOwogICAgICAgIH07CiAgICAgICAgLyogPT09PT0gRXZlbnQtVmVyZHJhaHR1bmcgKGtlaW5lIElubGluZS1vbmNsaWNrLUhhbmRsZXIgd2VnZW4gV29yZFByZXNzLUZpbHRlcikgPT09PT0gKi8KICAgICAgICBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCdbZGF0YS10aW4tbW9kZV0nKS5mb3JFYWNoKGZ1bmN0aW9uKGJ0bil7CiAgICAgICAgICAgIGJ0bi5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsZnVuY3Rpb24oKXt3aW5kb3cudGluU2V0TW9kZShidG4uZ2V0QXR0cmlidXRlKCdkYXRhLXRpbi1tb2RlJykpO30pOwogICAgICAgIH0pOwogICAgICAgIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoJ1tkYXRhLXRpbi12aWV3XScpLmZvckVhY2goZnVuY3Rpb24oYnRuKXsKICAgICAgICAgICAgYnRuLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJyxmdW5jdGlvbigpe3dpbmRvdy50aW5TZXRWaWV3KGJ0bi5nZXRBdHRyaWJ1dGUoJ2RhdGEtdGluLXZpZXcnKSk7fSk7CiAgICAgICAgfSk7CiAgICAgICAgZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgnW2RhdGEtdGluLWNhbV0nKS5mb3JFYWNoKGZ1bmN0aW9uKGJ0bil7CiAgICAgICAgICAgIGJ0bi5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsZnVuY3Rpb24oKXsKICAgICAgICAgICAgICAgIHZhciBwYXJ0cz1idG4uZ2V0QXR0cmlidXRlKCdkYXRhLXRpbi1jYW0nKS5zcGxpdCgnLCcpOwogICAgICAgICAgICAgICAgd2luZG93LnRpblNldENhbShwYXJzZUZsb2F0KHBhcnRzWzBdKSxwYXJzZUZsb2F0KHBhcnRzWzFdKSk7CiAgICAgICAgICAgIH0pOwogICAgICAgIH0pOwogICAgICAgIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoJ1tkYXRhLXRpbi1hY3Rpb25dJykuZm9yRWFjaChmdW5jdGlvbihidG4pewogICAgICAgICAgICBidG4uYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLGZ1bmN0aW9uKCl7CiAgICAgICAgICAgICAgICB2YXIgYT1idG4uZ2V0QXR0cmlidXRlKCdkYXRhLXRpbi1hY3Rpb24nKTsKICAgICAgICAgICAgICAgIGlmKGE9PT0ndW5kbycpd2luZG93LnRpblVuZG8oKTsKICAgICAgICAgICAgICAgIGVsc2UgaWYoYT09PSdyZWRvJyl3aW5kb3cudGluUmVkbygpOwogICAgICAgICAgICAgICAgZWxzZSBpZihhPT09J3Jlc2V0Jyl3aW5kb3cudGluUmVzZXQoKTsKICAgICAgICAgICAgICAgIGVsc2UgaWYoYT09PSdleHBvcnQnKXdpbmRvdy50aW5FeHBvcnRQTkcoKTsKICAgICAgICAgICAgfSk7CiAgICAgICAgfSk7CiAgICAgICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3RpbkNpcmN1bVRvZ2dsZScpLmFkZEV2ZW50TGlzdGVuZXIoJ2NoYW5nZScsZnVuY3Rpb24oKXt3aW5kb3cudGluVG9nZ2xlQ2lyY3VtKCk7fSk7CiAgICAgICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3RpblNsaWRlckF6JykuYWRkRXZlbnRMaXN0ZW5lcignaW5wdXQnLGZ1bmN0aW9uKCl7d2luZG93LnRpblNsaWRlckNhbSgpO30pOwogICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd0aW5TbGlkZXJFbCcpLmFkZEV2ZW50TGlzdGVuZXIoJ2lucHV0JyxmdW5jdGlvbigpe3dpbmRvdy50aW5TbGlkZXJDYW0oKTt9KTsKICAgICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgndGluWlNjYWxlJykuYWRkRXZlbnRMaXN0ZW5lcignaW5wdXQnLGZ1bmN0aW9uKCl7d2luZG93LnRpbkRyYXcoKTt9KTsKICAgICAgICBzeW5jU2xpZGVycygpOwogICAgICAgIGRyYXdBbGwoKTsKICAgIH0pKCk7Cg==\"))))<\/script>\n\n","protected":false},"excerpt":{"rendered":"<p>TIN-Explainer \u2014 Interaktive Delaunay-Triangulation Punkte setzen, Bruchkanten definieren, Dreiecksvermaschung verstehen Dieses Tool arbeitet vollst\u00e4ndig in deinem Browser. Keine Daten werden [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_uag_custom_page_level_css":"","site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"disabled","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[36],"tags":[],"class_list":["post-1882","post","type-post","status-publish","format-standard","hentry","category-gelaendemodellierung"],"uagb_featured_image_src":{"full":false,"thumbnail":false,"medium":false,"medium_large":false,"large":false,"1536x1536":false,"2048x2048":false},"uagb_author_info":{"display_name":false,"author_link":"https:\/\/cad-kompass.de\/?author=1"},"uagb_comment_info":0,"uagb_excerpt":"TIN-Explainer \u2014 Interaktive Delaunay-Triangulation Punkte setzen, Bruchkanten definieren, Dreiecksvermaschung verstehen Dieses Tool arbeitet vollst\u00e4ndig in deinem Browser. Keine Daten werden [&hellip;]","_links":{"self":[{"href":"https:\/\/cad-kompass.de\/index.php?rest_route=\/wp\/v2\/posts\/1882","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cad-kompass.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cad-kompass.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cad-kompass.de\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/cad-kompass.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1882"}],"version-history":[{"count":11,"href":"https:\/\/cad-kompass.de\/index.php?rest_route=\/wp\/v2\/posts\/1882\/revisions"}],"predecessor-version":[{"id":1908,"href":"https:\/\/cad-kompass.de\/index.php?rest_route=\/wp\/v2\/posts\/1882\/revisions\/1908"}],"wp:attachment":[{"href":"https:\/\/cad-kompass.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1882"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cad-kompass.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1882"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cad-kompass.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1882"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}