{"id":47233,"date":"2026-09-01T22:08:29","date_gmt":"2026-09-01T22:08:29","guid":{"rendered":"https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/?post_type=gsma_theme_resources&#038;p=47233"},"modified":"2026-10-01T13:27:05","modified_gmt":"2026-10-01T13:27:05","slug":"what-is-industrial-iot","status":"publish","type":"gsma_theme_resources","link":"https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/gsma_resources\/what-is-industrial-iot\/","title":{"rendered":"Smart Manufacturing Unpacked: What is industrial IoT?"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Industrial IoT (IIoT) turns isolated machines or dark assets into connected assets that tell you what is happening on the factory floor, as it happens. Machines, workstations, tools and materials become connected assets that help people understand what is happening on the factory floor.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That journey starts with visibility. Sensors act as the digital equivalents of human senses, collecting signals such as vibration, temperature, images and environmental conditions. This can help identify CNC misalignment through visual inspection, reveal temperature drift, detect hidden vibration faults or warn that conditions could lead to a line stoppage. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The information is then interpreted and used to support action. Instead of relying only on manual checks, gauges or individual machine displays, manufacturing teams can gain a clearer view of equipment condition and performance. This helps them investigate problems, make informed operational decisions and respond earlier. Explore the 3D factory environment to see how IIoT can help a manufacturing operation sense what is happening, process the information and support people to act.<\/p>\n\n\n\n<div style=\"height:50px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<!-- SR1 IIoT: The Foundation of Smart Manufacturing | single-div inline component -->\n<div id=\"iiot-sr1-app\" class=\"iiot-sr1-app\"><style>@import url(\"https:\/\/fonts.googleapis.com\/css2?family=Inter:wght@300;400;500;700;800&display=swap\");\n    .iiot-sr1-app{ --red:#DC002B; --red2:#BA0328; --g1:#C3C8C8; --g2:#878787; --g3:#3C3D3D; --panel:rgba(60,61,61,.96); --white:#fff; --ok:#32C87A; --warn:#F59E0B; --fault:#DC002B; --limit:#FFD166; }\n    .iiot-sr1-app *{box-sizing:border-box} .iiot-sr1-app{position:relative;width:100%;height:min(72vh,760px);min-height:560px;margin:0 auto;overflow:hidden;background:var(--g1);font-family:\"Inter\",Arial,sans-serif;color:#fff} .iiot-sr1-app button{font:inherit;cursor:pointer}\n    #iiot-sr1-app #webgl{position:absolute;inset:0;z-index:1} #iiot-sr1-app #ui{position:absolute;inset:0;z-index:10;pointer-events:none}\n    #iiot-sr1-app #intro{position:absolute;inset:0;z-index:100;display:none;align-items:center;justify-content:center;background:rgba(0,0,0,.84);backdrop-filter:blur(8px);transition:opacity .35s ease}\n    #iiot-sr1-app .card{width:min(860px,calc(100% - 32px));background:var(--panel);border-top:6px solid var(--red);box-shadow:0 20px 50px rgba(0,0,0,.28);padding:30px 34px}\n    #iiot-sr1-app .card h2{margin:0 0 14px 0;font-size:2rem;text-transform:uppercase}#iiot-sr1-app .card p{margin:0 0 12px 0;line-height:1.6}\n    #iiot-sr1-app .primary{background:var(--red);color:#fff;border:none;padding:13px 18px;font-weight:700;text-transform:uppercase;letter-spacing:.05em}#iiot-sr1-app .primary:hover{background:var(--red2)}#iiot-sr1-app .row #sNext.primary{position:relative;padding-right:34px;font-size:1.05rem}#iiot-sr1-app .row #sNext.primary:after{content:\"\";position:absolute;right:-17px;top:0;border-top:22px solid transparent;border-bottom:22px solid transparent;border-left:18px solid var(--red)}#iiot-sr1-app .row #sNext.primary:hover:after{border-left-color:var(--red2)}\n    #iiot-sr1-app .header{position:absolute;left:28px;top:22px;max-width:760px;color:#000}#iiot-sr1-app .header h1{margin:0;font-size:clamp(1.4rem,3vw,1.95rem);font-weight:300;line-height:1.18}#iiot-sr1-app .header h1 span{color:var(--red);font-weight:700}#iiot-sr1-app .header p{margin:8px 0 0 0;color:#333;line-height:1.45;max-width:720px;transition:opacity .45s ease}#iiot-sr1-app .header.dim p{display:none}#iiot-sr1-app .badge{display:none}\n    #iiot-sr1-app .label{position:absolute;transform:translate(-50%,-50%);display:inline-flex;align-items:center;gap:8px;background:var(--panel);border:1px solid rgba(255,255,255,.22);box-shadow:0 8px 18px rgba(0,0,0,.18);color:#fff;padding:8px 14px;font-size:.88rem;font-weight:700;text-transform:uppercase;white-space:nowrap;pointer-events:auto;cursor:pointer;opacity:0;z-index:8;transition:background .2s ease,border-color .2s ease,box-shadow .2s ease}#iiot-sr1-app .label:hover,#iiot-sr1-app .label:focus-visible{background:rgba(220,0,43,.92);border-color:var(--red);outline:none}#iiot-sr1-app .sub{display:none;font-size:.77rem;padding:7px 12px;background:#8a0a20;border-color:var(--red2);animation:pillPulse 1.85s ease-in-out infinite;box-shadow:0 0 0 rgba(220,0,43,0)} @keyframes pillPulse{0%,100%{box-shadow:0 0 0 0 rgba(220,0,43,.12),0 0 12px rgba(220,0,43,.18)}50%{box-shadow:0 0 0 8px rgba(220,0,43,0),0 0 22px rgba(220,0,43,.34)}} #iiot-sr1-app .num{margin-right:6px}\n    #iiot-sr1-app .icon{width:16px;height:16px;display:block}#iiot-sr1-app .icon svg{width:100%;height:100%;stroke:currentColor;fill:none;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}\n    #iiot-sr1-app #cross{position:absolute;top:50%;left:50%;width:20px;height:20px;border:2px solid rgba(220,0,43,.45);transform:translate(-50%,-50%);pointer-events:none;transition:all .2s ease;opacity:0} #iiot-sr1-app #cross.visible{opacity:1;transform:translate(-50%,-50%) scale(1.35);border-color:var(--red)}\n    #iiot-sr1-app #panel{position:absolute;top:50%;right:-560px;transform:translateY(-50%);width:min(500px,calc(100% - 32px));max-height:calc(100% - 60px);overflow:auto;background:var(--panel);border-left:6px solid var(--red);padding:20px 22px;transition:right .45s cubic-bezier(.16,1,.3,1);pointer-events:auto;box-shadow:0 14px 34px rgba(0,0,0,.24)} #iiot-sr1-app #panel.active{right:24px}#iiot-sr1-app #panel,#iiot-sr1-app .glossary-panel{scrollbar-width:thin;scrollbar-color:var(--red) rgba(255,255,255,.14)}#iiot-sr1-app #panel::-webkit-scrollbar,#iiot-sr1-app .glossary-panel::-webkit-scrollbar{width:10px;height:10px}#iiot-sr1-app #panel::-webkit-scrollbar-track,#iiot-sr1-app .glossary-panel::-webkit-scrollbar-track{background:rgba(255,255,255,.06)}#iiot-sr1-app #panel::-webkit-scrollbar-thumb,#iiot-sr1-app .glossary-panel::-webkit-scrollbar-thumb{background:var(--red);border-radius:6px;border:2px solid rgba(60,61,61,.92)}#iiot-sr1-app #panel::-webkit-scrollbar-thumb:hover,#iiot-sr1-app .glossary-panel::-webkit-scrollbar-thumb:hover{background:var(--red2)}\n    #iiot-sr1-app .phead{display:flex;justify-content:space-between;align-items:center;gap:12px;margin-bottom:12px;padding-bottom:10px;border-bottom:1px solid rgba(255,255,255,.16)} #iiot-sr1-app .phead h2{margin:0;font-size:1.2rem;text-transform:uppercase}\n    #iiot-sr1-app .btn{background:rgba(255,255,255,.06);color:#fff;border:1px solid rgba(255,255,255,.22);padding:10px 12px;text-transform:uppercase}#iiot-sr1-app .btn:hover{background:rgba(220,0,43,.14);border-color:var(--red)}\n    #iiot-sr1-app .metric{margin-bottom:10px;padding:10px 11px;border:1px solid rgba(255,255,255,.1)} #iiot-sr1-app .loc{background:linear-gradient(90deg,rgba(35,35,35,.55),rgba(60,61,61,.28))} #iiot-sr1-app .fun{background:linear-gradient(90deg,rgba(80,80,80,.45),rgba(135,135,135,.18))} #iiot-sr1-app .aim{background:linear-gradient(90deg,rgba(110,110,110,.35),rgba(195,200,200,.18))} #iiot-sr1-app .ml{font-size:.74rem;text-transform:uppercase;letter-spacing:.08em;margin-bottom:6px} #iiot-sr1-app .mv{font-size:.96rem;line-height:1.56}#iiot-sr1-app .mv .context-location{display:block;font-weight:800;color:#fff;margin-bottom:4px}#iiot-sr1-app .mv .context-guidance{display:block;color:rgba(255,255,255,.82);font-size:.96rem;line-height:1.56}\n    #iiot-sr1-app #overviewNote{display:none;margin-top:10px;padding:10px;background:rgba(255,255,255,.05);border-left:4px solid var(--red);font-size:.88rem;line-height:1.45} #iiot-sr1-app #overviewNote.active{display:block}\n    #iiot-sr1-app .vgrid{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-top:8px}#iiot-sr1-app .vgrid.single{grid-template-columns:1fr}#iiot-sr1-app .box{padding:10px;background:rgba(0,0,0,.26);border:1px solid rgba(255,255,255,.12)} #iiot-sr1-app .boxt{font-size:.76rem;text-transform:uppercase;letter-spacing:.08em;margin-bottom:8px} #iiot-sr1-app .wrap,#iiot-sr1-app .camWrap{height:168px;border:1px solid rgba(255,255,255,.1);background:rgba(0,0,0,.34);position:relative;overflow:hidden}#iiot-sr1-app .camWrap{background:linear-gradient(180deg,#10202e 0%,#213345 100%)} .iiot-sr1-app canvas{display:block;width:100%;height:100%}\n    #iiot-sr1-app .status{display:none!important}\n    #iiot-sr1-app #story{position:absolute;left:16px;bottom:16px;width:min(330px,calc(42% - 20px));height:58px;background:var(--g3);border-left:0;border-bottom:6px solid var(--red);padding:8px 14px;pointer-events:auto;z-index:18;box-shadow:0 12px 24px rgba(0,0,0,.24);display:flex;align-items:center;justify-content:space-between;gap:12px;overflow:hidden} #iiot-sr1-app #story h3{grid-column:1\/2;grid-row:1;margin:0;text-transform:uppercase;font-size:.72rem;letter-spacing:.09em;color:rgba(255,255,255,.72);font-weight:700} #iiot-sr1-app #sTitle{display:none;grid-column:1\/2;grid-row:2;font-weight:700;font-size:.9rem;line-height:1.1;color:#fff;white-space:nowrap;overflow:hidden;text-overflow:ellipsis} #iiot-sr1-app #sCopy{position:absolute!important;width:1px!important;height:1px!important;padding:0!important;margin:-1px!important;overflow:hidden!important;clip:rect(0,0,0,0)!important;white-space:nowrap!important;border:0!important}#iiot-sr1-app .row{grid-column:2\/3;grid-row:1\/3;display:flex;align-items:center;margin:0}#iiot-sr1-app #story .row{position:static;order:2;margin:0;flex:0 0 auto}#iiot-sr1-app .row #sNext.primary{position:static;padding:8px 12px;font-size:.72rem;line-height:1;border:none;background:var(--red);color:#fff;letter-spacing:.06em}#iiot-sr1-app .row #sNext.primary:after{display:none}#iiot-sr1-app .row #sNext.primary:hover{background:var(--red2)}#iiot-sr1-app .track{margin:0;height:4px;background:rgba(255,255,255,.14);border-radius:999px;overflow:hidden}#iiot-sr1-app #story .track{position:absolute;left:14px;right:14px;bottom:6px;top:auto;width:auto}#iiot-sr1-app .bar{height:100%;width:0%;border-radius:999px;background:linear-gradient(90deg,var(--red),#ff4a68);box-shadow:0 0 12px rgba(220,0,43,.35)} #iiot-sr1-app #sProg{position:static;order:1;margin:0;transform:none;color:#fff;font-size:.68rem;text-transform:uppercase;letter-spacing:.12em;font-weight:800;opacity:.9} #iiot-sr1-app #min{display:none}#iiot-sr1-app .header,#iiot-sr1-app #panel,#iiot-sr1-app #infoPanel,#iiot-sr1-app #intro .card{pointer-events:auto}#iiot-sr1-app .glossary-term{appearance:none;border:0;background:transparent;color:inherit;text-decoration:underline;text-decoration-color:currentColor;text-decoration-thickness:1px;text-underline-offset:2px;cursor:pointer;font:inherit;font-weight:700;padding:0;pointer-events:auto}#iiot-sr1-app .glossary-term:hover,#iiot-sr1-app .glossary-term:focus{text-decoration-thickness:2px;outline:2px solid rgba(220,0,43,.4);outline-offset:2px}#iiot-sr1-app .glossary-dismiss-layer{position:fixed;inset:0;z-index:2147483646;background:transparent;display:none;pointer-events:none}#iiot-sr1-app .glossary-dismiss-layer.active{display:block;pointer-events:auto}#iiot-sr1-app .glossary-tooltip{position:fixed;z-index:2147483647;display:none;width:min(340px,calc(100% - 28px));background:#3C3D3D;color:#fff;border-left:6px solid var(--red);box-shadow:0 18px 44px rgba(0,0,0,.32);padding:13px 38px 14px 15px;pointer-events:auto}#iiot-sr1-app .glossary-tooltip.active{display:block}#iiot-sr1-app .glossary-tooltip:before{content:\"\";position:absolute;left:20px;top:-8px;border-left:8px solid transparent;border-right:8px solid transparent;border-bottom:8px solid #3C3D3D}#iiot-sr1-app .glossary-tooltip h3{margin:0 0 6px;text-transform:uppercase;letter-spacing:.08em;font-size:.78rem;color:#fff}#iiot-sr1-app .glossary-tooltip p{margin:0;color:rgba(255,255,255,.9);font-size:.86rem;line-height:1.45}#iiot-sr1-app .glossary-tooltip button{position:absolute;right:8px;top:7px;border:0;background:transparent;color:#fff;font-size:1.12rem;line-height:1;cursor:pointer;opacity:.75}#iiot-sr1-app .glossary-tooltip button:hover{opacity:1}#iiot-sr1-app .glossary-panel{position:absolute;left:auto;right:16px;bottom:16px;width:min(520px,calc(50% - 20px));min-height:58px;max-height:58px;overflow:hidden;background:rgba(60,61,61,.96);color:#fff;border-left:0;box-shadow:0 14px 34px rgba(0,0,0,.24);padding:9px 13px;z-index:40;pointer-events:auto;transition:max-height .35s ease;border-bottom:6px solid var(--red)}#iiot-sr1-app .glossary-panel summary{cursor:pointer;font-size:.72rem;text-transform:uppercase;letter-spacing:.08em;color:rgba(255,255,255,.78);font-weight:800}#iiot-sr1-app .glossary-panel dl{display:grid;grid-template-columns:88px 1fr;gap:8px 14px;margin:10px 0 0}#iiot-sr1-app .glossary-panel dt{font-size:.72rem;font-weight:800;color:#fff}#iiot-sr1-app .glossary-panel dd{margin:0;font-size:.72rem;line-height:1.32;color:rgba(255,255,255,.76)}\n    #iiot-sr1-app .mode{display:inline-block;padding:3px 8px;border-radius:999px;font-size:.72rem;text-transform:uppercase;letter-spacing:.08em;font-weight:700}#iiot-sr1-app .normal{background:rgba(50,200,122,.18);color:var(--ok)}#iiot-sr1-app .warning{background:rgba(245,158,11,.18);color:var(--warn)}#iiot-sr1-app .fault{background:rgba(220,0,43,.18);color:var(--fault)}\n    @media (max-width:1024px){#iiot-sr1-app .header{left:16px;top:16px;max-width:calc(100% - 32px)}#iiot-sr1-app #panel{top:auto;bottom:16px;left:16px;right:16px;width:auto;max-height:60vh;transform:translateY(140%);transition:transform .4s ease}#iiot-sr1-app #panel.active{right:16px;transform:translateY(0)}#iiot-sr1-app #story{display:none}#iiot-sr1-app .status{left:16px;right:16px;max-width:none}#iiot-sr1-app .vgrid{grid-template-columns:1fr}#iiot-sr1-app .label{font-size:.8rem;padding:6px 10px}#iiot-sr1-app .label .icon{width:14px;height:14px}#iiot-sr1-app .glossary-panel{display:none}}\n  .iiot-sr1-app.sr1-narrow #story{display:none!important}.iiot-sr1-app.sr1-narrow .glossary-panel{display:none!important}.iiot-sr1-app.sr1-narrow #panel{top:auto;bottom:-115%;left:12px;right:12px;width:auto;max-width:none;max-height:64%;transform:none;border-left:0;border-top:6px solid var(--red);transition:bottom .42s cubic-bezier(.16,1,.3,1)}.iiot-sr1-app.sr1-narrow #panel.active{bottom:12px;right:12px;transform:none}.iiot-sr1-app.sr1-panel-open .glossary-panel{display:none!important}.iiot-sr1-app.sr1-narrow.sr1-panel-open #story{display:none!important}<\/style>\n  <div id=\"intro\"><div class=\"card\"><h2>What is IIoT?<\/h2><p><strong>Industrial Internet of Things, or IIoT,<\/strong> is the journey from isolated machines to truly smart manufacturing. Machines, workstations, tools and materials become connected assets that continuously sense, interpret and share what is happening on the factory floor.<\/p><p>That journey starts with visibility. Sensors become the digital equivalents of human senses, collecting signals such as vibration, heat, sight and environmental conditions. Those signals are then organised through the server layer, prioritised, and turned into information teams can use.<\/p><p>Once that foundation is in place, manufacturing teams can move from reactive responses to informed action.<\/p><button class=\"primary\" id=\"startBtn\" type=\"button\">Initialise Smart Factory<\/button><\/div><\/div>\n  <div id=\"webgl\"><\/div>\n  <div id=\"ui\">\n    <div id=\"cross\"><\/div>\n    <div class=\"header\"><h1><span>IIoT:<\/span> The Foundation of Smart Manufacturing<\/h1><p>Explore how connected manufacturing turns machine signals into action. Sensors capture live conditions from the CNC station, the server layer organises and prioritises that data, and the control desk turns the resulting insight into practical decisions for people and systems.<\/p><\/div>\n    <div id=\"lbl-phase1\" class=\"label\" tabindex=\"0\" role=\"button\"><span class=\"num\">1.<\/span> SENSE (CNC Machine)<\/div>\n    <div id=\"lbl-phase2\" class=\"label\" tabindex=\"0\" role=\"button\"><span class=\"num\">2.<\/span> PROCESS (Server)<\/div>\n    <div id=\"lbl-phase3\" class=\"label\" tabindex=\"0\" role=\"button\"><span class=\"num\">3.<\/span> ACT (Control Desk)<\/div>\n    <div id=\"lbl-sight\" class=\"label sub\" tabindex=\"0\" role=\"button\"><span class=\"icon\"><svg viewBox=\"0 0 24 24\"><path d=\"M2 12s3.5-6 10-6 10 6 10 6-3.5 6-10 6S2 12 2 12Z\"><\/path><circle cx=\"12\" cy=\"12\" r=\"2.8\"><\/circle><\/svg><\/span>Sight<\/div>\n    <div id=\"lbl-touch\" class=\"label sub\" tabindex=\"0\" role=\"button\"><span class=\"icon\"><svg viewBox=\"0 0 24 24\"><path d=\"M12 3v8\"><\/path><path d=\"M15.5 6.5A3.5 3.5 0 1 0 9 8.5v5a4 4 0 1 0 8 0v-5\"><\/path><path d=\"M12 16v3\"><\/path><\/svg><\/span>Touch<\/div>\n    <div id=\"lbl-hearing\" class=\"label sub\" tabindex=\"0\" role=\"button\"><span class=\"icon\"><svg viewBox=\"0 0 24 24\"><path d=\"M6 9a6 6 0 0 1 12 0c0 5-3 4.5-3 8\"><\/path><path d=\"M9 19a3 3 0 0 0 6 0\"><\/path><path d=\"M3 11h2\"><\/path><path d=\"M19 11h2\"><\/path><\/svg><\/span>Hearing<\/div>\n    <div id=\"lbl-smell\" class=\"label sub\" tabindex=\"0\" role=\"button\"><span class=\"icon\"><svg viewBox=\"0 0 24 24\"><path d=\"M7 16c0-5 5-7 5-11 0 4 5 6 5 11\"><\/path><path d=\"M9 17c0 2 1.4 4 3 4s3-2 3-4\"><\/path><path d=\"M4 11c1.5-1 2.1-2.4 2.3-3.8\"><\/path><path d=\"M20 11c-1.5-1-2.1-2.4-2.3-3.8\"><\/path><\/svg><\/span>Smell<\/div>\n    <div id=\"panel\" aria-live=\"polite\"><div class=\"phead\"><h2 id=\"pTitle\">Phase details<\/h2><button id=\"resetBtn\" class=\"btn\" type=\"button\">Back<\/button><\/div><div class=\"metric loc\"><div class=\"ml\">Overview<\/div><div class=\"mv\" id=\"pLoc\">&#8230;<\/div><\/div><div class=\"metric fun\"><div class=\"ml\">Function<\/div><div class=\"mv\" id=\"pFun\">&#8230;<\/div><\/div><div class=\"metric aim\"><div class=\"ml\">Aim<\/div><div class=\"mv\" id=\"pAim\">&#8230;<\/div><\/div><div id=\"overviewNote\">Sensing is the first step towards smart manufacturing. At this stage the factory builds digital equivalents of sight, touch, hearing and smell so it can sense machine condition before data is processed and teams respond.<\/div><div id=\"vgrid\" class=\"vgrid\"><div class=\"box\"><div class=\"boxt\">Live data stream <span id=\"modePill\" class=\"mode normal\">Normal<\/span><\/div><div class=\"wrap\"><canvas id=\"liveChart\"><\/canvas><\/div><\/div><div class=\"box\" id=\"cameraCard\"><div class=\"boxt\">Inspection view<\/div><div class=\"camWrap\"><canvas id=\"cameraView\"><\/canvas><\/div><\/div><\/div><\/div>\n    <div id=\"story\"><h3>Navigation<\/h3><div id=\"sTitle\">IIoT<\/div><div id=\"sCopy\">Start with the full system view showing how sensing, processing and action connect.<\/div><div class=\"row\"><button id=\"sNext\" class=\"btn primary\" type=\"button\" aria-label=\"Next navigation step\">Next<\/button><\/div><div class=\"track\"><div class=\"bar\" id=\"sBar\"><\/div><\/div><div id=\"sProg\">01 \/ 08<\/div><\/div><div id=\"glossaryDismissLayer\" class=\"glossary-dismiss-layer\" aria-hidden=\"true\" onclick=\"window.hideGlossaryTooltip()\"><\/div><div id=\"glossaryTooltip\" class=\"glossary-tooltip\" role=\"dialog\" aria-live=\"polite\" aria-hidden=\"true\"><button type=\"button\" aria-label=\"Close glossary tooltip\" onclick=\"window.hideGlossaryTooltip()\">\u00d7<\/button><h3 id=\"glossaryTipTitle\">Glossary<\/h3><p id=\"glossaryTipCopy\">Select a highlighted term.<\/p><\/div><aside class=\"glossary-panel\"><details><summary>Full glossary<\/summary><dl><dt>IIoT<\/dt><dd>Industrial Internet of Things \u2014 connecting machines, sensors and systems so factories can see what is happening and respond faster.<\/dd><dt>CNC<\/dt><dd>Computer Numerical Control \u2014 a machine tool controlled by digital instructions, often used for cutting, drilling or milling parts.<\/dd><dt>Signal<\/dt><dd>A measurable clue from the machine, such as temperature, vibration, image data or air quality.<\/dd><dt>Raw data<\/dt><dd>Unprocessed readings coming directly from sensors before filtering or interpretation.<\/dd><dt>Threshold<\/dt><dd>A pre-set limit that tells the system when something has moved from normal to warning or fault.<\/dd><dt>Tolerance<\/dt><dd>The acceptable amount of variation from the intended measurement or position.<\/dd><dt>Computer vision<\/dt><dd>Camera-based inspection that checks images for alignment, defects or changes.<\/dd><dt>Thermal drift<\/dt><dd>Small changes in machine behaviour caused by heat building up over time.<\/dd><dt>Vibration signature<\/dt><dd>The pattern of vibration a machine produces; changes in the pattern can indicate wear, imbalance or faults.<\/dd><dt>Spindle<\/dt><dd>The rotating part of the machine that holds and drives the cutting tool.<\/dd><dt>Bearing<\/dt><dd>A component that supports smooth rotation; wear here can cause vibration or failure.<\/dd><dt>VOCs<\/dt><dd>Volatile Organic Compounds \u2014 airborne chemicals that can indicate fumes, coolant issues or air-quality concerns.<\/dd><dt>Particulates<\/dt><dd>Tiny airborne particles that can affect air quality or safety.<\/dd><dt>Prioritised data<\/dt><dd>Data sorted by importance, so the most useful or urgent signals are easier to act on.<\/dd><dt>Dashboard<\/dt><dd>A live display that summarises machine or process status.<\/dd><\/dl><\/details><\/aside>\n    <div id=\"status\" class=\"status\">Overview mode. Click a stage label to begin.<\/div>\n  <\/div>\n  <script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/three.js\/r128\/three.min.js\"><\/script>\n  <script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/gsap\/3.12.2\/gsap.min.js\"><\/script>\n  <script>(function(){var b=\"CiAgKGZ1bmN0aW9uIGJvb3QoKXsgaWYodHlwZW9mIFRIUkVFPT09J3VuZGVmaW5lZCd8fHR5cGVvZiBnc2FwPT09J3VuZGVmaW5lZCcpe3JldHVybiBzZXRUaW1lb3V0KGJvb3QsNDApO30gY29uc3QgSUlPVF9ST09UPWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdpaW90LXNyMS1hcHAnKTsgaWYoIUlJT1RfUk9PVHx8IUlJT1RfUk9PVC5pc0Nvbm5lY3RlZHx8SUlPVF9ST09ULm9mZnNldFBhcmVudD09PW51bGx8fElJT1RfUk9PVC5jbGllbnRXaWR0aDwyfHxJSU9UX1JPT1QuY2xpZW50SGVpZ2h0PDIpe3JldHVybiBzZXRUaW1lb3V0KGJvb3QsODApO30gY29uc3QgSVc9KCk9PklJT1RfUk9PVC5jbGllbnRXaWR0aHx8ODAwLCBJSD0oKT0+SUlPVF9ST09ULmNsaWVudEhlaWdodHx8NTYwOwogICAgY29uc3QgZG9tPXtpbnRybzpkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnaW50cm8nKSxzdGFydEJ0bjpkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnc3RhcnRCdG4nKSx3ZWJnbDpkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnd2ViZ2wnKSxjcm9zczpkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnY3Jvc3MnKSxwYW5lbDpkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgncGFuZWwnKSxyZXNldEJ0bjpkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgncmVzZXRCdG4nKSxwVGl0bGU6ZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3BUaXRsZScpLHBMb2M6ZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3BMb2MnKSxwRnVuOmRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdwRnVuJykscEFpbTpkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgncEFpbScpLG92ZXJ2aWV3Tm90ZTpkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnb3ZlcnZpZXdOb3RlJyksdmdyaWQ6ZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3ZncmlkJyksY2FtZXJhQ2FyZDpkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnY2FtZXJhQ2FyZCcpLG1vZGVQaWxsOmRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdtb2RlUGlsbCcpLGxpdmVDaGFydDpkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnbGl2ZUNoYXJ0JyksY2FtZXJhVmlldzpkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnY2FtZXJhVmlldycpLHN0YXR1czpkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnc3RhdHVzJyksZ2xvc3NhcnlEaXNtaXNzTGF5ZXI6ZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2dsb3NzYXJ5RGlzbWlzc0xheWVyJyksZ2xvc3NhcnlUb29sdGlwOmRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdnbG9zc2FyeVRvb2x0aXAnKSxnbG9zc2FyeVRpcFRpdGxlOmRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdnbG9zc2FyeVRpcFRpdGxlJyksZ2xvc3NhcnlUaXBDb3B5OmRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdnbG9zc2FyeVRpcENvcHknKSxzdG9yeTpkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnc3RvcnknKSxtaW46ZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ21pbicpLHNUaXRsZTpkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnc1RpdGxlJyksc0NvcHk6ZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3NDb3B5Jyksc05leHQ6ZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3NOZXh0Jyksc0Jhcjpkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnc0JhcicpLHNQcm9nOmRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdzUHJvZycpLGxhYmVsc01haW46WydsYmwtcGhhc2UxJywnbGJsLXBoYXNlMicsJ2xibC1waGFzZTMnXS5tYXAoaWQ9PmRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGlkKSksbGFiZWxzU2Vuc29yOlsnbGJsLXNpZ2h0JywnbGJsLXRvdWNoJywnbGJsLWhlYXJpbmcnLCdsYmwtc21lbGwnXS5tYXAoaWQ9PmRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGlkKSl9OwogICAgY29uc3QgcGhhc2VEYXRhPXtwaGFzZTFfY25jOnt0aXRsZTonUGhhc2UgMTogU2Vuc2UnLGxvY2F0aW9uOidDTkMgbWlsbGluZyBzdGF0aW9uJyxkZXNjOidUaGUgbWFjaGluZSBpcyBnaXZlbiBkaWdpdGFsIHNlbnNlcy4gT3B0aWNhbCwgdGhlcm1hbCwgdmlicmF0aW9uIGFuZCBlbnZpcm9ubWVudGFsIHNlbnNvcnMgYmVoYXZlIGxpa2Ugc2lnaHQsIHRvdWNoLCBoZWFyaW5nIGFuZCBzbWVsbCwgdHVybmluZyByYXcgcGh5c2ljYWwgY29uZGl0aW9ucyBpbnRvIHNpZ25hbHMgdGhlIGZhY3RvcnkgY2FuIHVuZGVyc3RhbmQuJyxhaW06J0NyZWF0ZSB0cnVzdGVkIHZpc2liaWxpdHkgaW50byBtYWNoaW5lIGhlYWx0aCwgcGFydCBxdWFsaXR5IGFuZCBvcGVyYXRpbmcgY29uZGl0aW9ucyBzbyB0aGUgZmFjdG9yeSBjYW4gc2Vuc2Ugd2hhdCBpcyBoYXBwZW5pbmcgYmVmb3JlIGRhdGEgaXMgcHJvY2Vzc2VkIGFuZCB0ZWFtcyByZXNwb25kLicsY2hhcnRUeXBlOidwaGFzZTFfb3ZlcnZpZXcnLGNhbWVyYVZpZXc6ZmFsc2V9LHBoYXNlMl9lZGdlOnt0aXRsZTonUGhhc2UgMjogUHJvY2VzcyBhbmQgU3RydWN0dXJlIERhdGEnLGxvY2F0aW9uOidTZXJ2ZXIgcHJvY2Vzc2luZyBsYXllcicsZGVzYzonRGF0YSBpcyBmaXJzdCBzdG9yZWQgaW4gYSBzZXJ2ZXIgYW5kIHRoZW4gcHJvY2Vzc2VkLiBUaGUgc2VydmVyIGZpbHRlcnMgbm9pc3kgZGF0YSBhbmQgcHJpb3JpdGlzZXMgdGhlIG1vc3QgdXNlZnVsIG1hY2hpbmUgc2lnbmFscy4nLGFpbTonVHVybiBub2lzeSBzZW5zb3Igb3V0cHV0IGludG8gc3RydWN0dXJlZCwgcHJpb3JpdGlzZWQgaW5mb3JtYXRpb24gdGhhdCBzdXBwb3J0cyBkZWNpc2lvbnMgYWNyb3NzIHRoZSBmYWN0b3J5LicsY2hhcnRUeXBlOidhaV9wcm9jZXNzJyxjYW1lcmFWaWV3OmZhbHNlfSxwaGFzZTNfYWN0Ont0aXRsZTonUGhhc2UgMzogQWN0Jyxsb2NhdGlvbjonQ29udHJvbCBkZXNrIGFuZCBjb25uZWN0ZWQgd29ya2VyIGFjY2VzcycsZGVzYzonT25jZSBpbnNpZ2h0IGlzIGF2YWlsYWJsZSwgZGF0YSBjYW4gZHJpdmUgYWN0aW9uYWJsZSByZXNwb25zZXMgZm9yIG9wZXJhdG9ycywgZW5naW5lZXJzIGFuZCB3aWRlciBzeXN0ZW1zLicsYWltOidQdXQgdHJ1c3RlZCBpbnNpZ2h0IGludG8gdGhlIGhhbmRzIG9mIHRoZSByaWdodCBwZW9wbGUgb3Igc3lzdGVtcyBzbyBhY3Rpb24gaXMgcXVpY2tlciBhbmQgbW9yZSBjb25zaXN0ZW50LicsY2hhcnRUeXBlOidpbnNpZ2h0X2Rhc2hib2FyZCcsY2FtZXJhVmlldzpmYWxzZX0saWlvdF9sb29wOnt0aXRsZTonSUlvVDogRnJvbSBTaWduYWwgdG8gQWN0aW9uJyxsb2NhdGlvbjonRW5kLXRvLWVuZCBjb25uZWN0ZWQgbWFudWZhY3R1cmluZyBqb3VybmV5JyxkZXNjOidJSW9UIHNlbnNvcnMgY29sbGVjdCBkYXRhIGZyb20gbWFjaGluZXMgYW5kIGVxdWlwbWVudCB0byBwcm92aWRlIHJlYWwtdGltZSB2aXNpYmlsaXR5IGFjcm9zcyBmYWN0b3J5IG9wZXJhdGlvbnMuJyxhaW06J1R1cm4gbWFjaGluZSBkYXRhIGludG8gc3RydWN0dXJlZCBpbmZvcm1hdGlvbiB0aGF0IHN1cHBvcnRzIGRlY2lzaW9ucyBhY3Jvc3MgdGhlIGZhY3RvcnkuJyxjaGFydFR5cGU6J25ldHdvcmtfZmxvdycsY2FtZXJhVmlldzpmYWxzZX0sc2Vuc29yX3NpZ2h0Ont0aXRsZTonU2lnaHQnLGxvY2F0aW9uOidJbnNwZWN0aW9uIGNhbWVyYSBvdmVyIHRoZSB3b3JrcGllY2UnLGRlc2M6J0NvbXB1dGVyIHZpc2lvbiBjaGVja3MgcGFydCBhbGlnbm1lbnQsIG1lYXN1cmVzIHRvbGVyYW5jZXMgYW5kIGlkZW50aWZpZXMgdmlzaWJsZSBkZWZlY3RzIGluIHJlYWwgdGltZS4nLGFpbTonQ2F0Y2ggdmlzaWJsZSBxdWFsaXR5IGlzc3VlcyBlYXJseSBhbmQgY3JlYXRlIGEgcmVsaWFibGUgc3RyZWFtIG9mIHZpc3VhbCBldmlkZW5jZS4nLGNoYXJ0VHlwZTonYmFyc19jYW1lcmEnLGNhbWVyYVZpZXc6dHJ1ZSxhdXRvQ3ljbGU6dHJ1ZX0sc2Vuc29yX3RvdWNoOnt0aXRsZTonVG91Y2gnLGxvY2F0aW9uOidNb3RvciBkcml2ZSBob3VzaW5nJyxkZXNjOidUaGVybWFsIHNlbnNpbmcgdHJhY2tzIGhlYXQgZHJpZnQgdG8gcHJldmVudCB0aGVybWFsIGV4cGFuc2lvbiBhbmQgbW90b3IgYnVybm91dC4nLGFpbTonTWFpbnRhaW4gdGhlIG1hY2hpbmUgd2l0aGluIHNhZmUgb3BlcmF0aW5nIGxpbWl0cyBhbmQgaWRlbnRpZnkgdGhlcm1hbCBjaGFuZ2VzIHF1aWNrbHkgZW5vdWdoIHRvIHByZXZlbnQgYXZvaWRhYmxlIGRvd250aW1lLicsY2hhcnRUeXBlOid0aGVybWFsX2xpbmUnLGNhbWVyYVZpZXc6ZmFsc2UsYXV0b0N5Y2xlOnRydWV9LHNlbnNvcl9oZWFyaW5nOnt0aXRsZTonSGVhcmluZycsbG9jYXRpb246J1NwaW5kbGUgYmVhcmluZycsZGVzYzonVmlicmF0aW9uIGFuZCBhY291c3RpYyBkZXRlY3Rpb24gY2FwdHVyZXMgaGlnaC1mcmVxdWVuY3kgY2hhbmdlcyB0aGF0IGNhbiBpbmRpY2F0ZSBoaWRkZW4gZmF1bHRzIGJlZm9yZSBmYWlsdXJlLicsYWltOidSZXZlYWwgZWFybHkgd2FybmluZyBzaWducyBvZiBiZWFyaW5nIGFuZCBzcGluZGxlIGlzc3VlcyBiZWZvcmUgZmFpbHVyZXMgaW50ZXJydXB0IHByb2R1Y3Rpb24uJyxjaGFydFR5cGU6J3dhdmVmb3JtJyxjYW1lcmFWaWV3OmZhbHNlLGF1dG9DeWNsZTp0cnVlfSxzZW5zb3Jfc21lbGw6e3RpdGxlOidTbWVsbCcsbG9jYXRpb246J0V4aGF1c3QgLyBjb29sYW50IHZlbnQnLGRlc2M6J0Vudmlyb25tZW50YWwgc2Vuc2luZyBtZWFzdXJlcyBWT0NzLCBhaXIgcXVhbGl0eSBhbmQgdmVudCBjb25kaXRpb25zIGZvciBzYWZldHkgYW5kIHByb2Nlc3MgY29udGV4dC4nLGFpbTonUHJvdGVjdCBzYWZldHksIG1haW50YWluIGNvbXBsaWFuY2UgYW5kIGFkZCBjb250ZXh0IHRoYXQgY2FuIGV4cGxhaW4gd2h5IG1hY2hpbmUgcGVyZm9ybWFuY2UgbWF5IGJlIGNoYW5naW5nLicsY2hhcnRUeXBlOidwYXJ0aWNsZXMnLGNhbWVyYVZpZXc6ZmFsc2UsYXV0b0N5Y2xlOnRydWV9fTsKICAgIGNvbnN0IHN0b3J5U3RlcHM9WwogICAgICB7aWQ6J2lpb3RfbG9vcCcsdGl0bGU6J0lJb1QnLGNvcHk6J1N0YXJ0IHdpdGggdGhlIGZ1bGwgc3lzdGVtIHZpZXcgc2hvd2luZyBob3cgc2Vuc2luZywgcHJvY2Vzc2luZyBhbmQgYWN0aW9uIGNvbm5lY3QuJ30sCiAgICAgIHtpZDoncGhhc2UxX2NuYycsdGl0bGU6J1NlbnNlJyxjb3B5OidUaGUgZmFjdG9yeSBzZW5zZXMgY29uZGl0aW9ucyB0aHJvdWdoIGNvbm5lY3RlZCBtYWNoaW5lIHNlbnNvcnMuJ30sCiAgICAgIHtpZDonc2Vuc29yX3NpZ2h0Jyx0aXRsZTonU2lnaHQnLGNvcHk6J0NvbXB1dGVyIHZpc2lvbiBpbnNwZWN0cyB0aGUgdmlzaWJsZSBwYXJ0IGluIHJlYWwgdGltZS4nfSwKICAgICAge2lkOidzZW5zb3JfdG91Y2gnLHRpdGxlOidUb3VjaCcsY29weTonVGhlcm1hbCBzZW5zaW5nIG1vbml0b3JzIGhlYXQgYW5kIG1hY2hpbmUgY29uZGl0aW9uLid9LAogICAgICB7aWQ6J3NlbnNvcl9oZWFyaW5nJyx0aXRsZTonSGVhcmluZycsY29weTonVmlicmF0aW9uIGFuZCBhY291c3RpYyBzZW5zaW5nIGRldGVjdHMgaGlkZGVuIGZhdWx0cy4nfSwKICAgICAge2lkOidzZW5zb3Jfc21lbGwnLHRpdGxlOidTbWVsbCcsY29weTonRW52aXJvbm1lbnRhbCBzZW5zaW5nIG1vbml0b3JzIGFpciBhbmQgc2FmZXR5IGNvbmRpdGlvbnMuJ30sCiAgICAgIHtpZDoncGhhc2UyX2VkZ2UnLHRpdGxlOidQcm9jZXNzJyxjb3B5OidEYXRhIGlzIHN0cnVjdHVyZWQgYW5kIHByb2Nlc3NlZCBpbiB0aGUgc2VydmVyIGxheWVyLid9LAogICAgICB7aWQ6J3BoYXNlM19hY3QnLHRpdGxlOidBY3QnLGNvcHk6J0luc2lnaHRzIGFyZSBkZWxpdmVyZWQgdG8gcGVvcGxlIGFuZCBzeXN0ZW1zIGZvciBhY3Rpb24uJ30KICAgIF07CiAgICBjb25zdCBzdGF0ZT17c3RhcnRlZDpmYWxzZSx2aWV3OidPVkVSVklFVycsc2VsZWN0aW9uOidvdmVydmlldycsY2hhcnRUeXBlOidwaGFzZTFfb3ZlcnZpZXcnLHRpbWU6MCxjaGFydERhdGE6W10sc2Vuc29yTW9kZTonbm9ybWFsJyxzaWdodEJhZDpmYWxzZSxsYXN0SG92ZXJlZDpudWxsLGRyYWdnaW5nOmZhbHNlLHNjZW5lTW92ZWQ6ZmFsc2Usc3RvcnlJbmRleDowLHN0b3J5UnVubmluZzpmYWxzZSxzdG9yeVBhdXNlZDpmYWxzZSxzdG9yeVRpbWVyOm51bGwsc3RhdHVzVGV4dDonT3ZlcnZpZXcgbW9kZS4gQ2xpY2sgYSBzdGFnZSBsYWJlbCB0byBiZWdpbi4nfTsKICAgIGNvbnN0IHNldFN0YXR1cz10PT57c3RhdGUuc3RhdHVzVGV4dD10OyBpZihkb20uc3RhdHVzKSBkb20uc3RhdHVzLnRleHRDb250ZW50PXQ7IGlmKGRvbS5wYW5lbC5jbGFzc0xpc3QuY29udGFpbnMoJ2FjdGl2ZScpKSB1cGRhdGVQYW5lbENvbnRleHQoc3RhdGUuc2VsZWN0aW9uKTt9OwogICAgY29uc3QgZ2xvc3NhcnlUZXJtcz17IklJb1QiOiAiSW5kdXN0cmlhbCBJbnRlcm5ldCBvZiBUaGluZ3Mg4oCUIGNvbm5lY3RpbmcgbWFjaGluZXMsIHNlbnNvcnMgYW5kIHN5c3RlbXMgc28gZmFjdG9yaWVzIGNhbiBzZWUgd2hhdCBpcyBoYXBwZW5pbmcgYW5kIHJlc3BvbmQgZmFzdGVyLiIsICJDTkMiOiAiQ29tcHV0ZXIgTnVtZXJpY2FsIENvbnRyb2wg4oCUIGEgbWFjaGluZSB0b29sIGNvbnRyb2xsZWQgYnkgZGlnaXRhbCBpbnN0cnVjdGlvbnMsIG9mdGVuIHVzZWQgZm9yIGN1dHRpbmcsIGRyaWxsaW5nIG9yIG1pbGxpbmcgcGFydHMuIiwgIlNpZ25hbCI6ICJBIG1lYXN1cmFibGUgY2x1ZSBmcm9tIHRoZSBtYWNoaW5lLCBzdWNoIGFzIHRlbXBlcmF0dXJlLCB2aWJyYXRpb24sIGltYWdlIGRhdGEgb3IgYWlyIHF1YWxpdHkuIiwgIlJhdyBkYXRhIjogIlVucHJvY2Vzc2VkIHJlYWRpbmdzIGNvbWluZyBkaXJlY3RseSBmcm9tIHNlbnNvcnMgYmVmb3JlIGZpbHRlcmluZyBvciBpbnRlcnByZXRhdGlvbi4iLCAiVGhyZXNob2xkIjogIkEgcHJlLXNldCBsaW1pdCB0aGF0IHRlbGxzIHRoZSBzeXN0ZW0gd2hlbiBzb21ldGhpbmcgaGFzIG1vdmVkIGZyb20gbm9ybWFsIHRvIHdhcm5pbmcgb3IgZmF1bHQuIiwgIlRvbGVyYW5jZSI6ICJUaGUgYWNjZXB0YWJsZSBhbW91bnQgb2YgdmFyaWF0aW9uIGZyb20gdGhlIGludGVuZGVkIG1lYXN1cmVtZW50IG9yIHBvc2l0aW9uLiIsICJDb21wdXRlciB2aXNpb24iOiAiQ2FtZXJhLWJhc2VkIGluc3BlY3Rpb24gdGhhdCBjaGVja3MgaW1hZ2VzIGZvciBhbGlnbm1lbnQsIGRlZmVjdHMgb3IgY2hhbmdlcy4iLCAiVGhlcm1hbCBkcmlmdCI6ICJTbWFsbCBjaGFuZ2VzIGluIG1hY2hpbmUgYmVoYXZpb3VyIGNhdXNlZCBieSBoZWF0IGJ1aWxkaW5nIHVwIG92ZXIgdGltZS4iLCAiVmlicmF0aW9uIHNpZ25hdHVyZSI6ICJUaGUgcGF0dGVybiBvZiB2aWJyYXRpb24gYSBtYWNoaW5lIHByb2R1Y2VzOyBjaGFuZ2VzIGluIHRoZSBwYXR0ZXJuIGNhbiBpbmRpY2F0ZSB3ZWFyLCBpbWJhbGFuY2Ugb3IgZmF1bHRzLiIsICJTcGluZGxlIjogIlRoZSByb3RhdGluZyBwYXJ0IG9mIHRoZSBtYWNoaW5lIHRoYXQgaG9sZHMgYW5kIGRyaXZlcyB0aGUgY3V0dGluZyB0b29sLiIsICJCZWFyaW5nIjogIkEgY29tcG9uZW50IHRoYXQgc3VwcG9ydHMgc21vb3RoIHJvdGF0aW9uOyB3ZWFyIGhlcmUgY2FuIGNhdXNlIHZpYnJhdGlvbiBvciBmYWlsdXJlLiIsICJWT0NzIjogIlZvbGF0aWxlIE9yZ2FuaWMgQ29tcG91bmRzIOKAlCBhaXJib3JuZSBjaGVtaWNhbHMgdGhhdCBjYW4gaW5kaWNhdGUgZnVtZXMsIGNvb2xhbnQgaXNzdWVzIG9yIGFpci1xdWFsaXR5IGNvbmNlcm5zLiIsICJQYXJ0aWN1bGF0ZXMiOiAiVGlueSBhaXJib3JuZSBwYXJ0aWNsZXMgdGhhdCBjYW4gYWZmZWN0IGFpciBxdWFsaXR5IG9yIHNhZmV0eS4iLCAiUHJpb3JpdGlzZWQgZGF0YSI6ICJEYXRhIHNvcnRlZCBieSBpbXBvcnRhbmNlLCBzbyB0aGUgbW9zdCB1c2VmdWwgb3IgdXJnZW50IHNpZ25hbHMgYXJlIGVhc2llciB0byBhY3Qgb24uIiwgIkRhc2hib2FyZCI6ICJBIGxpdmUgZGlzcGxheSB0aGF0IHN1bW1hcmlzZXMgbWFjaGluZSBvciBwcm9jZXNzIHN0YXR1cy4ifTsKICAgIGNvbnN0IGdsb3NzYXJ5S2V5cz1PYmplY3Qua2V5cyhnbG9zc2FyeVRlcm1zKS5zb3J0KChhLGIpPT5iLmxlbmd0aC1hLmxlbmd0aCk7CiAgICBsZXQgZ2xvc3NhcnlUb29sdGlwSnVzdE9wZW5lZD1mYWxzZTsKICAgIGZ1bmN0aW9uIGVzY2FwZUh0bWwoc3RyKXtyZXR1cm4gU3RyaW5nKHN0cikucmVwbGFjZSgvWyY8PiJdL2csY2g9Pih7JyYnOicmYW1wOycsJzwnOicmbHQ7JywnPic6JyZndDsnLCciJzonJnF1b3Q7J31bY2hdKSk7fQogICAgZnVuY3Rpb24gaGlkZUdsb3NzYXJ5VG9vbHRpcCgpeyBpZihkb20uZ2xvc3NhcnlUb29sdGlwKXtkb20uZ2xvc3NhcnlUb29sdGlwLmNsYXNzTGlzdC5yZW1vdmUoJ2FjdGl2ZScpO2RvbS5nbG9zc2FyeVRvb2x0aXAuc2V0QXR0cmlidXRlKCdhcmlhLWhpZGRlbicsJ3RydWUnKTt9IGlmKGRvbS5nbG9zc2FyeURpc21pc3NMYXllcil7ZG9tLmdsb3NzYXJ5RGlzbWlzc0xheWVyLmNsYXNzTGlzdC5yZW1vdmUoJ2FjdGl2ZScpO30gfQogICAgd2luZG93LmhpZGVHbG9zc2FyeVRvb2x0aXA9aGlkZUdsb3NzYXJ5VG9vbHRpcDsKICAgIGZ1bmN0aW9uIHNob3dHbG9zc2FyeVRlcm0oa2V5LHNvdXJjZSl7IGlmKCFnbG9zc2FyeVRlcm1zW2tleV0pIHJldHVybjsgZG9tLmdsb3NzYXJ5VGlwVGl0bGUudGV4dENvbnRlbnQ9a2V5OyBkb20uZ2xvc3NhcnlUaXBDb3B5LnRleHRDb250ZW50PWdsb3NzYXJ5VGVybXNba2V5XTsgY29uc3QgdGlwPWRvbS5nbG9zc2FyeVRvb2x0aXA7IHRpcC5jbGFzc0xpc3QuYWRkKCdhY3RpdmUnKTsgdGlwLnNldEF0dHJpYnV0ZSgnYXJpYS1oaWRkZW4nLCdmYWxzZScpOyBjb25zdCByPXNvdXJjZT9zb3VyY2UuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk6e2xlZnQ6MjgsYm90dG9tOjEyMH07IGNvbnN0IG1hcmdpbj0xNDsgY29uc3Qgd2lkdGg9TWF0aC5taW4oMzQwLHdpbmRvdy5pbm5lcldpZHRoLTI4KTsgdGlwLnN0eWxlLndpZHRoPXdpZHRoKydweCc7IGxldCBsZWZ0PU1hdGgubWluKE1hdGgubWF4KG1hcmdpbixyLmxlZnQpLHdpbmRvdy5pbm5lcldpZHRoLXdpZHRoLW1hcmdpbik7IHRpcC5zdHlsZS5sZWZ0PWxlZnQrJ3B4JzsgdGlwLnN0eWxlLnRvcD0nMHB4JzsgY29uc3QgdG9wPU1hdGgubWluKHIuYm90dG9tKzEyLHdpbmRvdy5pbm5lckhlaWdodC10aXAub2Zmc2V0SGVpZ2h0LW1hcmdpbik7IHRpcC5zdHlsZS50b3A9TWF0aC5tYXgobWFyZ2luLHRvcCkrJ3B4JzsgZ2xvc3NhcnlUb29sdGlwSnVzdE9wZW5lZD10cnVlOyBpZihkb20uZ2xvc3NhcnlEaXNtaXNzTGF5ZXIpe2RvbS5nbG9zc2FyeURpc21pc3NMYXllci5jbGFzc0xpc3QuYWRkKCdhY3RpdmUnKTt9IHNldFRpbWVvdXQoKCk9PntnbG9zc2FyeVRvb2x0aXBKdXN0T3BlbmVkPWZhbHNlO30sMCk7IH0KICAgIHdpbmRvdy5zaG93R2xvc3NhcnlUZXJtPXNob3dHbG9zc2FyeVRlcm07CiAgICBmdW5jdGlvbiBsaW5raWZ5VGV4dCh2YWx1ZSl7IGxldCBodG1sPWVzY2FwZUh0bWwodmFsdWUpOyBnbG9zc2FyeUtleXMuZm9yRWFjaChrZXk9PnsgY29uc3QgZXNjYXBlZD1rZXkucmVwbGFjZSgvWy4qKz9eJHt9KCl8W1xdXFxdL2csJ1xcJCYnKTsgY29uc3Qgcng9bmV3IFJlZ0V4cCgnKF58W15BLVphLXowLTldKSgnK2VzY2FwZWQrJykoPz0kfFteQS1aYS16MC05XSknLCdnaScpOyBodG1sPWh0bWwucmVwbGFjZShyeCwobSxwMSxwMik9PnAxKyc8YnV0dG9uIHR5cGU9ImJ1dHRvbiIgY2xhc3M9Imdsb3NzYXJ5LXRlcm0iIG9uY2xpY2s9IndpbmRvdy5zaG93R2xvc3NhcnlUZXJtKCZxdW90Oycra2V5LnJlcGxhY2UoLyYvZywnJmFtcDsnKS5yZXBsYWNlKC8iL2csJyZxdW90OycpKycmcXVvdDssIHRoaXMpIj4nK3AyKyc8L2J1dHRvbj4nKTsgfSk7IHJldHVybiBodG1sOyB9CiAgICBmdW5jdGlvbiB1cGRhdGVQYW5lbENvbnRleHQoaWQpeyBjb25zdCBpbmZvPXBoYXNlRGF0YVtpZF07IGlmKCFpbmZvKSByZXR1cm47IGNvbnN0IHNlbnNlT3ZlcnZpZXc9e3NlbnNvcl9zaWdodDonQW4gb3B0aWNhbCBpbnNwZWN0aW9uIGNhbWVyYSBpcyBwb3NpdGlvbmVkIG92ZXIgdGhlIGN1dHRpbmcgYXJlYS4gSW4gYSByZWFsIGxpbmUsIHRoaXMgd291bGQgY2FwdHVyZSByZXBlYXRlZCBpbWFnZXMgb2YgdGhlIHBhcnQsIGNvbXBhcmUgZWRnZXMsIGFsaWdubWVudCBhbmQgc3VyZmFjZSBmZWF0dXJlcyBhZ2FpbnN0IHRvbGVyYW5jZSwgdGhlbiBmbGFnIHZpc2libGUgZGVmZWN0cyBvciBkcmlmdCBiZWZvcmUgdGhlIHBhcnQgbW92ZXMgZG93bnN0cmVhbS4nLHNlbnNvcl90b3VjaDonQSB0ZW1wZXJhdHVyZSBvciBjb250YWN0LXN0eWxlIHNlbnNpbmcgcG9pbnQgaXMgcGxhY2VkIG9uIHRoZSBtb3RvciBkcml2ZSBob3VzaW5nLiBJbiBwcmFjdGljZSwgdGhpcyB0cmFja3MgaGVhdCBidWlsZC11cCBhbmQgdGhlcm1hbCBkcmlmdCwgaGVscGluZyB0ZWFtcyBzcG90IGFibm9ybWFsIGxvYWQsIGZyaWN0aW9uIG9yIGNvb2xpbmcgaXNzdWVzIGJlZm9yZSB0aGV5IHR1cm4gaW50byBkb3dudGltZS4nLHNlbnNvcl9oZWFyaW5nOidBIHZpYnJhdGlvbiBvciBhY291c3RpYyBzZW5zaW5nIHBvaW50IGlzIG1vdW50ZWQgbmVhciB0aGUgc3BpbmRsZSBiZWFyaW5nLiBJdCBsaXN0ZW5zIGZvciBoaWdoLWZyZXF1ZW5jeSBjaGFuZ2VzIGluIHZpYnJhdGlvbiBzaWduYXR1cmUsIHdoZXJlIHNoaWZ0cyBpbiBhbXBsaXR1ZGUgb3IgcGF0dGVybiBjYW4gaW5kaWNhdGUgaW1iYWxhbmNlLCBiZWFyaW5nIHdlYXIgb3IgdG9vbCBjaGF0dGVyIGJlZm9yZSB0aGUgaXNzdWUgaXMgdmlzaWJsZS4nLHNlbnNvcl9zbWVsbDonQW4gZW52aXJvbm1lbnRhbCBhaXItcXVhbGl0eSBzZW5zaW5nIHBvaW50IHNpdHMgbmVhciB0aGUgZXhoYXVzdCBvciBjb29sYW50IHZlbnQuIEl0IHNhbXBsZXMgdmFwb3VycywgcGFydGljdWxhdGVzIG9yIFZPQyBjaGFuZ2VzIGFyb3VuZCB0aGUgcHJvY2VzcywgZ2l2aW5nIHNhZmV0eSBhbmQgcHJvY2VzcyBjb250ZXh0IHdoZW4gY29vbGFudCwgbWF0ZXJpYWwgb3IgdmVudGlsYXRpb24gY29uZGl0aW9ucyBiZWdpbiB0byBjaGFuZ2UuJ307IGNvbnN0IGd1aWRhbmNlPXNlbnNlT3ZlcnZpZXdbaWRdfHxzdGF0ZS5zdGF0dXNUZXh0fHwnU2VsZWN0IGEgc3RhZ2Ugb3Igc2Vuc29yIHRvIGV4cGxvcmUgdGhlIElJb1Qgam91cm5leS4nOyBkb20ucExvYy5pbm5lckhUTUw9JzxzcGFuIGNsYXNzPSJjb250ZXh0LWxvY2F0aW9uIj4nK2VzY2FwZUh0bWwoaW5mby5sb2NhdGlvbikrJzwvc3Bhbj48c3BhbiBjbGFzcz0iY29udGV4dC1ndWlkYW5jZSI+JytsaW5raWZ5VGV4dChndWlkYW5jZSkrJzwvc3Bhbj4nOyB9CiAgICBmdW5jdGlvbiBhcHBseUhlYWRlckdsb3NzYXJ5KCl7IElJT1RfUk9PVC5xdWVyeVNlbGVjdG9yQWxsKCcuaGVhZGVyIHAsI2ludHJvIHAnKS5mb3JFYWNoKGVsPT57IGlmKCFlbC5kYXRhc2V0Lmdsb3NzYXJ5RG9uZSl7IGVsLmlubmVySFRNTD1saW5raWZ5VGV4dChlbC50ZXh0Q29udGVudCk7IGVsLmRhdGFzZXQuZ2xvc3NhcnlEb25lPScxJzsgfSB9KTsgfQogICAgZnVuY3Rpb24gaW5pdEdsb3NzYXJ5KCl7IGFwcGx5SGVhZGVyR2xvc3NhcnkoKTsgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCgpPT57IGlmKGdsb3NzYXJ5VG9vbHRpcEp1c3RPcGVuZWQpIHJldHVybjsgaWYoZG9tLmdsb3NzYXJ5VG9vbHRpcCYmZG9tLmdsb3NzYXJ5VG9vbHRpcC5jbGFzc0xpc3QuY29udGFpbnMoJ2FjdGl2ZScpKSBoaWRlR2xvc3NhcnlUb29sdGlwKCk7IH0pOyBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdrZXlkb3duJyxlPT57aWYoZS5rZXk9PT0nRXNjYXBlJykgaGlkZUdsb3NzYXJ5VG9vbHRpcCgpO30pOyB9CiAgICBjb25zdCBzaG93TWFpbj12PT5kb20ubGFiZWxzTWFpbi5mb3JFYWNoKGVsPT57ZWwuc3R5bGUuZGlzcGxheT12PydpbmxpbmUtZmxleCc6J25vbmUnOyBpZighdikgZWwuc3R5bGUub3BhY2l0eT0wO30pOwogICAgY29uc3Qgc2hvd1NlbnNvcnM9dj0+ZG9tLmxhYmVsc1NlbnNvci5mb3JFYWNoKGVsPT57ZWwuc3R5bGUuZGlzcGxheT12PydpbmxpbmUtZmxleCc6J25vbmUnOyBpZighdikgZWwuc3R5bGUub3BhY2l0eT0wO30pOwogICAgY29uc3Qgc2hvd09ubHlTZW5zb3I9aWQ9PmRvbS5sYWJlbHNTZW5zb3IuZm9yRWFjaChlbD0+e2NvbnN0IG9uPWVsLmlkPT09aWQ7IGVsLnN0eWxlLmRpc3BsYXk9b24\/J2lubGluZS1mbGV4Jzonbm9uZSc7IGlmKCFvbikgZWwuc3R5bGUub3BhY2l0eT0wO30pOwogICAgY29uc3Qgc2V0T3ZlcnZpZXdOb3RlPXY9PmRvbS5vdmVydmlld05vdGUuY2xhc3NMaXN0LnRvZ2dsZSgnYWN0aXZlJyx2KTsKICAgIGZ1bmN0aW9uIGdldEF1dG9Nb2RlKHNlY29uZHMpe2NvbnN0IHQ9c2Vjb25kcyUyMDsgaWYodDwxNSkgcmV0dXJuICdub3JtYWwnOyBpZih0PDE4KSByZXR1cm4gJ3dhcm5pbmcnOyByZXR1cm4gJ2ZhdWx0Jzt9CiAgICBmdW5jdGlvbiB1cGRhdGVNb2RlUGlsbChtb2RlKXtkb20ubW9kZVBpbGwuY2xhc3NOYW1lPSdtb2RlICcrbW9kZTsgZG9tLm1vZGVQaWxsLnRleHRDb250ZW50PW1vZGU7fQogICAgY29uc3Qgc2NlbmU9bmV3IFRIUkVFLlNjZW5lKCk7IHNjZW5lLmJhY2tncm91bmQ9bmV3IFRIUkVFLkNvbG9yKDB4QzNDOEM4KTsgc2NlbmUuZm9nPW5ldyBUSFJFRS5Gb2coMHhDM0M4QzgsNzAsMjAwKTsKICAgIGNvbnN0IGNhbWVyYT1uZXcgVEhSRUUuUGVyc3BlY3RpdmVDYW1lcmEoNDUsIElXKCkvSUgoKSwgMC4xLCAxMjApOyBjb25zdCBkZWZhdWx0Q2FtUG9zPXt4OjAseToyMix6OjQwfTsgY29uc3QgZGVmYXVsdExvb2tBdD1uZXcgVEhSRUUuVmVjdG9yMygwLDcsMCk7IGNhbWVyYS5wb3NpdGlvbi5zZXQoZGVmYXVsdENhbVBvcy54LGRlZmF1bHRDYW1Qb3MueSxkZWZhdWx0Q2FtUG9zLnopOwogICAgY29uc3QgcmVuZGVyZXI9bmV3IFRIUkVFLldlYkdMUmVuZGVyZXIoe2FudGlhbGlhczp0cnVlfSk7IHJlbmRlcmVyLnNldFNpemUoSVcoKSxJSCgpKTsgcmVuZGVyZXIuc2V0UGl4ZWxSYXRpbyhNYXRoLm1pbih3aW5kb3cuZGV2aWNlUGl4ZWxSYXRpb3x8MSwyKSk7IHJlbmRlcmVyLnNoYWRvd01hcC5lbmFibGVkPXRydWU7IHJlbmRlcmVyLnNoYWRvd01hcC50eXBlPVRIUkVFLlBDRlNvZnRTaGFkb3dNYXA7IGRvbS53ZWJnbC5hcHBlbmRDaGlsZChyZW5kZXJlci5kb21FbGVtZW50KTsgdHJ5eyByZW5kZXJlci5kb21FbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3dlYmdsY29udGV4dGxvc3QnLGZ1bmN0aW9uKGUpe2UucHJldmVudERlZmF1bHQoKTt9LGZhbHNlKTsgcmVuZGVyZXIuZG9tRWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCd3ZWJnbGNvbnRleHRyZXN0b3JlZCcsZnVuY3Rpb24oKXsgdHJ5eyByZW5kZXJlci5zZXRTaXplKElXKCksSUgoKSk7IHJlbmRlcmVyLnNldFBpeGVsUmF0aW8oTWF0aC5taW4od2luZG93LmRldmljZVBpeGVsUmF0aW98fDEsMikpOyByZW5kZXJlci5zaGFkb3dNYXAuZW5hYmxlZD10cnVlOyByZW5kZXJlci5zaGFkb3dNYXAudHlwZT1USFJFRS5QQ0ZTb2Z0U2hhZG93TWFwOyB9Y2F0Y2goXyl7fX0gLGZhbHNlKTsgfWNhdGNoKF8pe30KICAgIGNvbnN0IGNvbnRyb2xzPXt0YXJnZXQ6ZGVmYXVsdExvb2tBdC5jbG9uZSgpLHVwZGF0ZSgpe2NhbWVyYS5sb29rQXQodGhpcy50YXJnZXQpfX07IGNvbnN0IHVwZGF0ZUNhbWVyYT0oKT0+Y2FtZXJhLmxvb2tBdChjb250cm9scy50YXJnZXQpOyBmdW5jdGlvbiBhcHBseVJlc3BvbnNpdmVGcmFtaW5nKCl7IHZhciBhPWNhbWVyYS5hc3BlY3R8fDE7IHZhciBrPWE8MT9NYXRoLm1pbigxLjcsMS4xMi9hKToxOyBkZWZhdWx0Q2FtUG9zLno9NDAqazsgZGVmYXVsdENhbVBvcy55PTIyKigwLjg2KzAuMTQqayk7IGlmKHN0YXRlLnZpZXc9PT0nT1ZFUlZJRVcnKXsgY2FtZXJhLnBvc2l0aW9uLnNldChkZWZhdWx0Q2FtUG9zLngsZGVmYXVsdENhbVBvcy55LGRlZmF1bHRDYW1Qb3Mueik7IGNvbnRyb2xzLnRhcmdldC5jb3B5KGRlZmF1bHRMb29rQXQpOyB1cGRhdGVDYW1lcmEoKTsgfSB9IGFwcGx5UmVzcG9uc2l2ZUZyYW1pbmcoKTsKICAgIGZ1bmN0aW9uIGdldFNwaGVyaWNhbCgpe2NvbnN0IG89Y2FtZXJhLnBvc2l0aW9uLmNsb25lKCkuc3ViKGNvbnRyb2xzLnRhcmdldCk7IGNvbnN0IHJhZGl1cz1NYXRoLm1heCgwLjAwMSxvLmxlbmd0aCgpKTsgY29uc3QgcG9sYXI9TWF0aC5hY29zKFRIUkVFLk1hdGhVdGlscy5jbGFtcChvLnkvcmFkaXVzLC0xLDEpKTsgY29uc3QgYXppbXV0aD1NYXRoLmF0YW4yKG8ueCxvLnopOyByZXR1cm4ge3JhZGl1cyxwb2xhcixhemltdXRofTt9CiAgICBmdW5jdGlvbiBzZXRGcm9tU3BoZXJpY2FsKHJhZGl1cyxwb2xhcixhemltdXRoKXtjb25zdCBtaW5SPTYsbWF4Uj00OCxtaW5QPTAuMjUsbWF4UD1NYXRoLlBJLzItMC4wNTsgY29uc3Qgcj1NYXRoLm1heChtaW5SLE1hdGgubWluKG1heFIscmFkaXVzKSksIHA9TWF0aC5tYXgobWluUCxNYXRoLm1pbihtYXhQLHBvbGFyKSk7IGNhbWVyYS5wb3NpdGlvbi5zZXQoY29udHJvbHMudGFyZ2V0LngrcipNYXRoLnNpbihwKSpNYXRoLnNpbihhemltdXRoKSwgY29udHJvbHMudGFyZ2V0LnkrcipNYXRoLmNvcyhwKSwgY29udHJvbHMudGFyZ2V0LnorcipNYXRoLnNpbihwKSpNYXRoLmNvcyhhemltdXRoKSk7IHVwZGF0ZUNhbWVyYSgpO30KICAgIHNjZW5lLmFkZChuZXcgVEhSRUUuQW1iaWVudExpZ2h0KDB4ZmZmZmZmLDAuNjUpKTsgY29uc3QgZGlyTGlnaHQ9bmV3IFRIUkVFLkRpcmVjdGlvbmFsTGlnaHQoMHhmZmZmZmYsMC45NSk7IGRpckxpZ2h0LnBvc2l0aW9uLnNldCgxNSwyNSwxMCk7IGRpckxpZ2h0LmNhc3RTaGFkb3c9dHJ1ZTsgZGlyTGlnaHQuc2hhZG93Lm1hcFNpemUud2lkdGg9MjA0ODsgZGlyTGlnaHQuc2hhZG93Lm1hcFNpemUuaGVpZ2h0PTIwNDg7IHNjZW5lLmFkZChkaXJMaWdodCk7CiAgICBjb25zdCBpbnRlcmFjdGFibGVzPVtdLCB0cmFja2luZ1BvaW50cz1bXSwgZGF0YUxpbmVzPVtdLCByYXdEYXRhUGFja2V0cz1bXSwgcHJpb3JpdHlEYXRhUGFja2V0cz1bXTsgbGV0IGNuY0dsYXNzRG9vcj1udWxsLCByb3RhdGluZ0RyaWxsQml0PW51bGwsIGluc3BlY3Rpb25DYW1lcmE9bnVsbCwgaW5zcGVjdGlvbkdsb3c9bnVsbCwgYWxlcnRCZWFjb25MaWdodD1udWxsLCBhbGVydEJlYWNvbk1hcmtlcj1udWxsLCBhbGVydEJlYWNvblN3ZWVwPW51bGwsIGFsZXJ0QmVhY29uRG9tZT1udWxsLCB3b3JrcGllY2VHcm91cD1udWxsLCB3b3JrcGllY2VDdXRHbG93PW51bGwsIGlpb3RCb2FyZD1udWxsOyBjb25zdCBzZXJ2ZXJCYXJzPVtdOwogICAgY29uc3QgZGFzaGJvYXJkVGV4dHVyZXM9W107CiAgICBjb25zdCBtYXRXaGl0ZU1ldGFsPW5ldyBUSFJFRS5NZXNoU3RhbmRhcmRNYXRlcmlhbCh7Y29sb3I6MHhmZmZmZmYscm91Z2huZXNzOjAuMjgsbWV0YWxuZXNzOjAuMTJ9KTsgY29uc3QgbWF0RGFya01ldGFsPW5ldyBUSFJFRS5NZXNoU3RhbmRhcmRNYXRlcmlhbCh7Y29sb3I6MHgzQzNEM0Qscm91Z2huZXNzOjAuNTUsbWV0YWxuZXNzOjAuNDV9KTsgY29uc3QgbWF0UmVkQWNjZW50PW5ldyBUSFJFRS5NZXNoU3RhbmRhcmRNYXRlcmlhbCh7Y29sb3I6MHg5NzA3MjUscm91Z2huZXNzOjAuMzUsbWV0YWxuZXNzOjAuMTh9KTsgY29uc3QgbWF0R2xhc3M9bmV3IFRIUkVFLk1lc2hQaHlzaWNhbE1hdGVyaWFsKHtjb2xvcjoweDg4Y2ZmZix0cmFuc3BhcmVudDp0cnVlLG9wYWNpdHk6MC4zLHJvdWdobmVzczowLjA4LHRyYW5zbWlzc2lvbjowLjV9KTsgY29uc3QgbWF0U2Vuc29yPW5ldyBUSFJFRS5NZXNoQmFzaWNNYXRlcmlhbCh7Y29sb3I6MHhEQzAwMkJ9KTsKICAgIGZ1bmN0aW9uIGFkZFB1bHNlKG1lc2gsY29sb3Isc2NhbGUpe2NvbnN0IGdsb3c9bmV3IFRIUkVFLlBvaW50TGlnaHQoY29sb3IsLjUsMyk7IG1lc2guYWRkKGdsb3cpOyBnc2FwLnRvKG1lc2guc2NhbGUse3g6c2NhbGUseTpzY2FsZSx6OnNjYWxlLHJlcGVhdDotMSx5b3lvOnRydWUsZHVyYXRpb246MS41K01hdGgucmFuZG9tKCkqLjYsZWFzZTonc2luZS5pbk91dCd9KTsgZ3NhcC50byhnbG93LHtpbnRlbnNpdHk6MSxyZXBlYXQ6LTEseW95bzp0cnVlLGR1cmF0aW9uOjEuNStNYXRoLnJhbmRvbSgpKi42LGVhc2U6J3NpbmUuaW5PdXQnfSk7fQogICAgZnVuY3Rpb24gY3JlYXRlRGFzaGJvYXJkVGV4dHVyZSh3aWR0aD00MjAsaGVpZ2h0PTI0MCl7Y29uc3QgY2FudmFzPWRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpOyBjYW52YXMud2lkdGg9d2lkdGg7IGNhbnZhcy5oZWlnaHQ9aGVpZ2h0OyBjb25zdCBjdHg9Y2FudmFzLmdldENvbnRleHQoJzJkJyk7IGNvbnN0IHRleD1uZXcgVEhSRUUuQ2FudmFzVGV4dHVyZShjYW52YXMpOyBkYXNoYm9hcmRUZXh0dXJlcy5wdXNoKHtjYW52YXMsY3R4LHRleH0pOyByZXR1cm4gdGV4O30KICAgIGZ1bmN0aW9uIHVwZGF0ZURhc2hib2FyZFRleHR1cmVzKCl7ZGFzaGJvYXJkVGV4dHVyZXMuZm9yRWFjaCgoe2NhbnZhcyxjdHgsdGV4fSk9Pntjb25zdCB3PWNhbnZhcy53aWR0aCxoPWNhbnZhcy5oZWlnaHQ7IGN0eC5jbGVhclJlY3QoMCwwLHcsaCk7IGN0eC5maWxsU3R5bGU9JyMwRjFBMjQnOyBjdHguZmlsbFJlY3QoMCwwLHcsaCk7IGN0eC5maWxsU3R5bGU9JyNGRkZGRkYnOyBjdHguZm9udD0nYm9sZCAxOHB4IEludGVyLCBBcmlhbCc7IGN0eC5maWxsVGV4dCgnRmFjdG9yeSBpbnNpZ2h0JywxOCwyNik7IGN0eC5maWxsU3R5bGU9JyM4Nzg3ODcnOyBjdHguZmlsbFJlY3QoMTgsNDIsdyouNDIsMzQpOyBjdHguZmlsbFJlY3QoMTgsODgsdyouMjgsMTEwKTsgY3R4LmZpbGxSZWN0KDE4K3cqLjMyLDg4LHcqLjI4LDExMCk7IGN0eC5maWxsUmVjdCgxOCt3Ki42NCw0Mix3Ki4yNiwxNTYpOyBjdHguZmlsbFN0eWxlPScjQkEwMzI4JzsgY29uc3QgcHVsc2U9KE1hdGguc2luKHN0YXRlLnRpbWUqMi40KSsxKS8yOyBjdHguZ2xvYmFsQWxwaGE9LjQ1Ky4zNSpwdWxzZTsgY3R4LmZpbGxSZWN0KDMwLDk4LHcqLjE4LDkwKTsgY3R4LmZpbGxSZWN0KDMwK3cqLjI0LDEyOCx3Ki4xOCw2MCk7IGN0eC5maWxsUmVjdCgzMCt3Ki40OCw3MCx3Ki4xNiwxMTgpOyBjdHguZ2xvYmFsQWxwaGE9MTsgY3R4LmZpbGxTdHlsZT0nI0ZGRkZGRic7IGN0eC5mb250PScxMnB4IEludGVyLCBBcmlhbCc7IGN0eC5maWxsVGV4dCgnTUVTIHF1ZXVlJywyOCw2Myk7IGN0eC5maWxsVGV4dCgnUHJpb3JpdHknLDM2LDEyMCk7IGN0eC5maWxsVGV4dCgnV29ya2VyIHRhc2snLDM2K3cqLjI0LDE1MCk7IGN0eC5maWxsVGV4dCgnUmVjb21tZW5kYXRpb24nLDM2K3cqLjQ4LDkyKTsgdGV4Lm5lZWRzVXBkYXRlPXRydWU7fSk7fQogICAgZnVuY3Rpb24gY3JlYXRlRGF0YVN0cmVhbSh4MSx5MSx6MSx4Mix5Mix6Mil7Y29uc3QgbWF0PW5ldyBUSFJFRS5MaW5lRGFzaGVkTWF0ZXJpYWwoe2NvbG9yOjB4QkEwMzI4LGRhc2hTaXplOi41LGdhcFNpemU6LjUsbGluZXdpZHRoOjN9KTsgY29uc3QgZ2VvPW5ldyBUSFJFRS5CdWZmZXJHZW9tZXRyeSgpLnNldEZyb21Qb2ludHMoW25ldyBUSFJFRS5WZWN0b3IzKHgxLHkxLHoxKSxuZXcgVEhSRUUuVmVjdG9yMyh4Mix5Mix6MildKTsgY29uc3QgbGluZT1uZXcgVEhSRUUuTGluZShnZW8sbWF0KTsgbGluZS5jb21wdXRlTGluZURpc3RhbmNlcygpOyBzY2VuZS5hZGQobGluZSk7IGRhdGFMaW5lcy5wdXNoKGxpbmUpO30KICAgIGZ1bmN0aW9uIGNyZWF0ZURhdGFQYWNrZXRTdHJlYW0oc3RhcnQsZW5kLG1vZGUpeyBjb25zdCBncm91cD1uZXcgVEhSRUUuR3JvdXAoKTsgZ3JvdXAudXNlckRhdGE9e3N0YXJ0Om5ldyBUSFJFRS5WZWN0b3IzKHN0YXJ0Lngsc3RhcnQueSxzdGFydC56KSxlbmQ6bmV3IFRIUkVFLlZlY3RvcjMoZW5kLngsZW5kLnksZW5kLnopLG1vZGV9OyBjb25zdCBjb3VudD1tb2RlPT09J3Jhdyc\/MTg6MTA7IGNvbnN0IGNvbG91cnM9bW9kZT09PSdyYXcnP1sweERDMDAyQiwweEJBMDMyOCwweGZmZmZmZiwweDg3ODc4N106WzB4ZmZmZmZmLDB4REMwMDJCLDB4MzJDODdBXTsgZm9yKGxldCBpPTA7aTxjb3VudDtpKyspeyBjb25zdCBnZW89bW9kZT09PSdyYXcnP25ldyBUSFJFRS5JY29zYWhlZHJvbkdlb21ldHJ5KC4wNTUrTWF0aC5yYW5kb20oKSouMDQsMCk6bmV3IFRIUkVFLkJveEdlb21ldHJ5KC4xMiwuMTIsLjEyKTsgY29uc3QgbWF0PW5ldyBUSFJFRS5NZXNoQmFzaWNNYXRlcmlhbCh7Y29sb3I6Y29sb3Vyc1tpJWNvbG91cnMubGVuZ3RoXSx0cmFuc3BhcmVudDp0cnVlLG9wYWNpdHk6bW9kZT09PSdyYXcnPy40NjouODJ9KTsgY29uc3QgcGFja2V0PW5ldyBUSFJFRS5NZXNoKGdlbyxtYXQpOyBwYWNrZXQudXNlckRhdGE9e3BoYXNlOmkvY291bnQsb2Zmc2V0OihNYXRoLnJhbmRvbSgpLS41KSoobW9kZT09PSdyYXcnPzEuMTouMTIpLGxpZnQ6KE1hdGgucmFuZG9tKCktLjUpKihtb2RlPT09J3Jhdyc\/Ljk6LjEwKSxyYW5rOml9OyBncm91cC5hZGQocGFja2V0KTsgfSBzY2VuZS5hZGQoZ3JvdXApOyAobW9kZT09PSdyYXcnP3Jhd0RhdGFQYWNrZXRzOnByaW9yaXR5RGF0YVBhY2tldHMpLnB1c2goZ3JvdXApOyByZXR1cm4gZ3JvdXA7IH0KICAgIGZ1bmN0aW9uIHVwZGF0ZURhdGFQYWNrZXRTdHJlYW0oZ3JvdXApeyBjb25zdCBtb2RlPWdyb3VwLnVzZXJEYXRhLm1vZGU7IGNvbnN0IHN0YXJ0PWdyb3VwLnVzZXJEYXRhLnN0YXJ0OyBjb25zdCBlbmQ9Z3JvdXAudXNlckRhdGEuZW5kOyBncm91cC5jaGlsZHJlbi5mb3JFYWNoKChwYWNrZXQsaSk9PnsgcGFja2V0LnVzZXJEYXRhLnBoYXNlPShwYWNrZXQudXNlckRhdGEucGhhc2UrKG1vZGU9PT0ncmF3Jz8uMDA0ODouMDA2OCkpJTE7IGNvbnN0IHA9cGFja2V0LnVzZXJEYXRhLnBoYXNlOyBjb25zdCB3b2JibGU9bW9kZT09PSdyYXcnP01hdGguc2luKHN0YXRlLnRpbWUqNStpKSpwYWNrZXQudXNlckRhdGEub2Zmc2V0OjA7IGNvbnN0IGxpZnQ9bW9kZT09PSdyYXcnP01hdGguY29zKHN0YXRlLnRpbWUqNCtpKSpwYWNrZXQudXNlckRhdGEubGlmdDpNYXRoLnNpbihwKk1hdGguUEkpKi4yMjsgcGFja2V0LnBvc2l0aW9uLmxlcnBWZWN0b3JzKHN0YXJ0LGVuZCxwKTsgcGFja2V0LnBvc2l0aW9uLngrPXdvYmJsZTsgcGFja2V0LnBvc2l0aW9uLnkrPWxpZnQ7IGlmKG1vZGU9PT0ncHJpb3JpdHknKXsgY29uc3QgbGFuZT0oaSUzKS0xOyBwYWNrZXQucG9zaXRpb24ueis9bGFuZSouMTI7IHBhY2tldC5zY2FsZS5zZXRTY2FsYXIoLjcyK3AqLjU1KTsgcGFja2V0LnJvdGF0aW9uLnkrPS4wNjsgfSBlbHNlIHsgcGFja2V0LnNjYWxlLnNldFNjYWxhciguNzIrTWF0aC5zaW4oc3RhdGUudGltZSo4K2kpKi4xOCk7IHBhY2tldC5yb3RhdGlvbi54Kz0uMDg7IHBhY2tldC5yb3RhdGlvbi55Kz0uMDU7IH0gcGFja2V0Lm1hdGVyaWFsLm9wYWNpdHk9bW9kZT09PSdyYXcnPyguMjgrLjMyKk1hdGguc2luKChwKk1hdGguUEkpKSk6KC40NSsuNDUqcCk7IH0pOyB9CiAgICBmdW5jdGlvbiBjcmVhdGVTZW5zb3IocGFyZW50LGlkLHgseSx6LGxhYmVsQW5jaG9yKXtsZXQgbWVzaDsgaWYoaWQ9PT0nc2Vuc29yX3NpZ2h0Jyl7bWVzaD1uZXcgVEhSRUUuR3JvdXAoKTsgY29uc3QgYm9keT1uZXcgVEhSRUUuTWVzaChuZXcgVEhSRUUuQm94R2VvbWV0cnkoLjc4LC40OCwuNTQpLCBuZXcgVEhSRUUuTWVzaFN0YW5kYXJkTWF0ZXJpYWwoe2NvbG9yOjB4ZmZmZmZmLHJvdWdobmVzczouMjIsbWV0YWxuZXNzOi4yfSkpOyBjb25zdCBsZW5zPW5ldyBUSFJFRS5NZXNoKG5ldyBUSFJFRS5DeWxpbmRlckdlb21ldHJ5KC4xOCwuMTgsLjM0LDI0KSwgbmV3IFRIUkVFLk1lc2hTdGFuZGFyZE1hdGVyaWFsKHtjb2xvcjoweDExMTExMX0pKTsgbGVucy5yb3RhdGlvbi56PU1hdGguUEkvMjsgbGVucy5wb3NpdGlvbi5zZXQoLS41NiwwLDApOyBjb25zdCBtb3VudD1uZXcgVEhSRUUuTWVzaChuZXcgVEhSRUUuQm94R2VvbWV0cnkoLjE0LC44NSwuMTQpLCBuZXcgVEhSRUUuTWVzaFN0YW5kYXJkTWF0ZXJpYWwoe2NvbG9yOjB4REMwMDJCfSkpOyBtb3VudC5wb3NpdGlvbi5zZXQoLjMwLC0uNTQsMCk7IGNvbnN0IGdsb3c9bmV3IFRIUkVFLk1lc2gobmV3IFRIUkVFLlNwaGVyZUdlb21ldHJ5KC43MiwxOCwxOCksIG5ldyBUSFJFRS5NZXNoQmFzaWNNYXRlcmlhbCh7Y29sb3I6MHhEQzAwMkIsdHJhbnNwYXJlbnQ6dHJ1ZSxvcGFjaXR5Oi4xNH0pKTsgY29uc3QgYmVhbT1uZXcgVEhSRUUuTWVzaChuZXcgVEhSRUUuQ29uZUdlb21ldHJ5KC40MiwxLjQ1LDIyLDEsdHJ1ZSksIG5ldyBUSFJFRS5NZXNoQmFzaWNNYXRlcmlhbCh7Y29sb3I6MHhEQzAwMkIsdHJhbnNwYXJlbnQ6dHJ1ZSxvcGFjaXR5Oi4xNixzaWRlOlRIUkVFLkRvdWJsZVNpZGV9KSk7IGJlYW0ucm90YXRpb24uej1NYXRoLlBJLzI7IGJlYW0ucm90YXRpb24ueT1NYXRoLlBJOyBiZWFtLnBvc2l0aW9uLnNldCgtMC45NSwtLjAyLDApOyBtZXNoLmFkZChib2R5LGxlbnMsbW91bnQsZ2xvdyxiZWFtKTsgbWVzaC5wb3NpdGlvbi5zZXQoeCx5KzAuMjAseiswLjEwKTsgbWVzaC5yb3RhdGlvbi5zZXQoMCxNYXRoLlBJLE1hdGguUEkvNCk7IGluc3BlY3Rpb25DYW1lcmE9bWVzaDsgaW5zcGVjdGlvbkdsb3c9Z2xvdzt9IGVsc2Uge21lc2g9bmV3IFRIUkVFLk1lc2gobmV3IFRIUkVFLlNwaGVyZUdlb21ldHJ5KC4yNCwxOCwxOCksbWF0U2Vuc29yKTsgbWVzaC5wb3NpdGlvbi5zZXQoeCx5LHopO30gY29uc3QgY2Ftcz17c2Vuc29yX3NpZ2h0Ont4Oi0xMC44LHk6Ny40LHo6MTIuNn0sc2Vuc29yX3RvdWNoOnt4Oi04LjkseTo3LjUsejoxMy4wfSxzZW5zb3JfaGVhcmluZzp7eDotOS44LHk6Ny44LHo6MTIuMn0sc2Vuc29yX3NtZWxsOnt4Oi03LjYseTo4LjYsejoxMy44fX07IG1lc2gudXNlckRhdGE9e2lkLHR5cGU6J21pY3JvJyxjYW1Qb3M6Y2Ftc1tpZF18fHt4Oi0xMC41LHk6OC41LHo6MTh9LGxvb2tBdDp7eDotMTAseTo0LHo6MH19OyBjb25zdCBsaWdodD1uZXcgVEhSRUUuUG9pbnRMaWdodCgweERDMDAyQiwxLDYpOyBtZXNoLmFkZChsaWdodCk7IHBhcmVudC5hZGQobWVzaCk7IGludGVyYWN0YWJsZXMucHVzaChtZXNoKTsgYWRkUHVsc2UobWVzaCwweERDMDAyQixpZD09PSdzZW5zb3Jfc2lnaHQnPzEuMTA6MS4zNSk7IGNvbnN0IGxhYmVsTWFwPXtzZW5zb3Jfc2lnaHQ6J2xibC1zaWdodCcsc2Vuc29yX3RvdWNoOidsYmwtdG91Y2gnLHNlbnNvcl9oZWFyaW5nOidsYmwtaGVhcmluZycsc2Vuc29yX3NtZWxsOidsYmwtc21lbGwnfTsgdHJhY2tpbmdQb2ludHMucHVzaCh7aWQ6bGFiZWxNYXBbaWRdLHBvczpsYWJlbEFuY2hvcn0pO30KICAgIGZ1bmN0aW9uIGNyZWF0ZUZhY3RvcnlGbG9vcigpewogICAgICBjb25zdCBmbG9vcj1uZXcgVEhSRUUuTWVzaChuZXcgVEhSRUUuUGxhbmVHZW9tZXRyeSg2MCw0MCksIG5ldyBUSFJFRS5NZXNoU3RhbmRhcmRNYXRlcmlhbCh7Y29sb3I6MHg4Nzg3ODcscm91Z2huZXNzOi44NX0pKTsKICAgICAgZmxvb3Iucm90YXRpb24ueD0tTWF0aC5QSS8yOyBmbG9vci5yZWNlaXZlU2hhZG93PXRydWU7IHNjZW5lLmFkZChmbG9vcik7CiAgICAgIGNvbnN0IGdyaWQ9bmV3IFRIUkVFLkdyaWRIZWxwZXIoNjAsMzAsMHgzQzNEM0QsMHgzQzNEM0QpOyBncmlkLnBvc2l0aW9uLnk9LjAxOyBncmlkLm1hdGVyaWFsLm9wYWNpdHk9LjM7IGdyaWQubWF0ZXJpYWwudHJhbnNwYXJlbnQ9dHJ1ZTsgc2NlbmUuYWRkKGdyaWQpOwogICAgICBjb25zdCBjbmNHcm91cD1uZXcgVEhSRUUuR3JvdXAoKTsgY25jR3JvdXAucG9zaXRpb24uc2V0KC0xMCwwLDApOwogICAgICBjb25zdCBjbmNCYXNlPW5ldyBUSFJFRS5NZXNoKG5ldyBUSFJFRS5Cb3hHZW9tZXRyeSg2LDEsNSksbWF0RGFya01ldGFsKTsgY25jQmFzZS5wb3NpdGlvbi55PS41OwogICAgICBjb25zdCBjbmNCYWNrPW5ldyBUSFJFRS5NZXNoKG5ldyBUSFJFRS5Cb3hHZW9tZXRyeSg2LDUsMSksbWF0V2hpdGVNZXRhbCk7IGNuY0JhY2sucG9zaXRpb24uc2V0KDAsMy41LC0yKTsKICAgICAgY29uc3QgY25jVG9wPW5ldyBUSFJFRS5NZXNoKG5ldyBUSFJFRS5Cb3hHZW9tZXRyeSg2LDEsNSksbWF0UmVkQWNjZW50KTsgY25jVG9wLnBvc2l0aW9uLnNldCgwLDYuNSwwKTsKICAgICAgY25jR2xhc3NEb29yPW5ldyBUSFJFRS5NZXNoKG5ldyBUSFJFRS5Cb3hHZW9tZXRyeSg1LjgsNSwuMiksbWF0R2xhc3MpOyBjbmNHbGFzc0Rvb3IucG9zaXRpb24uc2V0KDAsMy41LDIuNCk7CiAgICAgIGNvbnN0IHNwaW5kbGU9bmV3IFRIUkVFLk1lc2gobmV3IFRIUkVFLkN5bGluZGVyR2VvbWV0cnkoLjQyLC40MiwyLDMyKSxtYXREYXJrTWV0YWwpOyBzcGluZGxlLnBvc2l0aW9uLnNldCgwLDQuNSwwKTsKICAgICAgcm90YXRpbmdEcmlsbEJpdD1uZXcgVEhSRUUuR3JvdXAoKTsKICAgICAgY29uc3QgYml0R2VvPW5ldyBUSFJFRS5DeWxpbmRlckdlb21ldHJ5KC4xNSwuMTUsMi4wLDUsMTYpOwogICAgICBjb25zdCBwb3NBdHRyPWJpdEdlby5hdHRyaWJ1dGVzLnBvc2l0aW9uOwogICAgICBmb3IobGV0IGk9MDtpPHBvc0F0dHIuY291bnQ7aSsrKXsKICAgICAgICBjb25zdCB5PXBvc0F0dHIuZ2V0WShpKSwgYW5nbGU9eSpNYXRoLlBJKjMsIHg9cG9zQXR0ci5nZXRYKGkpLCB6PXBvc0F0dHIuZ2V0WihpKTsKICAgICAgICBjb25zdCBueD14Kk1hdGguY29zKGFuZ2xlKS16Kk1hdGguc2luKGFuZ2xlKTsKICAgICAgICBjb25zdCBuej14Kk1hdGguc2luKGFuZ2xlKSt6Kk1hdGguY29zKGFuZ2xlKTsKICAgICAgICBwb3NBdHRyLnNldFhZWihpLG54LHksbnopOwogICAgICB9CiAgICAgIGJpdEdlby5jb21wdXRlVmVydGV4Tm9ybWFscygpOwogICAgICBjb25zdCBkcmlsbEdyZXlNYXRlcmlhbD1uZXcgVEhSRUUuTWVzaFN0YW5kYXJkTWF0ZXJpYWwoe2NvbG9yOjB4ODc4Nzg3LHJvdWdobmVzczouMzYsbWV0YWxuZXNzOi41NX0pOwogICAgICBjb25zdCBiaXRNZXNoPW5ldyBUSFJFRS5NZXNoKGJpdEdlbyxkcmlsbEdyZXlNYXRlcmlhbCk7CiAgICAgIGJpdE1lc2gucG9zaXRpb24ueT0tLjM1OyBiaXRNZXNoLmNhc3RTaGFkb3c9dHJ1ZTsKICAgICAgcm90YXRpbmdEcmlsbEJpdC5hZGQoYml0TWVzaCk7IHJvdGF0aW5nRHJpbGxCaXQucG9zaXRpb24uc2V0KDAsMy45NiwwKTsKICAgICAgY29uc3QgYmVkPW5ldyBUSFJFRS5NZXNoKG5ldyBUSFJFRS5Cb3hHZW9tZXRyeSgzLC41LDIpLG1hdFdoaXRlTWV0YWwpOyBiZWQucG9zaXRpb24uc2V0KDAsMS4yNSwuNSk7CiAgICAgIHdvcmtwaWVjZUdyb3VwPW5ldyBUSFJFRS5Hcm91cCgpOwogICAgICBjb25zdCBzdWJzdHJhdGU9bmV3IFRIUkVFLk1lc2gobmV3IFRIUkVFLkJveEdlb21ldHJ5KDEuNTUsLjI0LDEuMDIpLCBuZXcgVEhSRUUuTWVzaFN0YW5kYXJkTWF0ZXJpYWwoe2NvbG9yOjB4ZDlkZGUyLHJvdWdobmVzczouMzQsbWV0YWxuZXNzOi4zOH0pKTsgc3Vic3RyYXRlLnBvc2l0aW9uLnk9MS43MjsKICAgICAgY29uc3QgcG9ja2V0PW5ldyBUSFJFRS5NZXNoKG5ldyBUSFJFRS5Cb3hHZW9tZXRyeSguODIsLjEwLC40NiksIG5ldyBUSFJFRS5NZXNoU3RhbmRhcmRNYXRlcmlhbCh7Y29sb3I6MHhhYWIyYmMscm91Z2huZXNzOi40MixtZXRhbG5lc3M6LjI0fSkpOyBwb2NrZXQucG9zaXRpb24uc2V0KDAsMS44ODUsMCk7CiAgICAgIGNvbnN0IGlzbGFuZD1uZXcgVEhSRUUuTWVzaChuZXcgVEhSRUUuQm94R2VvbWV0cnkoLjI0LC4wOCwuMTgpLCBuZXcgVEhSRUUuTWVzaFN0YW5kYXJkTWF0ZXJpYWwoe2NvbG9yOjB4YmRjN2QyLHJvdWdobmVzczouMyxtZXRhbG5lc3M6LjIyfSkpOyBpc2xhbmQucG9zaXRpb24uc2V0KC4xOCwxLjkyLC4wOCk7CiAgICAgIHdvcmtwaWVjZUN1dEdsb3c9bmV3IFRIUkVFLk1lc2gobmV3IFRIUkVFLkJveEdlb21ldHJ5KC44OCwuMDI1LC41KSwgbmV3IFRIUkVFLk1lc2hCYXNpY01hdGVyaWFsKHtjb2xvcjoweERDMDAyQix0cmFuc3BhcmVudDp0cnVlLG9wYWNpdHk6LjEwfSkpOyB3b3JrcGllY2VDdXRHbG93LnBvc2l0aW9uLnNldCgwLDEuODQsMCk7CiAgICAgIHdvcmtwaWVjZUdyb3VwLmFkZChzdWJzdHJhdGUscG9ja2V0LGlzbGFuZCx3b3JrcGllY2VDdXRHbG93KTsKICAgICAgY29uc3QgYmVhY29uR3JvdXA9bmV3IFRIUkVFLkdyb3VwKCk7CiAgICAgIGNvbnN0IGJlYWNvbkJhc2U9bmV3IFRIUkVFLk1lc2gobmV3IFRIUkVFLkJveEdlb21ldHJ5KC44NCwuMjQsLjg0KSwgbmV3IFRIUkVFLk1lc2hTdGFuZGFyZE1hdGVyaWFsKHtjb2xvcjoweDIwMjMyYSxyb3VnaG5lc3M6LjU1LG1ldGFsbmVzczouMzZ9KSk7IGJlYWNvbkJhc2UucG9zaXRpb24ueT0uMTQ7CiAgICAgIGNvbnN0IGJlYWNvbkNvbGxhcj1uZXcgVEhSRUUuTWVzaChuZXcgVEhSRUUuQm94R2VvbWV0cnkoLjY2LC4xNCwuNjYpLCBuZXcgVEhSRUUuTWVzaFN0YW5kYXJkTWF0ZXJpYWwoe2NvbG9yOjB4M2Y0MzRlLHJvdWdobmVzczouNDYsbWV0YWxuZXNzOi4yOH0pKTsgYmVhY29uQ29sbGFyLnBvc2l0aW9uLnk9LjMyOwogICAgICBjb25zdCBiZWFjb25TdGVtPW5ldyBUSFJFRS5NZXNoKG5ldyBUSFJFRS5DeWxpbmRlckdlb21ldHJ5KC4wNiwuMDYsLjM4LDE2KSwgbmV3IFRIUkVFLk1lc2hTdGFuZGFyZE1hdGVyaWFsKHtjb2xvcjoweDZmNjI0Yixyb3VnaG5lc3M6LjUsbWV0YWxuZXNzOi4yMn0pKTsgYmVhY29uU3RlbS5wb3NpdGlvbi55PS41MjsKICAgICAgY29uc3QgYmVhY29uRG9tZT1uZXcgVEhSRUUuTWVzaChuZXcgVEhSRUUuU3BoZXJlR2VvbWV0cnkoLjM0LDI0LDI0LDAsTWF0aC5QSSoyLDAsTWF0aC5QSS8yKSwgbmV3IFRIUkVFLk1lc2hTdGFuZGFyZE1hdGVyaWFsKHtjb2xvcjoweDQ0ZDI2Yix0cmFuc3BhcmVudDp0cnVlLG9wYWNpdHk6LjkyLHJvdWdobmVzczouMixtZXRhbG5lc3M6LjA1LGVtaXNzaXZlOjB4MTEzMzIyLGVtaXNzaXZlSW50ZW5zaXR5Oi41NX0pKTsgYmVhY29uRG9tZS5wb3NpdGlvbi55PS43MjsgYWxlcnRCZWFjb25Eb21lPWJlYWNvbkRvbWU7CiAgICAgIGNvbnN0IGJlYWNvbkhhbG89bmV3IFRIUkVFLk1lc2gobmV3IFRIUkVFLlNwaGVyZUdlb21ldHJ5KC41NCwyMCwyMCksIG5ldyBUSFJFRS5NZXNoQmFzaWNNYXRlcmlhbCh7Y29sb3I6MHg0NGQyNmIsdHJhbnNwYXJlbnQ6dHJ1ZSxvcGFjaXR5Oi4xMH0pKTsgYmVhY29uSGFsby5wb3NpdGlvbi55PS43MjsKICAgICAgY29uc3QgcmF5cz1bXTsKICAgICAgZm9yKGxldCBpPTA7aTw1O2krKyl7CiAgICAgICAgY29uc3QgcmF5PW5ldyBUSFJFRS5NZXNoKG5ldyBUSFJFRS5Db25lR2VvbWV0cnkoLjA1LC4zMiwxMCksIG5ldyBUSFJFRS5NZXNoQmFzaWNNYXRlcmlhbCh7Y29sb3I6MHg0NGQyNmIsdHJhbnNwYXJlbnQ6dHJ1ZSxvcGFjaXR5Oi41NX0pKTsKICAgICAgICByYXkucG9zaXRpb24uc2V0KE1hdGguc2luKCgtMC40NStpKjAuMjIpKSowLjQyLDEuMTgrTWF0aC5jb3MoaSkqMC4wMixNYXRoLmNvcygoLTAuNDUraSowLjIyKSkqMC4wMik7CiAgICAgICAgcmF5LnJvdGF0aW9uLno9LTAuMTUraSowLjE0OwogICAgICAgIGJlYWNvbkdyb3VwLmFkZChyYXkpOyByYXlzLnB1c2gocmF5KTsKICAgICAgfQogICAgICBhbGVydEJlYWNvbkxpZ2h0PW5ldyBUSFJFRS5Qb2ludExpZ2h0KDB4NDRkMjZiLDEuMTUsNik7IGFsZXJ0QmVhY29uTGlnaHQucG9zaXRpb24uc2V0KDAsLjgyLDApOwogICAgICBhbGVydEJlYWNvbk1hcmtlcj1iZWFjb25IYWxvOyBhbGVydEJlYWNvblN3ZWVwPXJheXM7IGJlYWNvbkdyb3VwLmFkZChiZWFjb25CYXNlLGJlYWNvbkNvbGxhcixiZWFjb25TdGVtLGJlYWNvbkhhbG8sYmVhY29uRG9tZSxhbGVydEJlYWNvbkxpZ2h0KTsgYmVhY29uR3JvdXAucG9zaXRpb24uc2V0KDIuMDgsNi4zNSwxLjE4KTsKICAgICAgY3JlYXRlU2Vuc29yKGNuY0dyb3VwLCdzZW5zb3JfaGVhcmluZycsMCw0LjUsLjUsbmV3IFRIUkVFLlZlY3RvcjMoLTEwLDUsLjUpKTsKICAgICAgY3JlYXRlU2Vuc29yKGNuY0dyb3VwLCdzZW5zb3JfdG91Y2gnLDAsNS41LDAsbmV3IFRIUkVFLlZlY3RvcjMoLTEwLDYsMCkpOwogICAgICBjcmVhdGVTZW5zb3IoY25jR3JvdXAsJ3NlbnNvcl9zaWdodCcsLTEuNSw0LjY1LDEsbmV3IFRIUkVFLlZlY3RvcjMoLTExLjUsNS4yLDEpKTsKICAgICAgY3JlYXRlU2Vuc29yKGNuY0dyb3VwLCdzZW5zb3Jfc21lbGwnLDIuNSw2LC0xLG5ldyBUSFJFRS5WZWN0b3IzKC03LjUsNi41LC0xKSk7CiAgICAgIGNuY0dyb3VwLmFkZChjbmNCYXNlLGNuY0JhY2ssY25jVG9wLGNuY0dsYXNzRG9vcixzcGluZGxlLHJvdGF0aW5nRHJpbGxCaXQsYmVkLHdvcmtwaWVjZUdyb3VwLGJlYWNvbkdyb3VwKTsgc2NlbmUuYWRkKGNuY0dyb3VwKTsKICAgICAgY29uc3QgaGl0MT1uZXcgVEhSRUUuTWVzaChuZXcgVEhSRUUuQm94R2VvbWV0cnkoOCw5LDgpLCBuZXcgVEhSRUUuTWVzaEJhc2ljTWF0ZXJpYWwoe3Zpc2libGU6ZmFsc2V9KSk7IGhpdDEucG9zaXRpb24uY29weShjbmNHcm91cC5wb3NpdGlvbik7IGhpdDEucG9zaXRpb24ueT00OyBoaXQxLnVzZXJEYXRhPXtpZDoncGhhc2UxX2NuYycsdHlwZTonbWFjcm8nLGNhbVBvczp7eDotMTAseTo1Ljg1LHo6MTguMn0sbG9va0F0Ont4Oi0xMCx5OjMuNDUsejowfX07IGludGVyYWN0YWJsZXMucHVzaChoaXQxKTsgc2NlbmUuYWRkKGhpdDEpOyB0cmFja2luZ1BvaW50cy5wdXNoKHtpZDonbGJsLXBoYXNlMScscG9zOm5ldyBUSFJFRS5WZWN0b3IzKC0xMCw4LjA1LDApfSk7IGFkZFB1bHNlKGhpdDEsMHhEQzAwMkIsMS4wMSk7CiAgICAgIGNvbnN0IHNydkdyb3VwPW5ldyBUSFJFRS5Hcm91cCgpOyBzcnZHcm91cC5wb3NpdGlvbi5zZXQoMiwwLC01KTsgY29uc3Qgc2VydmVyPW5ldyBUSFJFRS5NZXNoKG5ldyBUSFJFRS5Cb3hHZW9tZXRyeSgzLjIsNi4yLDIuMiksbWF0RGFya01ldGFsKTsgc2VydmVyLnBvc2l0aW9uLnk9Mzsgc3J2R3JvdXAuYWRkKHNlcnZlcik7IGZvcihsZXQgaT0wO2k8NDtpKyspe2NvbnN0IGJhcj1uZXcgVEhSRUUuTWVzaChuZXcgVEhSRUUuUGxhbmVHZW9tZXRyeSgyLjEsLjIyKSwgbmV3IFRIUkVFLk1lc2hCYXNpY01hdGVyaWFsKHtjb2xvcjoweDVhMGExOCx0cmFuc3BhcmVudDp0cnVlLG9wYWNpdHk6LjMyfSkpOyBiYXIucG9zaXRpb24uc2V0KDAsMS41K2ksMS4xMik7IHNydkdyb3VwLmFkZChiYXIpOyBzZXJ2ZXJCYXJzLnB1c2goYmFyKTt9IHNjZW5lLmFkZChzcnZHcm91cCk7IGNvbnN0IGhpdDI9bmV3IFRIUkVFLk1lc2gobmV3IFRIUkVFLkJveEdlb21ldHJ5KDQuNSw3LjUsMy41KSwgbmV3IFRIUkVFLk1lc2hCYXNpY01hdGVyaWFsKHt2aXNpYmxlOmZhbHNlfSkpOyBoaXQyLnBvc2l0aW9uLmNvcHkoc3J2R3JvdXAucG9zaXRpb24pOyBoaXQyLnBvc2l0aW9uLnk9MzsgaGl0Mi51c2VyRGF0YT17aWQ6J3BoYXNlMl9lZGdlJyx0eXBlOidtYWNybycsY2FtUG9zOnt4OjIseTo1LjIsejoxMC41fSxsb29rQXQ6e3g6Mix5OjMsejotNX19OyBpbnRlcmFjdGFibGVzLnB1c2goaGl0Mik7IHNjZW5lLmFkZChoaXQyKTsgdHJhY2tpbmdQb2ludHMucHVzaCh7aWQ6J2xibC1waGFzZTInLHBvczpuZXcgVEhSRUUuVmVjdG9yMygyLDcuMDUsLTUpfSk7IGFkZFB1bHNlKGhpdDIsMHhEQzAwMkIsMS4wMSk7CiAgICAgIGNvbnN0IGRlc2tHcm91cD1uZXcgVEhSRUUuR3JvdXAoKTsgZGVza0dyb3VwLnBvc2l0aW9uLnNldCgxMiwwLDIpOyBjb25zdCBkZXNrPW5ldyBUSFJFRS5NZXNoKG5ldyBUSFJFRS5Cb3hHZW9tZXRyeSg0LC4yLDIpLG1hdERhcmtNZXRhbCk7IGRlc2sucG9zaXRpb24ueT0yLjU7IGNvbnN0IGxlZzE9bmV3IFRIUkVFLk1lc2gobmV3IFRIUkVFLkN5bGluZGVyR2VvbWV0cnkoLjEsLjEsMi41KSxtYXRXaGl0ZU1ldGFsKTsgbGVnMS5wb3NpdGlvbi5zZXQoLTEuOCwxLjI1LDApOyBjb25zdCBsZWcyPW5ldyBUSFJFRS5NZXNoKG5ldyBUSFJFRS5DeWxpbmRlckdlb21ldHJ5KC4xLC4xLDIuNSksbWF0V2hpdGVNZXRhbCk7IGxlZzIucG9zaXRpb24uc2V0KDEuOCwxLjI1LDApOyBjb25zdCBtb25GcmFtZT1uZXcgVEhSRUUuTWVzaChuZXcgVEhSRUUuQm94R2VvbWV0cnkoMiwxLjIsLjEpLG1hdFdoaXRlTWV0YWwpOyBtb25GcmFtZS5wb3NpdGlvbi5zZXQoMCwzLjIsLS41KTsgbW9uRnJhbWUucm90YXRpb24ueD0tLjI7IGNvbnN0IG1vblRleD1jcmVhdGVEYXNoYm9hcmRUZXh0dXJlKCk7IGNvbnN0IG1vbml0b3I9bmV3IFRIUkVFLk1lc2gobmV3IFRIUkVFLlBsYW5lR2VvbWV0cnkoMS44MiwxLjAyKSwgbmV3IFRIUkVFLk1lc2hCYXNpY01hdGVyaWFsKHttYXA6bW9uVGV4LHNpZGU6VEhSRUUuRG91YmxlU2lkZX0pKTsgbW9uaXRvci5wb3NpdGlvbi5zZXQoMCwzLjIyLC0uNDQpOyBtb25pdG9yLnJvdGF0aW9uLng9LS4yOyBjb25zdCB0YWJCb2R5PW5ldyBUSFJFRS5NZXNoKG5ldyBUSFJFRS5Cb3hHZW9tZXRyeSgxLjA4LC43NiwuMDYpLG1hdFdoaXRlTWV0YWwpOyB0YWJCb2R5LnBvc2l0aW9uLnNldCgtMS4xLDIuNzgsLjM0KTsgdGFiQm9keS5yb3RhdGlvbi54PS0uNTI7IGNvbnN0IHRhYlRleD1jcmVhdGVEYXNoYm9hcmRUZXh0dXJlKCk7IGNvbnN0IHRhYmxldD1uZXcgVEhSRUUuTWVzaChuZXcgVEhSRUUuUGxhbmVHZW9tZXRyeSguOTQsLjYyKSwgbmV3IFRIUkVFLk1lc2hCYXNpY01hdGVyaWFsKHttYXA6dGFiVGV4LHNpZGU6VEhSRUUuRG91YmxlU2lkZX0pKTsgdGFibGV0LnBvc2l0aW9uLnNldCgtMS4xLDIuNzgzLC4zODUpOyB0YWJsZXQucm90YXRpb24ueD0tLjUyOyBjb25zdCBwaG9uZUJvZHk9bmV3IFRIUkVFLk1lc2gobmV3IFRIUkVFLkJveEdlb21ldHJ5KC40OCwuOTIsLjA1KSxtYXRXaGl0ZU1ldGFsKTsgcGhvbmVCb2R5LnBvc2l0aW9uLnNldCgxLjE1LDIuODQsLjQyKTsgcGhvbmVCb2R5LnJvdGF0aW9uLng9LS40ODsgY29uc3QgcGhvbmVUZXg9Y3JlYXRlRGFzaGJvYXJkVGV4dHVyZSgpOyBjb25zdCBwaG9uZT1uZXcgVEhSRUUuTWVzaChuZXcgVEhSRUUuUGxhbmVHZW9tZXRyeSguMzQsLjY4KSwgbmV3IFRIUkVFLk1lc2hCYXNpY01hdGVyaWFsKHttYXA6cGhvbmVUZXgsc2lkZTpUSFJFRS5Eb3VibGVTaWRlfSkpOyBwaG9uZS5wb3NpdGlvbi5zZXQoMS4xNSwyLjg0OCwuNDcyKTsgcGhvbmUucm90YXRpb24ueD0tLjQ4OyBkZXNrR3JvdXAuYWRkKGRlc2ssbGVnMSxsZWcyLG1vbkZyYW1lLG1vbml0b3IsdGFiQm9keSx0YWJsZXQscGhvbmVCb2R5LHBob25lKTsgc2NlbmUuYWRkKGRlc2tHcm91cCk7IGNvbnN0IGhpdDM9bmV3IFRIUkVFLk1lc2gobmV3IFRIUkVFLkJveEdlb21ldHJ5KDUsNSwzKSwgbmV3IFRIUkVFLk1lc2hCYXNpY01hdGVyaWFsKHt2aXNpYmxlOmZhbHNlfSkpOyBoaXQzLnBvc2l0aW9uLmNvcHkoZGVza0dyb3VwLnBvc2l0aW9uKTsgaGl0My5wb3NpdGlvbi55PTIuNTsgaGl0My51c2VyRGF0YT17aWQ6J3BoYXNlM19hY3QnLHR5cGU6J21hY3JvJyxjYW1Qb3M6e3g6MTIseTo1LHo6MTJ9LGxvb2tBdDp7eDoxMix5OjIuNSx6OjJ9fTsgaW50ZXJhY3RhYmxlcy5wdXNoKGhpdDMpOyBzY2VuZS5hZGQoaGl0Myk7IHRyYWNraW5nUG9pbnRzLnB1c2goe2lkOidsYmwtcGhhc2UzJyxwb3M6bmV3IFRIUkVFLlZlY3RvcjMoMTIsNS4wLDIpfSk7IGFkZFB1bHNlKGhpdDMsMHhEQzAwMkIsMS4wMSk7IGNyZWF0ZURhdGFTdHJlYW0oLTEwLDMsMCwyLDMsLTUpOyBjcmVhdGVEYXRhU3RyZWFtKDIsMywtNSwxMiwyLjUsMik7IGNyZWF0ZURhdGFQYWNrZXRTdHJlYW0oe3g6LTEwLHk6Myx6OjB9LHt4OjIseTozLHo6LTV9LCdyYXcnKTsgY3JlYXRlRGF0YVBhY2tldFN0cmVhbSh7eDoyLHk6Myx6Oi01fSx7eDoxMix5OjIuNSx6OjJ9LCdwcmlvcml0eScpO30gCiAgICBmdW5jdGlvbiBjcmVhdGVCb2FyZCgpe2NvbnN0IGM9ZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJyk7IGMud2lkdGg9MTIwMDsgYy5oZWlnaHQ9MzAwOyBjb25zdCBjdHg9Yy5nZXRDb250ZXh0KCcyZCcpOyBmdW5jdGlvbiBwYWludCgpe2N0eC5maWxsU3R5bGU9J3JnYmEoNjAsNjEsNjEsMC45MiknOyBjdHguZmlsbFJlY3QoMCwwLDEyMDAsMzAwKTsgY3R4LnN0cm9rZVN0eWxlPScjREMwMDJCJzsgY3R4LmxpbmVXaWR0aD0xMjsgY3R4LnN0cm9rZVJlY3QoMTAsMTAsMTE4MCwxOTYpOyBjdHguZmlsbFN0eWxlPScjRkZGRkZGJzsgY3R4LmZvbnQ9J2JvbGQgNDZweCBJbnRlciwgQXJpYWwnOyBjdHgudGV4dEFsaWduPSdjZW50ZXInOyBjdHguZmlsbFRleHQoJ0lJT1Q6IEZST00gU0lHTkFMIFRPIEFDVElPTicsNjAwLDcwKTsgY3R4LmZvbnQ9J2JvbGQgMzBweCBJbnRlciwgQXJpYWwnOyBjdHguZmlsbFN0eWxlPScjRkY3RTkzJzsgY3R4LmZpbGxUZXh0KCdTRU5TRSAoU2Vuc29ycykgIOKelCAgUFJPQ0VTUyAoU2VydmVyKSAg4p6UICBBQ1QgKFJlc3BvbnNlKScsNjAwLDEyNCk7IGN0eC5maWxsU3R5bGU9JyNGRkZGRkYnOyBjdHguZm9udD0nYm9sZCAyMnB4IEludGVyLCBBcmlhbCc7IGN0eC5maWxsVGV4dCgnQ0xJQ0sgQk9BUkQgVE8gRVhQTE9SRSBEQVRBIEZMT1cnLDYwMCwxNzIpO30gcGFpbnQoKTsgY29uc3QgdGV4PW5ldyBUSFJFRS5DYW52YXNUZXh0dXJlKGMpOyB0cnl7aWYoZG9jdW1lbnQuZm9udHMmJmRvY3VtZW50LmZvbnRzLnJlYWR5KWRvY3VtZW50LmZvbnRzLnJlYWR5LnRoZW4oZnVuY3Rpb24oKXtwYWludCgpO3RleC5uZWVkc1VwZGF0ZT10cnVlO30pO31jYXRjaChfKXt9IGlpb3RCb2FyZD1uZXcgVEhSRUUuTWVzaChuZXcgVEhSRUUuUGxhbmVHZW9tZXRyeSgyMi40LDUuNiksIG5ldyBUSFJFRS5NZXNoQmFzaWNNYXRlcmlhbCh7bWFwOnRleCx0cmFuc3BhcmVudDp0cnVlLHNpZGU6VEhSRUUuRG91YmxlU2lkZX0pKTsgaWlvdEJvYXJkLnBvc2l0aW9uLnNldCgxLDAuOTUsOSk7IGlpb3RCb2FyZC5yb3RhdGlvbi54PS1NYXRoLlBJLzQ7IGlpb3RCb2FyZC51c2VyRGF0YT17aWQ6J2lpb3RfbG9vcCcsdHlwZTonbWFjcm8nLGNhbVBvczp7eDoxLHk6MTIsejoyMn0sbG9va0F0Ont4OjEseToyLHo6OX19OyBzY2VuZS5hZGQoaWlvdEJvYXJkKTsgaW50ZXJhY3RhYmxlcy5wdXNoKGlpb3RCb2FyZCk7fSAKICAgIGNyZWF0ZUZhY3RvcnlGbG9vcigpOyBjcmVhdGVCb2FyZCgpOwogICAgZnVuY3Rpb24gaGlkZUJvYXJkKCl7IGlmKGlpb3RCb2FyZCl7IGdzYXAudG8oaWlvdEJvYXJkLnBvc2l0aW9uLHt5Oi00LGR1cmF0aW9uOjAuOCxlYXNlOidwb3dlcjIuaW5PdXQnfSk7IGdzYXAudG8oaWlvdEJvYXJkLm1hdGVyaWFsLHtvcGFjaXR5OjAsZHVyYXRpb246MC42fSk7IH0gfQogICAgZnVuY3Rpb24gc2hvd0JvYXJkKCl7IGlmKGlpb3RCb2FyZCl7IGdzYXAudG8oaWlvdEJvYXJkLnBvc2l0aW9uLHt5OjAuOTUsZHVyYXRpb246MC44LGVhc2U6J3Bvd2VyMi5pbk91dCd9KTsgZ3NhcC50byhpaW90Qm9hcmQubWF0ZXJpYWwse29wYWNpdHk6MSxkdXJhdGlvbjowLjZ9KTsgfSB9CiAgICBmdW5jdGlvbiBvcGVuUGFuZWwoaWQpeyBpZihJSU9UX1JPT1QpSUlPVF9ST09ULmNsYXNzTGlzdC5hZGQoJ3NyMS1wYW5lbC1vcGVuJyk7IGNvbnN0IGluZm89cGhhc2VEYXRhW2lkXTsgZG9tLnBUaXRsZS50ZXh0Q29udGVudD1pbmZvLnRpdGxlOyB1cGRhdGVQYW5lbENvbnRleHQoaWQpOyBkb20ucEZ1bi5pbm5lckhUTUw9bGlua2lmeVRleHQoaW5mby5kZXNjKTsgZG9tLnBBaW0uaW5uZXJIVE1MPWxpbmtpZnlUZXh0KGluZm8uYWltKTsgZG9tLmNhbWVyYUNhcmQuc3R5bGUuZGlzcGxheT1pbmZvLmNhbWVyYVZpZXc\/J2Jsb2NrJzonbm9uZSc7IGRvbS52Z3JpZC5jbGFzc0xpc3QudG9nZ2xlKCdzaW5nbGUnLCAhaW5mby5jYW1lcmFWaWV3KTsgZG9tLnBhbmVsLmNsYXNzTGlzdC5hZGQoJ2FjdGl2ZScpOyB2YXIgX2hkcj1JSU9UX1JPT1QucXVlcnlTZWxlY3RvcignLmhlYWRlcicpOyBpZihfaGRyKSBfaGRyLmNsYXNzTGlzdC5hZGQoJ2RpbScpOyBzZXRPdmVydmlld05vdGUoaWQ9PT0ncGhhc2UxX2NuYycpOyBzdGF0ZS5zZWxlY3Rpb249aWQ7IHN0YXRlLmNoYXJ0VHlwZT1pbmZvLmNoYXJ0VHlwZTsgc3RhdGUuY2hhcnREYXRhPVtdOyBzeW5jQ2FudmFzZXMoKTsgfQogICAgZnVuY3Rpb24gaGFuZGxlU2VsZWN0aW9uKGRhdGEpeyBjb25zdCBpbmZvPXBoYXNlRGF0YVtkYXRhLmlkXTsgaWYoIWluZm8pIHJldHVybjsgaWYoZGF0YS5pZD09PSdwaGFzZTFfY25jJyl7IHN0YXRlLnZpZXc9J1BIQVNFMSc7IGdzYXAudG8oY25jR2xhc3NEb29yLnBvc2l0aW9uLHt5OjYsZHVyYXRpb246MS4yLGVhc2U6J3Bvd2VyMi5pbk91dCd9KTsgZ3NhcC50byhjbmNHbGFzc0Rvb3IubWF0ZXJpYWwse29wYWNpdHk6MCxkdXJhdGlvbjoxfSk7IHNob3dTZW5zb3JzKHRydWUpOyBzaG93TWFpbihmYWxzZSk7IHNldE92ZXJ2aWV3Tm90ZSh0cnVlKTsgaGlkZUJvYXJkKCk7IHNldFN0YXR1cygnVGhlIGN1dHRlciwgYmVhY29uIGFuZCBsaXZlIHZpZXcgY3ljbGUgdG9nZXRoZXIuIFNlbGVjdCBhIHNlbnNvciB0byBpbnNwZWN0IGl0cyB0aHJlc2hvbGQgYmVoYXZpb3VyLicpOyB9IGVsc2UgaWYoZGF0YS50eXBlPT09J21pY3JvJyl7IHN0YXRlLnZpZXc9J01JQ1JPJzsgc2hvd1NlbnNvcnModHJ1ZSk7IHNob3dNYWluKGZhbHNlKTsgc2V0T3ZlcnZpZXdOb3RlKGZhbHNlKTsgY29uc3Qgc2VsZWN0ZWRJZD0nbGJsLScrZGF0YS5pZC5zcGxpdCgnXycpWzFdOyBkb20ubGFiZWxzU2Vuc29yLmZvckVhY2goZWw9PnsgaWYoZWwuaWQ9PT1zZWxlY3RlZElkKXsgZWwuc3R5bGUub3BhY2l0eT0xOyBlbC5zdHlsZS50cmFuc2Zvcm09J3RyYW5zbGF0ZSgtNTAlLC01MCUpIHNjYWxlKDEuMSknOyB9IGVsc2UgeyBlbC5zdHlsZS5vcGFjaXR5PTAuNDsgZWwuc3R5bGUudHJhbnNmb3JtPSd0cmFuc2xhdGUoLTUwJSwtNTAlKSBzY2FsZSgxKSc7IH0gfSk7IHNldFN0YXR1cyhpbmZvLnRpdGxlICsgJy4gRWFjaCBzZW5zb3Igbm93IHVzZXMgaXRzIG93biB2aXNpYmxlIHRocmVzaG9sZCwgYW5kIGZhdWx0IHN0YXRlcyBhcmUgc2hvd24gd2hlbiB0aGUgc2lnbmFsIGNyb3NzZXMgdGhhdCBsaW1pdC4nKTsgfSBlbHNlIHsgc3RhdGUudmlldz1kYXRhLmlkOyBzaG93U2Vuc29ycyhmYWxzZSk7IHNob3dNYWluKGZhbHNlKTsgc2V0T3ZlcnZpZXdOb3RlKGZhbHNlKTsgZ3NhcC50byhjbmNHbGFzc0Rvb3IucG9zaXRpb24se3k6My41LGR1cmF0aW9uOjEsZWFzZToncG93ZXIyLmluT3V0J30pOyBnc2FwLnRvKGNuY0dsYXNzRG9vci5tYXRlcmlhbCx7b3BhY2l0eTouMyxkdXJhdGlvbjoxfSk7IGlmKGRhdGEuaWQ9PT0ncGhhc2UyX2VkZ2UnKSBzZXRTdGF0dXMoJ0RhdGEgaXMgZmlyc3Qgc3RvcmVkIGluIGEgc2VydmVyLCB0aGVuIHByb2Nlc3NlZCBzbyB1c2VmdWwgc2lnbmFscyBjYW4gYmUgcHJpb3JpdGlzZWQuJyk7IGVsc2UgaWYoZGF0YS5pZD09PSdwaGFzZTNfYWN0Jykgc2V0U3RhdHVzKCdJbnNpZ2h0IGlzIHJvdXRlZCB0byB0aGUgcmlnaHQgcGVvcGxlIG9yIHN5c3RlbXMuJyk7IGVsc2Ugc2V0U3RhdHVzKCdSZXZpZXcgaG93IHNlbnNpbmcsIHNlcnZlcnMgYW5kIHJlc3BvbnNlIGNvbm5lY3QgaW50byBvbmUgam91cm5leS4nKTsgaWYoZGF0YS5pZD09PSdpaW90X2xvb3AnKSBzaG93Qm9hcmQoKTsgfQogICAgICB2YXIgX3BkeD1kYXRhLmNhbVBvcy54LWRhdGEubG9va0F0LngsX3BkeT1kYXRhLmNhbVBvcy55LWRhdGEubG9va0F0LnksX3Bkej1kYXRhLmNhbVBvcy56LWRhdGEubG9va0F0Lno7IHZhciBfcGRpc3Q9TWF0aC5zcXJ0KF9wZHgqX3BkeCtfcGR5Kl9wZHkrX3BkeipfcGR6KTsgdmFyIF9wYW5YPShJVygpPjYwMD9fcGRpc3QqMC4zMjowKTsgZ3NhcC50byhjYW1lcmEucG9zaXRpb24se3g6ZGF0YS5jYW1Qb3MueCtfcGFuWCx5OmRhdGEuY2FtUG9zLnksejpkYXRhLmNhbVBvcy56LGR1cmF0aW9uOjEuMCxlYXNlOidwb3dlcjMuaW5PdXQnLG9uVXBkYXRlOnVwZGF0ZUNhbWVyYX0pOyBnc2FwLnRvKGNvbnRyb2xzLnRhcmdldCx7eDpkYXRhLmxvb2tBdC54K19wYW5YLHk6ZGF0YS5sb29rQXQueSx6OmRhdGEubG9va0F0LnosZHVyYXRpb246MS4wLGVhc2U6J3Bvd2VyMy5pbk91dCcsb25VcGRhdGU6dXBkYXRlQ2FtZXJhfSk7IG9wZW5QYW5lbChkYXRhLmlkKTsgfQogICAgZnVuY3Rpb24gdHJpZ2dlclNlbGVjdGlvbihpZCl7IGNvbnN0IG89aW50ZXJhY3RhYmxlcy5maW5kKHY9PnYudXNlckRhdGEmJnYudXNlckRhdGEuaWQ9PT1pZCk7IGlmKG8pIGhhbmRsZVNlbGVjdGlvbihvLnVzZXJEYXRhKTsgfQogICAgZnVuY3Rpb24gcmVzZXRWaWV3KCl7IGlmKElJT1RfUk9PVClJSU9UX1JPT1QuY2xhc3NMaXN0LnJlbW92ZSgnc3IxLXBhbmVsLW9wZW4nKTsgc3RhdGUudmlldz0nT1ZFUlZJRVcnOyBzdGF0ZS5zZWxlY3Rpb249J292ZXJ2aWV3Jzsgc3RhdGUuc3RvcnlJbmRleD0wOyBpZihkb20uc1Byb2cpZG9tLnNQcm9nLnRleHRDb250ZW50PScwMSAvICcrU3RyaW5nKHN0b3J5U3RlcHMubGVuZ3RoKS5wYWRTdGFydCgyLCcwJyk7IGlmKGRvbS5zQmFyKWRvbS5zQmFyLnN0eWxlLndpZHRoPSgxL3N0b3J5U3RlcHMubGVuZ3RoKjEwMCkrJyUnOyBkb20ucGFuZWwuY2xhc3NMaXN0LnJlbW92ZSgnYWN0aXZlJyk7IHZhciBfaGRyPUlJT1RfUk9PVC5xdWVyeVNlbGVjdG9yKCcuaGVhZGVyJyk7IGlmKF9oZHIpIF9oZHIuY2xhc3NMaXN0LnJlbW92ZSgnZGltJyk7IGdzYXAudG8oY25jR2xhc3NEb29yLnBvc2l0aW9uLHt5OjMuNSxkdXJhdGlvbjoxLGVhc2U6J3Bvd2VyMi5pbk91dCd9KTsgZ3NhcC50byhjbmNHbGFzc0Rvb3IubWF0ZXJpYWwse29wYWNpdHk6LjMsZHVyYXRpb246MX0pOyBzaG93U2Vuc29ycyhmYWxzZSk7IGRvbS5sYWJlbHNTZW5zb3IuZm9yRWFjaChlbD0+e2VsLnN0eWxlLm9wYWNpdHk9MTsgZWwuc3R5bGUudHJhbnNmb3JtPSd0cmFuc2xhdGUoLTUwJSwtNTAlKSBzY2FsZSgxKSc7fSk7IHNob3dNYWluKHRydWUpOyBzZXRPdmVydmlld05vdGUoZmFsc2UpOyBzaG93Qm9hcmQoKTsgZ3NhcC50byhjYW1lcmEucG9zaXRpb24se3g6ZGVmYXVsdENhbVBvcy54LHk6ZGVmYXVsdENhbVBvcy55LHo6ZGVmYXVsdENhbVBvcy56LGR1cmF0aW9uOjEsZWFzZToncG93ZXIzLmluT3V0JyxvblVwZGF0ZTp1cGRhdGVDYW1lcmF9KTsgZ3NhcC50byhjb250cm9scy50YXJnZXQse3g6ZGVmYXVsdExvb2tBdC54LHk6ZGVmYXVsdExvb2tBdC55LHo6ZGVmYXVsdExvb2tBdC56LGR1cmF0aW9uOjEsZWFzZToncG93ZXIzLmluT3V0JyxvblVwZGF0ZTp1cGRhdGVDYW1lcmF9KTsgc2V0U3RhdHVzKCdPdmVydmlldyBtb2RlLiBDbGljayBhIHN0YWdlIGxhYmVsIHRvIGJlZ2luLicpOyB9CiAgICBmdW5jdGlvbiBzdGFydEV4cGVyaWVuY2UoKXsgaWYoc3RhdGUuc3RhcnRlZCkgcmV0dXJuOyBzdGF0ZS5zdGFydGVkPXRydWU7IGdzYXAudG8oZG9tLmludHJvLHtvcGFjaXR5OjAsZHVyYXRpb246LjM1LG9uQ29tcGxldGU6KCk9Pntkb20uaW50cm8uc3R5bGUuZGlzcGxheT0nbm9uZSc7IHNob3dNYWluKHRydWUpOyBzaG93U2Vuc29ycyhmYWxzZSk7IHNldFN0YXR1cygnT3ZlcnZpZXcgbW9kZS4gQ2xpY2sgYSBzdGFnZSBsYWJlbCB0byBiZWdpbi4nKTt9fSk7IH0KICAgIGRvbS5zdGFydEJ0bi5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIHN0YXJ0RXhwZXJpZW5jZSk7IGRvbS5yZXNldEJ0bi5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIHJlc2V0Vmlldyk7IFtbJ2xibC1waGFzZTEnLCdwaGFzZTFfY25jJ10sWydsYmwtcGhhc2UyJywncGhhc2UyX2VkZ2UnXSxbJ2xibC1waGFzZTMnLCdwaGFzZTNfYWN0J10sWydsYmwtc2lnaHQnLCdzZW5zb3Jfc2lnaHQnXSxbJ2xibC10b3VjaCcsJ3NlbnNvcl90b3VjaCddLFsnbGJsLWhlYXJpbmcnLCdzZW5zb3JfaGVhcmluZyddLFsnbGJsLXNtZWxsJywnc2Vuc29yX3NtZWxsJ11dLmZvckVhY2goKFtsYWJlbElkLHRhcmdldElkXSk9PnsgY29uc3QgZWw9ZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQobGFiZWxJZCk7IGVsLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywoKT0+dHJpZ2dlclNlbGVjdGlvbih0YXJnZXRJZCkpOyBlbC5hZGRFdmVudExpc3RlbmVyKCdrZXlkb3duJywoZSk9PnsgaWYoZS5rZXk9PT0nRW50ZXInfHxlLmtleT09PScgJyl7ZS5wcmV2ZW50RGVmYXVsdCgpOyB0cmlnZ2VyU2VsZWN0aW9uKHRhcmdldElkKTt9IH0pOyB9KTsKICAgIHJlbmRlcmVyLmRvbUVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigncG9pbnRlcmRvd24nLGU9PntpZihlLmJ1dHRvbiE9PTApIHJldHVybjsgc3RhdGUuZHJhZ2dpbmc9dHJ1ZTsgc3RhdGUuc2NlbmVNb3ZlZD1mYWxzZTsgcmVuZGVyZXIuZG9tRWxlbWVudC5kYXRhc2V0Lmxhc3RYPVN0cmluZyhlLmNsaWVudFgpOyByZW5kZXJlci5kb21FbGVtZW50LmRhdGFzZXQubGFzdFk9U3RyaW5nKGUuY2xpZW50WSk7IHRyeXtyZW5kZXJlci5kb21FbGVtZW50LnNldFBvaW50ZXJDYXB0dXJlKGUucG9pbnRlcklkKTt9Y2F0Y2goXyl7fX0pOwogICAgcmVuZGVyZXIuZG9tRWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCdwb2ludGVybW92ZScsZT0+e2lmKCFzdGF0ZS5kcmFnZ2luZykgcmV0dXJuOyBjb25zdCBseD1OdW1iZXIocmVuZGVyZXIuZG9tRWxlbWVudC5kYXRhc2V0Lmxhc3RYfHxlLmNsaWVudFgpLCBseT1OdW1iZXIocmVuZGVyZXIuZG9tRWxlbWVudC5kYXRhc2V0Lmxhc3RZfHxlLmNsaWVudFkpOyBjb25zdCBkeD1lLmNsaWVudFgtbHgsIGR5PWUuY2xpZW50WS1seTsgaWYoTWF0aC5hYnMoZHgpPjF8fE1hdGguYWJzKGR5KT4xKSBzdGF0ZS5zY2VuZU1vdmVkPXRydWU7IHJlbmRlcmVyLmRvbUVsZW1lbnQuZGF0YXNldC5sYXN0WD1TdHJpbmcoZS5jbGllbnRYKTsgcmVuZGVyZXIuZG9tRWxlbWVudC5kYXRhc2V0Lmxhc3RZPVN0cmluZyhlLmNsaWVudFkpOyBjb25zdCBzPWdldFNwaGVyaWNhbCgpOyBzZXRGcm9tU3BoZXJpY2FsKHMucmFkaXVzLCBzLnBvbGFyIC0gZHkqMC4wMDgsIHMuYXppbXV0aCAtIGR4KjAuMDA4KTt9KTsKICAgIHJlbmRlcmVyLmRvbUVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigncG9pbnRlcnVwJyxlPT57c3RhdGUuZHJhZ2dpbmc9ZmFsc2U7IHRyeXtyZW5kZXJlci5kb21FbGVtZW50LnJlbGVhc2VQb2ludGVyQ2FwdHVyZShlLnBvaW50ZXJJZCk7fWNhdGNoKF8pe319KTsKICAgIHJlbmRlcmVyLmRvbUVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignd2hlZWwnLGU9PntpZighc3RhdGUuc3RhcnRlZCkgcmV0dXJuOyBlLnByZXZlbnREZWZhdWx0KCk7IGNvbnN0IHM9Z2V0U3BoZXJpY2FsKCk7IHNldEZyb21TcGhlcmljYWwocy5yYWRpdXMgKyBNYXRoLnNpZ24oZS5kZWx0YVkpKjEuNSwgcy5wb2xhciwgcy5hemltdXRoKTt9LHtwYXNzaXZlOmZhbHNlfSk7CiAgICByZW5kZXJlci5kb21FbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2F1eGNsaWNrJyxlPT57aWYoZS5idXR0b249PT0xKXtlLnByZXZlbnREZWZhdWx0KCk7IHJlc2V0VmlldygpO319KTsgcmVuZGVyZXIuZG9tRWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZWRvd24nLGU9PntpZihlLmJ1dHRvbj09PTEpIGUucHJldmVudERlZmF1bHQoKTt9KTsgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ2tleWRvd24nLGU9PnsgaWYoZS5jdHJsS2V5ICYmIGUua2V5PT09JzAnKXtlLnByZXZlbnREZWZhdWx0KCk7IHJlc2V0VmlldygpO30gfSk7CiAgICBjb25zdCByYXljYXN0ZXI9bmV3IFRIUkVFLlJheWNhc3RlcigpLCBtb3VzZT1uZXcgVEhSRUUuVmVjdG9yMigpOyBmdW5jdGlvbiBzZXRQb2ludGVyKGUpe2NvbnN0IHI9cmVuZGVyZXIuZG9tRWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTsgbW91c2UueD0oKGUuY2xpZW50WC1yLmxlZnQpL3Iud2lkdGgpKjItMTsgbW91c2UueT0tKChlLmNsaWVudFktci50b3ApL3IuaGVpZ2h0KSoyKzE7fSBmdW5jdGlvbiBhY3RpdmVUYXJnZXRzKCl7cmV0dXJuIGludGVyYWN0YWJsZXMuZmlsdGVyKG9iaiA9PiAoc3RhdGUudmlldz09PSdPVkVSVklFVycgJiYgb2JqLnVzZXJEYXRhLnR5cGU9PT0nbWFjcm8nKSB8fCAoc3RhdGUudmlldyE9PSdPVkVSVklFVycgJiYgb2JqLnVzZXJEYXRhLnR5cGU9PT0nbWljcm8nKSk7fSBmdW5jdGlvbiBjbGVhckhvdmVyKCl7IGlmKHN0YXRlLmxhc3RIb3ZlcmVkKXsgZ3NhcC50byhzdGF0ZS5sYXN0SG92ZXJlZC5zY2FsZSx7eDoxLHk6MSx6OjEsZHVyYXRpb246LjIsb3ZlcndyaXRlOnRydWV9KTsgc3RhdGUubGFzdEhvdmVyZWQ9bnVsbDsgfSBJSU9UX1JPT1Quc3R5bGUuY3Vyc29yPSdkZWZhdWx0JzsgZG9tLmNyb3NzLmNsYXNzTGlzdC5yZW1vdmUoJ3Zpc2libGUnKTsgfQogICAgcmVuZGVyZXIuZG9tRWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLGU9PnsgaWYoIXN0YXRlLnN0YXJ0ZWQgfHwgZG9tLmludHJvLnN0eWxlLmRpc3BsYXkhPT0nbm9uZScpIHJldHVybjsgc2V0UG9pbnRlcihlKTsgcmF5Y2FzdGVyLnNldEZyb21DYW1lcmEobW91c2UsY2FtZXJhKTsgY29uc3QgaW50cz1yYXljYXN0ZXIuaW50ZXJzZWN0T2JqZWN0cyhhY3RpdmVUYXJnZXRzKCksdHJ1ZSk7IGNvbnN0IGhpdD1pbnRzLmZpbmQoaT0+aS5vYmplY3QudXNlckRhdGEmJmkub2JqZWN0LnVzZXJEYXRhLmlkKXx8aW50c1swXTsgaWYoaGl0KXsgY29uc3QgaG92ZXJlZD1oaXQub2JqZWN0LnVzZXJEYXRhJiZoaXQub2JqZWN0LnVzZXJEYXRhLmlkP2hpdC5vYmplY3Q6aGl0Lm9iamVjdC5wYXJlbnQ7IGlmKGhvdmVyZWQmJmhvdmVyZWQhPT1zdGF0ZS5sYXN0SG92ZXJlZCl7IGlmKHN0YXRlLmxhc3RIb3ZlcmVkKSBnc2FwLnRvKHN0YXRlLmxhc3RIb3ZlcmVkLnNjYWxlLHt4OjEseToxLHo6MSxkdXJhdGlvbjouMixvdmVyd3JpdGU6dHJ1ZX0pOyBzdGF0ZS5sYXN0SG92ZXJlZD1ob3ZlcmVkOyBnc2FwLnRvKGhvdmVyZWQuc2NhbGUse3g6MS4wNSx5OjEuMDUsejoxLjA1LGR1cmF0aW9uOi4yLG92ZXJ3cml0ZTp0cnVlfSk7IH0gSUlPVF9ST09ULnN0eWxlLmN1cnNvcj0ncG9pbnRlcic7IGRvbS5jcm9zcy5jbGFzc0xpc3QuYWRkKCd2aXNpYmxlJyk7IH0gZWxzZSBjbGVhckhvdmVyKCk7fSk7CiAgICByZW5kZXJlci5kb21FbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJyxlPT57IGlmKCFzdGF0ZS5zdGFydGVkIHx8IGRvbS5pbnRyby5zdHlsZS5kaXNwbGF5IT09J25vbmUnKSByZXR1cm47IGlmKHN0YXRlLnNjZW5lTW92ZWQpe3N0YXRlLnNjZW5lTW92ZWQ9ZmFsc2U7IHJldHVybjt9IGlmKGUudGFyZ2V0LmNsb3Nlc3QoJy5sYWJlbCcpfHxlLnRhcmdldC5jbG9zZXN0KCcjcGFuZWwnKXx8ZS50YXJnZXQuY2xvc2VzdCgnI3N0b3J5JykpIHJldHVybjsgc2V0UG9pbnRlcihlKTsgcmF5Y2FzdGVyLnNldEZyb21DYW1lcmEobW91c2UsY2FtZXJhKTsgY29uc3QgaW50cz1yYXljYXN0ZXIuaW50ZXJzZWN0T2JqZWN0cyhhY3RpdmVUYXJnZXRzKCksdHJ1ZSk7IGNvbnN0IGhpdD1pbnRzLmZpbmQoaT0+aS5vYmplY3QudXNlckRhdGEmJmkub2JqZWN0LnVzZXJEYXRhLmlkKXx8aW50c1swXTsgaWYoaGl0KXsgY29uc3QgdGFyZ2V0PWhpdC5vYmplY3QudXNlckRhdGEmJmhpdC5vYmplY3QudXNlckRhdGEuaWQ\/aGl0Lm9iamVjdDpoaXQub2JqZWN0LnBhcmVudDsgaWYodGFyZ2V0JiZ0YXJnZXQudXNlckRhdGEmJnRhcmdldC51c2VyRGF0YS5pZCkgaGFuZGxlU2VsZWN0aW9uKHRhcmdldC51c2VyRGF0YSk7IH0gfSk7CiAgICBmdW5jdGlvbiB1cGRhdGVTdG9yeSgpewogICAgICBjb25zdCBzdGVwPXN0b3J5U3RlcHNbc3RhdGUuc3RvcnlJbmRleF07CiAgICAgIGRvbS5zVGl0bGUudGV4dENvbnRlbnQ9c3RlcC50aXRsZTsKICAgICAgZG9tLnNDb3B5LnRleHRDb250ZW50PXN0ZXAuY29weTsKICAgICAgZG9tLnNQcm9nLnRleHRDb250ZW50PVN0cmluZyhzdGF0ZS5zdG9yeUluZGV4KzEpLnBhZFN0YXJ0KDIsJzAnKSsnIC8gJytTdHJpbmcoc3RvcnlTdGVwcy5sZW5ndGgpLnBhZFN0YXJ0KDIsJzAnKTsKICAgICAgZG9tLnNCYXIuc3R5bGUud2lkdGg9KChzdGF0ZS5zdG9yeUluZGV4KzEpL3N0b3J5U3RlcHMubGVuZ3RoKjEwMCkrJyUnOwogICAgfQogICAgZnVuY3Rpb24gcnVuU3RvcnlTdGVwKGlkeCl7CiAgICAgIHN0YXRlLnN0b3J5SW5kZXg9KChpZHglc3RvcnlTdGVwcy5sZW5ndGgpK3N0b3J5U3RlcHMubGVuZ3RoKSVzdG9yeVN0ZXBzLmxlbmd0aDsKICAgICAgY29uc3Qgc3RlcD1zdG9yeVN0ZXBzW3N0YXRlLnN0b3J5SW5kZXhdOwogICAgICBpZihzdGVwLmlkPT09J2lpb3RfbG9vcCcpewogICAgICAgIHJlc2V0VmlldygpOwogICAgICAgIHNldFRpbWVvdXQoKCk9PnRyaWdnZXJTZWxlY3Rpb24oc3RlcC5pZCksMjIwKTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0cmlnZ2VyU2VsZWN0aW9uKHN0ZXAuaWQpOwogICAgICB9CiAgICAgIHVwZGF0ZVN0b3J5KCk7CiAgICB9CiAgICBmdW5jdGlvbiBuZXh0U3RvcnlTdGVwKCl7CiAgICAgIGlmKCFzdGF0ZS5zdGFydGVkKXsgc3RhcnRFeHBlcmllbmNlKCk7IH0KICAgICAgcnVuU3RvcnlTdGVwKHN0YXRlLnN0b3J5SW5kZXgrMSk7CiAgICB9CiAgICBkb20uc05leHQuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLG5leHRTdG9yeVN0ZXApOwogICAgdXBkYXRlU3RvcnkoKTsKICAgIGNvbnN0IGNoYXJ0Q3R4PWRvbS5saXZlQ2hhcnQuZ2V0Q29udGV4dCgnMmQnKSwgY2FtQ3R4PWRvbS5jYW1lcmFWaWV3LmdldENvbnRleHQoJzJkJyk7IGZ1bmN0aW9uIHN5bmNDYW52YXNlcygpeyBbW2RvbS5saXZlQ2hhcnQsY2hhcnRDdHhdLFtkb20uY2FtZXJhVmlldyxjYW1DdHhdXS5mb3JFYWNoKChbY2FudmFzLGN0eF0pPT57IGNvbnN0IHA9Y2FudmFzLnBhcmVudEVsZW1lbnQ7IGNvbnN0IGRwcj1NYXRoLm1pbih3aW5kb3cuZGV2aWNlUGl4ZWxSYXRpb3x8MSwyKTsgY2FudmFzLndpZHRoPU1hdGgubWF4KDEsTWF0aC5mbG9vcihwLmNsaWVudFdpZHRoKmRwcikpOyBjYW52YXMuaGVpZ2h0PU1hdGgubWF4KDEsTWF0aC5mbG9vcihwLmNsaWVudEhlaWdodCpkcHIpKTsgY3R4LnNldFRyYW5zZm9ybSgxLDAsMCwxLDAsMCk7IGN0eC5zY2FsZShkcHIsZHByKTsgfSk7IH0gc3luY0NhbnZhc2VzKCk7IGZ1bmN0aW9uIGNTaXplKGNhbnZhcyl7IHJldHVybiB7d2lkdGg6Y2FudmFzLmNsaWVudFdpZHRoLGhlaWdodDpjYW52YXMuY2xpZW50SGVpZ2h0fTsgfQogICAgZnVuY3Rpb24gZHJhd092ZXJ2aWV3KHcsaCl7IGNoYXJ0Q3R4LmZpbGxTdHlsZT0ncmdiYSgyNTUsMjU1LDI1NSwuMDgpJzsgY2hhcnRDdHguZmlsbFJlY3QoMjAsMjAsdy00MCxoLTQwKTsgY2hhcnRDdHguZmlsbFN0eWxlPScjRkZGRkZGJzsgY2hhcnRDdHguZm9udD0nYm9sZCAxMnB4IEludGVyLCBBcmlhbCc7IGNoYXJ0Q3R4LmZpbGxUZXh0KCdMSVZFIFNFTlNFIElOUFVUUycsMjAsMTYpOyBbWydTSUdIVCcsLjgyXSxbJ1RPVUNIJywuNjhdLFsnSEVBUklORycsLjczXSxbJ1NNRUxMJywuNjFdXS5mb3JFYWNoKChyLGkpPT57IGNvbnN0IHk9MzgraSoyODsgY2hhcnRDdHguZmlsbFN0eWxlPScjRkZGRkZGJzsgY2hhcnRDdHguZmlsbFRleHQoclswXSwyMCx5KTsgY2hhcnRDdHguZmlsbFN0eWxlPSdyZ2JhKDI1NSwyNTUsMjU1LC4wOCknOyBjaGFydEN0eC5maWxsUmVjdCg5Mix5LTEwLHctMTMwLDEyKTsgY2hhcnRDdHguZmlsbFN0eWxlPScjQkEwMzI4JzsgY2hhcnRDdHguZmlsbFJlY3QoOTIseS0xMCwody0xMzApKnJbMV0sMTIpOyB9KTsgY2hhcnRDdHguZmlsbFN0eWxlPSdyZ2JhKDI1NSwyNTUsMjU1LC43KSc7IGNoYXJ0Q3R4LmZvbnQ9JzExcHggSW50ZXIsIEFyaWFsJzsgY2hhcnRDdHguZmlsbFRleHQoJ1NlbGVjdCBhIHNlbnNvciB0byB2aWV3IGl0cyBsaXZlIHN0cmVhbSBhbmQgdGhyZXNob2xkLicsMjAsaC0xOCk7IH0KICAgIGZ1bmN0aW9uIGdldE1vZGVDb2xvdXIobW9kZSl7IHJldHVybiBtb2RlPT09J2ZhdWx0JyA\/ICcjREMwMDJCJyA6IG1vZGU9PT0nd2FybmluZycgPyAnI0Y1OUUwQicgOiAnIzMyQzg3QSc7IH0KICAgIGZ1bmN0aW9uIGRyYXdMaW1pdChoLCByYXRpbz0uMjQsIGxhYmVsPSdMaW1pdCcsIGNvbG91cj0nI0ZGRDE2NicpeyBjb25zdCB5PWgqcmF0aW87IGNoYXJ0Q3R4LnN0cm9rZVN0eWxlPWNvbG91cjsgY2hhcnRDdHguc2V0TGluZURhc2goWzYsNF0pOyBjaGFydEN0eC5iZWdpblBhdGgoKTsgY2hhcnRDdHgubW92ZVRvKDAseSk7IGNoYXJ0Q3R4LmxpbmVUbyhkb20ubGl2ZUNoYXJ0LmNsaWVudFdpZHRoLHkpOyBjaGFydEN0eC5zdHJva2UoKTsgY2hhcnRDdHguc2V0TGluZURhc2goW10pOyBjaGFydEN0eC5maWxsU3R5bGU9Y29sb3VyOyBjaGFydEN0eC5mb250PScxMXB4IEludGVyLCBBcmlhbCc7IGNoYXJ0Q3R4LmZpbGxUZXh0KGxhYmVsLDgseS02KTsgcmV0dXJuIHk7IH0KICAgIGZ1bmN0aW9uIGRyYXdDaGFydCgpeyBjb25zdCB7d2lkdGg6dyxoZWlnaHQ6aH09Y1NpemUoZG9tLmxpdmVDaGFydCk7IGNoYXJ0Q3R4LmNsZWFyUmVjdCgwLDAsdyxoKTsgY29uc3QgaXNTZW5zb3I9c3RhdGUuc2VsZWN0aW9uLnN0YXJ0c1dpdGgoJ3NlbnNvcl8nKTsgc3RhdGUuc2Vuc29yTW9kZT1pc1NlbnNvcj9nZXRBdXRvTW9kZShzdGF0ZS50aW1lKTonbm9ybWFsJzsgdXBkYXRlTW9kZVBpbGwoc3RhdGUuc2Vuc29yTW9kZSk7IGlmKHN0YXRlLmNoYXJ0VHlwZT09PSdwaGFzZTFfb3ZlcnZpZXcnKXsgZHJhd092ZXJ2aWV3KHcsaCk7IHN0YXRlLnRpbWUrPTAuMDI7IHJldHVybjsgfSBjaGFydEN0eC5saW5lV2lkdGg9MjsKICAgICAgaWYoc3RhdGUuY2hhcnRUeXBlPT09J3dhdmVmb3JtJyl7IGNvbnN0IGxpbWl0WT1kcmF3TGltaXQoaCwuMjQsJ1ZpYnJhdGlvbiBsaW1pdCcsJyNGRkI4NEQnKTsgbGV0IGNyb3NzZWQ9ZmFsc2U7IGNoYXJ0Q3R4LmJlZ2luUGF0aCgpOyBjb25zdCBhbXA9c3RhdGUuc2Vuc29yTW9kZT09PSdub3JtYWwnPzEyOnN0YXRlLnNlbnNvck1vZGU9PT0nd2FybmluZyc\/MjQ6MjI7IGNvbnN0IG9mZnNldD1zdGF0ZS5zZW5zb3JNb2RlPT09J2ZhdWx0JyA\/IC0zNC0oTWF0aC5hYnMoTWF0aC5zaW4oc3RhdGUudGltZSo1KSkqMTIpIDogKHN0YXRlLnNlbnNvck1vZGU9PT0nd2FybmluZyc\/LTg6MCk7IGZvcihsZXQgaT0wO2k8dztpKz0yKXsgY29uc3Qgc3Bpa2U9c3RhdGUuc2Vuc29yTW9kZT09PSdmYXVsdCcgPyAoTWF0aC5zaW4oaSouMTErc3RhdGUudGltZSoxMSk+MC44OCA\/IC0yOCA6IDApIDogMDsgY29uc3QgeXk9KGgvMikrb2Zmc2V0K01hdGguc2luKGkqLjA1K3N0YXRlLnRpbWUqOCkqYW1wK3NwaWtlKyhNYXRoLnJhbmRvbSgpLS41KSooc3RhdGUuc2Vuc29yTW9kZT09PSdmYXVsdCc\/ODo0KTsgaWYoeXk8bGltaXRZKSBjcm9zc2VkPXRydWU7IGlmKGk9PT0wKSBjaGFydEN0eC5tb3ZlVG8oaSx5eSk7IGVsc2UgY2hhcnRDdHgubGluZVRvKGkseXkpO30gY2hhcnRDdHguc3Ryb2tlU3R5bGU9Y3Jvc3NlZD8nI0RDMDAyQic6JyM0RkQxOEInOyBjaGFydEN0eC5zdHJva2UoKTsgfQogICAgICBlbHNlIGlmKHN0YXRlLmNoYXJ0VHlwZT09PSd0aGVybWFsX2xpbmUnKXsgY29uc3QgbGltaXRZPWRyYXdMaW1pdChoLC4zNiwnSGVhdCBsaW1pdCcsJyNGRkM4NTcnKTsgY29uc3QgYmFzZWxpbmU9KGgqLjY4KStNYXRoLnNpbihzdGF0ZS50aW1lKi43KSo4OyBjb25zdCBzaGlmdD1zdGF0ZS5zZW5zb3JNb2RlPT09J25vcm1hbCc\/MDpzdGF0ZS5zZW5zb3JNb2RlPT09J3dhcm5pbmcnPy0yNjotNTY7IGNvbnN0IHBvaW50PWJhc2VsaW5lK3NoaWZ0KyhNYXRoLnJhbmRvbSgpKjQpOyBzdGF0ZS5jaGFydERhdGEucHVzaChwb2ludCk7IGlmKHN0YXRlLmNoYXJ0RGF0YS5sZW5ndGg+dy80KSBzdGF0ZS5jaGFydERhdGEuc2hpZnQoKTsgbGV0IGNyb3NzZWQ9ZmFsc2U7IGNoYXJ0Q3R4LmJlZ2luUGF0aCgpOyBmb3IobGV0IGk9MDtpPHN0YXRlLmNoYXJ0RGF0YS5sZW5ndGg7aSsrKXsgY29uc3QgeXk9c3RhdGUuY2hhcnREYXRhW2ldOyBpZih5eTxsaW1pdFkpIGNyb3NzZWQ9dHJ1ZTsgY29uc3QgeD1pKjQ7IGlmKGk9PT0wKSBjaGFydEN0eC5tb3ZlVG8oeCx5eSk7IGVsc2UgY2hhcnRDdHgubGluZVRvKHgseXkpO30gY2hhcnRDdHguc3Ryb2tlU3R5bGU9Y3Jvc3NlZD8nI0RDMDAyQic6JyM0RkQxOEInOyBjaGFydEN0eC5zdHJva2UoKTsgY2hhcnRDdHgubGluZVRvKChzdGF0ZS5jaGFydERhdGEubGVuZ3RoLTEpKjQsaCk7IGNoYXJ0Q3R4LmxpbmVUbygwLGgpOyBjaGFydEN0eC5maWxsU3R5bGU9KGNyb3NzZWQ\/JyNEQzAwMkInOicjRjU5RTBCJykrJzIyJzsgY2hhcnRDdHguZmlsbCgpOyB9CiAgICAgIGVsc2UgaWYoc3RhdGUuY2hhcnRUeXBlPT09J2JhcnNfY2FtZXJhJyl7IGNvbnN0IHRocmVzaG9sZD0zNDsgZHJhd0xpbWl0KGgsMS0odGhyZXNob2xkLzEwMCksJ1Zpc2lvbiB0b2xlcmFuY2UnLCcjRkZCODREJyk7IGNvbnN0IGJhclc9MTQsIHNwYWNlPTUsIG1heEJhcnM9TWF0aC5mbG9vcih3LyhiYXJXK3NwYWNlKSk7IGlmKE1hdGguZmxvb3Ioc3RhdGUudGltZSoxMCklND09PTApeyBjb25zdCBnb29kPTc4K01hdGgucmFuZG9tKCkqMTgsIHdhcm49NDQrTWF0aC5yYW5kb20oKSoxNiwgZmF1bHQ9MTgrTWF0aC5yYW5kb20oKSoxNjsgc3RhdGUuY2hhcnREYXRhLnB1c2goc3RhdGUuc2Vuc29yTW9kZT09PSdub3JtYWwnP2dvb2Q6c3RhdGUuc2Vuc29yTW9kZT09PSd3YXJuaW5nJz93YXJuOmZhdWx0KTsgaWYoc3RhdGUuY2hhcnREYXRhLmxlbmd0aD5tYXhCYXJzKSBzdGF0ZS5jaGFydERhdGEuc2hpZnQoKTsgfSBmb3IobGV0IGk9MDtpPHN0YXRlLmNoYXJ0RGF0YS5sZW5ndGg7aSsrKXsgY29uc3QgdmFsPXN0YXRlLmNoYXJ0RGF0YVtpXSwgaGg9KHZhbC8xMDApKmg7IGNvbnN0IGJhZD12YWw8dGhyZXNob2xkOyBjaGFydEN0eC5maWxsU3R5bGU9YmFkPycjREMwMDJCJzonIzRGRDE4Qic7IGNoYXJ0Q3R4LmZpbGxSZWN0KGkqKGJhclcrc3BhY2UpLCBoLWhoLCBiYXJXLCBoaCk7fSBzdGF0ZS5zaWdodEJhZD1zdGF0ZS5zZW5zb3JNb2RlPT09J2ZhdWx0JzsgfQogICAgICBlbHNlIGlmKHN0YXRlLmNoYXJ0VHlwZT09PSdwYXJ0aWNsZXMnKXsgY2hhcnRDdHguZmlsbFN0eWxlPScjRkZEMTY2JzsgY2hhcnRDdHguZm9udD0nMTFweCBJbnRlciwgQXJpYWwnOyBjaGFydEN0eC5maWxsVGV4dCgnVHJpZ2dlciBzaXplJyw4LDE4KTsgY29uc3QgbGVnZW5kWT0zMDsgWzMsNSw4XS5mb3JFYWNoKChyLGkpPT57IGNoYXJ0Q3R4LmJlZ2luUGF0aCgpOyBjaGFydEN0eC5maWxsU3R5bGU9aT09PTI\/JyNGRkQxNjYnOidyZ2JhKDI1NSwyMDksMTAyLC42NSknOyBjaGFydEN0eC5hcmMoMTYraSoyMCxsZWdlbmRZLHIsMCxNYXRoLlBJKjIpOyBjaGFydEN0eC5maWxsKCk7IH0pOyBjaGFydEN0eC5maWxsU3R5bGU9J3JnYmEoMjU1LDI1NSwyNTUsLjcyKSc7IGNoYXJ0Q3R4LmZvbnQ9JzEwcHggSW50ZXIsIEFyaWFsJzsgY2hhcnRDdHguZmlsbFRleHQoJ2xhcmdlIHBhcnRpY2xlcyA9IGZhdWx0Jyw3MCwzNCk7IGlmKE1hdGguZmxvb3Ioc3RhdGUudGltZSoxMCklMj09PTApeyBjb25zdCBzaXplPXN0YXRlLnNlbnNvck1vZGU9PT0nZmF1bHQnID8gKDcuMitNYXRoLnJhbmRvbSgpKjIuMCkgOiBzdGF0ZS5zZW5zb3JNb2RlPT09J3dhcm5pbmcnID8gKDQuNitNYXRoLnJhbmRvbSgpKjEuMikgOiAoMi4xK01hdGgucmFuZG9tKCkqMC45KTsgc3RhdGUuY2hhcnREYXRhLnB1c2goe3g6dyx5Ok1hdGgucmFuZG9tKCkqaCxzaXplOnNpemV9KTsgfSBjb25zdCBwYXJ0aWNsZUNvbG9yPXN0YXRlLnNlbnNvck1vZGU9PT0nZmF1bHQnPycjREMwMDJCJzpzdGF0ZS5zZW5zb3JNb2RlPT09J3dhcm5pbmcnPycjRjU5RTBCJzonIzRGRDE4Qic7IGNoYXJ0Q3R4LmZpbGxTdHlsZT1wYXJ0aWNsZUNvbG9yOyBmb3IobGV0IGk9c3RhdGUuY2hhcnREYXRhLmxlbmd0aC0xO2k+PTA7aS0tKXsgY29uc3QgcD1zdGF0ZS5jaGFydERhdGFbaV07IHAueC09c3RhdGUuc2Vuc29yTW9kZT09PSdmYXVsdCc\/NC4zOnN0YXRlLnNlbnNvck1vZGU9PT0nd2FybmluZyc\/Mi45OjEuODsgY2hhcnRDdHguYmVnaW5QYXRoKCk7IGNoYXJ0Q3R4LmFyYyhwLngscC55LHAuc2l6ZSwwLE1hdGguUEkqMik7IGNoYXJ0Q3R4LmZpbGwoKTsgaWYocC54PDApIHN0YXRlLmNoYXJ0RGF0YS5zcGxpY2UoaSwxKTt9IH0KICAgICAgZWxzZSBpZihzdGF0ZS5jaGFydFR5cGU9PT0nYWlfcHJvY2VzcycpeyBjb25zdCBwYWQ9MTQ7IGNvbnN0IGxlZnQ9cGFkLCBtaWQ9dyouNDYsIHJpZ2h0PXctMTE4OyBjb25zdCB0b3A9Mjg7IGNvbnN0IGZsb3c9KHN0YXRlLnRpbWUqLjc1KSUxOyBjaGFydEN0eC5maWxsU3R5bGU9J3JnYmEoMjU1LDI1NSwyNTUsLjA2KSc7IGNoYXJ0Q3R4LmZpbGxSZWN0KGxlZnQsdG9wLDkyLGgtNTYpOyBjaGFydEN0eC5maWxsUmVjdChtaWQtNDIsdG9wLDg0LGgtNTYpOyBjaGFydEN0eC5maWxsUmVjdChyaWdodCx0b3AsOTYsaC01Nik7IGNoYXJ0Q3R4LmZpbGxTdHlsZT0nI0ZGRkZGRic7IGNoYXJ0Q3R4LmZvbnQ9J2JvbGQgMTBweCBJbnRlciwgQXJpYWwnOyBjaGFydEN0eC5maWxsVGV4dCgnUkFXIElOUFVUJyxsZWZ0KzgsdG9wLTgpOyBjaGFydEN0eC5maWxsVGV4dCgnUFJPQ0VTUycsbWlkLTI0LHRvcC04KTsgY2hhcnRDdHguZmlsbFRleHQoJ1BSSU9SSVRJU0VEJyxyaWdodCs4LHRvcC04KTsgY2hhcnRDdHguc3Ryb2tlU3R5bGU9J3JnYmEoMjU1LDI1NSwyNTUsLjI4KSc7IGNoYXJ0Q3R4LmxpbmVXaWR0aD0xOyBjaGFydEN0eC5zZXRMaW5lRGFzaChbNCw0XSk7IGNoYXJ0Q3R4LmJlZ2luUGF0aCgpOyBjaGFydEN0eC5tb3ZlVG8obGVmdCs5MixoLzIpOyBjaGFydEN0eC5saW5lVG8obWlkLTQ0LGgvMik7IGNoYXJ0Q3R4Lm1vdmVUbyhtaWQrNDQsaC8yKTsgY2hhcnRDdHgubGluZVRvKHJpZ2h0LGgvMik7IGNoYXJ0Q3R4LnN0cm9rZSgpOyBjaGFydEN0eC5zZXRMaW5lRGFzaChbXSk7IGZvcihsZXQgaT0wO2k8MTg7aSsrKXsgY29uc3QgcD0oZmxvdytpLzE4KSUxOyBjb25zdCBub2lzeVk9dG9wKzE4KygoaSoxNytNYXRoLnNpbihzdGF0ZS50aW1lKjUraSkqMTgpJShoLTc2KSk7IGNvbnN0IHg9bGVmdCsxMCtwKihtaWQtbGVmdC01OCk7IGNvbnN0IHk9bm9pc3lZK01hdGguc2luKHN0YXRlLnRpbWUqOCtpKSo2OyBjaGFydEN0eC5nbG9iYWxBbHBoYT0uMzgrLjQyKk1hdGguc2luKHAqTWF0aC5QSSk7IGNoYXJ0Q3R4LmZpbGxTdHlsZT1pJTM9PT0wPycjREMwMDJCJzppJTM9PT0xPycjRkZGRkZGJzonIzg3ODc4Nyc7IGNoYXJ0Q3R4LmZpbGxSZWN0KHgseSw0KyhpJTMpKjIsNCsoaSUyKSoyKTsgfSBjaGFydEN0eC5nbG9iYWxBbHBoYT0xOyBjb25zdCBjeD1taWQsIGN5PWgvMjsgZm9yKGxldCByPTA7cjwzO3IrKyl7IGNoYXJ0Q3R4LnN0cm9rZVN0eWxlPXI9PT0xPycjREMwMDJCJzoncmdiYSgyNTUsMjU1LDI1NSwuMzgpJzsgY2hhcnRDdHgubGluZVdpZHRoPXI9PT0xPzI6MTsgY2hhcnRDdHguYmVnaW5QYXRoKCk7IGNoYXJ0Q3R4LmFyYyhjeCxjeSwxOCtyKjEyLHN0YXRlLnRpbWUqKC44K3IqLjI1KSxzdGF0ZS50aW1lKiguOCtyKi4yNSkrTWF0aC5QSSoxLjM1KTsgY2hhcnRDdHguc3Ryb2tlKCk7IH0gY2hhcnRDdHguZmlsbFN0eWxlPSdyZ2JhKDIyMCwwLDQzLC4yMiknOyBjaGFydEN0eC5maWxsUmVjdChtaWQtMzAsY3ktOSw2MCwxOCk7IGNoYXJ0Q3R4LmZpbGxTdHlsZT0nI0ZGRkZGRic7IGNoYXJ0Q3R4LmZvbnQ9J2JvbGQgOXB4IEludGVyLCBBcmlhbCc7IGNoYXJ0Q3R4LmZpbGxUZXh0KCdGSUxURVInLG1pZC0xNyxjeSszKTsgZm9yKGxldCBpPTA7aTw3O2krKyl7IGNvbnN0IHA9KGZsb3craS83KSUxOyBjb25zdCBsYW5lPShpJTMpLTE7IGNvbnN0IHg9bWlkKzQ4K3AqKHJpZ2h0LW1pZC01OCk7IGNvbnN0IHk9Y3krbGFuZSoxODsgY2hhcnRDdHguZ2xvYmFsQWxwaGE9LjU1Ky4zNSpwOyBjaGFydEN0eC5maWxsU3R5bGU9aSUzPT09MD8nIzMyQzg3QSc6aSUzPT09MT8nI0RDMDAyQic6JyNGRkZGRkYnOyBjaGFydEN0eC5maWxsUmVjdCh4LHktNSwxMSwxMCk7IGNoYXJ0Q3R4LnN0cm9rZVN0eWxlPSdyZ2JhKDI1NSwyNTUsMjU1LC41KSc7IGNoYXJ0Q3R4LnN0cm9rZVJlY3QoeCsuNSx5LTQuNSwxMCw5KTsgfSBjaGFydEN0eC5nbG9iYWxBbHBoYT0xOyBmb3IobGV0IGk9MDtpPDQ7aSsrKXsgY29uc3QgeXk9dG9wKzI0K2kqMjQ7IGNoYXJ0Q3R4LmZpbGxTdHlsZT1pPT09MD8nI0RDMDAyQic6aT09PTE\/JyMzMkM4N0EnOicjRkZGRkZGJzsgY2hhcnRDdHguZ2xvYmFsQWxwaGE9LjM0K2kqLjE0OyBjaGFydEN0eC5maWxsUmVjdChyaWdodCsxMix5eSw2NC1pKjgsOSk7IH0gY2hhcnRDdHguZ2xvYmFsQWxwaGE9MTsgY2hhcnRDdHguZmlsbFN0eWxlPSdyZ2JhKDI1NSwyNTUsMjU1LC43MiknOyBjaGFydEN0eC5mb250PSc5cHggSW50ZXIsIEFyaWFsJzsgY2hhcnRDdHguZmlsbFRleHQoJ25vaXNlIHJlZHVjZWQnLG1pZC0zNSxoLTE4KTsgY2hhcnRDdHguZmlsbFRleHQoJ3JhbmtlZCBzaWduYWxzJyxyaWdodCsxMixoLTE4KTsgfSAgCiAgICAgIGVsc2UgaWYoc3RhdGUuY2hhcnRUeXBlPT09J2luc2lnaHRfZGFzaGJvYXJkJyl7IGNoYXJ0Q3R4LmZpbGxTdHlsZT0nIzNDM0QzRCc7IGNoYXJ0Q3R4LmZpbGxSZWN0KDEyLDEyLHctMjQsaC0yNCk7IGNoYXJ0Q3R4LmZpbGxTdHlsZT0nI0ZGRkZGRic7IGNoYXJ0Q3R4LmZvbnQ9J2JvbGQgMTJweCBJbnRlciwgQXJpYWwnOyBjaGFydEN0eC5maWxsVGV4dCgnU0hPUCBGTE9PUiBJTlNJR0hUUycsMjAsMzApOyBjaGFydEN0eC5mb250PScxMnB4IEludGVyLCBBcmlhbCc7IGNvbnN0IHJvd3M9W1snTWFpbnRlbmFuY2UgcHJpb3JpdHknLCdIaWdoJ10sWydBY3Rpb24gcXVldWUnLCdTeW5jZWQnXSxbJ0Rvd250aW1lIHJpc2snLCdMb3cnXV07IHJvd3MuZm9yRWFjaCgocixpKT0+eyBjb25zdCB5eT01OCtpKjI2OyBjaGFydEN0eC5maWxsU3R5bGU9J3JnYmEoMjU1LDI1NSwyNTUsLjcpJzsgY2hhcnRDdHguZmlsbFRleHQoclswXSwyMCx5eSk7IGNoYXJ0Q3R4LmZpbGxTdHlsZT0nI0ZGRkZGRic7IGNoYXJ0Q3R4LmZpbGxUZXh0KHJbMV0sdy0yMC1jaGFydEN0eC5tZWFzdXJlVGV4dChyWzFdKS53aWR0aCx5eSk7IH0pOyB9CiAgICAgIGVsc2UgaWYoc3RhdGUuY2hhcnRUeXBlPT09J25ldHdvcmtfZmxvdycpeyAgCiAgICAgICAgY29uc3QgeT1oLzItMTg7IGNvbnN0IHNlbnNlWD0yMCwgcHJvY2Vzc1g9dy8yLTI3LCBhY3RYPXctNzQ7IGNvbnN0IGJveGVzPVt7eDpzZW5zZVgsbGFiZWw6J1NFTlNFJ30se3g6cHJvY2Vzc1gsbGFiZWw6J1BST0NFU1MnfSx7eDphY3RYLGxhYmVsOidBQ1QnfV07IGNvbnN0IGRhcmtSZWQ9JyM3NTBBMjInOyBjb25zdCBkYXJrUmVkMj0nIzQ1MTAxQSc7IGNvbnN0IHJlZE1pZD0nI0JBMDMyOCc7IGNvbnN0IHJlZEJyaWdodD0nI0RDMDAyQic7IGNvbnN0IGJsb2NrU2l6ZT01OyBjb25zdCBibG9ja1NldD1be3Jhbms6MywgY29sb3VyOnJlZEJyaWdodH0se3Jhbms6MSwgY29sb3VyOicjRkZGRkZGJ30se3Jhbms6NCwgY29sb3VyOnJlZE1pZH0se3Jhbms6MiwgY29sb3VyOicjRkZGRkZGJ30se3Jhbms6NSwgY29sb3VyOnJlZEJyaWdodH1dOyBjaGFydEN0eC5zYXZlKCk7IGJveGVzLmZvckVhY2goKGIsaWR4KT0+eyBjaGFydEN0eC5maWxsU3R5bGU9aWR4PT09MT9kYXJrUmVkMjpkYXJrUmVkOyBjaGFydEN0eC5maWxsUmVjdChiLngseSw1NCwzNik7IGNoYXJ0Q3R4LnN0cm9rZVN0eWxlPSdyZ2JhKDI1NSwyNTUsMjU1LC4yMiknOyBjaGFydEN0eC5saW5lV2lkdGg9MTsgY2hhcnRDdHguc3Ryb2tlUmVjdChiLngrLjUseSsuNSw1MywzNSk7fSk7IGNoYXJ0Q3R4LnN0cm9rZVN0eWxlPSdyZ2JhKDI1NSwyNTUsMjU1LC43OCknOyBjaGFydEN0eC5zZXRMaW5lRGFzaChbNiw0XSk7IGNoYXJ0Q3R4LmxpbmVEYXNoT2Zmc2V0PS1zdGF0ZS50aW1lKjEwOyBjaGFydEN0eC5iZWdpblBhdGgoKTsgY2hhcnRDdHgubW92ZVRvKHNlbnNlWCs0MixoLzIpOyBjaGFydEN0eC5saW5lVG8ocHJvY2Vzc1gtMTQsaC8yKTsgY2hhcnRDdHgubW92ZVRvKHByb2Nlc3NYKzY4LGgvMik7IGNoYXJ0Q3R4LmxpbmVUbyhhY3RYLTE0LGgvMik7IGNoYXJ0Q3R4LnN0cm9rZSgpOyBjaGFydEN0eC5zZXRMaW5lRGFzaChbXSk7IGNvbnN0IHRyYXZlbD0oc3RhdGUudGltZSouNDIpJTE7IGJsb2NrU2V0LmZvckVhY2goKGIsaSk9PnsgY29uc3Qgc3RhZ2dlcj0odHJhdmVsICsgaSouMTYpJTE7IGNvbnN0IHN0YXJ0WD1zZW5zZVgrMTAraSo3OyBjb25zdCBlbmRYPXByb2Nlc3NYKzcraSo4OyBjb25zdCBweD1zdGFydFgrKGVuZFgtc3RhcnRYKSpzdGFnZ2VyOyBjb25zdCB1bnNvcnRlZFk9KGgvMi0xNikrKChpKjEzK01hdGguc2luKHN0YXRlLnRpbWUqMitpKSo5KSUyOCk7IGNoYXJ0Q3R4Lmdsb2JhbEFscGhhPS4zNSsuNjUqc3RhZ2dlcjsgY2hhcnRDdHguZmlsbFN0eWxlPWIuY29sb3VyOyBjaGFydEN0eC5maWxsUmVjdChweCx1bnNvcnRlZFksYmxvY2tTaXplLGJsb2NrU2l6ZSk7fSk7IGNoYXJ0Q3R4Lmdsb2JhbEFscGhhPTE7IGNvbnN0IHNvcnRQdWxzZT0oTWF0aC5zaW4oc3RhdGUudGltZSoyLjgpKzEpLzI7IGJsb2NrU2V0LnNsaWNlKCkuc29ydCgoYSxiKT0+YS5yYW5rLWIucmFuaykuZm9yRWFjaCgoYixpKT0+eyBjb25zdCBsYW5lWD1wcm9jZXNzWCsxMCtpKjg7IGNvbnN0IHNodWZmbGVkWT15KzgrKCg0LWkpKjQpOyBjb25zdCBzb3J0ZWRZPXkrOStpKjQ7IGNvbnN0IHB5PXNodWZmbGVkWSsoc29ydGVkWS1zaHVmZmxlZFkpKnNvcnRQdWxzZTsgY2hhcnRDdHguZmlsbFN0eWxlPWIuY29sb3VyOyBjaGFydEN0eC5maWxsUmVjdChsYW5lWCxweSxibG9ja1NpemUrMSxibG9ja1NpemUrMSk7IGNoYXJ0Q3R4LmZpbGxTdHlsZT0ncmdiYSgyNTUsMjU1LDI1NSwuMjIpJzsgY2hhcnRDdHguZmlsbFJlY3QocHJvY2Vzc1grNyx5KzI4LWkqNCw0MCwxKTt9KTsgYmxvY2tTZXQuc2xpY2UoKS5zb3J0KChhLGIpPT5hLnJhbmstYi5yYW5rKS5mb3JFYWNoKChiLGkpPT57IGNvbnN0IG91dFBoYXNlPSh0cmF2ZWwraSouMTIpJTE7IGNvbnN0IHN0YXJ0WD1wcm9jZXNzWCs2MzsgY29uc3QgZW5kWD1hY3RYKzEwK2kqNzsgY29uc3QgcHg9c3RhcnRYKyhlbmRYLXN0YXJ0WCkqb3V0UGhhc2U7IGNvbnN0IHB5PWgvMi0xMitpKjU7IGNoYXJ0Q3R4Lmdsb2JhbEFscGhhPS4yOCsuNzIqb3V0UGhhc2U7IGNoYXJ0Q3R4LmZpbGxTdHlsZT1iLmNvbG91cjsgY2hhcnRDdHguZmlsbFJlY3QocHgscHksYmxvY2tTaXplLGJsb2NrU2l6ZSk7fSk7IGNoYXJ0Q3R4Lmdsb2JhbEFscGhhPTE7IGJsb2NrU2V0LnNsaWNlKCkuc29ydCgoYSxiKT0+YS5yYW5rLWIucmFuaykuZm9yRWFjaCgoYixpKT0+eyBjaGFydEN0eC5maWxsU3R5bGU9Yi5jb2xvdXI7IGNoYXJ0Q3R4LmZpbGxSZWN0KGFjdFgrMTAraSo3LHkrMjItaSozLGJsb2NrU2l6ZSxibG9ja1NpemUpO30pOyBjaGFydEN0eC5maWxsU3R5bGU9JyNGRkZGRkYnOyBjaGFydEN0eC5mb250PScxMHB4IEludGVyLCBBcmlhbCc7IGNoYXJ0Q3R4LmZpbGxUZXh0KCdTRU5TT1JTJyxzZW5zZVgsaC8yKzM1KTsgY2hhcnRDdHguZmlsbFRleHQoJ1NPUlQgLyBTVFJVQ1RVUkUnLHByb2Nlc3NYLTEwLGgvMiszNSk7IGNoYXJ0Q3R4LmZpbGxUZXh0KCdSRVNQT05TRScsYWN0WC00LGgvMiszNSk7IGNoYXJ0Q3R4LnJlc3RvcmUoKTsgfSBzdGF0ZS50aW1lKz0wLjAzOyB9CiAgICBmdW5jdGlvbiBkcmF3Q2FtKCl7IGNvbnN0IHt3aWR0aDp3LGhlaWdodDpofT1jU2l6ZShkb20uY2FtZXJhVmlldyk7IGNhbUN0eC5jbGVhclJlY3QoMCwwLHcsaCk7IGlmKGRvbS5jYW1lcmFDYXJkLnN0eWxlLmRpc3BsYXk9PT0nbm9uZScpIHJldHVybjsgY2FtQ3R4LmZpbGxTdHlsZT0nIzEwMjAyZSc7IGNhbUN0eC5maWxsUmVjdCgwLDAsdyxoKTsgY2FtQ3R4LmZpbGxTdHlsZT0ncmdiYSgyNTUsMjU1LDI1NSwuMDUpJzsgZm9yKGxldCBpPTA7aTw2O2krKykgY2FtQ3R4LmZpbGxSZWN0KDEyK2kqMjQsMCwxLGgpOyBmb3IobGV0IGo9MDtqPDQ7aisrKSBjYW1DdHguZmlsbFJlY3QoMCwxNCtqKjI0LHcsMSk7IGNvbnN0IGRldGFpbGVkPXN0YXRlLnNlbGVjdGlvbj09PSdzZW5zb3Jfc2lnaHQnLCBtb2RlPXN0YXRlLnNlbnNvck1vZGUsIG94PW1vZGU9PT0nZmF1bHQnPzE4OjAsIG95PW1vZGU9PT0nZmF1bHQnPzg6MDsgY2FtQ3R4LnN0cm9rZVN0eWxlPW1vZGU9PT0nZmF1bHQnPycjREMwMDJCJzptb2RlPT09J3dhcm5pbmcnPycjRkZEMTY2JzonIzdmZDlmZic7IGNhbUN0eC5saW5lV2lkdGg9MjsgY2FtQ3R4LnN0cm9rZVJlY3Qody8yLTQ4K294LGgvMi0yNitveSw5Niw1Mik7IGNhbUN0eC5zdHJva2VTdHlsZT0nI0ZGRkZGRic7IGNhbUN0eC5saW5lV2lkdGg9MTsgY2FtQ3R4LnN0cm9rZVJlY3Qody8yLTU4LGgvMi0zNiwxMTYsNzIpOyBpZihkZXRhaWxlZCl7IGNhbUN0eC5zdHJva2VTdHlsZT0ncmdiYSgxMjcsMjE3LDI1NSwuNTUpJzsgY2FtQ3R4LmJlZ2luUGF0aCgpOyBjYW1DdHgubW92ZVRvKHcvMiwxOCk7IGNhbUN0eC5saW5lVG8ody8yLGgtMTgpOyBjYW1DdHgubW92ZVRvKDE4LGgvMik7IGNhbUN0eC5saW5lVG8ody0xOCxoLzIpOyBjYW1DdHguc3Ryb2tlKCk7IGNhbUN0eC5maWxsU3R5bGU9J3JnYmEoMTI3LDIxNywyNTUsLjIpJzsgY2FtQ3R4LmZpbGxSZWN0KHcvMi01NixoLzIrMjYsMTEyLDEwKTsgY2FtQ3R4LmZpbGxTdHlsZT0nI0ZGRkZGRic7IGNhbUN0eC5mb250PScxMXB4IEludGVyLCBBcmlhbCc7IGNhbUN0eC5maWxsVGV4dCgnSW5zcGVjdGlvbiBjYW1lcmE6IGFsaWdubWVudCBjaGVjaycsMTQsMTgpOyBjYW1DdHguZmlsbFN0eWxlPW1vZGU9PT0nZmF1bHQnPycjREMwMDJCJzptb2RlPT09J3dhcm5pbmcnPycjRkZEMTY2JzonIzdmZDlmZic7IGNhbUN0eC5maWxsVGV4dChtb2RlPT09J2ZhdWx0Jz8nTGltaXQgcmVhY2hlZCc6J1RocmVzaG9sZCBpbiB2aWV3JywxNCxoLTEyKTsgfX0KICAgIGZ1bmN0aW9uIHVwZGF0ZVRyYWNraW5nKCl7IGNvbnN0IHRlbXBWPW5ldyBUSFJFRS5WZWN0b3IzKCk7IGNvbnN0IFc9SVcoKSwgSD1JSCgpLCBtYXJnaW49OCwgZ2FwPTg7IGxldCBleFRvcD1tYXJnaW47IHsgY29uc3QgX2g9SUlPVF9ST09ULnF1ZXJ5U2VsZWN0b3IoJy5oZWFkZXInKTsgaWYoX2gpeyBjb25zdCBfaHI9X2guZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCksIF9ycjA9SUlPVF9ST09ULmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpOyBjb25zdCBfaGI9X2hyLmJvdHRvbS1fcnIwLnRvcDsgaWYoX2hiPmV4VG9wICYmIF9oYjxIKjAuNzIpIGV4VG9wPV9oYitnYXA7IH0gfSBpZih0cnVlKXsgY29uc3Qgc3Jvdz1kb20ubGFiZWxzU2Vuc29yLmZpbHRlcihlbD0+ZWwgJiYgZWwuc3R5bGUuZGlzcGxheSE9PSdub25lJyk7IGlmKHNyb3cubGVuZ3RoKXsgY29uc3QgX3JyPUlJT1RfUk9PVC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTsgY29uc3QgYmg9c3Jvd1swXS5vZmZzZXRIZWlnaHR8fDM2OyBpZihkb20ucGFuZWwuY2xhc3NMaXN0LmNvbnRhaW5zKCdhY3RpdmUnKSl7IGNvbnN0IF9wcj1kb20ucGFuZWwuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7IGNvbnN0IF9wbD1fcHIubGVmdC1fcnIubGVmdDsgaWYoX3BsPj0xNDApeyBjb25zdCBsZWZ0UGFkPTIwOyBsZXQgYm90TGltPUgtbWFyZ2luOyBjb25zdCBfc3Q9ZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3N0b3J5Jyk7IGlmKF9zdCAmJiBnZXRDb21wdXRlZFN0eWxlKF9zdCkuZGlzcGxheSE9PSdub25lJyl7IGNvbnN0IF9zdHI9X3N0LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpOyBjb25zdCBfc3RUb3A9X3N0ci50b3AtX3JyLnRvcDsgaWYoX3N0VG9wPjAgJiYgX3N0VG9wPEgpIGJvdExpbT1fc3RUb3AtZ2FwOyB9IGxldCBzdGVwdj1iaCsxMjsgY29uc3QgYmFuZFRvcD1leFRvcCwgYmFuZEg9TWF0aC5tYXgoYmgsIGJvdExpbS1iYW5kVG9wKTsgaWYoc3RlcHYqKHNyb3cubGVuZ3RoLTEpK2JoPmJhbmRIKXsgc3RlcHY9TWF0aC5tYXgoYmgrMiwoYmFuZEgtYmgpLyhzcm93Lmxlbmd0aC0xKSk7IH0gY29uc3QgZ3JwPXN0ZXB2Kihzcm93Lmxlbmd0aC0xKStiaDsgbGV0IGN5MD1iYW5kVG9wK01hdGgubWF4KDAsKGJhbmRILWdycCkvMikrYmgvMjsgc3Jvdy5mb3JFYWNoKChlbCxpKT0+eyBjb25zdCB3PWVsLm9mZnNldFdpZHRofHwxMTA7IGVsLnN0eWxlLmxlZnQ9KGxlZnRQYWQgKyB3LzIpKydweCc7IGVsLnN0eWxlLnRvcD0oY3kwK3N0ZXB2KmkpKydweCc7IGVsLnN0eWxlLm9wYWNpdHk9MTsgfSk7IH0gZWxzZSB7IGNvbnN0IF9wcjI9ZG9tLnBhbmVsLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpOyBjb25zdCBfcHQ9X3ByMi50b3AtX3JyLnRvcDsgbGV0IHJvd1k9KGRvbS5wYW5lbC5jbGFzc0xpc3QuY29udGFpbnMoJ2FjdGl2ZScpICYmIF9wdD5leFRvcCk\/IChfcHQtYmgvMi0xMikgOiAoSC1tYXJnaW4tYmgvMik7IHJvd1k9TWF0aC5tYXgoZXhUb3AsIE1hdGgubWluKHJvd1ksIEgtbWFyZ2luLWJoLzIpKTsgY29uc3Qgc2xvdD0oVy0yKm1hcmdpbikvc3Jvdy5sZW5ndGg7IHNyb3cuZm9yRWFjaCgoZWwsaSk9PnsgZWwuc3R5bGUubGVmdD0obWFyZ2luK3Nsb3QqKGkrMC41KSkrJ3B4JzsgZWwuc3R5bGUudG9wPXJvd1krJ3B4JzsgZWwuc3R5bGUub3BhY2l0eT0xOyB9KTsgfSByZXR1cm47IH0gbGV0IHJvd1k9TWF0aC5tYXgoZXhUb3AsTWF0aC5taW4oSCowLjUsSC00MCkpOyBjb25zdCBzbG90PShXLTIqbWFyZ2luKS9zcm93Lmxlbmd0aDsgc3Jvdy5mb3JFYWNoKChlbCxpKT0+eyBlbC5zdHlsZS5sZWZ0PShtYXJnaW4rc2xvdCooaSswLjUpKSsncHgnOyBlbC5zdHlsZS50b3A9cm93WSsncHgnOyBlbC5zdHlsZS5vcGFjaXR5PTE7IH0pOyByZXR1cm47IH0gfSBsZXQgZXhSaWdodD1XLCBleEJvdHRvbT1IOyBpZihkb20ucGFuZWwuY2xhc3NMaXN0LmNvbnRhaW5zKCdhY3RpdmUnKSl7IGNvbnN0IF9wMD1kb20ucGFuZWwuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCksX3JyPUlJT1RfUk9PVC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKSxwcj17bGVmdDpfcDAubGVmdC1fcnIubGVmdCxyaWdodDpfcDAucmlnaHQtX3JyLmxlZnQsdG9wOl9wMC50b3AtX3JyLnRvcCxib3R0b206X3AwLmJvdHRvbS1fcnIudG9wfTsgaWYocHIucmlnaHQ+Vy00MCAmJiBwci5sZWZ0PlcqMC4zNSkgZXhSaWdodD1wci5sZWZ0LTEyOyBpZihwci5ib3R0b20+SC00MCAmJiBwci50b3A+SCowLjMwKSBleEJvdHRvbT1wci50b3AtMTI7IH0gY29uc3QgaXRlbXM9W107IHRyYWNraW5nUG9pbnRzLmZvckVhY2gocG9pbnQ9PnsgY29uc3QgZWw9ZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQocG9pbnQuaWQpOyBpZighZWwgfHwgZWwuc3R5bGUuZGlzcGxheT09PSdub25lJykgcmV0dXJuOyB0ZW1wVi5jb3B5KHBvaW50LnBvcyk7IHRlbXBWLnByb2plY3QoY2FtZXJhKTsgaWYodGVtcFYuej4xKXsgZWwuc3R5bGUub3BhY2l0eT0wOyByZXR1cm47IH0gY29uc3QgaHc9KGVsLm9mZnNldFdpZHRofHwxMjApLzIsIGhoPShlbC5vZmZzZXRIZWlnaHR8fDM0KS8yOyBsZXQgeD0odGVtcFYueCouNSsuNSkqVzsgaXRlbXMucHVzaCh7ZWwseCxodyxoaH0pOyB9KTsgaWYoaXRlbXMubGVuZ3RoKXsgbGV0IGhobWF4PTAsIGh3c3VtPTA7IGl0ZW1zLmZvckVhY2goaXQ9PnsgaWYoaXQuaGg+aGhtYXgpIGhobWF4PWl0LmhoOyBod3N1bSs9MippdC5odzsgfSk7IGNvbnN0IHRvdGFsVz1od3N1bStnYXAqKGl0ZW1zLmxlbmd0aC0xKTsgaXRlbXMuc29ydCgoYSxiKT0+eyB2YXIgbmE9cGFyc2VJbnQoKGEuZWwuaWQubWF0Y2goL1xkKy8pfHxbJzAnXSlbMF0sMTApLCBuYj1wYXJzZUludCgoYi5lbC5pZC5tYXRjaCgvXGQrLyl8fFsnMCddKVswXSwxMCk7IHJldHVybiBuYS1uYjsgfSk7IGlmKHRvdGFsVzw9Vy0yKm1hcmdpbil7IGNvbnN0IHJvd1k9ZXhUb3AraGhtYXgrODsgbGV0IGdFZmY9Z2FwOyBjb25zdCBzbGFjaz0oVy0yKm1hcmdpbiktdG90YWxXOyBpZihpdGVtcy5sZW5ndGg+MSl7IGdFZmY9TWF0aC5taW4oNjAsIGdhcCtzbGFjay8oaXRlbXMubGVuZ3RoLTEpKTsgfSBjb25zdCBncm91cFc9dG90YWxXK2dFZmYqKGl0ZW1zLmxlbmd0aC0xKTsgbGV0IGN4PU1hdGgubWF4KG1hcmdpbiwoVy1ncm91cFcpLzIpOyBpdGVtcy5mb3JFYWNoKGl0PT57IGl0LmVsLnN0eWxlLmxlZnQ9KGN4K2l0Lmh3KSsncHgnOyBpdC5lbC5zdHlsZS50b3A9cm93WSsncHgnOyBpdC5lbC5zdHlsZS5vcGFjaXR5PTE7IGN4Kz0yKml0Lmh3K2dFZmY7IH0pOyB9IGVsc2UgeyBjb25zdCBsZWZ0UGFkPTE2OyBjb25zdCBzdGVwdj0yKmhobWF4KzEwOyBsZXQgY3k9ZXhUb3AraGhtYXgrNjsgaXRlbXMuZm9yRWFjaCgoaXQsaSk9PnsgaXQuZWwuc3R5bGUubGVmdD0obGVmdFBhZCtpdC5odykrJ3B4JzsgaXQuZWwuc3R5bGUudG9wPShjeStzdGVwdippKSsncHgnOyBpdC5lbC5zdHlsZS5vcGFjaXR5PTE7IH0pOyB9IH0gfQogICAgZnVuY3Rpb24gYW5pbWF0ZSgpeyByZXF1ZXN0QW5pbWF0aW9uRnJhbWUoYW5pbWF0ZSk7IGNvbnRyb2xzLnVwZGF0ZSgpOwogICAgICBjb25zdCBwaGFzZTFBY3RpdmUgPSBzdGF0ZS5zZWxlY3Rpb249PT0ncGhhc2UxX2NuYycgfHwgc3RhdGUuc2VsZWN0aW9uPT09J3NlbnNvcl9zaWdodCcgfHwgc3RhdGUuc2VsZWN0aW9uPT09J3NlbnNvcl90b3VjaCcgfHwgc3RhdGUuc2VsZWN0aW9uPT09J3NlbnNvcl9oZWFyaW5nJyB8fCBzdGF0ZS5zZWxlY3Rpb249PT0nc2Vuc29yX3NtZWxsJzsKICAgICAgY29uc3QgYmVhY29uTW9kZSA9IHBoYXNlMUFjdGl2ZSA\/IGdldEF1dG9Nb2RlKHN0YXRlLnRpbWUpIDogKHN0YXRlLnNlbnNvck1vZGV8fCdub3JtYWwnKTsKICAgICAgaWYocm90YXRpbmdEcmlsbEJpdCl7IHJvdGF0aW5nRHJpbGxCaXQucm90YXRpb24ueSArPSAwLjQ0OyBjb25zdCBjeWNsZT0oc3RhdGUudGltZSowLjI4KSUxOyBsZXQgZW5nYWdlPTA7IGlmKHBoYXNlMUFjdGl2ZSl7IGlmKGN5Y2xlPDAuMTgpeyBlbmdhZ2UgPSBjeWNsZS8wLjE4OyB9IGVsc2UgaWYoY3ljbGU8MC43MCl7IGVuZ2FnZSA9IDE7IH0gZWxzZSB7IGVuZ2FnZSA9IE1hdGgubWF4KDAsMS0oKGN5Y2xlLTAuNzApLzAuMzApKTsgfSB9IHJvdGF0aW5nRHJpbGxCaXQucG9zaXRpb24ueSA9IDMuODggLSAoZW5nYWdlKjAuODYpOyB9CiAgICAgIGlmKHdvcmtwaWVjZUdyb3VwKXsgY29uc3QgY3V0UHVsc2U9cGhhc2UxQWN0aXZlPygwLjA4KyhNYXRoLnNpbihzdGF0ZS50aW1lKjUpKzEpKjAuMDYpOjAuMTA7IHdvcmtwaWVjZUN1dEdsb3cubWF0ZXJpYWwub3BhY2l0eT1jdXRQdWxzZTsgd29ya3BpZWNlQ3V0R2xvdy5tYXRlcmlhbC5jb2xvci5zZXQoYmVhY29uTW9kZT09PSdmYXVsdCc\/MHhEQzAwMkI6YmVhY29uTW9kZT09PSd3YXJuaW5nJz8weEY1OUUwQjoweDMyQzg3QSk7IH0KICAgICAgaWYoaW5zcGVjdGlvbkNhbWVyYSl7IGluc3BlY3Rpb25DYW1lcmEucm90YXRpb24ueT1NYXRoLlBJK01hdGguc2luKHN0YXRlLnRpbWUqMS44KSouMDg7IGlmKGluc3BlY3Rpb25HbG93KSBpbnNwZWN0aW9uR2xvdy5tYXRlcmlhbC5vcGFjaXR5PS4xKyhNYXRoLnNpbihzdGF0ZS50aW1lKjMuMikrMSkqLjA0OyB9CiAgICAgIGlmKGFsZXJ0QmVhY29uTGlnaHQmJmFsZXJ0QmVhY29uTWFya2VyKXsgY29uc3QgY29sb3I9YmVhY29uTW9kZT09PSdmYXVsdCc\/MHhmZjJhMzI6YmVhY29uTW9kZT09PSd3YXJuaW5nJz8weEYyQzk0QzoweDQ0ZDI2YjsgY29uc3QgcHVsc2U9YmVhY29uTW9kZT09PSdmYXVsdCc\/KDEuOStNYXRoLmFicyhNYXRoLnNpbihzdGF0ZS50aW1lKjgpKSoxLjApOmJlYWNvbk1vZGU9PT0nd2FybmluZyc\/KDEuMjUrTWF0aC5hYnMoTWF0aC5zaW4oc3RhdGUudGltZSo0KSkqMC40NSk6MC45NTsgYWxlcnRCZWFjb25MaWdodC5jb2xvci5zZXQoY29sb3IpOyBhbGVydEJlYWNvbkxpZ2h0LmludGVuc2l0eT1wdWxzZTsgYWxlcnRCZWFjb25NYXJrZXIubWF0ZXJpYWwuY29sb3Iuc2V0KGNvbG9yKTsgYWxlcnRCZWFjb25NYXJrZXIubWF0ZXJpYWwub3BhY2l0eT1iZWFjb25Nb2RlPT09J2ZhdWx0Jz8uMTg6KGJlYWNvbk1vZGU9PT0nd2FybmluZyc\/LjE0Oi4xMCk7IGlmKGFsZXJ0QmVhY29uRG9tZSl7IGFsZXJ0QmVhY29uRG9tZS5tYXRlcmlhbC5jb2xvci5zZXQoY29sb3IpOyBhbGVydEJlYWNvbkRvbWUubWF0ZXJpYWwuZW1pc3NpdmUuc2V0KGJlYWNvbk1vZGU9PT0nZmF1bHQnPzB4N2EwZTE4OihiZWFjb25Nb2RlPT09J3dhcm5pbmcnPzB4NmM1NDEwOjB4MTEzMzIyKSk7IH0gaWYoYWxlcnRCZWFjb25Td2VlcCl7IGFsZXJ0QmVhY29uU3dlZXAuZm9yRWFjaCgocmF5LGkpPT57IHJheS5tYXRlcmlhbC5jb2xvci5zZXQoY29sb3IpOyByYXkubWF0ZXJpYWwub3BhY2l0eT0oYmVhY29uTW9kZT09PSdmYXVsdCc\/Ljc4OihiZWFjb25Nb2RlPT09J3dhcm5pbmcnPy42NDouNTQpKSooMC43KzAuMypNYXRoLnNpbihzdGF0ZS50aW1lKjYraSkpOyByYXkucm90YXRpb24uej0oLTAuMjQraSowLjEyKSsoTWF0aC5zaW4oc3RhdGUudGltZSozK2kpKjAuMDYpOyB9KTsgfSB9CiAgICAgIGRhdGFMaW5lcy5mb3JFYWNoKGxpbmU9PmxpbmUubWF0ZXJpYWwuZGFzaE9mZnNldCAtPSAuMDUpOyByYXdEYXRhUGFja2V0cy5mb3JFYWNoKHVwZGF0ZURhdGFQYWNrZXRTdHJlYW0pOyBwcmlvcml0eURhdGFQYWNrZXRzLmZvckVhY2godXBkYXRlRGF0YVBhY2tldFN0cmVhbSk7IGlmKHNlcnZlckJhcnMubGVuZ3RoKXtjb25zdCBhY3RpdmVCYXI9TWF0aC5mbG9vcihzdGF0ZS50aW1lKjIuNSklc2VydmVyQmFycy5sZW5ndGg7IHNlcnZlckJhcnMuZm9yRWFjaCgoYmFyLGkpPT57Y29uc3QgYWN0aXZlPWk9PT1hY3RpdmVCYXI7IGJhci5tYXRlcmlhbC5jb2xvci5zZXQoYWN0aXZlPzB4RkY0QTY4OjB4NWEwYTE4KTsgYmFyLm1hdGVyaWFsLm9wYWNpdHk9YWN0aXZlPzE6LjI2OyBiYXIuc2NhbGUueD1hY3RpdmU\/MS4wODoxOyBiYXIuc2NhbGUueT1hY3RpdmU\/MS4xODoxO30pO30gdXBkYXRlRGFzaGJvYXJkVGV4dHVyZXMoKTsgcmVuZGVyZXIucmVuZGVyKHNjZW5lLGNhbWVyYSk7IGlmKHN0YXRlLnN0YXJ0ZWQpeyBkcmF3Q2hhcnQoKTsgZHJhd0NhbSgpOyB9IHVwZGF0ZVRyYWNraW5nKCk7IH0KICAgIGFuaW1hdGUoKTsgdHJ5e3N0YXRlLnN0YXJ0ZWQ9dHJ1ZTsgaWYoZG9tLmludHJvKWRvbS5pbnRyby5zdHlsZS5kaXNwbGF5PSdub25lJzsgc2hvd01haW4odHJ1ZSk7IHNob3dTZW5zb3JzKGZhbHNlKTsgc2V0U3RhdHVzKCdPdmVydmlldyBtb2RlLiBDbGljayBhIHN0YWdlIGxhYmVsIHRvIGJlZ2luLicpO31jYXRjaChfKXt9IChmdW5jdGlvbigpe3RyeXsgdmFyIGdwPUlJT1RfUk9PVC5xdWVyeVNlbGVjdG9yKCcuZ2xvc3NhcnktcGFuZWwnKTsgaWYoIWdwKSByZXR1cm47IHZhciBkZXQ9Z3AucXVlcnlTZWxlY3RvcignZGV0YWlscycpLCBzdW09Z3AucXVlcnlTZWxlY3Rvcignc3VtbWFyeScpOyBpZighZGV0fHwhc3VtKSByZXR1cm47IHZhciBDT0w9JzU4cHgnOyBncC5zdHlsZS5tYXhIZWlnaHQ9Q09MOyBncC5zdHlsZS5vdmVyZmxvdz0naGlkZGVuJzsgZnVuY3Rpb24gZXhwYW5kKCl7IGRldC5vcGVuPXRydWU7IHJlcXVlc3RBbmltYXRpb25GcmFtZShmdW5jdGlvbigpeyB2YXIgY2FwPU1hdGgucm91bmQoKElIKCl8fDYwMCkqMC45KTsgZ3Auc3R5bGUubWF4SGVpZ2h0PU1hdGgubWluKGdwLnNjcm9sbEhlaWdodCxjYXApKydweCc7IGdwLnN0eWxlLm92ZXJmbG93WT0nYXV0byc7IH0pOyB9IGZ1bmN0aW9uIGNvbGxhcHNlKCl7IGdwLnN0eWxlLm1heEhlaWdodD1ncC5zY3JvbGxIZWlnaHQrJ3B4JzsgcmVxdWVzdEFuaW1hdGlvbkZyYW1lKGZ1bmN0aW9uKCl7IGdwLnN0eWxlLm1heEhlaWdodD1DT0w7IH0pOyBzZXRUaW1lb3V0KGZ1bmN0aW9uKCl7IGRldC5vcGVuPWZhbHNlOyBncC5zdHlsZS5vdmVyZmxvdz0naGlkZGVuJzsgfSwzNzApOyB9IHN1bS5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsZnVuY3Rpb24oZSl7IGUucHJldmVudERlZmF1bHQoKTsgaWYoZGV0Lm9wZW4peyBjb2xsYXBzZSgpOyB9IGVsc2UgeyBleHBhbmQoKTsgfSB9KTsgZGV0LmFkZEV2ZW50TGlzdGVuZXIoJ3RyYW5zaXRpb25lbmQnLGZ1bmN0aW9uKCl7IGlmKGRldC5vcGVuKSBncC5zdHlsZS5vdmVyZmxvdz0nYXV0byc7IH0pOyB9Y2F0Y2goXyl7fX0pKCk7IGNvbnN0IF9paW9Sej0oKT0+eyBpZihJSU9UX1JPT1Qpe0lJT1RfUk9PVC5jbGFzc0xpc3QudG9nZ2xlKCdzcjEtbmFycm93JywgSVcoKTw5MDApO30gY2FtZXJhLmFzcGVjdD1JVygpL0lIKCk7IGNhbWVyYS51cGRhdGVQcm9qZWN0aW9uTWF0cml4KCk7IHJlbmRlcmVyLnNldFNpemUoSVcoKSxJSCgpKTsgcmVuZGVyZXIuc2V0UGl4ZWxSYXRpbyhNYXRoLm1pbih3aW5kb3cuZGV2aWNlUGl4ZWxSYXRpb3x8MSwyKSk7IHN5bmNDYW52YXNlcygpOyBhcHBseVJlc3BvbnNpdmVGcmFtaW5nKCk7IGNvbnRyb2xzLnVwZGF0ZSgpO307IGlmKHdpbmRvdy5SZXNpemVPYnNlcnZlcil7bmV3IFJlc2l6ZU9ic2VydmVyKF9paW9Seikub2JzZXJ2ZShJSU9UX1JPT1QpO30gd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ3Jlc2l6ZScsX2lpb1J6KTsgX2lpb1J6KCk7IHNldFRpbWVvdXQoX2lpb1J6LDYwKTsKICB9KSgpOwogIA==\";try{var js=decodeURIComponent(escape(atob(b)));var s=document.createElement('script');s.textContent=js;(document.getElementById('iiot-sr1-app')||document.body).appendChild(s);}catch(e){if(window&&window.console)console.log('SR1 bootstrap error',e);}})();<\/script>\n<\/div>\n\n\n\n<div style=\"height:50px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">You cannot improve what you do not measure. In traditional factories, many assets are dark assets: machines and processes that go unmeasured until something goes wrong. Sensors shine a light on these hidden variables. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The formula is simple: sensors plus connectivity let you listen to your factory in real time. First, we listen by gathering data. Then, we learn by analysing it. Finally, we act by automating or adjusting processes. This tightens feedback loops and replaces paper-based operations with digital ones.<\/p>\n\n\n\n<div style=\"height:48px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<div class=\"wp-block-gsma-banner-rihgt-img banner_right-img_block gsma-load-hidden right-copy\">\n<div class=\"wp-block-group banner_right-img_container gsma-load-hidden\"><div class=\"wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow\">\n<div class=\"wp-block-columns banner_right-img_columns is-layout-flex wp-container-core-columns-is-layout-8f761849 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column banner_right-img_column_left is-layout-flow wp-block-column-is-layout-flow\">\n<h2 id=\"h-why-are-sensors-foundational-to-industrial-iot\" class=\"wp-block-heading banner_right-img_title\">Why are sensors foundational to industrial IoT?<\/h2>\n\n\n\n<p class=\"banner_right-img_blurb wp-block-paragraph\">Sensors provide the raw facts about metrics like energy usage and machine health. This turns guesswork into evidence, enabling predictive maintenance, real-time optimisation and quality analytics, so problems are caught and corrected before they reach the production line. With a connected sensor, operators get advance warning. They can schedule repairs during planned downtime, avoiding unexpected failures.<\/p>\n\n\n<\/div>\n\n\n\n<div class=\"wp-block-column banner_right-img_column_right is-layout-flow wp-block-column-is-layout-flow\">\n<figure class=\"wp-block-image size-full banner_right-img_image\"><img loading=\"lazy\" decoding=\"async\" width=\"710\" height=\"688\" src=\"https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/wp-content\/uploads\/2026\/08\/IIoT_What_is_sensor_710x688.jpg\" alt=\"Industrial IoT sensor on conveyor belt sorting metal components\" class=\"wp-image-47254\" srcset=\"https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/wp-content\/uploads\/2026\/08\/IIoT_What_is_sensor_710x688.jpg 710w, https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/wp-content\/uploads\/2026\/08\/IIoT_What_is_sensor_710x688-300x291.jpg 300w\" sizes=\"auto, (max-width: 710px) 100vw, 710px\" \/><\/figure>\n<\/div>\n<\/div>\n<\/div><\/div>\n<\/div>\n\n\n\n<div style=\"height:50px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 id=\"h-grounded-in-reality-sensors-on-the-industrial-iot-factory-floor\" class=\"wp-block-heading\">Grounded in reality: sensors on the industrial IoT factory floor<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The shift from dark assets to sensor-driven intelligence is transforming global manufacturing. <\/p>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-8f761849 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<div class=\"wp-block-gsma-block-number number-block_container\" style=\"font-size:40px\"><div class=\"number-prepend\"><\/div><div class=\"number js-odometer odometer odometer-auto-theme\" data-odovalue=\"2\" data-odostart=\"0\"><\/div><div class=\"number-append\">x<\/div><\/div>\n\n\n\n<div style=\"height:50px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">faster response speed for remote crane operators<\/p>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<div class=\"wp-block-gsma-block-number number-block_container\" style=\"font-size:40px\"><div class=\"number-prepend\"><\/div><div class=\"number js-odometer odometer odometer-auto-theme\" data-odovalue=\"50\" data-odostart=\"0\"><\/div><div class=\"number-append\">%<\/div><\/div>\n\n\n\n<div style=\"height:50px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">reduction in production line floor space<\/p>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<div class=\"wp-block-gsma-block-number number-block_container\" style=\"font-size:40px\"><div class=\"number-prepend\"><\/div><div class=\"number js-odometer odometer odometer-auto-theme\" data-odovalue=\"34\" data-odostart=\"0\"><\/div><div class=\"number-append\">%<\/div><\/div>\n\n\n\n<div style=\"height:50px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">reduction in crane CO2 emissions (50 kg \u2192 33 kg)<\/p>\n<\/div>\n<\/div>\n\n\n\n<h3 id=\"h-schneider-electric-visual-sensors-and-flexible-manufacturing\" class=\"wp-block-heading\">Schneider Electric: visual sensors and flexible manufacturing<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">At its Shanghai smart factory, <a href=\"https:\/\/www.se.com\/ww\/en\/insights\/next-generation-automation\/industrial-intelligence\/unlocking-the-potential-of-5g-for-industrial-automation\/\">Schneider Electric<\/a> needed highly adaptable production lines. It also needed large amounts of visual data for quality control. Traditional wired networks made this difficult. Cable restrictions and the high bandwidth required for video created significant obstacles.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">They deployed a private 5G network as the wireless backbone. This let them embed high-resolution cameras directly into their machinery as advanced IIoT visual sensors. These sensors stream live video over 5G for AI-powered diagnostics, automating defect detection and preventing costly disruptions.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Replacing fragile communication cables on their hoisting cranes with wireless industrial IoT connectivity also delivered major results. Response speed for remote operators doubled. The production line load rate rose to 80%. Required floor space halved. Carbon emissions from the cranes dropped from 50 kg to 33 kg of CO2.<\/p>\n\n\n\n<div style=\"height:49px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<div class=\"wp-block-gsma-block-slider-container gsma-block_slider_container\"><div class=\"gsma-block_slider_inner\">\n<div class=\"wp-block-gsma-block-slider-thumbnail gsma-block_slider_thumb gsma-load-hidden\">\n<div class=\"wp-block-cover slider_thumbnail_container gsma-load-hidden\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"306\" class=\"wp-block-cover__image-background wp-image-47423 size-large\" alt=\"\" src=\"https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/wp-content\/uploads\/2026\/08\/Slider_1_1440x430-1024x306.jpg\" data-object-fit=\"cover\" srcset=\"https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/wp-content\/uploads\/2026\/08\/Slider_1_1440x430-1024x306.jpg 1024w, https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/wp-content\/uploads\/2026\/08\/Slider_1_1440x430-300x90.jpg 300w, https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/wp-content\/uploads\/2026\/08\/Slider_1_1440x430-768x229.jpg 768w, https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/wp-content\/uploads\/2026\/08\/Slider_1_1440x430.jpg 1440w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><span aria-hidden=\"true\" class=\"wp-block-cover__background has-gsma-black-background-color has-background-dim-40 has-background-dim\"><\/span><div class=\"wp-block-cover__inner-container is-layout-flow wp-block-cover-is-layout-flow\">\n<h2 id=\"h-iot-resources\" class=\"wp-block-heading slider_thumbnail_title\">IoT Resources<\/h2>\n\n\n\n<p class=\"slider_thumbnail_blurb wp-block-paragraph\">For more on the specifications that help underpin the mobile technologies used in smart manufacturing, please visit the GSMA&#8217;s IoT Resources page.<\/p>\n\n\n\n<div class=\"wp-block-button slider_thumbnail_button\"><a class=\"wp-block-button__link wp-element-button\" href=\"https:\/\/www.gsma.com\/solutions-and-impact\/technologies\/internet-of-things\/iot-resources\/\">Find out more<\/a><\/div>\n<\/div><\/div>\n<\/div>\n\n\n\n<div class=\"wp-block-gsma-block-slider-thumbnail gsma-block_slider_thumb gsma-load-hidden\">\n<div class=\"wp-block-cover slider_thumbnail_container gsma-load-hidden\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"306\" class=\"wp-block-cover__image-background wp-image-47424 size-large\" alt=\"\" src=\"https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/wp-content\/uploads\/2026\/08\/Slider_2_1440x430-1024x306.jpg\" data-object-fit=\"cover\" srcset=\"https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/wp-content\/uploads\/2026\/08\/Slider_2_1440x430-1024x306.jpg 1024w, https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/wp-content\/uploads\/2026\/08\/Slider_2_1440x430-300x90.jpg 300w, https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/wp-content\/uploads\/2026\/08\/Slider_2_1440x430-768x229.jpg 768w, https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/wp-content\/uploads\/2026\/08\/Slider_2_1440x430.jpg 1440w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><span aria-hidden=\"true\" class=\"wp-block-cover__background has-gsma-black-background-color has-background-dim-40 has-background-dim\"><\/span><div class=\"wp-block-cover__inner-container is-layout-flow wp-block-cover-is-layout-flow\">\n<h2 id=\"h-gsma-manufacturing-resources\" class=\"wp-block-heading slider_thumbnail_title\">GSMA Manufacturing Resources<\/h2>\n\n\n\n<p class=\"slider_thumbnail_blurb wp-block-paragraph\">The Connected Manufacturing and Production community advances the role and capabilities of mobile technology in smart manufacturing.<\/p>\n\n\n\n<div class=\"wp-block-button slider_thumbnail_button\"><a class=\"wp-block-button__link wp-element-button\" href=\"https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/digital-industries-resources\/\">Find out more<\/a><\/div>\n<\/div><\/div>\n<\/div>\n<\/div><div class=\"gsma-block_slider_nav\"><div class=\"gsma-block_slider_prev-button\"><\/div><div class=\"gsma-block_slider_next-button\"><\/div><\/div><\/div>\n\n\n\n<div style=\"height:51px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n","protected":false},"excerpt":{"rendered":"<p>Industrial IoT (IIoT) turns isolated machines or dark assets into connected assets that tell you what is happening on the factory floor, as it happens. Machines, workstations, tools and materials become connected assets that help people understand what is happening on the factory floor. That journey starts with visibility. Sensors act as the digital equivalents [&hellip;]<\/p>\n","protected":false},"author":29,"featured_media":47553,"template":"","meta":{"image":"https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/wp-content\/uploads\/2026\/09\/Navigation-image_11_500x500-.jpg","json":{"gsma_resources_type":"Other","gsma_resources_thumb":"[47552]","gsma_resources_file":"null","gsma_resources_multi":null,"gsma_resources_wgr":null,"gsma_resources_video":"","gsma_resources_image":"null","gsma_resources_url":"","gsma_resources_date":"","gsma_resources_button":""}},"tags":[],"resource_categories":[61,206],"algolia_discover_type":[155],"class_list":["post-47233","gsma_theme_resources","type-gsma_theme_resources","status-publish","has-post-thumbnail","hentry","applications_services-internet-of-things-iot","applications_services-manufacturing","resource_categories-manufacturing","resource_categories-smart-manufacturing-unpacked","algolia_discover_type-resource"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v28.2 (Yoast SEO v28.7) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Smart Manufacturing Unpacked: What is industrial IoT? - Connected Manufacturing - GSMA<\/title>\n<meta name=\"description\" content=\"Learn what industrial IoT is and how sensors, private 5G, and IIoT gateways turn factory machines into connected, data-driven assets.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/gsma_resources\/what-is-industrial-iot\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Smart Manufacturing Unpacked: What is industrial IoT? - Connected Manufacturing - GSMA\" \/>\n<meta property=\"og:description\" content=\"Learn what industrial IoT is and how sensors, private 5G, and IIoT gateways turn factory machines into connected, data-driven assets.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/gsma_resources\/what-is-industrial-iot\/\" \/>\n<meta property=\"og:site_name\" content=\"Connected Manufacturing\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/gsma\" \/>\n<meta property=\"article:modified_time\" content=\"2026-10-01T13:27:05+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/wp-content\/uploads\/2026\/09\/Robot-arm_header_3_800x500.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"800\" \/>\n\t<meta property=\"og:image:height\" content=\"500\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:title\" content=\"Smart Manufacturing Unpacked: What is industrial IoT? - Connected Manufacturing - GSMA\" \/>\n<meta name=\"twitter:description\" content=\"Learn what industrial IoT is and how sensors, private 5G, and IIoT gateways turn factory machines into connected, data-driven assets.\" \/>\n<meta name=\"twitter:site\" content=\"@GSMA\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"6 minutes\" \/>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Smart Manufacturing Unpacked: What is industrial IoT? - Connected Manufacturing - GSMA","description":"Learn what industrial IoT is and how sensors, private 5G, and IIoT gateways turn factory machines into connected, data-driven assets.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/gsma_resources\/what-is-industrial-iot\/","og_locale":"en_US","og_type":"article","og_title":"Smart Manufacturing Unpacked: What is industrial IoT? - Connected Manufacturing - GSMA","og_description":"Learn what industrial IoT is and how sensors, private 5G, and IIoT gateways turn factory machines into connected, data-driven assets.","og_url":"https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/gsma_resources\/what-is-industrial-iot\/","og_site_name":"Connected Manufacturing","article_publisher":"https:\/\/www.facebook.com\/gsma","article_modified_time":"2026-10-01T13:27:05+00:00","og_image":[{"width":800,"height":500,"url":"https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/wp-content\/uploads\/2026\/09\/Robot-arm_header_3_800x500.jpg","type":"image\/jpeg"}],"twitter_card":"summary_large_image","twitter_title":"Smart Manufacturing Unpacked: What is industrial IoT? - Connected Manufacturing - GSMA","twitter_description":"Learn what industrial IoT is and how sensors, private 5G, and IIoT gateways turn factory machines into connected, data-driven assets.","twitter_site":"@GSMA","twitter_misc":{"Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/gsma_resources\/what-is-industrial-iot\/","url":"https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/gsma_resources\/what-is-industrial-iot\/","name":"Smart Manufacturing Unpacked: What is industrial IoT? - Connected Manufacturing - GSMA","isPartOf":{"@id":"https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/gsma_resources\/what-is-industrial-iot\/#primaryimage"},"image":{"@id":"https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/gsma_resources\/what-is-industrial-iot\/#primaryimage"},"thumbnailUrl":"https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/wp-content\/uploads\/2026\/09\/Robot-arm_header_3_800x500.jpg","datePublished":"2026-09-01T22:08:29+00:00","dateModified":"2026-10-01T13:27:05+00:00","description":"Learn what industrial IoT is and how sensors, private 5G, and IIoT gateways turn factory machines into connected, data-driven assets.","breadcrumb":{"@id":"https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/gsma_resources\/what-is-industrial-iot\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/gsma_resources\/what-is-industrial-iot\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/gsma_resources\/what-is-industrial-iot\/#primaryimage","url":"https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/wp-content\/uploads\/2026\/09\/Robot-arm_header_3_800x500.jpg","contentUrl":"https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/wp-content\/uploads\/2026\/09\/Robot-arm_header_3_800x500.jpg","width":800,"height":500,"caption":"What is Industrial IoT?"},{"@type":"BreadcrumbList","@id":"https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/gsma_resources\/what-is-industrial-iot\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/"},{"@type":"ListItem","position":2,"name":"Smart Manufacturing Unpacked: What is industrial IoT?"}]},{"@type":"WebSite","@id":"https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/#website","url":"https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/","name":"Connected Manufacturing","description":"Digital Industries, Connected Manufacturing","publisher":{"@id":"https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/#organization"},"alternateName":"Digital Industries","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/#organization","name":"GSMA","url":"https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/#\/schema\/logo\/image\/","url":"https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/wp-content\/uploads\/2024\/04\/GSMA-Logo-Red-RGB_square.jpg","contentUrl":"https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/wp-content\/uploads\/2024\/04\/GSMA-Logo-Red-RGB_square.jpg","width":600,"height":600,"caption":"GSMA"},"image":{"@id":"https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/gsma","https:\/\/x.com\/GSMA"]}]}},"jetpack_sharing_enabled":true,"cats":[{"term_id":69,"name":"5G","slug":"5g-manufacturing-technology","term_group":0,"term_taxonomy_id":69,"taxonomy":"resource_categories","description":"","parent":0,"count":22,"filter":"raw"},{"term_id":55,"name":"5G","slug":"5g-auto","term_group":0,"term_taxonomy_id":55,"taxonomy":"resource_categories","description":"","parent":0,"count":8,"filter":"raw"},{"term_id":53,"name":"Advanced Air Mobility","slug":"drones","term_group":0,"term_taxonomy_id":53,"taxonomy":"resource_categories","description":"","parent":0,"count":2,"filter":"raw"},{"term_id":74,"name":"Artificial Intelligence","slug":"artificial-intelligence","term_group":0,"term_taxonomy_id":74,"taxonomy":"resource_categories","description":"","parent":0,"count":5,"filter":"raw"},{"term_id":58,"name":"Asia-Pacific","slug":"apac","term_group":0,"term_taxonomy_id":58,"taxonomy":"resource_categories","description":"","parent":0,"count":4,"filter":"raw"},{"term_id":75,"name":"Big Data Analytics","slug":"big-data-analytics","term_group":0,"term_taxonomy_id":75,"taxonomy":"resource_categories","description":"","parent":0,"count":6,"filter":"raw"},{"term_id":125,"name":"Digital Industries","slug":"digital-industries","term_group":0,"term_taxonomy_id":125,"taxonomy":"resource_categories","description":"","parent":0,"count":4,"filter":"raw"},{"term_id":82,"name":"Digital Industries Partner Spotlights","slug":"digital-industries-partner-spotlights","term_group":0,"term_taxonomy_id":82,"taxonomy":"resource_categories","description":"","parent":0,"count":11,"filter":"raw"},{"term_id":70,"name":"Edge Computing","slug":"edge-computing","term_group":0,"term_taxonomy_id":70,"taxonomy":"resource_categories","description":"","parent":0,"count":4,"filter":"raw"},{"term_id":64,"name":"Industry Engagement","slug":"industry-engagement","term_group":0,"term_taxonomy_id":64,"taxonomy":"resource_categories","description":"","parent":0,"count":1,"filter":"raw"},{"term_id":31,"name":"Internet of Things \u2013 general","slug":"internet-of-things-general","term_group":0,"term_taxonomy_id":31,"taxonomy":"resource_categories","description":"","parent":0,"count":1,"filter":"raw"},{"term_id":30,"name":"IoT Connection Efficiency","slug":"iot-connection-efficiency","term_group":0,"term_taxonomy_id":30,"taxonomy":"resource_categories","description":"","parent":0,"count":3,"filter":"raw"},{"term_id":33,"name":"IoT Policy and Regulations","slug":"iot-policy-and-regulations","term_group":0,"term_taxonomy_id":33,"taxonomy":"resource_categories","description":"","parent":0,"count":5,"filter":"raw"},{"term_id":52,"name":"IoT Security &amp; Connection Efficiency","slug":"iot-security-connection-efficiency","term_group":0,"term_taxonomy_id":52,"taxonomy":"resource_categories","description":"","parent":0,"count":4,"filter":"raw"},{"term_id":61,"name":"Manufacturing","slug":"manufacturing","term_group":0,"term_taxonomy_id":61,"taxonomy":"resource_categories","description":"","parent":0,"count":66,"filter":"raw"},{"term_id":81,"name":"Manufacturing Technology","slug":"manufacturing-technology","term_group":0,"term_taxonomy_id":81,"taxonomy":"resource_categories","description":"","parent":0,"count":21,"filter":"raw"},{"term_id":78,"name":"Manufacturing-GSMA","slug":"manufacturing-main","term_group":0,"term_taxonomy_id":78,"taxonomy":"resource_categories","description":"","parent":0,"count":7,"filter":"raw"},{"term_id":45,"name":"MIoT Case Studies","slug":"miot-case-studies","term_group":0,"term_taxonomy_id":45,"taxonomy":"resource_categories","description":"","parent":0,"count":5,"filter":"raw"},{"term_id":42,"name":"Mobile IoT Initiative","slug":"mobile-iot-initiative","term_group":0,"term_taxonomy_id":42,"taxonomy":"resource_categories","description":"","parent":0,"count":27,"filter":"raw"},{"term_id":88,"name":"MWC22","slug":"mwc22","term_group":0,"term_taxonomy_id":88,"taxonomy":"resource_categories","description":"","parent":0,"count":1,"filter":"raw"},{"term_id":89,"name":"MWC23","slug":"mwc23","term_group":0,"term_taxonomy_id":89,"taxonomy":"resource_categories","description":"","parent":0,"count":6,"filter":"raw"},{"term_id":67,"name":"North America","slug":"america","term_group":0,"term_taxonomy_id":67,"taxonomy":"resource_categories","description":"","parent":0,"count":2,"filter":"raw"},{"term_id":77,"name":"Private &amp; Dedicated Networks","slug":"private-networks","term_group":0,"term_taxonomy_id":77,"taxonomy":"resource_categories","description":"","parent":0,"count":18,"filter":"raw"},{"term_id":27,"name":"Resources","slug":"resources","term_group":0,"term_taxonomy_id":27,"taxonomy":"resource_categories","description":"","parent":0,"count":23,"filter":"raw"},{"term_id":86,"name":"Security","slug":"security-manufacturing-technology","term_group":0,"term_taxonomy_id":86,"taxonomy":"resource_categories","description":"","parent":0,"count":1,"filter":"raw"},{"term_id":35,"name":"Smart Cities Health","slug":"smart-cities-health","term_group":0,"term_taxonomy_id":35,"taxonomy":"resource_categories","description":"","parent":0,"count":3,"filter":"raw"},{"term_id":44,"name":"Smart Cities Highlights","slug":"smart-cities-highlights","term_group":0,"term_taxonomy_id":44,"taxonomy":"resource_categories","description":"","parent":0,"count":15,"filter":"raw"},{"term_id":48,"name":"Smart Cities Tourism Entertainment","slug":"smart-cities-tourism-entertainment","term_group":0,"term_taxonomy_id":48,"taxonomy":"resource_categories","description":"","parent":0,"count":5,"filter":"raw"},{"term_id":206,"name":"Smart Manufacturing Unpacked","slug":"smart-manufacturing-unpacked","term_group":0,"term_taxonomy_id":206,"taxonomy":"resource_categories","description":"","parent":61,"count":3,"filter":"raw"}],"_links":{"self":[{"href":"https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/wp-json\/wp\/v2\/gsma_theme_resources\/47233","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/wp-json\/wp\/v2\/gsma_theme_resources"}],"about":[{"href":"https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/wp-json\/wp\/v2\/types\/gsma_theme_resources"}],"author":[{"embeddable":true,"href":"https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/wp-json\/wp\/v2\/users\/29"}],"version-history":[{"count":58,"href":"https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/wp-json\/wp\/v2\/gsma_theme_resources\/47233\/revisions"}],"predecessor-version":[{"id":47609,"href":"https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/wp-json\/wp\/v2\/gsma_theme_resources\/47233\/revisions\/47609"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/wp-json\/wp\/v2\/media\/47553"}],"wp:attachment":[{"href":"https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/wp-json\/wp\/v2\/media?parent=47233"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/wp-json\/wp\/v2\/tags?post=47233"},{"taxonomy":"resource_categories","embeddable":true,"href":"https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/wp-json\/wp\/v2\/resource_categories?post=47233"},{"taxonomy":"algolia_discover_type","embeddable":true,"href":"https:\/\/www.gsma.com\/solutions-and-impact\/industries\/connected-manufacturing\/wp-json\/wp\/v2\/algolia_discover_type?post=47233"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}