{"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.11"},"kaggle":{"accelerator":"nvidiaTeslaT4","isGpuEnabled":true,"isInternetEnabled":false,"language":"python","sourceType":"notebook","title":"RSNA EXP-005 labels Axial fold0","slug":"rsna-exp-005-labels-axial-fold0"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","metadata":{},"source":"# RSNA EXP-005 label plumbing + Axial fold0\n\n唯一变量: report labels baseline → **EXP-005 plumbing**（GLOBAL_OA + Synovitis-effusion soft 进表）\n训练设定: 与 EXP-004 Axial fold0 **完全一致**（planes=axial, epochs=3, batch=8, n-clips=2, only-fold=0）\n对照: EXP-004 Axial fold0 LB=**0.687** / EXP-003 S+C=0.685\n\n- rsna_v3 sha256: `1612f21b81b0abb56735a5675504043aced36a468c25328004d7bf35f5f02630`（EXP-003/004 同源）\n- labels sha256: `15cf06b5f8ef9cd3e0e2d27727274c4fa44f8bb6d7c2ee695cfa5aaad3514c19`（EXP-005）\n- 本地覆盖: Synovitis 11.8%→**85.0%**；Medial OA 24.5%→29.5%；Lateral OA 21.7%→27.5%\n- gold Synovitis pos 抓取 10→16/27\n- 不自动提交；TIMING 以 meta.json 为准\n"},{"id":"e5-torch","cell_type":"code","metadata":{},"execution_count":null,"outputs":[],"source":"# 提交模式:禁网(enable_internet:false),torch 2.2.0+cu118 + nvidia-cu11 依赖全部离线安装\n# 坑1:Kaggle 挂载把文件名中 '+' 去掉(2.2.0cu118=非法 PEP440)→ 复制为合法名\n# 坑2:torch 2.2.0+cu118 的 CUDA 库在 nvidia-*-cu11 依赖包中(不在 torch wheel 内),\n#     只装 torch 会缺 libcudart(v8/v9 实证)→ 必须显式安装全部 13 个 wheel\n# 坑3:/kaggle/working 会被收集为 kernel 输出 → 装完立即删除\nimport subprocess, sys, os, glob, shutil\nwh = sorted(glob.glob('/kaggle/input/**/*.whl', recursive=True))\nprint('挂载 wheel 共', len(wh), '个')\nfor w in wh: print('  ', os.path.basename(w))\nassert len(wh) >= 13, 'FAIL: 离线 wheel 不足(应 13: torch+torchvision+11 nvidia-cu11)'\nfixed = []\nfor w in wh:\n    base = os.path.basename(w)\n    dst = os.path.join('/kaggle/working', base.replace('cu118', '+cu118', 1) if 'cu118' in base else base)\n    shutil.copy(w, dst)\n    fixed.append(dst)\nprint('安装 wheel:', [os.path.basename(f) for f in fixed])\nsubprocess.check_call([sys.executable,\"-m\",\"pip\",\"uninstall\",\"-y\",\"-q\",\"torch\",\"torchvision\",\"torchaudio\"])\n# 显式安装全部 wheel(--no-deps --no-index: 无版本解析/无联网)\nsubprocess.check_call([sys.executable,\"-m\",\"pip\",\"install\",\"-q\",\"--no-deps\",\"--no-index\"] + fixed)\nfor f in fixed: os.remove(f)\nimport numpy, torch, torchvision, sklearn, pandas\nprint(\"torch\", torch.__version__, \"cuda\", torch.version.cuda, \"| numpy\", numpy.__version__)\nassert torch.cuda.is_available()\nprint(\"GPU:\", torch.cuda.get_device_name(0))\n"},{"id":"e5-preflight","cell_type":"code","metadata":{},"execution_count":null,"outputs":[],"source":"# preflight: competition mount + Axial coverage\n# Correct layout: test_series/<StudyInstanceUID>/<SeriesInstanceUID>/*.dcm\nimport os, csv\nfrom collections import defaultdict\n\nbase = '/kaggle/input'\n\ndef _find(b, depth=0, max_depth=3):\n    if not os.path.isdir(b):\n        return None\n    try:\n        entries = sorted(os.listdir(b))\n    except OSError:\n        return None\n    for e in entries:\n        p = os.path.join(b, e)\n        if not os.path.isdir(p):\n            continue\n        if e in ('train_series', 'test_series'):\n            continue\n        if os.path.isfile(os.path.join(p, 'test.csv')) and os.path.isdir(os.path.join(p, 'test_series')):\n            return p\n        if depth < max_depth - 1:\n            r = _find(p, depth + 1)\n            if r:\n                return r\n    return None\n\nroot = _find(base)\nif root is None:\n    raise SystemExit('FAIL: 未找到含 test_series+test.csv 的比赛挂载')\nprint('root =', root)\n\ndef count_dcm(dirpath):\n    if not os.path.isdir(dirpath):\n        return -1\n    return sum(1 for f in os.listdir(dirpath) if f.lower().endswith('.dcm'))\n\ndef plane_stats(series_csv, series_dir, label):\n    if not os.path.isfile(series_csv):\n        print(label, 'series csv missing', series_csv)\n        return\n    with open(series_csv, newline='', encoding='utf-8') as f:\n        rows = list(csv.DictReader(f))\n    if not rows:\n        raise SystemExit(f'FAIL: {label} series csv empty')\n    plane_key = None\n    for k in rows[0].keys():\n        if 'plane' in k.lower() or 'anatom' in k.lower():\n            plane_key = k\n            break\n    uid_key = 'StudyInstanceUID'\n    ser_key = 'SeriesInstanceUID'\n    series_counts = defaultdict(int)\n    study_sets = defaultdict(set)\n    axial_series_rows = []\n    for r in rows:\n        pl = r.get(plane_key, '?') if plane_key else '?'\n        series_counts[pl] += 1\n        if uid_key in r:\n            study_sets[pl].add(r[uid_key])\n        if pl == 'Axial' and ser_key in r:\n            axial_series_rows.append(r)\n    print(label, 'plane series counts', dict(series_counts))\n    print(label, 'plane study counts', {k: len(v) for k, v in study_sets.items()})\n    print(label, 'Axial studies', len(study_sets.get('Axial', set())))\n    assert len(study_sets.get('Axial', set())) > 0, f'FAIL: {label} 无 Axial study'\n\n    # Walk both possible layouts\n    n_dcm = 0\n    hits = 0\n    misses = []\n    for r in axial_series_rows:\n        suid = r[uid_key]\n        seid = r[ser_key]\n        candidates = [\n            os.path.join(series_dir, suid, seid),\n            os.path.join(series_dir, seid),\n            os.path.join(series_dir, suid, 'series', seid),\n        ]\n        found = None\n        for c in candidates:\n            k = count_dcm(c)\n            if k and k > 0:\n                found = c\n                n_dcm += k\n                hits += 1\n                print(f'  axial OK study={suid[:14]} series={seid[:16]} dcm={k} path={c}')\n                break\n        if found is None:\n            # fallback: list study dir\n            sdir = os.path.join(series_dir, suid)\n            if os.path.isdir(sdir):\n                children = sorted(os.listdir(sdir))[:8]\n                print(f'  axial miss study={suid[:14]} series={seid[:16]} study_children={children}')\n            else:\n                print(f'  axial miss study={suid[:14]} series={seid[:16]} NO_STUDY_DIR {sdir}')\n            misses.append(seid)\n    print(label, f'axial series hits={hits}/{len(axial_series_rows)} dcm_total={n_dcm}')\n    assert hits > 0 and n_dcm > 0, f'FAIL: {label} Axial DICOM 为空 (hits={hits}, dcm={n_dcm})'\n\n    # also sample sagittal for sanity\n    sag = [r for r in rows if (r.get(plane_key) if plane_key else '') == 'Sagittal']\n    if sag:\n        r0 = sag[0]\n        for c in [os.path.join(series_dir, r0[uid_key], r0[ser_key]), os.path.join(series_dir, r0[ser_key])]:\n            k = count_dcm(c)\n            if k and k > 0:\n                print(label, 'sagittal sanity', r0[ser_key][:16], 'dcm', k)\n                break\n\nplane_stats(os.path.join(root, 'test_series.csv'), os.path.join(root, 'test_series'), 'test')\nplane_stats(os.path.join(root, 'train_series.csv'), os.path.join(root, 'train_series'), 'train')\nprint('preflight axial: OK')\n"},{"id":"e5-v3","cell_type":"code","metadata":{},"execution_count":null,"outputs":[],"source":"import base64, os, hashlib\nparts = []\nparts.append(\"IyAtKi0gY29kaW5nOiB1dGYtOCAtKi0KIiIiClJTTkEgS25lZSBBYm5vcm1hbGl0eSBEZXRlY3Rpb24g4oCUIHYyKOaMiSBBbmF0b21pY2FsX1BsYW5lIOWIhuW5s+mdoueLrOeri+W7uuaooSArIOiejeWQiCkKPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0K55u45a+5IGJhc2VsaW5lKHJzbmFfYmFzZWxpbmUucHkp55qE5qC45b+D5pS55YqoOgotIGJhc2VsaW5lIOaKiiBzdHVkeSDlhoXmiYDmnInlubPpnaLnmoQgc2VyaWVzIOeyl+aatOaLvOaIkOmAmumBkzt2MiDmjIkgQW5hdG9taWNhbF9QbGFuZQogIChBeGlhbCAvIFNhZ2l0dGFsIC8gQ29yb25hbCnlkITorq3kuIDkuKrni6znq4sgUmVzTmV0MzQs5bmz6Z2i5YaF6YOo5YaN5YGaIDIuNUQgY2xpcDsKLSB0ZXN0IOaOqOeQhuaXtuavj+S4quW5s+mdouaooeWei+eLrOeri+mihOa1iyzmnIDnu4jmjIkg5ZCE5bmz6Z2iIE9PRiDlro/lubPlnYcgQVVDIOWKoOadg+iejeWQiAogICjmnYPph43lj68gLS1mdXNlIHdlaWdodCDnlKggQVVDIOWKoOadgyzmiJYgLS1mdXNlIG1lYW4g566A5Y2V5bmz5Z2HKTsKLSDmn5Agc3R1ZHkg57y65p+Q5bmz6Z2i5pe2LOiejeWQiOWPquWvueivpSBzdHVkeSDlrp7pmYXlj6/nlKjnmoTlubPpnaLlvZLkuIDljJbmnYPph43jgIIKCuWFtuS9memAu+i+kSjova/moIfnrb7loavlhYXjgIFHcm91cEtGb2xk44CBdmFsaWQg5o6p56CB5o2f5aSx44CBRElDT00g6aKE5aSE55CGKeS4jiBiYXNlbGluZSDkuIDoh7TjgIIKCui/kOihjOeOr+WigzpLYWdnbGUgTm90ZWJvb2soR1BVLOaMgui9veavlOi1m+aVsOaNriArIOekvuWMuui9r+agh+etvuaVsOaNrumbhinjgIIK55So5rOVOgogICAgIXB5dGhvbiByc25hX3YyLnB5IC0tZXBvY2hzIDMgLS1iYXRjaCAxNiAtLW4tY2xpcHMgMiAtLXBsYW5lcyBzYWdpdHRhbCxjb3JvbmFsCiAgICAhcHl0aG9uIHJzbmFfdjIucHkgLS1lcG9jaHMgMyAtLWJhdGNoIDE2IC0tZnVzZSB3ZWlnaHQgLS1wc2V1ZG8tY29uZiAwLjMK6L6T5Ye6OiBzdWJtaXNzaW9uLmNzdihTdHVkeUluc3RhbmNlVUlEICsgMTIg5YiX572u5L+h5YiG5pWwKQoiIiIKaW1wb3J0IGFyZ3BhcnNlCmltcG9ydCBqc29uCmltcG9ydCBvcwppbXBvcnQgc3lzCmltcG9ydCB0aW1lCmltcG9ydCB3YXJuaW5ncwpmcm9tIHBhdGhsaWIgaW1wb3J0IFBhdGgKCmltcG9ydCBudW1weSBhcyBucAppbXBvcnQgcGFuZGFzIGFzIHBkCgp0cnk6CiAgICBpbXBvcnQgdG9yY2gKICAgIGltcG9ydCB0b3JjaC5ubiBhcyBubgogICAgZnJvbSB0b3JjaC51dGlscy5kYXRhIGltcG9ydCBEYXRhc2V0LCBEYXRhTG9hZGVyCiAgICBmcm9tIHRvcmNoLm9wdGltIGltcG9ydCBBZGFtVwogICAgZnJvbSB0b3JjaC5vcHRpbS5scl9zY2hlZHVsZXIgaW1wb3J0IENvc2luZUFubmVhbGluZ0xSCiAgICBIQVNfVE9SQ0ggPSBUcnVlCmV4Y2VwdCBJbXBvcnRFcnJvcjoKICAgIEhBU19UT1JDSCA9IEZhbHNlCgp0cnk6CiAgICBpbXBvcnQgdG9yY2h2aXNpb24ubW9kZWxzIGFzIHR2bQogICAgSEFTX1RWID0gVHJ1ZQpleGNlcHQgSW1wb3J0RXJyb3I6CiAgICBIQVNfVFYgPSBGYWxzZQoKdHJ5OgogICAgaW1wb3J0IHB5ZGljb20KICAgIEhBU19QWURJQ09NID0gVHJ1ZQpleGNlcHQgSW1wb3J0RXJyb3I6CiAgICBIQVNfUFlESUNPTSA9IEZhbHNlCgp0cnk6CiAgICBpbXBvcnQgcnNuYV9yZXBvcnRfbGFiZWxzIGFzIFJMICAgIyDmiqXlkYrihpIxMiDnl4XngbblvLHmoIfnrb4o5LiOIHJzbmFfdjMucHkg5ZCM55uu5b2VKQogICAgSEFTX1JMID0gVHJ1ZQpleGNlcHQgSW1wb3J0RXJyb3I6CiAgICBIQVNfUkwgPSBGYWxzZQoKZnJvbSBza2xlYXJuLm1vZGVsX3NlbGVjdGlvbiBpbXBvcnQgR3JvdXBLRm9sZApmcm9tIHNrbGVhcm4ubWV0cmljcyBpbXBvcnQgcm9jX2F1Y19zY29yZQoKd2FybmluZ3MuZmlsdGVyd2FybmluZ3MoImlnbm9yZSIpCgpMQUJFTFMgPSBbIkFDTCIsICJNQ0wiLCAiTWVkaWFsIE1lbmlzY3VzIiwgIkxhdGVyYWwgTWVuaXNjdXMiLAogICAgICAgICAgIk1lZGlhbCBPQSIsICJMYXRlcmFsIE9BIiwgIlBGIE9BIiwgIkVmZnVzaW9uIiwgIlN5bm92aXRpcyIsCiAgICAgICAgICAiQmFrZXIncyIsICJDb250dXNpb24iLCAiRnJhY3R1cmUiXQpMQUJFTFNfRU4gPSBbIkFDTCIsICJNQ0wiLCAiTWVkaWFsTWVuaXNjdXMiLCAiTGF0ZXJhbE1lbmlzY3VzIiwKICAgICAgICAgICAgICJNZWRpYWxPQSIsICJMYXRlcmFsT0EiLCAiUEZPQSIsICJFZmZ1c2lvbiIsICJTeW5vdml0aXMiLAogICAgICAgICAgICAgIkJha2VycyIsICJDb250dXNpb24iLCAiRnJhY3R1cmUiXSAgIyDliJflkI3lronlhajljJYo5YaZ5o+Q5Lqk55SoKQpQTEFORVMgPSBbIkF4aWFsIiwgIlNhZ2l0dGFsIiwgIkNvcm9uYWwiXQoKSU1HX1NJWkUgPSAyMjQKQ0xJUCA9IDMgICAgICAgICAgIyDmr48gY2xpcCDliIfniYfmlbAocHJldi9jZW50ZXIvbmV4dCkKTUFYX1NFUklFUyA9IDQgICAgIyDmr48gc3R1ZHkg5q+P5Liq5bmz6Z2i5pyA5aSa5Y+W55qEIHNlcmllcyDmlbAodjIg5oyJ5bmz6Z2i5Y+WLOWNleW5s+mdoiBzZXJpZXMg5pu05bCRLDQg6Laz5aSfKQpGT0xEUyA9IDUKU0VFRCA9IDQyCgoKZGVmIHJlc29sdmVfcGF0aHMoKToKICAgICIiIuaVsOaNruWumuS9jemhuuW6jzoxKSAva2FnZ2xlL2lucHV0IOaMgui9vTsyKSBrYWdnbGVodWIg6Ieq5Yqo5LiL6L29OzMpIOacrOWcsCByc25hX2tuZWUvIOebruW9leOAgiIiIgogICAgIyAxKSBLYWdnbGUg5oyC6L29KOWFvOWuueWkmuWxguaMgui9vTova2FnZ2xlL2lucHV0LzzmlbDmja7lkI0+LyDmiJYgL2thZ2dsZS9pbnB1dC885YiG57G7Pi885pWw5o2u5ZCNPi8pCiAgICBpZiBvcy5wYXRoLmlzZGlyKCIva2FnZ2xlL2lucHV0Iik6CiAgICAgICAgZm9yIHN1YiBpbiBzb3J0ZWQob3MubGlzdGRpcigiL2thZ2dsZS9pbnB1dCIpKToKICAgICAgICAgICAgZCA9IG9zLnBhdGguam9pbigiL2thZ2dsZS9pbnB1dCIsIHN1YikKICAgICAgICAgICAgZm9yIGNhbmQgaW4gKGQsIG9zLnBhdGguam9pbihkLCBzdWIpKTogICMg5aSE55CGIEthZ2dsZSDlj4zlsYLmjILovb0KICAgICAgICAgICAgICAgIGlmIG9zLnBhdGguZXhpc3RzKG9zLnBhdGguam9pbihjYW5kLCAidHJhaW4uY3N2IikpOgogICAgICAgICAgICAgICAgICAgIHJldHVybiBjYW5kLCAiL2thZ2dsZS93b3JraW5nIgogICAgICAgICAgICBpZiBvcy5wYXRoLmlzZGlyKGQpOiAgIyDlho3lvoDkuIvkuIDlsYLmib4o5aaCIC9rYWdnbGUvaW5wdXQvY29tcGV0aXRpb25zLzxuYW1lPi8pCiAgICAgICAgICAgICAgICBmb3Igc3ViMiBpbiBzb3J0ZWQob3MubGlzdGRpcihkKSk6CiAgICAgICAgICAgICAgICAgICAgY2FuZCA9IG9zLnBhdGguam9pbihkLCBzdWIyKQogICAgICAgICAgICAgICAgICAgIGlmIG9zLnBhdGguZXhpc3RzKG9zLnBhdGguam9pbihjYW5kLCAidHJhaW4uY3N2IikpOgogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gY2FuZCwgIi9rYWdnbGUvd29ya2luZyIKICAgICAgICBwcmludCgiW+iviuaWrV0gL2thZ2dsZS9pbnB1dCDlrZjlnKgs5L2G5rKh5om+5Yiw5ZCrIHRyYWluLmNzdiDnmoTnm67lvZXjgILlrp7pmYXmjILovb3lhoXlrrnlpoLkuIs6IiwgZmx1c2g9VHJ1ZSkKICAgICAgICBmb3Igc3ViIGluIHNvcnRlZChvcy5saXN0ZGlyKCIva2FnZ2xlL2lucHV0IikpOgogICAgICAgICAgICBwID0gb3MucGF0aC5qb2luKCIva2FnZ2xlL2lucHV0Iiwgc3ViKQogICAgICAgICAgICB0cnk6CiAgICAgICAgICAgICAgICBpbm5lciA9IG9zLmxpc3RkaXIocCkKICAgICAgICAgICAgZXhjZXB0IE9TRXJyb3I6CiAgICAgICAgICAgICAgICBpbm5lciA9IFsiKOaXoOazleivu+WPlikiXQogICAgICAgICAgICBwcmludChmIiAgL2thZ2dsZS9pbnB1dC97c3VifS8gIC0+ICB7aW5uZXJbOjhdfSIsIGZsdXNoPVRydWUpCiAgICAgICAgcHJpbnQoIlvor4rmlq1dIOWmguaenOS9oOaMgueahOaYryAn5L2c6ICF5pWw5o2u5YyFL+WIq+S6uueahCBrZXJuZWwg6L6T5Ye6Jywg6YeM6Z2i5rKh5pyJIHRyYWluLmNzdiDlkowgdHJhaW5fc2VyaWVzLywiLAogICAgICAgICAgICAgICLlv4XpobvmjILmr5TotZvmlbDmja7mnKzkvZMgcnNuYS1rbmVlLWFibm9ybWFsaXR5LWRldGVjdGlvbiAoQWRkIElucHV0IC0+IENvbXBldGl0aW9ucyDmoIfnrb7pobUpIiwgZmx1c2g9VHJ1ZSkKICAgICMgMikga2FnZ2xlaHViIOWFnOW6lTrmnKrmjILovb3ml7boh6rliqjkuIvovb3mr5TotZvmlbDmja4oS2FnZ2xlIE5vdGVib29rIOWGhee9ruWHreaNrikKICAgIHRyeToKICAgICAgICBpbXBvcnQga2FnZ2xlaHViCiAgICAgICAgZCA9IGthZ2dsZWh1Yi5jb21wZXRpdGlvbl9kb3dubG9hZCgicnNuYS1rbmVlLWFibm9ybWFsaXR5LWRldGVjdGlvbiIpCiAgICAgICAgaWYgb3MucGF0aC5leGlzdHMob3MucGF0aC5qb2luKGQsICJ0cmFpbi5jc3YiKSk6CiAgICAgICAgICAgIHByaW50KGYiW+i3r+W+hF0g5pyq5oyC6L29LOW3sueUqCBrYWdnbGVodWIg6I635Y+W5pWw5o2uOiB7ZH0iLCBmbHVzaD1UcnVlKQogICAgICAgICAgICByZXR1cm4gZCwgIi9rYWdnbGUvd29ya2luZyIKICAgIGV4Y2VwdCBJbXBvcnRFcnJvcjoKICAgICAgICBwYXNzICAjIOacrOWcsOacquijhSBrYWdnbGVodWIKICAgIGV4Y2VwdCBFeGNlcHRpb24gYXMgZToKICAgICAgICBwcmludChmIlvmj5DnpLpdIGthZ2dsZWh1YiDkuIvovb3mlbDmja7lpLHotKU6IHtlfSIsIGZsdXNoPVRydWUpCiAgICAjIDMpIOacrOWcsOWbnumAgCjohJrmnKznm67lvZUgLyBjd2QgLyBjd2Qg5LiL55qEIHJzbmFfa25lZSDlrZDnm67lvZXpg73mib4pCiAgICBjYW5kcyA9IFtdCiAgICB0cnk6CiAgICAgICAgY2FuZHMuYXBwZW5kKG9zLnBhdGguZGlybmFtZShvcy5wYXRoLmFic3BhdGgoX19maWxlX18pKSkKICAgIGV4Y2VwdCBOYW1lRXJyb3I6CiAgICAgICAgcGFzcwogICAgY2FuZHMuYXBwZW5kKG9zLmdldGN3ZCgpKQogICAgZm9yIGJhc2UgaW4gbGlzdChjYW5kcyk6CiAgICAgICAgY2FuZHMuYXBwZW5kKG9zLnBhdGguam9pbihiYXNlLCAicnNuYV9rbmVlIikpCiAgICBzZWVuID0gc2V0KCkKICAgIGZvciBiYXNlIGluIGNhbmRzOgogICAgICAgIGlmIGJhc2UgaW4gc2VlbjoKICAgICAgICAgICAgY29udGludWUKICAgICAgICBzZWVuLmFkZChiYXNlKQogICAgICAgIGlmIG9zLnBhdGguZXhpc3RzKG9zLnBhdGguam9pbihiYXNlLCAidHJhaW4uY3N2IikpOgogICAgICAgICAgICByZXR1cm4gYmFzZSwgYmFzZQogICAgc3lzLmV4aXQoIuaJvuS4jeWIsOaVsOaNrjror7flhYjlnKjmr5TotZvpobXliqDlhaXmr5TotZvlubblkIzmhI/mlbDmja7op4TliJks5YaNIEFkZCBJbnB1dCDmjILovb0gIgogICAgICAgICAgICAgInJzbmEta25lZS1hYm5vcm1hbGl0eS1kZXRlY3Rpb2475pys5Zyw6K+35ZyoIHJzbmFfa25lZS8g5LiL6L+Q6KGM44CCIikKCgpfUFNFVURPX0ZJTEVTID0gKCJ0cmFpbl9mb2xkc193aXRoX3BzZXVkby5jc3YiLCAidHJhaW5fd2l0aF9wc2V1ZG8uY3N2IiwKICAgICAgICAgICAgICAgICAidHJhaW5fd2l0aF9zb2Z0X2xhYmVscy5jc3YiLCAidHJhaW5fcHNldWRvLmNzdiIpCl9TS0lQX0RJUlMgPSB7InRyYWluX3NlcmllcyIsICJ0ZXN0X3NlcmllcyJ9ICAjIERJQ09NIOWkp+ebruW9lSznu53kuI3ljrvpgY3ljoYKX1dFSUdIVF9FWFQgPSAoIi5wdGgiLCAiLnB0IiwgIi5ja3B0IiwgIi5wdGgudGFyIikgICMg56a757q/6aKE6K6t57uD5p2D6YeN5paH5Lu25omp5bGV5ZCNCgojIDEyIOagh+etvuWkmuivreiogOWFs+mUruivjeivjeWFuCjoi7Ev6KW/L+iNty/lvrcv5rOVKeKAlOKAlOmbtuaMgui9vei9r+agh+etvuWFnOW6lQojIOWRveS4rSDihpIg6auY572u5L+hLOacquWRveS4rSDihpIg5L2O572u5L+hKOi9r+agh+etvizkuI3nu5nnoawgMC8xLOmBv+WFjemUmeivjeivr+WvvCkKX1JFUE9SVF9LRVlXT1JEUyA9IHsKICAgICJBQ0wiOiBbImFjbCIsICJhbnRlcmlvciBjcnVjaWF0ZSIsICJjcnVjaWFkbyBhbnRlcmlvciIsICJ2b29yc3RlIGtydWlzYmFuZCIsCiAgICAgICAgICAgICJ2b3JkZXJlbiBrcmV1emJhbmQiLCAibGNhIiwgImxpZ2FtZW50IGNyb2lzw6kgYW50w6lyaWV1ciJdLAogICAgIk1DTCI6IFsibWNsIiwgIm1lZGlhbCBjb2xsYXRlcmFsIiwgImNvbGF0ZXJhbCBtZWRpYWwiLCAibWVkaWFsZSBjb2xsYXRlcmFsZSIsCiAgICAgICAgICAgICJpbm5lcmVzIHNlaXRlbmJhbmQiLCAibGlnYW1lbnQgY29sbGF0w6lyYWwgbcOpZGlhbCJdLAogICAgIk1lZGlhbCBNZW5pc2N1cyI6IFsibWVkaWFsIG1lbmlzY3VzIiwgIm1lbmlzY28gaW50ZXJubyIsICJtZW5pc2N1cyBtZWRpYWxpcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICJtZW5pc2t1cyBtZWRpYWwiLCAibWVuaXNxdWUgbcOpZGlhbCIsICJpbm5lciBtZW5pc2N1cyIsICJtZW5pc2NvIG1lZGlhbCJdLAogICAgIkxhdGVyYWwgTWVuaXNjdXMiOiBbImxhdGVyYWwgbWVuaXNjdXMiLCAibWVuaXNjbyBleHRlcm5vIiwgIm1lbmlzY3VzIGxhdGVyYWxpcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAibWVuaXNrdXMgbGF0ZXJhbCIsICJtZW5pc3F1ZSBsYXTDqXJhbCIsICJvdXRlciBtZW5pc2N1cyJdLAogICAgIk1lZGlhbCBPQSI6IFsibWVkaWFsIG9zdGVvYXJ0aHJpdGlzIiwgImFydHJvc2lzIGZlbW9yb3RpYmlhbCBtZWRpYWwiLAogICAgICAgICAgICAgICAgICAibWVkaWFsZSBnb25hcnRyb3NlIiwgIm1lZGlhbGUgYXJ0aHJvc2UiLCAib3N0ZW9hcnRyaXRpcyBtZWRpYWwiLAogICAgICAgICAgICAgICAgICAibWVkaWFsIGNvbXBhcnRtZW50IG5hcnJvd2luZyIsICJtZWRpYWwgam9pbnQgc3BhY2UgbmFycm93aW5nIl0sCiAgICAiTGF0ZXJhbCBPQSI6IFsibGF0ZXJhbCBvc3Rlb2FydGhyaXRpcyIsICJhcnRyb3NpcyBmZW1vcm90aWJpYWwgbGF0ZXJhbCIsCiAgICAgICAgICAgICAgICAgICAibGF0ZXJhbGUgZ29uYXJ0cm9zZSIsICJsYXRlcmFsZSBhcnRocm9zZSIsICJsYXRlcmFsIGpvaW50IHNwYWNlIG5hcnJvd2luZyJdLAogICAgIlBGIE9BIjogWyJwYXRlbGxvZmVtb3JhbCBvc3Rlb2FydGhyaXRpcyIsICJhcnRyb3NpcyBwYXRlbG9mZW1vcmFsIiwKICAgICAgICAgICAgICAicGF0ZWxsb2ZlbW9yYWxlIGFydHJvc2UiLCAicGF0ZWxsb2ZlbW9yYWwgYXJ0aHJvc2UiLCAicGYgb2EiLAogICAgICAgICAgICAgICJwYXRlbGxvZmVtb3JhbCBuYXJyb3dpbmciLCAicGF0ZWxsb2ZlbW9yYWwgam9pbnQgc3BhY2UiXSwKICAgICJFZmZ1c2lvbiI6IFsiZWZmdXNpb24iLCAiZGVycmFtZSIsICJ2b2NodCIsICJlcmd1c3MiLCAiw6lwYW5jaGVtZW50IiwgImpvaW50IGVmZnVzaW9uIl0sCiAgICAiU3lub3ZpdGlzIjogWyJzeW5vdml0aXMiLCAic2lub3ZpdGlzIiwgInN5bm92aWFsZSIsICJzeW5vdmlhbCB0aGlja2VuaW5nIiwgInN5bm92aXRpcyJdLAogICAgIkJha2VyJ3MiOiBbImJha2VyIiwgInBvcGxpdGVhbCBjeXN0IiwgInF1aXN0ZSBkZSBiYWtlciIsICJiYWtlciBjeXN0Il0sCiAgICAiQ29udHVzaW9uIjogWyJjb250dXNpb24iLCAiYm9uZSBicnVpc2UiLCAiY29udHVzacOzbiIsICJrbmV1emluZyIsICJrb250dXNpb24iLAogICAgICAgICAgICAgICAgICAibWFycm93IGVkZW1hIiwgIsOzc2VvIiwgImJvbmUgYnJ1aXNpbmciXSwKICAgICJGcmFjdHVyZSI6IFsiZnJhY3R1cmUiLCAiZnJhY3R1cmEiLCAiZnJhY3R1dXIiLCAiZnJha3R1ciIsICJmcmFjdHVyZSBsaW5lIiwKICAgICAgICAgICAgICAgICAiZnJhY3R1cmUgbGluZSIsICJzdWJjaG9uZHJhbCBmcmFjdHVyZSJdLAp9CgoKZGVmIF9wc2V1ZG9fZnJvbV9yZXBvcnRzKHRyYWluX2NzdiwgY29uZl9oaXQ9MC45LCBjb25mX21pc3M9MC4xKToKICAgICIiIuS7juaUvuWwhOaKpeWRiuaWh+acrOeUqOWkmuivreiogOWFs+mUruivjeeUn+aIkCAxMiDmoIfnrb7ova/moIfnrb4o6Zu25oyC6L295YWc5bqVKeOAggoKICAgIOi/lOWbniBEYXRhRnJhbWUoU3R1ZHlJbnN0YW5jZVVJRCArIHBzZXVkb18qIOWIlynjgILlhbPplK7or43lkb3kuK3ihpJjb25mX2hpdCwKICAgIOacquWRveS4reKGkmNvbmZfbWlzcyjkuI3nu5nnoawgMC8xLOmZjeS9jumUmeivjeivr+WvvCnjgILlrpjmlrnlt7LmnInmoIfms6jnmoQgc3R1ZHkKICAgIOS7jeS7peWumOaWueS4uuWHhihsb2FkX2xhYmVscyDnmoTloavlhYXpgLvovpHkv53or4HlrpjmlrnkvJjlhYgp44CCCiAgICAiIiIKICAgIGlmICJSZXBvcnQiIG5vdCBpbiB0cmFpbl9jc3YuY29sdW1uczoKICAgICAgICByZXR1cm4gTm9uZQogICAgcmVwID0gdHJhaW5fY3N2WyJSZXBvcnQiXS5maWxsbmEoIiIpCiAgICByb3dzID0ge30KICAgIGZvciBsYWIsIGt3cyBpbiBfUkVQT1JUX0tFWVdPUkRTLml0ZW1zKCk6CiAgICAgICAgbG93ID0gW2subG93ZXIoKSBmb3IgayBpbiBrd3NdCiAgICAgICAgcm93c1tmInBzZXVkb197bGFifSJdID0gcmVwLmFwcGx5KAogICAgICAgICAgICBsYW1iZGEgdDogY29uZl9oaXQgaWYgYW55KGsgaW4gc3RyKHQpLmxvd2VyKCkgZm9yIGsgaW4gbG93KSBlbHNlIGNvbmZfbWlzcykKICAgIGRmID0gcGQuRGF0YUZyYW1lKHsiU3R1ZHlJbnN0YW5jZVVJRCI6IHRyYWluX2NzdlsiU3R1ZHlJbnN0YW5jZVVJRCJdLCAqKnJvd3N9KQogICAgcmV0dXJuIGRmCgoKZGVmIF9wcmludF9tb3VudF90cmVlKGJhc2U9Ii9rYWdnbGUvaW5wdXQiLCB0YWc9IuaVsOaNriIsIG1heF9maWxlcz02KToKICAgICIiIuaJk+WNsOaMgui9veebruW9leagkSjmnIDlpJrkuKTlsYIs5q+P55uu5b2V5YmN5Yeg5Liq5paH5Lu2KSzluK7nlKjmiLfnoa7orqTmjILovb3lhoXlrrnjgIIiIiIKICAgIGlmIG5vdCBvcy5wYXRoLmlzZGlyKGJhc2UpOgogICAgICAgIHByaW50KGYiW+iviuaWrS17dGFnfV0g55uu5b2V5LiN5a2Y5ZyoOiB7YmFzZX0iLCBmbHVzaD1UcnVlKQogICAgICAgIHJldHVybgogICAgcHJpbnQoZiJb6K+K5patLXt0YWd9XSAva2FnZ2xlL2lucHV0IOWunumZheaMgui9veWGheWuuToiLCBmbHVzaD1UcnVlKQogICAgZm9yIHN1YiBpbiBzb3J0ZWQob3MubGlzdGRpcihiYXNlKSk6CiAgICAgICAgcCA9IG9zLnBhdGguam9pbihiYXNlLCBzdWIpCiAgICAgICAgdHJ5OgogICAgICAgICAgICBpZiBvcy5wYXRoLmlzZGlyKHApOgogICAgICAgICAgICAgICAgaW5uZXIgPSBzb3J0ZWQob3MubGlzdGRpcihwKSlbOm1heF9maWxlc10KICAgICAgICAgICAgICAgIHByaW50KGYiICB7c3VifS8gLT4ge2lubmVyfSIsIGZsdXNoPVRydWUpCiAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICBwcmludChmIiAge3N1Yn0gKOaWh+S7tikiLCBmbHVzaD1UcnVlKQogICAgICAgIGV4Y2VwdCBPU0Vycm9yOgogICAgICAgICAgICBwcmludChmIiAge3N1Yn0gKOaXoOazleivu+WPlikiLCBmbHVzaD1UcnVlKQoKCmRlZiBfcHJpbnRfZGNtX3RyZWUocm9vdCwgdGFnPSJESUNPTSIsIG1heF9zaG93PTUpOgogICAgIiIi5omT5Y2wIHRyYWluX3NlcmllcyDnm67lvZXliY3lh6DlsYLnnJ/lrp7nu5PmnoQgKyDmir3moLcgLmRjbSDorqHmlbAs56Gu6K6kIERJQ09NIOW4g+WxgOOAggoKICAgIFJTTkEg5bi46KeB5biD5bGAOnRyYWluX3Nlcmllcy88U3R1ZHlJbnN0YW5jZVVJRD4vPFNlcmllc0luc3RhbmNlVUlEPi8qLmRjbSjkuKTlsYIpOwogICAg5Lmf5YW85a655LiA5bGCKDxTZXJpZXNJbnN0YW5jZVVJRD4vKi5kY20p5oiW5pu05rex5bGCLOi/memHjOaJk+WNsOWunumZheeci+WIsOeahOOAggogICAgIiIiCiAgICBkY20gPSBvcy5wYXRoLmpvaW4ocm9vdCwgInRyYWluX3NlcmllcyIpCiAgICBpZiBub3Qgb3MucGF0aC5pc2RpcihkY20pOgogICAgICAgIHByaW50KGYiW+iviuaWrS17dGFnfV0ge2RjbX0g5LiN5a2Y5ZyoISIsIGZsdXNoPVRydWUpCiAgICAgICAgcmV0dXJuCiAgICB0cnk6CiAgICAgICAgc3Vic19hbGwgPSBzb3J0ZWQob3MubGlzdGRpcihkY20pKQogICAgZXhjZXB0IE9TRXJyb3I6CiAgICAgICAgc3Vic19hbGwgPSBbXQogICAgc3VicyA9IHN1YnNfYWxsWzptYXhfc2hvd10KICAgIHByaW50KGYiW+iviuaWrS17dGFnfV0ge2RjbX0iLCBmbHVzaD1UcnVlKQogICAgcHJpbnQoZiJb6K+K5patLXt0YWd9XSDlrZDnm67lvZUv5paH5Lu25pWwOiB7bGVuKHN1YnNfYWxsKX0s5qC35pysOiIsIGZsdXNoPVRydWUpCiAgICBmb3IgcyBpbiBzdWJzOgogICAgICAgIHNwID0gb3MucGF0aC5qb2luKGRjbSwgcykKICAgICAgICBpZiBvcy5wYXRoLmlzZGlyKHNwKToKICAgICAgICAgICAgdHJ5OgogICAgICAgICAgICAgICAgaW5uZXIgPSBzb3J0ZWQob3MubGlzdGRpcihzcCkpWzptYXhfc2hvd10KICAgICAgICAgICAgZXhjZXB0IE9TRXJyb3I6CiAgICAgICAgICAgICAgICBpbm5lciA9IFtdCiAgICAgICAgICAgIHByaW50KGYiICB7c30vIC0+IHtpbm5lcn0iLCBmbHVzaD1UcnVlKQogICAgICAgICAgICBmb3IgaXQgaW4gaW5uZXJbOjJdOgogICAgICAgICAgICAgICAgaXRwID0gb3MucGF0aC5qb2luKHNwLCBpdCkKICAgICAgICAgICAgICAgIGlmIG9zLnBhdGguaXNkaXIoaXRwKToKICAgICAgICAgICAgICAgICAgICB0cnk6CiAgICAgICAgICAgICAgICAgICAgICAgIGZpbGVzID0gc29ydGVkKG9zLmxpc3RkaXIoaXRwKSlbOjNdCiAgICAgICAgICAgICAgICAgICAgZXhjZXB0IE9TRXJyb3I6CiAgICAgICAgICAgICAgICAgICAgICAgIGZpbGVzID0gW10KICAgICAgICAgICAgICAgICAgICBwcmludChmIiAgICAgIHtpdH0vIC0+IHtmaWxlc30iLCBmbHVzaD1UcnVlKQogICAgICAgIGVsc2U6CiAgICAgICAgICAgIHByaW50KGYiICB7c30gKOaWh+S7tikiLCBmbHVzaD1UcnVlKQogICAgIyDmir3moLcgLmRjbSDorqHmlbA65YmNIDMgc3R1ZHkgw5cg5YmNIDMgc2VyaWVzCiAgICBuX2RjbSA9IDAKICAgIHRyeToKICAgICAgICBmb3IgcyBpbiBzdWJzX2FsbFs6M106CiAgICAgICAgICAgIHNwID0gb3MucGF0aC5qb2luKGRjbSwgcykKICAgICAgICAgICAgaWYgbm90IG9zLnBhdGguaXNkaXIoc3ApOgogICAgICAgICAgICAgICAgY29udGludWUKICAgICAgICAgICAgZm9yIGl0IGluIHNvcnRlZChvcy5saXN0ZGlyKHNwKSlbOjNdOgogICAgICAgICAgICAgICAgaXRwID0gb3MucGF0aC5qb2luKHNwLCBpdCkKICAgICAgICAgICAgICAgIGlmIG9zLnBhdGguaXNkaXIoaXRwKToKICAgICAgICAgICAgICAgICAgICBuX2RjbSArPSBzdW0oMSBmb3IgZiBpbiBvcy5saXN0ZGlyKGl0cCkgaWYgZi5sb3dlcigpLmVuZHN3aXRoKCIuZGNtIikpCiAgICBleGNlcHQgT1NFcnJvcjoKICAgICAgICBwYXNzCiAgICBwcmludChmIlvor4rmlq0te3RhZ31dIOaKveagtyAuZGNtIOaWh+S7tuaVsDoge25fZGNtfSjliY0gMyBzdHVkeSDDlyDliY0gMyBzZXJpZXMpIiwgZmx1c2g9VHJ1ZSkKCgpkZWYgX3NjYW5fb2ZmbGluZV93ZWlnaHRzKGJhc2U9Ii9rYWdnbGUvaW5wdXQiLCBkZXB0aD0wLCBtYXhfZGVwdGg9NCk6CiAgICAiIiLpgJLlvZLmiavmj4/mjILovb3nm67lvZXkuIvnmoTpooTorq3nu4PmnYPph43mlofku7YoLnB0aC8ucHQg562JKSzot7Pov4cgRElDT00g5aSn55uu5b2V44CCCgogICAg6L+U5ZueIFso57ud5a+56Lev5b6ELCDnm7jlr7kgL2thZ2dsZS9pbnB1dCDnmoTmj4/ov7ApXTvmib7kuI3liLDov5Tlm57nqbrliJfooajjgIIKICAgIOekvuWMuuaJk+WMheeahOemu+e6v+adg+mHjeaVsOaNrumbhijlpoIgbWF0dGVvbmFjY2FyYXRvL3Jlc25ldDM0LWltYWdlbmV0LXB0aOOAgQogICAgbWFyY3NoYWRlL3Jlc25ldC1wcmV0cmFpbmVkLXdlaWdodHMtaW1hZ2VuZXTjgIFweXRvcmNoL3Jlc25ldDM0KeaMgui9veWQjuWNs+WPr+iiq+aJq+WIsCwKICAgIOaXoOmcgOiBlOe9keOAggogICAgIiIiCiAgICBoaXRzID0gW10KICAgIGlmIGRlcHRoID4gbWF4X2RlcHRoIG9yIG5vdCBvcy5wYXRoLmlzZGlyKGJhc2UpOgogICAgICAgIHJldHVybiBoaXRzCiAgICB0cnk6CiAgICAgICAgZW50cmllcyA9IHNvcnRlZChvcy5saXN0ZGlyKGJhc2UpKQogICAgZXhjZXB0IE9TRXJyb3I6CiAgICAgICAgcmV0dXJuIGhpdHMKICAgIGZvciBmbiBpbiBlbnRyaWVzOgogICAgICAgIHAgPSBvcy5wYXRoLmpvaW4oYmFzZSwgZm4pCiAgICAgICAgaWYgb3MucGF0aC5pc2ZpbGUocCkgYW5kIGZuLmxvd2VyKCkuZW5kc3dpdGgoX1dFSUdIVF9FWFQpOgogICAgICAgICAgICBoaXRzLmFwcGVuZCgocCwgb3MucGF0aC5yZWxwYXRoKHAsICIva2FnZ2xlL2lucHV0IikpKQogICAgICAgIGVsaWYgb3MucGF0aC5pc2RpcihwKSBhbmQgZm4gbm90IGluIF9TS0lQX0RJUlM6CiAgICAgICAgICAgIGhpdHMuZXh0ZW5kKF9zY2FuX29mZmxpbmVfd2VpZ2h0cyhwLCBkZXB0aCArIDEsIG1heF9kZXB0aCkpCiAgICByZXR1cm4gaGl0cwoKCmRlZiBfbG9hZF9zdGF0ZV9kaWN0X2Zyb21fZmlsZShwYXRoKToKICAgICIiIuS7juadg+mHjeaWh+S7tuivuyBzdGF0ZV9kaWN0KOWFvOWuuTrnm7TmjqUgc3RhdGVfZGljdCAvIOWMheWcqCBjaGVja3BvaW50IOmHjCAvIOWQhOenjeWJjee8gCnjgIIKCiAgICDor7vlj5blpLHotKXmiJbmoLzlvI/kuI3lr7nov5Tlm54gTm9uZeOAggogICAgIiIiCiAgICB0cnk6CiAgICAgICAgb2JqID0gdG9yY2gubG9hZChwYXRoLCBtYXBfbG9jYXRpb249ImNwdSIsIHdlaWdodHNfb25seT1UcnVlKQogICAgZXhjZXB0IFR5cGVFcnJvcjogICMg5pen54mIIHRvcmNoIOaXoCB3ZWlnaHRzX29ubHkg5Y+C5pWwCiAgICAgICAgb2JqID0gdG9yY2gubG9hZChwYXRoLCBtYXBfbG9jYXRpb249ImNwdSIpCiAgICBleGNlcHQgRXhjZXB0aW9uIGFzIGU6CiAgICAgICAgcHJpbnQoZiJb5p2D6YeNXSB7cGF0aH0g6K+75Y+W5aSx6LSlOiB7ZX0iLCBmbHVzaD1UcnVlKQogICAgICAgIHJldHVybiBOb25lCiAgICBpZiBpc2luc3RhbmNlKG9iaiwgZGljdCkgYW5kICJzdGF0ZV9kaWN0IiBpbiBvYmo6CiAgICAgICAgb2JqID0gb2JqWyJzdGF0ZV9kaWN0Il0KICAgIGVsaWYgaXNpbnN0YW5jZShvYmosIGRpY3QpIGFuZCAibW9kZWxfc3RhdGVfZGljdCIgaW4gb2JqOgogICAgICAgIG9iaiA9IG9ialsibW9kZWxfc3RhdGVfZGljdCJdCiAgICBlbGlmIGlzaW5zdGFuY2Uob2JqLCBkaWN0KSBhbmQgIm1vZGVsIiBpbiBvYmogYW5kIGlzaW5zdGFuY2Uob2JqWyJtb2RlbCJdLCBkaWN0KToKICAgICAgICBvYmogPSBvYmpbIm1vZGVsIl0KICAgIGlmIG5vdCBpc2luc3RhbmNlKG9iaiwgZGljdCk6CiAgICAgICAgcmV0dXJuIE5vbmUKICAgICMg5Yml5bi46KeB5YmN57yAOm1vZHVsZS4gLyBtb2RlbC4gLyBiYWNrYm9uZS4o6Iul5pW05L2T5bim5YmN57yALOe7n+S4gOi/mOWOnykKICAgIG91dCA9IHt9CiAgICBmb3IgaywgdiBpbiBvYmouaXRlbXMoKToKICAgICAgICBmb3IgcHJlIGluICgibW9kdWxlLiIsICJtb2RlbC4iLCAiYmFja2JvbmUuIik6CiAgICAgICAgICAgIGlmIGsuc3RhcnRzd2l0aChwcmUpOgogICAgICAgICAgICAgICAgayA9IGtbbGVuKHByZSk6XQogICAgICAgICAgICAgICAgYnJlYWsKICAgICAgICBvdXRba10gPSB2CiAgICByZXR1cm4gb3V0CgoKZGVmIF90cnlfbG9hZF9vZmZsaW5lKG5ldCwgcGF0aHMpOgogICAgIiIi5oyJ5bqP5bCd6K+V5oqK5YCZ6YCJ56a757q/5p2D6YeN5Yqg6L296L+bIG5ldChzdGF0ZV9kaWN0IOe7k+aehOmhu+S4jiBSZXNOZXQzNCDljLnphY0p44CCCgogICAg6YCC6YWN6KeE5YiZKOmdouWQkeekvuWMuiBSU05BIOadg+mHjSzlpoIgYmFydW4yMTA0IOeahCBiZXN0X3Jlc25ldDM0X2ZvbGQwLnB0aCk6CiAgICAtIGNvbnYxLndlaWdodCDpgJrpgZPmlbDkuI3lkIzml7Y6cmVzaGFwZSttZWFuIOmAgumFjeWIsCBuZXQg55qEIGNvbnYxIOmAmumBk+aVsCjlpoIgMjTihpIzLAogICAgICBiYXJ1bjIxMDQg5pivIDggY2xpcCDDlyAzIOmAmumBk+eahCAyLjVEIOaooeWeiyk7CiAgICAtIGZjLiogLyBoZWFkLiogLyBjbGFzc2lmaWVyLiog5LiA5b6L5Yml56a7KOaIkeS7rOeahOaooeWei+S8muabv+aNouaIkCAxMiDlpLQpOwogICAg6L+U5ZueICjmmK/lkKbmiJDlip8sIOWRveS4reaPj+i/sCnjgIIKICAgICIiIgogICAgZm9yIHAsIGRlc2MgaW4gcGF0aHM6CiAgICAgICAgc2QgPSBfbG9hZF9zdGF0ZV9kaWN0X2Zyb21fZmlsZShwKQogICAgICAgIGlmIHNkIGlzIE5vbmU6CiAgICAgICAgICAgIGNvbnRpbnVlCiAgICAgICAgIyAxKSDpgILphY0gY29udjE66YCa6YGT5pWw5LiN5ZCM5YiZIHJlc2hhcGUrbWVhbijlpoIgMjQg6YCa6YGTIOKGkiAzIOmAmumBkykKICAgICAgICBpZiAiY29udjEud2VpZ2h0IiBpbiBzZDoKICAgICAgICAgICAgdyA9IHNkWyJjb252MS53ZWlnaHQiXQogICAgICAgICAgICB0YXJnZXQgPSBuZXQuY29udjEud2VpZ2h0LnNoYXBlWzFdCiAgICAgICAgICAgIGlmIHcuc2hhcGVbMV0gIT0gdGFyZ2V0IGFuZCB3LnNoYXBlWzFdICUgdGFyZ2V0ID09IDA6CiAgICAgICAgICAgICAgICBCLCBDLCBILCBXID0gdy5zaGFwZQogICAgICAgICAgICAgICAgdzIgPSB3LnJlc2hhcGUoQiwgdGFyZ2V0LCBDIC8vIHRhcmdldCwgSCwgVykubWVhbihkaW09MikKICAgICAgICAgICAgICAgIHNkWyJjb252MS53ZWlnaHQiXSA9IHcyCiAgICAgICAgICAgICAgICBwcmludChmIlvmnYPph41dIHtkZXNjfSBjb252MSDpgJrpgZMge0N94oaSe3RhcmdldH0g5bmz5Z2H6YCC6YWNIiwgZmx1c2g9VHJ1ZSkKICAgICAgICAgICAgZWxpZiB3LnNoYXBlWzFdICE9IHRhcmdldDoKICAgICAgICAgICAgICAgIHNkLnBvcCgiY29udjEud2VpZ2h0IikgICMg5peg5rOV6YCC6YWNLOS4ouW8gyjnlKjpmo/mnLrliJ3lp4vljJYpCiAgICAgICAgIyAyKSDliaXnprsgZmMvaGVhZC9jbGFzc2lmaWVyKOaooeWei+S8muabv+aNouaIkCAxMiDlpLQpCiAgICAgICAgZm9yIGsgaW4gbGlzdChzZC5rZXlzKCkpOgogICAgICAgICAgICBpZiBrLnN0YXJ0c3dpdGgoKCJmYy4iLCAiaGVhZC4iLCAiY2xhc3NpZmllci4iKSk6CiAgICAgICAgICAgICAgICBzZC5wb3AoaykKICAgICAgICB0cnk6CiAgICAgICAgICAgIG1pc3NpbmcsIHVuZXhwZWN0ZWQgPSBuZXQubG9hZF9zdGF0ZV9kaWN0KHNkLCBzdHJpY3Q9RmFsc2UpCiAgICAgICAgZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOgogICAgICAgICAgICBwcmludChmIlvmnYPph41dIHtkZXNjfSDkuI4gUmVzTmV0MzQg57uT5p6E5LiN5Yy56YWNOiB7ZX0iLCBmbHVzaD1UcnVlKQogICAgICAgICAgICBjb250aW51ZQogICAgICAgIGV4ZW1wdCA9IHtrIGZvciBrIGluIG1pc3NpbmcgaWYgay5zdGFydHN3aXRoKCgiY29udjEuIiwgImZjLiIpKX0KICAgICAgICBpZiBub3QgdW5leHBlY3RlZCBhbmQgbGVuKG1pc3NpbmcpID09IGxlbihleGVtcHQpOgogICAgICAgICAgICBwcmludChmIlvmnYPph41dIOemu+e6v+mihOiuree7g+WKoOi9veaIkOWKnzoge2Rlc2N9ICjopobnm5Yge2xlbihzZCl9IOS4quWPguaVsOW8oOmHjykiLCBmbHVzaD1UcnVlKQogICAgICAgICAgICByZXR1cm4gVHJ1ZSwgZGVzYwogICAgICAgIHByaW50KGYiW+adg+mHjV0ge2Rlc2N9IOe7k+aehOS4jeWMuemFjShtaXNzaW5nIHtsZW4obWlzc2luZykgLSBsZW4oZXhlbXB0KX0g5Liq6Z2e6LGB5YWNIGtleSwgIgogICAgICAgICAgICAgIGYidW5leHBlY3RlZCB7bGVuKHVuZXhwZWN0ZWQpfSks5bCd6K+V5LiL5LiA5LiqIiwgZmx1c2g9VHJ1ZSkKICAgIHJldHVybiBGYWxzZSwgIiIKCgpkZWYgX3NjYW5fcHNldWRvKGJhc2UsIGRlcHRoPTAsIG1heF9kZXB0aD0zKToKICAgICIiIumAkuW9kuWcqOaMgui9veebruW9leS4i+aJvui9r+agh+etviBDU1Yo6ZmQ5Yi25rex5bqmLOi3s+i/hyBESUNPTSDnm67lvZUp44CCCgogICAg6L+U5ZueIChEYXRhRnJhbWUg5oiWIE5vbmUsIOadpea6kOaPj+i/sCnjgILor4bliKvop4TliJk65ZCrIFN0dWR5SW5zdGFuY2VVSUQg5LiU6Iez5bCR5pyJ5LiA5LiqCiAgICBwc2V1ZG9fIOWJjee8gOWIlyjlpoIgcHNldWRvX0FDTCnjgILmib7kuI3liLDov5Tlm54gKE5vbmUsICIiKeOAggoKICAgIOivhuWIq+aWueW8j+WPjOmAmumBkzoKICAgIDEuIOaWh+S7tuWQjeeZveWQjeWNlShfUFNFVURPX0ZJTEVTKeW/q+mAn+WRveS4rTsKICAgIDIuICoq5oyJ5YaF5a656K+G5YirKio65Lu75oSPICouY3N2IOWPquimgeihqOWktOWQqyBTdHVkeUluc3RhbmNlVUlEICsgcHNldWRvXyog5YiX5Y2z5ZG95LitCiAgICAgICAo5LiN5L6d6LWW5paH5Lu25ZCNLOekvuWMuuaVsOaNrumbhuaUueWQjS/mjaLnu5PmnoTkuZ/og73miavliLAp44CCCiAgICAiIiIKICAgIGlmIGRlcHRoID4gbWF4X2RlcHRoIG9yIG5vdCBvcy5wYXRoLmlzZGlyKGJhc2UpOgogICAgICAgIHJldHVybiBOb25lLCAiIgogICAgdHJ5OgogICAgICAgIGVudHJpZXMgPSBzb3J0ZWQob3MubGlzdGRpcihiYXNlKSkKICAgIGV4Y2VwdCBPU0Vycm9yOgogICAgICAgIHJldHVybiBOb25lLCAiIgogICAgIyDpgJrpgZMgMTrmlofku7blkI3nmb3lkI3ljZUo5ZCR5ZCO5YW85a65LOivu+WFqOmHjykKICAgIGZvciBmbiBpbiBfUFNFVURPX0ZJTEVTOgogICAgICAgIHAgPSBvcy5wYXRoLmpvaW4oYmFzZSwgZm4pCiAgICAgICAgaWYgb3MucGF0aC5leGlzdHMocCkgYW5kIG9zLnBhdGguaXNmaWxlKHApOgogICAgICAgICAgICB0cnk6CiAgICAgICAgICAgICAgICBjYW5kID0gcGQucmVhZF9jc3YocCkKICAgICAgICAgICAgZXhjZXB0IEV4Y2VwdGlvbjoKICAgICAgICAgICAgICAgIGNvbnRpbnVlCiAgICAgICAgICAgIGlmICJTdHVkeUluc3RhbmNlVUlEIiBpbiBjYW5kLmNvbHVtbnMgYW5kIGFueSgKICAgICAgICAgICAgICAgICAgICBjLnN0YXJ0c3dpdGgoInBzZXVkb18iKSBmb3IgYyBpbiBjYW5kLmNvbHVtbnMpOgogICAgICAgICAgICAgICAgcmV0dXJuIGNhbmQsIG9zLnBhdGgucmVscGF0aChwLCAiL2thZ2dsZS9pbnB1dCIpCiAgICAjIOmAmumBkyAyOuaMieWGheWuueivhuWIqyjlj6ror7vooajlpLQgbnJvd3M9MyDliKTmlq0s5ZG95Lit5YaN5YWo6K+7KQogICAgZm9yIGZuIGluIGVudHJpZXM6CiAgICAgICAgaWYgbm90IGZuLmxvd2VyKCkuZW5kc3dpdGgoIi5jc3YiKToKICAgICAgICAgICAgY29udGludWUKICAgICAgICBwID0gb3MucGF0aC5qb2luKGJhc2UsIGZuKQogICAgICAgIGlmIG5vdCBvcy5wYXRoLmlzZmlsZShwKToKICAgICAgICAgICAgY29udGludWUKICAgICAgICB0cnk6CiAgICAgICAgICAgIGhlYWQgPSBwZC5yZWFkX2NzdihwLCBucm93cz0zKQogICAgICAgIGV4Y2VwdCBFeGNlcHRpb246CiAgICAgICAgICAgIGNvbnRpbnVlCiAgICAgICAgaWYgIlN0dWR5SW5zdGFuY2VVSUQiIGluIGhlYWQuY29sdW1ucyBhbmQgYW55KAogICAgICAgICAgICAgICAgYy5zdGFydHN3aXRoKCJwc2V1ZG9fIikgZm9yIGMgaW4gaGVhZC5jb2x1bW5zKToKICAgICAgICAgICAgdHJ5OgogICAgICAgICAgICAgICAgY2FuZCA9IHBkLnJlYWRfY3N2KHApCiAgICAgICAgICAgICAgICByZXR1cm4gY2FuZCwgb3MucGF0aC5yZWxwYXRoKHAsICIva2FnZ2xlL2lucHV0IikKICAgICAgICAgICAgZXhjZXB0IEV4Y2VwdGlvbjoKICAgICAgICAgICAgICAgIGNvbnRpbnVlCiAgICBmb3Igc3ViIGluIGVudHJpZXM6CiAgICAgICAgaWYgc3ViIGluIF9TS0lQX0RJUlM6CiAgICAgICAgICAgIGNvbnRpbnVlCiAgICAgICAgY2FuZCwgc3JjID0gX3NjYW5fcHNldWRvKG9zLnBhdGguam9pbihiYXNlLCBzdWIpLCBkZXB0aCArIDEsIG1heF9kZXB0aCkKICAgICAgICBpZiBjYW5kIGlzIG5vdCBOb25lOgogICAgICAgICAgICByZXR1cm4gY2FuZCwgc3JjCiAgICByZXR1cm4gTm9uZSwgIiIKCgpkZWYgZmluZF9wc2V1ZG9fZGF0YXNldCgpOgogICAgIiIi5ZyoIC9rYWdnbGUvaW5wdXQg5LiL6YCS5b2S5omr5o+P56S+5Yy66L2v5qCH562+5pWw5o2u6ZuGKExMTSDku47miqXlkYrmj5Dlj5bnmoTkvKrmoIfnrb4p44CCCgogICAg5YW85a655Y2V5bGCKC9rYWdnbGUvaW5wdXQvPHNsdWc+LynkuI7lpJrlsYIoL2thZ2dsZS9pbnB1dC9kYXRhc2V0cy88c2x1Zz4vKeaMgui9veOAggogICAg6L+U5ZueIChEYXRhRnJhbWUg5oiWIE5vbmUsIOadpea6kOaPj+i/sCk75om+5LiN5Yiw6L+U5ZueIChOb25lLCAiIinjgIIKICAgICIiIgogICAgaWYgbm90IG9zLnBhdGguaXNkaXIoIi9rYWdnbGUvaW5wdXQiKToKICAgICAgICByZXR1cm4gTm9uZSwgIiIKICAgIHJldHVybiBfc2Nhbl9wc2V1ZG8oIi9rYWdnbGUvaW5wdXQiKQoKCmRlZiBsb2FkX2xhYmVscyhyb290LCBwc2V1ZG9fY29uZj0wLjAsIHVzZV9yZXBvcnRfbGFiZWxzPVRydWUpOgogICAgIiIi6L+U5ZueIHRyYWluIHN0dWR5IOe6p+agh+etviBEYXRhRnJhbWUo6KGMPVN0dWR5SW5zdGFuY2VVSUQsIOWIlz1MQUJFTFMsIOWIhuaVsC9OYU4p44CCCgogICAg5qCH562+5p2l5rqQ5LyY5YWI57qnKDIwMjYtMDktMDYg6LW3O+aXp+eahCLnpL7ljLrova/moIfnrb7mlbDmja7pm4Yi5pa55qGI5bey6K+B5Lyq5byD55So4oCU4oCUCiAgICBiYXJ1bjIxMDQg55qEIHBzZXVkb18qIDk4LjclIOaYr+Wtl+mdoiAwLjUg5q275YC844CB6Zu25aKe6YeP5L+h5oGvLOaYryBsb3NzIOaBkiAwLjY5MwogICAg55qE55yf5qC55ZugKToKICAgIDEuIOWumOaWuSB0cmFpbi5jc3Yg5qCH5rOoKDAvMSzku4UgNTgvNDQwNyDkvospOwogICAgMi4g5YaF572u5oql5ZGK6KeE5YiZ5oq95Y+W5ZmoIHJzbmFfcmVwb3J0X2xhYmVscyjnp7vmpI3oh6ogcnNuYS1rbmVlLWJhc2VsaW5lLXYxLAogICAgICAg5aSa6K+t6KiAL+aMieWPpeWQpuWumuaegeaApy/kuKXph43luqbliIbnuqcpOuWvueavj+S7veaUvuWwhOaKpeWRiuS6p+WHuiAxMiDnl4XngbYgc29mdCDliIbmlbAKICAgICAgICjpmLPmgKcgMC43Mn4wLjk1IC8g6Zi05oCnIDAuMDR+MC4yMCAvIOaXoOivgeaNrj1OYU4pOwogICAgICAg5a6Y5pa557y65aSx5qC855So5oq95Y+W5YiG5pWw5aGr5YWFLOaXoOivgeaNruagvOS/neaMgSBOYU4o5LiN6L+b5o2f5aSxLOeUsSB2YWxpZCDmjqnnoIHmjpLpmaQp44CCCiAgICAiIiIKICAgIHRyYWluID0gcGQucmVhZF9jc3Yob3MucGF0aC5qb2luKHJvb3QsICJ0cmFpbi5jc3YiKSkKICAgIGRmID0gdHJhaW5bWyJTdHVkeUluc3RhbmNlVUlEIl0gKyBMQUJFTFNdLmNvcHkoKQogICAgb2ZmaWNpYWxfY250ID0ge2M6IGludChkZltjXS5ub3RuYSgpLnN1bSgpKSBmb3IgYyBpbiBMQUJFTFN9CgogICAgaWYgbm90IHVzZV9yZXBvcnRfbGFiZWxzOgogICAgICAgIHByaW50KCJb5qCH562+XSAtLW5vLXJlcG9ydC1sYWJlbHM65LuF5a6Y5pa55qCH5rOo5Y+v55SoIikKICAgICAgICByZXR1cm4gZGYKICAgIGlmIG5vdCBIQVNfUkw6CiAgICAgICAgcHJpbnQoIlvmoIfnrb5dIOacquaJvuWIsCByc25hX3JlcG9ydF9sYWJlbHMucHko6ZyA5LiOIHJzbmFfdjMucHkg5ZCM55uu5b2VKSwiCiAgICAgICAgICAgICAgIuS7heWumOaWueagh+azqOWPr+eUqCIpCiAgICAgICAgcmV0dXJuIGRmCiAgICBpZiAiUmVwb3J0IiBub3QgaW4gdHJhaW4uY29sdW1uczoKICAgICAgICBwcmludCgiW+agh+etvl0gdHJhaW4uY3N2IOaXoCBSZXBvcnQg5YiXLOS7heWumOaWueagh+azqOWPr+eUqCIpCiAgICAgICAgcmV0dXJuIGRmCgogICAgcHNldWRvID0gUkwuYnVpbGRfcHNldWRvX3RhYmxlKHRyYWluLCB2ZXJib3NlPVRydWUpCiAgICBwc2V1ZG8gPSBwc2V1ZG8uc2V0X2luZGV4KCJTdHVkeUluc3RhbmNlVUlEIikKICAgIHByaW50KGYiW+agh+etvl0g5aGr5YWF57uf6K6hKHtsZW4oZGYpfSDkuKogc3R1ZHkpOiIpCiAgICBmb3IgYyBpbiBMQUJFTFM6CiAgICAgICAgbWFzayA9IGRmW2NdLmlzbmEoKS52YWx1ZXMKICAgICAgICBpZiBub3QgbWFzay5hbnkoKToKICAgICAgICAgICAgcHJpbnQoZiIgIHtjOjE4c30g5a6Y5pa55YWo6YePLOaXoOmcgOWhq+WFhSIpCiAgICAgICAgICAgIGNvbnRpbnVlCiAgICAgICAgdWlkcyA9IGRmLmxvY1ttYXNrLCAiU3R1ZHlJbnN0YW5jZVVJRCJdCiAgICAgICAgdmFscyA9IHBzZXVkb1sicHNldWRvXyIgKyBjXS5yZWluZGV4KHVpZHMpLnZhbHVlcwogICAgICAgIG5fZmlsbCA9IGludChwZC5ub3RuYSh2YWxzKS5zdW0oKSkKICAgICAgICBkZi5sb2NbbWFzaywgY10gPSB2YWxzCiAgICAgICAgcHJpbnQoZiIgIHtjOjE4c30g5a6Y5pa5IHtvZmZpY2lhbF9jbnRbY106NGR9ICsg5oql5ZGK5oq95Y+W5aGr5YWFIHtuX2ZpbGw6NGR9IgogICAgICAgICAgICAgIGYiID0g5pyJ5pWIIHtpbnQoZGZbY10ubm90bmEoKS5zdW0oKSk6NWR9IikKICAgIHJldHVybiBkZgoKCl9EQ01fTUlTU19QUklOVEVEID0gW0ZhbHNlXSAgIyDlj6rmiZPljbDkuIDmrKEgRElDT00g5pyq5ZG95Lit6K+K5patLOmBv+WFjSAyIOS4hyBzZXJpZXMg5Yi35bGPCgoKZGVmIHJlYWRfZGljb21fc2xpY2VzKGRjbV9kaXIsIHNlcmllc191aWQsIHN0dWR5X3VpZD1Ob25lKToKICAgICIiIuivu+WPluS4gOS4qiBzZXJpZXMg55qE5omA5pyJ5YiH54mHLOaMieeJqeeQhuS9jee9ruaOkuW6jyzov5Tlm54gWyhwYXRoLCB6KV3jgIIKCiAgICDot6/lvoTlhbzlrrnlpJrnp40gS2FnZ2xlIOW4g+WxgCjlrp7mtYsgUlNOQSAyMDI2IOS4uuS4pOWxgik6CiAgICAgIDEpIDxkY21fZGlyPi88c2VyaWVzX3VpZD4vICAgICAgICAgICAgICAgICjml6flgYforr46c2VyaWVzIOebruW9leebtOaOpeaMgikKICAgICAgMikgPGRjbV9kaXI+LzxzdHVkeV91aWQ+LzxzZXJpZXNfdWlkPi8gICAgKFJTTkEg5qCH5YeGOnN0dWR5IOebruW9leS4i+WGjeaMgiBzZXJpZXMpCiAgICDmib7kuI3liLDmiJbor7vkuI3liLDov5Tlm54gW13jgIIKICAgICIiIgogICAgY2FuZHMgPSBbb3MucGF0aC5qb2luKGRjbV9kaXIsIHNlcmllc191aWQpXQogICAgaWYgc3R1ZHlfdWlkOgogICAgICAgIGNhbmRzLmFwcGVuZChvcy5wYXRoLmpvaW4oZGNtX2Rpciwgc3R1ZHlfdWlkLCBzZXJpZXNfdWlkKSkKICAgIHNkaXIgPSBuZXh0KChjIGZvciBjIGluIGNhbmRzIGlmIG9zLnBhdGguaXNkaXIoYykpLCBOb25lKQogICAgaWYgc2RpciBpcyBOb25lOgogICAgICAgIGlmIG5vdCBfRENNX01JU1NfUFJJTlRFRFswXToKICAgICAgICAgICAgX0RDTV9NSVNTX1BSSU5URURbMF0gPSBUcnVlCiAgICAgICAgICAgIHByaW50KGYiW+iviuaWrS1ESUNPTV0g5om+5LiN5YiwIHNlcmllcyDnm67lvZUs5bCd6K+V6L+HOiB7Y2FuZHN9IiwgZmx1c2g9VHJ1ZSkKICAgICAgICAgICAgcHJpbnQoZiJb6K+K5patLURJQ09NXSB7ZGNtX2Rpcn0g5piv5ZCm5a2Y5ZyoOiB7b3MucGF0aC5pc2RpcihkY21fZGlyKX0iLCBmbHVzaD1UcnVlKQogICAgICAgICAgICB0cnk6CiAgICAgICAgICAgICAgICBpbm5lciA9IHNvcnRlZChvcy5saXN0ZGlyKGRjbV9kaXIpKVs6OF0gaWYgb3MucGF0aC5pc2RpcihkY21fZGlyKSBlbHNlIFtdCiAgICAgICAgICAgICAgICBwcmludChmIlvor4rmlq0tRElDT01dIHtkY21fZGlyfSDlrp7pmYXlhoXlrrnmoLfmnKw6IHtpbm5lcn0iLCBmbHVzaD1UcnVlKQogICAgICAgICAgICBleGNlcHQgT1NFcnJvcjoKICAgICAgICAgICAgICAgIHBhc3MKICAgICAgICByZXR1cm4gW10KICAgIGZpbGVzID0gW29zLnBhdGguam9pbihzZGlyLCBmKSBmb3IgZiBpbiBvcy5saXN0ZGlyKHNkaXIpIGlmIGYubG93ZXIoKS5lbmRzd2l0aCgiLmRjbSIpXQogICAgaWYgbm90IGZpbGVzOgogICAgICAgIGlmIG5vdCBfRENNX01JU1NfUFJJTlRFRFswXToKICAgICAgICAgICAgX0RDTV9NSVNTX1BSSU5URURbMF0gPSBUcnVlCiAgICAgICAgICAgIHByaW50KGYiW+iviuaWrS1ESUNPTV0g55uu5b2V5a2Y5Zyo5L2G5pegIC5kY20g5paH5Lu2OiB7c2Rpcn0iLCBmbHVzaD1UcnVlKQogICAgICAgICAgICBwcmludChmIlvor4rmlq0tRElDT01dIOebruW9leWGheWuueagt+acrDoge3NvcnRlZChvcy5saXN0ZGlyKHNkaXIpKVs6OF19IiwgZmx1c2g9VHJ1ZSkKICAgICAgICByZXR1cm4gW10KICAgIHJvd3MgPSBbXQogICAgZm9yIGYgaW4gZmlsZXM6CiAgICAgICAgdHJ5OgogICAgICAgICAgICBkID0gcHlkaWNvbS5kY21yZWFkKGYsIHN0b3BfYmVmb3JlX3BpeGVscz1GYWxzZSkKICAgICAgICAgICAgcG9zID0gZC5nZXQoIkltYWdlUG9zaXRpb25QYXRpZW50IikKICAgICAgICAgICAgeiA9IGZsb2F0KHBvc1syXSkgaWYgcG9zIGlzIG5vdCBOb25lIGFuZCBsZW4ocG9zKSA+PSAzIGVsc2UgTm9uZQogICAgICAgICAgICByb3dzLmFwcGVuZCgoZiwgeikpCiAgICAgICAgZXhjZXB0IEV4Y2VwdGlvbjoKICAgICAgICAgICAgY29udGludWUKICAgIHJvd3Muc29ydChrZXk9bGFtYmRhIHI6IChyWzFdIGlzIE5vbmUsIHJbMV0gaWYgclsxXSBpcyBub3QgTm9uZSBlbHNlIDAuMCkpCiAgICByZXR1cm4gcm93cwoKCiMgLS0tLS0tLS0tLS0tLS0tLSBESUNPTSAtPiAyLjVEIGNsaXAg6aKE5aSE55CGIC0tLS0tLS0tLS0tLS0tLS0KCmRlZiB3aW5kb3dfYW5kX3Jlc2l6ZShkY20sIGltZ19zaXplPUlNR19TSVpFKToKICAgICIiIuWNleW8oOWIh+eJhzpSZXNjYWxlIOWQjueZvuWIhuS9jeeql+WPo+WMliAtPiBbMCwxXSAtPiByZXNpemUgMjI044CCIiIiCiAgICBhcnIgPSBkY20ucGl4ZWxfYXJyYXkuYXN0eXBlKG5wLmZsb2F0MzIpCiAgICBzbG9wZSA9IGZsb2F0KGRjbS5nZXQoIlJlc2NhbGVTbG9wZSIsIDEpKQogICAgaW50ZXIgPSBmbG9hdChkY20uZ2V0KCJSZXNjYWxlSW50ZXJjZXB0IiwgMCkpCiAgICBhcnIgPSBhcnIgKiBzbG9wZSArIGludGVyCiAgICBpZiBkY20uZ2V0KCJQaG90b21ldHJpY0ludGVycHJldGF0aW9uIikgPT0gIk1PTk9DSFJPTUUxIjoKICAgICAgICBhcnIgPSBhcnIubWF4KCkgLSBhcnIKICAgIGxvLCBoaSA9IG5wLnBlcmNlbnRpbGUoYXJyLCBbMSwgOTldKQogICAgYXJyID0gbnAuY2xpcCgoYXJyIC0gbG8pIC8gbWF4KGhpIC0gbG8sIDFlLTYpLCAwLCAxKQogICAgZnJvbSBQSUwgaW1wb3J0IEltYWdlCiAgICBpbWcgPSBJbWFnZS5mcm9tYXJyYXkoKGFyciAqIDI1NSkuYXN0eXBlKG5wLnVpbnQ4KSkucmVzaXplKChpbWdfc2l6ZSwgaW1nX3NpemUpLCBJbWFnZS5CSUxJTkVBUikKICAgIHJldHVybiBucC5hc2FycmF5KGltZywgZHR5cGU9bnAuZmxvYXQzMikgLyAyNTUuMAoKCmRlZiBtYWtlX2NsaXBzKHNlcmllc19yb3dzLCBuX2NsaXBzPTIsIGltZ19zaXplPUlNR19TSVpFKToKICAgICIiIuS7juaOkuW6j+WlveeahOWIh+eJh+WIl+ihqOeUn+aIkOiLpeW5siAzIOmAmumBkyBjbGlwKOebuOmCu+S4ieW8oCnjgIIiIiIKICAgIGNsaXBzID0gW10KICAgIHBhdGhzID0gW3JbMF0gZm9yIHIgaW4gc2VyaWVzX3Jvd3NdCiAgICBpZiBsZW4ocGF0aHMpIDwgQ0xJUDoKICAgICAgICByZXR1cm4gY2xpcHMKICAgIHN0ZXAgPSBtYXgoMSwgKGxlbihwYXRocykgLSAyKSAvLyBuX2NsaXBzKQogICAgZm9yIGMgaW4gcmFuZ2UoMSwgbGVuKHBhdGhzKSAtIDEsIHN0ZXApOgogICAgICAgIGlmIGxlbihjbGlwcykgPj0gbl9jbGlwczoKICAgICAgICAgICAgYnJlYWsKICAgICAgICBjaGFuID0gW10KICAgICAgICBvayA9IFRydWUKICAgICAgICBmb3IgayBpbiAoYyAtIDEsIGMsIGMgKyAxKToKICAgICAgICAgICAgdHJ5OgogICAgICAgICAgICAgICAgZGNtID0gcHlkaWNvbS5kY21yZWFkKHBhdGhzW2tdKQogICAgICAgICAgICAgICAgY2hhbi5hcHBlbmQod2luZG93X2FuZF9yZXNpemUoZGNtLCBpbWdfc2l6ZSkpCiAgICAgICAgICAgIGV4Y2VwdCBFeGNlcHRpb246CiAgICAgICAgICAgICAgICBvayA9IEZhbHNlCiAgICAgICAgICAgICAgICBicmVhawogICAgICAgIGlmIG9rOgogICAgICAgICAgICBjbGlwcy5hcHBlbmQobnAuc3RhY2soY2hhbiwgYXhpcz0wKSkgICMgKDMsIEgsIFcpCiAgICByZXR1cm4gY2xpcHMKCgppZiBIQVNfVE9SQ0g6CiAgICAjIC0tLS0tLS0tLS0tLS0tLS0g5pWw5o2u6ZuGKHYyOuaMieW5s+mdoui/h+a7pCBzZXJpZXMpIC0tLS0tLS0tLS0tLS0tLS0KCiAgICBjbGFzcyBLbmVlRGF0YXNldChEYXRhc2V0KToKICAgICAgICAiIiJzdHVkeSDnuqfmlbDmja7pm4Ys5Y+q5Y+W5oyH5a6aIEFuYXRvbWljYWxfUGxhbmUg55qEIHNlcmllcyzmi7zmiJAgKEMqMywgSCwgVynjgIIiIiIKCiAgICAgICAgZGVmIF9faW5pdF9fKHNlbGYsIHN0dWRpZXMsIGxhYmVsc19kZiwgZGNtX3Jvb3QsIHNlcmllc19kZiwgcGxhbmUsCiAgICAgICAgICAgICAgICAgICAgIGhhc190YXJnZXRzPVRydWUsIG5fY2xpcHM9Mik6CiAgICAgICAgICAgIHNlbGYuc3R1ZGllcyA9IHN0dWRpZXMKICAgICAgICAgICAgc2VsZi5sYWJlbHNfZGYgPSBsYWJlbHNfZGYKICAgICAgICAgICAgc2VsZi5kY21fcm9vdCA9IGRjbV9yb290CiAgICAgICAgICAgIHNlbGYuc2VyaWVzX2RmID0gc2VyaWVzX2RmCiAgICAgICAgICAgIHNlbGYucGxhbmUgPSBwbGFuZQogICAgICAgICAgICBzZWxmLmhhc190YXJnZXRzID0gaGFzX3RhcmdldHMKICAgICAgICAgICAgc2VsZi5uX2NsaXBzID0gbl9jbGlwcwogICAgICAgICAgICBzZWxmLmNhY2hlID0ge30gICMg5q+P5oqY54us56uL57yT5a2YOmZvbGQg57uT5p2f6ZqPIGRhdGFzZXQg6YeK5pS+LOmBv+WFjSA1IOaKmOe0r+enryBPT00KICAgICAgICAgICAgIyDor4rmlq3orqHmlbA66K+75YiwIGNsaXAg55qEIHN0dWR5IC8g56m6IHN0dWR5IC8g57Sv6K6hIGNsaXAg5pWwCiAgICAgICAgICAgIHNlbGYubl9oaXQgPSAwCiAgICAgICAgICAgIHNlbGYubl9lbXB0eSA9IDAKICAgICAgICAgICAgc2VsZi5uX2NsaXBzX3RvdGFsID0gMAoKICAgICAgICBkZWYgc3RhdHMoc2VsZik6CiAgICAgICAgICAgICIiIui/lOWbniAo6K+75YiwIGNsaXAg55qEIHN0dWR5IOaVsCwg56m6IHN0dWR5IOaVsCwg5bmz5Z2HIGNsaXAg5pWwKSzpmLLmraLpnZnpu5jnmb3orq3nu4PjgIIiIiIKICAgICAgICAgICAgdG90YWwgPSBzZWxmLm5faGl0ICsgc2VsZi5uX2VtcHR5CiAgICAgICAgICAgIGF2ZyA9IChzZWxmLm5fY2xpcHNfdG90YWwgLyBzZWxmLm5faGl0KSBpZiBzZWxmLm5faGl0IGVsc2UgMC4wCiAgICAgICAgICAgIHJldHVybiBzZWxmLm5faGl0LCBzZWxmLm5fZW1wdHksIGF2ZwoKICAgICAgICBkZWYgX2xvYWRfc3R1ZHkoc2VsZiwgdWlkKToKICAgICAgICAgICAga2V5ID0gKHVpZCwgc2VsZi5wbGFuZSkKICAgICAgICAgICAgaWYga2V5IGluIHNlbGYuY2FjaGU6CiAgICAgICAgICAgICAgICByZXR1cm4gc2VsZi5jYWNoZVtrZXldCiAgICAgICAgICAgIHNyb3dzID0gc2VsZi5zZXJpZXNfZGZbc2VsZi5zZXJpZXNfZGZbIlN0dWR5SW5zdGFuY2VVSUQiXSA9PSB1aWRdCiAgICAgICAgICAgIGlmICJBbmF0b21pY2FsX1BsYW5lIiBpbiBzcm93cy5jb2x1bW5zOgogICAgICAgICAgICAgICAgc3Jvd3MgPSBzcm93c1tzcm93c1siQW5hdG9taWNhbF9QbGFuZSJdID09IHNlbGYucGxhbmVdCiAgICAgICAgICAgICAgICBzcm93cyA9IHNyb3dzLnNvcnRfdmFsdWVzKCJGbHVpZF9TZW5zaXRpdmUiLCBraW5kPSJzdGFibGUiKS5kcm9wX2R1cGxpY2F0ZXMoCiAgICAgICAgICAgICAgICAgICAgc3Vic2V0PVsiRmx1aWRfU2Vuc2l0aXZlIl0pLmhlYWQoTUFYX1NFUklFUykKICAgICAgICAgICAgZWxzZToKICAgICAgICAgICAgICAgIHNyb3dzID0gc3Jvd3MuaGVhZChNQVhfU0VSSUVTKQogICAgICAgICAgICBjbGlwcyA9IFtdCiAgICAgICAgICAgIGZvciBfLCBzciBpbiBzcm93cy5pdGVycm93cygpOgogICAgICAgICAgICAgICAgc2lkID0gc3JbIlNlcmllc0luc3RhbmNlVUlEIl0KICAgICAgICAgICAgICAgIHJvd3MgPSByZWFkX2RpY29tX3NsaWNlcyhzZWxmLmRjbV9yb290LCBzaWQsIHN0dWR5X3VpZD11aWQpCiAgICAgICAgICAgICAgICBjbGlwcy5leHRlbmQobWFrZV9jbGlwcyhyb3dzLCBuX2NsaXBzPXNlbGYubl9jbGlwcykpCiAgICAgICAgICAgIHNlbGYuY2FjaGVbdWlkXSA9IGNsaXBzCiAgICAgICAgICAgICMg5LuF6aaW5qyh5Yqg6L296K6h5pWwKOe8k+WtmOWRveS4reS4jeWGjee0r+WKoCzpgb/lhY3lpJogZXBvY2gg6YeN5aSNKQogICAgICAgICAgICBpZiBjbGlwczoKICAgICAgICAgICAgICAgIHNlbGYubl9oaXQgKz0gMQogICAgICAgICAgICAgICAgc2VsZi5uX2NsaXBzX3RvdGFsICs9IGxlbihjbGlwcykKICAgICAgICAgICAgZWxzZToKICAgICAgICAgICAgICAgIHNlbGYubl9lbXB0eSArPSAxCiAgICAgICAgICAgIHJldHVybiBjbGlwcwoKICAgICAgICBkZWYgX19sZW5fXyhzZWxmKToKICAgICAgICAgICAgcmV0dXJuIGxlbihzZWxmLnN0dWRpZXMpCgogICAgICAgIGRlZiBfX2dldGl0ZW1fXyhzZWxmLCBpKToKICAgICAgICAgICAgdWlkID0gc2VsZi5zdHVkaWVzW2ldCiAgICAgICAgICAgIGNsaXBzID0gc2VsZi5fbG9hZF9zdHVkeSh1aWQpICAjIOWRveS4rS/nqbrorqHmlbDlnKggX2xvYWRfc3R1ZHkg6aaW5qyh5Yqg6L295pe25a6M5oiQCiAgICAgICAgICAgIGluX2NoID0gc2VsZi5uX2NsaXBzICogQ0xJUCAgIyDovpPlhaXpgJrpgZPmlbA6Y2xpcCDmlbAgw5cg5q+PIGNsaXAgMyDliIfniYcKICAgICAgICAgICAgaWYgbm90IGNsaXBzOgogICAgICAgICAgICAgICAgeCA9IG5wLnplcm9zKChpbl9jaCwgSU1HX1NJWkUsIElNR19TSVpFKSwgZHR5cGU9bnAuZmxvYXQzMikKICAgICAgICAgICAgZWxzZToKICAgICAgICAgICAgICAgIHggPSBucC5jb25jYXRlbmF0ZShjbGlwc1s6IHNlbGYubl9jbGlwc10sIGF4aXM9MCkgICMgKGsqMywgSCwgVykKICAgICAgICAgICAgICAgIHBhZCA9IGluX2NoIC0geC5zaGFwZVswXQogICAgICAgICAgICAgICAgaWYgcGFkID4gMDoKICAgICAgICAgICAgICAgICAgICB4ID0gbnAuY29uY2F0ZW5hdGUoW3gsIG5wLnplcm9zKChwYWQsIElNR19TSVpFLCBJTUdfU0laRSksIGR0eXBlPW5wLmZsb2F0MzIpXSkKICAgICAgICAgICAgICAgIGVsaWYgcGFkIDwgMDoKICAgICAgICAgICAgICAgICAgICB4ID0geFs6IGluX2NoXQogICAgICAgICAgICB4ID0gdG9yY2gudGVuc29yKHgsIGR0eXBlPXRvcmNoLmZsb2F0MzIpCiAgICAgICAgICAgIHkgPSB0b3JjaC56ZXJvcyhsZW4oTEFCRUxTKSwgZHR5cGU9dG9yY2guZmxvYXQzMikKICAgICAgICAgICAgdmFsaWQgPSB0b3JjaC56ZXJvcyhsZW4oTEFCRUxTKSwgZHR5cGU9dG9yY2guZmxvYXQzMikKICAgICAgICAgICAgaWYgc2VsZi5oYXNfdGFyZ2V0czoKICAgICAgICAgICAgICAgIHJvdyA9IHNlbGYubGFiZWxzX2RmW3NlbGYubGFiZWxzX2RmWyJTdHVkeUluc3RhbmNlVUlEIl0gPT0gdWlkXQogICAgICAgICAgICAgICAgaWYgbGVuKHJvdyk6CiAgICAgICAgICAgICAgICAgICAgZm9yIGosIGMgaW4gZW51bWVyYXRlKExBQkVMUyk6CiAgICAgICAgICAgICAgICAgICAgICAgIHYgPSByb3cuaWxvY1swXVtjXQogICAgICAgICAgICAgICAgICAgICAgICBpZiBwZC5ub3RuYSh2KToKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHlbal0gPSBmbG9hdCh2KQogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsaWRbal0gPSAxLjAKICAgICAgICAgICAgcmV0dXJuIHgsIHksIHZhbGlkCgoKICAgICMgLS0tLS0tLS0tLS0tLS0tLSDmqKHlnosgLS0tLS0tLS0tLS0tLS0tLQoKICAgIF9QUkVUUkFJTkVEX1RSSUVEID0gW0ZhbHNlXSAgIyDmqKHlnZfnuqfmoIflv5c65LiL6L295aSx6LSl6L+H5LiA5qyh5bCx5LiN5YaN5Y+N5aSN6YeN6K+VCgoKICAgIGRlZiBfYnVpbGRfcmVzbmV0MzQodXNlX3ByZXRyYWluZWQ9RmFsc2UsIG9mZmxpbmVfcGF0aHM9Tm9uZSk6CiAgICAgICAgIiIi5p6E6YCgIFJlc05ldDM0IOW5tuWKoOi9vSBJbWFnZU5ldCDpooTorq3nu4PmnYPph43jgIIKCiAgICAgICAg5p2D6YeN5p2l5rqQ5LyY5YWI57qnOgogICAgICAgIDEuIG9mZmxpbmVfcGF0aHM65oyC6L2955qE56a757q/5p2D6YeN5paH5Lu2KOaJq+aPjyAva2FnZ2xlL2lucHV0IOW+l+WIsCzml6DpnIDogZTnvZEpOwogICAgICAgIDIuIHVzZV9wcmV0cmFpbmVkPVRydWU66IGU572R5LiL6L29IHRvcmNodmlzaW9uIOadg+mHjSjluKbph43or5Us5aSx6LSl5Zue6YCA6ZqP5py6KTsKICAgICAgICAzLiDlkKbliJnpmo/mnLrliJ3lp4vljJbjgIIKICAgICAgICDmiJDlip/liqDovb3lkI7mnYPph43nlLEgdG9yY2gg57yT5a2YLOWQjue7rSBmb2xkIOenkuWKoOi9veOAggogICAgICAgICIiIgogICAgICAgIG5ldCA9IHR2bS5yZXNuZXQzNCh3ZWlnaHRzPU5vbmUpCiAgICAgICAgaWYgb2ZmbGluZV9wYXRoczoKICAgICAgICAgICAgb2ssIGRlc2MgPSBfdHJ5X2xvYWRfb2ZmbGluZShuZXQsIG9mZmxpbmVfcGF0aHMpCiAgICAgICAgICAgIGlmIG9rOgogICAgICAgICAgICAgICAgcmV0dXJuIG5ldAogICAgICAgICAgICBwcmludChmIlvmnYPph41dIOemu+e6v+WAmemAieWdh+S4jeWMuemFjSh7ZGVzY30pLOWbnumAgOWIsOmaj+acui/ogZTnvZHot6/lvoQiLCBmbHVzaD1UcnVlKQogICAgICAgIGlmIG5vdCB1c2VfcHJldHJhaW5lZDoKICAgICAgICAgICAgcHJpbnQoIlvmnYPph41dIOacquW8gOWQryAtLXByZXRyYWluZWQg5LiU5peg56a757q/5p2D6YeNLOS9v+eUqOmaj+acuuWIneWni+WMliIKICAgICAgICAgICAgICAgICAgIijkuI3ogZTnvZE75aaC6ZyA6aKE6K6t57uD6K+35YqgIC0tcHJldHJhaW5lZCDlubblvIDlkK8gSW50ZXJuZXQsIgogICAgICAgICAgICAgICAgICAi5oiW5oyC6L2956a757q/5p2D6YeN5pWw5o2u6ZuGKSIsIGZsdXNoPVRydWUpCiAgICAgICAgICAgIHJldHVybiBuZXQKICAgICAgICBpZiBfUFJFVFJBSU5FRF9UUklFRFswXToKICAgICAgICAgICAgcmV0dXJuIG5ldCAgIyDkuYvliY3lt7Lnoa7orqTkuIvovb3kuI3kuoYs55u05o6l6ZqP5py6CiAgICAgICAgZm9yIGF0dGVtcHQgaW4gcmFuZ2UoMSwgNCk6CiAgICAgICAgICAgIHRyeToKICAgICAgICAgICAgICAgIG5ldCA9IHR2bS5yZXNuZXQzNCh3ZWlnaHRzPXR2bS5SZXNOZXQzNF9XZWlnaHRzLklNQUdFTkVUMUtfVjEKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiBoYXNhdHRyKHR2bSwgIlJlc05ldDM0X1dlaWdodHMiKSBlbHNlIE5vbmUpCiAgICAgICAgICAgICAgICByZXR1cm4gbmV0CiAgICAgICAgICAgIGV4Y2VwdCBFeGNlcHRpb24gYXMgZToKICAgICAgICAgICAgICAgIHByaW50KGYiW+adg+mHjV0gUmVzTmV0MzQg6aKE6K6t57uD5LiL6L295aSx6LSlKOesrCB7YXR0ZW1wdH0vMyDmrKEpOiB7ZX0iLCBmbHVzaD1UcnVlKQogICAgICAgICAgICAgICAgdGltZS5zbGVlcCg1KQogICAgICAgIF9QUkVUUkFJTkVEX1RSSUVEWzBdID0gVHJ1ZQogICAgICAgIHByaW50KCJb5p2D6YeNXSAzIOasoeWdh+Wksei0pSzmlLnnlKjpmo/mnLrliJ3lp4vljJYo57K+5bqm5Lya5piO5pi+5LiL6ZmNO+W7uuiurumHjeivleaIluaMgui9vemihOiuree7g+adg+mHjeaVsOaNrumbhikiLCBmbHVzaD1UcnVlKQogICAgICAgIHJldHVybiB0dm0ucmVzbmV0MzQod2VpZ2h0cz1Ob25lKQoKCiAgICBjbGFzcyBLbmVlTW9kZWwobm4uTW9kdWxlKToKICAgICAgICAiIiJSZXNOZXQzNCDlhbHkuqsgYmFja2JvbmUgKyDlhajlsYDmsaDljJYgKyAxMiBzaWdtb2lkIOWktCjmr4/kuKrlubPpnaLkuIDkuKrlrp7kvosp44CCIiIiCgogICAgICAgIGRlZiBfX2luaXRfXyhzZWxmLCBudW1fbGFiZWxzPWxlbihMQUJFTFMpLCBjaGFubmVscz1DTElQLCBwcmV0cmFpbmVkPUZhbHNlLCBvZmZsaW5lX3BhdGhzPU5vbmUpOgogICAgICAgICAgICBzdXBlcigpLl9faW5pdF9fKCkKICAgICAgICAgICAgaWYgSEFTX1RWOgogICAgICAgICAgICAgICAgc2VsZi5iYWNrYm9uZSA9IF9idWlsZF9yZXNuZXQzNCh1c2VfcHJldHJhaW5lZD1wcmV0cmFpbmVkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvZmZsaW5lX3BhdGhzPW9mZmxpbmVfcGF0aHMpCiAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICByYWlzZSBSdW50aW1lRXJyb3IoIumcgOimgSB0b3JjaHZpc2lvbijor7flnKggS2FnZ2xlIE5vdGVib29rIEdQVSDnjq/looPov5DooYwpIikKICAgICAgICAgICAgY29udjFfdyA9IHNlbGYuYmFja2JvbmUuY29udjEud2VpZ2h0ICAjIOS/neeVmemihOiuree7gyBjb252MSDmnYPph40KICAgICAgICAgICAgc2VsZi5iYWNrYm9uZS5jb252MSA9IG5uLkNvbnYyZChjaGFubmVscywgNjQsIGtlcm5lbF9zaXplPTcsIHN0cmlkZT0yLCBwYWRkaW5nPTMsIGJpYXM9RmFsc2UpCiAgICAgICAgICAgIGlmIGNvbnYxX3cuc2hhcGUgPT0gc2VsZi5iYWNrYm9uZS5jb252MS53ZWlnaHQuc2hhcGU6ICAjIGNoYW5uZWxzPT0zIOaXtuebtOaOpeayv+eUqAogICAgICAgICAgICAgICAgc2VsZi5iYWNrYm9uZS5jb252MS53ZWlnaHQuZGF0YS5jb3B5Xyhjb252MV93LmRhdGEpCiAgICAgICAgICAgIGVsaWYgY2hhbm5lbHMgJSAzID09IDAgYW5kIGNvbnYxX3cuc2hhcGVbMV0gPT0gMzoKICAgICAgICAgICAgICAgICMgMi41RCDpgJrpgZPmianlsZU65oqKIDMg6YCa6YGT6aKE6K6t57uD5p2D6YeN5aSN5Yi2IG5fY2xpcHMg5Lu9KOW4uOingeWBmuazlSkKICAgICAgICAgICAgICAgIHJlcCA9IGNoYW5uZWxzIC8vIDMKICAgICAgICAgICAgICAgIHNlbGYuYmFja2JvbmUuY29udjEud2VpZ2h0LmRhdGEuY29weV8oY29udjFfdy5yZXBlYXQoMSwgcmVwLCAxLCAxKSkKICAgICAgICAgICAgICAgIHByaW50KGYiW+adg+mHjV0gY29udjEg6aKE6K6t57uD5p2D6YeN5aSN5Yi2IHtyZXB9IOS7veaJqeWxleWIsCB7Y2hhbm5lbHN9IOmAmumBkyIsIGZsdXNoPVRydWUpCiAgICAgICAgICAgIHNlbGYuYmFja2JvbmUuZmMgPSBubi5JZGVudGl0eSgpCiAgICAgICAgICAgIHNlbGYuaGVhZCA9IG5uLkxpbmVhcig1MTIsIG51bV9sYWJlbHMpCgogICAgICAgIGRlZiBmb3J3YXJkKHNlbGYsIHgpOgogICAgICAgICAgICBmZWF0ID0gc2VsZi5iYWNrYm9uZSh4KSAgIyAoQiwgNTEyKQogICAgICAgICAgICByZXR1cm4gc2VsZi5oZWFkKGZlYXQpICAgIyBsb2dpdHMgKEIsIDEyKQoKCgojIC0tLS0tLS0tLS0tLS0tLS0g6K6t57uDIC8g6aqM6K+BIC0tLS0tLS0tLS0tLS0tLS0KCmRlZiB0cmFpbl9lcG9jaChtb2RlbCwgbG9hZGVyLCBvcHQsIGNyaXQsIGRldmljZSk6CiAgICBtb2RlbC50cmFpbigpCiAgICB0b3QsIGNudCA9IDAuMCwgMAogICAgZm9yIHgsIHksIHZhbGlkIGluIGxvYWRlcjoKICAgICAgICB4LCB5LCB2YWxpZCA9IHgudG8oZGV2aWNlKSwgeS50byhkZXZpY2UpLCB2YWxpZC50byhkZXZpY2UpCiAgICAgICAgb3B0Lnplcm9fZ3JhZCgpCiAgICAgICAgb3V0ID0gbW9kZWwoeCkKICAgICAgICBpZiB2YWxpZC5zdW0oKSA9PSAwOgogICAgICAgICAgICBjb250aW51ZQogICAgICAgIGxvc3MgPSAoY3JpdChvdXQsIHkpICogdmFsaWQpLnN1bSgpIC8gdmFsaWQuc3VtKCkKICAgICAgICBsb3NzLmJhY2t3YXJkKCkKICAgICAgICBvcHQuc3RlcCgpCiAgICAgICAgdG90ICs9IGxvc3MuaXRlbSgpICogbGVuKHgpCiAgICAgICAgY250ICs9IGxlbih4KQogICAgcmV0dXJuIHRvdCAvIG1heChjbnQsIDEpCgoKZGVmIHByZWRpY3QobW9kZWwsIGxvYWRlciwgZGV2aWNlKToKICAgIG1vZGVsLmV2YWwoKQogICAgcm93cyA9IFtdCiAgICB3aXRoIHRvcmNoLm5vX2dyYWQoKToKICAgICAgICBmb3IgeCwgXywgXyBpbiBsb2FkZXI6CiAgICAgICAgICAgIHggPSB4LnRvKGRldmljZSkKICAgICAgICAgICAgb3V0ID0gdG9yY2guc2lnbW9pZChtb2RlbCh4KSkKICAgICAgICAgICAgIyAuY3B1KCkudG9saXN0KCkg6ICM6Z2eIC5jcHUoKS5udW1weSgpOnRvcmNoIDIuMi4wK2N1MTE4IOe8luS6jiBudW1weTEueCwKICAgICAgICAgICAgIyDlnKggS2FnZ2xlIG51bXB5Mi4wLjIg5LiLIHRvcmNo4oaSbnVtcHkgaW50ZXJvcCDltKk7dG9saXN0IOe6ryBDKysg6Lev5b6E5a6J5YWo44CCCiAgICAgICAgICAgIHJvd3MuZXh0ZW5kKG91dC5jcHUoKS50b2xpc3QoKSkKICAgIHJldHVybiBucC5hc2FycmF5KHJvd3MsIGR0eXBlPW5wLmZsb2F0MzIpIGlmIHJvd3MgZWxzZSBucC56ZXJvcygoMCwgbGVuKExBQkVMUykpLCBkdHlwZT1ucC5mbG9hdDMyKQoKCmRlZiBydW5fZm9sZChtb2RlbCwgdHJhaW5fZHMsIHZhbF9kcywgZGV2aWNlLCBhcmdzKToKICAgIHRyYWluX2xvYWRlciA9IERhdGFMb2FkZXIodHJhaW5fZHMsIGJhdGNoX3NpemU9YXJncy5iYXRjaCwgc2h1ZmZsZT1UcnVlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBudW1fd29ya2Vycz1hcmdzLndvcmtlcnMsIGRyb3BfbGFzdD1GYWxzZSkKICAgIHZhbF9sb2FkZXIgPSBEYXRhTG9hZGVyKHZhbF9kcywgYmF0Y2hfc2l6ZT1hcmdzLmJhdGNoLCBzaHVmZmxlPUZhbHNlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgbnVtX3dvcmtlcnM9YXJncy53b3JrZXJzLCBkcm9wX2xhc3Q9RmFsc2UpCiAgICBvcHQgPSBBZGFtVyhtb2RlbC5wYXJhbWV0ZXJzKCksIGxyPWFyZ3MubHIsIHdlaWdodF9kZWNheT0xZS00KQogICAgc2NoZWQgPSBDb3NpbmVBbm5lYWxpbmdMUihvcHQsIFRfbWF4PWFyZ3MuZXBvY2hzKQogICAgY3JpdCA9IG5uLkJDRVdpdGhMb2dpdHNMb3NzKHJlZHVjdGlvbj0ibm9uZSIpCiAgICBmb3IgZXAgaW4gcmFuZ2UoYXJncy5lcG9jaHMpOgogICAgICAgIHQwID0gdGltZS50aW1lKCkKICAgICAgICBsb3NzID0gdHJhaW5fZXBvY2gobW9kZWwsIHRyYWluX2xvYWRlciwgb3B0LCBjcml0LCBkZXZpY2UpCiAgICAgICAgc2NoZWQuc3RlcCgpCiAgICAgICAgaWYgYXJncy52ZXJib3NlOgogICAgICAgICAgICBwcmludChmIiAgZXBvY2gge2VwICsgMX0ve2FyZ3MuZXBvY2hzfSBsb3NzIHtsb3NzOi40Zn0gKHt0aW1lLnRpbWUoKSAtIHQwOi4wZn1zKSIsIGZsdXNoPVRydWUpCiAgICB2YWxfcHJlZCA9IHByZWRpY3QobW9kZWwsIHZhbF9sb2FkZXIsIGRldmljZSkKICAgICMgRElDT00g5ZG95Lit6K+K5patOuiuree7gyvpqozor4Hlt7Lov63ku6Plrozmr5Us5q2k5pe26K6h5pWw5omN5YeG56GuCiAgICB0aCwgZWgsIGF0ID0gdHJhaW5fZHMuc3RhdHMoKQogICAgdmgsIGV2LCBhdiA9IHZhbF9kcy5zdGF0cygpCiAgICBwcmludChmIlvmlbDmja5dIHRyYWluIOWRveS4rSB7dGh9L3tsZW4odHJhaW5fZHMpfSBzdHVkeSjnqboge2VofSwg5bmz5Z2HIHthdDouMWZ9IGNsaXApIHwgIgogICAgICAgICAgZiJ2YWwg5ZG95LitIHt2aH0ve2xlbih2YWxfZHMpfSBzdHVkeSjnqboge2V2fSkiLCBmbHVzaD1UcnVlKQogICAgaWYgdGggPT0gMCBvciB2aCA9PSAwOgogICAgICAgIHByaW50KCJb6K2m5ZGKXSDmnInmipggRElDT00g5YWo6YOo5rKh6K+75YiwKOWRveS4rSAwKeKAlOKAlOi+k+WFpeWwhuaYr+WFqOmbtizliIbmlbDlv4XnhLYgfjAuNSEiLCBmbHVzaD1UcnVlKQogICAgdmFsX3VpZCA9IG5wLmFycmF5KHZhbF9kcy5zdHVkaWVzKSAgIyBzaHVmZmxlPUZhbHNlLOmhuuW6j+S4juaVsOaNrumbhuS4gOiHtAogICAgcmV0dXJuIHZhbF9wcmVkLCB2YWxfdWlkCgoKIyAtLS0tLS0tLS0tLS0tLS0tIOaOqOeQhiAvIOiejeWQiCAvIOaPkOS6pCAtLS0tLS0tLS0tLS0tLS0tCgpkZWYgcHJlZGljdF90ZXN0KG1vZGVsLCB0ZXN0X2RmLCBzZXJpZXNfZGYsIHJvb3QsIGRldmljZSwgcGxhbmUsIG5fY2xpcHM9Mik6CiAgICAiIiLlr7kgdGVzdCDmr4/kuKogc3R1ZHkg5oyJ5oyH5a6a5bmz6Z2i5pS26ZuGIGNsaXBzLOmihOa1iyAxMiDkuKrmpoLnjofjgIIiIiIKICAgIGRzID0gS25lZURhdGFzZXQodGVzdF9kZlsiU3R1ZHlJbnN0YW5jZVVJRCJdLnRvbGlzdCgpLCBOb25lLCByb290LCBzZXJpZXNfZGYsCiAgICAgICAgICAgICAgICAgICAgIHBsYW5lLCBoYXNfdGFyZ2V0cz1GYWxzZSwgbl9jbGlwcz1uX2NsaXBzKQogICAgbG9hZGVyID0gRGF0YUxvYWRlcihkcywgYmF0Y2hfc2l6ZT0xNiwgc2h1ZmZsZT1GYWxzZSwgbnVtX3dvcmtlcnM9MCkKICAgIHJldHVybiBwcmVkaWN0KG1vZGVsLCBsb2FkZXIsIGRldmljZSkKCgpkZWYgcGxhbmVfb29mX2F1Yyhvb2YsIGxhYmVsc19kZiwgdWlkX2xpc3QpOgogICAgIiIi6K6h566X5LiA5Liq5bmz6Z2i5qih5Z6L5Zyo5oyH5a6aIHN0dWR5IOWtkOmbhuS4iueahOWuj+W5s+WdhyBPT0YgQVVDKOWPqueul+acieagh+azqOeahOWIlynjgIIKCiAgICBsYWJlbHNfZGYg5b+F6aG75piv44CQ5a6Y5pa5IGdvbGQg5Y6f5aeL6KGo44CRKDAvMS9OYU4s5aaCIHRyYWluX2NzdiDljp/liJcpLOS4jeiDveS8oAogICAgbG9hZF9sYWJlbHMg5aGr5YWF5ZCO55qEIHNvZnQg6KGo4oCU4oCUc29mdCDkvKrmoIfnrb7ml6LpnZ4gZ3JvdW5kIHRydXRoLOS5n+S8muiuqQogICAgcm9jX2F1Y19zY29yZSDltKkoY29udGludW91cynjgII1OCDkvovlsI/moLfmnKzkuIvmn5DliJflj6/og73lj6rmnInljZXkuIDnsbvliKss6Lez6L+H6K+l5YiX44CCCiAgICAiIiIKICAgIGF1Y3MgPSBbXQogICAgZm9yIGosIGMgaW4gZW51bWVyYXRlKExBQkVMUyk6CiAgICAgICAgeV90cnVlID0gbGFiZWxzX2RmLnNldF9pbmRleCgiU3R1ZHlJbnN0YW5jZVVJRCIpW2NdLnJlaW5kZXgodWlkX2xpc3QpLnZhbHVlcy5hc3R5cGUoZmxvYXQpCiAgICAgICAgdmFsaWQgPSB+bnAuaXNuYW4oeV90cnVlKQogICAgICAgIGlmIHZhbGlkLnN1bSgpID49IDIwOgogICAgICAgICAgICB5diA9IHlfdHJ1ZVt2YWxpZF0KICAgICAgICAgICAgaWYgbGVuKG5wLnVuaXF1ZSh5dikpIDwgMjoKICAgICAgICAgICAgICAgIGNvbnRpbnVlCiAgICAgICAgICAgIGF1Y3MuYXBwZW5kKHJvY19hdWNfc2NvcmUoeXYsIG9vZlt2YWxpZCwgal0pKQogICAgcmV0dXJuIGZsb2F0KG5wLm1lYW4oYXVjcykpIGlmIGF1Y3MgZWxzZSAwLjAKCgojIC0tLS0tLS0tLS0tLS0tLS0gYXJ0aWZhY3QgLyByZXN1bWUgLyBlbnNlbWJsZSBoZWxwZXJzIC0tLS0tLS0tLS0tLS0tLS0KCmRlZiBfYXJ0aWZhY3Rfcm9vdChhcmdzKToKICAgIGJhc2UgPSBQYXRoKGdldGF0dHIoYXJncywgImFydGlmYWN0X2RpciIsICIiKSBvciAiYXJ0aWZhY3RzIikKICAgIGV4cCA9IGdldGF0dHIoYXJncywgImV4cGVyaW1lbnRfaWQiLCAiZXhwXzAwMV81Zm9sZF9zYWdpdHRhbCIpCiAgICByZXR1cm4gYmFzZSAvIGV4cAoKCmRlZiBfZm9sZF9kaXIoYXJ0aWZhY3Rfcm9vdCwgZm9sZCwgcGxhbmUpOgogICAgIiIiUGVyLXBsYW5lIGZvbGQgZGlyOiBmb2xke2t9L3twbGFuZX0vIOKAlCBwbGFuZXMgbXVzdCBub3Qgb3ZlcndyaXRlIGVhY2ggb3RoZXIuIiIiCiAgICByZXR1cm4gYXJ0aWZhY3Rfcm9vdCAvIGYiZm9sZHtmb2xkfSIgLyBzdHIocGxhbmUpCgoKZGVmIF9mb2xkX21ldGFfcGF0aChhcnRpZmFjdF9yb290LCBmb2xkLCBwbGFuZSk6CiAgICByZXR1cm4gX2ZvbGRfZGlyKGFydGlmYWN0X3Jvb3QsIGZvbGQsIHBsYW5lKSAvICJtZXRhLmpzb24iCgoKZGVmIF9pc19mb2xkX2RvbmUoYXJ0aWZhY3Rfcm9vdCwgZm9sZCwgcGxhbmUpOgogICAgcCA9IF9mb2xkX21ldGFfcGF0aChhcnRpZmFjdF9yb290LCBmb2xkLCBwbGFuZSkKICAgIGlmIG5vdCBwLmV4aXN0cygpOgogICAgICAgIHJldHVybiBGYWxzZQogICAgdHJ5OgogICAgICAgIG1ldGEgPSBqc29uLmxvYWRzKHAucmVhZF90ZXh0KGVuY29kaW5nPSJ1dGYtOCIpKQogICAgICAgIHJldHVybiBtZXRhLmdldCgiY29tcGxldGlvbl9zdGF0dXMiKSA9PSAiZG9uZSIKICAgIGV4Y2VwdCBFeGNlcHRpb246CiAgICAgICAgcmV0dXJuIEZhbHNlCgoKZGVmIF9zYXZlX2ZvbGRfYXJ0aWZhY3QoYXJ0aWZhY3Rfcm9vdCwgZm9sZCwgcGxhbmUsIHRlc3RfcHJlZCwgdGVzdF91aWRzLCBtZXRhKToKICAgIGZvbGRfZGlyID0gX2ZvbGRfZGlyKGFydGlmYWN0X3Jvb3QsIGZvbGQsIHBsYW5lKQogICAgZm9sZF9kaXIubWtkaXIocGFyZW50cz1UcnVlLCBleGlzdF9vaz1UcnVlKQogICAgbnAuc2F2ZShzdHIoZm9sZF9kaXIgLyAidGVzdF9wcmVkLm5weSIpLCB0ZXN0X3ByZWQuYXN0eXBlKG5wLmZsb2F0MzIpKQogICAgcGQuRGF0YUZyYW1lKHsiU3R1ZHlJbnN0YW5jZVVJRCI6IHRlc3RfdWlkc30pLnRvX2NzdigKICAgICAgICBmb2xkX2RpciAvICJ0ZXN0X3VpZC5jc3YiLCBpbmRleD1GYWxzZQogICAgKQogICAgbWV0YVsiZm9sZCJdID0gZm9sZAogICAgbWV0YVsicGxhbmUiXSA9IHBsYW5lCiAgICBtZXRhWyJjb21wbGV0aW9uX3N0YXR1cyJdID0gImRvbmUiCiAgICBtZXRhWyJwcmVkaWN0aW9uX3NoYXBlIl0gPSBsaXN0KHRlc3RfcHJlZC5zaGFwZSkKICAgIChmb2xkX2RpciAvICJtZXRhLmpzb24iKS53cml0ZV90ZXh0KAogICAgICAgIGpzb24uZHVtcHMobWV0YSwgZW5zdXJlX2FzY2lpPUZhbHNlLCBpbmRlbnQ9MiksIGVuY29kaW5nPSJ1dGYtOCIKICAgICkKCgpkZWYgX2xvYWRfZm9sZF9wcmVkaWN0aW9ucyhhcnRpZmFjdF9yb290LCBmb2xkLCBwbGFuZSwgY2Fub25pY2FsX3VpZHMpOgogICAgZm9sZF9kaXIgPSBfZm9sZF9kaXIoYXJ0aWZhY3Rfcm9vdCwgZm9sZCwgcGxhbmUpCiAgICBwcmVkID0gbnAubG9hZChmb2xkX2RpciAvICJ0ZXN0X3ByZWQubnB5IikKICAgIHVpZHMgPSBwZC5yZWFkX2Nzdihmb2xkX2RpciAvICJ0ZXN0X3VpZC5jc3YiKVsiU3R1ZHlJbnN0YW5jZVVJRCJdLnRvbGlzdCgpCiAgICBpZiBwcmVkLnNoYXBlICE9IChsZW4oY2Fub25pY2FsX3VpZHMpLCBsZW4oTEFCRUxTKSk6CiAgICAgICAgcmFpc2UgVmFsdWVFcnJvcihmImZvbGR7Zm9sZH0ve3BsYW5lfSBzaGFwZSBtaXNtYXRjaDoge3ByZWQuc2hhcGV9IHZzIGV4cGVjdGVkIHsobGVuKGNhbm9uaWNhbF91aWRzKSwgbGVuKExBQkVMUykpfSIpCiAgICBpZiB1aWRzICE9IGNhbm9uaWNhbF91aWRzOgogICAgICAgIHJhaXNlIFZhbHVlRXJyb3IoZiJmb2xke2ZvbGR9L3twbGFuZX0gVUlEIG9yZGVyIG1pc21hdGNoIikKICAgIGlmIG5vdCBucC5pc2Zpbml0ZShwcmVkKS5hbGwoKToKICAgICAgICByYWlzZSBWYWx1ZUVycm9yKGYiZm9sZHtmb2xkfS97cGxhbmV9IGNvbnRhaW5zIE5hTi9JbmYiKQogICAgaWYgcHJlZC5taW4oKSA8IDAgb3IgcHJlZC5tYXgoKSA+IDE6CiAgICAgICAgcmFpc2UgVmFsdWVFcnJvcihmImZvbGR7Zm9sZH0ve3BsYW5lfSBwcmVkaWN0aW9ucyBvdXQgb2YgWzAsMV0iKQogICAgcmV0dXJuIHByZWQKCgpkZWYgX3NhdmVfZXhwZXJpbWVudF9tZXRhKGFydGlmYWN0X3Jvb3QsIHRyYWluX2ZvbGRfdWlkcywgdGVzdF91aWRzLCBhcmdzKToKICAgIG1ldGEgPSB7CiAgICAgICAgImV4cGVyaW1lbnRfaWQiOiBnZXRhdHRyKGFyZ3MsICJleHBlcmltZW50X2lkIiwgImV4cF8wMDFfNWZvbGRfc2FnaXR0YWwiKSwKICAgICAgICAiZ2l0X2NvbW1pdCI6IF9fZ2l0X2NvbW1pdCgpLAogICAgICAgICJhcmdzIjogdmFycyhhcmdzKSwKICAgICAgICAibGFiZWxzIjogTEFCRUxTLAogICAgICAgICJ0cmFpbl9mb2xkMF91aWRzIjogdHJhaW5fZm9sZF91aWRzLAogICAgICAgICJ0ZXN0X3VpZHMiOiB0ZXN0X3VpZHMsCiAgICB9CiAgICAoYXJ0aWZhY3Rfcm9vdCAvICJjb25maWcuanNvbiIpLndyaXRlX3RleHQoCiAgICAgICAganNvbi5kdW1wcyhtZXRhLCBlbnN1cmVfYXNjaWk9RmFsc2UsIGluZGVudD0yKSwgZW5jb2Rpbmc9InV0Zi04IgogICAgKQogICAgcGQuRGF0YUZyYW1lKHsiU3R1ZHlJbnN0YW5jZVVJRCI6IHRlc3RfdWlkc30pLnRvX2NzdigKICAgICAgICBhcnRpZmFjdF9yb290IC8gInRlc3RfdWlkLmNzdiIsIGluZGV4PUZhbHNlCiAgICApCiAgICBmb2xkX3Jvd3MgPSBbXQogICAgZm9yIGsgaW4gcmFuZ2UoYXJncy5mb2xkcyk6CiAgICAgICAgZm9sZF9yb3dzLmFwcGVuZCh7ImZvbGQiOiBrLCAidHJhaW5fdWlkcyI6IHRyYWluX2ZvbGRfdWlkc1trXX0pCiAgICBwZC5EYXRhRnJhbWUoZm9sZF9yb3dzKS50b19jc3YoYXJ0aWZhY3Rfcm9vdCAvICJmb2xkX2Fzc2lnbm1lbnQuY3N2IiwgaW5kZXg9RmFsc2UpCgoKZGVmIF9tYXliZV9rYWdnbGVfZGF0YXNldF92ZXJzaW9uKGFydGlmYWN0X3Jvb3QsIG1lc3NhZ2UpOgogICAgaWYgb3MuZW52aXJvbi5nZXQoIktBR0dMRV9LRVJORUxfUlVOX1RZUEUiKSAhPSAiSW50ZXJhY3RpdmUiOgogICAgICAgIHJldHVybgogICAgc2x1ZyA9IG9zLmVudmlyb24uZ2V0KCJLQUdHTEVfS0VSTkVMX1NMVUciLCAicnNuYS1hcnRpZmFjdHMtdG1wIikKICAgIG93bmVyID0gb3MuZW52aXJvbi5nZXQoIktBR0dMRV9VU0VSTkFNRSIsICJ6aXlpbWluZyIpCiAgICBkYXRhc2V0X2lkID0gZiJ7b3duZXJ9L3tzbHVnfSIKICAgIHRyeToKICAgICAgICBzdWJwcm9jZXNzLnJ1bigKICAgICAgICAgICAgWwogICAgICAgICAgICAgICAgImthZ2dsZSIsCiAgICAgICAgICAgICAgICAiZGF0YXNldHMiLAogICAgICAgICAgICAgICAgInZlcnNpb24iLAogICAgICAgICAgICAgICAgIi1wIiwKICAgICAgICAgICAgICAgIHN0cihhcnRpZmFjdF9yb290KSwKICAgICAgICAgICAgICAgICItbSIsCiAgICAgICAgICAgICAgICBtZXNzYWdlLAogICAgICAgICAgICAgICAgIi0tZGlyLW1vZGUiLAogICAgICAgICAgICAgICAgInRhciIsCiAgICAgICAgICAgIF0sCiAgICAgICAgICAgIGNoZWNrPVRydWUsCiAgICAgICAgICAgIGNhcHR1cmVfb3V0cHV0PVRydWUsCiAgICAgICAgKQogICAgICAgIHByaW50KGYiW2FydGlmYWN0XSB1cGxvYWRlZCBkYXRhc2V0IHZlcnNpb246IHtkYXRhc2V0X2lkfSIsIGZsdXNoPVRydWUpCiAgICBleGNlcHQgRXhjZXB0aW9uIGFzIGU6CiAgICAgICAgcHJpbnQoZiJbYXJ0aWZhY3RdIGRhdGFzZXQgdXBsb2FkIHNraXBwZWQ6IHtlfSIsIGZsdXNoPVRydWUpCgoKZGVmIF9fZ2l0X2NvbW1pdCgpOgogICAgdHJ5OgogICAgICAgIGltcG9ydCBzdWJwcm9jZXNzCiAgICAgICAgcmV0dXJuIHN1YnByb2Nlc3MuY2hlY2tfb3V0cHV0KAogICAgICAgICAgICBbImdpdCIsICJyZXYtcGFyc2UiLCAiSEVBRCJdLCB0ZXh0PVRydWUKICAgICAgICApLnN0cmlwKCkKICAgIGV4Y2VwdCBFeGNlcHRpb246CiAgICAgICAgcmV0dXJuICJ1bmtub3duIgoKCmRlZiBtYWluKCk6CiAgICBhcCA9IGFyZ3BhcnNlLkFyZ3VtZW50UGFyc2VyKCkKICAgIGFwLmFkZF9hcmd1bWVudCgiLS1lcG9jaHMiLCB0eXBlPWludCwgZGVmYXVsdD0yKQogICAgYXAuYWRkX2FyZ3VtZW50KCItLWJhdGNoIiwgdHlwZT1pbnQsIGRlZmF1bHQ9OCkKICAgIGFwLmFkZF9hcmd1bWVudCgiLS1sciIsIHR5cGU9ZmxvYXQsIGRlZmF1bHQ9M2UtNCkKICAgIGFwLmFkZF9hcmd1bWVudCgiLS13b3JrZXJzIiwgdHlwZT1pbnQsIGRlZmF1bHQ9MCkKICAgIGFwLmFkZF9hcmd1bWVudCgiLS1uLWNsaXBzIiwgdHlwZT1pbnQsIGRlZmF1bHQ9MikKICAgIGFwLmFkZF9hcmd1bWVudCgiLS1zZWVkIiwgdHlwZT1pbnQsIGRlZmF1bHQ9U0VFRCkKICAgIGFwLmFkZF9hcmd1bWVudCgiLS1mb2xkcyIsIHR5cGU9aW50LCBkZWZhdWx0PUZPTERTKQogICAgYXAuYWRkX2FyZ3VtZW50KCItLW9ubHktZm9sZCIsIHR5cGU9aW50LCBkZWZhdWx0PS0xLAogICAgICAgICAgICAgICAgICAgIGhlbHA9IuWPqui3keaMh+WumuaKmCjlhbbkvZnot7Pov4c76buY6K6kIC0xPeWFqOmDqCnjgILmjqLot6/nlKg6LS1mb2xkcyA1IC0tb25seS1mb2xkIDAg6K6t56ysIDAg5oqYIgogICAgICAgICAgICAgICAgICAgICAgICAgIih0cmFpbiA0LzUg5LiO5q2j5byP5ZCM5YiG5biDKSx0ZXN0IOaOqOeQhueUqOivpeaKmOaooeWei+WHuuaPkOS6pCIpCiAgICBhcC5hZGRfYXJndW1lbnQoIi0tcGxhbmVzIiwgdHlwZT1zdHIsIGRlZmF1bHQ9IiwiLmpvaW4oUExBTkVTKSwKICAgICAgICAgICAgICAgICAgICBoZWxwPSLpgJflj7fliIbpmpTnmoTlubPpnaLlrZDpm4Ys5aaCIGF4aWFsLHNhZ2l0dGFsKOWwj+WGmSzkuI3ljLrliIblpKflsI/lhpkpIikKICAgIGFwLmFkZF9hcmd1bWVudCgiLS1mdXNlIiwgdHlwZT1zdHIsIGRlZmF1bHQ9IndlaWdodCIsCiAgICAgICAgICAgICAgICAgICAgY2hvaWNlcz1bIndlaWdodCIsICJtZWFuIl0sCiAgICAgICAgICAgICAgICAgICAgaGVscD0i5bmz6Z2i6J6N5ZCI5pa55byPOndlaWdodD3mjIkgT09GIEFVQyDliqDmnYM7bWVhbj3nroDljZXlubPlnYciKQogICAgYXAuYWRkX2FyZ3VtZW50KCItLXBzZXVkby1jb25mIiwgdHlwZT1mbG9hdCwgZGVmYXVsdD0wLjAsCiAgICAgICAgICAgICAgICAgICAgaGVscD0i5Lyq5qCH562+572u5L+h5bqm6L+H5ruk6ZiI5YC8KDA95LiN6L+H5rukOzAuNT3kuKLlvIPnva7kv6HluqY8MC4155qE5Lyq5qCH562+KSIpCiAgICBhcC5hZGRfYXJndW1lbnQoIi0tbm8tcmVwb3J0LWxhYmVscyIsIGFjdGlvbj0ic3RvcmVfdHJ1ZSIsCiAgICAgICAgICAgICAgICAgICAgaGVscD0i56aB55So5YaF572u5oql5ZGK5YWz6ZSu6K+N6L2v5qCH562+5YWc5bqVKOm7mOiupOW8gOWQrzrmnKrmjILnpL7ljLrmlbDmja7pm4bml7YiCiAgICAgICAgICAgICAgICAgICAgICAgICAi6Ieq5Yqo5LuOIDQ0MDcg5Lu95pS+5bCE5oql5ZGK55Sf5oiQ6L2v5qCH562+LOmbtuaMgui9vSkiKQogICAgYXAuYWRkX2FyZ3VtZW50KCItLXZlcmJvc2UiLCBhY3Rpb249InN0b3JlX3RydWUiKQogICAgYXAuYWRkX2FyZ3VtZW50KCItLXByZXRyYWluZWQiLCBhY3Rpb249InN0b3JlX3RydWUiLAogICAgICAgICAgICAgICAgICAgIGhlbHA9IuWwneivleS4i+i9vSBJbWFnZU5ldCDpooTorq3nu4PmnYPph40o6ZyA5byA5ZCvIEludGVybmV0KTvpu5jorqTpmo/mnLrliJ3lp4vljJbkuI3ogZTnvZEiKQogICAgYXAuYWRkX2FyZ3VtZW50KCItLW9mZmxpbmUtd2VpZ2h0cyIsIHR5cGU9c3RyLCBkZWZhdWx0PSIiLAogICAgICAgICAgICAgICAgICAgIGhlbHA9IumAl+WPt+WIhumalOeahOemu+e6v+adg+mHjSAucHRoIOi3r+W+hCjkvJjlhYjnuqfmnIDpq5gpO+eVmeepuuWImeiHquWKqOaJq+aPj+aMgui9veebruW9lSIpCiAgICBhcC5hZGRfYXJndW1lbnQoIi0tbm8tb2ZmbGluZS1zY2FuIiwgYWN0aW9uPSJzdG9yZV90cnVlIiwKICAgICAgICAgICAgICAgICAgICBoZWxwPSLnpoHnlKjoh6rliqjmiavmj48gL2thZ2dsZS9pbnB1dCDkuIvnmoTnprvnur/mnYPph43mlofku7YiKQogICAgYXAuYWRkX2FyZ3VtZW50KCItLWRhdGEiLCB0eXBlPXN0ciwgZGVmYXVsdD0iIiwKICAgICAgICAgICAgICAgICAgICBoZWxwPSLmmL7lvI/mjIflrprmlbDmja7moLnnm67lvZUo5aaCIGthZ2dsZWh1Yi5jb21wZXRpdGlvbl9kb3dubG9hZCDov5Tlm57nmoQgcGF0aCksIgogICAgICAgICAgICAgICAgICAgICAgICAgIuaMh+WumuWQjui3s+i/h+iHquWKqOafpeaJviIpCiAgICBhcC5hZGRfYXJndW1lbnQoIi0tYXJ0aWZhY3QtZGlyIiwgdHlwZT1zdHIsIGRlZmF1bHQ9ImFydGlmYWN0cyIsCiAgICAgICAgICAgICAgICAgICAgaGVscD0iYXJ0aWZhY3Qg5qC555uu5b2VKOm7mOiupCBhcnRpZmFjdHMpIikKICAgIGFwLmFkZF9hcmd1bWVudCgiLS1leHBlcmltZW50LWlkIiwgdHlwZT1zdHIsIGRlZmF1bHQ9ImV4cF8wMDFfNWZvbGRfc2FnaXR0YWwiLAogICAgICAgICAgICAgICAgICAgIGhlbHA9ImV4cGVyaW1lbnQgSUQo55So5LqOIGFydGlmYWN0IOWtkOebruW9lSkiKQogICAgYXAuYWRkX2FyZ3VtZW50KCItLXJlc3VtZS1kaXIiLCB0eXBlPXN0ciwgZGVmYXVsdD0iIiwKICAgICAgICAgICAgICAgICAgICBoZWxwPSLlt7LmnIkgYXJ0aWZhY3Qg55uu5b2VLOWQr+WKqOaXtuaJq+aPjyBtZXRhLmpzb24g6Lez6L+H5bey5a6M5oiQIGZvbGQiKQogICAgYXJncywgXyA9IGFwLnBhcnNlX2tub3duX2FyZ3MoKQoKICAgIHJlc3VtZV9yb290ID0gUGF0aChhcmdzLnJlc3VtZV9kaXIpIGlmIGFyZ3MucmVzdW1lX2RpciBlbHNlIE5vbmUKICAgIGlmIHJlc3VtZV9yb290IGFuZCBhcmdzLmFydGlmYWN0X2RpciBhbmQgbm90IGFyZ3MuZXhwZXJpbWVudF9pZDoKICAgICAgICBhcmdzLmV4cGVyaW1lbnRfaWQgPSByZXN1bWVfcm9vdC5uYW1lCgogICAgaWYgbm90IEhBU19UT1JDSCBvciBub3QgSEFTX1RWIG9yIG5vdCBIQVNfUFlESUNPTToKICAgICAgICBzeXMuZXhpdCgi5L6d6LWW57y65aSxOuivt+WcqCBLYWdnbGUgTm90ZWJvb2soR1BVKeeOr+Wig+i/kOihjCh0b3JjaC90b3JjaHZpc2lvbi9weWRpY29tKTvmnKzlnLDku4Xlj6/lgZrmlbDmja7lsYLpqozor4HjgIIiKQoKICAgIG5wLnJhbmRvbS5zZWVkKGFyZ3Muc2VlZCkKICAgIHRvcmNoLm1hbnVhbF9zZWVkKGFyZ3Muc2VlZCkKCiAgICBpZiBhcmdzLmRhdGE6CiAgICAgICAgaWYgb3MucGF0aC5leGlzdHMob3MucGF0aC5qb2luKGFyZ3MuZGF0YSwgInRyYWluLmNzdiIpKToKICAgICAgICAgICAgcm9vdCwgb3V0ID0gYXJncy5kYXRhLCBhcmdzLmRhdGEKICAgICAgICAgICAgcHJpbnQoZiJb5pWw5o2uXSDkvb/nlKggLS1kYXRhIOaMh+WumuebruW9lToge3Jvb3R9IikKICAgICAgICBlbHNlOgogICAgICAgICAgICBzeXMuZXhpdChmIi0tZGF0YSDmjIflrprnm67lvZUge2FyZ3MuZGF0YX0g5LiL5rKh5pyJIHRyYWluLmNzdizor7fmo4Dmn6Xot6/lvoQiKQogICAgZWxzZToKICAgICAgICByb290LCBvdXQgPSByZXNvbHZlX3BhdGhzKCkKICAgIHByaW50KGYiW+aVsOaNrl0gcm9vdD17cm9vdH0gIG91dD17b3V0fSIpCgogICAgdHJhaW5fY3N2ID0gcGQucmVhZF9jc3Yob3MucGF0aC5qb2luKHJvb3QsICJ0cmFpbi5jc3YiKSkKICAgIGxhYmVsc19kZiA9IGxvYWRfbGFiZWxzKHJvb3QsIHBzZXVkb19jb25mPWFyZ3MucHNldWRvX2NvbmYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1c2VfcmVwb3J0X2xhYmVscz1ub3QgYXJncy5ub19yZXBvcnRfbGFiZWxzKQogICAgc2VyaWVzX2RmID0gcGQucmVhZF9jc3Yob3MucGF0aC5qb2luKHJvb3QsICJ0cmFpbl9zZXJpZXMuY3N2IikpCiAgICB0ZXN0X2RmID0gcGQucmVhZF9jc3Yob3MucGF0aC5qb2luKHJvb3QsICJ0ZXN0LmNzdiIpKQogICAgdGVzdF9zZXJpZXMgPSBwZC5yZWFkX2Nzdihvcy5wYXRoLmpvaW4ocm9vdCwgInRlc3Rfc2VyaWVzLmNzdiIpKQogICAgZGNtX3RyYWluID0gb3MucGF0aC5qb2luKHJvb3QsICJ0cmFpbl9zZXJpZXMiKQogICAgZGNtX3Rlc3QgPSBvcy5wYXRoLmpvaW4ocm9vdCwgInRlc3Rfc2VyaWVzIikKICAgIHByaW50KGYiW+aVsOaNrl0gdHJhaW4ge2xlbih0cmFpbl9jc3YpfSBzdHVkeSAvIHRlc3Qge2xlbih0ZXN0X2RmKX0gc3R1ZHkgLyBzZXJpZXMge2xlbihzZXJpZXNfZGYpfSIpCiAgICBfcHJpbnRfZGNtX3RyZWUocm9vdCwgIkRJQ09NIikgICMg5omT5Y2wIHRyYWluX3NlcmllcyDnnJ/lrp7nm67lvZXnu5PmnoQs56Gu6K6k5biD5bGACgogICAgcGxhbmVzID0gW3Auc3RyaXAoKS50aXRsZSgpIGZvciBwIGluIGFyZ3MucGxhbmVzLnNwbGl0KCIsIikgaWYgcC5zdHJpcCgpXQogICAgcGxhbmVzID0gW3AgZm9yIHAgaW4gcGxhbmVzIGlmIHAgaW4gUExBTkVTXQogICAgaWYgbm90IHBsYW5lczoKICAgICAgICBzeXMuZXhpdChmIi0tcGxhbmVzIOaXoOaViCzlj6/pgIk6IHtQTEFORVN9IikKICAgIHByaW50KGYiW+W5s+mdol0g5L2/55SoIHtwbGFuZXN9IikKCiAgICBkZXZpY2UgPSB0b3JjaC5kZXZpY2UoImN1ZGEiIGlmIHRvcmNoLmN1ZGEuaXNfYXZhaWxhYmxlKCkgZWxzZSAiY3B1IikKICAgIHByaW50KGYiW+iuvuWkh10ge2RldmljZX0iKQoKICAgICMg56a757q/6aKE6K6t57uD5p2D6YeNOuaYvuW8j+aMh+WumuS8mOWFiCzlkKbliJnoh6rliqjmiavmj48gL2thZ2dsZS9pbnB1dAogICAgb2ZmbGluZV9wYXRocyA9IFtdCiAgICBpZiBhcmdzLm9mZmxpbmVfd2VpZ2h0cy5zdHJpcCgpOgogICAgICAgIGZvciBwIGluIFt4LnN0cmlwKCkgZm9yIHggaW4gYXJncy5vZmZsaW5lX3dlaWdodHMuc3BsaXQoIiwiKSBpZiB4LnN0cmlwKCldOgogICAgICAgICAgICBpZiBvcy5wYXRoLmlzZmlsZShwKToKICAgICAgICAgICAgICAgIG9mZmxpbmVfcGF0aHMuYXBwZW5kKChwLCBwKSkKICAgICAgICAgICAgZWxzZToKICAgICAgICAgICAgICAgIHByaW50KGYiW+adg+mHjV0gLS1vZmZsaW5lLXdlaWdodHMg5oyH5a6a55qE5paH5Lu25LiN5a2Y5ZyoLOi3s+i/hzoge3B9IiwgZmx1c2g9VHJ1ZSkKICAgIGVsaWYgbm90IGFyZ3Mubm9fb2ZmbGluZV9zY2FuOgogICAgICAgIG9mZmxpbmVfcGF0aHMgPSBfc2Nhbl9vZmZsaW5lX3dlaWdodHMoKQogICAgICAgIGlmIG9mZmxpbmVfcGF0aHM6CiAgICAgICAgICAgIHByaW50KGYiW+adg+mHjV0g6Ieq5Yqo5omr5o+P5YiwIHtsZW4ob2ZmbGluZV9wYXRocyl9IOS4quemu+e6v+adg+mHjeWAmemAiToiLCBmbHVzaD1UcnVlKQogICAgICAgICAgICBmb3IgcCwgZGVzYyBpbiBvZmZsaW5lX3BhdGhzWzo2XToKICAgICAgICAgICAgICAgIHByaW50KGYiICB7ZGVzY30iLCBmbHVzaD1UcnVlKQogICAgICAgICAgICBpZiBsZW4ob2ZmbGluZV9wYXRocykgPiA2OgogICAgICAgICAgICAgICAgcHJpbnQoZiIgIC4uLiDlhbEge2xlbihvZmZsaW5lX3BhdGhzKX0g5LiqIiwgZmx1c2g9VHJ1ZSkKICAgICAgICBlbHNlOgogICAgICAgICAgICBwcmludCgiW+adg+mHjV0g5pyq5Zyo5oyC6L2955uu5b2V5Y+R546w56a757q/5p2D6YeNKOWPr+aMgui9veekvuWMuuaJk+WMheeahCByZXNuZXQzNCDmnYPph43mlbDmja7pm4YpIiwgZmx1c2g9VHJ1ZSkKICAgICAgICAgICAgX3ByaW50X21vdW50X3RyZWUoIi9rYWdnbGUvaW5wdXQiLCAi5p2D6YeNIikKCiAgICBna2YgPSBHcm91cEtGb2xkKG5fc3BsaXRzPWFyZ3MuZm9sZHMpCiAgICBncm91cHMgPSB0cmFpbl9jc3ZbIlN0dWR5SW5zdGFuY2VVSUQiXS52YWx1ZXMKCiAgICAjIOavj+S4quW5s+mdoueLrOeri+i3keaKmCzorrDlvZUgT09GIOS4jiB0ZXN0IOmihOa1iwogICAgcGxhbmVfb29mLCBwbGFuZV90ZXN0LCBwbGFuZV9hdWMsIHBsYW5lX3VpZHMgPSB7fSwge30sIHt9LCB7fQogICAgZm9yIHBsYW5lIGluIHBsYW5lczoKICAgICAgICBwcmludChmIlxuIyMjIyMjIyMjIyDlubPpnaI6IHtwbGFuZX0gIyMjIyMjIyMjIyIpCiAgICAgICAgb29mID0gbnAuemVyb3MoKGxlbih0cmFpbl9jc3YpLCBsZW4oTEFCRUxTKSkpCiAgICAgICAgYXJ0aWZhY3Rfcm9vdCA9IF9hcnRpZmFjdF9yb290KGFyZ3MpCiAgICAgICAgY2Fub25pY2FsX3Rlc3RfdWlkcyA9IHRlc3RfZGZbIlN0dWR5SW5zdGFuY2VVSUQiXS50b2xpc3QoKQogICAgICAgIHRyYWluX2ZvbGRfdWlkcyA9IFtdCiAgICAgICAgZm9yIGssICh0cl9pZHgsIHZhX2lkeCkgaW4gZW51bWVyYXRlKGdrZi5zcGxpdCh0cmFpbl9jc3YsIGdyb3Vwcz1ncm91cHMpKToKICAgICAgICAgICAgdHJfc3R1ZGllcyA9IHRyYWluX2Nzdi5pbG9jW3RyX2lkeF1bIlN0dWR5SW5zdGFuY2VVSUQiXS50b2xpc3QoKQogICAgICAgICAgICB2YV9zdHVkaWVzID0gdHJhaW5fY3N2Lmlsb2NbdmFfaWR4XVsiU3R1ZHlJbnN0YW5jZVVJRCJdLnRvbGlzdCgpCiAgICAgICAgICAgIHRyYWluX2ZvbGRfdWlkcy5hcHBlbmQodHJfc3R1ZGllcykKICAgICAgICAgICAgaWYgYXJncy5vbmx5X2ZvbGQgPj0gMCBhbmQgayAhPSBhcmdzLm9ubHlfZm9sZDoKICAgICAgICAgICAgICAgIGNvbnRpbnVlCiAgICAgICAgICAgIGlmIHJlc3VtZV9yb290IGFuZCBfaXNfZm9sZF9kb25lKGFydGlmYWN0X3Jvb3QsIGssIHBsYW5lKToKICAgICAgICAgICAgICAgIHByaW50KGYiW2FydGlmYWN0XSBmb2xkIHtrfS97cGxhbmV9IGRvbmUsIHNraXAiLCBmbHVzaD1UcnVlKQogICAgICAgICAgICAgICAgY29udGludWUKICAgICAgICAgICAgdHJfZHMgPSBLbmVlRGF0YXNldCh0cl9zdHVkaWVzLCBsYWJlbHNfZGYsIGRjbV90cmFpbiwgc2VyaWVzX2RmLCBwbGFuZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuX2NsaXBzPWFyZ3Mubl9jbGlwcykKICAgICAgICAgICAgdmFfZHMgPSBLbmVlRGF0YXNldCh2YV9zdHVkaWVzLCBsYWJlbHNfZGYsIGRjbV90cmFpbiwgc2VyaWVzX2RmLCBwbGFuZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuX2NsaXBzPWFyZ3Mubl9jbGlwcykKICAgICAgICAgICAgbW9kZWwgPSBLbmVlTW9kZWwocHJldHJhaW5lZD1hcmdzLnByZXRyYWluZWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9mZmxpbmVfcGF0aHM9b2ZmbGluZV9wYXRocywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hhbm5lbHM9YXJncy5uX2NsaXBzICogQ0xJUCkudG8oZGV2aWNlKQogICAgICAgICAgICBwcmludChmIlvmipgge2sgKyAxfS97YXJncy5mb2xkc31dIHtwbGFuZX0gdHJhaW4ge2xlbih0cl9kcyl9IC8gdmFsIHtsZW4odmFfZHMpfSIsIGZsdXNoPVRydWUpCiAgICAgICAgICAgIHQwID0gdGltZS50aW1lKCkKICAgICAgICAgICAgdmFsX3ByZWQsIHZhbF91aWQgPSBydW5fZm9sZChtb2RlbCwgdHJfZHMsIHZhX2RzLCBkZXZpY2UsIGFyZ3MpCiAgICAgICAgICAgIGZvbGRfdHJhaW5fdGltZSA9IHRpbWUudGltZSgpIC0gdDAKICAgICAgICAgICAgZm9yIGosIHVpZCBpbiBlbnVtZXJhdGUodmFsX3VpZCk6CiAgICAgICAgICAgICAgICByb3cgPSBucC53aGVyZSh0cmFpbl9jc3ZbIlN0dWR5SW5zdGFuY2VVSUQiXS52YWx1ZXMgPT0gdWlkKVswXQogICAgICAgICAgICAgICAgaWYgbGVuKHJvdyk6CiAgICAgICAgICAgICAgICAgICAgb29mW3Jvd1swXV0gPSB2YWxfcHJlZFtqXQogICAgICAgICAgICB0MCA9IHRpbWUudGltZSgpCiAgICAgICAgICAgIHRlc3RfcHJlZCA9IHByZWRpY3RfdGVzdChtb2RlbCwgdGVzdF9kZiwgdGVzdF9zZXJpZXMsIGRjbV90ZXN0LCBkZXZpY2UsIHBsYW5lLCBuX2NsaXBzPWFyZ3Mubl9jbGlwcykKICAgICAgICAgICAgZm9sZF9pbmZlcmVuY2VfdGltZSA9IHRpbWUudGltZSgpIC0gdDAKICAgICAgICAgICAgbWV0YSA9IHsKICAgICAgICAgICAgICAgICJmb2xkIjogaywKICAgICAgICAgICAgICAgICJwbGFuZSI6IHBsYW5lLAogICAgICAgICAgICAgICAgIm5fY2xpcHMiOiBhcmdzLm5fY2xpcHMsCiAgICAgICAgICAgICAgICAiaW1hZ2Vfc2l6ZSI6IElNR19TSVpFLAogICAgICAgICAgICAgICAgImVwb2NocyI6IGFyZ3MuZXBvY2hzLAogICAgICAgICAgICAgICAgImJhdGNoX3NpemUiOiBhcmdzLmJhdGNoLAogICAgICAgICAgICAgICAgInNlZWQiOiBhcmdzLnNlZWQsCiAgICAgICAgICAgICAgICAiZ2l0X2NvbW1pdCI6IF9fZ2l0X2NvbW1pdCgpLAogICAgICAgICAgICAgICAgImV4cGVyaW1lbnRfaWQiOiBnZXRhdHRyKGFyZ3MsICJleHBlcmltZW50X2lkIiwgImV4cF8wMDFfNWZvbGRfc2FnaXR0YWwiKSwKICAgICAgICAgICAgICAgICJmb2xkX3RyYWluX3RpbWVfc2VjIjogZm9sZF90cmFpbl90aW1lLAogICAgICAgICAgICAgICAgImZvbGRfaW5mZXJlbmNlX3RpbWVfc2VjIjogZm9sZF9pbmZlcmVuY2VfdGltZSwKICAgICAgICAgICAgfQogICAgICAgICAgICBfc2F2ZV9mb2xkX2FydGlmYWN0KGFydGlmYWN0X3Jvb3QsIGssIHBsYW5lLCB0ZXN0X3ByZWQsIGNhbm9uaWNhbF90ZXN0X3VpZHMsIG1ldGEpCiAgICAgICAgICAgIHByaW50KGYiW2FydGlmYWN0XSBzYXZlZCBmb2xke2t9L3twbGFuZX0gLT4ge19mb2xkX2RpcihhcnRpZmFjdF9yb290LCBrLCBwbGFuZSl9IiwgZmx1c2g9VHJ1ZSkKICAgICAgICAjIGV4cGVyaW1lbnQtbGV2ZWwgbWV0YSBvbmNlIHBlciBwbGFuZQogICAgICAgIF9zYXZlX2V4cGVyaW1lbnRfbWV0YShhcnRpZmFjdF9yb290LCB0cmFpbl9mb2xkX3VpZHMsIGNhbm9uaWNhbF90ZXN0X3VpZHMsIGFyZ3MpCiAgICAgICAgcHJpbnQoZiJbYXJ0aWZhY3RdIHNhdmVkIGV4cGVyaW1lbnQgbWV0YSAtPiB7YXJ0aWZhY3Rfcm9vdH0iLCBmbHVzaD1UcnVlKQogICAgICAgICMg6K+l5bmz6Z2iIE9PRiBBVUMo5a6P5bmz5Z2HKQogICAgICAgIHVpZF9saXN0ID0gdHJhaW5fY3N2WyJTdHVkeUluc3RhbmNlVUlEIl0udG9saXN0KCkKICAgICAgICBpZiBhcmdzLm9ubHlfZm9sZCA+PSAwOgogICAgICAgICAgICBwcmludChmIlt7cGxhbmV9XSDmjqLot6/mqKHlvI8oLS1vbmx5LWZvbGQge2FyZ3Mub25seV9mb2xkfSk6T09GIOWNleaKmOS4jeWujOaVtCwiCiAgICAgICAgICAgICAgICAgIGYi6Lez6L+HIE9PRiBBVUMo5p2D6YeN6K6wIDA95Z2H562JKTt0ZXN0IOaOqOeQhueUqOivpeaKmOaooeWeiyIpCiAgICAgICAgICAgIGF1YyA9IDAuMAogICAgICAgIGVsc2U6CiAgICAgICAgICAgIGF1YyA9IHBsYW5lX29vZl9hdWMob29mLCB0cmFpbl9jc3ZbWyJTdHVkeUluc3RhbmNlVUlEIl0gKyBMQUJFTFNdLCB1aWRfbGlzdCkKICAgICAgICAgICAgcHJpbnQoZiJbe3BsYW5lfV0gT09GIOWuj+W5s+WdhyBBVUMge2F1YzouNGZ9IikKICAgICAgICBwbGFuZV9vb2ZbcGxhbmVdLCBwbGFuZV9hdWNbcGxhbmVdLCBwbGFuZV91aWRzW3BsYW5lXSA9IG9vZiwgYXVjLCB1aWRfbGlzdAogICAgICAgICMgbG9hZCBzYXZlZCBmb2xkIHByZWRpY3Rpb25zIGZvciB0aGlzIHBsYW5lCiAgICAgICAgcGVyX2ZvbGQgPSBbXQogICAgICAgIG1pc3NpbmcgPSBbXQogICAgICAgIGZvciBrIGluIHJhbmdlKGFyZ3MuZm9sZHMpOgogICAgICAgICAgICBwID0gX2ZvbGRfZGlyKGFydGlmYWN0X3Jvb3QsIGssIHBsYW5lKSAvICJ0ZXN0X3ByZWQubnB5IgogICAgICAgICAgICBpZiBub3QgcC5leGlzdHMoKToKICAgICAgICAgICAgICAgIG1pc3NpbmcuYXBwZW5kKGspCiAgICAgICAgICAgICAgICBjb250aW51ZQogICAgICAgICAgICB0cnk6CiAgICAgICAgICAgICAgICBwZXJfZm9sZC5hcHBlbmQoX2xvYWRfZm9sZF9wcmVkaWN0aW9ucyhhcnRpZmFjdF9yb290LCBrLCBwbGFuZSwgY2Fub25pY2FsX3Rlc3RfdWlkcykpCiAgICAgICAgICAgIGV4Y2VwdCBFeGNlcHRpb24gYXMgZToKICAgICAgICAgICAgICAgIG1pc3NpbmcuYXBwZW5kKGspCiAgICAgICAgICAgICAgICBwcmludChmIltlbnNlbWJsZV0gZm9sZHtrfS97cGxhbmV9IGludmFsaWQ6IHtlfSIsIGZsdXNoPVRydWUpCiAgICAgICAgaWYgbGVuKG1pc3NpbmcpID09IGFyZ3MuZm9sZHM6CiAgICAgICAgICAgIHN5cy5leGl0KGYiW2Vuc2VtYmxlXSBubyB2YWxpZCBmb2xkIHByZWRpY3Rpb25zIGF2YWlsYWJsZSB1bmRlciB7YXJ0aWZhY3Rfcm9vdH0iKQogICAgICAgIGlmIG1pc3Npbmc6CiAgICAgICAgICAgIHByaW50KGYiW2Vuc2VtYmxlXSBtaXNzaW5nIGZvbGRzOiB7bWlzc2luZ307IGVuc2VtYmxlIHdpdGggYXZhaWxhYmxlIGZvbGRzIG9ubHkiLCBmbHVzaD1UcnVlKQogICAgICAgIHBsYW5lX3Rlc3RbcGxhbmVdID0gbnAubWVhbihwZXJfZm9sZCwgYXhpcz0wKSBpZiBwZXJfZm9sZCBlbHNlIE5vbmUKICAgICAgICBpZiBwbGFuZV90ZXN0W3BsYW5lXSBpcyBub3QgTm9uZToKICAgICAgICAgICAgcHJpbnQoZiJbZW5zZW1ibGVdIHtwbGFuZX0gZW5zZW1ibGVkIGZyb20ge2xlbihwZXJfZm9sZCl9IGZvbGRzLCBzaGFwZT17cGxhbmVfdGVzdFtwbGFuZV0uc2hhcGV9IikKCiAgICAjIOiejeWQiAogICAgaWYgYXJncy5mdXNlID09ICJ3ZWlnaHQiOgogICAgICAgIHdzdW0gPSBzdW0obWF4KGEsIDFlLTYpIGZvciBhIGluIHBsYW5lX2F1Yy52YWx1ZXMoKSkKICAgICAgICB3ZWlnaHRzID0ge3A6IG1heChhLCAxZS02KSAvIHdzdW0gZm9yIHAsIGEgaW4gcGxhbmVfYXVjLml0ZW1zKCl9CiAgICAgICAgcHJpbnQoZiJb6J6N5ZCIXSBPT0YgQVVDIOWKoOadgzogeyB7cDogcm91bmQodywgNCkgZm9yIHAsIHcgaW4gd2VpZ2h0cy5pdGVtcygpfSB9IikKICAgIGVsc2U6CiAgICAgICAgd2VpZ2h0cyA9IHtwOiAxLjAgLyBsZW4ocGxhbmVzKSBmb3IgcCBpbiBwbGFuZXN9CiAgICAgICAgcHJpbnQoIlvono3lkIhdIOeugOWNleW5s+WdhyIpCiAgICBmdXNlZCA9IG5wLnplcm9zX2xpa2UocGxhbmVfdGVzdFtwbGFuZXNbMF1dKQogICAgZm9yIHAsIHcgaW4gd2VpZ2h0cy5pdGVtcygpOgogICAgICAgIGZ1c2VkICs9IHcgKiBwbGFuZV90ZXN0W3BdCiAgICBzdWIgPSBwZC5EYXRhRnJhbWUoeyJTdHVkeUluc3RhbmNlVUlEIjogdGVzdF9kZlsiU3R1ZHlJbnN0YW5jZVVJRCJdLCAqKnsKICAgICAgICBMQUJFTFNbal06IGZ1c2VkWzosIGpdIGZvciBqIGluIHJhbmdlKGxlbihMQUJFTFMpKX19KQogICAgc3ViX3BhdGggPSBvcy5wYXRoLmpvaW4ob3V0LCAic3VibWlzc2lvbi5jc3YiKQogICAgc3ViLnRvX2NzdihzdWJfcGF0aCwgaW5kZXg9RmFsc2UpCiAgICBwcmludChmIlxu5o+Q5Lqk5paH5Lu25bey55Sf5oiQOiB7c3ViX3BhdGh9ICBzaGFwZT17c3ViLnNoYXBlfSIpCgoKaWYgX19uYW1lX18gPT0gIl9fbWFpbl9fIjoKICAgIG1haW4oKQo=\")\npath = \"/kaggle/working/rsna_v3.py\"\nopen(path, \"w\", encoding=\"utf-8\").write(base64.b64decode(parts[0]).decode(\"utf-8\"))\nexpect = \"1612f21b81b0abb56735a5675504043aced36a468c25328004d7bf35f5f02630\"\nh = hashlib.sha256(open(path, \"rb\").read()).hexdigest()\nprint(\"rsna_v3\", h, os.path.getsize(path))\nassert h == expect\nassert \"_fold_dir\" in open(path, encoding=\"utf-8\").read()\nprint(\"rsna_v3 EXP-003-parity OK\")\n"},{"id":"e5-lab","cell_type":"code","metadata":{},"execution_count":null,"outputs":[],"source":"import base64, os, hashlib\nparts = []\nparts.append(\"IyAtKi0gY29kaW5nOiB1dGYtOCAtKi0NCiIiInJzbmFfcmVwb3J0X2xhYmVscyBFWFAtMDA1IC0gcGx1bWJpbmc6IGFkbWl0IEdMT0JBTF9PQSArIFN5bm92aXRpcy1lZmZ1c2lvbiBzb2Z0IHNjb3Jlcw0KDQpFWFAtMDA1IHNpbmdsZSB2YXJpYWJsZSB2cyBiYXNlbGluZSBsYWJlbHM6IG9ubHkgcmVwb3J0X3Njb3JlX3RvX3RhcmdldCAvIGV4dHJhY3Qgc29mdCBmbGFncy4NCg0KT3JpZ2luYWw6IOS7juaUvuWwhOaKpeWRiuaWh+acrOaKveWPliAxMiDnl4XngbblvLHmoIfnrb4o5aSa6K+t6KiA6KeE5YiZ5oq95Y+W5ZmoKQ0KDQrmnKzmlofku7bnlLEgdG9wX2tlcm5lbHMvcnNuYS1rbmVlLWJhc2VsaW5lLXYxLmlweW5iIOeahOaKveWPluWZqChjZWxscyA2LTExKeWOn+agt+enu+akjSwNCui0n+i0o+aKiiA0NDA3IOS7veWkmuivreiogCBNUkkg5pS+5bCE5oql5ZGK6L2s5oiQIDEyIOeXheeBtueahOivgeaNruWIhuaVsCArIOe9ruS/oeW6puOAgg0KDQrkuLrku4DkuYjlrZjlnKg65a6Y5pa5IGdvbGQg5Y+q5pyJIDU4IHN0dWR5LOekvuWMuiLova/moIfnrb4i5pWw5o2u6ZuGIDk4LjclIOaYr+Wtl+mdoiAwLjUg5q275YC8DQoo6Zu25aKe6YeP5L+h5oGvKSzlr7zoh7QgQkNFIOair+W6pue6piAw44CBbG9zcyDmgZIgMC42OTPjgIHmqKHlnovlrabkuI3liqgoMjAyNi0wOS0wNiDlrp7or4Ep44CCDQrmiqXlkYrmlofmnKzph4zmiY3mnInnnJ/mraPnmoTkv6Hlj7figJTigJTmnKzmir3lj5blmajljbPkv6Hlj7fmupDjgIINCg0K55So5rOVKOS4jiByc25hX3YzLmxvYWRfbGFiZWxzIOmbhuaIkCzpm7bmjILovb0s57qvIENQVSk6DQogICAgaW1wb3J0IHJzbmFfcmVwb3J0X2xhYmVscyBhcyBSDQogICAgdGFibGUgPSBSLmJ1aWxkX3BzZXVkb190YWJsZSh0cmFpbl9kZikgICAjIFN0dWR5SW5zdGFuY2VVSUQgKyBwc2V1ZG9fPDEyPijliIbmlbDmiJYgTmFOKQ0KDQrovpPlh7ror63kuYko5q+P5LiqIChzdHVkeSwgZmluZGluZykg5qC8KToNCiAgICAxKSBuX3Bvcz4wICAgICAgICAgICAgICAgLT4gc29mdCDnm67moIcgPSDor4Hmja7liIbmlbAoMC43Mn4wLjk1LOaMieS4pemHjeW6pi/ph43lpI3liIbnuqcpDQogICAgMikgbl9wb3M9PTAgYW5kIG5fbmVnPjAgIC0+IHNvZnQg55uu5qCHID0g6K+B5o2u5YiG5pWwKDAuMDR+MC4yMCzlkKblrprmrKHmlbDotorlpJrotorkvY4pDQogICAgMykg5rKJ6buYIC8g5LiN56Gu5a6aICAgICAgICAgLT4gTmFOKOS4jei/m+aNn+WksSznlLEgS25lZURhdGFzZXQgdmFsaWQg5o6p56CB5o6S6ZmkKQ0KICAgIDQpIOWumOaWuSBnb2xkIOeUsSBsb2FkX2xhYmVscyDkvJjlhYjopobnm5Ys5pys6KGo5Y+q5aGr56m657y65qC844CCDQoiIiINCmltcG9ydCBwYW5kYXMgYXMgcGQNCg0KIyAtLS0g5Lul5LiL5Li656S+5Yy65oq95Y+W5Zmo5Y6f5qC356e75qSNKOWLv+aUueivjeWFuCkgLS0tDQojIHNvdXJjZTogdG9wX2tlcm5lbHMvcnNuYS1rbmVlLWJhc2VsaW5lLXYxLmlweW5iIGNlbGxzIDYtMTEgKHJ1bGUgZXh0cmFjdG9yIHNlY3Rpb24pDQojIG5vcm1hbGlzZSAtPiBzZWdtZW50IC0+IHNjb3BlOyBuaW5lIGxhbmd1YWdlcyBwb29sZWQ7IHN0ZW0rc2lkZSBwcm94aW1pdHkgZmFsbGJhY2s7DQojIGFzc2VydGlvbi9uZWdhdGlvbi9oZWRnZSBwb2xhcml0eSBwZXIgY2xhdXNlOyBncmFkZWQgc2V2ZXJpdHkgc2NvcmluZy4NCg0KDQppbXBvcnQgcmUNCmltcG9ydCB1bmljb2RlZGF0YQ0KDQpUQVJHRVRTID0gWw0KICAgICJBQ0wiLCAiTUNMIiwgIk1lZGlhbCBNZW5pc2N1cyIsICJMYXRlcmFsIE1lbmlzY3VzIiwNCiAgICAiTWVkaWFsIE9BIiwgIkxhdGVyYWwgT0EiLCAiUEYgT0EiLCAiRWZmdXNpb24iLA0KICAgICJTeW5vdml0aXMiLCAiQmFrZXIncyIsICJDb250dXNpb24iLCAiRnJhY3R1cmUiLA0KXQ0KDQoNCiMgVHVya2lzaCBkb3R0ZWQvZG90bGVzcyBpIG11c3QgYmUgZm9sZGVkIGJlZm9yZSBjYXNlZm9sZGluZywgb3RoZXJ3aXNlICLEsFpMRU5NRVoiDQojIGFuZCAiaXpsZW5tZXoiIGRpdmVyZ2UuIMOfIGFuZCB0aGUgQ3JvYXRpYW4vU2VyYmlhbiBkLXdpdGgtc3Ryb2tlIGxpa2V3aXNlLg0KX1BSRSA9IHN0ci5tYWtldHJhbnMoew0KICAgICLEsSI6ICJpIiwgIsSwIjogImkiLCAiSSI6ICJpIiwgIsOfIjogInNzIiwgIsSRIjogImQiLCAixJAiOiAiZCIsDQogICAgIsO4IjogIm8iLCAiw5giOiAibyIsICLDpiI6ICJhZSIsICLDhiI6ICJhZSIsDQp9KQ0KDQoNCmRlZiBub3JtYWxpemUodGV4dDogc3RyKSAtPiBzdHI6DQogICAgIiIiRm9sZCBjYXNlLCBkaWFjcml0aWNzIGFuZCBzZXBhcmF0b3JzOyBrZWVwIEdyZWVrIGFuZCBDeXJpbGxpYyBsZXR0ZXJzLg0KDQogICAgTkZLRCBkZWNvbXBvc2l0aW9uIHN0cmlwcyBMYXRpbiBhY2NlbnRzIGFuZCBHcmVlayB0b25vcyBhbGlrZSAozqwgLT4gzrEpLCB3aGljaCBpcyB3aGF0DQogICAgd2Ugd2FudDogcmVwb3J0cyBhcmUgaW5jb25zaXN0ZW50IGFib3V0IGFjY2VudHMuIEl0IGFsc28gbWFwcyB0aGUgTUlDUk8gU0lHTiBVKzAwQjUNCiAgICB0byBhIHJlYWwgbXUsIHdoaWNoIG1hdHRlcnMgYmVjYXVzZSBtb3N0IEdyZWVrIHJlcG9ydHMgaGVyZSB1c2UgdGhlIHdyb25nIGNvZGVwb2ludC4NCiAgICAiIiINCiAgICBpZiBub3QgaXNpbnN0YW5jZSh0ZXh0LCBzdHIpOg0KICAgICAgICByZXR1cm4gIiINCiAgICB0ZXh0ID0gdGV4dC50cmFuc2xhdGUoX1BSRSkubG93ZXIoKQ0KICAgIHRleHQgPSB1bmljb2RlZGF0YS5ub3JtYWxpemUoIk5GS0QiLCB0ZXh0KQ0KICAgIHRleHQgPSAiIi5qb2luKGNoIGZvciBjaCBpbiB0ZXh0IGlmIG5vdCB1bmljb2RlZGF0YS5jb21iaW5pbmcoY2gpKQ0KICAgIHRleHQgPSB0ZXh0LnJlcGxhY2UoIsKtIiwgIiIpICAgICAgICAgICAgICAgICAgICAjIHNvZnQgaHlwaGVuDQogICAgdGV4dCA9IHJlLnN1YihyIltfXC0vXFxdKyIsICIgIiwgdGV4dCkNCiAgICB0ZXh0ID0gcmUuc3ViKHIiWyBcdF0rIiwgIiAiLCB0ZXh0KQ0KICAgIHJldHVybiB0ZXh0DQoNCg0KX1NFTlRfU1BMSVQgPSByZS5jb21waWxlKHIiKD88PVsuOyE/XSlccyt8XG4rIikNCg0KDQpkZWYgY2xhdXNlcyh0ZXh0OiBzdHIpOg0KICAgICIiIlNwbGl0IGludG8gY2xhdXNlcywgdGhlbiBhdHRhY2ggYGhlYWRlcjpgIGxpbmVzIHRvIHRoZSB2YWx1ZSB0aGF0IGZvbGxvd3MuDQoNCiAgICBBIHJlcG9ydCBsaW5lIHJlYWRpbmcgYEZyYWN0dXJlcyA6YCBmb2xsb3dlZCBieSBgQXVjdW5lLmAgaXMgb25lIHN0YXRlbWVudC4gU3BsaXR0aW5nDQogICAgb24gcHVuY3R1YXRpb24gYWxvbmUgc2VwYXJhdGVzIHRoZSBhbmF0b215IGZyb20gaXRzIG5lZ2F0aW9uIGFuZCBmbGlwcyB0aGUgbGFiZWwuDQogICAgIiIiDQogICAgbm9ybSA9IG5vcm1hbGl6ZSh0ZXh0KQ0KICAgIHJhdyA9IFtjLnN0cmlwKCkgZm9yIGMgaW4gX1NFTlRfU1BMSVQuc3BsaXQobm9ybSkgaWYgYyBhbmQgYy5zdHJpcCgpXQ0KDQogICAgbWVyZ2VkID0gW10NCiAgICBmb3IgaSwgYyBpbiBlbnVtZXJhdGUocmF3KToNCiAgICAgICAgIyBBIGZyYWdtZW50IGVuZGluZyBpbiBhIGNvbG9uIGlzIGEgaGVhZGluZyBmb3IgdGhlIG5leHQgZnJhZ21lbnQuIFN0cnVjdHVyZWQNCiAgICAgICAgIyBFbmdsaXNoIHJlcG9ydHMgd3JpdGUgbG9uZyBvbmVzIC0gImxhdGVyYWwgY29tcGFydG1lbnQgKG1lbmlzY3VzLCBjb2xsYXRlcmFsDQogICAgICAgICMgbGlnYW1lbnQgY29tcGxleCwgY2FydGlsYWdlKToiIGlzIGVpZ2h0IHdvcmRzIC0gc28gdGhlIGNhcCBpcyBnZW5lcm91cy4NCiAgICAgICAgIw0KICAgICAgICAjIEEgbWVyZ2VkIGhlYWRpbmcgbXVzdCBOT1QgYWxzbyBzdGFuZCBhbG9uZS4gT24gaXRzIG93biBpdCBjYXJyaWVzIHRoZSBhbmF0b215DQogICAgICAgICMgd29yZCB3aXRoIG5vIG5lZ2F0aW9uIGluIHNjb3BlLCBzbyBgRnJhY3R1cmVzIDpgIC8gYEF1Y3VuZS5gIGFzc2VydGVkIGEgZnJhY3R1cmUNCiAgICAgICAgIyBvZmYgdGhlIGhlYWRpbmcgd2hpbGUgdGhlIGpvaW5lZCBjbGF1c2UgY29ycmVjdGx5IHJlYWQgdGhlIGRlbmlhbC4gVGhlIGpvaW5lZA0KICAgICAgICAjIGNsYXVzZSBpcyBhIHN1cGVyc2V0IG9mIHRoZSBoZWFkaW5nLCBzbyBub3RoaW5nIGlzIGxvc3QgYnkgZHJvcHBpbmcgaXQ7IGENCiAgICAgICAgIyBoZWFkaW5nIHdpdGggbm8gdmFsdWUgYmVuZWF0aCBpdCBpcyBub3QgbWVyZ2VkIGFuZCBzdGlsbCBzdGFuZHMuDQogICAgICAgIGlmIGMuZW5kc3dpdGgoIjoiKSBhbmQgbGVuKGMuc3BsaXQoKSkgPD0gMTQgYW5kIGkgKyAxIDwgbGVuKHJhdyk6DQogICAgICAgICAgICBtZXJnZWQuYXBwZW5kKGMgKyAiICIgKyByYXdbaSArIDFdKQ0KICAgICAgICBlbHNlOg0KICAgICAgICAgICAgbWVyZ2VkLmFwcGVuZChjKQ0KICAgICMgQ29tbWEtc2VwYXJhdGVkIGVudW1lcmF0aW9ucyBpbnNpZGUgYSBsb25nIGNsYXVzZSBoaWRlIHNlcGFyYXRlIGFzc2VydGlvbnMuDQogICAgb3V0ID0gW10NCiAgICBmb3IgYyBpbiBtZXJnZWQ6DQogICAgICAgIG91dC5hcHBlbmQoYykNCiAgICAgICAgaWYgbGVuKGMuc3BsaXQoKSkgPiAyNToNCiAgICAgICAgICAgIG91dC5leHRlbmQocC5zdHJpcCgpIGZvciBwIGluIGMuc3BsaXQoIiwiKSBpZiBsZW4ocC5zcGxpdCgpKSA+IDIpDQogICAgcmV0dXJuIG91dA0KDQoNCmRlZiBfcngoKmFsdHM6IHN0cikgLT4gcmUuUGF0dGVybjoNCiAgICByZXR1cm4gcmUuY29tcGlsZSgifCIuam9pbihhbHRzKSkNCg0KDQpORUdBVElPTiA9IF9yeCgNCiAgICAjIGVuDQogICAgciJcYm5vXGIiLCByIlxibm90XGIiLCByIlxid2l0aG91dFxiIiwgciJcYm5lZ2F0aXZlIGZvclxiIiwgciJcYmFic2VuY2VcYiIsDQogICAgciJcYm5vIGV2aWRlbmNlXGIiLCByIlxidW5yZW1hcmthYmxlXGIiLCByIlxiZnJlZSBvZlxiIiwgciJcYm5vbmVcYiIsIHIiXGJuaWxcYiIsDQogICAgIyBlcw0KICAgIHIiXGJzaW5cYiIsIHIiXGJubyBoYXlcYiIsIHIiXGJhdXNlbmNpYVxiIiwgciJcYmF1c2VudGVzP1xiIiwNCiAgICAjIGZyDQogICAgciJcYnBhcyBkZVxiIiwgciJcYnNhbnNcYiIsIHIiXGJhdWN1bmU/XGIiLCByIlxiYWJzZW5jZVxiIiwNCiAgICAjIG5sDQogICAgciJcYmdlZW5cYiIsIHIiXGJ6b25kZXJcYiIsIHIiXGJuaWV0XGIiLA0KICAgICMgZGUNCiAgICByIlxia2VpbmU/XGIiLCByIlxib2huZVxiIiwgciJcYm5pY2h0XGIiLA0KICAgICMgdHINCiAgICByIlxieW9rXGIiLCByIlxieW9rdHVyXGIiLCByIml6bGVubWVtZWt0ZSIsIHIic2FwdGFubWFkaSIsIHIiXGJkZWdpbFxiIiwNCiAgICByImdvemxlbm1lbWVrdGUiLCByIm1ldmN1dCBkZWdpbCIsIHIiZXNsaWsgZXRtaXlvciIsIHIiXGJpemxlbm1lZGlcYiIsDQogICAgIyBociAvIHNyIC8gYnMNCiAgICByIlxibmVtYVxiIiwgciJcYmJlelxiIiwgciJcYm5pc3VcYiIsIHIiXGJuaWplXGIiLA0KICAgICMgZWwgKGFjY2VudHMgYWxyZWFkeSBzdHJpcHBlZCkNCiAgICByIlxizrTOtc69XGIiLCByIlxiz4fPic+BzrnPglxiIiwgciLOv8+FzrTOtc69IiwNCiAgICAjIGJnIC8gcnUNCiAgICByIlxi0LHQtdC3XGIiLCByIlxi0L3QtVxiIiwgciLQu9C40L/RgdCy0LAiLCByIlxi0L3Rj9C80LBcYiIsDQopDQoNCk5PUk1BTElUWSA9IF9yeCgNCiAgICByIlxibm9ybWFsIiwgciJcYmludGFjdFxiIiwgciJcYnByZXNlcnZlZFxiIiwgciJcYndpdGhpbiBub3JtYWwgbGltaXRzXGIiLA0KICAgIHIibGltaXRlcyBub3JtYWxlcyIsIHIiXGJjb25zZXJ2YWQiLCByIlxiaW50ZWdyIiwgciJcYm5vcm1hbGVzXGIiLA0KICAgIHIiXGJkb2dhKGx8bGwpXGIiLCByImtvcnVubXVzIiwgciJcYm5vcm1hbGRpclxiIiwgciJvbGFnYW4iLA0KICAgIHIiXGJ1cmVkbiIsIHIiXGJvY3V2YW4iLCByIlxib2RyemFuIiwgciJcYmludGFrdCIsDQogICAgciLPhs+Fz4POuc6/zrvOv86zzrnOuiIsIHIizrHOus61z4HOsc65IiwNCiAgICByInVuYXVmZmFsbGlnIiwgciJyZWdlbHJlY2h0IiwgciJcYmludGFrdFxiIiwNCiAgICByItC90L7RgNC80LDQuyIsIHIi0LfQsNC/0LDQt9C10L0iLCByItGB0YrRhdGA0LDQvdC10L0iLCByIlxi0LHQtdC3INC+0YHQvtCx0LXQvdC+0YHRgtC4XGIiLA0KICAgIHIiXGJnYWFmXGIiLCByIlxibm9ybWFhbFxiIiwNCikNCg0KVU5DRVJUQUlOID0gX3J4KA0KICAgIHIiXGJwb3NzaWJsZVxiIiwgciJcYnByb2JhYmxlXGIiLCByIlxic3VzcGljaW91c1xiIiwgciJcYnN1c3BlY3RlZFxiIiwNCiAgICByImNhbm5vdCAoYmUgKT9leGNsdWRlIiwgciJcYm1heVxiIiwgciJcYnF1ZXN0aW9uYWJsZVxiIiwgciJcYmVxdWl2b2NhbFxiIiwNCiAgICByIlxicG9zaWJsZVxiIiwgciJzaW4gY3JpdGVyaW9zIGNhdGVnb3JpY29zIiwgciJcYmR1ZG9zIiwNCiAgICByIlxibXVodGVtZWxcYiIsIHIiXGJvbGFzaVxiIiwgciJcYnN1cGhlbGlcYiIsIHIiXGJpemxlbmltIiwNCiAgICByIlxibW9ndWNlXGIiLCByIlxidmplcm9qYXRub1xiIiwgciJcYnN1bW5qYVxiIiwNCiAgICByIs+AzrnOuM6xzr0iLCByIs+Fz4DOv8+Az4QiLA0KICAgIHIiXGJtb2dsaWNoIiwgciJcYnZlcmRhY2h0aWciLCByIlxiZnJhZ2xpY2giLCByIlxiVlwuYVwuXGIiLA0KICAgIHIiXGLQstGK0LfQvNC+0LbQvdC+XGIiLCByIlxi0LLQtdGA0L7Rj9GC0L3QvlxiIiwgciLRgdGD0YHQv9C10LrRgiIsDQogICAgciJcYm1vZ2VsaWprXGIiLCByIlxidmVyZGFjaHRcYiIsDQopDQoNCiMgUGF0aG9sb2d5IHZvY2FidWxhcnkgc2hhcmVkIGJ5IHRoZSBwYWlyZWQgcnVsZXMuDQpURUFSID0gX3J4KA0KICAgIHIiXGJ0ZWFyIiwgciJcYnRvcm5cYiIsIHIiXGJydXB0dXJlIiwgciJcYmRpc3J1cHRpb25cYiIsIHIiZGlzY29udGludWl0IiwNCiAgICByIlxiYXZ1bHMiLA0KICAgIHIiXGJyb3R1cmFcYiIsIHIiXGJyb3R1cmFzXGIiLCByIlxicnVwdHVyYSIsIHIiXGJkZXNnYXJybyIsIHIiXGJyb3RvXGIiLA0KICAgIHIiXGJkZWNoaXJ1cmUiLCByIlxiZGVjaGlyZSIsDQogICAgciJcYnNjaGV1ciIsIHIiXGJydXB0dXVyIiwgciJnZXNjaGV1cmQiLA0KICAgIHIicmlzcyhiaWxkdW5nfGV8ZXMpP1xiIiwgciJlaW5yaXNzIiwgciJcYnJ1cHR1ciIsIHIiemVycmVpc3MiLCByIlxibGFzaW9uIiwNCiAgICByIlxieWlydGlrIiwgciJcYnlpcnRpZyIsIHIiXGJrb3BtYVxiIiwgciJidXR1bmx1ayBrYXliaSIsIHIiXGJydXB0dXJ1XGIiLA0KICAgIHIiXGJwdWtudWNlIiwgciJcYnJ1cHR1ciIsIHIiXGJwcmVraWRcYiIsIHIiXGJwdWtvdGluIiwNCiAgICByIs+BzrfOvs63IiwgciLPgc63zr7Ouc+CIiwgciLPgc63zrPOvM6xIiwNCiAgICByItGA0YPQv9GC0YPRgNCwIiwgciLRgNCw0LfQutGK0YHQsiIsIHIi0YDQsNC30YDQuNCyIiwgciLRgdC60YrRgdCyIiwNCikNCg0KREVHRU4gPSBfcngoDQogICAgciJkZWdlbmVyYXQiLCByIlxibXVjb2lkXGIiLCByIlxibXl4b2lkXGIiLCByIlxiZnJheSIsIHIiXGJmaXNzdXIiLA0KICAgIHIiZGVqZW5lcmF0aWYiLCByIlxibXVrb2lkXGIiLCByImRlZ2VuZXJhdGl2biIsIHIizrXOus+Gz4XOuyIsIHIi0LTQtdCz0LXQvdC10YDQsNGCIiwNCiAgICByIlxizrzPhc6+zr/Otc65zrQiLCByIlxizrzPhc6+z4nOtCIsDQogICAgciJcYm11Y28gP2lkZVxiIiwgciJhdWZnZWZhc2VydCIsDQopDQoNCklOSlVSWSA9IF9yeCgNCiAgICByIlxiaW5qdXIiLCByIlxic3ByYWluIiwgciJcYmxlc2lvbiIsIHIiXGJsYXNpb24iLCByIlxiZWRlbWFcYiIsIHIiXGJvZWRlbWFcYiIsDQogICAgciJcYm9kZW1cYiIsIHIiXGJlZGVtXGIiLCByIlxizr/Ouc60zrfOvM6xIiwgciJcYtC+0LTQtdC8IiwgciJcYtC10LTQtdC8IiwgciJcYnN0cmFpblxiIiwNCiAgICByIlxiaGlnaCBzaWduYWxcYiIsIHIiXGJzaWduYWwgYWx0ZXJhdGlvblxiIiwgciJcYmhpcGVyaW50ZW5zIiwgciJcYmh5cGVyaW50ZW5zIiwNCiAgICByImF1bWVudG8gZGUgc2VuYWwiLCByImFsdGVyYWNpb24gZGUgc2VuYWwiLCByImNhbWJpbyBkZSBzZW5hbCIsDQogICAgciJcYnNpZ25hbGFuaGVidW5nIiwgciJcYnNpZ25hbGFsdGVyYXRpb24iLCByInZlcmhvb2dkIHNpZ25hYWwiLCByInNpbnlhbCBhcnRpcyIsDQogICAgciLOsc+Fzr7Ot868zrXOvc6/IM+DzrfOvM6xIiwgciLQv9C+0LLQuNGI0LXQvSDRgdC40LPQvdCw0LsiLA0KICAgIHIiXGJ0aGlja2VuIiwgciJcYnphZGVibGphbmplXGIiLCByIlxidmVyZGlra2luZ1xiIiwgciJcYmRpc3RlbnppaiIsDQogICAgciJcYmxha3NpdGVcYiIsIHIiXGJsYXhpdHlcYiIsIHIiXGJwYXJ0aWFsXGIiLCByIlxicGFyY2lqYWxuIiwgciJcYnBhcmNpYWwiLA0KICAgIHIiXGJwYXJ0aWVsIiwgciJcYnBhcnRpZWxsIiwNCikNCg0KDQpBTkFUID0gew0KICAgICJBQ0wiOiBfcngoDQogICAgICAgIHIiYW50ZXJpb3IgY3J1Y2lhdGUiLCByIlxiYWNsXGIiLA0KICAgICAgICByImNydXphZG8gYW50ZXJpb3IiLCByIlxibGNhXGIiLA0KICAgICAgICByImNyb2lzZSBhbnRlcmlldXIiLA0KICAgICAgICByInZvb3JzdGUga3J1aXNiYW5kIiwgciJcYnZrYlxiIiwNCiAgICAgICAgciJ2b3JkZXJlcyBrcmV1emJhbmQiLCByInZvcmRlcmVuIGtyZXV6YmFuZCIsIHIidm9yZGVyZSBrcmV1emJhbmQiLA0KICAgICAgICByIm9uIGNhcHJheiIsIHIiXGJvY2JcYiIsDQogICAgICAgIHIicHJlZG5qaSBrcml6bmkiLCByInByZWRuamVnIGtyaXpuIiwNCiAgICAgICAgciLPgM+Bzr/Pg864zrlbzr/OsV1bXiBdKiDPh865zrHPg8+EIiwgciLPgM+Bzr/Pg864zrnOv8+FIM+HzrnOsc+Dz4TOv8+FIiwgciLPh865zrHPg8+Ezr9bXiBdKiDPg8+Fzr3OtM61z4POvCIsDQogICAgICAgICMgIs+HzrnOsc+Dz4TOv865IM66zrHOuSDPgM67zrHOs865zr/OuSDPg8+Fzr3OtM61z4POvM6/zrkiIHNlcGFyYXRlcyB0aGUgYWRqZWN0aXZlIGZyb20gaXRzIG5vdW4sIHNvIHRoZQ0KICAgICAgICAjIGFkamVjdGl2ZSBzdGVtIGhhcyB0byBzdGFuZCBhbG9uZS4gR3JlZWsgbWFya3MgY3J1Y2lhdGUgd2l0aCBpdCB1bmFtYmlndW91c2x5Lg0KICAgICAgICByIlxiz4fOuc6xz4PPhFx3KiIsDQogICAgICAgIHIi0L/RgNC10LTQvdCwINC60YDRitGB0YLQvdCwIiwgciLQv9GA0LXQtNC90LDRgtCwINC60YDRitGB0YLQvdCwIiwNCiAgICAgICAgIyBQbHVyYWwsIHVucXVhbGlmaWVkOiByZXBvcnRzIHJvdXRpbmVseSBjbGVhciBib3RoIGNydWNpYXRlcyBpbiBvbmUgY2xhdXNlDQogICAgICAgICMgKCJMaWdhbWVudG9zIGNydXphZG9zIHkgY29sYXRlcmFsZXMgZGVudHJvIGRlIGxpbWl0ZXMgbm9ybWFsZXMiKSwgc28gdGhlDQogICAgICAgICMgcGx1cmFsIGZvcm0gaGFzIHRvIG1hdGNoIHdpdGhvdXQgYSBzaWRlIHF1YWxpZmllciBvciB0aGUgd2hvbGUgY2xhdXNlIGlzIGxvc3QuDQogICAgICAgIHIiY3J1Y2lhdGUgbGlnYW1lbnRzIiwgciJsaWdhbWVudG9zIGNydXphZG9zIiwgciJsaWdhbWVudHMgY3JvaXNlcyIsDQogICAgICAgIHIia3J1aXNiYW5kZW4iLCByImtyZXV6YmFuZGVyIiwgciJjYXByYXogYmFnbGFyIiwgciJrcml6blthLXpdKiBsaWdhbWVudFthLXpdKiIsDQogICAgICAgIHIiz4fOuc6xz4PPhM6/zrkgz4PPhc69zrTOtc+DzrwiLCByIs+HzrnOsc+Dz4TPic69IM+Dz4XOvc60zrXPg868IiwgciLQutGA0YrRgdGC0L3QuNGC0LUg0LLRgNGK0LfQutC4IiwgciLQutGA0YrRgdGC0L3QuCDQstGA0YrQt9C60LgiLA0KICAgICksDQogICAgIk1DTCI6IF9yeCgNCiAgICAgICAgciJtZWRpYWwgY29sbGF0ZXJhbCIsIHIiXGJtY2xcYiIsIHIidGliaWFsIGNvbGxhdGVyYWwiLA0KICAgICAgICByImNvbGF0ZXJhbCBtZWRpYWwiLCByImNvbGF0ZXJhbCBpbnRlcm5vIiwgciJcYmxjbVxiIiwNCiAgICAgICAgciJjb2xsYXRlcmFsIG1lZGlhbCIsIHIiY29sbGF0ZXJhbCBpbnRlcm5lIiwNCiAgICAgICAgciJtZWRpYWxlIGNvbGxhdGVyYWxlIiwgciJiaW5uZW5iYW5kIiwgciJcYihtZWRpYWxlfGxhdGVyYWxlKSBiYW5kZW5cYiIsDQogICAgICAgIHIiXGJjb2xsYXRlcmFsZSBiYW5kZW5cYiIsDQogICAgICAgIHIiaW5uZW5iYW5kIiwgciJtZWRpYWxlcz8ga29sbGF0ZXJhbCIsDQogICAgICAgIHIiXGJpYyB5YW4gYmFnIiwgciJtZWRpYWwga29sbGF0ZXJhbCIsIHIiXGJpeWJcYiIsDQogICAgICAgIHIibWVkaWphbG5pIGtvbGF0ZXJhbG4iLCByIm1lZGlqYWxub2cga29sYXRlcmFsbiIsDQogICAgICAgIHIizrXPg8+JIM+AzrvOsc6zzrkiLCByIs61z4PPic+EzrXPgc65zrrOvyDPgM67zrHOs865IiwgciJcYs+AzrvOsc6zzrlcdyogz4PPhc69zrTOtc+DzrwiLCByIlxiz4DOu86xzrPOuc6/zrlcYiIsDQogICAgICAgIHIi0LzQtdC00LjQsNC70LXQvSDQutC+0LvQsNGC0LXRgNCw0LsiLCByItCy0YrRgtGA0LXRiNC90LAg0YHRgtGA0LDQvdC40YfQvdCwIiwgciJcYtC60L7Qu9Cw0YLQtdGA0LDQu1x3KiIsDQogICAgICAgICMgU2FtZSBwbHVyYWwgcGF0dGVybiBhcyB0aGUgY3J1Y2lhdGVzLg0KICAgICAgICAjICJMaWdhbWVudG9zIGNydXphZG9zIHkgY29sYXRlcmFsZXMiIHNlcGFyYXRlcyB0aGUgbm91biBmcm9tIGl0cyBhZGplY3RpdmUsIHNvDQogICAgICAgICMgdGhlIGFkamVjdGl2ZSBoYXMgdG8gc3RhbmQgYWxvbmUgYXMgYSBjdWUuDQogICAgICAgIHIiXGJjb2xhdGVyYWxlc1xiIiwgciJcYmNvbGxhdGVyYXV4XGIiLCByIlxiY29sbGF0ZXJhbGVuXGIiLCByIlxia29sYXRlcmFsbmlcYiIsDQogICAgICAgIHIiY29sbGF0ZXJhbCBsaWdhbWVudHMiLCByImxpZ2FtZW50b3MgY29sYXRlcmFsZXMiLCByImxpZ2FtZW50cyBjb2xsYXRlcmF1eCIsDQogICAgICAgIHIiY29sbGF0ZXJhbGUgYmFuZGVuIiwgciJrb2xsYXRlcmFsYmFuZGVyIiwgciJzZWl0ZW5iYW5kZXIiLCByInlhbiBiYWdsYXIiLA0KICAgICAgICByImtvbGF0ZXJhbG5bYS16XSogbGlnYW1lbnRbYS16XSoiLCByIs+AzrvOsc6zzrnOv865IM+Dz4XOvc60zrXPg868IiwgciLPgM67zrHOs865z4nOvSDPg8+Fzr3OtM61z4POvCIsDQogICAgICAgIHIi0LrQvtC70LDRgtC10YDQsNC70L3QuCDQstGA0YrQt9C60LgiLCByItGB0YLRgNCw0L3QuNGH0L3QuNGC0LUg0LLRgNGK0LfQutC4IiwNCiAgICApLA0KICAgICJNZWRpYWwgTWVuaXNjdXMiOiBfcngoDQogICAgICAgIHIibWVkaWFsIG1lbmlzY3VzIiwgciJcYm1tXGIoPz0gdGVhcikiLCByIm1lZGlhbCBtZW5pc2MiLA0KICAgICAgICByIm1lbmlzY28gbWVkaWFsIiwgciJtZW5pc2NvIGludGVybm8iLA0KICAgICAgICByIm1lbmlzcXVlIG1lZGlhbCIsIHIibWVuaXNxdWUgaW50ZXJuZSIsDQogICAgICAgIHIibWVkaWFsZSBtZW5pc2N1cyIsIHIiYmlubmVubWVuaXNjdXMiLA0KICAgICAgICByImlubmVubWVuaXNrdXMiLCByIm1lZGlhbGVuPyBtZW5pc2t1cyIsIHIiaW5uZW5tZW5pc2t1c2hpbnRlcmhvcm4iLA0KICAgICAgICByIm1lZHlhbCBtZW5pc2siLCByIlxiaWMgbWVuaXNrIiwNCiAgICAgICAgciJtZWRpamFsbmkgbWVuaXNrdXMiLCByIm1lZGlqYWxub2cgbWVuaXNrdXNhIiwgciJtZWRpamFsbm9tIG1lbmlza3VzdSIsDQogICAgICAgIHIizrXPg8+JIM68zrfOvc65z4POuiIsIHIizrzOt869zrnPg866W14gXSogz4TOv8+FIM61z4PPiSIsIHIizrXPg8+JIM60zrnOsc68zrXPgc65z4POvM6xW14uXXswLDQwfc68zrfOvc65z4POuiIsDQogICAgICAgIHIi0LzQtdC00LjQsNC70L3QuNGPINC80LXQvdC40YHQutGD0YEiLCByItC80LXQtNC40LDQu9C10L0g0LzQtdC90LjRgdC60YPRgSIsIHIi0LLRitGC0YDQtdGI0L3QuNGPINC80LXQvdC40YHQutGD0YEiLA0KICAgICksDQogICAgIkxhdGVyYWwgTWVuaXNjdXMiOiBfcngoDQogICAgICAgIHIibGF0ZXJhbCBtZW5pc2N1cyIsIHIibGF0ZXJhbCBtZW5pc2MiLA0KICAgICAgICByIm1lbmlzY28gbGF0ZXJhbCIsIHIibWVuaXNjbyBleHRlcm5vIiwNCiAgICAgICAgciJtZW5pc3F1ZSBsYXRlcmFsIiwgciJtZW5pc3F1ZSBleHRlcm5lIiwNCiAgICAgICAgciJsYXRlcmFsZSBtZW5pc2N1cyIsIHIiYnVpdGVubWVuaXNjdXMiLA0KICAgICAgICByImF1c3Nlbm1lbmlza3VzIiwgciJsYXRlcmFsZW4/IG1lbmlza3VzIiwNCiAgICAgICAgciJsYXRlcmFsIG1lbmlzayIsIHIiXGJkaXMgbWVuaXNrIiwNCiAgICAgICAgciJsYXRlcmFsbmkgbWVuaXNrdXMiLCByImxhdGVyYWxub2cgbWVuaXNrdXNhIiwgciJsYXRlcmFsbm9tIG1lbmlza3VzdSIsDQogICAgICAgIHIizrXOvs+JIM68zrfOvc65z4POuiIsIHIizrzOt869zrnPg866W14gXSogz4TOv8+FIM61zr7PiSIsIHIizrXOvs+JIM60zrnOsc68zrXPgc65z4POvM6xW14uXXswLDQwfc68zrfOvc65z4POuiIsDQogICAgICAgIHIi0LvQsNGC0LXRgNCw0LvQvdC40Y8g0LzQtdC90LjRgdC60YPRgSIsIHIi0LvQsNGC0LXRgNCw0LvQtdC9INC80LXQvdC40YHQutGD0YEiLCByItCy0YrQvdGI0L3QuNGPINC80LXQvdC40YHQutGD0YEiLA0KICAgICksDQp9DQoNCiMgT3N0ZW9hcnRocml0aXMgaXMgcmFyZWx5IHdyaXR0ZW4gYXMgIm9zdGVvYXJ0aHJpdGlzIi4gSXQgaXMgd3JpdHRlbiBhcyBjYXJ0aWxhZ2UgbG9zcywNCiMgY2hvbmRyb3BhdGh5IGdyYWRlLCBqb2ludCBzcGFjZSBuYXJyb3dpbmcsIG9yIG9zdGVvcGh5dGVzIC0gc2NvcGVkIHRvIGEgY29tcGFydG1lbnQuDQpPQV9FVklERU5DRSA9IF9yeCgNCiAgICByIm9zdGVvYXJ0aHJpdCIsIHIiXGJhcnRocm9zIiwgciJcYmdvbmFydGhyb3MiLCByIlxib3N0ZW9hcnRocm9zIiwNCiAgICByImNob25kcm9wYXRoIiwgciJjaG9uZHJvbWFsYWMiLCByImNvbmRyb3BhdCIsIHIiY29uZHJvbWFsYWMiLA0KICAgIHIiY2FydGlsYWdlIGxvc3MiLCByImNhcnRpbGFnZSB0aGlubmluZyIsIHIiY2hvbmRyYWwgKGxvc3N8ZGVmZWN0fHVsY2VyfHRoaW5uaW5nKSIsDQogICAgciJvc3Rlb3BoeXQiLCByIm9zdGVvZml0IiwgciJvc3Rlb2Z5dCIsIHIib3N0ZW9maXRvIiwgciJvc3Rlb3BoeXRlbiIsDQogICAgciJqb2ludCBzcGFjZSBuYXJyb3dpbmciLCByInBpbnphbWllbnRvIGFydGljdWxhciIsDQogICAgciJraWtpcmRhayBrYXliIiwgciJraWtpcmRhayBpbmNlbG1lIiwgciJrb25kcm9wYXRpIiwgciJrb25kcmFsIiwNCiAgICByImtyYWFrYmVlbihsaWpkZW58dmVybGllcykiLCByImdvbmFydHJvc2UiLCByImFydHJvc2UiLA0KICAgIHIia25vcnBlbCh2ZXJsdXN0fHNjaGFkZW58ZGVmZWt0KSIsIHIiYXJ0aHJvc2UiLCByImdvbmFydGhyb3NlIiwNCiAgICByImhyc2thdmljIiwgciJob25kcm9tYWxhYyIsIHIiYXJ0cm96IiwgciJvc3Rlb2FydHJpdCIsDQogICAgciLPh86/zr3OtM+BW14gXSrPgM6xzrgiLCByIs6xz4HOuM+BzrnPhCIsIHIizrHPgc64z4HPic+DIiwgciLOv8+Dz4TOtc6/z4bPhc+EIiwNCiAgICByIs6xz4HOuM+BzrnOus6/z4Ugz4fOv869zrTPgc6/z4UiLCByIs61zr7Osc67zrXOuc+Izrcgz4TOv8+FIM6xz4HOuM+BzrnOus6/z4Ugz4fOv869zrTPgc6/z4UiLA0KICAgIHIi0LDRgNGC0YDQvtC3IiwgciLRhdC+0L3QtNGA0L7Qv9Cw0YIiLCByItC+0YHRgtC10L7RhNC40YIiLCByItGF0YDRg9GJ0Y/Qu1teLl17MCwzMH0o0LjQt9GC0YrQvXzRg9Cy0YDQtdC0fNC00LXRhNC10LrRgikiLA0KICAgIHIidWxjZXJhW3NdPyBjb25kcmFsIiwgciJjYXJ0aWxhZ29bXi5dezAsMjV9KHBlcmRpZGF8YWRlbGdheikiLA0KICAgIHIiaWNycyBncmFkZSIsIHIib3V0ZXJicmlkZ2UiLA0KKQ0KDQpDT01QQVJUTUVOVCA9IHsNCiAgICAiTWVkaWFsIE9BIjogX3J4KA0KICAgICAgICByIm1lZGlhbCAoZmVtb3JvdGliaWFsfHRpYmlvZmVtb3JhbHxjb21wYXJ0bWVudCkiLA0KICAgICAgICByImNvbXBhcnRpbWVudG8gZmVtb3JvdGliaWFsIG1lZGlhbCIsIHIiZmVtb3JvdGliaWFsIGludGVybm8iLA0KICAgICAgICByIm1lZGlhYWwgZmVtb3JvdGliaWFhbCIsIHIibWVkaWFsZSBmZW1vcm90aWJpYWwiLA0KICAgICAgICByIm1lZGlhbCBmZW1vcm90aWJpYWwiLCByIm1lZGlhbGVuIGtvbXBhcnRpbWVudCIsIHIiaW5uZXJlW3NuXT8ga29tcGFydGltZW50IiwNCiAgICAgICAgciJtZWR5YWwgZmVtb3JvdGliaWFsIiwgciJpYyBrb21wYXJ0bWFuIiwgciJtZWR5YWwga29tcGFydG1hbiIsDQogICAgICAgIHIibWVkaWphbG5bXiBdKiAoZmVtb3JvdGliaXxvZGplbGp8a29tcGFydG0pIiwNCiAgICAgICAgciLOtc+Dz4kgzrTOuc6xzrzOtc+BzrnPg868zrEiLCByIs61z4PPiSDOus69zrfOvM65zrHOuSIsIHIizrXPg8+JIM68zrfPgc65zrHOuSIsDQogICAgICAgIHIi0LzQtdC00LjQsNC70L1bXiBdKiAo0LrQvtC80L/QsNGA0YLQvHzQvtGC0LTQtdC7fNGC0LjQsdC40LDQu3zRhNC10LzQvtGA0L7RgtC40LEpIiwNCiAgICAgICAgciJtZWRpYWwgKGZlbW9yYWx8dGliaWFsKSAoY29uZHlsZXxwbGF0ZWF1KSIsIHIiY29uZGlsbyBmZW1vcmFsIG1lZGlhbCIsDQogICAgICAgIHIibWVkaWFsZW4/IChmZW11cmtvbmR5bHx0aWJpYXBsYXRlYXUpIiwgciJtZWRpYWxlIGZlbW9yYWxlIGNvbmR5bCIsDQogICAgKSwNCiAgICAiTGF0ZXJhbCBPQSI6IF9yeCgNCiAgICAgICAgciJsYXRlcmFsIChmZW1vcm90aWJpYWx8dGliaW9mZW1vcmFsfGNvbXBhcnRtZW50KSIsDQogICAgICAgIHIiY29tcGFydGltZW50byBmZW1vcm90aWJpYWwgbGF0ZXJhbCIsIHIiZmVtb3JvdGliaWFsIGV4dGVybm8iLA0KICAgICAgICByImxhdGVyYWFsIGZlbW9yb3RpYmlhYWwiLCByImxhdGVyYWxlIGZlbW9yb3RpYmlhbCIsDQogICAgICAgIHIibGF0ZXJhbCBmZW1vcm90aWJpYWwiLCByImxhdGVyYWxlbiBrb21wYXJ0aW1lbnQiLCByImF1c3NlcmVbc25dPyBrb21wYXJ0aW1lbnQiLA0KICAgICAgICByImxhdGVyYWwgZmVtb3JvdGliaWFsIiwgciJkaXMga29tcGFydG1hbiIsIHIibGF0ZXJhbCBrb21wYXJ0bWFuIiwNCiAgICAgICAgciJsYXRlcmFsblteIF0qIChmZW1vcm90aWJpfG9kamVsanxrb21wYXJ0bSkiLA0KICAgICAgICByIs61zr7PiSDOtM65zrHOvM61z4HOuc+DzrzOsSIsIHIizrXOvs+JIM66zr3Ot868zrnOsc65IiwgciLOtc6+z4kgzrzOt8+BzrnOsc65IiwNCiAgICAgICAgciLQu9Cw0YLQtdGA0LDQu9C9W14gXSogKNC60L7QvNC/0LDRgNGC0Lx80L7RgtC00LXQu3zRgtC40LHQuNCw0Lt80YTQtdC80L7RgNC+0YLQuNCxKSIsDQogICAgICAgIHIibGF0ZXJhbCAoZmVtb3JhbHx0aWJpYWwpIChjb25keWxlfHBsYXRlYXUpIiwgciJjb25kaWxvIGZlbW9yYWwgbGF0ZXJhbCIsDQogICAgICAgIHIibGF0ZXJhbGVuPyAoZmVtdXJrb25keWx8dGliaWFwbGF0ZWF1KSIsIHIibGF0ZXJhbGUgZmVtb3JhbGUgY29uZHlsIiwNCiAgICApLA0KICAgICJQRiBPQSI6IF9yeCgNCiAgICAgICAgciJwYXRlbGxvZmVtb3JhbCIsIHIiZmVtb3JvcGF0ZWxsYXIiLCByImZlbW9yb3BhdGVsYXIiLCByInBhdGVsb2ZlbW9yYWwiLA0KICAgICAgICByInJldHJvcGF0ZWxsYXIiLCByInJldHJvcm90dWxpYW4iLCByIlxidHJvY2hsZWEiLCByIlxidHJvY2xlYSIsIHIiXGJ0cm9rbGVhIiwNCiAgICAgICAgciJcYnBhdGVsbGFcYiIsIHIiXGJwYXRlbGxhclxiIiwgciJcYnJvdHVsaWFuIiwgciJcYnJvdHVsYVxiIiwgciJcYnBhdGVsZVxiIiwNCiAgICAgICAgciJcYnBhdGVsbGFlP1xiIiwgciJwYXRlbGxvZmVtb3JhYWwiLCByImZlbW9yb3BhdGVsbGFpciIsDQogICAgICAgIHIizrXPgM65zrPOv869zrHPhM65zrQiLCByIs68zrfPgc6/zrXPgM65zrPOv869zrHPhM65zrQiLCByIs+Ez4HOv8+HzrnOuyIsDQogICAgICAgIHIi0L/QsNGC0LXQuyIsIHIi0YTQtdC80L7RgNC+0L/QsNGC0LXQuyIsIHIi0YLRgNC+0LvRhSIsDQogICAgICAgIHIiYW50ZXJpb3IgY29tcGFydG1lbnQiLCByImNvbXBhcnRpbWVudG8gYW50ZXJpb3IiLCByInByZWRualteIF0qIG9kamVsamsiLA0KICAgICksDQp9DQoNCiMgU2VsZi1kZWNsYXJpbmcgZmluZGluZ3M6IHRoZSB0ZXJtIGl0c2VsZiBpcyB0aGUgZmluZGluZy4NCkRJUkVDVCA9IHsNCiAgICAiRWZmdXNpb24iOiBfcngoDQogICAgICAgIHIiXGJlZmZ1c2lvbiIsIHIiam9pbnQgZmx1aWQiLCByImludHJhID9hcnRpY3VsYXIgZmx1aWQiLCByIlxiaHlkcm9wc1xiIiwNCiAgICAgICAgciJkZXJyYW1lIGFydGljdWxhciIsIHIiXGJkZXJyYW1lXGIiLCByImxpcXVpZG8gYXJ0aWN1bGFyIiwNCiAgICAgICAgciJlcGFuY2hlbWVudCIsDQogICAgICAgIHIiZ2V3cmljaHRzdm9jaHQiLCByIlxidm9jaHRcYiIsIHIiXGJoeWRyb3BzXGIiLCByImdld3JpY2h0c2VmZnVzaWUiLA0KICAgICAgICByImdlbGVua2VyZ3VzcyIsIHIiXGJlcmd1c3NcYiIsIHIiZ2VsZW5rc2VyZ3UiLA0KICAgICAgICAjICJkaXogZWtsZW1pIGljaSBzaXZpIG1pa3RhcmkgLi4uIGFydG1pcyIgYW5kICJla2xlbSBpY2VyaXNpbmRlIHlheWdpbiBzaXZpDQogICAgICAgICMgYXJ0aXNpIiBib3RoIG9jY3VyOyB0aGUgbm91biB0YWtlcyBhIHBvc3Nlc3NpdmUgc3VmZml4LCBzbyBgZWtsZW0gYCBhbG9uZQ0KICAgICAgICAjIG1pc3Nlcy4gTWF0Y2ggdGhlIHN0ZW0gcGx1cyBhbnkgc3VmZml4Lg0KICAgICAgICByImVrbGVtXHcqIGljXHcqIHNpdmkiLCByImVmdXp5b24iLCByImVrbGVtIHNpdmlzaSIsDQogICAgICAgIHIic2l2aSAobWlrdGFyaXxhcnRpc2l8YmlyaWtpbWkpIiwgciJzaXZpIGFydGlzIiwgciJcYnNpdmlcYlteLl17MCwyNX1hcnRtaXMiLA0KICAgICAgICByIlxiaXpsamV2IiwgciJcYml6bGl2IiwgciJ6Z2xvYm5bXiBdKiB0ZWt1Y2luIiwgciJcYmhpZHJvcHNcYiIsDQogICAgICAgIHIizrHPgc64z4HOuc66W14gXSogz4XOs8+BIiwgciLPhc6zz4HOv8+FIM61zr3OtM6xz4HOuM+BzrnOus6xIiwgciLOtc69zrTOsc+BzrjPgc65zrpbXiBdKiDPhc6zz4EiLCByIs+Azr/Pg86/z4TOt8+EzrEgz4XOs8+Bzr/PhSIsDQogICAgICAgIHIizrXOvc60zrHPgc64z4HOuc66IiwgciLOsc+BzrjPgc65zrrOtyDPg8+FzrvOu86/zrPOtyIsIHIiz4XOs8+Bzr8gz4PPhM63zr0gzrHPgc64z4HPic+DzrciLCByIs+FzrPPgc6/z4Ugz4PPhM63zr0gzrHPgc64z4HPic+DzrciLA0KICAgICAgICByItGB0YLQsNCy0LXQvSDQuNC30LvQuNCyIiwgciLQuNC30LvQuNCyIiwgciLRgdGC0LDQstC90LAg0YLQtdGH0L3QvtGB0YIiLCByItGB0LjQvdC+0LLQuNCw0LvQvdCwINGC0LXRh9C90L7RgdGCIiwNCiAgICApLA0KICAgICJTeW5vdml0aXMiOiBfcngoDQogICAgICAgIHIic3lub3ZpdCIsIHIic2lub3ZpdCIsIHIic3lub3ZpYWwgKHRoaWNrZW5pbmd8cHJvbGlmZXJhdGlvbnxoeXBlcnRyb3BoKSIsDQogICAgICAgIHIic3lub3ZpdGlzIiwgciJzeW5vdmlhbGU/ICh2ZXJkaWtraW5nfHByb2xpZmVyYXRpZSkiLA0KICAgICAgICByInN5bm92aWFsaXRpcyIsIHIic3lub3ZpYWxpcyh2ZXJkaWNrdW5nfHByb2xpZmVyYXRpb24pIiwNCiAgICAgICAgciJzaW5vdmlqYWxpdGlzIiwgciJzaW5vdml0aXMiLCByInphZGVibGphbmplIHNpbm92aWoiLA0KICAgICAgICByIs+FzrzOtc69zrnPhM65zrTOsSIsIHIiz4PPhc69zr/Oss65z4TOuc60zrEiLCByIs+FzrzOtc69zrnOulteIF0qIM+Fz4DOtc+Bz4TPgc6/z4YiLCByIs6xz4HOuM+BzrnOus6/z4Ugz4XOvM61zr0iLA0KICAgICAgICByItGB0LjQvdC+0LLQuNGCIiwgciLRgdC40L3QvtCy0LjQsNC7W14gXSogKNC30LDQtNC10LHQtdC7fNC/0YDQvtC70LjRhNC10YApIiwNCiAgICAgICAgciJ2ZXJkaWtraW5nZW4gdmFuIChoZXQgKT9zeW5vdml1bSIsIHIicGFubnVzIiwNCiAgICApLA0KICAgICJCYWtlcidzIjogX3J4KA0KICAgICAgICByImJha2VyIiwgciJwb3BsaXRlYWwgY3lzdCIsIHIicXVpc3RlIHBvcGxpdGVvIiwgciJxdWlzdGVzIHBvcGxpdGVvcyIsDQogICAgICAgIHIia3lzdGUgcG9wbGl0ZSIsIHIicG9wbGl0ZWFsZT8gY3lzdCIsIHIicG9wbGl0ZWFsenlzdGUiLCByImJha2VyenlzdGUiLA0KICAgICAgICByInBvcGxpdGVhbCBraXN0IiwgciJcYmJha2Vyb3ZhXGIiLCByInBvcGxpdGVhbG5bXiBdKiBjaXN0IiwNCiAgICAgICAgciLOus+Fz4PPhM63IGJha2VyIiwgciLPgM6/zrvPhc+Hz4nPgc63IM+Dz4XOvc6/zrLOuc6xzrrOtyDOus+Fz4PPhM63IiwgciLOus+Fz4PPhM63IM+Ezr/PhSBiYWtlciIsDQogICAgICAgIHIi0LrQuNGB0YLQsCDQvdCwINCx0LXQudC60YrRgCIsIHIi0LHQtdC50LrRitGA0L7QstCwINC60LjRgdGC0LAiLCByItC/0L7Qv9C70LjRgtC10LDQu9C90LAg0LrQuNGB0YLQsCIsDQogICAgICAgIHIiZ2FzdHJvY25lbWlvID9zZW1pbWVtYnJhbm9zIiwgciJnYXN0cm9jbmVtaXVzIHNlbWltZW1icmFub3N1cyBidXJzIiwNCiAgICApLA0KICAgICJDb250dXNpb24iOiBfcngoDQogICAgICAgIHIiXGJjb250dXNpb24iLCByImJvbmUgYnJ1aXNlIiwgciJib25lIG1hcnJvdyAobz9lZGVtYXxjb250dXNpb24pIiwNCiAgICAgICAgciJcYmtvbnR1eiIsIHIibWVkdWxhciBib25lIG8/ZWRlbWEiLCByIm1hcnJvdyBvP2VkZW1hIiwNCiAgICAgICAgciJjb250dXNpb24gb3NlYSIsIHIiZWRlbWEgb3NlbyIsIHIiZWRlbWEgZGUgbWVkdWxhIG9zZWEiLA0KICAgICAgICByIm9lZGVtZSBvc3NldXgiLCByImNvbnR1c2lvbiBvc3NldXNlIiwNCiAgICAgICAgciJib3Rjb250dXNpZSIsIHIiYm90b2VkZWVtIiwgciJiZWVubWVyZ29lZGVlbSIsIHIiYm90bWVyZ29lZGVlbSIsDQogICAgICAgIHIia25vY2hlbm1hcmtvZGVtIiwgciJrbm9jaGVub2RlbSIsIHIia29udHVzaW9uIiwgciJib25lIGJydWlzZSIsDQogICAgICAgIHIia2VtaWsga29udHV6eW9udSIsIHIia2VtaWsgaWxpZ2kgb2RlbWkiLCByImtlbWlrIG9kZW1pIiwNCiAgICAgICAgciJrb3N0YW5pIGVkZW0iLCByImVkZW0ga29zdGkiLCByImtvbnR1emlqIiwNCiAgICAgICAgciLOv8+Dz4TOtc6/zrzPhc61zrvOuc66W14gXSogzr/Ouc60zrfOvM6xIiwgciLOv8+Dz4TOuc66zr8gzr/Ouc60zrfOvM6xIiwgciLOvM+FzrXOu865zrrOvyDOv865zrTOt868zrEiLA0KICAgICAgICByItC60L7RgdGC0L3QvtC80L7Qt9GK0YfQtdC9INC10LTQtdC8IiwgciLQutC+0YHRgtC10L0g0LXQtNC10LwiLCByItC60L7QvdGC0YPQt9C40L7QvdC10L0iLA0KICAgICksDQogICAgIkZyYWN0dXJlIjogX3J4KA0KICAgICAgICByIlxiZnJhY3R1ciIsIHIiXGJmcmFjdFxiIiwNCiAgICAgICAgciJcYmZyYWN0dXJhIiwgciJcYmZyYWN0dXJhc1xiIiwNCiAgICAgICAgciJcYmZyYWN0dXVyIiwgciJcYmJyZXVrXGIiLA0KICAgICAgICByIlxiZnJha3R1ciIsIHIiXGJicnVjaFxiIiwNCiAgICAgICAgciJcYmtpcmlrXGIiLCByIlxia2lyaWdpXGIiLCByIlxia2lyaWtcYiIsDQogICAgICAgIHIiXGJmcmFrdHVyIiwgciJcYnByaWplbG9tIiwgciJpbXByZXNpanNrW14gXSogZnJha3R1ciIsDQogICAgICAgIHIizrrOsc+EzrHOs868zrEiLCByIs66zrHPhM6xzrPOvM6xz4QiLA0KICAgICAgICByItGE0YDQsNC60YLRg9GAIiwgciLRgdGH0YPQv9Cy0LDQvSIsIHIi0YTQuNGB0YPRgCIsDQogICAgICAgIHIiaW5zdWZmaWNpZW5jeSBmcmFjdHVyZSIsIHIic3RyZXNzIGZyYWN0dXJlIiwgciJhdnVsc2lvbiBmcmFjdHVyZSIsDQogICAgICAgIHIic3ViY2hvbmRyYWwgZnJhY3R1cmUiLCByInN1YmtvbmRyYWwga2lyaSIsDQogICAgKSwNCn0NCg0KIyBUZXJtcyB0aGF0IGxvb2sgbGlrZSBhIGZpbmRpbmcgYnV0IGFyZSBub3QgdGhlIGZpbmRpbmcgYmVpbmcgc2NvcmVkLg0KREVDT1kgPSB7DQogICAgIyBgbm8gZnJhY3R1cmVgIGlzIGRlbGliZXJhdGVseSBhYnNlbnQ6IGEgZGVjb3kgc2tpcHMgdGhlIGNsYXVzZSwgc28gbGlzdGluZyBpdCBoZXJlDQogICAgIyB0dXJuZWQgdGhlIGNvbW1vbmVzdCBFbmdsaXNoIGRlbmlhbCBpbnRvIHNpbGVuY2UsIGFuZCB0aGUgc3R1ZHkgdGhlbiBwdWxsZWQgb24gdGhlDQogICAgIyBmcmFjdHVyZSBoZWFkIHdpdGggdGhlIHdlaWdodCBvZiBhIHJlcG9ydCB0aGF0IG5ldmVyIG1lbnRpb25lZCBmcmFjdHVyZXMgYXQgYWxsLg0KICAgICMgYG1pY3JvZnJhY3R1cmAgaXMgYSBzdXJnaWNhbCBwcm9jZWR1cmUgYW5kIGBmcmFjdHVyZSByaXNrYCBhIHByZWRpY3Rpb247IGJvdGggc3RheS4NCiAgICAiRnJhY3R1cmUiOiBfcngociJtaWNyb2ZyYWN0dXIiLCByIlxiZnJhY3R1cmUgKHJpc2t8cHJvcGh5bGEpIiksDQogICAgIkJha2VyJ3MiOiBfcngociJtZW5pc2NhbCBjeXN0IiwgciJxdWlzdGUgbWVuaXNjYWwiLCByImdhbmdsaW9uIiksDQp9DQoNClBBSVJFRCA9IHsiQUNMIiwgIk1DTCIsICJNZWRpYWwgTWVuaXNjdXMiLCAiTGF0ZXJhbCBNZW5pc2N1cyJ9DQpPQV9UQVJHRVRTID0geyJNZWRpYWwgT0EiLCAiTGF0ZXJhbCBPQSIsICJQRiBPQSJ9DQoNCg0KU1RFTV9NRU5JU0NVUyA9IF9yeChyIm1lbmlzY1x3KiIsIHIibWVuaXNrXHcqIiwgciLOvM63zr3Ouc+DzrpcdyoiLCByItC80LXQvdC40YHQulx3KiIpDQpTVEVNX0NSVUNJQVRFID0gX3J4KHIiY3J1Y2lhdGUiLCByImNydXphZG8iLCByImNyb2lzZSIsIHIia3J1aXNiYW5kIiwgciJrcmV1emJhbmQiLA0KICAgICAgICAgICAgICAgICAgICByImNhcHJheiBiYWdcdyoiLCByImtyaXpuXHcqIiwgciLPh865zrHPg8+EXHcqIiwgciLQutGA0YrRgdGC0L1cdyoiLA0KICAgICAgICAgICAgICAgICAgICByIlxiYWNsXGIiLCByIlxicGNsXGIiLCByIlxibGNhXGIiLCByIlxibGNwXGIiLCByIlxidmtiXGIiLA0KICAgICAgICAgICAgICAgICAgICByIlxiaGtiXGIiLCByIlxib2NiXGIiLCByIlxiYWNiXGIiKQ0KU1RFTV9DT0xMQVRFUkFMID0gX3J4KHIiY29sbGF0ZXJhbFx3KiIsIHIiY29sYXRlcmFsXHcqIiwgciJrb2xsYXRlcmFsXHcqIiwNCiAgICAgICAgICAgICAgICAgICAgICByImNvbGxhdGVyYWxlXHcqIiwgciJrb2xhdGVyYWxuXHcqIiwgciJ5YW4gYmFnXHcqIiwNCiAgICAgICAgICAgICAgICAgICAgICByIs+AzrvOsc6zzrlcdyoiLCByItC60L7Qu9Cw0YLQtdGA0LDQu1x3KiIsIHIi0YHRgtGA0LDQvdC40YdcdyoiLA0KICAgICAgICAgICAgICAgICAgICAgIHIiaW5uZW5iYW5kXHcqIiwgciJhdXNzZW5iYW5kXHcqIiwgciJiaW5uZW5iYW5kXHcqIiwNCiAgICAgICAgICAgICAgICAgICAgICByIlxibWNsXGIiLCByIlxibGNsXGIiLCByIlxibGNtXGIiLCByIlxiaXliXGIiKQ0KDQpTSURFX01FRElBTCA9IF9yeChyIlxibWVkaWFsXHcqIiwgciJcYm1lZHlhbFx3KiIsIHIiXGJtZWRpamFsblx3KiIsIHIiXGJtZWRpYWFsXHcqIiwNCiAgICAgICAgICAgICAgICAgIHIiXGJtZWRpYWxlXHcqIiwgciJcYmludGVybltvYV1cdyoiLCByIlxiaW50ZXJuZVx3KiIsIHIiXGJpbm5lblx3KiIsDQogICAgICAgICAgICAgICAgICByIlxiaWNcYiIsIHIiXGJ1bnV0YXJualx3KiIsIHIiXGLOtc+Dz4lcdyoiLCByIlxizrXPg8+Jz4TOtc+BzrnOulx3KiIsDQogICAgICAgICAgICAgICAgICByIlxi0LzQtdC00LjQsNC7XHcqIiwgciJcYtCy0YrRgtGA0LXRiFx3KiIsIHIiXGJ0aWJpYWwgY29sbGF0ZXJhbFxiIiwNCiAgICAgICAgICAgICAgICAgIHIiXGJiaW5uZW5cdyoiLCByIlxibWVkaWFhbFxiIikNClNJREVfTEFURVJBTCA9IF9yeChyIlxibGF0ZXJhbFx3KiIsIHIiXGJleHRlcm5bb2FdXHcqIiwgciJcYmV4dGVybmVcdyoiLCByIlxiZGlzXGIiLA0KICAgICAgICAgICAgICAgICAgIHIiXGJsYXRlcmFsblx3KiIsIHIiXGJhdXNzZW5cdyoiLCByIlxiYnVpdGVuXHcqIiwgciJcYs61zr7PiVx3KiIsDQogICAgICAgICAgICAgICAgICAgciJcYs61zr7Pic+EzrXPgc65zrpcdyoiLCByIlxi0LvQsNGC0LXRgNCw0LtcdyoiLCByIlxi0LLRitC90YjQvVx3KiIsDQogICAgICAgICAgICAgICAgICAgciJcYmZpYnVsYXIgY29sbGF0ZXJhbFxiIiwgciJcYnZhbmpza1x3KiIpDQpTSURFX0FOVEVSSU9SID0gX3J4KHIiXGJhbnRlcmlvclx3KiIsIHIiXGJhbnRcYiIsIHIiXGJvblxiIiwgciJcYnByZWRualx3KiIsDQogICAgICAgICAgICAgICAgICAgIHIiXGJ2b3JkZXJcdyoiLCByIlxidm9vcnN0ZVxiIiwgciJcYs+Az4HOv8+DzrjOuVx3KiIsIHIiXGLQv9GA0LXQtNC9XHcqIiwNCiAgICAgICAgICAgICAgICAgICAgciJcYmFudGVyaXlvclx3KiIsIHIiXGJhdmFudFxiIiwgciJcYmFudFtlw6ldcmlldXJcdyoiKQ0KDQojIFRoZSBjb250cmFyeSBvZiBTSURFX0FOVEVSSU9SLCBuZWVkZWQgb25seSB0byBzdG9wIGEgc2lkZS1ibGluZCBjcnVjaWF0ZSBjdWUgZmlyaW5nIG9uDQojIHRoZSBwb3N0ZXJpb3IgbGlnYW1lbnQuIEl0IGlzIG5ldmVyIHVzZWQgdG8gYXNzZXJ0IGEgdGFyZ2V0IC0gdGhlcmUgaXMgbm8gUENMIHRhcmdldCAtDQojIHNvIGl0IGlzIGRlbGliZXJhdGVseSBuYXJyb3c6IGBwb3N0ZXJpb3IgaG9ybmAgaXMgb25lIG9mIHRoZSBjb21tb25lc3QgcGhyYXNlcyBpbiBhDQojIGtuZWUgcmVwb3J0IGFuZCBtdXN0IG5vdCBiZSByZWFkIGFzIGEgY3J1Y2lhdGUgcXVhbGlmaWVyLCB3aGljaCBpcyB3aHkgdGhlIGd1YXJkIGJlbG93DQojIHRlc3RzIHByb3hpbWl0eSB0byB0aGUgY3J1Y2lhdGUgc3RlbSByYXRoZXIgdGhhbiBwcmVzZW5jZSBpbiB0aGUgY2xhdXNlLg0KU0lERV9QT1NURVJJT1IgPSBfcngociJcYnBvc3Rlcmlvclx3KiIsIHIiXGJwb3N0W2XDqV1yaWV1clx3KiIsIHIiXGJwb3N0ZXJpb3JlXHcqIiwNCiAgICAgICAgICAgICAgICAgICAgIHIiXGJoaW50ZXJcdyoiLCByIlxiYWNodGVyc3RlXGIiLCByIlxiYXJrYVxiIiwgciJcYnN0cmF6bmpcdyoiLA0KICAgICAgICAgICAgICAgICAgICAgciJcYnphZG5qXHcqIiwgciJcYs6/z4DOuc+DzrjOuVx3KiIsIHIiXGLQt9Cw0LTQvVx3KiIsIHIiXGJwb3N0ZXJvXHcqIikNCg0KIyBGcmFjdHVyZSBpcyB0aGUgdGFyZ2V0IHdob3NlIHN0ZW0gdmFyaWVzIG1vc3QgYWNyb3NzIHRoZSBjb3JwdXMuDQpTVEVNX0ZSQUNUVVJFID0gX3J4KHIiZnJhY3R1clx3KiIsIHIiZnJha3R1clx3KiIsIHIiZnJhY3R1dXJcdyoiLCByIlxiZnJhY3RcYiIsDQogICAgICAgICAgICAgICAgICAgIHIia2lyaVtrZ8SfXVx3KiIsIHIicHJpamVsb21cdyoiLCByImxvbSBrb3N0aSIsIHIiXGJicmV1a1x3KiIsDQogICAgICAgICAgICAgICAgICAgIHIiXGJicnVjaFx3KiIsIHIizrrOsc+EzrHOs868zrFcdyoiLCByIs66zrHPhM6xzrPOvM6xz4RcdyoiLCByItGE0YDQsNC60YLRg9GAXHcqIiwNCiAgICAgICAgICAgICAgICAgICAgIyBOT1QgYSBiYXJlIGBmaXNzdXJcdypgOiAiZmlzdXJhcyBjb25kcmFsZXMiIGFuZCAiZnVsbCB0aGlja25lc3MNCiAgICAgICAgICAgICAgICAgICAgIyBmaXNzdXJlcyBpbiB0aGUgYXJ0aWN1bGFyIGNhcnRpbGFnZSIgZGVzY3JpYmUgY2FydGlsYWdlLCBub3QgYm9uZS4NCiAgICAgICAgICAgICAgICAgICAgIyBUaGUgc3RlbSBoYXMgdG8gYmUgYW5jaG9yZWQgdG8gYSBib25lIHdvcmQgdG8gbWVhbiBhIGZyYWN0dXJlLg0KICAgICAgICAgICAgICAgICAgICByItGB0YfRg9C/0LLQsNC9XHcqIiwgciJmaXN1clx3KiAob3NlYXxvc2Vhc3xrb3N0KSIsIHIiZmlzc3VyXHcqIGtvc3QiKQ0KDQpTVEVNX09BX0NPTVBBUlRNRU5UID0gX3J4KHIiY29tcGFydG1lbnRcdyoiLCByImNvbXBhcnRpbWVudG9cdyoiLCByImNvbXBhcnRpbWVudFx3KiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgIHIia29tcGFydG1hblx3KiIsIHIia29tcGFydGltZW50XHcqIiwgciJvZGplbGpcdyoiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICByIs60zrnOsc68zrXPgc65z4POvM6xXHcqIiwgciLQutC+0LzQv9Cw0YDRgtC8XHcqIiwgciJcYtC+0YLQtNC10LtcdyoiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICByImZlbW9yb3RpYmlhbFx3KiIsIHIiZmVtb3JvdGliaWFhbFx3KiIsIHIidGliaW9mZW1vcmFsXHcqIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgciJmZW1vcm8gdGliaWFsXHcqIiwgciLOus69zrfOvM65zrHOuVx3KiIsIHIizrzOt8+BzrnOsc65XHcqIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgciJmZW1vcmFsIGNvbmR5bFx3KiIsIHIidGliaWFsIHBsYXRlYXVcdyoiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICByImNvbmRpbG8gZmVtb3JhbCIsIHIicGxhdGlsbG8gdGliaWFsIiwgciJ0aWJpYXBsYXRlYXVcdyoiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICByImZlbXVya29uZHlsXHcqIiwgciJmZW1vcmFsbmU/IGtvbmRpbFx3KiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgIHIidGliaWphbG5cdyogcGxhdG8iLCByImZlbW9yYWwga29uZGlsXHcqIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgciJ0aWJpYSBwbGF0byIsIHIidGlieWFsIHBsYXRvIikNCg0KDQpkZWYgX2Rpc3RhbmNlKGNsYXVzZTogc3RyLCBzdGVtX3J4OiByZS5QYXR0ZXJuLCBxdWFsX3J4OiByZS5QYXR0ZXJuLCB3aW5kb3c6IGludCA9IDU1KToNCiAgICAiIiJDaGFyYWN0ZXJzIGZyb20gdGhlIG5lYXJlc3Qgc3RlbSB0byB0aGUgbmVhcmVzdCBxdWFsaWZpZXIsIG9yIE5vbmUgaWYgbm9uZSBpcyBuZWFyLg0KDQogICAgQ2hhcmFjdGVyIHdpbmRvd3MgcmF0aGVyIHRoYW4gdG9rZW4gd2luZG93cywgYmVjYXVzZSB3b3JkIG9yZGVyIGRpZmZlcnM6IEVuZ2xpc2gNCiAgICBwdXRzIHRoZSBzaWRlIGJlZm9yZSB0aGUgbm91biwgR3JlZWsgYW5kIEJ1bGdhcmlhbiBvZnRlbiBhZnRlciwgYW5kIFR1cmtpc2gNCiAgICBhdHRhY2hlcyBpdCBhcyBhIHNlcGFyYXRlIHByZWNlZGluZyBhZGplY3RpdmUuDQoNCiAgICBBIGRpc3RhbmNlIHJhdGhlciB0aGFuIGEgeWVzLiBQcmVzZW5jZSBpcyBlbm91Z2ggdG8gZGVjaWRlIHRoYXQgYSBxdWFsaWZpZXIgYXBwbGllcw0KICAgIHRvIGEgc3RydWN0dXJlLCBidXQgbm90IGVub3VnaCB0byBkZWNpZGUgd2hpY2ggb2YgdHdvIHF1YWxpZmllcnMgYXBwbGllczogYSBrbmVlDQogICAgcmVwb3J0IHNheXMgImFudGVyaW9yIGhvcm4iIGFuZCAicG9zdGVyaW9yIGhvcm4iIGNvbnN0YW50bHksIHNvIGFueSB3aW5kb3cgd2lkZQ0KICAgIGVub3VnaCB0byBjYXRjaCBhIHJlYWwgc2lkZSB3b3JkIGFsc28gY2F0Y2hlcyBhbiB1bnJlbGF0ZWQgb25lLCBhbmQgdHdvIHJ1bGVzIHRoYXQNCiAgICBib3RoIGFuc3dlciAieWVzIiBjYW5ub3QgYmUgdG9sZCBhcGFydC4gQ29tcGFyaW5nIGhvdyBmYXIgYXdheSB0aGV5IGFyZSBjYW4uDQogICAgIiIiDQogICAgYmVzdCA9IE5vbmUNCiAgICBmb3IgbSBpbiBzdGVtX3J4LmZpbmRpdGVyKGNsYXVzZSk6DQogICAgICAgIGxvID0gbWF4KDAsIG0uc3RhcnQoKSAtIHdpbmRvdykNCiAgICAgICAgaGkgPSBtaW4obGVuKGNsYXVzZSksIG0uZW5kKCkgKyB3aW5kb3cpDQogICAgICAgIGZvciBxIGluIHF1YWxfcnguZmluZGl0ZXIoY2xhdXNlW2xvOmhpXSk6DQogICAgICAgICAgICBxcywgcWUgPSBsbyArIHEuc3RhcnQoKSwgbG8gKyBxLmVuZCgpDQogICAgICAgICAgICBkID0gMCBpZiBxcyA8IG0uZW5kKCkgYW5kIHFlID4gbS5zdGFydCgpIGVsc2UgXA0KICAgICAgICAgICAgICAgIG1pbihhYnMobS5zdGFydCgpIC0gcWUpLCBhYnMocXMgLSBtLmVuZCgpKSkNCiAgICAgICAgICAgIGJlc3QgPSBkIGlmIGJlc3QgaXMgTm9uZSBlbHNlIG1pbihiZXN0LCBkKQ0KICAgIHJldHVybiBiZXN0DQoNCg0KZGVmIF9uZWFyKGNsYXVzZTogc3RyLCBzdGVtX3J4OiByZS5QYXR0ZXJuLCBxdWFsX3J4OiByZS5QYXR0ZXJuLCB3aW5kb3c6IGludCA9IDU1KToNCiAgICAiIiJUcnVlIGlmIGEgc3RlbSBtYXRjaCBoYXMgYSBxdWFsaWZpZXIgd2l0aGluIGB3aW5kb3dgIGNoYXJhY3RlcnMgZWl0aGVyIHNpZGUuIiIiDQogICAgcmV0dXJuIF9kaXN0YW5jZShjbGF1c2UsIHN0ZW1fcngsIHF1YWxfcngsIHdpbmRvdykgaXMgbm90IE5vbmUNCiAgICByZXR1cm4gRmFsc2UNCg0KDQojIGNvbmNlcHQgLT4gKHN0ZW0sIHNpZGUpIHBhaXJzIHVzZWQgaW4gYWRkaXRpb24gdG8gdGhlIHBocmFzZSBsZXhpY29ucyBhYm92ZQ0KU1RFTV9SVUxFUyA9IHsNCiAgICAiQUNMIjogKFNURU1fQ1JVQ0lBVEUsIFNJREVfQU5URVJJT1IpLA0KICAgICJNQ0wiOiAoU1RFTV9DT0xMQVRFUkFMLCBTSURFX01FRElBTCksDQogICAgIk1lZGlhbCBNZW5pc2N1cyI6IChTVEVNX01FTklTQ1VTLCBTSURFX01FRElBTCksDQogICAgIkxhdGVyYWwgTWVuaXNjdXMiOiAoU1RFTV9NRU5JU0NVUywgU0lERV9MQVRFUkFMKSwNCiAgICAiTWVkaWFsIE9BIjogKFNURU1fT0FfQ09NUEFSVE1FTlQsIFNJREVfTUVESUFMKSwNCiAgICAiTGF0ZXJhbCBPQSI6IChTVEVNX09BX0NPTVBBUlRNRU5ULCBTSURFX0xBVEVSQUwpLA0KfQ0KDQoNClNFVl9MT1cgPSBfcngoDQogICAgciJcYnNtYWxsXGIiLCByIlxibWluaW1hbFxiIiwgciJcYnRyYWNlXGIiLCByIlxibWlsZFxiIiwgciJcYnNsaWdodFxiIiwNCiAgICByIlxidGlueVxiIiwgciJcYnNjYW50XGIiLCByIlxibWltaW1hbFxiIiwgciJcYmRpc2NyZXRlXGIiLCByIlxiZm9jYWxcYiIsDQogICAgciJcYmxldmVcYiIsIHIiXGJtaW5pbSIsIHIiXGJwZXF1ZSIsIHIiXGJsaWdlcm9cYiIsIHIiXGJlc2Nhc29cYiIsIHIiXGJkaXNjcmV0b1xiIiwNCiAgICByIlxiaGFmaWZcYiIsIHIiXGJtaW5pbWFsXGIiLCByIlxiYXogbWlrdGFyZGFcYiIsIHIiXGJzaWxpa1xiIiwNCiAgICByIlxibWFuamFcYiIsIHIiXGJtYW5qaVxiIiwgciJcYmJsYWdvXGIiLCByIlxiZGlza3JldG4iLCByIlxibWFsb1xiIiwNCiAgICByIlxiZ2VyaW5nIiwgciJcYmRpc2tyZXQiLCByIlxia2xlaW5lP3I/XGIiLCByIlxid2VuaWdcYiIsIHIiXGJ6YXJ0ZT9cYiIsDQogICAgciJcYmJlcGVya3RlP1xiIiwgciJcYmdlcmluZ2VcYiIsIHIiXGJ3ZWluaWdcYiIsIHIiXGJsaWNodGU/XGIiLA0KICAgIHIiXGLOt8+AzrkiLCByIlxizrzOuc66z4EiLCByIlxizrXOu86xz4fOuc+Dz4QiLA0KICAgIHIiXGLQvNC40L3QuNC80LDQuyIsIHIiXGLQu9C10LoiLCByIlxi0LzQsNC70LoiLCByIlxi0L3QtdCz0L7Qu9GP0LwiLA0KKQ0KDQpTRVZfSElHSCA9IF9yeCgNCiAgICByIlxibGFyZ2VcYiIsIHIiXGJtYXJrZWRcYiIsIHIiXGJtYXNzaXZlXGIiLCByIlxic2V2ZXJlXGIiLCByIlxiZXh0ZW5zaXZlXGIiLA0KICAgIHIiXGJtb2RlcmF0ZVxiIiwgciJcYmdyb3NzXGIiLCByIlxic2lnbmlmaWNhbnRcYiIsIHIiXGJhYnVuZGFudFxiIiwgciJcYnRlbnNlXGIiLA0KICAgIHIiXGJtb2RlcmFkIiwgciJcYmltcG9ydGFudGVcYiIsIHIiXGJzZXZlcmE/XGIiLCByIlxibWFyY2FkIiwgciJcYmN1YW50aW9zIiwNCiAgICByIlxiYmVsaXJnaW5cYiIsIHIiXGJ5YXlnaW5cYiIsIHIiXGJpbGVyaVxiIiwgciJcYmNpZGRpXGIiLCByIlxiYm9sXGIiLA0KICAgIHIiXGJvcHNlemFuXGIiLCByIlxidmVsaWtpXGIiLCByIlxiaXpyYXppdCIsIHIiXGJ6bmFjYWpuIiwgciJcYnVtamVyZW4iLA0KICAgIHIiXGJhdXNnZXByYWd0IiwgciJcYmRldXRsaWNoIiwgciJcYm1hc3NpdiIsIHIiXGJtYXNzaWciLCByIlxiZ3Jvc3MiLA0KICAgIHIiXGJ1aXRnZWJyZWlkIiwgciJcYmdldm9yZGVyZCIsIHIiXGJ2ZWVsXGIiLCByIlxibWF0aWdlP1xiIiwNCiAgICByIlxizrzOtc+Ez4HOuSIsIHIiXGLOvM61zrPOsc67IiwgciJcYs61zrrPhM61z4TOsc68zrXOvSIsIHIiXGLOtc+FzrzOtc6zzrXOuCIsIHIiXGLPg86/zrLOsc+BIiwNCiAgICByIlxi0LPQvtC70Y/QvCIsIHIiXGLQuNC30YDQsNC30LXQvSIsIHIiXGLQt9C90LDRh9C40LwiLCByIlxi0YPQvNC10YDQtdC9IiwgciJcYtC+0LHQuNC70LXQvSIsDQopDQoNCiMgT0EgaXMgb2Z0ZW4gYXNzZXJ0ZWQgZm9yIHRoZSB3aG9sZSBqb2ludCByYXRoZXIgdGhhbiBwZXIgY29tcGFydG1lbnQNCiMgKCJ0cmljb21wYXJ0bWVudGFsIG9zdGVvYXJ0aHJpdGlzIiwgImdvbmFydGhyb3NlIiwgImluY2lwaWVudCBPQSBvZiBhbGwgdGhyZWUNCiMgY29tcGFydG1lbnRzIikuIFRob3NlIHN0YXRlbWVudHMgYXJlIGV2aWRlbmNlIGZvciBhbGwgdGhyZWUgT0EgdGFyZ2V0cy4NCkdMT0JBTF9PQSA9IF9yeCgNCiAgICByInRyaSA/Y29tcGFydG1lbnQiLCByImFsbCB0aHJlZSBjb21wYXJ0bWVudCIsIHIiZ2xvYmFsKGlzZWQpPyAob2F8b3N0ZW9hcnRocml0KSIsDQogICAgciJcYmdvbmFydGhyb3MiLCByIlxiZ29uYXJ0cm9zIiwgciJcYmdvbmFydGhyb3NlIiwgciJcYmdvbmFydHJvc2UiLA0KICAgIHIib3N0ZW9hcnRocml0aXMgb2YgdGhlIGtuZWUiLCByImFydHJvc2lzIChkZSB8KShsYSApP3JvZGlsbGEiLCByImtuZWUgb3N0ZW9hcnRocml0IiwNCiAgICByIlxiZGl6IG9zdGVvYXJ0cml0IiwgciJcYmdvbmFydHJveiIsIHIiYXJ0cm96YSBrb2xqZW5hIiwNCiAgICByIs6/z4PPhM61zr/Osc+BzrjPgc65z4TOuc60zrEiLCByIs6xz4HOuM+BzrnPhM65zrTOsSDPhM6/z4UgzrPOv869zrHPhM6/z4IiLA0KICAgIHIi0LDRgNGC0YDQvtC30LAg0L3QsCDQutC+0LvRj9C90L3QsNGC0LAiLCByItCz0L7QvdCw0YDRgtGA0L7QtyIsDQogICAgciJkZWdlbmVyYXRpdmUgam9pbnQgZGlzZWFzZSIsIHIiXGJkamRcYiIsDQopDQoNCiMgQSBiYXJlICJib25lIG1hcnJvdyBvZWRlbWEiIGlzIG5vdCBhIGNvbnR1c2lvbiB3aGVuIGl0IHNpdHMgdW5kZXIgYSBjYXJ0aWxhZ2UNCiMgZGVmZWN0OiBzdWJjaG9uZHJhbCBvZWRlbWEgYmVuZWF0aCBhIHdvcm4gY29tcGFydG1lbnQgaXMgcmVhY3RpdmUgZGVnZW5lcmF0aXZlIHNpZ25hbCwNCiMgYW5kIHJlYWRpbmcgaXQgYXMgYSBicnVpc2UgdHVybnMgZXZlcnkgb3N0ZW9hcnRocml0aWMga25lZSBpbnRvIGEgdHJhdW1hIGNhc2UuDQpERUdFTkVSQVRJVkVfTUFSUk9XID0gX3J4KA0KICAgIHIic3ViY2hvbmRyYWwiLCByInN1YmNvbmRyYWwiLCByInN1YmtvbmRyYWwiLCByInN1cGtvbmRyYWxuIiwgciJzdWJjaG9uZHJhbG4iLA0KICAgIHIiz4XPgM6/z4fOv869zrTPgc65IiwgciLRgdGD0LHRhdC+0L3QtNGA0LDQuyIsIHIic3ViY2hvbmRyYWxlPyIsDQogICAgciJcYmN5c3QiLCByIlxicXVpc3QiLCByIlxienlzdGVcYiIsIHIiXGJjaXN0aWMiLCByInJlYWN0aXZlIiwgciJyZWFjdGl2byIsDQopDQoNClRSQVVNQSA9IF9yeCgNCiAgICByIlxiYnJ1aXNlXGIiLCByIlxiY29udHVzaW9uIiwgciJcYmtvbnR1eiIsIHIiXGJjb250dXNpb24gb3NlYVxiIiwNCiAgICByIlxidHJhdW1hIiwgciJcYmltcGFjdGlvblxiIiwgciJcYnBpdm90IHNoaWZ0XGIiLCByIlxia2lzc2luZ1xiIiwNCiAgICByIlxiYWN1dGVcYiIsIHIiXGJhZ3Vkb1xiIiwgciJcYmFrdXQiLCByIlxicGl2b3Qga2F5bWFzaVxiIiwNCiAgICByIlxiY29udHVzaW9uIG9zc2V1c2VcYiIsIHIiXGJib25lIGJydWlzZVxiIiwgciJcYmJvdGNvbnR1c2llXGIiLA0KICAgIHIiXGLQutC+0L3RgtGD0LfQuNC+0L0iLCByIlxizrzPic67z4nPgCIsIHIiXGJrb250dXppaiIsDQopDQoNCg0KZGVmIF9wb2xhcml0eShjbGF1c2U6IHN0ciwgYW5jaG9yX2VuZDogaW50KSAtPiBzdHI6DQogICAgIiIiQ2xhc3NpZnkgb25lIGNsYXVzZSBhcyBwb3NpdGl2ZSwgbmVnYXRpdmUgb3IgdW5jZXJ0YWluIGZvciBhIG1hdGNoZWQgdGVybS4NCg0KICAgIFNjb3BlIGlzIHRoZSB3aG9sZSBjbGF1c2UuIENsYXVzZSBzZWdtZW50YXRpb24gYWxyZWFkeSBrZWVwcyBzdGF0ZW1lbnRzIHNob3J0LCBhbmQNCiAgICBhIHdpbmRvdyBpbiBjaGFyYWN0ZXJzIG1pcy1zY29wZXMgYmFkbHkgYWNyb3NzIGxhbmd1YWdlcyB3aXRoIGRpZmZlcmVudCB3b3JkIG9yZGVycyAtDQogICAgVHVya2lzaCBwdXRzIGl0cyBuZWdhdG9yIGF0IHRoZSBlbmQgb2YgdGhlIHNlbnRlbmNlLCBFbmdsaXNoIGF0IHRoZSBmcm9udC4NCiAgICAiIiINCiAgICBpZiBVTkNFUlRBSU4uc2VhcmNoKGNsYXVzZSk6DQogICAgICAgIHJldHVybiAidW5jZXJ0YWluIg0KICAgIGlmIE5FR0FUSU9OLnNlYXJjaChjbGF1c2UpOg0KICAgICAgICByZXR1cm4gIm5lZ2F0aXZlIg0KICAgIGlmIE5PUk1BTElUWS5zZWFyY2goY2xhdXNlKToNCiAgICAgICAgIyAibWVuaXNjdXMgbm9ybWFsIiBuZWdhdGVzOyAibm9ybWFsIC4uLiBidXQgdGVhciIgZG9lcyBub3QuDQogICAgICAgIGlmIFRFQVIuc2VhcmNoKGNsYXVzZSkgb3IgcmUuc2VhcmNoKHIiXGJncmFkZSBbMzRdXGIiLCBjbGF1c2UpOg0KICAgICAgICAgICAgcmV0dXJuICJwb3NpdGl2ZSINCiAgICAgICAgcmV0dXJuICJuZWdhdGl2ZSINCiAgICByZXR1cm4gInBvc2l0aXZlIg0KDQoNCmNsYXNzIF9NYXRjaGVyOg0KICAgICIiIlBocmFzZSBsZXhpY29uIGZpcnN0LCBzdGVtK3NpZGUgcHJveGltaXR5IGFzIHRoZSBmYWxsYmFjay4NCg0KICAgIEV4cG9zZXMgYC5zZWFyY2hgIHNvIGl0IGRyb3BzIGludG8gdGhlIHNhbWUgc2xvdCBhcyBhIGNvbXBpbGVkIHBhdHRlcm4uDQogICAgIiIiDQoNCiAgICBkZWYgX19pbml0X18oc2VsZiwgcGhyYXNlX3J4LCBzdGVtPU5vbmUsIHNpZGU9Tm9uZSwgd2luZG93PTU1LCBjb250cmFyeT1Ob25lKToNCiAgICAgICAgc2VsZi5waHJhc2VfcnggPSBwaHJhc2VfcngNCiAgICAgICAgc2VsZi5zdGVtID0gc3RlbQ0KICAgICAgICBzZWxmLnNpZGUgPSBzaWRlDQogICAgICAgIHNlbGYud2luZG93ID0gd2luZG93DQogICAgICAgIHNlbGYuY29udHJhcnkgPSBjb250cmFyeQ0KDQogICAgZGVmIHNlYXJjaChzZWxmLCBjbGF1c2UpOg0KICAgICAgICBtID0gc2VsZi5waHJhc2Vfcnguc2VhcmNoKGNsYXVzZSkNCiAgICAgICAgaWYgbSBpcyBub3QgTm9uZSBhbmQgbm90IHNlbGYuX3dyb25nX3NpZGUoY2xhdXNlKToNCiAgICAgICAgICAgIHJldHVybiBtDQogICAgICAgIGlmIHNlbGYuc3RlbSBpcyBub3QgTm9uZSBhbmQgX25lYXIoY2xhdXNlLCBzZWxmLnN0ZW0sIHNlbGYuc2lkZSwgc2VsZi53aW5kb3cpOg0KICAgICAgICAgICAgcmV0dXJuIHNlbGYuc3RlbS5zZWFyY2goY2xhdXNlKQ0KICAgICAgICByZXR1cm4gTm9uZQ0KDQogICAgZGVmIF93cm9uZ19zaWRlKHNlbGYsIGNsYXVzZSk6DQogICAgICAgICIiIlRydWUgd2hlbiB0aGUgY2xhdXNlIG5hbWVzIHRoZSBvdGhlciBtZW1iZXIgb2YgdGhpcyBzdHJ1Y3R1cmUncyBwYWlyLg0KDQogICAgICAgIFNvbWUgY3VlcyBpbiB0aGUgbGV4aWNvbiBhcmUgc2lkZS1ibGluZCBieSBkZXNpZ246IEdyZWVrIHNlcGFyYXRlcyB0aGUgYWRqZWN0aXZlDQogICAgICAgIGZyb20gaXRzIG5vdW4gKCJjcnVjaWF0ZSBhbmQgY29sbGF0ZXJhbCBsaWdhbWVudHMiKSwgc28gdGhlIGJhcmUgYWRqZWN0aXZlIHN0ZW0NCiAgICAgICAgaGFzIHRvIHN0YW5kIGFsb25lIG9yIHRoZSBjbGF1c2UgaXMgbG9zdC4gVGhhdCBzdGVtIHRoZW4gYWxzbyBtYXRjaGVzIHRoZQ0KICAgICAgICBwb3N0ZXJpb3IgY3J1Y2lhdGUgYW5kIHRoZSBsYXRlcmFsIGNvbGxhdGVyYWwsIG5laXRoZXIgb2Ygd2hpY2ggaXMgYSB0YXJnZXQgaGVyZSwNCiAgICAgICAgYW5kIGEgcG9zaXRpdmUgb3V0cmFua3MgZXZlcnkgbmVnYXRpdmUgaW4gdGhlIHNjb3JlciAtIHNvIG9uZSBQQ0wgY2xhdXNlIHdhcw0KICAgICAgICBlbm91Z2ggdG8gb3ZlcnJpZGUgYW4gZXhwbGljaXQgInRoZSBBQ0wgaXMgbm9ybWFsIi4NCg0KICAgICAgICBUaGUgdGVzdCBpcyBwcm94aW1pdHkgdG8gdGhlIHN0cnVjdHVyZSdzIG93biBzdGVtLCBub3QgcHJlc2VuY2UgaW4gdGhlIGNsYXVzZS4NCiAgICAgICAgIlBvc3RlcmlvciBob3JuIG9mIHRoZSBtZWRpYWwgbWVuaXNjdXMiIGFwcGVhcnMgaW4gYSBsYXJnZSBzaGFyZSBvZiBrbmVlIHJlcG9ydHMNCiAgICAgICAgYW5kIHNheXMgbm90aGluZyBhYm91dCBhIGNydWNpYXRlOyBvbmx5IGEgcXVhbGlmaWVyIHNpdHRpbmcgYmVzaWRlIHRoZSBsaWdhbWVudA0KICAgICAgICB3b3JkIGlzIG9uZS4gQSBjbGF1c2UgbmFtaW5nIGJvdGggc2lkZXMga2VlcHMgdGhlIG1hdGNoLCBiZWNhdXNlIGl0IGRvZXMgbWVudGlvbg0KICAgICAgICB0aGlzIHRhcmdldC4NCiAgICAgICAgIiIiDQogICAgICAgIGlmIHNlbGYuY29udHJhcnkgaXMgTm9uZSBvciBzZWxmLnN0ZW0gaXMgTm9uZToNCiAgICAgICAgICAgIHJldHVybiBGYWxzZQ0KICAgICAgICBvdGhlciA9IF9kaXN0YW5jZShjbGF1c2UsIHNlbGYuc3RlbSwgc2VsZi5jb250cmFyeSwgc2VsZi53aW5kb3cpDQogICAgICAgIGlmIG90aGVyIGlzIE5vbmU6DQogICAgICAgICAgICByZXR1cm4gRmFsc2UNCiAgICAgICAgb3duID0gX2Rpc3RhbmNlKGNsYXVzZSwgc2VsZi5zdGVtLCBzZWxmLnNpZGUsIHNlbGYud2luZG93KQ0KICAgICAgICAjIE5vdCAiaXMgdGhlIG90aGVyIHNpZGUgbWVudGlvbmVkIiBidXQgImlzIGl0IHRoZSBuZWFyZXIgb2YgdGhlIHR3byIuIEEgY2xhdXNlDQogICAgICAgICMgcmVhZGluZyAidGVhciBvZiB0aGUgcG9zdGVyaW9yIGhvcm4gb2YgdGhlIG1lZGlhbCBtZW5pc2N1czsgdGhlIGNydWNpYXRlDQogICAgICAgICMgbGlnYW1lbnRzIGFyZSBpbnRhY3QiIG1lbnRpb25zIHBvc3RlcmlvciwgYW5kIHVuZGVyIGEgcHJlc2VuY2UgdGVzdCB0aGF0IHdhcw0KICAgICAgICAjIGVub3VnaCB0byBzdXBwcmVzcyB0aGUgY3J1Y2lhdGUgY3VlIC0gd2hpY2ggaXMgdGhlIG9wcG9zaXRlIG9mIHRoZSBpbnRlbnQsDQogICAgICAgICMgc2luY2UgdGhlIGNsYXVzZSBkb2VzIGRlc2NyaWJlIHRoZSBsaWdhbWVudHMuIFRpZXMgZ28gdG8ga2VlcGluZyB0aGUgbWF0Y2g6DQogICAgICAgICMgYSBjbGF1c2UgbmFtaW5nIGJvdGggc2lkZXMgZG9lcyBtZW50aW9uIHRoaXMgb25lLg0KICAgICAgICByZXR1cm4gb3duIGlzIE5vbmUgb3Igb3RoZXIgPCBvd24NCg0KDQojIFdoaWNoIGN1ZSwgaWYgaXQgc2l0cyBiZXNpZGUgdGhlIHN0cnVjdHVyZSdzIHN0ZW0sIG1lYW5zIHRoZSBjbGF1c2UgaXMgYWJvdXQgdGhlIG90aGVyDQojIG1lbWJlciBvZiB0aGUgcGFpci4gT25seSB0aGUgdHdvIHN0cnVjdHVyZXMgd2l0aCBhIHNpZGUtYmxpbmQgY3VlIG5lZWQgb25lLg0KQ09OVFJBUlkgPSB7IkFDTCI6IFNJREVfUE9TVEVSSU9SLCAiTUNMIjogU0lERV9MQVRFUkFMfQ0KDQpBTkFUX01BVENIID0gew0KICAgIHRndDogX01hdGNoZXIoQU5BVFt0Z3RdLCAqU1RFTV9SVUxFU1t0Z3RdLCBjb250cmFyeT1DT05UUkFSWS5nZXQodGd0KSkNCiAgICBmb3IgdGd0IGluIFBBSVJFRA0KfQ0KQ09NUEFSVE1FTlRfTUFUQ0ggPSB7DQogICAgIk1lZGlhbCBPQSI6IF9NYXRjaGVyKENPTVBBUlRNRU5UWyJNZWRpYWwgT0EiXSwgKlNURU1fUlVMRVNbIk1lZGlhbCBPQSJdKSwNCiAgICAiTGF0ZXJhbCBPQSI6IF9NYXRjaGVyKENPTVBBUlRNRU5UWyJMYXRlcmFsIE9BIl0sICpTVEVNX1JVTEVTWyJMYXRlcmFsIE9BIl0pLA0KICAgICJQRiBPQSI6IF9NYXRjaGVyKENPTVBBUlRNRU5UWyJQRiBPQSJdKSwNCn0NCkRJUkVDVF9NQVRDSCA9IHsNCiAgICB0Z3Q6IF9NYXRjaGVyKF9yeChyeC5wYXR0ZXJuLCBTVEVNX0ZSQUNUVVJFLnBhdHRlcm4pIGlmIHRndCA9PSAiRnJhY3R1cmUiIGVsc2UgcngpDQogICAgZm9yIHRndCwgcnggaW4gRElSRUNULml0ZW1zKCkNCn0NCg0KDQpkZWYgX3NldmVyaXR5KGNsYXVzZTogc3RyKSAtPiBmbG9hdDoNCiAgICAiIiJXZWlnaHQgb25lIHBvc2l0aXZlIG1lbnRpb24gYnkgaG93IGVtcGhhdGljIHRoZSBzZW50ZW5jZSBpcy4NCg0KICAgIE9yZGVyZWQsIG5vdCBjYWxpYnJhdGVkLiBBICJtb2RlcmF0ZSBlZmZ1c2lvbiIgbXVzdCBvdXRyYW5rIGEgInRyYWNlIGVmZnVzaW9uIiBhbmQNCiAgICBib3RoIG11c3Qgb3V0cmFuayBzaWxlbmNlOyB0aGUgYWJzb2x1dGUgbnVtYmVycyBkbyBub3QgbWF0dGVyIHRvIEFVQy4NCiAgICAiIiINCiAgICBoaWdoID0gU0VWX0hJR0guc2VhcmNoKGNsYXVzZSkgaXMgbm90IE5vbmUNCiAgICBsb3cgPSBTRVZfTE9XLnNlYXJjaChjbGF1c2UpIGlzIG5vdCBOb25lDQogICAgaWYgaGlnaCBhbmQgbm90IGxvdzoNCiAgICAgICAgcmV0dXJuIDEuMA0KICAgIGlmIGxvdyBhbmQgbm90IGhpZ2g6DQogICAgICAgIHJldHVybiAwLjQ1DQogICAgcmV0dXJuIDAuNzUgICAgICAgICAgICAgICAgICAgICAgICMgdW5xdWFsaWZpZWQgbWVudGlvbg0KDQoNCmRlZiBfc2NvcmVfY2xhdXNlcyhjbHMsIGFuYXRfcngsIHBhdGhfcng9Tm9uZSwgZGVjb3lfcng9Tm9uZSwgY29udGV4dF9wZW5hbHR5PU5vbmUsDQogICAgICAgICAgICAgICAgICAgY29udGV4dF9ib251cz1Ob25lKToNCiAgICAiIiJBY2N1bXVsYXRlIGdyYWRlZCBldmlkZW5jZSBvdmVyIGNsYXVzZXMgZm9yIG9uZSB0YXJnZXQuDQoNCiAgICBSZXR1cm5zIChzY29yZSwgY29uZmlkZW5jZSwgbl9wb3MsIG5fbmVnKS4gUG9zaXRpdmVzIGFyZSBncmFkZWQgYnkgc2V2ZXJpdHkgYW5kIGJ5DQogICAgb3B0aW9uYWwgY29udGV4dCByZWdleGVzOyBuZWdhdGl2ZXMgb25seSBtYXR0ZXIgd2hlbiBub3RoaW5nIHBvc2l0aXZlIHdhcyBmb3VuZCwNCiAgICBiZWNhdXNlIHJlcG9ydHMgYXNzZXJ0IG5vcm1hbGl0eSBmb3IgZXZlcnkgc3RydWN0dXJlIHRoZXkgY2hlY2suDQogICAgIiIiDQogICAgbl9wb3MgPSBuX25lZyA9IG5fdW5jID0gMA0KICAgIGJlc3QgPSAwLjANCiAgICBmb3IgYyBpbiBjbHM6DQogICAgICAgIG0gPSBhbmF0X3J4LnNlYXJjaChjKQ0KICAgICAgICBpZiBub3QgbToNCiAgICAgICAgICAgIGNvbnRpbnVlDQogICAgICAgIGlmIGRlY295X3J4IGlzIG5vdCBOb25lIGFuZCBkZWNveV9yeC5zZWFyY2goYyk6DQogICAgICAgICAgICBjb250aW51ZQ0KICAgICAgICBpZiBwYXRoX3J4IGlzIG5vdCBOb25lIGFuZCBub3QgcGF0aF9yeC5zZWFyY2goYyk6DQogICAgICAgICAgICBpZiBOT1JNQUxJVFkuc2VhcmNoKGMpIGFuZCBub3QgTkVHQVRJT04uc2VhcmNoKGMpOg0KICAgICAgICAgICAgICAgIG5fbmVnICs9IDENCiAgICAgICAgICAgIGNvbnRpbnVlDQogICAgICAgIHBvbCA9IF9wb2xhcml0eShjLCBtLmVuZCgpKQ0KICAgICAgICBpZiBwb2wgPT0gInBvc2l0aXZlIjoNCiAgICAgICAgICAgIG5fcG9zICs9IDENCiAgICAgICAgICAgIHcgPSBfc2V2ZXJpdHkoYykNCiAgICAgICAgICAgIGlmIGNvbnRleHRfcGVuYWx0eSBpcyBub3QgTm9uZSBhbmQgY29udGV4dF9wZW5hbHR5LnNlYXJjaChjKToNCiAgICAgICAgICAgICAgICB3ICo9IDAuNDUNCiAgICAgICAgICAgIGlmIGNvbnRleHRfYm9udXMgaXMgbm90IE5vbmUgYW5kIGNvbnRleHRfYm9udXMuc2VhcmNoKGMpOg0KICAgICAgICAgICAgICAgIHcgPSBtaW4oMS4wLCB3ICogMS4zNSkNCiAgICAgICAgICAgIGJlc3QgPSBtYXgoYmVzdCwgdykNCiAgICAgICAgZWxpZiBwb2wgPT0gIm5lZ2F0aXZlIjoNCiAgICAgICAgICAgIG5fbmVnICs9IDENCiAgICAgICAgZWxzZToNCiAgICAgICAgICAgIG5fdW5jICs9IDENCiAgICAgICAgICAgIGJlc3QgPSBtYXgoYmVzdCwgMC4zMCkNCg0KICAgIGlmIG5fcG9zIG9yIG5fdW5jOg0KICAgICAgICAjIDAuNTIgLi4gMC45NSwgb3JkZXJlZCBieSB0aGUgc3Ryb25nZXN0IHNpbmdsZSBtZW50aW9uLCBudWRnZWQgYnkgcmVwZXRpdGlvbi4NCiAgICAgICAgc2NvcmUgPSBtaW4oMC45NSwgMC41MCArIDAuNDIgKiBiZXN0ICsgMC4wMyAqIG1pbihuX3BvcywgMykpDQogICAgICAgIGNvbmYgPSBtaW4oMS4wLCAwLjU1ICsgMC4xNSAqIG5fcG9zKQ0KICAgIGVsaWYgbl9uZWc6DQogICAgICAgIHNjb3JlID0gbWF4KDAuMDQsIDAuMjAgLSAwLjA0ICogbl9uZWcpDQogICAgICAgIGNvbmYgPSBtaW4oMC45LCAwLjQ1ICsgMC4xMiAqIG5fbmVnKQ0KICAgIGVsc2U6DQogICAgICAgIHNjb3JlLCBjb25mID0gMC4yOCwgMC4wNSAgICAgICAgICAjIHNpbGVuY2Ugc2l0cyBhYm92ZSBhc3NlcnRlZC1uZWdhdGl2ZQ0KICAgIHJldHVybiBzY29yZSwgY29uZiwgbl9wb3MsIG5fbmVnDQoNCg0KZGVmIGV4dHJhY3QocmVwb3J0OiBzdHIpIC0+IGRpY3Q6DQogICAgIiIiRXh0cmFjdCB0d2VsdmUgKHNjb3JlLCBjb25maWRlbmNlKSBwYWlycyBmcm9tIG9uZSByZXBvcnQuIiIiDQogICAgY2xzID0gY2xhdXNlcyhyZXBvcnQpDQogICAgb3V0ID0ge30NCiAgICBwYXRoX3BhaXJlZCA9IF9yeChURUFSLnBhdHRlcm4sIERFR0VOLnBhdHRlcm4sIElOSlVSWS5wYXR0ZXJuKQ0KDQogICAgZm9yIHRndCBpbiBUQVJHRVRTOg0KICAgICAgICBpZiB0Z3QgaW4gUEFJUkVEOg0KICAgICAgICAgICAgcywgYywgbnBvcywgbm5lZyA9IF9zY29yZV9jbGF1c2VzKGNscywgQU5BVF9NQVRDSFt0Z3RdLCBwYXRoX3BhaXJlZCkNCiAgICAgICAgZWxpZiB0Z3QgaW4gT0FfVEFSR0VUUzoNCiAgICAgICAgICAgIHMsIGMsIG5wb3MsIG5uZWcgPSBfc2NvcmVfY2xhdXNlcyhjbHMsIENPTVBBUlRNRU5UX01BVENIW3RndF0sIE9BX0VWSURFTkNFKQ0KICAgICAgICBlbGlmIHRndCA9PSAiQ29udHVzaW9uIjoNCiAgICAgICAgICAgICMgUmVhY3RpdmUgc3ViY2hvbmRyYWwgb2VkZW1hIHVuZGVyIGEgY2FydGlsYWdlIGRlZmVjdCBpcyBvc3Rlb2FydGhyaXRpcywNCiAgICAgICAgICAgICMgbm90IGEgYnJ1aXNlLiBFeHBsaWNpdCB0cmF1bWEgd29yZGluZyBwdXNoZXMgdGhlIG90aGVyIHdheS4NCiAgICAgICAgICAgIHMsIGMsIG5wb3MsIG5uZWcgPSBfc2NvcmVfY2xhdXNlcyhjbHMsIERJUkVDVF9NQVRDSFt0Z3RdLCBOb25lLCBERUNPWS5nZXQodGd0KSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250ZXh0X3BlbmFsdHk9REVHRU5FUkFUSVZFX01BUlJPVywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250ZXh0X2JvbnVzPVRSQVVNQSkNCiAgICAgICAgZWxzZToNCiAgICAgICAgICAgIHMsIGMsIG5wb3MsIG5uZWcgPSBfc2NvcmVfY2xhdXNlcyhjbHMsIERJUkVDVF9NQVRDSFt0Z3RdLCBOb25lLCBERUNPWS5nZXQodGd0KSkNCiAgICAgICAgb3V0W3RndF0gPSBzDQogICAgICAgIG91dFt0Z3QgKyAiX19jb25mIl0gPSBjDQogICAgICAgIG91dFt0Z3QgKyAiX19ucG9zIl0gPSBucG9zDQogICAgICAgIG91dFt0Z3QgKyAiX19ubmVnIl0gPSBubmVnDQoNCiAgICAjIC0tLSBjcm9zcy10YXJnZXQgY29ycmVjdGlvbnMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICMNCiAgICAjIEEgd2hvbGUtam9pbnQgb3N0ZW9hcnRocml0aXMgc3RhdGVtZW50IGlzIGV2aWRlbmNlIGZvciBldmVyeSBjb21wYXJ0bWVudCB0aGF0IHdhcw0KICAgICMgbm90IHNlcGFyYXRlbHkgYXNzZXNzZWQuIFdpdGhvdXQgdGhpcywgImluY2lwaWVudCBPQSBvZiBhbGwgdGhyZWUgY29tcGFydG1lbnRzIg0KICAgICMgc2NvcmVzIHplcm8gb24gYWxsIHRocmVlIE9BIHRhcmdldHMuDQogICAgZ19oaXRzID0gW2MgZm9yIGMgaW4gY2xzIGlmIEdMT0JBTF9PQS5zZWFyY2goYykgYW5kIF9wb2xhcml0eShjLCAwKSA9PSAicG9zaXRpdmUiXQ0KICAgIGlmIGdfaGl0czoNCiAgICAgICAgZ3Njb3JlID0gMC41MCArIDAuNDIgKiBtYXgoX3NldmVyaXR5KGMpIGZvciBjIGluIGdfaGl0cykNCiAgICAgICAgZm9yIHRndCBpbiBPQV9UQVJHRVRTOg0KICAgICAgICAgICAgaWYgb3V0W3RndCArICJfX25wb3MiXSA9PSAwIGFuZCBvdXRbdGd0ICsgIl9fbm5lZyJdID09IDA6DQogICAgICAgICAgICAgICAgb3V0W3RndF0gPSBtYXgob3V0W3RndF0sIGdzY29yZSAqIDAuOTIpDQogICAgICAgICAgICAgICAgb3V0W3RndCArICJfX2NvbmYiXSA9IG1heChvdXRbdGd0ICsgIl9fY29uZiJdLCAwLjQpDQogICAgICAgICAgICAgICAgIyBFWFAtMDA1OiBhZG1pdCBHTE9CQUxfT0Egc29mdCBzY29yZSBpbnRvIHBzZXVkbyB0YWJsZQ0KICAgICAgICAgICAgICAgIG91dFt0Z3QgKyAiX19zb2Z0Il0gPSAxDQoNCiAgICAjIFN5bm92aXRpcyBpcyBmcmVxdWVudGx5IHZpc2libGUgb24gdGhlIGltYWdlcyBhbmQgYWJzZW50IGZyb20gdGhlIHRleHQsIHNvIHNpbGVuY2UNCiAgICAjIGlzIHdlYWsgZXZpZGVuY2Ugb2YgYWJzZW5jZSBoZXJlIGluIGEgd2F5IGl0IGlzIG5vdCBmb3Igb3RoZXIgZmluZGluZ3MuIEVmZnVzaW9uIGlzDQogICAgIyBpdHMgbW9zdCByZWxpYWJsZSB0ZXh0dWFsIHByb3h5IC0gdGhlIHR3byBzaGFyZSBhIG1lY2hhbmlzbSAtIHNvIGEgc2lsZW50IHN5bm92aXRpcw0KICAgICMgaW5oZXJpdHMgYSBmcmFjdGlvbiBvZiB0aGUgZWZmdXNpb24gZXZpZGVuY2UgaW5zdGVhZCBvZiBmYWxsaW5nIHRvIHRoZSBmbG9vci4NCiAgICBpZiBvdXRbIlN5bm92aXRpc19fbnBvcyJdID09IDAgYW5kIG91dFsiU3lub3ZpdGlzX19ubmVnIl0gPT0gMDoNCiAgICAgICAgb3V0WyJTeW5vdml0aXMiXSA9IG1heChvdXRbIlN5bm92aXRpcyJdLCAwLjI4ICsgMC40NSAqIChvdXRbIkVmZnVzaW9uIl0gLSAwLjI4KSkNCiAgICAgICAgIyBFWFAtMDA1OiBpZiBlZmZ1c2lvbiBoYXMgdGV4dHVhbCBldmlkZW5jZSwga2VlcCB0aGUgc3lub3ZpdGlzIHByb3h5IGluIHRoZSB0YWJsZQ0KICAgICAgICBpZiBvdXQuZ2V0KCJFZmZ1c2lvbl9fbnBvcyIsIDApID4gMCBvciBvdXQuZ2V0KCJFZmZ1c2lvbl9fbm5lZyIsIDApID4gMDoNCiAgICAgICAgICAgIG91dFsiU3lub3ZpdGlzX19zb2Z0Il0gPSAxDQoNCiAgICByZXR1cm4gb3V0DQoNCg0KIyA9PT09PT09PT09PT09PT09PSDpm4bmiJAgQVBJKOacrOS7k+W6k+aWsOWinizpnZ7np7vmpI3ku6PnoIEpID09PT09PT09PT09PT09PT09DQoNCg0KZGVmIHJlcG9ydF9zY29yZV90b190YXJnZXQocmVzOiBkaWN0LCB0Z3Q6IHN0cik6DQogICAgIiIi5oqKIGV4dHJhY3QoKSDnmoTkuIDkuKrnm67moIfnu5PmnpzmmKDlsITkuLogQkNFIHNvZnQg55uu5qCHKOaIliBOYU4p44CCDQoNCiAgICBuX3Bvcz4wIC0+IOivgeaNruWIhuaVsCjpmLPmgKcsMC43Mn4wLjk1KQ0KICAgIG5fcG9zPT0wIOS4lCBuX25lZz4wIC0+IOivgeaNruWIhuaVsCjpmLTmgKcsMC4wNH4wLjIwKQ0KICAgIOWFtuS9mSjmsonpu5gv5LiN56Gu5a6aKS0+IE5hTjror6XmoLzkuI3ov5vmjZ/lpLENCiAgICAiIiINCiAgICBucG9zID0gcmVzLmdldCh0Z3QgKyAiX19ucG9zIiwgMCkNCiAgICBubmVnID0gcmVzLmdldCh0Z3QgKyAiX19ubmVnIiwgMCkNCiAgICBpZiBucG9zID4gMDoNCiAgICAgICAgcmV0dXJuIGZsb2F0KHJlc1t0Z3RdKQ0KICAgIGlmIG5uZWcgPiAwOg0KICAgICAgICByZXR1cm4gZmxvYXQocmVzW3RndF0pDQogICAgIyBFWFAtMDA1IHBsdW1iaW5nOiBjcm9zcy10YXJnZXQgY29ycmVjdGlvbnMgdGhhdCBpbnRlbnRpb25hbGx5IHdyb3RlIGEgc2NvcmUNCiAgICBpZiByZXMuZ2V0KHRndCArICJfX3NvZnQiKToNCiAgICAgICAgcmV0dXJuIGZsb2F0KHJlc1t0Z3RdKQ0KICAgIHJldHVybiBmbG9hdCgibmFuIikNCg0KDQpkZWYgX2V4dHJhY3RfY2FjaGVkKHJlcG9ydHMpOg0KICAgIHJldHVybiBbZXh0cmFjdChyKSBmb3IgciBpbiByZXBvcnRzXQ0KDQoNCmRlZiBidWlsZF9wc2V1ZG9fdGFibGUodHJhaW5fZGYsIHJlcG9ydF9jb2w9IlJlcG9ydCIsIHZlcmJvc2U9VHJ1ZSk6DQogICAgIiIi5LuOIHRyYWluX2RmIOeahOaUvuWwhOaKpeWRiueUn+aIkOS8quagh+etvuihqChTdHVkeUluc3RhbmNlVUlEICsgcHNldWRvXzwxMj4p44CCDQoNCiAgICDov5Tlm54gRGF0YUZyYW1lO+WIhuaVsOWIlyBmbG9hdCzml6Dor4Hmja7moLzkuLogTmFO44CCDQogICAg5a6Y5pa5IGdvbGQg55SxIGxvYWRfbGFiZWxzIOS8mOWFiOimhueblizmraTlpITkuI3mjrrlkozjgIINCiAgICAiIiINCiAgICByZXBvcnRzID0gdHJhaW5fZGZbcmVwb3J0X2NvbF0uZmlsbG5hKCIiKS50b2xpc3QoKQ0KICAgIHVpZHMgPSB0cmFpbl9kZlsiU3R1ZHlJbnN0YW5jZVVJRCJdLnRvbGlzdCgpDQogICAgcmVzID0gX2V4dHJhY3RfY2FjaGVkKHJlcG9ydHMpDQogICAgcm93cyA9IHt9DQogICAgY250ID0ge3Q6IFswLCAwLCAwXSBmb3IgdCBpbiBUQVJHRVRTfSAgICMgW3BvcywgbmVnLCBuYW5dDQogICAgZm9yIHQgaW4gVEFSR0VUUzoNCiAgICAgICAgdmFscyA9IFtdDQogICAgICAgIGZvciByIGluIHJlczoNCiAgICAgICAgICAgIHYgPSByZXBvcnRfc2NvcmVfdG9fdGFyZ2V0KHIsIHQpDQogICAgICAgICAgICBpZiBwZC5pc25hKHYpOg0KICAgICAgICAgICAgICAgIGNudFt0XVsyXSArPSAxDQogICAgICAgICAgICBlbGlmIHYgPiAwLjU6DQogICAgICAgICAgICAgICAgY250W3RdWzBdICs9IDENCiAgICAgICAgICAgIGVsc2U6DQogICAgICAgICAgICAgICAgY250W3RdWzFdICs9IDENCiAgICAgICAgICAgIHZhbHMuYXBwZW5kKHYpDQogICAgICAgIHJvd3NbInBzZXVkb18iICsgdF0gPSB2YWxzDQogICAgb3V0ID0gcGQuRGF0YUZyYW1lKHsiU3R1ZHlJbnN0YW5jZVVJRCI6IHVpZHMsICoqcm93c30pDQogICAgaWYgdmVyYm9zZToNCiAgICAgICAgcHJpbnQoZiJb5qCH562+XSDmiqXlkYrmir3lj5blmagocnNuYV9yZXBvcnRfbGFiZWxzKTp7bGVuKHVpZHMpfSBzdHVkeSwiDQogICAgICAgICAgICAgIGYi6Zu25oyC6L2957qvIENQVTvmr4/nl4XngbYgcG9zL25lZy/ml6Dor4Hmja46IikNCiAgICAgICAgZm9yIHQgaW4gVEFSR0VUUzoNCiAgICAgICAgICAgIHAsIG4sIHogPSBjbnRbdF0NCiAgICAgICAgICAgIHByaW50KGYiICB7dDoxOHN9IHBvcz17cDo1ZH0gbmVnPXtuOjVkfSDml6Dor4Hmja49e3o6NWR9Ig0KICAgICAgICAgICAgICAgICAgZiIg6KaG55uWPXsocCtuKS9sZW4odWlkcykqMTAwOjUuMWZ9JSIpDQogICAgcmV0dXJuIG91dA0KDQoNCmlmIF9fbmFtZV9fID09ICJfX21haW5fXyI6DQogICAgIyBDUFUgc2FuaXR5OnB5dGhvbiByc25hX3JlcG9ydF9sYWJlbHMucHkNCiAgICBkZiA9IHBkLnJlYWRfY3N2KCJ0cmFpbi5jc3YiLCBucm93cz0yMDApDQogICAgdGFiID0gYnVpbGRfcHNldWRvX3RhYmxlKGRmLCB2ZXJib3NlPVRydWUpDQogICAgcHJpbnQodGFiLmhlYWQoNikudG9fc3RyaW5nKCkpDQo=\")\npath = \"/kaggle/working/rsna_report_labels.py\"\nopen(path, \"w\", encoding=\"utf-8\").write(base64.b64decode(parts[0]).decode(\"utf-8\"))\nexpect = \"15cf06b5f8ef9cd3e0e2d27727274c4fa44f8bb6d7c2ee695cfa5aaad3514c19\"\nh = hashlib.sha256(open(path, \"rb\").read()).hexdigest()\nprint(\"labels exp005\", h, os.path.getsize(path))\nassert h == expect\nsrc = open(path, encoding=\"utf-8\").read()\nassert \"__soft\" in src, \"missing EXP-005 soft plumbing\"\nassert \"EXP-005\" in src\nprint(\"labels EXP-005 OK\")\n"},{"id":"e5-run","cell_type":"code","metadata":{},"execution_count":null,"outputs":[],"source":"import subprocess, sys, os, json\nos.chdir(\"/kaggle/working\")\n# smoke: coverage print from load path\ncmd = [sys.executable, \"-u\", \"rsna_v3.py\",\n       \"--planes\", \"axial\",\n       \"--epochs\", \"3\", \"--folds\", \"5\", \"--only-fold\", \"0\",\n       \"--batch\", \"8\", \"--n-clips\", \"2\",\n       \"--experiment-id\", \"exp_005_label_plumbing\",\n       \"--verbose\"]\nprint(\"=== EXP-005 labels + Axial fold0 ===\", flush=True)\nprint(\" \".join(cmd), flush=True)\nr = subprocess.run(cmd)\nprint(\"returncode\", r.returncode, flush=True)\n\nimport numpy as np, pandas as pd\nartifact_root = \"/kaggle/working/artifacts/exp_005_label_plumbing\"\ncanon = None\nfor uid_path in [\n    os.path.join(artifact_root, \"test_uid.csv\"),\n    os.path.join(artifact_root, \"fold0\", \"Axial\", \"test_uid.csv\"),\n    os.path.join(artifact_root, \"fold0\", \"test_uid.csv\"),\n]:\n    if os.path.isfile(uid_path):\n        canon = pd.read_csv(uid_path)[\"StudyInstanceUID\"].tolist()\n        print(\"canonical uids\", len(canon), uid_path)\n        break\nfor d in [\n    os.path.join(artifact_root, \"fold0\", \"Axial\"),\n    os.path.join(artifact_root, \"fold0\"),\n]:\n    ok = all(os.path.isfile(os.path.join(d, n)) for n in [\"test_pred.npy\", \"test_uid.csv\", \"meta.json\"])\n    print(f\"[artifact] {d}: {'PASS' if ok else 'MISSING'}\")\n    if ok:\n        meta = json.load(open(os.path.join(d, \"meta.json\"), encoding=\"utf-8\"))\n        pred = np.load(os.path.join(d, \"test_pred.npy\"))\n        uids = pd.read_csv(os.path.join(d, \"test_uid.csv\"))[\"StudyInstanceUID\"].tolist()\n        print(\" meta\", {k: meta.get(k) for k in [\"fold\",\"plane\",\"completion_status\",\"fold_train_time_sec\",\"prediction_shape\"]})\n        print(\" pred\", pred.shape, \"uid_match\", uids==canon, \"finite\", bool(np.isfinite(pred).all()),\n              \"range\", float(pred.min()), float(pred.max()), \"mean\", float(pred.mean()))\n        assert meta.get(\"completion_status\")==\"done\"\nsub = \"/kaggle/working/submission.csv\"\nif os.path.isfile(sub):\n    s = pd.read_csv(sub)\n    print(\"[sub]\", s.shape, \"NaN\", int(s.isna().sum().sum()), \"uid_match\",\n          s[\"StudyInstanceUID\"].tolist()==canon if canon else \"n/a\")\nprint(\"[exp005] done\")\n"}]}