AutorÃa | Ultima modificación | Ver Log |
{"version":3,"file":"async_backup.min.js","sources":["../src/async_backup.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * This module updates the UI during an asynchronous\n * backup or restore process.\n *\n * @module core_backup/async_backup\n * @copyright 2018 Matt Porritt <mattp@catalyst-au.net>\n * @license http://www.gnu.org
/copyleft/gpl.html GNU GPL v3 or later\n * @since 3.7\n */\ndefine(['jquery', 'core/ajax', 'core/str', 'core/notification', 'core/templates'],\n function($, ajax, Str, notification, Templates) {\n\n /**\n * Module level constants.\n *\n * Using var instead of const as ES6 isn't fully supported yet.\n */\n var STATUS_EXECUTING = 800;\n var STATUS_FINISHED_ERR = 900;\n var STATUS_FINISHED_OK = 1000;\n\n /**\n * Module level variables.\n */\n var Asyncbackup = {};\n var checkdelayoriginal = 15000; // This is the default time to use.\n var checkdelay = 15000; // How often we should check for progress updates.\n var checkdelaymultipler = 1.5; // If a request fails this multiplier will be used to increase the checkdelay value\n var backupid; // The backup id to get the progress for.\n var contextid; // The course this backup progress is for.\n var restoreurl; // The URL to view course restores.\n var typeid; // The type of operation bac
kup or restore.\n var backupintervalid; // The id of the setInterval function.\n var allbackupintervalid; // The id of the setInterval function.\n var allcopyintervalid; // The id of the setInterval function.\n var timeout = 2000; // Timeout for ajax requests.\n\n /**\n * Helper function to update UI components.\n *\n * @param {string} backupid The id to match elements on.\n * @param {string} type The type of operation, backup or restore.\n * @param {number} percentage The completion percentage to apply.\n */\n function updateElement(backupid, type, percentage) {\n var percentagewidth = Math.round(percentage) + '%';\n var elementbar = document.querySelectorAll(\"[data-\" + type + \"id=\" + CSS.escape(backupid) + \"]\")[0];\n var percentagetext = percentage.toFixed(2) + '%';\n\n // Set progress bar percentage indicators\n elementbar.setAttribute('aria-valuenow', percentagewidth);\n elementbar.style.width = percentagewidth;\
n elementbar.innerHTML = percentagetext;\n }\n\n /**\n * Updates the interval we use to check for backup progress.\n *\n * @param {Number} intervalid The id of the interval\n * @param {Function} callback The function to use in setInterval\n * @param {Number} value The specified interval (in milliseconds)\n * @returns {Number}\n */\n function updateInterval(intervalid, callback, value) {\n clearInterval(intervalid);\n return setInterval(callback, value);\n }\n\n /**\n * Update backup table row when an async backup completes.\n *\n * @param {string} backupid The id to match elements on.\n */\n function updateBackupTableRow(backupid) {\n var statuscell = $('#' + backupid + '_bar').parent().parent();\n var tablerow = statuscell.parent();\n var cellsiblings = statuscell.siblings();\n var timecell = cellsiblings[1];\n var timevalue = $(timecell).text();\n var filenamecell = cellsiblings[0];\
n var filename = $(filenamecell).text();\n\n ajax.call([{\n // Get the table data via webservice.\n methodname: 'core_backup_get_async_backup_links_backup',\n args: {\n 'filename': filename,\n 'contextid': contextid,\n 'backupid': backupid\n },\n }])[0].done(function(response) {\n // We have the data now update the UI.\n var context = {\n filename: filename,\n time: timevalue,\n size: response.filesize,\n fileurl: response.fileurl,\n restoreurl: response.restoreurl\n };\n\n Templates.render('core/async_backup_progress_row', context).then(function(html, js) {\n Templates.replaceNodeContents(tablerow, html, js);\n return;\n }).fail(function() {\n notification.exception(new Error('Failed to load table ro
w'));\n return;\n });\n });\n }\n\n /**\n * Update restore table row when an async restore completes.\n *\n * @param {string} backupid The id to match elements on.\n */\n function updateRestoreTableRow(backupid) {\n var statuscell = $('#' + backupid + '_bar').parent().parent();\n var tablerow = statuscell.parent();\n var cellsiblings = statuscell.siblings();\n var coursecell = cellsiblings[0];\n var timecell = cellsiblings[1];\n var timevalue = $(timecell).text();\n\n ajax.call([{\n // Get the table data via webservice.\n methodname: 'core_backup_get_async_backup_links_restore',\n args: {\n 'backupid': backupid,\n 'contextid': contextid\n },\n }])[0].done(function(response) {\n // We have the data now update the UI.\n var resourcename = $(coursecell).text();\n var context = {\n
resourcename: resourcename,\n restoreurl: response.restoreurl,\n time: timevalue\n };\n\n Templates.render('core/async_restore_progress_row', context).then(function(html, js) {\n Templates.replaceNodeContents(tablerow, html, js);\n return;\n }).fail(function() {\n notification.exception(new Error('Failed to load table row'));\n return;\n });\n });\n }\n\n /**\n * Update copy table row when an course copy completes.\n *\n * @param {string} backupid The id to match elements on.\n */\n function updateCopyTableRow(backupid) {\n var elementbar = document.querySelectorAll(\"[data-restoreid=\" + CSS.escape(backupid) + \"]\")[0];\n var restorecourse = elementbar.closest('tr').children[1];\n var coursename = restorecourse.innerHTML;\n var courselink = document.createElement('a');\n var elementbarparen
t = elementbar.closest('td');\n var operation = elementbarparent.previousElementSibling;\n\n // Replace the prgress bar.\n Str.get_string('complete').then(function(content) {\n operation.innerHTML = content;\n return;\n }).catch(function() {\n notification.exception(new Error('Failed to load string: complete'));\n return;\n });\n\n Templates.render('core/async_copy_complete_cell', {}).then(function(html, js) {\n Templates.replaceNodeContents(elementbarparent, html, js);\n return;\n }).fail(function() {\n notification.exception(new Error('Failed to load table cell'));\n return;\n });\n\n // Update the destination course name to a link to that course.\n ajax.call([{\n methodname: 'core_backup_get_async_backup_links_restore',\n args: {\n 'backupid': backupid,\n 'contextid': 0\n },\n }])[
0].done(function(response) {\n courselink.setAttribute('href', response.restoreurl);\n courselink.innerHTML = coursename;\n restorecourse.innerHTML = null;\n restorecourse.appendChild(courselink);\n\n return;\n }).fail(function() {\n notification.exception(new Error('Failed to update table row'));\n return;\n });\n }\n\n /**\n * Update the Moodle user interface with the progress of\n * the backup process.\n *\n * @param {object} progress The progress and status of the process.\n */\n function updateProgress(progress) {\n var percentage = progress.progress * 100;\n var type = 'backup';\n var elementbar = document.querySelectorAll(\"[data-\" + type + \"id=\" + CSS.escape(backupid) + \"]\")[0];\n var elementstatus = $('#' + backupid + '_status');\n var elementdetail = $('#' + backupid + '_detail');\n var elementbutton = $('#' + backupid + '_button');\n
var stringRequests;\n\n if (progress.status == STATUS_EXECUTING) {\n // Process is in progress.\n // Add in progress class color to bar.\n elementbar.classList.add('bg-success');\n\n updateElement(backupid, type, percentage);\n\n // Change heading.\n var strProcessing = 'async' + typeid + 'processing';\n Str.get_string(strProcessing, 'backup').then(function(title) {\n elementstatus.text(title);\n return;\n }).catch(function() {\n notification.exception(new Error('Failed to load string: backup ' + strProcessing));\n });\n\n } else if (progress.status == STATUS_FINISHED_ERR) {\n // Process completed with error.\n\n // Add in fail class color to bar.\n elementbar.classList.add('bg-danger');\n\n // Remove in progress class color to bar.\n elementbar.classList.remove('bg-success');\n\n
updateElement(backupid, type, 100);\n\n // Change heading and text.\n var strStatus = 'async' + typeid + 'error';\n var strStatusDetail = 'async' + typeid + 'errordetail';\n stringRequests = [\n {key: strStatus, component: 'backup'},\n {key: strStatusDetail, component: 'backup'}\n ];\n Str.get_strings(stringRequests).then(function(strings) {\n elementstatus.text(strings[0]);\n elementdetail.text(strings[1]);\n\n return;\n })\n .catch(function() {\n notification.exception(new Error('Failed to load string'));\n return;\n });\n\n $('.backup_progress').children('span').removeClass('backup_stage_current');\n $('.backup_progress').children('span').last().addClass('backup_stage_current');\n\n // Stop checking when we either have an error or a completion.\n clearInterval(
backupintervalid);\n\n } else if (progress.status == STATUS_FINISHED_OK) {\n // Process completed successfully.\n\n // Add in progress class color to bar\n elementbar.classList.add('bg-success');\n\n updateElement(backupid, type, 100);\n\n // Change heading and text\n var strComplete = 'async' + typeid + 'complete';\n Str.get_string(strComplete, 'backup').then(function(title) {\n elementstatus.text(title);\n return;\n }).catch(function() {\n notification.exception(new Error('Failed to load string: backup ' + strComplete));\n });\n\n if (typeid == 'restore') {\n ajax.call([{\n // Get the table data via webservice.\n methodname: 'core_backup_get_async_backup_links_restore',\n args: {\n 'backupid': backupid,\n 'contextid': contextid\n
},\n }])[0].done(function(response) {\n var strDetail = 'async' + typeid + 'completedetail';\n var strButton = 'async' + typeid + 'completebutton';\n var stringRequests = [\n {key: strDetail, component: 'backup', param: response.restoreurl},\n {key: strButton, component: 'backup'}\n ];\n Str.get_strings(stringRequests).then(function(strings) {\n elementdetail.html(strings[0]);\n elementbutton.text(strings[1]);\n elementbutton.attr('href', response.restoreurl);\n\n return;\n })\n .catch(function() {\n notification.exception(new Error('Failed to load string'));\n return;\n });\n\n });\n } else {\n var strDet
ail = 'async' + typeid + 'completedetail';\n var strButton = 'async' + typeid + 'completebutton';\n stringRequests = [\n {key: strDetail, component: 'backup', param: restoreurl},\n {key: strButton, component: 'backup'}\n ];\n Str.get_strings(stringRequests).then(function(strings) {\n elementdetail.html(strings[0]);\n elementbutton.text(strings[1]);\n elementbutton.attr('href', restoreurl);\n\n return;\n })\n .catch(function() {\n notification.exception(new Error('Failed to load string'));\n return;\n });\n\n }\n\n $('.backup_progress').children('span').removeClass('backup_stage_current');\n $('.backup_progress').children('span').last().addClass('backup_stage_current');\n\n // Stop checking when we either have an
error or a completion.\n clearInterval(backupintervalid);\n }\n }\n\n /**\n * Update the Moodle user interface with the progress of\n * all the pending processes for backup and restore operations.\n *\n * @param {object} progress The progress and status of the process.\n */\n function updateProgressAll(progress) {\n progress.forEach(function(element) {\n var percentage = element.progress * 100;\n var backupid = element.backupid;\n var type = element.operation;\n var elementbar = document.querySelectorAll(\"[data-\" + type + \"id=\" + CSS.escape(backupid) + \"]\")[0];\n\n if (element.status == STATUS_EXECUTING) {\n // Process is in element.\n\n // Add in element class color to bar\n elementbar.classList.add('bg-success');\n\n updateElement(backupid, type, percentage);\n\n } else if (element.status == STATUS_FINISHED_ERR) {\n
// Process completed with error.\n\n // Add in fail class color to bar\n elementbar.classList.add('bg-danger');\n elementbar.classList.add('complete');\n\n // Remove in element class color to bar\n elementbar.classList.remove('bg-success');\n\n updateElement(backupid, type, 100);\n\n } else if (element.status == STATUS_FINISHED_OK) {\n // Process completed successfully.\n\n // Add in element class color to bar\n elementbar.classList.add('bg-success');\n elementbar.classList.add('complete');\n\n updateElement(backupid, type, 100);\n\n // We have a successful backup. Update the UI with download and file details.\n if (type == 'backup') {\n updateBackupTableRow(backupid);\n } else {\n updateRestoreTableRow(backupid);\n }\n\n
}\n\n });\n }\n\n /**\n * Update the Moodle user interface with the progress of\n * all the pending processes for copy operations.\n *\n * @param {object} progress The progress and status of the process.\n */\n function updateProgressCopy(progress) {\n progress.forEach(function(element) {\n var percentage = element.progress * 100;\n var backupid = element.backupid;\n var type = element.operation;\n var elementbar = document.querySelectorAll(\"[data-\" + type + \"id=\" + CSS.escape(backupid) + \"]\")[0];\n\n if (type == 'restore') {\n let restorecell = elementbar.closest('tr').children[3];\n Str.get_string('restore').then(function(content) {\n restorecell.innerHTML = content;\n return;\n }).catch(function() {\n notification.exception(new Error('Failed to load string: restore'));\n });\n
}\n\n if (element.status == STATUS_EXECUTING) {\n // Process is in element.\n\n // Add in element class color to bar\n elementbar.classList.add('bg-success');\n\n updateElement(backupid, type, percentage);\n\n } else if (element.status == STATUS_FINISHED_ERR) {\n // Process completed with error.\n\n // Add in fail class color to bar\n elementbar.classList.add('bg-danger');\n elementbar.classList.add('complete');\n\n // Remove in element class color to bar\n elementbar.classList.remove('bg-success');\n\n updateElement(backupid, type, 100);\n\n } else if ((element.status == STATUS_FINISHED_OK) && (type == 'restore')) {\n // Process completed successfully.\n\n // Add in element class color to bar\n elementbar.classList.add('bg-success');\n elementba
r.classList.add('complete');\n\n updateElement(backupid, type, 100);\n\n // We have a successful copy. Update the UI link to copied course.\n updateCopyTableRow(backupid);\n }\n\n });\n }\n\n /**\n * Get the progress of the backup process via ajax.\n */\n function getBackupProgress() {\n ajax.call([{\n // Get the backup progress via webservice.\n methodname: 'core_backup_get_async_backup_progress',\n args: {\n 'backupids': [backupid],\n 'contextid': contextid\n },\n }], true, true, false, timeout)[0].done(function(response) {\n // We have the progress now update the UI.\n updateProgress(response[0]);\n checkdelay = checkdelayoriginal;\n backupintervalid = updateInterval(backupintervalid, getBackupProgress, checkdelayoriginal);\n }).fail(function() {\n checkdelay = checkdelay * check
delaymultipler;\n backupintervalid = updateInterval(backupintervalid, getBackupProgress, checkdelay);\n });\n }\n\n /**\n * Get the progress of all backup processes via ajax.\n */\n function getAllBackupProgress() {\n var backupids = [];\n var progressbars = $('.progress').find('.progress-bar').not('.complete');\n\n progressbars.each(function() {\n backupids.push((this.id).substring(0, 32));\n });\n\n if (backupids.length > 0) {\n ajax.call([{\n // Get the backup progress via webservice.\n methodname: 'core_backup_get_async_backup_progress',\n args: {\n 'backupids': backupids,\n 'contextid': contextid\n },\n }], true, true, false, timeout)[0].done(function(response) {\n updateProgressAll(response);\n checkdelay = checkdelayoriginal;\n allbackupintervalid = updateInte
rval(allbackupintervalid, getAllBackupProgress, checkdelayoriginal);\n }).fail(function() {\n checkdelay = checkdelay * checkdelaymultipler;\n allbackupintervalid = updateInterval(allbackupintervalid, getAllBackupProgress, checkdelay);\n });\n } else {\n clearInterval(allbackupintervalid); // No more progress bars to update, stop checking.\n }\n }\n\n /**\n * Get the progress of all copy processes via ajax.\n */\n function getAllCopyProgress() {\n var copyids = [];\n var progressbars = $('.progress').find('.progress-bar[data-operation][data-backupid][data-restoreid]').not('.complete');\n\n progressbars.each(function() {\n let progressvars = {\n 'backupid': this.dataset.backupid,\n 'restoreid': this.dataset.restoreid,\n 'operation': this.dataset.operation,\n };\n copyids.push(progressvars);\n });\n\n
if (copyids.length > 0) {\n ajax.call([{\n // Get the copy progress via webservice.\n methodname: 'core_backup_get_copy_progress',\n args: {\n 'copies': copyids\n },\n }], true, true, false, timeout)[0].done(function(response) {\n updateProgressCopy(response);\n checkdelay = checkdelayoriginal;\n allcopyintervalid = updateInterval(allcopyintervalid, getAllCopyProgress, checkdelayoriginal);\n }).fail(function() {\n checkdelay = checkdelay * checkdelaymultipler;\n allcopyintervalid = updateInterval(allcopyintervalid, getAllCopyProgress, checkdelay);\n });\n } else {\n clearInterval(allcopyintervalid); // No more progress bars to update, stop checking.\n }\n }\n\n /**\n * Get status updates for all backups.\n *\n * @public\n * @param {number} context The context i
d.\n */\n Asyncbackup.asyncBackupAllStatus = function(context) {\n contextid = context;\n allbackupintervalid = setInterval(getAllBackupProgress, checkdelay);\n };\n\n /**\n * Get status updates for all course copies.\n *\n * @public\n */\n Asyncbackup.asyncCopyAllStatus = function() {\n allcopyintervalid = setInterval(getAllCopyProgress, checkdelay);\n };\n\n /**\n * Get status updates for backup.\n *\n * @public\n * @param {string} backup The backup record id.\n * @param {number} context The context id.\n * @param {string} restore The restore link.\n * @param {string} type The operation type (backup or restore).\n */\n Asyncbackup.asyncBackupStatus = function(backup, context, restore, type) {\n backupid = backup;\n contextid = context;\n restoreurl = restore;\n\n if (type == 'backup') {\n typeid = 'backup';\n } else {\n typeid = 'restore';\n }\n\n
// Remove the links from the progress bar, no going back now.\n $('.backup_progress').children('a').removeAttr('href');\n\n // Periodically check for progress updates and update the UI as required.\n backupintervalid = setInterval(getBackupProgress, checkdelay);\n\n };\n\n return Asyncbackup;\n});\n"],"names":["define","$","ajax","Str","notification","Templates","backupid","contextid","restoreurl","typeid","backupintervalid","allbackupintervalid","allcopyintervalid","Asyncbackup","checkdelay","updateElement","type","percentage","percentagewidth","Math","round","elementbar","document","querySelectorAll","CSS","escape","percentagetext","toFixed","setAttribute","style","width","innerHTML","updateInterval","intervalid","callback","value","clearInterval","setInterval","updateProgressAll","progress","forEach","element","operation","status","classList","add","remove","statuscell","parent","tablerow","cellsiblings","siblings","timecell","timevalue","text","filenamecell","filename"
,"call","methodname","args","done","response","context","time","size","filesize","fileurl","render","then","html","js","replaceNodeContents","fail","exception","Error","updateBackupTableRow","coursecell","resourcename","updateRestoreTableRow","updateProgressCopy","restorecell","closest","children","get_string","content","catch","restorecourse","coursename","courselink","createElement","elementbarparent","previousElementSibling","appendChild","updateCopyTableRow","getBackupProgress","stringRequests","elementstatus","elementdetail","elementbutton","strProcessing","title","key","component","get_strings","strings","removeClass","last","addClass","strComplete","strButton","param","attr","updateProgress","getAllBackupProgress","backupids","find","not","each","push","this","id","substring","length","getAllCopyProgress","copyids","progressvars","dataset","restoreid","asyncBackupAllStatus","asyncCopyAllStatus","asyncBackupStatus","backup","restore","removeAttr"],"mappings":";;;;;;;;;AAwBAA,kCAAO,CAAC,SAAU,YAAa,WAAY,o
BAAqB,mBACxD,SAASC,EAAGC,KAAMC,IAAKC,aAAcC,eAkBrCC,SACAC,UACAC,WACAC,OACAC,iBACAC,oBACAC,kBAVAC,YAAc,GAEdC,WAAa,cAkBRC,cAAcT,SAAUU,KAAMC,gBAC/BC,gBAAkBC,KAAKC,MAAMH,YAAc,IAC3CI,WAAaC,SAASC,iBAAiB,SAAWP,KAAO,MAAQQ,IAAIC,OAAOnB,UAAY,KAAK,GAC7FoB,eAAiBT,WAAWU,QAAQ,GAAK,IAG7CN,WAAWO,aAAa,gBAAiBV,iBACzCG,WAAWQ,MAAMC,MAAQZ,gBACzBG,WAAWU,UAAYL,wBAWlBM,eAAeC,WAAYC,SAAUC,cAC1CC,cAAcH,YACPI,YAAYH,SAAUC,gBAwRxBG,kBAAkBC,UACvBA,SAASC,SAAQ,SAASC,aAClBxB,WAAgC,IAAnBwB,QAAQF,SACrBjC,SAAWmC,QAAQnC,SACnBU,KAAOyB,QAAQC,UACfrB,WAAaC,SAASC,iBAAiB,SAAWP,KAAO,MAAQQ,IAAIC,OAAOnB,UAAY,KAAK,GA7UlF,KA+UXmC,QAAQE,QAIRtB,WAAWuB,UAAUC,IAAI,cAEzB9B,cAAcT,SAAUU,KAAMC,aApVhB,KAsVPwB,QAAQE,QAIftB,WAAWuB,UAAUC,IAAI,aACzBxB,WAAWuB,UAAUC,IAAI,YAGzBxB,WAAWuB,UAAUE,OAAO,cAE5B/B,cAAcT,SAAUU,KAAM,MA/VjB,KAiWNyB,QAAQE,SAIftB,WAAWuB,UAAUC,IAAI,cACzBxB,WAAWuB,UAAUC,IAAI,YAEzB9B,cAAcT,SAAUU,KAAM,KAGlB,UAARA,cArTcV,cACtByC,WAAa9C,EAAE,IAAMK,SAAW,QAAQ0C,SAASA,SACjDC,SAAWF,WAAWC,SACtBE,aAAeH,WAAWI,WAC1BC,SAAWF,aAAa,GACxBG,UAAYpD,EAAEmD,UAAUE,OACxBC,aAAeL
,aAAa,GAC5BM,SAAWvD,EAAEsD,cAAcD,OAE/BpD,KAAKuD,KAAK,CAAC,CAEPC,WAAY,4CACZC,KAAM,UACUH,mBACCjD,mBACDD,aAEhB,GAAGsD,MAAK,SAASC,cAEbC,QAAU,CACNN,SAAUA,SACVO,KAAMV,UACNW,KAAMH,SAASI,SACfC,QAASL,SAASK,QAClB1D,WAAYqD,SAASrD,YAG7BH,UAAU8D,OAAO,iCAAkCL,SAASM,MAAK,SAASC,KAAMC,IAC5EjE,UAAUkE,oBAAoBtB,SAAUoB,KAAMC,OAE/CE,MAAK,WACJpE,aAAaqE,UAAU,IAAIC,MAAM,mCAuR7BC,CAAqBrE,mBA5QNA,cACvByC,WAAa9C,EAAE,IAAMK,SAAW,QAAQ0C,SAASA,SACjDC,SAAWF,WAAWC,SACtBE,aAAeH,WAAWI,WAC1ByB,WAAa1B,aAAa,GAC1BE,SAAWF,aAAa,GACxBG,UAAYpD,EAAEmD,UAAUE,OAE5BpD,KAAKuD,KAAK,CAAC,CAEPC,WAAY,6CACZC,KAAM,UACUrD,mBACCC,cAEjB,GAAGqD,MAAK,SAASC,cAGbC,QAAU,CACNe,aAFW5E,EAAE2E,YAAYtB,OAGzB9C,WAAYqD,SAASrD,WACrBuD,KAAMV,WAGdhD,UAAU8D,OAAO,kCAAmCL,SAASM,MAAK,SAASC,KAAMC,IAC7EjE,UAAUkE,oBAAoBtB,SAAUoB,KAAMC,OAE/CE,MAAK,WACJpE,aAAaqE,UAAU,IAAIC,MAAM,mCAkP7BI,CAAsBxE,uBAc7ByE,mBAAmBxC,UACxBA,SAASC,SAAQ,SAASC,aAClBxB,WAAgC,IAAnBwB,QAAQF,SACrBjC,SAAWmC,QAAQnC,SACnBU,KAAOyB,QAAQC,UACfrB,WAAaC,SAASC,iBAAiB,SAAWP,KAAO,MAAQQ,IAAIC,OAAOnB,UAAY,KAAK,MAErF,WAARU,KAAmB,K
ACdgE,YAAc3D,WAAW4D,QAAQ,MAAMC,SAAS,GACpD/E,IAAIgF,WAAW,WAAWf,MAAK,SAASgB,SACpCJ,YAAYjD,UAAYqD,WAEzBC,OAAM,WACLjF,aAAaqE,UAAU,IAAIC,MAAM,sCA3Y3B,KA+YXjC,QAAQE,QAIRtB,WAAWuB,UAAUC,IAAI,cAEzB9B,cAAcT,SAAUU,KAAMC,aApZhB,KAsZPwB,QAAQE,QAIftB,WAAWuB,UAAUC,IAAI,aACzBxB,WAAWuB,UAAUC,IAAI,YAGzBxB,WAAWuB,UAAUE,OAAO,cAE5B/B,cAAcT,SAAUU,KAAM,MA/ZjB,KAiaLyB,QAAQE,QAA0C,WAAR3B,OAIlDK,WAAWuB,UAAUC,IAAI,cACzBxB,WAAWuB,UAAUC,IAAI,YAEzB9B,cAAcT,SAAUU,KAAM,cAjSdV,cACpBe,WAAaC,SAASC,iBAAiB,mBAAqBC,IAAIC,OAAOnB,UAAY,KAAK,GACxFgF,cAAgBjE,WAAW4D,QAAQ,MAAMC,SAAS,GAClDK,WAAaD,cAAcvD,UAC3ByD,WAAalE,SAASmE,cAAc,KACpCC,iBAAmBrE,WAAW4D,QAAQ,MACtCvC,UAAYgD,iBAAiBC,uBAGjCxF,IAAIgF,WAAW,YAAYf,MAAK,SAASgB,SACrC1C,UAAUX,UAAYqD,WAEvBC,OAAM,WACLjF,aAAaqE,UAAU,IAAIC,MAAM,uCAIrCrE,UAAU8D,OAAO,gCAAiC,IAAIC,MAAK,SAASC,KAAMC,IACtEjE,UAAUkE,oBAAoBmB,iBAAkBrB,KAAMC,OAEvDE,MAAK,WACJpE,aAAaqE,UAAU,IAAIC,MAAM,iCAKrCxE,KAAKuD,KAAK,CAAC,CACPC,WAAY,6CACZC,KAAM,UACUrD,mBACC,MAEjB,GAAGsD,MAAK,SAASC,UACjB2B,WAAW5D,aAAa,OAAQiC,SAASrD,YACzCgF,WAAWzD,UAAYwD,WAC
vBD,cAAcvD,UAAY,KAC1BuD,cAAcM,YAAYJ,eAG3BhB,MAAK,WACJpE,aAAaqE,UAAU,IAAIC,MAAM,kCA4P7BmB,CAAmBvF,uBAStBwF,oBACL5F,KAAKuD,KAAK,CAAC,CAEPC,WAAY,wCACZC,KAAM,WACW,CAACrD,oBACDC,cAEjB,GAAM,GAAM,EA5aN,KA4asB,GAAGqD,MAAK,SAASC,oBAlQ7BtB,cAOhBwD,eANA9E,WAAiC,IAApBsB,SAASA,SACtBvB,KAAO,SACPK,WAAaC,SAASC,iBAAiB,kBAA0BC,IAAIC,OAAOnB,UAAY,KAAK,GAC7F0F,cAAgB/F,EAAE,IAAMK,SAAW,WACnC2F,cAAgBhG,EAAE,IAAMK,SAAW,WACnC4F,cAAgBjG,EAAE,IAAMK,SAAW,cAlMpB,KAqMfiC,SAASI,OAA4B,CAGrCtB,WAAWuB,UAAUC,IAAI,cAEzB9B,cAAcT,SAAUU,KAAMC,gBAG1BkF,cAAgB,QAAU1F,OAAS,aACvCN,IAAIgF,WAAWgB,cAAe,UAAU/B,MAAK,SAASgC,OAClDJ,cAAc1C,KAAK8C,UAEpBf,OAAM,WACLjF,aAAaqE,UAAU,IAAIC,MAAM,iCAAmCyB,wBAGrE,GApNe,KAoNX5D,SAASI,OAIhBtB,WAAWuB,UAAUC,IAAI,aAGzBxB,WAAWuB,UAAUE,OAAO,cAE5B/B,cAAcT,SAAUU,KAAM,KAK9B+E,eAAiB,CACb,CAACM,IAHW,QAAU5F,OAAS,QAGd6F,UAAW,UAC5B,CAACD,IAHiB,QAAU5F,OAAS,cAGd6F,UAAW,WAEtCnG,IAAIoG,YAAYR,gBAAgB3B,MAAK,SAASoC,SAC1CR,cAAc1C,KAAKkD,QAAQ,IAC3BP,cAAc3C,KAAKkD,QAAQ,OAI9BnB,OAAM,WACHjF,aAAaqE,UAAU,IAAIC,MAAM,6BAIrCzE,EAAE,oBAAoBiF,SAAS,QAAQu
B,YAAY,wBACnDxG,EAAE,oBAAoBiF,SAAS,QAAQwB,OAAOC,SAAS,wBAGvDvE,cAAc1B,uBAEX,GAtPc,KAsPV6B,SAASI,OAA8B,CAI9CtB,WAAWuB,UAAUC,IAAI,cAEzB9B,cAAcT,SAAUU,KAAM,SAG1B4F,YAAc,QAAUnG,OAAS,WACrCN,IAAIgF,WAAWyB,YAAa,UAAUxC,MAAK,SAASgC,OAChDJ,cAAc1C,KAAK8C,UAEpBf,OAAM,WACLjF,aAAaqE,UAAU,IAAIC,MAAM,iCAAmCkC,iBAG1D,WAAVnG,OACAP,KAAKuD,KAAK,CAAC,CAEPC,WAAY,6CACZC,KAAM,UACUrD,mBACCC,cAEjB,GAAGqD,MAAK,SAASC,cAEbgD,UAAY,QAAUpG,OAAS,iBAC/BsF,eAAiB,CACjB,CAACM,IAHW,QAAU5F,OAAS,iBAGd6F,UAAW,SAAUQ,MAAOjD,SAASrD,YACtD,CAAC6F,IAAKQ,UAAWP,UAAW,WAEhCnG,IAAIoG,YAAYR,gBAAgB3B,MAAK,SAASoC,SAC1CP,cAAc5B,KAAKmC,QAAQ,IAC3BN,cAAc5C,KAAKkD,QAAQ,IAC3BN,cAAca,KAAK,OAAQlD,SAASrD,eAIvC6E,OAAM,WACHjF,aAAaqE,UAAU,IAAIC,MAAM,iCAQzCqB,eAAiB,CACb,CAACM,IAHW,QAAU5F,OAAS,iBAGd6F,UAAW,SAAUQ,MAAOtG,YAC7C,CAAC6F,IAHW,QAAU5F,OAAS,iBAGd6F,UAAW,WAEhCnG,IAAIoG,YAAYR,gBAAgB3B,MAAK,SAASoC,SAC1CP,cAAc5B,KAAKmC,QAAQ,IAC3BN,cAAc5C,KAAKkD,QAAQ,IAC3BN,cAAca,KAAK,OAAQvG,eAI9B6E,OAAM,WACHjF,aAAaqE,UAAU,IAAIC,MAAM,8BAMzCzE,EAAE,oBAAoBiF,SAAS,QAAQuB,YAAY,wBACnDxG,EAAE,oBA
AoBiF,SAAS,QAAQwB,OAAOC,SAAS,wBAGvDvE,cAAc1B,mBAkIdsG,CAAenD,SAAS,IACxB/C,WAzbiB,KA0bjBJ,iBAAmBsB,eAAetB,iBAAkBoF,kBA1bnC,SA2blBtB,MAAK,WAEJ9D,iBAAmBsB,eAAetB,iBAAkBoF,kBADpDhF,YA1bkB,iBAkcjBmG,2BACDC,UAAY,GACGjH,EAAE,aAAakH,KAAK,iBAAiBC,IAAI,aAE/CC,MAAK,WACdH,UAAUI,KAAMC,KAAKC,GAAIC,UAAU,EAAG,QAGtCP,UAAUQ,OAAS,EACnBxH,KAAKuD,KAAK,CAAC,CAEPC,WAAY,wCACZC,KAAM,WACWuD,oBACA3G,cAEjB,GAAM,GAAM,EA1cV,KA0c0B,GAAGqD,MAAK,SAASC,UAC7CvB,kBAAkBuB,UAClB/C,WAtda,KAudbH,oBAAsBqB,eAAerB,oBAAqBsG,qBAvd7C,SAwddzC,MAAK,WAEJ7D,oBAAsBqB,eAAerB,oBAAqBsG,qBAD1DnG,YAvdc,QA2dlBsB,cAAczB,8BAObgH,yBACDC,QAAU,GACK3H,EAAE,aAAakH,KAAK,gEAAgEC,IAAI,aAE9FC,MAAK,eACVQ,aAAe,UACCN,KAAKO,QAAQxH,mBACZiH,KAAKO,QAAQC,oBACbR,KAAKO,QAAQpF,WAElCkF,QAAQN,KAAKO,iBAGbD,QAAQF,OAAS,EACjBxH,KAAKuD,KAAK,CAAC,CAEPC,WAAY,gCACZC,KAAM,QACQiE,YAEd,GAAM,GAAM,EA9eV,KA8e0B,GAAGhE,MAAK,SAASC,UAC7CkB,mBAAmBlB,UACnB/C,WA1fa,KA2fbF,kBAAoBoB,eAAepB,kBAAmB+G,mBA3fzC,SA4fdnD,MAAK,WAEJ5D,kBAAoBoB,eAAepB,kBAAmB+G,mBADtD7G,YA3fc,QA+flBsB,cAAcxB,0BAUtBC,YAAYmH,qBAAuB,SAASlE
,SACxCvD,UAAYuD,QACZnD,oBAAsB0B,YAAY4E,qBAAsBnG,aAQ5DD,YAAYoH,mBAAqB,WAC7BrH,kBAAoByB,YAAYsF,mBAAoB7G,aAYxDD,YAAYqH,kBAAoB,SAASC,OAAQrE,QAASsE,QAASpH,MAC/DV,SAAW6H,OACX5H,UAAYuD,QACZtD,WAAa4H,QAGT3H,OADQ,UAARO,KACS,SAEA,UAIbf,EAAE,oBAAoBiF,SAAS,KAAKmD,WAAW,QAG/C3H,iBAAmB2B,YAAYyD,kBAAmBhF,aAI7CD"}