龙虾监考排班

智能排班 · 一键导出 · 教师友好

👨‍🏫

老师管理

批量导入老师名单,设置每位老师的监考次数需求,支持Excel/CSV/文本多种导入方式

📋

场次安排

灵活配置考试日期、时间、科目,支持多天多场次,自动生成排班表格

🖨️

一键导出

生成专业监考安排表,支持A4横向打印、班级时钟一键导出、时钟数据CSV

三步完成排班

1

导入老师

批量导入或手动添加监考老师名单

2

配置场次

设置考试日期、时间、科目和考场

3

拖拽排班

拖拽老师到表格完成排班,一键导出

准备好了吗?

只需几分钟,轻松完成全校监考排班

🦞 龙虾老师 · aiedge.top
'); w.document.close(); setTimeout(function(){ w.print(); }, 500); } function downloadExport(){ var content = freezeExportInputs(); var useScale = (printMode === 'fit') ? exportScale : 1.0; var styleStr; var bodyStr; if(useScale < 1.0){ styleStr = '@page{size:A4 landscape;margin:0.5cm;}body{margin:0;padding:0;background:#fff;font-family:Microsoft YaHei,sans-serif;}.export-wrap{transform:scale('+useScale+');transform-origin:top left;width:'+(100/useScale)+'%;overflow:hidden;}'; bodyStr = '
' + content + '
'; } else { styleStr = '@page{size:A4 landscape;margin:0.5cm;}body{margin:0;padding:0;background:#fff;font-family:Microsoft YaHei,sans-serif;}'; bodyStr = content; } var fullHtml = '监考安排表'+bodyStr+'
🦞 龙虾老师 · aiedge.top
'; var blob = new Blob([fullHtml], {type:'text/html;charset=utf-8'}); var a = document.createElement('a'); a.href = URL.createObjectURL(blob); a.download = '监考安排表_A4横向.html'; a.click(); } function exportJSON(){ var data = { teachers: teachers, sessions: sessions, rooms: rooms, matrix: matrix, roleChief: roleChief, roleXs: roleXs, cellCap: cellCap, exportTime: new Date().toLocaleString('zh-CN') }; var json = JSON.stringify(data, null, 2); var blob = new Blob([json], {type:'application/json;charset=utf-8'}); var a = document.createElement('a'); a.href = URL.createObjectURL(blob); a.download = '监考排班配置.json'; a.click(); showToast('配置已导出', 'ok'); } // V3.0:导出到考试中控台 - 智能转换为examConfig格式 function exportToConsole(){ // 从导出页input读取学校名/考试名(如果有) var schoolName = '防城港市第二中学'; var examName = '期末考试监考安排'; var exSchool = document.querySelector('#exportContent input.export-edit-input'); var exTitle = document.querySelectorAll('#exportContent input.export-edit-input')[1]; if(exSchool && exSchool.value) schoolName = exSchool.value; if(exTitle && exTitle.value) examName = exTitle.value; // 解析考试日期(取第一场日期的年月) var firstDate = sessions.length > 0 ? sessions[0].date : ''; var yearMatch = firstDate.match(/(\d{4})年/); var year = yearMatch ? yearMatch[1] : '2025'; var dateMatch = firstDate.match(/(\d{1,2})月(\d{1,2})日/); var isoDate = year + '-' + (dateMatch ? String(dateMatch[1]).padStart(2,'0') : '01') + '-' + (dateMatch ? String(dateMatch[2]).padStart(2,'0') : '01'); var cnDate = year + '年' + (dateMatch ? dateMatch[1]+'月'+dateMatch[2]+'日' : ''); // 转换sessions为中控台格式(按教室组织) var roomSessions = {}; var sessionId = 1; // 遍历所有教室 rooms.forEach(function(room, ri){ roomSessions[room] = { id: sessionId++, name: room, date: isoDate, status: 'upcoming', subjects: [] }; // 遍历所有场次 sessions.forEach(function(ses, si){ // 解析时间 HH:MM~HH:MM var normalizedTime = (ses.time || '').replace(/:/g,':').replace(/~/g,'~'); var timeMatch = normalizedTime.match(/(\d+:\d+)~(\d+:\d+)/); var startTime = timeMatch ? timeMatch[1] : ''; var endTime = timeMatch ? timeMatch[2] : ''; // 科目拆分(可能含顿号、逗号) var subjects = ses.subject.split(/[、,,]/).map(function(s){ return s.trim(); }).filter(function(s){ return s; }); // 获取该教室的监考老师 var teachers = (matrix[si] && matrix[si][ri]) || []; var mainTeacher = teachers[0] || ''; var viceTeacher = teachers[1] || ''; // 如果该教室有排班数据 if(mainTeacher && mainTeacher !== '×'){ subjects.forEach(function(subj){ var hasListening = subj.indexOf('英语') !== -1; roomSessions[room].subjects.push({ subject: subj, start: startTime, end: endTime, teacher: mainTeacher, chief: (roleChief[si] || []).join('、'), collector: (roleXs[si] || []).join('、'), hasListening: hasListening }); }); } }); }); // 转换为数组 var consoleSessions = Object.values(roomSessions); // 第一个session标记为current(如果有),其余upcoming if(consoleSessions.length > 0){ consoleSessions[0].status = 'current'; } var examConfig = { examInfo: { name: schoolName + ' ' + examName, date: cnDate, isoDate: isoDate, grade: '', school: schoolName }, sessions: consoleSessions, encourageMsgs: ['认真复习','保持安静','诚信考试','加油同学们'], alerts: { entry: 15, remain: 15, collect: 5 }, _source: '监考排班V4.1', _exportTime: new Date().toLocaleString('zh-CN') }; var json = JSON.stringify(examConfig, null, 2); var blob = new Blob([json], {type:'application/json;charset=utf-8'}); var a = document.createElement('a'); a.href = URL.createObjectURL(blob); a.download = '考试中控台配置_' + isoDate + '.json'; a.click(); playSfx('success'); showToast('已导出中控台配置('+consoleSessions.length+'个场次)', 'ok'); } /* ================================================================== */ /* 下拉菜单控制 */ /* ================================================================== */ function toggleExportDropdown(e){ e.stopPropagation(); var menu = document.getElementById('exportDropdownMenu'); menu.classList.toggle('show'); } // 点击外部关闭下拉菜单 document.addEventListener('click', function(e){ var dd = document.getElementById('exportDropdown'); if(dd && !dd.contains(e.target)){ document.getElementById('exportDropdownMenu').classList.remove('show'); } }); /* ================================================================== */ /* 导出为班级时钟(模式1) */ /* ================================================================== */ var V6_TEMPLATE_B64 = 'PCFET0NUWVBFIGh0bWw+CjxodG1sIGxhbmc9InpoLUNOIj4KPGhlYWQ+CjxtZXRhIGNoYXJzZXQ9IlVURi04Ij4KPG1ldGEgbmFtZT0idmlld3BvcnQiIGNvbnRlbnQ9IndpZHRoPWRldmljZS13aWR0aCwgaW5pdGlhbC1zY2FsZT0xLjAiPgo8dGl0bGU+8J+mniDpvpnomb7mlZnliqHlj7Agwrcg54+t57qn5pe26ZKf5aSn5bGPIFY2LjA8L3RpdGxlPgo8c3R5bGU+Ci8qID09PT09PT09PSBDU1Mg5Y+Y6YeP77ya5L2O6aWx5ZKM5pqW5qmZ5L2T57O7ID09PT09PT09PSAqLwo6cm9vdCB7CiAgLS1wcmltYXJ5OiAjNWI4ZGVmOwogIC0tcHJpbWFyeS1saWdodDogI2Y1YTU2MjsKICAtLXByaW1hcnktYmc6ICNmZmY5ZjU7CiAgLS1wcmltYXJ5LWJnMjogI2ZmZjFlODsKICAtLXdhcm0tZ3JheTogI2ZhZmFmODsKICAtLXN0YXR1cy1vbmdvaW5nOiB2YXIoLS1wcmltYXJ5KTsKICAtLXN0YXR1cy13YWl0aW5nOiAjN2E5ZWM4OwogIC0tc3RhdHVzLWRvbmU6ICNiMGIwYjA7CiAgLS1zdGF0dXMtZW5kZWQ6ICNkOTRmNGY7CiAgLS1zdGF0dXMtZW5kZWQtbGlnaHQ6ICNmZGYwZjA7CiAgLS1iZzogI2ZhZmFmODsKICAtLWJnLWNhcmQ6ICNmZmZmZmY7CiAgLS10ZXh0OiAjMmMyYzJjOwogIC0tdGV4dC1zZWM6ICM1YTVhNWE7CiAgLS10ZXh0LXN1YjogI2EwYTBhMDsKICAtLWJvcmRlcjogI2VhZThlNDsKICAtLWJvcmRlci1sdDogI2YwZWVlODsKICAtLXNoYWRvdy1zbTogMCAxcHggNHB4IHJnYmEoMCwwLDAsMC4wNCk7CiAgLS1zaGFkb3ctbWQ6IDAgNHB4IDIwcHggcmdiYSgwLDAsMCwwLjA3KTsKICAtLXNoYWRvdy1sZzogMCA4cHggNDBweCByZ2JhKDAsMCwwLDAuMTApOwogIC0tcmFkaXVzOiAxNHB4OwogIC0tcmFkaXVzLXNtOiAxMHB4OwogIC0tcmFkaXVzLXhzOiA2cHg7CiAgLS1lYXNlOiBjdWJpYy1iZXppZXIoMC40LCAwLCAwLjIsIDEpOwogIC0tZm9udC1tb25vOiAnU291cmNlIENvZGUgUHJvJywgJ0NvbnNvbGFzJywgJ05vdG8gU2FucyBNb25vJywgbW9ub3NwYWNlOwogIC0tZm9udC1zYW5zOiAnTm90byBTYW5zIFNDJywgLWFwcGxlLXN5c3RlbSwgJ01pY3Jvc29mdCBZYUhlaScsIHNhbnMtc2VyaWY7Cn0KLyog5pqW6Imy5Li76aKYICovCmJvZHkud2FybSB7CiAgLS1wcmltYXJ5OiAjZjI3YzIyOwogIC0tcHJpbWFyeS1saWdodDogI2Y1YTU2MjsKICAtLXByaW1hcnktYmc6ICNmZmY5ZjU7CiAgLS1wcmltYXJ5LWJnMjogI2ZmZjFlODsKfQpib2R5LmRhcmsgewogIC0tYmc6ICMxNDE0MTg7CiAgLS1iZy1jYXJkOiAjMWUxZTI4OwogIC0tdGV4dDogI2U4ZThlODsKICAtLXRleHQtc2VjOiAjYTBhMGEwOwogIC0tdGV4dC1zdWI6ICM2NjY7CiAgLS1ib3JkZXI6ICMyYTJhMzA7CiAgLS1ib3JkZXItbHQ6ICMyMjIyMjg7CiAgLS1wcmltYXJ5OiAjZjVhNTYyOwogIC0tcHJpbWFyeS1iZzogIzJhMjIxODsKICAtLXByaW1hcnktYmcyOiAjMzIyYTFlOwogIC0td2FybS1ncmF5OiAjMTQxNDE4OwogIC0tc2hhZG93LXNtOiAwIDFweCA0cHggcmdiYSgwLDAsMCwwLjIpOwogIC0tc2hhZG93LW1kOiAwIDRweCAyMHB4IHJnYmEoMCwwLDAsMC4yNSk7CiAgLS1zaGFkb3ctbGc6IDAgOHB4IDQwcHggcmdiYSgwLDAsMCwwLjMpOwp9CiogeyBtYXJnaW46MDsgcGFkZGluZzowOyBib3gtc2l6aW5nOmJvcmRlci1ib3g7IH0KYm9keSB7CiAgZm9udC1mYW1pbHk6IHZhcigtLWZvbnQtc2Fucyk7CiAgYmFja2dyb3VuZDogdmFyKC0tYmcpOyBjb2xvcjogdmFyKC0tdGV4dCk7CiAgbGluZS1oZWlnaHQ6IDEuNjsgbWluLWhlaWdodDogMTAwdmg7CiAgLXdlYmtpdC1mb250LXNtb290aGluZzogYW50aWFsaWFzZWQ7CiAgdHJhbnNpdGlvbjogYmFja2dyb3VuZCAwLjRzLCBjb2xvciAwLjRzOwogIG92ZXJmbG93LXg6IGhpZGRlbjsgZm9udC1zaXplOiAxNnB4Owp9CgovKiA9PT09PT09PT0g6aG26YOo5a+86IiqID09PT09PT09PSAqLwoubmF2IHsKICBwb3NpdGlvbjogZml4ZWQ7IHRvcDowOyBsZWZ0OjA7IHJpZ2h0OjA7IHotaW5kZXg6MTAwOwogIGJhY2tncm91bmQ6IHJnYmEoMjU1LDI1NSwyNTUsMC45NCk7IGJhY2tkcm9wLWZpbHRlcjogYmx1cigyNHB4KTsKICBib3JkZXItYm90dG9tOiAxcHggc29saWQgdmFyKC0tYm9yZGVyKTsKICBwYWRkaW5nOiAwIDEuNXJlbTsgaGVpZ2h0OiA1MHB4OwogIGRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiBjZW50ZXI7IGp1c3RpZnktY29udGVudDogc3BhY2UtYmV0d2VlbjsKICB0cmFuc2l0aW9uOiB0cmFuc2Zvcm0gMC4zNXMgdmFyKC0tZWFzZSksIG9wYWNpdHkgMC4zNXM7Cn0KYm9keS5kYXJrIC5uYXYgeyBiYWNrZ3JvdW5kOiByZ2JhKDIwLDIwLDI0LDAuOTYpOyBib3JkZXItYm90dG9tLWNvbG9yOiB2YXIoLS1ib3JkZXIpOyB9Ci5uYXYtYnJhbmQgeyBkaXNwbGF5OmZsZXg7IGFsaWduLWl0ZW1zOmNlbnRlcjsgZ2FwOjAuNnJlbTsgfQoubmF2LWxvZ28gewogIHdpZHRoOiAzMnB4OyBoZWlnaHQ6MzJweDsgYm9yZGVyLXJhZGl1czo4cHg7CiAgYmFja2dyb3VuZDogbGluZWFyLWdyYWRpZW50KDEzNWRlZywgdmFyKC0tcHJpbWFyeSksIHZhcigtLXByaW1hcnktbGlnaHQpKTsKICBkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczpjZW50ZXI7IGp1c3RpZnktY29udGVudDpjZW50ZXI7CiAgZmxleC1zaHJpbms6MDsgb3ZlcmZsb3c6aGlkZGVuOyBjdXJzb3I6cG9pbnRlcjsKICB0cmFuc2l0aW9uOiB0cmFuc2Zvcm0gMC4yNXMgdmFyKC0tZWFzZSk7CiAgYm94LXNoYWRvdzogMCAycHggNnB4IHJnYmEoMCwwLDAsMC4xNSk7Cn0KLm5hdi1sb2dvOmhvdmVyIHsgdHJhbnNmb3JtOiBzY2FsZSgxLjA4KSByb3RhdGUoLTNkZWcpOyB9Ci5uYXYtbG9nbyBzdmcgeyB3aWR0aDoxMDAlOyBoZWlnaHQ6MTAwJTsgY29sb3I6I2ZmZjsgfQoubmF2LXRpdGxlIHsgZm9udC1zaXplOjAuOTVyZW07IGZvbnQtd2VpZ2h0OjgwMDsgbGV0dGVyLXNwYWNpbmc6LTAuMDJlbTsgfQoubmF2LXN1YiB7IGZvbnQtc2l6ZTowLjY1cmVtOyBjb2xvcjp2YXIoLS10ZXh0LXN1Yik7IGZvbnQtd2VpZ2h0OjUwMDsgbWFyZ2luLWxlZnQ6MC4zcmVtOyB9Ci5uYXYtbW9kZXMgeyBkaXNwbGF5OmZsZXg7IGFsaWduLWl0ZW1zOmNlbnRlcjsgZ2FwOjRweDsgZmxleDoxOyBqdXN0aWZ5LWNvbnRlbnQ6Y2VudGVyOyB9Ci5uYXYtbW9kZXMgLm1vZGUtYnRuIHsKICBwYWRkaW5nOjAuMjJyZW0gMC42NXJlbTsgYm9yZGVyLXJhZGl1czoxMDBweDsgZm9udC1zaXplOjAuNjNyZW07IGZvbnQtd2VpZ2h0OjYwMDsKICBib3JkZXI6bm9uZTsgYmFja2dyb3VuZDp0cmFuc3BhcmVudDsgY29sb3I6dmFyKC0tdGV4dC1zdWIpOyBjdXJzb3I6cG9pbnRlcjsKICB0cmFuc2l0aW9uOmFsbCAwLjJzIHZhcigtLWVhc2UpOyBmb250LWZhbWlseTppbmhlcml0OyB3aGl0ZS1zcGFjZTpub3dyYXA7Cn0KLm5hdi1tb2RlcyAubW9kZS1idG46aG92ZXIgeyBiYWNrZ3JvdW5kOnZhcigtLXByaW1hcnktYmcyKTsgY29sb3I6dmFyKC0tcHJpbWFyeSk7IH0KLm5hdi1tb2RlcyAubW9kZS1idG4uYWN0aXZlIHsgYmFja2dyb3VuZDp2YXIoLS1wcmltYXJ5KTsgY29sb3I6I2ZmZjsgYm94LXNoYWRvdzowIDJweCA4cHggcmdiYSgyNDIsMTI0LDM0LDAuMyk7IH0KLm5hdi1hY3RzIHsgZGlzcGxheTpmbGV4OyBhbGlnbi1pdGVtczpjZW50ZXI7IGdhcDowLjNyZW07IH0KLm5hdi1idG4gewogIHdpZHRoOiAzNHB4OyBoZWlnaHQ6MzRweDsgYm9yZGVyLXJhZGl1czo1MCU7IGJvcmRlcjpub25lOyBiYWNrZ3JvdW5kOnRyYW5zcGFyZW50OwogIGNvbG9yOiB2YXIoLS10ZXh0LXNlYyk7IGZvbnQtc2l6ZToxcmVtOyBjdXJzb3I6cG9pbnRlcjsKICBkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczpjZW50ZXI7IGp1c3RpZnktY29udGVudDpjZW50ZXI7CiAgdHJhbnNpdGlvbjogYWxsIDAuMnMgdmFyKC0tZWFzZSk7Cn0KLm5hdi1idG46aG92ZXIgeyBiYWNrZ3JvdW5kOnZhcigtLXByaW1hcnktYmcyKTsgY29sb3I6dmFyKC0tcHJpbWFyeSk7IHRyYW5zZm9ybTpzY2FsZSgxLjA4KTsgfQoKLnRoZW1lLWJ0bnMgeyBkaXNwbGF5OmZsZXg7IGdhcDo0cHg7IGJhY2tncm91bmQ6dmFyKC0tYmctY2FyZCk7IHBhZGRpbmc6M3B4OyBib3JkZXItcmFkaXVzOjEwMHB4OyBtYXJnaW4tcmlnaHQ6MC4zcmVtOyBib3JkZXI6MXB4IHNvbGlkIHZhcigtLWJvcmRlcik7IH0KLnRoZW1lLWJ0biB7IHdpZHRoOjIycHg7IGhlaWdodDoyMnB4OyBib3JkZXItcmFkaXVzOjUwJTsgYm9yZGVyOjJweCBzb2xpZCB0cmFuc3BhcmVudDsgY3Vyc29yOnBvaW50ZXI7IHRyYW5zaXRpb246YWxsIDAuMnM7IH0KLnRoZW1lLWJ0bi5hY3RpdmUgeyBib3JkZXItY29sb3I6dmFyKC0tcHJpbWFyeSk7IHRyYW5zZm9ybTpzY2FsZSgxLjE1KTsgfQoudGhlbWUtYnRuW2Q9ImxpZ2h0Il0geyBiYWNrZ3JvdW5kOmxpbmVhci1ncmFkaWVudCgxMzVkZWcsI2ZmZiwjZjBmMGYwKTsgfQoudGhlbWUtYnRuW2Q9Indhcm0iXSB7IGJhY2tncm91bmQ6bGluZWFyLWdyYWRpZW50KDEzNWRlZyx2YXIoLS1wcmltYXJ5KSx2YXIoLS1wcmltYXJ5LWxpZ2h0KSk7IH0KLnRoZW1lLWJ0bltkPSJkYXJrIl0geyBiYWNrZ3JvdW5kOmxpbmVhci1ncmFkaWVudCgxMzVkZWcsIzFlMWUyOCwjMmEyYTMwKTsgfQoKLm1vcmUtd3JhcCB7IHBvc2l0aW9uOnJlbGF0aXZlOyB9Ci5tb3JlLW1lbnUgewogIHBvc2l0aW9uOiBhYnNvbHV0ZTsgdG9wOjQycHg7IHJpZ2h0OjA7IGJhY2tncm91bmQ6dmFyKC0tYmctY2FyZCk7CiAgYm9yZGVyLXJhZGl1czogdmFyKC0tcmFkaXVzLXNtKTsgYm94LXNoYWRvdzp2YXIoLS1zaGFkb3ctbGcpOyBib3JkZXI6MXB4IHNvbGlkIHZhcigtLWJvcmRlcik7CiAgcGFkZGluZzogMC4zNXJlbTsgbWluLXdpZHRoOjE2MHB4OyB6LWluZGV4OjIwMDsKICBvcGFjaXR5OiAwOyBwb2ludGVyLWV2ZW50czpub25lOyB0cmFuc2Zvcm06dHJhbnNsYXRlWSgtOHB4KTsKICB0cmFuc2l0aW9uOiBhbGwgMC4ycyB2YXIoLS1lYXNlKTsKfQoubW9yZS1tZW51LnNob3cgeyBvcGFjaXR5OjE7IHBvaW50ZXItZXZlbnRzOmF1dG87IHRyYW5zZm9ybTp0cmFuc2xhdGVZKDApOyB9Ci5tb3JlLWl0ZW0gewogIGRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOmNlbnRlcjsgZ2FwOjAuNXJlbTsgcGFkZGluZzowLjQ1cmVtIDAuOHJlbTsKICBib3JkZXItcmFkaXVzOiB2YXIoLS1yYWRpdXMteHMpOyBmb250LXNpemU6MC43OHJlbTsgZm9udC13ZWlnaHQ6NjAwOwogIGNvbG9yOiB2YXIoLS10ZXh0KTsgY3Vyc29yOnBvaW50ZXI7IHRyYW5zaXRpb246YWxsIDAuMTVzOwogIHdpZHRoOiAxMDAlOyBib3JkZXI6bm9uZTsgYmFja2dyb3VuZDpub25lOyB0ZXh0LWFsaWduOmxlZnQ7IGZvbnQtZmFtaWx5OmluaGVyaXQ7Cn0KLm1vcmUtaXRlbTpob3ZlciB7IGJhY2tncm91bmQ6dmFyKC0tcHJpbWFyeS1iZzIpOyBjb2xvcjp2YXIoLS1wcmltYXJ5KTsgfQoKLyogPT09PT09PT09IOS4u+S9k+WuueWZqCA9PT09PT09PT0gKi8KLndyYXAgeyBtYXgtd2lkdGg6MTM4MHB4OyBtYXJnaW46MCBhdXRvOyBwYWRkaW5nOjU4cHggMS41cmVtIDNyZW07IH0KCi8qID09PT09PT09PSDnrKwx5q6177ya6aG26YOo5pe26Ze05qih5Z2X77yI5pyA5aSn5YyW77yJPT09PT09PT09ICovCi50aW1lLWhlcm8gewogIGJhY2tncm91bmQ6IGxpbmVhci1ncmFkaWVudCgxODBkZWcsIHZhcigtLXByaW1hcnktYmcpIDAlLCB2YXIoLS1iZy1jYXJkKSAxMDAlKTsKICBib3JkZXItcmFkaXVzOiB2YXIoLS1yYWRpdXMpOyBib3gtc2hhZG93OnZhcigtLXNoYWRvdy1tZCk7CiAgYm9yZGVyOiAxcHggc29saWQgdmFyKC0tYm9yZGVyKTsgcGFkZGluZzoyLjVyZW0gMS41cmVtIDEuNXJlbTsKICBwb3NpdGlvbjogcmVsYXRpdmU7IG92ZXJmbG93OmhpZGRlbjsgdGV4dC1hbGlnbjpjZW50ZXI7IG1hcmdpbi1ib3R0b206MXJlbTsKICB0cmFuc2l0aW9uOiBhbGwgMC4zcyB2YXIoLS1lYXNlKTsKfQovKiDpobbpg6jnirbmgIHoibLnur8gKi8KLnRpbWUtaGVybzo6YmVmb3JlIHsKICBjb250ZW50OiAnJzsgcG9zaXRpb246YWJzb2x1dGU7IHRvcDowOyBsZWZ0OjA7IHJpZ2h0OjA7IGhlaWdodDozcHg7CiAgYmFja2dyb3VuZDogdmFyKC0taGVyby1saW5lLWNvbG9yLCB2YXIoLS1wcmltYXJ5KSk7IHRyYW5zaXRpb246YmFja2dyb3VuZCAwLjRzOwp9CgovKiDnirbmgIHmjIfnpLogKi8KLnRpbWUtYXV4IHsKICBmb250LXNpemU6IDAuNzVyZW07IGZvbnQtd2VpZ2h0OjUwMDsgY29sb3I6dmFyKC0tdGV4dC1zdWIpOwogIGxldHRlci1zcGFjaW5nOiAwLjA4ZW07IG1hcmdpbi1ib3R0b206MC4zcmVtOwogIGRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOmNlbnRlcjsganVzdGlmeS1jb250ZW50OmNlbnRlcjsgZ2FwOjAuNHJlbTsKfQoudGltZS1hdXggLmF1eC1kb3QgewogIHdpZHRoOiA2cHg7IGhlaWdodDo2cHg7IGJvcmRlci1yYWRpdXM6NTAlOyBiYWNrZ3JvdW5kOnZhcigtLXByaW1hcnkpOwogIGFuaW1hdGlvbjogcGQgMnMgaW5maW5pdGU7IHRyYW5zaXRpb246YmFja2dyb3VuZCAwLjRzOwp9CkBrZXlmcmFtZXMgcGQgeyAwJSwxMDAle29wYWNpdHk6MTt9IDUwJXtvcGFjaXR5OjAuMzt9IH0KCi8qIOWAkuiuoeaXtuaVsOWtlyDigJTigJQg5pyA5aSn5YyW5pyA6YaS55uuICovCi50aW1lLWRpc3BsYXkgewogIGZvbnQtZmFtaWx5OiB2YXIoLS1mb250LW1vbm8pOwogIGZvbnQtc2l6ZTogMTNyZW07IGZvbnQtd2VpZ2h0OiA5MDA7IGxpbmUtaGVpZ2h0OiAxLjA7CiAgbGV0dGVyLXNwYWNpbmc6IDAuMDhlbTsgY29sb3I6dmFyKC0tY2xvY2stY29sb3IsIHZhcigtLXByaW1hcnkpKTsKICBtYXJnaW46IDAuMXJlbSAwIDAuMnJlbTsgdHJhbnNpdGlvbjpmb250LXNpemUgMC4zcywgY29sb3IgMC40czsKICBmb250LXZhcmlhbnQtbnVtZXJpYzogdGFidWxhci1udW1zOyBmb250LWZlYXR1cmUtc2V0dGluZ3M6ICJ0bnVtIiwibG51bSI7Cn0KLyogVjUuMO+8muaXtumSn+minOiJsuaho+S9jSAqLwoudGltZS1kaXNwbGF5LmMtb3JhbmdlIHsgLS1jbG9jay1jb2xvcjojRkY2NzAwOyB9Ci50aW1lLWRpc3BsYXkuYy1ibGFjayB7IC0tY2xvY2stY29sb3I6IzFhMWExYTsgfQoudGltZS1kaXNwbGF5LmMtYmx1ZSB7IC0tY2xvY2stY29sb3I6dmFyKC0tcHJpbWFyeSk7IH0KLnRpbWUtZGlzcGxheS5zbWFsbCB7IGZvbnQtc2l6ZTogN3JlbTsgfQoudGltZS1kaXNwbGF5LndhaXRpbmcgeyBjb2xvcjp2YXIoLS1zdGF0dXMtd2FpdGluZyk7IH0KLnRpbWUtZGlzcGxheS5lbmRlZCB7IGNvbG9yOnZhcigtLXN0YXR1cy1lbmRlZCk7IH0KCi8qIOW6lemDqOagh+ivhu+8muaegeeugCAqLwoudGltZS1pZCB7CiAgZm9udC1zaXplOiAxcmVtOyBmb250LXdlaWdodDo3MDA7IGNvbG9yOnZhcigtLXRleHQtc2VjKTsKICBsZXR0ZXItc3BhY2luZzogMC4wNGVtOyBtYXJnaW4tYm90dG9tOjAuNnJlbTsKfQoKLyog5a2X5L2T5YiH5o2iICovCi5mb250LWN0cmwgewogIHBvc2l0aW9uOiBhYnNvbHV0ZTsgYm90dG9tOjAuOHJlbTsgcmlnaHQ6MXJlbTsKICBvcGFjaXR5OiAwOyB0cmFuc2l0aW9uOm9wYWNpdHkgMC4yNXM7IGRpc3BsYXk6ZmxleDsgYWxpZ24taXRlbXM6Y2VudGVyOyBnYXA6MC41cmVtOwp9Ci50aW1lLWhlcm86aG92ZXIgLmZvbnQtY3RybCB7IG9wYWNpdHk6MC44OyB9Ci5mb250LWN0cmwgc2VsZWN0IHsKICBwYWRkaW5nOiAwLjE1cmVtIDAuNHJlbTsgYm9yZGVyLXJhZGl1czo0cHg7IGJvcmRlcjoxcHggc29saWQgdmFyKC0tYm9yZGVyKTsKICBiYWNrZ3JvdW5kOiB2YXIoLS1iZy1jYXJkKTsgY29sb3I6dmFyKC0tdGV4dCk7IGZvbnQtc2l6ZTowLjYycmVtOyBmb250LWZhbWlseTppbmhlcml0OyBvdXRsaW5lOm5vbmU7Cn0KLyogVjUuMO+8muaXtumSn+S4ieiJsuWIh+aNoiAqLwouY29sb3Itc3dpdGNoe2Rpc3BsYXk6ZmxleDtnYXA6NHB4O2FsaWduLWl0ZW1zOmNlbnRlcjtiYWNrZ3JvdW5kOnZhcigtLWJnLWNhcmQpO3BhZGRpbmc6M3B4IDVweDtib3JkZXItcmFkaXVzOjEwMHB4O2JvcmRlcjoxcHggc29saWQgdmFyKC0tYm9yZGVyKTt9Ci5jb2xvci1kb3R7d2lkdGg6MTZweDtoZWlnaHQ6MTZweDtib3JkZXItcmFkaXVzOjUwJTtjdXJzb3I6cG9pbnRlcjtib3JkZXI6MnB4IHNvbGlkIHRyYW5zcGFyZW50O3RyYW5zaXRpb246YWxsIDAuMnM7fQouY29sb3ItZG90OmhvdmVye3RyYW5zZm9ybTpzY2FsZSgxLjE1KTt9Ci5jb2xvci1kb3QuYWN0aXZle2JvcmRlci1jb2xvcjp2YXIoLS10ZXh0LXN1Yik7dHJhbnNmb3JtOnNjYWxlKDEuMSk7fQouYy1vcmFuZ2UtZG90e2JhY2tncm91bmQ6I0ZGNjcwMDt9Ci5jLWJsYWNrLWRvdHtiYWNrZ3JvdW5kOiMxYTFhMWE7fQouYy1ibHVlLWRvdHtiYWNrZ3JvdW5kOiM1YjhkZWY7fQoKLyogPT09PT09PT09IOesrDLmrrXvvJrlt6blj7Plj4zmoI8gPT09PT09PT09ICovCi5ncmlkIHsgZGlzcGxheTpmbGV4OyBnYXA6MS4ycmVtOyBhbGlnbi1pdGVtczpmbGV4LXN0YXJ0OyBtYXJnaW4tYm90dG9tOjFyZW07IH0KCi8qIOW3puagj++8muacrOWcuuiAg+ivle+8iOe0p+WHkeaOkueJiO+8jOa2iOmZpOepuueZve+8iSAqLwouY29sLWwgeyBmbGV4OjE7IG1pbi13aWR0aDowOyB9Ci8qIOW3puagj+WNoeeJh++8mue0p+WHke+8jOWHj+WwkeepuueZvSAqLwouY2FyZCB7CiAgYmFja2dyb3VuZDogdmFyKC0tYmctY2FyZCk7IGJvcmRlci1yYWRpdXM6dmFyKC0tcmFkaXVzKTsKICBib3gtc2hhZG93OiB2YXIoLS1zaGFkb3ctc20pOyBib3JkZXI6MXB4IHNvbGlkIHZhcigtLWJvcmRlcik7CiAgcGFkZGluZzogMC44cmVtIDFyZW07IHRyYW5zaXRpb246YWxsIDAuMjVzIHZhcigtLWVhc2UpOyBwb3NpdGlvbjpyZWxhdGl2ZTsgb3ZlcmZsb3c6aGlkZGVuOwogIGhlaWdodDogMTAwJTsKfQouY2FyZDpob3ZlciB7IGJveC1zaGFkb3c6dmFyKC0tc2hhZG93LW1kKTsgdHJhbnNmb3JtOnRyYW5zbGF0ZVkoLTFweCk7IH0KCi5jYXJkLWhkIHsKICBkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczpjZW50ZXI7IGp1c3RpZnktY29udGVudDpzcGFjZS1iZXR3ZWVuOwogIG1hcmdpbi1ib3R0b206IDAuNXJlbTsgcGFkZGluZy1ib3R0b206MC40cmVtOyBib3JkZXItYm90dG9tOjFweCBzb2xpZCB2YXIoLS1ib3JkZXItbHQpOwp9Ci5jYXJkLWhkLXRpdGxlIHsgZm9udC1zaXplOjAuODVyZW07IGZvbnQtd2VpZ2h0OjcwMDsgZGlzcGxheTpmbGV4OyBhbGlnbi1pdGVtczpjZW50ZXI7IGdhcDowLjRyZW07IH0KLmNhcmQtYmFkZ2UgewogIHBhZGRpbmc6IDAuMTJyZW0gMC41NXJlbTsgYm9yZGVyLXJhZGl1czoxMDBweDsgZm9udC1zaXplOjAuNjNyZW07IGZvbnQtd2VpZ2h0OjcwMDsgdHJhbnNpdGlvbjphbGwgMC4zczsKfQouY2FyZC1iYWRnZS5saXZlIHsgYmFja2dyb3VuZDp2YXIoLS1zdGF0dXMtZW5kZWQtbGlnaHQpOyBjb2xvcjp2YXIoLS1zdGF0dXMtZW5kZWQpOyBhbmltYXRpb246cGIgMnMgaW5maW5pdGU7IH0KLmNhcmQtYmFkZ2Uud2FpdCB7IGJhY2tncm91bmQ6I2VlZjZmZjsgY29sb3I6dmFyKC0tc3RhdHVzLXdhaXRpbmcpOyB9CkBrZXlmcmFtZXMgcGIgeyAwJSwxMDAle29wYWNpdHk6MTt9IDUwJXtvcGFjaXR5OjAuNTU7fSB9CgovKiDogIPor5Xml7bpl7TojIPlm7Qg4oCU4oCUIOWKoOWkp+eqgeWHuiAqLwouZXhhbS1yYW5nZSB7CiAgZm9udC1zaXplOiAxLjhyZW07IGZvbnQtd2VpZ2h0OjgwMDsgY29sb3I6dmFyKC0tdGV4dCk7CiAgZm9udC12YXJpYW50LW51bWVyaWM6IHRhYnVsYXItbnVtczsgbWFyZ2luLWJvdHRvbTowLjhyZW07IGxldHRlci1zcGFjaW5nOi0wLjAxZW07Cn0KCi8qIOS/oeaBr+e9keagvO+8muaegee0p+WHkSAqLwouaW5mby1ncmlkIHsKICBkaXNwbGF5OiBncmlkOyBncmlkLXRlbXBsYXRlLWNvbHVtbnM6IDFmciAxZnI7IGdhcDowLjNyZW0gMC44cmVtOwogIG1hcmdpbi1ib3R0b206IDAuNXJlbTsKfQouaW5mby1pdGVtIHsKICBkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczpjZW50ZXI7IGdhcDowLjNyZW07IGZvbnQtc2l6ZTowLjc1cmVtOwogIHBhZGRpbmc6IDAuMjhyZW0gMC40NXJlbTsgYmFja2dyb3VuZDp2YXIoLS1iZyk7IGJvcmRlci1yYWRpdXM6dmFyKC0tcmFkaXVzLXhzKTsKfQouaW5mby1sYWJlbCB7IGNvbG9yOnZhcigtLXRleHQtc3ViKTsgZm9udC13ZWlnaHQ6NjAwOyBmb250LXNpemU6MC42NXJlbTsgbWluLXdpZHRoOjM4cHg7IH0KLmluZm8tdmFsdWUgeyBmb250LXdlaWdodDo3MDA7IGNvbG9yOnZhcigtLXRleHQpOyB9CgovKiDnp5Hnm67ljaHniYfvvJrmnoHntKflh5EgKi8KLnN1Yi1jYXJkIHsKICBiYWNrZ3JvdW5kOiB2YXIoLS1iZyk7IGJvcmRlci1yYWRpdXM6dmFyKC0tcmFkaXVzLXNtKTsgcGFkZGluZzowLjQ1cmVtIDAuN3JlbTsKICBtYXJnaW4tYm90dG9tOiAwLjM1cmVtOyBib3JkZXI6MXB4IHNvbGlkIHZhcigtLWJvcmRlci1sdCk7Cn0KLnN1Yi1jYXJkLW5hbWUgeyBmb250LXNpemU6MC44MnJlbTsgZm9udC13ZWlnaHQ6NzAwOyBjb2xvcjp2YXIoLS10ZXh0KTsgbWFyZ2luLWJvdHRvbTowLjJyZW07IH0KLnN1Yi1jYXJkLW1ldGEgeyBmb250LXNpemU6MC43cmVtOyBjb2xvcjp2YXIoLS10ZXh0LXN1Yik7IGRpc3BsYXk6ZmxleDsgZ2FwOjAuNnJlbTsgZmxleC13cmFwOndyYXA7IGFsaWduLWl0ZW1zOmNlbnRlcjsgfQoKLyog5qCH562+5byP54mp5paZICovCi50YWctZ3JwIHsgZGlzcGxheTpmbGV4OyBnYXA6MC40cmVtOyBmbGV4LXdyYXA6d3JhcDsgbWFyZ2luLXRvcDowLjVyZW07IH0KLnRhZyB7CiAgcGFkZGluZzogMC4yNXJlbSAwLjZyZW07IGJvcmRlci1yYWRpdXM6NnB4OyBmb250LXNpemU6MC43cmVtOyBmb250LXdlaWdodDo2MDA7CiAgZGlzcGxheTogaW5saW5lLWZsZXg7IGFsaWduLWl0ZW1zOmNlbnRlcjsgZ2FwOjAuM3JlbTsKICBib3JkZXI6IDFweCBzb2xpZCB2YXIoLS1ib3JkZXIpOyBiYWNrZ3JvdW5kOnZhcigtLWJnKTsgY29sb3I6dmFyKC0tdGV4dC1zZWMpOyB0cmFuc2l0aW9uOmFsbCAwLjJzOwp9Ci50YWcucHJpIHsgYmFja2dyb3VuZDp2YXIoLS1wcmltYXJ5LWJnMik7IGJvcmRlci1jb2xvcjpyZ2JhKDI0MiwxMjQsMzQsMC4yKTsgY29sb3I6dmFyKC0tcHJpbWFyeSk7IH0KLnRhZy5vayB7IGJhY2tncm91bmQ6I2VlZjlmMDsgYm9yZGVyLWNvbG9yOnJnYmEoMCwxODEsMTIwLDAuMik7IGNvbG9yOiMwMGI1Nzg7IH0KCi8qIOaXoOiAg+ivleeKtuaAgSAqLwoubm8tZXhhbSB7IHRleHQtYWxpZ246Y2VudGVyOyBwYWRkaW5nOjEuNXJlbSAwLjVyZW07IH0KLm5vLWV4YW0taWMgeyBmb250LXNpemU6Mi41cmVtOyBtYXJnaW4tYm90dG9tOjAuM3JlbTsgfQoubm8tZXhhbS1tc2cgeyBmb250LXNpemU6MC45NXJlbTsgZm9udC13ZWlnaHQ6NzAwOyBjb2xvcjp2YXIoLS10ZXh0KTsgbWFyZ2luLWJvdHRvbTowLjJyZW07IH0KLm5vLWV4YW0tdGlwIHsgZm9udC1zaXplOjAuNzhyZW07IGNvbG9yOnZhcigtLXByaW1hcnkpOyBmb250LXdlaWdodDo2MDA7IH0KCi8qID09PT09PT09PSDlj7PmoI/vvJrku4rml6Xml6XnqIvvvIjku4XpooTop4jvvIxob3ZlcuW8ueivpuaDhe+8iT09PT09PT09PSAqLwouY29sLXIgeyB3aWR0aDozNjBweDsgZmxleC1zaHJpbms6MDsgfQoKLyog5pel56iL5Y2h54mHICovCi5zY2gtY2FyZCB7IH0KLnNjaC1oZCB7IGRpc3BsYXk6ZmxleDsgYWxpZ24taXRlbXM6Y2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6c3BhY2UtYmV0d2VlbjsgbWFyZ2luLWJvdHRvbTowLjZyZW07IH0KLnNjaC10aXRsZSB7IGZvbnQtc2l6ZTowLjhyZW07IGZvbnQtd2VpZ2h0OjcwMDsgY29sb3I6dmFyKC0tdGV4dC1zZWMpOyB9Ci5zY2gtZGF0ZSB7IGZvbnQtc2l6ZTowLjY1cmVtOyBjb2xvcjp2YXIoLS10ZXh0LXN1Yik7IH0KLnNjaC1saXN0IHsgZGlzcGxheTpmbGV4OyBmbGV4LWRpcmVjdGlvbjpjb2x1bW47IGdhcDowLjM1cmVtOyB9CgovKiDml6XnqIvmnaHnm64gKi8KLnNjaC1pdGVtIHsKICBkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczpjZW50ZXI7IGdhcDowLjVyZW07IHBhZGRpbmc6MC40NXJlbSAwLjZyZW07CiAgYm9yZGVyLXJhZGl1czogdmFyKC0tcmFkaXVzLXhzKTsgZm9udC1zaXplOjAuNzVyZW07IGN1cnNvcjpwb2ludGVyOwogIHRyYW5zaXRpb246IGFsbCAwLjJzIHZhcigtLWVhc2UpOyBwb3NpdGlvbjpyZWxhdGl2ZTsKICBib3JkZXI6IDFweCBzb2xpZCB0cmFuc3BhcmVudDsKfQouc2NoLWl0ZW06aG92ZXIgeyBiYWNrZ3JvdW5kOnZhcigtLXByaW1hcnktYmcyKTsgYm9yZGVyLWNvbG9yOnJnYmEoMjQyLDEyNCwzNCwwLjE1KTsgfQouc2NoLWl0ZW0uY3VyIHsgYmFja2dyb3VuZDp2YXIoLS1wcmltYXJ5LWJnMik7IGJvcmRlci1jb2xvcjpyZ2JhKDI0MiwxMjQsMzQsMC4yKTsgfQouc2NoLWl0ZW0uZG9uZSB7IG9wYWNpdHk6MC41OyB9Ci5zY2gtZG90IHsgd2lkdGg6OHB4OyBoZWlnaHQ6OHB4OyBib3JkZXItcmFkaXVzOjUwJTsgZmxleC1zaHJpbms6MDsgdHJhbnNpdGlvbjpiYWNrZ3JvdW5kIDAuM3M7IH0KLnNjaC1kb3QubGl2ZSB7IGJhY2tncm91bmQ6dmFyKC0tcHJpbWFyeSk7IGFuaW1hdGlvbjpwZCAycyBpbmZpbml0ZTsgfQouc2NoLWRvdC5kb24geyBiYWNrZ3JvdW5kOnZhcigtLXN0YXR1cy1kb25lKTsgfQouc2NoLWRvdC53YWl0IHsgYmFja2dyb3VuZDp2YXIoLS1zdGF0dXMtd2FpdGluZyk7IG9wYWNpdHk6MC41OyB9Ci5zY2gtaWNvbiB7CiAgd2lkdGg6IDI4cHg7IGhlaWdodDoyOHB4OyBib3JkZXItcmFkaXVzOjZweDsgZGlzcGxheTpmbGV4OyBhbGlnbi1pdGVtczpjZW50ZXI7IGp1c3RpZnktY29udGVudDpjZW50ZXI7CiAgZm9udC1zaXplOiAwLjlyZW07IGZsZXgtc2hyaW5rOjA7IGJhY2tncm91bmQ6dmFyKC0tYmcpOyBib3JkZXI6MXB4IHNvbGlkIHZhcigtLWJvcmRlci1sdCk7Cn0KLnNjaC1pbmZvIHsgZmxleDoxOyBtaW4td2lkdGg6MDsgfQouc2NoLW5hbWUgeyBmb250LXdlaWdodDo2MDA7IGNvbG9yOnZhcigtLXRleHQpOyBmb250LXNpemU6MC43NXJlbTsgd2hpdGUtc3BhY2U6bm93cmFwOyBvdmVyZmxvdzpoaWRkZW47IHRleHQtb3ZlcmZsb3c6ZWxsaXBzaXM7IH0KLnNjaC10aW1lIHsgY29sb3I6dmFyKC0tdGV4dC1zdWIpOyBmb250LXNpemU6MC42OHJlbTsgfQoKLyogaG92ZXLlvLnnqpcgKi8KLnNjaC10aXAgewogIHBvc2l0aW9uOiBhYnNvbHV0ZTsgdG9wOjEwMCU7IGxlZnQ6MDsgcmlnaHQ6MDsgei1pbmRleDo1MDsKICBiYWNrZ3JvdW5kOiB2YXIoLS1iZy1jYXJkKTsgYm9yZGVyLXJhZGl1czp2YXIoLS1yYWRpdXMteHMpOwogIGJveC1zaGFkb3c6IHZhcigtLXNoYWRvdy1sZyk7IGJvcmRlcjoxcHggc29saWQgdmFyKC0tYm9yZGVyKTsKICBwYWRkaW5nOiAwLjZyZW0gMC44cmVtOyBmb250LXNpemU6MC43MnJlbTsKICBvcGFjaXR5OiAwOyBwb2ludGVyLWV2ZW50czpub25lOyB0cmFuc2Zvcm06dHJhbnNsYXRlWSgtNHB4KTsKICB0cmFuc2l0aW9uOiBhbGwgMC4ycyB2YXIoLS1lYXNlKTsgbWFyZ2luLXRvcDo0cHg7Cn0KLnNjaC1pdGVtOmhvdmVyIC5zY2gtdGlwIHsgb3BhY2l0eToxOyBwb2ludGVyLWV2ZW50czphdXRvOyB0cmFuc2Zvcm06dHJhbnNsYXRlWSgwKTsgfQouc2NoLXRpcC1yb3cgeyBkaXNwbGF5OmZsZXg7IGdhcDowLjRyZW07IG1hcmdpbi1ib3R0b206MC4yNXJlbTsgY29sb3I6dmFyKC0tdGV4dC1zZWMpOyB9Ci5zY2gtdGlwLWxibCB7IGNvbG9yOnZhcigtLXRleHQtc3ViKTsgbWluLXdpZHRoOjQycHg7IH0KCi8qIOaKmOWPoC/lsZXlvIAgKi8KLnNjaC10b2dnbGUgewogIGRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOmNlbnRlcjsganVzdGlmeS1jb250ZW50OmNlbnRlcjsKICBwYWRkaW5nOiAwLjM1cmVtOyBtYXJnaW4tdG9wOjAuNHJlbTsgZm9udC1zaXplOjAuNjVyZW07CiAgY29sb3I6IHZhcigtLXRleHQtc3ViKTsgY3Vyc29yOnBvaW50ZXI7IGJvcmRlcjpub25lOyBiYWNrZ3JvdW5kOm5vbmU7CiAgd2lkdGg6IDEwMCU7IGZvbnQtZmFtaWx5OmluaGVyaXQ7IGJvcmRlci1yYWRpdXM6dmFyKC0tcmFkaXVzLXhzKTsgdHJhbnNpdGlvbjphbGwgMC4yczsKfQouc2NoLXRvZ2dsZTpob3ZlciB7IGJhY2tncm91bmQ6dmFyKC0tcHJpbWFyeS1iZzIpOyBjb2xvcjp2YXIoLS1wcmltYXJ5KTsgfQoKLyogPT09PT09PT09IOW6lemDqOaTjeS9nOagjyA9PT09PT09PT0gKi8KLmJvdHRvbS1iYXIgewogIG1heC13aWR0aDogMTM4MHB4OyBtYXJnaW46MCBhdXRvOwogIGJhY2tncm91bmQ6IHZhcigtLWJnLWNhcmQpOyBib3JkZXItcmFkaXVzOnZhcigtLXJhZGl1cy1zbSk7CiAgYm94LXNoYWRvdzogdmFyKC0tc2hhZG93LW1kKTsgYm9yZGVyOjFweCBzb2xpZCB2YXIoLS1ib3JkZXIpOwogIGRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOmNlbnRlcjsganVzdGlmeS1jb250ZW50OnNwYWNlLWJldHdlZW47CiAgcGFkZGluZzogMC42cmVtIDEuMnJlbTsgZ2FwOjAuOHJlbTsKfQouYm90LWdycCB7IGRpc3BsYXk6ZmxleDsgYWxpZ24taXRlbXM6Y2VudGVyOyBnYXA6MC41cmVtOyB9Ci5ib3QtbGJsIHsgZm9udC1zaXplOjAuN3JlbTsgZm9udC13ZWlnaHQ6NjAwOyBjb2xvcjp2YXIoLS10ZXh0LXN1Yik7IHdoaXRlLXNwYWNlOm5vd3JhcDsgfQoucGlsbC1ncnAgeyBkaXNwbGF5OmZsZXg7IGdhcDowLjNyZW07IGZsZXgtd3JhcDp3cmFwOyB9Ci5waWxsIHsKICBwYWRkaW5nOiAwLjE4cmVtIDAuNTVyZW07IGJvcmRlci1yYWRpdXM6MTAwcHg7IGZvbnQtc2l6ZTowLjY1cmVtOyBmb250LXdlaWdodDo2MDA7CiAgYmFja2dyb3VuZDogdmFyKC0tYmcpOyBjb2xvcjp2YXIoLS10ZXh0LXN1Yik7IGJvcmRlcjoxcHggc29saWQgdmFyKC0tYm9yZGVyKTsKICBjdXJzb3I6IHBvaW50ZXI7IHRyYW5zaXRpb246YWxsIDAuMnM7IGRpc3BsYXk6ZmxleDsgYWxpZ24taXRlbXM6Y2VudGVyOyBnYXA6MC4yNXJlbTsKfQoucGlsbDpob3ZlciB7IGJvcmRlci1jb2xvcjp2YXIoLS1wcmltYXJ5KTsgY29sb3I6dmFyKC0tcHJpbWFyeSk7IH0KLnBpbGwuY3VyIHsgYmFja2dyb3VuZDp2YXIoLS1wcmltYXJ5KTsgY29sb3I6I2ZmZjsgYm9yZGVyLWNvbG9yOnZhcigtLXByaW1hcnkpOyB9Ci5waWxsLmRvbmUgeyBvcGFjaXR5OjAuNDU7IHRleHQtZGVjb3JhdGlvbjpsaW5lLXRocm91Z2g7IH0KCi8qIOWQrOWKm+aOp+WItiAqLwoubGlzdGVuLWN0cmwgeyBkaXNwbGF5OmZsZXg7IGFsaWduLWl0ZW1zOmNlbnRlcjsgZ2FwOjAuNHJlbTsgfQoubGlzdGVuLXN0cyB7IGZvbnQtc2l6ZTowLjcycmVtOyBjb2xvcjp2YXIoLS10ZXh0LXN1Yik7IHdoaXRlLXNwYWNlOm5vd3JhcDsgfQoubGlzdGVuLWJ0biB7CiAgd2lkdGg6IDMycHg7IGhlaWdodDozMnB4OyBib3JkZXItcmFkaXVzOjUwJTsgYm9yZGVyOm5vbmU7CiAgYmFja2dyb3VuZDogdmFyKC0tYmcpOyBjb2xvcjp2YXIoLS10ZXh0KTsgZm9udC1zaXplOjAuOXJlbTsgY3Vyc29yOnBvaW50ZXI7CiAgZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6Y2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6Y2VudGVyOyB0cmFuc2l0aW9uOmFsbCAwLjJzIHZhcigtLWVhc2UpOwp9Ci5saXN0ZW4tYnRuOmhvdmVyIHsgYmFja2dyb3VuZDp2YXIoLS1wcmltYXJ5KTsgY29sb3I6I2ZmZjsgdHJhbnNmb3JtOnNjYWxlKDEuMSk7IH0KLmxpc3Rlbi1idG4ucGxheWluZyB7IGJhY2tncm91bmQ6dmFyKC0tc3RhdHVzLWVuZGVkKTsgY29sb3I6I2ZmZjsgYW5pbWF0aW9uOnBiIDFzIGluZmluaXRlOyB9Ci5wcm9nLW1pbmkgeyB3aWR0aDo2MHB4OyBoZWlnaHQ6M3B4OyBiYWNrZ3JvdW5kOnZhcigtLWJnKTsgYm9yZGVyLXJhZGl1czoycHg7IG92ZXJmbG93OmhpZGRlbjsgfQoucHJvZy1taW5pLWZpbGwgeyBoZWlnaHQ6MTAwJTsgYmFja2dyb3VuZDp2YXIoLS1wcmltYXJ5KTsgd2lkdGg6MCU7IHRyYW5zaXRpb246d2lkdGggMC4zczsgfQoKLyogPT09PT09PT09IOWQrOWKm+mdouadvyA9PT09PT09PT0gKi8KLmxwLW92ZXJsYXkgeyBwb3NpdGlvbjpmaXhlZDsgaW5zZXQ6MDsgYmFja2dyb3VuZDpyZ2JhKDAsMCwwLDAuMzUpOyB6LWluZGV4OjMwMDsgb3BhY2l0eTowOyBwb2ludGVyLWV2ZW50czpub25lOyB0cmFuc2l0aW9uOm9wYWNpdHkgMC4zczsgfQoubHAtb3ZlcmxheS5zaG93IHsgb3BhY2l0eToxOyBwb2ludGVyLWV2ZW50czphdXRvOyB9Ci5scC1wYW5lbCB7CiAgcG9zaXRpb246IGZpeGVkOyBib3R0b206MDsgbGVmdDowOyByaWdodDowOwogIGJhY2tncm91bmQ6IHZhcigtLWJnLWNhcmQpOyBib3JkZXItcmFkaXVzOnZhcigtLXJhZGl1cykgdmFyKC0tcmFkaXVzKSAwIDA7CiAgYm94LXNoYWRvdzogMCAtNnB4IDQwcHggcmdiYSgwLDAsMCwwLjEyKTsgcGFkZGluZzoxLjJyZW0gMS41cmVtOwogIHotaW5kZXg6IDMwMTsgdHJhbnNmb3JtOnRyYW5zbGF0ZVkoMTAwJSk7IHRyYW5zaXRpb246dHJhbnNmb3JtIDAuMzVzIHZhcigtLWVhc2UpOwogIG1heC1oZWlnaHQ6IDY1dmg7IG92ZXJmbG93LXk6YXV0bzsKfQoubHAtcGFuZWwuc2hvdyB7IHRyYW5zZm9ybTp0cmFuc2xhdGVZKDApOyB9Ci5scC1oZCB7IGRpc3BsYXk6ZmxleDsgYWxpZ24taXRlbXM6Y2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6c3BhY2UtYmV0d2VlbjsgbWFyZ2luLWJvdHRvbTowLjdyZW07IH0KLmxwLXRpdGxlIHsgZm9udC1zaXplOjAuOTVyZW07IGZvbnQtd2VpZ2h0OjcwMDsgfQoubHAtY2xvc2UgewogIHdpZHRoOiAyOHB4OyBoZWlnaHQ6MjhweDsgYm9yZGVyLXJhZGl1czo1MCU7IGJvcmRlcjpub25lOyBiYWNrZ3JvdW5kOnZhcigtLWJnKTsKICBmb250LXNpemU6IDAuOXJlbTsgY3Vyc29yOnBvaW50ZXI7IGRpc3BsYXk6ZmxleDsgYWxpZ24taXRlbXM6Y2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6Y2VudGVyOyB0cmFuc2l0aW9uOmFsbCAwLjJzOwp9Ci5scC1jbG9zZTpob3ZlciB7IGJhY2tncm91bmQ6dmFyKC0tcHJpbWFyeS1iZzIpOyBjb2xvcjp2YXIoLS1wcmltYXJ5KTsgfQoubHAtbm93IHsgdGV4dC1hbGlnbjpjZW50ZXI7IHBhZGRpbmc6MC44cmVtOyBiYWNrZ3JvdW5kOnZhcigtLWJnKTsgYm9yZGVyLXJhZGl1czp2YXIoLS1yYWRpdXMtc20pOyBtYXJnaW4tYm90dG9tOjAuN3JlbTsgfQoubHAtbm93LWljIHsgZm9udC1zaXplOjEuNnJlbTsgbWFyZ2luLWJvdHRvbTowLjJyZW07IH0KLmxwLW5vdy1uYW1lIHsgZm9udC1zaXplOjEuMDVyZW07IGZvbnQtd2VpZ2h0OjgwMDsgfQoubHAtbm93LWRlc2MgeyBmb250LXNpemU6MC43NXJlbTsgY29sb3I6dmFyKC0tdGV4dC1zdWIpOyB9Ci5scC1wcm9nIHsgbWFyZ2luLWJvdHRvbTowLjdyZW07IH0KLmxwLWJhciB7IHdpZHRoOjEwMCU7IGhlaWdodDo1cHg7IGJhY2tncm91bmQ6dmFyKC0tYmcpOyBib3JkZXItcmFkaXVzOjNweDsgY3Vyc29yOnBvaW50ZXI7IG92ZXJmbG93OmhpZGRlbjsgfQoubHAtYmFyLWZpbGwgeyBoZWlnaHQ6MTAwJTsgYmFja2dyb3VuZDp2YXIoLS1wcmltYXJ5KTsgd2lkdGg6MCU7IHRyYW5zaXRpb246d2lkdGggMC4yczsgfQoubHAtdGltZXMgeyBkaXNwbGF5OmZsZXg7IGp1c3RpZnktY29udGVudDpzcGFjZS1iZXR3ZWVuOyBmb250LXNpemU6MC43cmVtOyBjb2xvcjp2YXIoLS10ZXh0LXN1Yik7IG1hcmdpbi10b3A6MC4ycmVtOyBmb250LXZhcmlhbnQtbnVtZXJpYzp0YWJ1bGFyLW51bXM7IH0KLmxwLWN0cmwgeyBkaXNwbGF5OmZsZXg7IGFsaWduLWl0ZW1zOmNlbnRlcjsganVzdGlmeS1jb250ZW50OmNlbnRlcjsgZ2FwOjAuOHJlbTsgbWFyZ2luLWJvdHRvbTowLjdyZW07IH0KLmN0cmwtYnRuIHsKICB3aWR0aDogNDRweDsgaGVpZ2h0OjQ0cHg7IGJvcmRlci1yYWRpdXM6NTAlOyBib3JkZXI6bm9uZTsgYmFja2dyb3VuZDp2YXIoLS1iZyk7CiAgZm9udC1zaXplOiAxcmVtOyBjdXJzb3I6cG9pbnRlcjsgZGlzcGxheTpmbGV4OyBhbGlnbi1pdGVtczpjZW50ZXI7IGp1c3RpZnktY29udGVudDpjZW50ZXI7IHRyYW5zaXRpb246YWxsIDAuMnMgdmFyKC0tZWFzZSk7Cn0KLmN0cmwtYnRuOmhvdmVyIHsgdHJhbnNmb3JtOnNjYWxlKDEuMTIpOyB9Ci5jdHJsLWJ0bi5wbGF5IHsgd2lkdGg6NTZweDsgaGVpZ2h0OjU2cHg7IGJhY2tncm91bmQ6dmFyKC0tcHJpbWFyeSk7IGNvbG9yOiNmZmY7IGZvbnQtc2l6ZToxLjJyZW07IGJveC1zaGFkb3c6MCA0cHggMjBweCByZ2JhKDI0MiwxMjQsMzQsMC4zNSk7IH0KLnRyYWNrLWdyaWQgeyBkaXNwbGF5OmdyaWQ7IGdyaWQtdGVtcGxhdGUtY29sdW1uczpyZXBlYXQoYXV0by1maWxsLG1pbm1heCgxNzBweCwxZnIpKTsgZ2FwOjAuMzVyZW07IH0KLnRyYWNrLWl0ZW0gewogIHBhZGRpbmc6IDAuNDVyZW0gMC42cmVtOyBiYWNrZ3JvdW5kOnZhcigtLWJnKTsgYm9yZGVyLXJhZGl1czp2YXIoLS1yYWRpdXMteHMpOwogIGRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOmNlbnRlcjsgZ2FwOjAuNHJlbTsgY3Vyc29yOnBvaW50ZXI7IHRyYW5zaXRpb246YWxsIDAuMnM7IGJvcmRlcjoycHggc29saWQgdHJhbnNwYXJlbnQ7Cn0KLnRyYWNrLWl0ZW06aG92ZXIgeyBib3JkZXItY29sb3I6cmdiYSgyNDIsMTI0LDM0LDAuMyk7IH0KLnRyYWNrLWl0ZW0uYWN0aXZlIHsgYm9yZGVyLWNvbG9yOnZhcigtLXByaW1hcnkpOyBiYWNrZ3JvdW5kOnZhcigtLXByaW1hcnktYmcyKTsgfQoudHJhY2staXRlbS5wbGF5aW5nIHsgYm9yZGVyLWNvbG9yOnZhcigtLXN0YXR1cy1lbmRlZCk7IH0KLnRyYWNrLW51bSB7IHdpZHRoOjIwcHg7IGhlaWdodDoyMHB4OyBib3JkZXItcmFkaXVzOjUwJTsgYmFja2dyb3VuZDp2YXIoLS1wcmltYXJ5KTsgY29sb3I6I2ZmZjsgZm9udC1zaXplOjAuNnJlbTsgZm9udC13ZWlnaHQ6NzAwOyBkaXNwbGF5OmZsZXg7IGFsaWduLWl0ZW1zOmNlbnRlcjsganVzdGlmeS1jb250ZW50OmNlbnRlcjsgZmxleC1zaHJpbms6MDsgfQoudHJhY2staW5mbyB7IGZsZXg6MTsgbWluLXdpZHRoOjA7IH0KLnRyYWNrLW5hbWUgeyBmb250LXNpemU6MC43NXJlbTsgZm9udC13ZWlnaHQ6NjAwOyB3aGl0ZS1zcGFjZTpub3dyYXA7IG92ZXJmbG93OmhpZGRlbjsgdGV4dC1vdmVyZmxvdzplbGxpcHNpczsgfQoudHJhY2stZGVzYyB7IGZvbnQtc2l6ZTowLjYzcmVtOyBjb2xvcjp2YXIoLS10ZXh0LXN1Yik7IH0KLnRyYWNrLWR1ciB7IGZvbnQtc2l6ZTowLjY1cmVtOyBjb2xvcjp2YXIoLS10ZXh0LXN1Yik7IGZvbnQtdmFyaWFudC1udW1lcmljOnRhYnVsYXItbnVtczsgfQoKLyogPT09PT09PT09IOaPkOmGkuW8ueeqlyA9PT09PT09PT0gKi8KLmFsZXJ0LW92IHsKICBwb3NpdGlvbjogZml4ZWQ7IGluc2V0OjA7IGJhY2tncm91bmQ6cmdiYSgwLDAsMCwwLjQpOyB6LWluZGV4OjUwMDsKICBkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczpjZW50ZXI7IGp1c3RpZnktY29udGVudDpjZW50ZXI7CiAgb3BhY2l0eTogMDsgcG9pbnRlci1ldmVudHM6bm9uZTsgdHJhbnNpdGlvbjpvcGFjaXR5IDAuM3M7Cn0KLmFsZXJ0LW92LnNob3cgeyBvcGFjaXR5OjE7IHBvaW50ZXItZXZlbnRzOmF1dG87IH0KLmFsZXJ0LWJveCB7CiAgYmFja2dyb3VuZDogdmFyKC0tYmctY2FyZCk7IGJvcmRlci1yYWRpdXM6dmFyKC0tcmFkaXVzKTsgcGFkZGluZzoxLjVyZW0gMnJlbTsKICBib3gtc2hhZG93OiB2YXIoLS1zaGFkb3ctbGcpOyB0ZXh0LWFsaWduOmNlbnRlcjsgbWF4LXdpZHRoOjM4MHB4OyB3aWR0aDo5MCU7CiAgYW5pbWF0aW9uOiBhcCAwLjM1cyB2YXIoLS1lYXNlKTsKfQpAa2V5ZnJhbWVzIGFwIHsgMCV7dHJhbnNmb3JtOnNjYWxlKDAuOSk7b3BhY2l0eTowO30gMTAwJXt0cmFuc2Zvcm06c2NhbGUoMSk7b3BhY2l0eToxO30gfQouYWxlcnQtaWMgeyBmb250LXNpemU6Mi41cmVtOyBtYXJnaW4tYm90dG9tOjAuNHJlbTsgfQouYWxlcnQtbXNnIHsgZm9udC1zaXplOjFyZW07IGZvbnQtd2VpZ2h0OjcwMDsgbWFyZ2luLWJvdHRvbTowLjNyZW07IH0KLmFsZXJ0LXN1YiB7IGZvbnQtc2l6ZTowLjhyZW07IGNvbG9yOnZhcigtLXRleHQtc3ViKTsgbWFyZ2luLWJvdHRvbToxcmVtOyB9Ci5hbGVydC1idG4gewogIHBhZGRpbmc6IDAuNHJlbSAxLjVyZW07IGJvcmRlci1yYWRpdXM6MTAwcHg7IGZvbnQtc2l6ZTowLjhyZW07IGZvbnQtd2VpZ2h0OjYwMDsKICBib3JkZXI6IG5vbmU7IGJhY2tncm91bmQ6dmFyKC0tcHJpbWFyeSk7IGNvbG9yOiNmZmY7IGN1cnNvcjpwb2ludGVyOyBmb250LWZhbWlseTppbmhlcml0OyB0cmFuc2l0aW9uOmFsbCAwLjJzOwp9Ci5hbGVydC1idG46aG92ZXIgeyBiYWNrZ3JvdW5kOnZhcigtLXByaW1hcnktbGlnaHQpOyB9CgovKiA9PT09PT09PT0gVG9hc3QgPT09PT09PT09ICovCi50b2FzdCB7CiAgcG9zaXRpb246IGZpeGVkOyB0b3A6NjRweDsgbGVmdDo1MCU7IHRyYW5zZm9ybTp0cmFuc2xhdGVYKC01MCUpIHRyYW5zbGF0ZVkoLTEycHgpOwogIHBhZGRpbmc6IDAuNXJlbSAxLjJyZW07IGJvcmRlci1yYWRpdXM6MTAwcHg7IGZvbnQtc2l6ZTowLjhyZW07IGZvbnQtd2VpZ2h0OjYwMDsKICBjb2xvcjogI2ZmZjsgei1pbmRleDo5OTk5OyBvcGFjaXR5OjA7IHBvaW50ZXItZXZlbnRzOm5vbmU7IHRyYW5zaXRpb246YWxsIDAuM3MgdmFyKC0tZWFzZSk7Cn0KLnRvYXN0LnNob3cgeyBvcGFjaXR5OjE7IHRyYW5zZm9ybTp0cmFuc2xhdGVYKC01MCUpIHRyYW5zbGF0ZVkoMCk7IH0KLnRvYXN0Lm9rIHsgYmFja2dyb3VuZDpsaW5lYXItZ3JhZGllbnQoMTM1ZGVnLCMxMGI5ODEsIzA1OTY2OSk7IH0KLnRvYXN0LmVyciB7IGJhY2tncm91bmQ6bGluZWFyLWdyYWRpZW50KDEzNWRlZywjZWY0NDQ0LCNkYzI2MjYpOyB9Ci50b2FzdC53YXJuIHsgYmFja2dyb3VuZDpsaW5lYXItZ3JhZGllbnQoMTM1ZGVnLHZhcigtLXByaW1hcnkpLHZhcigtLXByaW1hcnktbGlnaHQpKTsgfQoKLyogPT09PT09PT09IOS4ieenjeW4g+WxgOaooeW8jyA9PT09PT09PT0gKi8KLyog5pe26ZKf5qih5byP77ya5Y+q55WZ5YWo5bGP5pe26Ze0ICovCmJvZHkuY2xvY2stbW9kZSAuZ3JpZCwKYm9keS5jbG9jay1tb2RlIC5ib3R0b20tYmFyLApib2R5LmNsb2NrLW1vZGUgLmJvdHRvbS1iYXItdjUgeyBkaXNwbGF5Om5vbmU7IH0KYm9keS5jbG9jay1tb2RlIC53cmFwIHsgcGFkZGluZzo1OHB4IDN2dyAwOyBtYXgtd2lkdGg6bm9uZTsgfQpib2R5LmNsb2NrLW1vZGUgLnRpbWUtaGVybyB7CiAgbWluLWhlaWdodDogY2FsYygxMDB2aCAtIDU4cHgpOyBtYXJnaW4tYm90dG9tOjA7CiAgZGlzcGxheTpmbGV4OyBmbGV4LWRpcmVjdGlvbjpjb2x1bW47IGp1c3RpZnktY29udGVudDpjZW50ZXI7IGFsaWduLWl0ZW1zOmNlbnRlcjsKfQoKLyog5b6F6ICD5qih5byP77ya5Y+q5pi+56S65pe26Ze0ICsg5LuK5pel5pel56iLICovCmJvZHkud2FpdGluZy1tb2RlIC5jb2wtbCB7IGRpc3BsYXk6bm9uZTsgfQpib2R5LndhaXRpbmctbW9kZSAuY29sLXIgeyB3aWR0aDoxMDAlOyB9CmJvZHkud2FpdGluZy1tb2RlIC5ib3R0b20tYmFyLApib2R5LndhaXRpbmctbW9kZSAuYm90dG9tLWJhci12NSB7IGRpc3BsYXk6bm9uZTsgfQoKLyogPT09PT09PT09IOWTjeW6lOW8jyA9PT09PT09PT0gKi8KQG1lZGlhIChtYXgtd2lkdGg6OTYwcHgpIHsKICAuZ3JpZCB7IGZsZXgtZGlyZWN0aW9uOmNvbHVtbjsgfQogIC5jb2wtciB7IHdpZHRoOjEwMCU7IH0KICAudGltZS1kaXNwbGF5IHsgZm9udC1zaXplOjUuNXJlbTsgfQogIC50aW1lLWRpc3BsYXkuc21hbGwgeyBmb250LXNpemU6NHJlbTsgfQogIC53cmFwIHsgcGFkZGluZzo1OHB4IDAuOHJlbSAxcmVtOyB9CiAgLmJvdHRvbS1iYXIgeyBmbGV4LWRpcmVjdGlvbjpjb2x1bW47IGdhcDowLjRyZW07IH0KICAuaW5mby1ncmlkIHsgZ3JpZC10ZW1wbGF0ZS1jb2x1bW5zOiAxZnI7IH0KICBib2R5LmNsb2NrLW1vZGUgLnRpbWUtZGlzcGxheSB7IGZvbnQtc2l6ZTo2cmVtOyB9Cn0KCi8qIOe8lui+keaooeW8jyAqLwpib2R5LmVkaXQtbW9kZSAuZXhhbS1yYW5nZSwKYm9keS5lZGl0LW1vZGUgLmluZm8tdmFsdWUsCmJvZHkuZWRpdC1tb2RlIC5zdWItY2FyZC1uYW1lLApib2R5LmVkaXQtbW9kZSAuc3ViLWNhcmQtbWV0YSBzcGFuLApib2R5LmVkaXQtbW9kZSAudGFnIHsgb3V0bGluZToycHggZGFzaGVkIHZhcigtLXByaW1hcnkpOyBvdXRsaW5lLW9mZnNldDoycHg7IGN1cnNvcjpwb2ludGVyOyBib3JkZXItcmFkaXVzOjRweDsgcGFkZGluZzoycHggNHB4OyB9CmJvZHkuZWRpdC1tb2RlIC5leGFtLXJhbmdlOmhvdmVyLApib2R5LmVkaXQtbW9kZSAuaW5mby12YWx1ZTpob3ZlciwKYm9keS5lZGl0LW1vZGUgLnN1Yi1jYXJkLW5hbWU6aG92ZXIsCmJvZHkuZWRpdC1tb2RlIC5zdWItY2FyZC1tZXRhIHNwYW46aG92ZXIsCmJvZHkuZWRpdC1tb2RlIC50YWc6aG92ZXIgeyBiYWNrZ3JvdW5kOnZhcigtLXByaW1hcnktYmcyKTsgfQouZWRpdC1zYXZlLWJhciB7CiAgcG9zaXRpb246Zml4ZWQ7IGJvdHRvbTowOyBsZWZ0OjA7IHJpZ2h0OjA7IHotaW5kZXg6NDAwOwogIGJhY2tncm91bmQ6dmFyKC0tYmctY2FyZCk7IGJvcmRlci10b3A6MnB4IHNvbGlkIHZhcigtLXByaW1hcnkpOwogIGRpc3BsYXk6ZmxleDsgYWxpZ24taXRlbXM6Y2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6Y2VudGVyOyBnYXA6MXJlbTsKICBwYWRkaW5nOjAuNnJlbSAxLjVyZW07IHRyYW5zZm9ybTp0cmFuc2xhdGVZKDEwMCUpOyB0cmFuc2l0aW9uOnRyYW5zZm9ybSAwLjNzIHZhcigtLWVhc2UpOwp9Ci5lZGl0LXNhdmUtYmFyLnNob3cgeyB0cmFuc2Zvcm06dHJhbnNsYXRlWSgwKTsgfQovKiDlhajlsY/mqKHlvI8gKi8KLmV4aXQtZnVsbCB7IGRpc3BsYXk6bm9uZTsgfQpib2R5LmZ1bGwtbW9kZSAuZXhpdC1mdWxsIHsKICBkaXNwbGF5OmZsZXggIWltcG9ydGFudDsgcG9zaXRpb246Zml4ZWQ7IHRvcDoxMnB4OyByaWdodDoxMnB4OyB6LWluZGV4Ojk5OTsKICB3aWR0aDo0MHB4OyBoZWlnaHQ6NDBweDsgYm9yZGVyLXJhZGl1czo1MCU7CiAgYmFja2dyb3VuZDpyZ2JhKDAsMCwwLDAuNDApOyBiYWNrZHJvcC1maWx0ZXI6Ymx1cig4cHgpOwogIGJvcmRlcjoxLjVweCBzb2xpZCByZ2JhKDI1NSwyNTUsMjU1LDAuMjUpOyBjb2xvcjojZmZmOyBmb250LXNpemU6MS4xNXJlbTsgY3Vyc29yOnBvaW50ZXI7CiAgYWxpZ24taXRlbXM6Y2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6Y2VudGVyOwogIHRyYW5zaXRpb246b3BhY2l0eSAwLjNzLCBiYWNrZ3JvdW5kIDAuMnM7IG9wYWNpdHk6MC41NTsKfQpib2R5LmZ1bGwtbW9kZSAuZXhpdC1mdWxsOmhvdmVyIHsgYmFja2dyb3VuZDpyZ2JhKDI0MiwxMjQsMzQsMC44NSk7IG9wYWNpdHk6MTsgfQpib2R5LmZ1bGwtbW9kZSAubmF2IHsgdHJhbnNmb3JtOnRyYW5zbGF0ZVkoLTEwMCUpOyBwb2ludGVyLWV2ZW50czpub25lOyB0cmFuc2l0aW9uOnRyYW5zZm9ybSAwLjM1cyB2YXIoLS1lYXNlKTsgfQpib2R5LmZ1bGwtbW9kZSAuYm90dG9tLWJhci12NSB7IGRpc3BsYXk6bm9uZSAhaW1wb3J0YW50OyB9CmJvZHkuZnVsbC1tb2RlIC53cmFwIHsgbWF4LXdpZHRoOm5vbmUgIWltcG9ydGFudDsgbWFyZ2luOjA7IHBhZGRpbmc6MCAzdnc7IH0KYm9keS5mdWxsLW1vZGUgLm1haW4geyBwYWRkaW5nLXRvcDowOyBoZWlnaHQ6MTAwdmg7IGRpc3BsYXk6ZmxleDsgYWxpZ24taXRlbXM6Y2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6Y2VudGVyOyB9CmJvZHkuZnVsbC1tb2RlIC50aW1lLWhlcm8geyBtaW4taGVpZ2h0OjEwMHZoOyBkaXNwbGF5OmZsZXg7IGZsZXgtZGlyZWN0aW9uOmNvbHVtbjsgYWxpZ24taXRlbXM6Y2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6Y2VudGVyOyBwYWRkaW5nOjJyZW0gNHJlbSA0cmVtOyBib3JkZXItcmFkaXVzOjA7IH0KYm9keS5mdWxsLW1vZGUgLnRpbWUtZGlzcGxheSB7IGZvbnQtc2l6ZToyMHJlbTsgfQpib2R5LmZ1bGwtbW9kZSAubW9kZS1wYW5lbCB7IGRpc3BsYXk6bm9uZTsgfQpib2R5LmZ1bGwtbW9kZSAubGVmdC1jb2wsIGJvZHkuZnVsbC1tb2RlIC5yaWdodC1jb2wgeyBkaXNwbGF5Om5vbmUgIWltcG9ydGFudDsgfQpib2R5LmZ1bGwtbW9kZSAuZ3JpZCB7IGRpc3BsYXk6bm9uZTsgfQoKLyog5pel56iL5pel5pyf5a+86IiqICovCi5zY2gtbmF2LWJ0biB7CiAgd2lkdGg6MjhweDsgaGVpZ2h0OjI4cHg7IGJvcmRlci1yYWRpdXM6NTAlOwogIGJvcmRlcjoxcHggc29saWQgdmFyKC0tYm9yZGVyKTsgYmFja2dyb3VuZDp2YXIoLS1iZy1jYXJkKTsKICBjb2xvcjp2YXIoLS10ZXh0LXNlYyk7IGZvbnQtc2l6ZToxLjFyZW07IGN1cnNvcjpwb2ludGVyOwogIGRpc3BsYXk6ZmxleDsgYWxpZ24taXRlbXM6Y2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6Y2VudGVyOwogIHRyYW5zaXRpb246YWxsIDAuMnMgdmFyKC0tZWFzZSk7IGZsZXgtc2hyaW5rOjA7Cn0KLnNjaC1uYXYtYnRuOmhvdmVyIHsgYmFja2dyb3VuZDp2YXIoLS1wcmltYXJ5LWJnMik7IGNvbG9yOnZhcigtLXByaW1hcnkpOyBib3JkZXItY29sb3I6dmFyKC0tcHJpbWFyeS1saWdodCk7IH0KCjwvc3R5bGU+CjwvaGVhZD4KPGJvZHk+Cgo8IS0tIOmhtumDqOWvvOiIqiAtLT4KPG5hdiBjbGFzcz0ibmF2IiBpZD0ibmF2Ij4KICA8ZGl2IGNsYXNzPSJuYXYtYnJhbmQiPgogICAgPGRpdiBjbGFzcz0ibmF2LWxvZ28iIGlkPSJuYXZMb2dvQm94IiB0aXRsZT0i6b6Z6Jm+6ICB5biIIj4KICAgICAgPHN2ZyBpZD0ibmF2TG9nb1N2ZyIgdmlld0JveD0iMCAwIDIwMCAyMDAiPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEwMCwxMDApIj4KICAgICAgICA8bGluZSB4MT0iLTc1IiB5MT0iLTg1IiB4Mj0iLTQ1IiB5Mj0iLTYwIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyLjgiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgogICAgICAgIDxsaW5lIHgxPSI3NSIgeTE9Ii04NSIgeDI9IjQ1IiB5Mj0iLTYwIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyLjgiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgogICAgICAgIDxjaXJjbGUgY3g9Ii0xNCIgY3k9Ii02NiIgcj0iNyIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMi41Ii8+CiAgICAgICAgPGNpcmNsZSBjeD0iMTQiIGN5PSItNjYiIHI9IjciIGZpbGw9Im5vbmUiIHN0cm9rZT0iY3VycmVudENvbG9yIiBzdHJva2Utd2lkdGg9IjIuNSIvPgogICAgICAgIDxjaXJjbGUgY3g9Ii0xNCIgY3k9Ii02NiIgcj0iMy4yIiBmaWxsPSJjdXJyZW50Q29sb3IiIGRhdGEtaWQ9InB1cGlsTCIvPgogICAgICAgIDxjaXJjbGUgY3g9IjE0IiBjeT0iLTY2IiByPSIzLjIiIGZpbGw9ImN1cnJlbnRDb2xvciIgZGF0YS1pZD0icHVwaWxSIi8+CiAgICAgICAgPHBvbHlnb24gcG9pbnRzPSItNDIsLTU2IDQyLC01NiA1OCwtMTUgNTAsNDUgLTUwLDQ1IC01OCwtMTUiIGZpbGw9Im5vbmUiIHN0cm9rZT0iY3VycmVudENvbG9yIiBzdHJva2Utd2lkdGg9IjMuMiIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPgogICAgICAgIDxsaW5lIHgxPSItNTIiIHkxPSItMzgiIHgyPSItODAiIHkyPSItMzgiIHN0cm9rZT0iY3VycmVudENvbG9yIiBzdHJva2Utd2lkdGg9IjMuMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+CiAgICAgICAgPGNpcmNsZSBjeD0iLTgwIiBjeT0iLTM4IiByPSI0LjUiIGZpbGw9Im5vbmUiIHN0cm9rZT0iY3VycmVudENvbG9yIiBzdHJva2Utd2lkdGg9IjIuMiIvPgogICAgICAgIDxsaW5lIHgxPSI1MiIgeTE9Ii0zOCIgeDI9IjgwIiB5Mj0iLTM4IiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIzLjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgogICAgICAgIDxjaXJjbGUgY3g9IjgwIiBjeT0iLTM4IiByPSI0LjUiIGZpbGw9Im5vbmUiIHN0cm9rZT0iY3VycmVudENvbG9yIiBzdHJva2Utd2lkdGg9IjIuMiIvPgogICAgICAgIDxsaW5lIHgxPSItODAiIHkxPSItMzgiIHgyPSItOTQiIHkyPSItNTUiIHN0cm9rZT0iY3VycmVudENvbG9yIiBzdHJva2Utd2lkdGg9IjIuOCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+CiAgICAgICAgPGxpbmUgeDE9Ii04MCIgeTE9Ii0zOCIgeDI9Ii05NCIgeTI9Ii0yMSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMi44IiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4KICAgICAgICA8bGluZSB4MT0iODAiIHkxPSItMzgiIHgyPSI5NCIgeTI9Ii01NSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMi44IiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4KICAgICAgICA8bGluZSB4MT0iODAiIHkxPSItMzgiIHgyPSI5NCIgeTI9Ii0yMSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMi44IiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4KICAgICAgICA8bGluZSB4MT0iLTU2IiB5MT0iLTEwIiB4Mj0iLTc1IiB5Mj0iMiIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMi4yIiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4KICAgICAgICA8bGluZSB4MT0iLTU2IiB5MT0iMTAiIHgyPSItNzgiIHkyPSIyMiIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMi4yIiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4KICAgICAgICA8bGluZSB4MT0iLTUzIiB5MT0iMjgiIHgyPSItNzQiIHkyPSIzOCIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMi4yIiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4KICAgICAgICA8bGluZSB4MT0iNTYiIHkxPSItMTAiIHgyPSI3NSIgeTI9IjIiIHN0cm9rZT0iY3VycmVudENvbG9yIiBzdHJva2Utd2lkdGg9IjIuMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+CiAgICAgICAgPGxpbmUgeDE9IjU2IiB5MT0iMTAiIHgyPSI3OCIgeTI9IjIyIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyLjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgogICAgICAgIDxsaW5lIHgxPSI1MyIgeTE9IjI4IiB4Mj0iNzQiIHkyPSIzOCIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMi4yIiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4KICAgICAgICA8cG9seWdvbiBwb2ludHM9Ii00OCw0MyAtNjAsNTggLTM1LDU0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyLjgiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KICAgICAgICA8cG9seWdvbiBwb2ludHM9IjQ4LDQzIDM1LDU0IDYwLDU4IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyLjgiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KICAgICAgPC9nPjwvc3ZnPgogICAgPC9kaXY+CiAgICA8c3BhbiBjbGFzcz0ibmF2LXRpdGxlIj7pvpnomb7ogIHluIggwrcg54+t57qn5pe26ZKf5aSn5bGPPC9zcGFuPgogICAgPHNwYW4gY2xhc3M9Im5hdi1zdWIiPlY2LjAgwrcg5o6S54+t6IGU5Yqo54mIPC9zcGFuPgogIDwvZGl2PgogIDxkaXYgY2xhc3M9Im5hdi1tb2RlcyI+CiAgICA8YnV0dG9uIGNsYXNzPSJtb2RlLWJ0biIgZGF0YS1tPSJjbG9jayIgb25jbGljaz0ic2V0TW9kZSgnY2xvY2snKSIgdGl0bGU9IuaXtumSnyI+8J+VkCDml7bpkp88L2J1dHRvbj4KICAgIDxidXR0b24gY2xhc3M9Im1vZGUtYnRuIGFjdGl2ZSIgZGF0YS1tPSJpbmZvIiBvbmNsaWNrPSJzZXRNb2RlKCdpbmZvJykiIHRpdGxlPSLogIPlnLrkv6Hmga8iPvCfk50g6ICD5Zy65L+h5oGvPC9idXR0b24+CiAgICA8YnV0dG9uIGNsYXNzPSJtb2RlLWJ0biIgZGF0YS1tPSJ3YWl0aW5nIiBvbmNsaWNrPSJzZXRNb2RlKCd3YWl0aW5nJykiIHRpdGxlPSLlvoXogIMiPuKPsyDlvoXogIM8L2J1dHRvbj4KICA8L2Rpdj4KICA8ZGl2IGNsYXNzPSJuYXYtYWN0cyI+CiAgICA8ZGl2IGNsYXNzPSJ0aGVtZS1idG5zIj4KICAgICAgPGJ1dHRvbiBjbGFzcz0idGhlbWUtYnRuIGFjdGl2ZSIgZD0ibGlnaHQiIG9uY2xpY2s9InNldFRoZW1lKCdsaWdodCcpIiB0aXRsZT0i5rWF6ImyIj48L2J1dHRvbj4KICAgICAgPGJ1dHRvbiBjbGFzcz0idGhlbWUtYnRuIiBkPSJ3YXJtIiBvbmNsaWNrPSJzZXRUaGVtZSgnd2FybScpIiB0aXRsZT0i5pqW6ImyIj48L2J1dHRvbj4KICAgICAgPGJ1dHRvbiBjbGFzcz0idGhlbWUtYnRuIiBkPSJkYXJrIiBvbmNsaWNrPSJzZXRUaGVtZSgnZGFyaycpIiB0aXRsZT0i5rex6ImyIj48L2J1dHRvbj4KICAgIDwvZGl2PgogICAgPGJ1dHRvbiBjbGFzcz0ibmF2LWJ0biIgb25jbGljaz0iZ29GdWxsKCkiIHRpdGxlPSLlhajlsY8iPuKbtjwvYnV0dG9uPgogICAgPGRpdiBjbGFzcz0ibW9yZS13cmFwIj4KICAgICAgPGJ1dHRvbiBjbGFzcz0ibmF2LWJ0biIgb25jbGljaz0idG9nZ2xlTW9yZSgpIiB0aXRsZT0i5pu05aSaIj7ii688L2J1dHRvbj4KICAgICAgPGRpdiBjbGFzcz0ibW9yZS1tZW51IiBpZD0ibW9yZU1lbnUiPgogICAgICAgIDxidXR0b24gY2xhc3M9Im1vcmUtaXRlbSIgb25jbGljaz0iaW1wb3J0Q2ZnKCkiIHN0eWxlPSJmb250LXdlaWdodDo4MDA7Ij7wn5OlIOWvvOWFpeaOkuePrS/phY3nva48L2J1dHRvbj4KICAgICAgICA8YnV0dG9uIGNsYXNzPSJtb3JlLWl0ZW0iIG9uY2xpY2s9ImV4cG9ydENmZygpIj7wn5OkIOWvvOWHuumFjee9rjwvYnV0dG9uPgogICAgICAgIDxkaXYgc3R5bGU9ImhlaWdodDoxcHg7YmFja2dyb3VuZDp2YXIoLS1ib3JkZXItbHQpO21hcmdpbjoycHggOHB4OyI+PC9kaXY+CiAgICAgICAgPGJ1dHRvbiBjbGFzcz0ibW9yZS1pdGVtIiBvbmNsaWNrPSJ0b2dnbGVFZGl0TW9kZSgpIj7inI/vuI8g57yW6L6R5qih5byPPC9idXR0b24+CiAgICAgICAgPGJ1dHRvbiBjbGFzcz0ibW9yZS1pdGVtIiBvbmNsaWNrPSJyZXNldFRpbWVyKCkiPuKPse+4jyDph43nva7mj5DphpI8L2J1dHRvbj4KICAgICAgPC9kaXY+CiAgICA8L2Rpdj4KICA8L2Rpdj4KPC9uYXY+Cgo8ZGl2IGNsYXNzPSJ3cmFwIj4KCiAgPCEtLSDnrKwx5q6177ya6aG26YOo5pe26Ze05qih5Z2X77yI5pyA5aSn5YyW77yJIC0tPgogIDxkaXYgY2xhc3M9InRpbWUtaGVybyIgaWQ9InRpbWVIZXJvIj4KICAgIDxkaXYgY2xhc3M9InRpbWUtYXV4IiBpZD0idGltZUF1eCI+CiAgICAgIDxzcGFuIGNsYXNzPSJhdXgtZG90IiBpZD0iYXV4RG90Ij48L3NwYW4+CiAgICAgIDxzcGFuIGlkPSJhdXhUZXh0Ij7mnKzlnLrliankvZnkvZznrZTml7bpl7Q8L3NwYW4+CiAgICA8L2Rpdj4KICAgIDxkaXYgY2xhc3M9InRpbWUtZGlzcGxheSBjLWJsdWUiIGlkPSJ0aW1lRGlzcCI+LS06LS06LS08L2Rpdj4KICAgIDxkaXYgY2xhc3M9InRpbWUtaWQiIGlkPSJ0aW1lSWQiPuKAlOKAlDwvZGl2PgogICAgPGRpdiBjbGFzcz0iZm9udC1jdHJsIj4KICAgICAgPGRpdiBjbGFzcz0iY29sb3Itc3dpdGNoIiB0aXRsZT0i5YiH5o2i5pe26ZKf6aKc6ImyIj4KICAgICAgICA8c3BhbiBjbGFzcz0iY29sb3ItZG90IGMtb3JhbmdlLWRvdCIgb25jbGljaz0ic2V0Q2xvY2tDb2xvcignb3JhbmdlJykiIHRpdGxlPSLmqZnoibIiPjwvc3Bhbj4KICAgICAgICA8c3BhbiBjbGFzcz0iY29sb3ItZG90IGMtYmxhY2stZG90IiBvbmNsaWNrPSJzZXRDbG9ja0NvbG9yKCdibGFjaycpIiB0aXRsZT0i6buR6ImyIj48L3NwYW4+CiAgICAgICAgPHNwYW4gY2xhc3M9ImNvbG9yLWRvdCBjLWJsdWUtZG90IGFjdGl2ZSIgb25jbGljaz0ic2V0Q2xvY2tDb2xvcignYmx1ZScpIiB0aXRsZT0i6JOd6ImyIj48L3NwYW4+CiAgICAgIDwvZGl2PgogICAgICA8bGFiZWwgc3R5bGU9ImZvbnQtc2l6ZTowLjYycmVtO2NvbG9yOnZhcigtLXRleHQtc3ViKTsiPuWtl+S9kzwvbGFiZWw+CiAgICAgIDxzZWxlY3Qgb25jaGFuZ2U9ImNoYW5nZUZvbnQodGhpcy52YWx1ZSkiPgogICAgICAgIDxvcHRpb24gdmFsdWU9IidTb3VyY2UgQ29kZSBQcm8nLCdDb25zb2xhcycsbW9ub3NwYWNlIj5Tb3VyY2UgQ29kZSBQcm88L29wdGlvbj4KICAgICAgICA8b3B0aW9uIHZhbHVlPSInQ29uc29sYXMnLCdTb3VyY2UgQ29kZSBQcm8nLG1vbm9zcGFjZSI+Q29uc29sYXM8L29wdGlvbj4KICAgICAgICA8b3B0aW9uIHZhbHVlPSJtb25vc3BhY2UiPuezu+e7n+etieWuvTwvb3B0aW9uPgogICAgICA8L3NlbGVjdD4KICAgIDwvZGl2PgogIDwvZGl2PgoKICA8IS0tIOesrDLmrrXvvJrlt6blj7Plj4zmoI8gLS0+CiAgPGRpdiBjbGFzcz0iZ3JpZCI+CgogICAgPCEtLSDlt6bmoI/vvJrmnKzlnLrogIPor5XvvIjntKflh5HmjpLniYjvvIkgLS0+CiAgICA8ZGl2IGNsYXNzPSJjb2wtbCI+CiAgICAgIDxkaXYgY2xhc3M9ImNhcmQiIGlkPSJsZWZ0Q2FyZCI+CiAgICAgICAgPGRpdiBjbGFzcz0iY2FyZC1oZCI+CiAgICAgICAgICA8ZGl2IGNsYXNzPSJjYXJkLWhkLXRpdGxlIj7wn5OdIOacrOWcuuiAg+ivlTwvZGl2PgogICAgICAgICAgPHNwYW4gY2xhc3M9ImNhcmQtYmFkZ2UiIGlkPSJsZWZ0QmFkZ2UiPjwvc3Bhbj4KICAgICAgICA8L2Rpdj4KICAgICAgICA8ZGl2IGNsYXNzPSJleGFtLXJhbmdlIiBpZD0ibGVmdFJhbmdlIj4tLTotLSDigJQgLS06LS08L2Rpdj4KICAgICAgICA8ZGl2IGlkPSJsZWZ0Q29udGVudCI+PC9kaXY+CiAgICAgIDwvZGl2PgogICAgPC9kaXY+CgogICAgPCEtLSDlj7PmoI/vvJrku4rml6Xml6XnqIsgLS0+CiAgICA8ZGl2IGNsYXNzPSJjb2wtciI+CiAgICAgIDxkaXYgY2xhc3M9ImNhcmQgc2NoLWNhcmQiPgogICAgICAgIDxkaXYgY2xhc3M9InNjaC1oZCI+CiAgICAgICAgICA8YnV0dG9uIGNsYXNzPSJzY2gtbmF2LWJ0biIgb25jbGljaz0iY2hhbmdlU2NoRGF0ZSgtMSkiIHRpdGxlPSLliY3kuIDlpKkiPuKAuTwvYnV0dG9uPgogICAgICAgICAgPGRpdiBzdHlsZT0idGV4dC1hbGlnbjpjZW50ZXI7ZmxleDoxOyI+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9InNjaC10aXRsZSI+8J+TiyDml6XnqIs8L2Rpdj4KICAgICAgICAgICAgPGRpdiBjbGFzcz0ic2NoLWRhdGUiIGlkPSJzY2hEYXRlIj48L2Rpdj4KICAgICAgICAgIDwvZGl2PgogICAgICAgICAgPGJ1dHRvbiBjbGFzcz0ic2NoLW5hdi1idG4iIG9uY2xpY2s9ImNoYW5nZVNjaERhdGUoMSkiIHRpdGxlPSLlkI7kuIDlpKkiPuKAujwvYnV0dG9uPgogICAgICAgIDwvZGl2PgogICAgICAgIDxkaXYgY2xhc3M9InNjaC1saXN0IiBpZD0ic2NoTGlzdCI+PC9kaXY+CiAgICAgICAgPGJ1dHRvbiBjbGFzcz0ic2NoLXRvZ2dsZSIgaWQ9InNjaFRvZ2dsZSIgb25jbGljaz0idG9nZ2xlU2NoKCkiPuaUtui1t+W3suWujOaIkOWcuuasoSDilrI8L2J1dHRvbj4KICAgICAgPC9kaXY+CiAgICA8L2Rpdj4KCiAgPC9kaXY+CgogIDwhLS0g5bqV6YOo5pON5L2c5qCPIC0tPgogIDxkaXYgY2xhc3M9ImJvdHRvbS1iYXIiPgogICAgPHNwYW4gc3R5bGU9ImZvbnQtc2l6ZTowLjYycmVtOyBjb2xvcjp2YXIoLS10ZXh0LXN1Yik7IHdoaXRlLXNwYWNlOm5vd3JhcDsgZmxleC1zaHJpbms6MDsgbWFyZ2luLXJpZ2h0OjAuOHJlbTsiPvCfpp4gVjYuMCDCtyDpvpnomb7mlZnliqHlj7A8L3NwYW4+CiAgICA8ZGl2IGNsYXNzPSJib3QtZ3JwIj4KICAgICAgPHNwYW4gY2xhc3M9ImJvdC1sYmwiPvCfk4U8L3NwYW4+CiAgICAgIDxkaXYgY2xhc3M9InBpbGwtZ3JwIiBpZD0iYm90UGlsbHMiPjwvZGl2PgogICAgPC9kaXY+CiAgICA8ZGl2IGNsYXNzPSJib3QtZ3JwIj4KICAgICAgPHNwYW4gY2xhc3M9ImJvdC1sYmwiPvCfjrU8L3NwYW4+CiAgICAgIDxkaXYgY2xhc3M9Imxpc3Rlbi1jdHJsIj4KICAgICAgICA8c3BhbiBjbGFzcz0ibGlzdGVuLXN0cyIgaWQ9Imxpc3RlblN0cyI+5YeG5aSH5bCx57uqPC9zcGFuPgogICAgICAgIDxkaXYgY2xhc3M9InByb2ctbWluaSI+PGRpdiBjbGFzcz0icHJvZy1taW5pLWZpbGwiIGlkPSJwcm9nRmlsbCI+PC9kaXY+PC9kaXY+CiAgICAgICAgPCEtLSBWNS4w77ya5ZCs5Yqb5qih5Z2X56CN5o6J77yM5LiL54mI5pys5YaN5LyY5YyWIC0tPgogICAgICA8L2Rpdj4KICAgIDwvZGl2PgogIDwvZGl2PgoKPC9kaXY+Cgo8IS0tIOe8lui+keS/neWtmOadoSDigJTigJQg5pS+5ZyoIGJvZHkg5bqV6YOo77yM6buY6K6k6ZqQ6JePIC0tPgo8ZGl2IGNsYXNzPSJlZGl0LXNhdmUtYmFyIiBpZD0iZWRpdFNhdmVCYXIiPgogIDxzcGFuIHN0eWxlPSJmb250LXNpemU6MC44cmVtO2ZvbnQtd2VpZ2h0OjYwMDtjb2xvcjp2YXIoLS1wcmltYXJ5KTsiPuKcj++4jyDnvJbovpHmqKHlvI/lt7LlvIDlkK8g4oCUIOeCueWHu+aWh+Wtl+WPr+S/ruaUue+8jOWujOaIkOWQjueCueS/neWtmDwvc3Bhbj4KICA8YnV0dG9uIGNsYXNzPSJhbGVydC1idG4iIG9uY2xpY2s9InNhdmVFZGl0KCkiIHN0eWxlPSJwYWRkaW5nOjAuM3JlbSAxLjJyZW07Ij7wn5K+IOS/neWtmDwvYnV0dG9uPgogIDxidXR0b24gb25jbGljaz0idG9nZ2xlRWRpdE1vZGUoKSIgc3R5bGU9InBhZGRpbmc6MC4zcmVtIDAuOHJlbTtiYWNrZ3JvdW5kOnZhcigtLWJnKTtib3JkZXI6MXB4IHNvbGlkIHZhcigtLWJvcmRlcik7Ym9yZGVyLXJhZGl1czp2YXIoLS1yYWRpdXMteHMpO2N1cnNvcjpwb2ludGVyO2ZvbnQtZmFtaWx5OmluaGVyaXQ7Zm9udC1zaXplOjAuNzhyZW07Zm9udC13ZWlnaHQ6NjAwO2NvbG9yOnZhcigtLXRleHQtc2VjKTsiPuWPlua2iDwvYnV0dG9uPgo8L2Rpdj4KCjwhLS0gVjUuMO+8muWQrOWKm+mdouadv+W3suegjeaOie+8jOS4i+eJiOacrOWGjeS8mOWMliAtLT4KCjwhLS0g5o+Q6YaS5by556qXIC0tPgo8ZGl2IGNsYXNzPSJhbGVydC1vdiIgaWQ9ImFsZXJ0T3YiPgogIDxkaXYgY2xhc3M9ImFsZXJ0LWJveCI+CiAgICA8ZGl2IGNsYXNzPSJhbGVydC1pYyIgaWQ9ImFsZXJ0SWMiPuKPsDwvZGl2PgogICAgPGRpdiBjbGFzcz0iYWxlcnQtbXNnIiBpZD0iYWxlcnRNc2ciPuaPkOmGkjwvZGl2PgogICAgPGRpdiBjbGFzcz0iYWxlcnQtc3ViIiBpZD0iYWxlcnRTdWIiPjwvZGl2PgogICAgPGJ1dHRvbiBjbGFzcz0iYWxlcnQtYnRuIiBvbmNsaWNrPSJjbG9zZUFsZXJ0KCkiPuefpemBk+S6hjwvYnV0dG9uPgogIDwvZGl2Pgo8L2Rpdj4KCjxkaXYgY2xhc3M9InRvYXN0IiBpZD0idG9hc3QiPjwvZGl2PgoKPHNjcmlwdD4KLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQogICDnvJbovpHmqKHlvI8KICAgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSAqLwpsZXQgaXNFZGl0TW9kZSA9IGZhbHNlOwpmdW5jdGlvbiB0b2dnbGVFZGl0TW9kZSgpewogIGlzRWRpdE1vZGUgPSAhaXNFZGl0TW9kZTsKICBkb2N1bWVudC5ib2R5LmNsYXNzTGlzdC50b2dnbGUoJ2VkaXQtbW9kZScsIGlzRWRpdE1vZGUpOwogIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdlZGl0U2F2ZUJhcicpLmNsYXNzTGlzdC50b2dnbGUoJ3Nob3cnLCBpc0VkaXRNb2RlKTsKICB2YXIgYnRuID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignLm1vcmUtaXRlbVtvbmNsaWNrKj0idG9nZ2xlRWRpdE1vZGUiXScpOwogIGlmKGJ0bikgYnRuLnRleHRDb250ZW50ID0gaXNFZGl0TW9kZSA/ICfinI/vuI8g6YCA5Ye657yW6L6RJyA6ICfinI/vuI8g57yW6L6R5qih5byPJzsKICBpZihpc0VkaXRNb2RlKXsKICAgIGVuYWJsZUVkaXQoKTsKICAgIHNob3dUb2FzdCgn4pyP77iPIOe8lui+keaooeW8j+W3suW8gOWQr++8jOeCueWHu+aWh+Wtl+S/ruaUuScsJ3dhcm4nKTsKICB9IGVsc2UgewogICAgY2FuY2VsRWRpdCgpOwogIH0KfQpmdW5jdGlvbiBlbmFibGVFZGl0KCl7CiAgLyog5bem5qCPICsg5pel56iL5p2h55uu57uf5LiA57uR5a6aICovCiAgZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgnLmV4YW0tcmFuZ2UsLmluZm8tdmFsdWUsLnN1Yi1jYXJkLW5hbWUsLnN1Yi1jYXJkLW1ldGEgc3BhbiwudGFnLC5zY2gtbmFtZScpLmZvckVhY2goZnVuY3Rpb24oZWwpewogICAgZWwub25jbGljayA9IGZ1bmN0aW9uKCl7IGlmKCFpc0VkaXRNb2RlKSByZXR1cm47CiAgICAgIHZhciBvcmlnPWVsLnRleHRDb250ZW50OyBlbC5zZXRBdHRyaWJ1dGUoJ2RhdGEtb3JpZycsb3JpZyk7CiAgICAgIHZhciBpbnA9ZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnaW5wdXQnKTsgaW5wLnR5cGU9J3RleHQnOyBpbnAudmFsdWU9b3JpZzsKICAgICAgdmFyIHc9TWF0aC5tYXgoNjAsZWwub2Zmc2V0V2lkdGgrMjApOwogICAgICBpbnAuc3R5bGUuY3NzVGV4dD0nYm9yZGVyOjFweCBzb2xpZCB2YXIoLS1wcmltYXJ5KTtib3JkZXItcmFkaXVzOjRweDtwYWRkaW5nOjJweCA2cHg7Zm9udC1zaXplOmluaGVyaXQ7Zm9udC1mYW1pbHk6aW5oZXJpdDtmb250LXdlaWdodDppbmhlcml0O2NvbG9yOnZhcigtLXByaW1hcnkpO2JhY2tncm91bmQ6dmFyKC0tcHJpbWFyeS1iZzIpO291dGxpbmU6bm9uZTt3aWR0aDonK3crJ3B4Oyc7CiAgICAgIGlucC5vbmJsdXI9ZnVuY3Rpb24oKXsKICAgICAgICB2YXIgbmV3VmFsPWlucC52YWx1ZXx8b3JpZzsKICAgICAgICBlbC50ZXh0Q29udGVudD1uZXdWYWw7CiAgICAgICAgLyog5pel56iL5ZCN56ew77ya5Zue5YaZ5pWw5o2u5qih5Z6LICovCiAgICAgICAgdmFyIGlkQXR0cj1lbC5nZXRBdHRyaWJ1dGUoJ2RhdGEtaWQnKTsKICAgICAgICBpZihpZEF0dHIgJiYgZWwuY2xhc3NMaXN0LmNvbnRhaW5zKCdzY2gtbmFtZScpKXsKICAgICAgICAgIHZhciBzZXNzPWV4YW1Db25maWcuc2Vzc2lvbnMuZmluZChmdW5jdGlvbihzKXsgcmV0dXJuIHMuaWQ9PT1wYXJzZUludChpZEF0dHIpOyB9KTsKICAgICAgICAgIGlmKHNlc3MpIHNlc3MubmFtZT1uZXdWYWw7CiAgICAgICAgfQogICAgICAgIGVsLm9uY2xpY2s9ZnVuY3Rpb24oKXtlbmFibGVFZGl0KCk7fTsKICAgICAgICBpbnAucmVtb3ZlKCk7CiAgICAgIH07CiAgICAgIGlucC5vbmtleWRvd249ZnVuY3Rpb24oZSl7IGlmKGUua2V5PT09J0VudGVyJyl7ZS5wcmV2ZW50RGVmYXVsdCgpO2lucC5ibHVyKCk7fSBpZihlLmtleT09PSdFc2NhcGUnKXtpbnAudmFsdWU9b3JpZztpbnAuYmx1cigpO30gfTsKICAgICAgZWwudGV4dENvbnRlbnQ9Jyc7IGVsLmFwcGVuZENoaWxkKGlucCk7IGlucC5mb2N1cygpOyBpbnAuc2VsZWN0KCk7CiAgICB9OwogIH0pOwp9CmZ1bmN0aW9uIHNhdmVFZGl0KCl7CiAgdHJ5IHsgc2F2ZUFsbCgpOyBzaG93VG9hc3QoJ+KchSDlt7Lkv53lrZjkv67mlLknLCdvaycpOyB0b2dnbGVFZGl0TW9kZSgpOyByZW5kZXJBbGwoKTsgfQogIGNhdGNoKGUpeyBzaG93VG9hc3QoJ+KdjCDkv53lrZjlpLHotKU6ICcrZS5tZXNzYWdlLCdlcnInKTsgfQp9CmZ1bmN0aW9uIGNhbmNlbEVkaXQoKXsKICBpc0VkaXRNb2RlPWZhbHNlOyBkb2N1bWVudC5ib2R5LmNsYXNzTGlzdC5yZW1vdmUoJ2VkaXQtbW9kZScpOwogIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdlZGl0U2F2ZUJhcicpLmNsYXNzTGlzdC5yZW1vdmUoJ3Nob3cnKTsKICB2YXIgYnRuID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignLm1vcmUtaXRlbVtvbmNsaWNrKj0idG9nZ2xlRWRpdE1vZGUiXScpOwogIGlmKGJ0bikgYnRuLnRleHRDb250ZW50ID0gJ+Kcj++4jyDnvJbovpHmqKHlvI8nOwogIHJlbmRlckFsbCgpOwp9CgovKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CiAgIFY2LjAg5pWw5o2u5qih5Z6LCiAgID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0gKi8KY29uc3QgU1VCSkVDVF9JQ09OUyA9IHsKICAn6K+t5paHJzon8J+TlicsICfmlbDlraYnOifwn5SiJywgJ+iLseivrSc6J/CfjJAnLCAn54mp55CGJzon8J+nqicsCiAgJ+WMluWtpic6J/Cfp6snLCAn55Sf54mpJzon8J+MvycsICfljoblj7InOifwn5OcJywgJ+WcsOeQhic6J/CfjI0nLCAn5pS/5rK7Jzon8J+TiycsICfpgZPms5UnOifwn5OLJwp9OwoKY29uc3QgZXhhbUNvbmZpZyA9IHsKICBleGFtSW5mbzogeyBuYW1lOifpmLLln47muK/luILnrKzkuozkuK3lrabmnJ/kuK3ogIPor5UnLCBkYXRlOicyMDI25bm0NuaciDIx5pelJywgaXNvRGF0ZTonMjAyNi0wNi0yMScsIGdyYWRlOiflhavlubTnuqcnIH0sCiAgc2Vzc2lvbnM6IFsKICAgIHsgaWQ6MSwgbmFtZTon5LiK5Y2I5Zy6JywgZGF0ZTonMjAyNi0wNi0yMScsIHN0YXR1czonY29tcGxldGVkJywgc3ViamVjdHM6WwogICAgICB7IHN1YmplY3Q6J+ivreaWhycsIHN0YXJ0OicwODowMCcsIGVuZDonMTA6MDAnLCB0ZWFjaGVyOiflvKDogIHluIgnLCBwYXBlcnM6J+WFsTjpobUnLCBzaGVldHM6JzHlvKAnIH0KICAgIF19LAogICAgeyBpZDoyLCBuYW1lOifkuIrljYjlnLrvvIjnu63vvIknLCBkYXRlOicyMDI2LTA2LTIxJywgc3RhdHVzOidjdXJyZW50Jywgc3ViamVjdHM6WwogICAgICB7IHN1YmplY3Q6J+aVsOWtpicsIHN0YXJ0OicxMDozMCcsIGVuZDonMTI6MDAnLCB0ZWFjaGVyOifmnY7ogIHluIgnLCBwYXBlcnM6J+WFsTbpobUnLCBzaGVldHM6JzHlvKAnIH0sCiAgICAgIHsgc3ViamVjdDon6Iux6K+tJywgc3RhcnQ6JzEwOjMwJywgZW5kOicxMjowMCcsIHRlYWNoZXI6J+eOi+iAgeW4iCcsIHBhcGVyczon5YWxMTDpobUnLCBzaGVldHM6JzHlvKDnrZTpopjljaErMeW8oOWQrOWKmycgfQogICAgXX0sCiAgICB7IGlkOjMsIG5hbWU6J+S4i+WNiOWcuicsIGRhdGU6JzIwMjYtMDYtMjInLCBzdGF0dXM6J3VwY29taW5nJywgc3ViamVjdHM6WwogICAgICB7IHN1YmplY3Q6J+eJqeeQhicsIHN0YXJ0OicxNDozMCcsIGVuZDonMTY6MDAnLCB0ZWFjaGVyOifotbXogIHluIgnLCBwYXBlcnM6J+WFsTTpobUnLCBzaGVldHM6JzHlvKAnIH0KICAgIF19CiAgXSwKICBlbmNvdXJhZ2VNc2dzOiBbJ+iupOecn+WkjeS5oCDwn5OaJywn5L+d5oyB5a6J6Z2ZIPCfpKsnLCfor5rkv6HogIPor5Ug4pyFJywn5Yqg5rK55ZCM5a2m5LusIPCfkqonXSwKICB0cmFja3M6IFsKICAgIHsgaWQ6MSwgbmFtZTon5ZCs5Yqb6K+V6Z+zJywgZGVzYzon6ICD5YmN6K+V5ZCsJywgZHVyYXRpb246JzAwOjMwJyB9LAogICAgeyBpZDoyLCBuYW1lOidTZWN0aW9uIEEnLCBkZXNjOifnn63lr7nor50nLCBkdXJhdGlvbjonMDM6MTUnIH0sCiAgICB7IGlkOjMsIG5hbWU6J1NlY3Rpb24gQicsIGRlc2M6J+mVv+WvueivnScsIGR1cmF0aW9uOicwNDoyMCcgfSwKICAgIHsgaWQ6NCwgbmFtZTonU2VjdGlvbiBDJywgZGVzYzon55+t5paH55CG6KejJywgZHVyYXRpb246JzA1OjQ1JyB9LAogICAgeyBpZDo1LCBuYW1lOidTZWN0aW9uIEQnLCBkZXNjOiflkKzlhpnloavnqbonLCBkdXJhdGlvbjonMDY6MzAnIH0KICBdLAogIGFsZXJ0czogeyBlbnRyeToxNSwgcmVtYWluOjE1LCBjb2xsZWN0OjUgfQp9OwoKbGV0IGxheW91dE1vZGUgPSAnaW5mbyc7IC8qIGNsb2NrIC8gaW5mbyAvIHdhaXRpbmcgKi8KbGV0IG1hbnVhbExvY2tVbnRpbCA9IDA7IC8qIOeUqOaIt+aJi+WKqOWIh+aooeW8j+WQju+8jDYw56eS5YaF5LiN6Ieq5Yqo6KaG55uWICovCnZhciBjbG9ja0NvbG9yQ2xhc3MgPSAnYy1ibHVlJzsgLyogVjUuMO+8muaXtumSn+minOiJsuaho+S9jSBjLWJsdWUvYy1vcmFuZ2UvYy1ibGFjayAqLwpsZXQgY3VycmVudFRyayA9IC0xLCBpc1BsYXlpbmcgPSBmYWxzZSwgc2ltVCA9IDAsIHNpbUQgPSAwLCBwbGF5SXYgPSBudWxsOwpsZXQgc2NoQ29sbGFwc2VkID0gZmFsc2U7CmxldCBjdXJyZW50U2NoRGF0ZSA9ICcnOyAgLyog5b2T5YmN5pi+56S655qE5pel56iL5pel5pyfICovCmxldCBhbGVydFRtcyA9IFtdOwoKLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQogICDlt6Xlhbflh73mlbAKICAgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSAqLwpmdW5jdGlvbiBwYXJzZU1pbih0KXsgY29uc3QgcD10LnNwbGl0KCc6Jyk7IHJldHVybiBwYXJzZUludChwWzBdLDEwKSo2MCtwYXJzZUludChwWzFdLDEwKTsgfQpmdW5jdGlvbiBtYWtlRHQodCl7IGNvbnN0IGQ9bmV3IERhdGUoKSxwPXQuc3BsaXQoJzonKTsgZC5zZXRIb3VycyhwWzBdLHBbMV0sMCwwKTsgcmV0dXJuIGQ7IH0KZnVuY3Rpb24gcGFkMihuKXsgcmV0dXJuIFN0cmluZyhuKS5wYWRTdGFydCgyLCcwJyk7IH0KZnVuY3Rpb24gZXNjKHMpeyByZXR1cm4gKHN8fCcnKS5yZXBsYWNlKC8mL2csJyZhbXA7JykucmVwbGFjZSgvPC9nLCcmbHQ7JykucmVwbGFjZSgvPi9nLCcmZ3Q7Jyk7IH0KZnVuY3Rpb24gaXNvRnJvbUNoaW5lc2Uocyl7CiAgaWYoIXMpIHJldHVybiAnJzsKICB2YXIgbSA9IHMubWF0Y2goLyhcZHs0fSnlubQoXGR7MSwyfSnmnIgoXGR7MSwyfSnml6UvKTsKICByZXR1cm4gbSA/IG1bMV0rJy0nK1N0cmluZyhtWzJdKS5wYWRTdGFydCgyLCcwJykrJy0nK1N0cmluZyhtWzNdKS5wYWRTdGFydCgyLCcwJykgOiBzOwp9CgovKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CiAgIOWIneWni+WMlgogICA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09ICovCmZ1bmN0aW9uIGluaXQoKXsKICBsb2FkQWxsKCk7CiAgYXBwbHlUaGVtZShsb2NhbFN0b3JhZ2UuZ2V0SXRlbSgnbG9iNFRoZW1lJyl8fCdsaWdodCcpOwogIC8qIFY1LjDvvJrmgaLlpI3ml7bpkp/popzoibLlgY/lpb0gKi8KICB2YXIgc2F2ZWRDb2xvciA9IGxvY2FsU3RvcmFnZS5nZXRJdGVtKCdsb2I1Q2xvY2tDb2xvcicpOwogIGlmKHNhdmVkQ29sb3IpIHNldENsb2NrQ29sb3Ioc2F2ZWRDb2xvcik7CiAgLyog6Ieq5Yqo6YCJ5oup5Yid5aeL5qih5byP77ya5pyJ5b6F6ICD5YiZ5b6F6ICD77yM5ZCm5YiZ6ICD5Zy65L+h5oGvICovCiAgdmFyIGNzID0gZXhhbUNvbmZpZy5zZXNzaW9ucy5maW5kKGZ1bmN0aW9uKHMpeyByZXR1cm4gcy5zdGF0dXM9PT0nY3VycmVudCc7IH0pOwogIHZhciBucyA9IGV4YW1Db25maWcuc2Vzc2lvbnMuZmluZChmdW5jdGlvbihzKXsgcmV0dXJuIHMuc3RhdHVzPT09J3VwY29taW5nJzsgfSk7CiAgdmFyIHNhdmVkTW9kZSA9IGxvY2FsU3RvcmFnZS5nZXRJdGVtKCdsb2I0TGF5b3V0Jyk7CiAgaWYoc2F2ZWRNb2RlICYmIFsnY2xvY2snLCdpbmZvJywnd2FpdGluZyddLmluZGV4T2Yoc2F2ZWRNb2RlKT49MCl7CiAgICBzZXRMYXlvdXQoc2F2ZWRNb2RlKTsKICB9IGVsc2UgewogICAgc2V0TGF5b3V0KGNzID8gJ2luZm8nIDogbnMgPyAnd2FpdGluZycgOiAnaW5mbycpOwogIH0KICByZW5kZXJBbGwoKTsKICBzdGFydENsb2NrKCk7CiAgc3RhcnRBbGVydHMoKTsKfQoKZnVuY3Rpb24gcmVuZGVyQWxsKCl7CiAgLyog5Yid5aeL5YyW5b2T5YmN5pel56iL5pel5pyfICovCiAgaWYoIWN1cnJlbnRTY2hEYXRlKSBjdXJyZW50U2NoRGF0ZSA9IGV4YW1Db25maWcuZXhhbUluZm8uZGF0ZTsKICByZW5kZXJTY2goKTsKICByZW5kZXJMZWZ0KCk7CiAgcmVuZGVyQm90UGlsbHMoKTsKICAvKiBWNS4w77ya5ZCs5YqbVUnlt7LnoI3vvIxyZW5kZXJUcmFja3PkuI3lho3osIPnlKggKi8KfQoKLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQogICDkuLvpopgKICAgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSAqLwpmdW5jdGlvbiBzZXRUaGVtZSh0KXsKICBhcHBseVRoZW1lKHQpOwogIGxvY2FsU3RvcmFnZS5zZXRJdGVtKCdsb2I0VGhlbWUnLCB0KTsKfQpmdW5jdGlvbiBhcHBseVRoZW1lKHQpewogIHZhciBib2R5ID0gZG9jdW1lbnQuYm9keTsKICBib2R5LmNsYXNzTGlzdC5yZW1vdmUoJ2RhcmsnLCd3YXJtJyk7CiAgaWYodD09PSdkYXJrJykgYm9keS5jbGFzc0xpc3QuYWRkKCdkYXJrJyk7CiAgaWYodD09PSd3YXJtJykgYm9keS5jbGFzc0xpc3QuYWRkKCd3YXJtJyk7CiAgZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgnLnRoZW1lLWJ0bicpLmZvckVhY2goZnVuY3Rpb24oYil7IGIuY2xhc3NMaXN0LnRvZ2dsZSgnYWN0aXZlJywgYi5nZXRBdHRyaWJ1dGUoJ2QnKT09PXQpOyB9KTsKfQoKLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQogICDmqKHlvI/liIfmjaIKICAgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSAqLwpmdW5jdGlvbiBzZXRNb2RlKG0pewogIG1hbnVhbExvY2tVbnRpbCA9IERhdGUubm93KCkgKyA2MCoxMDAwOyAvKiDnlKjmiLfmiYvliqjliIflkI7plIHlrpo2MOenkiAqLwogIHNldExheW91dChtKTsKICBsb2NhbFN0b3JhZ2Uuc2V0SXRlbSgnbG9iNExheW91dCcsIG0pOwp9CgpmdW5jdGlvbiBzZXRMYXlvdXQobSl7CiAgbGF5b3V0TW9kZSA9IG07CiAgdmFyIGJvZHkgPSBkb2N1bWVudC5ib2R5OwogIGJvZHkuY2xhc3NMaXN0LnJlbW92ZSgnY2xvY2stbW9kZScsJ2luZm8tbW9kZScsJ3dhaXRpbmctbW9kZScpOwogIGlmKG09PT0nY2xvY2snKSBib2R5LmNsYXNzTGlzdC5hZGQoJ2Nsb2NrLW1vZGUnKTsKICBpZihtPT09J2luZm8nKSBib2R5LmNsYXNzTGlzdC5hZGQoJ2luZm8tbW9kZScpOwogIGlmKG09PT0nd2FpdGluZycpIGJvZHkuY2xhc3NMaXN0LmFkZCgnd2FpdGluZy1tb2RlJyk7CiAgZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgnLm5hdi1tb2RlcyAubW9kZS1idG4nKS5mb3JFYWNoKGZ1bmN0aW9uKGIpeyBiLmNsYXNzTGlzdC50b2dnbGUoJ2FjdGl2ZScsIGIuZ2V0QXR0cmlidXRlKCdkYXRhLW0nKT09PW0pOyB9KTsKfQoKLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQogICDpobbpg6jlgJLorqHml7bmoLjlv4MKICAgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSAqLwpmdW5jdGlvbiBzdGFydENsb2NrKCl7CiAgdmFyIHRpY2sgPSAwOwogIHNldEludGVydmFsKGZ1bmN0aW9uKCl7CiAgICBjb25zdCBub3cgPSBuZXcgRGF0ZSgpOwogICAgY29uc3QgY3MgPSBleGFtQ29uZmlnLnNlc3Npb25zLmZpbmQoZnVuY3Rpb24ocyl7IHJldHVybiBzLnN0YXR1cz09PSdjdXJyZW50JzsgfSk7CiAgICBjb25zdCBucyA9IGV4YW1Db25maWcuc2Vzc2lvbnMuZmluZChmdW5jdGlvbihzKXsgcmV0dXJuIHMuc3RhdHVzPT09J3VwY29taW5nJzsgfSk7CiAgICBsZXQgZGlzcGxheT0nLS06LS06LS0nLCBsYWJlbD0nJywgaWQ9JycsIGNscz0nJzsKCiAgICAvKiDoh6rliqjluIPlsYDliIfmjaLvvIjmr482MOenkuajgOa1i+S4gOasoe+8jOeUqOaIt+aJi+WKqOmUgeWumuacn+mXtOS4jeWIh+aNou+8iSAqLwogICAgdGljaysrOwogICAgaWYodGljayA+PSA2MCAmJiBEYXRlLm5vdygpID4gbWFudWFsTG9ja1VudGlsKXsKICAgICAgdGljayA9IDA7CiAgICAgIGlmKGNzKSBzZXRMYXlvdXQoJ2luZm8nKTsKICAgICAgZWxzZSBpZihucykgc2V0TGF5b3V0KCd3YWl0aW5nJyk7CiAgICAgIGVsc2Ugc2V0TGF5b3V0KCdpbmZvJyk7CiAgICB9CgogICAgaWYobGF5b3V0TW9kZT09PSdjbG9jaycpewogICAgICBkaXNwbGF5ID0gZ2V0Q2xvY2sobm93KTsgbGFiZWwgPSAn5YyX5Lqs5pe26Ze0JzsgaWQgPSBleGFtQ29uZmlnLmV4YW1JbmZvLmRhdGU7CiAgICB9CiAgICBlbHNlIGlmKGxheW91dE1vZGU9PT0nd2FpdGluZycpewogICAgICBpZihucyl7CiAgICAgICAgY29uc3Qgc3RhcnRTdHIgPSBucy5zdWJqZWN0cy5tYXAoZnVuY3Rpb24ocyl7IHJldHVybiBzLnN0YXJ0OyB9KS5zb3J0KGZ1bmN0aW9uKGEsYil7IHJldHVybiBwYXJzZU1pbihhKS1wYXJzZU1pbihiKTsgfSlbMF07CiAgICAgICAgY29uc3QgZGlmZiA9IE1hdGgubWF4KDAsIE1hdGguZmxvb3IoKG1ha2VEdChzdGFydFN0ciktbm93KS8xMDAwKSk7CiAgICAgICAgZGlzcGxheSA9IHBhZDIoTWF0aC5mbG9vcihkaWZmLzM2MDApKSsnOicrcGFkMihNYXRoLmZsb29yKGRpZmYlMzYwMC82MCkpKyc6JytwYWQyKGRpZmYlNjApOwogICAgICAgIGxhYmVsID0gJ+i3neemu+W8gOiAgyc7IGlkID0gbnMubmFtZSsnIMK3ICcrbnMuc3ViamVjdHMubWFwKGZ1bmN0aW9uKHMpeyByZXR1cm4gcy5zdWJqZWN0OyB9KS5qb2luKCcrJyk7IGNscz0nd2FpdGluZyc7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgZGlzcGxheSA9IGdldENsb2NrKG5vdyk7IGxhYmVsID0gJ+WMl+S6rOaXtumXtCc7IGlkID0gJ+aaguaXoOW+heiAgyc7CiAgICAgIH0KICAgIH0KICAgIGVsc2UgewogICAgICAvKiDogIPlnLrkv6Hmga/mqKHlvI/vvJrkvJjlhYjmmL7npLrmnKzlnLrliankvZnvvIzml6DmnKzlnLrliJnmmL7npLrot53kuIvkuIDlnLrmiJbml7bpl7QgKi8KICAgICAgaWYoY3MpewogICAgICAgIGNvbnN0IGVuZFN0ciA9IGNzLnN1YmplY3RzLm1hcChmdW5jdGlvbihzKXsgcmV0dXJuIHMuZW5kOyB9KS5zb3J0KGZ1bmN0aW9uKGEsYil7IHJldHVybiBwYXJzZU1pbihiKS1wYXJzZU1pbihhKTsgfSlbMF07CiAgICAgICAgY29uc3QgZGlmZiA9IE1hdGgubWF4KDAsIE1hdGguZmxvb3IoKG1ha2VEdChlbmRTdHIpLW5vdykvMTAwMCkpOwogICAgICAgIGlmKGRpZmY+MCl7CiAgICAgICAgICBkaXNwbGF5ID0gcGFkMihNYXRoLmZsb29yKGRpZmYvMzYwMCkpKyc6JytwYWQyKE1hdGguZmxvb3IoZGlmZiUzNjAwLzYwKSkrJzonK3BhZDIoZGlmZiU2MCk7CiAgICAgICAgICBsYWJlbCA9ICfmnKzlnLrliankvZnkvZznrZTml7bpl7QnOwogICAgICAgICAgaWQgPSBjcy5zdWJqZWN0cy5tYXAoZnVuY3Rpb24ocyl7IHJldHVybiBzLnN1YmplY3Q7IH0pLmpvaW4oJysnKSsnIMK3ICcrY3Muc3ViamVjdHMubWFwKGZ1bmN0aW9uKHMpeyByZXR1cm4gcy50ZWFjaGVyOyB9KS5qb2luKCcrJyk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGFkdmFuY2VTZXNzaW9uKCk7CiAgICAgICAgICBkaXNwbGF5ID0gZ2V0Q2xvY2sobm93KTsgbGFiZWwgPSAn5YyX5Lqs5pe26Ze0JzsgaWQgPSBleGFtQ29uZmlnLmV4YW1JbmZvLmRhdGU7IGNscz0nZW5kZWQnOwogICAgICAgIH0KICAgICAgfSBlbHNlIGlmKG5zKXsKICAgICAgICBjb25zdCBzdGFydFN0ciA9IG5zLnN1YmplY3RzLm1hcChmdW5jdGlvbihzKXsgcmV0dXJuIHMuc3RhcnQ7IH0pLnNvcnQoZnVuY3Rpb24oYSxiKXsgcmV0dXJuIHBhcnNlTWluKGEpLXBhcnNlTWluKGIpOyB9KVswXTsKICAgICAgICBjb25zdCBkaWZmID0gTWF0aC5tYXgoMCwgTWF0aC5mbG9vcigobWFrZUR0KHN0YXJ0U3RyKS1ub3cpLzEwMDApKTsKICAgICAgICBpZihkaWZmPjApewogICAgICAgICAgZGlzcGxheSA9IHBhZDIoTWF0aC5mbG9vcihkaWZmLzM2MDApKSsnOicrcGFkMihNYXRoLmZsb29yKGRpZmYlMzYwMC82MCkpKyc6JytwYWQyKGRpZmYlNjApOwogICAgICAgICAgbGFiZWwgPSAn6Led56a75byA6ICDJzsgaWQgPSBucy5uYW1lKycgwrcgJytucy5zdWJqZWN0cy5tYXAoZnVuY3Rpb24ocyl7IHJldHVybiBzLnN1YmplY3Q7IH0pLmpvaW4oJysnKTsgY2xzPSd3YWl0aW5nJzsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgZGlzcGxheSA9IGdldENsb2NrKG5vdyk7IGxhYmVsID0gJ+WMl+S6rOaXtumXtCc7IGlkID0gJ+aJgOacieiAg+ivleW3sue7k+adnyc7IGNscz0nZW5kZWQnOwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICBkaXNwbGF5ID0gZ2V0Q2xvY2sobm93KTsgbGFiZWwgPSAn5YyX5Lqs5pe26Ze0JzsgaWQgPSBleGFtQ29uZmlnLmV4YW1JbmZvLmRhdGUrJyDCtyAnK2V4YW1Db25maWcuZXhhbUluZm8uZ3JhZGU7IGNscz0nZW5kZWQnOwogICAgICB9CiAgICB9CgogICAgLyog5pu05pawRE9NICovCiAgICB2YXIgdGQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgndGltZURpc3AnKTsKICAgIHRkLnRleHRDb250ZW50ID0gZGlzcGxheTsKICAgIHZhciBpc1NtYWxsID0gZGlzcGxheS5pbmNsdWRlcygnOicpICYmIHBhcnNlSW50KGRpc3BsYXkuc3BsaXQoJzonKVswXSwxMCk8MTA7CiAgICB0ZC5jbGFzc05hbWUgPSAndGltZS1kaXNwbGF5ICcgKyBjbG9ja0NvbG9yQ2xhc3MgKyAoaXNTbWFsbD8nIHNtYWxsJzonJykgKyAoY2xzPT09J3dhaXRpbmcnPycgd2FpdGluZyc6JycpICsgKGNscz09PSdlbmRlZCc/JyBlbmRlZCc6JycpOwogICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2F1eFRleHQnKS50ZXh0Q29udGVudCA9IGxhYmVsOwogICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3RpbWVJZCcpLnRleHRDb250ZW50ID0gaWQ7CgogICAgLyog54q25oCB6Imy57q/ICovCiAgICB2YXIgbGluZUNvbG9yID0gY3MgPyAndmFyKC0tcHJpbWFyeSknIDogbnMgPyAndmFyKC0tc3RhdHVzLXdhaXRpbmcpJyA6ICd2YXIoLS1zdGF0dXMtZW5kZWQpJzsKICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd0aW1lSGVybycpLnN0eWxlLnNldFByb3BlcnR5KCctLWhlcm8tbGluZS1jb2xvcicsIGxpbmVDb2xvcik7CgogICAgLyog5q+P56eS5Yi35paw5bem5Y2hICsg5pel56iLICovCiAgICByZW5kZXJMZWZ0KCk7CiAgICByZW5kZXJTY2goKTsKICB9LCAxMDAwKTsKfQoKZnVuY3Rpb24gZ2V0Q2xvY2sobil7IHJldHVybiBwYWQyKG4uZ2V0SG91cnMoKSkrJzonK3BhZDIobi5nZXRNaW51dGVzKCkpKyc6JytwYWQyKG4uZ2V0U2Vjb25kcygpKTsgfQoKZnVuY3Rpb24gYWR2YW5jZVNlc3Npb24oKXsKICBjb25zdCBpZHggPSBleGFtQ29uZmlnLnNlc3Npb25zLmZpbmRJbmRleChmdW5jdGlvbihzKXsgcmV0dXJuIHMuc3RhdHVzPT09J2N1cnJlbnQnOyB9KTsKICBpZihpZHg+PTApIGV4YW1Db25maWcuc2Vzc2lvbnNbaWR4XS5zdGF0dXM9J2NvbXBsZXRlZCc7CiAgY29uc3QgbmkgPSBleGFtQ29uZmlnLnNlc3Npb25zLmZpbmRJbmRleChmdW5jdGlvbihzKXsgcmV0dXJuIHMuc3RhdHVzPT09J3VwY29taW5nJzsgfSk7CiAgaWYobmk+PTApIGV4YW1Db25maWcuc2Vzc2lvbnNbbmldLnN0YXR1cz0nY3VycmVudCc7CiAgc2F2ZUFsbCgpOyByZW5kZXJBbGwoKTsgc3RhcnRBbGVydHMoKTsKfQoKZnVuY3Rpb24gc2VsZWN0U2Vzc2lvbihpZCl7CiAgZXhhbUNvbmZpZy5zZXNzaW9ucy5mb3JFYWNoKGZ1bmN0aW9uKHMpeyBzLnN0YXR1cyA9IHMuaWQ8aWQ/J2NvbXBsZXRlZCc6cy5pZD09PWlkPydjdXJyZW50JzondXBjb21pbmcnOyB9KTsKICBzYXZlQWxsKCk7IHJlbmRlckFsbCgpOyBzdGFydEFsZXJ0cygpOwp9CgovKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CiAgIOW3puagj++8muacrOWcuuiAg+ivle+8iOe0p+WHkeaOkueJiO+8iQogICA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09ICovCmZ1bmN0aW9uIHJlbmRlckxlZnQoKXsKICBjb25zdCBjcyA9IGV4YW1Db25maWcuc2Vzc2lvbnMuZmluZChmdW5jdGlvbihzKXsgcmV0dXJuIHMuc3RhdHVzPT09J2N1cnJlbnQnOyB9KTsKICBjb25zdCBucyA9IGV4YW1Db25maWcuc2Vzc2lvbnMuZmluZChmdW5jdGlvbihzKXsgcmV0dXJuIHMuc3RhdHVzPT09J3VwY29taW5nJzsgfSk7CiAgY29uc3QgYmFkZ2UgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnbGVmdEJhZGdlJyk7CiAgY29uc3QgcmFuZ2UgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnbGVmdFJhbmdlJyk7CiAgY29uc3QgY29udGVudCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdsZWZ0Q29udGVudCcpOwoKICBpZihjcyl7CiAgICBiYWRnZS50ZXh0Q29udGVudCA9ICfov5vooYzkuK0nOwogICAgYmFkZ2UuY2xhc3NOYW1lID0gJ2NhcmQtYmFkZ2UgbGl2ZSc7CiAgICBjb25zdCBtaW5TID0gY3Muc3ViamVjdHMubWFwKGZ1bmN0aW9uKHMpeyByZXR1cm4gcy5zdGFydDsgfSkuc29ydChmdW5jdGlvbihhLGIpeyByZXR1cm4gcGFyc2VNaW4oYSktcGFyc2VNaW4oYik7IH0pWzBdOwogICAgY29uc3QgbWF4RSA9IGNzLnN1YmplY3RzLm1hcChmdW5jdGlvbihzKXsgcmV0dXJuIHMuZW5kOyB9KS5zb3J0KGZ1bmN0aW9uKGEsYil7IHJldHVybiBwYXJzZU1pbihiKS1wYXJzZU1pbihhKTsgfSlbMF07CiAgICByYW5nZS50ZXh0Q29udGVudCA9IG1pblMrJyDigJQgJyttYXhFOwoKICAgIC8qIOe0p+WHkeWGheWuue+8mue9keagvOS/oeaBryArIOenkeebruWNoeeJhyAqLwogICAgdmFyIGh0bWwgPSAnJzsKCiAgICAvKiDkv6Hmga/nvZHmoLwgKi8KICAgIGh0bWwgKz0gJzxkaXYgY2xhc3M9ImluZm8tZ3JpZCI+JzsKICAgIGh0bWwgKz0gJzxkaXYgY2xhc3M9ImluZm8taXRlbSI+PHNwYW4gY2xhc3M9ImluZm8tbGFiZWwiPuWcuuasoTwvc3Bhbj48c3BhbiBjbGFzcz0iaW5mby12YWx1ZSI+Jytlc2MoY3MubmFtZSkrJzwvc3Bhbj48L2Rpdj4nOwogICAgaHRtbCArPSAnPGRpdiBjbGFzcz0iaW5mby1pdGVtIj48c3BhbiBjbGFzcz0iaW5mby1sYWJlbCI+56eR55uuPC9zcGFuPjxzcGFuIGNsYXNzPSJpbmZvLXZhbHVlIj4nK2NzLnN1YmplY3RzLmxlbmd0aCsn6ZeoPC9zcGFuPjwvZGl2Pic7CiAgICBodG1sICs9ICc8L2Rpdj4nOwoKICAgIC8qIOebkeiAg+iAgeW4iOaoquaOkuW+veeroCAqLwogICAgaHRtbCArPSAnPGRpdiBzdHlsZT0ibWFyZ2luLWJvdHRvbTowLjVyZW07Ij48c3BhbiBzdHlsZT0iZm9udC1zaXplOjAuNjVyZW07Y29sb3I6dmFyKC0tdGV4dC1zdWIpO2ZvbnQtd2VpZ2h0OjYwMDttYXJnaW4tcmlnaHQ6MC40cmVtOyI+55uR6ICDPC9zcGFuPjxzcGFuIHN0eWxlPSJkaXNwbGF5OmlubGluZS1mbGV4O2dhcDowLjNyZW07ZmxleC13cmFwOndyYXA7Ij4nOwogICAgdmFyIHRlYWNoZXJTZXQgPSBbXTsKICAgIGNzLnN1YmplY3RzLmZvckVhY2goZnVuY3Rpb24ocyl7CiAgICAgIGlmKHRlYWNoZXJTZXQuaW5kZXhPZihzLnRlYWNoZXIpPT09LTEpIHRlYWNoZXJTZXQucHVzaChzLnRlYWNoZXIpOwogICAgfSk7CiAgICB0ZWFjaGVyU2V0LmZvckVhY2goZnVuY3Rpb24odCl7CiAgICAgIGh0bWwgKz0gJzxzcGFuIHN0eWxlPSJwYWRkaW5nOjAuMThyZW0gMC41cmVtO2JhY2tncm91bmQ6dmFyKC0tcHJpbWFyeS1iZzIpO2JvcmRlci1yYWRpdXM6MTAwcHg7Zm9udC1zaXplOjAuNjhyZW07Zm9udC13ZWlnaHQ6NjAwO2NvbG9yOnZhcigtLXByaW1hcnkpOyI+Jytlc2ModCkrJzwvc3Bhbj4nOwogICAgfSk7CiAgICBodG1sICs9ICc8L3NwYW4+PC9kaXY+JzsKCiAgICAvKiDnp5Hnm67ljaHniYcgKi8KICAgIGNzLnN1YmplY3RzLmZvckVhY2goZnVuY3Rpb24ocyl7CiAgICAgIGh0bWwgKz0gJzxkaXYgY2xhc3M9InN1Yi1jYXJkIj4nOwogICAgICBodG1sICs9ICc8ZGl2IGNsYXNzPSJzdWItY2FyZC1uYW1lIj4nKyhTVUJKRUNUX0lDT05TW3Muc3ViamVjdF18fCfwn5OdJykrJyAnK2VzYyhzLnN1YmplY3QpKyc8L2Rpdj4nOwogICAgICBodG1sICs9ICc8ZGl2IGNsYXNzPSJzdWItY2FyZC1tZXRhIj48c3Bhbj4nK2VzYyhzLnN0YXJ0KSsn4oCUJytlc2Mocy5lbmQpKyc8L3NwYW4+PHNwYW4+Jytlc2Mocy50ZWFjaGVyKSsnPC9zcGFuPjwvZGl2Pic7CiAgICAgIGh0bWwgKz0gJzxkaXYgY2xhc3M9InRhZy1ncnAiPic7CiAgICAgIGh0bWwgKz0gJzxzcGFuIGNsYXNzPSJ0YWcgcHJpIj7wn5OEICcrZXNjKHMucGFwZXJzKSsnPC9zcGFuPic7CiAgICAgIGh0bWwgKz0gJzxzcGFuIGNsYXNzPSJ0YWcgb2siPvCfk50gJytlc2Mocy5zaGVldHMpKyc8L3NwYW4+JzsKICAgICAgaHRtbCArPSAnPC9kaXY+PC9kaXY+JzsKICAgIH0pOwoKICAgIGNvbnRlbnQuaW5uZXJIVE1MID0gaHRtbDsKCiAgfSBlbHNlIGlmKG5zKXsKICAgIGJhZGdlLnRleHRDb250ZW50ID0gJ+etieW+heS4rSc7CiAgICBiYWRnZS5jbGFzc05hbWUgPSAnY2FyZC1iYWRnZSB3YWl0JzsKICAgIHJhbmdlLnRleHRDb250ZW50ID0gJ+W8gOiAg++8micrbnMuc3ViamVjdHMubWFwKGZ1bmN0aW9uKHMpeyByZXR1cm4gcy5zdGFydDsgfSkuc29ydChmdW5jdGlvbihhLGIpeyByZXR1cm4gcGFyc2VNaW4oYSktcGFyc2VNaW4oYik7IH0pWzBdOwogICAgY29udGVudC5pbm5lckhUTUwgPSAnPGRpdiBjbGFzcz0ibm8tZXhhbSI+PGRpdiBjbGFzcz0ibm8tZXhhbS1pYyI+8J+TljwvZGl2PjxkaXYgY2xhc3M9Im5vLWV4YW0tbXNnIj4nK2VzYyhucy5uYW1lKSsnPC9kaXY+PGRpdiBjbGFzcz0ibm8tZXhhbS10aXAiPicrZXhhbUNvbmZpZy5lbmNvdXJhZ2VNc2dzW01hdGguZmxvb3IoTWF0aC5yYW5kb20oKSpleGFtQ29uZmlnLmVuY291cmFnZU1zZ3MubGVuZ3RoKV0rJzwvZGl2PjwvZGl2Pic7CiAgfSBlbHNlIHsKICAgIGJhZGdlLnRleHRDb250ZW50ID0gJ+W3sue7k+adnyc7CiAgICBiYWRnZS5jbGFzc05hbWUgPSAnY2FyZC1iYWRnZSc7CiAgICBiYWRnZS5zdHlsZS5iYWNrZ3JvdW5kID0gJ3ZhcigtLXN0YXR1cy1lbmRlZC1saWdodCknOwogICAgYmFkZ2Uuc3R5bGUuY29sb3IgPSAndmFyKC0tc3RhdHVzLWVuZGVkKSc7CiAgICByYW5nZS50ZXh0Q29udGVudCA9ICfmiYDmnInogIPor5Xlt7Lnu5PmnZ8nOwogICAgY29udGVudC5pbm5lckhUTUwgPSAnPGRpdiBjbGFzcz0ibm8tZXhhbSI+PGRpdiBjbGFzcz0ibm8tZXhhbS1pYyI+8J+OiTwvZGl2PjxkaXYgY2xhc3M9Im5vLWV4YW0tbXNnIj7ovpvoi6bkuobvvIE8L2Rpdj48L2Rpdj4nOwogIH0KfQoKLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQogICDlj7PmoI/vvJrku4rml6Xml6XnqIvvvIjku4XpooTop4jvvIxob3ZlcuW8ueivpuaDhe+8iQogICA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09ICovCmZ1bmN0aW9uIHJlbmRlclNjaCgpewogIC8qIOehruS/nSBjdXJyZW50U2NoRGF0ZSDmnInlgLwgKi8KICBpZighY3VycmVudFNjaERhdGUpIGN1cnJlbnRTY2hEYXRlID0gZXhhbUNvbmZpZy5leGFtSW5mby5pc29EYXRlIHx8IGlzb0Zyb21DaGluZXNlKGV4YW1Db25maWcuZXhhbUluZm8uZGF0ZSkgfHwgJzIwMjYtMDYtMjEnOwoKICAvKiDml6XmnJ/mmL7npLrvvJrkvJjlhYjnlKjkuK3mlofmoLzlvI8gKi8KICB2YXIgZGlzcGxheURhdGUgPSBleGFtQ29uZmlnLmV4YW1JbmZvLmRhdGUgfHwgY3VycmVudFNjaERhdGU7CiAgaWYoY3VycmVudFNjaERhdGUpewogICAgdmFyIGQgPSBuZXcgRGF0ZShjdXJyZW50U2NoRGF0ZSsnVDAwOjAwOjAwJyk7CiAgICB2YXIgdG9kYXlTdHIgPSBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCkuc2xpY2UoMCwxMCk7CiAgICB2YXIgdG9tU3RyID0gbmV3IERhdGUoRGF0ZS5ub3coKSs4NjQwMDAwMCkudG9JU09TdHJpbmcoKS5zbGljZSgwLDEwKTsKICAgIGlmKGN1cnJlbnRTY2hEYXRlID09PSB0b2RheVN0cikgZGlzcGxheURhdGUgPSAoZXhhbUNvbmZpZy5leGFtSW5mby5kYXRlfHxjdXJyZW50U2NoRGF0ZSkrJ++8iOS7iuWkqe+8iSc7CiAgICBlbHNlIGlmKGN1cnJlbnRTY2hEYXRlID09PSB0b21TdHIpIGRpc3BsYXlEYXRlID0gY3VycmVudFNjaERhdGUuc2xpY2UoNSkucmVwbGFjZSgnLScsJ+aciCcpKyfml6XvvIjmmI7lpKnvvIknOwogICAgZWxzZSBkaXNwbGF5RGF0ZSA9IGN1cnJlbnRTY2hEYXRlLnNsaWNlKDUpLnJlcGxhY2UoJy0nLCfmnIgnKSsn5pelJzsKICB9CiAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3NjaERhdGUnKS50ZXh0Q29udGVudCA9IGRpc3BsYXlEYXRlOwoKICAvKiDmjInml6XmnJ/ov4fmu6TlnLrmrKHvvJvml6AgZGF0ZSDlrZfmrrXnmoTlnLrmrKHpu5jorqTmmL7npLogKi8KICBjb25zdCBsaXN0ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3NjaExpc3QnKTsKICBjb25zdCB2aXNpYmxlID0gZXhhbUNvbmZpZy5zZXNzaW9ucy5maWx0ZXIoZnVuY3Rpb24ocyl7CiAgICBpZihzLmRhdGUgJiYgY3VycmVudFNjaERhdGUpIHJldHVybiBzLmRhdGUgPT09IGN1cnJlbnRTY2hEYXRlOwogICAgcmV0dXJuIHRydWU7IC8qIOWQkeWQjuWFvOWuue+8muaXoCBkYXRlIOWtl+auteWImeWFqOmDqOaYvuekuiAqLwogIH0pLmZpbHRlcihmdW5jdGlvbihzKXsKICAgIHJldHVybiBzY2hDb2xsYXBzZWQgPyBzLnN0YXR1cyE9PSdjb21wbGV0ZWQnIDogdHJ1ZTsKICB9KTsKCiAgbGlzdC5pbm5lckhUTUwgPSB2aXNpYmxlLm1hcChmdW5jdGlvbihzKXsKICAgIHZhciBjbHMgPSBzLnN0YXR1cz09PSdjdXJyZW50Jz8nY3VyJzpzLnN0YXR1cz09PSdjb21wbGV0ZWQnPydkb25lJzondXBjb21pbmcnOwogICAgdmFyIGRvdENscyA9IHMuc3RhdHVzPT09J2N1cnJlbnQnPydsaXZlJzpzLnN0YXR1cz09PSdjb21wbGV0ZWQnPydkb24nOid3YWl0JzsKICAgIHZhciBzdWJqU3RyID0gcy5zdWJqZWN0cy5sZW5ndGg+MQogICAgICA/IHMuc3ViamVjdHMubWFwKGZ1bmN0aW9uKHgpeyByZXR1cm4geC5zdWJqZWN0OyB9KS5qb2luKCcrJykKICAgICAgOiBzLnN1YmplY3RzWzBdLnN1YmplY3Q7CiAgICB2YXIgdGltZVN0ciA9IHMuc3ViamVjdHMubGVuZ3RoPjEKICAgICAgPyBzLnN1YmplY3RzWzBdLnN0YXJ0KyfigJQnK3Muc3ViamVjdHNbcy5zdWJqZWN0cy5sZW5ndGgtMV0uZW5kCiAgICAgIDogcy5zdWJqZWN0c1swXS5zdGFydCsn4oCUJytzLnN1YmplY3RzWzBdLmVuZDsKICAgIHZhciBpY29uID0gU1VCSkVDVF9JQ09OU1tzLnN1YmplY3RzWzBdLnN1YmplY3RdfHwn8J+TnSc7CgogICAgLyogaG92ZXLlvLnnqpflhoXlrrkgKi8KICAgIHZhciB0aXAgPSAnJzsKICAgIHMuc3ViamVjdHMuZm9yRWFjaChmdW5jdGlvbihzdWIpewogICAgICB0aXAgKz0gJzxkaXYgY2xhc3M9InNjaC10aXAtcm93Ij48c3BhbiBjbGFzcz0ic2NoLXRpcC1sYmwiPicrZXNjKHN1Yi5zdWJqZWN0KSsnPC9zcGFuPjxzcGFuPicrZXNjKHN1Yi50ZWFjaGVyKSsnIHwgJytlc2Moc3ViLnBhcGVycykrJzwvc3Bhbj48L2Rpdj4nOwogICAgfSk7CgogICAgcmV0dXJuICc8ZGl2IGNsYXNzPSJzY2gtaXRlbSAnK2NscysnIiBvbmNsaWNrPSJzZWxlY3RTZXNzaW9uKCcrcy5pZCsnKSI+JysKICAgICAgJzxkaXYgY2xhc3M9InNjaC1kb3QgJytkb3RDbHMrJyI+PC9kaXY+JysKICAgICAgJzxkaXYgY2xhc3M9InNjaC1pY29uIj4nK2ljb24rJzwvZGl2PicrCiAgICAgICAgJzxkaXYgY2xhc3M9InNjaC1pbmZvIj4nKwogICAgICAgICc8ZGl2IGNsYXNzPSJzY2gtbmFtZSIgZGF0YS1pZD0iJytzLmlkKyciPicrZXNjKHMubmFtZSkrJzwvZGl2PicrCiAgICAgICAgJzxkaXYgY2xhc3M9InNjaC10aW1lIj4nK3RpbWVTdHIrJzwvZGl2PicrCiAgICAgICc8L2Rpdj4nKwogICAgICAnPGRpdiBjbGFzcz0ic2NoLXRpcCI+Jyt0aXArJzwvZGl2PicrCiAgICAnPC9kaXY+JzsKICB9KS5qb2luKCcnKTsKCiAgLyog57yW6L6R5qih5byP5LiL6YeN5paw57uR5a6a5pel56iL5p2h55uuICovCiAgaWYoaXNFZGl0TW9kZSkgc2V0VGltZW91dChlbmFibGVFZGl0LCAwKTsKfQoKZnVuY3Rpb24gdG9nZ2xlU2NoKCl7CiAgc2NoQ29sbGFwc2VkID0gIXNjaENvbGxhcHNlZDsKICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnc2NoVG9nZ2xlJykudGV4dENvbnRlbnQgPSBzY2hDb2xsYXBzZWQgPyAn5bGV5byA5bey5a6M5oiQ5Zy65qyhIOKWvCcgOiAn5pS26LW35bey5a6M5oiQ5Zy65qyhIOKWsic7CiAgcmVuZGVyU2NoKCk7Cn0KCmZ1bmN0aW9uIGNoYW5nZVNjaERhdGUob2Zmc2V0KXsKICB2YXIgZCA9IGN1cnJlbnRTY2hEYXRlID8gbmV3IERhdGUoY3VycmVudFNjaERhdGUrJ1QwMDowMDowMCcpIDogbmV3IERhdGUoKTsKICBkLnNldERhdGUoZC5nZXREYXRlKCkgKyBvZmZzZXQpOwogIGN1cnJlbnRTY2hEYXRlID0gZC50b0lTT1N0cmluZygpLnNsaWNlKDAsMTApOwogIHJlbmRlclNjaCgpOwp9CgovKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CiAgIOW6lemDqOiNr+S4uAogICA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09ICovCmZ1bmN0aW9uIHJlbmRlckJvdFBpbGxzKCl7CiAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2JvdFBpbGxzJykuaW5uZXJIVE1MID0gZXhhbUNvbmZpZy5zZXNzaW9ucy5tYXAoZnVuY3Rpb24ocyl7CiAgICB2YXIgY2xzID0gcy5zdGF0dXM9PT0nY29tcGxldGVkJz8nZG9uZSc6cy5zdGF0dXM9PT0nY3VycmVudCc/J2N1cic6Jyc7CiAgICB2YXIgdHh0ID0gcy5zdWJqZWN0cy5sZW5ndGg+MQogICAgICA/IHMuc3ViamVjdHNbMF0uc3RhcnQuc2xpY2UoMCw1KSsnICcrcy5zdWJqZWN0cy5tYXAoZnVuY3Rpb24oeCl7cmV0dXJuIHguc3ViamVjdDt9KS5qb2luKCcrJykKICAgICAgOiBzLnN1YmplY3RzWzBdLnN0YXJ0LnNsaWNlKDAsNSkrJyAnK3Muc3ViamVjdHNbMF0uc3ViamVjdDsKICAgIHJldHVybiAnPGRpdiBjbGFzcz0icGlsbCAnK2NscysnIiBvbmNsaWNrPSJzZWxlY3RTZXNzaW9uKCcrcy5pZCsnKSI+Jyt0eHQrJzwvZGl2Pic7CiAgfSkuam9pbignJyk7Cn0KCi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KICAg5YiG5q615o+Q6YaS6K6h5pe25ZmoCiAgID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0gKi8KZnVuY3Rpb24gc3RhcnRBbGVydHMoKXsKICAvKiDmuIXpmaTml6flrprml7blmaggKi8KICBhbGVydFRtcy5mb3JFYWNoKGZ1bmN0aW9uKHQpeyBjbGVhclRpbWVvdXQodCk7IH0pOwogIGFsZXJ0VG1zID0gW107CgogIHZhciBjcyA9IGV4YW1Db25maWcuc2Vzc2lvbnMuZmluZChmdW5jdGlvbihzKXsgcmV0dXJuIHMuc3RhdHVzPT09J2N1cnJlbnQnOyB9KTsKICBpZighY3MpIHJldHVybjsKCiAgdmFyIG5vdyA9IG5ldyBEYXRlKCk7CiAgdmFyIGVuZFN0ciA9IGNzLnN1YmplY3RzLm1hcChmdW5jdGlvbihzKXsgcmV0dXJuIHMuZW5kOyB9KS5zb3J0KGZ1bmN0aW9uKGEsYil7IHJldHVybiBwYXJzZU1pbihiKS1wYXJzZU1pbihhKTsgfSlbMF07CiAgdmFyIGVuZFRpbWUgPSBtYWtlRHQoZW5kU3RyKTsKICB2YXIgcmVtYWluTXMgPSBlbmRUaW1lIC0gbm93OwoKICAvKiDliankvZkxNeWIhumSn+aPkOmGkiAqLwogIHZhciByZW1haW5BbGVydCA9IHJlbWFpbk1zIC0gMTUqNjAqMTAwMDsKICBpZihyZW1haW5BbGVydD4wKXsKICAgIGFsZXJ0VG1zLnB1c2goc2V0VGltZW91dChmdW5jdGlvbigpeyBzaG93QWxlcnQoJ+KPse+4jycsJ+WJqeS9mTE15YiG6ZKfJywn6K+35o+Q6YaS6ICD55Sf5rOo5oSP5pe26Ze077yBJyk7IH0sIHJlbWFpbkFsZXJ0KSk7CiAgfQoKICAvKiDmlLbljbfliY015YiG6ZKf5o+Q6YaSICovCiAgdmFyIGNvbGxlY3RBbGVydCA9IHJlbWFpbk1zIC0gNSo2MCoxMDAwOwogIGlmKGNvbGxlY3RBbGVydD4wKXsKICAgIGFsZXJ0VG1zLnB1c2goc2V0VGltZW91dChmdW5jdGlvbigpeyBzaG93QWxlcnQoJ/Cfk4snLCfmlLbljbfliY015YiG6ZKfJywn6K+35YeG5aSH5pS25Y2377yBJyk7IH0sIGNvbGxlY3RBbGVydCkpOwogIH0KCiAgLyog5YWl5Zy65o+Q6YaS77yI5byA6ICD5YmNMTXliIbpkp/vvIkqLwogIHZhciBzdGFydFN0ciA9IGNzLnN1YmplY3RzLm1hcChmdW5jdGlvbihzKXsgcmV0dXJuIHMuc3RhcnQ7IH0pLnNvcnQoZnVuY3Rpb24oYSxiKXsgcmV0dXJuIHBhcnNlTWluKGEpLXBhcnNlTWluKGIpOyB9KVswXTsKICB2YXIgZW50cnlBbGVydCA9IG1ha2VEdChzdGFydFN0cikgLSBub3cgLSAxNSo2MCoxMDAwOwogIGlmKGVudHJ5QWxlcnQ+MCl7CiAgICBhbGVydFRtcy5wdXNoKHNldFRpbWVvdXQoZnVuY3Rpb24oKXsgc2hvd0FsZXJ0KCfwn5qqJywn5YWl5Zy65pe26Ze0Jywn6K+357uE57uH6ICD55Sf5YWl5Zy677yBJyk7IH0sIGVudHJ5QWxlcnQpKTsKICB9Cn0KCmZ1bmN0aW9uIHNob3dBbGVydChpY29uLCBtc2csIHN1Yil7CiAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2FsZXJ0SWMnKS50ZXh0Q29udGVudCA9IGljb247CiAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2FsZXJ0TXNnJykudGV4dENvbnRlbnQgPSBtc2c7CiAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2FsZXJ0U3ViJykudGV4dENvbnRlbnQgPSBzdWI7CiAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2FsZXJ0T3YnKS5jbGFzc0xpc3QuYWRkKCdzaG93Jyk7CiAgaWYobmF2aWdhdG9yLnZpYnJhdGUpIG5hdmlnYXRvci52aWJyYXRlKFsyMDAsMTAwLDIwMF0pOwp9CmZ1bmN0aW9uIGNsb3NlQWxlcnQoKXsgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2FsZXJ0T3YnKS5jbGFzc0xpc3QucmVtb3ZlKCdzaG93Jyk7IH0KCi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KICAg5ZCs5YqbCiAgID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0gKi8KZnVuY3Rpb24gb3Blbkxpc3RlbigpeyAvKiBWNS4w77ya5ZCs5YqbVUnlt7LnoI0gKi8gfQpmdW5jdGlvbiBjbG9zZUxpc3RlbigpeyAvKiBWNS4w77ya5ZCs5YqbVUnlt7LnoI0gKi8gfQoKZnVuY3Rpb24gcmVuZGVyVHJhY2tzKCl7CiAgLyogVjUuMO+8muWQrOWKm1VJ5bey56CN77yM5q2k5Ye95pWw5L+d55WZ5Li656m65aOz77yM5LiL54mI5pys5oGi5aSNICovCn0KCmZ1bmN0aW9uIHBsYXlUcmsoaWR4KXsKICAvKiBWNS4w77ya5ZCs5YqbVUnlt7LnoI3vvIzkuIvniYjmnKzmgaLlpI0gKi8KfQoKZnVuY3Rpb24gdG9nZ2xlUGxheSgpeyAvKiBWNS4w77ya5ZCs5YqbVUnlt7LnoI0gKi8gfQpmdW5jdGlvbiBwcmV2VHJrKCl7IC8qIFY1LjDvvJrlkKzliptVSeW3suegjSAqLyB9CmZ1bmN0aW9uIG5leHRUcmsoKXsgLyogVjUuMO+8muWQrOWKm1VJ5bey56CNICovIH0KZnVuY3Rpb24gc2Vla0xwKGUpeyAvKiBWNS4w77ya5ZCs5YqbVUnlt7LnoI0gKi8gfQoKLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQogICDphY3nva7lr7zlhaXlr7zlh7oKICAgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSAqLwovLyBWNS4w77ya6K+G5Yir5o6S54+t57O757uf5a+85Ye655qESlNPTuW5tuaZuuiDvei9rOaNogpmdW5jdGlvbiBjb252ZXJ0RnJvbVNjaGVkdWxlKHNjaGVkRGF0YSl7CiAgLy8g5o6S54+tSlNPTue7k+aehO+8mnt0ZWFjaGVycywgc2Vzc2lvbnM6W3tkYXRlLHBlcmlvZCx0aW1lLHN1YmplY3R9XSwgcm9vbXMsIG1hdHJpeCwgcm9sZUNoaWVmLCByb2xlWHN9CiAgdmFyIHNyYyA9IHNjaGVkRGF0YTsKICB2YXIgc2Vzc2lvbnMgPSBzcmMuc2Vzc2lvbnMgfHwgW107CiAgdmFyIG1hdHJpeCA9IHNyYy5tYXRyaXggfHwge307CiAgdmFyIHJvb21zID0gc3JjLnJvb21zIHx8IFtdOwogIHZhciByb2xlQ2hpZWYgPSBzcmMucm9sZUNoaWVmIHx8IFtdOwogIHZhciByb2xlWHMgPSBzcmMucm9sZVhzIHx8IFtdOwoKICAvLyDop6PmnpDogIPor5Xml6XmnJ8KICB2YXIgZmlyc3REYXRlID0gc2Vzc2lvbnMubGVuZ3RoID4gMCA/IChzZXNzaW9uc1swXS5kYXRlIHx8ICcnKSA6ICcnOwogIHZhciB5ZWFyTWF0Y2ggPSBmaXJzdERhdGUubWF0Y2goLyhcZHs0fSnlubQvKTsKICB2YXIgeWVhciA9IHllYXJNYXRjaCA/IHllYXJNYXRjaFsxXSA6IG5ldyBEYXRlKCkuZ2V0RnVsbFllYXIoKS50b1N0cmluZygpOwogIHZhciBkYXRlTWF0Y2ggPSBmaXJzdERhdGUubWF0Y2goLyhcZHsxLDJ9KeaciChcZHsxLDJ9KeaXpS8pOwogIHZhciBpc29EYXRlID0geWVhciArICctJyArIChkYXRlTWF0Y2ggPyBTdHJpbmcoZGF0ZU1hdGNoWzFdKS5wYWRTdGFydCgyLCcwJykgOiAnMDEnKSArICctJyArIChkYXRlTWF0Y2ggPyBTdHJpbmcoZGF0ZU1hdGNoWzJdKS5wYWRTdGFydCgyLCcwJykgOiAnMDEnKTsKICB2YXIgY25EYXRlID0geWVhciArICflubQnICsgKGRhdGVNYXRjaCA/IGRhdGVNYXRjaFsxXSsn5pyIJytkYXRlTWF0Y2hbMl0rJ+aXpScgOiAnJyk7CgogIC8vIOi9rOaNonNlc3Npb25zCiAgdmFyIGNvbnNvbGVTZXNzaW9ucyA9IFtdOwogIHZhciBzZXNzaW9uSWQgPSAxOwogIHNlc3Npb25zLmZvckVhY2goZnVuY3Rpb24oc2VzLCBzaSl7CiAgICB2YXIgbm9ybWFsaXplZFRpbWUgPSAoc2VzLnRpbWUgfHwgJycpLnJlcGxhY2UoL++8mi9nLCc6JykucmVwbGFjZSgv772eL2csJ34nKTsKICAgIHZhciB0aW1lTWF0Y2ggPSBub3JtYWxpemVkVGltZS5tYXRjaCgvKFxkKzpcZCspfihcZCs6XGQrKS8pOwogICAgdmFyIHN0YXJ0VGltZSA9IHRpbWVNYXRjaCA/IHRpbWVNYXRjaFsxXSA6ICcnOwogICAgdmFyIGVuZFRpbWUgPSB0aW1lTWF0Y2ggPyB0aW1lTWF0Y2hbMl0gOiAnJzsKCiAgICB2YXIgc3ViamVjdHMgPSAoc2VzLnN1YmplY3QgfHwgJycpLnNwbGl0KC9b44CBLO+8jF0vKS5tYXAoZnVuY3Rpb24ocyl7IHJldHVybiBzLnRyaW0oKTsgfSkuZmlsdGVyKGZ1bmN0aW9uKHMpeyByZXR1cm4gczsgfSk7CiAgICB2YXIgZ3JhZGUgPSAn5LiD5bm057qnJzsKICAgIGlmKChzZXMuc3ViamVjdCB8fCAnJykuaW5kZXhPZign5YWr5bm057qnJykgIT09IC0xIHx8IChzZXMuc3ViamVjdCB8fCAnJykuaW5kZXhPZign54mp55CGJykgIT09IC0xKSBncmFkZSA9ICflhavlubTnuqcnOwoKICAgIC8vIOS7o+ihqOiAgeW4iAogICAgdmFyIHJlcFRlYWNoZXIgPSAnJzsKICAgIGZvcih2YXIgcmkgPSAwOyByaSA8IHJvb21zLmxlbmd0aDsgcmkrKyl7CiAgICAgIHZhciBhcnIgPSBtYXRyaXhbc2ldICYmIG1hdHJpeFtzaV1bcmldOwogICAgICBpZihhcnIgJiYgYXJyLmxlbmd0aCA+IDAgJiYgYXJyWzBdICE9PSAnw5cnKXsgcmVwVGVhY2hlciA9IGFyclswXTsgYnJlYWs7IH0KICAgIH0KICAgIHZhciBjaGllZk5hbWVzID0gKHJvbGVDaGllZltzaV0gfHwgW10pLmpvaW4oJ+OAgScpOwogICAgdmFyIHhzTmFtZXMgPSAocm9sZVhzW3NpXSB8fCBbXSkuam9pbign44CBJyk7CgogICAgdmFyIHNlc3Npb25OYW1lID0gc2VzLnBlcmlvZCB8fCAn6ICD6K+VJzsKICAgIHZhciBleGlzdFNlcyA9IGNvbnNvbGVTZXNzaW9ucy5maW5kKGZ1bmN0aW9uKHMpeyByZXR1cm4gcy5kYXRlID09PSBpc29EYXRlICYmIHMubmFtZSA9PT0gc2Vzc2lvbk5hbWU7IH0pOwogICAgaWYoIWV4aXN0U2VzKXsKICAgICAgZXhpc3RTZXMgPSB7IGlkOiBzZXNzaW9uSWQrKywgbmFtZTogc2Vzc2lvbk5hbWUsIGRhdGU6IGlzb0RhdGUsIHN0YXR1czogJ3VwY29taW5nJywgc3ViamVjdHM6IFtdIH07CiAgICAgIGNvbnNvbGVTZXNzaW9ucy5wdXNoKGV4aXN0U2VzKTsKICAgIH0KICAgIHN1YmplY3RzLmZvckVhY2goZnVuY3Rpb24oc3Viail7CiAgICAgIGV4aXN0U2VzLnN1YmplY3RzLnB1c2goewogICAgICAgIHN1YmplY3Q6IHN1YmosCiAgICAgICAgc3RhcnQ6IHN0YXJ0VGltZSwKICAgICAgICBlbmQ6IGVuZFRpbWUsCiAgICAgICAgdGVhY2hlcjogcmVwVGVhY2hlciwKICAgICAgICBjaGllZjogY2hpZWZOYW1lcywKICAgICAgICBjb2xsZWN0b3I6IHhzTmFtZXMsCiAgICAgICAgaGFzTGlzdGVuaW5nOiBzdWJqLmluZGV4T2YoJ+iLseivrScpICE9PSAtMQogICAgICB9KTsKICAgIH0pOwogIH0pOwogIGlmKGNvbnNvbGVTZXNzaW9ucy5sZW5ndGggPiAwKSBjb25zb2xlU2Vzc2lvbnNbMF0uc3RhdHVzID0gJ2N1cnJlbnQnOwoKICByZXR1cm4gewogICAgZXhhbUluZm86IHsKICAgICAgbmFtZTogJ+iAg+ivleWuieaOkiAnICsgY25EYXRlLAogICAgICBkYXRlOiBjbkRhdGUsCiAgICAgIGlzb0RhdGU6IGlzb0RhdGUsCiAgICAgIGdyYWRlOiAnJywKICAgICAgc2Nob29sOiAn6Ziy5Z+O5riv5biC56ys5LqM5Lit5a2mJwogICAgfSwKICAgIHNlc3Npb25zOiBjb25zb2xlU2Vzc2lvbnMsCiAgICBlbmNvdXJhZ2VNc2dzOiBleGFtQ29uZmlnLmVuY291cmFnZU1zZ3MsCiAgICBhbGVydHM6IGV4YW1Db25maWcuYWxlcnRzCiAgfTsKfQoKZnVuY3Rpb24gaW1wb3J0Q2ZnKCl7CiAgdmFyIGlucCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2lucHV0Jyk7IGlucC50eXBlPSdmaWxlJzsgaW5wLmFjY2VwdD0nLmpzb24nOwogIGlucC5vbmNoYW5nZSA9IGZ1bmN0aW9uKGUpewogICAgdmFyIGYgPSBlLnRhcmdldC5maWxlc1swXTsgaWYoIWYpIHJldHVybjsKICAgIHZhciBmciA9IG5ldyBGaWxlUmVhZGVyKCk7CiAgICBmci5vbmxvYWQgPSBmdW5jdGlvbihldil7CiAgICAgIHRyeSB7CiAgICAgICAgdmFyIGNmZyA9IEpTT04ucGFyc2UoZXYudGFyZ2V0LnJlc3VsdCk7CiAgICAgICAgdmFyIHNyYyA9ICcnOwogICAgICAgIC8vIFY2LjDvvJrmmbrog73or4bliKvkuInnp43moLzlvI8KICAgICAgICBpZihjZmcudGVhY2hlcnMgJiYgY2ZnLnNlc3Npb25zICYmIGNmZy5tYXRyaXgpewogICAgICAgICAgLy8g5o6S54+t57O757uf5Y6f5aeLSlNPTu+8iOWQq3RlYWNoZXJzL21hdHJpeO+8ieKGkiDotbDovazmjaIKICAgICAgICAgIHZhciBjb252ZXJ0ZWQgPSBjb252ZXJ0RnJvbVNjaGVkdWxlKGNmZyk7CiAgICAgICAgICBleGFtQ29uZmlnLmV4YW1JbmZvID0gY29udmVydGVkLmV4YW1JbmZvOwogICAgICAgICAgZXhhbUNvbmZpZy5zZXNzaW9ucyA9IGNvbnZlcnRlZC5zZXNzaW9uczsKICAgICAgICAgIHNyYyA9ICfmjpLnj63ns7vnu58nOwogICAgICAgIH0gZWxzZSBpZihjZmcuZXhhbUluZm8gJiYgY2ZnLnNlc3Npb25zKXsKICAgICAgICAgIC8vIOS4reaOp+WPsC/ml7bpkp/lpKflsY/oh6rlt7HnmoRKU09O5qC85byPCiAgICAgICAgICBleGFtQ29uZmlnLmV4YW1JbmZvID0gY2ZnLmV4YW1JbmZvOwogICAgICAgICAgZXhhbUNvbmZpZy5zZXNzaW9ucyA9IGNmZy5zZXNzaW9uczsKICAgICAgICAgIGlmKGNmZy50cmFja3MpIGV4YW1Db25maWcudHJhY2tzID0gY2ZnLnRyYWNrczsKICAgICAgICAgIGlmKGNmZy5lbmNvdXJhZ2VNc2dzKSBleGFtQ29uZmlnLmVuY291cmFnZU1zZ3MgPSBjZmcuZW5jb3VyYWdlTXNnczsKICAgICAgICAgIGlmKGNmZy5hbGVydHMpIGV4YW1Db25maWcuYWxlcnRzID0gY2ZnLmFsZXJ0czsKICAgICAgICAgIHNyYyA9ICfml7bpkp/lpKflsY/phY3nva4nOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBzaG93VG9hc3QoJ+aXoOazleivhuWIq+aWh+S7tuagvOW8jycsICdlcnInKTsKICAgICAgICAgIHJldHVybjsKICAgICAgICB9CiAgICAgICAgc2F2ZUFsbCgpOyByZW5kZXJBbGwoKTsgc3RhcnRBbGVydHMoKTsKICAgICAgICBzaG93VG9hc3QoJ+W3suS7jicrc3JjKyflr7zlhaUgJytleGFtQ29uZmlnLnNlc3Npb25zLmxlbmd0aCsnIOS4quWcuuasoScsICdvaycpOwogICAgICB9IGNhdGNoKGV4KXsgc2hvd1RvYXN0KCflr7zlhaXlpLHotKXvvJonK2V4Lm1lc3NhZ2UsICdlcnInKTsgfQogICAgfTsgZnIucmVhZEFzVGV4dChmKTsKICB9OyBpbnAuY2xpY2soKTsKfQpmdW5jdGlvbiBleHBvcnRDZmcoKXsKICB2YXIgYmxvYiA9IG5ldyBCbG9iKFtKU09OLnN0cmluZ2lmeShleGFtQ29uZmlnLG51bGwsMildLCB7dHlwZTonYXBwbGljYXRpb24vanNvbid9KTsKICB2YXIgdXJsID0gVVJMLmNyZWF0ZU9iamVjdFVSTChibG9iKSwgYSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2EnKTsKICBhLmhyZWY9dXJsOyBhLmRvd25sb2FkPSfogIPor5XphY3nva5fJytleGFtQ29uZmlnLmV4YW1JbmZvLmRhdGUrJy5qc29uJzsgYS5jbGljaygpOwogIFVSTC5yZXZva2VPYmplY3RVUkwodXJsKTsgc2hvd1RvYXN0KCfwn5OkIOW3suWvvOWHuicsJ29rJyk7Cn0KZnVuY3Rpb24gZWRpdEluZm8oKXsKICB2YXIgbmFtZSA9IHByb21wdCgn6ICD6K+V5ZCN56ew77yaJywgZXhhbUNvbmZpZy5leGFtSW5mby5uYW1lKTsKICBpZihuYW1lIT09bnVsbCkgZXhhbUNvbmZpZy5leGFtSW5mby5uYW1lID0gbmFtZTsKICB2YXIgZGF0ZSA9IHByb21wdCgn6ICD6K+V5pel5pyf77yaJywgZXhhbUNvbmZpZy5leGFtSW5mby5kYXRlKTsKICBpZihkYXRlIT09bnVsbCkgZXhhbUNvbmZpZy5leGFtSW5mby5kYXRlID0gZGF0ZTsKICBzYXZlQWxsKCk7IHJlbmRlckFsbCgpOyBzaG93VG9hc3QoJ+KchSDlt7Lkv53lrZgnLCdvaycpOwp9CmZ1bmN0aW9uIHJlc2V0VGltZXIoKXsgc3RhcnRBbGVydHMoKTsgc2hvd1RvYXN0KCfij7HvuI8g5o+Q6YaS6K6h5pe25Zmo5bey6YeN572uJywnb2snKTsgfQoKLyogVjUuMO+8muaXtumSn+minOiJsuWIh+aNoiAqLwpmdW5jdGlvbiBzZXRDbG9ja0NvbG9yKGNvbG9yKXsKICBjbG9ja0NvbG9yQ2xhc3MgPSAnYy0nICsgY29sb3I7CiAgdmFyIHRkID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3RpbWVEaXNwJyk7CiAgaWYodGQpewogICAgdGQuY2xhc3NOYW1lID0gdGQuY2xhc3NOYW1lLnJlcGxhY2UoL2MtXHcrL2csICcnKS50cmltKCkgKyAnICcgKyBjbG9ja0NvbG9yQ2xhc3M7CiAgfQogIC8qIOabtOaWsOS4ieiJsuaMiemSrumrmOS6riAqLwogIHZhciBkb3RzID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgnLmNvbG9yLWRvdCcpOwogIGRvdHMuZm9yRWFjaChmdW5jdGlvbihkKXsgZC5jbGFzc0xpc3QucmVtb3ZlKCdhY3RpdmUnKTsgfSk7CiAgdmFyIG1hcCA9IHtvcmFuZ2U6J2Mtb3JhbmdlLWRvdCcsIGJsYWNrOidjLWJsYWNrLWRvdCcsIGJsdWU6J2MtYmx1ZS1kb3QnfTsKICB2YXIgdGFyZ2V0ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignLicgKyBtYXBbY29sb3JdKTsKICBpZih0YXJnZXQpIHRhcmdldC5jbGFzc0xpc3QuYWRkKCdhY3RpdmUnKTsKICBsb2NhbFN0b3JhZ2Uuc2V0SXRlbSgnbG9iNUNsb2NrQ29sb3InLCBjb2xvcik7Cn0KCmZ1bmN0aW9uIHNhdmVBbGwoKXsgbG9jYWxTdG9yYWdlLnNldEl0ZW0oJ2xvYjQnLCBKU09OLnN0cmluZ2lmeShleGFtQ29uZmlnKSk7IH0KZnVuY3Rpb24gbG9hZEFsbCgpewogIHRyeSB7CiAgICB2YXIgcyA9IGxvY2FsU3RvcmFnZS5nZXRJdGVtKCdsb2I0Jyk7CiAgICBpZihzKXsgdmFyIGMgPSBKU09OLnBhcnNlKHMpOyBPYmplY3Qua2V5cyhjKS5mb3JFYWNoKGZ1bmN0aW9uKGspeyBleGFtQ29uZmlnW2tdPWNba107IH0pOyB9CiAgfSBjYXRjaChlKXt9Cn0KCi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KICAgVG9hc3QKICAgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSAqLwpmdW5jdGlvbiBzaG93VG9hc3QobXNnLCB0eXBlKXsKICB0eXBlID0gdHlwZXx8J29rJzsKICB2YXIgdCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd0b2FzdCcpOwogIHQudGV4dENvbnRlbnQgPSBtc2c7IHQuY2xhc3NOYW1lID0gJ3RvYXN0ICcrdHlwZSsnIHNob3cnOwogIHNldFRpbWVvdXQoZnVuY3Rpb24oKXsgdC5jbGFzc0xpc3QucmVtb3ZlKCdzaG93Jyk7IH0sIDI1MDApOwp9CgovKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CiAgIOWtl+S9kwogICA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09ICovCmZ1bmN0aW9uIGNoYW5nZUZvbnQodil7IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zdHlsZS5zZXRQcm9wZXJ0eSgnLS1mb250LW1vbm8nLCB2KTsgbG9jYWxTdG9yYWdlLnNldEl0ZW0oJ2xvYjRGb250Jywgdik7IH0KCi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KICAg5YWo5bGPCiAgID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0gKi8KLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CiAgIOWFqOWxj+aooeW8j++8iOa1j+iniOWZqOecn+WFqOWxj++8iQogICA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0gKi8KbGV0IHByZXZNb2RlQmVmb3JlRnVsbCA9ICcnOyAgLyog6K6w5b2V5YWo5bGP5YmN55qE5qih5byP77yM6YCA5Ye65pe25oGi5aSNICovCmZ1bmN0aW9uIGdvRnVsbCgpewogIGlmKCFkb2N1bWVudC5mdWxsc2NyZWVuRWxlbWVudCl7CiAgICAvKiDov5vlhaXlhajlsY/vvJrlhYjliIfliLDml7bpkp/mqKHlvI/vvIzkv53or4Hml7bpkp/mnIDlpKfljJYgKi8KICAgIHByZXZNb2RlQmVmb3JlRnVsbCA9IGxheW91dE1vZGU7CiAgICBzZXRNb2RlKCdjbG9jaycpOwogICAgLyog6K+35rGC5rWP6KeI5Zmo5YWo5bGPICovCiAgICB2YXIgZWwgPSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQ7CiAgICBpZihlbC5yZXF1ZXN0RnVsbHNjcmVlbikgZWwucmVxdWVzdEZ1bGxzY3JlZW4oKTsKICAgIGVsc2UgaWYoZWwud2Via2l0UmVxdWVzdEZ1bGxzY3JlZW4pIGVsLndlYmtpdFJlcXVlc3RGdWxsc2NyZWVuKCk7CiAgICBlbHNlIGlmKGVsLm1zUmVxdWVzdEZ1bGxzY3JlZW4pIGVsLm1zUmVxdWVzdEZ1bGxzY3JlZW4oKTsKICAgIGRvY3VtZW50LmJvZHkuY2xhc3NMaXN0LmFkZCgnZnVsbC1tb2RlJyk7CiAgICBzaG93VG9hc3QoJ/CflqUg5YWo5bGP5qih5byP5bey5byA5ZCv77yM5oyJRXNj5oiW54K55Y+z5LiK6KeS6YCA5Ye6Jywnb2snKTsKICB9IGVsc2UgewogICAgZXhpdEZ1bGwoKTsKICB9Cn0KZnVuY3Rpb24gZXhpdEZ1bGwoKXsKICBpZihkb2N1bWVudC5mdWxsc2NyZWVuRWxlbWVudCl7CiAgICBpZihkb2N1bWVudC5leGl0RnVsbHNjcmVlbikgZG9jdW1lbnQuZXhpdEZ1bGxzY3JlZW4oKTsKICAgIGVsc2UgaWYoZG9jdW1lbnQud2Via2l0RXhpdEZ1bGxzY3JlZW4pIGRvY3VtZW50LndlYmtpdEV4aXRGdWxsc2NyZWVuKCk7CiAgfQp9Ci8qIOebkeWQrOa1j+iniOWZqOWFqOWxj+eKtuaAgeWPmOWMlu+8mumAgOWHuuWFqOWxj+aXtuaBouWkjeWOn+aooeW8jyAqLwpkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdmdWxsc2NyZWVuY2hhbmdlJywgZnVuY3Rpb24oKXsKICBpZighZG9jdW1lbnQuZnVsbHNjcmVlbkVsZW1lbnQpewogICAgZG9jdW1lbnQuYm9keS5jbGFzc0xpc3QucmVtb3ZlKCdmdWxsLW1vZGUnKTsKICAgIC8qIOaBouWkjeWOn+aooeW8jyAqLwogICAgaWYocHJldk1vZGVCZWZvcmVGdWxsICYmIHByZXZNb2RlQmVmb3JlRnVsbCE9PSdjbG9jaycpewogICAgICBzZXRNb2RlKHByZXZNb2RlQmVmb3JlRnVsbCk7CiAgICB9CiAgICBwcmV2TW9kZUJlZm9yZUZ1bGwgPSAnJzsKICB9Cn0pOwpkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCd3ZWJraXRmdWxsc2NyZWVuY2hhbmdlJywgZnVuY3Rpb24oKXsKICBpZighZG9jdW1lbnQud2Via2l0RnVsbHNjcmVlbkVsZW1lbnQpewogICAgZG9jdW1lbnQuYm9keS5jbGFzc0xpc3QucmVtb3ZlKCdmdWxsLW1vZGUnKTsKICAgIGlmKHByZXZNb2RlQmVmb3JlRnVsbCAmJiBwcmV2TW9kZUJlZm9yZUZ1bGwhPT0nY2xvY2snKXsKICAgICAgc2V0TW9kZShwcmV2TW9kZUJlZm9yZUZ1bGwpOwogICAgfQogICAgcHJldk1vZGVCZWZvcmVGdWxsID0gJyc7CiAgfQp9KTsKCi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KICAg6I+c5Y2VCiAgID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0gKi8KZnVuY3Rpb24gdG9nZ2xlTW9yZSgpewogIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdtb3JlTWVudScpLmNsYXNzTGlzdC50b2dnbGUoJ3Nob3cnKTsKfQpkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIGZ1bmN0aW9uKGUpewogIHZhciBtID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ21vcmVNZW51Jyk7CiAgaWYobS5jbGFzc0xpc3QuY29udGFpbnMoJ3Nob3cnKSAmJiAhZS50YXJnZXQuY2xvc2VzdCgnLm1vcmUtd3JhcCcpKSBtLmNsYXNzTGlzdC5yZW1vdmUoJ3Nob3cnKTsKfSk7CgovKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CiAgIOWQr+WKqAogICA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09ICovCmluaXQoKTsKCi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KICAgVjUuMO+8muWTgeeJjOS9k+ezu+WQjOatpSAtIOmfs+aViCvnnLznkIPov73ouKor5bqV6YOo5byV5rWBCiAgID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0gKi8KLy8g6Z+z5pWI57O757ufCnZhciBBdWRpb0N0eDUgPSB3aW5kb3cuQXVkaW9Db250ZXh0IHx8IHdpbmRvdy53ZWJraXRBdWRpb0NvbnRleHQ7CnZhciBhdWRpb0N0eDUgPSBudWxsOwpmdW5jdGlvbiBwbGF5U2Z4KHR5cGUpewogIGlmKCFhdWRpb0N0eDUpeyB0cnkgeyBhdWRpb0N0eDUgPSBuZXcgQXVkaW9DdHg1KCk7IH0gY2F0Y2goZSl7IHJldHVybjsgfSB9CiAgdmFyIG9zYyA9IGF1ZGlvQ3R4NS5jcmVhdGVPc2NpbGxhdG9yKCksIGdhaW4gPSBhdWRpb0N0eDUuY3JlYXRlR2FpbigpOwogIG9zYy5jb25uZWN0KGdhaW4pOyBnYWluLmNvbm5lY3QoYXVkaW9DdHg1LmRlc3RpbmF0aW9uKTsKICB2YXIgbm93ID0gYXVkaW9DdHg1LmN1cnJlbnRUaW1lOwogIGlmKHR5cGU9PT0nY2xpY2snKXsgb3NjLmZyZXF1ZW5jeS5zZXRWYWx1ZUF0VGltZSg2MDAsbm93KTsgb3NjLmZyZXF1ZW5jeS5leHBvbmVudGlhbFJhbXBUb1ZhbHVlQXRUaW1lKDMwMCxub3crMC4wNCk7IGdhaW4uZ2Fpbi5zZXRWYWx1ZUF0VGltZSgwLjEsbm93KTsgZ2Fpbi5nYWluLmV4cG9uZW50aWFsUmFtcFRvVmFsdWVBdFRpbWUoMC4wMSxub3crMC4wNCk7IG9zYy5zdGFydChub3cpOyBvc2Muc3RvcChub3crMC4wNCk7IH0KICBlbHNlIGlmKHR5cGU9PT0nc3VjY2VzcycpeyBvc2MuZnJlcXVlbmN5LnNldFZhbHVlQXRUaW1lKDUyMyxub3cpOyBvc2MuZnJlcXVlbmN5LnNldFZhbHVlQXRUaW1lKDY1OSxub3crMC4wOCk7IG9zYy5mcmVxdWVuY3kuc2V0VmFsdWVBdFRpbWUoNzg0LG5vdyswLjE2KTsgZ2Fpbi5nYWluLnNldFZhbHVlQXRUaW1lKDAuMSxub3cpOyBnYWluLmdhaW4uZXhwb25lbnRpYWxSYW1wVG9WYWx1ZUF0VGltZSgwLjAxLG5vdyswLjI0KTsgb3NjLnN0YXJ0KG5vdyk7IG9zYy5zdG9wKG5vdyswLjI0KTsgfQogIGVsc2UgaWYodHlwZT09PSdlcnJvcicpeyBvc2MuZnJlcXVlbmN5LnNldFZhbHVlQXRUaW1lKDIwMCxub3cpOyBvc2MuZnJlcXVlbmN5LmV4cG9uZW50aWFsUmFtcFRvVmFsdWVBdFRpbWUoMTAwLG5vdyswLjE1KTsgZ2Fpbi5nYWluLnNldFZhbHVlQXRUaW1lKDAuMTIsbm93KTsgZ2Fpbi5nYWluLmV4cG9uZW50aWFsUmFtcFRvVmFsdWVBdFRpbWUoMC4wMSxub3crMC4xNSk7IG9zYy5zdGFydChub3cpOyBvc2Muc3RvcChub3crMC4xNSk7IH0KfQpkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIGZ1bmN0aW9uKGUpeyBpZihlLnRhcmdldC5jbG9zZXN0KCdidXR0b24nKSkgcGxheVNmeCgnY2xpY2snKTsgfSwgdHJ1ZSk7CgovLyDlk4HniYzpk77mjqUKZnVuY3Rpb24gb3BlbkJyYW5kTGluayh0eXBlKXsKICBwbGF5U2Z4KCdjbGljaycpOwogIGlmKHR5cGU9PT0nc2hvcCcpIHdpbmRvdy5vcGVuKCdodHRwczovL3Nob3AueGt3LmNvbS8xNTk4NTEnLCdfYmxhbmsnKTsKICBlbHNlIGlmKHR5cGU9PT0nd2VjaGF0Jykgc2hvd1RvYXN0KCfor7flvq7kv6HmkJzntKLlhazkvJflj7fjgIzpvpnomb7ogIHluIjjgI3lhbPms6gnLCdpbmZvJyk7Cn0KCi8vIExvZ2/nnLznkIPov73ouKoKKGZ1bmN0aW9uKCl7CiAgdmFyIEVZRV9MPXt4Oi0xNCx5Oi02Nn0sIEVZRV9SPXt4OjE0LHk6LTY2fSwgTUFYX1BVUElMPTMuODsKICB2YXIgbXg9LTk5OTksbXk9LTk5OTksbW91c2VPbj1mYWxzZTsKICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLGZ1bmN0aW9uKGUpe214PWUuY2xpZW50WDtteT1lLmNsaWVudFk7bW91c2VPbj10cnVlO30pOwogIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlbGVhdmUnLGZ1bmN0aW9uKCl7bW91c2VPbj1mYWxzZTt9KTsKICBmdW5jdGlvbiBjbGFtcFB1cGlsKGR4LGR5KXt2YXIgZD1NYXRoLnNxcnQoZHgqZHgrZHkqZHkpO2lmKGQ8MC4yKXJldHVybnt4OjAseTowfTt2YXIgcj1NYXRoLm1pbihkLE1BWF9QVVBJTCkvZDtyZXR1cm57eDpkeCpyLHk6ZHkqcn07fQogIGZ1bmN0aW9uIG1Qb3NJblN2ZyhzdmdFbCl7aWYoIW1vdXNlT24pcmV0dXJuIG51bGw7dmFyIHI9c3ZnRWwuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7aWYoci53aWR0aDwxKXJldHVybiBudWxsO3JldHVybnt4OihteC1yLmxlZnQpKjIwMC9yLndpZHRoLTEwMCx5OihteS1yLnRvcCkqMjAwL3IuaGVpZ2h0LTEwMH07fQogIHZhciB0cmFja2Vycz1bXTsKICBmdW5jdGlvbiByZWdUcmFja2VyKHN2Z0VsKXsKICAgIGlmKCFzdmdFbClyZXR1cm47dmFyIGNzPXN2Z0VsLmdldEVsZW1lbnRzQnlUYWdOYW1lKCdjaXJjbGUnKTt2YXIgcEw9bnVsbCxwUj1udWxsOwogICAgZm9yKHZhciBpPTA7aTxjcy5sZW5ndGg7aSsrKXtpZihjc1tpXS5nZXRBdHRyaWJ1dGUoJ2RhdGEtaWQnKT09PSdwdXBpbEwnKXBMPWNzW2ldO2lmKGNzW2ldLmdldEF0dHJpYnV0ZSgnZGF0YS1pZCcpPT09J3B1cGlsUicpcFI9Y3NbaV07aWYocEwmJnBSKWJyZWFrO30KICAgIGlmKCFwTHx8IXBSKXJldHVybjsKICAgIHRyYWNrZXJzLnB1c2goe3N2ZzpzdmdFbCxwTDpwTCxwUjpwUixjdXJMOnt4OkVZRV9MLngseTpFWUVfTC55fSxjdXJSOnt4OkVZRV9SLngseTpFWUVfUi55fX0pOwogIH0KICBmdW5jdGlvbiB0aWNrKCl7CiAgICB0cmFja2Vycy5mb3JFYWNoKGZ1bmN0aW9uKHQpewogICAgICB2YXIgbXA9bVBvc0luU3ZnKHQuc3ZnKTsKICAgICAgaWYobXApe3ZhciBkeEw9bXAueC1FWUVfTC54LGR5TD1tcC55LUVZRV9MLnksZHhSPW1wLngtRVlFX1IueCxkeVI9bXAueS1FWUVfUi55O3ZhciBwTD1jbGFtcFB1cGlsKGR4TCxkeUwpLHBSPWNsYW1wUHVwaWwoZHhSLGR5Uik7dC5jdXJMLngrPShwTC54LXQuY3VyTC54KSowLjE1O3QuY3VyTC55Kz0ocEwueS10LmN1ckwueSkqMC4xNTt0LmN1clIueCs9KHBSLngtdC5jdXJSLngpKjAuMTU7dC5jdXJSLnkrPShwUi55LXQuY3VyUi55KSowLjE1O30KICAgICAgZWxzZXt0LmN1ckwueCs9KDAtdC5jdXJMLngpKjAuMTt0LmN1ckwueSs9KDAtdC5jdXJMLnkpKjAuMTt0LmN1clIueCs9KDAtdC5jdXJSLngpKjAuMTt0LmN1clIueSs9KDAtdC5jdXJSLnkpKjAuMTt9CiAgICAgIHQucEwuc2V0QXR0cmlidXRlKCdjeCcsRVlFX0wueCt0LmN1ckwueCk7dC5wTC5zZXRBdHRyaWJ1dGUoJ2N5JyxFWUVfTC55K3QuY3VyTC55KTt0LnBSLnNldEF0dHJpYnV0ZSgnY3gnLEVZRV9SLngrdC5jdXJSLngpO3QucFIuc2V0QXR0cmlidXRlKCdjeScsRVlFX1IueSt0LmN1clIueSk7CiAgICB9KTsKICAgIHJlcXVlc3RBbmltYXRpb25GcmFtZSh0aWNrKTsKICB9CiAgdmFyIG5hdlN2Zz1kb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnbmF2TG9nb1N2ZycpOwogIGlmKG5hdlN2Zyl7cmVnVHJhY2tlcihuYXZTdmcpO3JlcXVlc3RBbmltYXRpb25GcmFtZSh0aWNrKTt9Cn0pKCk7Cjwvc2NyaXB0PgoKPCEtLSBWNS4w77ya5bqV6YOo5byV5rWB5p2hIC0tPgo8ZGl2IGNsYXNzPSJib3R0b20tYmFyLXY1Ij4KICA8ZGl2IGNsYXNzPSJiYi1sZWZ0Ij4KICAgIDxzcGFuIGNsYXNzPSJiYi12ZXIiPlY2LjA8L3NwYW4+CiAgICA8c3BhbiBjbGFzcz0iYmItYXV0aG9yIj7pvpnomb7ogIHluIggLSDpmLLln47muK/luILnrKzkuozkuK3lraYgwrcg6auY5b2m5p6tPC9zcGFuPgogICAgPHNwYW4gY2xhc3M9ImJiLXNsb2dhbiI+QUnotYvog73mlZnogrIgwrcg6K6p5q+P5L2N6ICB5biI6YO96IO96L275p2+5Yi25L2c5LiT5Lia5bel5YW3PC9zcGFuPgogIDwvZGl2PgogIDxkaXYgY2xhc3M9ImJiLXJpZ2h0Ij4KICAgIDxzcGFuIGNsYXNzPSJiYi1waWxsIiBvbmNsaWNrPSJzaG93VG9hc3QoJ+m+meiZvuaVmeeglOezu+WIl+W3peWFtycsJ2luZm8nKSI+6b6Z6Jm+5pWZ56CUPC9zcGFuPgogICAgPHNwYW4gY2xhc3M9ImJiLXBpbGwgYWN0aXZlIiBvbmNsaWNrPSJzaG93VG9hc3QoJ+W9k+WJjeW3peWFt++8muePree6p+aXtumSn+Wkp+WxjycsJ2luZm8nKSI+6b6Z6Jm+5pWZ5YqhPC9zcGFuPgogICAgPHNwYW4gY2xhc3M9ImJiLXBpbGwiIG9uY2xpY2s9InNob3dUb2FzdCgn6b6Z6Jm+5pWZ5a2m57O75YiX5bel5YW3JywnaW5mbycpIj7pvpnomb7mlZnlraY8L3NwYW4+CiAgICA8c3BhbiBjbGFzcz0iYmItcGlsbCIgb25jbGljaz0ic2hvd1RvYXN0KCfpvpnomb7nj63kuLvku7vns7vliJflt6XlhbcnLCdpbmZvJykiPum+meiZvuePreS4u+S7uzwvc3Bhbj4KICAgIDxzcGFuIGNsYXNzPSJiYi1zZXAiPjwvc3Bhbj4KICAgIDxidXR0b24gY2xhc3M9ImJiLWJ0biIgb25jbGljaz0ib3BlbkJyYW5kTGluaygnd2VjaGF0JykiPuWFrOS8l+WPt+OAjOm+meiZvuiAgeW4iOOAjTwvYnV0dG9uPgogICAgPGJ1dHRvbiBjbGFzcz0iYmItYnRuIiBvbmNsaWNrPSJvcGVuQnJhbmRMaW5rKCdzaG9wJykiPvCfm5Ig5a2m56eR572R44CM5bGx5rW36L6555+l6K+G5Z2K44CNPC9idXR0b24+CiAgPC9kaXY+CjwvZGl2PgoKPHN0eWxlPgouYm90dG9tLWJhci12NXtwb3NpdGlvbjpmaXhlZDtib3R0b206MDtsZWZ0OjA7cmlnaHQ6MDt6LWluZGV4OjEwMDtiYWNrZ3JvdW5kOnJnYmEoMjU1LDI1NSwyNTUsMC45Mik7YmFja2Ryb3AtZmlsdGVyOmJsdXIoMjBweCk7Ym9yZGVyLXRvcDoxcHggc29saWQgdmFyKC0tYm9yZGVyKTtwYWRkaW5nOjAuMzVyZW0gMXJlbTtkaXNwbGF5OmZsZXg7YWxpZ24taXRlbXM6Y2VudGVyO2p1c3RpZnktY29udGVudDpzcGFjZS1iZXR3ZWVuO2ZvbnQtc2l6ZTowLjY4cmVtO30KYm9keS5kYXJrIC5ib3R0b20tYmFyLXY1e2JhY2tncm91bmQ6cmdiYSgyMCwyMCwyNCwwLjk2KTt9Ci5iYi1sZWZ0e2Rpc3BsYXk6ZmxleDthbGlnbi1pdGVtczpjZW50ZXI7Z2FwOjAuNXJlbTt9Ci5iYi12ZXJ7Y29sb3I6dmFyKC0tcHJpbWFyeSk7Zm9udC13ZWlnaHQ6ODAwO30KLmJiLWF1dGhvcntjb2xvcjp2YXIoLS10ZXh0LXNlYyk7Zm9udC13ZWlnaHQ6NjAwO30KLmJiLXNsb2dhbntjb2xvcjp2YXIoLS10ZXh0LXN1Yik7fQouYmItcmlnaHR7ZGlzcGxheTpmbGV4O2FsaWduLWl0ZW1zOmNlbnRlcjtnYXA6MC4zNXJlbTt9Ci5iYi1waWxse2ZvbnQtd2VpZ2h0OjcwMDtwYWRkaW5nOjAuMTVyZW0gMC41cmVtO2JvcmRlci1yYWRpdXM6MTAwcHg7YmFja2dyb3VuZDp2YXIoLS13YXJtLWdyYXkpO2NvbG9yOnZhcigtLXRleHQtc3ViKTtjdXJzb3I6cG9pbnRlcjt0cmFuc2l0aW9uOmFsbCAwLjE1cztib3JkZXI6MXB4IHNvbGlkIHRyYW5zcGFyZW50O30KLmJiLXBpbGw6aG92ZXJ7YmFja2dyb3VuZDp2YXIoLS1wcmltYXJ5LWJnMik7Y29sb3I6dmFyKC0tcHJpbWFyeSk7Ym9yZGVyLWNvbG9yOnZhcigtLXByaW1hcnkpO3RyYW5zZm9ybTp0cmFuc2xhdGVZKC0xcHgpO30KLmJiLXBpbGwuYWN0aXZle2JhY2tncm91bmQ6dmFyKC0tcHJpbWFyeSk7Y29sb3I6I2ZmZjtib3JkZXItY29sb3I6dmFyKC0tcHJpbWFyeSk7fQouYmItc2Vwe3dpZHRoOjFweDtoZWlnaHQ6MTRweDtiYWNrZ3JvdW5kOnZhcigtLWJvcmRlcik7bWFyZ2luOjAgMC4zcmVtO30KLmJiLWJ0bntmb250LXNpemU6MC42OHJlbTtwYWRkaW5nOjAuMnJlbSAwLjVyZW07Ym9yZGVyLXJhZGl1czo2cHg7Ym9yZGVyOjFweCBzb2xpZCB2YXIoLS1ib3JkZXIpO2JhY2tncm91bmQ6dmFyKC0tYmctY2FyZCk7Y29sb3I6dmFyKC0tdGV4dC1zZWMpO2N1cnNvcjpwb2ludGVyO2ZvbnQtZmFtaWx5OmluaGVyaXQ7dHJhbnNpdGlvbjphbGwgMC4xNXM7fQouYmItYnRuOmhvdmVye2JvcmRlci1jb2xvcjp2YXIoLS1wcmltYXJ5KTtjb2xvcjp2YXIoLS1wcmltYXJ5KTtiYWNrZ3JvdW5kOnZhcigtLXByaW1hcnktYmcyKTt9Cjwvc3R5bGU+Cgo8YnV0dG9uIGNsYXNzPSJleGl0LWZ1bGwiIGlkPSJleGl0RnVsbEJ0biIgb25jbGljaz0iZXhpdEZ1bGwoKSIgdGl0bGU9IumAgOWHuuWFqOWxjyI+4pu2PC9idXR0b24+CjwvYm9keT4KPC9odG1sPgo='; var _clockRoomData = []; // 缓存时钟数据供弹窗使用 function exportClassClocks(){ document.getElementById('exportDropdownMenu').classList.remove('show'); // 收集每个考场的数据 _clockRoomData = []; rooms.forEach(function(rm, ri){ var exams = []; sessions.forEach(function(ses, si){ var teachersHere = (matrix[si] && matrix[si][ri]) || []; if(teachersHere.length === 0 || (teachersHere.length === 1 && teachersHere[0] === '×')) return; var normalizedTime = ses.time.replace(/:/g,':').replace(/~/g,'~'); var timeMatch = normalizedTime.match(/(\d+:\d+)~(\d+:\d+)/); var dateMatch = ses.date.match(/(\d+)月(\d+)日/); var weekMatch = ses.date.match(/((周.))/); exams.push({ date: ses.date, dateShort: dateMatch ? dateMatch[1]+'/'+dateMatch[2] : ses.date, week: weekMatch ? weekMatch[1] : '', period: ses.period, startTime: timeMatch ? timeMatch[1] : '', endTime: timeMatch ? timeMatch[2] : '', subject: ses.subject, teachers: teachersHere.filter(function(t){ return t && t !== '×'; }) }); }); if(exams.length > 0){ _clockRoomData.push({ room: rm, exams: exams }); } }); if(_clockRoomData.length === 0){ showToast('没有排班数据,请先完成排班', 'warn'); return; } // 弹出考场选择弹窗 var list = document.getElementById('clockSelectList'); var html = ''; _clockRoomData.forEach(function(rd, idx){ html += ''; }); list.innerHTML = html; document.getElementById('clockSelectOv').classList.add('show'); } function clockSelectAll(on){ var cbs = document.querySelectorAll('.clock-cb'); for(var i=0;i|]/g,'_') + '.html'; a.click(); URL.revokeObjectURL(a.href); count++; if(count === selected.length){ showToast('已导出 ' + count + ' 个班级时钟成品', 'ok'); } }, seq * 300); }); } function generateClockFromTemplate(rd){ // 解码V6.0模板 var tpl = decodeURIComponent(escape(atob(V6_TEMPLATE_B64))); // 构建examConfig var year = new Date().getFullYear().toString(); var firstDate = rd.exams[0] ? rd.exams[0].date : ''; var dm = firstDate.match(/(\d+)月(\d+)日/); var isoDate = dm ? year+'-'+('0'+dm[1]).slice(-2)+'-'+('0'+dm[2]).slice(-2) : ''; var sessions = []; rd.exams.forEach(function(exam, i){ sessions.push({ id: i+1, name: exam.period+'场', date: exam.isoDate || isoDate, status: i===0 ? 'current' : 'upcoming', subjects: [{ subject: exam.subject, start: exam.startTime, end: exam.endTime, teacher: exam.teachers.join('、'), chief: exam.chief || '', collector: exam.collector || '', hasListening: exam.subject.indexOf('英语')!==-1, papers: '', sheets: '' }] }); }); var cfg = { examInfo: { name: rd.room+' 考试时钟', date: firstDate, isoDate: isoDate, grade: '', school: '防城港市第二中学' }, sessions: sessions, encourageMsgs: ['认真复习','保持安静','诚信考试','加油同学们'], tracks: [], alerts: {entry:15, remain:15, collect:5} }; // 注入数据:替换const examConfig = {...}; var cfgJson = JSON.stringify(cfg); tpl = tpl.replace(/const examConfig\s*=\s*\{[^;]*?\};/s, 'const examConfig = '+cfgJson+';'); // 改标题 tpl = tpl.replace('🦞 龙虾教务台 · 班级时钟大屏 V6.0', '🦞 班级时钟 - '+rd.room+''); // 默认暖色+时钟模式 tpl = tpl.replace("applyTheme(localStorage.getItem('lob4Theme')||'light');", "applyTheme('warm');"); tpl = tpl.replace("setLayout(cs ? 'info' : ns ? 'waiting' : 'info');", "setLayout('clock');"); // 跳过localStorage加载 tpl = tpl.replace( "function loadAll(){\n try {\n var s = localStorage.getItem('lob4');", "function loadAll(){\n if(true) return;\n try {\n var s = localStorage.getItem('lob4');" ); return tpl; } function generateClockHTML(rd){ var examDataJSON = JSON.stringify(rd.exams); var roomName = rd.room.replace(/"/g, '"'); return '\n\ \n\ \n\ \n\ \n\ 班级时钟 - ' + roomName + '\n\ \n\ \n\ \n\
\n\
🏫 ' + roomName + '
\n\
\n\
运行中
\n\
--:--:--
\n\
----年--月--日
\n\
\n\
📋 考试安排
\n\
\n\
\n\ \n\
🦞 龙虾老师 · aiedge.top
\n\ '; } /* ================================================================== */ /* 导出时钟数据(模式2) */ /* ================================================================== */ function exportClockData(){ document.getElementById('exportDropdownMenu').classList.remove('show'); var headers = ['考试日期','星期','午别','考试开始时间','考试结束时间','考试科目','考试年级','考场编号','主监考员','副监考员']; var rows = []; rows.push(headers.join(',')); sessions.forEach(function(ses, si){ var dateMatch = ses.date.match(/(\d+)月(\d+)日/); var examDate = dateMatch ? new Date().getFullYear() + '年' + dateMatch[1] + '月' + dateMatch[2] + '日' : ses.date; var weekMatch = ses.date.match(/((周.))/); var week = weekMatch ? weekMatch[1] : ''; var normalizedTime = ses.time.replace(/:/g,':').replace(/~/g,'~'); var timeMatch = normalizedTime.match(/(\d+:\d+)~(\d+:\d+)/); var startTime = timeMatch ? timeMatch[1] : ''; var endTime = timeMatch ? timeMatch[2] : ''; var grade = '七年级'; if(ses.subject.indexOf('八年级') !== -1 || (ses.subject.indexOf('物理') !== -1 && ses.period === '下午')){ grade = '八年级'; } rooms.forEach(function(rm, ri){ var teachersHere = matrix[si][ri] || []; if(teachersHere.length === 0 || (teachersHere.length === 1 && teachersHere[0] === '×')) return; var mainTeacher = teachersHere[0] || ''; var viceTeacher = teachersHere[1] || ''; var row = [ examDate, week, ses.period, startTime, endTime, ses.subject, grade, rm, mainTeacher, viceTeacher ]; rows.push(row.map(function(c){ return '"' + String(c).replace(/"/g,'""') + '"'; }).join(',')); }); }); var csvContent = '\uFEFF' + rows.join('\n'); var blob = new Blob([csvContent], {type:'text/csv;charset=utf-8'}); var a = document.createElement('a'); a.href = URL.createObjectURL(blob); a.download = '考场时钟导入文件.csv'; a.click(); showToast('时钟数据已导出', 'ok'); } /* ================================================================== */ /* 导出数据配置(JSON/CSV双格式) */ /* ================================================================== */ function exportDataConfig(){ document.getElementById('exportDropdownMenu').classList.remove('show'); // 显示格式选择弹窗 var overlay = document.createElement('div'); overlay.className = 'overlay show'; overlay.id = 'dataFormatOverlay'; overlay.innerHTML = ''; document.body.appendChild(overlay); } function exportDataAsJSON(){ document.getElementById('dataFormatOverlay').remove(); exportToConsole(); } function exportDataAsCSV(){ document.getElementById('dataFormatOverlay').remove(); exportClockData(); } /* ================================================================== */ /* 重置 */ /* ================================================================== */ function resetAll(){ // 用内联二次确认条替代confirm弹窗 var bar = document.getElementById('batchSetNeedBar'); bar.innerHTML = '确认重置所有数据?此操作不可恢复!' + '' + ''; bar.classList.add('show'); } function confirmResetAll(){ teachers = JSON.parse(JSON.stringify(defaultTeachers)); sessions = JSON.parse(JSON.stringify(defaultSessions)); rooms = JSON.parse(JSON.stringify(defaultRooms)); cellCap = 2; matrix = {}; roleChief = sessions.map(function(){ return []; }); roleXs = sessions.map(function(){ return []; }); sessions.forEach(function(ses, si){ matrix[si] = {}; rooms.forEach(function(rm, ri){ matrix[si][ri] = []; }); }); versions = []; currentVersionId = null; selectedTeacherIdx = {}; hideBatchSetNeed(); renderTeachers(); renderSchedule(); renderRoleAssigned(); showToast('已重置', 'ok'); } /* ================================================================== */ /* 本地存储 */ /* ================================================================== */ function saveToLocal(){ try { localStorage.setItem('examSchedule_v2', JSON.stringify({ teachers: teachers, sessions: sessions, rooms: rooms, matrix: matrix, roleChief: roleChief, roleXs: roleXs, cellCap: cellCap, versions: versions, currentVersionId: currentVersionId })); } catch(e){} } function loadFromLocal(){ try { var data = JSON.parse(localStorage.getItem('examSchedule_v2')); if(data){ teachers = data.teachers || teachers; sessions = data.sessions || sessions; rooms = data.rooms || rooms; matrix = data.matrix || matrix; roleChief = data.roleChief || sessions.map(function(){return [];}); roleXs = data.roleXs || sessions.map(function(){return [];}); cellCap = data.cellCap || 2; versions = data.versions || []; currentVersionId = data.currentVersionId || null; } } catch(e){} } /* ================================================================== */ /* 初始化 */ /* ================================================================== */ loadFromLocal(); renderTeachers(); renderSchedule(); renderRoleAssigned(); // V2.0.9:teacher-tag删除按钮(通过canvasWrap事件委托) document.getElementById('canvasWrap').addEventListener('click', function(e){ var removeBtn = e.target.closest('.remove-btn'); if(!removeBtn) return; var tag = removeBtn.closest('.teacher-tag'); if(!tag) return; var si = parseInt(tag.getAttribute('data-session')); var ri = parseInt(tag.getAttribute('data-room')); var tname = tag.getAttribute('data-tname'); var idx = (matrix[si][ri] || []).indexOf(tname); if(idx !== -1){ matrix[si][ri].splice(idx, 1); renderSchedule(); renderTeachers(); showToast('已移除 ' + tname, 'ok'); } }); // V2.1.1:点击空白处立即退出编辑模式(blur 所有 contenteditable) document.addEventListener('mousedown', function(e){ var active = document.activeElement; if(!active) return; // 如果当前焦点在 contenteditable 或 input 上,且点击的是空白区域 if((active.getAttribute('contenteditable') === 'true' || active.tagName === 'INPUT' || active.tagName === 'TEXTAREA') && !e.target.closest('.ses-edit') && !e.target.closest('.room-edit-input') && !e.target.closest('input') && !e.target.closest('textarea') && !e.target.closest('[contenteditable]') && !e.target.closest('.cell-editor') && !e.target.closest('.popup') && !e.target.closest('.overlay') && !e.target.closest('.inline-input-bar') && !e.target.closest('#versionNameBar')){ active.blur(); } }); setInterval(function(){ saveToLocal(); // V3.0:更新自动保存指示 var el = document.getElementById('autoSaveIndicator'); if(el){ var now = new Date(); var h = String(now.getHours()).padStart(2,'0'); var m = String(now.getMinutes()).padStart(2,'0'); el.textContent = '已自动保存 ' + h + ':' + m; } }, 30000); /* ================================================================== */ /* V3.0:键盘快捷键系统 */ /* ================================================================== */ document.addEventListener('keydown', function(e){ // 在输入框/编辑态中只处理 Esc var activeEl = document.activeElement; var inInput = activeEl && (activeEl.tagName === 'INPUT' || activeEl.tagName === 'TEXTAREA' || activeEl.getAttribute('contenteditable') === 'true'); // Esc:取消编辑/关闭弹窗/关闭内联确认条 if(e.key === 'Escape'){ if(inInput){ // 编辑中 Esc 由 startEdit 的 onkeydown 处理,这里不重复 return; } // 关闭打开的弹窗(按优先级) var overlays = document.querySelectorAll('.overlay.show'); if(overlays.length > 0){ overlays[overlays.length - 1].classList.remove('show'); e.preventDefault(); return; } // 关闭版本命名条 var vbar = document.getElementById('versionNameBar'); if(vbar.style.display === 'flex'){ vbar.style.display = 'none'; e.preventDefault(); return; } // 关闭内联确认条 var inlineBars = document.querySelectorAll('.inline-input-bar.show'); if(inlineBars.length > 0){ inlineBars[inlineBars.length - 1].classList.remove('show'); e.preventDefault(); return; } return; } // 以下快捷键在输入框中不触发 if(inInput) return; var ctrl = e.ctrlKey || e.metaKey; // Ctrl+S:保存版本 if(ctrl && e.key === 's'){ e.preventDefault(); showVersionNameInput(); return; } // Ctrl+F:聚焦搜索框 if(ctrl && e.key === 'f'){ e.preventDefault(); var searchInput = document.getElementById('teacherSearch'); if(searchInput){ searchInput.focus(); searchInput.select(); } return; } // Ctrl+0:重置画板视图到100% if(ctrl && e.key === '0'){ e.preventDefault(); if(typeof canvasFitWidth === 'function'){ // 先重置缩放到100% var inner = document.getElementById('canvasInner'); if(inner){ inner.style.transform = 'scale(1)'; var zv = document.getElementById('canvasZoomVal'); if(zv) zv.textContent = '100%'; } } return; } }); // V3.0:首次访问快捷键引导 (function(){ var shown = localStorage.getItem('shortcutHintShown'); if(!shown){ setTimeout(function(){ showToast('支持快捷键:Ctrl+S保存 · Ctrl+F搜索 · Esc取消', 'info'); }, 1500); localStorage.setItem('shortcutHintShown', '1'); } })(); /* ================================================================== */ /* V3.0:音效系统 (Web Audio API) + 品牌链接 + 眼球追踪 */ /* ================================================================== */ // 音效系统 var AudioCtx = window.AudioContext || window.webkitAudioContext; var audioCtx = null; var soundEnabled = true; function initAudio(){ if(!audioCtx){ try { audioCtx = new AudioCtx(); } catch(e){ soundEnabled = false; } } } function playSfx(type){ if(!soundEnabled) return; initAudio(); if(!audioCtx) return; var osc = audioCtx.createOscillator(); var gain = audioCtx.createGain(); osc.connect(gain); gain.connect(audioCtx.destination); var now = audioCtx.currentTime; switch(type){ case 'click': osc.frequency.setValueAtTime(600, now); osc.frequency.exponentialRampToValueAtTime(300, now + 0.04); gain.gain.setValueAtTime(0.12, now); gain.gain.exponentialRampToValueAtTime(0.01, now + 0.04); osc.start(now); osc.stop(now + 0.04); break; case 'drag': osc.frequency.setValueAtTime(400, now); osc.frequency.exponentialRampToValueAtTime(800, now + 0.08); gain.gain.setValueAtTime(0.1, now); gain.gain.exponentialRampToValueAtTime(0.01, now + 0.08); osc.start(now); osc.stop(now + 0.08); break; case 'drop': osc.frequency.setValueAtTime(800, now); osc.frequency.exponentialRampToValueAtTime(1200, now + 0.06); gain.gain.setValueAtTime(0.15, now); gain.gain.exponentialRampToValueAtTime(0.01, now + 0.1); osc.start(now); osc.stop(now + 0.1); break; case 'success': osc.frequency.setValueAtTime(523, now); osc.frequency.setValueAtTime(659, now + 0.08); osc.frequency.setValueAtTime(784, now + 0.16); gain.gain.setValueAtTime(0.12, now); gain.gain.exponentialRampToValueAtTime(0.01, now + 0.24); osc.start(now); osc.stop(now + 0.24); break; case 'error': osc.frequency.setValueAtTime(200, now); osc.frequency.exponentialRampToValueAtTime(100, now + 0.15); gain.gain.setValueAtTime(0.15, now); gain.gain.exponentialRampToValueAtTime(0.01, now + 0.15); osc.start(now); osc.stop(now + 0.15); break; } } // 全局按钮点击音效 document.addEventListener('click', function(e){ if(e.target.closest('button') && !e.target.closest('.teacher-item')){ playSfx('click'); } }, true); // 品牌链接 function openBrandLink(type){ playSfx('click'); if(type === 'shop'){ window.open('https://shop.xkw.com/159851', '_blank'); } else if(type === 'wechat'){ showToast('请微信搜索公众号「龙虾老师」关注', 'info'); } } // Logo眼球追踪系统 (function(){ var EYE_L = {x:-14, y:-66}, EYE_R = {x:14, y:-66}; var MAX_PUPIL = 3.8; var mx = -9999, my = -9999, mouseOn = false; document.addEventListener('mousemove', function(e){ mx = e.clientX; my = e.clientY; mouseOn = true; }); document.addEventListener('mouseleave', function(){ mouseOn = false; }); function clampPupil(dx, dy){ var d = Math.sqrt(dx*dx + dy*dy); if(d < 0.2) return {x:0, y:0}; var r = Math.min(d, MAX_PUPIL) / d; return {x:dx*r, y:dy*r}; } function mPosInSvg(svgEl){ if(!mouseOn) return null; var r = svgEl.getBoundingClientRect(); if(r.width < 1 || r.height < 1) return null; return {x:(mx - r.left) * 200 / r.width - 100, y:(my - r.top) * 200 / r.height - 100}; } var trackers = []; function regTracker(svgEl){ if(!svgEl) return; var circles = svgEl.getElementsByTagNameNS ? svgEl.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'circle') : svgEl.getElementsByTagName('circle'); var pL = null, pR = null; for(var i = 0; i < circles.length; i++){ var c = circles[i]; if(c.getAttribute('data-id') === 'pupilL') pL = c; if(c.getAttribute('data-id') === 'pupilR') pR = c; if(pL && pR) break; } if(!pL || !pR) return; trackers.push({svg:svgEl, pL:pL, pR:pR, curL:{x:EYE_L.x, y:EYE_L.y}, curR:{x:EYE_R.x, y:EYE_R.y}}); } function tick(){ trackers.forEach(function(t){ var mp = mPosInSvg(t.svg); if(mp){ var dxL = mp.x - EYE_L.x, dyL = mp.y - EYE_L.y; var dxR = mp.x - EYE_R.x, dyR = mp.y - EYE_R.y; var pL = clampPupil(dxL, dyL); var pR = clampPupil(dxR, dyR); t.curL.x += (pL.x - t.curL.x) * 0.15; t.curL.y += (pL.y - t.curL.y) * 0.15; t.curR.x += (pR.x - t.curR.x) * 0.15; t.curR.y += (pR.y - t.curR.y) * 0.15; t.pL.setAttribute('cx', EYE_L.x + t.curL.x); t.pL.setAttribute('cy', EYE_L.y + t.curL.y); t.pR.setAttribute('cx', EYE_R.x + t.curR.x); t.pR.setAttribute('cy', EYE_R.y + t.curR.y); } else { t.curL.x += (0 - t.curL.x) * 0.1; t.curL.y += (0 - t.curL.y) * 0.1; t.curR.x += (0 - t.curR.x) * 0.1; t.curR.y += (0 - t.curR.y) * 0.1; t.pL.setAttribute('cx', EYE_L.x + t.curL.x); t.pL.setAttribute('cy', EYE_L.y + t.curL.y); t.pR.setAttribute('cx', EYE_R.x + t.curR.x); t.pR.setAttribute('cy', EYE_R.y + t.curR.y); } }); requestAnimationFrame(tick); } function initEyeTracker(){ var navSvg = document.getElementById('navLogoSvg'); if(navSvg) regTracker(navSvg); requestAnimationFrame(tick); } if(document.readyState === 'loading'){ document.addEventListener('DOMContentLoaded', initEyeTracker); } else { initEyeTracker(); } })(); /* ================================================================== */ /* V2.0.9:拖拽禁搜 + 画板缩放/平移 */ /* ================================================================== */ // 全局 dragstart 拦截 document.addEventListener('dragstart', function(e){ if(!e.target.closest('.teacher-item') && !e.target.closest('[draggable="true"]')){ e.preventDefault(); return false; } document.body.classList.add('suppress-selection'); }, true); // dragend 恢复 document.addEventListener('dragend', function(e){ document.body.classList.remove('suppress-selection'); }, true); // dragover 全局 preventDefault document.addEventListener('dragover', function(e){ e.preventDefault(); }, true); // drop 全局清理(不阻止冒泡) document.addEventListener('drop', function(e){ document.body.classList.remove('suppress-selection'); }, true); // 拖拽时禁止文字选中(CSS层) var styleEl = document.createElement('style'); styleEl.textContent = [ 'body.suppress-selection, body.suppress-selection *{', ' user-select:none !important;', ' -webkit-user-select:none !important;', ' -moz-user-select:none !important;', ' -ms-user-select:none !important;', '}', 'body.suppress-selection *{cursor:default !important;}', '.teacher-item{cursor:grab !important;}', '.teacher-item:active{cursor:grabbing !important;}', 'img, a{-webkit-user-drag:none !important;user-drag:none !important;}', '.cell-drop, .role-assigned{pointer-events:auto !important;}' ].join(''); document.head.appendChild(styleEl); /* ================================================================== */ /* V2.0.9:画板缩放 + 拖动平移 */ /* ================================================================== */ var canvasState = { scale: 1.0, tx: 0, ty: 0, dragging: false, startX: 0, startY: 0, startTx: 0, startTy: 0 }; function canvasApplyTransform(){ var inner = document.getElementById('canvasInner'); if(!inner) return; inner.style.transform = 'translate(' + canvasState.tx + 'px,' + canvasState.ty + 'px) scale(' + canvasState.scale + ')'; var el = document.getElementById('canvasZoomVal'); if(el) el.textContent = Math.round(canvasState.scale * 100) + '%'; } function canvasZoom(delta){ var oldScale = canvasState.scale; canvasState.scale = Math.max(0.2, Math.min(3.0, canvasState.scale + delta)); canvasApplyTransform(); } function canvasFitWidth(){ var wrap = document.getElementById('canvasWrap'); var inner = document.getElementById('canvasInner'); if(!wrap || !inner) return; var table = inner.querySelector('.schedule-table'); if(!table) return; var wrapW = wrap.clientWidth - 4; var tableW = table.scrollWidth; if(tableW > 0){ canvasState.scale = Math.min(1.0, Math.max(0.2, (wrapW - 10) / tableW)); canvasState.tx = 0; canvasState.ty = 0; canvasApplyTransform(); } } // 初始化:绑定事件 (function(){ var wrap = document.getElementById('canvasWrap'); var inner = document.getElementById('canvasInner'); if(!wrap || !inner) return; // 滚轮缩放(围绕鼠标位置) wrap.addEventListener('wheel', function(e){ e.preventDefault(); var rect = wrap.getBoundingClientRect(); var mx = e.clientX - rect.left; var my = e.clientY - rect.top; var oldScale = canvasState.scale; var delta = e.deltaY < 0 ? 0.08 : -0.08; var newScale = Math.max(0.15, Math.min(3.5, oldScale + delta)); // 围绕鼠标位置缩放:调整平移量使鼠标下内容点不动 canvasState.tx = mx - (mx - canvasState.tx) * (newScale / oldScale); canvasState.ty = my - (my - canvasState.ty) * (newScale / oldScale); canvasState.scale = newScale; canvasApplyTransform(); }, {passive:false}); // 鼠标拖动平移(右键或左键均可) wrap.addEventListener('mousedown', function(e){ // 左键拖动平移 if(e.button === 0 && !e.target.closest('.teacher-item') && !e.target.closest('.cell-close-x') && !e.target.closest('.remove-btn') && !e.target.closest('.edit-icon')){ canvasState.dragging = true; canvasState.startX = e.clientX; canvasState.startY = e.clientY; canvasState.startTx = canvasState.tx; canvasState.startTy = canvasState.ty; inner.classList.add('dragging-canvas'); e.preventDefault(); } }); document.addEventListener('mousemove', function(e){ if(!canvasState.dragging) return; canvasState.tx = canvasState.startTx + (e.clientX - canvasState.startX); canvasState.ty = canvasState.startTy + (e.clientY - canvasState.startY); canvasApplyTransform(); }); document.addEventListener('mouseup', function(){ if(canvasState.dragging){ canvasState.dragging = false; inner.classList.remove('dragging-canvas'); } }); // 初始适配:等渲染完成后自动适配宽度 setTimeout(canvasFitWidth, 200); })(); /* ================================================================== */ /* V4.0:引导页 + 示例模式 */ /* ================================================================== */ // 引导页Logo SVG var LANDING_LOGO_SVG = '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '龙虾老师' + 'LONG XIA LAO SHI' + ''; // 注入引导页Logo function initLandingPage(){ var logoContainer = document.getElementById('landingLogo'); if(logoContainer && !logoContainer.hasChildNodes()){ var div = document.createElement('div'); div.innerHTML = LANDING_LOGO_SVG; var svg = div.querySelector('svg'); if(svg){ svg.style.width = '100%'; svg.style.height = '100%'; svg.style.color = '#1A1A1A'; logoContainer.appendChild(svg); // 眼球追踪 initLandingEyeTracking(svg); } } // 滚动动画 var observer = new IntersectionObserver(function(entries){ entries.forEach(function(entry){ if(entry.isIntersecting) entry.target.classList.add('visible'); }); }, {threshold: 0.2}); document.querySelectorAll('.landing-feature-card, .landing-step').forEach(function(el){ observer.observe(el); }); } // 引导页眼球追踪 function initLandingEyeTracking(svgEl){ var pL = svgEl.querySelector('.pupil-l'); var pR = svgEl.querySelector('.pupil-r'); if(!pL || !pR) return; var lcx = parseFloat(pL.getAttribute('cx')); var lcy = parseFloat(pL.getAttribute('cy')); var rcx = parseFloat(pR.getAttribute('cx')); var rcy = parseFloat(pR.getAttribute('cy')); var maxOff = 4; document.addEventListener('mousemove', function(e){ var r = svgEl.getBoundingClientRect(); var vb = svgEl.viewBox.baseVal; var sx = vb.width / r.width; var sy = vb.height / r.height; var dx = (e.clientX - r.left - r.width / 2) * sx; var dy = (e.clientY - r.top - r.height / 2) * sy; var d = Math.sqrt(dx * dx + dy * dy); var f = Math.min(d / 200, 1) * maxOff; var a = Math.atan2(dy, dx); var cx = Math.cos(a) * f; var cy = Math.sin(a) * f; pL.setAttribute('cx', lcx + cx); pL.setAttribute('cy', lcy + cy); pR.setAttribute('cx', rcx + cx); pR.setAttribute('cy', rcy + cy); }); } // 进入应用 function enterApp(){ document.getElementById('landingPage').classList.remove('show'); document.getElementById('appPage').style.display = 'block'; // 记录用户已进入过应用 localStorage.setItem('lobster_exam_v4_entered', '1'); // 首次进入时自动适配 setTimeout(canvasFitWidth, 300); } // 返回首页 function goHome(){ document.getElementById('appPage').style.display = 'none'; document.getElementById('landingPage').classList.add('show'); window.scrollTo(0, 0); } // 示例数据 - 防城港市第二中学真实配置 var exampleTeachers = [ {name:'刘建荣',need:1},{name:'赵静',need:2},{name:'李雄',need:1},{name:'黎丰慧',need:1}, {name:'范家盛',need:1},{name:'曾显华',need:1},{name:'宋成凡',need:1},{name:'张蕾',need:1}, {name:'陈月英',need:2},{name:'张晋',need:2},{name:'蓝维娥',need:1},{name:'王直文',need:1}, {name:'农鹏东',need:1},{name:'张超婷',need:1},{name:'张洁梅',need:1},{name:'创业秋',need:1}, {name:'韦姣伶',need:2},{name:'李秋风',need:1},{name:'刘光洪',need:1},{name:'廖新源',need:1}, {name:'周启来',need:1},{name:'杨梦金',need:1},{name:'农彩结',need:1},{name:'符筱晨',need:1}, {name:'吴斯婷',need:1},{name:'陈春蓉',need:1},{name:'朱小琴',need:1},{name:'胡可欣',need:1}, {name:'徐维静',need:1},{name:'何业秋',need:1},{name:'黄国孙',need:1},{name:'何澄宇',need:1}, {name:'张福林',need:1},{name:'刘盛荣',need:1},{name:'潘常均',need:1},{name:'赵静怡',need:1}, {name:'李艳',need:1},{name:'彭丽明',need:1},{name:'韦秋凤',need:1},{name:'马培洪',need:2}, {name:'张新琼',need:1},{name:'孟桂',need:1},{name:'严琼子',need:1},{name:'李锦辉',need:1}, {name:'唐韦碧',need:1},{name:'廖善凤',need:1},{name:'郭智恒',need:1},{name:'韦本仪',need:1}, {name:'温子琪',need:1},{name:'梁颖玲',need:1} ]; var exampleSessions = [ {date:'6月28日(周六)',period:'上午',time:'9:00~11:30',subject:'语文'}, {date:'6月28日(周六)',period:'下午',time:'14:30~17:00',subject:'道法与历史'}, {date:'6月29日(周日)',period:'上午',time:'9:00~11:00',subject:'数学'}, {date:'6月29日(周日)',period:'下午',time:'15:00~16:30',subject:'八年级物理'}, {date:'6月30日(周一)',period:'上午',time:'9:00~11:00',subject:'英语'}, {date:'6月30日(周一)',period:'下午',time:'15:00~17:00',subject:'七年级地理、八年级生物'} ]; var exampleRooms = [ '七①','七②','七③','七④','七⑤','七⑥','七⑦','七⑧', '八①','八②','八③','八④','八⑤','八⑥','八⑦','八⑧', '生物实验室','化学实验室','学术交流中心二楼','书法室','物理实验室(力学)','物理实验室(电学)','善为楼三楼录播室' ]; /* ================================================================== */ /* V4.0:模板管理系统 */ /* ================================================================== */ // 模板存储键 var TEMPLATE_STORAGE_KEY = 'lobster_exam_templates'; // 获取所有已保存模板 function getTemplates(){ try{ var data = localStorage.getItem(TEMPLATE_STORAGE_KEY); return data ? JSON.parse(data) : []; }catch(e){ return []; } } // 保存模板列表 function saveTemplates(templates){ try{ localStorage.setItem(TEMPLATE_STORAGE_KEY, JSON.stringify(templates)); }catch(e){ showToast('❌ 保存模板失败:' + e.message, 'err'); } } // 获取当前配置数据 function getCurrentConfig(){ return { teachers: JSON.parse(JSON.stringify(teachers)), sessions: JSON.parse(JSON.stringify(sessions)), rooms: JSON.parse(JSON.stringify(rooms)), matrix: JSON.parse(JSON.stringify(matrix)), roleChief: JSON.parse(JSON.stringify(roleChief)), roleXs: JSON.parse(JSON.stringify(roleXs)) }; } // 加载配置到系统 function loadConfig(config){ teachers = config.teachers || []; sessions = config.sessions || []; rooms = config.rooms || []; matrix = config.matrix || {}; roleChief = config.roleChief || sessions.map(function(){ return []; }); roleXs = config.roleXs || sessions.map(function(){ return []; }); renderTeachers(); renderSchedule(); renderRoleAssigned(); saveToLocal(); } // 打开模板管理弹窗 function openTemplateMgr(){ document.getElementById('templateMgrOv').classList.add('show'); renderTemplateList(); } // 关闭模板管理弹窗 function closeTemplateMgr(){ document.getElementById('templateMgrOv').classList.remove('show'); } // 渲染模板列表 function renderTemplateList(){ var templates = getTemplates(); var listEl = document.getElementById('templateList'); var countEl = document.getElementById('templateCount'); countEl.textContent = templates.length + '个模板'; if(templates.length === 0){ listEl.innerHTML = '
暂无保存的模板
点击"另存为模板"保存当前配置
'; return; } var html = ''; templates.forEach(function(tpl, idx){ var teacherCount = (tpl.teachers || []).length; var sessionCount = (tpl.sessions || []).length; var roomCount = (tpl.rooms || []).length; var saveTime = tpl.savedAt ? new Date(tpl.savedAt).toLocaleString('zh-CN') : '未知时间'; html += '
'; html += '
'; html += '
' + esc(tpl.name) + '
'; html += '
'; html += '' + teacherCount + '位老师 · '; html += '' + sessionCount + '个场次 · '; html += '' + roomCount + '个考场'; html += '
'; html += '
' + saveTime + '
'; html += '
'; html += '
'; html += ''; html += ''; html += ''; html += '
'; html += '
'; }); listEl.innerHTML = html; } // 另存为模板 function saveAsTemplate(){ var name = prompt('请输入模板名称:', '我的排班模板 ' + new Date().toLocaleDateString('zh-CN')); if(!name) return; var templates = getTemplates(); var newTemplate = getCurrentConfig(); newTemplate.name = name; newTemplate.savedAt = Date.now(); newTemplate.id = 'tpl_' + Date.now() + '_' + Math.random().toString(36).substr(2,6); templates.push(newTemplate); saveTemplates(templates); renderTemplateList(); showToast('✅ 模板已保存:' + name, 'ok'); } // 加载模板 function loadTemplate(idx){ var templates = getTemplates(); if(!templates[idx]){ showToast('❌ 模板不存在', 'err'); return; } var tpl = templates[idx]; if(confirm('加载模板"' + tpl.name + '"?\n\n此操作将覆盖当前所有数据,确定继续?')){ loadConfig(tpl); closeTemplateMgr(); showToast('✅ 模板已加载:' + tpl.name, 'ok'); } } // 删除模板 function deleteTemplate(idx){ var templates = getTemplates(); if(!templates[idx]) return; if(confirm('确定删除模板"' + templates[idx].name + '"?此操作不可恢复!')){ templates.splice(idx, 1); saveTemplates(templates); renderTemplateList(); showToast('🗑️ 模板已删除', 'ok'); } } // 导出单个模板为JSON文件 function exportSingleTemplate(idx){ var templates = getTemplates(); if(!templates[idx]){ showToast('❌ 模板不存在', 'err'); return; } var tpl = templates[idx]; var exportData = { version: 'V4.0', type: 'lobster_exam_template', exportedAt: new Date().toISOString(), template: tpl }; var blob = new Blob([JSON.stringify(exportData, null, 2)], {type: 'application/json'}); var url = URL.createObjectURL(blob); var a = document.createElement('a'); a.href = url; a.download = '龙虾监考排班_模板_' + tpl.name + '.json'; a.click(); URL.revokeObjectURL(url); showToast('📤 模板已导出', 'ok'); } // 导出当前配置为模板文件 function exportTemplate(){ var name = prompt('请输入模板名称:', '我的排班模板 ' + new Date().toLocaleDateString('zh-CN')); if(!name) return; var exportData = { version: 'V4.0', type: 'lobster_exam_template', exportedAt: new Date().toISOString(), template: { name: name, savedAt: Date.now(), ...getCurrentConfig() } }; var blob = new Blob([JSON.stringify(exportData, null, 2)], {type: 'application/json'}); var url = URL.createObjectURL(blob); var a = document.createElement('a'); a.href = url; a.download = '龙虾监考排班_模板_' + name + '.json'; a.click(); URL.revokeObjectURL(url); showToast('📤 模板已导出', 'ok'); } // 导入模板文件(触发文件选择) function importTemplateFile(){ document.getElementById('templateFileInput').click(); } // 处理模板文件导入 function handleTemplateImport(event){ var file = event.target.files[0]; if(!file) return; var reader = new FileReader(); reader.onload = function(e){ try{ var data = JSON.parse(e.target.result); // 验证文件格式 if(data.type !== 'lobster_exam_template' || !data.template){ showToast('❌ 无效的模板文件', 'err'); return; } var tpl = data.template; if(!tpl.teachers || !tpl.sessions || !tpl.rooms){ showToast('❌ 模板数据不完整', 'err'); return; } // 添加到模板列表 var templates = getTemplates(); tpl.id = 'tpl_' + Date.now() + '_' + Math.random().toString(36).substr(2,6); tpl.savedAt = tpl.savedAt || Date.now(); tpl.name = tpl.name + '(导入)'; templates.push(tpl); saveTemplates(templates); renderTemplateList(); showToast('✅ 模板已导入:' + tpl.name, 'ok'); }catch(err){ showToast('❌ 解析模板文件失败:' + err.message, 'err'); } }; reader.readAsText(file); event.target.value = ''; // 重置input } // 加载示例数据(防城港市第二中学配置) function loadExampleData(){ if(confirm('加载防城港市第二中学监考配置?\n\n包含:50位老师 + 23个考场 + 6个场次\n\n此操作将覆盖当前所有数据,确定继续?')){ loadConfig({ teachers: JSON.parse(JSON.stringify(exampleTeachers)), sessions: JSON.parse(JSON.stringify(exampleSessions)), rooms: JSON.parse(JSON.stringify(exampleRooms)) }); closeTemplateMgr(); showToast('✅ 防城港二中配置已加载(50位老师/23考场/6场次)', 'ok'); } } // 清空所有数据 function clearAllData(){ if(confirm('确定清空所有数据?此操作不可恢复!')){ teachers = []; sessions = []; rooms = []; matrix = {}; roleChief = []; roleXs = []; versions = []; currentVersionId = null; renderTeachers(); renderSchedule(); renderRoleAssigned(); saveToLocal(); closeTemplateMgr(); showToast('🗑️ 数据已清空', 'ok'); } } // 初始化引导页 initLandingPage(); // V4.0:始终显示引导页(除非用户明确点击过"开始排班") // 通过localStorage记录用户是否已进入过应用 var hasEnteredApp = localStorage.getItem('lobster_exam_v4_entered'); if(hasEnteredApp === '1'){ document.getElementById('landingPage').classList.remove('show'); document.getElementById('appPage').style.display = 'block'; }
🦞 龙虾老师 · aiedge.top
🦞 已有 - 人使用过此工具 · 今日 - 次访问