{"id":3964,"date":"2026-07-10T16:34:12","date_gmt":"2026-07-10T16:34:12","guid":{"rendered":"https:\/\/www.chess.lumn.eu\/wordpress\/?p=3964"},"modified":"2026-08-22T17:24:46","modified_gmt":"2026-08-22T17:24:46","slug":"fritz-sous-gui-alternatives","status":"publish","type":"post","link":"https:\/\/www.chess.lumn.eu\/wordpress\/2026\/07\/10\/fritz-sous-gui-alternatives\/","title":{"rendered":"UPDATE: Chessbase engines sous autres GUI"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-post\" data-elementor-id=\"3964\" class=\"elementor elementor-3964\">\n\t\t\t\t\t\t<div class=\"elementor-inner\">\n\t\t\t\t<div class=\"elementor-section-wrap\">\n\t\t\t\t\t\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-b7bf6e2 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"b7bf6e2\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t\t\t<div class=\"elementor-row\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-d3145fb\" data-id=\"d3145fb\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-column-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-391c71f elementor-widget elementor-widget-html\" data-id=\"391c71f\" data-element_type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<!DOCTYPE html>\n<html lang=\"fr\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<title>Faire rejouer les moteurs d'\u00e9checs classiques \u2014 les ponts eng2uci et shredder2uci<\/title>\n<link rel=\"preconnect\" href=\"https:\/\/fonts.googleapis.com\">\n<link rel=\"preconnect\" href=\"https:\/\/fonts.gstatic.com\" crossorigin>\n<link href=\"https:\/\/fonts.googleapis.com\/css2?family=DM+Serif+Display:ital@0;1&family=DM+Sans:ital,opsz,wght@0,9..40,300..700;1,9..40,400&family=JetBrains+Mono:wght@400;500;700&display=swap\" rel=\"stylesheet\">\n<style>\n  :root{\n    --creme:#f7f4ee; --encre:#2b2b2b; --rouge:#c0392b;\n    --or:#b8863b; --trait:#e3ddd0; --gris:#6b665c;\n  }\n  *{box-sizing:border-box;}\n  html{scroll-behavior:smooth;}\n  body{\n    margin:0; background:var(--creme); color:var(--encre);\n    font-family:'DM Sans',system-ui,sans-serif; font-weight:400;\n    font-size:18px; line-height:1.72; -webkit-font-smoothing:antialiased;\n  }\n  .naum-body{max-width:900px; margin:0 auto; padding:64px 28px 120px;}\n\n  h1{font-family:'DM Serif Display',serif; font-weight:400; font-size:2.9rem;\n     line-height:1.08; letter-spacing:-.5px; margin:0 0 .35em;}\n  h2{font-family:'DM Serif Display',serif; font-weight:400; font-size:1.85rem;\n     line-height:1.15; letter-spacing:-.3px; margin:2.6em 0 .5em; padding-bottom:.25em;\n     border-bottom:2px solid var(--rouge);}\n  h3{font-family:'DM Sans',sans-serif; font-weight:700; font-size:1.1rem;\n     letter-spacing:.2px; text-transform:uppercase; margin:1.8em 0 .4em; color:var(--rouge);}\n  .eyebrow{font-family:'JetBrains Mono',monospace; font-size:.78rem; letter-spacing:3px;\n     text-transform:uppercase; color:var(--or); margin:0 0 1.2em;}\n  .chapeau{font-size:1.22rem; line-height:1.6; color:var(--gris); font-style:italic;\n     margin:0 0 2.4em; padding-left:1.1em; border-left:3px solid var(--or);}\n  p{margin:0 0 1.15em;}\n  a{color:var(--rouge); text-decoration:none; border-bottom:1px solid rgba(192,57,43,.35);}\n  a:hover{border-bottom-color:var(--rouge);}\n  strong{font-weight:700;}\n  code{font-family:'JetBrains Mono',monospace; font-size:.85em; background:#efe9dd;\n     padding:.08em .35em; border-radius:3px; color:#7a3b2e;}\n  ul,ol{margin:0 0 1.2em; padding-left:1.35em;}\n  li{margin:.4em 0;}\n\n  ol.etapes{list-style:none; padding-left:0; counter-reset:et;}\n  ol.etapes>li{counter-increment:et; position:relative; padding-left:52px; margin:1.1em 0;}\n  ol.etapes>li::before{content:counter(et); position:absolute; left:0; top:-2px;\n     width:34px; height:34px; border-radius:50%; background:var(--rouge); color:#fff;\n     font-family:'JetBrains Mono',monospace; font-weight:700; font-size:1rem;\n     display:flex; align-items:center; justify-content:center;}\n\n  .box{border-radius:8px; padding:18px 22px; margin:1.6em 0; font-size:.97rem; line-height:1.62;}\n  .box .box-titre{font-family:'JetBrains Mono',monospace; font-size:.72rem; letter-spacing:2px;\n     text-transform:uppercase; display:block; margin-bottom:.5em; font-weight:700;}\n  .naum-note-box{background:#f3ecda; border:1px solid #ddd0ab;}\n  .naum-note-box .box-titre{color:#9a7b2e;}\n  .naum-alert-box{background:#fbeae7; border:1px solid #e8b6ac;}\n  .naum-alert-box .box-titre{color:var(--rouge);}\n  .naum-coherence-box{background:#e9f2e6; border:1px solid #b6d3ab;}\n  .naum-coherence-box .box-titre{color:#4e7a3b;}\n\n  .tbl-wrap{overflow-x:auto; margin:1.6em 0;}\n  table{border-collapse:collapse; width:100%; font-size:.9rem;}\n  th,td{border:1px solid var(--trait); padding:10px 13px; text-align:left; vertical-align:top;}\n  th{background:#efe9dd; font-weight:700; letter-spacing:.3px;}\n  tbody tr:nth-child(even){background:#faf7f0;}\n  .ok{color:#4e7a3b; font-weight:700;}\n  .taille{font-family:'JetBrains Mono',monospace; font-size:.86em; white-space:nowrap;}\n\n  .champ{font-family:'JetBrains Mono',monospace; font-size:.82rem; background:#20232a;\n     color:#e6e1d6; padding:14px 18px; border-radius:6px; margin:.6em 0; overflow-x:auto;\n     border-left:3px solid var(--or);}\n  .champ b{color:#e8b17a; font-weight:700;}\n\n  .dl-zone{background:#20232a; border-radius:12px; padding:34px 30px; margin:2.2em 0;\n     text-align:center; color:#e6e1d6;}\n  .dl-zone h3{color:#e8b17a; margin:0 0 .3em;}\n  .dl-zone p{color:#b7b1a4; font-size:.95rem; margin:0 0 1.4em;}\n  .dl-button{font-family:'DM Sans',sans-serif; font-weight:700; font-size:1.05rem;\n     background:var(--rouge); color:#fff; border:none; padding:15px 34px; border-radius:8px;\n     cursor:pointer; letter-spacing:.3px; transition:transform .12s ease, background .2s ease;}\n  .dl-button:hover{background:#a5301f; transform:translateY(-2px);}\n  .dl-button:active{transform:translateY(0);}\n  .dl-sub{font-family:'JetBrains Mono',monospace; font-size:.74rem; color:#8a857a; margin-top:1em;}\n\n  hr{border:none; border-top:1px solid var(--trait); margin:3em 0;}\n  .sig{font-family:'JetBrains Mono',monospace; font-size:.78rem; color:var(--gris);\n     text-align:right; margin-top:3.5em;}\n\n  @media (max-width:600px){\n    body{font-size:16px;} h1{font-size:2.1rem;} h2{font-size:1.45rem;}\n    .naum-body{padding:44px 18px 90px;}\n  }\n<\/style>\n<\/head>\n<body>\n<article class=\"naum-body\">\n\n  <p class=\"eyebrow\">Laboratoire &middot; moteurs d'\u00e9checs classiques<\/p>\n  <h1>Faire rejouer les moteurs classiques<\/h1>\n  <p class=\"chapeau\">\n    Fritz, Junior, Shredder, Nimzo, Hiarcs &mdash; les grands moteurs de 1997 \u00e0 2005 sont\n    enferm\u00e9s dans le logiciel ChessBase qui les a vus na\u00eetre. Deux petits ponts les lib\u00e8rent :\n    ils les font passer pour des moteurs UCI ordinaires, afin qu'on puisse enfin les faire jouer\n    et les calibrer dans les interfaces modernes.\n  <\/p>\n\n  <h2>Ce qu'on cherche \u00e0 faire<\/h2>\n  <p>\n    Un moteur d'\u00e9checs moderne est un programme autonome qui dialogue en texte, selon un\n    langage universel appel\u00e9 <strong>UCI<\/strong> : l'interface lui envoie une position, il\n    r\u00e9pond son coup. C'est ce langage que parlent toutes les interfaces d'aujourd'hui, et c'est\n    lui qui permet de faire s'affronter des moteurs de toutes origines.\n  <\/p>\n  <p>\n    Les vieux moteurs ChessBase, eux, ne fonctionnent pas ainsi. Ce ne sont pas des programmes\n    autonomes mais des <strong>modules internes<\/strong> : seul le logiciel d'origine sait les\n    charger et les faire parler. Impossible, tel quel, de les brancher sur une interface\n    moderne &mdash; ils restent muets.\n  <\/p>\n  <p>\n    L'id\u00e9e des ponts est de <strong>se glisser \u00e0 la place du logiciel d'origine<\/strong>. Le\n    programme charge le vieux moteur, lui parle exactement comme le faisait le logiciel\n    d'\u00e9poque, r\u00e9cup\u00e8re le coup choisi, puis le retraduit en UCI. Vu de l'ext\u00e9rieur, le vieux\n    moteur devient un moteur UCI comme les autres.\n  <\/p>\n  <div class=\"box naum-note-box\">\n    <span class=\"box-titre\">Pourquoi le faire<\/span>\n    Pour donner \u00e0 ces moteurs historiques une place dans une \u00e9chelle de calibration Elo :\n    les faire jouer des centaines de parties contre des r\u00e9f\u00e9rences, mesurer leur force r\u00e9elle,\n    et comparer les g\u00e9n\u00e9rations. Sans ces ponts, ils resteraient \u00e0 jamais prisonniers de leur\n    logiciel d'origine.\n  <\/div>\n\n  <h2>Deux ponts, seize moteurs<\/h2>\n  <p>\n    Les moteurs ChessBase ne sont pas tous b\u00e2tis pareil, d'o\u00f9 <strong>deux outils<\/strong> :\n  <\/p>\n  <ul>\n    <li><strong><code>eng2uci.py<\/code><\/strong> &mdash; pour les moteurs livr\u00e9s sous forme de\n      fichier <code>.eng<\/code> (Fritz, Deep Fritz, Junior, Shredder&nbsp;7, les Tiger, Hiarcs,\n      Nimzo). Il reconna\u00eet le moteur <strong>\u00e0 la taille exacte du fichier<\/strong>.<\/li>\n    <li><strong><code>shredder2uci.py<\/code><\/strong> &mdash; pour Shredder&nbsp;5.32 et\n      Shredder&nbsp;6, qui exposent directement une biblioth\u00e8que <code>.dll<\/code> et se pilotent\n      d'une tout autre fa\u00e7on.<\/li>\n  <\/ul>\n\n  <h2>Les moteurs pris en charge<\/h2>\n  <p>\n    Tous tournent d\u00e9sormais comme des moteurs UCI natifs &mdash; coups l\u00e9gaux, promotions,\n    roques, prise en passant, gestion du temps, et depuis ao\u00fbt 2026 <strong>d\u00e9tection des\n    r\u00e9p\u00e9titions et de la r\u00e8gle des cinquante coups<\/strong> (voir plus bas). La colonne\n    <em>taille<\/em> est essentielle : c'est elle qui sert d'identification.\n  <\/p>\n  <div class=\"tbl-wrap\">\n  <table>\n    <thead>\n      <tr><th>Moteur<\/th><th>Fichier<\/th><th class=\"taille\">Taille (octets)<\/th><th>\u00c9tat<\/th><th>\u00c0 savoir<\/th><\/tr>\n    <\/thead>\n    <tbody>\n      <tr><td><strong>Fritz 5.32<\/strong><\/td><td><code>.eng<\/code><\/td><td class=\"taille\">126&nbsp;976<\/td><td class=\"ok\">OK<\/td>\n        <td>Le doyen (1997). Format interne un peu diff\u00e9rent des suivants (cases \u00e9chang\u00e9es).<\/td><\/tr>\n      <tr><td><strong>Fritz 6<\/strong><\/td><td><code>.eng<\/code><\/td><td class=\"taille\">311&nbsp;296<\/td><td class=\"ok\">OK<\/td>\n        <td>La premi\u00e8re version mise au point, r\u00e9f\u00e9rence de tout le reste.<\/td><\/tr>\n      <tr><td><strong>Fritz 7<\/strong><\/td><td><code>.eng<\/code><\/td><td class=\"taille\">434&nbsp;176<\/td><td class=\"ok\">OK<\/td>\n        <td>\u00c9valuations et meilleur coup lus dans le canal de rapport (voir plus bas).<\/td><\/tr>\n      <tr><td><strong>Fritz 8<\/strong><\/td><td><code>.eng<\/code><\/td><td class=\"taille\">471&nbsp;040<\/td><td class=\"ok\">OK<\/td>\n        <td>M\u00eame base que la 7.<\/td><\/tr>\n      <tr><td><strong>Fritz 9<\/strong><\/td><td><code>.eng<\/code><\/td><td class=\"taille\">446&nbsp;464<\/td><td class=\"ok\">OK<\/td>\n        <td>R\u00e9clame <code>MSVCR71.dll<\/code> et v\u00e9rifie la pr\u00e9sence du CD &mdash; les deux sont g\u00e9r\u00e9s.<\/td><\/tr>\n      <tr><td><strong>Deep Fritz 8<\/strong><\/td><td><code>.eng<\/code> + <code>.dll<\/code><\/td><td class=\"taille\">487&nbsp;424<\/td><td class=\"ok\">OK<\/td>\n        <td>Le seul vrai multiprocesseur du lot. <strong>Les noms de fichiers doivent contenir des\n        espaces<\/strong> (<code>Deep Fritz 8.eng<\/code>) : la coquille se cherche elle-m\u00eame sous ce nom.<\/td><\/tr>\n      <tr><td><strong>Junior 7<\/strong><\/td><td><code>.eng<\/code> + <code>.dll<\/code><\/td><td class=\"taille\">212&nbsp;992<\/td><td class=\"ok\">OK<\/td>\n        <td>M\u00eame taille que la 8 : distingu\u00e9s automatiquement par une signature interne.<\/td><\/tr>\n      <tr><td><strong>Junior 8<\/strong><\/td><td><code>.eng<\/code> + <code>.dll<\/code><\/td><td class=\"taille\">212&nbsp;992<\/td><td class=\"ok\">OK<\/td>\n        <td>Ignore les limites de profondeur : \u00e0 piloter au temps, jamais en <code>go depth<\/code>.<\/td><\/tr>\n      <tr><td><strong>Hiarcs 7<\/strong><\/td><td><code>.eng<\/code> + <code>.dll<\/code><\/td><td class=\"taille\">155&nbsp;648<\/td><td class=\"ok\">OK<\/td>\n        <td>Protection par contr\u00f4le de volume, contourn\u00e9e.<\/td><\/tr>\n      <tr><td><strong>Hiarcs 8<\/strong><\/td><td><code>.eng<\/code> + <code>.dll<\/code><\/td><td class=\"taille\">245&nbsp;760<\/td><td class=\"ok\">OK<\/td>\n        <td>Trois contr\u00f4les successifs \u00e0 l'initialisation, tous neutralis\u00e9s.<\/td><\/tr>\n      <tr><td><strong>Nimzo 8<\/strong><\/td><td><code>.eng<\/code> + <code>.dll<\/code><\/td><td class=\"taille\">202&nbsp;240<\/td><td class=\"ok\">OK<\/td>\n        <td>Le fichier <code>Nimzo_8.cmp<\/code> n'est pas un ex\u00e9cutable mais la base de\n        combinaisons : il doit simplement rester \u00e0 c\u00f4t\u00e9 du <code>.eng<\/code>.<\/td><\/tr>\n      <tr><td><strong>Shredder 7<\/strong><\/td><td><code>.eng<\/code> + <code>.dll<\/code><\/td><td class=\"taille\">86&nbsp;016<\/td><td class=\"ok\">OK<\/td>\n        <td>Le <code>.eng<\/code> charge <code>Shredder7.dll<\/code>, qui v\u00e9rifie le CD &mdash; contourn\u00e9.<\/td><\/tr>\n      <tr><td><strong>Chess Tiger 15.0<\/strong><\/td><td><code>.eng<\/code> + <code>.dll<\/code><\/td><td class=\"taille\">114&nbsp;688<\/td><td>Jouable<\/td>\n        <td>Le plus fiable des deux Tiger, mais \u00e9cart\u00e9 de l'\u00e9chelle de calibration (voir encadr\u00e9).<\/td><\/tr>\n      <tr><td><strong>Gambit Tiger 2.0<\/strong><\/td><td><code>.eng<\/code> + <code>.dll<\/code><\/td><td class=\"taille\">98&nbsp;304<\/td><td>Instable<\/td>\n        <td>Se corrompt de lui-m\u00eame sur certaines positions ; \u00e9cart\u00e9 de la calibration.<\/td><\/tr>\n      <tr><td><strong>Shredder 5.32<\/strong><\/td><td><code>.dll<\/code><\/td><td class=\"taille\">&mdash;<\/td><td class=\"ok\">OK<\/td>\n        <td>Pilot\u00e9 par <code>shredder2uci.py<\/code> (pas par <code>eng2uci.py<\/code>).<\/td><\/tr>\n      <tr><td><strong>Shredder 6<\/strong><\/td><td><code>.dll<\/code><\/td><td class=\"taille\">&mdash;<\/td><td class=\"ok\">OK<\/td>\n        <td>Idem. Multi-thread d'origine, ramen\u00e9 \u00e0 un seul processeur pour des mesures comparables.<\/td><\/tr>\n    <\/tbody>\n  <\/table>\n  <\/div>\n\n  <div class=\"box naum-alert-box\">\n    <span class=\"box-titre\">Important : la taille fait foi<\/span>\n    <p style=\"margin:.4em 0 .8em;\">\n      Il a circul\u00e9 <strong>plusieurs \u00e9ditions d'un m\u00eame Fritz<\/strong> (versions localis\u00e9es,\n      mises \u00e0 jour, r\u00e9\u00e9ditions), qui n'ont pas toutes exactement la m\u00eame taille de fichier.\n      Le pont identifie le moteur <em>par sa taille<\/em> : si votre fichier ne fait pas le\n      compte \u00e0 l'octet pr\u00e8s, il s'arr\u00eatera avec un message du type\n      &laquo;&nbsp;taille non reconnue&nbsp;&raquo; suivi de la liste des tailles connues.\n    <\/p>\n    <p style=\"margin:0;\">\n      Ce n'est pas un \u00e9chec : cela signifie simplement que votre \u00e9dition n'a pas encore \u00e9t\u00e9\n      analys\u00e9e. Les adresses internes diff\u00e8rent d'une \u00e9dition \u00e0 l'autre, et les reprendre\n      demande une passe de r\u00e9tro-ing\u00e9nierie d\u00e9di\u00e9e. V\u00e9rifiez la taille exacte par un clic\n      droit &rarr; Propri\u00e9t\u00e9s sur le fichier <code>.eng<\/code>.\n    <\/p>\n  <\/div>\n\n  <h2>T\u00e9l\u00e9charger les ponts<\/h2>\n\n  <div class=\"dl-zone\">\n    <h3>eng2uci.py<\/h3>\n    <p>Le pont principal, en un seul fichier. G\u00e8re les quatorze moteurs \u00e0 fichier <code>.eng<\/code> :\n       les cinq Fritz, Deep Fritz 8, les deux Junior, les deux Hiarcs, Nimzo 8, Shredder&nbsp;7\n       et les deux Tiger.<\/p>\n    <button id=\"dl-eng\" class=\"dl-button\">&#x2193;&nbsp;&nbsp;T\u00e9l\u00e9charger eng2uci.py<\/button>\n    <div class=\"dl-sub\">script Python &middot; \u00e0 placer dans le dossier du moteur<\/div>\n  <\/div>\n\n  <div class=\"dl-zone\">\n    <h3>shredder2uci.py<\/h3>\n    <p>Le pont d\u00e9di\u00e9 \u00e0 Shredder&nbsp;5.32 et Shredder&nbsp;6, qui se pilotent directement par\n       leur biblioth\u00e8que <code>.dll<\/code>.<\/p>\n    <button id=\"dl-shr\" class=\"dl-button\">&#x2193;&nbsp;&nbsp;T\u00e9l\u00e9charger shredder2uci.py<\/button>\n    <div class=\"dl-sub\">script Python &middot; \u00e0 placer dans le dossier du moteur<\/div>\n  <\/div>\n\n  <div class=\"box naum-alert-box\">\n    <span class=\"box-titre\">Pr\u00e9requis indispensable<\/span>\n    Ces moteurs sont en <strong>32 bits<\/strong> : il faut donc un <strong>Python 32\n    bits<\/strong> (les versions 64 bits ne pourront pas les charger). Sous Windows,\n    installer Python puis v\u00e9rifier depuis un terminal : <code>py -3-32 --version<\/code> doit\n    r\u00e9pondre sans erreur.\n  <\/div>\n\n  <h3>Le dossier \u00e0 pr\u00e9parer<\/h3>\n  <p>Un dossier par moteur, contenant :<\/p>\n  <ul>\n    <li><code>eng2uci.py<\/code> &mdash; le pont ;<\/li>\n    <li><code>Chess32.dll<\/code> &mdash; le petit relais que les moteurs <code>.eng<\/code> r\u00e9clament ;<\/li>\n    <li>le fichier du moteur, par exemple <code>Fritz 6.eng<\/code> ;<\/li>\n    <li><strong>la DLL associ\u00e9e<\/strong> quand le moteur en a une : <code>Shredder7.dll<\/code>,\n      <code>Tiger_g.dll<\/code>, <code>Tiger15.dll<\/code>, <code>hiarcs7.dll<\/code>,\n      <code>Hiarcs8.dll<\/code>, <code>Jr_70.dll<\/code>, <code>Jr_80.dll<\/code>,\n      <code>Nimzo_8.dll<\/code>, <code>Deep Fritz 8.dll<\/code> ;<\/li>\n    <li>pour Fritz 9 uniquement : <code>MSVCR71.dll<\/code> ;<\/li>\n    <li>pour Nimzo 8 : <code>Nimzo_8.cmp<\/code>.<\/li>\n  <\/ul>\n  <p>Pour Shredder&nbsp;5.32 et 6, le dossier contient <code>shredder2uci.py<\/code> et la DLL du\n     moteur (pas de <code>.eng<\/code>, pas de <code>Chess32.dll<\/code>).<\/p>\n\n  <h2>Utilisation dans Banksia<\/h2>\n  <p>\n    Banksia est l'interface recommand\u00e9e : elle pilote les ponts sans configuration exotique.\n  <\/p>\n  <ol class=\"etapes\">\n    <li>Dans Banksia, ouvrir <strong>Engines<\/strong> puis <strong>Add<\/strong>.<\/li>\n    <li>Au champ <strong>Fichier du moteur<\/strong> (l'ex\u00e9cutable), indiquer le chemin du\n      <strong>Python 32 bits<\/strong>, typiquement :\n      <div class=\"champ\">C:\\Users\\...\\Python313-32\\python.exe<\/div><\/li>\n    <li>Au champ <strong>Dossier de travail<\/strong>, indiquer le dossier pr\u00e9par\u00e9.<\/li>\n    <li>Au champ <strong>Ligne de commandes<\/strong>, passer le pont suivi du nom du fichier\n      moteur, entre guillemets s'il contient une espace :\n      <div class=\"champ\">eng2uci.py <b>\"Fritz 6.eng\"<\/b><\/div>\n      &hellip; ou, pour Shredder 5.32 \/ 6 :\n      <div class=\"champ\">shredder2uci.py <b>shredder6.dll<\/b><\/div><\/li>\n    <li>Choisir le protocole <strong>UCI<\/strong>, puis valider. Banksia interroge le moteur :\n      il doit r\u00e9pondre son nom et son auteur.<\/li>\n    <li>R\u00e9gler la <strong>taille de hash<\/strong>, cr\u00e9er un tournoi, choisir la cadence et lancer.<\/li>\n  <\/ol>\n  <div class=\"box naum-coherence-box\">\n    <span class=\"box-titre\">V\u00e9rification rapide<\/span>\n    Avant de lancer un tournoi, un test en ligne de commande confirme tout :\n    <div class=\"champ\" style=\"border-left-color:#4e7a3b; margin-top:.8em;\">py -3-32 eng2uci.py \"Fritz 6.eng\"<br>uci<br>isready<br>position startpos<br>go depth 8<\/div>\n    Le moteur doit annoncer sa profondeur qui grimpe, puis un <code>bestmove<\/code>.\n    En ajoutant l'option <code>--calib<\/code> juste apr\u00e8s le nom du script, on obtient une trace\n    d\u00e9taill\u00e9e, utile en cas de probl\u00e8me.\n  <\/div>\n\n  <h2>Utilisation dans Arena<\/h2>\n  <p>\n    Arena fonctionne aussi. Comme il pr\u00e9f\u00e8re pointer vers un <strong>lanceur unique<\/strong>, le\n    plus simple est de cr\u00e9er \u00e0 c\u00f4t\u00e9 du moteur un petit fichier <code>lancer.bat<\/code> d'une ligne :\n  <\/p>\n  <div class=\"champ\">py -3-32 eng2uci.py \"Fritz 6.eng\"<\/div>\n  <ol class=\"etapes\">\n    <li>Menu <strong>Engines &rarr; Install New Engine<\/strong>.<\/li>\n    <li>S\u00e9lectionner le <code>lancer.bat<\/code> qu'on vient de cr\u00e9er.<\/li>\n    <li>Quand Arena demande le type de moteur, choisir <strong>UCI<\/strong>.<\/li>\n    <li>V\u00e9rifier que le <strong>dossier de travail<\/strong> pointe bien sur le dossier du moteur.<\/li>\n    <li>Le moteur appara\u00eet dans la liste, pr\u00eat \u00e0 jouer ou \u00e0 analyser.<\/li>\n  <\/ol>\n\n  <h2>Ce que ces moteurs ont dans le ventre<\/h2>\n  <p>\n    Un pont ne suffit pas : encore faut-il que le moteur joue <em>juste<\/em>. Plusieurs pi\u00e8ges\n    n'apparaissent qu'en partie r\u00e9elle, et valent d'\u00eatre signal\u00e9s \u00e0 qui voudrait refaire le chemin.\n  <\/p>\n  <h3>L'\u00e9valuation affich\u00e9e<\/h3>\n  <p>\n    Sur Fritz 6, 7 et 8, la valeur la plus visible en m\u00e9moire n'est pas l'\u00e9valuation : c'est un\n    score de tri interne, environ deux fois et demie trop optimiste. Le pont lit d\u00e9sormais le champ\n    correct, port\u00e9 par le canal de rapport du moteur, ce qui donne une \u00e9valuation conforme \u00e0 celle\n    du logiciel d'origine &mdash; y compris les annonces de mat.\n  <\/p>\n  <h3>Le meilleur coup, et l'affaire des promotions fant\u00f4mes<\/h3>\n  <p>\n    Ce m\u00eame tableau de tri servait aussi \u00e0 d\u00e9signer le coup \u00e0 jouer, en y prenant simplement la\n    meilleure valeur. Erreur : dans les positions o\u00f9 plusieurs coups atteignent la m\u00eame borne de mat,\n    le tableau les donne <em>\u00e0 \u00e9galit\u00e9<\/em>, et le choix retombait au hasard de l'ordre interne.\n    Cons\u00e9quence observ\u00e9e en partie : trois promotions <strong>en cavalier<\/strong> alors que le\n    moteur annon\u00e7ait le mat &mdash; dont une qui a transform\u00e9 une victoire en nulle par mat\u00e9riel\n    insuffisant. Le pont lit maintenant le coup <em>d\u00e9clar\u00e9<\/em> par le moteur dans son canal de\n    rapport ; le tableau ne sert plus que de secours.\n  <\/p>\n  <h3>Le codage des coups<\/h3>\n  <p>\n    Chez les Tiger, un bit signale une <em>prise<\/em> l\u00e0 o\u00f9 les autres moteurs signalent une\n    <em>promotion<\/em>. Mal interpr\u00e9t\u00e9, il produisait des coups impossibles &mdash; et autant de\n    parties perdues sur coup ill\u00e9gal. Le pont v\u00e9rifie d\u00e9sormais qu'un pion se trouve bien sur la\n    case de d\u00e9part avant de conclure \u00e0 une promotion.\n  <\/p>\n  <h3>La gestion du temps<\/h3>\n  <p>\n    Ces moteurs ne v\u00e9rifient l'ordre d'arr\u00eat qu'\u00e0 intervalles ; certains d\u00e9bordent de plusieurs\n    secondes. Le pont anticipe l'arr\u00eat, plafonne le temps par coup, et rend malgr\u00e9 tout un coup\n    si le moteur tarde. En cadence \u00e0 la pendule, il r\u00e9partit le temps selon le nombre de coups\n    restants annonc\u00e9 par l'interface.\n  <\/p>\n  <div class=\"box naum-alert-box\">\n    <span class=\"box-titre\">Le cas Gambit Tiger 2.0<\/span>\n    Ce moteur se corrompt de lui-m\u00eame sur certaines positions : il l'annonce d'ailleurs par un\n    message parlant d'un &laquo;&nbsp;probl\u00e8me de r\u00e9entrance&nbsp;&raquo; et conseillant de\n    red\u00e9marrer le programme. Le pont rattrape l'incident et rend le dernier coup connu au lieu\n    de perdre la partie, mais le moteur reste diminu\u00e9 jusqu'\u00e0 la fin de celle-ci. Les deux Tiger\n    sont donc jouables pour le plaisir, mais \u00e9cart\u00e9s de l'\u00e9chelle de calibration.\n  <\/div>\n\n  <hr>\n\n  <p class=\"eyebrow\">Deuxi\u00e8me partie &middot; calibration Elo<\/p>\n  <h2>Calibrer les moteurs adapt\u00e9s<\/h2>\n  <p>\n    Faire rejouer ces moteurs n'\u00e9tait que la premi\u00e8re moiti\u00e9 du travail. Un moteur peut jouer\n    des coups parfaitement l\u00e9gaux et pourtant ne plus jouer <em>\u00e0 son niveau<\/em>. La seule fa\u00e7on\n    de trancher est la calibration : plusieurs centaines de parties contre des adversaires dont la\n    cote est d\u00e9j\u00e0 \u00e9tablie, puis le calcul d'une performance Elo qu'on confronte \u00e0 celle de la\n    version d'origine.\n  <\/p>\n\n  <h3>La m\u00e9thode<\/h3>\n  <p>\n    Banksia reste l'interface conseill\u00e9e pour <em>utiliser<\/em> les moteurs au quotidien. Pour\n    <em>mesurer<\/em>, on lui a pr\u00e9f\u00e9r\u00e9 <strong>cutechess-cli<\/strong>, l'outil en ligne de commande\n    qui sert de r\u00e9f\u00e9rence aux grandes listes de calibration. Le protocole est identique pour tous :\n  <\/p>\n  <ul>\n    <li><strong>quinze secondes par coup<\/strong>, cadence fixe ;<\/li>\n    <li><strong>table de hachage de 512 Mo<\/strong> ;<\/li>\n    <li><strong>livre d'ouvertures Perfect 2023<\/strong> ;<\/li>\n    <li>une vingtaine de parties contre <strong>chacun de trois adversaires<\/strong> UCI de niveau\n      voisin, choisis dans notre \u00e9chelle maison (Ruffian, SOS, List, Shredder 10, Fruit&hellip;) ;<\/li>\n    <li>mesure \u00e0 un seul processeur pour tous, <strong>sauf Deep Fritz 8<\/strong>, seul vrai\n      moteur multiprocesseur du lot, mesur\u00e9 et publi\u00e9 en huit threads.<\/li>\n  <\/ul>\n  <p>\n    La performance est ancr\u00e9e sur les cotes connues des adversaires, par la formule habituelle :\n    perf = cote adverse + 400 &middot; log<sub>10<\/sub>(p \/ (1 &minus; p)).\n  <\/p>\n\n  <h3>Premi\u00e8re campagne : un verdict s\u00e9v\u00e8re<\/h3>\n  <p>\n    Les premi\u00e8res mesures, faites au printemps 2026, donnaient un tableau d\u00e9courageant. Tous les\n    moteurs adapt\u00e9s perdaient de cent \u00e0 deux cents points par rapport \u00e0 leur version native, et la\n    famille Fritz s'effondrait au point d'en para\u00eetre inexploitable. La conclusion publi\u00e9e alors\n    \u00e9tait que cet \u00e9cart constituait une <em>signature du pont<\/em> : quelque chose de\n    l'environnement d'\u00e9poque ne serait pas reproductible, et il faudrait s'en accommoder.\n  <\/p>\n  <div class=\"tbl-wrap\">\n  <table>\n    <thead><tr><th>Moteur adapt\u00e9<\/th><th class=\"taille\">Perf. premi\u00e8re campagne<\/th><th class=\"taille\">Cote native<\/th><th class=\"taille\">\u00c9cart<\/th><\/tr><\/thead>\n    <tbody>\n      <tr><td>Deep Fritz 8 (py)<\/td><td class=\"taille\">2776<\/td><td class=\"taille\">&mdash;<\/td><td class=\"taille\">&mdash;<\/td><\/tr>\n      <tr><td>Shredder 6 (py)<\/td><td class=\"taille\">2705<\/td><td class=\"taille\">2814<\/td><td class=\"taille\">&minus;109<\/td><\/tr>\n      <tr><td>Hiarcs 8 (py)<\/td><td class=\"taille\">2599<\/td><td class=\"taille\">2768<\/td><td class=\"taille\">&minus;169<\/td><\/tr>\n      <tr><td>Junior 8 (py)<\/td><td class=\"taille\">2588<\/td><td class=\"taille\">2758<\/td><td class=\"taille\">&minus;170<\/td><\/tr>\n      <tr><td>Junior 7 (py)<\/td><td class=\"taille\">2500<\/td><td class=\"taille\">2717<\/td><td class=\"taille\">&minus;217<\/td><\/tr>\n      <tr><td>Hiarcs 7 (py)<\/td><td class=\"taille\">2510<\/td><td class=\"taille\">2617<\/td><td class=\"taille\">&minus;107<\/td><\/tr>\n      <tr><td>Nimzo 8 (py)<\/td><td class=\"taille\">2450<\/td><td class=\"taille\">2629<\/td><td class=\"taille\">&minus;179<\/td><\/tr>\n      <tr><td>Fritz 8 (py)<\/td><td class=\"taille\">2707<\/td><td class=\"taille\">2804<\/td><td class=\"taille\">&minus;97<\/td><\/tr>\n    <\/tbody>\n  <\/table>\n  <\/div>\n  <p style=\"font-size:.88rem; color:var(--gris);\">\n    R\u00e9sultats de la premi\u00e8re campagne, aujourd'hui p\u00e9rim\u00e9s : ils mesuraient un d\u00e9faut du pont, pas la force des moteurs. Conserv\u00e9s ici comme rep\u00e8re de d\u00e9part.\n  <\/p>\n  <p>\n    Un d\u00e9tail aurait d\u00fb mettre la puce \u00e0 l'oreille : l'\u00e9cart \u00e9tait <em>trop constant<\/em> d'un\n    moteur \u00e0 l'autre, et trop indiff\u00e9rent \u00e0 leur famille. Une faiblesse de recherche ne se\n    distribue pas si r\u00e9guli\u00e8rement. Il ne s'agissait pas d'un manque de force, mais d'un manque\n    d'<em>information<\/em>.\n  <\/p>\n\n  <h3>Le diagnostic : l'historique manquant<\/h3>\n  <p>\n    En reprenant non plus les scores mais les <strong>parties elles-m\u00eames<\/strong>, l'anomalie a\n    saut\u00e9 aux yeux. Sur les vingt-trois premi\u00e8res parties de Hiarcs 8, <strong>les onze nulles\n    \u00e9taient toutes des triples r\u00e9p\u00e9titions<\/strong>, et dans au moins cinq d'entre elles le moteur\n    r\u00e9p\u00e9tait alors qu'il \u00e9tait <em>gagnant<\/em> &mdash; l'adversaire lui-m\u00eame s'\u00e9valuant entre\n    &minus;1,2 et &minus;3,6. Dans une partie, Hiarcs donnait lui-m\u00eame les \u00e9checs perp\u00e9tuels qui\n    lui co\u00fbtaient le point, avec une tour et un fou d'avance.\n  <\/p>\n  <p>\n    Le d\u00e9sassemblage a livr\u00e9 l'explication. Les coquilles ChessBase poss\u00e8dent\n    <strong>depuis toujours un m\u00e9canisme de rejeu de la partie<\/strong> : l'interface d'\u00e9poque leur\n    transmettait, \u00e0 chaque coup, la liste des coups d\u00e9j\u00e0 jou\u00e9s, que le moteur rejouait en interne\n    pour reconstituer son propre enregistrement. Ce m\u00e9canisme se trouve \u00e0 quelques octets fixes de\n    la structure de param\u00e8tres, et il est pr\u00e9sent dans toutes les coquilles examin\u00e9es &mdash; les\n    six Fritz, les deux Hiarcs, les deux Junior, Nimzo.\n  <\/p>\n  <div class=\"box naum-alert-box\">\n    <span class=\"box-titre\">La cause, en une phrase<\/span>\n    Le pont ne remplissait jamais cette liste. Les moteurs jouaient donc <strong>sans aucune\n    m\u00e9moire de la partie en cours<\/strong> : aveugles \u00e0 la triple r\u00e9p\u00e9tition, aveugles \u00e0 la r\u00e8gle\n    des cinquante coups. Ils bradaient des positions gagnantes en r\u00e9p\u00e9tant, sans savoir qu'ils\n    r\u00e9p\u00e9taient.\n  <\/div>\n\n  <h3>Les correctifs<\/h3>\n  <ol class=\"etapes\">\n    <li><strong>Rejeu de l'historique<\/strong> sur les onze moteurs \u00e0 coquille ChessBase, selon\n      deux variantes : les moteurs monolithiques (les Fritz) rejouent la liste eux-m\u00eames, les\n      moteurs \u00e0 DLL s\u00e9par\u00e9e (Hiarcs, Junior, Nimzo) la font rejouer \u00e0 leur biblioth\u00e8que.<\/li>\n    <li><strong>Rejeu limit\u00e9 \u00e0 la fin de partie utile<\/strong> : on ne retransmet que les coups\n      post\u00e9rieurs \u00e0 la derni\u00e8re prise ou au dernier coup de pion. C'est math\u00e9matiquement suffisant\n      &mdash; aucune position ne peut r\u00e9p\u00e9ter quelque chose d'ant\u00e9rieur \u00e0 un coup irr\u00e9versible\n      &mdash; et cela garde les compteurs internes du moteur dans leur domaine de validit\u00e9.<\/li>\n    <li><strong>Meilleur coup et \u00e9valuation<\/strong> lus dans le canal de rapport pour Fritz 6, 7\n      et 8 : fin des promotions fant\u00f4mes, et scores enfin conformes.<\/li>\n    <li><strong>Garde-fous assainis.<\/strong> Un filet de s\u00e9curit\u00e9 destin\u00e9 \u00e0 rattraper d'\u00e9ventuels\n      refus du moteur se d\u00e9clenchait en r\u00e9alit\u00e9 \u00e0 tort, et <em>retirait l'historique<\/em> qu'il\n      \u00e9tait cens\u00e9 prot\u00e9ger &mdash; exactement dans les finales o\u00f9 il servait. Il a fallu cinq\n      exp\u00e9riences successives pour \u00e9tablir que les centaines d'incidents journalis\u00e9s \u00e9taient de\n      fausses alertes : le moteur n'avait jamais rien refus\u00e9.<\/li>\n  <\/ol>\n\n  <h3>Deuxi\u00e8me campagne : les premiers r\u00e9sultats<\/h3>\n  <p>\n    La re-calibration compl\u00e8te est en cours. Le premier moteur men\u00e9 jusqu'au bout de la nouvelle\n    proc\u00e9dure donne la mesure de ce qui \u00e9tait en jeu.\n  <\/p>\n  <div class=\"tbl-wrap\">\n  <table>\n    <thead><tr><th>Moteur<\/th><th class=\"taille\">Avant<\/th><th class=\"taille\">Apr\u00e8s correction<\/th><th class=\"taille\">Cote native<\/th><th class=\"taille\">\u00c9cart au natif<\/th><th class=\"taille\">Parties<\/th><\/tr><\/thead>\n    <tbody>\n      <tr><td><strong>Hiarcs 8 (py)<\/strong><\/td><td class=\"taille\">2599<\/td><td class=\"taille\"><strong>2744 &plusmn; 36<\/strong><\/td><td class=\"taille\">2768<\/td><td class=\"taille ok\">&minus;24 (n.&nbsp;s.)<\/td><td class=\"taille\">94<\/td><\/tr>\n      <tr><td>Fritz 8 (py)<\/td><td class=\"taille\">2707<\/td><td class=\"taille\">2769 &plusmn; 76<\/td><td class=\"taille\">2804<\/td><td class=\"taille\">&minus;35 (n.&nbsp;s.)<\/td><td class=\"taille\">22<\/td><\/tr>\n    <\/tbody>\n  <\/table>\n  <\/div>\n  <p style=\"font-size:.88rem; color:var(--gris);\">\n    &laquo;&nbsp;n.&nbsp;s.&nbsp;&raquo; : \u00e9cart non significatif, inf\u00e9rieur \u00e0 l'incertitude de mesure. Fritz 8 est un r\u00e9sultat provisoire, obtenu sur une seconde machine dont le facteur de compensation reste \u00e0 valider.\n  <\/p>\n  <p>\n    <strong>Cent quarante-cinq points r\u00e9cup\u00e9r\u00e9s sur Hiarcs 8<\/strong>, et un \u00e9cart r\u00e9siduel avec la\n    version native qui n'est plus distinguable de z\u00e9ro. La qualit\u00e9 des parties a chang\u00e9 de nature\n    autant que le score : les onze nulles par r\u00e9p\u00e9tition du d\u00e9part sont devenues onze nulles\n    r\u00e9parties sur quatre causes r\u00e9glementaires diff\u00e9rentes &mdash; r\u00e9p\u00e9tition, cinquante coups,\n    mat\u00e9riel insuffisant, pat &mdash; toutes \u00e0 \u00e9galit\u00e9 r\u00e9elle. Le moteur va d\u00e9sormais au bout des\n    finales.\n  <\/p>\n  <div class=\"box naum-coherence-box\">\n    <span class=\"box-titre\">Et les Fritz classiques ?<\/span>\n    La conclusion pr\u00e9c\u00e9dente &mdash; &laquo;&nbsp;les Fritz de la 5.32 \u00e0 la 9 ne sont pas\n    exploitables pour une mesure Elo&nbsp;&raquo; &mdash; <strong>\u00e9tait fausse<\/strong>. Ils\n    souffraient du m\u00eame mal que les autres, aggrav\u00e9 par le bug du meilleur coup. Les cinq passent\n    aujourd'hui les tests de validation, et la premi\u00e8re mesure de Fritz 8 le place dans l'intervalle\n    de sa cote native. Leur re-calibration compl\u00e8te est en file d'attente.\n  <\/div>\n\n  <div class=\"box naum-alert-box\">\n    <span class=\"box-titre\">La machine est un instrument de mesure<\/span>\n    <p style=\"margin:.4em 0 .8em;\">\n      Une seconde le\u00e7on, co\u00fbteuse, m\u00e9rite d'\u00eatre partag\u00e9e. Faire tourner plusieurs tournois en\n      m\u00eame temps sur une machine \u00e0 seize c\u0153urs <strong>invalide toutes les mesures<\/strong>, et pas\n      seulement en les ralentissant. La perte n'est pas la m\u00eame pour tout le monde : un moteur\n      adapt\u00e9 paye deux fois (sa recherche <em>et<\/em> la couche Python), un moteur multiprocesseur\n      vole les c\u0153urs de ses adversaires, et les processeurs modernes \u00e0 c\u0153urs h\u00e9t\u00e9rog\u00e8nes ajoutent\n      leur propre loterie. On a vu un m\u00eame moteur passer de 75&nbsp;% \u00e0 40&nbsp;% en cours de\n      tournoi, simplement parce que d'autres calculs avaient d\u00e9marr\u00e9 \u00e0 c\u00f4t\u00e9.\n    <\/p>\n    <p style=\"margin:0;\">\n      La r\u00e8gle est donc devenue absolue : <strong>un seul tournoi \u00e0 la fois, machine d\u00e9di\u00e9e<\/strong>.\n      Les mesures faites autrement ont \u00e9t\u00e9 jet\u00e9es, y compris quand elles \u00e9taient flatteuses.\n    <\/p>\n  <\/div>\n\n  <h3>Ce qui reste \u00e0 faire<\/h3>\n  <ul>\n    <li>Terminer la calibration de Hiarcs 8 (120 parties), puis re-calibrer dans l'ordre\n      Deep Fritz 8, les cinq Fritz, Junior 7 et 8, Nimzo 8 et Hiarcs 7.<\/li>\n    <li>Pour Deep Fritz 8, un triptyque en conditions strictement identiques : version native,\n      version adapt\u00e9e sans historique, version adapt\u00e9e avec historique. C'est la comparaison la\n      plus directe qu'on puisse faire entre un moteur et son propre pont.<\/li>\n    <li>Les trois Shredder n'ont pas encore d'historique : leur structure interne est diff\u00e9rente et\n      demande sa propre passe de r\u00e9tro-ing\u00e9nierie. C'est le prochain gisement.<\/li>\n    <li>R\u00e9tablir l'\u00e9mission des \u00e9valuations dans le mode de gestion du temps interne, o\u00f9 le moteur\n      reste muet sur les recherches courtes &mdash; sans effet sur la force, mais on y perd un\n      indicateur utile.<\/li>\n    <li>Valider le facteur de compensation d'une seconde machine, en y refaisant tourner un moteur\n      d\u00e9j\u00e0 calibr\u00e9 : c'est la seule fa\u00e7on honn\u00eate de doubler la cadence de mesure.<\/li>\n    <li>Explorer Fritz 13 SE, d'une toute autre g\u00e9n\u00e9ration : plus de table de fonctions, un\n      protocole \u00e0 commandes s\u00e9rialis\u00e9es et un m\u00e9canisme de signature. Chantier ouvert, sans\n      promesse.<\/li>\n  <\/ul>\n\n  <div class=\"box naum-coherence-box\">\n    <span class=\"box-titre\">Ce qu'on en fait dans le classement<\/span>\n    Les moteurs adapt\u00e9s gardent leur place dans la liste sous leur cote <em>r\u00e9ellement mesur\u00e9e<\/em>,\n    jamais celle de leur pass\u00e9 natif, et portent une marque distinctive (couleur et mention\n    &laquo;&nbsp;py&nbsp;&raquo;) pour qu'on ne les confonde jamais avec un moteur UCI d'origine.\n    Les entr\u00e9es issues de la premi\u00e8re campagne sont progressivement remplac\u00e9es \u00e0 mesure que la\n    seconde avance ; d'ici l\u00e0, elles sous-estiment leurs moteurs d'environ cent cinquante points.\n  <\/div>\n\n  <hr>\n  <p>\n    La le\u00e7on de la premi\u00e8re partie tenait en une phrase : un moteur ne se juge qu'en partie r\u00e9elle.\n    La seconde en ajoute deux. Un moteur ne se calibre qu'en plusieurs centaines de parties &mdash;\n    et quand l'\u00e9cart mesur\u00e9 est trop r\u00e9gulier pour \u00eatre honn\u00eate, ce n'est pas le moteur qu'il faut\n    interroger, mais l'outil qui le mesure. Il aura fallu regarder les parties, et non les\n    tableaux, pour s'apercevoir que ces vieux moteurs ne perdaient pas leur force : on leur avait\n    simplement retir\u00e9 la m\u00e9moire de ce qu'ils venaient de jouer.\n  <\/p>\n\n  <p class=\"sig\">chess.lumn.eu &middot; laboratoire de calibration<\/p>\n\n<\/article>\n\n<script>\n  (function(){\n    function telecharger(b64, nom){\n      var bin=atob(b64), arr=new Uint8Array(bin.length);\n      for(var i=0;i<bin.length;i++) arr[i]=bin.charCodeAt(i);\n      var blob=new Blob([arr],{type:'text\/x-python'});\n      var url=URL.createObjectURL(blob), a=document.createElement('a');\n      a.href=url; a.download=nom;\n      document.body.appendChild(a); a.click(); document.body.removeChild(a);\n      URL.revokeObjectURL(url);\n    }\n    var ENG=\"IyEvdXNyL2Jpbi9lbnYgcHl0aG9uMwojIC0qLSBjb2Rpbmc6IHV0Zi04IC0qLQoiIiIKZW5nMnVjaS5weSAgLS0gIHBhc3NlcmVsbGUgVUNJIHBvdXIgbGVzIG1vdGV1cnMgRnJpdHogLmVuZyAoQ2hlc3NCYXNlIG5hdGlmKQogICAgICAgICAgICAgICBHZXJlIEZyaXR6IDUuMzIgLyA2IC8gNyAvIDgsIGF1dG8tZGV0ZWN0ZXMgcGFyIGxhIHRhaWxsZSBkdSAuZW5nLgoKTUVNRSBGQU1JTExFICh2ZXJpZmllIHBhciBkZXNhc3NlbWJsYWdlIGRlcyA0IGJpbmFpcmVzKSA6CiAgLSBjYWxsYmFjayBob3RlIHVuaXF1ZSBDaGVzczMyLmRsbDo6RnVuYzMgKGxlIHN0dWIgZm91cm5pIGxlIHJlc291dCkgOwogIC0gaW5pdCBFbmcxKGN0eDAuLmN0eDQsIGhhc2hLQikgKyBFbmcxNSA7IHJlY2hlcmNoZSBFbmc5KHNwYXJhbXMpIGJsb3F1YW50ZSA7CiAgLSBtZXNzYWdlcyAweDE1OD1wcm9mb25kZXVyLCAweDE1ND1yYXBwb3J0IHNjb3JlL1BWLCAweDE1Ni8weDE1Nz1wZXJpb2RpcXVlcy4KCkVOVFJFRSBVTklWRVJTRUxMRSAob2Zmc2V0cyBpZGVudGlxdWVzIHN1ciBsZXMgNCA7IGNvZGVzIGRlIHJvcXVlIHZlcmlmaWVzKSA6CiAgYm9hcmQgID0gc3BhcmFtc1sweDE4ICsgZmljaGllcio4ICsgcmFuZ2VlXSAgKGZpbGUtbWFqb3IgOiBhMT0wLGUxPTMyLGU4PTM5LGg4PTYzKQogIDB4NTg9ZmxhZygwKSAgMHg1OT10cmFpdCgwPWJsYW5jKSAgMHg1QT1lbi1wYXNzYW50KDApICAweDVCPXJvcXVlcyhiaXRzIDEvMi80LzgpCiAgY29kZXMgYnJ1dHMgOiBibGFuY3MgUj0xIEQ9MiBDPTMgRj00IFQ9NSBQPTYgOyBub2lycyA9ICs4CiAgcGFyYW1zIDogMHg4NjI9bW9kZSgyPXByb2ZvbmRldXIgZml4ZSkgIDB4ODVFPXByb2ZvbmRldXIoaXRlcmF0aW9uKSAgMHg4NzQ9Y2FwKDw9NDcpCiAgc29ydGllIDogY2FzZXMgZmlsZS1tYWpvciwgcHJvbW8gMj1DIDM9RiA0PVQgNT1ELgoKUFJPUFJFIEEgQ0hBUVVFIEJVSUxEIChhZHJlc3NlcyByZWxhdGl2ZXMgYSBsYSBiYXNlLCBleHRyYWl0ZXMgc3RhdGlxdWVtZW50KSA6CiAgTk1PVkVTIC8gU0NPUkVTIC8gTU9WRUJBU0UgIC0+IG1laWxsZXVyIGNvdXAgPSBhcmdtYXggZGVzIHNjb3JlcyByYWNpbmUKICBQViAgICAgICAtPiBsaWduZSBwcmluY2lwYWxlIChqdXNxdSdhIGZyb209PXRvKQogIE5PREUgICAgIC0+IGNvbXB0ZXVyIGRlIG5vZXVkcyA2NCBiaXRzIChiYXMgOyBoYXV0ID0gKzQpCiAgQ1AgICAgICAgLT4gY2hlY2tzIGNvcHktcHJvdGVjdGlvbiBkJ0VuZzEgYSBuZXV0cmFsaXNlciAoamUgMHg3NCAtPiBqbXAgMHhFQikKCkZyaXR6IDUuMzIgOiBzYSByZWNoZXJjaGUgaW50ZXJuZSBkaWZmZXJlIChwYXMgZGUgdGFibGVhdSBkZSBzY29yZXMgZWJ4KjQpIDsKICBsZSBtZWlsbGV1ciBjb3VwIGVzdCBkb25jIGx1IHZpYSBQVlswXSAocmVwbGkpLCBzY29yZSBub24gZGlzcG9uaWJsZSAoY3AgMCkuCiAgLT4gbGUgcGx1cyBhIHZhbGlkZXIgZGVzIHF1YXRyZS4KClRPVVQgY2VjaSBlc3QgZGVyaXZlIGRlIGwnYW5hbHlzZSBzdGF0aXF1ZSA6IGNoYXF1ZSBtb3RldXIgZGVtYW5kZSB1bmUgcGFzc2UKLS1jYWxpYiBkZSB2YWxpZGF0aW9uIChjb21tZSBGcml0eiA2IGwnYSBkZW1hbmRlKS4gU3VyIHN0YXJ0cG9zLCAiZ28gZGVwdGggNiIKZG9pdCBzb3J0aXIgdW4gY291cCBMRUdBTCBldCB1biBzY29yZSBwbGF1c2libGUuCgpVU0FHRQogIHB5IC0zLTMyIGVuZzJ1Y2kucHkgIkZyaXR6IDcuZW5nIgogIHB5IC0zLTMyIGVuZzJ1Y2kucHkgLS1jYWxpYiAiRnJpdHogOC5lbmciCiIiIgoKaW1wb3J0IHN5cywgb3MsIGN0eXBlcywgdGhyZWFkaW5nLCBzdHJ1Y3QsIHRpbWUKZnJvbSBjdHlwZXMgaW1wb3J0IHdpbnR5cGVzCgojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CiMgIENvbmZpZyBwYXIgbW90ZXVyIChjbGUgPSB0YWlsbGUgZHUgZmljaGllciAuZW5nIGVuIG9jdGV0cykuIFJWQSA9IGFkcmVzc2UKIyAgYWJzb2x1ZSAtIDB4MTAwMDAwMDAuIGNwID0gbGlzdGUgZGVzIFJWQSBkZSAnamUnIGEgcGFzc2VyIGVuICdqbXAnLgojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CkVOR0lORVMgPSB7CiAgICAxMjY5NzY6IGRpY3QobmFtZT0iRnJpdHogNS4zMiIsIG5tb3Zlcz0weDE4MDhjLCBzY29yZXM9MHhlOWE4LCBtb3ZlYmFzZT0weDE4Y2MwLAogICAgICAgICAgICAgICAgIHB2PTB4MTBjYzAsIG5vZGU9MHhkNzYwLCBub2RlX2FjY3VtdWxhdGVzPVRydWUsCiAgICAgICAgICAgICAgICAgc3dhcF9zcT1UcnVlLCBtb3ZlYmFzZV9kaXJlY3Q9VHJ1ZSwgY3A9WzB4MmIzNV0sCiAgICAgICAgICAgICAgICAgIyBoaXN0ICdpbmxpbmUnIDE5LzA4IDogYm91Y2xlIEAweDI2ODUgdmVyaWZpZWUgLS0gZWxsZSBzd2FwcGUgRUxMRS1NRU1FIGxlcwogICAgICAgICAgICAgICAgICMgY2FzZXMgKFNQIGZpbGUtbWFqb3IgLT4gaW50ZXJuZSByYW5rLW1ham9yKSwgZmxhZ3MgU1AgaWRlbnRpcXVlcyBhIGxhIGZhbWlsbGUKICAgICAgICAgICAgICAgICAjIChuaWJibGUgYmFzPWUucC4sIDB4MjA9cm9xdWUsIDB4NDA9cHJvbW8gY29kZXMgUkFXIDIuLjUpLiBXcml0ZXIgaW5jaGFuZ2UuCiAgICAgICAgICAgICAgICAgaGlzdF9yZXBsYXk9J2lubGluZScpLAogICAgMzExMjk2OiBkaWN0KG5hbWU9IkZyaXR6IDYiLCAgICBubW92ZXM9MHgyY2I4MCwgc2NvcmVzPTB4MmNiODgsIG1vdmViYXNlPTB4MmVjYzQsIHNjb3JlMTU0PVRydWUsCiAgICAgICAgICAgICAgICAgbW92ZTE1ND1UcnVlLCBwdj0weDMxMDljLCBub2RlPTB4MmE0MTAsIGNwPVsweDM0YTcsIDB4MzRkMV0sCiAgICAgICAgICAgICAgICAgaGlzdF9yZXBsYXk9J2lubGluZScpLCAgICMgYm91Y2xlIEAweDJmMDggdmVyaWZpZWUgMTkvMDggKHByb3RvY29sZSBTUCBpZGVudGlxdWUpCiAgICA0MzQxNzY6IGRpY3QobmFtZT0iRnJpdHogNyIsICAgIG5tb3Zlcz0weDMxNTRjLCBzY29yZXM9MHgzMTU1MCwgbW92ZWJhc2U9MHgzNjFhMCwgc2NvcmUxNTQ9VHJ1ZSwKICAgICAgICAgICAgICAgICBtb3ZlMTU0PVRydWUsIHB2PTB4MzYxYWMsIG5vZGU9MHgyZTg4MCwgY3A9WzB4NDc2NSwgMHg0NzkwLCAweDQ3YmJdLAogICAgICAgICAgICAgICAgIGhpc3RfcmVwbGF5PSdpbmxpbmUnKSwgICAjIGJvdWNsZSBAMHg0MGYwIHZlcmlmaWVlIDE5LzA4IChyb3F1ZSB2aWEgcmVnaXN0cmUgYmw9MHgyMCkKICAgICMgRnJpdHogOCA6IG1vdmUxNTQvc2NvcmUxNTQgYWN0aXZlcyBsZSAxOS8wOCAoZW5xdWV0ZSAiPUMiKSAtLSByYXBwb3J0IDB4MTU0IGF1IGZvcm1hdCBKdW5pb3IsCiAgICAjIGV0YWJsaSBwYXIgbGEgc29uZGUgcnVudGltZSBERjggKG1lbWUgbGlnbmVlKSA6IGNvdXAgY3R4KzB4NWMsIHNjb3JlIGN0eCsweDI3NjguIEwnYXJnbWF4IHN1cgogICAgIyAnc2NvcmVzJyAodmFsZXVycyBkJ29yZG9ubmFuY2VtZW50KSByZXN0ZSBlbiBSRVBMSSBzaSBhdWN1biByYXBwb3J0IChyZWNoZXJjaGUgdHJpdmlhbGUpLgogICAgNDcxMDQwOiBkaWN0KG5hbWU9IkZyaXR6IDgiLCAgICBubW92ZXM9MHgzMmI1NCwgc2NvcmVzPTB4MzJiNTgsIG1vdmViYXNlPTB4M2IzZTAsIHNjb3JlMTU0PVRydWUsCiAgICAgICAgICAgICAgICAgbW92ZTE1ND1UcnVlLCBwdj0weDNiM2VjLCBub2RlPTB4MmZhMTAsIGNwPVsweDQ5NTMsIDB4NDk3ZiwgMHg0OWFiLCAweDRhMjIsIDB4NGI0Nl0sCiAgICAgICAgICAgICAgICAgIyBoaXN0ICdpbmxpbmUnIDE5LzA4IDogYm91Y2xlIGRlIHJlamV1IEAweDQxY2EgdmVyaWZpZWUgKGVudHJlZXMgMHg1YywgY29tcHRlIDB4ODVjLAogICAgICAgICAgICAgICAgICMgdGFibGUgcHJvbW8gQDB4NDI1MCBpZGVudGlxdWUgYSBGcml0eiA5LCByb3F1ZSAweDIwLCBlLnAuIG5pYmJsZSkuIFBBUyBkZSB2YWxpZGF0aW9uCiAgICAgICAgICAgICAgICAgIyBpbnRlcm5lIGRlcyBjb3VwcyAtPiBmbGFncyBleGFjdHMgb2JsaWdhdG9pcmVzICh2b2lyIGhpc3RvcnlfdG9fZW5naW5lKS4KICAgICAgICAgICAgICAgICBoaXN0X3JlcGxheT0naW5saW5lJyksCiAgICA0NDY0NjQ6IGRpY3QobmFtZT0iRnJpdHogOSIsICAgIG5tb3Zlcz1Ob25lLCBzY29yZXM9Tm9uZSwgbW92ZWJhc2U9Tm9uZSwgcHY9MHg2YzE3MCwKICAgICAgICAgICAgICAgICBiZXN0bW92ZV9kd29yZD0weDg0MzgwLCBzY29yZV9kd29yZD0weDcxZTU0LCBub2RlPTB4NmYzZjAsIHdwZXJzcGVjdGl2ZT1UcnVlLAogICAgICAgICAgICAgICAgIGNwPVsoMHgxMzk0MiwgYiJceDkwIio2KSwgKDB4MTM5NWQsIGIiXHg5MCIqNiksICgweDEzOTkyLCBiIlx4OTAiKjYpLAogICAgICAgICAgICAgICAgICAgICAoMHgxMzlmZCwgYiJceDkwIio2KSwgKDB4MTNhMTUsIGIiXHg5MCIqNiksIDB4MTNiODUsCiAgICAgICAgICAgICAgICAgICAgICgweDEzYzY5LCBiIlx4QjhceDAxXHgwMFx4MDBceDAwIildLCAgICMgY2hlY2sgQ0QgLT4gIkNEIHByZXNlbnQiIChtb3YgZWF4LDEpCiAgICAgICAgICAgICAgICAgIyBoaXN0ICdpbmxpbmUnIDE5LzA4IDogYm91Y2xlIGRlIHJlamV1IEAweDEzNmIwIHZlcmlmaWVlIChtZW1lIHN0cnVjdHVyZSBxdWUgRnJpdHogOCkuCiAgICAgICAgICAgICAgICAgaGlzdF9yZXBsYXk9J2lubGluZScpLAogICAgIyBTaHJlZGRlciA3IChTaHJlZGRlcjcuZW5nLCA4NjAxNiBvKSA6IGNvcXVpbGxlIENoZXNzQmFzZSBFbmcqL0Z1bmMzIHF1aSBjaGFyZ2UgbGUgbW90ZXVyIGEKICAgICMgbCdleGVjdXRpb24gKExvYWRMaWJyYXJ5KSB2aWEgc2EgUFJPUFJFIHNlcXVlbmNlIGQnaW5pdCB2ZW5kZXVyIC0+IGNvbnRvdXJuZSBsZSBtdXIgZGUKICAgICMgdGhyZWFkaW5nIGR1IHBpbG90YWdlIG5hdGlmIGRlIFNocmVkZGVyNy5kbGwuIENQIGRhbnMgRW5nMSA6IFFVQVRSRSBwb3J0ZXMgY2hlY2tzdW0gcXVpCiAgICAjIGNvbnZlcmdlbnQgdmVycyAnbW92IGVheCwzJyAtPiBqbmUoZmFpbCkgTk9QZXMgQCAweDMyY2UvMHgzMzIxLzB4MzNjMiArIGplKHN1Y2NlcykgZm9yY2UgQCAweDM0ODMuCiAgICAjIDJlIGV0YWdlIGRlIHByb3RlY3Rpb24gZGFucyBTaHJlZGRlcjcuZGxsIChjaGFyZ2VlIHBhciBsZSAuZW5nKSA6IGNvbnRyb2xlIGR1IENELVJPTSBkJ29yaWdpbmUKICAgICMgKE1lc3NhZ2VCb3ggJ05vIENELVJPTSBmb3VuZCcpLiBGb25jdGlvbiBDRCAweDQwYzAgOiAxPXRyb3V2ZS8wPWFic2VudC4gQVRURU5USU9OIDogY2V0dGUgZm9uY3Rpb24KICAgICMgZmFpdCBBVVNTSSBkZSBsJ2luaXQgZXNzZW50aWVsbGUgYXUgbW90ZXVyIChjYWxsIDB4NDBhMCwgYm91Y2xlIGNoZWNrc3VtLCBjYWxsIDB4NTE3MCkgQVZBTlQgbGUgc2NhbgogICAgIyAtPiBsYSBjb3VydC1jaXJjdWl0ZXIgZGVzIGwnZW50cmVlIGZhaXNhaXQgY3Jhc2hlciBFbmc5IChkZXJlZiBudWwgZGFucyBsYSByZWNoZXJjaGUpLiBPbiBsYSBsYWlzc2UKICAgICMgZG9uYyBleGVjdXRlciBzb24gc2V0dXAgZXQgb24gUkVESVJJR0UganVzdGUgYXZhbnQgbGUgc2NhbiAoMHg0MTMzKSB2ZXJzIGxlIHJldG91ciAndHJvdXZlJyAweDQ3ZGYKICAgICMgKG1vdiBlYXgsMSArIGVwaWxvZ3VlKS4gJ3ByZWxvYWQnZWUgY2FyIGNoYXJnZWUgcGFyIGxlIC5lbmcuCiAgICAjIFBST1RPQ09MRSBGdW5jMyA9IE1FTUUgZmFtaWxsZSBDaGVzc0Jhc2UgcXVlIEp1bmlvci4gTGUgcmFwcG9ydCAweDE1NCBlc3QgY29uc3RydWl0IEEgTCdJREVOVElRVUUKICAgICMgZGUgSnVuaW9yIChzY29yZSBvYmorMHgyNzY4L3R5cGUgMHgyNzZhIHZpYSBjYWxsIDB4MWJlMCA7IGNvdXAgb2JqKzB4NWMgOyBQViBsZW4gb2JqKzB4NWEpIC0+IG9uCiAgICAjIHJldXRpbGlzZSBsZSBjaGVtaW4ganVuaW9yPVRydWUuIFNFVUxFIGRpZmZlcmVuY2UgOiBsYSBwcm9mb25kZXVyIG4nZXN0IFBBUyBlbiAweDI3NmMgaWNpIG1haXMKICAgICMgcG9ydGVlIHBhciBsZSBtZXNzYWdlIDB4MTU4IGVuIGN0eCsweDE0IChzdHlsZSBGcml0eikgLT4ganJfZGVwdGgxNTg9MHgxNC4KICAgICMgUEVSU1BFQ1RJVkUgZHUgc2NvcmUgKGpyX3dwZXJzcGVjdGl2ZSkgQSBWQUxJREVSIGF1IHRyYWl0IE5vaXIgKFRlc3QgQSkgOiBGYWxzZSBwYXIgZGVmYXV0LgogICAgODYwMTY6ICBkaWN0KG5hbWU9IlNocmVkZGVyIDciLCBhdXRob3I9IlN0ZWZhbiBNZXllci1LYWhsZW4iLAogICAgICAgICAgICAgICAgIG5tb3Zlcz1Ob25lLCBzY29yZXM9Tm9uZSwgbW92ZWJhc2U9Tm9uZSwgcHY9Tm9uZSwgbm9kZT1Ob25lLAogICAgICAgICAgICAgICAgIGNwPVsoMHgzMmNlLCBiIlx4OTAiKjYpLCAoMHgzMzIxLCBiIlx4OTAiKjYpLCAoMHgzM2MyLCBiIlx4OTAiKjYpLCAweDM0ODNdLAogICAgICAgICAgICAgICAgIHByZWxvYWQ9WygiU2hyZWRkZXI3LmRsbCIsIFsoMHg0MTMzLCBiIlx4RTlceEE3XHgwNlx4MDBceDAwXHg5MCIpXSldLCAgIyBhcHJlcyBzZXR1cCAtPiByZXRvdXIgJ0NEIHRyb3V2ZScgMHg0N2RmCiAgICAgICAgICAgICAgICAganVuaW9yPVRydWUsIGpyX3dwZXJzcGVjdGl2ZT1GYWxzZSwganJfZGVwdGgxNTg9MHgxNCwgc2hyZWRkZXJfc3A9VHJ1ZSksCiAgICAjIEdhbWJpdCBUaWdlciAyLjAgKFRpZ2VyX2cuZW5nLCA5ODMwNCBvKSA6IGNvcXVpbGxlIENoZXNzQmFzZSBFbmcqL0Z1bmMzIHF1aSBjaGFyZ2UgVGlnZXJfZy5kbGwKICAgICMgKG1vdGV1ciBuYXRpZiBkZSBDaHJpc3RvcGhlIFRoZXJvbiwgQVBJIF9DVF8qKSAtPiBNRU1FIGFyY2hpdGVjdHVyZSBxdWUgU2hyZWRkZXIgNy4gQ1AgY29xdWlsbGUgOgogICAgIyB1bmUgcG9ydGUgJ2NtcCBlY3gsZWF4IDsgamUgMHg0YzEwJyBhdmVjIGNodXRlIC0+IG1vdiBlYXgsMyAtPiBqZS0+am1wIEAgMHg0YmY4LgogICAgIyBQYXMgZGUgbXVyIENEIGVuIHByYXRpcXVlIChFbmcxLT4wLCBmbGFnIHByZXQgcG9zZSkuIEVuZzkgOiBsZSBkaXNwYXRjaGVyIDB4NDI3MCBkZWNpZGUgcydpbCBmYXV0CiAgICAjIHJlbGFuY2VyIHVuZSByZWNoZXJjaGUgKGNvbXBhcmUgbGUgcGxhdGVhdSBhIHVuZSByZWZlcmVuY2UpIC0+IG9uIGZvcmNlICdqbmUnLT4nam1wJyBAIDB4NGY0ZiBwb3VyCiAgICAjIFRPVUpPVVJTIGNoZXJjaGVyIHN1ciB1biAnZ28nLiBSYXBwb3J0IDB4MTU0IGlkZW50aXF1ZSBhIEp1bmlvciA6IHNjb3JlIFsrMHgyNzY4XSwgdHlwZSBbKzB4Mjc2YV0sCiAgICAjIFBWIGxlbiBbKzB4NWFdLCBjb3VwIFsrMHg1Y10gOyBwcm9mb25kZXVyIHBvcnRlZSBwYXIgMHgxNTggZW4gY3R4KzB4MTQgKHN0eWxlIEZyaXR6L1NocmVkZGVyKS4KICAgICMgUGFyYW1zIFNQIDogb2Zmc2V0cyBGcml0eiBzdGFuZGFyZCAobW9kZSAweDg2MiwgcHJvZi4gMHg4NWUsIGNhcCAweDg3NCkgOyBTUCsweDg1YyA9IE5CIGRlIGNvdXBzLgogICAgOTgzMDQ6ICBkaWN0KG5hbWU9IkdhbWJpdCBUaWdlciAyLjAiLCBhdXRob3I9IkNocmlzdG9waGUgVGhlcm9uIiwKICAgICAgICAgICAgICAgICBubW92ZXM9Tm9uZSwgc2NvcmVzPU5vbmUsIG1vdmViYXNlPU5vbmUsIHB2PU5vbmUsIG5vZGU9Tm9uZSwKICAgICAgICAgICAgICAgICBjcD1bMHg0YmY4LCAoMHg0ZjRmLCBiIlx4RUIiKV0sICAgIyBkaXNwYXRjaGVyIGZvcmNlIChqbmUtPmptcCkgOiB0b3Vqb3VycyBjaGVyY2hlciAocHJvdXZlIGVuIHBhcnRpZSkKICAgICAgICAgICAgICAgICBqdW5pb3I9VHJ1ZSwganJfd3BlcnNwZWN0aXZlPUZhbHNlLCBqcl9kZXB0aDE1OD0weDE0LCBqcl9mbGFnMTU0PTB4MzAwMTMsIGNhcF9iaXQ4MD1UcnVlKSwKICAgICMgQ2hlc3MgVGlnZXIgMTUuMCAoVGlnZXIxNS5lbmcsIDExNDY4OCBvKSA6IE1FTUUgYXJjaGl0ZWN0dXJlIHF1ZSBHYW1iaXQgVGlnZXIgMi4wIChjb3F1aWxsZQogICAgIyBFbmcqL0Z1bmMzICsgVGlnZXIxNS5kbGwsIEFQSSBfQ1RfKikuIE9mZnNldHMgcHJvcHJlcyBhIGNlIGJ1aWxkIDogcG9ydGUgQ1AgJ2NtcCBlY3gsZWF4IDsgamUnCiAgICAjIEAgMHg0ZGU4IChjaHV0ZSAtPiBtb3YgZWF4LDMpIDsgZGlzcGF0Y2hlciBkZSByZWNoZXJjaGUgZCdFbmc5ICdjYWxsIDB4NDM4MCA7IHRlc3QgYWwsYWwgOyBqbmUnCiAgICAjIEAgMHg1MTFmIC0+IGZvcmNlIGVuIGptcCBwb3VyIFRPVUpPVVJTIGNoZXJjaGVyIHN1ciB1biAnZ28nLiBSYXBwb3J0IDB4MTU0IGlkZW50aXF1ZSAocHJpbmNpcGFsCiAgICAjIGZsYWdzIDB4MzAwMTMgOiBzY29yZSArMHgyNzY4LCB0eXBlICsweDI3NmEsIFBWIGxlbiArMHg1YSwgY291cCArMHg1YyA7IHNlY29uZGFpcmUgMHgxMDAxMSBmaWx0cmUpLgogICAgMTE0Njg4OiBkaWN0KG5hbWU9IkNoZXNzIFRpZ2VyIDE1LjAiLCBhdXRob3I9IkNocmlzdG9waGUgVGhlcm9uIiwKICAgICAgICAgICAgICAgICBubW92ZXM9Tm9uZSwgc2NvcmVzPU5vbmUsIG1vdmViYXNlPU5vbmUsIHB2PU5vbmUsIG5vZGU9Tm9uZSwKICAgICAgICAgICAgICAgICBjcD1bMHg0ZGU4LCAoMHg1MTFmLCBiIlx4RUIiKV0sCiAgICAgICAgICAgICAgICAganVuaW9yPVRydWUsIGpyX3dwZXJzcGVjdGl2ZT1GYWxzZSwganJfZGVwdGgxNTg9MHgxNCwganJfZmxhZzE1ND0weDMwMDEzLCBjYXBfYml0ODA9VHJ1ZSksCiAgICAjIC0tLSBISUFSQ1MgNyAvIDggKGNvcXVpbGxlIEVuZyovRnVuYzMgKyBoaWFyY3M3LmRsbCAvIEhpYXJjczguZGxsLCBBUEkgSGlhcmNzSW5pdC9TdGFydFRoaW5raW5nKSAtLS0KICAgICMgUHJvdGVjdGlvbiA6IEdldFZvbHVtZUluZm9ybWF0aW9uQSBkYW5zIGxlIC5lbmcsIHBvcnRlICdjbXAgLi4uIDsgamUnIGRvbnQgbGEgY2h1dGUgbWVuZSBhCiAgICAjICdtb3YgZWF4LDMnLiBPbiBmb3JjZSBsZSBqZSAtPiBqbXAuIExlcyBETEwgbW90ZXVyLCBlbGxlcywgbmUgcG9ydGVudCBBVUNVTkUgcHJvdGVjdGlvbi4KICAgICMgRm9ybWF0IGRlIHJhcHBvcnQgQ09ORklSTUUgaWRlbnRpcXVlIGEgSnVuaW9yIChzb25kZSBydW50aW1lKSA6IGNvdXAgY3R4KzB4NWMsIFBWIGxlbiBjdHgrMHg1YSwKICAgICMgc2NvcmUgY3R4KzB4Mjc2OCAvIHR5cGUgY3R4KzB4Mjc2YSwgcmFwcG9ydCBwcmluY2lwYWwgZmxhZ3M9MHgzMDAxMyAobGUgc2Vjb25kYWlyZSBlc3QgZmlsdHJlLAogICAgIyBhdmVjIHJlcGxpIGpyX2FsdCBzaSBsZSBwcmluY2lwYWwgbmUgdmllbnQgcGFzIHN1ciB1bmUgcmVjaGVyY2hlIHRyaXZpYWxlKS4KICAgIDE1NTY0ODogZGljdChuYW1lPSJIaWFyY3MgNyIsIGF1dGhvcj0iTWFyayBVbmlhY2tlIiwKICAgICAgICAgICAgICAgICBubW92ZXM9Tm9uZSwgc2NvcmVzPU5vbmUsIG1vdmViYXNlPU5vbmUsIHB2PU5vbmUsIG5vZGU9Tm9uZSwKICAgICAgICAgICAgICAgICBjcD1bMHgyNDBlXSwKICAgICAgICAgICAgICAgICBqdW5pb3I9VHJ1ZSwganJfd3BlcnNwZWN0aXZlPUZhbHNlLCBqcl9kZXB0aDE1OD0weDE0LCBqcl9mbGFnMTU0PTB4MzAwMTMsCiAgICAgICAgICAgICAgICAgIyBoaXN0ICdzaGVsbCcgMTkvMDggOiBFbmcxMSAoY29ycHMgQDB4MWVhMCkgU1RSSUNURU1FTlQgaWRlbnRpcXVlIGEgSGlhcmNzIDggLS0KICAgICAgICAgICAgICAgICAjIGZsYWcgMHg1OCAoIT0wIC0+IE5ld1Bvc2l0aW9uIHN0YXJ0cG9zIEAweDFkMjM4KSwgbGlzdGUgMHg1ZCwgY29tcHRlIDB4ODVjLAogICAgICAgICAgICAgICAgICMgdGFibGUgcHJvbW8gd29yZCBAMHgxODAwOCA9IHsyLDMsNyw2fSwgYXBwZWxzIHBOZXdNb3ZlLiBWZXJpZmllIGF1IGRlc2Fzc2VtYmxhZ2UuCiAgICAgICAgICAgICAgICAgaGlzdF9yZXBsYXk9VHJ1ZSksCiAgICAyNDU3NjA6IGRpY3QobmFtZT0iSGlhcmNzIDgiLCBhdXRob3I9Ik1hcmsgVW5pYWNrZSIsCiAgICAgICAgICAgICAgICAgbm1vdmVzPU5vbmUsIHNjb3Jlcz1Ob25lLCBtb3ZlYmFzZT1Ob25lLCBwdj1Ob25lLCBub2RlPU5vbmUsCiAgICAgICAgICAgICAgICAgIyBIaWFyY3MgOCBhIFRST0lTIGNvbnRyb2xlcyBzdWNjZXNzaWZzIGRhbnMgRW5nMSAobGUgMWVyIGVjaGVjIHN1ZmZpdCBhIHJlbnZveWVyIDMpIDoKICAgICAgICAgICAgICAgICAjICAgMHgyNzJlIDogY21wIGVjeCxlYXggOyBqbmUgLT4gZWNoZWMgICAgICAtPiBuZXV0cmFsaXNlICg2IE5PUCwgc2F1dCBuZWFyKQogICAgICAgICAgICAgICAgICMgICAweDI3NjcgOiBjbXAgZWF4LDB4N2E3ZTlhODYgOyBqbmUgLT4gZWNoZWMgLT4gbmV1dHJhbGlzZSAoNiBOT1ApCiAgICAgICAgICAgICAgICAgIyAgIDB4MjgyMiA6IGNtcCBlYXgsMHgyMWY4ZTZiNSA7IGplIHN1Y2NlcyAgLT4gZm9yY2UgZW4gam1wCiAgICAgICAgICAgICAgICAgY3A9WygweDI3MmUsIGIiXHg5MCIqNiksICgweDI3NjcsIGIiXHg5MCIqNiksIDB4MjgyMl0sCiAgICAgICAgICAgICAgICAganVuaW9yPVRydWUsIGpyX3dwZXJzcGVjdGl2ZT1GYWxzZSwganJfZGVwdGgxNTg9MHgxNCwganJfZmxhZzE1ND0weDMwMDEzLAogICAgICAgICAgICAgICAgICMgUmVqZXUgZCdoaXN0b3JpcXVlIChyZXBldGl0aW9ucy81MCBjb3VwcykgOiBFbmcxMSBAMHgyMTMwIGRlIEhpYXJjczguZW5nIGxpdAogICAgICAgICAgICAgICAgICMgU1ArMHg1OCAoZmxhZyksIFNQKzB4NWMgKGxpc3RlIGRlIGNvdXBzIDQgb2N0ZXRzKSBldCBTUCsweDg1YyAoY29tcHRlLCB3b3JkKSwKICAgICAgICAgICAgICAgICAjIHB1aXMgcmVqb3VlIGxhIHBhcnRpZSB2aWEgTmV3TW92ZSAtPiBsZSBtb3RldXIgcmV0cm91dmUgc29uIGVucmVnaXN0cmVtZW50CiAgICAgICAgICAgICAgICAgIyBpbnRlcm5lLiBWYWxpZGUgcGFyIGRlc2Fzc2VtYmxhZ2UgOyBBIENPTkZJUk1FUiBlbiBydW50aW1lIGF2YW50IGV4dGVuc2lvbgogICAgICAgICAgICAgICAgICMgYXV4IGF1dHJlcyBjb3F1aWxsZXMgZGUgbGEgZmFtaWxsZSAoSGlhcmNzIDcsIE5pbXpvIDgsIEp1bmlvci4uLikuCiAgICAgICAgICAgICAgICAgaGlzdF9yZXBsYXk9VHJ1ZSksCiAgICAjIC0tLSBOSU1aTyA4IChOaW16b184LmVuZyArIE5pbXpvXzguZGxsLCBBUEkgSW5pdEVuZ2luZS9BbmFseXNlL1NldFBvc2l0aW9uKSAtLS0KICAgICMgTWVtZSBmYW1pbGxlIHF1ZSBIaWFyY3MgOiBjb3F1aWxsZSBFbmcqL0Z1bmMzLCBwcm90ZWN0aW9uIEdldFZvbHVtZUluZm9ybWF0aW9uQSBkYW5zIGxlIC5lbmcKICAgICMgKHBvcnRlICdjbXAgZWN4LGVheCA7IGplJyBAIDB4MjJlZSBkb250IGxhIGNodXRlIG1lbmUgYSAnbW92IGVheCwzJykgLT4gamUgZm9yY2UgZW4gam1wLgogICAgIyBMZSBmaWNoaWVyIE5pbXpvXzguY21wIG4nZXN0IFBBUyB1biBleGVjdXRhYmxlIDogYydlc3QgbGEgYmFzZSBkZSBjb21iaW5haXNvbnMgZHUgbW90ZXVyCiAgICAjIChjaGFyZ2VlIHBhciBOekZpbmRDb21iaW5hdGlvbikgOyBpbCBkb2l0IHNpbXBsZW1lbnQgcmVzdGVyIGEgY290ZSBkdSAuZW5nLgogICAgIyBSYXBwb3J0IDB4MTU0IGlkZW50aXF1ZSBhIEp1bmlvciA6IGZsYWdzIDB4MzAwMTMsIHNjb3JlICsweDI3NjgsIHR5cGUgKzB4Mjc2YSwgUFYgbGVuICsweDVhLgogICAgMjAyMjQwOiBkaWN0KG5hbWU9Ik5pbXpvIDgiLCBhdXRob3I9IkNocmlsbHkgRG9ubmluZ2VyIiwKICAgICAgICAgICAgICAgICBubW92ZXM9Tm9uZSwgc2NvcmVzPU5vbmUsIG1vdmViYXNlPU5vbmUsIHB2PU5vbmUsIG5vZGU9Tm9uZSwKICAgICAgICAgICAgICAgICBjcD1bMHgyMmVlXSwKICAgICAgICAgICAgICAgICBqdW5pb3I9VHJ1ZSwganJfd3BlcnNwZWN0aXZlPUZhbHNlLCBqcl9kZXB0aDE1OD0weDE0LCBqcl9mbGFnMTU0PTB4MzAwMTMsCiAgICAgICAgICAgICAgICAgIyBoaXN0ICdzaGVsbCcgMTkvMDggOiBpbnN0YWxsYXRldXIgQDB4MjA2MCAtLSBmbGFnIDB4NTggKCE9MCAtPiBOZXdHYW1lKSwKICAgICAgICAgICAgICAgICAjIGZsYWc9MCAtPiBTZXRQb3NpdGlvbihwbGF0ZWF1IFNQKzB4MTgsIHRyYWl0LCBlLnAuLCByb3F1ZSkgU0FOUyB0cmFuc2Zvcm1hdGlvbiwKICAgICAgICAgICAgICAgICAjIHJlamV1IE1ha2VNb3ZlKHtmcm9tLHRvLHByb21vfSkgb2N0ZXRzIGJydXRzLCBsaXN0ZSAweDVkLCBjb21wdGUgMHg4NWMuCiAgICAgICAgICAgICAgICAgIyBTZXVsIGxlIGJpdCAweDQwIGRlcyBmbGFncyBlc3QgbHUgKHJvcXVlIGluZmVyZSBwYXIgbGEgRExMKS4KICAgICAgICAgICAgICAgICBoaXN0X3JlcGxheT1UcnVlKSwKICAgICMgLS0tIERFRVAgRlJJVFogOCAoRGVlcCBGcml0eiA4LmVuZyArIERlZXAgRnJpdHogOC5kbGwpIC0tLQogICAgIyBBVFRFTlRJT04gQVVYIE5PTVMgOiBsYSBjb3F1aWxsZSBzZSBjaGVyY2hlIGVsbGUtbWVtZSBzb3VzICJEZWVwIEZyaXR6IDguZW5nIiAoYXZlYyBFU1BBQ0VTKQogICAgIyBwdWlzIGVuIGRlZHVpdCAiRGVlcCBGcml0eiA4LmRsbCIuIEF2ZWMgZGVzIHVuZGVyc2NvcmVzLCBFbmcxIHJlbnZvaWUgOSAoZWNoZWMgZGUgY2hhcmdlbWVudCkuCiAgICAjIEVuZzEgZW5jaGFpbmUgU0lYIGNvbnRyb2xlcyBwYXIgc29tbWUgZGUgY29udHJvbGUsIHRvdXMgbWVuYW50IGEgJ21vdiBlYXgsMycgOgogICAgIyAgIDB4NDU0MiBoYW5kbGUgZHUgbW9kdWxlIHwgMHg0NTcxIGNoZWNrc3VtIGR1IGNoZW1pbiAoMHgyMjAyOTMxNikKICAgICMgICAweDQ1YmQgIkRlZXAgRnJpdHogOCIgKDB4MGI3OTYyM2MpIHwgMHg0NjdlICJGcmFucyBNb3JzY2giICgweDQ4ZDM0YzhhKQogICAgIyAgIDB4NDZhNyBkcmFwZWF1eCBpbnRlcm5lcyAoJiAweDUwMDApIHwgMHg0ODI3ICJORUQiICgweDEzN2I5OTg0KQogICAgIyBUb3VzIHNvbnQgZGVzICdqZScgY291cnRzIC0+IGZvcmNlcyBlbiAnam1wJy4gVmVyc2lvbiBtdWx0aXByb2Nlc3NldXIgOiBmaXhlciBUaHJlYWRzL0NvcmVzIGEgMQogICAgIyBjb3RlIEdVSSBwb3VyIHJlc3RlciBjb21wYXJhYmxlIGF1IHJlc3RlIGR1IHZpdmllciAobW9uby10aHJlYWQpLgogICAgNDg3NDI0OiBkaWN0KG5hbWU9IkRlZXAgRnJpdHogOCIsIGF1dGhvcj0iRnJhbnMgTW9yc2NoIiwKICAgICAgICAgICAgICAgICBubW92ZXM9Tm9uZSwgc2NvcmVzPU5vbmUsIG1vdmViYXNlPU5vbmUsIHB2PU5vbmUsIG5vZGU9Tm9uZSwKICAgICAgICAgICAgICAgICBjcD1bMHg0NTQyLCAweDQ1NzEsIDB4NDViZCwgMHg0NjdlLCAweDQ2YTcsIDB4NDgyN10sCiAgICAgICAgICAgICAgICAgIyBDb250cmFpcmVtZW50IGEgRnJpdHogOCAodGFibGVhdSBkZSBzY29yZXMgcmFjaW5lICsgYXJnbWF4KSwgbGEgdmVyc2lvbiBERUVQIGVzdAogICAgICAgICAgICAgICAgICMgbXVsdGlwcm9jZXNzZXVyIDogcGx1c2lldXJzIHRocmVhZHMgbmUgcGV1dmVudCBwYXMgcGFydGFnZXIgY2UgdGFibGVhdSwgZXQgTW9yc2NoCiAgICAgICAgICAgICAgICAgIyBlc3QgcGFzc2UgYXUgcmFwcG9ydCAweDE1NCBmYWNvbiBKdW5pb3IgKHZlcmlmaWUgYXUgZGVzYXNzZW1ibGFnZSA6IHNjb3JlIGN0eCsweDI3NjgsCiAgICAgICAgICAgICAgICAgIyB0eXBlICsweDI3NmEsIFBWIGxlbiArMHg1YSwgUFZbMF0gKzB4NTgpLiBMZSBmbGFnIG9ic2VydmUgZXN0IDB4MTMwMDEzIGV0IG5vbiAweDMwMDEzLAogICAgICAgICAgICAgICAgICMgbWFpcyBvbiBuZSBGSUxUUkUgUEFTIDogbGVzIGVtZXR0ZXVycyBzb250IG11bHRpcGxlcyBldCB1biBmaWx0cmUgdHJvcCBzdHJpY3QgYXZhaXQKICAgICAgICAgICAgICAgICAjIGNvdXRlIGRlcyBjb3VwcyBtYW5xdWFudHMgc3VyIFRpZ2VyLiBMZSByZXBsaSBqcl9hbHQgc3VmZml0LgogICAgICAgICAgICAgICAgICMgTmIgZGUgdGhyZWFkcyA6IEVuZzEgbGl0IEdldFN5c3RlbUluZm8gZXQgc3RvY2tlIGxlIGNvbXB0ZSAocGxhZm9ubmUgYSA4KSBkYW5zCiAgICAgICAgICAgICAgICAgIyBjZXMgZGV1eCBnbG9iYWxlcyAodmVyaWZpZSBhdSBkZXNhc3NlbWJsYWdlIEAgMHg0NjU0LzB4NDY1YSkuIExlcyBlY3JpcmUgQVBSRVMKICAgICAgICAgICAgICAgICAjIEVuZzEgcGVybWV0IGQnaW1wb3NlciB1bmUgdmFsZXVyIDsgMCA9IG9uIG5lIHRvdWNoZSBhIHJpZW4gKHRvdXMgbGVzIGNvZXVycykuCiAgICAgICAgICAgICAgICAgdGhyZWFkc19ydmE9KDB4MmQxZTQsIDB4MmQxZTgpLAogICAgICAgICAgICAgICAgIGp1bmlvcj1UcnVlLCBqcl93cGVyc3BlY3RpdmU9RmFsc2UsIGpyX2RlcHRoMTU4PTB4MTQsCiAgICAgICAgICAgICAgICAgIyBoaXN0ICdpbmxpbmUnIDE5LzA4IDogYm91Y2xlIGRlIHJlamV1IEAweDM4NWMgdmVyaWZpZWUgKHByb3RvY29sZSBTUCBpZGVudGlxdWUKICAgICAgICAgICAgICAgICAjIGEgdG91dGUgbGEgZmFtaWxsZSBGcml0eiA7IHJvcXVlIHZpYSByZWdpc3RyZSBibD0weDIwIGNvbW1lIEZyaXR6IDcpLgogICAgICAgICAgICAgICAgIGhpc3RfcmVwbGF5PSdpbmxpbmUnKSwKfQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiMgSnVuaW9yIDogbGUgLmVuZyBlc3QgdW5lIENPUVVJTExFIENoZXNzQmFzZSBxdWkgY2hhcmdlIEpyX1hYLmRsbCAobGUgdnJhaSBtb3RldXIpIHZpYQojIEVuZ2luZUluaXQgOyBwcm90b2NvbGUgRW5nKi9jYWxsYmFjayBpZGVudGlxdWUgYSBGcml0eiwgTUFJUyBKdW5pb3IgSUdOT1JFIGwnb2Zmc2V0IGRlCiMgcHJvZm9uZGV1ciBGcml0eiBzcGFyYW1zWzB4ODVlXSA6ICJnbyBkZXB0aCBOIiBuJ2VzdCBwYXMgcGxhZm9ubmUgKEp1bmlvciB0b3VybmUganVzcXUnYSBzYQojIGxpbWl0ZSBpbnRlcm5lKS4gTGUgY29udHJvbGUgc2UgZmFpdCBkb25jIGF1IFRFTVBTIDogdGltZXIgLT4gRW5nMygpIChzdG9wKS4gQSBWQUxJREVSIHF1ZQojIEVuZzMgaW50ZXJyb21wdCBiaWVuIHVuZSByZWNoZXJjaGUgbG9uZ3VlIChjZi4gZG9fc2VhcmNoLCBjaGVtaW4gYnVkZ2V0X21zKS4KIyBMZXMgZGV1eCAuZW5nIGZvbnQgMjEyOTkyIG8gLT4gb24gbGVzIGRpc3Rpbmd1ZSBwYXIgbGEgY2hhaW5lICJKdW5pb3IgNyIvIkp1bmlvciA4Ii4KIyBFWFRSQUNUSU9OIEVUQUJMSUUgKHZpYSAtLWNhbGliKSA6IHRvdXQgdHJhbnNpdGUgcGFyIGxlIHJhcHBvcnQgRnVuYzMgMHgxNTQgLT4KIyAgIGNvdXArUFYgZW4gY3R4KzB4NWEvMHg1YyA7IHNjb3JlIGVuIGN0eCsweDI3NjggKHZhbCkgLyAweDI3NmEgKHR5cGUgMT1jcCAyPW1hdCkgOwojICAgcHJvZm9uZGV1ciBlbiBjdHgrMHgyNzZjIChjaGFtcCBkdSByYXBwb3J0LCBmaWFibGUpIDsgbm9ldWRzIDB4MTU3IChjdHgrMHgxNCkuIENmLiBob3N0X2NhbGxiYWNrLgojIFJFU1RFIEEgVkFMSURFUiA6IHBlcnNwZWN0aXZlIGR1IHNjb3JlIGF1IHRyYWl0IE5vaXIgLT4ganJfd3BlcnNwZWN0aXZlICh2b2lyIF9qcl9yZWFkX3Njb3JlKS4KSlVOSU9SID0gewogICAgIkp1bmlvciA3IjogZGljdChuYW1lPSJKdW5pb3IgNyIsIGF1dGhvcj0iQW1pciBCYW4sIFNoYXkgQnVzaGluc2t5IiwKICAgICAgICAgICAgICAgICAgICAgbm1vdmVzPU5vbmUsIHNjb3Jlcz1Ob25lLCBtb3ZlYmFzZT1Ob25lLCBwdj1Ob25lLCBub2RlPU5vbmUsCiAgICAgICAgICAgICAgICAgICAgIGNwPVsweDIzNWEsIDB4MjM4NF0sIGp1bmlvcj1UcnVlLCBqcl93cGVyc3BlY3RpdmU9RmFsc2UsCiAgICAgICAgICAgICAgICAgICAgICMgaGlzdCAnc2hlbGwnIDE5LzA4IDogaW5zdGFsbGF0ZXVyIEAweDFkOTAgLS0gZmxhZyAweDU4ICghPTAgLT4gTmV3R2FtZSgwKSB2aWEKICAgICAgICAgICAgICAgICAgICAgIyBbMHgyMmE1OF0pLCBsaXN0ZSAweDVjLCBjb21wdGUgMHg4NWMsIGNhc2VzIGNvbnZlcnRpZXMgcGFyIGxhIGNvcXVpbGxlIHZlcnMgbGUKICAgICAgICAgICAgICAgICAgICAgIyBmb3JtYXQgMHg4OCBkdSBtb3RldXIgKChyYW5nPDw0KXxjb2xvbm5lKSwgcHJvbW8gPSB0YWJsZSBBU0NJSSBAMHgxZTJkNAogICAgICAgICAgICAgICAgICAgICAjIHsnICcsJyAnLCdRJywnTicsJ0InLCdSJywnICcsJyAnfSA9IG5vdHJlIG9yZHJlIFJBVy4gVmVyaWZpZSBhdSBkZXNhc3NlbWJsYWdlLgogICAgICAgICAgICAgICAgICAgICBoaXN0X3JlcGxheT1UcnVlKSwKICAgICMgSnVuaW9yIDggOiBDUCBldGFibGllIHBhciBhbmFseXNlIHN0YXRpcXVlIGRlIEp1bmlvcjgwLmVuZyAoRW5nMSBAIDB4MjM3MCkuIExlIGNvZGUgYQogICAgIyBkZWNhbGUgdnMgNy4wIC0+IG9mZnNldHMgcHJvcHJlcy4gUXVhdHJlIHBvcnRlcyAiamUgc3VjY2VzIC8gY2h1dGUgLT4gbW92IGVheCwzIChjb2RlIDMpIgogICAgIyBnYXJkZWVzIHBhciB1biBjaGVja3N1bSAoY21wIGVheCwgbWFnaWMpIDogMHgyM2RiLCAweDI0NGMsIDB4MjRjYiwgMHgyNTJmIC0+IGplLT5qbXAuCiAgICAjIFByb3RvY29sZSBkZSByYXBwb3J0IChjb3VwL3Njb3JlL3Byb2YuKSBzdXBwb3NlIGlkZW50aXF1ZSBhIDcuMCAobWVtZSBmYW1pbGxlKSAtPiBBIENPTkZJUk1FUgogICAgIyBwYXIgdW4gcnVuIC0tY2FsaWIgKGxlIGRpYWdub3N0aWMgU0NPUkU\/IHJldmVsZSB0b3V0IGRlY2FsYWdlIGV2ZW50dWVsKS4KICAgICJKdW5pb3IgOCI6IGRpY3QobmFtZT0iSnVuaW9yIDgiLCBhdXRob3I9IkFtaXIgQmFuLCBTaGF5IEJ1c2hpbnNreSIsCiAgICAgICAgICAgICAgICAgICAgIG5tb3Zlcz1Ob25lLCBzY29yZXM9Tm9uZSwgbW92ZWJhc2U9Tm9uZSwgcHY9Tm9uZSwgbm9kZT1Ob25lLAogICAgICAgICAgICAgICAgICAgICBjcD1bMHgyM2RiLCAweDI0NGMsIDB4MjRjYiwgMHgyNTJmXSwganVuaW9yPVRydWUsIGpyX3dwZXJzcGVjdGl2ZT1GYWxzZSwKICAgICAgICAgICAgICAgICAgICAgIyBoaXN0ICdzaGVsbCcgMTkvMDggOiBib3VjbGUgQDB4MWZjNSBpZGVudGlxdWUgYSBKdW5pb3IgNyAodGFibGUgQVNDSUkgQDB4MWU0ZTgpLgogICAgICAgICAgICAgICAgICAgICBoaXN0X3JlcGxheT1UcnVlKSwKfQojIG9mZnNldHMgZCdlbnRyZWUgY29tbXVucyAoc3BhcmFtcykgZXQgcGFyYW1ldHJlcyBkZSByZWNoZXJjaGUKQk9BUkRfT0ZGLCBGTEFHX09GRiwgU0lERV9PRkYsIEVQX09GRiwgQ0FTVExFX09GRiA9IDB4MTgsIDB4NTgsIDB4NTksIDB4NWEsIDB4NWIKIyBPZmZzZXRzIHNwYXJhbXMgcGlsb3RhbnQgbGEgcmVjaGVyY2hlIChldGFibGlzIHBhciBkZXNhc3NlbWJsYWdlIGQnRW5nOSAtPiAweDM5ODApIDoKIyAgIDB4ODVlICBJVEVSREVQVEggIHByb2ZvbmRldXIgY2libGUgKGx1ZSBwYXIgRW5nOSwgZm9yY2VlID49MSkKIyAgIDB4ODYyICBNT0RFICAgICAgIHNlbGVjdGV1ciBkJ2FycmV0IDogMC8+PTQgPSBwcm9mb25kZXVyK2FycmV0IGFudGljaXBlIDsgMSA9IFRFTVBTIHJlZWwKIyAgICAgICAgICAgICAgICAgICAgIChsaXQgMHg4NjgvMHg4NjQvMHg4NzAvMHg4NmMvMHg4NzIpIDsgMi8zID0gYm9ybmUgdW5pcXVlIDB4ODc0IHRyYWl0ZWUgZW4gdGVtcHMKIyAgIDB4ODc0ICBUVkFMICAgICAgIHZhbGV1ci10ZW1wcyBxdWFuZCBtb2RlIDIvMyAoYm9ybmVlIGludGVybmUpCk1PREVfT0ZGLCBJVEVSREVQVEhfT0ZGLCBDQVBERVBUSF9PRkYgPSAweDg2MiwgMHg4NWUsIDB4ODc0CiMgQ2hhbXBzIGR1IG1vZGUgVEVNUFMgcmVlbCAobW9kZSAxKSwgcmFuZ2VzIHBhciAweDM5ODAgZW4gYm9ybmVzIG1pbi9jaWJsZS9tYXggOgpUX0FWQUlMX09GRiwgVF9VU0VEX09GRiwgVF9JTkNfT0ZGID0gMHg4NjgsIDB4ODY0LCAweDg2YyAgICMgZHdvcmRzIDogdGVtcHMgZGlzcG8gLyBlY291bGUgLyBpbmNyZW1lbnQKVF9NVEdfT0ZGLCBUX0ZMQUdfT0ZGICAgICAgICAgICAgID0gMHg4NzIsIDB4ODcwICAgICAgICAgICAjIHdvcmRzICA6IG1vdmVzdG9nbyAvIGRyYXBlYXUgKDB4N2ZmZj1zYW5zKQpNT0RFX0ZJWEVEX0RFUFRIID0gMgojIC0tLSBNT0RFIHBvdXIgImdvIGRlcHRoIE4iIDogY2UgbW90ZXVyIG4nYSBwYXMgZGUgdnJhaSBwcm9mb25kZXVyLWZpeGUgKHBpbG90ZSBhdSB0ZW1wcyArIGNhcCkuCiMgVmVyaWZpZSBlbiBydW50aW1lIDogMHg4NjI9MiBhdHRlaW50IGxhIHByb2ZvbmRldXIgZGVtYW5kZWUgKGRlZmF1dCkgOyAweDg2Mj0wIHMnYXJyZXRlIHRvdC4KREVQVEhfTU9ERSA9IG9zLmVudmlyb24uZ2V0KCdFTkcyVUNJX0RNT0RFJywgJzInKQojIC0tLSBkaWFnbm9zdGljIChyZXRyby1jb21wYXQpIDogb3ZlcnJpZGUgbWFudWVsIGRlIDB4ODYyIC8gMHg4NzQgLS0tCk1PREVfVkFMVUUgICA9IGludChvcy5lbnZpcm9uWydFTkcyVUNJX01PREUnXSkgaWYgJ0VORzJVQ0lfTU9ERScgaW4gb3MuZW52aXJvbiBlbHNlIE5vbmUKQ0FQREVQVEhfU0VUID0gb3MuZW52aXJvbi5nZXQoJ0VORzJVQ0lfQ0FQJywgJzEnKSAhPSAnMCcKIyAtLS0gbW9kZSBURU1QUyBpbnRlcm5lICgweDg2Mj0xKSA6IGxhaXNzZSBsZSBtb3RldXIgZ2VyZXIgc29uIGJ1ZGdldCBhdSBsaWV1IGR1IHdhdGNoZG9nIGV4dGVybmUgLS0tCklOTkVSX1RJTUUgPSBvcy5lbnZpcm9uLmdldCgnRU5HMlVDSV9JTk5FUlRJTUUnLCAnMCcpICE9ICcwJwojIEVjaGVsbGUgZHUgYnVkZ2V0IHBhc3NlIGF1IG1vdGV1ciA6IGRlcGFydGFnZSBzb3VzLWFsbG9jYXRpb24gKDB4ODY4PXRlbXBzIFRPVEFMKSB2cyBlYXN5LW1vdmUuCiMgU2kgeE4gcmFsbG9uZ2UgbGEgcmVjaGVyY2hlIH54TiAtPiBzb3VzLWFsbG9jYXRpb24sIGNvcnJpZ2VyIGwnZWNoZWxsZS4gU2lub24gLT4gY2hhbXAgbWFucXVhbnQuClRTQ0FMRSA9IGZsb2F0KG9zLmVudmlyb24uZ2V0KCdFTkcyVUNJX1RTQ0FMRScsICcxJykpClRNVEcgICA9IGludChvcy5lbnZpcm9uLmdldCgnRU5HMlVDSV9UTVRHJywgJzAnKSkgICAgICAgICAgIyBtb3Zlc3RvZ28gZm9yY2UgKDAgPSBsYWlzc2VyIGVzdGltZXIpCkY4NzYgPSBvcy5lbnZpcm9uLmdldCgnRU5HMlVDSV9GODc2JywgJzEnKSAgICMgU1ArMHg4NzYgOiAxID0gcmVnaW1lIFBBUlRJRSAodmFsZXVyIENoZXNzQmFzZSwgZHVtcHMpIDsgMiA9IGFuYWx5c2UvcmVjaGVyY2hlIGNvbXBsZXRlCkY4NUMgPSBvcy5lbnZpcm9uLmdldCgnRU5HMlVDSV9GODVDJykgICAjIFNQKzB4ODVjIDogbmIgZGUgY291cHMgcmFjaW5lIChzZWFyY2htb3Zlcy9NdWx0aVBWKSAtLSBORSBQQVMgZWNyaXJlIGVuIGpldSA6IHRyb25xdWUgbGEgbGlzdGUKCmRlZiBfcGFyc2VfcG9rZShzcGVjKToKICAgICIiIicweDg3OD0xMCwweDg3MD04JyAtPiBbKDB4ODc4LDEwKSwoMHg4NzAsOCldIDsgb2Zmc2V0cy92YWxldXJzIGVuIGhleCAoMHguLikgb3UgZGVjaW1hbC4iIiIKICAgIG91dD1bXQogICAgZm9yIGl0ZW0gaW4gKHNwZWMgb3IgJycpLnJlcGxhY2UoJzsnLCcsJykuc3BsaXQoJywnKToKICAgICAgICBpdGVtPWl0ZW0uc3RyaXAoKQogICAgICAgIGlmIG5vdCBpdGVtIG9yICc9JyBub3QgaW4gaXRlbTogY29udGludWUKICAgICAgICBvZmYsdmFsPWl0ZW0uc3BsaXQoJz0nLDEpCiAgICAgICAgb2ZmPWludChvZmYuc3RyaXAoKSwwKTsgdmFsPWludCh2YWwuc3RyaXAoKSwwKQogICAgICAgIG91dC5hcHBlbmQoKG9mZix2YWwpKQogICAgcmV0dXJuIG91dApQT0tFID0gX3BhcnNlX3Bva2Uob3MuZW52aXJvbi5nZXQoJ0VORzJVQ0lfUE9LRScpKSAgICMgZWNyaXR1cmVzIGJydXRlcyBkZSBtb3RzIHN1ciBzcGFyYW1zIChkaWFnbm9zdGljKQojIEFwcGVsIGQnRW5nMTUgYXZhbnQgY2hhcXVlIHJlY2hlcmNoZSAoY29tbWUgbCdpbnRlcmZhY2UgOiByZWxldmUgZGVib2d1ZXVyIEVuZzE1LT5Fbmc5KS4KRU5HMTVfQkVGT1JFX1NFQVJDSCA9IG9zLmVudmlyb24uZ2V0KCdFTkcyVUNJX0VORzE1JywgJzAnKSAhPSAnMCcKIyBPcHRpb24gOiBORSBQQVMgYXBwZWxlciBFbmcxNSBhIGwnaW5pdCAocG91ciBuZSBwYXMgY29uc29tbWVyIGxlIGZsYWcgMHgyZDIzNCB0cm9wIHRvdCkuCkVORzE1X1NLSVBfSU5JVCAgICAgPSBvcy5lbnZpcm9uLmdldCgnRU5HMlVDSV9FTkcxNV9TS0lQSU5JVCcsICcwJykgIT0gJzAnIAojICdhZnRlcicgOiBhcHBlbGVyIEVuZzE1IEFQUkVTIGxhIDFyZSByZWNoZXJjaGUgKG9yZHJlIGludGVyZmFjZSBFbmc5LT5FbmcxNSksIGFtb3JjZSBsZXMgdGFibGVzLgpFTkcxNV9BRlRFUiA9IG9zLmVudmlyb24uZ2V0KCdFTkcyVUNJX0VORzE1X0FGVEVSJywgJzAnKSAhPSAnMCcKX2VuZzE1X3ByaW1lZCA9IFtGYWxzZV0KCmRlZiBhcHBseV9wb2tlKCk6CiAgICAiIiJFY3JpdCBsZXMgcGFpcmVzIChvZmZzZXQsIHZhbGV1cikgZGUgRU5HMlVDSV9QT0tFIGRhbnMgc3BhcmFtcywgZW4gZGVybmllci4iIiIKICAgIGZvciBvZmYsdmFsIGluIFBPS0U6CiAgICAgICAgc3RydWN0LnBhY2tfaW50bygiPGgiLCBzcGFyYW1zLCBvZmYsIHZhbCAmIDB4ZmZmZiBpZiB2YWw+PTAgZWxzZSB2YWwpCiAgICBpZiBDQUxJQiBhbmQgUE9LRToKICAgICAgICBsb2coIltkaWFnXSBQT0tFICIgKyAiICIuam9pbigiMHgleD0lZCIlKG8sdikgZm9yIG8sdiBpbiBQT0tFKSkKU0VOVElORUwgPSAtMzI3NjggICAgICAgICAgICAgICAgICMgMHhmZmZmODAwMCA6IHNjb3JlIGRlIHJlc2V0CgojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCkNBTElCID0gRmFsc2UKYXJndiA9IGxpc3Qoc3lzLmFyZ3ZbMTpdKQppZiBhcmd2IGFuZCBhcmd2WzBdID09ICItLWNhbGliIjoKICAgIENBTElCID0gVHJ1ZTsgYXJndiA9IGFyZ3ZbMTpdCkVOR19QQVRIID0gYXJndlswXSBpZiBhcmd2IGVsc2UgIkZyaXR6IDYuZW5nIgpIQVNIX01CICA9IDY0ClRIUkVBRFMgID0gMCAgICAgICAgIyAwID0gbmUgcmllbiBpbXBvc2VyIDogbGUgbW90ZXVyIGdhcmRlIGNlIHF1J0VuZzEgYSBkZXRlY3RlICh0b3VzIGxlcyBjb2V1cnMsIG1heCA4KQpIRVJFICAgICA9IG9zLnBhdGguZGlybmFtZShvcy5wYXRoLmFic3BhdGgoX19maWxlX18pKQpMT0dfUEFUSCA9IG9zLnBhdGguam9pbihIRVJFLCBmImVuZzJ1Y2lfe29zLmdldHBpZCgpfS5sb2ciKSAgICMgMSBmaWNoaWVyIHBhciBwcm9jZXNzdXMgKHBhcnRpZXMgc2ltdWx0YW5lZXMpCgojIExlIGZpY2hpZXIgbG9nIG4nZXN0IG91dmVydCBRVUUgc291cyAtLWNhbGliIChkaWFnbm9zdGljKS4gRW4gdG91cm5vaSBub3JtYWwgOiBhdWN1biBmaWNoaWVyIGVjcml0LAojIGRvbmMgcGFzIGRlIHBvbGx1dGlvbiBkZXMgZG9zc2llcnMgbW90ZXVycy4KX2xvZ2YgPSBvcGVuKExPR19QQVRILCAidyIsIGJ1ZmZlcmluZz0xLCBlbmNvZGluZz0idXRmLTgiLCBlcnJvcnM9InJlcGxhY2UiKSBpZiBDQUxJQiBlbHNlIE5vbmUKZGVmIGxvZygqYSk6CiAgICBpZiBub3QgQ0FMSUI6IHJldHVybgogICAgbSA9ICIgIi5qb2luKHN0cih4KSBmb3IgeCBpbiBhKQogICAgaWYgX2xvZ2Y6IF9sb2dmLndyaXRlKG0gKyAiXG4iKQogICAgc3lzLnN0ZGVyci53cml0ZSgiW2RiZ10gIiArIG0gKyAiXG4iKTsgc3lzLnN0ZGVyci5mbHVzaCgpCmRlZiBsb2dfY3Jhc2goKmEpOgogICAgIyBKb3VybmFsIGRlcyBJTkNJREVOVFMgdW5pcXVlbWVudCAoY3Jhc2ggZCdFbmc5KS4gTGUgZmljaGllciBuJ2VzdCBjcmVlIHF1ZSBzaSB1biBjcmFzaCBzdXJ2aWVudCA6CiAgICAjIGF1Y3VuZSBwb2xsdXRpb24gZGVzIGRvc3NpZXJzIHF1YW5kIHRvdXQgdmEgYmllbiwgbWFpcyBvbiBnYXJkZSB1bmUgdHJhY2UgZXhwbG9pdGFibGUgZW4gdG91cm5vaS4KICAgIG0gPSAiICIuam9pbihzdHIoeCkgZm9yIHggaW4gYSkKICAgIGxvZyhtKQogICAgdHJ5OgogICAgICAgIHdpdGggb3Blbihvcy5wYXRoLmpvaW4oSEVSRSwgImVuZzJ1Y2lfaW5jaWRlbnRzLmxvZyIpLCAiYSIsIGVuY29kaW5nPSJ1dGYtOCIsIGVycm9ycz0icmVwbGFjZSIpIGFzIGY6CiAgICAgICAgICAgIGYud3JpdGUoZiJbe3RpbWUuc3RyZnRpbWUoJyVZLSVtLSVkICVIOiVNOiVTJyl9XSBwaWQ9e29zLmdldHBpZCgpfSB7Q0ZHWyduYW1lJ119IDoge219XG4iKQogICAgZXhjZXB0IEV4Y2VwdGlvbjogcGFzcwoKUFZfRlVMTCA9IG9zLmVudmlyb24uZ2V0KCdFTkcyVUNJX1BWRlVMTCcsICcwJykgIT0gJzAnICAgIyAxID0gUFYgY29tcGxldGUgKHdhcm5pbmdzIHBvc3NpYmxlcykKCmRlZiBfdHJpbV9wdihzKToKICAgICMgRmlsdHJhZ2UgVEVYVEUgYXUgcG9pbnQgZGUgc29ydGllLCBob3JzIGJvdWNsZSBkZSByZWNoZXJjaGUgOiBzaSBsYSBsaWduZQogICAgIyBjb250aWVudCAiIHB2ICIsIG5lIGdhcmRlciBxdWUgbGUgMWVyIGNvdXAgKGxlIGJlc3Rtb3ZlLCB0b3Vqb3VycyBsZWdhbCkuCiAgICAjIENhdXNlIGRlcyB3YXJuaW5ncyBjdXRlY2hlc3MgOiBwcm9tb3Rpb25zIGRlY29kZWVzIHNhbnMgc3VmZml4ZSAoZXguIGg3aDgpCiAgICAjIGF1IGZpbCBkZSBsYSBQVi4gQ291cGVyIGF1IDFlciBjb3VwIHN1cHByaW1lIGxlcyAiSWxsZWdhbCBQViBtb3ZlIi4KICAgIGlmIFBWX0ZVTEw6CiAgICAgICAgcmV0dXJuIHMKICAgIGkgPSBzLmZpbmQoIiBwdiAiKQogICAgaWYgaSA8IDA6CiAgICAgICAgcmV0dXJuIHMKICAgIHJlc3QgPSBzW2krNDpdLnNwbGl0KCkKICAgIHJldHVybiBzWzppKzRdICsgKHJlc3RbMF0gaWYgcmVzdCBlbHNlICIiKQoKZGVmIHVjaV9vdXQocyk6CiAgICBzID0gX3RyaW1fcHYocykKICAgIHN5cy5zdGRvdXQud3JpdGUocyArICJcbiIpOyBzeXMuc3Rkb3V0LmZsdXNoKCk7IGxvZygiPj4gIiArIHMpCgppZiBjdHlwZXMuc2l6ZW9mKGN0eXBlcy5jX3ZvaWRfcCkgIT0gNDoKICAgIHN5cy5zdGRlcnIud3JpdGUoIkZBVEFMOiBQeXRob24gMzIgYml0cyByZXF1aXMgKHB5IC0zLTMyKS5cbiIpOyBzeXMuZXhpdCgxKQppZiBub3Qgb3MucGF0aC5leGlzdHMoRU5HX1BBVEgpOgogICAgc3lzLnN0ZGVyci53cml0ZShmIkZBVEFMOiB7RU5HX1BBVEh9IGludHJvdXZhYmxlXG4iKTsgc3lzLmV4aXQoMSkKClNJWkUgPSBvcy5wYXRoLmdldHNpemUoRU5HX1BBVEgpCkNGRyA9IEVOR0lORVMuZ2V0KFNJWkUpCmlmIENGRyBpcyBOb25lIGFuZCBTSVpFID09IDIxMjk5MjogICAgICAgICAgICAgICAjIEp1bmlvciA6IDcuMCBldCA4LjAgZm9udCBsYSBtZW1lIHRhaWxsZQogICAgX3Jhd2UgPSBvcGVuKEVOR19QQVRILCAicmIiKS5yZWFkKCkKICAgIGlmICAgYiJKdW5pb3IgOCIgaW4gX3Jhd2U6IENGRyA9IEpVTklPUi5nZXQoIkp1bmlvciA4IikKICAgIGVsaWYgYiJKdW5pb3IgNyIgaW4gX3Jhd2U6IENGRyA9IEpVTklPUi5nZXQoIkp1bmlvciA3IikKaWYgQ0ZHIGlzIE5vbmU6CiAgICBzeXMuc3RkZXJyLndyaXRlKGYiRkFUQUw6IHRhaWxsZSB7U0laRX0gbm9uIHJlY29ubnVlLiBNb3RldXJzIGNvbm51cyA6ICIKICAgICAgICAgICAgICAgICAgICAgKyAiLCAiLmpvaW4oZiJ7dlsnbmFtZSddfSh7a30pIiBmb3IgaywgdiBpbiBFTkdJTkVTLml0ZW1zKCkpICsgIlxuIikKICAgIHN5cy5leGl0KDEpCmxvZyhmIm1vdGV1ciBkZXRlY3RlIDoge0NGR1snbmFtZSddfSAodGFpbGxlIHtTSVpFfSkiKQoKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQprMzIgPSBjdHlwZXMud2luZGxsLmtlcm5lbDMyCmszMi5Mb2FkTGlicmFyeUEucmVzdHlwZSAgID0gd2ludHlwZXMuSE1PRFVMRQprMzIuTG9hZExpYnJhcnlBLmFyZ3R5cGVzICA9IFt3aW50eXBlcy5MUENTVFJdCmszMi5HZXRQcm9jQWRkcmVzcy5yZXN0eXBlID0gY3R5cGVzLmNfdm9pZF9wCmszMi5HZXRQcm9jQWRkcmVzcy5hcmd0eXBlcz0gW3dpbnR5cGVzLkhNT0RVTEUsIHdpbnR5cGVzLkxQQ1NUUl0KazMyLlZpcnR1YWxQcm90ZWN0LnJlc3R5cGUgPSB3aW50eXBlcy5CT09MCmszMi5WaXJ0dWFsUHJvdGVjdC5hcmd0eXBlcz0gW2N0eXBlcy5jX3ZvaWRfcCwgY3R5cGVzLmNfc2l6ZV90LCB3aW50eXBlcy5EV09SRCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3R5cGVzLlBPSU5URVIod2ludHlwZXMuRFdPUkQpXQpQQUdFX1JXWCA9IDB4NDAKZGVmIHBhdGNoX2J5dGVzKGFkZHIsIGRhdGEpOgogICAgb2xkID0gd2ludHlwZXMuRFdPUkQoMCkKICAgIGszMi5WaXJ0dWFsUHJvdGVjdChhZGRyLCBsZW4oZGF0YSksIFBBR0VfUldYLCBjdHlwZXMuYnlyZWYob2xkKSkKICAgIGN0eXBlcy5tZW1tb3ZlKGFkZHIsIGRhdGEsIGxlbihkYXRhKSkKICAgIGszMi5WaXJ0dWFsUHJvdGVjdChhZGRyLCBsZW4oZGF0YSksIG9sZC52YWx1ZSwgY3R5cGVzLmJ5cmVmKG9sZCkpCiAgICBrMzIuRmx1c2hJbnN0cnVjdGlvbkNhY2hlKGszMi5HZXRDdXJyZW50UHJvY2VzcygpLCBhZGRyLCBsZW4oZGF0YSkpCgpQUkVMT0FEX0JBU0UgPSB7fSAgICMgbm9tX2RsbCAtPiBiYXNlIGNoYXJnZWUgKHBvdXIgc29uZGVzIGRlIGRpYWdub3N0aWMpCgpkZWYgc3VwcHJlc3NfbWVzc2FnZV9ib3hlcygpOgogICAgIyBVbiBtb3RldXIgZW4gZGV0cmVzc2UgcGV1dCBvdXZyaXIgdW5lIGJvaXRlIGRlIGRpYWxvZ3VlIE1PREFMRSAoVGlnZXIgbGUgZmFpdCBhcHJlcyB1biBjcmFzaCA6CiAgICAjICJUaGUgVGlnZXIgZW5naW5lIGhhcyBiZWVuIGNvcnJ1cHRlZC4uLiIpLiBFbiB0b3Vybm9pLCBwZXJzb25uZSBuJ2VzdCBsYSBwb3VyIGNsaXF1ZXIgOiBsZQogICAgIyBwcm9jZXNzdXMgcmVzdGUgYmxvcXVlLCBhdWN1biBiZXN0bW92ZSBuZSBzb3J0LCBldCBsYSBwYXJ0aWUgZXN0IHBlcmR1ZSBwYXIgZm9yZmFpdC4gT24gcmVtcGxhY2UKICAgICMgZG9uYyBNZXNzYWdlQm94QS9XIHBhciB1biBzdHViIHF1aSByZW52b2llIElET0sgKDEpIGltbWVkaWF0ZW1lbnQsIHNhbnMgcmllbiBhZmZpY2hlci4KICAgICMgICB4ODYgc3RkY2FsbCwgNCBhcmd1bWVudHMgPSAxNiBvY3RldHMgYSBkZXBpbGVyIDogbW92IGVheCwxIDsgcmV0IDE2CiAgICBzdHViID0gYiJceEI4XHgwMVx4MDBceDAwXHgwMFx4QzJceDEwXHgwMCIKICAgIHRyeToKICAgICAgICB1MzIgPSBrMzIuTG9hZExpYnJhcnlBKGIidXNlcjMyLmRsbCIpCiAgICAgICAgZm9yIG5hbWUgaW4gKGIiTWVzc2FnZUJveEEiLCBiIk1lc3NhZ2VCb3hXIik6CiAgICAgICAgICAgIGFkZHIgPSBrMzIuR2V0UHJvY0FkZHJlc3ModTMyLCBuYW1lKQogICAgICAgICAgICBpZiBhZGRyOiBwYXRjaF9ieXRlcyhhZGRyLCBzdHViKQogICAgICAgIGxvZygiYm9pdGVzIGRlIGRpYWxvZ3VlIG1vZGFsZXMgbmV1dHJhbGlzZWVzIChhbnRpLWJsb2NhZ2UpIikKICAgIGV4Y2VwdCBFeGNlcHRpb24gYXMgZToKICAgICAgICBsb2coZiJzdXBwcmVzc19tZXNzYWdlX2JveGVzOiB7ZSFyfSIpCgpkZWYgcHJlbG9hZF9hbmRfcGF0Y2goKToKICAgICMgQ2VydGFpbnMgLmVuZyBjaGFyZ2VudCBsZSB2cmFpIG1vdGV1ciAodW5lIGF1dHJlIERMTCkgYSBsJ2V4ZWN1dGlvbiB2aWEgTG9hZExpYnJhcnksIGV0IGNldHRlCiAgICAjIERMTCBwb3J0ZSBzYSBwcm9wcmUgcHJvdGVjdGlvbiAoZXguIFNocmVkZGVyNy5kbGwgOiBjb250cm9sZSBkdSBDRC1ST00pLiBPbiBsYSBjaGFyZ2UgTk9VUy1NRU1FUwogICAgIyBlbiBwcmVtaWVyIChMb2FkTGlicmFyeSBlc3QgaWRlbXBvdGVudCA6IGxlIExvYWRMaWJyYXJ5IGludGVybmUgZHUgLmVuZyByZW52ZXJyYSBjZSBtZW1lIG1vZHVsZQogICAgIyBkZWphIHBhdGNoZSksIHB1aXMgb24gYXBwbGlxdWUgbGVzIHBhdGNocyBhIGJhc2UrcnZhLiBBIGFwcGVsZXIgQVZBTlQgRW5nMS4KICAgIGZvciBuYW1lLCBwYXRjaGVzIGluIENGRy5nZXQoJ3ByZWxvYWQnLCBbXSk6CiAgICAgICAgaCA9IGszMi5Mb2FkTGlicmFyeUEobmFtZS5lbmNvZGUoKSkKICAgICAgICBpZiBub3QgaDoKICAgICAgICAgICAgbG9nKGYicHJlbG9hZDogTG9hZExpYnJhcnkoe25hbWV9KSBlY2hlYyBlcnI9e2N0eXBlcy5nZXRfbGFzdF9lcnJvcigpfSIpOyBjb250aW51ZQogICAgICAgIFBSRUxPQURfQkFTRVtuYW1lXSA9IGggJiAweGZmZmZmZmZmCiAgICAgICAgZm9yIHJ2YSwgZGF0YSBpbiBwYXRjaGVzOgogICAgICAgICAgICBwYXRjaF9ieXRlcyhoICsgcnZhLCBkYXRhKQogICAgICAgIGxvZyhmInByZWxvYWQ6IHtuYW1lfSBiYXNlPXtoICYgMHhmZmZmZmZmZjojMDEweH0gOyB7bGVuKHBhdGNoZXMpfSBwYXRjaChzKSBwb3NlcyIpCgojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CiMgIEVjaGlxdWllciBpbnRlcm5lIChyYW5rLW1ham9yIHN0YW5kYXJkIGExPTApIC0+IGVuY29kYWdlIGZpbGUtbWFqb3IgbW90ZXVyCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KRklMRVMgPSAiYWJjZGVmZ2giCmRlZiB1Y2lfc3FfdG9faWR4KHMpOiByZXR1cm4gKGludChzWzFdKSAtIDEpICogOCArIEZJTEVTLmluZGV4KHNbMF0pCmRlZiBfaXNfdWNpX21vdmUocyk6CiAgICAjIGdhcmRlLWZvdSBhbnRpLWNyYXNoIDogbidhY2NlcHRlIHF1J3VuIHZyYWkgY291cCBVQ0kgKGUyZTQsIGU3ZThxKS4gVW5lIGVudHJlZQogICAgIyBjb25zb2xlIG1hbGZvcm1lZSAoMiBjb21tYW5kZXMgY29sbGVlcykgbmUgZG9pdCBwbHVzIGZhaXJlIHRvbWJlciBsJ2FkYXB0YXRldXIuCiAgICByZXR1cm4gKGlzaW5zdGFuY2Uocywgc3RyKSBhbmQgNCA8PSBsZW4ocykgPD0gNQogICAgICAgICAgICBhbmQgc1swXSBpbiBGSUxFUyBhbmQgc1sxXSBpbiAiMTIzNDU2NzgiCiAgICAgICAgICAgIGFuZCBzWzJdIGluIEZJTEVTIGFuZCBzWzNdIGluICIxMjM0NTY3OCIKICAgICAgICAgICAgYW5kIChsZW4ocykgPT0gNCBvciBzWzRdIGluICJxcmJuIikpClNUQVJUX0ZFTiA9ICJybmJxa2Juci9wcHBwcHBwcC84LzgvOC84L1BQUFBQUFBQL1JOQlFLQk5SIHcgS1FrcSAtIDAgMSIKCmNsYXNzIEJvYXJkOgogICAgZGVmIF9faW5pdF9fKHNlbGYpOgogICAgICAgIHNlbGYuc3EgPSBbJy4nXSAqIDY0OyBzZWxmLndoaXRlID0gVHJ1ZTsgc2VsZi5jYXN0bGUgPSBzZXQoKTsgc2VsZi5lcCA9IE5vbmUKICAgIGRlZiBzZXRfZmVuKHNlbGYsIGZlbik6CiAgICAgICAgcGFydHMgPSBmZW4uc3BsaXQoKTsgcm93cyA9IHBhcnRzWzBdLnNwbGl0KCcvJyk7IHNlbGYuc3EgPSBbJy4nXSAqIDY0CiAgICAgICAgZm9yIHIgaW4gcmFuZ2UoOCk6CiAgICAgICAgICAgIHJhbmsgPSA3IC0gcjsgZiA9IDAKICAgICAgICAgICAgZm9yIGMgaW4gcm93c1tyXToKICAgICAgICAgICAgICAgIGlmIGMuaXNkaWdpdCgpOiBmICs9IGludChjKQogICAgICAgICAgICAgICAgZWxzZTogc2VsZi5zcVtyYW5rKjggKyBmXSA9IGM7IGYgKz0gMQogICAgICAgIHNlbGYud2hpdGUgPSAobGVuKHBhcnRzKSA8IDIgb3IgcGFydHNbMV0gPT0gJ3cnKQogICAgICAgIHNlbGYuY2FzdGxlID0gc2V0KGMgZm9yIGMgaW4gKHBhcnRzWzJdIGlmIGxlbihwYXJ0cykgPiAyIGVsc2UgJycpIGlmIGMgaW4gJ0tRa3EnKQogICAgICAgIHNlbGYuZXAgPSB1Y2lfc3FfdG9faWR4KHBhcnRzWzNdKSBpZiAobGVuKHBhcnRzKSA+IDMgYW5kIHBhcnRzWzNdICE9ICctJykgZWxzZSBOb25lCiAgICBkZWYgYXBwbHlfdWNpKHNlbGYsIG12KToKICAgICAgICBmcm0gPSB1Y2lfc3FfdG9faWR4KG12WzA6Ml0pOyB0byA9IHVjaV9zcV90b19pZHgobXZbMjo0XSkKICAgICAgICBwcm9tbyA9IG12WzRdIGlmIGxlbihtdikgPiA0IGVsc2UgTm9uZQogICAgICAgIHBjID0gc2VsZi5zcVtmcm1dOyBzZWxmLnNxW2ZybV0gPSAnLicKICAgICAgICBpZiBwYyBpbiAnUHAnIGFuZCB0byA9PSBzZWxmLmVwIGFuZCBzZWxmLnNxW3RvXSA9PSAnLic6CiAgICAgICAgICAgIHNlbGYuc3FbdG8gLSA4IGlmIHBjID09ICdQJyBlbHNlIHRvICsgOF0gPSAnLicKICAgICAgICBpZiBwYyA9PSAnSycgYW5kIGZybSA9PSA0IGFuZCB0byA9PSA2OiAgIHNlbGYuc3FbNV0gPSBzZWxmLnNxWzddOyBzZWxmLnNxWzddID0gJy4nCiAgICAgICAgaWYgcGMgPT0gJ0snIGFuZCBmcm0gPT0gNCBhbmQgdG8gPT0gMjogICBzZWxmLnNxWzNdID0gc2VsZi5zcVswXTsgc2VsZi5zcVswXSA9ICcuJwogICAgICAgIGlmIHBjID09ICdrJyBhbmQgZnJtID09IDYwIGFuZCB0byA9PSA2Mjogc2VsZi5zcVs2MV0gPSBzZWxmLnNxWzYzXTsgc2VsZi5zcVs2M10gPSAnLicKICAgICAgICBpZiBwYyA9PSAnaycgYW5kIGZybSA9PSA2MCBhbmQgdG8gPT0gNTg6IHNlbGYuc3FbNTldID0gc2VsZi5zcVs1Nl07IHNlbGYuc3FbNTZdID0gJy4nCiAgICAgICAgc2VsZi5lcCA9IE5vbmUKICAgICAgICBpZiBwYyA9PSAnUCcgYW5kIHRvIC0gZnJtID09IDE2OiBzZWxmLmVwID0gZnJtICsgOAogICAgICAgIGlmIHBjID09ICdwJyBhbmQgZnJtIC0gdG8gPT0gMTY6IHNlbGYuZXAgPSBmcm0gLSA4CiAgICAgICAgaWYgcHJvbW86IHBjID0gcHJvbW8udXBwZXIoKSBpZiBwYyA9PSAnUCcgZWxzZSBwcm9tby5sb3dlcigpCiAgICAgICAgc2VsZi5zcVt0b10gPSBwYwogICAgICAgIGZvciBzLCBjcyBpbiAoKDQsICdLUScpLCAoNjAsICdrcScpKToKICAgICAgICAgICAgaWYgZnJtID09IHM6CiAgICAgICAgICAgICAgICBmb3IgeCBpbiBjczogc2VsZi5jYXN0bGUuZGlzY2FyZCh4KQogICAgICAgIGZvciBzLCBjIGluICgoNywgJ0snKSwgKDAsICdRJyksICg2MywgJ2snKSwgKDU2LCAncScpKToKICAgICAgICAgICAgaWYgZnJtID09IHMgb3IgdG8gPT0gczogc2VsZi5jYXN0bGUuZGlzY2FyZChjKQogICAgICAgIHNlbGYud2hpdGUgPSBub3Qgc2VsZi53aGl0ZQoKIyAtLS0gSGlzdG9yaXF1ZSBkZSBwYXJ0aWUgKG1vZGUgaGlzdF9yZXBsYXkpIDogYmFzZSBVQ0kgKCdwb3NpdGlvbicpICsgY291cHMgam91ZXMgLS0tCmdhbWVfYmFzZV9mZW4gPSBOb25lICAgICAgIyBOb25lID0gc3RhcnRwb3MgOyBzaW5vbiBsYSBGRU4gZGUgYmFzZSByZWN1ZSBkZSBsYSBHVUkKZ2FtZV9tb3ZlcyAgICA9IFtdICAgICAgICAjIGNvdXBzIFVDSSBhcHBsaXF1ZXMgZGVwdWlzIGxhIGJhc2UsIGRhbnMgbCdvcmRyZQpfaGlzdF9vayAgICAgID0gW0ZhbHNlXSAgICMgbGEgREVSTklFUkUgYWxpbWVudGF0aW9uIGEtdC1lbGxlIHV0aWxpc2UgbGUgcmVqZXUgZCdoaXN0b3JpcXVlID8KX2hpc3RfbiAgICAgICA9IFswXSAgICAgICAjIGxvbmd1ZXVyIGRlIGxhIGRlcm5pZXJlIHF1ZXVlIHJlam91ZWUgKGRpYWdub3N0aWMgaW5jaWRlbnRzKQpfaGlzdF9mZWVkICAgID0gW05vbmVdICAgICMgZGV0YWlscyBkdSBkZXJuaWVyIGZlZWQgKHYxMSkgOiBiYXNlLCBxdWV1ZSwgb2N0ZXRzIFNQIC0+IGR1bXAgc3VyIHJlamV0CgpkZWYgX2JpKHNwLCBpKToKICAgICIiIkxpdCBsJ29jdGV0IGkgZHUgYnVmZmVyIFNQIGVuIEVOVElFUiwgcXVlIHNwIHNvaXQgdW4gYnVmZmVyIGN0eXBlcyAoc3BbaV0gLT4gYnl0ZXMsCiAgICBjZi4gbG9ncyBjYWxpYiAnc2lkZT1iXFx4MDAnKSBvdSB1biBieXRlYXJyYXkgZGUgc2ltdWxhdGlvbiAoc3BbaV0gLT4gaW50KS4gTGEgdjExIGEKICAgIHBsYW50ZSA3OCBwYXJ0aWVzIHN1ciBjZSBwaWVnZSA6IG5lIEpBTUFJUyBsaXJlIHNwW2ldIGRpcmVjdGVtZW50IGRhbnMgZHUgY29kZSBkZSBkdW1wLiIiIgogICAgYiA9IHNwW2ldCiAgICByZXR1cm4gYlswXSBpZiBpc2luc3RhbmNlKGIsIChieXRlcywgYnl0ZWFycmF5KSkgZWxzZSBiCl9oaXN0X2R1bXBzICAgPSBbMF0gICAgICAgIyBuYiBkZSBkdW1wcyBkZXRhaWxsZXMgZGVqYSBlbWlzIHBhciBjZSBwcm9jZXNzdXMgKHBsYWZvbmQgMykKClJBVyA9IHsnSyc6MSwnUSc6MiwnTic6MywnQic6NCwnUic6NSwnUCc6NiwKICAgICAgICdrJzo5LCdxJzoxMCwnbic6MTEsJ2InOjEyLCdyJzoxMywncCc6MTQsICcuJzowfQojIFNocmVkZGVyNy5lbmcgYSBzYSBQUk9QUkUgc3RydWN0dXJlIFNQIChkaWZmZXJlbnRlIGRlIEZyaXR6L0p1bmlvcikgOiBwbGF0ZWF1IGEgU1ArMHgxYyBlbgojIHJhbmstbWFqb3IgKGNvcGllIGRpcmVjdGUgZGUgYmQuc3EpLCBlbmNvZGFnZSBQPTEgTj0yIEI9MyBSPTQgUT01IEs9NiAoTm9pcnMgKzgpLCBwcm9mb25kZXVyIGVuCiMgU1ArMHgxOCAod29yZCksIGRyYXBlYXUtRkVOIFNQKzB4NWM9MCwgdHJhaXQgU1ArMHg1ZCAoIT0wPUJsYW5jcyksIGUucC4gU1ArMHg1ZSwgcm9xdWUgU1ArMHg1ZgojICgweDE9SyAweDI9USAweDQ9ayAweDg9cSkuIERlY291dmVydCB2aWEgbGUgY29uc3RydWN0ZXVyIGRlIEZFTiBpbnRlcm5lICgweDI1ZDApIGR1IC5lbmcuClNIUl9SQVcgPSB7J1AnOjEsJ04nOjIsJ0InOjMsJ1InOjQsJ1EnOjUsJ0snOjYsCiAgICAgICAgICAgJ3AnOjksJ24nOjEwLCdiJzoxMSwncic6MTIsJ3EnOjEzLCdrJzoxNCwgJy4nOjB9CmRlZiBfc2hyZWRkZXJfZmVlZChiZCwgc3ApOgogICAgZm9yIGkgaW4gcmFuZ2UoNjQpOiAgICAgICAgICAgICAgICAgICAgICAjIGJkLnNxW2ldIHJhbmstbWFqb3IgKGExPTApIC0+IFNQKzB4MWMraSAobWVtZSBvcmRyZSkKICAgICAgICBzcFsweDFjICsgaV0gPSBTSFJfUkFXW2JkLnNxW2ldXQogICAgc3BbMHg1Y10gPSAwICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIDAgPSBjb25zdHJ1aXJlIGxlIEZFTiBkZXB1aXMgbGUgcGxhdGVhdQogICAgc3BbMHg1ZF0gPSAxIGlmIGJkLndoaXRlIGVsc2UgMCAgICAgICAgICAjICE9MCA9IHRyYWl0IGF1eCBCbGFuY3MKICAgIHNwWzB4NWVdID0gMCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBlLnAuIChzaW1wbGlmaWUgOiBwYXMgZGUgcHJpc2UgZW4gcGFzc2FudCB0cmFuc21pc2UpCiAgICBjciA9IDAKICAgIGlmICdLJyBpbiBiZC5jYXN0bGU6IGNyIHw9IDB4MDEKICAgIGlmICdRJyBpbiBiZC5jYXN0bGU6IGNyIHw9IDB4MDIKICAgIGlmICdrJyBpbiBiZC5jYXN0bGU6IGNyIHw9IDB4MDQKICAgIGlmICdxJyBpbiBiZC5jYXN0bGU6IGNyIHw9IDB4MDgKICAgIHNwWzB4NWZdID0gY3IKICAgIHNwWzB4NDYyXSA9IDAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBkaXNwYXRjaGVyIDB4MjhlMCA6IHBhcyBkZSBzb3VzLWNvbW1hbmRlCiAgICBpZiBDQUxJQjoKICAgICAgICBsb2coZiJmZWVkW1NIUl0gc2lkZT17c3BbMHg1ZF19IGNhc3RsZT17Y3I6I3h9IGExPXtzcFsweDFjXX0gZTE9e3NwWzB4MjBdfSAiCiAgICAgICAgICAgIGYiZTg9e3NwWzB4NThdfSBhOD17c3BbMHg1NF19IikKCmRlZiBib2FyZF90b19lbmdpbmUoYmQsIHNwKToKICAgIGlmIENGRy5nZXQoJ3NocmVkZGVyX3NwJyk6CiAgICAgICAgX3NocmVkZGVyX2ZlZWQoYmQsIHNwKTsgcmV0dXJuCiAgICBmb3IgcmFuayBpbiByYW5nZSg4KToKICAgICAgICBmb3IgZiBpbiByYW5nZSg4KToKICAgICAgICAgICAgc3BbQk9BUkRfT0ZGICsgZio4ICsgcmFua10gPSBSQVdbYmQuc3FbcmFuayo4ICsgZl1dICAgICAjIGZpbGUtbWFqb3IKICAgIHNwW0ZMQUdfT0ZGXSA9IDAKICAgIHNwW1NJREVfT0ZGXSA9IDAgaWYgYmQud2hpdGUgZWxzZSAxCiAgICBzcFtFUF9PRkZdICAgPSAwCiAgICBjciA9IDAKICAgIGlmICdRJyBpbiBiZC5jYXN0bGU6IGNyIHw9IDB4MDEKICAgIGlmICdLJyBpbiBiZC5jYXN0bGU6IGNyIHw9IDB4MDIKICAgIGlmICdxJyBpbiBiZC5jYXN0bGU6IGNyIHw9IDB4MDQKICAgIGlmICdrJyBpbiBiZC5jYXN0bGU6IGNyIHw9IDB4MDgKICAgIHNwW0NBU1RMRV9PRkZdID0gY3IKICAgIHN0cnVjdC5wYWNrX2ludG8oIjxIIiwgc3AsIDB4ODVjLCAwKSAgICAgIyBtb2RlIHBsYXRlYXUtZmluYWwgOiBBVUNVTiBjb3VwIGEgcmVqb3VlciAoRW5nMTEKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBsaXJhaXQgc2lub24gdW4gY29tcHRlIHBlcmltZSAtPiByZWpldSBkZSBkZWNoZXRzKQogICAgaWYgQ0FMSUI6CiAgICAgICAgbG9nKGYiZmVlZCBzaWRlPXtzcFtTSURFX09GRl19IGNhc3RsZT17Y3I6I3h9IGExPXtzcFtCT0FSRF9PRkZdfSAiCiAgICAgICAgICAgIGYiZTE9e3NwW0JPQVJEX09GRiszMl19IGUyPXtzcFtCT0FSRF9PRkYrMzNdfSBlOD17c3BbQk9BUkRfT0ZGKzM5XX0iKQoKIyBDb2RlcyBwaWVjZSBkZSBQUk9NT1RJT04gcG91ciBsJ29jdGV0IDMgZGVzIGVudHJlZXMgZGUgY291cCAobW9kZSBoaXN0X3JlcGxheSkuCiMgSFlQT1RIRVNFIDogbWVtZSBpbmRleGF0aW9uIFJBVy8iWEtRTkJSUFkiIHF1ZSBsZSBwbGF0ZWF1IChRPTIgTj0zIEI9NCBSPTUpLCBsYSB0YWJsZSBkZSBsYQojIGNvcXVpbGxlIEAweDIwMGFjIG1hcHBhbnQgY2VzIGluZGV4IHZlcnMgbGVzIGNvZGVzIERMTCB7MiwzLDcsNn0uIExlIGRlY29kZXVyIDB4NDNkMCBkZSBsYSBETEwKIyBtYXRjaGUgZnJvbS90byAoMTIgYml0cykgY29udHJlIHNlcyBjb3VwcyBMRUdBVVggZXQgY2Fub25pc2UgbHVpLW1lbWUgbGVzIGZsYWdzIGRlcyBjb3VwcwojIG9yZGluYWlyZXMgKHJvcXVlLCBlLnAuIGNvbXByaXMpIDsgc2V1bGVzIGxlcyBwcm9tb3Rpb25zIGdhcmRlbnQgbm9zIGJpdHMuIFVuIGNvZGUgZXJyb25lID0KIyBOZXdNb3ZlIHJlZnVzZSA9IEVuZzExIHJlbmQgMCA9IEVuZzkgbmUgY2hlcmNoZSBQQVMgLT4gY291dmVydCBwYXIgbGUgcmVwbGkgZGUgZG9fc2VhcmNoLgojID4+PiBBIFZBTElERVIgZW4gY2FsaWJyYXRpb24gYXZlYyB1bmUgcGFydGllIGNvbnRlbmFudCB1bmUgcHJvbW90aW9uICh2b2lyIHRlc3QgZm91cm5pKS4gPDw8CkhJU1RfUFJPTU8gPSB7J3EnOiAyLCAnbic6IDMsICdiJzogNCwgJ3InOiA1fQpISVNUX01BWCAgICA9IDUxMiAgICAgICAgICAgICAgICAjIHpvbmUgU1ArMHg1Yy4uMHg4NWIgPSA1MTIgZW50cmVlcyBkZSA0IG9jdGV0cywgY29tcHRlIGVuIDB4ODVjCkhJU1RfV0lORE9XID0gODAgICAgICAgICAgICAgICAgICMgcGxpZXMgbWF4IHJlam91ZXMgKHF1ZXVlIFJFVkVSU0lCTEUgc2V1bGVtZW50KS4gQ29uc3RhdCBnYXVudGxldAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIDE5LzA4ICgxNTAgaW5jaWRlbnRzKSA6IE5ld01vdmUgcmVmdXNlIHF1YW5kIGwnaGlzdG9yaXF1ZSBjb21wbGV0CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgY29udGllbnQgc2h1ZmZsZXMgYW5jaWVucyBvdSBsb25ndWVzIG1hcmNoZXMgc2FucyBwcmlzZSAtLSBsYSBETEwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBkZWNsYXJlIHNhIHBhcnRpZSBpbnRlcm5lIFRFUk1JTkVFIChyZXBldGl0aW9ucy81MCBjb3VwcyBpbnRlcm5lcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyByZWpldHMgb2JzZXJ2ZXMgfjEwMCBwbGllcyBhcHJlcyBsYSBkZXJuaWVyZSBwcmlzZSkgZXQgcmVmdXNlIHRvdXQKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBjb3VwIHN1aXZhbnQuIFVuZSBwb3NpdGlvbiBuZSBwb3V2YW50IGphbWFpcyByZXBldGVyIHVuZSBwb3NpdGlvbgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIGFudGVyaWV1cmUgYXUgZGVybmllciBjb3VwIGlycmV2ZXJzaWJsZSAocHJpc2UvcGlvbiksIG5lIHJlam91ZXIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBxdWUgY2V0dGUgcXVldWUgZXN0IGEgbGEgZm9pcyBTVUZGSVNBTlQgcG91ciBsYSBkZXRlY3Rpb24gZGVzCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgcmVwZXRpdGlvbnMgZXQgTkVDRVNTQUlSRSBwb3VyIG5lIHBhcyBkZWNsZW5jaGVyIGxlIGdhbWUtb3Zlci4KCmRlZiBoaXN0b3J5X3RvX2VuZ2luZShzcCk6CiAgICAiIiJBbGltZW50YXRpb24gZmFjb24gaW50ZXJmYWNlIE5BVElWRSA6IHBsYXRlYXUgZGUgQkFTRSArIGxpc3RlIGRlcyBjb3VwcyBqb3VlcywgbGUgbW90ZXVyCiAgICByZWpvdWUgdG91dGUgbGEgcGFydGllIGV0IHJlY29uc3RydWl0IHNvbiBoaXN0b3JpcXVlIGludGVybmUgKGRldGVjdGlvbiBkZXMgdHJpcGxlcwogICAgcmVwZXRpdGlvbnMgKyByZWdsZSBkZXMgNTAgY291cHMpLiBEZXV4IHZhcmlhbnRlcyBzZWxvbiBDRkdbJ2hpc3RfcmVwbGF5J10gOgoKICAgICAgJ3NoZWxsJy9UcnVlIChIaWFyY3MgOCwgRW5nMTEgQDB4MjEzMCBkZSBsYSBjb3F1aWxsZSkgOgogICAgICAgIFNQKzB4NTggIT0gMCAtPiBOZXdQb3NpdGlvbihzdGFydHBvcyBpbnRlcm5lKSA7ID09IDAgLT4gRkVOIGNvbnN0cnVpdCBkdSBwbGF0ZWF1IFNQLgogICAgICAgIExhIERMTCByZS1tYXRjaGUgY2hhcXVlIGNvdXAgY29udHJlIHNvbiBnZW5lcmF0ZXVyIGxlZ2FsIChmbGFncyBjYW5vbmlzZXMgc2F1ZiBwcm9tbykuCiAgICAgICdpbmxpbmUnIChGcml0eiA4IEAweDQxY2EgLyBGcml0eiA5IEAweDEzNmIwLCBtb3RldXJzIG1vbm9saXRoaXF1ZXMpIDoKICAgICAgICBUT1VKT1VSUyBmbGFnIDB4NTggPSAwICsgcGxhdGVhdSBkZSBCQVNFIGVjcml0IChsYSBzZW1hbnRpcXVlIGZsYWchPTAgbid5IGVzdCBQQVMKICAgICAgICB2ZXJpZmllZSkuIExhIGJvdWNsZSBkZSByZWpldSBOJ0VGRkVDVFVFIEFVQ1VORSBWQUxJREFUSU9OIDogZWxsZSBkaXNwYXRjaCBzdXIgbCdvY3RldAogICAgICAgIGRlIGZsYWdzIC0+IGlscyBkb2l2ZW50IGV0cmUgRVhBQ1RTIChyb3F1ZSAweDIwLCBlLnAuIG5pYmJsZSBiYXMsIHByb21vIDB4NDArY29kZSBSQVcKICAgICAgICBvY3RldCAzKSwgc2lub24gY29ycnVwdGlvbiBzaWxlbmNpZXVzZSBkZSBsYSBwb3NpdGlvbiBpbnRlcm5lLiBDYXNlcyBmaWxlLW1ham9yIHNhbnMKICAgICAgICB0cmFuc2Zvcm1hdGlvbiAodmVyaWZpZSA6IGxhIGJvdWNsZSBwYXNzZSBmcm9tL3RvIHRlbHMgcXVlbHMgYXUgbWFrZS1tb3ZlIDB4MWI1MGUpLgoKICAgIE5FIFJFSk9VRSBRVUUgTEEgUVVFVUUgUkVWRVJTSUJMRSAoZGVwdWlzIGxlIGRlcm5pZXIgY291cCBkZSBwaW9uL3ByaXNlLCBjYXAKICAgIEhJU1RfV0lORE9XKSA6IHN1ZmZpc2FudCBwb3VyIGxlcyByZXBldGl0aW9ucywgZXQgZXZpdGUgbGUgZ2FtZS1vdmVyIGludGVybmUgZGUgbGEKICAgIERMTCAoMTUwIHJlamV0cyBOZXdNb3ZlIGNvbnN0YXRlcyBhdSBnYXVudGxldCBkdSAxOS8wOCBzdXIgcmVqZXV4IGludGVncmF1eCkuCiAgICBGb3JtYXQgY29tbXVuIGRlcyBlbnRyZWVzIChTUCsweDVjICsgNCppLCBjb21wdGUgd29yZCBlbiBTUCsweDg1YywgbWF4IDUxMikgOgogICAgICAgIFtmcm9tXVt0b11bZmxhZ3NdW3BpZWNlXSA7IGZsYWdzIDogMD1vcmRpbmFpcmUsIDB4MjA9cm9xdWUsIDB4MDE9cHJpc2UgZW4gcGFzc2FudCwKICAgICAgICAweDQwPXByb21vdGlvbiAocGllY2UgPSBISVNUX1BST01PLCBjb2RlcyBSQVcgdmFsaWRlcyBlbiBydW50aW1lIFQyIEhpYXJjcykuCiAgICBMZXMgZmxhZ3MgZW5yaWNoaXMgc29udCBzYW5zIGVmZmV0IGNoZXogSGlhcmNzIChzZXVsIGxlIGJpdCAweDQwIHkgZXN0IGx1KS4KICAgIFJldG91cm5lIFRydWUgc2kgYXBwbGlxdWUgOyBGYWxzZSAtPiBsJ2FwcGVsYW50IHNlIHJlcGxpZSBzdXIgYm9hcmRfdG9fZW5naW5lLiIiIgogICAgaWYgb3MuZW52aXJvbi5nZXQoJ0VORzJVQ0lfSElTVCcsICcxJykgPT0gJzAnOgogICAgICAgIHJldHVybiBGYWxzZQogICAgaWYgbm90IGdhbWVfbW92ZXM6CiAgICAgICAgcmV0dXJuIEZhbHNlICAgICAgICAgICAgICAgICAgICAgIyByaWVuIGEgcmVqb3VlciAtPiBwbGF0ZWF1IGZpbmFsCiAgICBtb2RlID0gQ0ZHLmdldCgnaGlzdF9yZXBsYXknKQogICAgIyAtLS0gVHJvbmNhdHVyZSBhIGxhIHF1ZXVlIHJldmVyc2libGUgOiB0cm91dmVyIGxlIGRlcm5pZXIgY291cCBpcnJldmVyc2libGUgKHByaXNlLAogICAgIyBjb3VwIGRlIHBpb24gLS0gcHJvbW90aW9ucyBjb21wcmlzZXMpIDsgbGEgYmFzZSBkZSByZWpldSBlc3QgbGEgcG9zaXRpb24gcXVpIGxlIFNVSVQuCiAgICBzY3JhdGNoID0gQm9hcmQoKTsgc2NyYXRjaC5zZXRfZmVuKGdhbWVfYmFzZV9mZW4gb3IgU1RBUlRfRkVOKQogICAgY3V0ID0gMCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgaW5kZXggZHUgMWVyIGNvdXAgZGUgbGEgcXVldWUgZGFucyBnYW1lX21vdmVzCiAgICBmb3IgaSwgbXYgaW4gZW51bWVyYXRlKGdhbWVfbW92ZXMpOgogICAgICAgIGZmLCBmciA9IEZJTEVTLmluZGV4KG12WzBdKSwgaW50KG12WzFdKSAtIDEKICAgICAgICB0ZiwgdHIgPSBGSUxFUy5pbmRleChtdlsyXSksIGludChtdlszXSkgLSAxCiAgICAgICAgcGMsIHRndCA9IHNjcmF0Y2guc3FbZnIqOCArIGZmXSwgc2NyYXRjaC5zcVt0cio4ICsgdGZdCiAgICAgICAgaWYgcGMgaW4gJ1BwJyBvciB0Z3QgIT0gJy4nOiAgICAgIyBwaW9uIChjb3V2cmUgcHJvbW8gKyBlLnAuIGRpYWcpIG91IHByaXNlCiAgICAgICAgICAgIGN1dCA9IGkgKyAxCiAgICAgICAgc2NyYXRjaC5hcHBseV91Y2kobXYpCiAgICB0YWlsID0gZ2FtZV9tb3Zlc1tjdXQ6XQogICAgaWYgbGVuKHRhaWwpID4gSElTVF9XSU5ET1c6ICAgICAgICAgICMgcGxhZm9uZCBhbnRpLTUwLWNvdXBzIGludGVybmUgOiBnYXJkZXIgbGEgZmluCiAgICAgICAgY3V0ICs9IGxlbih0YWlsKSAtIEhJU1RfV0lORE9XCiAgICAgICAgdGFpbCA9IGdhbWVfbW92ZXNbY3V0Ol0KICAgICMgdjE0ICgyMS8wOCkgOiBsZSAic3VmZml4ZSBzYW5zIHJlcGV0aXRpb24iIGRlIGxhIHYxMCBlc3QgU1VQUFJJTUUuIElsIHJlcG9uZGFpdCBhIGRlcwogICAgIyByZWZ1cyBOZXdNb3ZlIGRvbnQgbGVzIHNvbmRlcyAxLTMgb250IHByb3V2ZSBxdSdpbHMgbidvbnQgamFtYWlzIGV4aXN0ZSAoZmF1c3NlcyBhbGVydGVzCiAgICAjIGR1IGdhcmRlLWZvdSBlbiBtb2RlIElOTkVSVElNRSkgLS0gZXQgaWwgY291dGFpdCBjaGVyIDogZGFucyBsZXMgbWFub2V1dnJlcyBkZSBmaW5hbGUgaWwKICAgICMgcmVkdWlzYWl0IGwnaGlzdG9yaXF1ZSBhIDEtNSBjb3VwcywgYWZmYW1hbnQgbGEgZGV0ZWN0aW9uIGRlcyByZXBldGl0aW9ucyBxdSdpbCBwcmV0ZW5kYWl0CiAgICAjIHNlcnZpci4gT24gcmV2aWVudCBhIGxhIHF1ZXVlIHJldmVyc2libGUgY29tcGxldGUgKGNhcCBISVNUX1dJTkRPVyksIHRyb25jYXR1cmUgU0FOUyBQRVJURQogICAgIyBlY2hpcXVlZW5uZSA6IGF1Y3VuZSBwb3NpdGlvbiBuZSBwZXV0IHJlcGV0ZXIgcXVvaSBxdWUgY2Ugc29pdCBkJ2FudGVyaWV1ciBhdSBkZXJuaWVyIGNvdXAKICAgICMgaXJyZXZlcnNpYmxlLgogICAgbiA9IGxlbih0YWlsKQogICAgaWYgbiA9PSAwOgogICAgICAgIHJldHVybiBGYWxzZSAgICAgICAgICAgICAgICAgICAgICMgZGVybmllciBjb3VwIGlycmV2ZXJzaWJsZSA9IGRlcm5pZXIgY291cCBqb3VlIDoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIGF1Y3VuZSByZXBldGl0aW9uIHBvc3NpYmxlIC0+IHBsYXRlYXUgZmluYWwgc3VmZml0CiAgICAjIC0tLSBCYXNlIGRlIHJlamV1ID0gcG9zaXRpb24gYXByZXMgZ2FtZV9tb3Zlc1s6Y3V0XSAtLS0KICAgIHNjcmF0Y2ggPSBCb2FyZCgpOyBzY3JhdGNoLnNldF9mZW4oZ2FtZV9iYXNlX2ZlbiBvciBTVEFSVF9GRU4pCiAgICBmb3IgbXYgaW4gZ2FtZV9tb3Zlc1s6Y3V0XToKICAgICAgICBzY3JhdGNoLmFwcGx5X3VjaShtdikKICAgIGlmIG1vZGUgPT0gJ2lubGluZScgb3IgZ2FtZV9iYXNlX2ZlbiBpcyBub3QgTm9uZSBvciBjdXQgPiAwOgogICAgICAgICMgcGxhdGVhdSBkZSBCQVNFICsgdHJhaXQvcm9xdWUgOyBmbGFnPTAgLT4gbGUgbW90ZXVyL2xhIGNvcXVpbGxlIHBhcnQgZGUgY2UgcGxhdGVhdQogICAgICAgIGZvciByYW5rIGluIHJhbmdlKDgpOgogICAgICAgICAgICBmb3IgZiBpbiByYW5nZSg4KToKICAgICAgICAgICAgICAgIHNwW0JPQVJEX09GRiArIGYqOCArIHJhbmtdID0gUkFXW3NjcmF0Y2guc3FbcmFuayo4ICsgZl1dCiAgICAgICAgc3BbRkxBR19PRkZdID0gMAogICAgICAgIHNwW1NJREVfT0ZGXSA9IDAgaWYgc2NyYXRjaC53aGl0ZSBlbHNlIDEKICAgICAgICBpZiBtb2RlID09ICdpbmxpbmUnOgogICAgICAgICAgICBzcFtFUF9PRkZdID0gMCAgICAgICAgICAgICAgICMgZW5jb2RhZ2UgMHg1YSBOT04gdmVyaWZpZSBjaGV6IEZyaXR6IDsgbmUgY29tcHRlIHF1ZSBzaQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgbGUgMWVyIGNvdXAgcmVqb3VlIGVzdCB1bmUgcHJpc2UgZS5wLiBkZXB1aXMgdW5lIEZFTiBkZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgYmFzZSAtPiBjYXMgaW5leGlzdGFudCBlbiB0b3Vybm9pIChzdGFydHBvcyttb3ZlcykKICAgICAgICBlbHNlOgogICAgICAgICAgICBzcFtFUF9PRkZdID0gKHNjcmF0Y2guZXAgJSA4KSArIDEgaWYgc2NyYXRjaC5lcCBpcyBub3QgTm9uZSBlbHNlIDAgICMgY29sb25uZSAxLi44CiAgICAgICAgY3IgPSAwCiAgICAgICAgaWYgJ1EnIGluIHNjcmF0Y2guY2FzdGxlOiBjciB8PSAweDAxCiAgICAgICAgaWYgJ0snIGluIHNjcmF0Y2guY2FzdGxlOiBjciB8PSAweDAyCiAgICAgICAgaWYgJ3EnIGluIHNjcmF0Y2guY2FzdGxlOiBjciB8PSAweDA0CiAgICAgICAgaWYgJ2snIGluIHNjcmF0Y2guY2FzdGxlOiBjciB8PSAweDA4CiAgICAgICAgc3BbQ0FTVExFX09GRl0gPSBjcgogICAgZWxzZToKICAgICAgICBzcFtGTEFHX09GRl0gPSAxICAgICAgICAgICAgICAgICAjIGNvcXVpbGxlIEhpYXJjcyA6IE5ld1Bvc2l0aW9uKHN0YXJ0cG9zKSwgcGxhdGVhdSBpZ25vcmUKICAgIG9mZiA9IDB4NWMKICAgIGZvciBtdiBpbiB0YWlsOgogICAgICAgIGZmLCBmciA9IEZJTEVTLmluZGV4KG12WzBdKSwgaW50KG12WzFdKSAtIDEKICAgICAgICB0ZiwgdHIgPSBGSUxFUy5pbmRleChtdlsyXSksIGludChtdlszXSkgLSAxCiAgICAgICAgaWYgZmYgPT0gdGYgYW5kIGZyID09IHRyOgogICAgICAgICAgICByZXR1cm4gRmFsc2UgICAgICAgICAgICAgICAgICMgY291cCBudWwgKCIwMDAwIikgOiBqYW1haXMgbGVnYWwgLT4gcmVwbGkgcGxhdGVhdSBmaW5hbAogICAgICAgIGZybSA9IChmZiA8PCAzKSB8IGZyICAgICAgICAgICAgICMgZmlsZS1tYWpvciwgY29tbWUgc3Ffb3V0L2RlY29kZV9tb3ZlCiAgICAgICAgdG8gID0gKHRmIDw8IDMpIHwgdHIKICAgICAgICBwYyAgPSBzY3JhdGNoLnNxW2ZyKjggKyBmZl0gICAgICAjIHBpZWNlIEFWQU5UIGFwcGxpY2F0aW9uIChwbGF0ZWF1IHNjcmF0Y2ggcmFuay1tYWpvcikKICAgICAgICBpZiBsZW4obXYpID4gNDoKICAgICAgICAgICAgZmxhZ3MsIHBpZWNlID0gMHg0MCwgSElTVF9QUk9NTy5nZXQobXZbNF0sIDIpCiAgICAgICAgZWxpZiBwYyBpbiAnS2snIGFuZCBhYnModGYgLSBmZikgPT0gMjoKICAgICAgICAgICAgZmxhZ3MsIHBpZWNlID0gMHgyMCwgMCAgICAgICAjIHJvcXVlIChyb2kgZGUgMiBjb2xvbm5lcykKICAgICAgICBlbGlmIHBjIGluICdQcCcgYW5kIGZmICE9IHRmIGFuZCBzY3JhdGNoLnNxW3RyKjggKyB0Zl0gPT0gJy4nOgogICAgICAgICAgICBmbGFncywgcGllY2UgPSAweDAxLCAwICAgICAgICMgcHJpc2UgZW4gcGFzc2FudCAoZGlhZ29uYWxlIHZlcnMgY2FzZSB2aWRlKQogICAgICAgIGVsc2U6CiAgICAgICAgICAgIGZsYWdzLCBwaWVjZSA9IDAsIDAKICAgICAgICBzdHJ1Y3QucGFja19pbnRvKCI8QkJCQiIsIHNwLCBvZmYsIGZybSwgdG8sIGZsYWdzLCBwaWVjZSkKICAgICAgICBvZmYgKz0gNAogICAgICAgIHNjcmF0Y2guYXBwbHlfdWNpKG12KSAgICAgICAgICAgICMgYXZhbmNlciBsZSBwbGF0ZWF1IHNjcmF0Y2ggcG91ciBsZSBjb3VwIHN1aXZhbnQKICAgIHN0cnVjdC5wYWNrX2ludG8oIjxIIiwgc3AsIDB4ODVjLCBuKQogICAgX2hpc3RfblswXSA9IG4KICAgICMgdjEyIDogY29uc2VydmVyIGxlIGZlZWQgZXhhY3QgcG91ciB1biBldmVudHVlbCBkdW1wIGQnaW5jaWRlbnQuIFJFR0xFIEFCU09MVUUgZGVwdWlzIGxlCiAgICAjIGNyYXNoIHYxMSAoNzggcGFydGllcyBmb3JmYWl0cykgOiBjZSBibG9jIGVzdCBkdSBESUFHTk9TVElDIC0tIGlsIGxpdCB2aWEgX2JpKCkgZXQgbmUgcGV1dAogICAgIyBzb3VzIEFVQ1VOIHByZXRleHRlIGxldmVyIHVuZSBleGNlcHRpb24gdmVycyBsYSByZWNoZXJjaGUuCiAgICB0cnk6CiAgICAgICAgcm93cyA9IFtdCiAgICAgICAgZm9yIHJrIGluIHJhbmdlKDcsIC0xLCAtMSk6CiAgICAgICAgICAgIHJvdywgZW1wdHkgPSAiIiwgMAogICAgICAgICAgICBmb3IgZmwgaW4gcmFuZ2UoOCk6CiAgICAgICAgICAgICAgICB2ID0gX2JpKHNwLCBCT0FSRF9PRkYgKyBmbCo4ICsgcmspCiAgICAgICAgICAgICAgICBpZiB2ID09IDA6CiAgICAgICAgICAgICAgICAgICAgZW1wdHkgKz0gMTsgY29udGludWUKICAgICAgICAgICAgICAgIGMgPSAiIi5qb2luKGsgZm9yIGssIGtrIGluIFJBVy5pdGVtcygpIGlmIGtrID09ICh2ICYgNykgYW5kIGsgIT0gJy4nKQogICAgICAgICAgICAgICAgaWYgZW1wdHk6IHJvdyArPSBzdHIoZW1wdHkpOyBlbXB0eSA9IDAKICAgICAgICAgICAgICAgIHJvdyArPSAoYy5sb3dlcigpIGlmIHYgJiA4IGVsc2UgYykKICAgICAgICAgICAgaWYgZW1wdHk6IHJvdyArPSBzdHIoZW1wdHkpCiAgICAgICAgICAgIHJvd3MuYXBwZW5kKHJvdykKICAgICAgICBvY3RzID0gYnl0ZXMoX2JpKHNwLCAweDVjICsgaikgZm9yIGogaW4gcmFuZ2UoNCpuKSkKICAgICAgICBfaGlzdF9mZWVkWzBdID0gZGljdCgKICAgICAgICAgICAgYmFzZT0iLyIuam9pbihyb3dzKSArICgiIHciIGlmIF9iaShzcCwgU0lERV9PRkYpID09IDAgZWxzZSAiIGIiKQogICAgICAgICAgICAgICAgICsgZiIgY2FzdGxlPXtfYmkoc3AsIENBU1RMRV9PRkYpOiMwNHh9IGVwPXtfYmkoc3AsIEVQX09GRil9IGZsYWc9e19iaShzcCwgRkxBR19PRkYpfSIsCiAgICAgICAgICAgIHRhaWw9bGlzdCh0YWlsKSwKICAgICAgICAgICAgb2N0ZXRzPW9jdHMuaGV4KCkpCiAgICBleGNlcHQgRXhjZXB0aW9uIGFzIGU6CiAgICAgICAgX2hpc3RfZmVlZFswXSA9IGRpY3QoYmFzZT1mIihjYXB0dXJlIGltcG9zc2libGU6IHtlIXJ9KSIsIHRhaWw9bGlzdCh0YWlsKSwgb2N0ZXRzPSI\/IikKICAgIGlmIENBTElCOgogICAgICAgIGxvZyhmIltoaXN0Onttb2RlIGlmIG1vZGUgIT0gVHJ1ZSBlbHNlICdzaGVsbCd9XSByZWpldSBkZSB7bn0ve2xlbihnYW1lX21vdmVzKX0gY291cHMgIgogICAgICAgICAgICBmIihxdWV1ZSByZXZlcnNpYmxlIGRlcHVpcyBsZSBwbHkge2N1dH0sIGRlcm5pZXI6IHt0YWlsWy0xXX0pIikKICAgIHJldHVybiBUcnVlCgojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CiMgIFN0dWIgQ2hlc3MzMi5kbGwgKyBjYWxsYmFjawojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CkNCX1RZUEUgPSBjdHlwZXMuQ0ZVTkNUWVBFKGN0eXBlcy5jX2ludCwgY3R5cGVzLmNfaW50LCBjdHlwZXMuY19pbnQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGN0eXBlcy5jX2ludCwgY3R5cGVzLmNfdm9pZF9wKQpzdHViID0gb3MucGF0aC5qb2luKEhFUkUsICJDaGVzczMyLmRsbCIpCmlmIG5vdCBvcy5wYXRoLmV4aXN0cyhzdHViKToKICAgIHN5cy5zdGRlcnIud3JpdGUoIkZBVEFMOiBDaGVzczMyLmRsbCAoc3R1YikgYWJzZW50IGEgY290ZSBkZSBlbmcydWNpLnB5XG4iKTsgc3lzLmV4aXQoMSkKaFN0dWIgPSBrMzIuTG9hZExpYnJhcnlBKHN0dWIuZW5jb2RlKCkpCl9zZXRfY2IgPSBjdHlwZXMuQ0ZVTkNUWVBFKE5vbmUsIENCX1RZUEUpKGszMi5HZXRQcm9jQWRkcmVzcyhoU3R1YiwgYiJDaGVzczMyX1NldENhbGxiYWNrIikpCgpjbGFzcyBTdDogYmVzdD1Ob25lOyBkZXB0aD0wOyBzY29yZT0wOyBzZWFyY2hpbmc9RmFsc2U7IHQwPTAuMDsgbGFzdF9lbWl0PU5vbmU7IGJlc3RfcHY9Tm9uZTsgcmVxX2RlcHRoPTA7IG5vZGUwPTA7IGJlc3Rfc2NvcmVfc2Vlbj0tMjAwMDAwMDAwMDsgYXJnbWF4X2RlcHRoPS0xOyBqcl9tb3ZlPU5vbmU7IGpyX2N0eD0wOyBqcl9wdj1Ob25lOyBqcl9ub2Rlcz0wOyBqcl9zY29yZT0wOyBqcl9zY29yZV9raW5kPTE7IGpyX2FsdD1Ob25lOyBmel9tb3ZlPU5vbmU7IGZ6X3Njb3JlPTA7IGZ6X3JzY29yZT0wOyBmel9ya2luZD0xOyBmel9ybW92ZT1Ob25lOyBiZXN0bW92ZV9zZW50PUZhbHNlCnN0ID0gU3QoKQoKZGVmIHNxX291dChzcSk6ICAgICAgICAgICAgICAgICAgIyBTT1JUSUUgOiBmaWxlLW1ham9yCiAgICBzcSAmPSAweDNGCiAgICByZXR1cm4gRklMRVNbc3EgPj4gM10gKyBzdHIoKHNxICYgNykgKyAxKQoKIyBlbnRyZWUgZGUgY291cCA0IG9jdGV0cy4gUHJvbW90aW9uIDogYml0NyBkJ3VuIG9jdGV0IGRlIGZsYWdzLCAoZmxhZ3M+PjUpJjMgLT4KIyAwPUMgMT1EIDI9VCAzPUYgKGlkZW50aXF1ZSBzdXIgbGVzIDQpLiA2LzcvOCA6IGZsYWdzPWJ5dGUyLCBjYXNlcyBmaWxlLW1ham9yLgojIDUuMzIgOiBmbGFncz1ieXRlMywgY2FzZXMgcmFuay1tYWpvciAoYml0cyBlY2hhbmdlcykuCiMgTk9URSAxOS8wOC8yMDI2IDogY2V0IG9yZHJlIGVzdCBDT05GSVJNRSBlbiBydW50aW1lIHBvdXIgbGEgU09SVElFICh0ZXN0IEsrUCwgYW5jaWVuCiMgYWRhcHRhdGV1ciwgImdvIGRlcHRoIiAtPiBlN2U4cSBhdmVjIGluZGV4IDEgPSBEKS4gTkUgUEFTIGNvbmZvbmRyZSBhdmVjIGxhIHRhYmxlIGRlCiMgUkVKRVUgZW4gZW50cmVlIChvY3RldCAzLCBjb2RlcyBSQVcgUT0yIE49MyBCPTQgUj01IC0+IHR5cGVzIGludGVybmVzIDB4ODAvMHhhMC8weGMwLzB4ZTAsCiMgZGVzYXNzZW1ibGFnZSBGcml0eiA4IEAweDQyNTAgLyBGcml0eiA5IEAweDEzNzE2KSA6IGZvcm1hdHMgZGlzdGluY3RzLiBMZXMgdHJvaXMgIj1DIgojIGR1IFBHTiBkdSAxOS8wOCAoZzMvZzIyL2cyMywgc2NvcmVzIGRlIG1hdCkgcmVzdGVudCBpbmV4cGxpcXVlcyAtPiBlbnF1ZXRlIGVuIGNvdXJzLgpQUk9NT19UQkwgPSBbIm4iLCAicSIsICJyIiwgImIiXQpkZWYgZGVjb2RlX21vdmUoZW50cnkpOgogICAgZnJtID0gZW50cnkgJiAweEZGOyB0byA9IChlbnRyeSA+PiA4KSAmIDB4RkYKICAgIGlmIENGRy5nZXQoJ3N3YXBfc3EnKTogICAgICAgICAgICAgICAgICAgICAgICMgNS4zMgogICAgICAgIGZybSA9ICgoZnJtICYgNykgPDwgMykgfCAoKGZybSA+PiAzKSAmIDcpCiAgICAgICAgdG8gID0gKCh0byAgJiA3KSA8PCAzKSB8ICgodG8gID4+IDMpICYgNykKICAgICAgICBmbGFncyA9IChlbnRyeSA+PiAyNCkgJiAweEZGCiAgICBlbHNlOiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIDYvNy84CiAgICAgICAgZmxhZ3MgPSAoZW50cnkgPj4gMTYpICYgMHhGRgogICAgIyBQcm9tb3Rpb24gOiBiaXQ3IGRlcyBmbGFncyBDSEVaIEZSSVRaLiBNYWlzIGNoZXogR2FtYml0L0NoZXNzIFRpZ2VyIGNlIGJpdCBzaWduYWxlIHVuZSBDQVBUVVJFCiAgICAjIChkJ291ICJiN2E4biIsICJkNWU0biIgZW4gcGFydGllIC0+IGNvdXBzIHJlamV0ZXMpLiBQb3VyIGNlcyBtb3RldXJzIChjYXBfYml0ODApLCBkZWNvZGVfbW92ZQogICAgIyBuJ2Fqb3V0ZSBBVUNVTkUgcHJvbW90aW9uIDogYydlc3QgbGUgZmlsZXQtcGlvbiBkZSBfanJfcmVhZF9tb3ZlICh2ZXJpZmllIHF1ZSBsYSBwaWVjZSBkZSBkZXBhcnQKICAgICMgZXN0IHVuIHBpb24gdmlhIGwnZWNoaXF1aWVyIGNvdXJhbnQpIHF1aSBwb3NlIGxhIHZyYWllIHByb21vdGlvbiBzdXIgbGUgY291cCBqb3VlLgogICAgaWYgQ0ZHLmdldCgnY2FwX2JpdDgwJyk6CiAgICAgICAgcHJvbW8gPSAiIgogICAgZWxzZToKICAgICAgICBfcmYsIF9ydCA9IGZybSAmIDcsIHRvICYgNwogICAgICAgIHByb21vID0gKFBST01PX1RCTFsoZmxhZ3MgPj4gNSkgJiAzXQogICAgICAgICAgICAgICAgIGlmIChmbGFncyAmIDB4ODApIGFuZCAoKF9yZiwgX3J0KSBpbiAoKDYsIDcpLCAoMSwgMCkpKSBlbHNlICIiKQogICAgaWYgZnJtID09IHRvIG9yIGZybSA+IDYzIG9yIHRvID4gNjM6CiAgICAgICAgcmV0dXJuIE5vbmUKICAgIHJldHVybiBzcV9vdXQoZnJtKSArIHNxX291dCh0bykgKyBwcm9tbwoKZGVmIF9qcl9yZWFkX21vdmUoY3R4KToKICAgICMgSnVuaW9yIDogbGUgbWVzc2FnZSAweDE1NCAocmFwcG9ydCBvZmZpY2llbCAibWVpbGxldXJlIGxpZ25lIiBhdSBHVUkpIHBvcnRlIGxlIGNvdXAKICAgICMgcmFjaW5lIGVuIGN0eCsweDVjIChkZXBhcnQpIC8gKzB4NWQgKGFycml2ZWUpIDsgZW5jb2RhZ2UgZmlsZS1tYWpvciAoY2FzZSA9IGZpbGUqOCtyYW5nKSwKICAgICMgSURFTlRJUVVFIGEgRnJpdHogNi83LzggLT4gb24gcmV1dGlsaXNlIGRlY29kZV9tb3ZlIGVuIGVtcGFxdWV0YW50IGxlcyBvY3RldHMuCiAgICAjIENvbmZpcm1lIHBhciBjb3JyZWxhdGlvbiA6IG1hdCBmb3JjZSAtPiBjdHgrMHg1Yy8weDVkID0gM2MgMmUgPSBoNWY3ID0gRHhmNyMuCiAgICB0cnk6CiAgICAgICAgYiA9IGJ5dGVzKChjdHlwZXMuY191Ynl0ZSAqIDMpLmZyb21fYWRkcmVzcyhjdHggKyAweDVjKSkKICAgIGV4Y2VwdCBFeGNlcHRpb246CiAgICAgICAgcmV0dXJuIE5vbmUKICAgIGZybSwgdG8sIGZsZyA9IGJbMF0sIGJbMV0sIGJbMl0KICAgIGlmIGZybSA9PSB0byBvciBmcm0gPiA2MyBvciB0byA+IDYzOgogICAgICAgIHJldHVybiBOb25lCiAgICBtdiA9IGRlY29kZV9tb3ZlKGZybSB8ICh0byA8PCA4KSB8IChmbGcgPDwgMTYpKSAgICMgZGVjb2RhZ2UgRnJpdHogOiBmaWxlLW1ham9yICsgcHJvbW8KICAgIGlmIG12IGFuZCBsZW4obXYpID09IDQ6ICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgZmlsZXQgcHJvbW90aW9uIDogcGlvbiAtPiBkZXJuaWVyZSByYW5nZWUKICAgICAgICB0cnk6CiAgICAgICAgICAgIGlmIGJvYXJkLnNxWyhmcm0gJiA3KSAqIDggKyAoZnJtID4+IDMpXSBpbiAnUHAnIGFuZCAodG8gJiA3KSBpbiAoMCwgNyk6CiAgICAgICAgICAgICAgICBtdiArPSAncScgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIGRhbWUgcGFyIGRlZmF1dCAoc291cy1wcm9tbyA6IGEgcmFmZmluZXIpCiAgICAgICAgZXhjZXB0IEV4Y2VwdGlvbjoKICAgICAgICAgICAgcGFzcwogICAgcmV0dXJuIG12CgpkZWYgX2pyX3JlYWRfcHYoY3R4LCBtYXhsZW49MTIpOgogICAgIyBQViBjb21wbGV0ZSA6IGxvbmd1ZXVyIGVuIGN0eCsweDVhICgxNiBiaXRzKSwgcHVpcyBOIGVudHJlZXMgZGUgNCBvY3RldHMgYSBwYXJ0aXIgZGUKICAgICMgY3R4KzB4NWMgKGZyb20sIHRvLCBwcm9tby9mbGFncywgZmxhZykuIENvbmZpcm1lIDogbWF0IC0+IE49MSA7IG91dmVydHVyZSAtPiBOPTIuCiAgICB0cnk6CiAgICAgICAgbiA9IHN0cnVjdC51bnBhY2soIjxIIiwgKGN0eXBlcy5jX3VieXRlICogMikuZnJvbV9hZGRyZXNzKGN0eCArIDB4NWEpKVswXQogICAgZXhjZXB0IEV4Y2VwdGlvbjoKICAgICAgICBuID0gMAogICAgb3V0ID0gW10KICAgIGlmIDEgPD0gbiA8PSA2NDoKICAgICAgICBmb3IgaSBpbiByYW5nZShtaW4obiwgbWF4bGVuKSk6CiAgICAgICAgICAgIHRyeToKICAgICAgICAgICAgICAgIGIgPSBieXRlcygoY3R5cGVzLmNfdWJ5dGUgKiAzKS5mcm9tX2FkZHJlc3MoY3R4ICsgMHg1YyArIDQgKiBpKSkKICAgICAgICAgICAgZXhjZXB0IEV4Y2VwdGlvbjoKICAgICAgICAgICAgICAgIGJyZWFrCiAgICAgICAgICAgIGZybSwgdG8sIGZsZyA9IGJbMF0sIGJbMV0sIGJbMl0KICAgICAgICAgICAgaWYgZnJtID09IHRvIG9yIGZybSA+IDYzIG9yIHRvID4gNjM6CiAgICAgICAgICAgICAgICBicmVhawogICAgICAgICAgICBtdiA9IGRlY29kZV9tb3ZlKGZybSB8ICh0byA8PCA4KSB8IChmbGcgPDwgMTYpKQogICAgICAgICAgICBpZiBub3QgbXY6CiAgICAgICAgICAgICAgICBicmVhawogICAgICAgICAgICBvdXQuYXBwZW5kKG12KQogICAgcmV0dXJuIG91dAoKZGVmIF9qcl9yZWFkX3Njb3JlKGN0eCk6CiAgICAjIEp1bmlvciA6IGwnb2JqZXQtcmFwcG9ydCBkdSBtZXNzYWdlIDB4MTU0IHBvcnRlIGwnZXZhbHVhdGlvbiBlbiBQQUlSRSA6CiAgICAjICAgY3R4KzB4Mjc2OCAoaW50MTYpID0gdmFsZXVyIDsgY3R4KzB4Mjc2YSAoaW50MTYpID0gdHlwZSAoMT1jZW50aXBpZWNlcywgMj1tYXQpLgogICAgIyBDb25maXJtZSBwYXIgY29ycmVsYXRpb24gU1VSIFBPU0lUSU9OUyBBVSBUUkFJVCBCTEFOQyA6IDEuZTQgZTUgLT4gdHlwZT0xIHZhbGV1cj0rMTkgKGNwKSA7CiAgICAjIER4ZjcjIC0+IHR5cGU9MiB2YWxldXI9MSAobWF0IGVuIDEpLiBBVFRFTlRJT04gOiBjZXMgZGV1eCBjYXMgbmUgZGlzdGluZ3VlbnQgUEFTCiAgICAjICJwZXJzcGVjdGl2ZSBkdSB0cmFpdCIgZGUgInBlcnNwZWN0aXZlIGFic29sdWUtQmxhbmNzIiAobWVtZSBzaWduZSBhdXggQmxhbmNzKS4gU2kgdW5lCiAgICAjIHZhbGlkYXRpb24gQVUgVFJBSVQgTk9JUiBtb250cmUgZGVzIHNjb3JlcyBpbnZlcnNlcywgbWV0dHJlIGpyX3dwZXJzcGVjdGl2ZT1UcnVlIGRhbnMgbGEKICAgICMgY29uZmlnIDogb24gbmVnYXRpZSBhbG9ycyB2YWwgcXVhbmQgYydlc3QgYXV4IE5vaXJzIChjb3JyaWdlIGNwIEVUIG1hdCwgY29tbWUgRnJpdHogOSkuCiAgICB0cnk6CiAgICAgICAgdmFsICA9IHN0cnVjdC51bnBhY2soIjxoIiwgKGN0eXBlcy5jX3VieXRlICogMikuZnJvbV9hZGRyZXNzKGN0eCArIDB4Mjc2OCkpWzBdCiAgICAgICAga2luZCA9IHN0cnVjdC51bnBhY2soIjxoIiwgKGN0eXBlcy5jX3VieXRlICogMikuZnJvbV9hZGRyZXNzKGN0eCArIDB4Mjc2YSkpWzBdCiAgICBleGNlcHQgRXhjZXB0aW9uOgogICAgICAgIHJldHVybiAoMSwgMCkKICAgIGlmIENGRy5nZXQoJ2pyX3dwZXJzcGVjdGl2ZScpIGFuZCBub3QgYm9hcmQud2hpdGU6CiAgICAgICAgdmFsID0gLXZhbCAgICAgICAgICAgICAgICAgICAgICAgICAgICMgc2NvcmUvbWF0IGFic29sdS1CbGFuY3MgLT4gcGVyc3BlY3RpdmUgZHUgdHJhaXQKICAgIHJldHVybiAoa2luZCwgdmFsKQoKCl9jYXBfc2VlbiA9IHt9CmRlZiBfY2FwdHVyZV9sb2cobXNnLCBhMSwgYTIsIGN0eCk6CiAgICAjIE1vZGUgY2FwdHVyZSAoLS1jYWxpYiArIGNhcHR1cmU9VHJ1ZSkgOiBsb2d1ZXIgbGUgdHJhZmljIEZ1bmMzIHBvdXIgREVDT0RFUiB1biBub3V2ZWF1IG1vdGV1ci4KICAgICMgSGV4ZHVtcCBkdSBjb250ZXh0ZSBhIGxhIDFlcmUgb2NjdXJyZW5jZSBkZSBjaGFxdWUgY29kZSwgcHVpcyB1bmUgbGlnbmUgcGFyIG1lc3NhZ2UuCiAgICBpZiBub3QgQ0FMSUI6IHJldHVybgogICAgbiA9IF9jYXBfc2Vlbi5nZXQobXNnLCAwKTsgX2NhcF9zZWVuW21zZ10gPSBuICsgMQogICAgY3UgPSAoY3R4IG9yIDApICYgMHhmZmZmZmZmZgogICAgaWYgbXNnICE9IDB4MTU2IG9yIG4gPT0gMDoKICAgICAgICBsb2coZiJGMyBtc2c9e21zZzojMDZ4fSN7bn0gYTE9e2ExICYgMHhmZmZmZmZmZjojMDEweH0gYTI9e2EyICYgMHhmZmZmZmZmZjojMDEweH0gY3R4PXtjdTojMDEweH0iKQogICAgaWYgbiA9PSAwIGFuZCBjdHg6CiAgICAgICAgdHJ5OgogICAgICAgICAgICBkYXRhID0gYnl0ZXMoKGN0eXBlcy5jX3VieXRlICogMHg4MCkuZnJvbV9hZGRyZXNzKGN0eCkpCiAgICAgICAgICAgIGZvciBvZmYgaW4gcmFuZ2UoMCwgMHg4MCwgMTYpOgogICAgICAgICAgICAgICAgbG9nKCIgICBjdHgrJSMwNHg6ICVzIiAlIChvZmYsICcgJy5qb2luKCclMDJ4JyAlIGIgZm9yIGIgaW4gZGF0YVtvZmY6b2ZmKzE2XSkpKQogICAgICAgIGV4Y2VwdCBFeGNlcHRpb24gYXMgZToKICAgICAgICAgICAgbG9nKGYiICAgY3R4IGR1bXAgRVhDOiB7ZSFyfSIpCgpkZWYgaG9zdF9jYWxsYmFjayhtc2csIGExLCBhMiwgY3R4KToKICAgIHRyeToKICAgICAgICBpZiBDRkcuZ2V0KCdjYXB0dXJlJyk6ICAgICAgICAgICAgICAgIyBkZWNvZGFnZSBkJ3VuIG5vdXZlYXUgbW90ZXVyIDogY2FwdHVyZSBwdXJlLCBhdWN1bmUgZXh0cmFjdGlvbgogICAgICAgICAgICBfY2FwdHVyZV9sb2cobXNnLCBhMSwgYTIsIGN0eCk7IHJldHVybiAwCiAgICAgICAgaWYgQ0ZHLmdldCgnanVuaW9yJyk6ICAgICAgICAgICAgICAgICMgSnVuaW9yL1NocmVkZGVyIDogY291cCBsdSBkYW5zIGxlIHJhcHBvcnQgb2ZmaWNpZWwgMHgxNTQKICAgICAgICAgICAgaWYgbXNnID09IDB4MTU4IGFuZCBjdHg6ICAgICAgICAgIyAweDE1OCA6IHByb2ZvbmRldXIgKFNocmVkZGVyIDogY3R4K29mZiwgc3R5bGUgRnJpdHopCiAgICAgICAgICAgICAgICBvZmYgPSBDRkcuZ2V0KCdqcl9kZXB0aDE1OCcpCiAgICAgICAgICAgICAgICBpZiBvZmYgaXMgbm90IE5vbmU6CiAgICAgICAgICAgICAgICAgICAgdHJ5OgogICAgICAgICAgICAgICAgICAgICAgICBkID0gc3RydWN0LnVucGFjaygiPEgiLCAoY3R5cGVzLmNfdWJ5dGUqMikuZnJvbV9hZGRyZXNzKGN0eCArIG9mZikpWzBdCiAgICAgICAgICAgICAgICAgICAgICAgIGlmIDAgPCBkIDwgMjAwOiBzdC5kZXB0aCA9IG1heChzdC5kZXB0aCwgZCkKICAgICAgICAgICAgICAgICAgICBleGNlcHQgRXhjZXB0aW9uOiBwYXNzCiAgICAgICAgICAgICAgICAjIFNocmVkZGVyIChtb2RlIHByb2ZvbmRldXIpIDogRW5nOSBjaGVyY2hlIGVuIGluZmluaSAtPiBhcnJldCBkZXMgbGEgcHJvZm9uZGV1ciBjaWJsZQogICAgICAgICAgICAgICAgaWYgKHN0LmxpbWl0X2RlcHRoIGFuZCBzdC5kZXB0aCA+PSBzdC5saW1pdF9kZXB0aCBhbmQgbm90IHN0LnN0b3Bfc2VudCk6CiAgICAgICAgICAgICAgICAgICAgc3Quc3RvcF9zZW50ID0gVHJ1ZQogICAgICAgICAgICAgICAgICAgIHRocmVhZGluZy5UaHJlYWQodGFyZ2V0PV9zYWZlX3N0b3AsIGRhZW1vbj1UcnVlKS5zdGFydCgpCiAgICAgICAgICAgIGVsaWYgbXNnID09IDB4MTU0IGFuZCBjdHg6ICAgICAgICMgbWVpbGxldXJlIGxpZ25lIDogY291cCArIFBWICsgc2NvcmUgKyBwcm9mb25kZXVyCiAgICAgICAgICAgICAgICB3YW50ID0gQ0ZHLmdldCgnanJfZmxhZzE1NCcpCiAgICAgICAgICAgICAgICBpZiB3YW50IGlzIG5vdCBOb25lOgogICAgICAgICAgICAgICAgICAgICMgR2FtYml0L0NoZXNzIFRpZ2VyIG9udCBERVVYIGVtZXR0ZXVycyAweDE1NCA6IGxlIHByaW5jaXBhbCAoZmxhZ3MgMHgzMDAxMyA9CiAgICAgICAgICAgICAgICAgICAgIyB2cmFpZSBsaWduZSBwcmluY2lwYWxlLCBhdmVjIHNjb3JlKSBldCB1biBzZWNvbmRhaXJlICgweDEwMDExLCBzYW5zIHNjb3JlKS4KICAgICAgICAgICAgICAgICAgICAjIExlIHByaW5jaXBhbCBwcmltZSwgTUFJUyBzdXIgdW5lIHJlY2hlcmNoZSB0cml2aWFsZSAocmVwcmlzZSBxdWFzaSBmb3JjZWUpIGxlCiAgICAgICAgICAgICAgICAgICAgIyBtb3RldXIgbidlbWV0IFFVRSBsZSBzZWNvbmRhaXJlIDogbGUgcmVqZXRlciBsYWlzc2FpdCBsZSBjb3VwIGEgTm9uZSAtPiBhdWN1bgogICAgICAgICAgICAgICAgICAgICMgY291cCByZW5kdSAoZm9yZmFpdCBhdSB0ZW1wcykgb3UgY291cCBwZXJpbWUgKGNvdXAgaWxsZWdhbCkuIE9uIGxlIGdhcmRlIGRvbmMKICAgICAgICAgICAgICAgICAgICAjIGNvbW1lIFJFUExJIDogY291cCBtZW1vcmlzZSBhIHBhcnQsIHNhbnMgdG91Y2hlciBhdSBzY29yZSBuaSBhIGxhIFBWLgogICAgICAgICAgICAgICAgICAgIHRyeToKICAgICAgICAgICAgICAgICAgICAgICAgZmwgPSBzdHJ1Y3QudW5wYWNrKCI8SSIsIChjdHlwZXMuY191Ynl0ZSo0KS5mcm9tX2FkZHJlc3MoY3R4ICsgMHgxNCkpWzBdCiAgICAgICAgICAgICAgICAgICAgZXhjZXB0IEV4Y2VwdGlvbjoKICAgICAgICAgICAgICAgICAgICAgICAgZmwgPSB3YW50CiAgICAgICAgICAgICAgICAgICAgaWYgZmwgIT0gd2FudDoKICAgICAgICAgICAgICAgICAgICAgICAgbXYgPSBfanJfcmVhZF9tb3ZlKGN0eCkKICAgICAgICAgICAgICAgICAgICAgICAgaWYgbXY6IHN0LmpyX2FsdCA9IG12CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAwCiAgICAgICAgICAgICAgICBzdC5qcl9jdHggPSBjdHgKICAgICAgICAgICAgICAgIG12ID0gX2pyX3JlYWRfbW92ZShjdHgpCiAgICAgICAgICAgICAgICBpZiBtdjogc3QuanJfbW92ZSA9IG12CiAgICAgICAgICAgICAgICBzdC5qcl9wdiA9IF9qcl9yZWFkX3B2KGN0eCkKICAgICAgICAgICAgICAgIHN0LmpyX3Njb3JlX2tpbmQsIHN0LmpyX3Njb3JlID0gX2pyX3JlYWRfc2NvcmUoY3R4KQogICAgICAgICAgICAgICAgdHJ5OiAgICAgICAgICAgICAgICAgICAgICAgICAjIHByb2ZvbmRldXIgZHUgcmFwcG9ydCBKdW5pb3IgOiBjdHgrMHgyNzZjCiAgICAgICAgICAgICAgICAgICAgZCA9IHN0cnVjdC51bnBhY2soIjxIIiwgKGN0eXBlcy5jX3VieXRlKjIpLmZyb21fYWRkcmVzcyhjdHggKyAweDI3NmMpKVswXQogICAgICAgICAgICAgICAgICAgIGlmIDAgPCBkIDwgMjAwOiBzdC5kZXB0aCA9IG1heChzdC5kZXB0aCwgZCkKICAgICAgICAgICAgICAgIGV4Y2VwdCBFeGNlcHRpb246IHBhc3MKICAgICAgICAgICAgICAgIGVtaXRfaW5mbygpCiAgICAgICAgICAgIGVsaWYgbXNnID09IDB4MTU3IGFuZCBjdHg6ICAgICAgICMgMHgxNTcgOiBjb21wdGV1ciBkZSBub2V1ZHMgZW4gY3R4KzB4MTQKICAgICAgICAgICAgICAgIHRyeToKICAgICAgICAgICAgICAgICAgICBzdC5qcl9ub2RlcyA9IHN0cnVjdC51bnBhY2soIjxJIiwgKGN0eXBlcy5jX3VieXRlKjQpLmZyb21fYWRkcmVzcyhjdHggKyAweDE0KSlbMF0KICAgICAgICAgICAgICAgIGV4Y2VwdCBFeGNlcHRpb246CiAgICAgICAgICAgICAgICAgICAgcGFzcwogICAgICAgICAgICByZXR1cm4gMAogICAgICAgIGlmIG1zZyA9PSAweDE1ODogICAgICAgICAgICAgICAgICAgICAjIEZyaXR6IDogcHJvZm9uZGV1ciAocmFwcG9ydCBzb3V2ZW50IHRocm90dGxlKQogICAgICAgICAgICBkID0gMAogICAgICAgICAgICBpZiBjdHg6CiAgICAgICAgICAgICAgICB0cnk6IGQgPSBzdHJ1Y3QudW5wYWNrKCI8SCIsIChjdHlwZXMuY191Ynl0ZSoyKS5mcm9tX2FkZHJlc3MoY3R4ICsgMHgxNCkpWzBdCiAgICAgICAgICAgICAgICBleGNlcHQgRXhjZXB0aW9uOiBkID0gMAogICAgICAgICAgICBpZiAwIDwgZCA8IDIwMDogc3QuZGVwdGggPSBtYXgoc3QuZGVwdGgsIGQpCiAgICAgICAgICAgIGVsc2U6ICAgICAgICAgICBzdC5kZXB0aCArPSAxCiAgICAgICAgZWxpZiBtc2cgPT0gMHgxNTQ6ICAgICAgICAgICAgICAgICAgICMgcmFwcG9ydCBzY29yZS9QViAoZnJlcXVlbnQgOiBwcm9mb25kZXVyIGN0eFsweDI3NmNdKQogICAgICAgICAgICBpZiBjdHg6CiAgICAgICAgICAgICAgICB0cnk6CiAgICAgICAgICAgICAgICAgICAgZCA9IHN0cnVjdC51bnBhY2soIjxIIiwgKGN0eXBlcy5jX3VieXRlKjIpLmZyb21fYWRkcmVzcyhjdHggKyAweDI3NmMpKVswXQogICAgICAgICAgICAgICAgICAgIGlmIDAgPCBkIDwgMjAwOiBzdC5kZXB0aCA9IG1heChzdC5kZXB0aCwgZCkKICAgICAgICAgICAgICAgIGV4Y2VwdCBFeGNlcHRpb246IHBhc3MKICAgICAgICAgICAgICAgIGlmIENGRy5nZXQoJ3Njb3JlMTU0Jyk6ICAgICAgIyBGcml0eiA2LzcvOCA6IGxhIFZSQUlFIGV2YWwgZXN0IGVuIGN0eCsweDI3NjggKGNvbW1lIEp1bmlvciksCiAgICAgICAgICAgICAgICAgICAgdHJ5OiAgICAgICAgICAgICAgICAgICAgICMgcGFzIGRhbnMgbGUgdGFibGVhdSBhcmdtYXggKHF1aSBjb250aWVudCBkZXMgc2NvcmVzIGQnb3JkbykuCiAgICAgICAgICAgICAgICAgICAgICAgIHN0LmZ6X3JzY29yZSA9IHN0cnVjdC51bnBhY2soIjxoIiwgKGN0eXBlcy5jX3VieXRlKjIpLmZyb21fYWRkcmVzcyhjdHggKyAweDI3NjgpKVswXQogICAgICAgICAgICAgICAgICAgICAgICBzdC5mel9ya2luZCAgPSBzdHJ1Y3QudW5wYWNrKCI8aCIsIChjdHlwZXMuY191Ynl0ZSoyKS5mcm9tX2FkZHJlc3MoY3R4ICsgMHgyNzZhKSlbMF0KICAgICAgICAgICAgICAgICAgICBleGNlcHQgRXhjZXB0aW9uOiBwYXNzCiAgICAgICAgICAgICAgICAjIENPVVAgZHUgcmFwcG9ydCAoY3R4KzB4NWMsIGZvcm1hdCBKdW5pb3IsIHZhbGlkZSBwYXIgc29uZGUgcnVudGltZSBzdXIgREY4ID0gbWVtZQogICAgICAgICAgICAgICAgIyBsaWduZWUgcXVlIEZyaXR6IDgpIDogY2FuYWwgUFJJTUFJUkUgZHUgYmVzdG1vdmUgZGVwdWlzIGwnZW5xdWV0ZSAiPUMiIGR1IDE5LzA4LgogICAgICAgICAgICAgICAgIyBMZXMgZHVtcHMgW3Byb21vLWR1bXBdIG9udCBwcm91dmUgcXVlIGxlIHRhYmxlYXUgYXJnbWF4IG1lbGUgc2NvcmVzIGQnb3Jkb25uYW5jZW1lbnQsCiAgICAgICAgICAgICAgICAjIGJvcm5lcyBkZSBtYXQgaWRlbnRpcXVlcyAoMzI3MzYgc3VyIHBsdXNpZXVycyBlbnRyZWVzKSBldCBzZW50aW5lbGxlcyAtMzI3NjggOiBsJ2FyZ21heAogICAgICAgICAgICAgICAgIyB5IHNlbGVjdGlvbm5lIHBhcmZvaXMgdW5lIGVudHJlZSBzb2V1ciAoPUMgYXUgbGlldSBkZSA9RCwgZzMvZzIyL2cyMyArIHJlcHJvIFAyKS4KICAgICAgICAgICAgICAgICMgTGUgcmFwcG9ydCAweDE1NCBwb3J0ZSBsZSBjaG9peCBERUNMQVJFIHBhciBsZSBtb3RldXIgLT4gcHJpb3JpdGFpcmUgOyBhcmdtYXggPSByZXBsaS4KICAgICAgICAgICAgICAgIGlmIENGRy5nZXQoJ21vdmUxNTQnKToKICAgICAgICAgICAgICAgICAgICBtdiA9IF9qcl9yZWFkX21vdmUoY3R4KQogICAgICAgICAgICAgICAgICAgIGlmIG12OgogICAgICAgICAgICAgICAgICAgICAgICBpZiBDQUxJQiBhbmQgbXYgIT0gc3QuZnpfcm1vdmU6IGxvZyhmIltyZXBvcnQxNTRdIGNvdXA9e212fSIpCiAgICAgICAgICAgICAgICAgICAgICAgIHN0LmZ6X3Jtb3ZlID0gbXYKICAgICAgICAgICAgZW1pdF9pbmZvKCkKICAgICAgICAjIDB4MTU2IC8gMHgxNTcgOiBwZXJpb2RpcXVlcyAtPiBpZ25vcmVzIChsYSBmaW4gPSByZXRvdXIgZGUgRW5nOSkKICAgIGV4Y2VwdCBFeGNlcHRpb24gYXMgZToKICAgICAgICBsb2coImNhbGxiYWNrIEVYQzoiLCByZXByKGUpKQogICAgcmV0dXJuIDAKX2NiID0gQ0JfVFlQRShob3N0X2NhbGxiYWNrKQpfc2V0X2NiKF9jYikKCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KIyAgQ2hhcmdlciBsZSAuZW5nLCBwYXRjaGVyIENQLCByZXNvdWRyZSBleHBvcnRzCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KaEVuZyA9IGszMi5Mb2FkTGlicmFyeUEoRU5HX1BBVEguZW5jb2RlKCkpCmlmIG5vdCBoRW5nOgogICAgc3lzLnN0ZGVyci53cml0ZShmIkZBVEFMOiBMb2FkTGlicmFyeSh7RU5HX1BBVEh9KSBlY2hlYyBlcnI9e2N0eXBlcy5nZXRfbGFzdF9lcnJvcigpfVxuIik7IHN5cy5leGl0KDEpCkJBU0UgPSBoRW5nCmZvciBjIGluIENGR1snY3AnXToKICAgIGlmIGlzaW5zdGFuY2UoYywgdHVwbGUpOgogICAgICAgIHJ2YSwgcGF0Y2ggPSBjCiAgICAgICAgcGF0Y2hfYnl0ZXMoQkFTRSArIHJ2YSwgcGF0Y2gpICAgICAgICAgICMgZXguIGpuZSAtPiBOT1AgKDYgb2N0ZXRzKQogICAgZWxzZToKICAgICAgICBwYXRjaF9ieXRlcyhCQVNFICsgYywgYiJceEVCIikgICAgICAgICAgICMgamUgKDB4NzQpIC0+IGptcCAoMHhFQikKbG9nKGYie0NGR1snbmFtZSddfSBiYXNlPXtCQVNFOiMwMTB4fSA7IHtsZW4oQ0ZHWydjcCddKX0gcGF0Y2gocykgQ1AgcG9zZXMiKQojIHByZWRlY3J5cHQgOiBjZXJ0YWluZXMgcHJvdGVjdGlvbnMgKEp1bmlvciA5KSBvbnQgdW5lIGJvdWNsZSBhbnRpLXRhbXBlciBxdWkgcmVtcGxpdCB1biBidWZmZXIKIyAnZHN0JyAoUlZBKSBwYXIgJ2RzdFtpXSBePSBjbGVbaV0nLCBjbGUgdmFsaWRlZSA9PSAnc3JjJyAoUlZBLCBkb25uZWUgc3RhdGlxdWUpLiBPbiBOT1AgbGEgYm91Y2xlCiMgKHZpYSBjcCkgZXQgb24gcG9zZSBJQ0kgZGlyZWN0ZW1lbnQgZHN0W2ldIF49IHNyY1tpXSAoYXZlYyBsYSB2cmFpZSBjbGUgc3RhdGlxdWUpLCBhdSBjaGFyZ2VtZW50Lgpmb3IgZHN0X3J2YSwgc3JjX3J2YSwgbG4gaW4gQ0ZHLmdldCgncHJlZGVjcnlwdCcsIFtdKToKICAgIGRzdCA9IChjdHlwZXMuY191Ynl0ZSAqIGxuKS5mcm9tX2FkZHJlc3MoQkFTRSArIGRzdF9ydmEpCiAgICBzcmMgPSAoY3R5cGVzLmNfdWJ5dGUgKiBsbikuZnJvbV9hZGRyZXNzKEJBU0UgKyBzcmNfcnZhKQogICAgb2xkID0gd2ludHlwZXMuRFdPUkQoMCkKICAgIGszMi5WaXJ0dWFsUHJvdGVjdChCQVNFICsgZHN0X3J2YSwgbG4sIFBBR0VfUldYLCBjdHlwZXMuYnlyZWYob2xkKSkKICAgIGZvciBpIGluIHJhbmdlKGxuKTogZHN0W2ldIF49IHNyY1tpXQogICAgazMyLlZpcnR1YWxQcm90ZWN0KEJBU0UgKyBkc3RfcnZhLCBsbiwgb2xkLnZhbHVlLCBjdHlwZXMuYnlyZWYob2xkKSkKICAgIGxvZyhmInByZWRlY3J5cHQ6IHtsbn0gb2N0ZXRzIHBvc2VzIEAgcnZhIHtkc3RfcnZhOiN4fSAoXj0gcnZhIHtzcmNfcnZhOiN4fSkiKQoKZGVmIEEocnZhKTogcmV0dXJuIEJBU0UgKyBydmEgICAgICAgICAgICAjIFJWQSAtPiBhZHJlc3NlIGFic29sdWUKZGVmIF9yZDMyKGEpOiAgcmV0dXJuIHN0cnVjdC51bnBhY2soIjxJIiwgKGN0eXBlcy5jX3VieXRlKjQpLmZyb21fYWRkcmVzcyhhKSlbMF0KZGVmIF9yZHMzMihhKTogcmV0dXJuIHN0cnVjdC51bnBhY2soIjxpIiwgKGN0eXBlcy5jX3VieXRlKjQpLmZyb21fYWRkcmVzcyhhKSlbMF0KCmRlZiByZWFkX25vZGVzKCk6CiAgICBpZiBub3QgQ0ZHWydub2RlJ106IHJldHVybiAwCiAgICB0cnk6CiAgICAgICAgcmF3ID0gX3JkMzIoQShDRkdbJ25vZGUnXSkpIHwgKF9yZDMyKEEoQ0ZHWydub2RlJ10rNCkpIDw8IDMyKQogICAgICAgIHJldHVybiBtYXgoMCwgcmF3IC0gc3Qubm9kZTApICAgICAgICAjIG5vZGUwPTAgc2F1ZiA1LjMyIChjb21wdGV1ciBjdW11bGF0aWYpCiAgICBleGNlcHQgRXhjZXB0aW9uOgogICAgICAgIHJldHVybiAwCgpkZWYgcmVhZF9ub2Rlc19yYXcoKToKICAgIHRyeTogcmV0dXJuIF9yZDMyKEEoQ0ZHWydub2RlJ10pKSB8IChfcmQzMihBKENGR1snbm9kZSddKzQpKSA8PCAzMikKICAgIGV4Y2VwdCBFeGNlcHRpb246IHJldHVybiAwCgpkZWYgcmVhZF9wdihtYXhsZW49MTIpOgogICAgb3V0ID0gW10KICAgIGlmIG5vdCBDRkdbJ3B2J106IHJldHVybiBvdXQKICAgIHRyeToKICAgICAgICBmb3IgaSBpbiByYW5nZShtYXhsZW4pOgogICAgICAgICAgICBtdiA9IGRlY29kZV9tb3ZlKF9yZDMyKEEoQ0ZHWydwdiddKSArIDQqaSkpCiAgICAgICAgICAgIGlmIG12IGlzIE5vbmU6IGJyZWFrCiAgICAgICAgICAgIG91dC5hcHBlbmQobXYpCiAgICBleGNlcHQgRXhjZXB0aW9uOiBwYXNzCiAgICByZXR1cm4gb3V0CgpkZWYgcmVhZF9iZXN0X21vdmUoKToKICAgICIiIk1laWxsZXVyIGNvdXAuIEF2ZWMgdGFibGVhdSBkZSBzY29yZXMgOiBhcmdtYXggKGZpYWJsZSkgKyBzdC5zY29yZS4KICAgICAgIFNpbm9uICg1LjMyKSA6IFBWWzBdLCBzY29yZSBpbmNvbm51ICgwKS4iIiIKICAgIHRyeToKICAgICAgICBpZiBDRkcuZ2V0KCdqdW5pb3InKTogICAgICAgICAgICAgICAgIyBKdW5pb3IgOiBjb3VwICsgc2NvcmUgaXNzdXMgZHUgcmFwcG9ydCAweDE1NCAoaG9zdF9jYWxsYmFjaykKICAgICAgICAgICAgIyByZXBsaSBzdXIgbGUgcmFwcG9ydCBzZWNvbmRhaXJlIHNpIGxlIHByaW5jaXBhbCBuJ2EgcmllbiBkb25uZSAocmVjaGVyY2hlIHRyaXZpYWxlKQogICAgICAgICAgICByZXR1cm4gc3QuanJfbW92ZSBvciBzdC5qcl9hbHQgICAjIHNjb3JlL21hdCBwb3J0ZXMgcGFyIHN0LmpyX3Njb3JlL3N0LmpyX3Njb3JlX2tpbmQKICAgICAgICBpZiBDRkcuZ2V0KCdiZXN0bW92ZV9kd29yZCcpOiAgICAgICAgIyBGcml0eiA5IDogbWVpbGxldXIgY291cCArIHNjb3JlIFNUQUJMRVMKICAgICAgICAgICAgc3Quc2NvcmUgPSBzdHJ1Y3QudW5wYWNrKCI8aSIsIChjdHlwZXMuY191Ynl0ZSo0KS5mcm9tX2FkZHJlc3MoQShDRkdbJ3Njb3JlX2R3b3JkJ10pKSlbMF0KICAgICAgICAgICAgaWYgQ0ZHLmdldCgnd3BlcnNwZWN0aXZlJykgYW5kIG5vdCBib2FyZC53aGl0ZToKICAgICAgICAgICAgICAgIHN0LnNjb3JlID0gLXN0LnNjb3JlCiAgICAgICAgICAgIG12ID0gZGVjb2RlX21vdmUoX3JkMzIoQShDRkdbJ2Jlc3Rtb3ZlX2R3b3JkJ10pKSkKICAgICAgICAgICAgcmV0dXJuIG12CiAgICAgICAgaWYgQ0ZHWydzY29yZXMnXSBhbmQgQ0ZHWydubW92ZXMnXSBhbmQgQ0ZHWydtb3ZlYmFzZSddOgogICAgICAgICAgICBuID0gX3JkMzIoQShDRkdbJ25tb3ZlcyddKSkKICAgICAgICAgICAgIyA2LzcvOCA6IGxlIGdsb2JhbCBNT1ZFQkFTRSBlc3QgdW4gUE9JTlRFVVIgdmVycyBsZSB0YWJsZWF1IChkZXJlZikuCiAgICAgICAgICAgICMgNS4zMiAgOiBsZSBnbG9iYWwgRVNUIGxlIHRhYmxlYXUgKGluZGV4YXRpb24gZGlyZWN0ZSwgcGFzIGRlIGRlcmVmKS4KICAgICAgICAgICAgYmFzZSA9IEEoQ0ZHWydtb3ZlYmFzZSddKSBpZiBDRkcuZ2V0KCdtb3ZlYmFzZV9kaXJlY3QnKSBlbHNlIF9yZDMyKEEoQ0ZHWydtb3ZlYmFzZSddKSkKICAgICAgICAgICAgaWYgYmFzZSA+IDB4MTAwMDAgYW5kIDEgPD0gbiA8PSAyNTY6ICAgIyBnYXJkZS1mb3UgOiBhZHJlc3NlIHBsYXVzaWJsZQogICAgICAgICAgICAgICAgc2NzID0gW19yZHMzMihBKENGR1snc2NvcmVzJ10pICsgNCppKSBmb3IgaSBpbiByYW5nZShuKV0KICAgICAgICAgICAgICAgICMgTCdhcmdtYXggc3VyIGNlIHRhYmxlYXUgZG9ubmUgbGUgYm9uIENPVVAgKEZyaXR6IGpvdWUgYmllbikgbWFpcyB1biBTQ09SRSBnb25mbGUgOgogICAgICAgICAgICAgICAgIyBjZXMgdmFsZXVycyBzb250IGRlcyBzY29yZXMgZCdvcmRvbm5hbmNlbWVudCwgcGFzIGwnZXZhbC4gTGEgdnJhaWUgZXZhbCBlc3QgbHVlIGRhbnMKICAgICAgICAgICAgICAgICMgbGUgcmFwcG9ydCAweDE1NCAoY3R4KzB4Mjc2OCwgY2YuIHNjb3JlMTU0IC0+IHN0LmZ6X3JzY29yZSksIGNvbW1lIHBvdXIgSnVuaW9yLgogICAgICAgICAgICAgICAgIyAtMzI3NjggPSBjb3VwIHBhcyBlbmNvcmUgcmVjaGVyY2hlIDogb24gbmUgZmlnZSBsZSBtZWlsbGV1ciBjb3VwIHF1J2VuIGl0ZXJhdGlvbiBjb21wbGV0ZS4KICAgICAgICAgICAgICAgIGNvbXBsZXRlID0gYWxsKHMgPiAtMzAwMDAgZm9yIHMgaW4gc2NzKQogICAgICAgICAgICAgICAgaWYgY29tcGxldGU6CiAgICAgICAgICAgICAgICAgICAgYmkgPSBtYXgocmFuZ2UobiksIGtleT1sYW1iZGEgaTogc2NzW2ldKQogICAgICAgICAgICAgICAgICAgIHN0LmZ6X21vdmUgID0gZGVjb2RlX21vdmUoX3JkMzIoYmFzZSArIDQqYmkpKQogICAgICAgICAgICAgICAgICAgIHN0LmZ6X3Njb3JlID0gc2NzW2JpXQogICAgICAgICAgICAgICAgaWYgQ0FMSUI6CiAgICAgICAgICAgICAgICAgICAgbG9nKGYiW3Njb3JlXSBjb21wbGV0ZT17Y29tcGxldGV9IGFyZ21heD17c3QuZnpfc2NvcmV9IHJlcG9ydD17c3QuZnpfcnNjb3JlfSAiCiAgICAgICAgICAgICAgICAgICAgICAgIGYidHJhaXQ9eydCJyBpZiBib2FyZC53aGl0ZSBlbHNlICdOJ30iKQogICAgICAgICAgICAgICAgICAgICMgRU5RVUVURSAiPUMiIGR1IDE5LzA4IDogc2kgdW5lIHByb21vdGlvbiBmaWd1cmUgcGFybWkgbGVzIGNvdXBzIHJhY2luZSwKICAgICAgICAgICAgICAgICAgICAjIGpvdXJuYWxpc2VyIFRPVVRFIGxhIGxpc3RlIChpbmRleCwgc2NvcmUsIGNvdXApIHBvdXIgdmVyaWZpZXIgbCdoeXBvdGhlc2UKICAgICAgICAgICAgICAgICAgICAjIGRlcyBlZ2FsaXRlcyBkZSBzY29yZXMgZmFpbC1oaWdoIGVudHJlIGVudHJlZXMgc29ldXJzICg9RCB2cyA9QykgcXVpIGZlcmFpZW50CiAgICAgICAgICAgICAgICAgICAgIyByZXRvbWJlciBsJ2FyZ21heCBzdXIgbGEgcHJlbWllcmUgZW50cmVlIGdlbmVyZWUuIFZvbHVtZSBmYWlibGUgOiBwb3NpdGlvbnMgcmFyZXMuCiAgICAgICAgICAgICAgICAgICAgdHJ5OgogICAgICAgICAgICAgICAgICAgICAgICBlbnRyaWVzID0gW2RlY29kZV9tb3ZlKF9yZDMyKGJhc2UgKyA0KmkpKSBmb3IgaSBpbiByYW5nZShuKV0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgYW55KG0gYW5kIGxlbihtKSA+IDQgZm9yIG0gaW4gZW50cmllcyk6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgaSBpbiByYW5nZShuKToKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2coZiJbcHJvbW8tZHVtcF0gaT17aX0gc2M9e3Njc1tpXX0gbXY9e2VudHJpZXNbaV19IikKICAgICAgICAgICAgICAgICAgICBleGNlcHQgRXhjZXB0aW9uIGFzIGU6CiAgICAgICAgICAgICAgICAgICAgICAgIGxvZygicHJvbW8tZHVtcCBFWEM6IiwgcmVwcihlKSkKICAgICAgICAgICAgICAgIHNjID0gc3QuZnpfcnNjb3JlIGlmIENGRy5nZXQoJ3Njb3JlMTU0JykgZWxzZSBzdC5mel9zY29yZQogICAgICAgICAgICAgICAgaWYgQ0ZHLmdldCgnbW92ZTE1NCcpIGFuZCBzdC5mel9ybW92ZSBpcyBub3QgTm9uZToKICAgICAgICAgICAgICAgICAgICBzdC5zY29yZSA9IHNjICAgICAgICAgICAgIyBjb3VwIGRlY2xhcmUgcGFyIGxlIG1vdGV1ciAocmFwcG9ydCAweDE1NCkgOiBwcmlvcml0YWlyZQogICAgICAgICAgICAgICAgICAgIHJldHVybiBzdC5mel9ybW92ZQogICAgICAgICAgICAgICAgaWYgc3QuZnpfbW92ZSBpcyBub3QgTm9uZToKICAgICAgICAgICAgICAgICAgICBzdC5zY29yZSA9IHNjCiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHN0LmZ6X21vdmUKICAgICAgICAgICAgICAgICMgYXVjdW5lIGl0ZXJhdGlvbiBjb21wbGV0ZSBlbmNvcmUgLT4gcmVwbGkgc3VyIGwnYXJnbWF4IHBhcnRpZWwgKHRvdXQgZGVidXQgZGUgcmVjaGVyY2hlKQogICAgICAgICAgICAgICAgYmkgPSBtYXgocmFuZ2UobiksIGtleT1sYW1iZGEgaTogc2NzW2ldKQogICAgICAgICAgICAgICAgc3Quc2NvcmUgPSBzdC5mel9yc2NvcmUgaWYgQ0ZHLmdldCgnc2NvcmUxNTQnKSBlbHNlIHNjc1tiaV0KICAgICAgICAgICAgICAgIHJldHVybiBkZWNvZGVfbW92ZShfcmQzMihiYXNlICsgNCpiaSkpCiAgICAgICAgcHYgPSByZWFkX3B2KCkgICAgICAgICAgICAgICAgICAgICAgICMgcmVwbGkgKDUuMzIgLyBGcml0eiA5KSA6IGJlc3Rtb3ZlID0gUFZbMF0KICAgICAgICBpZiBDRkcuZ2V0KCdzY29yZV9kd29yZCcpOgogICAgICAgICAgICBzdC5zY29yZSA9IHN0cnVjdC51bnBhY2soIjxpIiwgKGN0eXBlcy5jX3VieXRlKjQpLmZyb21fYWRkcmVzcyhBKENGR1snc2NvcmVfZHdvcmQnXSkpKVswXQogICAgICAgIGVsaWYgQ0ZHLmdldCgnc2NvcmVfd29yZCcpOgogICAgICAgICAgICBzdC5zY29yZSA9IHN0cnVjdC51bnBhY2soIjxoIiwgKGN0eXBlcy5jX3VieXRlKjIpLmZyb21fYWRkcmVzcyhBKENGR1snc2NvcmVfd29yZCddKSkpWzBdCiAgICAgICAgZWxzZToKICAgICAgICAgICAgc3Quc2NvcmUgPSAwCiAgICAgICAgaWYgQ0ZHLmdldCgnd3BlcnNwZWN0aXZlJykgYW5kIG5vdCBib2FyZC53aGl0ZTogICAjIHNjb3JlIGFic29sdSBCbGFuY3MgLT4gdHJhaXQKICAgICAgICAgICAgc3Quc2NvcmUgPSAtc3Quc2NvcmUKICAgICAgICBpZiBwdjoKICAgICAgICAgICAgcmV0dXJuIHB2WzBdCiAgICBleGNlcHQgRXhjZXB0aW9uIGFzIGU6CiAgICAgICAgbG9nKCJyZWFkX2Jlc3QgRVhDOiIsIHJlcHIoZSkpCiAgICByZXR1cm4gTm9uZQoKZGVmIGVtaXRfaW5mbyhmaW5hbD1GYWxzZSk6CiAgICBpZiBDRkcuZ2V0KCdqdW5pb3InKTogICAgICAgICAgICAgICAgICAgICMgSnVuaW9yIDogY291cCByYWNpbmUgKyBQViBjb21wbGV0ZSArIHNjb3JlIChyYXBwb3J0IDB4MTU0KQogICAgICAgIGJlc3QgPSBzdC5qcl9tb3ZlCiAgICAgICAgaWYgYmVzdCBpcyBOb25lIGFuZCBub3QgZmluYWw6IHJldHVybgogICAgICAgIGxpbmUgPSAoW2Jlc3RdICsgc3QuanJfcHZbMTpdKSBpZiAoc3QuanJfcHYgYW5kIGJlc3QpIGVsc2UgKFtiZXN0XSBpZiBiZXN0IGVsc2UgW10pCiAgICAgICAgaWYgbm90IGxpbmU6IHJldHVybgogICAgICAgIHNjc3RyID0gZiJtYXRlIHtzdC5qcl9zY29yZX0iIGlmIHN0LmpyX3Njb3JlX2tpbmQgPT0gMiBlbHNlIGYiY3Age3N0LmpyX3Njb3JlfSIKICAgICAgICBrZXkgPSAoc3QuZGVwdGgsIGJlc3QsIHN0LmpyX3Njb3JlX2tpbmQsIHN0LmpyX3Njb3JlLCBzdC5qcl9ub2RlcywgdHVwbGUobGluZSkpCiAgICAgICAgaWYga2V5ID09IHN0Lmxhc3RfZW1pdCBhbmQgbm90IGZpbmFsOiByZXR1cm4KICAgICAgICBzdC5sYXN0X2VtaXQgPSBrZXkKICAgICAgICBtcyA9IG1heCgxLCBpbnQoKHRpbWUudGltZSgpIC0gc3QudDApICogMTAwMCkpCiAgICAgICAgc3QuYmVzdCA9IGJlc3QKICAgICAgICBkc2hvd24gPSBzdC5kZXB0aCBpZiBzdC5kZXB0aCA+IDAgZWxzZSAxCiAgICAgICAgbnN0ciA9ICIiCiAgICAgICAgaWYgc3QuanJfbm9kZXM6CiAgICAgICAgICAgIG5zdHIgPSBmIiBub2RlcyB7c3QuanJfbm9kZXN9IG5wcyB7c3QuanJfbm9kZXMgKiAxMDAwIC8vIG1zfSIKICAgICAgICB1Y2lfb3V0KGYiaW5mbyBkZXB0aCB7ZHNob3dufSBzY29yZSB7c2NzdHJ9IHRpbWUge21zfXtuc3RyfSBwdiAiICsgIiAiLmpvaW4obGluZSkpCiAgICAgICAgcmV0dXJuCiAgICBiZXN0ID0gcmVhZF9iZXN0X21vdmUoKSAgICAgICAgICAgICAgICAgICMgYXJnbWF4IChmaWFibGUpIDsgbWV0IGEgam91ciBzdC5zY29yZQogICAgaWYgYmVzdCBpcyBOb25lIGFuZCBub3QgZmluYWw6IHJldHVybgogICAgc2MgPSBzdC5zY29yZQogICAgaWYgc2MgPT0gU0VOVElORUwgYW5kIG5vdCBmaW5hbDogcmV0dXJuCiAgICBwdiA9IHJlYWRfcHYoKSBpZiBDRkdbJ3B2J10gZWxzZSBbXQogICAgaWYgbm90IENGR1snc2NvcmVzJ10gYW5kIENGR1sncHYnXSBhbmQgbm90IENGRy5nZXQoJ2Jlc3Rtb3ZlX2R3b3JkJyk6CiAgICAgICAgIyAoYnJhbmNoZSBhcmdtYXggaGlzdG9yaXF1ZSAtIHBsdXMgdXRpbGlzZWUgOiA1LjMyIGEgZGVzIHNjb3JlcywgRjkgYSBiZXN0bW92ZV9kd29yZCkKICAgICAgICBpZiBzdC5kZXB0aCAhPSBzdC5hcmdtYXhfZGVwdGg6CiAgICAgICAgICAgIHN0LmFyZ21heF9kZXB0aCA9IHN0LmRlcHRoOyBzdC5iZXN0X3Njb3JlX3NlZW4gPSAtMjAwMDAwMDAwMAogICAgICAgIGlmIHB2IGFuZCBzYyA+IHN0LmJlc3Rfc2NvcmVfc2VlbjoKICAgICAgICAgICAgc3QuYmVzdF9wdiA9IHB2OyBzdC5iZXN0X3Njb3JlX3NlZW4gPSBzYwogICAgICAgIGlmIGZpbmFsIGFuZCBwdiBhbmQgKG5vdCBzdC5iZXN0X3B2IG9yIHNjID4gc3QuYmVzdF9zY29yZV9zZWVuKToKICAgICAgICAgICAgc3QuYmVzdF9wdiA9IHB2OyBzdC5iZXN0X3Njb3JlX3NlZW4gPSBzYwogICAgICAgIGlmIG5vdCBzdC5iZXN0X3B2OiByZXR1cm4KICAgICAgICBsaW5lID0gc3QuYmVzdF9wdjsgYmVzdCA9IGxpbmVbMF07IHNjID0gc3QuYmVzdF9zY29yZV9zZWVuCiAgICBlbGlmIHB2IGFuZCBiZXN0IGFuZCBwdlswXSA9PSBiZXN0OiAgICAgICMgdnJhaWUgbWVpbGxldXJlIGxpZ25lICg1LjMyLzYvNy84LzkpCiAgICAgICAgaWYgbGVuKHB2KSA+IDE6IHN0LmJlc3RfcHYgPSBwdgogICAgICAgIGxpbmUgPSBzdC5iZXN0X3B2IGlmIChzdC5iZXN0X3B2IGFuZCBzdC5iZXN0X3B2WzBdID09IGJlc3QpIGVsc2UgcHYKICAgIGVsaWYgQ0ZHWydwdiddIGFuZCBub3QgZmluYWw6ICAgICAgICAgICAgIyByYXBwb3J0ICJjb3VwIGNvdXJhbnQiIC0+IHNhdXRlCiAgICAgICAgcmV0dXJuCiAgICBlbGlmIGJlc3Q6ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgcGFzIGRlIHRhYmxlIFBWICg1LjMyKSBvdSBmaW5hbCAtPiBjb3VwIHNldWwKICAgICAgICBsaW5lID0gc3QuYmVzdF9wdiBpZiAoc3QuYmVzdF9wdiBhbmQgc3QuYmVzdF9wdlswXSA9PSBiZXN0KSBlbHNlIFtiZXN0XQogICAgZWxzZToKICAgICAgICByZXR1cm4KICAgIGtleSA9IChzdC5kZXB0aCwgYmVzdCwgc2MsIHR1cGxlKGxpbmUpKQogICAgaWYga2V5ID09IHN0Lmxhc3RfZW1pdCBhbmQgbm90IGZpbmFsOiByZXR1cm4KICAgIHN0Lmxhc3RfZW1pdCA9IGtleQogICAgbm9kZXMgPSByZWFkX25vZGVzKCk7IG1zID0gbWF4KDEsIGludCgodGltZS50aW1lKCkgLSBzdC50MCkgKiAxMDAwKSkKICAgIHN0LmJlc3QgPSBiZXN0CiAgICBkc2hvd24gPSBzdC5kZXB0aCBpZiBzdC5kZXB0aCA+IDAgZWxzZSAoc3QucmVxX2RlcHRoIG9yIDEpCiAgICBzY3N0ciA9IChmIm1hdGUge3NjfSIgaWYgQ0ZHLmdldCgnc2NvcmUxNTQnKSBhbmQgc3QuZnpfcmtpbmQgPT0gMiBlbHNlCiAgICAgICAgICAgICAoZiJjcCB7c2N9IiBpZiBzYyAhPSBTRU5USU5FTCBlbHNlICJjcCAwIikpCiAgICBuc3RyID0gZiJub2RlcyB7bm9kZXN9IG5wcyB7bm9kZXMgKiAxMDAwIC8vIG1zfSAiIGlmIG5vZGVzIGVsc2UgIiIKICAgIHVjaV9vdXQoZiJpbmZvIGRlcHRoIHtkc2hvd259IHNjb3JlIHtzY3N0cn0ge25zdHJ9dGltZSB7bXN9IHB2ICIgKyAiICIuam9pbihsaW5lKSkKClZQID0gY3R5cGVzLmNfdm9pZF9wCmRlZiBleHBvcnQobmFtZSwgcnQsIGF0LCByZXF1aXJlZD1UcnVlKToKICAgIHAgPSBrMzIuR2V0UHJvY0FkZHJlc3MoaEVuZywgbmFtZS5lbmNvZGUoKSkKICAgIGlmIG5vdCBwOgogICAgICAgIGlmIHJlcXVpcmVkOiBzeXMuc3RkZXJyLndyaXRlKGYiRkFUQUw6IGV4cG9ydCB7bmFtZX0gYWJzZW50XG4iKTsgc3lzLmV4aXQoMSkKICAgICAgICBsb2coZiJub3RlOiBleHBvcnQgb3B0aW9ubmVsIHtuYW1lfSBhYnNlbnQiKTsgcmV0dXJuIE5vbmUKICAgIHJldHVybiBjdHlwZXMuQ0ZVTkNUWVBFKHJ0LCAqYXQpKHApCkVuZzEgID0gZXhwb3J0KCJFbmcxIiwgIGN0eXBlcy5jX2ludCwgW1ZQLFZQLFZQLFZQLFZQLCBjdHlwZXMuY191aW50XSkKRW5nMiAgPSBleHBvcnQoIkVuZzIiLCAgTm9uZSwgW10sIHJlcXVpcmVkPUZhbHNlKQpFbmczICA9IGV4cG9ydCgiRW5nMyIsICBOb25lLCBbXSwgcmVxdWlyZWQ9RmFsc2UpCkVuZzQgID0gZXhwb3J0KCJFbmc0IiwgIGN0eXBlcy5jX2ludCwgW10sIHJlcXVpcmVkPUZhbHNlKQpFbmc2ICA9IGV4cG9ydCgiRW5nNiIsICBjdHlwZXMuY19jaGFyX3AsIFtdLCByZXF1aXJlZD1GYWxzZSkKRW5nNyAgPSBleHBvcnQoIkVuZzciLCAgY3R5cGVzLmNfY2hhcl9wLCBbXSwgcmVxdWlyZWQ9RmFsc2UpCkVuZzggID0gZXhwb3J0KCJFbmc4IiwgIGN0eXBlcy5jX3VpbnQsIFtdLCByZXF1aXJlZD1GYWxzZSkKRW5nOSAgPSBleHBvcnQoIkVuZzkiLCAgTm9uZSwgW1ZQXSkKRW5nMTUgPSBleHBvcnQoIkVuZzE1IiwgTm9uZSwgW10sIHJlcXVpcmVkPUZhbHNlKQoKQ1RYID0gMHgzMDAwCmN0eCA9IFtjdHlwZXMuY3JlYXRlX3N0cmluZ19idWZmZXIoQ1RYKSBmb3IgXyBpbiByYW5nZSg1KV0KY3R4X3B0ciA9IFtjdHlwZXMuY2FzdChiLCBjdHlwZXMuY192b2lkX3ApLnZhbHVlIGZvciBiIGluIGN0eF0Kc3BhcmFtcyA9IGN0eXBlcy5jcmVhdGVfc3RyaW5nX2J1ZmZlcigweDEwMDApClNQID0gY3R5cGVzLmNhc3Qoc3BhcmFtcywgY3R5cGVzLmNfdm9pZF9wKS52YWx1ZQoKRU5HX05BTUUgICA9IENGR1snbmFtZSddICAgICAgICAgICAgIyBhZmZpY2hlIGRlcyBsZSAndWNpJyAoaW5pdCByZWVsbGUgZGlmZmVyZWUpCkVOR19BVVRIT1IgPSBDRkcuZ2V0KCdhdXRob3InLCAiRnJhbnMgTW9yc2NoIikgICAjIEp1bmlvciA6IEFtaXIgQmFuIC8gU2hheSBCdXNoaW5za3kKX2luaXRlZCA9IEZhbHNlCgpkZWYgc2V0X3RocmVhZHMobik6CiAgICAjIExlcyB2ZXJzaW9ucyBtdWx0aXByb2Nlc3NldXIgKERlZXAgRnJpdHopIGxpc2VudCBsZSBub21icmUgZGUgY29ldXJzIHZpYSBHZXRTeXN0ZW1JbmZvIGRhbnMgRW5nMQogICAgIyBldCBsZSBzdG9ja2VudCBkYW5zIGRldXggZ2xvYmFsZXMgKHBsYWZvbm5lZXMgYSA4KS4gUGFyIGRlZmF1dCBvbiBuZSB0b3VjaGUgYSBSSUVOIDogbGUgbW90ZXVyCiAgICAjIGV4cGxvaXRlIHRvdXMgbGVzIGNvZXVycywgY29tbWUgcHJldnUgcGFyIHNlcyBhdXRldXJzLiBMJ29wdGlvbiBVQ0kgVGhyZWFkcyBwZXJtZXQgZGUgZm9yY2VyIHVuZQogICAgIyB2YWxldXIgc2kgbCdvbiB2ZXV0IGNvbXBhcmVyIGEgZGVzIG1vdGV1cnMgbW9uby10aHJlYWQgKG49MCA6IG9uIGxhaXNzZSBsZSBtb3RldXIgZGVjaWRlcikuCiAgICBydmFzID0gQ0ZHLmdldCgndGhyZWFkc19ydmEnKQogICAgaWYgbm90IHJ2YXMgb3Igbm90IG46IHJldHVybgogICAgdHJ5OgogICAgICAgIGZvciBydmEgaW4gcnZhczoKICAgICAgICAgICAgc3RydWN0LnBhY2tfaW50bygiPEkiLCAoY3R5cGVzLmNfdWJ5dGUqNCkuZnJvbV9hZGRyZXNzKEEocnZhKSksIDAsIG1heCgxLCBuKSkKICAgICAgICBsb2coZiJ0aHJlYWRzIGltcG9zZXMgYSB7bWF4KDEsIG4pfSIpCiAgICBleGNlcHQgRXhjZXB0aW9uIGFzIGU6CiAgICAgICAgbG9nKGYic2V0X3RocmVhZHM6IHtlIXJ9IikKCmRlZiBlbnN1cmVfaW5pdCgpOgogICAgIyBJbml0IHJlZWxsZSBkdSBtb3RldXIgOiBhcHBlbGVlIGF1IDFlciBpc3JlYWR5L2dvLCBBUFJFUyBsZXMgc2V0b3B0aW9uCiAgICAjIChwZXJtZXQgZCdhcHBsaXF1ZXIgbGEgdGFpbGxlIGRlIGhhc2ggZGVtYW5kZWUsIGFsbG91ZWUgdW5lIGZvaXMgcGFyIEVuZzEpLgogICAgZ2xvYmFsIF9pbml0ZWQsIEVOR19OQU1FLCBFTkdfQVVUSE9SCiAgICBpZiBfaW5pdGVkOiByZXR1cm4KICAgIF9pbml0ZWQgPSBUcnVlCiAgICBzdXBwcmVzc19tZXNzYWdlX2JveGVzKCkgICAjIGF1Y3VuIGRpYWxvZ3VlIG1vZGFsIG5lIGRvaXQgcG91dm9pciBibG9xdWVyIGxlIHByb2Nlc3N1cyBlbiB0b3Vybm9pCiAgICBwcmVsb2FkX2FuZF9wYXRjaCgpICAgICAgICAjIHBhdGNoZXIgbGVzIERMTCBkZXBlbmRhbnRlcyAoZXguIENELWNoZWNrIFNocmVkZGVyNy5kbGwpIGF2YW50IEVuZzEKICAgIHIgPSBFbmcxKGN0eF9wdHJbMF0sIGN0eF9wdHJbMV0sIGN0eF9wdHJbMl0sIGN0eF9wdHJbM10sIGN0eF9wdHJbNF0sIEhBU0hfTUIqMTAyNCkKICAgIGxvZyhmIkVuZzEgLT4ge3J9ICAoaGFzaD17SEFTSF9NQn0gTW8pIikKICAgIGlmIHIgIT0gMDoKICAgICAgICBzeXMuc3RkZXJyLndyaXRlKGYiRkFUQUw6IEVuZzE9e3J9ICgzPWNvcHktcHJvdGVjdGlvbiA6IHBhdGNoKHMpIENQIGEgY29tcGxldGVyKVxuIik7IHN5cy5leGl0KDEpCiAgICBpZiBFbmcxNSBhbmQgbm90IEVORzE1X1NLSVBfSU5JVDogRW5nMTUoKSAgICMgc2lub24gcmVwb3J0ZSBhIGxhIDFyZSByZWNoZXJjaGUKICAgIHNldF90aHJlYWRzKFRIUkVBRFMpICAgICAgICMgbmUgZmFpdCByaWVuIHNpIFRIUkVBRFM9MCAobGUgbW90ZXVyIGdhcmRlIHRvdXMgc2VzIGNvZXVycykKICAgIG4gPSAoRW5nNygpIGlmIEVuZzcgZWxzZSBiIiIpIG9yIENGR1snbmFtZSddLmVuY29kZSgpCiAgICBhID0gKEVuZzYoKSBpZiBFbmc2IGVsc2UgYiIiKSBvciBDRkcuZ2V0KCdhdXRob3InLCAiRnJhbnMgTW9yc2NoIikuZW5jb2RlKCkKICAgIEVOR19OQU1FID0gbi5kZWNvZGUoImxhdGluMSIsICJyZXBsYWNlIik7IEVOR19BVVRIT1IgPSBhLmRlY29kZSgibGF0aW4xIiwgInJlcGxhY2UiKQogICAgbG9nKGYicHJldCA6IHtFTkdfTkFNRX0gLyB7RU5HX0FVVEhPUn0iKQoKZGVmIHNldF90aW1lX3BhcmFtcyhhdmFpbF9tcywgaW5jX21zPTAsIG1vdmVzdG9nbz0wKToKICAgICIiIlByb2dyYW1tZSBsZSBidWRnZXQtdGVtcHMgSU5URVJORSBkdSBtb3RldXIgc2Vsb24gbGEgY2FydGUgUkVFTExFIGRlIENoZXNzQmFzZQogICAgKGV0YWJsaWUgcGFyIGR1bXBzIHNwYXJhbXMgc291cyBsJ2ludGVyZmFjZSBuYXRpdmUsIGNvbmZpcm1lZSBlbiBydW50aW1lIHN1ciBKdW5pb3IgOCkgOgogICAgICAweDg2MiA9IDEgKG1vZGUgdGVtcHMpLCAweDg2NCA9IHRlbXBzIHJlc3RhbnQgZW4gU0VDT05ERVMgKGR3b3JkKSwKICAgICAgMHg4NzAgPSBjb3VwcyByZXN0YW50cyAod29yZCksIDB4ODc2ID0gMSAocmVnaW1lIHBhcnRpZSA7IDIgPSBhbmFseXNlKSwKICAgICAgMHg4NWUgPSAxLCBldCAweDg2OC8weDg2Yy8weDg3MiByZXN0ZW50IGEgMCAoQ0IgbmUgbGVzIHJlbXBsaXQgcGFzKS4KICAgIFJlY2V0dGUgQ0IgcG91ciBkdSB0ZW1wcy1wYXItY291cCAodnUgZGFucyBsZSBkdW1wIDYgcy9jb3VwIC0+IDQ4IHMgLyA4IGNvdXBzKSA6CiAgICBlY3JpcmUgKE4geCB0ZW1wc19wYXJfY291cCwgTikuIiIiCiAgICBpZiBDRkcuZ2V0KCdzaHJlZGRlcl9zcCcpOiAgICAgICAgICAgICAgICMgU2hyZWRkZXIgOiBwYXMgZGUgbW9kZSB0ZW1wcyBNb3JzY2ggLT4gcmVwbGkgcHJvZm9uZGV1cgogICAgICAgIHN0cnVjdC5wYWNrX2ludG8oIjxoIiwgc3BhcmFtcywgMHgxOCwgNDcpOyByZXR1cm4KICAgIGlmIG1vdmVzdG9nbzogICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBwZW5kdWxlIHJlZWxsZSA6IHRlbXBzIHJlc3RhbnQgKyBjb3VwcyByZXN0YW50cyB2cmFpcwogICAgICAgIHNlY3MgPSBtYXgoMSwgaW50KHJvdW5kKGF2YWlsX21zIC8gMTAwMC4wKSkpCiAgICAgICAgbXRnICA9IG1heCgyLCBpbnQobW92ZXN0b2dvKSkgICAgICAgICMgMSAtPiAyIDogcHJ1ZGVuY2UgZGl2MCAoY3Jhc2ggY29uc3RhdGUgc3VyIGwnYW5jaWVubmUgY2FydGUpCiAgICBlbHNlOiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgbW92ZXRpbWUgLyBzYW5zIG10ZyA6IHJlY2V0dGUgQ0IgKE4geCB0cGMsIE4pCiAgICAgICAgTiA9IDgKICAgICAgICBzZWNzID0gbWF4KDEsIGludChyb3VuZChhdmFpbF9tcyAqIE4gLyAxMDAwLjApKSkKICAgICAgICBtdGcgID0gTgogICAgc3RydWN0LnBhY2tfaW50bygiPGgiLCBzcGFyYW1zLCBJVEVSREVQVEhfT0ZGLCAxKSAgICAgICAgICMgY29tbWUgQ0IgKGxlIHRlbXBzIGJvcm5lLCBwYXMgbGEgcHJvZm9uZGV1cikKICAgIHN0cnVjdC5wYWNrX2ludG8oIjxoIiwgc3BhcmFtcywgTU9ERV9PRkYsIDEpICAgICAgICAgICAgICAjIG1vZGUgdGVtcHMKICAgIHN0cnVjdC5wYWNrX2ludG8oIjxpIiwgc3BhcmFtcywgMHg4NjQsIHNlY3MpICAgICAgICAgICAgICAjIHRlbXBzIHJlc3RhbnQgKHNlY29uZGVzKSAtIGNoYW1wIHJlZWxsZW1lbnQgbHUKICAgIHN0cnVjdC5wYWNrX2ludG8oIjxoIiwgc3BhcmFtcywgMHg4NzAsIG10ZykgICAgICAgICAgICAgICAjIGNvdXBzIHJlc3RhbnRzIC0gY2hhbXAgcmVlbGxlbWVudCBsdQogICAgc3RydWN0LnBhY2tfaW50bygiPGkiLCBzcGFyYW1zLCBUX0FWQUlMX09GRiwgMCkgICAgICAgICAgICMgMHg4NjggOiBDQiBsYWlzc2UgMAogICAgc3RydWN0LnBhY2tfaW50bygiPGkiLCBzcGFyYW1zLCBUX0lOQ19PRkYsIDApICAgICAgICAgICAgICMgMHg4NmMgOiBDQiBsYWlzc2UgMAogICAgc3RydWN0LnBhY2tfaW50bygiPGgiLCBzcGFyYW1zLCBUX01UR19PRkYsIDApICAgICAgICAgICAgICMgMHg4NzIgOiBDQiBsYWlzc2UgMAogICAgc3RydWN0LnBhY2tfaW50bygiPGgiLCBzcGFyYW1zLCAweDg3NiwgaW50KEY4NzYpIGlmIEY4NzYgaXMgbm90IE5vbmUgZWxzZSAxKSAgICMgMSA9IHBhcnRpZSAoQ0IpCiAgICBpZiBGODVDIGlzIG5vdCBOb25lIGFuZCBub3QgX2hpc3Rfb2tbMF06ICAgICAgIyBuZSBwYXMgZWNyYXNlciBsZSBDT01QVEUgREUgQ09VUFMgZHUgcmVqZXUKICAgICAgICBzdHJ1Y3QucGFja19pbnRvKCI8aCIsIHNwYXJhbXMsIDB4ODVjLCBpbnQoRjg1QykpCiAgICBhcHBseV9wb2tlKCkKICAgIGlmIENBTElCOiBsb2coZiJbZGlhZ10gc2V0X3RpbWVfcGFyYW1zIENCbWFwIHNlY3M9e3NlY3N9IG10Zz17bXRnfSAweDg3Nj17Rjg3NiBvciAxfSAoYXZhaWxfbXM9e2F2YWlsX21zfSkiKQoKCmRlZiBzZXRfcGFyYW1zKGRlcHRoKToKICAgIGlmIENGRy5nZXQoJ3NocmVkZGVyX3NwJyk6CiAgICAgICAgc3RydWN0LnBhY2tfaW50bygiPGgiLCBzcGFyYW1zLCAweDE4LCBkZXB0aCkgICAjIEVuZzkgbGl0IFNQKzB4MTggLT4gcHJvZm9uZGV1ciBwYXNzZWUgYSBBbmFseXNlCiAgICAgICAgcmV0dXJuCiAgICAjICJnbyBkZXB0aCBOIiA6IHByb2ZvbmRldXIgZW4gMHg4NWUsIHBsdXMgbGUgc2VsZWN0ZXVyIGQnYXJyZXQgMHg4NjIgKG1vZGUgMiA9IGNvbm51LWJvbiwgYXR0ZWludAogICAgIyBsYSBwcm9mb25kZXVyIGRlbWFuZGVlKS4gMHg4NzQgbidhIGRlIHNlbnMgcXUnZW4gbW9kZSAyLzMgKGJvcm5lLXRlbXBzKSA6IHNpbm9uIG9uIGxlIG5ldXRyYWxpc2UuCiAgICBzdHJ1Y3QucGFja19pbnRvKCI8aCIsIHNwYXJhbXMsIElURVJERVBUSF9PRkYsIGRlcHRoKQogICAgaWYgTU9ERV9WQUxVRSBpcyBub3QgTm9uZTogICAgICAgICAgICAgICAjIG92ZXJyaWRlIG1hbnVlbCBkZSBkaWFnbm9zdGljCiAgICAgICAgc3RydWN0LnBhY2tfaW50bygiPGgiLCBzcGFyYW1zLCBNT0RFX09GRiwgTU9ERV9WQUxVRSkKICAgICAgICBzdHJ1Y3QucGFja19pbnRvKCI8aCIsIHNwYXJhbXMsIENBUERFUFRIX09GRiwgbWluKGRlcHRoLCA0NykgaWYgQ0FQREVQVEhfU0VUIGVsc2UgMCkKICAgICAgICBpZiBDQUxJQjogbG9nKGYiW2RpYWddIHNldF9wYXJhbXMoZGVwdGg9e2RlcHRofSkgT1ZFUlJJREUgMHg4NjI9e01PREVfVkFMVUV9IDB4ODc0PXttaW4oZGVwdGgsNDcpIGlmIENBUERFUFRIX1NFVCBlbHNlIDB9IikKICAgICAgICByZXR1cm4KICAgIG0gPSBpbnQoREVQVEhfTU9ERSkgaWYgREVQVEhfTU9ERS5sc3RyaXAoJy0nKS5pc2RpZ2l0KCkgZWxzZSAyCiAgICBzdHJ1Y3QucGFja19pbnRvKCI8aCIsIHNwYXJhbXMsIE1PREVfT0ZGLCBtKQogICAgc3RydWN0LnBhY2tfaW50bygiPGgiLCBzcGFyYW1zLCBDQVBERVBUSF9PRkYsIG1pbihkZXB0aCwgNDcpIGlmIG0gaW4gKDIsIDMpIGVsc2UgMCkKICAgIGlmIEY4NzYgaXMgbm90IE5vbmU6IHN0cnVjdC5wYWNrX2ludG8oIjxoIiwgc3BhcmFtcywgMHg4NzYsIGludChGODc2KSkgICMgMiA9IHJlY2hlcmNoZSBjb21wbGV0ZQogICAgYXBwbHlfcG9rZSgpCiAgICBpZiBDQUxJQjogbG9nKGYiW2RpYWddIHNldF9wYXJhbXMoZGVwdGg9e2RlcHRofSkgMHg4NjI9e219IDB4ODc0PXtzdHJ1Y3QudW5wYWNrX2Zyb20oJzxoJyxzcGFyYW1zLENBUERFUFRIX09GRilbMF19IikKCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KIyAgQm91Y2xlIFVDSQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CmJvYXJkID0gQm9hcmQoKTsgYm9hcmQuc2V0X2ZlbihTVEFSVF9GRU4pCgpkZWYgX3NhZmVfc3RvcCgpOgogICAgdHJ5OgogICAgICAgIGlmIEVuZzM6IEVuZzMoKQogICAgZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOiBsb2coInN0b3AgRVhDOiIsIHJlcHIoZSkpCgpfc2VhcmNoX3RocmVhZCA9IE5vbmUKX2NyYXNoX3N0cmVhayA9IDAgICAgICAgICAgIyBjcmFzaGVzIGNvbnNlY3V0aWZzIGQnRW5nOSA6IGF1LWRlbGEgZCd1biBzZXVpbCwgbGUgbW90ZXVyIGVzdCBwZXJkdQoKZGVmIF9lbWl0X2Jlc3Rtb3ZlKG12KToKICAgICMgRW1ldCBsZSAiYmVzdG1vdmUiIFVORSBTRVVMRSBmb2lzIDogbGUgcHJlbWllciBkZXMgdHJvaXMgY2hlbWlucyBnYWduZSAocmV0b3VyIG5vcm1hbCwgY3Jhc2gKICAgICMgcmF0dHJhcGUsIG91IHdhdGNoZG9nIGFudGktZGVib3JkZW1lbnQpLiBMZXMgYXV0cmVzIGRldmllbm5lbnQgc2lsZW5jaWV1eCAtPiBqYW1haXMgZGUgZG91YmxlIGNvdXAuCiAgICBpZiBzdC5iZXN0bW92ZV9zZW50OiByZXR1cm4KICAgIHN0LmJlc3Rtb3ZlX3NlbnQgPSBUcnVlCiAgICB1Y2lfb3V0KGYiYmVzdG1vdmUge212IGlmIG12IGVsc2UgJzAwMDAnfSIpCgpkZWYgX3dhdGNoZG9nKCk6CiAgICAjIEZpbGV0IEFOVEktREVCT1JERU1FTlQuIEwnYXJyZXQgRW5nMyBlc3Qgbm9uIGZpYWJsZSBzdXIgVGlnZXIgOiBpbCBwcmVuZCBlbiBnZW5lcmFsICh+NSwyIHMgcG91cgogICAgIyB1biBidWRnZXQgZGUgNSBzKSBtYWlzIGRlYm9yZGUgcGFyZm9pcyBlbm9ybWVtZW50ICg2LDcgcywgdm9pcmUgMTEgcyBvYnNlcnZlcykgY2FyIGxhIHJlY2hlcmNoZSBuZQogICAgIyB2ZXJpZmllIGxlIGRyYXBlYXUgc3RvcCBxdSdhIHVuZSBmcm9udGllcmUgbmF0dXJlbGxlIGxvaW50YWluZS4gQXVjdW5lIG1hcmdlIGZpeGUgbmUgY291dnJlIDExIHMuCiAgICAjIFNpIGxhIHJlY2hlcmNoZSBkZXBhc3NlIGxlIGJ1ZGdldCwgb24gcmVuZCBsZSBkZXJuaWVyIG1laWxsZXVyIGNvdXAgY29ubnUgU0FOUyBhdHRlbmRyZSBFbmc5IC0+CiAgICAjIGxlIHRlbXBzIHBhciBjb3VwIGVzdCBwbGFmb25uZSBhdSBidWRnZXQsIHF1b2kgcXVlIGZhc3NlIGxlIG1vdGV1ci4KICAgICMgTUFJUyA6IHNpIEFVQ1VOIGNvdXAgbidlc3QgZW5jb3JlIGNvbm51ICh0b3V0IHByZW1pZXIgY291cCBhcHJlcyBsZSBsaXZyZSwgbGUgbW90ZXVyIG4nYSBwYXMKICAgICMgZW5jb3JlIGVtaXMgZGUgcmFwcG9ydCAweDE1NCksIGlsIG5lIGZhdXQgUklFTiBlbWV0dHJlIDogdW4gImJlc3Rtb3ZlIDAwMDAiIGVzdCByZWZ1c2UgcGFyIGxhIEdVSQogICAgIyBldCBwZXJkIGxhIHBhcnRpZSBzdXItbGUtY2hhbXAuIE1pZXV4IHZhdXQgbGFpc3NlciBsYSByZWNoZXJjaGUgYWJvdXRpciwgcXVpdHRlIGEgZGVib3JkZXIgdW4gcGV1CiAgICAjIChsYSB0b2xlcmFuY2UgZGUgbGEgR1VJIGFic29yYmUgY2UgcmV0YXJkKSBxdWUgZGUgcmVuZHJlIHVuIGNvdXAgbnVsLgogICAgaWYgc3Quc2VhcmNoaW5nIGFuZCBub3Qgc3QuYmVzdG1vdmVfc2VudDoKICAgICAgICBtdiA9IHN0LmJlc3Qgb3IgKHN0LmpyX21vdmUgb3Igc3QuanJfYWx0KSBvciBzdC5mel9tb3ZlCiAgICAgICAgaWYgbXY6IF9lbWl0X2Jlc3Rtb3ZlKG12KQogICAgICAgIGVsc2U6ICBsb2dfY3Jhc2goIndhdGNoZG9nIDogYXVjdW4gY291cCBjb25udSBhdSBidWRnZXQgLT4gb24gbGFpc3NlIGxhIHJlY2hlcmNoZSBhYm91dGlyIikKCmRlZiBkb19zZWFyY2goZGVwdGg9Tm9uZSwgYnVkZ2V0X21zPU5vbmUsIGluY19tcz0wLCBtb3Zlc3RvZ289MCk6CiAgICBpZiBFTkcxNV9CRUZPUkVfU0VBUkNIIGFuZCBFbmcxNToKICAgICAgICBFbmcxNSgpCiAgICAgICAgaWYgQ0FMSUI6IGxvZygnW2RpYWddIEVuZzE1KCkgYXBwZWxlIGF2YW50IGxhIHJlY2hlcmNoZScpCiAgICBzdC5iZXN0ID0gTm9uZTsgc3QuZGVwdGggPSAwOyBzdC5zY29yZSA9IDA7IHN0LnNlYXJjaGluZyA9IFRydWU7IHN0LnQwID0gdGltZS50aW1lKCkKICAgIHN0LmJlc3Rtb3ZlX3NlbnQgPSBGYWxzZQogICAgc3QuanJfbW92ZSA9IE5vbmU7IHN0LmpyX2N0eCA9IDA7IHN0LmpyX25vZGVzID0gMDsgc3QuanJfc2NvcmUgPSAwOyBzdC5qcl9zY29yZV9raW5kID0gMQogICAgc3QuanJfcHYgPSBOb25lOyBzdC5qcl9hbHQgPSBOb25lICAgICAgIyBQVi9jb3VwIGRlIHJlcGxpIDogbmUgSkFNQUlTIHJldXRpbGlzZXIgY2V1eCBkdSBjb3VwIHByZWNlZGVudAogICAgc3QuZnpfbW92ZSA9IE5vbmU7IHN0LmZ6X3Njb3JlID0gMDsgc3QuZnpfcnNjb3JlID0gMDsgc3QuZnpfcmtpbmQgPSAxOyBzdC5mel9ybW92ZSA9IE5vbmUgICAjIEZyaXR6IDogcmVpbml0IHBhciByZWNoZXJjaGUKICAgIHN0Lmxhc3RfZW1pdCA9IE5vbmU7IHN0LmJlc3RfcHYgPSBOb25lOyBzdC5yZXFfZGVwdGggPSBkZXB0aCBvciAwOyBzdC5iZXN0X3Njb3JlX3NlZW4gPSAtMjAwMDAwMDAwMDsgc3QuYXJnbWF4X2RlcHRoID0gLTEKICAgIHN0LnN0b3Bfc2VudCA9IEZhbHNlOyBzdC5saW1pdF9kZXB0aCA9IE5vbmUgICAgIyBTaHJlZGRlciA6IGFycmV0IHBhciBsZSBjYWxsYmFjayBhIGxhIHByb2ZvbmRldXIgY2libGUKICAgIHN0Lm5vZGUwID0gcmVhZF9ub2Rlc19yYXcoKSBpZiAoQ0ZHWydub2RlJ10gYW5kIENGRy5nZXQoJ25vZGVfYWNjdW11bGF0ZXMnKSkgZWxzZSAwCiAgICB0cnk6CiAgICAgICAgX2hpc3Rfb2tbMF0gPSBib29sKENGRy5nZXQoJ2hpc3RfcmVwbGF5JykpIGFuZCBoaXN0b3J5X3RvX2VuZ2luZShzcGFyYW1zKQogICAgZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOgogICAgICAgIGxvZ19jcmFzaChmImhpc3RvcnlfdG9fZW5naW5lIEVYQ0VQVElPTiB7ZSFyfSAtPiByZXBsaSBwbGF0ZWF1IGZpbmFsIikKICAgICAgICBfaGlzdF9va1swXSA9IEZhbHNlCiAgICBpZiBub3QgX2hpc3Rfb2tbMF06CiAgICAgICAgYm9hcmRfdG9fZW5naW5lKGJvYXJkLCBzcGFyYW1zKQogICAgdGltZXIgPSBOb25lOyB3YXRjaGRvZyA9IE5vbmUKICAgIGlmIGJ1ZGdldF9tcyBpcyBub3QgTm9uZToKICAgICAgICBpZiBJTk5FUl9USU1FOgogICAgICAgICAgICBzZXRfdGltZV9wYXJhbXMoYnVkZ2V0X21zLCBpbmNfbXM9aW5jX21zLCBtb3Zlc3RvZ289bW92ZXN0b2dvKQogICAgICAgIGVsc2U6CiAgICAgICAgICAgIHNldF9wYXJhbXMoNDcpCiAgICAgICAgIyBNYXJnZSBhbnRpLWZvcmZhaXQuIEJhbmtzaWEgY2hyb25vbWV0cmUgZGUgbCdlbnZvaSBkZSAiZ28iIGEgbGEgcmVjZXB0aW9uIGRlICJiZXN0bW92ZSIgOwogICAgICAgICMgbm90cmUgcmV0b3VyID0gZmVlZCArIGJ1ZGdldCArIExBVEVOQ0UgRCdBUlJFVCAoRW5nMyBzaWduYWxlIGxlIHN0b3AsIG1haXMgbGUgbW90ZXVyIG5lIGxlCiAgICAgICAgIyByZW1hcnF1ZSBxdSdhIHNhIHByb2NoYWluZSB2ZXJpZmljYXRpb24gZHUgZHJhcGVhdSkgKyByZW5kdS4gR2FtYml0L0NoZXNzIFRpZ2VyIG5lIHZlcmlmaWVudAogICAgICAgICMgY2UgZHJhcGVhdSBxdWUgdG91cyBsZXMgfjEyMCBtcyBkZSByZWNoZXJjaGUgLT4gYXZlYyB1bmUgbWFyZ2UgZGUgMTIwIG1zIGxlIGNvdXAgc29ydGFpdAogICAgICAgICMgQVBSRVMgbGEgYmFycmUgZGUgQmFua3NpYSAodGltZXIgMjg4MCBtcyBtYWlzIHJlY2hlcmNoZSBqdXNxdSdhIDMwMDAgbXMpID0gZm9yZmFpdC4gUGxhbmNoZXIKICAgICAgICAjIHJlbGV2ZSBhIDMwMCBtcyBwb3VyIGFic29yYmVyIGNldHRlIGxhdGVuY2UgOyB+MTAlIGR1IGJ1ZGdldCwgcGxhZm9uZCA2MDAgbXMuCiAgICAgICAgbWFyZ2luID0gbWluKG1heCgzMDAsIGJ1ZGdldF9tcyAvLyAxMCksIDYwMCkKICAgICAgICBlZmYgPSBtYXgoMjAsIGJ1ZGdldF9tcyAtIG1hcmdpbikKICAgICAgICB0aW1lciA9IHRocmVhZGluZy5UaW1lcihlZmYgLyAxMDAwLjAsIF9zYWZlX3N0b3ApOyB0aW1lci5zdGFydCgpCiAgICAgICAgIyBXYXRjaGRvZyA6IHBsYWZvbmQgRFVSIGF1IGJ1ZGdldC4gU2kgRW5nMyBuJ2EgcGFzIGZhaXQgcmVuZHJlIGxhIG1haW4gYSB0ZW1wcywgb24gcmVuZCBxdWFuZAogICAgICAgICMgbWVtZSBsZSBkZXJuaWVyIG1laWxsZXVyIGNvdXAgY29ubnUgKHZvaXIgX3dhdGNoZG9nKS4gSW5kaXNwZW5zYWJsZSA6IGwnYXJyZXQgVGlnZXIgZGVib3JkZQogICAgICAgICMgcGFyZm9pcyBkZSBwbHVzaWV1cnMgc2Vjb25kZXMsIGNlIHF1J2F1Y3VuZSBtYXJnZSBuZSBjb3V2cmUuCiAgICAgICAgd2F0Y2hkb2cgPSB0aHJlYWRpbmcuVGltZXIoYnVkZ2V0X21zIC8gMTAwMC4wLCBfd2F0Y2hkb2cpOyB3YXRjaGRvZy5zdGFydCgpCiAgICAgICAgaWYgQ0FMSUI6IGxvZyhmInNlYXJjaCBidWRnZXQ9e2J1ZGdldF9tc31tcyAodGltZXIge2VmZn1tcywgbWFyZ2Uge21hcmdpbn1tcywgd2F0Y2hkb2cge2J1ZGdldF9tc31tcykiKQogICAgZWxzZToKICAgICAgICBzZXRfcGFyYW1zKGRlcHRoKQogICAgICAgICMgU2hyZWRkZXIgaWdub3JlIGxhIGxpbWl0ZSBkZSBwcm9mb25kZXVyIChjaGVyY2hlIGVuIGluZmluaSkgLT4gb24gbCdhcnJldGVyYSB2aWEgbGUgY2FsbGJhY2sKICAgICAgICAjIHF1YW5kIGxhIHByb2ZvbmRldXIgY2libGUgZXN0IGF0dGVpbnRlIChFbmc5IG5lIHJlbmQgcGFzIGxhIG1haW4gdG91dCBzZXVsIGVuIG1vZGUgcHJvZm9uZGV1cikuCiAgICAgICAgaWYgQ0ZHLmdldCgnc2hyZWRkZXJfc3AnKTogc3QubGltaXRfZGVwdGggPSBkZXB0aAogICAgICAgIGlmIENBTElCOiBsb2coZiJzZWFyY2ggZGVwdGg9e2RlcHRofSIpCiAgICB0cnk6CiAgICAgICAgRW5nOShTUCkgICAgICAgICAgICAgICAgICAgICAgICAgICMgYmxvcXVhbnQKICAgICAgICAjIEdhcmRlLWZvdSBkdSBtb2RlIGhpc3RvcmlxdWUgOiBzaSB1biBOZXdNb3ZlIGEgZXRlIFJFRlVTRSAoZW5jb2RhZ2UgaW5hdHRlbmR1KSwgRW5nMTEKICAgICAgICAjIHJlbmQgMCBldCBFbmc5IHJldmllbnQgSU1NRURJQVRFTUVOVCBzYW5zIGNoZXJjaGVyIChhdWN1biByYXBwb3J0LCBhdWN1biBjb3VwKS4gT24gc2UKICAgICAgICAjIHJlcGxpZSBhbG9ycyBzdXIgbGUgcGxhdGVhdSBmaW5hbCBldCBvbiByZWxhbmNlIFVORSBmb2lzIDsgbGVzIHRpbWVycy93YXRjaGRvZyBkdSBidWRnZXQKICAgICAgICAjIHJlc3RlbnQgYXJtZXMsIGxhIHJlbGFuY2UgY29uc29tbWUgbGUgcmVzdGUgZHUgYnVkZ2V0LiBJbmNpZGVudCBqb3VybmFsaXNlIHBvdXIgYW5hbHlzZS4KICAgICAgICBpZiAoX2hpc3Rfb2tbMF0gYW5kIHN0LmJlc3QgaXMgTm9uZSBhbmQgc3QuanJfbW92ZSBpcyBOb25lCiAgICAgICAgICAgICAgICBhbmQgKHRpbWUudGltZSgpIC0gc3QudDApIDwgMC41KToKICAgICAgICAgICAgIyB2MTMgLS0gVkVSRElDVCBERVMgU09OREVTIDEtMyAoMjEvMDgpIDogY2UgcmV0b3VyIHJhcGlkZSBzYW5zIHJhcHBvcnQgbidlc3QgUEFTCiAgICAgICAgICAgICMgdW4gcmVmdXMgZCdFbmcxMS4gRW4gbW9kZSBJTk5FUlRJTUUgbGEgY2FydGUgZGUgdGVtcHMgYWxsb3VlIHBhcmZvaXMgPDFzIGV0IGxlCiAgICAgICAgICAgICMgbW90ZXVyIHJlcG9uZCBzYW5zIGVtZXR0cmUgZGUgcmFwcG9ydCA6IG1vdGV1ciBTQUlOLCBhbGFybWUgZmF1c3NlLiBMZXMgfjcwMAogICAgICAgICAgICAjICJSRUpFVEUiIGRlcyBnYXVudGxldHMgZXRhaWVudCB0b3VzIGRlIGNldHRlIGNsYXNzZSAoYXVjdW4gdnJhaSByZWZ1cyByZXByb2R1aXQsCiAgICAgICAgICAgICMgNzYgZmVlZHMgdmVyaWZpZXMgY29ycmVjdHMgYml0IGEgYml0KS4gTCdhbmNpZW4gZ2FyZGUtZm91IHJlLWFsaW1lbnRhaXQgYWxvcnMgZW4KICAgICAgICAgICAgIyBwbGF0ZWF1IGZpbmFsIC0tIHJldGlyYW50IGwnaGlzdG9yaXF1ZSBwaWxlIGRhbnMgbGVzIGZpbmFsZXMgOiBjJ2V0YWl0IExVSSBsYQogICAgICAgICAgICAjIGNhdXNlIGRlcyBudWxsZXMgcGFyIHJlcGV0aXRpb24gcmVzaWR1ZWxsZXMgKGc5IGV0IGNvbnNvcnRzKS4KICAgICAgICAgICAgIyBOb3V2ZWF1IHByb3RvY29sZSA6IHJlbGFuY2UgMSA9IFNQIElOVEFDVCAoaGlzdG9yaXF1ZSBjb25zZXJ2ZSkgOyBsJ29ic2VydmF0aW9uCiAgICAgICAgICAgICMgZGVzIHNvbmRlcyBCL0QgbW9udHJlIHF1ZSBsYSAyZSByZWNoZXJjaGUgcHJvZHVpdCBsZSBjb3VwLiBQbGF0ZWF1IGZpbmFsIGVuCiAgICAgICAgICAgICMgREVSTklFUiByZWNvdXJzIHNldWxlbWVudCwgc2kgYXVjdW4gY291cCBuJ2VtZXJnZSAtLSBzZXVsIGNlIGNhcyBlc3QgdW4gaW5jaWRlbnQuCiAgICAgICAgICAgIGlmIGJ1ZGdldF9tcyBpcyBub3QgTm9uZToKICAgICAgICAgICAgICAgIGlmIElOTkVSX1RJTUU6IHNldF90aW1lX3BhcmFtcyhidWRnZXRfbXMsIGluY19tcz1pbmNfbXMsIG1vdmVzdG9nbz1tb3Zlc3RvZ28pCiAgICAgICAgICAgICAgICBlbHNlOiAgICAgICAgICBzZXRfcGFyYW1zKDQ3KQogICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgc2V0X3BhcmFtcyhkZXB0aCkKICAgICAgICAgICAgRW5nOShTUCkgICAgICAgICAgICAgICAgICAgICAgIyByZWxhbmNlIDEgOiBtZW1lIGFsaW1lbnRhdGlvbiwgaGlzdG9yaXF1ZSBpbnRhY3QKICAgICAgICAgICAgaWYgKHN0LmJlc3QgaXMgTm9uZSBhbmQgc3QuanJfbW92ZSBpcyBOb25lCiAgICAgICAgICAgICAgICAgICAgYW5kICh0aW1lLnRpbWUoKSAtIHN0LnQwKSA8IDEuMCk6CiAgICAgICAgICAgICAgICBsb2dfY3Jhc2goZiJhdWN1biBjb3VwIGFwcmVzIHJlbGFuY2UgYSBmZWVkIGludGFjdCAocGFydGllIHtsZW4oZ2FtZV9tb3Zlcyl9ICIKICAgICAgICAgICAgICAgICAgICAgICAgICBmImNvdXBzLCBxdWV1ZSB7X2hpc3RfblswXX0pIC0+IHBsYXRlYXUgZmluYWwgZW4gZGVybmllciByZWNvdXJzIikKICAgICAgICAgICAgICAgIHRyeToKICAgICAgICAgICAgICAgICAgICBpZiBfaGlzdF9mZWVkWzBdIGlzIG5vdCBOb25lIGFuZCBfaGlzdF9kdW1wc1swXSA8IDM6CiAgICAgICAgICAgICAgICAgICAgICAgIF9oaXN0X2R1bXBzWzBdICs9IDEKICAgICAgICAgICAgICAgICAgICAgICAgZiA9IF9oaXN0X2ZlZWRbMF0KICAgICAgICAgICAgICAgICAgICAgICAgbG9nX2NyYXNoKGYiICBbZHVtcCB7X2hpc3RfZHVtcHNbMF19LzNdIGJhc2U6IHtmWydiYXNlJ119IikKICAgICAgICAgICAgICAgICAgICAgICAgbG9nX2NyYXNoKGYiICBbZHVtcF0gcXVldWU6IHsnICcuam9pbihmWyd0YWlsJ10pfSIpCiAgICAgICAgICAgICAgICAgICAgICAgIGxvZ19jcmFzaChmIiAgW2R1bXBdIG9jdGV0cyBTUCsweDVjOiB7Zlsnb2N0ZXRzJ119IikKICAgICAgICAgICAgICAgIGV4Y2VwdCBFeGNlcHRpb24gYXMgZToKICAgICAgICAgICAgICAgICAgICBsb2dfY3Jhc2goZiIgIFtkdW1wXSBlY2hlYzoge2Uhcn0iKQogICAgICAgICAgICAgICAgX2hpc3Rfb2tbMF0gPSBGYWxzZQogICAgICAgICAgICAgICAgYm9hcmRfdG9fZW5naW5lKGJvYXJkLCBzcGFyYW1zKQogICAgICAgICAgICAgICAgaWYgYnVkZ2V0X21zIGlzIG5vdCBOb25lOgogICAgICAgICAgICAgICAgICAgIGlmIElOTkVSX1RJTUU6IHNldF90aW1lX3BhcmFtcyhidWRnZXRfbXMsIGluY19tcz1pbmNfbXMsIG1vdmVzdG9nbz1tb3Zlc3RvZ28pCiAgICAgICAgICAgICAgICAgICAgZWxzZTogICAgICAgICAgc2V0X3BhcmFtcyg0NykKICAgICAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICAgICAgc2V0X3BhcmFtcyhkZXB0aCkKICAgICAgICAgICAgICAgIEVuZzkoU1ApICAgICAgICAgICAgICAgICAgIyByZWxhbmNlIDIgZXQgZGVybmllcmUgOiBwbGF0ZWF1IGZpbmFsCiAgICAgICAgaWYgRU5HMTVfQUZURVIgYW5kIEVuZzE1IGFuZCBub3QgX2VuZzE1X3ByaW1lZFswXToKICAgICAgICAgICAgX2VuZzE1X3ByaW1lZFswXSA9IFRydWUKICAgICAgICAgICAgRW5nMTUoKSAgICAgICAgICAgICAgICAgICAgICAgIyBhbW9yY2UgbGVzIHRhYmxlcyBBUFJFUyBsYSAxcmUgcmVjaGVyY2hlIChjb21tZSBsJ2ludGVyZmFjZSkKICAgICAgICAgICAgaWYgQ0FMSUI6IGxvZygnW2RpYWddIEVuZzE1KCkgYW1vcmNlIGFwcmVzIGxhIDFyZSByZWNoZXJjaGUnKQogICAgZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOgogICAgICAgICMgQ2VydGFpbnMgbW90ZXVycyAoR2FtYml0IFRpZ2VyIDIuMCwgYWdyZXNzaWYgZXQgYW5jaWVuKSBwZXV2ZW50IENSQVNIRVIgZGFucyBFbmc5IHN1cgogICAgICAgICMgY2VydGFpbmVzIHBvc2l0aW9ucyAodmlvbGF0aW9uIGQnYWNjZXMpLiBTYW5zIGdhcmRlLWZvdSwgbGUgdGhyZWFkIG1ldXJ0IHNhbnMgcmVuZHJlIGRlCiAgICAgICAgIyBjb3VwIC0+IEJhbmtzaWEgZm9yZmFpdC4gT24gcmF0dHJhcGUgZXQgb24gcmVuZCBsZSBkZXJuaWVyIG1laWxsZXVyIGNvdXAgY29ubnUgKGlzc3UgZGVzCiAgICAgICAgIyByYXBwb3J0cyBkZWphIHJlY3VzKSwgcG91ciBzYXV2ZXIgbGEgcGFydGllIGF1IGxpZXUgZGUgbGEgcGVyZHJlIHN1ciB0aW1lLW91dC4KICAgICAgICAjIEFwcmVzIGNlIGNyYXNoLCBUaWdlciBlc3QgaXJyZWN1cGVyYWJsZSBlbiB2b2wgOiBpbCBsYWlzc2Ugc29uIGRyYXBlYXUgaW50ZXJuZSBhcm1lIGV0IHRvdXQKICAgICAgICAjIGFwcGVsIHVsdGVyaWV1ciBkZWNsZW5jaGUgdW5lIGFsZXJ0ZSBkZSByZWVudHJhbmNlLiBPbiBzZSBjb250ZW50ZSBkb25jIGR1IGNvdXAgZGUgcmVwbGkgOwogICAgICAgICMgc2V1bCB1biByZWRlbWFycmFnZSBkdSBwcm9jZXNzdXMgKGZhaXQgcGFyIGxhIEdVSSBhIGxhIHBhcnRpZSBzdWl2YW50ZSkgbGUgcmVtZXQgZCdhcGxvbWIuCiAgICAgICAgZ2xvYmFsIF9jcmFzaF9zdHJlYWsKICAgICAgICBfY3Jhc2hfc3RyZWFrICs9IDEKICAgICAgICBsb2dfY3Jhc2goZiJFbmc5IENSQVNIICh7ZSFyfSkgI3tfY3Jhc2hfc3RyZWFrfSAtPiByZXBsaSBzdXIgbGUgZGVybmllciBtZWlsbGV1ciBjb3VwIGNvbm51IikKICAgICAgICBpZiBfY3Jhc2hfc3RyZWFrID49IDM6CiAgICAgICAgICAgICMgTGUgbW90ZXVyIGNyYXNoZSBlbiBib3VjbGUgOiBjaGFxdWUgImdvIiByZXBsYW50ZSBpbnN0YW50YW5lbWVudCwgb24gcmVwb25kIHVuIGNvdXAgbnVsLAogICAgICAgICAgICAjIGxhIEdVSSBsZSByZWZ1c2UgZXQgcmVkZW1hbmRlIC0+IGJvdWNsZSBmb2xsZSAoMTY1IDAwMCBjcmFzaGVzIGVuIDMgbWluIG9ic2VydmVzLCBqb3VybmFsCiAgICAgICAgICAgICMgZGUgbGEgbWVtZSB0YWlsbGUsIHBhcnRpZSBwZXJkdWUgYXUgdGVtcHMgZGUgdG91dGUgZmFjb24pLiBNaWV1eCB2YXV0IGFycmV0ZXIgbGUgcHJvY2Vzc3VzIDoKICAgICAgICAgICAgIyBsYSBHVUkgcGVyZCBjZXR0ZSBwYXJ0aWUgbWFpcyBlbmNoYWluZSBsYSBzdWl2YW50ZSBhdmVjIHVuIG1vdGV1ciBuZXVmLCBhdSBsaWV1IGRlIHRvdXJuZXIKICAgICAgICAgICAgIyBhIHZpZGUuIFNldWwgdW4gcmVkZW1hcnJhZ2UgcmVtZXQgY2VzIG1vdGV1cnMgZCdhcGxvbWIgKGlscyBsZSBkaXNlbnQgZXV4LW1lbWVzKS4KICAgICAgICAgICAgbG9nX2NyYXNoKCJjcmFzaGVzIGVuIGJvdWNsZSAtPiBhcnJldCBkdSBwcm9jZXNzdXMgKHNldWwgdW4gcmVkZW1hcnJhZ2UgcmVzdGF1cmUgbGUgbW90ZXVyKSIpCiAgICAgICAgICAgIHRyeTogX2VtaXRfYmVzdG1vdmUoc3QuYmVzdCBvciAoc3QuanJfbW92ZSBvciBzdC5qcl9hbHQpIG9yIHN0LmZ6X21vdmUpCiAgICAgICAgICAgIGV4Y2VwdCBFeGNlcHRpb246IHBhc3MKICAgICAgICAgICAgb3MuX2V4aXQoMSkKICAgICAgICBpZiB0aW1lcjogdGltZXIuY2FuY2VsKCkKICAgICAgICBpZiB3YXRjaGRvZzogd2F0Y2hkb2cuY2FuY2VsKCkKICAgICAgICBzdC5zZWFyY2hpbmcgPSBGYWxzZQogICAgICAgIF9lbWl0X2Jlc3Rtb3ZlKHN0LmJlc3Qgb3IgKHN0LmpyX21vdmUgb3Igc3QuanJfYWx0KSBvciBzdC5mel9tb3ZlKQogICAgICAgIHJldHVybgogICAgaWYgdGltZXI6IHRpbWVyLmNhbmNlbCgpCiAgICBpZiB3YXRjaGRvZzogd2F0Y2hkb2cuY2FuY2VsKCkKICAgIHN0LnNlYXJjaGluZyA9IEZhbHNlCiAgICBnbG9iYWxzKClbJ19jcmFzaF9zdHJlYWsnXSA9IDAgICAgICAjIHJlY2hlcmNoZSBtZW5lZSBhIGJpZW4gOiBsYSBzZXJpZSBkZSBjcmFzaGVzIGVzdCByb21wdWUKICAgIGVtaXRfaW5mbyhmaW5hbD1UcnVlKQogICAgaWYgbm90IHN0LmJlc3Q6CiAgICAgICAgc3QuYmVzdCA9IHJlYWRfYmVzdF9tb3ZlKCkKICAgIF9lbWl0X2Jlc3Rtb3ZlKHN0LmJlc3QpCgpkZWYgc3RhcnRfc2VhcmNoKCoqa3cpOgogICAgZ2xvYmFsIF9zZWFyY2hfdGhyZWFkCiAgICBpZiBfc2VhcmNoX3RocmVhZCBhbmQgX3NlYXJjaF90aHJlYWQuaXNfYWxpdmUoKToKICAgICAgICAjIFVuZSByZWNoZXJjaGUgcHJlY2VkZW50ZSB0b3VybmUgZW5jb3JlICh3YXRjaGRvZyBheWFudCByZW5kdSB1biBjb3VwLCBvdSBzdG9wIG5vbiBwcmlzIGVuCiAgICAgICAgIyBjb21wdGUpLiBFbmc5IG4nZXN0IFBBUyByZWVudHJhbnQgOiBlbiBsYW5jZXIgdW5lIHNlY29uZGUgZW4gcGFyYWxsZWxlIGNvcnJvbXB0IGxlIG1vdGV1ci4KICAgICAgICAjIE9uIGluc2lzdGUgc3VyIGwnYXJyZXQgZXQgb24gYXR0ZW5kIHZyYWltZW50IDsgc2kgbGUgdGhyZWFkIHJlZnVzZSBkZSBtb3VyaXIsIG9uIHJlbmQgbGUKICAgICAgICAjIGRlcm5pZXIgY291cCBjb25udSBTQU5TIHJlbGFuY2VyIEVuZzkgKG1pZXV4IHF1J3VuZSBjb3JydXB0aW9uIHF1aSBwZXJkcmFpdCB0b3V0ZSBsYSBwYXJ0aWUpLgogICAgICAgIGZvciBfIGluIHJhbmdlKDMpOgogICAgICAgICAgICBfc2FmZV9zdG9wKCk7IF9zZWFyY2hfdGhyZWFkLmpvaW4odGltZW91dD0yLjApCiAgICAgICAgICAgIGlmIG5vdCBfc2VhcmNoX3RocmVhZC5pc19hbGl2ZSgpOiBicmVhawogICAgICAgIGlmIF9zZWFyY2hfdGhyZWFkLmlzX2FsaXZlKCk6CiAgICAgICAgICAgIGxvZ19jcmFzaCgicmVjaGVyY2hlIHByZWNlZGVudGUgYmxvcXVlZSBkYW5zIEVuZzkgLT4gY291cCBkZSByZXBsaSBzYW5zIHJlbGFuY2VyIikKICAgICAgICAgICAgc3QuYmVzdG1vdmVfc2VudCA9IEZhbHNlCiAgICAgICAgICAgIF9lbWl0X2Jlc3Rtb3ZlKHN0LmJlc3Qgb3IgKHN0LmpyX21vdmUgb3Igc3QuanJfYWx0KSBvciBzdC5mel9tb3ZlKQogICAgICAgICAgICByZXR1cm4KICAgIF9zZWFyY2hfdGhyZWFkID0gdGhyZWFkaW5nLlRocmVhZCh0YXJnZXQ9ZG9fc2VhcmNoLCBrd2FyZ3M9a3csIGRhZW1vbj1UcnVlKQogICAgX3NlYXJjaF90aHJlYWQuc3RhcnQoKQoKZGVmIG1haW4oKToKICAgIGdsb2JhbCBib2FyZCwgZ2FtZV9iYXNlX2ZlbiwgZ2FtZV9tb3ZlcwogICAgZm9yIHJhd19saW5lIGluIHN5cy5zdGRpbjoKICAgICAgICBsaW5lID0gcmF3X2xpbmUuc3RyaXAoKQogICAgICAgIGlmIG5vdCBsaW5lOiBjb250aW51ZQogICAgICAgIGxvZygiPDwgIiArIGxpbmUpOyB0b2sgPSBsaW5lLnNwbGl0KCk7IGNtZCA9IHRva1swXQogICAgICAgIGlmIGNtZCA9PSAidWNpIjoKICAgICAgICAgICAgdWNpX291dChmImlkIG5hbWUge0VOR19OQU1FfSIpCiAgICAgICAgICAgIHVjaV9vdXQoZiJpZCBhdXRob3Ige0VOR19BVVRIT1J9IikKICAgICAgICAgICAgdWNpX291dCgib3B0aW9uIG5hbWUgSGFzaCB0eXBlIHNwaW4gZGVmYXVsdCA2NCBtaW4gMSBtYXggMTAyNCIpCiAgICAgICAgICAgIGlmIENGRy5nZXQoJ3RocmVhZHNfcnZhJyk6CiAgICAgICAgICAgICAgICB1Y2lfb3V0KCJvcHRpb24gbmFtZSBUaHJlYWRzIHR5cGUgc3BpbiBkZWZhdWx0IDAgbWluIDAgbWF4IDgiKSAgICMgMCA9IGF1dG8gKHRvdXMgbGVzIGNvZXVycykKICAgICAgICAgICAgdWNpX291dCgidWNpb2siKQogICAgICAgIGVsaWYgY21kID09ICJzZXRvcHRpb24iOgogICAgICAgICAgICBpZiAiVGhyZWFkcyIgaW4gdG9rIGFuZCAidmFsdWUiIGluIHRvazoKICAgICAgICAgICAgICAgIGdsb2JhbCBUSFJFQURTCiAgICAgICAgICAgICAgICB0cnk6CiAgICAgICAgICAgICAgICAgICAgVEhSRUFEUyA9IG1heCgwLCBtaW4oOCwgaW50KHRva1t0b2suaW5kZXgoInZhbHVlIikrMV0pKSkKICAgICAgICAgICAgICAgICAgICBsb2coZiJzZXRvcHRpb24gVGhyZWFkcyA9IHtUSFJFQURTfSIpCiAgICAgICAgICAgICAgICAgICAgaWYgX2luaXRlZDogc2V0X3RocmVhZHMoVEhSRUFEUykgICAgICMgZGVqYSBpbml0aWFsaXNlIDogYXBwbGlxdWVyIHRvdXQgZGUgc3VpdGUKICAgICAgICAgICAgICAgIGV4Y2VwdCBFeGNlcHRpb246IHBhc3MKICAgICAgICAgICAgaWYgIkhhc2giIGluIHRvayBhbmQgInZhbHVlIiBpbiB0b2s6CiAgICAgICAgICAgICAgICBnbG9iYWwgSEFTSF9NQgogICAgICAgICAgICAgICAgdHJ5OgogICAgICAgICAgICAgICAgICAgIEhBU0hfTUIgPSBtYXgoMSwgbWluKDEwMjQsIGludCh0b2tbdG9rLmluZGV4KCJ2YWx1ZSIpKzFdKSkpCiAgICAgICAgICAgICAgICAgICAgbG9nKGYic2V0b3B0aW9uIEhhc2ggPSB7SEFTSF9NQn0gTW8iICsgKCIgKHRyb3AgdGFyZCA6IG1vdGV1ciBkZWphIGluaXRpYWxpc2UpIiBpZiBfaW5pdGVkIGVsc2UgIiIpKQogICAgICAgICAgICAgICAgZXhjZXB0IEV4Y2VwdGlvbjogcGFzcwogICAgICAgIGVsaWYgY21kID09ICJpc3JlYWR5IjoKICAgICAgICAgICAgZW5zdXJlX2luaXQoKQogICAgICAgICAgICB1Y2lfb3V0KCJyZWFkeW9rIikKICAgICAgICBlbGlmIGNtZCA9PSAidWNpbmV3Z2FtZSI6CiAgICAgICAgICAgIGVuc3VyZV9pbml0KCkKICAgICAgICAgICAgYm9hcmQgPSBCb2FyZCgpOyBib2FyZC5zZXRfZmVuKFNUQVJUX0ZFTikKICAgICAgICAgICAgZ2FtZV9iYXNlX2ZlbiA9IE5vbmU7IGdhbWVfbW92ZXMgPSBbXQogICAgICAgIGVsaWYgY21kID09ICJwb3NpdGlvbiI6CiAgICAgICAgICAgIGVuc3VyZV9pbml0KCkKICAgICAgICAgICAgYm9hcmQgPSBCb2FyZCgpCiAgICAgICAgICAgIGdhbWVfbW92ZXMgPSBbXQogICAgICAgICAgICBpZiB0b2tbMV0gPT0gInN0YXJ0cG9zIjoKICAgICAgICAgICAgICAgIGJvYXJkLnNldF9mZW4oU1RBUlRfRkVOKTsgZ2FtZV9iYXNlX2ZlbiA9IE5vbmUKICAgICAgICAgICAgZWxzZToKICAgICAgICAgICAgICAgIGZlbiA9ICIgIi5qb2luKHRva1syOjhdKSBpZiBsZW4odG9rKSA+PSA4IGVsc2UgIiAiLmpvaW4odG9rWzI6XSkKICAgICAgICAgICAgICAgIGJvYXJkLnNldF9mZW4oZmVuKTsgZ2FtZV9iYXNlX2ZlbiA9IGZlbgogICAgICAgICAgICBpZiAibW92ZXMiIGluIHRvazoKICAgICAgICAgICAgICAgIGZvciBtdiBpbiB0b2tbdG9rLmluZGV4KCJtb3ZlcyIpKzE6XToKICAgICAgICAgICAgICAgICAgICBpZiBub3QgX2lzX3VjaV9tb3ZlKG12KToKICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWsgICAgICAgICAgICAgICAgICAgICAgICMgbGUgcmVzdGUgZGUgbGEgbGlnbmUgZXN0IHN1c3BlY3QgLT4gb24gc3RvcHBlCiAgICAgICAgICAgICAgICAgICAgYm9hcmQuYXBwbHlfdWNpKG12KTsgZ2FtZV9tb3Zlcy5hcHBlbmQobXYpCiAgICAgICAgZWxpZiBjbWQgPT0gImdvIjoKICAgICAgICAgICAgZW5zdXJlX2luaXQoKQogICAgICAgICAgICBkZWYgZ3YoaywgZD0wKTogcmV0dXJuIGludCh0b2tbdG9rLmluZGV4KGspKzFdKSBpZiBrIGluIHRvayBlbHNlIGQKICAgICAgICAgICAgaWYgImRlcHRoIiBpbiB0b2s6ICAgICAgICAgICAgICBzdGFydF9zZWFyY2goZGVwdGg9bWluKGd2KCJkZXB0aCIpLCA0NykpCiAgICAgICAgICAgIGVsaWYgIm1vdmV0aW1lIiBpbiB0b2s6ICAgICAgICAgc3RhcnRfc2VhcmNoKGJ1ZGdldF9tcz1ndigibW92ZXRpbWUiKSkKICAgICAgICAgICAgZWxpZiAiaW5maW5pdGUiIGluIHRvazogICAgICAgICBzdGFydF9zZWFyY2goZGVwdGg9NDcpCiAgICAgICAgICAgIGVsaWYgInd0aW1lIiBpbiB0b2sgb3IgImJ0aW1lIiBpbiB0b2s6CiAgICAgICAgICAgICAgICBtdCwgbWkgPSAoZ3YoInd0aW1lIiksIGd2KCJ3aW5jIikpIGlmIGJvYXJkLndoaXRlIGVsc2UgKGd2KCJidGltZSIpLCBndigiYmluYyIpKQogICAgICAgICAgICAgICAgbXRnID0gZ3YoIm1vdmVzdG9nbyIsIDApCiAgICAgICAgICAgICAgICBpZiBtdGcgPiAwOgogICAgICAgICAgICAgICAgICAgICMgY2FkZW5jZSAibiBjb3VwcyBlbiBtIG1pbnV0ZXMgKyBpL2NvdXAiIChleC4gNDAgY291cHMgLyAzIG1pbiArIDEgcykuCiAgICAgICAgICAgICAgICAgICAgIyBMJ2luY3JlbWVudCBSRUdBUk5JVCBsYSBwZW5kdWxlIGFwcmVzIGNoYXF1ZSBjb3VwIC0+IGlsIGZhaXQgcGFydGllIGR1IHJ5dGhtZSwKICAgICAgICAgICAgICAgICAgICAjIHBhcyBkJ3VuIGJvbnVzIGEgYWpvdXRlciB0ZWwgcXVlbC4gVGVtcHMgdG90YWwgZGlzcG9uaWJsZSBzdXIgbGVzIGNvdXBzIHJlc3RhbnRzCiAgICAgICAgICAgICAgICAgICAgIyA9IHRlbXBzX3Jlc3RhbnQgKyBjb3Vwc19yZXN0YW50cyB4IGluY3JlbWVudC4gT24gbGUgcmVwYXJ0aXQgc3VyIChjb3Vwcyt0YW1wb24pCiAgICAgICAgICAgICAgICAgICAgIyBwb3VyIGdhcmRlciB1bmUgcmVzZXJ2ZSAobGUgdGFtcG9uIGFic29yYmUgbGEgbGF0ZW5jZSBkJ2FycmV0IGV0IGV2aXRlIGRlIGZvcmZhaXQKICAgICAgICAgICAgICAgICAgICAjIGEgbGEgYmFycmUgZHUgY29udHJvbGUsIGNvbW1lIGxlIGZhaXQgdW4gdnJhaSBtb3RldXIgcXVpIHJlZHVpdCBzb24gdGVtcHMpLgogICAgICAgICAgICAgICAgICAgIGJ1ZGdldCA9IChtdCArIG10ZyAqIG1pKSAvLyAobXRnICsgNCkKICAgICAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICAgICAgYnVkZ2V0ID0gKG10ICsgMzAgKiBtaSkgLy8gMzQgICAgIyBtb3J0IHN1Yml0ZSAvIGluY3JlbWVudCA6IH4xLzMwIGR1IHJlc3RhbnQsIHBydWRlbnQKICAgICAgICAgICAgICAgIGJ1ZGdldCA9IG1pbihidWRnZXQsIG10IC8vIDMpICAgICAgICAjIGphbWFpcyBwbHVzIGQnMS8zIGR1IHJlc3RhbnQgc3VyIHVuIHNldWwgY291cAogICAgICAgICAgICAgICAgbG9nKGYiW3BlbmR1bGVdIHd0aW1lL2J0aW1lPXttdH0gbW92ZXN0b2dvPXttdGd9IGluYz17bWl9IC0+IGJ1ZGdldD17YnVkZ2V0fW1zIikKICAgICAgICAgICAgICAgIHN0YXJ0X3NlYXJjaChidWRnZXRfbXM9bWF4KDEwLCBidWRnZXQpLCBpbmNfbXM9bWksIG1vdmVzdG9nbz1tdGcpCiAgICAgICAgICAgIGVsc2U6ICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnRfc2VhcmNoKGRlcHRoPTEyKQogICAgICAgIGVsaWYgY21kID09ICJzdG9wIjoKICAgICAgICAgICAgX3NhZmVfc3RvcCgpCiAgICAgICAgZWxpZiBjbWQgPT0gInF1aXQiOgogICAgICAgICAgICB0cnk6CiAgICAgICAgICAgICAgICBfc2FmZV9zdG9wKCkKICAgICAgICAgICAgICAgIGlmIEVuZzI6IEVuZzIoKQogICAgICAgICAgICBleGNlcHQgRXhjZXB0aW9uOiBwYXNzCiAgICAgICAgICAgIGJyZWFrCiAgICAjIFNvcnRpZSAocXVpdCBPVSBzdGRpbiBmZXJtZSBwYXIgQmFua3NpYSkuIExlIHRocmVhZCBkZSByZWNoZXJjaGUgcGV1dCBldHJlIEJMT1FVRSBkYW5zIEVuZzkKICAgICMgKGFwcGVsIEMgbm9uLXR1YWJsZSBwYXIgUHl0aG9uKSAtPiB1biBzaW1wbGUgcmV0dXJuIGxhaXNzZXJhaXQgbGUgcHJvY2Vzc3VzIHpvbWJpZSBxdWkgY29udGludWUKICAgICMgYSBjaGVyY2hlciBldCBhIHJlbXBsaXIgbGUgbG9nLiBvcy5fZXhpdCgpIHR1ZSBsZSBwcm9jZXNzdXMgSU1NRURJQVRFTUVOVCwgdGhyZWFkcyBDIGNvbXByaXMuCiAgICB0cnk6IF9zYWZlX3N0b3AoKQogICAgZXhjZXB0IEV4Y2VwdGlvbjogcGFzcwogICAgdHJ5OgogICAgICAgIGlmIF9sb2dmOiBfbG9nZi5mbHVzaCgpCiAgICBleGNlcHQgRXhjZXB0aW9uOiBwYXNzCiAgICBvcy5fZXhpdCgwKQoKaWYgX19uYW1lX18gPT0gIl9fbWFpbl9fIjoKICAgIHRyeTogbWFpbigpCiAgICBmaW5hbGx5OgogICAgICAgIGlmIF9sb2dmOiBfbG9nZi5jbG9zZSgpCg==\";\n    var SHR=\"aW1wb3J0IG9zCiMhL3Vzci9iaW4vZW52IHB5dGhvbjMKIyAtKi0gY29kaW5nOiB1dGYtOCAtKi0KIiIiCnNocmVkZGVyMnVjaS5weSAtIHBvbnQgVUNJIHBvdXIgU2hyZWRkZXIgKDUuMzIgLT4gNyksIFBJTE9UQUdFIERJUkVDVCBkZSBzaHJlZGRlci5kbGwuClZlcnNpb24gImdhdW50bGV0LXJlYWR5IiA6IHNpbGVuY2lldXNlIGVuIHByb2QsIHZlcmJldXNlIHNldWxlbWVudCBhdmVjIC0tY2FsaWIuCgpDb250cmFpcmVtZW50IGEgZW5nMnVjaS5weSAocXVpIGxpdCBkZXMgZ2xvYmF1eCBpbnRlcm5lcyBkZXMgLmVuZyBGcml0eiksIFNocmVkZGVyIGV4cG9zZSB1bmUKQVBJIHByb3ByZS4gT24gZW5yZWdpc3RyZSBkZXMgY2FsbGJhY2tzIHtTaG93Tm9kZXMsIFNob3dEZXB0aCwgU2hvd01vdmUsIFNob3dNYWlubGluZSwgU2hvd1RleHR9CnF1ZSBzaHJlZGRlci5kbGwgYXBwZWxsZSBwZW5kYW50IGxhIHJlY2hlcmNoZSA7IG9uIHBvdXNzZSBsYSBwb3NpdGlvbiB2aWEKU2hyZWRkZXJTZXRTdGFydFBvc2l0aW9uKCkgKyBTaHJlZGRlckVudGVyTW92ZSgiZTJlNCIpIDsgb24gbGFuY2UgU2hyZWRkZXJBbmFseXNlKCkgKEJMT1FVQU5UKSA7CmV0IGxlIG1laWxsZXVyIGNvdXAgYXJyaXZlIGRhbnMgbm9zIGNhbGxiYWNrcyAoY2hhaW5lIFVDSSkuCgogIC0gUHl0aG9uIDMyIGJpdHMgcmVxdWlzICAobGVzIERMTCBTaHJlZGRlciBzb250IDMyIGJpdHMpIDogIHB5IC0zLTMyIHNocmVkZGVyMnVjaS5weQogIC0gVW5lIERMTCBTaHJlZGRlciBkb2l0IGV0cmUgZGFucyBsZSBtZW1lIGRvc3NpZXIgcXVlIGNlIHNjcmlwdC4KICAgICAgICBweSAtMy0zMiBzaHJlZGRlcjJ1Y2kucHkgc2hyZWRkZXI2LmRsbCAgICAgICAgKFNocmVkZGVyIDYpCiAgICAgICAgcHkgLTMtMzIgc2hyZWRkZXIydWNpLnB5ICAgICAgICAgICAgICAgICAgICAgIChhdXRvIDogc2hyZWRkZXIqLmRsbCBkdSBkb3NzaWVyKQoKSk9VUk5BTElTQVRJT04gOgogIC0gRW4gcnVuIG5vcm1hbCAoZ2F1bnRsZXQpLCBBVUNVTkUgZWNyaXR1cmUgZGlzcXVlIDogc2V1bGVzIGxlcyBlcnJldXJzIGltcG9ydGFudGVzCiAgICBwYXJ0ZW50IHN1ciBzdGRlcnIgKGNhcHR1cmVlcyBwYXIgbGEgR1VJKSwgc2FucyBqYW1haXMgYmxvcXVlci4KICAtIEF2ZWMgLS1jYWxpYiA6IHRyYWNlIHZlcmJldXNlIGNvbXBsZXRlIHN1ciBzdGRlcnIgRVQgZGFucyBzaHJlZGRlcjZfZGJnLnR4dCAoZWNyYXNlIGEKICAgIGNoYXF1ZSBsYW5jZW1lbnQpLiBBVFRFTlRJT04gOiBlbiAtLWNhbGliLCBTaG93Tm9kZXMgZXN0IGpvdXJuYWxpc2UgYSBjaGFxdWUgYXBwZWwKICAgIChkZXMgY2VudGFpbmVzIGRlIG1pbGxpZXJzIHBhciByZWNoZXJjaGUpIC0+IGEgcmVzZXJ2ZXIgYXUgZGlhZ25vc3RpYywgcGFzIGF1IGdhdW50bGV0LgoKRkFJVFMgRVRBQkxJUyBQQVIgUkVUUk8tSU5HRU5JRVJJRSAoc2hyZWRkZXI2LmRsbCwgTWV5ZXItS2FobGVuKSA6CiAgKiBTaHJlZGRlckluaXQoYXJnMSwgYXJnMiwgYXJnMywgYXJnNCkgbmUgbGl0IFFVRSBhcmcyIGV0IGFyZzMgZW4gdjYgOgogICAgICAtIGFyZzIgPSBlbi10ZXRlIGRlIGNhbGxiYWNrcyAoNyBkd29yZHMpLCByZWNvcGllIHZlcnMgbGUgZ2xvYmFsIDB4MTAwNThlYzAgOwogICAgICAtIGFyZzMgPSBDSEFJTkUgKGNoZW1pbiBkdSBkb3NzaWVyIG1vdGV1ciksIHJlY29waWVlIHZlcnMgbGUgZ2xvYmFsIDB4MTAwM2UzNDguCiAgICBhcmcxIGV0IGFyZzQgc29udCBpZ25vcmVzLiA9PiBMZSBjaGVtaW4gZG9pdCBldHJlIGVuIEFSRzMgKHBhcyBhcmc0IGNvbW1lIGVuIDUuMzIpLgogICogTCdvYmpldCBtb3RldXIgZXN0IHVuIEdMT0JBTCBJTlRFUk5FIGZpeGUgKDB4MTAwNThlZTAsIH4weDE0OGFjIG9jdGV0cyksIGVjcml0IHBhciBJbml0LgogICAgYXJnMiBuJ2VzdCBkb25jIFBBUyBsJ29iamV0IG1vdGV1ciA6IDB4MWMgb2N0ZXRzIHN1ZmZpc2VudCBhIGwnZW4tdGV0ZSBkZSBjYWxsYmFja3MuCiAgKiBTaHJlZGRlckFuYWx5c2UobW9kZSwgZmxhZykgOiBtb2RlPT0xID0+IGFuYWx5c2UgaW5maW5pZSA7IG1vZGU9PTAgPT4gam91ZSBldCBzJ2FycmV0ZQogICAgKHRlbXBzL3Byb2ZvbmRldXIpLCBwdWlzIHJhcHBvcnRlIGxlIGJlc3Rtb3ZlLiBMZSAyZSBhcmd1bWVudCBlc3QgdW4gZmxhZyBpbnRlcm5lLgogICogc2hyZWRkZXIuZGxsIHBhcmxlIFVDSSBlbiBpbnRlcm5lIDogU2hyZWRkZXJBbmFseXNlIGNvbmNhdGVuZSB1bmUgY29tbWFuZGUgZGUgYmFzZQogICAgKGJ1ZmZlciAweDEwMDQ0NzgwKSBhdmVjIGxlcyBwYXJhbWV0cmVzIGR1ICJnbyIgKGJ1ZmZlciBkZXRlY3RlIGR5bmFtaXF1ZW1lbnQsIGV4LgogICAgMHgxMDA0NWIwOCBlbiB2NiAvIDB4M2UyNzQgZW4gNS4zMikuIE9uIHkgZWNyaXQgIm1vdmV0aW1lIE4iIC8gImRlcHRoIE4iIC8gInd0aW1lIC4uLiIuCiAgKiBDYWxsYmFja3MgU2hvdyogOiBjb252ZW50aW9uIGNkZWNsIChuZXR0b3lhZ2UgY290ZSBhcHBlbGFudCksIGNvbmZvcm1lIGEgQ0ZVTkNUWVBFLgoKU0hSRURERVIgNyAoU2hyZWRkZXI3LmRsbCwgMzA3MjAwIG8pIDogTUVNRSBBUEkgcXVlIGxhIHY2ICgyNiBleHBvcnRzIGlkZW50aXF1ZXMpIC0+IHBpbG90ZSBwYXIKY2UgbWVtZSBzY3JpcHQsIFNBTlMgbW9kaWZpY2F0aW9uLiBDb25maXJtZSBwYXIgYW5hbHlzZSBzdGF0aXF1ZSA6CiAgLSBtdWx0aS10aHJlYWQgKEdldFN5c3RlbUluZm8gKyBfYmVnaW50aHJlYWQpLCBjb21tZSBsYSB2NiAtPiBmb3JjYWdlIG1vbm8gcmVxdWlzIDsKICAtIHNpZ25hdHVyZSBtb25vLXRocmVhZCB2NiBQUkVTRU5URSBAIFJWQSAweDFiNzkwIC0+IF9mb3JjZV9zaW5nbGVfY3B1IGxhIHBhdGNoZSBhdXRvbWF0aXF1ZW1lbnQgOwogIC0gYnVmZmVyIGRlIGNvbW1hbmRlICJnbyIgYXV0by1kZXRlY3RlIEAgMHgxMDA0NzBjMCAodmlhIFNocmVkZGVyU2V0RGVwdGgsIG1lbWUgaWRpb21lIHNwcmludGYpIDsKICAtIFNocmVkZGVySW5pdCBsaXQgYXJnMj1jYWxsYmFja3MgKDcgZHdvcmRzIC0+IGdsb2JhbCAweDEwMDVhNDQwKSBldCBhcmczPWNoZW1pbiwgY29tbWUgbGEgdjYuCiAgTGFuY2VyIDogIHB5IC0zLTMyIHNocmVkZGVyMnVjaS5weSBTaHJlZGRlcjcuZGxsICAgKGEgdmFsaWRlciBwYXIgdW4gcnVuIC0tY2FsaWIgKyB1biBtYXRjaCkuCgpDQVVTRSBSQUNJTkUgKFNocmVkZGVyIDYpIDogbGEgNiBlc3QgbXVsdGktdGhyZWFkLiBBIGwnaW5pdCBlbGxlIGxpdCBsZSBub21icmUgZGUgQ1BVCihHZXRTeXN0ZW1JbmZvKSBldCBjcmVlIChuQ1BVLTEpIHRocmVhZHMgd29ya2VyLCBjaGFjdW4gYWxsb3VhbnQgc29uIHByb3ByZSBvYmpldCBtb3RldXIKZGFucyB1biB0YWJsZWF1IGludGVybmUgKDB4MTAwNThlMDApLCBhdmFudCBxdSd1bmUgYm91Y2xlIG5lIGNvcGllIHVuIGdhYmFyaXQgZGFucyBjaGFxdWUKc2xvdC4gTm90cmUgaG90ZSBjdHlwZXMgbWluaW1hbCBuZSBtZW5lIHBhcyBjZXR0ZSBtb250ZWUgYSBiaWVuIC0+IHNsb3QgbnVsIC0+IGRlcmVmIG51bAooUlZBIDB4MTA3Y2IpLiBPbiBmb3JjZSBkb25jIFNocmVkZGVyIGVuIE1PTk8tVEhSRUFEIChwYXRjaCBydW50aW1lIGR1IHdyYXBwZXIgR2V0U3lzdGVtSW5mbwotPiAxKSwgcmVnaW1lIHZvdWx1IHBvdXIgdW4gZ2F1bnRsZXQgY29udHJvbGUuIExhIDUuMzIsIGRlamEgbW9ubywgbidlc3QgcGFzIHRvdWNoZWUuCgpVbiBoYW5kbGVyIGQnZXhjZXB0aW9uIHZlY3RvcmlzZSBjYXB0dXJlIGwnYWRyZXNzZSBmYXV0aXZlIChSVkEpIGRlIHRvdXRlIGFjY2VzcyB2aW9sYXRpb24gOwplbiBjYXMgZGUgcGxhbnRhZ2UsIGVsbGUgZXN0IHJlcG9ydGVlIHN1ciBzdGRlcnIgcG91ciBkaWFnbm9zdGljLgoiIiIKaW1wb3J0IHN5cywgb3MsIGN0eXBlcywgdGhyZWFkaW5nLCB0aW1lLCBzdHJ1Y3QsIGdsb2IsIHJlCgpDQUxJQiA9ICItLWNhbGliIiBpbiBzeXMuYXJndgoKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gam91cm5hbGlzYXRpb24KX2RiZ2YgPSBOb25lCmRlZiBfZGJnKG1zZyk6CiAgICAiIiJFY3JpdCBkYW5zIHNocmVkZGVyNl9kYmcudHh0ICh1bmlxdWVtZW50IGFwcGVsZSBlbiAtLWNhbGliIDsgZmljaGllciBlY3Jhc2UgYXUgbGFuY2VtZW50KS4iIiIKICAgIGdsb2JhbCBfZGJnZgogICAgdHJ5OgogICAgICAgIGlmIF9kYmdmIGlzIE5vbmU6CiAgICAgICAgICAgIGQgPSBvcy5wYXRoLmRpcm5hbWUob3MucGF0aC5hYnNwYXRoKHN5cy5hcmd2WzBdKSkKICAgICAgICAgICAgX2RiZ2YgPSBvcGVuKG9zLnBhdGguam9pbihkLCAic2hyZWRkZXI2X2RiZy50eHQiKSwgInciLCBlbmNvZGluZz0idXRmLTgiKQogICAgICAgIF9kYmdmLndyaXRlKG1zZyArICJcbiIpOyBfZGJnZi5mbHVzaCgpCiAgICBleGNlcHQgRXhjZXB0aW9uOgogICAgICAgIHBhc3MKCmRlZiBsb2coKmEpOgogICAgIiIiVHJhY2UgVkVSQkVVU0UgOiB1bmlxdWVtZW50IGVuIC0tY2FsaWIgKHN0ZGVyciArIGZpY2hpZXIpLiBOby1vcCBzaW5vbi4iIiIKICAgIGlmIG5vdCBDQUxJQjoKICAgICAgICByZXR1cm4KICAgIG1zZyA9ICJbZGJnXSAiICsgIiAiLmpvaW4oc3RyKHgpIGZvciB4IGluIGEpCiAgICBzeXMuc3RkZXJyLndyaXRlKG1zZyArICJcbiIpOyBzeXMuc3RkZXJyLmZsdXNoKCkKICAgIF9kYmcobXNnKQoKZGVmIGVycigqYSk6CiAgICAiIiJFcnJldXIgSU1QT1JUQU5URSA6IHRvdWpvdXJzIHN1ciBzdGRlcnIgKGNhcHR1cmVlIHBhciBsYSBHVUkpLCBqYW1haXMgYmxvcXVhbnRlLiIiIgogICAgbXNnID0gIltzaHJlZGRlcjJ1Y2ldICIgKyAiICIuam9pbihzdHIoeCkgZm9yIHggaW4gYSkKICAgIHRyeToKICAgICAgICBzeXMuc3RkZXJyLndyaXRlKG1zZyArICJcbiIpOyBzeXMuc3RkZXJyLmZsdXNoKCkKICAgIGV4Y2VwdCBFeGNlcHRpb246CiAgICAgICAgcGFzcwogICAgaWYgQ0FMSUI6CiAgICAgICAgX2RiZyhtc2cpCgpkZWYgb3V0KHMpOgogICAgIiIiU29ydGllIFVDSSB2ZXJzIGxhIEdVSSAoc3Rkb3V0LCBmbHVzaCBpbW1lZGlhdCBvYmxpZ2F0b2lyZSkuIiIiCiAgICBzeXMuc3Rkb3V0LndyaXRlKHMgKyAiXG4iKTsgc3lzLnN0ZG91dC5mbHVzaCgpCiAgICBsb2coIj4+IiwgcykKCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIGNoYXJnZW1lbnQKSEVSRSA9IG9zLnBhdGguZGlybmFtZShvcy5wYXRoLmFic3BhdGgoc3lzLmFyZ3ZbMF0pKQojIENob2l4IGRlIGxhIERMTCA6IGFyZ3VtZW50IGV4cGxpY2l0ZSAoZXguICJzaHJlZGRlcjJ1Y2kucHkgc2hyZWRkZXI2LmRsbCIpLAojIHNpbm9uIGF1dG8tZGV0ZWN0aW9uIGRlIHNocmVkZGVyKi5kbGwgZGFucyBsZSBkb3NzaWVyIGR1IHNjcmlwdC4KRExMUEFUSCA9IE5vbmUKZm9yIGEgaW4gc3lzLmFyZ3ZbMTpdOgogICAgaWYgYS5sb3dlcigpLmVuZHN3aXRoKCIuZGxsIik6CiAgICAgICAgY2FuZCA9IGEgaWYgb3MucGF0aC5pc2FicyhhKSBlbHNlIG9zLnBhdGguam9pbihIRVJFLCBhKQogICAgICAgIGlmIG9zLnBhdGguZXhpc3RzKGNhbmQpOgogICAgICAgICAgICBETExQQVRIID0gY2FuZDsgYnJlYWsKaWYgbm90IERMTFBBVEg6CiAgICBjYW5kcyA9IHNvcnRlZChnbG9iLmdsb2Iob3MucGF0aC5qb2luKEhFUkUsICJbU3NdaHJlZGRlciouZGxsIikpLCByZXZlcnNlPVRydWUpCiAgICBpZiBjYW5kczoKICAgICAgICBETExQQVRIID0gY2FuZHNbMF0KaWYgbm90IERMTFBBVEg6CiAgICBlcnIoIkZBVEFMOiBhdWN1bmUgc2hyZWRkZXIqLmRsbCB0cm91dmVlIGRhbnMiLCBIRVJFKTsgc3lzLmV4aXQoMSkKbG9nKCJETEw6IiwgRExMUEFUSCkKdHJ5OgogICAgb3MuY2hkaXIoSEVSRSkKICAgICMgUHlETEwgKGV0IG5vbiBDRExMKSA6IGdhcmRlIGxlIEdJTCBwZW5kYW50IGxlcyBhcHBlbHMuIFNocmVkZGVyQW5hbHlzZSB0b3VybmUgaW5saW5lCiAgICAjIGV0IHJhcHBlbGxlIG5vcyBjYWxsYmFja3Mgc3VyIGxlIG1lbWUgdGhyZWFkIDsgc2FucyByZWxhY2hlbWVudCBkdSBHSUwsIHBhcyBkZQogICAgIyBjb25mbGl0ICJfUHlUaHJlYWRTdGF0ZV9BdHRhY2g6IG5vbi1OVUxMIG9sZCB0aHJlYWQgc3RhdGUiIChQeXRob24gMy4xMykuCiAgICBkbGwgPSBjdHlwZXMuUHlETEwoRExMUEFUSCkKZXhjZXB0IE9TRXJyb3IgYXMgZToKICAgIGVycigiRkFUQUw6IGNoYXJnZW1lbnQiLCBvcy5wYXRoLmJhc2VuYW1lKERMTFBBVEgpLCAiOiIsIHN0cihlKSwgIihQeXRob24gMzIgYml0cyByZXF1aXMpIikKICAgIHN5cy5leGl0KDEpCgpJbml0ICAgICAgICA9IGRsbC5TaHJlZGRlckluaXQKU2V0U3RhcnRQb3MgPSBkbGwuU2hyZWRkZXJTZXRTdGFydFBvc2l0aW9uCkVudGVyTW92ZSAgID0gZGxsLlNocmVkZGVyRW50ZXJNb3ZlClNldERlcHRoICAgID0gZGxsLlNocmVkZGVyU2V0RGVwdGgKU2V0VGltZSAgICAgPSBkbGwuU2hyZWRkZXJTZXRUaW1lClNldEJsaXR6ICAgID0gZGxsLlNocmVkZGVyU2V0QmxpdHoKQW5hbHlzZSAgICAgPSBkbGwuU2hyZWRkZXJBbmFseXNlClN0b3BBbmFseXNlID0gZGxsLlNocmVkZGVyU3RvcEFuYWx5c2UKQ2xlYXJIYXNoICAgPSBkbGwuU2hyZWRkZXJDbGVhckhhc2h0YWJsZQpTZXRQYXJhbSAgICA9IGRsbC5TaHJlZGRlclNldFBhcmFtCkdldFZlcnNpb24gID0gZGxsLlNocmVkZGVyR2V0VmVyc2lvbgpHZXRBdXRob3IgICA9IGRsbC5TaHJlZGRlckdldEF1dGhvcgpJbml0LmFyZ3R5cGVzICAgICAgPSBbY3R5cGVzLmNfdm9pZF9wLCBjdHlwZXMuY192b2lkX3AsIGN0eXBlcy5jX3ZvaWRfcCwgY3R5cGVzLmNfdm9pZF9wXQpFbnRlck1vdmUuYXJndHlwZXMgPSBbY3R5cGVzLmNfY2hhcl9wXQpTZXREZXB0aC5hcmd0eXBlcyAgPSBbY3R5cGVzLmNfaW50XQpBbmFseXNlLmFyZ3R5cGVzICAgPSBbY3R5cGVzLmNfaW50LCBjdHlwZXMuY19pbnRdICAgIyAobW9kZT0wIGpvdWUgLyAxIGFuYWx5c2UgaW5maW5pZSwgZmxhZyBpbnRlcm5lKQpTZXRQYXJhbS5hcmd0eXBlcyAgPSBbY3R5cGVzLmNfY2hhcl9wLCBjdHlwZXMuY19jaGFyX3BdCkdldFZlcnNpb24ucmVzdHlwZSA9IGN0eXBlcy5jX2NoYXJfcApHZXRBdXRob3IucmVzdHlwZSAgPSBjdHlwZXMuY19jaGFyX3AKCkhBU0hfTUIgPSA2NAoKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gaGFuZGxlciBkJ2V4Y2VwdGlvbiAoZGlhZ25vc3RpYykKIyBDYXB0dXJlIGwnYWRyZXNzZSBmYXV0aXZlIChSVkEgcmVsYXRpdmUgYSBsYSBiYXNlIERMTCkgZGUgdG91dGUgYWNjZXNzIHZpb2xhdGlvbiwgQVZBTlQKIyBxdWUgY3R5cGVzIG5lIGxhIHRyYWR1aXNlIGVuIE9TRXJyb3IuIF92ZWhfbG9nIGVzdCB0b3Vqb3VycyByZW5zZWlnbmUgKGNvdXQgbnVsLCBlbiBtZW1vaXJlKSA7CiMgbGEgdHJhY2Ugbidlc3QgZWNyaXRlIHF1J2VuIC0tY2FsaWIsIG1haXMgbGEgUlZBIGVzdCByZXBvcnRlZSBzdXIgc3RkZXJyIHNpIHVuIGFwcGVsIHBsYW50ZS4KX0RMTEJBU0UgPSBkbGwuX2hhbmRsZSAmIDB4RkZGRkZGRkYKX3ZlaF9sb2cgPSBbXSAgICAgICAgICAjIHR1cGxlcyAoY29kZSwgYWRkcl9pbnN0ciwgcnZhLCBhY2NlcywgYWRkcl9jaWJsZSkKaWYgb3MubmFtZSA9PSAibnQiOgogICAgX1BWRUNUT1JFRCA9IGN0eXBlcy5XSU5GVU5DVFlQRShjdHlwZXMuY19sb25nLCBjdHlwZXMuY192b2lkX3ApCiAgICBAX1BWRUNUT1JFRAogICAgZGVmIF92ZWgocGV4Yyk6CiAgICAgICAgdHJ5OgogICAgICAgICAgICBwICAgPSBjdHlwZXMuY2FzdChwZXhjLCBjdHlwZXMuUE9JTlRFUihjdHlwZXMuY191aW50MzIpKQogICAgICAgICAgICByZWMgPSBjdHlwZXMuY2FzdChwWzBdLCBjdHlwZXMuUE9JTlRFUihjdHlwZXMuY191aW50MzIpKQogICAgICAgICAgICBjb2RlICAgICA9IHJlY1swXSAgICAgICAgICAjIEV4Y2VwdGlvbkNvZGUKICAgICAgICAgICAgZXhjX2FkZHIgPSByZWNbM10gICAgICAgICAgIyBFeGNlcHRpb25BZGRyZXNzCiAgICAgICAgICAgIGlmIGNvZGUgPT0gMHhDMDAwMDAwNTogICAgICMgRVhDRVBUSU9OX0FDQ0VTU19WSU9MQVRJT04KICAgICAgICAgICAgICAgIGFjYyA9IHJlY1s1XSAgICAgICAgICAgIyAwPWxlY3R1cmUgMT1lY3JpdHVyZSA4PWV4ZWMKICAgICAgICAgICAgICAgIHRndCA9IHJlY1s2XSAgICAgICAgICAgIyBhZHJlc3NlIGZhdXRpdmUKICAgICAgICAgICAgICAgIHJ2YSA9IChleGNfYWRkciAtIF9ETExCQVNFKSAmIDB4RkZGRkZGRkYKICAgICAgICAgICAgICAgIF92ZWhfbG9nLmFwcGVuZCgoY29kZSwgZXhjX2FkZHIsIHJ2YSwgYWNjLCB0Z3QpKQogICAgICAgICAgICAgICAga2luZCA9IHswOiAicmVhZCIsIDE6ICJ3cml0ZSIsIDg6ICJleGVjIn0uZ2V0KGFjYywgc3RyKGFjYykpCiAgICAgICAgICAgICAgICBsb2coZiJbVkVIXSBBViBAIHtleGNfYWRkcjojMDEweH0gIFJWQSB7cnZhOiN4fSAge2tpbmR9IHt0Z3Q6IzAxMHh9IikKICAgICAgICBleGNlcHQgRXhjZXB0aW9uIGFzIGU6CiAgICAgICAgICAgIGxvZygiW1ZFSF0gcGFyc2UgRVhDIiwgcmVwcihlKSkKICAgICAgICByZXR1cm4gMCAgICAgICAgICAgICAgICAgICAgICAgIyBFWENFUFRJT05fQ09OVElOVUVfU0VBUkNICiAgICB0cnk6CiAgICAgICAgY3R5cGVzLndpbmRsbC5rZXJuZWwzMi5BZGRWZWN0b3JlZEV4Y2VwdGlvbkhhbmRsZXIoMSwgX3ZlaCkKICAgIGV4Y2VwdCBFeGNlcHRpb24gYXMgZToKICAgICAgICBsb2coIlZFSCBpbnN0YWxsIEVYQyIsIHJlcHIoZSkpCgpkZWYgX2ZhdWx0X3J2YXMoKToKICAgIHJldHVybiAiLCAiLmpvaW4oaGV4KHJbMl0pIGZvciByIGluIF92ZWhfbG9nKSBpZiBfdmVoX2xvZyBlbHNlICJhdWN1bmUiCgojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBmb3JjYWdlIG1vbm8tdGhyZWFkIChTaHJlZGRlciA2KykKIyBWb2lyICJDQVVTRSBSQUNJTkUiIGRhbnMgbCdlbnRldGUuIE9uIG5ldXRyYWxpc2UgbGUgd3JhcHBlciBHZXRTeXN0ZW1JbmZvIHBvdXIgcXUnaWwgcmVudm9pZQojIDEgOiBsYSBib3VjbGUgZGUgY3JlYXRpb24gZGUgdGhyZWFkcyBlc3Qgc2F1dGVlLCBzZXVsIGFycmF5WzBdIChvYmpldCBzdGF0aXF1ZSB2YWxpZGUpIGVzdAojIHRvdWNoZSwgZXQgbGEgcmVjaGVyY2hlIHJhcHBlbGxlIG5vcyBjYWxsYmFja3Mgc3VyIGxlIHRocmVhZCBwcmluY2lwYWwgKGRlc2lnbiBzeW5jaHJvbmUpLgojIERldGVjdGlvbiBwYXIgU0lHTkFUVVJFIGRlIGwnaWRpb21lIChpbmRlcGVuZGFudGUgdmVyc2lvbi9BU0xSKSA6CiMgICA4MyBFQyAyNCAvIDhEIDQ0IDI0IDAwIC8gNTAgLyBGRiAxNSA\/PyA\/PyA\/PyA\/PyAvIDhCIDQ0IDI0IDE0IC8gODMgQzQgMjQgLyBDMwojIFBhdGNoIGRlcyA2IHByZW1pZXJzIG9jdGV0cyAtPiBCOCAwMSAwMCAwMCAwMCBDMyAobW92IGVheCwxIDsgcmV0KS4gTW90aWYgYWJzZW50ID0+IG5vLW9wIHN1ci4KZGVmIF9mb3JjZV9zaW5nbGVfY3B1KCk6CiAgICBTSUcgICA9IHJlLmNvbXBpbGUocmIiXHg4M1x4RUNceDI0XHg4RFx4NDRceDI0XHgwMFx4NTBceEZGXHgxNS4uLi5ceDhCXHg0NFx4MjRceDE0XHg4M1x4QzRceDI0XHhDMyIsIHJlLkRPVEFMTCkKICAgIFBBVENIID0gYiJceEI4XHgwMVx4MDBceDAwXHgwMFx4QzMiICAgICAgICAgICAjIG1vdiBlYXgsMSA7IHJldAogICAgaWYgb3MubmFtZSAhPSAibnQiOgogICAgICAgIHJldHVybiBGYWxzZQogICAgdHJ5OgogICAgICAgIGJhc2UgPSBkbGwuX2hhbmRsZSAmIDB4RkZGRkZGRkYKICAgICAgICB0cnk6CiAgICAgICAgICAgIGVfbGZhbmV3ID0gc3RydWN0LnVucGFja19mcm9tKCI8SSIsIGN0eXBlcy5zdHJpbmdfYXQoYmFzZSArIDB4M0MsIDQpKVswXQogICAgICAgICAgICBzaXogICAgICA9IHN0cnVjdC51bnBhY2tfZnJvbSgiPEkiLCBjdHlwZXMuc3RyaW5nX2F0KGJhc2UgKyBlX2xmYW5ldyArIDB4NTAsIDQpKVswXQogICAgICAgIGV4Y2VwdCBFeGNlcHRpb246CiAgICAgICAgICAgIHNpeiA9IDB4ODAwMDAKICAgICAgICBzcGFuID0gbWF4KDB4MTAwMCwgbWluKDB4ODAwMDAsIHNpeiAtIDB4MTAwMCkpCiAgICAgICAgYmxvYiA9IGN0eXBlcy5zdHJpbmdfYXQoYmFzZSArIDB4MTAwMCwgc3BhbikgICAgICMgLnRleHQgbWFwcGUKICAgICAgICBtID0gU0lHLnNlYXJjaChibG9iKQogICAgICAgIGlmIG5vdCBtOgogICAgICAgICAgICBsb2coIm1vbm86IGlkaW9tZSBHZXRTeXN0ZW1JbmZvIGFic2VudCAoZGVqYSBtb25vIC8gYXV0cmUgdmVyc2lvbikgLT4gYXVjdW4gcGF0Y2giKQogICAgICAgICAgICByZXR1cm4gRmFsc2UKICAgICAgICBhZGRyID0gYmFzZSArIDB4MTAwMCArIG0uc3RhcnQoKQogICAgICAgIGszMiAgPSBjdHlwZXMud2luZGxsLmtlcm5lbDMyCiAgICAgICAgb2xkICA9IGN0eXBlcy5jX3VpbnQzMigwKQogICAgICAgIFBBR0VfRVhFQ1VURV9SRUFEV1JJVEUgPSAweDQwCiAgICAgICAgaWYgbm90IGszMi5WaXJ0dWFsUHJvdGVjdChjdHlwZXMuY192b2lkX3AoYWRkciksIGN0eXBlcy5jX3NpemVfdChsZW4oUEFUQ0gpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFBBR0VfRVhFQ1VURV9SRUFEV1JJVEUsIGN0eXBlcy5ieXJlZihvbGQpKToKICAgICAgICAgICAgZXJyKCJtb25vOiBWaXJ0dWFsUHJvdGVjdCBlY2hlYyAtPiBTaHJlZGRlciA2IHJpc3F1ZSBkZSBwbGFudGVyIGEgbCdpbml0Iik7IHJldHVybiBGYWxzZQogICAgICAgIGN0eXBlcy5tZW1tb3ZlKGFkZHIsIFBBVENILCBsZW4oUEFUQ0gpKQogICAgICAgIHRtcCA9IGN0eXBlcy5jX3VpbnQzMigwKQogICAgICAgIGszMi5WaXJ0dWFsUHJvdGVjdChjdHlwZXMuY192b2lkX3AoYWRkciksIGN0eXBlcy5jX3NpemVfdChsZW4oUEFUQ0gpKSwgb2xkLCBjdHlwZXMuYnlyZWYodG1wKSkKICAgICAgICB0cnk6CiAgICAgICAgICAgIGszMi5GbHVzaEluc3RydWN0aW9uQ2FjaGUoazMyLkdldEN1cnJlbnRQcm9jZXNzKCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3R5cGVzLmNfdm9pZF9wKGFkZHIpLCBjdHlwZXMuY19zaXplX3QobGVuKFBBVENIKSkpCiAgICAgICAgZXhjZXB0IEV4Y2VwdGlvbjoKICAgICAgICAgICAgcGFzcwogICAgICAgIGxvZyhmIm1vbm86IHBhdGNoIGFwcGxpcXVlIEAge2FkZHI6IzAxMHh9IChSVkEge2FkZHIgLSBiYXNlOiN4fSkgLT4gU2hyZWRkZXIgZm9yY2UgbW9uby10aHJlYWQiKQogICAgICAgIHJldHVybiBUcnVlCiAgICBleGNlcHQgRXhjZXB0aW9uIGFzIGU6CiAgICAgICAgZXJyKCJtb25vOiBwYXRjaCBFWEMiLCByZXByKGUpKTsgcmV0dXJuIEZhbHNlCgojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBidWZmZXIgZGUgY29tbWFuZGUgImdvIiAodGVtcHMpCiMgU2hyZWRkZXJBbmFseXNlIGNvbnN0cnVpdCAiZ28gIiArIHVuIGJ1ZmZlciBkZSBjb21tYW5kZSwgcHVpcyBsZSBmYWl0IHRyYWl0ZXIuIE9uIHkgZWNyaXQKIyBkaXJlY3RlbWVudCBsZXMgcGFyYW1ldHJlcyBVQ0kgZHUgImdvIiAoIm1vdmV0aW1lIE4iLCAid3RpbWUgVyBidGltZSBCIC4uLiIsICJkZXB0aCBOIikKIyBwb3VyIHVuIGNvbnRyb2xlIGR1IHRlbXBzIHByZWNpcy4gTCdBRFJFU1NFIGRlIGNlIGJ1ZmZlciBkZXBlbmQgZGUgbGEgdmVyc2lvbiBkZSBsYSBETEwKIyAoNS4zMiAtPiAweDNlMjc0LCA2IC0+IDB4NDViMDguLi4pLiBEZXRlY3Rpb24gZHluYW1pcXVlIDogU2hyZWRkZXJTZXREZXB0aCBmYWl0CiMgc3ByaW50ZihCVUZGRVIsICJkZXB0aCAlZCIsIG4pIDsgbGEgZGVzdGluYXRpb24gZXN0IGxlIGRlcm5pZXIgJ3B1c2ggaW1tMzInIGF2YW50IHNwcmludGYuCmRlZiBfZGV0ZWN0X2dvX2J1ZmZlcigpOgogICAgdHJ5OgogICAgICAgIGszMiA9IGN0eXBlcy53aW5kbGwua2VybmVsMzIKICAgICAgICBrMzIuR2V0UHJvY0FkZHJlc3MucmVzdHlwZSAgPSBjdHlwZXMuY192b2lkX3AKICAgICAgICBrMzIuR2V0UHJvY0FkZHJlc3MuYXJndHlwZXMgPSBbY3R5cGVzLmNfdm9pZF9wLCBjdHlwZXMuY19jaGFyX3BdCiAgICAgICAgZm9yIG5hbWUgaW4gKGIiU2hyZWRkZXJTZXREZXB0aCIsIGIiU2hyZWRkZXJTZXRUaW1lIik6CiAgICAgICAgICAgIGZuID0gazMyLkdldFByb2NBZGRyZXNzKGRsbC5faGFuZGxlLCBuYW1lKQogICAgICAgICAgICBpZiBub3QgZm46CiAgICAgICAgICAgICAgICBjb250aW51ZQogICAgICAgICAgICBjb2RlID0gY3R5cGVzLnN0cmluZ19hdChmbiwgOTYpCiAgICAgICAgICAgIGRlc3QsIGkgPSBOb25lLCAwCiAgICAgICAgICAgIHdoaWxlIGkgPCBsZW4oY29kZSkgLSA1OgogICAgICAgICAgICAgICAgYiA9IGNvZGVbaV0KICAgICAgICAgICAgICAgIGlmIGIgPT0gMHg2ODogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgcHVzaCBpbW0zMgogICAgICAgICAgICAgICAgICAgIGRlc3QgPSBzdHJ1Y3QudW5wYWNrX2Zyb20oIjxJIiwgY29kZSwgaSArIDEpWzBdOyBpICs9IDUKICAgICAgICAgICAgICAgIGVsaWYgYiA9PSAweEU4IG9yIChiID09IDB4RkYgYW5kIGNvZGVbaSArIDFdID09IDB4MTUpOiAgICMgY2FsbCAtPiBzdG9wCiAgICAgICAgICAgICAgICAgICAgYnJlYWsKICAgICAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICAgICAgaSArPSAxCiAgICAgICAgICAgIGlmIGRlc3QgYW5kIGRsbC5faGFuZGxlIDwgZGVzdCA8IGRsbC5faGFuZGxlICsgMHgyMDAwMDA6CiAgICAgICAgICAgICAgICByZXR1cm4gZGVzdAogICAgZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOgogICAgICAgIGxvZygiZGV0ZWN0aW9uIGJ1ZmZlciBFWEMiLCByZXByKGUpKQogICAgcmV0dXJuIE5vbmUKCl9HT0JVRiA9IF9kZXRlY3RfZ29fYnVmZmVyKCkKbG9nKCJidWZmZXIgY29tbWFuZGUgPSIsIGhleChfR09CVUYpIGlmIF9HT0JVRiBlbHNlICJOT04gREVURUNURSAodGVtcHMgaW5hY3RpZikiKQoKZGVmIHNldF9nbyhwYXJhbXMpOgogICAgaWYgbm90IF9HT0JVRjoKICAgICAgICByZXR1cm4KICAgIGIgPSBwYXJhbXMuZW5jb2RlKCJsYXRpbjEiKSArIGIiXHgwMCIKICAgIGN0eXBlcy5tZW1tb3ZlKF9HT0JVRiwgYiwgbGVuKGIpKQoKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gZXRhdApjbGFzcyBTdDoKICAgIGJlc3QgPSAiIjsgZGVwdGggPSAwOyBzY29yZSA9IDA7IG5vZGVzID0gMDsgdDAgPSAwLjA7IHB2ID0gIiI7IGxhc3RfZW1pdCA9IE5vbmUKc3QgPSBTdCgpCgpQVl9GSVJTVF9PTkxZID0gb3MuZW52aXJvbi5nZXQoJ0VORzJVQ0lfUFZGVUxMJywnMCcpID09ICcwJyAgIyBkZWZhdXQ6IFBWIDEgY291cCAoYW50aS1pbGxlZ2FsIGVuIGNvbnNvbGUpCgpkZWYgZW1pdF9pbmZvKCk6CiAgICBtcyAgPSBtYXgoMSwgaW50KCh0aW1lLnRpbWUoKSAtIHN0LnQwKSAqIDEwMDApKQogICAgbnBzID0gaW50KHN0Lm5vZGVzICogMTAwMCAvIG1zKQogICAgcHYgID0gc3QucHYgaWYgc3QucHYgZWxzZSBzdC5iZXN0CiAgICBpZiBQVl9GSVJTVF9PTkxZIGFuZCBwdjoKICAgICAgICBwdiA9IHB2LnNwbGl0KClbMF0gICAgICAgICMgUFYgbGltaXRlZSBhdSAxZXIgY291cCAtPiBwbHVzIGF1Y3VuIGNvdXAgaWxsZWdhbCBlbiBjb25zb2xlCiAgICBrZXkgPSAoc3QuZGVwdGgsIHN0LnNjb3JlLCBzdC5ub2RlcywgcHYpCiAgICBpZiBrZXkgPT0gc3QubGFzdF9lbWl0OiByZXR1cm4KICAgIHN0Lmxhc3RfZW1pdCA9IGtleQogICAgb3V0KGYiaW5mbyBkZXB0aCB7c3QuZGVwdGh9IHNjb3JlIGNwIHtzdC5zY29yZX0gbm9kZXMge3N0Lm5vZGVzfSBucHMge25wc30gdGltZSB7bXN9IHB2IHtwdn0iKQoKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gY2FsbGJhY2tzCiMgc2hyZWRkZXIuZGxsIGFwcGVsbGUgY2VzIGZvbmN0aW9ucyAoY2RlY2wpIHBlbmRhbnQgU2hyZWRkZXJBbmFseXNlLiBDb3JwcyBtaW5pbWFsIGhvcnMgZGVidWcuCkNCX01PVkUgID0gY3R5cGVzLkNGVU5DVFlQRShOb25lLCBjdHlwZXMuY19jaGFyX3AsIGN0eXBlcy5jX2ludCwgY3R5cGVzLmNfaW50LCBjdHlwZXMuY19pbnQpCkNCX0RFUFRIID0gY3R5cGVzLkNGVU5DVFlQRShOb25lLCBjdHlwZXMuY19pbnQsICAgIGN0eXBlcy5jX2ludCwgY3R5cGVzLmNfaW50KQpDQl9OT0RFUyA9IGN0eXBlcy5DRlVOQ1RZUEUoTm9uZSwgY3R5cGVzLmNfaW50LCAgICBjdHlwZXMuY19pbnQsIGN0eXBlcy5jX2ludCkKQ0JfTUFJTiAgPSBjdHlwZXMuQ0ZVTkNUWVBFKE5vbmUsIGN0eXBlcy5jX2NoYXJfcCwgY3R5cGVzLmNfaW50LCBjdHlwZXMuY19pbnQpCkNCX1RFWFQgID0gY3R5cGVzLkNGVU5DVFlQRShOb25lLCBjdHlwZXMuY19jaGFyX3ApCgpAQ0JfTU9WRQpkZWYgY2JfbW92ZSh1Y2ksIGEsIGIsIGMpOgogICAgIyBTaG93TW92ZSA9ICJjdXJybW92ZSIgOiBsZSBjb3VwIHJhY2luZSBFTiBDT1VSUyBkJ2FuYWx5c2UgKGEgPSBuwrAsIGIgPSB0b3RhbCksIHBhcyBsZQogICAgIyBtZWlsbGV1ciBjb3VwLiBMYSBETEwgbmUgbCdlbWV0IHF1J2EgcGFydGlyIGRlIGRlcHRoIDcgKGdhcmRlICdjbXAgZGVwdGgsNicpLgogICAgIyBORSBKQU1BSVMgbCd1dGlsaXNlciBwb3VyIGJlc3Rtb3ZlIDogc2lub24sIHNpIGxhIHJlY2hlcmNoZSBzJ2FycmV0ZSBwZW5kYW50CiAgICAjIGwnZW51bWVyYXRpb24gZGVzIGNvdXBzIHJhY2luZXMsIG9uIHJlbnZlcnJhaXQgdW4gY291cCBxdWVsY29ucXVlIChzb3V2ZW50IG1hdXZhaXMpLgogICAgIyBMZSBtZWlsbGV1ciBjb3VwIHZpZW50IEVYQ0xVU0lWRU1FTlQgZGUgU2hvd01haW5saW5lIChjYl9tYWluKS4KICAgIGlmIENBTElCOgogICAgICAgIHRyeToKICAgICAgICAgICAgbXYgPSB1Y2kuZGVjb2RlKCJsYXRpbjEiKS5zdHJpcCgpIGlmIHVjaSBlbHNlICIiCiAgICAgICAgICAgIGlmIG12OiBsb2coZiJTaG93TW92ZShjdXJybW92ZSk6IHttdn0gICgje2F9L3tifSkiKQogICAgICAgIGV4Y2VwdCBFeGNlcHRpb246CiAgICAgICAgICAgIHBhc3MKCkBDQl9ERVBUSApkZWYgY2JfZGVwdGgoZGVwdGgsIGEyLCB4KToKICAgIHN0LmRlcHRoID0gZGVwdGgKICAgIGlmIENBTElCOiBsb2coZiJTaG93RGVwdGg6IGQ9e2RlcHRofSBhcmcyPXthMn0gYXJnMz17eH0iKQogICAgZW1pdF9pbmZvKCkKCkBDQl9OT0RFUwpkZWYgY2Jfbm9kZXMobG8sIGhpLCB0KToKICAgICMgQXBwZWxlIFRSRVMgc291dmVudCAocGFyIFNocmVkZGVyKSA6IG9uIGdhcmRlIGxlIGNvcnBzIG1pbmltYWwuIFBhcyBkZSBsb2cgaG9ycyAtLWNhbGliLgogICAgc3Qubm9kZXMgPSAoKGhpICYgMHhmZmZmZmZmZikgPDwgMzIgfCAobG8gJiAweGZmZmZmZmZmKSkgaWYgaGkgZWxzZSAobG8gJiAweGZmZmZmZmZmKQogICAgaWYgQ0FMSUI6IGxvZyhmIlNob3dOb2RlczogbG89e2xvfSBoaT17aGl9IC0+IHtzdC5ub2Rlc30iKQoKQENCX01BSU4KZGVmIGNiX21haW4ocHYsIHNjb3JlLCBhMyk6CiAgICAjIFNob3dNYWlubGluZSA9ICJub3V2ZWxsZSBtZWlsbGV1cmUgbGlnbmUiLiBTaHJlZGRlciBsZXMgZW1ldCBkYW5zIGwnb3JkcmUgQ1JPSVNTQU5UCiAgICAjIChsYSBkZXJuaWVyZSBlc3QgbGEgbWVpbGxldXJlIGEgbGEgcHJvZm9uZGV1ciBjb3VyYW50ZSkuIExhIGRlcm5pZXJlIHJlY3VlID0gbGUKICAgICMgbWVpbGxldXIgY291cCBjb3VyYW50LiBDJ2VzdCBsYSBTRVVMRSBzb3VyY2UgZGUgYmVzdG1vdmUuIFNjb3JlID0gUE9WIHRyYWl0IChVQ0kpLgogICAgdHJ5OgogICAgICAgIGlmIG5vdCBwdjogcmV0dXJuCiAgICAgICAgcHZzID0gcHYuZGVjb2RlKCJsYXRpbjEiKS5zdHJpcCgpCiAgICAgICAgcGFydHMgPSBwdnMuc3BsaXQoKQogICAgICAgIGlmIHBhcnRzIGFuZCBsZW4ocGFydHNbMF0pID49IDQ6CiAgICAgICAgICAgIHN0LmJlc3QgPSBwYXJ0c1swXTsgc3Quc2NvcmUgPSBzY29yZTsgc3QucHYgPSBwdnMKICAgICAgICAgICAgZW1pdF9pbmZvKCkKICAgICAgICBpZiBDQUxJQjogbG9nKGYiU2hvd01haW5saW5lOiBwdj0ne3B2c30nIHNjb3JlPXtzY29yZX0gLT4gYmVzdD17c3QuYmVzdH0iKQogICAgZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOgogICAgICAgIGxvZygiY2JfbWFpbiBFWEMiLCByZXByKGUpKQoKQENCX1RFWFQKZGVmIGNiX3RleHQodHh0KToKICAgIGlmIENBTElCIGFuZCB0eHQ6CiAgICAgICAgdHJ5OiBsb2coIlNob3dUZXh0OiIsIHR4dC5kZWNvZGUoImxhdGluMSIpWzo4MF0pCiAgICAgICAgZXhjZXB0IEV4Y2VwdGlvbjogcGFzcwoKIyBFbi10ZXRlIGRlIGNhbGxiYWNrcyBwYXNzZSBhIFNocmVkZGVySW5pdCAoYXJnMikgOgojICAgWzBdPXRhaWxsZSgweDFjKSAgWzFdPVNob3dOb2RlcyBbMl09U2hvd0RlcHRoIFszXT1TaG93TW92ZSBbNF09U2hvd01haW5saW5lCiMgICBbNV09U2hvd1RleHQgICAgICBbNl09cG9pbnRldXIgdmVycyB1biBidWZmZXIgZGUgdHJhdmFpbAojIEluaXQgbidlbiByZWNvcGllIHF1ZSA3IGR3b3JkcyB2ZXJzIGxlIGdsb2JhbCAweDEwMDU4ZWMwIDsgbCdvYmpldCBtb3RldXIgZXN0IHVuIGdsb2JhbAojIGludGVybmUgKDB4MTAwNThlZTApLiAweDFjIG9jdGV0cyBzdWZmaXJhaWVudCA7IG1hcmdlIGRlZmVuc2l2ZS4KX3dvcmtidWYgPSBjdHlwZXMuY3JlYXRlX3N0cmluZ19idWZmZXIoMHgxMDAwKQpfY2JidWYgICA9IGN0eXBlcy5jcmVhdGVfc3RyaW5nX2J1ZmZlcigweDQwMCkKZGVmIF9hZGRyKHgpOiByZXR1cm4gY3R5cGVzLmNhc3QoeCwgY3R5cGVzLmNfdm9pZF9wKS52YWx1ZSBvciAwCnN0cnVjdC5wYWNrX2ludG8oIjw3SSIsIF9jYmJ1ZiwgMCwKICAgIDB4MWMsCiAgICBfYWRkcihjYl9ub2RlcyksIF9hZGRyKGNiX2RlcHRoKSwgX2FkZHIoY2JfbW92ZSksIF9hZGRyKGNiX21haW4pLCBfYWRkcihjYl90ZXh0KSwKICAgIF9hZGRyKF93b3JrYnVmKSwKKQpDQlN0cnVjdCA9IF9jYmJ1ZgojIGdhcmRlciB1bmUgcmVmZXJlbmNlIGZvcnRlIHBvdXIgZXZpdGVyIGxlIEdDIGRlcyB0cmFtcG9saW5lcyBjdHlwZXMKX0tFRVAgPSAoY2JfbW92ZSwgY2JfZGVwdGgsIGNiX25vZGVzLCBjYl9tYWluLCBjYl90ZXh0LCBDQlN0cnVjdCwgX3dvcmtidWYpCgojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBpbml0IG1vdGV1cgojIEFSRzMgPSBDSEFJTkUgKGNoZW1pbiBkdSBkb3NzaWVyIG1vdGV1cikgOiBsYSB2NiBsYSByZWNvcGllIGVuIGludGVybmUgKDB4MTAwM2UzNDgpIHBvdXIKIyBsb2NhbGlzZXIgbGl2cmUvdGFibGVzL2NvbmZpZyA7IGxhIHBhc3NlciB2aWRlIGZhaXQgcGxhbnRlciBJbml0LiBBUkcxL0FSRzQgaWdub3JlcyBwYXIgbGEgdjYuCnRyeToKICAgIF9wID0gSEVSRS5lbmNvZGUoIm1iY3MiLCAicmVwbGFjZSIpIGlmIG9zLm5hbWUgPT0gIm50IiBlbHNlIEhFUkUuZW5jb2RlKCJ1dGYtOCIsICJyZXBsYWNlIikKZXhjZXB0IEV4Y2VwdGlvbjoKICAgIF9wID0gSEVSRS5lbmNvZGUoImxhdGluMSIsICJyZXBsYWNlIikKX2FyZzEgICAgPSBjdHlwZXMuY3JlYXRlX3N0cmluZ19idWZmZXIoMHg0MCkKX2FyZ3BhdGggPSBjdHlwZXMuY3JlYXRlX3N0cmluZ19idWZmZXIoX3AsIDB4NDAwKSAgICMgPC0tIEFSRzMgOiBsZSBjaGVtaW4KX2FyZzQgICAgPSBjdHlwZXMuY3JlYXRlX3N0cmluZ19idWZmZXIoX3AsIDB4NDAwKQpfaW5pdGVkICA9IEZhbHNlCgpkZWYgZW5zdXJlX2luaXQoKToKICAgIGdsb2JhbCBfaW5pdGVkCiAgICBpZiBfaW5pdGVkOiByZXR1cm4KICAgIF9pbml0ZWQgPSBUcnVlCiAgICAjIFNocmVkZGVyIDYrIGVzdCBtdWx0aS10aHJlYWQgOiBvbiBsZSBmb3JjZSBlbiBtb25vLXRocmVhZCBBVkFOVCBJbml0IHBvdXIgZXZpdGVyCiAgICAjIGwnYWxsb2NhdGlvbiBkZXMgb2JqZXRzIG1vdGV1ciBwYXIgdGhyZWFkIHdvcmtlciAobm9uIGFib3V0aWUgc291cyBob3RlIGN0eXBlcykuCiAgICBfZm9yY2Vfc2luZ2xlX2NwdSgpCiAgICAjIFNocmVkZGVySW5pdChhcmcxLCBjYWxsYmFja3MsIGFyZzM9Y2hlbWluX2Rvc3NpZXIsIGFyZzQpCiAgICB0cnk6CiAgICAgICAgSW5pdChjdHlwZXMuY2FzdChfYXJnMSwgICAgY3R5cGVzLmNfdm9pZF9wKSwKICAgICAgICAgICAgIGN0eXBlcy5jYXN0KENCU3RydWN0LCBjdHlwZXMuY192b2lkX3ApLAogICAgICAgICAgICAgY3R5cGVzLmNhc3QoX2FyZ3BhdGgsIGN0eXBlcy5jX3ZvaWRfcCksICAgIyBBUkczID0gY2hlbWluCiAgICAgICAgICAgICBjdHlwZXMuY2FzdChfYXJnNCwgICAgY3R5cGVzLmNfdm9pZF9wKSkKICAgICAgICBsb2coIlNocmVkZGVySW5pdCBmYWl0IikKICAgIGV4Y2VwdCBFeGNlcHRpb24gYXMgZToKICAgICAgICBlcnIoIlNocmVkZGVySW5pdCBhIHBsYW50ZToiLCByZXByKGUpLCAifCBSVkEgZmF1dGUocyk6IiwgX2ZhdWx0X3J2YXMoKSkKICAgICMgdGFpbGxlIGRlIGhhc2gKICAgIHRyeToKICAgICAgICBTZXRQYXJhbShiIkhhc2giLCBzdHIoSEFTSF9NQikuZW5jb2RlKCkpCiAgICAgICAgbG9nKGYiU2V0UGFyYW0gSGFzaCB7SEFTSF9NQn0iKQogICAgZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOgogICAgICAgIGxvZygiU2V0UGFyYW0gRVhDIiwgcmVwcihlKSkKICAgIHRyeToKICAgICAgICB2ZXIgPSBHZXRWZXJzaW9uKCk7IGF1dCA9IEdldEF1dGhvcigpCiAgICAgICAgbG9nKCJ2ZXJzaW9uOiIsIHZlciwgImF1dGV1cjoiLCBhdXQpCiAgICBleGNlcHQgRXhjZXB0aW9uOgogICAgICAgIHBhc3MKCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIHBvc2l0aW9uCl9NT1ZFX1JFID0gcmUuY29tcGlsZShyIl5bYS1oXVsxLThdW2EtaF1bMS04XVtxcmJuUVJCTl0\/JCIpCgpkZWYgc2V0X3Bvc2l0aW9uKHRva2Vucyk6CiAgICBlbnN1cmVfaW5pdCgpCiAgICBTZXRTdGFydFBvcygpCiAgICBtb3ZlcyA9IFtdCiAgICBpZiAibW92ZXMiIGluIHRva2VuczoKICAgICAgICBtb3ZlcyA9IHRva2Vuc1t0b2tlbnMuaW5kZXgoIm1vdmVzIikgKyAxOl0KICAgIGVsaWYgImZlbiIgbm90IGluIHRva2VucyBhbmQgbGVuKHRva2VucykgPiAyIGFuZCB0b2tlbnNbMV0gPT0gInN0YXJ0cG9zIjoKICAgICAgICAjIFRPTEVSQU5DRSA6IGNvdXBzIGNvbGxlcyBhcHJlcyAnc3RhcnRwb3MnIHNhbnMgbGUgbW90LWNsZSAnbW92ZXMnICh0ZXN0IG1hbnVlbCkuCiAgICAgICAgIyBTYW5zIGVmZmV0IHN1ciBsZXMgR1VJcywgcXVpIGVudm9pZW50IHRvdWpvdXJzICdwb3NpdGlvbiBzdGFydHBvcyBtb3ZlcyAuLi4nLgogICAgICAgIGNhbmQgPSBbdCBmb3IgdCBpbiB0b2tlbnNbMjpdIGlmIF9NT1ZFX1JFLm1hdGNoKHQpXQogICAgICAgIGlmIGNhbmQ6CiAgICAgICAgICAgIG1vdmVzID0gY2FuZAogICAgICAgICAgICBsb2coIk5PVEU6IGNvdXBzIGFwcGxpcXVlcyBzYW5zIG1vdC1jbGUgJ21vdmVzJyAodG9sZXJhbmNlKSA6IiwgIiAiLmpvaW4oY2FuZCkpCiAgICBmb3IgbXYgaW4gbW92ZXM6CiAgICAgICAgdHJ5OgogICAgICAgICAgICBFbnRlck1vdmUobXYuZW5jb2RlKCJsYXRpbjEiKSkKICAgICAgICBleGNlcHQgRXhjZXB0aW9uIGFzIGU6CiAgICAgICAgICAgIGVycigiRW50ZXJNb3ZlIiwgbXYsICI6IiwgcmVwcihlKSkKICAgIGlmICJmZW4iIGluIHRva2VuczoKICAgICAgICAjIFNocmVkZGVyIHBhcnQgZGUgbGEgcG9zaXRpb24gZGUgZGVwYXJ0ICsgY291cHMgOyAncG9zaXRpb24gZmVuJyBub24gZ2VyZSBpY2kuCiAgICAgICAgbG9nKCJBVkVSVElTU0VNRU5UOiAncG9zaXRpb24gZmVuJyBub24gc3VwcG9ydGUgKGRlcGFydCtjb3VwcyBzZXVsZW1lbnQpIikKCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIHJlY2hlcmNoZQpfZGxsX2RpcnR5ID0gRmFsc2UgICAgICAgICMgYXJtZSBzaSBTaHJlZGRlckFuYWx5c2UgcGxhbnRlIDogbCdldGF0IGRlIGxhIERMTCBlc3QgY29ycm9tcHUKCmRlZiBsb2dfaW5jaWRlbnQoKmEpOgogICAgIyBKb3VybmFsIGRlcyBJTkNJREVOVFMgdW5pcXVlbWVudCA6IGxlIGZpY2hpZXIgbidlc3QgY3JlZSBxdSdlbiBjYXMgZGUgcGxhbnRhZ2UsIGRvbmMgYXVjdW5lCiAgICAjIHBvbGx1dGlvbiBkZXMgZG9zc2llcnMgcXVhbmQgdG91dCB2YSBiaWVuLCBtYWlzIHVuZSB0cmFjZSBleHBsb2l0YWJsZSBlbiB0b3Vybm9pLgogICAgbSA9ICIgIi5qb2luKHN0cih4KSBmb3IgeCBpbiBhKQogICAgbG9nKG0pCiAgICB0cnk6CiAgICAgICAgd2l0aCBvcGVuKG9zLnBhdGguam9pbihIRVJFLCAic2hyZWRkZXIydWNpX2luY2lkZW50cy5sb2ciKSwgImEiLAogICAgICAgICAgICAgICAgICBlbmNvZGluZz0idXRmLTgiLCBlcnJvcnM9InJlcGxhY2UiKSBhcyBmOgogICAgICAgICAgICBmLndyaXRlKGYiW3t0aW1lLnN0cmZ0aW1lKCclWS0lbS0lZCAlSDolTTolUycpfV0gcGlkPXtvcy5nZXRwaWQoKX0ge219XG4iKQogICAgZXhjZXB0IEV4Y2VwdGlvbjogcGFzcwoKZGVmIHJlaW5pdF9hZnRlcl9jcmFzaCgpOgogICAgIyBBcHJlcyB1biBwbGFudGFnZSBkZSBTaHJlZGRlckFuYWx5c2UsIGwnZXRhdCBpbnRlcm5lIGRlIGxhIERMTCBlc3QgY29ycm9tcHUgOiBzYW5zIHJlbWlzZSBhCiAgICAjIHplcm8sIGxlcyByZWNoZXJjaGVzIFNVSVZBTlRFUyBlY2hvdWVudCBhdXNzaSAtPiAiYmVzdG1vdmUgMDAwMCIgYSByZXBldGl0aW9uLCBxdWUgQmFua3NpYQogICAgIyBjb21wdGUgY29tbWUgdW4gY3Jhc2ggZXQgcXVpIHBlcmQgbGEgcGFydGllLiBPbiByZWpvdWUgZG9uYyBsJ2luaXQgY29tcGxldGUuCiAgICBnbG9iYWwgX2RsbF9kaXJ0eSwgX2luaXRlZAogICAgaWYgbm90IF9kbGxfZGlydHk6IHJldHVybgogICAgX2RsbF9kaXJ0eSA9IEZhbHNlCiAgICB0cnk6IFN0b3BBbmFseXNlKCkKICAgIGV4Y2VwdCBFeGNlcHRpb246IHBhc3MKICAgIHRyeToKICAgICAgICBfaW5pdGVkID0gRmFsc2UKICAgICAgICBlbnN1cmVfaW5pdCgpCiAgICAgICAgbG9nX2luY2lkZW50KCJyZWluaXQgYXByZXMgcGxhbnRhZ2UgOiBTaHJlZGRlckluaXQgcmVqb3VlIikKICAgIGV4Y2VwdCBFeGNlcHRpb24gYXMgZToKICAgICAgICBsb2dfaW5jaWRlbnQoZiJyZWluaXQgYXByZXMgcGxhbnRhZ2UgRUNIRUMgOiB7ZSFyfSIpCgpkZWYgZG9fc2VhcmNoKGRlcHRoPU5vbmUsIG1vdmV0aW1lX21zPU5vbmUsIHd0aW1lPU5vbmUsIGJ0aW1lPU5vbmUsCiAgICAgICAgICAgICAgd2luYz0wLCBiaW5jPTAsIG1vdmVzdG9nbz0wKToKICAgIHJlaW5pdF9hZnRlcl9jcmFzaCgpICAgICAgIyBzaSBsYSByZWNoZXJjaGUgcHJlY2VkZW50ZSBhIHBsYW50ZSwgcmVtZXR0cmUgbGEgRExMIGQnYXBsb21iCiAgICBzdC5iZXN0ID0gIiI7IHN0LmRlcHRoID0gMDsgc3Quc2NvcmUgPSAwOyBzdC5ub2RlcyA9IDA7IHN0LnB2ID0gIiI7IHN0Lmxhc3RfZW1pdCA9IE5vbmUKICAgIHN0LnQwID0gdGltZS50aW1lKCkKICAgICMgb24gZWNyaXQgZGlyZWN0ZW1lbnQgbGVzIHBhcmFtZXRyZXMgVUNJIGR1ICJnbyIgZGFucyBsZSBidWZmZXIgZGUgc2hyZWRkZXIuZGxsCiAgICBpZiBkZXB0aDoKICAgICAgICBzZXRfZ28oZiJkZXB0aCB7aW50KGRlcHRoKX0iKQogICAgZWxpZiBtb3ZldGltZV9tczoKICAgICAgICAjIFNocmVkZGVyIGRlYm9yZGUgZCdlbnZpcm9uIDM1MC00NTAgbXMgYXUtZGVsYSBkZSBtb3ZldGltZSAoaWwgZmluaXQgc29uCiAgICAgICAgIyBpdGVyYXRpb24gYXZhbnQgZGUgcydhcnJldGVyKS4gT24gcmV0aXJlIHVuZSBtYXJnZSBwb3VyIG5lIHBhcyBldHJlIGZsYWdnZQogICAgICAgICMgcGFyIGxhIEdVSSAoQmFua3NpYSBtZXN1cmUgZ28tPmJlc3Rtb3ZlIGVuIHRlbXBzIHJlZWwpLgogICAgICAgIG1hcmdpbiA9IG1heCg1MDAsIG1vdmV0aW1lX21zIC8vIDEwKQogICAgICAgIHNldF9nbyhmIm1vdmV0aW1lIHttYXgoNTAsIGludChtb3ZldGltZV9tcykgLSBtYXJnaW4pfSIpCiAgICBlbHNlOgogICAgICAgIHAgPSBmInd0aW1lIHtpbnQod3RpbWUgb3IgMCl9IGJ0aW1lIHtpbnQoYnRpbWUgb3IgMCl9IgogICAgICAgIGlmIHdpbmMgb3IgYmluYzogcCArPSBmIiB3aW5jIHtpbnQod2luYyl9IGJpbmMge2ludChiaW5jKX0iCiAgICAgICAgaWYgbW92ZXN0b2dvOiAgICBwICs9IGYiIG1vdmVzdG9nbyB7aW50KG1vdmVzdG9nbyl9IgogICAgICAgIHNldF9nbyhwKQogICAgdHJ5OgogICAgICAgIEFuYWx5c2UoMCwgMSkgICAgICAgICAgICAgICMgbW9kZT0wIDogam91ZSBldCBzJ2FycmV0ZSAodGVtcHMvcHJvZm9uZGV1cikgOyAyZSBhcmcgOiBmbGFnIGludGVybmUKICAgIGV4Y2VwdCBFeGNlcHRpb24gYXMgZToKICAgICAgICBnbG9iYWwgX2RsbF9kaXJ0eQogICAgICAgIF9kbGxfZGlydHkgPSBUcnVlICAgICAgICAgICMgZXRhdCBETEwgY29ycm9tcHUgLT4gcmVpbml0IGF2YW50IGxhIHByb2NoYWluZSByZWNoZXJjaGUKICAgICAgICBsb2dfaW5jaWRlbnQoZiJTaHJlZGRlckFuYWx5c2UgYSBwbGFudGU6IHtlIXJ9IHwgUlZBIGZhdXRlKHMpOiB7X2ZhdWx0X3J2YXMoKX0iKQogICAgZW1pdF9pbmZvKCkKICAgICMgUmVwbGkgOiBzdC5iZXN0IHZpZW50IGRlIFNob3dNYWlubGluZS4gUydpbCBlc3QgdmlkZSAocGxhbnRhZ2UgcHJlY29jZSksIHByZW5kcmUgbGUgMWVyIGNvdXAgZGUKICAgICMgbGEgUFYgY29ubnVlIHBsdXRvdCBxdWUgZCdlbWV0dHJlICIwMDAwIiwgcXVlIGxhIEdVSSBjb21wdGUgY29tbWUgdW4gY3Jhc2ggZXQgcXVpIHBlcmQgbGEgcGFydGllLgogICAgbXYgPSBzdC5iZXN0IG9yIChzdC5wdi5zcGxpdCgpWzBdIGlmIHN0LnB2IGVsc2UgIiIpCiAgICBvdXQoZiJiZXN0bW92ZSB7bXYgaWYgbXYgZWxzZSAnMDAwMCd9IikKCiMgTGEgcmVjaGVyY2hlIHRvdXJuZSBkYW5zIGxlIFRIUkVBRCBQUklOQ0lQQUwgKHN5bmNocm9uZSkgOiBzaHJlZGRlci5kbGwgcmFwcGVsbGUgbm9zCiMgY2FsbGJhY2tzIGRlcHVpcyBjZSBtZW1lIHRocmVhZCwgY2UgcXVpIGV2aXRlIGxlIGNvbmZsaXQgZCdldGF0IGRlIHRocmVhZCBkZSBQeXRob24gMy4xMy4KIyBTaHJlZGRlckFuYWx5c2UgZXN0IGJsb3F1YW50IGV0IHMnYXJyZXRlIHNldWwgKHByb2ZvbmRldXIvdGVtcHMgZml4ZSksIGFkYXB0ZSBhdXggZ2F1bnRsZXRzLgoKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gYm91Y2xlIFVDSQpkZWYgbWFpbigpOgogICAgbG9nKCI9PT0gYm91Y2xlIFVDSSBkZW1hcnJlZSAoRExMOiIsIG9zLnBhdGguYmFzZW5hbWUoRExMUEFUSCksICIpID09PSIpCiAgICBmb3IgcmF3IGluIHN5cy5zdGRpbjoKICAgICAgICBsaW5lID0gcmF3LnN0cmlwKCkKICAgICAgICBpZiBub3QgbGluZTogY29udGludWUKICAgICAgICBsb2coIjw8IiwgbGluZSkKICAgICAgICB0b2sgPSBsaW5lLnNwbGl0KCk7IGNtZCA9IHRva1swXQogICAgICAgIGlmIGNtZCA9PSAidWNpIjoKICAgICAgICAgICAgIyBoYW5kc2hha2UgSU5TVEFOVEFORSA6IHBhcyBkJ2luaXQgaWNpIChub20vYXV0ZXVyIHNvbnQgZGVzIGNoYWluZXMgc3RhdGlxdWVzKS4KICAgICAgICAgICAgIyBMJ2luaXQgbG91cmRlIGRlIFNocmVkZGVyIDYgc2UgZmFpdCBzdXIgJ2lzcmVhZHknLCBzaW5vbiBCYW5rc2lhIGFiYW5kb25uZQogICAgICAgICAgICAjIGxlIGhhbmRzaGFrZSBhdmFudCBkZSByZWNldm9pciAndWNpb2snLgogICAgICAgICAgICB0cnk6CiAgICAgICAgICAgICAgICBuYW1lID0gKEdldFZlcnNpb24oKSBvciBiIlNocmVkZGVyIikuZGVjb2RlKCJsYXRpbjEiLCAicmVwbGFjZSIpCiAgICAgICAgICAgICAgICBhdXRoID0gKEdldEF1dGhvcigpICBvciBiIlN0ZWZhbiBNZXllci1LYWhsZW4iKS5kZWNvZGUoImxhdGluMSIsICJyZXBsYWNlIikKICAgICAgICAgICAgZXhjZXB0IEV4Y2VwdGlvbjoKICAgICAgICAgICAgICAgIG5hbWUsIGF1dGggPSAiU2hyZWRkZXIiLCAiU3RlZmFuIE1leWVyLUthaGxlbiIKICAgICAgICAgICAgb3V0KGYiaWQgbmFtZSB7bmFtZX0iKQogICAgICAgICAgICBvdXQoZiJpZCBhdXRob3Ige2F1dGh9IikKICAgICAgICAgICAgb3V0KCJvcHRpb24gbmFtZSBIYXNoIHR5cGUgc3BpbiBkZWZhdWx0IDY0IG1pbiAxIG1heCAxMDI0IikKICAgICAgICAgICAgb3V0KCJ1Y2lvayIpCiAgICAgICAgZWxpZiBjbWQgPT0gInNldG9wdGlvbiI6CiAgICAgICAgICAgIGlmICJIYXNoIiBpbiB0b2sgYW5kICJ2YWx1ZSIgaW4gdG9rOgogICAgICAgICAgICAgICAgZ2xvYmFsIEhBU0hfTUIKICAgICAgICAgICAgICAgIHRyeTogSEFTSF9NQiA9IG1heCgxLCBtaW4oMTAyNCwgaW50KHRva1t0b2suaW5kZXgoInZhbHVlIikgKyAxXSkpKQogICAgICAgICAgICAgICAgZXhjZXB0IEV4Y2VwdGlvbjogcGFzcwogICAgICAgICAgICAgICAgdHJ5OiBTZXRQYXJhbShiIkhhc2giLCBzdHIoSEFTSF9NQikuZW5jb2RlKCkpCiAgICAgICAgICAgICAgICBleGNlcHQgRXhjZXB0aW9uOiBwYXNzCiAgICAgICAgZWxpZiBjbWQgPT0gImlzcmVhZHkiOgogICAgICAgICAgICBlbnN1cmVfaW5pdCgpOyBvdXQoInJlYWR5b2siKQogICAgICAgIGVsaWYgY21kID09ICJ1Y2luZXdnYW1lIjoKICAgICAgICAgICAgZW5zdXJlX2luaXQoKQogICAgICAgICAgICB0cnk6IENsZWFySGFzaCgpCiAgICAgICAgICAgIGV4Y2VwdCBFeGNlcHRpb246IHBhc3MKICAgICAgICBlbGlmIGNtZCA9PSAicG9zaXRpb24iOgogICAgICAgICAgICBzZXRfcG9zaXRpb24odG9rKQogICAgICAgIGVsaWYgY21kID09ICJnbyI6CiAgICAgICAgICAgIGRlZiBndihrLCBkPTApOiByZXR1cm4gaW50KHRva1t0b2suaW5kZXgoaykgKyAxXSkgaWYgayBpbiB0b2sgZWxzZSBkCiAgICAgICAgICAgIGlmICJkZXB0aCIgaW4gdG9rOiAgICAgICAgICAgIGRvX3NlYXJjaChkZXB0aD1taW4oZ3YoImRlcHRoIiksIDQwKSkKICAgICAgICAgICAgZWxpZiAibW92ZXRpbWUiIGluIHRvazogICAgICAgZG9fc2VhcmNoKG1vdmV0aW1lX21zPWd2KCJtb3ZldGltZSIpKQogICAgICAgICAgICBlbGlmICJ3dGltZSIgaW4gdG9rIG9yICJidGltZSIgaW4gdG9rOgogICAgICAgICAgICAgICAgZG9fc2VhcmNoKHd0aW1lPWd2KCJ3dGltZSIpLCBidGltZT1ndigiYnRpbWUiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICB3aW5jPWd2KCJ3aW5jIiksIGJpbmM9Z3YoImJpbmMiKSwgbW92ZXN0b2dvPWd2KCJtb3Zlc3RvZ28iLCAwKSkKICAgICAgICAgICAgZWxzZTogICAgICAgICAgICAgICAgICAgICAgICAgZG9fc2VhcmNoKGRlcHRoPTgpCiAgICAgICAgZWxpZiBjbWQgPT0gInN0b3AiOgogICAgICAgICAgICB0cnk6IFN0b3BBbmFseXNlKCkKICAgICAgICAgICAgZXhjZXB0IEV4Y2VwdGlvbjogcGFzcwogICAgICAgIGVsaWYgY21kID09ICJxdWl0IjoKICAgICAgICAgICAgdHJ5OiBTdG9wQW5hbHlzZSgpCiAgICAgICAgICAgIGV4Y2VwdCBFeGNlcHRpb246IHBhc3MKICAgICAgICAgICAgYnJlYWsKICAgICMgU29ydGllIDogbGEgRExMIHBldXQgcmV0ZW5pciBkZXMgcmVzc291cmNlcyA7IG9zLl9leGl0IHRlcm1pbmUgbGUgcHJvY2Vzc3VzIGltbWVkaWF0ZW1lbnQKICAgICMgKGNvbW1lIGRhbnMgZW5nMnVjaS5weSkgcG91ciBuZSBqYW1haXMgbGFpc3NlciBkZSBwcm9jZXNzdXMgZmFudG9tZSBlbnRyZSBkZXV4IHBhcnRpZXMuCiAgICBvcy5fZXhpdCgwKQoKaWYgX19uYW1lX18gPT0gIl9fbWFpbl9fIjoKICAgIG1haW4oKQo=\";\n    document.getElementById('dl-eng').addEventListener('click',function(){\n      telecharger(ENG,'eng2uci.py');\n    });\n    document.getElementById('dl-shr').addEventListener('click',function(){\n      telecharger(SHR,'shredder2uci.py');\n    });\n  })();\n<\/script>\n<\/body>\n<\/html>\n\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>Faire rejouer les moteurs d&#8217;\u00e9checs classiques \u2014 les ponts eng2uci et shredder2uci Laboratoire &middot; moteurs d&#8217;\u00e9checs classiques Faire rejouer les moteurs classiques Fritz, Junior, Shredder, Nimzo, Hiarcs &mdash; les grands moteurs de 1997 \u00e0 2005 sont enferm\u00e9s dans le logiciel ChessBase qui les a vus na\u00eetre. Deux petits ponts les lib\u00e8rent : ils les font&hellip;&nbsp;<a href=\"https:\/\/www.chess.lumn.eu\/wordpress\/2026\/07\/10\/fritz-sous-gui-alternatives\/\" class=\"\" rel=\"bookmark\">Read More &raquo;<span class=\"screen-reader-text\">UPDATE: Chessbase engines sous autres GUI<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"neve_meta_sidebar":"","neve_meta_container":"","neve_meta_enable_content_width":"","neve_meta_content_width":0,"neve_meta_title_alignment":"","neve_meta_author_avatar":"","neve_post_elements_order":"","neve_meta_disable_header":"","neve_meta_disable_footer":"","neve_meta_disable_title":""},"categories":[53],"tags":[],"rttpg_featured_image_url":null,"rttpg_author":{"display_name":"valterd","author_link":"https:\/\/www.chess.lumn.eu\/wordpress\/author\/valterd\/"},"rttpg_comment":0,"rttpg_category":"<a href=\"https:\/\/www.chess.lumn.eu\/wordpress\/category\/blog\/\" rel=\"category tag\">Blog<\/a>","rttpg_excerpt":"Faire rejouer les moteurs d&#8217;\u00e9checs classiques \u2014 les ponts eng2uci et shredder2uci Laboratoire &middot; moteurs d&#8217;\u00e9checs classiques Faire rejouer les moteurs classiques Fritz, Junior, Shredder, Nimzo, Hiarcs &mdash; les grands moteurs de 1997 \u00e0 2005 sont enferm\u00e9s dans le logiciel ChessBase qui les a vus na\u00eetre. Deux petits ponts les lib\u00e8rent : ils les font&hellip;&nbsp;Read&hellip;","_links":{"self":[{"href":"https:\/\/www.chess.lumn.eu\/wordpress\/wp-json\/wp\/v2\/posts\/3964"}],"collection":[{"href":"https:\/\/www.chess.lumn.eu\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.chess.lumn.eu\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.chess.lumn.eu\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.chess.lumn.eu\/wordpress\/wp-json\/wp\/v2\/comments?post=3964"}],"version-history":[{"count":22,"href":"https:\/\/www.chess.lumn.eu\/wordpress\/wp-json\/wp\/v2\/posts\/3964\/revisions"}],"predecessor-version":[{"id":4007,"href":"https:\/\/www.chess.lumn.eu\/wordpress\/wp-json\/wp\/v2\/posts\/3964\/revisions\/4007"}],"wp:attachment":[{"href":"https:\/\/www.chess.lumn.eu\/wordpress\/wp-json\/wp\/v2\/media?parent=3964"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.chess.lumn.eu\/wordpress\/wp-json\/wp\/v2\/categories?post=3964"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.chess.lumn.eu\/wordpress\/wp-json\/wp\/v2\/tags?post=3964"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}