diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7841542046..71b3a06e23 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,12 @@
LifterLMS Changelog
===================
+v3.19.4 - 2018-06-??
+--------------------
+
++ Add subscription event on builder to allow integrations to run custom code on heartbeat ticks
+
+
v3.19.3 - 2018-06-14
--------------------
diff --git a/assets/js/builder/Controllers/Sync.js b/assets/js/builder/Controllers/Sync.js
index eb43582195..16db93f1c6 100644
--- a/assets/js/builder/Controllers/Sync.js
+++ b/assets/js/builder/Controllers/Sync.js
@@ -1,7 +1,7 @@
/**
* Sync builder data to the server
* @since 3.16.0
- * @version 3.17.1
+ * @version [version]
*/
define( [], function() {
@@ -312,10 +312,12 @@ define( [], function() {
* @param obj data data set that was processed by the server
* @return void
* @since 3.16.11
- * @version 3.16.6
+ * @version [version]
*/
function maybe_restart_tracking( model, data ) {
+ Backbone.pubSub.trigger( model.get( 'type' ) + '-maybe-restart-tracking', model, data );
+
var omit = [ 'id', 'orig_id' ];
if ( model.get_relationships ) {
diff --git a/assets/js/llms-builder.js b/assets/js/llms-builder.js
index 935765d6cd..8a28378e89 100644
--- a/assets/js/llms-builder.js
+++ b/assets/js/llms-builder.js
@@ -6159,6 +6159,8 @@ define( 'Controllers/Sync',[], function() {
*/
function maybe_restart_tracking( model, data ) {
+ Backbone.pubSub.trigger( model.get( 'type' ) + '-maybe-restart-tracking', model, data );
+
var omit = [ 'id', 'orig_id' ];
if ( model.get_relationships ) {
diff --git a/assets/js/llms-builder.js.map b/assets/js/llms-builder.js.map
index b46747d0cf..ec8e0076a5 100644
--- a/assets/js/llms-builder.js.map
+++ b/assets/js/llms-builder.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../../../config-wrap-start-default.js","vendor/almond.js","underscore.js","backbone.js","jquery.js","vendor/backbone.collectionView.js","vendor/backbone.trackit.js","Models/Image.js","Models/_Relationships.js","Models/QuestionChoice.js","Collections/QuestionChoices.js","Models/QuestionType.js","Models/Question.js","Collections/Questions.js","Models/_Utilities.js","Schemas/Quiz.js","Models/Quiz.js","Schemas/Lesson.js","Models/Lesson.js","Collections/Lessons.js","Collections/QuestionTypes.js","Models/Section.js","Collections/Sections.js","Collections/loader.js","Models/Abstract.js","Models/Course.js","Models/loader.js","Views/_Detachable.js","Views/_Editable.js","Views/_Receivable.js","Views/_Shiftable.js","Views/_Subview.js","Views/_Trashable.js","Views/_loader.js","Controllers/Construct.js","Controllers/Debug.js","Controllers/Schemas.js","Controllers/Sync.js","Views/Lesson.js","Views/LessonList.js","Views/Section.js","Views/SectionList.js","Views/Course.js","Views/SettingsFields.js","Views/LessonEditor.js","Views/Popover.js","Views/PostSearch.js","Views/QuestionType.js","Views/QuestionBank.js","Views/QuestionChoice.js","Views/QuestionChoiceList.js","Views/Question.js","Views/QuestionList.js","Views/Quiz.js","Views/Assignment.js","Views/Editor.js","Views/Elements.js","Views/Utilities.js","Views/Sidebar.js","main.js","../../../config-wrap-end-default.js"],"names":[],"mappings":"AAAA;AACA,ACDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACrbA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACVA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACVA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACVA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC72CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACvMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACvBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACxKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AClGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC9GA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACtJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC1WA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACtEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC3FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC9EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACtOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC5JA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC9QA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC3FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC7CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC1KA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACxDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC7BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACXA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACvKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC3CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC1DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC3nBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC9CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACjFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC5LA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC1DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AClCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACxIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AClFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACnDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC1tBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AClOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AChFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC/PA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACnEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACjJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AClaA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC/GA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC1FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACzIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACzGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACvCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC9HA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACxDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACxSA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC9JA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACxZA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC/TA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACjJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC3KA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACjFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AChUA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AClKA;AACA","file":"llms-builder.js","sourcesContent":["(function($){\n","/**\n * @license almond 0.3.3 Copyright jQuery Foundation and other contributors.\n * Released under MIT license, http://github.com/requirejs/almond/LICENSE\n */\n//Going sloppy to avoid 'use strict' string cost, but strict practices should\n//be followed.\n/*global setTimeout: false */\n\nvar requirejs, require, define;\n(function (undef) {\n\tvar main, req, makeMap, handlers,\n\t\tdefined = {},\n\t\twaiting = {},\n\t\tconfig = {},\n\t\tdefining = {},\n\t\thasOwn = Object.prototype.hasOwnProperty,\n\t\taps = [].slice,\n\t\tjsSuffixRegExp = /\\.js$/;\n\n\tfunction hasProp(obj, prop) {\n\t\treturn hasOwn.call(obj, prop);\n\t}\n\n\t/**\n\t * Given a relative module name, like ./something, normalize it to\n\t * a real name that can be mapped to a path.\n\t * @param {String} name the relative name\n\t * @param {String} baseName a real name that the name arg is relative\n\t * to.\n\t * @returns {String} normalized name\n\t */\n\tfunction normalize(name, baseName) {\n\t\tvar nameParts, nameSegment, mapValue, foundMap, lastIndex,\n\t\t\tfoundI, foundStarMap, starI, i, j, part, normalizedBaseParts,\n\t\t\tbaseParts = baseName && baseName.split(\"/\"),\n\t\t\tmap = config.map,\n\t\t\tstarMap = (map && map['*']) || {};\n\n\t\t//Adjust any relative paths.\n\t\tif (name) {\n\t\t\tname = name.split('/');\n\t\t\tlastIndex = name.length - 1;\n\n\t\t\t// If wanting node ID compatibility, strip .js from end\n\t\t\t// of IDs. Have to do this here, and not in nameToUrl\n\t\t\t// because node allows either .js or non .js to map\n\t\t\t// to same file.\n\t\t\tif (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) {\n\t\t\t\tname[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, '');\n\t\t\t}\n\n\t\t\t// Starts with a '.' so need the baseName\n\t\t\tif (name[0].charAt(0) === '.' && baseParts) {\n\t\t\t\t//Convert baseName to array, and lop off the last part,\n\t\t\t\t//so that . matches that 'directory' and not name of the baseName's\n\t\t\t\t//module. For instance, baseName of 'one/two/three', maps to\n\t\t\t\t//'one/two/three.js', but we want the directory, 'one/two' for\n\t\t\t\t//this normalization.\n\t\t\t\tnormalizedBaseParts = baseParts.slice(0, baseParts.length - 1);\n\t\t\t\tname = normalizedBaseParts.concat(name);\n\t\t\t}\n\n\t\t\t//start trimDots\n\t\t\tfor (i = 0; i < name.length; i++) {\n\t\t\t\tpart = name[i];\n\t\t\t\tif (part === '.') {\n\t\t\t\t\tname.splice(i, 1);\n\t\t\t\t\ti -= 1;\n\t\t\t\t} else if (part === '..') {\n\t\t\t\t\t// If at the start, or previous value is still ..,\n\t\t\t\t\t// keep them so that when converted to a path it may\n\t\t\t\t\t// still work when converted to a path, even though\n\t\t\t\t\t// as an ID it is less than ideal. In larger point\n\t\t\t\t\t// releases, may be better to just kick out an error.\n\t\t\t\t\tif (i === 0 || (i === 1 && name[2] === '..') || name[i - 1] === '..') {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t} else if (i > 0) {\n\t\t\t\t\t\tname.splice(i - 1, 2);\n\t\t\t\t\t\ti -= 2;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t//end trimDots\n\n\t\t\tname = name.join('/');\n\t\t}\n\n\t\t//Apply map config if available.\n\t\tif ((baseParts || starMap) && map) {\n\t\t\tnameParts = name.split('/');\n\n\t\t\tfor (i = nameParts.length; i > 0; i -= 1) {\n\t\t\t\tnameSegment = nameParts.slice(0, i).join(\"/\");\n\n\t\t\t\tif (baseParts) {\n\t\t\t\t\t//Find the longest baseName segment match in the config.\n\t\t\t\t\t//So, do joins on the biggest to smallest lengths of baseParts.\n\t\t\t\t\tfor (j = baseParts.length; j > 0; j -= 1) {\n\t\t\t\t\t\tmapValue = map[baseParts.slice(0, j).join('/')];\n\n\t\t\t\t\t\t//baseName segment has config, find if it has one for\n\t\t\t\t\t\t//this name.\n\t\t\t\t\t\tif (mapValue) {\n\t\t\t\t\t\t\tmapValue = mapValue[nameSegment];\n\t\t\t\t\t\t\tif (mapValue) {\n\t\t\t\t\t\t\t\t//Match, update name to the new value.\n\t\t\t\t\t\t\t\tfoundMap = mapValue;\n\t\t\t\t\t\t\t\tfoundI = i;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (foundMap) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t//Check for a star map match, but just hold on to it,\n\t\t\t\t//if there is a shorter segment match later in a matching\n\t\t\t\t//config, then favor over this star map.\n\t\t\t\tif (!foundStarMap && starMap && starMap[nameSegment]) {\n\t\t\t\t\tfoundStarMap = starMap[nameSegment];\n\t\t\t\t\tstarI = i;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!foundMap && foundStarMap) {\n\t\t\t\tfoundMap = foundStarMap;\n\t\t\t\tfoundI = starI;\n\t\t\t}\n\n\t\t\tif (foundMap) {\n\t\t\t\tnameParts.splice(0, foundI, foundMap);\n\t\t\t\tname = nameParts.join('/');\n\t\t\t}\n\t\t}\n\n\t\treturn name;\n\t}\n\n\tfunction makeRequire(relName, forceSync) {\n\t\treturn function () {\n\t\t\t//A version of a require function that passes a moduleName\n\t\t\t//value for items that may need to\n\t\t\t//look up paths relative to the moduleName\n\t\t\tvar args = aps.call(arguments, 0);\n\n\t\t\t//If first arg is not require('string'), and there is only\n\t\t\t//one arg, it is the array form without a callback. Insert\n\t\t\t//a null so that the following concat is correct.\n\t\t\tif (typeof args[0] !== 'string' && args.length === 1) {\n\t\t\t\targs.push(null);\n\t\t\t}\n\t\t\treturn req.apply(undef, args.concat([relName, forceSync]));\n\t\t};\n\t}\n\n\tfunction makeNormalize(relName) {\n\t\treturn function (name) {\n\t\t\treturn normalize(name, relName);\n\t\t};\n\t}\n\n\tfunction makeLoad(depName) {\n\t\treturn function (value) {\n\t\t\tdefined[depName] = value;\n\t\t};\n\t}\n\n\tfunction callDep(name) {\n\t\tif (hasProp(waiting, name)) {\n\t\t\tvar args = waiting[name];\n\t\t\tdelete waiting[name];\n\t\t\tdefining[name] = true;\n\t\t\tmain.apply(undef, args);\n\t\t}\n\n\t\tif (!hasProp(defined, name) && !hasProp(defining, name)) {\n\t\t\tthrow new Error('No ' + name);\n\t\t}\n\t\treturn defined[name];\n\t}\n\n\t//Turns a plugin!resource to [plugin, resource]\n\t//with the plugin being undefined if the name\n\t//did not have a plugin prefix.\n\tfunction splitPrefix(name) {\n\t\tvar prefix,\n\t\t\tindex = name ? name.indexOf('!') : -1;\n\t\tif (index > -1) {\n\t\t\tprefix = name.substring(0, index);\n\t\t\tname = name.substring(index + 1, name.length);\n\t\t}\n\t\treturn [prefix, name];\n\t}\n\n\t//Creates a parts array for a relName where first part is plugin ID,\n\t//second part is resource ID. Assumes relName has already been normalized.\n\tfunction makeRelParts(relName) {\n\t\treturn relName ? splitPrefix(relName) : [];\n\t}\n\n\t/**\n\t * Makes a name map, normalizing the name, and using a plugin\n\t * for normalization if necessary. Grabs a ref to plugin\n\t * too, as an optimization.\n\t */\n\tmakeMap = function (name, relParts) {\n\t\tvar plugin,\n\t\t\tparts = splitPrefix(name),\n\t\t\tprefix = parts[0],\n\t\t\trelResourceName = relParts[1];\n\n\t\tname = parts[1];\n\n\t\tif (prefix) {\n\t\t\tprefix = normalize(prefix, relResourceName);\n\t\t\tplugin = callDep(prefix);\n\t\t}\n\n\t\t//Normalize according\n\t\tif (prefix) {\n\t\t\tif (plugin && plugin.normalize) {\n\t\t\t\tname = plugin.normalize(name, makeNormalize(relResourceName));\n\t\t\t} else {\n\t\t\t\tname = normalize(name, relResourceName);\n\t\t\t}\n\t\t} else {\n\t\t\tname = normalize(name, relResourceName);\n\t\t\tparts = splitPrefix(name);\n\t\t\tprefix = parts[0];\n\t\t\tname = parts[1];\n\t\t\tif (prefix) {\n\t\t\t\tplugin = callDep(prefix);\n\t\t\t}\n\t\t}\n\n\t\t//Using ridiculous property names for space reasons\n\t\treturn {\n\t\t\tf: prefix ? prefix + '!' + name : name, //fullName\n\t\t\tn: name,\n\t\t\tpr: prefix,\n\t\t\tp: plugin\n\t\t};\n\t};\n\n\tfunction makeConfig(name) {\n\t\treturn function () {\n\t\t\treturn (config && config.config && config.config[name]) || {};\n\t\t};\n\t}\n\n\thandlers = {\n\t\trequire: function (name) {\n\t\t\treturn makeRequire(name);\n\t\t},\n\t\texports: function (name) {\n\t\t\tvar e = defined[name];\n\t\t\tif (typeof e !== 'undefined') {\n\t\t\t\treturn e;\n\t\t\t} else {\n\t\t\t\treturn (defined[name] = {});\n\t\t\t}\n\t\t},\n\t\tmodule: function (name) {\n\t\t\treturn {\n\t\t\t\tid: name,\n\t\t\t\turi: '',\n\t\t\t\texports: defined[name],\n\t\t\t\tconfig: makeConfig(name)\n\t\t\t};\n\t\t}\n\t};\n\n\tmain = function (name, deps, callback, relName) {\n\t\tvar cjsModule, depName, ret, map, i, relParts,\n\t\t\targs = [],\n\t\t\tcallbackType = typeof callback,\n\t\t\tusingExports;\n\n\t\t//Use name if no relName\n\t\trelName = relName || name;\n\t\trelParts = makeRelParts(relName);\n\n\t\t//Call the callback to define the module, if necessary.\n\t\tif (callbackType === 'undefined' || callbackType === 'function') {\n\t\t\t//Pull out the defined dependencies and pass the ordered\n\t\t\t//values to the callback.\n\t\t\t//Default to [require, exports, module] if no deps\n\t\t\tdeps = !deps.length && callback.length ? ['require', 'exports', 'module'] : deps;\n\t\t\tfor (i = 0; i < deps.length; i += 1) {\n\t\t\t\tmap = makeMap(deps[i], relParts);\n\t\t\t\tdepName = map.f;\n\n\t\t\t\t//Fast path CommonJS standard dependencies.\n\t\t\t\tif (depName === \"require\") {\n\t\t\t\t\targs[i] = handlers.require(name);\n\t\t\t\t} else if (depName === \"exports\") {\n\t\t\t\t\t//CommonJS module spec 1.1\n\t\t\t\t\targs[i] = handlers.exports(name);\n\t\t\t\t\tusingExports = true;\n\t\t\t\t} else if (depName === \"module\") {\n\t\t\t\t\t//CommonJS module spec 1.1\n\t\t\t\t\tcjsModule = args[i] = handlers.module(name);\n\t\t\t\t} else if (hasProp(defined, depName) ||\n\t\t\t\t\t\t hasProp(waiting, depName) ||\n\t\t\t\t\t\t hasProp(defining, depName)) {\n\t\t\t\t\targs[i] = callDep(depName);\n\t\t\t\t} else if (map.p) {\n\t\t\t\t\tmap.p.load(map.n, makeRequire(relName, true), makeLoad(depName), {});\n\t\t\t\t\targs[i] = defined[depName];\n\t\t\t\t} else {\n\t\t\t\t\tthrow new Error(name + ' missing ' + depName);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tret = callback ? callback.apply(defined[name], args) : undefined;\n\n\t\t\tif (name) {\n\t\t\t\t//If setting exports via \"module\" is in play,\n\t\t\t\t//favor that over return value and exports. After that,\n\t\t\t\t//favor a non-undefined return value over exports use.\n\t\t\t\tif (cjsModule && cjsModule.exports !== undef &&\n\t\t\t\t\t\tcjsModule.exports !== defined[name]) {\n\t\t\t\t\tdefined[name] = cjsModule.exports;\n\t\t\t\t} else if (ret !== undef || !usingExports) {\n\t\t\t\t\t//Use the return value from the function.\n\t\t\t\t\tdefined[name] = ret;\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (name) {\n\t\t\t//May just be an object definition for the module. Only\n\t\t\t//worry about defining if have a module name.\n\t\t\tdefined[name] = callback;\n\t\t}\n\t};\n\n\trequirejs = require = req = function (deps, callback, relName, forceSync, alt) {\n\t\tif (typeof deps === \"string\") {\n\t\t\tif (handlers[deps]) {\n\t\t\t\t//callback in this case is really relName\n\t\t\t\treturn handlers[deps](callback);\n\t\t\t}\n\t\t\t//Just return the module wanted. In this scenario, the\n\t\t\t//deps arg is the module name, and second arg (if passed)\n\t\t\t//is just the relName.\n\t\t\t//Normalize module name, if it contains . or ..\n\t\t\treturn callDep(makeMap(deps, makeRelParts(callback)).f);\n\t\t} else if (!deps.splice) {\n\t\t\t//deps is a config object, not an array.\n\t\t\tconfig = deps;\n\t\t\tif (config.deps) {\n\t\t\t\treq(config.deps, config.callback);\n\t\t\t}\n\t\t\tif (!callback) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (callback.splice) {\n\t\t\t\t//callback is an array, which means it is a dependency list.\n\t\t\t\t//Adjust args if there are dependencies\n\t\t\t\tdeps = callback;\n\t\t\t\tcallback = relName;\n\t\t\t\trelName = null;\n\t\t\t} else {\n\t\t\t\tdeps = undef;\n\t\t\t}\n\t\t}\n\n\t\t//Support require(['a'])\n\t\tcallback = callback || function () {};\n\n\t\t//If relName is a function, it is an errback handler,\n\t\t//so remove it.\n\t\tif (typeof relName === 'function') {\n\t\t\trelName = forceSync;\n\t\t\tforceSync = alt;\n\t\t}\n\n\t\t//Simulate async callback;\n\t\tif (forceSync) {\n\t\t\tmain(undef, deps, callback, relName);\n\t\t} else {\n\t\t\t//Using a non-zero value because of concern for what old browsers\n\t\t\t//do, and latest browsers \"upgrade\" to 4 if lower value is used:\n\t\t\t//http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#dom-windowtimers-settimeout:\n\t\t\t//If want a value immediately, use require('id') instead -- something\n\t\t\t//that works in almond on the global level, but not guaranteed and\n\t\t\t//unlikely to work in other AMD implementations.\n\t\t\tsetTimeout(function () {\n\t\t\t\tmain(undef, deps, callback, relName);\n\t\t\t}, 4);\n\t\t}\n\n\t\treturn req;\n\t};\n\n\t/**\n\t * Just drops the config on the floor, but returns req in case\n\t * the config return value is used.\n\t */\n\treq.config = function (cfg) {\n\t\treturn req(cfg);\n\t};\n\n\t/**\n\t * Expose module registry for debugging and tooling\n\t */\n\trequirejs._defined = defined;\n\n\tdefine = function (name, deps, callback) {\n\t\tif (typeof name !== 'string') {\n\t\t\tthrow new Error('See almond README: incorrect module build, no module name');\n\t\t}\n\n\t\t//This module may not have dependencies\n\t\tif (!deps.splice) {\n\t\t\t//deps is not an array, so probably means\n\t\t\t//an object literal or factory function for\n\t\t\t//the value. Adjust args.\n\t\t\tcallback = deps;\n\t\t\tdeps = [];\n\t\t}\n\n\t\tif (!hasProp(defined, name) && !hasProp(waiting, name)) {\n\t\t\twaiting[name] = [name, deps, callback];\n\t\t}\n\t};\n\n\tdefine.amd = {\n\t\tjQuery: true\n\t};\n}());\n\ndefine(\"vendor/almond\", function(){});\n\n","/**\n * Returns the WordPress-loaded version of Underscore for use with things that need it and use Require.\n * @return obj\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'underscore',[],function() {\n\treturn _;\n} );\n\n","/**\n * Returns the WordPress-loaded version of Backbone for use with things that need it and use Require.\n * @return obj\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'backbone',[],function() {\n\treturn Backbone;\n} );\n\n","/**\n * Returns the WordPress-loaded version of Underscore for use with things that need it and use Require.\n * @return obj\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'jquery',[],function() {\n\treturn jQuery;\n} );\n\n","/*!\n* Backbone.CollectionView, v1.3.4\n* Copyright (c)2013 Rotunda Software, LLC.\n* Distributed under MIT license\n* http://github.com/rotundasoftware/backbone-collection-view\n*/\n\n( function( root, factory ) {\n\t// UMD wrapper\n\tif ( typeof define === 'function' && define.amd ) {\n\t\t// AMD\n\t\tdefine( 'vendor/backbone.collectionView',[ 'underscore', 'backbone', 'jquery' ], factory );\n\t} else if ( typeof exports !== 'undefined' ) {\n\t\t// Node/CommonJS\n\t\tmodule.exports = factory( require('underscore' ), require( 'backbone' ), require( 'backbone' ).$ );\n\t} else {\n\t\t// Browser globals\n\t\tfactory( root._, root.Backbone, ( root.jQuery || root.Zepto || root.$ ) );\n\t}\n}( this, function( _, Backbone, $ ) {\n\tvar mDefaultModelViewConstructor = Backbone.View;\n\n\tvar kDefaultReferenceBy = \"model\";\n\n\tvar kOptionsRequiringRerendering = [ \"collection\", \"modelView\", \"modelViewOptions\", \"itemTemplate\", \"itemTemplateFunction\", \"detachedRendering\" ];\n\n\tvar kStylesForEmptyListCaption = {\n\t\t\"background\" : \"transparent\",\n\t\t\"border\" : \"none\",\n\t\t\"box-shadow\" : \"none\"\n\t};\n\n\tBackbone.CollectionView = Backbone.View.extend( {\n\n\t\ttagName : \"ul\",\n\n\t\tevents : {\n\t\t\t\"mousedown > li, tbody > tr > td\" : \"_listItem_onMousedown\",\n\t\t\t\"dblclick > li, tbody > tr > td\" : \"_listItem_onDoubleClick\",\n\t\t\t\"click\" : \"_listBackground_onClick\",\n\t\t\t\"click ul.collection-view, table.collection-view\" : \"_listBackground_onClick\",\n\t\t\t\"keydown\" : \"_onKeydown\"\n\t\t},\n\n\t\t// only used if Backbone.Courier is available\n\t\tspawnMessages : {\n\t\t\t\"focus\" : \"focus\"\n\t\t},\n\n\t\t//only used if Backbone.Courier is available\n\t\tpassMessages : { \"*\" : \".\" },\n\n\t\t// viewOption definitions with default values.\n\t\tinitializationOptions : [\n\t\t\t{ \"collection\" : null },\n\t\t\t{ \"modelView\" : null },\n\t\t\t{ \"modelViewOptions\" : {} },\n\t\t\t{ \"itemTemplate\" : null },\n\t\t\t{ \"itemTemplateFunction\" : null },\n\t\t\t{ \"selectable\" : true },\n\t\t\t{ \"clickToSelect\" : true },\n\t\t\t{ \"selectableModelsFilter\" : null },\n\t\t\t{ \"visibleModelsFilter\" : null },\n\t\t\t{ \"sortableModelsFilter\" : null },\n\t\t\t{ \"selectMultiple\" : false },\n\t\t\t{ \"clickToToggle\" : false },\n\t\t\t{ \"processKeyEvents\" : true },\n\t\t\t{ \"sortable\" : false },\n\t\t\t{ \"sortableOptions\" : null },\n\t\t\t{ \"reuseModelViews\" : true },\n\t\t\t{ \"detachedRendering\" : false },\n\t\t\t{ \"emptyListCaption\" : null }\n\t\t],\n\n\t\tinitialize : function( options ) {\n\t\t\tBackbone.ViewOptions.add( this, \"initializationOptions\" ); // setup the ViewOptions functionality.\n\t\t\tthis.setOptions( options ); // and make use of any provided options\n\n\t\t\tif( ! this.collection ) this.collection = new Backbone.Collection();\n\n\t\t\tthis._hasBeenRendered = false;\n\n\t\t\tif( this._isBackboneCourierAvailable() ) {\n\t\t\t\tBackbone.Courier.add( this );\n\t\t\t}\n\n\t\t\tthis.$el.data( \"view\", this ); // needed for connected sortable lists\n\t\t\tthis.$el.addClass( \"collection-view collection-list\" ); // collection-list is in there for legacy purposes\n\t\t\tif( this.selectable ) this.$el.addClass( \"selectable\" );\n\n\t\t\tif( this.selectable && this.processKeyEvents )\n\t\t\t\tthis.$el.attr( \"tabindex\", 0 ); // so we get keyboard events\n\n\t\t\tthis.selectedItems = [];\n\n\t\t\tthis._updateItemTemplate();\n\n\t\t\tif( this.collection )\n\t\t\t\tthis._registerCollectionEvents();\n\n\t\t\tthis.viewManager = new ChildViewContainer();\n\t\t},\n\n\t\t_onOptionsChanged : function( changedOptions, originalOptions ) {\n\t\t\tvar _this = this;\n\t\t\tvar rerender = false;\n\n\t\t\t_.each( _.keys( changedOptions ), function( changedOptionKey ) {\n\t\t\t\tvar newVal = changedOptions[ changedOptionKey ];\n\t\t\t\tvar oldVal = originalOptions[ changedOptionKey ];\n\t\t\t\tswitch( changedOptionKey ) {\n\t\t\t\t\tcase \"collection\" :\n\t\t\t\t\t\tif ( newVal !== oldVal ) {\n\t\t\t\t\t\t\t_this.stopListening( oldVal );\n\t\t\t\t\t\t\t_this._registerCollectionEvents();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"selectMultiple\" :\n\t\t\t\t\t\tif( ! newVal && _this.selectedItems.length > 1 )\n\t\t\t\t\t\t\t_this.setSelectedModel( _.first( _this.selectedItems ), { by : \"cid\" } );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"selectable\" :\n\t\t\t\t\t\tif( ! newVal && _this.selectedItems.length > 0 )\n\t\t\t\t\t\t\t_this.setSelectedModels( [] );\n\n\t\t\t\t\t\tif( newVal && this.processKeyEvents ) _this.$el.attr( \"tabindex\", 0 ); // so we get keyboard events\n\t\t\t\t\t\telse _this.$el.removeAttr( \"tabindex\", 0 );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"sortable\" :\n\t\t\t\t\t\tchangedOptions.sortable ? _this._setupSortable() : _this.$el.sortable( \"destroy\" );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"selectableModelsFilter\" :\n\t\t\t\t\t\t_this.reapplyFilter( 'selectableModels' );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"sortableOptions\" :\n\t\t\t\t\t\t_this.$el.sortable( \"destroy\" );\n\t\t\t\t\t\t_this._setupSortable();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"sortableModelsFilter\" :\n\t\t\t\t\t\t_this.reapplyFilter( 'sortableModels' );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"visibleModelsFilter\" :\n\t\t\t\t\t\t_this.reapplyFilter( 'visibleModels' );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"itemTemplate\" :\n\t\t\t\t\t\t_this._updateItemTemplate();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"processKeyEvents\" :\n\t\t\t\t\t\tif( newVal && this.selectable ) _this.$el.attr( \"tabindex\", 0 ); // so we get keyboard events\n\t\t\t\t\t\telse _this.$el.removeAttr( \"tabindex\", 0 );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"modelView\" :\n\t\t\t\t\t\t//need to remove all old view instances\n\t\t\t\t\t\t_this.viewManager.each( function( view ) {\n\t\t\t\t\t\t\t_this.viewManager.remove( view );\n\t\t\t\t\t\t\t// destroy the View itself\n\t\t\t\t\t\t\tview.remove();\n\t\t\t\t\t\t} );\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif( _.contains( kOptionsRequiringRerendering, changedOptionKey ) ) rerender = true;\n\t\t\t} );\n\n\t\t\tif( this._hasBeenRendered && rerender ) {\n\t\t\t\tthis.render();\n\t\t\t}\n\t\t},\n\n\t\tsetOption : function( optionName, optionValue ) { // now is mearly a wrapper around backbone.viewOptions' setOptions()\n\t\t\tvar optionHash = {};\n\t\t\toptionHash[ optionName ] = optionValue;\n\t\t\tthis.setOptions( optionHash );\n\t\t},\n\n\t\tgetSelectedModel : function( options ) {\n\t\t\treturn this.selectedItems.length ? _.first( this.getSelectedModels( options ) ) : null;\n\t\t},\n\n\t\tgetSelectedModels : function ( options ) {\n\t\t\tvar _this = this;\n\n\t\t\toptions = _.extend( {}, {\n\t\t\t\tby : kDefaultReferenceBy\n\t\t\t}, options );\n\n\t\t\tvar referenceBy = options.by;\n\t\t\tvar items = [];\n\n\t\t\tswitch( referenceBy ) {\n\t\t\t\tcase \"id\" :\n\t\t\t\t\t_.each( this.selectedItems, function ( item ) {\n\t\t\t\t\t\titems.push( _this.collection.get( item ).id );\n\t\t\t\t\t} );\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"cid\" :\n\t\t\t\t\titems = items.concat( this.selectedItems );\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"offset\" :\n\t\t\t\t\tvar curLineNumber = 0;\n\n\t\t\t\t\tvar itemElements = this._getVisibleItemEls();\n\n\t\t\t\t\titemElements.each( function() {\n\t\t\t\t\t\tvar thisItemEl = $( this );\n\t\t\t\t\t\tif( thisItemEl.is( \".selected\" ) )\n\t\t\t\t\t\t\titems.push( curLineNumber );\n\t\t\t\t\t\tcurLineNumber++;\n\t\t\t\t\t} );\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"model\" :\n\t\t\t\t\t_.each( this.selectedItems, function ( item ) {\n\t\t\t\t\t\titems.push( _this.collection.get( item ) );\n\t\t\t\t\t} );\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"view\" :\n\t\t\t\t\t_.each( this.selectedItems, function ( item ) {\n\t\t\t\t\t\titems.push( _this.viewManager.findByModel( _this.collection.get( item ) ) );\n\t\t\t\t\t} );\n\t\t\t\t\tbreak;\n\t\t\t\tdefault :\n\t\t\t\t\tthrow new Error( \"Invalid referenceBy option: \" + referenceBy );\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\treturn items;\n\n\t\t},\n\n\t\tsetSelectedModels : function( newSelectedItems, options ) {\n\t\t\tif( ! _.isArray( newSelectedItems ) ) throw \"Invalid parameter value\";\n\t\t\tif( ! this.selectable && newSelectedItems.length > 0 ) return; // used to throw error, but there are some circumstances in which a list can be selectable at times and not at others, don't want to have to worry about catching errors\n\n\t\t\toptions = _.extend( {}, {\n\t\t\t\tsilent : false,\n\t\t\t\tby : kDefaultReferenceBy\n\t\t\t}, options );\n\n\t\t\tvar referenceBy = options.by;\n\t\t\tvar newSelectedCids = [];\n\n\t\t\tswitch( referenceBy ) {\n\t\t\t\tcase \"cid\" :\n\t\t\t\t\tnewSelectedCids = newSelectedItems;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"id\" :\n\t\t\t\t\tthis.collection.each( function( thisModel ) {\n\t\t\t\t\t\tif( _.contains( newSelectedItems, thisModel.id ) ) newSelectedCids.push( thisModel.cid );\n\t\t\t\t\t} );\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"model\" :\n\t\t\t\t\tnewSelectedCids = _.pluck( newSelectedItems, \"cid\" );\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"view\" :\n\t\t\t\t\t_.each( newSelectedItems, function( item ) {\n\t\t\t\t\t\tnewSelectedCids.push( item.model.cid );\n\t\t\t\t\t} );\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"offset\" :\n\t\t\t\t\tvar curLineNumber = 0;\n\t\t\t\t\tvar selectedItems = [];\n\n\t\t\t\t\tvar itemElements = this._getVisibleItemEls();\n\t\t\t\t\titemElements.each( function() {\n\t\t\t\t\t\tvar thisItemEl = $( this );\n\t\t\t\t\t\tif( _.contains( newSelectedItems, curLineNumber ) )\n\t\t\t\t\t\t\tnewSelectedCids.push( thisItemEl.attr( \"data-model-cid\" ) );\n\t\t\t\t\t\tcurLineNumber++;\n\t\t\t\t\t} );\n\t\t\t\t\tbreak;\n\t\t\t\tdefault :\n\t\t\t\t\tthrow new Error( \"Invalid referenceBy option: \" + referenceBy );\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tvar oldSelectedModels = this.getSelectedModels();\n\t\t\tvar oldSelectedCids = _.clone( this.selectedItems );\n\n\t\t\tthis.selectedItems = this._convertStringsToInts( newSelectedCids );\n\t\t\tthis._validateSelection();\n\n\t\t\tvar newSelectedModels = this.getSelectedModels();\n\n\t\t\tif( ! this._containSameElements( oldSelectedCids, this.selectedItems ) )\n\t\t\t{\n\t\t\t\tthis._addSelectedClassToSelectedItems( oldSelectedCids );\n\n\t\t\t\tif( ! options.silent )\n\t\t\t\t{\n\t\t\t\t\tif( this._isBackboneCourierAvailable() ) {\n\t\t\t\t\t\tthis.spawn( \"selectionChanged\", {\n\t\t\t\t\t\t\tselectedModels : newSelectedModels,\n\t\t\t\t\t\t\toldSelectedModels : oldSelectedModels\n\t\t\t\t\t\t} );\n\t\t\t\t\t} else this.trigger( \"selectionChanged\", newSelectedModels, oldSelectedModels );\n\t\t\t\t}\n\n\t\t\t\tthis.updateDependentControls();\n\t\t\t}\n\t\t},\n\n\t\tsetSelectedModel : function( newSelectedItem, options ) {\n\t\t\tif( ! newSelectedItem && newSelectedItem !== 0 )\n\t\t\t\tthis.setSelectedModels( [], options );\n\t\t\telse\n\t\t\t\tthis.setSelectedModels( [ newSelectedItem ], options );\n\t\t},\n\n\t\tgetView : function( reference, options ) {\n\t\t\toptions = _.extend( {}, {\n\t\t\t\tby : kDefaultReferenceBy\n\t\t\t}, options );\n\n\t\t\tswitch( options.by ) {\n\t\t\t\tcase \"id\" :\n\t\t\t\tcase \"cid\" :\n\t\t\t\t\tvar model = this.collection.get( reference ) || null;\n\t\t\t\t\treturn model && this.viewManager.findByModel( model );\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"offset\" :\n\t\t\t\t\tvar itemElements = this._getVisibleItemEls();\n\t\t\t\t\treturn $( itemElements.get( reference ) );\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"model\" :\n\t\t\t\t\treturn this.viewManager.findByModel( reference );\n\t\t\t\t\tbreak;\n\t\t\t\tdefault :\n\t\t\t\t\tthrow new Error( \"Invalid referenceBy option: \" + referenceBy );\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t},\n\n\t\trender : function() {\n\t\t\tvar _this = this;\n\n\t\t\tthis._hasBeenRendered = true;\n\n\t\t\tif( this.selectable ) this._saveSelection();\n\n\t\t\tvar modelViewContainerEl;\n\n\t\t\t// If collection view element is a table and it has a tbody\n\t\t\t// within it, render the model views inside of the tbody\n\t\t\tmodelViewContainerEl = this._getContainerEl();\n\n\t\t\tvar oldViewManager = this.viewManager;\n\t\t\tthis.viewManager = new ChildViewContainer();\n\n\t\t\t// detach each of our subviews that we have already created to represent models\n\t\t\t// in the collection. We are going to re-use the ones that represent models that\n\t\t\t// are still here, instead of creating new ones, so that we don't loose state\n\t\t\t// information in the views.\n\t\t\toldViewManager.each( function( thisModelView ) {\n\t\t\t\t// to boost performance, only detach those views that will be sticking around.\n\t\t\t\t// we won't need the other ones later, so no need to detach them individually.\n\t\t\t\tif( this.reuseModelViews && this.collection.get( thisModelView.model.cid ) ) {\n\t\t\t\t\tthisModelView.$el.detach();\n\t\t\t\t} else thisModelView.remove();\n\t\t\t}, this );\n\n\t\t\tmodelViewContainerEl.empty();\n\t\t\tvar fragmentContainer;\n\n\t\t\tif( this.detachedRendering )\n\t\t\t\tfragmentContainer = document.createDocumentFragment();\n\n\t\t\tthis.collection.each( function( thisModel ) {\n\t\t\t\tvar thisModelView = oldViewManager.findByModelCid( thisModel.cid );\n\t\t\t\tif( ! this.reuseModelViews || _.isUndefined( thisModelView ) ) {\n\t\t\t\t\t// if the model view has not already been created on a\n\t\t\t\t\t// previous render then create and initialize it now.\n\t\t\t\t\tthisModelView = this._createNewModelView( thisModel, this._getModelViewOptions( thisModel ) );\n\t\t\t\t}\n\n\t\t\t\tthis._insertAndRenderModelView( thisModelView, fragmentContainer || modelViewContainerEl );\n\t\t\t}, this );\n\n\t\t\tif( this.detachedRendering )\n\t\t\t\tmodelViewContainerEl.append( fragmentContainer );\n\n\t\t\tif( this.sortable ) this._setupSortable();\n\n\t\t\tthis._showEmptyListCaptionIfAppropriate();\n\n\t\t\tif( this._isBackboneCourierAvailable() )\n\t\t\t\tthis.spawn( \"render\" );\n\t\t\telse this.trigger( \"render\" );\n\n\t\t\tif( this.selectable ) {\n\t\t\t\tthis._restoreSelection();\n\t\t\t\tthis.updateDependentControls();\n\t\t\t}\n\n\t\t\tthis.forceRerenderOnNextSortEvent = false;\n\t\t},\n\n\t\t_showEmptyListCaptionIfAppropriate : function ( ) {\n\t\t\tthis._removeEmptyListCaption();\n\n\t\t\tif( this.emptyListCaption ) {\n\t\t\t\tvar visibleEls = this._getVisibleItemEls();\n\n\t\t\t\tif( visibleEls.length === 0 ) {\n\t\t\t\t\tvar emptyListString;\n\n\t\t\t\t\tif( _.isFunction( this.emptyListCaption ) )\n\t\t\t\t\t\temptyListString = this.emptyListCaption();\n\t\t\t\t\telse\n\t\t\t\t\t\temptyListString = this.emptyListCaption;\n\n\t\t\t\t\tvar $emptyListCaptionEl;\n\t\t\t\t\tvar $varEl = $( \"\" + emptyListString + \" \" );\n\n\t\t\t\t\t// need to wrap the empty caption to make it fit the rendered list structure (either with an li or a tr td)\n\t\t\t\t\tif( this._isRenderedAsList() )\n\t\t\t\t\t\t$emptyListCaptionEl = $varEl.wrapAll( \"
\" ).parent().css( kStylesForEmptyListCaption );\n\t\t\t\t\telse\n\t\t\t\t\t\t$emptyListCaptionEl = $varEl.wrapAll( \" \" ).parent().parent().css( kStylesForEmptyListCaption );\n\n\t\t\t\t\tthis._getContainerEl().append( $emptyListCaptionEl );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t_removeEmptyListCaption : function( ) {\n\t\t\tif( this._isRenderedAsList() )\n\t\t\t\tthis._getContainerEl().find( \"> li > var.empty-list-caption\" ).parent().remove();\n\t\t\telse\n\t\t\t\tthis._getContainerEl().find( \"> tr > td > var.empty-list-caption\" ).parent().parent().remove();\n\t\t},\n\n\t\t// Render a single model view in container object \"parentElOrDocumentFragment\", which is either\n\t\t// a documentFragment or a jquery object. optional arg atIndex is not support for document fragments.\n\t\t_insertAndRenderModelView : function( modelView, parentElOrDocumentFragment, atIndex ) {\n\t\t\tvar thisModelViewWrapped = this._wrapModelView( modelView );\n\n\t\t\tif( parentElOrDocumentFragment.nodeType === 11 ) // if we are inserting into a document fragment, we need to use the DOM appendChild method\n\t\t\t\tparentElOrDocumentFragment.appendChild( thisModelViewWrapped.get( 0 ) );\n\t\t\telse {\n\t\t\t\tvar numberOfModelViewsCurrentlyInDOM = parentElOrDocumentFragment.children().length;\n\t\t\t\tif( ! _.isUndefined( atIndex ) && atIndex >= 0 && atIndex < numberOfModelViewsCurrentlyInDOM )\n\t\t\t\t\t// note this.collection.length might be greater than parentElOrDocumentFragment.children().length here\n\t\t\t\t\tparentElOrDocumentFragment.children().eq( atIndex ).before( thisModelViewWrapped );\n\t\t\t\telse {\n\t\t\t\t\t// if we are attempting to insert a modelView in an position that is beyond what is currently in the\n\t\t\t\t\t// DOM, then make a note that we need to re-render the collection view on the next sort event. If we dont\n\t\t\t\t\t// force this re-render, we can end up with modelViews in the wrong order when the collection defines\n\t\t\t\t\t// a comparator and multiple models are added at once. See https://github.com/rotundasoftware/backbone.collectionView/issues/69\n\t\t\t\t\tif( ! _.isUndefined( atIndex ) && atIndex > numberOfModelViewsCurrentlyInDOM ) this.forceRerenderOnNextSortEvent = true;\n\n\t\t\t\t\tparentElOrDocumentFragment.append( thisModelViewWrapped );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.viewManager.add( modelView );\n\n\t\t\t// we have to render the modelView after it has been put in context, as opposed to in the\n\t\t\t// initialize function of the modelView, because some rendering might be dependent on\n\t\t\t// the modelView's context in the DOM tree. For example, if the modelView stretch()'s itself,\n\t\t\t// it must be in full context in the DOM tree or else the stretch will not behave as intended.\n\t\t\tvar renderResult = modelView.render();\n\n\t\t\t// return false from the view's render function to hide this item\n\t\t\tif( renderResult === false ) {\n\t\t\t\tthisModelViewWrapped.hide();\n\t\t\t\tthisModelViewWrapped.addClass( \"not-visible\" );\n\t\t\t}\n\n\t\t\tvar hideThisModelView = false;\n\t\t\tif( _.isFunction( this.visibleModelsFilter ) )\n\t\t\t\thideThisModelView = ! this.visibleModelsFilter( modelView.model );\n\n\t\t\tif( thisModelViewWrapped.children().length === 1 )\n\t\t\t\tthisModelViewWrapped.toggle( ! hideThisModelView );\n\t\t\telse modelView.$el.toggle( ! hideThisModelView );\n\n\t\t\tthisModelViewWrapped.toggleClass( \"not-visible\", hideThisModelView );\n\n\t\t\tif( ! hideThisModelView && this.emptyListCaption ) this._removeEmptyListCaption();\n\t\t},\n\n\t\tupdateDependentControls : function() {\n\t\t\tif( this._isBackboneCourierAvailable() ) {\n\t\t\t\tthis.spawn( \"updateDependentControls\", {\n\t\t\t\t\tselectedModels : this.getSelectedModels()\n\t\t\t\t} );\n\t\t\t} else this.trigger( \"updateDependentControls\", this.getSelectedModels() );\n\t\t},\n\n\t\t// Override `Backbone.View.remove` to also destroy all Views in `viewManager`\n\t\tremove : function() {\n\t\t\tthis.viewManager.each( function( view ) {\n\t\t\t\tview.remove();\n\t\t\t} );\n\n\t\t\tBackbone.View.prototype.remove.apply( this, arguments );\n\t\t},\n\n\t\treapplyFilter : function( whichFilter ) {\n\t\t\tvar _this = this;\n\n\t\t\tif( ! _.contains( [ \"selectableModels\", \"sortableModels\", \"visibleModels\" ], whichFilter ) ) {\n\t\t\t\tthrow new Error( \"Invalid filter identifier supplied to reapplyFilter: \" + whichFilter );\n\t\t\t}\n\n\t\t\tswitch( whichFilter ) {\n\t\t\t\tcase \"visibleModels\":\n\t\t\t\t\t_this.viewManager.each( function( thisModelView ) {\n\t\t\t\t\t\tvar notVisible = _this.visibleModelsFilter && ! _this.visibleModelsFilter.call( _this, thisModelView.model );\n\n\t\t\t\t\t\tthisModelView.$el.toggleClass( \"not-visible\", notVisible );\n\t\t\t\t\t\tif( _this._modelViewHasWrapperLI( thisModelView ) ) {\n\t\t\t\t\t\t\tthisModelView.$el.closest( \"li\" ).toggleClass( \"not-visible\", notVisible ).toggle( ! notVisible );\n\t\t\t\t\t\t} else thisModelView.$el.toggle( ! notVisible );\n\t\t\t\t\t} );\n\n\t\t\t\t\tthis._showEmptyListCaptionIfAppropriate();\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"sortableModels\":\n\t\t\t\t\t_this.$el.sortable( \"destroy\" );\n\n\t\t\t\t\t_this.viewManager.each( function( thisModelView ) {\n\t\t\t\t\t\tvar notSortable = _this.sortableModelsFilter && ! _this.sortableModelsFilter.call( _this, thisModelView.model );\n\n\t\t\t\t\t\tthisModelView.$el.toggleClass( \"not-sortable\", notSortable );\n\t\t\t\t\t\tif( _this._modelViewHasWrapperLI( thisModelView ) ) {\n\t\t\t\t\t\t\tthisModelView.$el.closest( \"li\" ).toggleClass( \"not-sortable\", notSortable );\n\t\t\t\t\t\t}\n\t\t\t\t\t} );\n\n\t\t\t\t\t_this._setupSortable();\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"selectableModels\":\n\t\t\t\t\t_this.viewManager.each( function( thisModelView ) {\n\t\t\t\t\t\tvar notSelectable = _this.selectableModelsFilter && ! _this.selectableModelsFilter.call( _this, thisModelView.model );\n\n\t\t\t\t\t\tthisModelView.$el.toggleClass( \"not-selectable\", notSelectable );\n\t\t\t\t\t\tif( _this._modelViewHasWrapperLI( thisModelView ) ) {\n\t\t\t\t\t\t\tthisModelView.$el.closest( \"li\" ).toggleClass( \"not-selectable\", notSelectable );\n\t\t\t\t\t\t}\n\t\t\t\t\t} );\n\n\t\t\t\t\t_this._validateSelection();\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t},\n\n\t\t// A method to remove the view relating to model.\n\t\t_removeModelView : function( modelView ) {\n\t\t\tif( this.selectable ) this._saveSelection();\n\n\t\t\tthis.viewManager.remove( modelView ); // Remove the view from the viewManager\n\t\t\tif( this._modelViewHasWrapperLI( modelView ) ) modelView.$el.parent().remove(); // Remove the li wrapper from the DOM\n\t\t\tmodelView.remove(); // Remove the view from the DOM and stop listening to events\n\n\t\t\tif( this.selectable ) this._restoreSelection();\n\n\t\t\tthis._showEmptyListCaptionIfAppropriate();\n\t\t},\n\n\t\t_validateSelectionAndRender : function() {\n\t\t\tthis._validateSelection();\n\t\t\tthis.render();\n\t\t},\n\n\t\t_registerCollectionEvents : function() {\n\n\t\t\tthis.listenTo( this.collection, \"add\", function( model ) {\n\t\t\t\tvar modelView;\n\t\t\t\tif( this._hasBeenRendered ) {\n\t\t\t\t\tmodelView = this._createNewModelView( model, this._getModelViewOptions( model ) );\n\t\t\t\t\tthis._insertAndRenderModelView( modelView, this._getContainerEl(), this.collection.indexOf( model ) );\n\t\t\t\t}\n\n\t\t\t\tif( this._isBackboneCourierAvailable() )\n\t\t\t\t\tthis.spawn( \"add\", modelView );\n\t\t\t\telse this.trigger( \"add\", modelView );\n\t\t\t} );\n\n\t\t\tthis.listenTo( this.collection, \"remove\", function( model ) {\n\t\t\t\tvar modelView;\n\n\t\t\t\tif( this._hasBeenRendered ) {\n\t\t\t\t\tmodelView = this.viewManager.findByModelCid( model.cid );\n\t\t\t\t\tthis._removeModelView( modelView );\n\t\t\t\t}\n\n\t\t\t\tif( this._isBackboneCourierAvailable() )\n\t\t\t\t\tthis.spawn( \"remove\" );\n\t\t\t\telse this.trigger( \"remove\" );\n\t\t\t} );\n\n\t\t\tthis.listenTo( this.collection, \"reset\", function() {\n\t\t\t\tif( this._hasBeenRendered ) this.render();\n\t\t\t\tif( this._isBackboneCourierAvailable() )\n\t\t\t\t\tthis.spawn( \"reset\" );\n\t\t\t\telse this.trigger( \"reset\" );\n\t\t\t} );\n\n\t\t\t// we should not be listening to change events on the model as a default behavior. the models\n\t\t\t// should be responsible for re-rendering themselves if necessary, and if the collection does\n\t\t\t// also need to re-render as a result of a model change, this should be handled by overriding\n\t\t\t// this method. by default the collection view should not re-render in response to model changes\n\t\t\t// this.listenTo( this.collection, \"change\", function( model ) {\n\t\t\t// \tif( this._hasBeenRendered ) this.viewManager.findByModel( model ).render();\n\t\t\t// \tif( this._isBackboneCourierAvailable() )\n\t\t\t// \t\tthis.spawn( \"change\", { model : model } );\n\t\t\t// } );\n\n\t\t\tthis.listenTo( this.collection, \"sort\", function( collection, options ) {\n\t\t\t\tif( this._hasBeenRendered && ( options.add !== true || this.forceRerenderOnNextSortEvent ) ) this.render();\n\t\t\t\tif( this._isBackboneCourierAvailable() )\n\t\t\t\t\tthis.spawn( \"sort\" );\n\t\t\t\telse this.trigger( \"sort\" );\n\t\t\t} );\n\t\t},\n\n\t\t_getContainerEl : function() {\n\t\t\tif ( this._isRenderedAsTable() ) {\n\t\t\t\t// not all tables have a tbody, so we test\n\t\t\t\tvar tbody = this.$el.find( \"> tbody\" );\n\t\t\t\tif ( tbody.length > 0 )\n\t\t\t\t\treturn tbody;\n\t\t\t}\n\t\t\treturn this.$el;\n\t\t},\n\n\t\t_getClickedItemId : function( theEvent ) {\n\t\t\tvar clickedItemId = null;\n\n\t\t\t// important to use currentTarget as opposed to target, since we could be bubbling\n\t\t\t// an event that took place within another collectionList\n\t\t\tvar clickedItemEl = $( theEvent.currentTarget );\n\t\t\tif( clickedItemEl.closest( \".collection-view\" ).get(0) !== this.$el.get(0) ) return;\n\n\t\t\t// determine which list item was clicked. If we clicked in the blank area\n\t\t\t// underneath all the elements, we want to know that too, since in this\n\t\t\t// case we will want to deselect all elements. so check to see if the clicked\n\t\t\t// DOM element is the list itself to find that out.\n\t\t\tvar clickedItem = clickedItemEl.closest( \"[data-model-cid]\" );\n\t\t\tif( clickedItem.length > 0 )\n\t\t\t{\n\t\t\t\tclickedItemId = clickedItem.attr( \"data-model-cid\" );\n\t\t\t\tif( $.isNumeric( clickedItemId ) ) clickedItemId = parseInt( clickedItemId, 10 );\n\t\t\t}\n\n\t\t\treturn clickedItemId;\n\t\t},\n\n\t\t_updateItemTemplate : function() {\n\t\t\tvar itemTemplateHtml;\n\t\t\tif( this.itemTemplate )\n\t\t\t{\n\t\t\t\tif( $( this.itemTemplate ).length === 0 )\n\t\t\t\t\tthrow \"Could not find item template from selector: \" + this.itemTemplate;\n\n\t\t\t\titemTemplateHtml = $( this.itemTemplate ).html();\n\t\t\t}\n\t\t\telse\n\t\t\t\titemTemplateHtml = this.$( \".item-template\" ).html();\n\n\t\t\tif( itemTemplateHtml ) this.itemTemplateFunction = _.template( itemTemplateHtml );\n\n\t\t},\n\n\t\t_validateSelection : function() {\n\t\t\t// note can't use the collection's proxy to underscore because \"cid\" is not an attribute,\n\t\t\t// but an element of the model object itself.\n\t\t\tvar modelReferenceIds = _.pluck( this.collection.models, \"cid\" );\n\t\t\tthis.selectedItems = _.intersection( modelReferenceIds, this.selectedItems );\n\n\t\t\tif( _.isFunction( this.selectableModelsFilter ) )\n\t\t\t{\n\t\t\t\tthis.selectedItems = _.filter( this.selectedItems, function( thisItemId ) {\n\t\t\t\t\treturn this.selectableModelsFilter.call( this, this.collection.get( thisItemId ) );\n\t\t\t\t}, this );\n\t\t\t}\n\t\t},\n\n\t\t_saveSelection : function() {\n\t\t\t// save the current selection. use restoreSelection() to restore the selection to the state it was in the last time saveSelection() was called.\n\t\t\tif( ! this.selectable ) throw \"Attempt to save selection on non-selectable list\";\n\t\t\tthis.savedSelection = {\n\t\t\t\titems : _.clone( this.selectedItems ),\n\t\t\t\toffset : this.getSelectedModel( { by : \"offset\" } )\n\t\t\t};\n\t\t},\n\n\t\t_restoreSelection : function() {\n\t\t\tif( ! this.savedSelection ) throw \"Attempt to restore selection but no selection has been saved!\";\n\n\t\t\t// reset selectedItems to empty so that we \"redraw\" all \"selected\" classes\n\t\t\t// when we set our new selection. We do this because it is likely that our\n\t\t\t// contents have been refreshed, and we have thus lost all old \"selected\" classes.\n\t\t\tthis.setSelectedModels( [], { silent : true } );\n\n\t\t\tif( this.savedSelection.items.length > 0 )\n\t\t\t{\n\t\t\t\t// first try to restore the old selected items using their reference ids.\n\t\t\t\tthis.setSelectedModels( this.savedSelection.items, { by : \"cid\", silent : true } );\n\n\t\t\t\t// all the items with the saved reference ids have been removed from the list.\n\t\t\t\t// ok. try to restore the selection based on the offset that used to be selected.\n\t\t\t\t// this is the expected behavior after a item is deleted from a list (i.e. select\n\t\t\t\t// the line that immediately follows the deleted line).\n\t\t\t\tif( this.selectedItems.length === 0 )\n\t\t\t\t\tthis.setSelectedModel( this.savedSelection.offset, { by : \"offset\" } );\n\n\t\t\t\t// Trigger a selection changed if the previously selected items were not all found\n\t\t\t\tif (this.selectedItems.length !== this.savedSelection.items.length)\n\t\t\t\t{\n\t\t\t\t\tif( this._isBackboneCourierAvailable() ) {\n\t\t\t\t\t\tthis.spawn( \"selectionChanged\", {\n\t\t\t\t\t\t\tselectedModels : this.getSelectedModels(),\n\t\t\t\t\t\t\toldSelectedModels : []\n\t\t\t\t\t\t} );\n\t\t\t\t\t} else this.trigger( \"selectionChanged\", this.getSelectedModels(), [] );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t_addSelectedClassToSelectedItems : function( oldItemsIdsWithSelectedClass ) {\n\t\t\tif( _.isUndefined( oldItemsIdsWithSelectedClass ) ) oldItemsIdsWithSelectedClass = [];\n\n\t\t\t// oldItemsIdsWithSelectedClass is used for optimization purposes only. If this info is supplied then we\n\t\t\t// only have to add / remove the \"selected\" class from those items that \"selected\" state has changed.\n\n\t\t\tvar itemsIdsFromWhichSelectedClassNeedsToBeRemoved = oldItemsIdsWithSelectedClass;\n\t\t\titemsIdsFromWhichSelectedClassNeedsToBeRemoved = _.without( itemsIdsFromWhichSelectedClassNeedsToBeRemoved, this.selectedItems );\n\n\t\t\t_.each( itemsIdsFromWhichSelectedClassNeedsToBeRemoved, function( thisItemId ) {\n\t\t\t\tthis._getContainerEl().find( \"[data-model-cid=\" + thisItemId + \"]\" ).removeClass( \"selected\" );\n\n\t\t\t\tif( this._isRenderedAsList() ) {\n\t\t\t\t\tthis._getContainerEl().find( \"li[data-model-cid=\" + thisItemId + \"] > *\" ).removeClass( \"selected\" );\n\t\t\t\t}\n\t\t\t}, this );\n\n\t\t\tvar itemsIdsFromWhichSelectedClassNeedsToBeAdded = this.selectedItems;\n\t\t\titemsIdsFromWhichSelectedClassNeedsToBeAdded = _.without( itemsIdsFromWhichSelectedClassNeedsToBeAdded, oldItemsIdsWithSelectedClass );\n\n\t\t\t_.each( itemsIdsFromWhichSelectedClassNeedsToBeAdded, function( thisItemId ) {\n\t\t\t\tthis._getContainerEl().find( \"[data-model-cid=\" + thisItemId + \"]\" ).addClass( \"selected\" );\n\n\t\t\t\tif( this._isRenderedAsList() ) {\n\t\t\t\t\tthis._getContainerEl().find( \"li[data-model-cid=\" + thisItemId + \"] > *\" ).addClass( \"selected\" );\n\t\t\t\t}\n\t\t\t}, this );\n\t\t},\n\n\t\t_reorderCollectionBasedOnHTML : function() {\n\n\t\t\tvar _this = this;\n\n\t\t\tthis._getContainerEl().children().each( function() {\n\t\t\t\tvar thisModelCid = $( this ).attr( \"data-model-cid\" );\n\n\t\t\t\tif( thisModelCid )\n\t\t\t\t{\n\t\t\t\t\t// remove the current model and then add it back (at the end of the collection).\n\t\t\t\t\t// When we are done looping through all models, they will be in the correct order.\n\t\t\t\t\tvar thisModel = _this.collection.get( thisModelCid );\n\t\t\t\t\tif( thisModel )\n\t\t\t\t\t{\n\t\t\t\t\t\t_this.collection.remove( thisModel, { silent : true } );\n\t\t\t\t\t\t_this.collection.add( thisModel, { silent : true, sort : ! _this.collection.comparator } );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\tif( this._isBackboneCourierAvailable() ) this.spawn( \"reorder\" );\n\t\t\telse this.collection.trigger( \"reorder\" );\n\n\t\t\tif( this.collection.comparator ) this.collection.sort();\n\n\t\t},\n\n\t\t_getModelViewConstructor : function( thisModel ) {\n\t\t\treturn this.modelView || mDefaultModelViewConstructor;\n\t\t},\n\n\t\t_getModelViewOptions : function( thisModel ) {\n\t\t\tvar modelViewOptions = this.modelViewOptions;\n\t\t\tif( _.isFunction( modelViewOptions ) ) modelViewOptions = modelViewOptions( thisModel );\n\n\t\t\treturn _.extend( { model : thisModel }, modelViewOptions );\n\t\t},\n\n\t\t_createNewModelView : function( model, modelViewOptions ) {\n\t\t\tvar modelViewConstructor = this._getModelViewConstructor( model );\n\t\t\tif( _.isUndefined( modelViewConstructor ) ) throw \"Could not find modelView constructor for model\";\n\n\t\t\tvar newModelView = new( modelViewConstructor )( modelViewOptions );\n\t\t\tnewModelView.collectionListView = newModelView.collectionView = this; // collectionListView for legacy\n\n\t\t\treturn newModelView;\n\t\t},\n\n\t\t_wrapModelView : function( modelView ) {\n\t\t\tvar _this = this;\n\n\t\t\t// we use items client ids as opposed to real ids, since we may not have a representation\n\t\t\t// of these models on the server\n\t\t\tvar modelViewWrapperEl;\n\n\t\t\tif( this._isRenderedAsTable() ) {\n\t\t\t\t// if we are rendering the collection in a table, the template $el is a tr so we just need to set the data-model-cid\n\t\t\t\tmodelViewWrapperEl = modelView.$el;\n\t\t\t\tmodelView.$el.attr( \"data-model-cid\", modelView.model.cid );\n\t\t\t}\n\t\t\telse if( this._isRenderedAsList() ) {\n\t\t\t\t// if we are rendering the collection in a list, we need wrap each item in an (if its not already an )\n\t\t\t\t// and set the data-model-cid\n\t\t\t\tif( modelView.$el.is( \"li\" ) ) {\n\t\t\t\t\tmodelViewWrapperEl = modelView.$el;\n\t\t\t\t\tmodelView.$el.attr( \"data-model-cid\", modelView.model.cid );\n\t\t\t\t} else {\n\t\t\t\t\tmodelViewWrapperEl = modelView.$el.wrapAll( \" \" ).parent();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif( _.isFunction( this.sortableModelsFilter ) )\n\t\t\t\tif( ! this.sortableModelsFilter.call( _this, modelView.model ) ) {\n\t\t\t\t\tmodelViewWrapperEl.addClass( \"not-sortable\" );\n\t\t\t\t\tmodelView.$el.addClass( \"not-selectable\" );\n\t\t\t\t}\n\n\t\t\tif( _.isFunction( this.selectableModelsFilter ) )\n\t\t\t\tif( ! this.selectableModelsFilter.call( _this, modelView.model ) ) {\n\t\t\t\t\tmodelViewWrapperEl.addClass( \"not-selectable\" );\n\t\t\t\t\tmodelView.$el.addClass( \"not-selectable\" );\n\t\t\t\t}\n\n\t\t\treturn modelViewWrapperEl;\n\t\t},\n\n\t\t_convertStringsToInts : function( theArray ) {\n\t\t\treturn _.map( theArray, function( thisEl ) {\n\t\t\t\tif( ! _.isString( thisEl ) ) return thisEl;\n\t\t\t\tvar thisElAsNumber = parseInt( thisEl, 10 );\n\t\t\t\treturn( thisElAsNumber == thisEl ? thisElAsNumber : thisEl );\n\t\t\t} );\n\t\t},\n\n\t\t_containSameElements : function( arrayA, arrayB ) {\n\t\t\tif( arrayA.length != arrayB.length ) return false;\n\t\t\tvar intersectionSize = _.intersection( arrayA, arrayB ).length;\n\t\t\treturn intersectionSize == arrayA.length; // and must also equal arrayB.length, since arrayA.length == arrayB.length\n\t\t},\n\n\t\t_isRenderedAsTable : function() {\n\t\t\treturn this.$el.prop( \"tagName\" ).toLowerCase() === \"table\";\n\t\t},\n\n\t\t_isRenderedAsList : function() {\n\t\t\treturn ! this._isRenderedAsTable();\n\t\t},\n\n\t\t_modelViewHasWrapperLI : function( modelView ) {\n\t\t\treturn this._isRenderedAsList() && ! modelView.$el.is( \"li\" );\n\t\t},\n\n\t\t// Returns the wrapper HTML element for each visible modelView.\n\t\t// When rendering in a table context, the returned elements are the $el of each modelView.\n\t\t// When rendering in a list context,\n\t\t// If the $el of the modelView is an , the returned elements are the $el of each modelView.\n\t\t// Otherwise, the returned elements are the 's the collectionView wrapped around each modelView $el.\n\t\t_getVisibleItemEls : function() {\n\t\t\tvar itemElements = [];\n\t\t\titemElements = this._getContainerEl().find( \"> [data-model-cid]:not(.not-visible)\" );\n\n\t\t\treturn itemElements;\n\t\t},\n\n\t\t_charCodes : {\n\t\t\tupArrow : 38,\n\t\t\tdownArrow : 40\n\t\t},\n\n\t\t_isBackboneCourierAvailable : function() {\n\t\t\treturn !_.isUndefined( Backbone.Courier );\n\t\t},\n\n\t\t_setupSortable : function() {\n\t\t\tvar sortableOptions = _.extend( {\n\t\t\t\taxis : \"y\",\n\t\t\t\tdistance : 10,\n\t\t\t\tforcePlaceholderSize : true,\n\t\t\t\titems : this._isRenderedAsTable() ? \"> tbody > tr:not(.not-sortable)\" : \"> li:not(.not-sortable)\",\n\t\t\t\tstart : _.bind( this._sortStart, this ),\n\t\t\t\tchange : _.bind( this._sortChange, this ),\n\t\t\t\tstop : _.bind( this._sortStop, this ),\n\t\t\t\treceive : _.bind( this._receive, this ),\n\t\t\t\tover : _.bind( this._over, this )\n\t\t\t}, _.result( this, \"sortableOptions\" ) );\n\n\t\t\tthis.$el = this.$el.sortable( sortableOptions );\n\t\t\t//this.$el.sortable( \"enable\" ); // in case it was disabled previously\n\t\t},\n\n\t\t_sortStart : function( event, ui ) {\n\t\t\tvar modelBeingSorted = this.collection.get( ui.item.attr( \"data-model-cid\" ) );\n\t\t\tif( this._isBackboneCourierAvailable() )\n\t\t\t\tthis.spawn( \"sortStart\", { modelBeingSorted : modelBeingSorted } );\n\t\t\telse this.trigger( \"sortStart\", modelBeingSorted );\n\t\t},\n\n\t\t_sortChange : function( event, ui ) {\n\t\t\tvar modelBeingSorted = this.collection.get( ui.item.attr( \"data-model-cid\" ) );\n\n\t\t\tif( this._isBackboneCourierAvailable() )\n\t\t\t\tthis.spawn( \"sortChange\", { modelBeingSorted : modelBeingSorted } );\n\t\t\telse this.trigger( \"sortChange\", modelBeingSorted );\n\t\t},\n\n\t\t_sortStop : function( event, ui ) {\n\t\t\tvar modelBeingSorted = this.collection.get( ui.item.attr( \"data-model-cid\" ) );\n\t\t\tvar modelViewContainerEl = this._getContainerEl();\n\t\t\tvar newIndex = modelViewContainerEl.children().index( ui.item );\n\n\t\t\tif( newIndex == -1 && modelBeingSorted ) {\n\t\t\t\t// the element was removed from this list. can happen if this sortable is connected\n\t\t\t\t// to another sortable, and the item was dropped into the other sortable.\n\t\t\t\tthis.collection.remove( modelBeingSorted );\n\t\t\t}\n\n\t\t\tif( ! modelBeingSorted ) return; // something is wacky. we don't mess with this case, preferring to guarantee that we can always provide a reference to the model\n\n\t\t\tthis._reorderCollectionBasedOnHTML();\n\t\t\tthis.updateDependentControls();\n\n\t\t\tif( this._isBackboneCourierAvailable() )\n\t\t\t\tthis.spawn( \"sortStop\", { modelBeingSorted : modelBeingSorted, newIndex : newIndex } );\n\t\t\telse this.trigger( \"sortStop\", modelBeingSorted, newIndex );\n\t\t},\n\n\t\t_receive : function( event, ui ) {\n\n\t\t\tvar senderListEl = ui.sender;\n\t\t\tvar senderCollectionListView = senderListEl.data( \"view\" );\n\t\t\tif( ! senderCollectionListView || ! senderCollectionListView.collection ) return;\n\n\t\t\tvar newIndex = this._getContainerEl().children().index( ui.item );\n\t\t\tvar modelReceived = senderCollectionListView.collection.get( ui.item.attr( \"data-model-cid\" ) );\n\t\t\tsenderCollectionListView.collection.remove( modelReceived );\n\t\t\tthis.collection.add( modelReceived, { at : newIndex } );\n\t\t\tmodelReceived.collection = this.collection; // otherwise will not get properly set, since modelReceived.collection might already have a value.\n\t\t\tthis.setSelectedModel( modelReceived );\n\t\t},\n\n\t\t_over : function( event, ui ) {\n\t\t\t// when an item is being dragged into the sortable,\n\t\t\t// hide the empty list caption if it exists\n\t\t\tthis._getContainerEl().find( \"> var.empty-list-caption\" ).hide();\n\t\t},\n\n\t\t_onKeydown : function( event ) {\n\t\t\tif( ! this.processKeyEvents ) return true;\n\n\t\t\tvar trap = false;\n\n\t\t\tif( this.getSelectedModels( { by : \"offset\" } ).length == 1 )\n\t\t\t{\n\t\t\t\t// need to trap down and up arrows or else the browser\n\t\t\t\t// will end up scrolling a autoscroll div.\n\n\t\t\t\tvar currentOffset = this.getSelectedModel( { by : \"offset\" } );\n\t\t\t\tif( event.which === this._charCodes.upArrow && currentOffset !== 0 )\n\t\t\t\t{\n\t\t\t\t\tthis.setSelectedModel( currentOffset - 1, { by : \"offset\" } );\n\t\t\t\t\ttrap = true;\n\t\t\t\t}\n\t\t\t\telse if( event.which === this._charCodes.downArrow && currentOffset !== this.collection.length - 1 )\n\t\t\t\t{\n\t\t\t\t\tthis.setSelectedModel( currentOffset + 1, { by : \"offset\" } );\n\t\t\t\t\ttrap = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn ! trap;\n\t\t},\n\n\t\t_listItem_onMousedown : function( theEvent ) {\n\t\t\tvar clickedItemId = this._getClickedItemId( theEvent );\n\n\t\t\tif( clickedItemId ) {\n\t\t\t\tvar clickedModel = this.collection.get( clickedItemId );\n\t\t\t\tif( this._isBackboneCourierAvailable() ) {\n\t\t\t\t\tvar data = {\n\t\t\t\t\t\tclickedModel : clickedModel,\n\t\t\t\t\t\tmetaKeyPressed : theEvent.ctrlKey || theEvent.metaKey\n\t\t\t\t\t};\n\n\t\t\t\t\t_.each( [ 'preventDefault', 'stopPropagation', 'stopImmediatePropagation' ], function( thisMethod ) {\n\t\t\t\t\t\tdata[ thisMethod ] = function() {\n\t\t\t\t\t\t\ttheEvent[ thisMethod ]();\n\t\t\t\t\t\t};\n\t\t\t\t\t} );\n\n\t\t\t\t\tthis.spawn( \"click\", data );\n\t\t\t\t}\n\t\t\t\telse this.trigger( \"click\", clickedModel );\n\t\t\t}\n\n\t\t\tif( ! this.selectable || ! this.clickToSelect ) return;\n\n\t\t\tif( clickedItemId )\n\t\t\t{\n\t\t\t\t// Exit if an unselectable item was clicked\n\t\t\t\tif( _.isFunction( this.selectableModelsFilter ) &&\n\t\t\t\t\t! this.selectableModelsFilter.call( this, this.collection.get( clickedItemId ) ) )\n\t\t\t\t{\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// a selectable list item was clicked\n\t\t\t\tif( this.selectMultiple && theEvent.shiftKey )\n\t\t\t\t{\n\t\t\t\t\tvar firstSelectedItemIndex = -1;\n\n\t\t\t\t\tif( this.selectedItems.length > 0 )\n\t\t\t\t\t{\n\t\t\t\t\t\tthis.collection.find( function( thisItemModel ) {\n\t\t\t\t\t\t\tfirstSelectedItemIndex++;\n\n\t\t\t\t\t\t\t// exit when we find our first selected element\n\t\t\t\t\t\t\treturn _.contains( this.selectedItems, thisItemModel.cid );\n\t\t\t\t\t\t}, this );\n\t\t\t\t\t}\n\n\t\t\t\t\tvar clickedItemIndex = -1;\n\t\t\t\t\tthis.collection.find( function( thisItemModel ) {\n\t\t\t\t\t\tclickedItemIndex++;\n\n\t\t\t\t\t\t// exit when we find the clicked element\n\t\t\t\t\t\treturn thisItemModel.cid == clickedItemId;\n\t\t\t\t\t}, this );\n\n\t\t\t\t\tvar shiftKeyRootSelectedItemIndex = firstSelectedItemIndex == -1 ? clickedItemIndex : firstSelectedItemIndex;\n\t\t\t\t\tvar minSelectedItemIndex = Math.min( clickedItemIndex, shiftKeyRootSelectedItemIndex );\n\t\t\t\t\tvar maxSelectedItemIndex = Math.max( clickedItemIndex, shiftKeyRootSelectedItemIndex );\n\n\t\t\t\t\tvar newSelectedItems = [];\n\t\t\t\t\tfor( var thisIndex = minSelectedItemIndex; thisIndex <= maxSelectedItemIndex; thisIndex ++ )\n\t\t\t\t\t\tnewSelectedItems.push( this.collection.at( thisIndex ).cid );\n\t\t\t\t\tthis.setSelectedModels( newSelectedItems, { by : \"cid\" } );\n\n\t\t\t\t\t// shift clicking will usually highlight selectable text, which we do not want.\n\t\t\t\t\t// this is a cross browser (hopefully) snippet that deselects all text selection.\n\t\t\t\t\tif( document.selection && document.selection.empty )\n\t\t\t\t\t\tdocument.selection.empty();\n\t\t\t\t\telse if(window.getSelection) {\n\t\t\t\t\t\tvar sel = window.getSelection();\n\t\t\t\t\t\tif( sel && sel.removeAllRanges )\n\t\t\t\t\t\t\tsel.removeAllRanges();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if( ( this.selectMultiple || _.contains( this.selectedItems, clickedItemId ) ) && ( this.clickToToggle || theEvent.metaKey || theEvent.ctrlKey ) )\n\t\t\t\t{\n\t\t\t\t\tif( _.contains( this.selectedItems, clickedItemId ) )\n\t\t\t\t\t\tthis.setSelectedModels( _.without( this.selectedItems, clickedItemId ), { by : \"cid\" } );\n\t\t\t\t\telse this.setSelectedModels( _.union( this.selectedItems, [clickedItemId] ), { by : \"cid\" } );\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tthis.setSelectedModels( [ clickedItemId ], { by : \"cid\" } );\n\t\t\t}\n\t\t\telse\n\t\t\t\t// the blank area of the list was clicked\n\t\t\t\tthis.setSelectedModels( [] );\n\n\t\t},\n\n\t\t_listItem_onDoubleClick : function( theEvent ) {\n\n\t\t\tvar clickedItemId = this._getClickedItemId( theEvent );\n\n\t\t\tif( clickedItemId )\n\t\t\t{\n\t\t\t\tvar clickedModel = this.collection.get( clickedItemId );\n\n\t\t\t\tif( this._isBackboneCourierAvailable() )\n\t\t\t\t\tthis.spawn( \"doubleClick\", { clickedModel : clickedModel, metaKeyPressed : theEvent.ctrlKey || theEvent.metaKey } );\n\t\t\t\telse this.trigger( \"doubleClick\", clickedModel );\n\t\t\t}\n\t\t},\n\n\t\t_listBackground_onClick : function( theEvent ) {\n\t\t\tif( ! this.selectable || ! this.clickToSelect ) return;\n\t\t\tif( ! $( theEvent.target ).is( \".collection-view\" ) ) return;\n\n\t\t\tthis.setSelectedModels( [] );\n\t\t}\n\n\t}, {\n\t\tsetDefaultModelViewConstructor : function( theConstructor ) {\n\t\t\tmDefaultModelViewConstructor = theConstructor;\n\t\t}\n\t});\n\n\t/*\n\t* Backbone.ViewOptions, v0.2.4\n\t* Copyright (c)2014 Rotunda Software, LLC.\n\t* Distributed under MIT license\n\t* http://github.com/rotundasoftware/backbone.viewOptions\n\t*/\n\n\tBackbone.ViewOptions = {};\n\n\tBackbone.ViewOptions.add = function( view, optionsDeclarationsProperty ) {\n\t\tif( _.isUndefined( optionsDeclarationsProperty ) ) optionsDeclarationsProperty = \"options\";\n\n\t\t// ****************** Public methods added to view ******************\n\n\t\tview.setOptions = function( options ) {\n\t\t\tvar _this = this;\n\t\t\tvar optionsThatWereChanged = {};\n\t\t\tvar optionsThatWereChangedPreviousValues = {};\n\n\t\t\tvar optionDeclarations = _.result( this, optionsDeclarationsProperty );\n\n\t\t\tif( ! _.isUndefined( optionDeclarations ) ) {\n\t\t\t\tvar normalizedOptionDeclarations = _normalizeOptionDeclarations( optionDeclarations );\n\n\t\t\t\t_.each( normalizedOptionDeclarations, function( thisOptionProperties, thisOptionName ) {\n\t\t\t\t\tvar thisOptionRequired = thisOptionProperties.required;\n\t\t\t\t\tvar thisOptionDefaultValue = thisOptionProperties.defaultValue;\n\n\t\t\t\t\tif( thisOptionRequired ) {\n\t\t\t\t\t\t// note we do not throw an error if a required option is not supplied, but it is\n\t\t\t\t\t\t// found on the object itself (due to a prior call of view.setOptions, most likely)\n\n\t\t\t\t\t\tif( ( ! options || ! _.contains( _.keys( options ), thisOptionName ) ) && _.isUndefined( _this[ thisOptionName ] ) )\n\t\t\t\t\t\t\tthrow new Error( \"Required option \\\"\" + thisOptionName + \"\\\" was not supplied.\" );\n\n\t\t\t\t\t\tif( options && _.contains( _.keys( options ), thisOptionName ) && _.isUndefined( options[ thisOptionName ] ) )\n\t\t\t\t\t\t\tthrow new Error( \"Required option \\\"\" + thisOptionName + \"\\\" can not be set to undefined.\" );\n\t\t\t\t\t}\n\n\t\t\t\t\t// attach the supplied value of this option, or the appropriate default value, to the view object\n\t\t\t\t\tif( options && thisOptionName in options && ! _.isUndefined( options[ thisOptionName ] ) ) {\n\t\t\t\t\t\tvar oldValue = _this[ thisOptionName ];\n\t\t\t\t\t\tvar newValue = options[ thisOptionName ];\n\t\t\t\t\t\t// if this option already exists on the view, and the new value is different,\n\t\t\t\t\t\t// make a note that we will be changing it\n\t\t\t\t\t\tif( ! _.isUndefined( oldValue ) && oldValue !== newValue ) {\n\t\t\t\t\t\t\toptionsThatWereChangedPreviousValues[ thisOptionName ] = oldValue;\n\t\t\t\t\t\t\toptionsThatWereChanged[ thisOptionName ] = newValue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t_this[ thisOptionName ] = newValue;\n\t\t\t\t\t\t// note we do NOT delete the option off the options object here so that\n\t\t\t\t\t\t// multiple views can be passed the same options object without issue.\n\t\t\t\t\t}\n\t\t\t\t\telse if( _.isUndefined( _this[ thisOptionName ] ) ) {\n\t\t\t\t\t\t// note defaults do not write over any existing properties on the view itself.\n\t\t\t\t\t\t_this[ thisOptionName ] = thisOptionDefaultValue;\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\tif( _.keys( optionsThatWereChanged ).length > 0 ) {\n\t\t\t\tif( _.isFunction( _this.onOptionsChanged ) )\n\t\t\t\t\t_this.onOptionsChanged( optionsThatWereChanged, optionsThatWereChangedPreviousValues );\n\t\t\t\telse if( _.isFunction( _this._onOptionsChanged ) )\n\t\t\t\t\t_this._onOptionsChanged( optionsThatWereChanged, optionsThatWereChangedPreviousValues );\n\t\t\t}\n\t\t};\n\n\t\tview.getOptions = function() {\n\t\t\tvar optionDeclarations = _.result( this, optionsDeclarationsProperty );\n\t\t\tif( _.isUndefined( optionDeclarations ) ) return {};\n\n\t\t\tvar normalizedOptionDeclarations = _normalizeOptionDeclarations( optionDeclarations );\n\t\t\tvar optionsNames = _.keys( normalizedOptionDeclarations );\n\n\t\t\treturn _.pick( this, optionsNames );\n\t\t};\n\t};\n\n\t// ****************** Private Utility Functions ******************\n\n\tfunction _normalizeOptionDeclarations( optionDeclarations ) {\n\t\t// convert our short-hand option syntax (with exclamation marks, etc.)\n\t\t// to a simple array of standard option declaration objects.\n\n\t\tvar normalizedOptionDeclarations = {};\n\n\t\tif( ! _.isArray( optionDeclarations ) ) throw new Error( \"Option declarations must be an array.\" );\n\n\t\t_.each( optionDeclarations, function( thisOptionDeclaration ) {\n\t\t\tvar thisOptionName, thisOptionRequired, thisOptionDefaultValue;\n\n\t\t\tthisOptionRequired = false;\n\t\t\tthisOptionDefaultValue = undefined;\n\n\t\t\tif( _.isString( thisOptionDeclaration ) )\n\t\t\t\tthisOptionName = thisOptionDeclaration;\n\t\t\telse if( _.isObject( thisOptionDeclaration ) ) {\n\t\t\t\tthisOptionName = _.first( _.keys( thisOptionDeclaration ) );\n\t\t\t\tif( _.isFunction( thisOptionDeclaration[ thisOptionName ] ) )\n\t\t\t\t\tthisOptionDefaultValue = thisOptionDeclaration[ thisOptionName ];\n\t\t\t\telse\n\t\t\t\t\tthisOptionDefaultValue = _.clone( thisOptionDeclaration[ thisOptionName ] );\n\t\t\t}\n\t\t\telse throw new Error( \"Each element in the option declarations array must be either a string or an object.\" );\n\n\t\t\tif( thisOptionName[ thisOptionName.length - 1 ] === \"!\" ) {\n\t\t\t\tthisOptionRequired = true;\n\t\t\t\tthisOptionName = thisOptionName.slice( 0, thisOptionName.length - 1 );\n\t\t\t}\n\n\t\t\tnormalizedOptionDeclarations[ thisOptionName ] = normalizedOptionDeclarations[ thisOptionName ] || {};\n\t\t\tnormalizedOptionDeclarations[ thisOptionName ].required = thisOptionRequired;\n\t\t\tif( ! _.isUndefined( thisOptionDefaultValue ) ) normalizedOptionDeclarations[ thisOptionName ].defaultValue = thisOptionDefaultValue;\n\t\t} );\n\n\t\treturn normalizedOptionDeclarations;\n\t}\n\n\n\t// Backbone.BabySitter\n\t// -------------------\n\t// v0.0.6\n\t//\n\t// Copyright (c)2013 Derick Bailey, Muted Solutions, LLC.\n\t// Distributed under MIT license\n\t//\n\t// http://github.com/babysitterjs/backbone.babysitter\n\n\t// Backbone.ChildViewContainer\n\t// ---------------------------\n\t//\n\t// Provide a container to store, retrieve and\n\t// shut down child views.\n\n\tChildViewContainer = (function(Backbone, _){\n\n\t\t// Container Constructor\n\t\t// ---------------------\n\n\t\tvar Container = function(views){\n\t\t\tthis._views = {};\n\t\t\tthis._indexByModel = {};\n\t\t\tthis._indexByCustom = {};\n\t\t\tthis._updateLength();\n\n\t\t\t_.each(views, this.add, this);\n\t\t};\n\n\t\t// Container Methods\n\t\t// -----------------\n\n\t\t_.extend(Container.prototype, {\n\n\t\t\t// Add a view to this container. Stores the view\n\t\t\t// by `cid` and makes it searchable by the model\n\t\t\t// cid (and model itself). Optionally specify\n\t\t\t// a custom key to store an retrieve the view.\n\t\t\tadd: function(view, customIndex){\n\t\t\t\tvar viewCid = view.cid;\n\n\t\t\t\t// store the view\n\t\t\t\tthis._views[viewCid] = view;\n\n\t\t\t\t// index it by model\n\t\t\t\tif (view.model){\n\t\t\t\t\tthis._indexByModel[view.model.cid] = viewCid;\n\t\t\t\t}\n\n\t\t\t\t// index by custom\n\t\t\t\tif (customIndex){\n\t\t\t\t\tthis._indexByCustom[customIndex] = viewCid;\n\t\t\t\t}\n\n\t\t\t\tthis._updateLength();\n\t\t\t},\n\n\t\t\t// Find a view by the model that was attached to\n\t\t\t// it. Uses the model's `cid` to find it.\n\t\t\tfindByModel: function(model){\n\t\t\t\treturn this.findByModelCid(model.cid);\n\t\t\t},\n\n\t\t\t// Find a view by the `cid` of the model that was attached to\n\t\t\t// it. Uses the model's `cid` to find the view `cid` and\n\t\t\t// retrieve the view using it.\n\t\t\tfindByModelCid: function(modelCid){\n\t\t\t\tvar viewCid = this._indexByModel[modelCid];\n\t\t\t\treturn this.findByCid(viewCid);\n\t\t\t},\n\n\t\t\t// Find a view by a custom indexer.\n\t\t\tfindByCustom: function(index){\n\t\t\t\tvar viewCid = this._indexByCustom[index];\n\t\t\t\treturn this.findByCid(viewCid);\n\t\t\t},\n\n\t\t\t// Find by index. This is not guaranteed to be a\n\t\t\t// stable index.\n\t\t\tfindByIndex: function(index){\n\t\t\t\treturn _.values(this._views)[index];\n\t\t\t},\n\n\t\t\t// retrieve a view by it's `cid` directly\n\t\t\tfindByCid: function(cid){\n\t\t\t\treturn this._views[cid];\n\t\t\t},\n\n\t\t\tfindIndexByCid : function( cid ) {\n\t\t\t\tvar index = -1;\n\t\t\t\tvar view = _.find( this._views, function ( view ) {\n\t\t\t\t\tindex++;\n\t\t\t\t\tif( view.model.cid == cid )\n\t\t\t\t\t\treturn view;\n\t\t\t\t} );\n\t\t\t\treturn ( view ) ? index : -1;\n\t\t\t},\n\n\t\t\t// Remove a view\n\t\t\tremove: function(view){\n\t\t\t\tvar viewCid = view.cid;\n\n\t\t\t\t// delete model index\n\t\t\t\tif (view.model){\n\t\t\t\t\tdelete this._indexByModel[view.model.cid];\n\t\t\t\t}\n\n\t\t\t\t// delete custom index\n\t\t\t\t_.any(this._indexByCustom, function(cid, key) {\n\t\t\t\t\tif (cid === viewCid) {\n\t\t\t\t\t\tdelete this._indexByCustom[key];\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}, this);\n\n\t\t\t\t// remove the view from the container\n\t\t\t\tdelete this._views[viewCid];\n\n\t\t\t\t// update the length\n\t\t\t\tthis._updateLength();\n\t\t\t},\n\n\t\t\t// Call a method on every view in the container,\n\t\t\t// passing parameters to the call method one at a\n\t\t\t// time, like `function.call`.\n\t\t\tcall: function(method){\n\t\t\t\tthis.apply(method, _.tail(arguments));\n\t\t\t},\n\n\t\t\t// Apply a method on every view in the container,\n\t\t\t// passing parameters to the call method one at a\n\t\t\t// time, like `function.apply`.\n\t\t\tapply: function(method, args){\n\t\t\t\t_.each(this._views, function(view){\n\t\t\t\t\tif (_.isFunction(view[method])){\n\t\t\t\t\t\tview[method].apply(view, args || []);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t},\n\n\t\t\t// Update the `.length` attribute on this container\n\t\t\t_updateLength: function(){\n\t\t\t\tthis.length = _.size(this._views);\n\t\t\t}\n\t\t});\n\n\t\t// Borrowing this code from Backbone.Collection:\n\t\t// http://backbonejs.org/docs/backbone.html#section-106\n\t\t//\n\t\t// Mix in methods from Underscore, for iteration, and other\n\t\t// collection related features.\n\t\tvar methods = ['forEach', 'each', 'map', 'find', 'detect', 'filter',\n\t\t\t 'select', 'reject', 'every', 'all', 'some', 'any', 'include',\n\t\t\t 'contains', 'invoke', 'toArray', 'first', 'initial', 'rest',\n\t\t\t 'last', 'without', 'isEmpty', 'pluck'];\n\n\t\t_.each(methods, function(method) {\n\t\t\tContainer.prototype[method] = function() {\n\t\t\t\tvar views = _.values(this._views);\n\t\t\t\tvar args = [views].concat(_.toArray(arguments));\n\t\t\t\treturn _[method].apply(_, args);\n\t\t\t};\n\t\t});\n\n\t\t// return the public API\n\t\treturn Container;\n\t})(Backbone, _);\n\n\treturn Backbone.CollectionView;\n} ) );\n\n","//\n// backbone.trackit - 0.1.0\n// The MIT License\n// Copyright (c) 2013 The New York Times, CMS Group, Matthew DeLambo \n//\n(function() {\n\n\t// Unsaved Record Keeping\n\t// ----------------------\n\n\t// Collection of all models in an app that have unsaved changes.\n\tvar unsavedModels = [];\n\n\t// If the given model has unsaved changes then add it to\n\t// the `unsavedModels` collection, otherwise remove it.\n\tvar updateUnsavedModels = function(model) {\n\t\tif (!_.isEmpty(model._unsavedChanges)) {\n\t\t\tif (!_.findWhere(unsavedModels, {cid:model.cid})) unsavedModels.push(model);\n\t\t} else {\n\t\t\tunsavedModels = _.filter(unsavedModels, function(m) { return model.cid != m.cid; });\n\t\t}\n\t};\n\n\t// Unload Handlers\n\t// ---------------\n\n\t// Helper which returns a prompt message for an unload handler.\n\t// Uses the given function name (one of the callback names\n\t// from the `model.unsaved` configuration hash) to evaluate\n\t// whether a prompt is needed/returned.\n\tvar getPrompt = function(fnName) {\n\t\tvar prompt, args = _.rest(arguments);\n\t\t// Evaluate and return a boolean result. The given `fn` may be a\n\t\t// boolean value, a function, or the name of a function on the model.\n\t\tvar evaluateModelFn = function(model, fn) {\n\t\t\tif (_.isBoolean(fn)) return fn;\n\t\t\treturn (_.isString(fn) ? model[fn] : fn).apply(model, args);\n\t\t};\n\t\t_.each(unsavedModels, function(model) {\n\t\t\tif (!prompt && evaluateModelFn(model, model._unsavedConfig[fnName]))\n\t\t\t\tprompt = model._unsavedConfig.prompt;\n\t\t});\n\t\treturn prompt;\n\t};\n\n\t// Wrap Backbone.History.navigate so that in-app routing\n\t// (`router.navigate('/path')`) can be intercepted with a\n\t// confirmation if there are any unsaved models.\n\tBackbone.History.prototype.navigate = _.wrap(Backbone.History.prototype.navigate, function(oldNav, fragment, options) {\n\t\tvar prompt = getPrompt('unloadRouterPrompt', fragment, options);\n\t\tif (prompt) {\n\t\t\tif (confirm(prompt + ' \\n\\nAre you sure you want to leave this page?')) {\n\t\t\t\toldNav.call(this, fragment, options);\n\t\t\t}\n\t\t} else {\n\t\t\toldNav.call(this, fragment, options);\n\t\t}\n\t});\n\n\t// Create a browser unload handler which is triggered\n\t// on the refresh, back, or forward button.\n\twindow.onbeforeunload = function(e) {\n\t\treturn getPrompt('unloadWindowPrompt', e);\n\t};\n\n\t// Backbone.Model API\n\t// ------------------\n\n\t_.extend(Backbone.Model.prototype, {\n\n\t\tunsaved: {},\n\t\t_trackingChanges: false,\n\t\t_originalAttrs: {},\n\t\t_unsavedChanges: {},\n\n\t\t// Opt in to tracking attribute changes\n\t\t// between saves.\n\t\tstartTracking: function() {\n\t\t\tthis._unsavedConfig = _.extend({}, {\n\t\t\t\tprompt: 'You have unsaved changes!',\n\t\t\t\tunloadRouterPrompt: false,\n\t\t\t\tunloadWindowPrompt: false\n\t\t\t}, this.unsaved || {});\n\t\t\tthis._trackingChanges = true;\n\t\t\tthis._resetTracking();\n\t\t\tthis._triggerUnsavedChanges();\n\t\t\treturn this;\n\t\t},\n\n\t\t// Resets the default tracking values\n\t\t// and stops tracking attribute changes.\n\t\tstopTracking: function() {\n\t\t\tthis._trackingChanges = false;\n\t\t\tthis._originalAttrs = {};\n\t\t\tthis._unsavedChanges = {};\n\t\t\tthis._triggerUnsavedChanges();\n\t\t\treturn this;\n\t\t},\n\n\t\t// Gets rid of accrued changes and\n\t\t// resets state.\n\t\trestartTracking: function() {\n\t\t\tthis._resetTracking();\n\t\t\tthis._triggerUnsavedChanges();\n\t\t\treturn this;\n\t\t},\n\n\t\t// Restores this model's attributes to\n\t\t// their original values since tracking\n\t\t// started, the last save, or last restart.\n\t\tresetAttributes: function() {\n\t\t\tif (!this._trackingChanges) return;\n\t\t\tthis.attributes = this._originalAttrs;\n\t\t\tthis._resetTracking();\n\t\t\tthis._triggerUnsavedChanges();\n\t\t\treturn this;\n\t\t},\n\n\t\t// Symmetric to Backbone's `model.changedAttributes()`,\n\t\t// except that this returns a hash of the model's attributes that\n\t\t// have changed since the last save, or `false` if there are none.\n\t\t// Like `changedAttributes`, an external attributes hash can be\n\t\t// passed in, returning the attributes in that hash which differ\n\t\t// from the model.\n\t\tunsavedAttributes: function(attrs) {\n\t\t\tif (!attrs) return _.isEmpty(this._unsavedChanges) ? false : _.clone(this._unsavedChanges);\n\t\t\tvar val, changed = false, old = this._unsavedChanges;\n\t\t\tfor (var attr in attrs) {\n\t\t\t\tif (_.isEqual(old[attr], (val = attrs[attr]))) continue;\n\t\t\t\t(changed || (changed = {}))[attr] = val;\n\t\t\t}\n\t\t\treturn changed;\n\t\t},\n\n\t\t_resetTracking: function() {\n\t\t\tthis._originalAttrs = _.clone(this.attributes);\n\t\t\tthis._unsavedChanges = {};\n\t\t},\n\n\t\t// Trigger an `unsavedChanges` event on this model,\n\t\t// supplying the result of whether there are unsaved\n\t\t// changes and a changed attributes hash.\n\t\t_triggerUnsavedChanges: function() {\n\t\t\tthis.trigger('unsavedChanges', !_.isEmpty(this._unsavedChanges), _.clone(this._unsavedChanges));\n\t\t\tif (this.unsaved) updateUnsavedModels(this);\n\t\t}\n\t});\n\n\t// Wrap `model.set()` and update the internal\n\t// unsaved changes record keeping.\n\tBackbone.Model.prototype.set = _.wrap(Backbone.Model.prototype.set, function(oldSet, key, val, options) {\n\t\tvar attrs, ret;\n\t\tif (key == null) return this;\n\t\t// Handle both `\"key\", value` and `{key: value}` -style arguments.\n\t\tif (typeof key === 'object') {\n\t\t\tattrs = key;\n\t\t\toptions = val;\n\t\t} else {\n\t\t\t(attrs = {})[key] = val;\n\t\t}\n\t\toptions || (options = {});\n\n\t\t// Delegate to Backbone's set.\n\t\tret = oldSet.call(this, attrs, options);\n\n\t\tif (this._trackingChanges && !options.silent) {\n\t\t\t_.each(attrs, _.bind(function(val, key) {\n\t\t\t\tif (_.isEqual(this._originalAttrs[key], val))\n\t\t\t\t\tdelete this._unsavedChanges[key];\n\t\t\t\telse\n\t\t\t\t\tthis._unsavedChanges[key] = val;\n\t\t\t}, this));\n\t\t\tthis._triggerUnsavedChanges();\n\t\t}\n\t\treturn ret;\n\t});\n\n\t// Intercept `model.save()` and reset tracking/unsaved\n\t// changes if it was successful.\n\tBackbone.sync = _.wrap(Backbone.sync, function(oldSync, method, model, options) {\n\t\toptions || (options = {});\n\n\t\tif (method == 'update') {\n\t\t\toptions.success = _.wrap(options.success, _.bind(function(oldSuccess, data, textStatus, jqXHR) {\n\t\t\t\tvar ret;\n\t\t\t\tif (oldSuccess) ret = oldSuccess.call(this, data, textStatus, jqXHR);\n\t\t\t\tif (model._trackingChanges) {\n\t\t\t\t\tmodel._resetTracking();\n\t\t\t\t\tmodel._triggerUnsavedChanges();\n\t\t\t\t}\n\t\t\t\treturn ret;\n\t\t\t}, this));\n\t\t}\n\t\treturn oldSync(method, model, options);\n\t});\n\n})();\ndefine(\"vendor/backbone.trackit\", function(){});\n\n","/**\n * Image object model for use in various models for the 'image' attribute\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Models/Image',[], function() {\n\n\treturn Backbone.Model.extend( {\n\n\t\tdefaults: {\n\t\t\tenabled: 'no',\n\t\t\tid: '',\n\t\t\tsize: 'full',\n\t\t\tsrc: '',\n\t\t},\n\n\t\tinitialize: function() {\n\t\t\tthis.startTracking();\n\t\t},\n\n\t} );\n} );\n\n","/**\n * Model relationships mixin\n * @since 3.16.0\n * @version 3.16.11\n */\ndefine( 'Models/_Relationships',[], function() {\n\n\treturn {\n\n\t\t/**\n\t\t * Default relationship settings object\n\t\t * @type {Object}\n\t\t */\n\t\trelationship_defaults: {\n\t\t\tparent: {},\n\t\t\tchildren: {},\n\t\t},\n\n\t\t/**\n\t\t * Relationship settings object\n\t\t * Should be overriden in the model\n\t\t * @type {Object}\n\t\t */\n\t\trelationships: {},\n\n\t\t/**\n\t\t * Initialize all parent and child relationships\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinit_relationships: function( options ) {\n\n\t\t\tvar rels = this.get_relationships();\n\n\t\t\t// initialize parent relaxtionships\n\t\t\t// useful when adding a model to ensure parent is initialized\n\t\t\tif ( rels.parent && options && options.parent ) {\n\t\t\t\tthis.set_parent( options.parent );\n\t\t\t}\n\n\t\t\t// initialize all children relationships\n\t\t\t_.each( rels.children, function( child_data, child_key ) {\n\n\t\t\t\tif ( ! child_data.conditional || true === child_data.conditional( this ) ) {\n\n\t\t\t\t\tvar child_val = this.get( child_key ),\n\t\t\t\t\t\tchild;\n\n\t\t\t\t\tif ( child_data.lookup ) {\n\t\t\t\t\t\tchild = child_data.lookup( child_val );\n\t\t\t\t\t} else if ( 'model' === child_data.type ) {\n\t\t\t\t\t\tchild = window.llms_builder.construct.get_model( child_data.class, child_val );\n\t\t\t\t\t} else if ( 'collection' === child_data.type ) {\n\t\t\t\t\t\tchild = window.llms_builder.construct.get_collection( child_data.class, child_val );\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.set( child_key, child );\n\n\t\t\t\t\t// if the child defines a parent, save a reference to the parent on the child\n\t\t\t\t\tif ( 'model' === child_data.type ) {\n\t\t\t\t\t\tthis._maybe_set_parent_reference( child );\n\n\t\t\t\t\t// save directly to each model in the collection\n\t\t\t\t\t} else if ( 'collection' === child_data.type ) {\n\n\t\t\t\t\t\tchild.parent = this;\n\t\t\t\t\t\tchild.each( function( child_model ) {\n\n\t\t\t\t\t\t\tthis._maybe_set_parent_reference( child_model );\n\n\t\t\t\t\t\t}, this );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t}, this );\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the property names for all children of the model\n\t\t * @return array\n\t\t * @since 3.16.11\n\t\t * @version 3.16.11\n\t\t */\n\t\tget_child_props: function() {\n\n\t\t\tvar props = [];\n\n\t\t\t_.each( this.get_relationships().children, function( data, key ) {\n\n\t\t\t\tif ( ! data.conditional || true === data.conditional( this ) ) {\n\t\t\t\t\tprops.push( key );\n\t\t\t\t}\n\n\t\t\t}, this );\n\n\t\t\treturn props;\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the model's parent (if set)\n\t\t * @return obj|false\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_parent: function() {\n\n\t\t\tvar rels = this.get_relationships();\n\n\t\t\tif ( rels.parent ) {\n\t\t\t\treturn rels.parent.reference;\n\t\t\t}\n\n\t\t\treturn false;\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve relationships for the model\n\t\t * Extends with defaults\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_relationships: function() {\n\n\t\t\treturn $.extend( true, this.relationships, this.relationship_defaults );\n\n\t\t},\n\n\t\t/**\n\t\t * Set the parent reference for the given model\n\t\t * @param obj obj parent model obj\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tset_parent: function( obj ) {\n\t\t\tthis.relationships.parent.reference = obj;\n\t\t},\n\n\t\t/**\n\t\t * Set up the parent relationships for qualifying children during relationship initialization\n\t\t * @param obj model child model\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\t_maybe_set_parent_reference: function( model ) {\n\n\t\t\tif ( ! model || ! model.get_relationships ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar rels = model.get_relationships();\n\t\t\tif ( rels.parent && rels.parent.model === this.get( 'type' ) ) {\n\t\t\t\tmodel.set_parent( this );\n\t\t\t}\n\n\t\t},\n\n\t};\n\n} );\n\n","/**\n * Quiz Question Choice\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Models/QuestionChoice',[ 'Models/Image', 'Models/_Relationships' ], function( Image, Relationships ) {\n\n\treturn Backbone.Model.extend( _.defaults( {\n\n\t\t/**\n\t\t * Model relationships\n\t\t * @type {Object}\n\t\t */\n\t\trelationships: {\n\t\t\tparent: {\n\t\t\t\tmodel: 'llms_question',\n\t\t\t\ttype: 'model',\n\t\t\t},\n\t\t\tchildren: {\n\t\t\t\tchoice: {\n\t\t\t\t\tconditional: function( model ) {\n\t\t\t\t\t\treturn ( 'image' === model.get( 'choice_type' ) );\n\t\t\t\t\t},\n\t\t\t\t\tclass: 'Image',\n\t\t\t\t\tmodel: 'image',\n\t\t\t\t\ttype: 'model',\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\n\t\t/**\n\t\t * Model defaults\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tdefaults: function() {\n\t\t\treturn {\n\t\t\t\tid: _.uniqueId( 'temp_' ),\n\t\t\t\tchoice: '',\n\t\t\t\tchoice_type: 'text',\n\t\t\t\tcorrect: false,\n\t\t\t\tmarker: 'A',\n\t\t\t\tquestion_id: '',\n\t\t\t\ttype: 'choice',\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Initializer\n\t\t * @param obj data object of model attributes\n\t\t * @param obj options additional options\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function( data, options ) {\n\n\t\t\tthis.startTracking();\n\t\t\tthis.init_relationships( options );\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the choice's parent question\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_parent: function() {\n\t\t\treturn this.collection.parent;\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the ID used when trashing the model\n\t\t * @return string\n\t\t * @since 3.17.1\n\t\t * @version 3.17.1\n\t\t */\n\t\tget_trash_id: function() {\n\t\t\treturn this.get( 'question_id' ) + ':' + this.get( 'id' );\n\t\t},\n\n\t\t/**\n\t\t * Determine if \"selection\" is enabled for the question type\n\t\t * Choice type questions are selectable by reorder type questions are not but still use choices\n\t\t * @return {Boolean}\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tis_selectable: function() {\n\t\t\treturn this.get_parent().get( 'question_type' ).get_choice_selectable();\n\t\t},\n\n\t}, Relationships ) );\n\n} );\n\n","/**\n * Question Choice Collection\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Collections/QuestionChoices',[ 'Models/QuestionChoice' ], function( model ) {\n\n\treturn Backbone.Collection.extend( {\n\n\t\t/**\n\t\t * Model for collection items\n\t\t * @type obj\n\t\t */\n\t\tmodel: model,\n\n\t\tinitialize: function() {\n\n\t\t\t// reorder called by QuestionList view when sortable drops occur\n\t\t\tthis.on( 'reorder', this.update_order );\n\n\t\t\t// when a choice is added or removed, update order\n\t\t\tthis.on( 'add', this.update_order );\n\t\t\tthis.on( 'remove', this.update_order );\n\n\t\t\t// when a choice is added or remove, ensure min/max correct answers exist\n\t\t\tthis.on( 'add', this.update_correct );\n\t\t\tthis.on( 'remove', this.update_correct );\n\n\t\t\t// when a choice is toggled, ensure min/max correct exist\n\t\t\tthis.on( 'correct-update', this.update_correct );\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the number of correct choices in the collection\n\t\t * @return int\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tcount_correct: function() {\n\n\t\t\treturn _.size( this.get_correct() );\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the collection reduced to only correct choices\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_correct: function() {\n\t\t\treturn this.filter( function( choice ) {\n\t\t\t\treturn choice.get( 'correct' );\n\t\t\t} );\n\t\t},\n\n\t\t/**\n\t\t * Ensure min/max correct choices exist in the collection based on the question's settings\n\t\t * @param obj choice model of the choice that was toggled\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tupdate_correct: function( choice ) {\n\n\t\t\tif ( ! this.parent.get( 'question_type' ).get_choice_selectable() ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar siblings = this.without( choice ), // exclude the toggled choice from loops\n\t\t\t\tquestion = this.parent;\n\n\t\t\t// if multiple choices aren't enabled turn all other choices to incorrect\n\t\t\tif ( 'no' === question.get( 'multi_choices' ) ) {\n\t\t\t\t_.each( siblings, function( model ) {\n\t\t\t\t\tmodel.set( 'correct', false );\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\t// if we don't have a single corret answer & the question has points, set one\n\t\t\t// allows users to create quizzes / questions with no points and therefore no correct answers are allowed\n\t\t\tif ( 0 === this.count_correct() && question.get( 'points' ) > 0 ) {\n\t\t\t\tvar models = 1 === this.size() ? this.models : siblings;\n\t\t\t\t_.first( models ).set( 'correct', true );\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Update the marker attr of each choice in the list to reflect the order of the collection\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tupdate_order: function() {\n\n\t\t\tvar self = this,\n\t\t\t\tquestion = this.parent;\n\n\t\t\tthis.each( function( choice ) {\n\t\t\t\tchoice.set( 'marker', question.get( 'question_type' ).get_choice_markers()[ self.indexOf( choice ) ] );\n\t\t\t} );\n\n\t\t},\n\n\t} );\n\n} );\n\n","/**\n * Quiz Question Type\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Models/QuestionType',[], function() {\n\n\treturn Backbone.Model.extend( {\n\n\t\t/**\n\t\t * Get model default attributes\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tdefaults: function() {\n\t\t\treturn {\n\t\t\t\tchoices: false,\n\t\t\t\tclarifications: true,\n\t\t\t\tdefault_choices: [],\n\t\t\t\tdescription: true,\n\t\t\t\ticon: 'question',\n\t\t\t\tid: 'generic',\n\t\t\t\timage: true,\n\t\t\t\tkeywords: [],\n\t\t\t\tname: 'Generic',\n\t\t\t\tplaceholder: '',\n\t\t\t\tpoints: true,\n\t\t\t\tvideo: true,\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Retrieve an array of keywords for the question type\n\t\t * Used for filtering questions by search term in the quiz builder\n\t\t * @return array\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_keywords: function() {\n\n\t\t\tvar name = this.get( 'name' ),\n\t\t\t\twords = [ name ];\n\n\t\t\treturn words.concat( this.get( 'keywords' ) ).concat( name.split( ' ' ) );\n\n\t\t},\n\n\t\t/**\n\t\t * Get marker array for the question choices\n\t\t * @return array\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_choice_markers: function() {\n\n\t\t\treturn this._get_choice_option( 'markers' );\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if the question's choices are selectable\n\t\t * @return bool\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_choice_selectable: function() {\n\n\t\t\treturn this._get_choice_option( 'selectable' );\n\n\t\t},\n\n\t\t/**\n\t\t * Get the choice type (text,image)\n\t\t * @return string\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_choice_type: function() {\n\n\t\t\treturn this._get_choice_option( 'type' );\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve defined min. choices\n\t\t * @return int\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_min_choices: function() {\n\n\t\t\treturn this._get_choice_option( 'min' );\n\n\t\t},\n\n\t\t/**\n\t\t * Get type-defined max choices\n\t\t * @return string\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_max_choices: function() {\n\n\t\t\treturn this._get_choice_option( 'max' );\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if multi-choice selection is enabled\n\t\t * @return bool\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_multi_choices: function() {\n\n\t\t\tvar choices = this.get( 'choices' );\n\n\t\t\tif ( ! choices ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\treturn this._get_choice_option( 'multi' );\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve data from the type's \"choices\" attribute\n\t\t * Allows quick handling of types with no choice definitions w/o additional checks\n\t\t * @param string option name of the choice option to retrieve\n\t\t * @return mixed\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\t_get_choice_option: function( option ) {\n\n\t\t\tvar choices = this.get( 'choices' );\n\n\t\t\tif ( ! choices || ! choices[ option ] ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\treturn choices[ option ];\n\n\t\t},\n\n\t} );\n\n} );\n\n","/**\n * Quiz Question\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Models/Question',[\n\t\t'Models/Image',\n\t\t'Collections/Questions',\n\t\t'Collections/QuestionChoices',\n\t\t'Models/QuestionType',\n\t\t'Models/_Relationships'\n\t], function(\n\t\tImage,\n\t\tQuestions,\n\t\tQuestionChoices,\n\t\tQuestionType,\n\t\tRelationships\n\t) {\n\n\treturn Backbone.Model.extend( _.defaults( {\n\n\t\t/**\n\t\t * Model relationships\n\t\t * @type {Object}\n\t\t */\n\t\trelationships: {\n\t\t\tparent: {\n\t\t\t\tmodel: 'llms_quiz',\n\t\t\t\ttype: 'model',\n\t\t\t},\n\t\t\tchildren: {\n\t\t\t\tchoices: {\n\t\t\t\t\tclass: 'QuestionChoices',\n\t\t\t\t\tmodel: 'choice',\n\t\t\t\t\ttype: 'collection',\n\t\t\t\t},\n\t\t\t\timage: {\n\t\t\t\t\tclass: 'Image',\n\t\t\t\t\tmodel: 'image',\n\t\t\t\t\ttype: 'model',\n\t\t\t\t},\n\t\t\t\tquestions: {\n\t\t\t\t\tclass: 'Questions',\n\t\t\t\t\tconditional: function( model ) {\n\t\t\t\t\t\tvar type = model.get( 'question_type' ),\n\t\t\t\t\t\t\ttype_id = _.isString( type ) ? type : type.get( 'id' );\n\t\t\t\t\t\treturn ( 'group' === type_id );\n\t\t\t\t\t},\n\t\t\t\t\tmodel: 'llms_question',\n\t\t\t\t\ttype: 'collection',\n\t\t\t\t},\n\t\t\t\tquestion_type: {\n\t\t\t\t\tclass: 'QuestionType',\n\t\t\t\t\tlookup: function( val ) {\n\t\t\t\t\t\tif ( _.isString( val ) ) {\n\t\t\t\t\t\t\treturn window.llms_builder.questions.get( val );\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn val;\n\t\t\t\t\t},\n\t\t\t\t\tmodel: 'question_type',\n\t\t\t\t\ttype: 'model',\n\t\t\t\t},\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Model defaults\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tdefaults: function() {\n\t\t\treturn {\n\t\t\t\tid: _.uniqueId( 'temp_' ),\n\t\t\t\tchoices: [],\n\t\t\t\tcontent: '',\n\t\t\t\tdescription_enabled: 'no',\n\t\t\t\timage: {},\n\t\t\t\tmulti_choices: 'no',\n\t\t\t\tmenu_order: 1,\n\t\t\t\tpoints: 1,\n\t\t\t\tquestion_type: 'generic',\n\t\t\t\tquestions: [], // for question groups\n\t\t\t\tparent_id: '',\n\t\t\t\ttitle: '',\n\t\t\t\ttype: 'llms_question',\n\t\t\t\tvideo_enabled: 'no',\n\t\t\t\tvideo_src: '',\n\n\t\t\t\t_expanded: false,\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Initializer\n\t\t * @param obj data object of data for the model\n\t\t * @param obj options additional options\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function( data, options ) {\n\n\t\t\tvar self = this;\n\n\t\t\tthis.startTracking();\n\t\t\tthis.init_relationships( options );\n\n\t\t\tif ( false !== this.get( 'question_type' ).choices ) {\n\n\t\t\t\tthis._ensure_min_choices();\n\n\t\t\t\t// when a choice is removed, maybe add back some defaults so we always have the minimum\n\t\t\t\tthis.listenTo( this.get( 'choices' ), 'remove', function() {\n\t\t\t\t\t// new itmes are added at index 0 when there's only 1 item in the collection, not sure why exactly...\n\t\t\t\t\tsetTimeout( function() {\n\t\t\t\t\t\tself._ensure_min_choices();\n\t\t\t\t\t}, 0 );\n\t\t\t\t} );\n\n\t\t\t}\n\n\t\t\t// ensure question types that don't support points don't record default 1 point in database\n\t\t\tif ( ! this.get( 'question_type' ).get( 'points' ) ) {\n\t\t\t\tthis.set( 'points', 0 );\n\t\t\t}\n\n\t\t\t_.delay( function( self ) {\n\t\t\t\tself.on( 'change:points', self.get_parent().update_points, self.get_parent() );\n\t\t\t}, 1, this );\n\n\t\t},\n\n\t\t/**\n\t\t * Add a new question choice\n\t\t * @param obj data object of choice data\n\t\t * @param obj options additional options\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tadd_choice: function( data, options ) {\n\n\t\t\tvar max = this.get( 'question_type' ).get_max_choices();\n\t\t\tif ( this.get( 'choices' ).size() >= max ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tdata = data || {};\n\t\t\toptions = options || {};\n\n\t\t\tdata.choice_type = this.get( 'question_type' ).get_choice_type();\n\t\t\tdata.question_id = this.get( 'id' );\n\t\t\toptions.parent = this;\n\n\t\t\tvar choice = this.get( 'choices' ).add( data, options );\n\n\t\t\tBackbone.pubSub.trigger( 'question-add-choice', choice, this );\n\n\t\t},\n\n\t\t/**\n\t\t * Collapse question_type attribute during full syncs to save to database\n\t\t * Not needed because question types cannot be adjusted after question creation\n\t\t * Called from sync controller\n\t\t * @param obj atts flat object of attributes to be saved to db\n\t\t * @param string sync_type full or partial\n\t\t * full indicates a force resync or that the model isn't persisted yet\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tbefore_save: function( atts, sync_type ) {\n\t\t\tif ( 'full' === sync_type ) {\n\t\t\t\tatts.question_type = this.get( 'question_type' ).get( 'id' );\n\t\t\t}\n\t\t\treturn atts;\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the model's parent (if set)\n\t\t * @return obj|false\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_parent: function() {\n\n\t\t\tvar rels = this.get_relationships();\n\n\t\t\tif ( rels.parent ) {\n\t\t\t\tif ( this.collection && this.collection.parent ) {\n\t\t\t\t\treturn this.collection.parent;\n\t\t\t\t} else if ( rels.parent.reference ) {\n\t\t\t\t\treturn rels.parent.reference;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false;\n\n\t\t},\n\n\t\t/**\n\t\t * Gets the index of the question within it's parent\n\t\t * Question numbers skip content elements\n\t\t * & content elements skip questions\n\t\t * @return int\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_type_index: function() {\n\n\t\t\t// current models type, used to check the predicate in the filter function below\n\t\t\tvar curr_type = this.get( 'question_type' ).get( 'id' ),\n\t\t\t\tquestions;\n\n\t\t\tquestions = this.collection.filter( function( question ) {\n\n\t\t\t\tvar type = question.get( 'question_type' ).get( 'id' );\n\n\t\t\t\t// if current model is not content, return all non-content questions\n\t\t\t\tif ( curr_type !== 'content' ) {\n\t\t\t\t\treturn ( 'content' !== type );\n\t\t\t\t}\n\n\t\t\t\t// current model is content, return only content questions\n\t\t\t\treturn 'content' === type;\n\n\t\t\t} );\n\n\t\t\treturn questions.indexOf( this );\n\n\t\t},\n\n\t\t/**\n\t\t * Gets iterator for the given type\n\t\t * Questions use numbers and content uses alphabet\n\t\t * @return mixed\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_type_iterator: function() {\n\n\t\t\tvar index = this.get_type_index();\n\n\t\t\tif ( -1 === index ) {\n\t\t\t\treturn '';\n\t\t\t}\n\n\t\t\tif ( 'content' === this.get( 'question_type' ).get( 'id' ) ) {\n\t\t\t\tvar alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split( '' );\n\t\t\t\treturn alphabet[ index ];\n\t\t\t}\n\n\t\t\treturn index + 1;\n\n\t\t},\n\n\n\t\tget_qid: function() {\n\n\t\t\tvar parent = this.get_parent_question(),\n\t\t\t\tprefix = '';\n\n\t\t\tif ( parent ) {\n\n\t\t\t\tprefix = parent.get_qid() + '.';\n\n\t\t\t}\n\n\t\t\t// return short_id + this.get_type_iterator();\n\t\t\treturn prefix + this.get_type_iterator();\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the parent question (if the question is in a question group)\n\t\t * @return obj|false\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_parent_question: function() {\n\n\t\t\tif ( this.is_in_group() ) {\n\n\t\t\t\treturn this.collection.parent;\n\n\t\t\t}\n\n\t\t\treturn false;\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the parent quiz\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_parent_quiz: function() {\n\t\t\treturn this.get_parent();\n\t\t},\n\n\t\t/**\n\t\t * Points getter\n\t\t * ensures that 0 is always returned if the question type doesn't support points\n\t\t * @return int\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_points: function() {\n\n\t\t\tif ( ! this.get( 'question_type' ).get( 'points' ) ) {\n\t\t\t\treturn 0;\n\t\t\t}\n\n\t\t\treturn this.get( 'points' );\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the questions percentage value within the quiz\n\t\t * @return string\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_points_percentage: function() {\n\n\t\t\tvar total = this.get_parent().get( '_points' ),\n\t\t\t\tpoints = this.get( 'points' );\n\n\t\t\tif ( 0 === total ) {\n\t\t\t\treturn '0%';\n\t\t\t}\n\n\t\t\treturn ( ( points / total ) * 100 ).toFixed( 2 ) + '%';\n\n\t\t},\n\n\t\t/**\n\t\t * Deterine if the question belongs to a question group\n\t\t * @return {Boolean}\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tis_in_group: function() {\n\n\t\t\treturn ( 'question' === this.collection.parent.get( 'type' ) );\n\n\t\t},\n\n\t\t_ensure_min_choices: function() {\n\n\t\t\tvar choices = this.get( 'choices' );\n\t\t\twhile ( choices.size() < this.get( 'question_type' ).get_min_choices() ) {\n\t\t\t\tthis.add_choice();\n\t\t\t}\n\n\t\t},\n\n\t}, Relationships ) );\n\n} );\n\n","/**\n * Questions Collection\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Collections/Questions',[ 'Models/Question' ], function( model ) {\n\n\treturn Backbone.Collection.extend( {\n\n\t\t/**\n\t\t * Model for collection items\n\t\t * @type obj\n\t\t */\n\t\tmodel: model,\n\n\t\t/**\n\t\t * Initialize\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\t// reorder called by QuestionList view when sortable drops occur\n\t\t\tthis.on( 'reorder', this.update_order );\n\n\t\t\t// when a question is added or removed, update order\n\t\t\tthis.on( 'add', this.update_order );\n\t\t\tthis.on( 'remove', this.update_order );\n\n\t\t\tthis.on( 'add', this.update_parent );\n\n\t\t},\n\n\t\t/**\n\t\t * Update the order attr of each question in the list to reflect the order of the collection\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tupdate_order: function() {\n\n\t\t\tvar self = this;\n\n\t\t\tthis.each( function( question ) {\n\n\t\t\t\tquestion.set( 'menu_order', self.indexOf( question ) + 1 );\n\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * When adding a question to a question list, update the question's parent\n\t\t * Will ensure that questions moved into and out of groups always have the corerct parent_id\n\t\t * @param obj model instance of the question model\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tupdate_parent: function( model ) {\n\n\t\t\tmodel.set( 'parent_id', this.parent.get( 'id' ) );\n\n\t\t},\n\n\t} );\n\n} );\n\n","/**\n * Utility functions for Models\n * @since 3.16.0\n * @version 3.17.1\n */\ndefine( 'Models/_Utilities',[], function() {\n\n\treturn {\n\n\t\tfields: [],\n\n\t\t/**\n\t\t * Retrieve the edit post link for the current model\n\t\t * @return string\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_edit_post_link: function() {\n\n\t\t\tif ( this.has_temp_id() ) {\n\t\t\t\treturn '';\n\t\t\t}\n\n\t\t\treturn window.llms_builder.admin_url + 'post.php?post=' + this.get( 'id' ) + '&action=edit';\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve schema fields defined for the model\n\t\t * @return object\n\t\t * @since 3.17.0\n\t\t * @version 3.17.1\n\t\t */\n\t\tget_settings_fields: function() {\n\n\t\t\tvar schema = this.schema || {};\n\t\t\treturn window.llms_builder.schemas.get( schema, this.get( 'type' ).replace( 'llms_', '' ), this );\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if the model has a temporary ID\n\t\t * @return {Boolean}\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\thas_temp_id: function() {\n\n\t\t\treturn ( ! _.isNumber( this.get( 'id' ) ) && 0 === this.get( 'id' ).indexOf( 'temp_' ) );\n\n\t\t},\n\n\t\t/**\n\t\t * Initializes 3rd party custom schema (field) data for a model\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tinit_custom_schema: function() {\n\n\t\t\tvar groups = _.filter( this.get_settings_fields(), function( group ) {\n\t\t\t\treturn ( group.custom );\n\t\t\t} );\n\n\t\t\t_.each( groups, function( group ) {\n\t\t\t\t_.each( _.flatten( group.fields ), function( field ) {\n\n\n\t\t\t\t\tvar keys = [ field.attribute ],\n\t\t\t\t\t\tcustoms = this.get( 'custom' );\n\n\t\t\t\t\tif ( field.switch_attribute ) {\n\t\t\t\t\t\tkeys.push( field.switch_attribute );\n\t\t\t\t\t}\n\n\t\t\t\t\t_.each( keys, function( key ) {\n\t\t\t\t\t\tvar attr = field.attribute_prefix ? field.attribute_prefix + key : key;\n\t\t\t\t\t\tif ( customs && customs[ attr ] ) {\n\t\t\t\t\t\t\tthis.set( key, customs[ attr ][0] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}, this );\n\n\t\t\t\t}, this );\n\t\t\t}, this );\n\n\t\t},\n\n\t};\n\n} );\n\n","/**\n * Quiz Schema\n * @since 3.17.6\n * @version 3.17.6\n */\ndefine( 'Schemas/Quiz',[], function() {\n\n\treturn {\n\n\t\tdefault: {\n\t\t\ttitle: LLMS.l10n.translate( 'General Settings' ),\n\t\t\ttoggleable: true,\n\t\t\tfields: [\n\t\t\t\t[\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'permalink',\n\t\t\t\t\t\tid: 'permalink',\n\t\t\t\t\t\ttype: 'permalink',\n\t\t\t\t\t},\n\t\t\t\t], [\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'content',\n\t\t\t\t\t\tid: 'description',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Description' ),\n\t\t\t\t\t\ttype: 'editor',\n\t\t\t\t\t},\n\t\t\t\t], [\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'passing_percent',\n\t\t\t\t\t\tid: 'passing-percent',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Passing Percentage' ),\n\t\t\t\t\t\tmin: 0,\n\t\t\t\t\t\tmax: 100,\n\t\t\t\t\t\ttip: LLMS.l10n.translate( 'Minimum percentage of total points required to pass the quiz' ),\n\t\t\t\t\t\ttype: 'number',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'allowed_attempts',\n\t\t\t\t\t\tid: 'allowed-attempts',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Limit Attempts' ),\n\t\t\t\t\t\tswitch_attribute: 'limit_attempts',\n\t\t\t\t\t\ttip: LLMS.l10n.translate( 'Limit the maximum number of times a student can take this quiz' ),\n\t\t\t\t\t\ttype: 'switch-number',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'time_limit',\n\t\t\t\t\t\tid: 'time-limit',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Time Limit' ),\n\t\t\t\t\t\tmin: 1,\n\t\t\t\t\t\tmax: 360,\n\t\t\t\t\t\tswitch_attribute: 'limit_time',\n\t\t\t\t\t\ttip: LLMS.l10n.translate( 'Enforce a maximum number of minutes a student can spend on each attempt' ),\n\t\t\t\t\t\ttype: 'switch-number',\n\t\t\t\t\t},\n\t\t\t\t], [\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'show_correct_answer',\n\t\t\t\t\t\tid: 'show-correct-answer',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Show Correct Answers' ),\n\t\t\t\t\t\ttip: LLMS.l10n.translate( 'When enabled, students will be shown the correct answer to any question they answered incorrectly.' ),\n\t\t\t\t\t\ttype: 'switch',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'random_questions',\n\t\t\t\t\t\tid: 'random-questions',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Randomize Question Order' ),\n\t\t\t\t\t\ttip: LLMS.l10n.translate( 'Display questions in a random order for each attempt. Content questions are locked into their defined positions.' ),\n\t\t\t\t\t\ttype: 'switch',\n\t\t\t\t\t},\n\t\t\t\t],\n\n\t\t\t],\n\t\t},\n\n\t};\n\n} );\n\n","/**\n * Quiz Model\n * @since 3.16.0\n * @version 3.19.2\n */\ndefine( 'Models/Quiz',[\n\t\t'Collections/Questions',\n\t\t'Models/Lesson',\n\t\t'Models/Question',\n\t\t'Models/_Relationships',\n\t\t'Models/_Utilities',\n\t\t'Schemas/Quiz',\n\t], function(\n\t\tQuestions,\n\t\tLesson,\n\t\tQuestion,\n\t\tRelationships,\n\t\tUtilities,\n\t\tQuizSchema\n\t) {\n\n\treturn Backbone.Model.extend( _.defaults( {\n\n\t\t/**\n\t\t * model relationships\n\t\t * @type {Object}\n\t\t */\n\t\trelationships: {\n\t\t\tparent: {\n\t\t\t\tmodel: 'lesson',\n\t\t\t\ttype: 'model',\n\t\t\t},\n\t\t\tchildren: {\n\t\t\t\tquestions: {\n\t\t\t\t\tclass: 'Questions',\n\t\t\t\t\tmodel: 'llms_question',\n\t\t\t\t\ttype: 'collection',\n\t\t\t\t},\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Lesson Settings Schema\n\t\t * @type {Object}\n\t\t */\n\t\tschema: QuizSchema,\n\n\t\t/**\n\t\t * New lesson defaults\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.6\n\t\t */\n\t\tdefaults: function() {\n\n\t\t\treturn {\n\t\t\t\tid: _.uniqueId( 'temp_' ),\n\t\t\t\ttitle: LLMS.l10n.translate( 'New Quiz' ),\n\t\t\t\ttype: 'llms_quiz',\n\t\t\t\tlesson_id: '',\n\n\t\t\t\tstatus: 'draft',\n\n\t\t\t\t// editable fields\n\t\t\t\tcontent: '',\n\t\t\t\tallowed_attempts: 5,\n\t\t\t\tlimit_attempts: 'no',\n\t\t\t\tlimit_time: 'no',\n\t\t\t\tpassing_percent: 65,\n\t\t\t\tname: '',\n\t\t\t\trandom_answers: 'no',\n\t\t\t\ttime_limit: 30,\n\t\t\t\tshow_correct_answer: 'no',\n\n\t\t\t\tquestions: [],\n\n\t\t\t\t// calculated\n\t\t\t\t_points: 0,\n\n\t\t\t\t// display\n\t\t\t\tpermalink: '',\n\t\t\t\t_show_settings: false,\n\t\t\t\t_questions_loaded: false,\n\t\t\t};\n\n\t\t},\n\n\t\t/**\n\t\t * Initializer\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.17.6\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\tthis.init_custom_schema();\n\t\t\tthis.startTracking();\n\t\t\tthis.init_relationships();\n\n\t\t\tthis.listenTo( this.get( 'questions' ), 'add', this.update_points );\n\t\t\tthis.listenTo( this.get( 'questions' ), 'remove', this.update_points );\n\n\t\t\tthis.set( '_points', this.get_total_points() );\n\n\t\t\t// when a quiz is published, ensure the parent lesson is marked as \"Enabled\" for quizzing\n\t\t\tthis.on( 'change:status', function() {\n\t\t\t\tif ( 'publish' === this.get( 'status' ) ) {\n\t\t\t\t\tthis.get_parent().set( 'quiz_enabled', 'yes' );\n\t\t\t\t}\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * Add a new question to the quiz\n\t\t * @param obj data question data\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tadd_question: function( data ) {\n\n\t\t\tdata.parent_id = this.get( 'id' );\n\t\t\tvar question = this.get( 'questions' ).add( data, {\n\t\t\t\tparent: this,\n\t\t\t} );\n\t\t\tBackbone.pubSub.trigger( 'quiz-add-question', question, this );\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the translated post type name for the model's type\n\t\t * @param bool plural if true, returns the plural, otherwise returns singular\n\t\t * @return string\n\t\t * @since 3.16.12\n\t\t * @version 3.16.12\n\t\t */\n\t\tget_l10n_type: function( plural ) {\n\n\t\t\tif ( plural ) {\n\t\t\t\treturn LLMS.l10n.translate( 'quizzes' );\n\t\t\t}\n\n\t\t\treturn LLMS.l10n.translate( 'quiz' );\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the quiz's total points\n\t\t * @return int\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_total_points: function() {\n\n\t\t\tvar points = 0;\n\n\t\t\tthis.get( 'questions' ).each( function( question ) {\n\t\t\t\tpoints += question.get_points();\n\t\t\t} );\n\n\t\t\treturn points;\n\n\t\t},\n\n\t\t/**\n\t\t * Lazy load questions via AJAX\n\t\t * @param {Function} cb callback function\n\t\t * @return void\n\t\t * @since 3.19.2\n\t\t * @version 3.19.2\n\t\t */\n\t\tload_questions: function( cb ) {\n\n\t\t\tif ( this.get( '_questions_loaded' ) ) {\n\n\t\t\t\tcb();\n\n\t\t\t} else {\n\n\t\t\t\tvar self = this;\n\n\t\t\t\tLLMS.Ajax.call( {\n\t\t\t\t\tdata: {\n\t\t\t\t\t\taction: 'llms_builder',\n\t\t\t\t\t\taction_type: 'lazy_load',\n\t\t\t\t\t\tcourse_id: window.llms_builder.CourseModel.get( 'id' ),\n\t\t\t\t\t\tload_id: this.get( 'id' ),\n\t\t\t\t\t},\n\t\t\t\t\terror: function( xhr, status, error ) {\n\n\t\t\t\t\t\tconsole.log( xhr, status, error );\n\t\t\t\t\t\twindow.llms_builder.debug.log( '==== start load_questions error ====', xhr, status, error, '==== finish load_questions error ====' );\n\t\t\t\t\t\tcb( true );\n\n\t\t\t\t\t},\n\t\t\t\t\tsuccess: function( res ) {\n\t\t\t\t\t\tif ( res && res.questions ) {\n\t\t\t\t\t\t\tself.set( '_questions_loaded', true );\n\t\t\t\t\t\t\tif ( res.questions ) {\n\t\t\t\t\t\t\t\t_.each( res.questions, self.add_question, self );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcb();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tcb( true );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t} );\n\n\t\t\t}\n\n\n\t\t},\n\n\t\t/**\n\t\t * Update total number of points calculated property\n\t\t * @return int\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tupdate_points: function() {\n\n\t\t\tthis.set( '_points', this.get_total_points() );\n\n\t\t},\n\n\t}, Relationships, Utilities ) );\n\n} );\n\n","/**\n * Lesson Schemas\n * @since 3.17.0\n * @version 3.17.1\n */\ndefine( 'Schemas/Lesson',[], function() {\n\n\treturn {\n\n\t\tdefault: {\n\t\t\ttitle: LLMS.l10n.translate( 'General Settings' ),\n\t\t\ttoggleable: true,\n\t\t\tfields: [\n\t\t\t\t[\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'permalink',\n\t\t\t\t\t\tid: 'permalink',\n\t\t\t\t\t\ttype: 'permalink',\n\t\t\t\t\t},\n\t\t\t\t], [\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'video_embed',\n\t\t\t\t\t\tid: 'video-embed',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Video Embed URL' ),\n\t\t\t\t\t\ttype: 'video_embed',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'audio_embed',\n\t\t\t\t\t\tid: 'audio-embed',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Audio Embed URL' ),\n\t\t\t\t\t\ttype: 'audio_embed',\n\t\t\t\t\t},\n\t\t\t\t], [\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'free_lesson',\n\t\t\t\t\t\tid: 'free-lesson',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Free Lesson' ),\n\t\t\t\t\t\ttip: LLMS.l10n.translate( \"Free lessons can be accessed without enrollment.\" ),\n\t\t\t\t\t\ttype: 'switch',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'require_passing_grade',\n\t\t\t\t\t\tid: 'require-passing-grade',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Require Passing Grade on Quiz' ),\n\t\t\t\t\t\ttip: LLMS.l10n.translate( \"When enabled, students must pass this lesson's quiz before the lesson can be completed.\" ),\n\t\t\t\t\t\ttype: 'switch',\n\t\t\t\t\t\tcondition: function() {\n\t\t\t\t\t\t\treturn ( 'yes' === this.get( 'quiz_enabled' ) );\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'require_assignment_passing_grade',\n\t\t\t\t\t\tid: 'require-assignment-passing-grade',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Require Passing Grade on Assignment' ),\n\t\t\t\t\t\ttip: LLMS.l10n.translate( \"When enabled, students must pass this lesson's assignment before the lesson can be completed.\" ),\n\t\t\t\t\t\ttype: 'switch',\n\t\t\t\t\t\tcondition: function() {\n\t\t\t\t\t\t\treturn ( 'undefined' !== window.llms_builder.assignments && 'yes' === this.get( 'assignment_enabled' ) );\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t], [\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'prerequisite',\n\t\t\t\t\t\tcondition: function() {\n\t\t\t\t\t\t\treturn ( false === this.is_first_in_course() );\n\t\t\t\t\t\t},\n\t\t\t\t\t\tid: 'prerequisite',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Prerequisite' ),\n\t\t\t\t\t\tswitch_attribute: 'has_prerequisite',\n\t\t\t\t\t\ttype: 'switch-select',\n\t\t\t\t\t\toptions: function() {\n\t\t\t\t\t\t\treturn this.get_available_prereq_options();\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t], [\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'drip_method',\n\t\t\t\t\t\tid: 'drip-method',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Drip Method' ),\n\t\t\t\t\t\tswitch_attribute: 'drip_method',\n\t\t\t\t\t\ttype: 'select',\n\t\t\t\t\t\toptions: function() {\n\n\t\t\t\t\t\t\tvar options = [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tkey: '',\n\t\t\t\t\t\t\t\t\tval: LLMS.l10n.translate( 'None' ),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tkey: 'date',\n\t\t\t\t\t\t\t\t\tval: LLMS.l10n.translate( 'On a specific date' ),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tkey: 'enrollment',\n\t\t\t\t\t\t\t\t\tval: LLMS.l10n.translate( '# of days after course enrollment' ),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t];\n\n\t\t\t\t\t\t\tif ( this.get_course().get( 'start_date' ) ) {\n\t\t\t\t\t\t\t\toptions.push( {\n\t\t\t\t\t\t\t\t\tkey: 'start',\n\t\t\t\t\t\t\t\t\tval: LLMS.l10n.translate( '# of days after course start date' ),\n\t\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif ( 'yes' === this.get( 'has_prerequisite' ) ) {\n\t\t\t\t\t\t\t\toptions.push( {\n\t\t\t\t\t\t\t\t\tkey: 'prerequisite',\n\t\t\t\t\t\t\t\t\tval: LLMS.l10n.translate( '# of days after prerequisite lesson completion' ),\n\t\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\treturn options;\n\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'days_before_available',\n\t\t\t\t\t\tcondition: function() {\n\t\t\t\t\t\t\treturn ( -1 !== [ 'enrollment', 'start', 'prerequisite' ].indexOf( this.get( 'drip_method' ) ) );\n\t\t\t\t\t\t},\n\t\t\t\t\t\tid: 'days-before-available',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( '# of days' ),\n\t\t\t\t\t\tmin: 0,\n\t\t\t\t\t\ttype: 'number',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'date_available',\n\t\t\t\t\t\tdate_format: 'Y-m-d',\n\t\t\t\t\t\tcondition: function() {\n\t\t\t\t\t\t\treturn ( 'date' === this.get( 'drip_method' ) );\n\t\t\t\t\t\t},\n\t\t\t\t\t\tid: 'date-available',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Date' ),\n\t\t\t\t\t\ttimepicker: 'false',\n\t\t\t\t\t\ttype: 'datepicker',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'time_available',\n\t\t\t\t\t\tcondition: function() {\n\t\t\t\t\t\t\treturn ( 'date' === this.get( 'drip_method' ) );\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdatepicker: 'false',\n\t\t\t\t\t\tdate_format: 'h:i A',\n\t\t\t\t\t\tid: 'time-available',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Time' ),\n\t\t\t\t\t\ttype: 'datepicker',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t],\n\t\t},\n\n\t};\n\n} );\n\n","/**\n * Lesson Model\n * @since 3.13.0\n * @version 3.19.3\n */\ndefine( 'Models/Lesson',[ 'Models/Quiz', 'Models/_Relationships', 'Models/_Utilities', 'Schemas/Lesson' ], function( Quiz, Relationships, Utilities, LessonSchema ) {\n\n\treturn Backbone.Model.extend( _.defaults( {\n\n\t\t/**\n\t\t * Model relationships\n\t\t * @type {Object}\n\t\t */\n\t\trelationships: {\n\t\t\tparents: {\n\t\t\t\tmodel: 'section',\n\t\t\t\ttype: 'model',\n\t\t\t},\n\t\t\tchildren: {\n\t\t\t\tquiz: {\n\t\t\t\t\tclass: 'Quiz',\n\t\t\t\t\tconditional: function( model ) {\n\t\t\t\t\t\t// if quiz is enabled OR not enabled but we have some quiz data as an obj\n\t\t\t\t\t\treturn ( 'yes' === model.get( 'quiz_enabled' ) || ! _.isEmpty( model.get( 'quiz' ) ) );\n\t\t\t\t\t},\n\t\t\t\t\tmodel: 'llms_quiz',\n\t\t\t\t\ttype: 'model',\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\n\t\t/**\n\t\t * Lesson Settings Schema\n\t\t * @type {Object}\n\t\t */\n\t\tschema: LessonSchema,\n\n\t\t/**\n\t\t * New lesson defaults\n\t\t * @return obj\n\t\t * @since 3.13.0\n\t\t * @version 3.17.1\n\t\t */\n\t\tdefaults: function() {\n\t\t\treturn {\n\t\t\t\tid: _.uniqueId( 'temp_' ),\n\t\t\t\ttitle: LLMS.l10n.translate( 'New Lesson' ),\n\t\t\t\ttype: 'lesson',\n\t\t\t\torder: this.collection ? this.collection.length + 1 : 1,\n\t\t\t\tparent_course: window.llms_builder.course.id,\n\t\t\t\tparent_section: '',\n\n\t\t\t\t// urls\n\t\t\t\tedit_url: '',\n\t\t\t\tview_url: '',\n\n\t\t\t\t// editable fields\n\t\t\t\tcontent: '',\n\t\t\t\taudio_embed: '',\n\t\t\t\thas_prerequisite: 'no',\n\t\t\t\trequire_passing_grade: 'yes',\n\t\t\t\trequire_assignment_passing_grade: 'yes',\n\t\t\t\tvideo_embed: '',\n\t\t\t\tfree_lesson: '',\n\n\t\t\t\t// other fields\n\t\t\t\tassignment: {}, // assignment model/data\n\t\t\t\tassignment_enabled: 'no',\n\n\t\t\t\tquiz: {}, // quiz model/data\n\t\t\t\tquiz_enabled: 'no',\n\n\t\t\t\t_forceSync: false,\n\n\t\t\t};\n\t\t},\n\n\t\t/**\n\t\t * Initializer\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\tthis.init_custom_schema();\n\t\t\tthis.startTracking();\n\t\t\tthis.maybe_init_assignments();\n\t\t\tthis.init_relationships();\n\n\t\t\t// if the lesson ID isn't set on a quiz, set it\n\t\t\tvar quiz = this.get( 'quiz' );\n\t\t\tif ( ! _.isEmpty( quiz ) && ! quiz.get( 'lesson_id' ) ) {\n\t\t\t\tquiz.set( 'lesson_id', this.get( 'id' ) );\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve a reference to the parent course of the lesson\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_course: function() {\n\t\t\treturn this.get_parent().get_parent();\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the translated post type name for the model's type\n\t\t * @param bool plural if true, returns the plural, otherwise returns singular\n\t\t * @return string\n\t\t * @since 3.16.12\n\t\t * @version 3.16.12\n\t\t */\n\t\tget_l10n_type: function( plural ) {\n\n\t\t\tif ( plural ) {\n\t\t\t\treturn LLMS.l10n.translate( 'lessons' );\n\t\t\t}\n\n\t\t\treturn LLMS.l10n.translate( 'lesson' );\n\t\t},\n\n\t\t/**\n\t\t * Override default get_parent to grab from collection if models parent isn't set\n\t\t * @return obj\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tget_parent: function() {\n\n\t\t\tvar rels = this.get_relationships();\n\t\t\tif ( rels.parent && rels.parent.reference ) {\n\t\t\t\treturn rels.parent.reference;\n\t\t\t} else if ( this.collection && this.collection.parent ) {\n\t\t\t\treturn this.collection.parent;\n\t\t\t}\n\t\t\treturn false;\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve an array of prerequisite options available for the current lesson\n\t\t * @return obj\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tget_available_prereq_options: function() {\n\n\t\t\tvar parent_section_index = this.get_parent().collection.indexOf( this.get_parent() ),\n\t\t\t\tlesson_index_in_section = this.collection.indexOf( this ),\n\t\t\t\toptions = [];\n\n\t\t\tthis.get_course().get( 'sections' ).each( function( section, curr_sec_index ) {\n\t\t\t\tif ( curr_sec_index <= parent_section_index ) {\n\t\t\t\t\tvar group = {\n\t\t\t\t\t\t\t/* translators: %1$d = section order number, %2$s = section title */\n\t\t\t\t\t\t\tlabel: LLMS.l10n.replace( 'Section %1$d: %2$s', {\n\t\t\t\t\t\t\t\t'%1$d': section.get( 'order' ),\n\t\t\t\t\t\t\t\t'%2$s': section.get( 'title' )\n\t\t\t\t\t\t\t} ),\n\t\t\t\t\t\t\toptions: [],\n\t\t\t\t\t\t};\n\n\t\t\t\t\tsection.get( 'lessons' ).each( function( lesson, curr_les_index ) {\n\t\t\t\t\t\tif ( curr_sec_index !== parent_section_index || curr_les_index < lesson_index_in_section ) {\n\t\t\t\t\t\t\t/* translators: %1$d = lesson order number, %2$s = lesson title */\n\t\t\t\t\t\t\tgroup.options.push( {\n\t\t\t\t\t\t\t\tkey: lesson.get( 'id' ),\n\t\t\t\t\t\t\t\tval: LLMS.l10n.replace( 'Lesson %1$d: %2$s', {\n\t\t\t\t\t\t\t\t\t'%1$d': lesson.get( 'order' ),\n\t\t\t\t\t\t\t\t\t'%2$s': lesson.get( 'title' )\n\t\t\t\t\t\t\t\t} ),\n\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t}\n\t\t\t\t\t}, this );\n\n\t\t\t\t\toptions.push( group );\n\t\t\t\t}\n\t\t\t}, this );\n\n\t\t\treturn options;\n\n\t\t},\n\n\t\t/**\n\t\t * Add a new quiz to the lesson\n\t\t * @param obj data object of quiz data used to construct a new quiz model\n\t\t * @return obj model for the created quiz\n\t\t * @since 3.16.0\n\t\t * @version 3.19.3\n\t\t */\n\t\tadd_quiz: function( data ) {\n\n\t\t\tdata = data || {};\n\n\t\t\tdata.lesson_id = this.id;\n\t\t\tdata._questions_loaded = true;\n\n\t\t\tif ( ! data.title ) {\n\n\t\t\t\tdata.title = LLMS.l10n.replace( '%1$s Quiz', {\n\t\t\t\t\t'%1$s': this.get( 'title' ),\n\t\t\t\t} );\n\n\t\t\t}\n\n\t\t\tthis.set( 'quiz', data );\n\t\t\tthis.init_relationships();\n\n\t\t\tvar quiz = this.get( 'quiz' );\n\t\t\tthis.set( 'quiz_enabled', 'yes' );\n\n\t\t\treturn quiz;\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if this is the first lesson\n\t\t * @return {Boolean}\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tis_first_in_course: function() {\n\n\t\t\t// if it's not the first item in the section it cant be the first lesson\n\t\t\tif ( this.collection.indexOf( this ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// if it's not the first section it cant' be first lesson\n\t\t\tvar section = this.get_parent();\n\t\t\tif ( section.collection.indexOf( section ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// it's first lesson in first section\n\t\t\treturn true;\n\n\t\t},\n\n\t\t/**\n\t\t * Initialize lesson assignments *if* the assignments addon is availalbe and enabled\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tmaybe_init_assignments: function() {\n\n\t\t\tif ( ! window.llms_builder.assignments ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis.relationships.children.assignment = {\n\t\t\t\tclass: 'Assignment',\n\t\t\t\tconditional: function( model ) {\n\t\t\t\t\t// if assignment is enabled OR not enabled but we have some assignment data as an obj\n\t\t\t\t\treturn ( 'yes' === model.get( 'assignment_enabled' ) || ! _.isEmpty( model.get( 'assignment' ) ) );\n\t\t\t\t},\n\t\t\t\tmodel: 'llms_assignment',\n\t\t\t\ttype: 'model',\n\t\t\t};\n\n\t\t},\n\n\t}, Relationships, Utilities ) );\n\n} );\n\n","/**\n * Lessons Collection\n * @since 3.13.0\n * @version 3.17.0\n */\ndefine( 'Collections/Lessons',[ 'Models/Lesson' ], function( model ) {\n\n\treturn Backbone.Collection.extend( {\n\n\t\t/**\n\t\t * Model for collection items\n\t\t * @type obj\n\t\t */\n\t\tmodel: model,\n\n\t\t/**\n\t\t * Initializer\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\t// reorder called by LessonList view when sortable drops occur\n\t\t\tthis.on( 'reorder', this.on_reorder );\n\n\t\t\t// when a lesson is added or removed, update order\n\t\t\tthis.on( 'add', this.on_reorder );\n\t\t\tthis.on( 'remove', this.on_reorder );\n\n\t\t},\n\n\t\t/**\n\t\t * On lesson reorder callback\n\t\t *\n\t\t * Update the order attr of each lesson to reflect the new lesson order\n\t\t * Validate prerequisite (if set) and unset it if it's no longer a valid prereq\n\t\t *\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\ton_reorder: function() {\n\t\t\tthis.update_order();\n\t\t\tthis.validate_prereqs();\n\t\t},\n\n\t\t/**\n\t\t * Update lesson order attribute of all lessons when lessons are reordered\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tupdate_order: function() {\n\n\t\t\tthis.each( function( lesson ) {\n\t\t\t\tlesson.set( 'order', this.indexOf( lesson ) + 1 );\n\t\t\t}, this );\n\n\t\t},\n\n\n\t\t/**\n\t\t * Validate prerequisite (if set) and unset it if it's no longer a valid prereq\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tvalidate_prereqs: function() {\n\n\t\t\tthis.each( function( lesson ) {\n\n\t\t\t\t// validate prereqs\n\t\t\t\tif ( 'yes' === lesson.get( 'has_prerequisite' ) ) {\n\t\t\t\t\tvar valid = _.pluck( _.flatten( _.pluck( lesson.get_available_prereq_options(), 'options' ) ), 'key' );\n\t\t\t\t\tif ( -1 === valid.indexOf( lesson.get( 'prerequisite' ) * 1 ) ) {\n\t\t\t\t\t\tlesson.set( {\n\t\t\t\t\t\t\tprerequisite: 0,\n\t\t\t\t\t\t\thas_prerequisite: 'no',\n\t\t\t\t\t\t} );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t}, this );\n\n\t\t},\n\n\t} );\n\n} );\n\n","/**\n * Quiz Question Type Collection\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Collections/QuestionTypes',[ 'Models/QuestionType' ], function( model ) {\n\n\treturn Backbone.Collection.extend( {\n\n\t\t/**\n\t\t * Model for collection items\n\t\t * @type obj\n\t\t */\n\t\tmodel: model,\n\n\t\t/**\n\t\t * Initializer\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\tthis.on( 'add', this.comparator );\n\t\t\tthis.on( 'remove', this.comparator );\n\n\t\t},\n\n\t\t/**\n\t\t * Comparator (sorts collection)\n\t\t * @param obj model QuestionType model\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tcomparator: function( model ) {\n\n\t\t\treturn model.get( 'group' ).order;\n\n\t\t},\n\n\t} );\n\n} );\n\n","/**\n * Section Model\n * @since 3.16.0\n * @version 3.16.12\n */\ndefine( 'Models/Section',[ 'Collections/Lessons', 'Models/_Relationships' ], function( Lessons, Relationships ) {\n\n\treturn Backbone.Model.extend( _.defaults( {\n\n\t\trelationships: {\n\t\t\tparent: {\n\t\t\t\tmodel: 'course',\n\t\t\t\ttype: 'model',\n\t\t\t},\n\t\t\tchildren: {\n\t\t\t\tlessons: {\n\t\t\t\t\tclass: 'Lessons',\n\t\t\t\t\tmodel: 'lesson',\n\t\t\t\t\ttype: 'collection',\n\t\t\t\t},\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * New section defaults\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tdefaults: function() {\n\t\t\treturn {\n\t\t\t\tid: _.uniqueId( 'temp_' ),\n\t\t\t\tlessons: [],\n\t\t\t\torder: this.collection ? this.collection.length + 1 : 1,\n\t\t\t\tparent_course: window.llms_builder.course.id,\n\t\t\t\ttitle: LLMS.l10n.translate( 'New Section' ),\n\t\t\t\ttype: 'section',\n\n\t\t\t\t_expanded: false,\n\t\t\t\t_selected: false,\n\t\t\t};\n\t\t},\n\n\t\t/**\n\t\t * Initialize\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\tthis.startTracking();\n\t\t\tthis.init_relationships();\n\n\t\t},\n\n\t\t/**\n\t\t * Add a lesson to the section\n\t\t * @param obj data hash of lesson data (creates new lesson)\n\t\t * or existing lesson as a Backbone.Model\n\t\t * @param obj options has of options\n\t\t * @return obj Backbone.Model of the new/updated lesson\n\t\t * @since 3.16.0\n\t\t * @version 3.16.11\n\t\t */\n\t\tadd_lesson: function( data, options ) {\n\n\t\t\tdata = data || {};\n\t\t\toptions = options || {};\n\n\t\t\tif ( data instanceof Backbone.Model ) {\n\t\t\t\tdata.set( 'parent_section', this.get( 'id' ) );\n\t\t\t\tdata.set_parent( this );\n\t\t\t} else {\n\t\t\t\tdata.parent_section = this.get( 'id' );\n\t\t\t}\n\n\t\t\treturn this.get( 'lessons' ).add( data, options );\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the translated post type name for the model's type\n\t\t * @param bool plural if true, returns the plural, otherwise returns singular\n\t\t * @return string\n\t\t * @since 3.16.12\n\t\t * @version 3.16.12\n\t\t */\n\t\tget_l10n_type: function( plural ) {\n\n\t\t\tif ( plural ) {\n\t\t\t\treturn LLMS.l10n.translate( 'sections' );\n\t\t\t}\n\n\t\t\treturn LLMS.l10n.translate( 'section' );\n\t\t},\n\n\t\t/**\n\t\t * Get next section in the collection\n\t\t * @param bool circular if true handles the collection in a circle\n\t\t * \tif current is the last section, returns the first section\n\t\t * \tif current is the first section, returns the last section\n\t\t * @return obj|false\n\t\t * @since 3.16.11\n\t\t * @version 3.16.11\n\t\t */\n\t\tget_next: function( circular ) {\n\t\t\treturn this._get_sibling( 'next', circular );\n\t\t},\n\n\t\t/**\n\t\t * Get prev section in the collection\n\t\t * @param bool circular if true handles the collection in a circle\n\t\t * \tif current is the last section, returns the first section\n\t\t * \tif current is the first section, returns the last section\n\t\t * @return obj|false\n\t\t * @since 3.16.11\n\t\t * @version 3.16.11\n\t\t */\n\t\tget_prev: function( circular ) {\n\t\t\treturn this._get_sibling( 'prev', circular );\n\t\t},\n\n\t\t/**\n\t\t * Get a sibling section\n\t\t * @param string direction siblings direction [next|prev]\n\t\t * @param bool circular if true handles the collection in a circle\n\t\t * \tif current is the last section, returns the first section\n\t\t * \tif current is the first section, returns the last section\n\t\t * @return obj|false\n\t\t * @since 3.16.11\n\t\t * @version 3.16.11\n\t\t */\n\t\t_get_sibling: function( direction, circular ) {\n\n\t\t\tcircular = ( 'undefined' === circular ) ? true : circular;\n\n\t\t\tvar max = this.collection.size() - 1,\n\t\t\t\tindex = this.collection.indexOf( this ),\n\t\t\t\tsibling_index;\n\n\t\t\tif ( 'next' === direction ) {\n\t\t\t\tsibling_index = index + 1;\n\t\t\t} else if ( 'prev' === direction ) {\n\t\t\t\tsibling_index = index - 1;\n\t\t\t}\n\n\t\t\t// dont retrieve greater than max or less than min\n\t\t\tif ( sibling_index <= max || sibling_index <= 0 ) {\n\n\t\t\t\treturn this.collection.at( sibling_index );\n\n\t\t\t} else if ( circular ) {\n\n\t\t\t\tif ( 'next' === direction ) {\n\t\t\t\t\treturn this.collection.first();\n\t\t\t\t} else if ( 'prev' === direction ) {\n\t\t\t\t\treturn this.collection.last();\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn false;\n\n\t\t},\n\n\t}, Relationships ) );\n\n} );\n\n","/**\n * Sections Collection\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Collections/Sections',[ 'Models/Section' ], function( model ) {\n\n\treturn Backbone.Collection.extend( {\n\n\t\t/**\n\t\t * Model for collection items\n\t\t * @type obj\n\t\t */\n\t\tmodel: model,\n\n\t\t/**\n\t\t * Initialize\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\tvar self = this;\n\n\t\t\t// reorder called by SectionList view when sortable drops occur\n\t\t\tthis.on( 'reorder', this.update_order );\n\n\t\t\t// when a section is added or removed, update order\n\t\t\tthis.on( 'add', this.update_order );\n\t\t\tthis.on( 'remove', this.update_order );\n\n\t\t},\n\n\t\t/**\n\t\t * Update the order attr of each section in the list to reflect the order of the collection\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tupdate_order: function() {\n\n\t\t\tvar self = this;\n\n\t\t\tthis.each( function( section ) {\n\n\t\t\t\tsection.set( 'order', self.indexOf( section ) + 1 );\n\n\t\t\t} );\n\n\t\t},\n\n\t} );\n\n} );\n\n","/**\n * Lessons Collection\n * @since 3.13.0\n * @version 3.16.0\n */\ndefine( 'Collections/loader',[\n\t\t'Collections/Lessons',\n\t\t'Collections/QuestionChoices',\n\t\t'Collections/Questions',\n\t\t'Collections/QuestionTypes',\n\t\t'Collections/Sections'\n\t], function(\n\t\tLessons,\n\t\tQuestionChoices,\n\t\tQuestions,\n\t\tQuestionTypes,\n\t\tSections\n\t) {\n\n\treturn {\n\t\tLessons: Lessons,\n\t\tQuestionChoices: QuestionChoices,\n\t\tQuestions: Questions,\n\t\tQuestionTypes: QuestionTypes,\n\t\tSections: Sections,\n\t};\n\n} );\n\n","/**\n * Abstract LifterLMS Model\n * @since 3.17.0\n * @version 3.17.0\n */\ndefine( 'Models/Abstract',[ 'Models/_Relationships', 'Models/_Utilities' ], function( Relationships, Utilities ) {\n\n\treturn Backbone.Model.extend( _.defaults( {}, Relationships, Utilities ) );\n\n} );\n\n","/**\n * Course Model\n * @since 3.16.0\n * @version 3.16.11\n */\ndefine( 'Models/Course',[ 'Collections/Sections', 'Models/_Relationships', 'Models/_Utilities' ], function( Sections, Relationships, Utilities ) {\n\n\treturn Backbone.Model.extend( _.defaults( {\n\n\t\trelationships: {\n\t\t\tchildren: {\n\t\t\t\tsections: {\n\t\t\t\t\tclass: 'Sections',\n\t\t\t\t\tmodel: 'section',\n\t\t\t\t\ttype: 'collection',\n\t\t\t\t},\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * New Course Defaults\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tdefaults: function() {\n\t\t\treturn {\n\t\t\t\tedit_url: '',\n\t\t\t\tsections: [],\n\t\t\t\ttitle: 'New Course',\n\t\t\t\ttype: 'course',\n\t\t\t\tview_url: '',\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Init\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\tthis.startTracking();\n\t\t\tthis.init_relationships();\n\n\t\t\t// Sidebar \"New Section\" button broadcast\n\t\t\tBackbone.pubSub.on( 'add-new-section', this.add_section, this );\n\n\t\t\t// Sidebar \"New Lesson\" button broadcast\n\t\t\tBackbone.pubSub.on( 'add-new-lesson', this.add_lesson, this );\n\n\t\t\tBackbone.pubSub.on( 'lesson-search-select', this.add_existing_lesson, this );\n\n\t\t},\n\n\t\t/**\n\t\t * Add an existing lesson to the course\n\t\t * Duplicate a lesson from this or another course or attach an orphaned lesson\n\t\t * @param obj lesson lesson data obj\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.11\n\t\t */\n\t\tadd_existing_lesson: function( lesson ) {\n\n\t\t\tvar data = lesson.data;\n\n\t\t\tif ( 'clone' === lesson.action ) {\n\n\t\t\t\tdelete data.id;\n\t\t\t\tif ( data.quiz ) {\n\t\t\t\t\tdelete data.quiz;\n\t\t\t\t\tdata.quiz_enabled = 'no';\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\tdata._forceSync = true;\n\n\t\t\t}\n\n\t\t\tdelete data.order;\n\t\t\tdelete data.parent_course;\n\t\t\tdelete data.parent_section;\n\n\t\t\tthis.add_lesson( data );\n\n\t\t},\n\n\t\t/**\n\t\t * Add a new lesson to the course\n\t\t * @param obj data lesson data\n\t\t * @return obj Backbone.Model of the lesson\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tadd_lesson: function( data ) {\n\n\t\t\tdata = data || {};\n\t\t\tvar options = {},\n\t\t\t\tsection;\n\n\t\t\tif ( ! data.parent_section ) {\n\t\t\t\tsection = this.get_selected_section();\n\t\t\t\tif ( ! section ) {\n\t\t\t\t\tsection = this.get( 'sections' ).last();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tsection = this.get( 'sections' ).get( data.parent_section );\n\t\t\t}\n\n\t\t\tdata._selected = true;\n\n\t\t\tdata.parent_course = this.get( 'id' );\n\n\t\t\tvar lesson = section.add_lesson( data, options );\n\t\t\tBackbone.pubSub.trigger( 'new-lesson-added', lesson );\n\n\t\t\t// expand the section\n\t\t\tsection.set( '_expanded', true );\n\n\t\t\treturn lesson;\n\n\t\t},\n\n\t\t/**\n\t\t * Add a new section to the course\n\t\t * @param obj data section data\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tadd_section: function( data ) {\n\n\t\t\tdata = data || {};\n\t\t\tvar sections = this.get( 'sections' ),\n\t\t\t\toptions = {},\n\t\t\t\tselected = this.get_selected_section();\n\n\t\t\t// if a section is selected, add the new section after the currently selected one\n\t\t\tif ( selected ) {\n\t\t\t\toptions.at = sections.indexOf( selected ) + 1;\n\t\t\t}\n\n\t\t\tsections.add( data, options );\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the currently selected section in the course\n\t\t * @return obj|undefined\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_selected_section: function() {\n\n\t\t\treturn this.get( 'sections' ).find( function( model ) {\n\t\t\t\treturn model.get( '_selected' );\n\t\t\t} );\n\n\t\t},\n\n\t}, Relationships, Utilities ) );\n\n} );\n\n","/**\n * Load all models\n * @return obj\n * @since 3.16.0\n * @version 3.17.0\n */\ndefine( 'Models/loader',[\n\t\t'Models/Abstract',\n\t\t'Models/Course',\n\t\t'Models/Image',\n\t\t'Models/Lesson',\n\t\t'Models/Question',\n\t\t'Models/QuestionChoice',\n\t\t'Models/QuestionType',\n\t\t'Models/Quiz',\n\t\t'Models/Section'\n\t],\n\tfunction(\n\t\tAbstract,\n\t\tCourse,\n\t\tImage,\n\t\tLesson,\n\t\tQuestion,\n\t\tQuestionChoice,\n\t\tQuestionType,\n\t\tQuiz,\n\t\tSection\n\t) {\n\n\treturn {\n\t\tAbstract: Abstract,\n\t\tCourse: Course,\n\t\tImage: Image,\n\t\tLesson: Lesson,\n\t\tQuestion: Question,\n\t\tQuestionChoice: QuestionChoice,\n\t\tQuestionType: QuestionType,\n\t\tQuiz: Quiz,\n\t\tSection: Section,\n\t};\n\n} );\n\n","/**\n * Detachable model\n * @type {Object}\n * @since 3.16.12\n * @version 3.16.12\n */\ndefine( 'Views/_Detachable',[], function() {\n\n\treturn {\n\n\t\t/**\n\t\t * DOM Events\n\t\t * @type {Object}\n\t\t * @since 3.16.12\n\t\t * @version 3.16.12\n\t\t */\n\t\tevents: {\n\t\t\t'click a[href=\"#llms-detach-model\"]': 'detach_model',\n\t\t},\n\n\t\t/**\n\t\t * Detaches a model from it's parent (doesn't delete)\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.16.12\n\t\t * @version 3.16.12\n\t\t */\n\t\tdetach_model: function( event ) {\n\n\t\t\tif ( event ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tevent.stopPropagation();\n\t\t\t}\n\n\t\t\tvar msg = LLMS.l10n.replace( 'Are you sure you want to detach this %s?', {\n\t\t\t\t'%s': this.model.get_l10n_type(),\n\t\t\t} );\n\n\t\t\tif ( window.confirm( msg ) ) {\n\n\t\t\t\tif ( this.model.collection ) {\n\t\t\t\t\tthis.model.collection.remove( this.model );\n\t\t\t\t}\n\n\t\t\t\t// publish global event\n\t\t\t\tBackbone.pubSub.trigger( 'model-detached', this.model );\n\n\t\t\t\t// trigger local event so extending views can run other actions where necessary\n\t\t\t\tthis.trigger( 'model-trashed', this.model );\n\n\t\t\t}\n\n\t\t},\n\n\t}\n\n} );\n\n","/**\n * Handles UX and Events for inline editing of views\n * Use with a Model's View\n * Allows editing model.title field via .llms-editable-title elements\n * @type {Object}\n * @since 3.16.0\n * @version 3.17.8\n */\ndefine( 'Views/_Editable',[], function() {\n\n\treturn {\n\n\t\tmedia_lib: null,\n\n\t\t/**\n\t\t * DOM Events\n\t\t * @type {Object}\n\t\t * @since 3.16.0\n\t\t * @version 3.17.8\n\t\t */\n\t\tevents: {\n\t\t\t'click .llms-add-image': 'open_media_lib',\n\t\t\t'click a[href=\"#llms-edit-slug\"]': 'make_slug_editable',\n\t\t\t'click a[href=\"#llms-remove-image\"]': 'remove_image',\n\t\t\t'change .llms-editable-select select': 'on_select',\n\t\t\t'change .llms-switch input[type=\"checkbox\"]': 'toggle_switch',\n\t\t\t'change .llms-editable-radio input': 'on_radio_select',\n\t\t\t'focusin .llms-input': 'on_focus',\n\t\t\t'focusout .llms-input': 'on_blur',\n\t\t\t'keydown .llms-input': 'on_keydown',\n\t\t\t'input .llms-input[type=\"number\"]': 'on_blur',\n\t\t\t'paste .llms-input[data-formatting]': 'on_paste',\n\t\t},\n\n\t\t/**\n\t\t * Retrieve a list of allowed tags for a given element\n\t\t * @param obj $el jQuery selector for the element\n\t\t * @return array\n\t\t * @since 3.16.0\n\t\t * @version 3.17.8\n\t\t */\n\t\tget_allowed_tags: function( $el ) {\n\n\t\t\tif ( $el.attr( 'data-formatting' ) ) {\n\t\t\t\treturn _.map( $el.attr( 'data-formatting' ).split( ',' ), function( tag ) {\n\t\t\t\t\treturn tag.trim();\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\treturn [ 'b', 'i', 'u', 'strong', 'em' ];\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the content of an element\n\t\t * @param obj $el jQuery object of the element\n\t\t * @return string\n\t\t * @since 3.16.0\n\t\t * @version 3.17.8\n\t\t */\n\t\tget_content: function( $el ) {\n\n\t\t\tif ( 'INPUT' === $el[0].tagName ) {\n\t\t\t\treturn $el.val();\n\t\t\t}\n\n\t\t\tif ( ! $el.attr( 'data-formatting' ) && ! $el.hasClass( 'ql-editor' ) ) {\n\t\t\t\treturn $el.text();\n\t\t\t}\n\n\t\t\treturn _.stripFormatting( $el.html(), this.get_allowed_tags( $el ) );\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if changes have been made to the element\n\t\t * @param {[obj]} event js event object\n\t\t * @return {Boolean} true when changes have been made, false otherwise\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\thas_changed: function( event ) {\n\t\t\tvar $el = $( event.target );\n\t\t\treturn ( $el.attr( 'data-original-content' ) !== this.get_content( $el ) );\n\t\t},\n\n\t\t/**\n\t\t * Ensure that new content is at least 1 character long\n\t\t * @param obj event js event object\n\t\t * @return boolean\n\t\t * @since 3.16.0\n\t\t * @version 3.17.2\n\t\t */\n\t\tis_valid: function( event ) {\n\n\t\t\tvar self = this,\n\t\t\t\t$el = $( event.target ),\n\t\t\t\tcontent = this.get_content( $el ),\n\t\t\t\ttype = $el.attr( 'data-type' );\n\n\t\t\tif ( ( $el.attr( 'required' ) || $el.attr( 'data-required' ) ) && content.length < 1 ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tif ( 'url' === type || 'video' === type ) {\n\t\t\t\tif ( ! this._validate_url( this.get_content( $el ) ) ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t} else if ( 'permalink' === type ) {\n\n\t\t\t\tLLMS.Ajax.call( {\n\t\t\t\t\tdata: {\n\t\t\t\t\t\taction: 'llms_builder',\n\t\t\t\t\t\taction_type: 'get_permalink',\n\t\t\t\t\t\tcourse_id: window.llms_builder.CourseModel.get( 'id' ),\n\t\t\t\t\t\tid: self.model.get( 'id' ),\n\t\t\t\t\t\ttitle: self.model.get( 'title' ),\n\t\t\t\t\t\tslug: content,\n\t\t\t\t\t},\n\t\t\t\t\tbeforeSend: function() {\n\t\t\t\t\t\tLLMS.Spinner.start( $el.closest( '.llms-editable-toggle-group' ), 'small' );\n\t\t\t\t\t},\n\t\t\t\t\tsuccess: function( r ) {\n\n\t\t\t\t\t\tif ( r.permalink && r.slug ) {\n\t\t\t\t\t\t\tself.model.set( 'permalink', r.permalink );\n\t\t\t\t\t\t\tself.model.set( 'name', r.slug );\n\t\t\t\t\t\t\tself.render();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\t\t\t\t} );\n\n\t\t\t}\n\n\t\t\treturn true;\n\n\t\t},\n\n\t\t/**\n\t\t * Initialize datepicker elements\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tinit_datepickers: function() {\n\n\t\t\tthis.$el.find( '.llms-editable-date input' ).each( function() {\n\n\t\t\t\t$( this ).datetimepicker( {\n\t\t\t\t\tformat: $( this ).attr( 'data-date-format' ) || 'Y-m-d h:i A',\n\t\t\t\t\tdatepicker: ( undefined === $( this ).attr( 'data-date-datepicker' ) ) ? true : ( 'true' == $( this ).attr( 'data-date-datepicker' ) ),\n\t\t\t\t\ttimepicker: ( undefined === $( this ).attr( 'data-date-timepicker' ) ) ? true : ( 'true' == $( this ).attr( 'data-date-timepicker' ) ),\n\t\t\t\t\tonClose: function( current_time, $input ) {\n\t\t\t\t\t\t$input.blur();\n\t\t\t\t\t}\n\t\t\t\t} );\n\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * Initialize elements that allow inline formatting\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinit_formatting_els: function() {\n\n\t\t\tvar self = this;\n\n\t\t\tthis.$el.find( '.llms-input-formatting[data-formatting]' ).each( function() {\n\n\t\t\t\tvar formatting = $( this ).attr( 'data-formatting' ).split( ',' ),\n\t\t\t\t\tattr = $( this ).attr( 'data-attribute' );\n\n\t\t\t\tvar ed = new Quill( this, {\n\t\t\t\t\tmodules: {\n\t\t\t\t\t\ttoolbar: [ formatting ],\n\t\t\t\t\t\tkeyboard: {\n\t\t\t\t\t\t\tbindings: {\n\t\t\t\t\t\t\t\ttab: {\n\t\t\t\t\t\t\t\t\tkey: 9,\n\t\t\t\t\t\t\t\t\thandler: function( range, context ) {\n\t\t\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t13: {\n\t\t\t\t\t\t\t\t\tkey: 13,\n\t\t\t\t\t\t\t\t\thandler: function( range, context ) {\n\t\t\t\t\t\t\t\t\t\ted.root.blur();\n\t\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tplaceholder: $( this ).attr( 'data-placeholder' ),\n\t\t\t\t\ttheme: 'bubble',\n\t\t\t\t} );\n\n\t\t\t\ted.on( 'text-change', function( delta, oldDelta, source ) {\n\t\t\t\t\tself.model.set( attr, self.get_content( $( ed.root ) ) );\n\t\t\t\t} );\n\n\t\t\t\tBackbone.pubSub.trigger( 'formatting-ed-init', ed, $( this ), self );\n\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * Initialize editable select elements\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinit_selects: function() {\n\n\t\t\tthis.$el.find( '.llms-editable-select select' ).llmsSelect2( {\n\t\t\t\twidth: '100%',\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * Blur/focusout function for .llms-editable-title elements\n\t\t * Automatically saves changes if changes have been made\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.6\n\t\t */\n\t\ton_blur: function( event ) {\n\n\t\t\tevent.stopPropagation();\n\n\t\t\tthis.model.set( '_has_focus', false, { silent: true } );\n\n\t\t\tvar self = this,\n\t\t\t\t$el = $( event.target ),\n\t\t\t\tchanged = this.has_changed( event );\n\n\t\t\tif ( changed ) {\n\n\t\t\t\tif ( ! self.is_valid( event ) ) {\n\t\t\t\t\tself.revert_edits( event );\n\t\t\t\t} else {\n\t\t\t\t\tthis.save_edits( event );\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Focus event for editable inputs\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.16.6\n\t\t * @version 3.16.6\n\t\t */\n\t\ton_focus: function( event ) {\n\n\t\t\tevent.stopPropagation();\n\t\t\tthis.model.set( '_has_focus', true, { silent: true } );\n\n\t\t},\n\n\t\t/**\n\t\t * Handle content pasted into contenteditable fields\n\t\t * This will ensure that HTML from RTF editors isn't pasted into the dom\n\t\t * @param obj event js event obj\n\t\t * @return void\n\t\t * @since 3.17.8\n\t\t * @version 3.17.8\n\t\t */\n\t\ton_paste: function( event ) {\n\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\n\t\t\tvar text = ( event.originalEvent || event ).clipboardData.getData( 'text/plain' );\n\t\t\twindow.document.execCommand( 'insertText', false, text );\n\n\t\t},\n\n\t\t/**\n\t\t * Change event for selectables\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\ton_select: function( event ) {\n\n\t\t\tvar $el = $( event.target ),\n\t\t\t\tmulti = ( $el.attr( 'multiple' ) ),\n\t\t\t\tattr = $el.attr( 'name' ),\n\t\t\t\t$selected = $el.find( 'option:selected' ),\n\t\t\t\tval;\n\n\t\t\tif ( multi ) {\n\t\t\t\tval = [];\n\t\t\t\tval = $selected.map( function() {\n\t\t\t\t\treturn this.value;\n\t\t\t\t} ).get();\n\t\t\t} else {\n\t\t\t\tval = $selected[0].value;\n\t\t\t}\n\n\t\t\tthis.model.set( attr, val );\n\n\t\t},\n\n\t\t/**\n\t\t * Change event for radio element groups\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.17.6\n\t\t * @version 3.17.6\n\t\t */\n\t\ton_radio_select: function( event ) {\n\n\t\t\tvar $el = $( event.target ),\n\t\t\t\tattr = $el.attr( 'name' ),\n\t\t\t\tval = $el.val();\n\n\t\t\tthis.model.set( attr, val );\n\n\t\t},\n\n\t\t/**\n\t\t * Keydown function for .llms-editable-title elements\n\t\t * Blurs\n\t\t * @param {obj} event js event object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.17.8\n\t\t */\n\t\ton_keydown: function( event ) {\n\n\t\t\tevent.stopPropagation();\n\n\t\t\tvar self = this,\n\t\t\t\tkey = event.which || event.keyCode,\n\t\t\t\tshift = event.shiftKey;\n\t\t\t\t// ctrl = event.metaKey || event.ctrlKey;\n\n\t\t\tswitch ( key ) {\n\n\t\t\t\tcase 13: // enter\n\t\t\t\t\t// shift + enter should add a return\n\t\t\t\t\tif ( ! shift ) {\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\tevent.target.blur();\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t\tcase 27: // escape\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tthis.revert_edits( event );\n\t\t\t\t\tevent.target.blur();\n\t\t\t\tbreak;\n\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Open the WP media lib\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.6\n\t\t */\n\t\topen_media_lib: function( event ) {\n\n\t\t\tevent.stopPropagation();\n\n\t\t\tvar self = this,\n\t\t\t\t$el = $( event.currentTarget );\n\n\t\t\tif ( self.media_lib ) {\n\n\t\t\t\tself.media_lib.uploader.uploader.param( 'post_id' );\n\n\t\t\t} else {\n\n\t\t\t\tself.media_lib = wp.media.frames.file_frame = wp.media( {\n\t\t\t\t\ttitle: LLMS.l10n.translate( 'Select an image' ),\n\t\t\t\t\tbutton: {\n\t\t\t\t\t\ttext: LLMS.l10n.translate( 'Use this image' ),\n\t\t\t\t\t},\n\t\t\t\t\tmultiple: false\t// Set to true to allow multiple files to be selected\n\t\t\t\t} );\n\n\t\t\t\tself.media_lib.on( 'select', function() {\n\n\t\t\t\t\tvar size = $el.attr( 'data-image-size' ),\n\t\t\t\t\t\tattachment = self.media_lib.state().get( 'selection' ).first().toJSON(),\n\t\t\t\t\t\timage = self.model.get( $el.attr( 'data-attribute' ) ),\n\t\t\t\t\t\turl;\n\n\t\t\t\t\tif ( size && attachment.sizes[ size ] ) {\n\t\t\t\t\t\turl = attachment.sizes[ size ].url;\n\t\t\t\t\t} else {\n\t\t\t\t\t\turl = attachment.url;\n\t\t\t\t\t}\n\n\t\t\t\t\timage.set( {\n\t\t\t\t\t\tid: attachment.id,\n\t\t\t\t\t\tsrc: url,\n\t\t\t\t\t} );\n\n\t\t\t\t} );\n\n\t\t\t}\n\n\t\t\tself.media_lib.open();\n\n\n\t\t},\n\n\t\t/**\n\t\t * Click event to remove an image\n\t\t * @param obj event js event obj\n\t\t * @return voids\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tremove_image: function( event ) {\n\n\t\t\tevent.preventDefault();\n\n\t\t\tthis.model.get( $( event.currentTarget ).attr( 'data-attribute' ) ).set( {\n\t\t\t\tid: '',\n\t\t\t\tsrc: '',\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * Helper to undo changes\n\t\t * Bound to \"escape\" key via on_keydwon function\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trevert_edits: function( event ) {\n\t\t\tvar $el = $( event.target ),\n\t\t\t\tval = $el.attr( 'data-original-content' );\n\t\t\t$el.html( val );\n\t\t},\n\n\t\t/**\n\t\t * Sync chages to the model and DB\n\t\t * @param {obj} event js event object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tsave_edits: function( event ) {\n\n\t\t\tvar $el = $( event.target ),\n\t\t\t\tval = this.get_content( $el );\n\n\t\t\tthis.model.set( $el.attr( 'data-attribute' ), val );\n\n\t\t},\n\n\t\t/**\n\t\t * Change event for a switch element\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.17.0\n\t\t */\n\t\ttoggle_switch: function( event ) {\n\n\t\t\tevent.stopPropagation();\n\t\t\tvar $el = $( event.target ),\n\t\t\t\tattr = $el.attr( 'name' ),\n\t\t\t\trerender = $el.attr( 'data-rerender' ),\n\t\t\t\tval;\n\n\t\t\tif ( $el.is( ':checked' ) ) {\n\t\t\t\tval = $el.attr( 'data-on' ) ? $el.attr( 'data-on' ) : 'yes';\n\t\t\t} else {\n\t\t\t\tval = $el.attr( 'data-off' ) ? $el.attr( 'data-off' ) : 'no';\n\t\t\t}\n\n\t\t\tif ( -1 !== attr.indexOf( '.' ) ) {\n\n\t\t\t\tvar split = attr.split( '.' );\n\n\t\t\t\tif ( 'parent' === split[0] ) {\n\t\t\t\t\tthis.model.get_parent().set( split[1], val );\n\t\t\t\t} else {\n\t\t\t\t\tthis.model.get( split[0] ).set( split[1], val );\n\t\t\t\t}\n\n\n\t\t\t} else {\n\n\t\t\t\tthis.model.set( attr, val );\n\n\t\t\t}\n\n\t\t\tthis.trigger( attr.replace( '.', '-' ) + '_toggle', val );\n\n\t\t\tif ( ! rerender || 'yes' === rerender ) {\n\t\t\t\tvar self = this;\n\t\t\t\tsetTimeout( function() {\n\t\t\t\t\tself.render();\n\t\t\t\t}, 100 );\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Initializes a WP Editor on a textarea\n\t\t * @param string id CSS ID of the editor (don't include #)\n\t\t * @param obj settings optional object of settings to pass to wp.editor.initialize()\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinit_editor: function( id, settings ) {\n\n\t\t\tsettings = settings || {};\n\n\t\t\twp.editor.remove( id );\n\n\t\t\twp.editor.initialize( id, $.extend( true, wp.editor.getDefaultSettings(), {\n\t\t\t\tmediaButtons: true,\n\t\t\t\ttinymce: {\n\t\t\t\t\ttoolbar1: 'bold,italic,strikethrough,bullist,numlist,blockquote,hr,alignleft,aligncenter,alignright,link,unlink,wp_adv',\n\t\t\t\t\ttoolbar2: 'formatselect,underline,alignjustify,forecolor,pastetext,removeformat,charmap,outdent,indent,undo,redo,wp_help',\n\t\t\t\t\tsetup: _.bind( this.on_editor_ready, this ),\n\t\t\t\t}\n\t\t\t}, settings ) );\n\n\t\t},\n\n\t\t/**\n\t\t * Setup a permalink editor to allow editing of a permalink\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.16.6\n\t\t * @version 3.16.6\n\t\t */\n\t\tmake_slug_editable: function( event ) {\n\n\t\t\tvar self = this,\n\t\t\t\t$btn = $( event.currentTarget ),\n\t\t\t\t$link = $btn.prevAll( 'a' ),\n\t\t\t\t$input = $btn.prev( 'input.permalink' ),\n\t\t\t\tfull_url = $link.attr( 'href' ),\n\t\t\t\tslug = $input.val(),\n\t\t\t\tshort_url = full_url.replace( slug, '' );\n\n\t\t\t// hide the button\n\t\t\t$btn.hide();\n\n\t\t\t// make the link not clickable\n\t\t\t$link.css( {\n\t\t\t\tcolor: '#999',\n\t\t\t\t'pointer-events': 'none',\n\t\t\t\t'text-decoration': 'none',\n\t\t\t} );\n\n\t\t\t// remove the current slug & trailing slash from the URL\n\t\t\t$link.text( short_url.substring( 0, short_url.length - 1 ) );\n\n\t\t\t// focus in on the field\n\t\t\t$input.show().focus();\n\n\t\t},\n\n\t\t/**\n\t\t * Callback function called after initialization of an editor\n\t\t * Updates UI if a label is present\n\t\t * Binds a change event to ensure editor changes are saved to the model\n\t\t * @param obj editor wp.editor instance\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.17.1\n\t\t */\n\t\ton_editor_ready: function( editor ) {\n\n\t\t\tvar self = this,\n\t\t\t\t$ed = $( '#' + editor.id ),\n\t\t\t\t$parent = $ed.closest( '.llms-editable-editor' ),\n\t\t\t\t$label = $parent.find( '.llms-label' ),\n\t\t\t\tprop = $ed.attr( 'data-attribute' )\n\n\t\t\tif ( $label.length ) {\n\t\t\t\t$label.prependTo( $parent.find( '.wp-editor-tools' ) );\n\t\t\t}\n\n\t\t\t// save changes to the model via Visual ed\n\t\t\teditor.on( 'change', function( event ) {\n\t\t\t\tself.model.set( prop, wp.editor.getContent( editor.id ) );\n\t\t\t} );\n\n\t\t\t// save changes via Text ed\n\t\t\t$ed.on( 'input', function( event ) {\n\t\t\t\tself.model.set( prop, $ed.val() );\n\t\t\t} );\n\n\t\t\t// trigger an input on the Text ed when quicktags buttons are clicked\n\t\t\t$parent.on( 'click', '.quicktags-toolbar .ed_button', function() {\n\t\t\t\tsetTimeout( function() {\n\t\t\t\t\t$ed.trigger( 'input' );\n\t\t\t\t}, 10 );\n\t\t\t} );\n\n\t\t},\n\n\t\t_validate_url: function( str ) {\n\n\t\t\tvar a = document.createElement( 'a' );\n\t\t\ta.href = str;\n\t\t\treturn ( a.host && a.host !== window.location.host );\n\n\t\t}\n\n\t};\n\n} );\n\n","/**\n * _receive override for Backbone.CollectionView core\n * enables connection with jQuery UI draggable buttons\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Views/_Receivable',[], function() {\n\n\treturn {\n\n\t\t/**\n\t\t * Overloads the function from Backbone.CollectionView core because it doesn't properly handle\n\t\t * receieves from a jQuery UI draggable object\n\t\t * @param obj event js event object\n\t\t * @param obj ui jQuery UI object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\t_receive : function( event, ui ) {\n\n\t\t\t// came from sidebar drag\n\t\t\tif ( ui.sender.hasClass( 'ui-draggable' ) ) {\n\t\t\t\tvar index = this._getContainerEl().children().index( ui.helper );\n\t\t\t\tui.helper.remove(); // remove the helper\n\t\t\t\tthis.collection.add( {}, { at: index } );\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar senderListEl = ui.sender;\n\t\t\tvar senderCollectionListView = senderListEl.data( 'view' );\n\t\t\tif( ! senderCollectionListView || ! senderCollectionListView.collection ) return;\n\n\t\t\tvar newIndex = this._getContainerEl().children().index( ui.item );\n\t\t\tvar modelReceived = senderCollectionListView.collection.get( ui.item.attr( 'data-model-cid' ) );\n\t\t\tsenderCollectionListView.collection.remove( modelReceived );\n\t\t\tthis.collection.add( modelReceived, { at : newIndex } );\n\t\t\tmodelReceived.collection = this.collection; // otherwise will not get properly set, since modelReceived.collection might already have a value.\n\t\t\tthis.setSelectedModel( modelReceived );\n\t\t},\n\n\t}\n\n} );\n\n\n","/**\n * Shiftable view mixin function\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Views/_Shiftable',[], function() {\n\n\treturn {\n\n\t\t/**\n\t\t * Conditionally hide action buttons based on section position in collection\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tmaybe_hide_shiftable_buttons: function() {\n\n\t\t\tif ( ! this.model.collection ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar type = this.model.get( 'type' );\n\n\t\t\tif ( this.model.collection.first() === this.model ) {\n\t\t\t\tthis.$el.find( '.shift-up--' + type ).hide();\n\t\t\t} else if ( this.model.collection.last() === this.model ) {\n\t\t\t\tthis.$el.find( '.shift-down--' + type ).hide();\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Move an item in a collection from one position to another\n\t\t * @param int old_index current (old) index within the collection\n\t\t * @param int new_index desired (new) index within the collection\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tshift: function( old_index, new_index ) {\n\n\t\t\tvar collection = this.model.collection;\n\n\t\t\tcollection.remove( this.model );\n\t\t\tcollection.add( this.model, { at: new_index } );\n\t\t\tcollection.trigger( 'reorder' );\n\n\t\t},\n\n\t\t/**\n\t\t * Move an item down the tree one position\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tshift_down: function( e ) {\n\n\t\t\te.preventDefault();\n\t\t\tvar index = this.model.collection.indexOf( this.model );\n\t\t\tthis.shift( index, index + 1 );\n\n\t\t},\n\n\t\t/**\n\t\t * Move an item up the tree one position\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tshift_up: function( e ) {\n\n\t\t\te.preventDefault();\n\t\t\tvar index = this.model.collection.indexOf( this.model );\n\t\t\tthis.shift( index, index - 1 );\n\n\t\t},\n\n\t};\n\n} );\n\n","/**\n * Subview utility mixin\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Views/_Subview',[], function() {\n\n\treturn {\n\n\t\tsubscriptions: {},\n\n\t\t/**\n\t\t * Name of the current subview\n\t\t * @type {String}\n\t\t */\n\t\tstate: '',\n\n\t\t/**\n\t\t * Object of subview data\n\t\t * @type {Object}\n\t\t */\n\t\tviews: {},\n\n\t\t/**\n\t\t * Retrieve a subview by name from this.views\n\t\t * @param string name name of the subview\n\t\t * @return obl|false\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_subview: function( name ) {\n\n\t\t\tif ( this.views[ name ] ) {\n\t\t\t\treturn this.views[ name ];\n\t\t\t}\n\n\t\t\treturn false;\n\n\t\t},\n\n\t\tevents_subscribe: function( events ) {\n\n\t\t\t_.each( events, function( func, event ) {\n\n\t\t\t\tthis.subscriptions[ event ] = func;\n\t\t\t\tBackbone.pubSub.on( event, func, this );\n\n\t\t\t}, this );\n\n\t\t},\n\n\t\tevents_unsubscribe: function() {\n\n\t\t\t_.each( this.subscriptions, function( func, event ) {\n\n\t\t\t\tBackbone.pubSub.off( event, func, this );\n\t\t\t\tdelete this.subscriptions[ event ];\n\n\t\t\t}, this );\n\n\t\t},\n\n\t\t/**\n\t\t * Remove a single subview (and all it's subviews) by name\n\t\t * @param string name name of the subview\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tremove_subview: function( name ) {\n\n\t\t\tvar view = this.get_subview( name );\n\n\t\t\tif ( ! view ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( view.instance ) {\n\n\t\t\t\t// remove the subviews if the view has subviews\n\t\t\t\tif ( ! _.isEmpty( view.instance.views ) ) {\n\t\t\t\t\tview.instance.events_unsubscribe();\n\t\t\t\t\tview.instance.remove_subviews();\n\t\t\t\t}\n\n\t\t\t\tview.instance.off();\n\t\t\t\tview.instance.off( null, null, null );\n\t\t\t\tview.instance.remove();\n\t\t\t\tview.instance.undelegateEvents();\n\n\t\t\t\t// _.each( view.instance, function( val, key ) {\n\t\t\t\t// \tdelete view.instance[ key ];\n\t\t\t\t// } );\n\n\t\t\t\tview.instance = null;\n\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Remove all subviews (and all the subviews of those subviews)\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tremove_subviews: function() {\n\n\t\t\t_.each( this.views, function( data, name ) {\n\n\t\t\t\tthis.remove_subview( name );\n\n\t\t\t}, this );\n\n\t\t},\n\n\t\t/**\n\t\t * Render subviews based on current state\n\t\t * @param obj view_data additional data to pass to the subviews\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender_subviews: function( view_data ) {\n\n\t\t\tview_data = view_data || {};\n\n\t\t\t_.each( this.views, function( data, name ) {\n\n\t\t\t\tif ( this.state === data.state ) {\n\n\t\t\t\t\tthis.render_subview( name, view_data );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tthis.remove_subview( name );\n\n\t\t\t\t}\n\n\t\t\t}, this );\n\n\t\t},\n\n\t\t/**\n\t\t * Render a single subview by name\n\t\t * @param string name name of the subview\n\t\t * @param obj view_data additional data to pass to the subview initializer\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender_subview: function( name, view_data ) {\n\n\t\t\tvar view = this.get_subview( name );\n\n\t\t\tif ( ! view ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis.remove_subview( name );\n\n\t\t\tif ( ! view.instance ) {\n\t\t\t\tview.instance = new view.class( view_data );\n\t\t\t}\n\n\t\t\tview.instance.render();\n\n\t\t},\n\n\t\t/**\n\t\t * Set the current subview\n\t\t * Must call render after!\n\t\t * @param string state name of the state [builder|editor]\n\t\t * @return obj this for chaining\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tset_state: function ( state ) {\n\n\t\t\tthis.state = state;\n\t\t\treturn this;\n\n\t\t},\n\n\t}\n\n} );\n\n","/**\n * Trashable model\n * @type {Object}\n * @since 3.16.12\n * @version 3.16.12\n */\ndefine( 'Views/_Trashable',[], function() {\n\n\treturn {\n\n\t\t/**\n\t\t * DOM Events\n\t\t * @type {Object}\n\t\t * @since 3.16.12\n\t\t * @version 3.16.12\n\t\t */\n\t\tevents: {\n\t\t\t'click a[href=\"#llms-trash-model\"]': 'trash_model',\n\t\t},\n\n\t\t/**\n\t\t * Remove a model from it's parent and delete it\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.16.12\n\t\t * @version 3.16.12\n\t\t */\n\t\ttrash_model: function( event ) {\n\n\t\t\tif ( event ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tevent.stopPropagation();\n\t\t\t}\n\n\t\t\tvar msg = LLMS.l10n.replace( 'Are you sure you want to move this %s to the trash?', {\n\t\t\t\t'%s': this.model.get_l10n_type(),\n\t\t\t} );\n\n\t\t\tif ( window.confirm( msg ) ) {\n\n\t\t\t\tif ( this.model.collection ) {\n\t\t\t\t\tthis.model.collection.remove( this.model );\n\t\t\t\t}\n\n\t\t\t\t// publish event\n\t\t\t\tBackbone.pubSub.trigger( 'model-trashed', this.model );\n\n\t\t\t\t// trigger local event so extending views can run other actions where necessary\n\t\t\t\tthis.trigger( 'model-trashed', this.model );\n\n\t\t\t}\n\n\t\t},\n\n\t}\n\n} );\n\n","/**\n * Load view mixins\n * @return obj\n * @since 3.17.1\n * @version 3.17.1\n */\ndefine( 'Views/_loader',[\n\t\t'Views/_Detachable',\n\t\t'Views/_Editable',\n\t\t'Views/_Receivable',\n\t\t'Views/_Shiftable',\n\t\t'Views/_Subview',\n\t\t'Views/_Trashable'\n\t],\n\tfunction(\n\t\tDetachable,\n\t\tEditable,\n\t\tReceivable,\n\t\tShiftable,\n\t\tSubview,\n\t\tTrashable\n\t) {\n\n\treturn {\n\t\tDetachable: Detachable,\n\t\tEditable: Editable,\n\t\tReceivable: Receivable,\n\t\tShiftable: Shiftable,\n\t\tSubview: Subview,\n\t\tTrashable: Trashable,\n\t};\n\n} );\n\n","/**\n * Constructor functions for constructing models, views, and collections\n * @since 3.16.0\n * @version 3.17.1\n */\ndefine( 'Controllers/Construct',[\n\t\t'Collections/loader',\n\t\t'Models/loader',\n\t\t'Views/_loader'\n\t], function(\n\t\tCollections,\n\t\tModels,\n\t\tViews\n\t) {\n\n\treturn function() {\n\n\t\t/**\n\t\t * Internal getter\n\t\t * Constructs new Collections, Models, and Views\n\t\t * @param obj type type of object to construct [Collection,Model,View]\n\t\t * @param string name name of the object to construct\n\t\t * @param obj data object data to pass into the object's constructor\n\t\t * @param obj options object options to pass into the constructor\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tfunction get( type, name, data, options ) {\n\n\t\t\tif ( ! type[ name ] ) {\n\t\t\t\tconsole.log( '\"' + name + '\" not found.' );\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\treturn new type[ name ]( data, options );\n\n\t\t}\n\n\t\t/**\n\t\t * Instantiate a collection\n\t\t * @param string name Collection class name (EG: \"Sections\")\n\t\t * @param array data Array of model objects to pass to the constructor\n\t\t * @param obj options Object of options to pass to the constructor\n\t\t * @return obj\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tthis.get_collection = function( name, data, options ) {\n\n\t\t\treturn get( Collections, name, data, options );\n\n\t\t};\n\n\t\t/**\n\t\t * Instantiate a model\n\t\t * @param string name Model class name (EG: \"Section\")\n\t\t * @param obj data Object of model attributes to pass to the constructor\n\t\t * @param obj options Object of options to pass to the constructor\n\t\t * @return obj\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tthis.get_model = function( name, data, options ) {\n\n\t\t\treturn get( Models, name, data, options );\n\n\t\t};\n\n\t\t/**\n\t\t * Let 3rd parties extend a view using any of the mixin (_) views\n\t\t * @param {obj} view base object used for the view\n\t\t * @param... {string} extends any number of strings that should be mixed into the view\n\t\t * @return obj\n\t\t * @since 3.17.1\n\t\t * @version 3.17.1\n\t\t */\n\t\tthis.extend_view = function() {\n\n\t\t\tvar view = arguments[0],\n\t\t\t\ti = 1;\n\n\t\t\twhile ( arguments[ i ] ) {\n\n\t\t\t\tvar classname = arguments[ i ];\n\t\t\t\tif ( Views[ classname ] ) {\n\n\t\t\t\t\tif ( view.events && Views[ classname ].events ) {\n\t\t\t\t\t\tview.events = _.defaults( view.events, Views[ classname ].events );\n\t\t\t\t\t}\n\n\t\t\t\t\tview = _.defaults( view, Views[ classname ] );\n\n\t\t\t\t}\n\n\t\t\t\ti++;\n\t\t\t}\n\n\t\t\treturn Backbone.View.extend( view );\n\n\t\t};\n\n\t\t/**\n\t\t * Allows custom collection registration by extending the default BackBone collection\n\t\t * @param string name model name\n\t\t * @param obj props properties to extend the collection with\n\t\t * @return void\n\t\t * @since 3.17.1\n\t\t * @version 3.17.1\n\t\t */\n\t\tthis.register_collection = function( name, props ) {\n\n\t\t\tCollections[ name ] = Backbone.Collection.extend( props );\n\n\t\t};\n\n\t\t/**\n\t\t * Allows custom model registration by extending the default abstract model\n\t\t * @param string name model name\n\t\t * @param obj props properties to extend the abstract model with\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tthis.register_model = function( name, props ) {\n\n\t\t\tModels[ name ] = Models['Abstract'].extend( props );\n\n\t\t};\n\n\t\treturn this;\n\n\t};\n\n} );\n\n","/**\n * LifterLMS Builder Debugging suite\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Controllers/Debug',[], function() {\n\n \treturn function( settings ) {\n\n \t\tvar self = this,\n \t\t\tenabled = settings.enabled || false;\n\n\t\t/**\n\t\t * Disable debugging\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n \t\tthis.disable = function() {\n\n \t\t\tself.log( 'LifterLMS Builder debugging disabled' );\n \t\t\tenabled = false;\n\n \t\t};\n\n\t\t/**\n\t\t * Enable debugging\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n \t\tthis.enable = function() {\n\n \t\t\tenabled = true;\n \t\t\tself.log( 'LifterLMS Builder debugging enabled' );\n\n \t\t};\n\n \t\t/**\n \t\t * General logging function\n \t\t * Logs to the js console only if logging is enabled\n \t\t * @return void\n \t\t * @since 3.16.0\n \t\t * @version 3.16.0\n \t\t */\n \t\tthis.log = function() {\n\n\t\t\tif ( ! enabled ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t_.each( arguments, function( data ) {\n\t\t\t\tconsole.log( data );\n\t\t\t} );\n\n \t\t};\n\n \t\t/**\n \t\t * Toggles current state of the logger on or off\n \t\t * @return void\n \t\t * @since 3.16.0\n \t\t * @version 3.16.0\n \t\t */\n \t\tthis.toggle = function() {\n\n\t\t\tif ( enabled ) {\n\t\t\t\tself.disable();\n\t\t\t} else {\n\t\t\t\tself.enable();\n\t\t\t}\n\n \t\t};\n\n \t\t// on startup, log a message if logging is enabled\n \t\tif ( enabled ) {\n \t\t\tself.enable();\n \t\t}\n\n \t}\n\n } );\n\n","/**\n * Model schema functions\n * @since 3.17.0\n * @version 3.17.0\n */\ndefine( 'Controllers/Schemas',[], function() {\n\n\t/**\n\t * Main Schemas class\n\t * @param obj schemas schemas definitions initialized via PHP filters\n\t * @return obj\n\t * @since 3.17.0\n\t * @version 3.17.0\n\t */\n\treturn function( schemas ) {\n\n\t\t// initialize any custom schemas defined via PHP\n\t\tvar custom_schemas = schemas;\n\t\t_.each( custom_schemas, function( type ) {\n\t\t\t_.each( type, function( schema ) {\n\t\t\t\tschema.custom = true;\n\t\t\t} );\n\t\t} );\n\n\t\t/**\n\t\t * Retrieve a schema for a given model by type\n\t\t * Extends default schemas definitions with custom 3rd party definitions\n\t\t * @param obj schema default schema definition from the model (or empty object if none defined)\n\t\t * @param string model_type the model type ('lesson', 'quiz', etc)\n\t\t * @param obj model Instance of the Backbone.Model for the given model\n\t\t * @return obj\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tthis.get = function( schema, model_type, model ) {\n\n\t\t\t// extend the default schema with custom php schemas for the type if they exist\n\t\t\tif ( custom_schemas[ model_type ] ) {\n\t\t\t\tschema = _.extend( schema, custom_schemas[ model_type ] );\n\t\t\t}\n\n\t\t\treturn schema;\n\n\t\t};\n\n\t\treturn this;\n\n\t};\n\n} );\n\n","/**\n * Sync builder data to the server\n * @since 3.16.0\n * @version 3.17.1\n */\ndefine( 'Controllers/Sync',[], function() {\n\n \treturn function( Course, settings ) {\n\n \t\tthis.saving = false;\n\n \t\tvar self = this,\n \t\t\tautosave = true,\n \t\t\tcheck_interval = null,\n \t\t\tcheck_interval_ms = settings.check_interval_ms || 10000,\n \t\t\tdetached = new Backbone.Collection(),\n \t\t\ttrashed = new Backbone.Collection();\n\n\t\t/**\n\t\t * init\n\t\t * @return void\n\t\t * @since 3.16.7\n\t\t * @version 3.16.7\n\t\t */\n \t\tfunction init() {\n\n \t\t\t// determine if autosaving is possible\n \t\t\tif ( 'undefined' === typeof wp.heartbeat ) {\n\n \t\t\t\twindow.llms_builder.debug.log( 'WordPress Heartbeat disabled. Autosaving is disabled!' );\n \t\t\t\tautosave = false;\n\n \t\t\t}\n\n\t\t\t// setup the check interval\n\t\t\tif ( check_interval_ms ) {\n\t\t\t\tself.set_check_interval( check_interval_ms );\n\t\t\t}\n\n\t\t\t// warn when users attempt to leave the page\n\t\t\t$( window ).on( 'beforeunload', function() {\n\n\t\t\t\tif ( self.has_unsaved_changes() ) {\n\t\t\t\t\tcheck_for_changes();\n\t\t\t\t\treturn 'Are you sure you want to abandon your changes?';\n\t\t\t\t}\n\n\t\t\t} );\n\n \t\t};\n\n \t\t/*\n \t\t\t /$$ /$$ /$$ /$$\n \t\t\t|__/ | $$ | $$ |__/\n \t\t\t /$$ /$$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$$ /$$$$$$ | $$ /$$$$$$ /$$$$$$ /$$\n \t\t\t| $$| $$__ $$|_ $$_/ /$$__ $$ /$$__ $$| $$__ $$ |____ $$| $$ |____ $$ /$$__ $$| $$\n \t\t\t| $$| $$ \\ $$ | $$ | $$$$$$$$| $$ \\__/| $$ \\ $$ /$$$$$$$| $$ /$$$$$$$| $$ \\ $$| $$\n \t\t\t| $$| $$ | $$ | $$ /$$| $$_____/| $$ | $$ | $$ /$$__ $$| $$ /$$__ $$| $$ | $$| $$\n \t\t\t| $$| $$ | $$ | $$$$/| $$$$$$$| $$ | $$ | $$| $$$$$$$| $$ | $$$$$$$| $$$$$$$/| $$\n \t\t\t|__/|__/ |__/ \\___/ \\_______/|__/ |__/ |__/ \\_______/|__/ \\_______/| $$____/ |__/\n \t\t\t | $$\n \t\t\t | $$\n \t\t\t |__/\n \t\t*/\n\n \t\t/**\n \t\t * Adds error message(s) to the data object returned by heartbeat-tick\n \t\t * @param obj data llms_builder data object from heartbeat-tick\n \t\t * @param string|array err error messages array or string\n \t\t * @return obj\n \t\t * @since 3.16.0\n \t\t * @version 3.16.0\n \t\t */\n\t\tfunction add_error_msg( data, err ) {\n\n\t\t\tif ( 'success' === data.status ) {\n\t\t\t\tdata.message = [];\n\t\t\t}\n\n\t\t\tdata.status = 'error';\n\t\t\tif ( 'string' === typeof err ) {\n\t\t\t\terr = [ err ];\n\t\t\t}\n\t\t\tdata.message = data.message.concat( err );\n\n\t\t\treturn data;\n\n\t\t};\n\n\t\t/**\n\t\t * Publish sync status so other areas of the application can see what's happening here\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tfunction check_for_changes() {\n\n\t\t\tvar data = {};\n\t\t\tdata.changes = self.get_unsaved_changes();\n\t\t\tdata.has_unsaved_changes = self.has_unsaved_changes( data.changes );\n\t\t\tdata.saving = self.saving;\n\n\t\t\twindow.llms_builder.debug.log( '==== start changes check ====', data, '==== finish changes check ====' );\n\n\t\t\tBackbone.pubSub.trigger( 'current-save-status', data );\n\n\t\t};\n\n\t\t/**\n\t\t * Manually Save data via Admin AJAX when the heartbeat API has been disabled\n\t\t * @return void\n\t\t * @since 3.16.7\n\t\t * @version 3.16.7\n\t\t */\n\t\tfunction do_ajax_save() {\n\n\t\t\t// prevent simultaneous saves\n\t\t\tif ( self.saving ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar changes = self.get_unsaved_changes();\n\n\t\t\t// only send data if we have data to send\n\t\t\tif ( self.has_unsaved_changes( changes ) ) {\n\n\t\t\t\tchanges.id = Course.get( 'id' );\n\n\t\t\t\tLLMS.Ajax.call( {\n\t\t\t\t\tdata: {\n\t\t\t\t\t\taction: 'llms_builder',\n\t\t\t\t\t\taction_type: 'ajax_save',\n\t\t\t\t\t\tcourse_id: changes.id,\n\t\t\t\t\t\tllms_builder: JSON.stringify( changes ),\n\t\t\t\t\t},\n\t\t\t\t\tbeforeSend: function() {\n\n\t\t\t\t\t\twindow.llms_builder.debug.log( '==== start do_ajax_save before ====', changes, '==== finish do_ajax_save before ====' );\n\n\t\t\t\t\t\tself.saving = true;\n\n\t\t\t\t\t\tBackbone.pubSub.trigger( 'heartbeat-send', self );\n\n\t\t\t\t\t},\n\t\t\t\t\terror: function( xhr, status, error ) {\n\n\t\t\t\t\t\twindow.llms_builder.debug.log( '==== start do_ajax_save error ====', data, '==== finish do_ajax_save error ====' );\n\n\t\t\t\t\t\tself.saving = false;\n\n\t\t\t\t\t\tBackbone.pubSub.trigger( 'heartbeat-tick', self, {\n\t\t\t\t\t\t\tstatus: 'error',\n\t\t\t\t\t\t\tmessage: xhr.responseText + ' (' + error + ' ' + status +')',\n\t\t\t\t\t\t} );\n\n\t\t\t\t\t},\n\t\t\t\t\tsuccess: function( res ) {\n\n\t\t\t\t\t\tif ( ! res.llms_builder ) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\twindow.llms_builder.debug.log( '==== start do_ajax_save success ====', res, '==== finish do_ajax_save success ====' );\n\n\t\t\t\t\t\tres.llms_builder = process_removals( res.llms_builder );\n\t\t\t\t\t\tres.llms_builder = process_updates( res.llms_builder );\n\n\t\t\t\t\t\tself.saving = false;\n\n\t\t\t\t\t\tBackbone.pubSub.trigger( 'heartbeat-tick', self, res.llms_builder );\n\n\t\t\t\t\t}\n\n\t\t\t\t} );\n\n\t\t\t}\n\n\n\t\t};\n\n\t\t/**\n\t\t * Retrieve all the attributes changed on a model since the last sync\n\t\t *\n\t\t * For a new model (a model with a temp ID) or a model where _forceSync has been defined ALL atts will be returned\n\t\t * For an existing model (without a temp ID) only retrieves changed attributes as tracked by Backbone.TrackIt\n\t\t *\n\t\t * This function excludes any attributes defined as child attributes via the models relationship settings\n\t\t *\n\t\t * @param obj model instance of a Backbone.Model\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.6\n\t\t */\n\t\tfunction get_changed_attributes( model ) {\n\n\t\t\tvar atts = {},\n\t\t\t\tsync_type;\n\n\t\t\t// don't save mid editing\n\t\t\tif ( model.get( '_has_focus' ) ) {\n\t\t\t\treturn atts;\n\t\t\t}\n\n\t\t\t// model hasn't been persisted to the database to get a real ID yet\n\t\t\t// send *all* of it's atts\n\t\t\tif ( has_temp_id( model ) || true === model.get( '_forceSync' ) ) {\n\n\t\t\t\tatts = _.clone( model.attributes );\n\t\t\t\tsync_type = 'full';\n\n\t\t\t// only send the changed atts\n\t\t\t} else {\n\n\t\t\t\tatts = model.unsavedAttributes();\n\t\t\t\tsync_type = 'partial';\n\n\t\t\t}\n\n\t\t\tvar exclude = ( model.get_relationships ) ? model.get_child_props() : [];\n\t\t\tatts = _.omit( atts, function( val, key ) {\n\n\t\t\t\t// exclude keys that start with an underscore which are used by the\n\t\t\t\t// application but don't need to be stored in the database\n\t\t\t\tif ( 0 === key.indexOf( '_' ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t} else if ( -1 !== exclude.indexOf( key ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\treturn false;\n\n\t\t\t} );\n\n\t\t\tif ( model.before_save ) {\n\t\t\t\tatts = model.before_save( atts, sync_type );\n\t\t\t}\n\n\t\t\treturn atts;\n\n\t\t};\n\n\t\t/**\n\t\t * Get all the changes to an object (either a Model or a Collection of models)\n\t\t * Returns only changes to models and the IDs of that model (should changes exist)\n\t\t * Uses get_changed_attributes() to determine if all atts or only changed atts are needed\n\t\t * Processes children intelligently to only return changed children rather than the entire collection of children\n\t\t *\n\t\t * @param obj object instance of a Backbone.Model or Backbone.Collection\n\t\t * @return obj|array\t \t\tif object is a model, returns an object\n\t\t * \tif object is a collection, returns an array of objects\n\t\t * @since 3.16.0\n\t\t * @version 3.16.11\n\t\t */\n\t\tfunction get_changes_to_object( object ) {\n\n\t\t\tvar changed_atts;\n\n\t\t\tif ( object instanceof Backbone.Model ) {\n\n\t\t\t\tchanged_atts = get_changed_attributes( object );\n\n\t\t\t\tif ( object.get_relationships ) {\n\n\t\t\t\t\t_.each( object.get_child_props(), function( prop ) {\n\n\t\t\t\t\t\tvar children = get_changes_to_object( object.get( prop ) );\n\t\t\t\t\t\tif ( ! _.isEmpty( children ) ) {\n\t\t\t\t\t\t\tchanged_atts[ prop ] = children;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} );\n\n\t\t\t\t}\n\n\t\t\t\t// if we have any data, add the id to the model\n\t\t\t\tif ( ! _.isEmpty( changed_atts ) ) {\n\t\t\t\t\tchanged_atts.id = object.get( 'id' );\n\t\t\t\t}\n\n\t\t\t} else if ( object instanceof Backbone.Collection ) {\n\n\t\t\t\tchanged_atts = [];\n\t\t\t\tobject.each( function( model ) {\n\t\t\t\t\tvar model_changes = get_changes_to_object( model );\n\t\t\t\t\tif ( ! _.isEmpty( model_changes ) ) {\n\t\t\t\t\t\tchanged_atts.push( model_changes );\n\t\t\t\t\t}\n\t\t\t\t} );\n\n\t\t\t}\n\n\t\t\treturn changed_atts;\n\n\t\t};\n\n\t\t/**\n\t\t * Determines if a model has a temporary ID or a real persisted ID\n\t\t * @param obj model instance of a model\n\t\t * @return boolean\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tfunction has_temp_id( model ) {\n\n\t\t\treturn ( ! _.isNumber( model.id ) && 0 === model.id.indexOf( 'temp_' ) );\n\n\t\t};\n\n\t\t/**\n\t\t * Compares changes synced to the server against current model and restarts\n\t\t * tracking on elements that haven't changed since the last sync\n\t\t * @param obj model instance of a Backbone.Model\n\t\t * @param obj data data set that was processed by the server\n\t\t * @return void\n\t\t * @since 3.16.11\n\t\t * @version 3.16.6\n\t\t */\n\t\tfunction maybe_restart_tracking( model, data ) {\n\n\t\t\tvar omit = [ 'id', 'orig_id' ];\n\n\t\t\tif ( model.get_relationships ) {\n\t\t\t\tomit.concat( model.get_child_props() );\n\t\t\t}\n\n\t\t\t_.each( _.omit( data, omit ), function( val, prop ) {\n\n\t\t\t\tif ( _.isEqual( model.get( prop ), val ) ) {\n\t\t\t\t\tdelete model._unsavedChanges[ prop ];\n\t\t\t\t\tmodel._originalAttrs[ prop ] = val;\n\t\t\t\t}\n\n\t\t\t} );\n\n\t\t\t// if syncing was forced, allow tracking to move forward as normal moving forward\n\t\t\tmodel.unset( '_forceSync' );\n\n\t\t};\n\n\t\t/**\n\t\t * Processes response data from heartbeat-tick related to trashing & detaching models\n\t\t * On success, removes from local removal collection\n\t\t * On error, appends error messages to the data object returned to UI for on-screen feedback\n\t\t * @param obj data data.llms_builder object from heartbeat-tick response\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.17.1\n\t\t */\n\t\tfunction process_removals( data ) {\n\n\t\t\t// check removals for errors\n\t\t\tvar removals = {\n\t\t\t\tdetach: detached,\n\t\t\t\ttrash: trashed,\n\t\t\t};\n\n\t\t\t_.each( removals, function( coll, key ) {\n\n\t\t\t\tif ( data[ key ] ) {\n\n\t\t\t\t\tvar errors = [];\n\n\t\t\t\t\t_.each( data[ key ] , function( info ) {\n\n\t\t\t\t\t\t// succesfully detached, remove it from the detached collection\n\t\t\t\t\t\tif ( ! info.error ) {\n\n\t\t\t\t\t\t\tcoll.remove( info.id );\n\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\terrors.push( info.error );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} );\n\n\t\t\t\t\tif ( errors.length ) {\n\t\t\t\t\t\t_.extend( data, add_error_msg( data, errors ) );\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t} );\n\n\t\t\treturn data;\n\t\t}\n\n\t\t/**\n\t\t * Processes response data from heartbeat-tick related to creating / updating a single object\n\t\t * Handles both collections and models as a recursive function\n\t\t * @param {[type]} data [description]\n\t\t * @param {[type]} type [description]\n\t\t * @param {[type]} parent [description]\n\t\t * @param {[type]} main_data [description]\n\t\t * @return {[type]}\n\t\t * @since 3.16.0\n\t\t * @version 3.16.11\n\t\t */\n\t\tfunction process_object_updates( data, type, parent, main_data ) {\n\n\t\t\tif ( ! data[ type ] ) {\n\t\t\t\treturn data;\n\t\t\t}\n\n\t\t\tif ( parent.get( type ) instanceof Backbone.Model ) {\n\n\t\t\t\tvar info = data[ type ];\n\n\t\t\t\tif ( info.error ) {\n\n\t\t\t\t\t_.extend( main_data, add_error_msg( main_data, info.error ) );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tvar model = parent.get( type );\n\n\t\t\t\t\t// update temp ids with the real id\n\t\t\t\t\tif ( info.id != info.orig_id ) {\n\t\t\t\t\t\tmodel.set( 'id', info.id );\n\t\t\t\t\t\tdelete model._unsavedChanges.id;\n\t\t\t\t\t}\n\t\t\t\t\tmaybe_restart_tracking( model, info );\n\n\t\t\t\t\t// check children\n\t\t\t\t\tif ( model.get_relationships ) {\n\n\t\t\t\t\t\t_.each( model.get_child_props(), function( child_key ) {\n\t\t\t\t\t\t\t_.extend( data[ type ], process_object_updates( data[ type ], child_key, model, main_data ) );\n\t\t\t\t\t\t} );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t} else if ( parent.get( type ) instanceof Backbone.Collection ) {\n\n\t\t\t\t_.each( data[ type ], function( info, index ) {\n\n\t\t\t\t\tif ( info.error ) {\n\n\t\t\t\t\t\t_.extend( main_data, add_error_msg( main_data, info.error ) );\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tvar model = parent.get( type ).get( info.orig_id );\n\n\t\t\t\t\t\t// update temp ids with the real id\n\t\t\t\t\t\tif ( info.id != info.orig_id ) {\n\t\t\t\t\t\t\tmodel.set( 'id', info.id );\n\t\t\t\t\t\t\tdelete model._unsavedChanges.id;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmaybe_restart_tracking( model, info );\n\n\t\t\t\t\t\t// check children\n\t\t\t\t\t\tif ( model.get_relationships ) {\n\n\t\t\t\t\t\t\t_.each( model.get_child_props(), function( child_key ) {\n\t\t\t\t\t\t\t\t_.extend( data[ type ], process_object_updates( data[ type ][ index ], child_key, model, main_data ) );\n\t\t\t\t\t\t\t} );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t} );\n\n\t\t\t}\n\n\t\t\treturn main_data;\n\n\t\t};\n\n\t\t/**\n\t\t * Processes response data from heartbeat-tick related to updating & creating new models\n\t\t * On success, removes from local removal collection\n\t\t * On error, appends error messages to the data object returned to UI for on-screen feedback\n\t\t * @param obj data data.llms_builder object from heartbeat-tick response\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tfunction process_updates( data ) {\n\n\t\t\t// only mess with updates data\n\t\t\tif ( ! data.updates ) {\n\t\t\t\treturn data;\n\t\t\t}\n\n\t\t\tif ( data.updates ) {\n\t\t\t\tdata = process_object_updates( data.updates, 'sections', Course, data );\n\t\t\t}\n\n\t\t\treturn data;\n\n\t\t};\n\n\t\t/*\n\t\t\t /$$ /$$ /$$ /$$\n\t\t\t | $$ | $$|__/ |__/\n\t\t\t /$$$$$$ /$$ /$$| $$$$$$$ | $$ /$$ /$$$$$$$ /$$$$$$ /$$$$$$ /$$\n\t\t\t /$$__ $$| $$ | $$| $$__ $$| $$| $$ /$$_____/ |____ $$ /$$__ $$| $$\n\t\t\t| $$ \\ $$| $$ | $$| $$ \\ $$| $$| $$| $$ /$$$$$$$| $$ \\ $$| $$\n\t\t\t| $$ | $$| $$ | $$| $$ | $$| $$| $$| $$ /$$__ $$| $$ | $$| $$\n\t\t\t| $$$$$$$/| $$$$$$/| $$$$$$$/| $$| $$| $$$$$$$ | $$$$$$$| $$$$$$$/| $$\n\t\t\t| $$____/ \\______/ |_______/ |__/|__/ \\_______/ \\_______/| $$____/ |__/\n\t\t\t| $$ | $$\n\t\t\t| $$ | $$\n\t\t\t|__/ |__/\n\t\t*/\n\n\t\t/**\n\t\t * Retrieve all unsaved changes for the builder instance\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.17.1\n\t\t */\n\t\tthis.get_unsaved_changes = function() {\n\n\t\t\treturn {\n\t\t\t\tdetach: detached.pluck( 'id' ),\n\t\t\t\ttrash: trashed.pluck( 'id' ),\n\t\t\t\tupdates: get_changes_to_object( Course ),\n\n\t\t\t}\n\t\t};\n\n\t\t/**\n\t\t * Check if the builder instance has unsaved changes\n\t\t * @param obj changes optionally pass in an object from the return of this.get_unsaved_changes()\n\t\t * save some resources by not running the check twice during heartbeats\n\t\t * @return boolean\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tthis.has_unsaved_changes = function( changes ) {\n\n\t\t\tif ( 'undefined' === typeof changes ) {\n\t\t\t\tchanges = self.get_unsaved_changes();\n\t\t\t}\n\n\t\t\t// check all possible keys, once we find one with content we have some changes to persist\n\t\t\tvar found = _.find( changes, function( data ) {\n\n\t\t\t\treturn ( false === _.isEmpty( data ) );\n\n\t\t\t} );\n\n\t\t\treturn found ? true : false;\n\n\t\t};\n\n\t\t/**\n\t\t * Save changes right now.\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.7\n\t\t */\n\t\tthis.save_now = function() {\n\t\t\tif ( autosave ) {\n\t\t\t\twp.heartbeat.connectNow();\n\t\t\t} else {\n\t\t\t\tdo_ajax_save();\n\t\t\t}\n\t\t};\n\n\t\t/**\n\t\t * Update the interval that checks for changes to the builder instance\n\t\t * @param int ms time (in milliseconds) to run the check on\n\t\t * pass 0 to disable the check\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tthis.set_check_interval = function( ms ) {\n\t\t\tcheck_interval_ms = ms;\n\t\t\tif ( check_interval ) {\n\t\t\t\tclearInterval( check_interval );\n\t\t\t}\n\t\t\tif ( check_interval_ms ) {\n\t\t\t\tcheck_interval = setInterval( check_for_changes, check_interval_ms );\n\t\t\t}\n\t\t};\n\n\t\t/*\n\t\t\t /$$ /$$ /$$\n\t\t\t| $$|__/ | $$\n\t\t\t| $$ /$$ /$$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$$\n\t\t\t| $$| $$ /$$_____/|_ $$_/ /$$__ $$| $$__ $$ /$$__ $$ /$$__ $$ /$$_____/\n\t\t\t| $$| $$| $$$$$$ | $$ | $$$$$$$$| $$ \\ $$| $$$$$$$$| $$ \\__/| $$$$$$\n\t\t\t| $$| $$ \\____ $$ | $$ /$$| $$_____/| $$ | $$| $$_____/| $$ \\____ $$\n\t\t\t| $$| $$ /$$$$$$$/ | $$$$/| $$$$$$$| $$ | $$| $$$$$$$| $$ /$$$$$$$/\n\t\t\t|__/|__/|_______/ \\___/ \\_______/|__/ |__/ \\_______/|__/ |_______/\n\t\t*/\n\n\t\t/**\n\t\t * Listen for detached models and send them to the server for persistence\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tBackbone.pubSub.on( 'model-detached', function( model ) {\n\n\t\t\t// detached models with temp ids haven't been persisted so we don't care\n\t\t\tif ( has_temp_id( model ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tdetached.add( _.clone( model.attributes ) );\n\n\t\t} );\n\n\t\t/**\n\t\t * Listen for trashed models and send them to the server for deletion\n\t\t * @since 3.16.0\n\t\t * @version 3.17.1\n\t\t */\n\t\tBackbone.pubSub.on( 'model-trashed', function( model ) {\n\n\t\t\t// if the model has a temp ID we don't have to persist the deletion\n\t\t\tif ( has_temp_id( model ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar data = _.clone( model.attributes );\n\n\t\t\tif ( model.get_trash_id ) {\n\t\t\t\tdata.id = model.get_trash_id();\n\t\t\t}\n\n\t\t\ttrashed.add( data );\n\n\t\t} );\n\n\t\t/*\n\t\t\t /$$ /$$ /$$ /$$\n\t\t\t| $$ | $$ | $$ | $$\n\t\t\t| $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ | $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$\n\t\t\t| $$__ $$ /$$__ $$ |____ $$ /$$__ $$|_ $$_/ | $$__ $$ /$$__ $$ |____ $$|_ $$_/\n\t\t\t| $$ \\ $$| $$$$$$$$ /$$$$$$$| $$ \\__/ | $$ | $$ \\ $$| $$$$$$$$ /$$$$$$$ | $$\n\t\t\t| $$ | $$| $$_____/ /$$__ $$| $$ | $$ /$$| $$ | $$| $$_____/ /$$__ $$ | $$ /$$\n\t\t\t| $$ | $$| $$$$$$$| $$$$$$$| $$ | $$$$/| $$$$$$$/| $$$$$$$| $$$$$$$ | $$$$/\n\t\t\t|__/ |__/ \\_______/ \\_______/|__/ \\___/ |_______/ \\_______/ \\_______/ \\___/\n\t\t*/\n\n\t\t/**\n\t\t * Add data to the WP heartbeat to persist new models, changes, and deletions to the DB\n\t\t * @since 3.16.0\n\t\t * @version 3.16.7\n\t\t */\n\t\t$( document ).on( 'heartbeat-send', function( event, data ) {\n\n\t\t\t// prevent simultaneous saves\n\t\t\tif ( self.saving ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar changes = self.get_unsaved_changes();\n\n\t\t\t// only send data if we have data to send\n\t\t\tif ( self.has_unsaved_changes( changes ) ) {\n\n\t\t\t\tchanges.id = Course.get( 'id' );\n\t\t\t\tself.saving = true;\n\t\t\t\tdata.llms_builder = JSON.stringify( changes );\n\n\t\t\t}\n\n\t\t\twindow.llms_builder.debug.log( '==== start heartbeat-send ====', data, '==== finish heartbeat-send ====' );\n\n\t\t\tBackbone.pubSub.trigger( 'heartbeat-send', self );\n\n\t\t} );\n\n\t\t/**\n\t\t * Confirm detachments & deletions and replace temp IDs with new persisted IDs\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\t$( document ).on( 'heartbeat-tick', function( event, data ) {\n\n\t\t\tif ( ! data.llms_builder ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\twindow.llms_builder.debug.log( '==== start heartbeat-tick ====', data, '==== finish heartbeat-tick ====' );\n\n\t\t\tdata.llms_builder = process_removals( data.llms_builder );\n\t\t\tdata.llms_builder = process_updates( data.llms_builder );\n\n\t\t\tself.saving = false;\n\n\t\t\tBackbone.pubSub.trigger( 'heartbeat-tick', self, data.llms_builder );\n\n\t\t} );\n\n\t\t/**\n\t\t * On heartbeat errors publish an error to the main builder application\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\t$( document ).on( 'heartbeat-error', function( event, data ) {\n\n\t\t\twindow.llms_builder.debug.log( '==== start heartbeat-error ====', data, '==== finish heartbeat-error ====' );\n\n\t\t\tself.saving = false;\n\n\t\t\tBackbone.pubSub.trigger( 'heartbeat-tick', self, {\n\t\t\t\tstatus: 'error',\n\t\t\t\tmessage: data.responseText + ' (' + data.status + ' ' + data.statusText +')',\n\t\t\t} );\n\n\t\t} );\n\n\t\t/*\n\t\t\t /$$ /$$ /$$\n\t\t\t|__/ |__/ | $$\n\t\t\t /$$ /$$$$$$$ /$$ /$$$$$$\n\t\t\t| $$| $$__ $$| $$|_ $$_/\n\t\t\t| $$| $$ \\ $$| $$ | $$\n\t\t\t| $$| $$ | $$| $$ | $$ /$$\n\t\t\t| $$| $$ | $$| $$ | $$$$/\n\t\t\t|__/|__/ |__/|__/ \\___/\n\t\t*/\n\t\tinit();\n\n\t\treturn this;\n\n\t};\n\n} );\n\n","/**\n * Single Lesson View\n * @since 3.16.0\n * @version 3.17.0\n */\ndefine( 'Views/Lesson',[\n\t\t'Views/_Detachable',\n\t\t'Views/_Editable',\n\t\t'Views/_Shiftable',\n\t\t'Views/_Trashable'\n\t], function(\n\t\tDetachable,\n\t\tEditable,\n\t\tShiftable,\n\t\tTrashable\n\t) {\n\n\treturn Backbone.View.extend( _.defaults( {\n\n\t\t/**\n\t\t * Get default attributes for the html wrapper element\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tattributes: function() {\n\t\t\treturn {\n\t\t\t\t'data-id': this.model.id,\n\t\t\t\t'data-section-id': this.model.get( 'parent_section' ),\n\t\t\t};\n\t\t},\n\n\t\t/**\n\t\t * HTML class names\n\t\t * @type {String}\n\t\t */\n\t\tclassName: 'llms-builder-item llms-lesson',\n\n\t\t/**\n\t\t * Events\n\t\t * @type {Object}\n\t\t * @since 3.16.0\n\t\t * @version 3.16.12\n\t\t */\n\t\tevents: _.defaults( {\n\t\t\t'click .edit-lesson': 'open_lesson_editor',\n\t\t\t'click .edit-quiz': 'open_quiz_editor',\n\t\t\t'click .edit-assignment': 'open_assignment_editor',\n\t\t\t'click .section-prev': 'section_prev',\n\t\t\t'click .section-next': 'section_next',\n\t\t\t'click .shift-up--lesson': 'shift_up',\n\t\t\t'click .shift-down--lesson': 'shift_down',\n\t\t}, Detachable.events, Editable.events, Trashable.events ),\n\n\t\t/**\n\t\t * HTML element wrapper ID attribute\n\t\t * @return string\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tid: function() {\n\t\t\treturn 'llms-lesson-' + this.model.id;\n\t\t},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'li',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-lesson-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.14.1\n\t\t * @version 3.14.1\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\tthis.render();\n\n\t\t\tthis.listenTo( this.model, 'change', this.render );\n\n\t\t\tBackbone.pubSub.on( 'lesson-selected', this.on_select, this );\n\t\t\tBackbone.pubSub.on( 'new-lesson-added', this.on_select, this );\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender: function() {\n\n\t\t\tthis.$el.html( this.template( this.model ) );\n\t\t\tthis.maybe_hide_shiftable_buttons();\n\t\t\tif ( this.model.get( '_selected' ) ) {\n\t\t\t\tthis.$el.addClass( 'selected' );\n\t\t\t} else {\n\t\t\t\tthis.$el.removeClass( 'selected' );\n\t\t\t}\n\t\t\treturn this;\n\n\t\t},\n\n\t\t/**\n\t\t * Click event for the assignment editor action icon\n\t\t * Opens sidebar to the assignment editor tab\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\topen_assignment_editor: function() {\n\n\t\t\tBackbone.pubSub.trigger( 'lesson-selected', this.model, 'assignment' );\n\t\t\tthis.model.set( '_selected', true );\n\n\t\t},\n\n\t\t/**\n\t\t * Click event for lesson settings action icon\n\t\t * Opens sidebar to the lesson editor tab\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\topen_lesson_editor: function() {\n\n\t\t\tBackbone.pubSub.trigger( 'lesson-selected', this.model, 'lesson' );\n\t\t\tthis.model.set( '_selected', true );\n\n\t\t},\n\n\t\t/**\n\t\t * Click event for the quiz editor action icon\n\t\t * Opens sidebar to the quiz editor tab\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\topen_quiz_editor: function() {\n\n\t\t\tBackbone.pubSub.trigger( 'lesson-selected', this.model, 'quiz' );\n\t\t\tthis.model.set( '_selected', true );\n\n\t\t},\n\n\t\t/**\n\t\t * When a lesson is selected mark it as selected in the hidden prop\n\t\t * Allows views to re-render and reflect current state properly\n\t\t * @param obj model lesson model that's been selected\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\ton_select: function( model ) {\n\n\t\t\tif ( this.model.id !== model.id ) {\n\t\t\t\tthis.model.set( '_selected', false );\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Click event for the \"Next Section\" button\n\t\t * @param obj event js event obj\n\t\t * @return void\n\t\t * @since 3.16.11\n\t\t * @version 3.16.11\n\t\t */\n\t\tsection_next: function( event ) {\n\t\t\tevent.preventDefault();\n\t\t\tthis._move_to_section( 'next' );\n\t\t},\n\n\t\t/**\n\t\t * Click event for the \"Previous Section\" button\n\t\t * @param obj event js event obj\n\t\t * @return void\n\t\t * @since 3.16.11\n\t\t * @version 3.16.11\n\t\t */\n\t\tsection_prev: function( event ) {\n\t\t\tevent.preventDefault();\n\t\t\tthis._move_to_section( 'prev' );\n\t\t},\n\n\t\t/**\n\t\t * Move the lesson into a new section\n\t\t * @param string direction direction [prev|next]\n\t\t * @return void\n\t\t * @since 3.16.11\n\t\t * @version 3.16.11\n\t\t */\n\t\t_move_to_section: function( direction ) {\n\n\t\t\tvar from_coll = this.model.collection,\n\t\t\t\tto_section;\n\n\t\t\tif ( 'next' === direction ) {\n\t\t\t\tto_section = from_coll.parent.get_next();\n\t\t\t} else if ( 'prev' === direction ) {\n\t\t\t\tto_section = from_coll.parent.get_prev();\n\t\t\t}\n\n\t\t\tif ( to_section ) {\n\n\t\t\t\tfrom_coll.remove( this.model );\n\t\t\t\tto_section.add_lesson( this.model );\n\t\t\t\tto_section.set( '_expanded', true );\n\n\t\t\t}\n\n\t\t},\n\n\t}, Detachable, Editable, Shiftable, Trashable ) );\n\n} );\n\n","/**\n * Single Section View\n * @since 3.13.0\n * @version 3.16.0\n */\ndefine( 'Views/LessonList',[ 'Views/Lesson', 'Views/_Receivable' ], function( LessonView, Receivable ) {\n\n\treturn Backbone.CollectionView.extend( _.defaults( {\n\n\t\tclassName: 'llms-lessons',\n\n\t\t/**\n\t\t * Section model\n\t\t * @type {[type]}\n\t\t */\n\t\tmodelView: LessonView,\n\n\t\t/**\n\t\t * Are sections selectable?\n\t\t * @type {Bool}\n\t\t */\n\t\tselectable: false,\n\n\t\t/**\n\t\t * Are sections sortable?\n\t\t * @type {Bool}\n\t\t */\n\t\tsortable: true,\n\n\t\tsortableOptions: {\n\t\t\taxis: false,\n\t\t\tconnectWith: '.llms-lessons',\n\t\t\tcursor: 'move',\n\t\t\thandle: '.drag-lesson',\n\t\t\titems: '.llms-lesson',\n\t\t\tplaceholder: 'llms-lesson llms-sortable-placeholder',\n\t\t},\n\n\t\tsortable_start: function( collection ) {\n\t\t\t$( '.llms-lessons' ).addClass( 'dragging' );\n\t\t},\n\n\t\tsortable_stop: function( collection ) {\n\t\t\t$( '.llms-lessons' ).removeClass( 'dragging' );\n\t\t},\n\n\t\t/**\n\t\t * Overloads the function from Backbone.CollectionView core because it doesn't send stop events\n\t\t * if moving from one sortable to another... :-(\n\t\t * @param obj event js event object\n\t\t * @param obj ui jQuery UI object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\t_sortStop : function( event, ui ) {\n\n\t\t\tvar modelBeingSorted = this.collection.get( ui.item.attr( 'data-model-cid' ) ),\n\t\t\t\tmodelViewContainerEl = this._getContainerEl(),\n\t\t\t\tnewIndex = modelViewContainerEl.children().index( ui.item );\n\n\t\t\tif ( newIndex == -1 && modelBeingSorted ) {\n\t\t\t\tthis.collection.remove( modelBeingSorted );\n\t\t\t}\n\n\t\t\tthis._reorderCollectionBasedOnHTML();\n\t\t\tthis.updateDependentControls();\n\n\t\t\tif( this._isBackboneCourierAvailable() ) {\n\t\t\t\tthis.spawn( 'sortStop', { modelBeingSorted : modelBeingSorted, newIndex : newIndex } );\n\t\t\t} else {\n\t\t\t\tthis.trigger( 'sortStop', modelBeingSorted, newIndex );\n\t\t\t}\n\n\t\t},\n\n\t}, Receivable ) );\n\n} );\n\n","/**\n * Single Section View\n * @since 3.13.0\n * @version 3.16.12\n */\ndefine( 'Views/Section',[\n\t\t'Views/LessonList',\n\t\t'Views/_Editable',\n\t\t'Views/_Shiftable',\n\t\t'Views/_Trashable'\n\t], function(\n\t\tLessonListView,\n\t\tEditable,\n\t\tShiftable,\n\t\tTrashable\n\t) {\n\n\treturn Backbone.View.extend( _.defaults( {\n\n\t\t/**\n\t\t * Get default attributes for the html wrapper element\n\t\t * @return obj\n\t\t * @since 3.13.0\n\t\t * @version 3.13.0\n\t\t */\n\t\tattributes: function() {\n\t\t\treturn {\n\t\t\t\t'data-id': this.model.id,\n\t\t\t};\n\t\t},\n\n\t\t/**\n\t\t * Element classnames\n\t\t * @type {String}\n\t\t */\n\t\tclassName: 'llms-builder-item llms-section',\n\n\t\t/**\n\t\t * Events\n\t\t * @type {Object}\n\t\t * @since 3.16.0\n\t\t * @version 3.16.12\n\t\t */\n\t\tevents: _.defaults( {\n\n\t\t\t'click': 'select',\n\t\t\t'click .expand': 'expand',\n\t\t\t'click .collapse': 'collapse',\n\t\t\t'click .shift-up--section': 'shift_up',\n\t\t\t'click .shift-down--section': 'shift_down',\n\n\t\t\t'mouseenter .llms-lessons': 'on_mouseenter',\n\n\t\t}, Editable.events, Trashable.events ),\n\n\t\t/**\n\t\t * HTML element wrapper ID attribute\n\t\t * @return string\n\t\t * @since 3.13.0\n\t\t * @version 3.13.0\n\t\t */\n\t\tid: function() {\n\t\t\treturn 'llms-section-' + this.model.id;\n\t\t},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'li',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-section-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.13.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\tthis.render();\n\t\t\tthis.listenTo( this.model, 'change', this.render );\n\t\t\tthis.listenTo( this.model, 'change:_expanded', this.toggle_expanded );\n\t\t\tthis.lessonListView.collection.on( 'add', this.on_lesson_add, this );\n\n\t\t\tthis.dragTimeout = null;\n\n\t\t\tBackbone.pubSub.on( 'expand-all', this.expand, this );\n\t\t\tBackbone.pubSub.on( 'collapse-all', this.collapse, this );\n\n\t\t},\n\n\t\t/**\n\t\t * Render the section\n\t\t * Initalizes a new collection and views for all lessons in the section\n\t\t * @return void\n\t\t * @since 3.13.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender: function() {\n\n\t\t\tthis.$el.html( this.template( this.model.toJSON() ) );\n\n\t\t\tthis.maybe_hide_shiftable_buttons();\n\n\t\t\tthis.lessonListView = new LessonListView( {\n\t\t\t\tel: this.$el.find( '.llms-lessons' ),\n\t\t\t\tcollection: this.model.get( 'lessons' ),\n\t\t\t} );\n\t\t\tthis.lessonListView.render();\n\t\t\tthis.lessonListView.on( 'sortStart', this.lessonListView.sortable_start );\n\t\t\tthis.lessonListView.on( 'sortStop', this.lessonListView.sortable_stop );\n\n\t\t\t// selection changes\n\t\t\tthis.lessonListView.on( 'selectionChanged', this.active_lesson_change, this );\n\n\t\t\tthis.maybe_hide_trash_button();\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\tactive_lesson_change: function( current, previous ) {\n\n\t\t\tBackbone.pubSub.trigger( 'active-lesson-change', {\n\t\t\t\tcurrent: current,\n\t\t\t\tprevious: previous,\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * Collapse lessons within the section\n\t\t * @param obj event js event object\n\t\t * @param bool update if true, updates the model to reflect the new state\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tcollapse: function( event, update ) {\n\n\t\t\tif ( 'undefined' === typeof update ) {\n\t\t\t\tupdate = true;\n\t\t\t}\n\n\t\t\tif ( event ) {\n\t\t\t\tevent.stopPropagation();\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\n\t\t\tthis.$el.removeClass( 'expanded' ).find( '.drag-expanded' ).removeClass( 'drag-expanded' );\n\t\t\tif ( update ) {\n\t\t\t\tthis.model.set( '_expanded', false );\n\t\t\t}\n\t\t\tBackbone.pubSub.trigger( 'section-toggle', this.model );\n\n\t\t},\n\n\t\t/**\n\t\t * Expand lessons within the section\n\t\t * @param obj event js event object\n\t\t * @param bool update if true, updates the model to reflect the new state\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\texpand: function( event, update ) {\n\n\t\t\tif ( 'undefined' === typeof update ) {\n\t\t\t\tupdate = true;\n\t\t\t}\n\n\t\t\tif ( event ) {\n\t\t\t\tevent.stopPropagation();\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\n\t\t\tthis.$el.addClass( 'expanded' );\n\t\t\tif ( update ) {\n\t\t\t\tthis.model.set( '_expanded', true );\n\t\t\t}\n\t\t\tBackbone.pubSub.trigger( 'section-toggle', this.model );\n\n\t\t},\n\n\t\tmaybe_hide_trash_button: function() {\n\n\t\t\tvar $btn = this.$el.find( '.trash--section' );\n\n\t\t\tif ( this.model.get( 'lessons' ).isEmpty() ) {\n\n\t\t\t\t$btn.show();\n\n\t\t\t} else {\n\n\t\t\t\t$btn.hide()\n\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * When a lesson is added to the section trigger a collection reorder & update the lesson's id\n\t\t * @param obj model Lesson model\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\ton_lesson_add: function( model ) {\n\n\t\t\tthis.lessonListView.collection.trigger( 'reorder' );\n\t\t\tmodel.set( 'parent_section', this.model.get( 'id' ) );\n\t\t\tthis.expand();\n\n\t\t},\n\n\t\ton_mouseenter: function( event ) {\n\n\n\t\t\tif ( $( event.target ).hasClass( 'dragging' ) ) {\n\n\t\t\t\t$( '.drag-expanded' ).removeClass( 'drag-expanded' );\n\t\t\t\t$( event.target ).addClass( 'drag-expanded' );\n\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Expand\n\t\t * @param {[type]} model [description]\n\t\t * @param {[type]} value [description]\n\t\t * @return {[type]}\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\ttoggle_expanded: function( model, value ) {\n\n\t\t\tif ( value ) {\n\t\t\t\tthis.expand( null, false );\n\t\t\t} else {\n\t\t\t\tthis.collapse( null, false );\n\t\t\t}\n\n\t\t},\n\n\t}, Editable, Shiftable, Trashable ) );\n\n} );\n\n","/**\n * Single Section View\n * @since 3.13.0\n * @version 3.16.0\n */\ndefine( 'Views/SectionList',[ 'Views/Section', 'Views/_Receivable' ], function( SectionView, Receivable ) {\n\n\treturn Backbone.CollectionView.extend( _.defaults( {\n\n\t\t/**\n\t\t * Parent element\n\t\t * @type {String}\n\t\t */\n\t\tel: '#llms-sections',\n\n\t\tevents : {\n\t\t\t'mousedown > li.llms-section > .llms-builder-header .llms-headline' : '_listItem_onMousedown',\n\t\t\t// 'dblclick > li, tbody > tr > td' : '_listItem_onDoubleClick',\n\t\t\t'click' : '_listBackground_onClick',\n\t\t\t'click ul.collection-view' : '_listBackground_onClick',\n\t\t\t'keydown' : '_onKeydown'\n\t\t},\n\n\t\t/**\n\t\t * Section model\n\t\t * @type {[type]}\n\t\t */\n\t\tmodelView: SectionView,\n\n\t\t/**\n\t\t * Enable keyboard events\n\t\t * @type {Bool}\n\t\t */\n\t\tprocessKeyEvents: false,\n\n\t\t/**\n\t\t * Are sections selectable?\n\t\t * @type {Bool}\n\t\t */\n\t\tselectable: true,\n\n\t\t/**\n\t\t * Are sections sortable?\n\t\t * @type {Bool}\n\t\t */\n\t\tsortable: true,\n\n\t\tsortableOptions: {\n\t\t\taxis: false,\n\t\t\tcursor: 'move',\n\t\t\thandle: '.drag-section',\n\t\t\titems: '.llms-section',\n\t\t\tplaceholder: 'llms-section llms-sortable-placeholder',\n\t\t},\n\n\t\tsortable_start: function( collection ) {\n\t\t\tthis.$el.addClass( 'dragging' );\n\t\t},\n\n\t\tsortable_stop: function( collection ) {\n\t\t\tthis.$el.removeClass( 'dragging' );\n\t\t},\n\n\t}, Receivable ) );\n\n} );\n\n","/**\n * Single Course View\n * @since 3.13.0\n * @version 3.16.0\n */\ndefine( 'Views/Course',[ 'Views/SectionList', 'Views/_Editable' ], function( SectionListView, Editable ) {\n\n\treturn Backbone.View.extend( _.defaults( {\n\n\t\t/**\n\t\t * Get default attributes for the html wrapper element\n\t\t * @return obj\n\t\t * @since 3.13.0\n\t\t * @version 3.13.0\n\t\t */\n\t\tattributes: function() {\n\t\t\treturn {\n\t\t\t\t'data-id': this.model.id,\n\t\t\t};\n\t\t},\n\n\t\t/**\n\t\t * HTML element selector\n\t\t * @type {String}\n\t\t */\n\t\tel: '#llms-builder-main',\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'div',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-course-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.13.0\n\t\t * @version 3.13.0\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\tvar self = this;\n\n\t\t\t// this.listenTo( this.model, 'sync', this.render );\n\t\t\tthis.render();\n\n\t\t\tthis.sectionListView = new SectionListView( {\n\t\t\t\tcollection: this.model.get( 'sections' ),\n\t\t\t} );\n\t\t\tthis.sectionListView.render();\n\t\t\t// drag and drop start\n\t\t\tthis.sectionListView.on( 'sortStart', this.sectionListView.sortable_start );\n\t\t\t// drag and drop stop\n\t\t\tthis.sectionListView.on( 'sortStop', this.sectionListView.sortable_stop );\n\t\t\t// selection changes\n\t\t\tthis.sectionListView.on( 'selectionChanged', this.active_section_change );\n\t\t\t// \"select\" a section when it's added to the course\n\t\t\tthis.listenTo( this.model.get( 'sections'), 'add', this.on_section_add );\n\n\t\t\tBackbone.pubSub.on( 'section-toggle', this.on_section_toggle, this );\n\n\t\t\tBackbone.pubSub.on( 'expand-section', this.expand_section, this );\n\n\t\t\tBackbone.pubSub.on( 'lesson-selected', this.active_lesson_change, this );\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.13.0\n\t\t * @version 3.13.0\n\t\t */\n\t\trender: function() {\n\t\t\tthis.$el.html( this.template( this.model ) );\n\t\t\treturn this;\n\t\t},\n\n\t\tactive_lesson_change: function( model ) {\n\n\t\t\t// set parent section to be active\n\t\t\tvar section = this.model.get( 'sections' ).get( model.get( 'parent_section' ) );\n\t\t\tthis.sectionListView.setSelectedModel( section );\n\n\t\t},\n\n\t\t/**\n\t\t * When a section \"selection\" changes in the list\n\t\t * Update each section model so we can figure out which one is selected from other views\n\t\t * @param array current array of selected models\n\t\t * @param array previous array of previously selected models\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tactive_section_change: function( current, previous ) {\n\n\t\t\t_.each( current, function( model ) {\n\t\t\t\tmodel.set( '_selected', true );\n\t\t\t} );\n\n\t\t\t_.each( previous, function( model ) {\n\t\t\t\tmodel.set( '_selected', false );\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * \"Selects\" the new section when it's added to the course\n\t\t * @param obj model Section model that's just been added\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\ton_section_add: function( model ) {\n\n\t\t\tthis.sectionListView.setSelectedModel( model );\n\n\t\t},\n\n\t\t/**\n\t\t * When expanding/collapsing sections\n\t\t * if collapsing, unselect, if expanding, select\n\t\t * @param obj model toggled section\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\ton_section_toggle: function( model ) {\n\n\t\t\tvar selected = model.get( '_expanded' ) ? [ model ] : [];\n\t\t\tthis.sectionListView.setSelectedModels( selected );\n\n\t\t}\n\n\t}, Editable ) );\n\n} );\n\n","/**\n * Model settings fields view\n * @since 3.17.0\n * @version 3.17.7\n */\ndefine( 'Views/SettingsFields',[], function() {\n\n\treturn Backbone.View.extend( _.defaults( {\n\n\t\t/**\n\t\t * DOM events\n\t\t * @type {Object}\n\t\t */\n\t\tevents: {\n\t\t\t'click .llms-settings-group-toggle': 'toggle_group',\n\t\t},\n\n\t\t/**\n\t\t * Processed fields data\n\t\t * Allows access by ID without traversing the schema\n\t\t * @type {Object}\n\t\t */\n\t\tfields: {},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'div',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-settings-fields-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\t// initialize: function() {},\n\n\t\t/**\n\t\t * Retrieve an array of all editor fields in all groups\n\t\t * @return array\n\t\t * @since 3.17.1\n\t\t * @version 3.17.1\n\t\t */\n\t\tget_editor_fields: function() {\n\t\t\treturn _.filter( this.fields, function( field ) {\n\t\t\t\treturn this.is_editor_field( field.type );\n\t\t\t}, this );\n\t\t},\n\n\t\t/**\n\t\t * Get settings group data from a model\n\t\t * @return {[type]}\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tget_groups: function() {\n\n\t\t\treturn this.model.get_settings_fields();\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if a settings group is hidden in localStorage\n\t\t * @param string group_id id of the group\n\t\t * @return {Boolean}\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tis_group_hidden: function( group_id ) {\n\n\t\t\tvar id = 'llms-' + this.model.get( 'type' ) + '-settings-group--' + group_id;\n\n\t\t\tif ( 'undefined' !== window.localStorage ) {\n\t\t\t\treturn ( 'hidden' === window.localStorage.getItem( id ) );\n\t\t\t}\n\n\t\t\treturn false;\n\n\t\t},\n\n\t\t/**\n\t\t * Get the switch attribute for a field with switches\n\t\t * @param obj field field data obj\n\t\t * @return string\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tget_switch_attribute: function( field ) {\n\n\t\t\treturn field.switch_attribute ? field.switch_attribute : field.attribute;\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if a field has a switch\n\t\t * @param string type field type string\n\t\t * @return {Boolean}\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\thas_switch: function( type ) {\n\t\t\treturn ( -1 !== type.indexOf( 'switch' ) );\n\t\t},\n\n\t\t/**\n\t\t * Determine if a field is a default (text) field\n\t\t * @param string type field type string\n\t\t * @return {Boolean}\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tis_default_field: function( type ) {\n\n\t\t\tvar types = [ 'audio_embed', 'datepicker', 'number', 'text', 'video_embed' ];\n\t\t\treturn ( -1 !== types.indexOf( type.replace( 'switch-', '' ) ) );\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if a field is a WYSIWYG editor field\n\t\t * @param string type field type string\n\t\t * @return {Boolean}\n\t\t * @since 3.17.1\n\t\t * @version 3.17.1\n\t\t */\n\t\tis_editor_field: function( type ) {\n\n\t\t\tvar types = [ 'editor', 'switch-editor' ];\n\t\t\treturn ( -1 !== types.indexOf( type.replace( 'switch-', '' ) ) );\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if a switch is enabled for a field\n\t\t * @param obj field field data object\n\t\t * @return {Boolean}\n\t\t * @since 3.17.0\n\t\t * @version 3.17.6\n\t\t */\n\t\tis_switch_condition_met: function( field ) {\n\n\t\t\treturn ( field.switch_on === this.model.get( field.switch_attribute ) );\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.17.0\n\t\t * @version 3.17.1\n\t\t */\n\t\trender: function() {\n\n\t\t\tthis.$el.html( this.template( this ) );\n\n\t\t\t// if editors exist, render them\n\t\t\t_.each( this.get_editor_fields(), function( field ) {\n\t\t\t\tthis.render_editor( field );\n\t\t\t}, this );\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\t/**\n\t\t * Renders an editor field\n\t\t * @param obj field field data object\n\t\t * @return void\n\t\t * @since 3.17.1\n\t\t * @version 3.17.1\n\t\t */\n\t\trender_editor: function( field ) {\n\n\t\t\tvar self = this;\n\n\t\t\twp.editor.remove( field.id );\n\t\t\tfield.settings.tinymce.setup = function( editor ) {\n\n\t\t\t\tvar $ed = $( '#' + editor.id ),\n\t\t\t\t\t$parent = $ed.closest( '.llms-editable-editor' ),\n\t\t\t\t\t$label = $parent.find( '.llms-label' ),\n\t\t\t\t\tprop = $ed.attr( 'data-attribute' )\n\n\t\t\t\tif ( $label.length ) {\n\t\t\t\t\t$label.prependTo( $parent.find( '.wp-editor-tools' ) );\n\t\t\t\t}\n\n\t\t\t\t// save changes to the model via Visual ed\n\t\t\t\teditor.on( 'change', function( event ) {\n\t\t\t\t\tself.model.set( prop, wp.editor.getContent( editor.id ) );\n\t\t\t\t} );\n\n\t\t\t\t// save changes via Text ed\n\t\t\t\t$ed.on( 'input', function( event ) {\n\t\t\t\t\tself.model.set( prop, $ed.val() );\n\t\t\t\t} );\n\n\t\t\t\t// trigger an input on the Text ed when quicktags buttons are clicked\n\t\t\t\t$parent.on( 'click', '.quicktags-toolbar .ed_button', function() {\n\t\t\t\t\tsetTimeout( function() {\n\t\t\t\t\t\t$ed.trigger( 'input' );\n\t\t\t\t\t}, 10 );\n\t\t\t\t} );\n\t\t\t};\n\n\t\t\twp.editor.initialize( field.id, field.settings );\n\n\t\t},\n\n\t\t/**\n\t\t * Get the HTML for a select field\n\t\t * @param obj options flat or multi-dimensional options object\n\t\t * @param string attribute name of the select field's attribute\n\t\t * @return string\n\t\t * @since 3.17.0\n\t\t * @version 3.17.2\n\t\t */\n\t\trender_select_options: function( options, attribute ) {\n\n\t\t\tvar html = '',\n\t\t\t\tselected = this.model.get( attribute );\n\n\t\t\tfunction option_html( label, val ) {\n\n\t\t\t\treturn '' + label + ' ';\n\n\t\t\t}\n\n\t\t\t_.each( options, function( option, index ) {\n\n\t\t\t\t// this will be an key:val object\n\t\t\t\tif ( 'string' === typeof option ) {\n\t\t\t\t\thtml += option_html( option, index );\n\t\t\t\t// either option group or array of key,val objects\n\t\t\t\t} else if ( 'object' === typeof option ) {\n\t\t\t\t\t// option group\n\t\t\t\t\tif ( option.label && option.options ) {\n\t\t\t\t\t\thtml += '';\n\t\t\t\t\t\thtml += this.render_select_options( option.options, attribute );\n\t\t\t\t\t} else {\n\t\t\t\t\t\thtml += option_html( option.val, option.key );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t}, this );\n\n\t\t\treturn html;\n\n\t\t},\n\n\t\t/**\n\t\t * Setup and fill fields with default data based on field type\n\t\t * @param obj orig_field original field as defined in the settings\n\t\t * @param int field_index index of the field in the current row\n\t\t * @return obj\n\t\t * @since 3.17.0\n\t\t * @version 3.17.7\n\t\t */\n\t\tsetup_field: function( orig_field, field_index ) {\n\n\t\t\tvar defaults = {\n\t\t\t\tclasses: [],\n\t\t\t\tid: _.uniqueId( orig_field.attribute + '_' ),\n\t\t\t\tinput_type: 'text',\n\t\t\t\tlabel: '',\n\t\t\t\toptions: {},\n\t\t\t\tplaceholder: '',\n\t\t\t\ttip: '',\n\t\t\t\ttip_position: 'top-right',\n\t\t\t\tsettings: {},\n\t\t\t};\n\n\t\t\t// check the field condition if set\n\t\t\tif ( orig_field.condition && false === _.bind( orig_field.condition, this.model )() ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tswitch ( orig_field.type ) {\n\n\t\t\t\tcase 'audio_embed':\n\t\t\t\t\tdefaults.classes.push( 'llms-editable-audio' );\n\t\t\t\t\tdefaults.placeholder = 'https://';\n\t\t\t\t\tdefaults.tip = LLMS.l10n.translate( 'Use SoundCloud or Spotify audio URLS.' );\n\t\t\t\t\tdefaults.input_type = 'url';\n\t\t\t\tbreak;\n\n\t\t\t\tcase 'datepicker':\n\t\t\t\t\tdefaults.classes.push( 'llms-editable-date' );\n\t\t\t\tbreak;\n\n\t\t\t\tcase 'editor':\n\t\t\t\tcase 'switch-editor':\n\t\t\t\t\tvar orig_settings = orig_field.settings || {};\n\t\t\t\t\tdefaults.settings = $.extend( true, wp.editor.getDefaultSettings(), {\n\t\t\t\t\t\tmediaButtons: true,\n\t\t\t\t\t\ttinymce: {\n\t\t\t\t\t\t\ttoolbar1: 'bold,italic,strikethrough,bullist,numlist,blockquote,hr,alignleft,aligncenter,alignright,link,unlink,wp_adv',\n\t\t\t\t\t\t\ttoolbar2: 'formatselect,underline,alignjustify,forecolor,pastetext,removeformat,charmap,outdent,indent,undo,redo,wp_help',\n\t\t\t\t\t\t}\n\t\t\t\t\t}, orig_settings );\n\t\t\t\tbreak;\n\n\t\t\t\tcase 'number':\n\t\t\t\t\tdefaults.input_type = 'number';\n\t\t\t\tbreak;\n\n\t\t\t\tcase 'permalink':\n\t\t\t\t\tdefaults.label = LLMS.l10n.translate( 'Permalink' );\n\t\t\t\tbreak;\n\n\t\t\t\tcase 'video_embed':\n\t\t\t\t\tdefaults.classes.push( 'llms-editable-video' );\n\t\t\t\t\tdefaults.placeholder = 'https://';\n\t\t\t\t\tdefaults.tip = LLMS.l10n.translate( 'Use YouTube, Vimeo, or Wistia video URLS.' );\n\t\t\t\t\tdefaults.input_type = 'url';\n\t\t\t\tbreak;\n\n\t\t\t}\n\n\t\t\tif ( this.has_switch( orig_field.type ) ) {\n\t\t\t\tdefaults.switch_on = 'yes';\n\t\t\t\tdefaults.switch_off = 'no';\n\t\t\t}\n\n\t\t\tvar field = _.defaults( _.deepClone( orig_field ), defaults );\n\n\t\t\t// if options is a function run it\n\t\t\tif ( _.isFunction( field.options ) ) {\n\t\t\t\tfield.options = _.bind( field.options, this.model )();\n\t\t\t}\n\n\t\t\t// if it's a radio field options values can be submitted as images\n\t\t\t// this will transform those images into html\n\t\t\tif ( -1 !== [ 'radio', 'switch-radio' ].indexOf( orig_field.type ) ) {\n\n\t\t\t\tvar has_images = false;\n\t\t\t\t_.each( orig_field.options, function( val, key ) {\n\t\t\t\t\tif ( -1 !== val.indexOf( '.png' ) || -1 !== val.indexOf( '.jpg' ) ) {\n\t\t\t\t\t\tfield.options[key] = ' ';\n\t\t\t\t\t\thas_images = true;\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t\tif ( has_images ) {\n\t\t\t\t\tfield.classes.push( 'has-images' );\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t// add tooltip position classes\n\t\t\tif ( field.tip ) {\n\t\t\t\tfield.classes.push( 'tip--' + field.tip_position );\n\t\t\t}\n\n\t\t\t// transform classes array to a css class string\n\t\t\tif ( field.classes.length ) {\n\t\t\t\tfield.classes = ' ' + field.classes.join( ' ' );\n\t\t\t}\n\n\t\t\tthis.fields[ field.id ] = field;\n\n\t\t\treturn field;\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if toggling a switch select should rerender the view\n\t\t * @param string field_type field type string\n\t\t * @return boolean\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tshould_rerender_on_toggle: function( field_type ) {\n\n\t\t\treturn ( -1 !== field_type.indexOf( 'switch-' ) ) ? 'yes' : 'no';\n\n\t\t},\n\n\t\t/**\n\t\t * Click event for toggling visibility of settings groups\n\t\t * If localStorage is available, persist state\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\ttoggle_group: function( event ) {\n\n\t\t\tevent.preventDefault();\n\n\t\t\tvar $el = $( event.currentTarget ),\n\t\t\t\t$group = $el.closest( '.llms-model-settings' );\n\n\t\t\t$group.toggleClass( 'hidden' );\n\n\t\t\tif ( 'undefined' !== window.localStorage ) {\n\n\t\t\t\tvar id = $group.attr( 'id' );\n\t\t\t\tif ( $group.hasClass( 'hidden' ) ) {\n\t\t\t\t\twindow.localStorage.setItem( id, 'hidden' );\n\t\t\t\t} else {\n\t\t\t\t\twindow.localStorage.removeItem( id );\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t},\n\n\t} ) );\n\n} );\n\n","/**\n * Lesson Editor (Sidebar) View\n * @since 3.17.0\n * @version 3.17.0\n */\ndefine( 'Views/LessonEditor',[\n\t\t'Views/_Detachable',\n\t\t'Views/_Editable',\n\t\t'Views/_Trashable',\n\t\t'Views/_Subview',\n\t\t'Views/SettingsFields'\n\t], function(\n\t\tDetachable,\n\t\tEditable,\n\t\tTrashable,\n\t\tSubview,\n\t\tSettingsFields\n\t) {\n\n\treturn Backbone.View.extend( _.defaults( {\n\n\t\t/**\n\t\t * Current view state\n\t\t * @type {String}\n\t\t */\n\t\tstate: 'default',\n\n\t\t/**\n\t\t * Current Subviews\n\t\t * @type {Object}\n\t\t */\n\t\tviews: {\n\t\t\tsettings: {\n\t\t\t\tclass: SettingsFields,\n\t\t\t\tinstance: null,\n\t\t\t\tstate: 'default',\n\t\t\t},\n\t\t},\n\n\t\tel: '#llms-editor-lesson',\n\n\t\t/**\n\t\t * Events\n\t\t * @type {Object}\n\t\t */\n\t\tevents: _.defaults( {}, Detachable.events, Editable.events, Trashable.events ),\n\n\t\t/**\n\t\t * Template function\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-lesson-settings-template' ),\n\n\t\t/**\n\t\t * Init\n\t\t * @param obj data parent template data\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tinitialize: function( data ) {\n\n\t\t\tthis.model = data.lesson;\n\n\t\t\tvar change_events = [\n\t\t\t\t'change:date_available',\n\t\t\t\t'change:drip_method',\n\t\t\t\t'change:time_available',\n\t\t\t];\n\t\t\t_.each( change_events, function( event ) {\n\t\t\t\tthis.listenTo( this.model, event, this.render );\n\t\t\t}, this );\n\n\t\t\t// when the \"has_prerequisite\" attr is toggled ON\n\t\t\t// trigger the prereq select object to set the default (first available) prereq for the lesson\n\t\t\tthis.listenTo( this.model, 'change:has_prerequisite', function( lesson, val ) {\n\t\t\t\tif ( 'yes' === val ) {\n\t\t\t\t\tthis.$el.find( 'select[name=\"prerequisite\"]' ).trigger( 'change' );\n\t\t\t\t}\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * Render the view\n\t\t * @return obj\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\trender: function() {\n\n\t\t\tthis.$el.html( this.template( this.model ) );\n\n\t\t\tthis.remove_subview( 'settings' );\n\n\t\t\tthis.render_subview( 'settings', {\n\t\t\t\tel: '#llms-lesson-settings-fields',\n\t\t\t\tmodel: this.model,\n\t\t\t} );\n\n\t\t\tthis.init_datepickers();\n\t\t\tthis.init_selects();\n\n\t\t\treturn this;\n\n\t\t},\n\n\t}, Detachable, Editable, Trashable, Subview, SettingsFields ) );\n\n} );\n\n","/**\n * Single Quiz View\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Views/Popover',[], function() {\n\n\treturn Backbone.View.extend( {\n\n\t\tdefaults: {\n\t\t\tplacement: 'auto',\n\t\t\t// container: document.body,\n\t\t\twidth: 'auto',\n\t\t\ttrigger: 'manual',\n\t\t\tstyle: 'light',\n\t\t\tanimation: 'pop',\n\t\t\ttitle: '',\n\t\t\tcontent: '',\n\t\t\tcloseable: false,\n\t\t\tbackdrop: false,\n\t\t\tonShow: function( $el ) {},\n\t\t\tonHide: function( $el ) {},\n\t\t},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'div',\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.14.1\n\t\t * @version 3.14.1\n\t\t */\n\t\tinitialize: function( data ) {\n\n\t\t\tif ( this.$el.length ) {\n\t\t\t\tthis.defaults.container = this.$el.parent();\n\t\t\t}\n\n\t\t\tthis.args = _.defaults( data.args, this.defaults );\n\t\t\tthis.render();\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender: function() {\n\n\t\t\tthis.$el.webuiPopover( this.args );\n\t\t\treturn this;\n\n\t\t},\n\n\t\t/**\n\t\t * Hide the popover\n\t\t * @return self (for chaining)\n\t\t * @since 3.16.0\n\t\t * @version 3.16.12\n\t\t */\n\t\thide: function() {\n\n\t\t\tthis.$el.webuiPopover( 'hide' );\n\t\t\treturn this;\n\n\t\t},\n\n\t\t/**\n\t\t * Show the popover\n\t\t * @return self (for chaining)\n\t\t * @since 3.16.0\n\t\t * @version 3.16.12\n\t\t */\n\t\tshow: function() {\n\n\t\t\tthis.$el.webuiPopover( 'show' );\n\t\t\treturn this;\n\n\t\t},\n\n\t} );\n\n} );\n\n","/**\n * Post Popover Serach content View\n * @since 3.16.0\n * @version 3.17.0\n */\ndefine( 'Views/PostSearch',[], function() {\n\n\treturn Backbone.View.extend( {\n\n\t\t/**\n\t\t * DOM Events\n\t\t * @type obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tevents: {\n\t\t\t'select2:select': 'add_post',\n\t\t},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'select',\n\n\t\t/**\n\t\t * Initializer\n\t\t * @param obj data customize the search box with data\n\t\t * @return void\n\t\t * @since 3.16.12\n\t\t * @version 3.16.12\n\t\t */\n\t\tinitialize: function( data ) {\n\n\t\t\tthis.post_type = data.post_type;\n\t\t\tthis.searching_message = data.searching_message || LLMS.l10n.translate( 'Searching...' );\n\n\t\t},\n\n\t\t/**\n\t\t * Select event, adds the existing lesson to the course\n\t\t * @param obj event select2:select event object\n\t\t * @since 3.16.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tadd_post: function( event ) {\n\n\t\t\tvar type = this.$el.attr( 'data-post-type' );\n\n\t\t\tBackbone.pubSub.trigger( type.replace( 'llms_', '' ) + '-search-select', event.params.data, event );\n\t\t\tthis.$el.val( null ).trigger( 'change' );\n\n\t\t},\n\n\t\t/**\n\t\t * Render the section\n\t\t * Initalizes a new collection and views for all lessons in the section\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.12\n\t\t */\n\t\trender: function() {\n\t\t\tvar self = this;\n\t\t\tsetTimeout( function () {\n\t\t\t\tself.$el.llmsSelect2( {\n\t\t\t\t\tajax: {\n\t\t\t\t\t\tdataType: 'JSON',\n\t\t\t\t\t\tdelay: 250,\n\t\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\t\turl: window.ajaxurl,\n\t\t\t\t\t\tdata: function( params ) {\n\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\taction: 'llms_builder',\n\t\t\t\t\t\t\t\taction_type: 'search',\n\t\t\t\t\t\t\t\tcourse_id: window.llms_builder.course.id,\n\t\t\t\t\t\t\t\tpost_type: self.post_type,\n\t\t\t\t\t\t\t\tterm: params.term,\n\t\t\t\t\t\t\t\tpage: params.page,\n\t\t\t\t\t\t\t\t_ajax_nonce: wp_ajax_data.nonce,\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t},\n\t\t\t\t\t\t// error: function( xhr, status, error ) {\n\t\t\t\t\t\t// \tconsole.log( status, error );\n\t\t\t\t\t\t// },\n\t\t\t\t\t},\n\t\t\t\t\tdropdownParent: $( '.wrap.lifterlms.llms-builder' ),\n\t\t\t\t\t// don't escape html from render_result\n\t\t\t\t\tescapeMarkup: function( markup ) {\n\t\t\t\t\t\treturn markup;\n\t\t\t\t\t},\n\t\t\t\t\tplaceholder: self.searching_message,\n\t\t\t\t\ttemplateResult: self.render_result,\n\t\t\t\t\twidth: '100%',\n\t\t\t\t} );\n\t\t\t\tself.$el.attr( 'data-post-type', self.post_type );\n\t\t\t}, 0 );\n\t\t\treturn this;\n\n\t\t},\n\n\t\t/**\n\t\t * Render a nicer UI for each search result in the in the Select2 search results\n\t\t * @param object res result data\n\t\t * @return string\n\t\t * @since 3.16.0\n\t\t * @version 3.16.12\n\t\t */\n\t\trender_result: function( res ) {\n\n\t\t\tvar $html = $( '
' );\n\n\t\t\tif ( res.loading ) {\n\t\t\t\treturn $html.append( res.text );\n\t\t\t}\n\n\t\t\tvar $side = $( '' ),\n\t\t\t\t$main = $( '
' );\n\t\t\t\ticon = ( 'attach' === res.action ) ? 'paperclip' : 'clone',\n\t\t\t\ttext = ( 'attach' === res.action ) ? LLMS.l10n.translate( 'Attach' ) : LLMS.l10n.translate( 'Clone' );\n\n\t\t\t$side.append( '' + text + ' ' );\n\n\t\t\t$main.append( '' + res.data.title + ' ' );\n\t\t\t$main.append( '' + LLMS.l10n.translate( 'ID' ) + ': ' + res.data.id + ' ' );\n\n\t\t\t_.each( res.parents, function( parent ) {\n\t\t\t\t$main.append( '' + parent + ' ' );\n\t\t\t} );\n\n\t\t\treturn $html.append( $side ).append( $main );\n\n\t\t},\n\n\t} );\n\n} );\n\n","/**\n * Single Lesson View\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Views/QuestionType',[ ], function() {\n\n\treturn Backbone.View.extend( {\n\n\t\t/**\n\t\t * HTML class names\n\t\t * @type {String}\n\t\t */\n\t\tclassName: 'llms-question-type',\n\n\t\tevents: {\n\t\t\t'click .llms-add-question': 'add_question',\n\t\t},\n\n\t\t/**\n\t\t * HTML element wrapper ID attribute\n\t\t * @return string\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tid: function() {\n\t\t\treturn 'llms-question-type-' + this.model.id;\n\t\t},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'li',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-question-type-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\tthis.render();\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender: function() {\n\t\t\tthis.$el.html( this.template( this.model ) );\n\t\t\treturn this;\n\t\t},\n\n\t\t/**\n\t\t * Add a question of the selected type to the current quiz\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tadd_question: function() {\n\n\t\t\tthis.quiz.add_question( {\n\t\t\t\t_expanded: true,\n\t\t\t\tchoices: this.model.get( 'default_choices' ) ? this.model.get( 'default_choices' ) : null,\n\t\t\t\tquestion_type: this.model,\n\t\t\t} );\n\n\t\t\tthis.quiz.trigger( 'new-question-added' );\n\n\t\t},\n\n\t\t// filter: function( term ) {\n\n\t\t// \tvar words = this.model.get_keywords().map( function( word ) {\n\t\t// \t\treturn word.toLowerCase();\n\t\t// \t} );\n\n\t\t// \tterm = term.toLowerCase();\n\n\t\t// \tif ( -1 === words.indexOf( term ) ) {\n\t\t// \t\tthis.$el.addClass( 'filtered' );\n\t\t// \t} else {\n\t\t// \t\tthis.$el.removeClass( 'filtered' );\n\t\t// \t}\n\n\t\t// },\n\n\t\t// clear_filter: function() {\n\t\t// \tthis.$el.removeClass( 'filtered' );\n\t\t// }\n\n\t} );\n\n} );\n\n","/**\n * Quiz question bank view\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Views/QuestionBank',[ 'Views/QuestionType' ], function( QuestionView ) {\n\n\treturn Backbone.CollectionView.extend( {\n\n\t\tclassName: 'llms-question',\n\n\t\t/**\n\t\t * Parent element\n\t\t * @type {String}\n\t\t */\n\t\tel: '#llms-question-bank',\n\n\t\t/**\n\t\t * Section model\n\t\t * @type {[type]}\n\t\t */\n\t\tmodelView: QuestionView,\n\n\t\t/**\n\t\t * Are sections selectable?\n\t\t * @type {Bool}\n\t\t */\n\t\tselectable: false,\n\n\t\t/**\n\t\t * Are sections sortable?\n\t\t * @type {Bool}\n\t\t */\n\t\tsortable: false,\n\n\t} );\n\n} );\n\n","/**\n * Single Question Choice View\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Views/QuestionChoice',[ 'Views/_Editable', ], function( Editable ) {\n\n\treturn Backbone.View.extend( _.defaults( {\n\n\t\t/**\n\t\t * HTML class names\n\t\t * @type {String}\n\t\t */\n\t\tclassName: 'llms-question-choice',\n\n\t\tevents: _.defaults( {\n\t\t\t'change input[name=\"correct\"]': 'toggle_correct',\n\t\t\t'click .llms-action-icon[href=\"#llms-add-choice\"]': 'add_choice',\n\t\t\t'click .llms-action-icon[href=\"#llms-del-choice\"]': 'del_choice',\n\t\t}, Editable.events ),\n\n\t\t/**\n\t\t * HTML element wrapper ID attribute\n\t\t * @return string\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tid: function() {\n\t\t\treturn 'llms-question-choice-' + this.model.id;\n\t\t},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'li',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-question-choice-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.14.1\n\t\t * @version 3.14.1\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\tthis.render();\n\n\t\t\tthis.listenTo( this.model.collection, 'add', this.maybe_disable_buttons );\n\t\t\tthis.listenTo( this.model, 'change', this.render );\n\n\t\t\tif ( 'image' === this.model.get( 'choice_type' ) ) {\n\t\t\t\tthis.listenTo( this.model.get( 'choice' ), 'change', this.render );\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender: function() {\n\t\t\tthis.$el.html( this.template( this.model ) );\n\t\t\treturn this;\n\t\t},\n\n\t\t/**\n\t\t * Add a new choice to the current choice list\n\t\t * Adds *after* the clicked choice\n\t\t * @param obj event JS event object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tadd_choice: function( event ) {\n\n\t\t\tevent.stopPropagation();\n\t\t\tevent.preventDefault();\n\n\t\t\tvar index = this.model.collection.indexOf( this.model );\n\t\t\tthis.model.collection.parent.add_choice( {}, {\n\t\t\t\tat: index + 1,\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * Delete the choice from the choice list & ensure there's at least one correct choice\n\t\t * @param obj event js event obj\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tdel_choice: function( event ) {\n\n\t\t\tevent.preventDefault();\n\t\t\tBackbone.pubSub.trigger( 'model-trashed', this.model );\n\t\t\tthis.model.collection.remove( this.model );\n\n\t\t},\n\n\t\t/**\n\t\t * When the correct answer input changes sync status to model\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\ttoggle_correct: function() {\n\n\t\t\tvar correct = this.$el.find( 'input[name=\"correct\"]' ).is( ':checked' );\n\t\t\tthis.model.set( 'correct', correct );\n\t\t\tthis.model.collection.trigger( 'correct-update', this.model );\n\n\t\t},\n\n\t}, Editable ) );\n\n} );\n\n","/**\n * Quiz question bank view\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Views/QuestionChoiceList',[ 'Views/QuestionChoice' ], function( ChoiceView ) {\n\n\treturn Backbone.CollectionView.extend( {\n\n\t\tclassName: 'llms-quiz-questions',\n\n\t\t/**\n\t\t * Choice model view\n\t\t * @type {[type]}\n\t\t */\n\t\tmodelView: ChoiceView,\n\n\t\t/**\n\t\t * Enable keyboard events\n\t\t * @type {Bool}\n\t\t */\n\t\tprocessKeyEvents: false,\n\n\t\t/**\n\t\t * Are sections selectable?\n\t\t * @type {Bool}\n\t\t */\n\t\tselectable: false,\n\n\t\t/**\n\t\t * Are sections sortable?\n\t\t * @type {Bool}\n\t\t */\n\t\tsortable: true,\n\n\t\tsortableOptions: {\n\t\t\taxis: false,\n\t\t\t// connectWith: '.llms-lessons',\n\t\t\tcursor: 'move',\n\t\t\thandle: '.llms-choice-id',\n\t\t\titems: '.llms-question-choice',\n\t\t\tplaceholder: 'llms-question-choice llms-sortable-placeholder',\n\t\t},\n\n\t\tsortable_start: function( model ) {\n\t\t\tthis.$el.addClass( 'dragging' );\n\t\t},\n\n\t\tsortable_stop: function( model ) {\n\t\t\tthis.$el.removeClass( 'dragging' );\n\t\t},\n\n\t} );\n\n} );\n\n","/**\n * Single Question View\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Views/Question',[\n\t\t'Views/_Editable',\n\t\t'Views/QuestionChoiceList'\n\t], function(\n\t\tEditable,\n\t\tChoiceListView\n\t) {\n\n\treturn Backbone.View.extend( _.defaults( {\n\n\t\t/**\n\t\t * Generate CSS classes for the question\n\t\t * @return string\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tclassName: function() {\n\t\t\treturn 'llms-question qtype--' + this.model.get( 'question_type' ).get( 'id' );\n\t\t},\n\n\t\tevents: _.defaults( {\n\t\t\t'click .clone--question': 'clone',\n\t\t\t'click .delete--question': 'delete',\n\t\t\t'click .expand--question': 'expand',\n\t\t\t'click .collapse--question': 'collapse',\n\t\t\t'change input[name=\"question_points\"]': 'update_points',\n\t\t}, Editable.events ),\n\n\t\t/**\n\t\t * HTML element wrapper ID attribute\n\t\t * @return string\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tid: function() {\n\t\t\treturn 'llms-question-' + this.model.id;\n\t\t},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'li',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-question-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\tvar change_events = [\n\t\t\t\t'change:_expanded',\n\t\t\t\t'change:menu_order',\n\t\t\t];\n\t\t\t_.each( change_events, function( event ) {\n\t\t\t\tthis.listenTo( this.model, event, this.render );\n\t\t\t}, this );\n\n\t\t\tthis.listenTo( this.model.get( 'image' ), 'change', this.render );\n\n\t\t\tthis.listenTo( this.model.get_parent(), 'change:_points', this.render_points_percentage );\n\n\t\t\tthis.on( 'multi_choices_toggle', this.multi_choices_toggle, this );\n\n\t\t\tBackbone.pubSub.on( 'del-question-choice', this.del_choice, this );\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender: function() {\n\n\t\t\tthis.$el.html( this.template( this.model ) );\n\n\t\t\tif ( this.model.get( 'question_type').get( 'choices' ) ) {\n\n\t\t\t\tthis.choiceListView = new ChoiceListView( {\n\t\t\t\t\tel: this.$el.find( '.llms-question-choices' ),\n\t\t\t\t\tcollection: this.model.get( 'choices' ),\n\t\t\t\t} );\n\t\t\t\tthis.choiceListView.render();\n\t\t\t\tthis.choiceListView.on( 'sortStart', this.choiceListView.sortable_start );\n\t\t\t\tthis.choiceListView.on( 'sortStop', this.choiceListView.sortable_stop );\n\n\t\t\t}\n\n\t\t\tif ( 'group' === this.model.get( 'question_type' ).get( 'id' ) ) {\n\n\t\t\t\tvar self = this;\n\t\t\t\tsetTimeout( function() {\n\t\t\t\t\tself.questionListView = self.collectionListView.quiz.get_question_list( {\n\t\t\t\t\t\tel: self.$el.find( '.llms-quiz-questions' ),\n\t\t\t\t\t\tcollection: self.model.get( 'questions' ),\n\t\t\t\t\t} );\n\t\t\t\t\tself.questionListView.render();\n\t\t\t\t\tself.questionListView.on( 'sortStart', self.questionListView.sortable_start );\n\t\t\t\t\tself.questionListView.on( 'sortStop', self.questionListView.sortable_stop );\n\t\t\t\t}, 1 );\n\n\t\t\t}\n\n\t\t\tif ( this.model.get( 'description_enabled' ) ) {\n\t\t\t\tthis.init_editor( 'question-desc--' + this.model.get( 'id' ) );\n\t\t\t}\n\n\t\t\tif ( this.model.get( 'clarifications_enabled' ) ) {\n\t\t\t\tthis.init_editor( 'question-clarifications--' + this.model.get( 'id' ), {\n\t\t\t\t\tmediaButtons: false,\n\t\t\t\t\ttinymce: {\n\t\t\t\t\t\ttoolbar1: 'bold,italic,strikethrough,bullist,numlist,alignleft,aligncenter,alignright',\n\t\t\t\t\t\ttoolbar2: '',\n\t\t\t\t\t\tsetup: _.bind( this.on_editor_ready, this ),\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\tthis.init_formatting_els();\n\t\t\tthis.init_selects();\n\n\t\t\treturn this;\n\t\t},\n\n\t\t/**\n\t\t * rerender points percentage when question points are updated\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender_points_percentage: function() {\n\n\t\t\tthis.$el.find( '.llms-question-points' ).attr( 'data-tip', this.model.get_points_percentage() );\n\n\t\t},\n\n\t\t/**\n\t\t * Click event to duplicate a question within a quiz\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tclone: function( event ) {\n\n\t\t\tevent.stopPropagation();\n\t\t\tevent.preventDefault();\n\t\t\tthis.model.collection.add( this._get_question_clone( this.model ) );\n\n\t\t},\n\n\t\t/**\n\t\t * Recursive clone function which will correctly clone children of a question\n\t\t * @param obj question queston model\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\t_get_question_clone: function( question ) {\n\n\t\t\t// create a duplicate\n\t\t\tvar clone = _.clone( question.attributes );\n\n\t\t\t// remove id (we want the duplicate to have a temp id)\n\t\t\tdelete clone.id;\n\n\t\t\tclone.parent_id = question.get( 'id' );\n\n\t\t\t// set the question type ID\n\t\t\tclone.question_type = question.get( 'question_type' ).get( 'id' );\n\n\t\t\t// clone the image attributes seperately\n\t\t\tclone.image = _.clone( question.get( 'image' ).attributes );\n\n\t\t\t// if it has choices clone all the choices\n\t\t\tif ( question.get( 'choices' ) ) {\n\n\t\t\t\tclone.choices = [];\n\n\t\t\t\tquestion.get( 'choices' ).each( function ( choice ) {\n\n\t\t\t\t\tvar choice_clone = _.clone( choice.attributes );\n\t\t\t\t\tdelete choice_clone.id;\n\t\t\t\t\tdelete choice_clone.question_id;\n\n\t\t\t\t\tclone.choices.push( choice_clone );\n\n\t\t\t\t} );\n\n\t\t\t}\n\n\t\t\tif ( 'group' === question.get( 'question_type' ).get( 'id' ) ) {\n\n\t\t\t\tclone.questions = [];\n\t\t\t\tquestion.get( 'questions' ).each( function( child ) {\n\t\t\t\t\tclone.questions.push( this._get_question_clone( child ) );\n\t\t\t\t}, this );\n\n\t\t\t}\n\n\t\t\treturn clone;\n\n\t\t},\n\n\t\t/**\n\t\t * Collapse a question and hide it's settings\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tcollapse: function() {\n\n\t\t\tthis.model.set( '_expanded', false );\n\n\t\t},\n\n\t\t/**\n\t\t * Delete the question from a quiz / question group\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tdelete: function( event ) {\n\n\t\t\tevent.preventDefault();\n\n\t\t\tif ( window.confirm( LLMS.l10n.translate( 'Are you sure you want to delete this question?' ) ) ) {\n\n\t\t\t\tthis.model.collection.remove( this.model );\n\t\t\t\tBackbone.pubSub.trigger( 'model-trashed', this.model );\n\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Click event to reveal a question's settings & choices\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\texpand: function() {\n\n\t\t\tthis.model.set( '_expanded', true );\n\n\t\t},\n\n\t\t/**\n\t\t * When toggling multiple correct answers *off* remove all correct choices except the first correct choice in the list\n\t\t * @param string val value of the question's `multi_choice` attr [yes|no]\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tmulti_choices_toggle: function( val ) {\n\n\t\t\tif ( 'yes' === val ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis.model.get( 'choices' ).update_correct( _.first( this.model.get( 'choices' ).get_correct() ) );\n\n\t\t},\n\n\t\t/**\n\t\t * Update the model's points when the value of the points input is updated\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tupdate_points: function() {\n\n\t\t\tthis.model.set( 'points', this.$el.find( 'input[name=\"question_points\"]' ).val() * 1 );\n\n\t\t}\n\n\t}, Editable ) );\n\n} );\n\n","/**\n * Quiz question bank view\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Views/QuestionList',[ 'Views/Question' ], function( QuestionView ) {\n\n\treturn Backbone.CollectionView.extend( {\n\n\t\tclassName: 'llms-quiz-questions',\n\n\t\t/**\n\t\t * Parent element\n\t\t * @type {String}\n\t\t */\n\t\t// el: '#llms-quiz-questions',\n\n\t\t/**\n\t\t * Section model\n\t\t * @type {[type]}\n\t\t */\n\t\tmodelView: QuestionView,\n\n\t\t/**\n\t\t * Enable keyboard events\n\t\t * @type {Bool}\n\t\t */\n\t\tprocessKeyEvents: false,\n\n\t\t/**\n\t\t * Are sections selectable?\n\t\t * @type {Bool}\n\t\t */\n\t\tselectable: false,\n\n\t\t/**\n\t\t * Are sections sortable?\n\t\t * @type {Bool}\n\t\t */\n\t\tsortable: true,\n\n\t\tsortableOptions: {\n\t\t\taxis: false,\n\t\t\tconnectWith: '.llms-quiz-questions',\n\t\t\tcursor: 'move',\n\t\t\thandle: '.llms-data-stamp',\n\t\t\titems: '.llms-question',\n\t\t\tplaceholder: 'llms-question llms-sortable-placeholder',\n\t\t},\n\n\t\t/**\n\t\t * Highlight drop areas when dragging starts\n\t\t * @param obj model model being sorted\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tsortable_start: function( model ) {\n\t\t\tvar selector = 'group' === model.get( 'question_type' ).get( 'id' ) ? '.llms-editor-tab > .llms-quiz-questions' : '.llms-quiz-questions';\n\t\t\t$( selector ).addClass( 'dragging' );\n\t\t},\n\n\t\t/**\n\t\t * Remove highlights when dragging stops\n\t\t * @param obj model model being sorted\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tsortable_stop: function() {\n\t\t\t$( '.llms-quiz-questions' ).removeClass( 'dragging' );\n\t\t},\n\n\t\t/**\n\t\t * Overrides receive to ensure that question groups can't be moved into queston groups\n\t\t * @param obj event js event object\n\t\t * @param obj ui jQuery UI Sortable ui object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\t_receive : function( event, ui ) {\n\n\t\t\tevent.stopPropagation();\n\n\t\t\t// prevent moving a question group into a question group\n\t\t\tif ( ui.item.hasClass( 'qtype--group' ) && $( event.target ).closest( '.qtype--group' ).length ) {;\n\t\t\t\tui.sender.sortable( 'cancel' );\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar senderListEl = ui.sender;\n\t\t\tvar senderCollectionListView = senderListEl.data( \"view\" );\n\t\t\tif( ! senderCollectionListView || ! senderCollectionListView.collection ) return;\n\n\t\t\tvar newIndex = this._getContainerEl().children().index( ui.item );\n\t\t\tvar modelReceived = senderCollectionListView.collection.get( ui.item.attr( \"data-model-cid\" ) );\n\t\t\tsenderCollectionListView.collection.remove( modelReceived );\n\t\t\tthis.collection.add( modelReceived, { at : newIndex } );\n\t\t\tmodelReceived.collection = this.collection; // otherwise will not get properly set, since modelReceived.collection might already have a value.\n\t\t\tthis.setSelectedModel( modelReceived );\n\t\t},\n\n\t\t/**\n\t\t * Override to allow manipulatino of placeholder element\n\t\t * @param {[type]} event [description]\n\t\t * @param {[type]} ui [description]\n\t\t * @return {[type]}\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\t_sortStart : function( event, ui ) {\n\n\t\t\tvar modelBeingSorted = this.collection.get( ui.item.attr( \"data-model-cid\" ) );\n\n\t\t\tui.placeholder.addClass( 'qtype--' + modelBeingSorted.get( 'question_type' ).get( 'id' ) );\n\n\t\t\tif( this._isBackboneCourierAvailable() )\n\t\t\t\tthis.spawn( \"sortStart\", { modelBeingSorted : modelBeingSorted } );\n\t\t\telse this.trigger( \"sortStart\", modelBeingSorted );\n\t\t},\n\n\t\t/**\n\t\t * Overloads the function from Backbone.CollectionView core because it doesn't send stop events\n\t\t * if moving from one sortable to another... :-(\n\t\t * @param obj event js event object\n\t\t * @param obj ui jQuery UI object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\t_sortStop : function( event, ui ) {\n\n\t\t\tevent.stopPropagation();\n\n\t\t\tvar modelBeingSorted = this.collection.get( ui.item.attr( 'data-model-cid' ) ),\n\t\t\t\tmodelViewContainerEl = this._getContainerEl(),\n\t\t\t\tnewIndex = modelViewContainerEl.children().index( ui.item );\n\n\t\t\tif ( newIndex == -1 && modelBeingSorted ) {\n\t\t\t\tthis.collection.remove( modelBeingSorted );\n\t\t\t}\n\n\t\t\tthis._reorderCollectionBasedOnHTML();\n\t\t\tthis.updateDependentControls();\n\n\t\t\tif( this._isBackboneCourierAvailable() ) {\n\t\t\t\tthis.spawn( 'sortStop', { modelBeingSorted : modelBeingSorted, newIndex : newIndex } );\n\t\t\t} else {\n\t\t\t\tthis.trigger( 'sortStop', modelBeingSorted, newIndex );\n\t\t\t}\n\n\t\t},\n\n\t} );\n\n} );\n\n","/**\n * Single Quiz View\n * @since 3.16.0\n * @version 3.19.2\n */\ndefine( 'Views/Quiz',[\n\t\t'Models/Quiz',\n\t\t'Views/Popover',\n\t\t'Views/PostSearch',\n\t\t'Views/QuestionBank',\n\t\t'Views/QuestionList',\n\t\t'Views/SettingsFields',\n\t\t'Views/_Detachable',\n\t\t'Views/_Editable',\n\t\t'Views/_Subview',\n\t\t'Views/_Trashable'\n\t], function(\n\t\tQuizModel,\n\t\tPopover,\n\t\tPostSearch,\n\t\tQuestionBank,\n\t\tQuestionList,\n\t\tSettingsFields,\n\t\tDetachable,\n\t\tEditable,\n\t\tSubview,\n\t\tTrashable\n\t) {\n\n\treturn Backbone.View.extend( _.defaults( {\n\n\t\t/**\n\t\t * Current view state\n\t\t * @type {String}\n\t\t */\n\t\tstate: 'default',\n\n\t\t/**\n\t\t * Current Subviews\n\t\t * @type {Object}\n\t\t */\n\t\tviews: {\n\t\t\tsettings: {\n\t\t\t\tclass: SettingsFields,\n\t\t\t\tinstance: null,\n\t\t\t\tstate: 'default',\n\t\t\t},\n\t\t\tbank: {\n\t\t\t\tclass: QuestionBank,\n\t\t\t\tinstance: null,\n\t\t\t\tstate: 'default',\n\t\t\t},\n\t\t\tlist: {\n\t\t\t\tclass: QuestionList,\n\t\t\t\tinstance: null,\n\t\t\t\tstate: 'default',\n\t\t\t},\n\t\t},\n\n\t\tel: '#llms-editor-quiz',\n\n\t\t/**\n\t\t * Events\n\t\t * @type {Object}\n\t\t */\n\t\tevents: _.defaults( {\n\t\t\t'click #llms-existing-quiz': 'add_existing_quiz_click',\n\t\t\t'click #llms-new-quiz': 'add_new_quiz',\n\t\t\t'click #llms-show-question-bank': 'show_tools',\n\t\t\t'click .bulk-toggle': 'bulk_toggle',\n\t\t\t// 'keyup #llms-question-bank-filter': 'filter_question_types',\n\t\t\t// 'search #llms-question-bank-filter': 'filter_question_types',\n\t\t}, Detachable.events, Editable.events, Trashable.events ),\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'div',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-quiz-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.19.2\n\t\t */\n\t\tinitialize: function( data ) {\n\n\t\t\tthis.lesson = data.lesson;\n\n\t\t\t// initialize the model if the quiz is enabled or it's disabled but we still have data for a quiz\n\t\t\tif ( 'yes' === this.lesson.get( 'quiz_enabled' ) || ! _.isEmpty( this.lesson.get( 'quiz' ) ) ) {\n\n\t\t\t\tthis.model = this.lesson.get( 'quiz' );\n\n\t\t\t\t/**\n\t\t\t\t * @todo this is a terrilbe terrible patch\n\t\t\t\t * I've spent nearly 3 days trying to figure out how to not use this line of code\n\t\t\t\t * ISSUE REPRODUCTION:\n\t\t\t\t * Open course builder\n\t\t\t\t * Open a lesson (A) and add a quiz\n\t\t\t\t * Switch to a new lesson (B)\n\t\t\t\t * Add a new quiz\n\t\t\t\t * Return to lesson A and the quizzes parent will be set to LESSON B\n\t\t\t\t * This will happen for *every* quiz in the builder...\n\t\t\t\t * Adding this set_parent on init guarantees that the quizzes correct parent is set\n\t\t\t\t * after adding new quizzes to other lessons\n\t\t\t\t * it's awful and it's gross...\n\t\t\t\t * I'm confused and tired and going to miss release dates again because of it\n\t\t\t\t */\n\t\t\t\tthis.model.set_parent( this.lesson );\n\n\t\t\t\tthis.listenTo( this.model, 'change:_points', this.render_points );\n\n\t\t\t}\n\n\t\t\tthis.on( 'model-trashed', this.on_trashed );\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.16.0\n\t\t * @version 3.19.2\n\t\t */\n\t\trender: function() {\n\n\t\t\tthis.$el.html( this.template( this.model ) );\n\n\t\t\t// render the quiz builder\n\t\t\tif ( this.model ) {\n\n\t\t\t\t// don't allow interaction until questions are lazy loaded\n\t\t\t\tLLMS.Spinner.start( this.$el );\n\n\t\t\t\tthis.render_subview( 'settings', {\n\t\t\t\t\tel: '#llms-quiz-settings-fields',\n\t\t\t\t\tmodel: this.model,\n\t\t\t\t} );\n\n\t\t\t\tthis.init_datepickers();\n\t\t\t\tthis.init_selects();\n\n\t\t\t\tthis.render_subview( 'bank', {\n\t\t\t\t\tcollection: window.llms_builder.questions,\n\t\t\t\t} );\n\n\t\t\t\tvar last_group = null,\n\t\t\t\t\tgroup = null;\n\t\t\t\t// let all the question types reference the quiz for adding questions quickly\n\t\t\t\tthis.get_subview( 'bank' ).instance.viewManager.each( function( view ) {\n\n\t\t\t\t\tview.quiz = this.model;\n\n\t\t\t\t\tgroup = view.model.get( 'group' ).name;\n\n\t\t\t\t\tif ( last_group !== group ) {\n\t\t\t\t\t\tlast_group = group;\n\t\t\t\t\t\tview.$el.before( '' );\n\t\t\t\t\t}\n\n\t\t\t\t}, this );\n\n\t\t\t\tthis.model.load_questions( _.bind( function( err ) {\n\n\t\t\t\t\tif ( err ) {\n\t\t\t\t\t\talert( LLMS.l10n.translate( 'An error occurred while trying to load the questions. Please refresh the page and try again.' ) );\n\t\t\t\t\t\treturn this;\n\t\t\t\t\t}\n\n\t\t\t\t\tLLMS.Spinner.stop( this.$el );\n\t\t\t\t\tthis.render_subview( 'list', {\n\t\t\t\t\t\tel: '#llms-quiz-questions',\n\t\t\t\t\t\tcollection: this.model.get( 'questions' ),\n\t\t\t\t\t} );\n\t\t\t\t\tvar list = this.get_subview( 'list' ).instance;\n\t\t\t\t\tlist.quiz = this;\n\t\t\t\t\tlist.collection.on( 'add', function() {\n\t\t\t\t\t\tlist.collection.trigger( 'reorder' );\n\t\t\t\t\t}, this );\n\t\t\t\t\tlist.on( 'sortStart', list.sortable_start );\n\t\t\t\t\tlist.on( 'sortStop', list.sortable_stop );\n\n\t\t\t\t}, this ) );\n\n\t\t\t\tthis.model.on( 'new-question-added', function() {\n\t\t\t\t\tvar $questions = this.$el.find( '#llms-quiz-questions' );\n\t\t\t\t\t$questions.animate( { scrollTop: $questions.prop( 'scrollHeight' ) }, 200 );\n\t\t\t\t}, this );\n\n\t\t\t}\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\t/**\n\t\t * On quiz points update, update the value of the Total Points area in the header\n\t\t * @param obj quiz Instance of the quiz model\n\t\t * @param int points Updated number of points\n\t\t * @return void\n\t\t * @since 3.17.6\n\t\t * @version 3.17.6\n\t\t */\n\t\trender_points: function( quiz, points ) {\n\n\t\t\tthis.$el.find( '#llms-quiz-total-points' ).text( points );\n\n\t\t},\n\n\t\t/**\n\t\t * Bulk expand / collapse question buttons\n\t\t * @param obj event js event object\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tbulk_toggle: function( event ) {\n\n\t\t\tvar expanded = ( 'expand' === $( event.target ).attr( 'data-action' ) );\n\n\t\t\tthis.model.get( 'questions' ).each( function( question ) {\n\t\t\t\tquestion.set( '_expanded', expanded );\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * Adds a new quiz to a lesson which currently has no quiz associated wlith it\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tadd_new_quiz: function() {\n\n\t\t\tvar quiz = this.lesson.get( 'quiz' );\n\t\t\tif ( _.isEmpty( quiz ) ) {\n\t\t\t\tquiz = this.lesson.add_quiz();\n\t\t\t} else {\n\t\t\t\tthis.lesson.set( 'quiz_enabled', 'yes' );\n\t\t\t}\n\n\t\t\tthis.model = quiz;\n\t\t\tthis.render();\n\n\t\t},\n\n\t\t// come back to this and make sure cloning resets all the IDs\n\t\tadd_existing_quiz: function( event ) {\n\n\t\t\tthis.post_search_popover.hide();\n\n\t\t\tvar quiz = event.data;\n\n\t\t\tif ( 'clone' === event.action ) {\n\n\t\t\t\tdelete quiz.id;\n\n\t\t\t\t_.each( quiz.questions, function( question ) {\n\n\t\t\t\t\tdelete question.parent_id;\n\t\t\t\t\tdelete question.id;\n\n\t\t\t\t\tif ( question.choices ) {\n\n\t\t\t\t\t\t_.each( question.choices, function( choice ) {\n\n\t\t\t\t\t\t\tdelete choice.question_id;\n\t\t\t\t\t\t\tdelete choice.id;\n\n\t\t\t\t\t\t} );\n\n\t\t\t\t\t}\n\n\t\t\t\t} );\n\n\t\t\t} else {\n\n\t\t\t\tquiz._forceSync = true;\n\n\t\t\t}\n\n\t\t\tdelete quiz.lesson_id;\n\n\t\t\tthis.lesson.add_quiz( quiz );\n\t\t\tthis.model = this.lesson.get( 'quiz' );\n\t\t\tthis.render();\n\n\t\t},\n\n\t\t/**\n\t\t * Open add existing quiz popover\n\t\t * @param obj event JS event object\n\t\t * @return void\n\t\t * @since 3.16.12\n\t\t * @version 3.16.12\n\t\t */\n\t\tadd_existing_quiz_click: function( event ) {\n\n\t\t\tevent.preventDefault();\n\n\t\t\tthis.post_search_popover = new Popover( {\n\t\t\t\tel: '#llms-existing-quiz',\n\t\t\t\targs: {\n\t\t\t\t\tbackdrop: true,\n\t\t\t\t\tcloseable: true,\n\t\t\t\t\tcontainer: '.wrap.lifterlms.llms-builder',\n\t\t\t\t\tdismissible: true,\n\t\t\t\t\tplacement: 'left',\n\t\t\t\t\twidth: 480,\n\t\t\t\t\ttitle: LLMS.l10n.translate( 'Add Existing Quiz' ),\n\t\t\t\t\tcontent: new PostSearch( {\n\t\t\t\t\t\tpost_type: 'llms_quiz',\n\t\t\t\t\t\tsearching_message: LLMS.l10n.translate( 'Search for existing quizzes...' ),\n\t\t\t\t\t} ).render().$el,\n\t\t\t\t\tonHide: function() {\n\t\t\t\t\t\tBackbone.pubSub.off( 'quiz-search-select' );\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\tthis.post_search_popover.show();\n\t\t\tBackbone.pubSub.once( 'quiz-search-select', this.add_existing_quiz, this );\n\n\t\t},\n\n\t\t// filter_question_types: _.debounce( function( event ) {\n\n\t\t// \tvar term = $( event.target ).val();\n\n\t\t// \tthis.QuestionBankView.viewManager.each( function( view ) {\n\t\t// \t\tif ( ! term ) {\n\t\t// \t\t\tview.clear_filter();\n\t\t// \t\t} else {\n\t\t// \t\t\tview.filter( term );\n\t\t// \t\t}\n\t\t// \t} );\n\n\n\t\t// }, 300 ),\n\n\t\t/**\n\t\t * Callback function when the quiz has been deleted\n\t\t * @param object quiz Quiz Model\n\t\t * @return void\n\t\t * @since 3.16.6\n\t\t * @version 3.16.6\n\t\t */\n\t\ton_trashed: function( quiz ) {\n\n\t\t\tthis.lesson.set( 'quiz_enabled', 'no' );\n\t\t\tthis.lesson.set( 'quiz', '' );\n\n\t\t\tdelete this.model;\n\n\t\t\tthis.render();\n\n\t\t},\n\n\t\t/**\n\t\t * \"Add Question\" button click event\n\t\t * Creates a popover with question type list interface\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tshow_tools: function() {\n\n\t\t\t// create popover\n\t\t\tvar pop = new Popover( {\n\t\t\t\tel: '#llms-show-question-bank',\n\t\t\t\targs: {\n\t\t\t\t\tbackdrop: true,\n\t\t\t\t\tcloseable: true,\n\t\t\t\t\tcontainer: '#llms-builder-sidebar',\n\t\t\t\t\tdismissible: true,\n\t\t\t\t\tplacement: 'top-left',\n\t\t\t\t\twidth: 'calc( 100% - 40px )',\n\t\t\t\t\ttitle: LLMS.l10n.translate( 'Add a Question' ),\n\t\t\t\t\turl: '#llms-quiz-tools',\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\t// show it\n\t\t\tpop.show();\n\n\t\t\t// if a question is added, hide the popover\n\t\t\tthis.model.on( 'new-question-added', function() {\n\t\t\t\tpop.hide();\n\t\t\t} );\n\n\t\t},\n\n\t\tget_question_list: function( options ) {\n\t\t\treturn new QuestionList( options );\n\t\t}\n\n\t}, Detachable, Editable, Subview, Trashable, SettingsFields ) );\n\n} );\n\n","/**\n * Single Assignment View\n * @since 3.17.0\n * @version 3.17.7\n */\ndefine( 'Views/Assignment',[\n\t\t'Views/Popover',\n\t\t'Views/PostSearch',\n\t\t'Views/_Detachable',\n\t\t'Views/_Editable',\n\t\t'Views/_Trashable',\n\t\t'Views/_Subview',\n\t\t'Views/SettingsFields'\n\t], function(\n\t\tPopover,\n\t\tPostSearch,\n\t\tDetachable,\n\t\tEditable,\n\t\tTrashable,\n\t\tSubview,\n\t\tSettingsFields\n\t) {\n\n\treturn Backbone.View.extend( _.defaults( {\n\n\t\t/**\n\t\t * Current view state\n\t\t * @type {String}\n\t\t */\n\t\tstate: 'default',\n\n\t\t/**\n\t\t * Current Subviews\n\t\t * @type {Object}\n\t\t */\n\t\tviews: {\n\t\t\tsettings: {\n\t\t\t\tclass: SettingsFields,\n\t\t\t\tinstance: null,\n\t\t\t\tstate: 'default',\n\t\t\t},\n\t\t},\n\n\t\tel: '#llms-editor-assignment',\n\n\t\t/**\n\t\t * DOM Events\n\t\t * @return obj\n\t\t * @since 3.17.1\n\t\t * @version 3.17.1\n\t\t */\n\t\tevents: function() {\n\t\t\tvar addon_events = this.is_addon_available() ? window.llms_builder.assignments.get_view_events() : {};\n\t\t\treturn _.defaults( {\n\t\t\t\t'click #llms-existing-assignment': 'add_existing_assignment_click',\n\t\t\t\t'click #llms-new-assignment': 'add_new_assignment',\n\t\t\t}, Detachable.events, Editable.events, Trashable.events, addon_events );\n\t\t},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'div',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-assignment-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.2\n\t\t */\n\t\tinitialize: function( data ) {\n\n\t\t\tthis.lesson = data.lesson;\n\n\t\t\t// initialize the model if the assignment is enabled or it's disabled but we still have data for a assignment\n\t\t\tif ( 'yes' === this.lesson.get( 'assignment_enabled' ) || ! _.isEmpty( this.lesson.get( 'assignment' ) ) ) {\n\n\t\t\t\tthis.model = this.lesson.get( 'assignment' );\n\n\t\t\t\t/**\n\t\t\t\t * @todo this is a terrilbe terrible patch\n\t\t\t\t * I've spent nearly 3 days trying to figure out how to not use this line of code\n\t\t\t\t * ISSUE REPRODUCTION:\n\t\t\t\t * Open course builder\n\t\t\t\t * Open a lesson (A) and add a assignment\n\t\t\t\t * Switch to a new lesson (B)\n\t\t\t\t * Add a new assignment\n\t\t\t\t * Return to lesson A and the assignment's parent will be set to LESSON B\n\t\t\t\t * This will happen for *every* assignment in the builder...\n\t\t\t\t * Adding this set_parent on init guarantees that the assignment's correct parent is set\n\t\t\t\t * after adding new assignment's to other lessons\n\t\t\t\t * it's awful and it's gross...\n\t\t\t\t * I'm confused and tired and going to miss release dates again because of it\n\t\t\t\t */\n\t\t\t\tthis.model.set_parent( this.lesson );\n\n\t\t\t}\n\n\t\t\tthis.on( 'model-trashed', this.on_trashed );\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.17.0\n\t\t * @version 3.17.7\n\t\t */\n\t\trender: function() {\n\n\t\t\tthis.$el.html( this.template( this.model ) );\n\n\t\t\tif ( this.model && this.is_addon_available() ) {\n\n\t\t\t\tthis.stopListening( this.model, 'change:assignment_type', this.render );\n\n\t\t\t\tthis.render_subview( 'settings', {\n\t\t\t\t\tel: '#llms-assignment-settings-fields',\n\t\t\t\t\tmodel: this.model,\n\t\t\t\t} );\n\n\t\t\t\t// this.init_datepickers();\n\t\t\t\tthis.init_selects();\n\n\t\t\t\twindow.llms_builder.assignments.render_editor( this );\n\n\t\t\t\tthis.listenTo( this.model, 'change:assignment_type', this.render );\n\n\t\t\t}\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\t/**\n\t\t * Adds a new assignment to a lesson which currently has no assignment associated wlith it\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tadd_new_assignment: function() {\n\n\t\t\tif ( this.is_addon_available() ) {\n\n\t\t\t\tthis.model = window.llms_builder.assignments.get_assignment( {\n\t\t\t\t\t/* translators: %1$s = associated lesson title */\n\t\t\t\t\ttitle: LLMS.l10n.replace( '%1$s Assignment', {\n\t\t\t\t\t\t'%1$s': this.lesson.get( 'title' ),\n\t\t\t\t\t} ),\n\t\t\t\t\tlesson_id: this.lesson.get( 'id' ),\n\t\t\t\t} );\n\n\t\t\t\tthis.lesson.set( 'assignment_enabled', 'yes' );\n\t\t\t\tthis.lesson.set( 'assignment', this.model );\n\n\t\t\t\tthis.render();\n\n\t\t\t} else {\n\n\t\t\t\tthis.show_ad_popover( '#llms-new-assignment' );\n\n\t\t\t}\n\n\n\t\t},\n\n\t\t/**\n\t\t * When an assignment is selected from the post select popover\n\t\t * instantiate it and add it to the current lesson\n\t\t * @param object event data from the select2 select event\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tadd_existing_assignment: function( event ) {\n\n\t\t\tthis.post_search_popover.hide();\n\n\t\t\tvar assignment = event.data;\n\n\t\t\tif ( 'clone' === event.action ) {\n\n\t\t\t\tdelete assignment.id;\n\n\t\t\t} else {\n\n\t\t\t\tassignment._forceSync = true;\n\n\t\t\t}\n\n\t\t\tassignment.lesson_id = this.lesson.get( 'id' )\n\n\t\t\tassignment = window.llms_builder.construct.get_model( 'Assignment', assignment );\n\n\t\t\tthis.lesson.set( 'assignment_enabled', 'yes' );\n\t\t\tthis.lesson.set( 'assignment', assignment );\n\t\t\tthis.model = assignment;\n\n\t\t\tthis.render();\n\n\t\t},\n\n\t\t/**\n\t\t * Open add existing assignment popover\n\t\t * @param obj event JS event object\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tadd_existing_assignment_click: function( event ) {\n\n\t\t\tevent.preventDefault();\n\n\t\t\tif ( this.is_addon_available() ) {\n\n\t\t\t\tthis.post_search_popover = new Popover( {\n\t\t\t\t\tel: '#llms-existing-assignment',\n\t\t\t\t\targs: {\n\t\t\t\t\t\tbackdrop: true,\n\t\t\t\t\t\tcloseable: true,\n\t\t\t\t\t\tcontainer: '.wrap.lifterlms.llms-builder',\n\t\t\t\t\t\tdismissible: true,\n\t\t\t\t\t\tplacement: 'left',\n\t\t\t\t\t\twidth: 480,\n\t\t\t\t\t\ttitle: LLMS.l10n.translate( 'Add Existing Assignment' ),\n\t\t\t\t\t\tcontent: new PostSearch( {\n\t\t\t\t\t\t\tpost_type: 'llms_assignment',\n\t\t\t\t\t\t\tsearching_message: LLMS.l10n.translate( 'Search for existing assignments...' ),\n\t\t\t\t\t\t} ).render().$el,\n\t\t\t\t\t\tonHide: function() {\n\t\t\t\t\t\t\tBackbone.pubSub.off( 'assignment-search-select' );\n\t\t\t\t\t\t},\n\t\t\t\t\t}\n\t\t\t\t} );\n\n\t\t\t\tthis.post_search_popover.show();\n\t\t\t\tBackbone.pubSub.once( 'assignment-search-select', this.add_existing_assignment, this );\n\n\t\t\t} else {\n\n\t\t\t\tthis.show_ad_popover( '#llms-existing-assignment' );\n\n\t\t\t}\n\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if Assignments addon is available to use\n\t\t * @return {Boolean}\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tis_addon_available: function() {\n\n\t\t\treturn ( window.llms_builder.assignments );\n\n\t\t},\n\n\t\t/**\n\t\t * Called when assignment is trashed\n\t\t * @param obj assignment Assignment model\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\ton_trashed: function( assignment ) {\n\n\t\t\tthis.lesson.set( 'assignment_enabled', 'no' );\n\t\t\tthis.lesson.set( 'assignment', '' );\n\n\t\t\tdelete this.model;\n\n\t\t\tthis.render();\n\n\t\t},\n\n\t\t/**\n\t\t * Shows a dirty dirty ad popoever for advanced assignments\n\t\t * @param string el jQuery selector string\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tshow_ad_popover: function( el ) {\n\n\t\t\tvar h3 = LLMS.l10n.translate( 'Get Your Students Taking Action' ),\n\t\t\t\tp = 'Great learning content is only half of teaching online. When your learners fully engage, they will take your content and move into action. Remove barriers for your learners by telling them what to do to apply what they just learned. Create graded assignments or simply give them a checklist of action items to complete before moving on.',\n\t\t\t\tbtn = LLMS.l10n.translate( 'Get Assignments Now!' ),\n\t\t\t\turl = 'https://lifterlms.com/product/lifterlms-assignments?utm_source=LifterLMS%20Plugin&utm_medium=Assignment%20Builder%20Button&utm_campaign=Assignment%20Addon%20Upsell&utm_content=3.17.0';\n\n\t\t\tthis.ad_popover = new Popover( {\n\t\t\t\tel: el,\n\t\t\t\targs: {\n\t\t\t\t\tbackdrop: true,\n\t\t\t\t\tcloseable: true,\n\t\t\t\t\tcontainer: '.wrap.lifterlms.llms-builder',\n\t\t\t\t\tdismissible: true,\n\t\t\t\t\t// placement: 'left',\n\t\t\t\t\twidth: 380,\n\t\t\t\t\ttitle: LLMS.l10n.translate( 'Unlock LifterLMS Assignments' ),\n\t\t\t\t\tcontent: '' + h3 + ' ' + p + '
' + btn + '
'\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\tthis.ad_popover.show();\n\n\t\t},\n\n\t}, Detachable, Editable, Trashable, Subview, SettingsFields ) );\n\n} );\n\n","/**\n * Sidebar Editor View\n * @since 3.16.0\n * @version 3.17.0\n */\ndefine( 'Views/Editor',[\n\t\t'Views/LessonEditor',\n\t\t'Views/Quiz',\n\t\t'Views/Assignment',\n\t\t'Views/_Subview'\n\t], function(\n\t\tLessonEditor,\n\t\tQuiz,\n\t\tAssignment,\n\t\tSubview\n\t) {\n\n\treturn Backbone.View.extend( _.defaults( {\n\n\t\t/**\n\t\t * Current view state\n\t\t * @type {String}\n\t\t */\n\t\tstate: 'lesson', // [lesson|quiz]\n\n\t\t/**\n\t\t * Current Subviews\n\t\t * @type {Object}\n\t\t */\n\t\tviews: {\n\t\t\tlesson: {\n\t\t\t\tclass: LessonEditor,\n\t\t\t\tinstance: null,\n\t\t\t\tstate: 'lesson',\n\t\t\t},\n\t\t\tassignment: {\n\t\t\t\tclass: Assignment,\n\t\t\t\tinstance: null,\n\t\t\t\tstate: 'assignment',\n\t\t\t},\n\t\t\tquiz: {\n\t\t\t\tclass: Quiz,\n\t\t\t\tinstance: null,\n\t\t\t\tstate: 'quiz',\n\t\t\t},\n\t\t},\n\n\t\t/**\n\t\t * HTML element selector\n\t\t * @type {String}\n\t\t */\n\t\tel: '#llms-editor',\n\n\t\tevents: {\n\t\t\t'click .llms-editor-nav a[href=\"#llms-editor-close\"]': 'close_editor',\n\t\t\t'click .llms-editor-nav a:not([href=\"#llms-editor-close\"])': 'switch_tab',\n\t\t},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'div',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-editor-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function( data ) {\n\n\t\t\tthis.SidebarView = data.SidebarView;\n\t\t\tif ( data.tab ) {\n\t\t\t\tthis.state = data.tab;\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender: function( view_data ) {\n\n\t\t\tview_data = view_data || {};\n\n\t\t\tthis.$el.html( this.template( this ) );\n\n\t\t\tthis.render_subviews( _.extend( view_data, {\n\t\t\t\tlesson: this.model,\n\t\t\t} ) );\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\t/**\n\t\t * Click event for close sidebar editor button\n\t\t * Sends event to main SidebarView to trigger editor closing events\n\t\t * @param obj event js event obj\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tclose_editor: function( event ) {\n\n\t\t\tevent.preventDefault();\n\t\t\tBackbone.pubSub.trigger( 'sidebar-editor-close' );\n\n\t\t},\n\n\t\t/**\n\t\t * Click event for switching tabs in the editor navigation\n\t\t * @param object event js event object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tswitch_tab: function( event ) {\n\n\t\t\tevent.preventDefault();\n\n\t\t\tvar $btn = $( event.target ),\n\t\t\t\tview = $btn.attr( 'data-view' ),\n\t\t\t\t$tab = this.$el.find( $btn.attr( 'href' ) );\n\n\t\t\tthis.set_state( view ).render();\n\n\t\t\t// Backbone.pubSub.trigger( 'editor-tab-activated', $btn.attr( 'href' ).substring( 1 ) );\n\n\t\t},\n\n\t}, Subview ) );\n\n} );\n\n","/**\n * Sidebar Elements View\n * @since 3.16.0\n * @version 3.16.12\n */\ndefine( 'Views/Elements',[ 'Models/Section', 'Views/Section', 'Models/Lesson', 'Views/Lesson', 'Views/Popover', 'Views/PostSearch' ], function( Section, SectionView, Lesson, LessonView, Popover, LessonSearch ) {\n\n\treturn Backbone.View.extend( {\n\n\t\t/**\n\t\t * HTML element selector\n\t\t * @type {String}\n\t\t */\n\t\tel: '#llms-elements',\n\n\t\tevents: {\n\t\t\t'click #llms-new-section': 'add_new_section',\n\t\t\t'click #llms-new-lesson': 'add_new_lesson',\n\t\t\t'click #llms-existing-lesson': 'add_existing_lesson',\n\t\t},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'div',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-elements-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function( data ) {\n\n\t\t\t// save a reference to the main Course view\n\t\t\tthis.SidebarView = data.SidebarView;\n\n\t\t\t// watch course sections and enable/disable lesson buttons conditionally\n\t\t\tthis.listenTo( this.SidebarView.CourseView.model.get( 'sections' ), 'add', this.maybe_disable_buttons );\n\t\t\tthis.listenTo( this.SidebarView.CourseView.model.get( 'sections' ), 'remove', this.maybe_disable_buttons );\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender: function() {\n\n\t\t\tthis.$el.html( this.template() );\n\t\t\tthis.draggable();\n\t\t\tthis.maybe_disable_buttons();\n\n\t\t\treturn this;\n\t\t},\n\n\t\tdraggable: function() {\n\n\t\t\t$( '#llms-new-section' ).draggable( {\n\t\t\t\tappendTo: '#llms-sections',\n\t\t\t\tcancel: false,\n\t\t\t\tconnectToSortable: '.llms-sections',\n\t\t\t\thelper: function() {\n\t\t\t\t\treturn new SectionView( { model: new Section() } ).render().$el;\n\t\t\t\t},\n\t\t\t\tstart: function() {\n\t\t\t\t\t$( '.llms-sections' ).addClass( 'dragging' );\n\t\t\t\t},\n\t\t\t\tstop: function() {\n\t\t\t\t\t$( '.llms-sections' ).removeClass( 'dragging' );\n\t\t\t\t},\n\t\t\t} );\n\n\t\t\t$( '#llms-new-lesson' ).draggable( {\n\t\t\t\t// appendTo: '#llms-sections .llms-section:first-child .llms-lessons',\n\t\t\t\tappendTo: '#llms-sections',\n\t\t\t\tcancel: false,\n\t\t\t\tconnectToSortable: '.llms-lessons',\n\t\t\t\thelper: function() {\n\t\t\t\t\treturn new LessonView( { model: new Lesson() } ).render().$el;\n\t\t\t\t},\n\t\t\t\tstart: function() {\n\n\t\t\t\t\t$( '.llms-lessons' ).addClass( 'dragging' );\n\n\t\t\t\t},\n\t\t\t\tstop: function() {\n\t\t\t\t\t$( '.llms-lessons' ).removeClass( 'dragging' );\n\t\t\t\t\t$( '.drag-expanded' ).removeClass( '.drag-expanded' );\n\t\t\t\t},\n\t\t\t} );\n\n\t\t},\n\n\t\tadd_new_section: function( event ) {\n\n\t\t\tevent.preventDefault();\n\t\t\tBackbone.pubSub.trigger( 'add-new-section' );\n\t\t},\n\n\t\tadd_new_lesson: function( event ) {\n\t\t\tevent.preventDefault();\n\t\t\tBackbone.pubSub.trigger( 'add-new-lesson' );\n\t\t},\n\n\t\t/**\n\t\t * Show the popover to add an existing lessons\n\t\t * @param object event JS Event OBject\n\t\t * @return void\n\t\t * @since 3.16.12\n\t\t * @version 3.16.12\n\t\t */\n\t\tadd_existing_lesson: function( event ) {\n\n\t\t\tevent.preventDefault();\n\n\t\t\tvar pop = new Popover( {\n\t\t\t\tel: '#llms-existing-lesson',\n\t\t\t\targs: {\n\t\t\t\t\tbackdrop: true,\n\t\t\t\t\tcloseable: true,\n\t\t\t\t\tcontainer: '.wrap.lifterlms.llms-builder',\n\t\t\t\t\tdismissible: true,\n\t\t\t\t\tplacement: 'left',\n\t\t\t\t\twidth: 480,\n\t\t\t\t\ttitle: LLMS.l10n.translate( 'Add Existing Lesson' ),\n\t\t\t\t\tcontent: new LessonSearch( {\n\t\t\t\t\t\tpost_type: 'lesson',\n\t\t\t\t\t\tsearching_message: LLMS.l10n.translate( 'Search for existing lessons...' ),\n\t\t\t\t\t} ).render().$el,\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\tpop.show();\n\t\t\tBackbone.pubSub.on( 'lesson-search-select', function() {\n\t\t\t\tpop.hide()\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * Disables lesson add buttons if no sections are available to add a lesson to\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tmaybe_disable_buttons: function() {\n\n\t\t\tvar $els = $( '#llms-new-lesson, #llms-existing-lesson' );\n\n\t\t\tif ( ! this.SidebarView.CourseView.model.get( 'sections' ).length ) {\n\t\t\t\t$els.attr( 'disabled', 'disabled' );\n\t\t\t} else {\n\t\t\t\t$els.removeAttr( 'disabled' );\n\t\t\t}\n\n\t\t},\n\n\t} );\n\n} );\n\n","/**\n * Sidebar Utilities View\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Views/Utilities',[], function() {\n\n\treturn Backbone.View.extend( {\n\n\t\t/**\n\t\t * HTML element selector\n\t\t * @type {String}\n\t\t */\n\t\tel: '#llms-utilities',\n\n\t\tevents: {\n\t\t\t'click #llms-collapse-all': 'collapse_all',\n\t\t\t'click #llms-expand-all': 'expand_all'\n\t\t},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'div',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-utilities-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\t// this.render();\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender: function() {\n\t\t\tthis.$el.html( this.template() );\n\t\t\treturn this;\n\t\t},\n\n\t\t/**\n\t\t * Collapse all sections\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tcollapse_all: function( event ) {\n\t\t\tevent.preventDefault();\n\t\t\tBackbone.pubSub.trigger( 'collapse-all' );\n\t\t},\n\n\t\t/**\n\t\t * Expand all sections\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\texpand_all: function( event ) {\n\t\t\tevent.preventDefault();\n\t\t\tBackbone.pubSub.trigger( 'expand-all' );\n\t\t},\n\n\t} );\n\n} );\n\n","/**\n * Main sidebar view\n * @since 3.16.0\n * @version 3.16.7\n */\ndefine( 'Views/Sidebar',[\n\t\t'Views/Editor',\n\t\t'Views/Elements',\n\t\t'Views/Utilities',\n\t\t'Views/_Subview'\n\t], function(\n\t\tEditor,\n\t\tElements,\n\t\tUtilities,\n\t\tSubview\n\t) {\n\n\treturn Backbone.View.extend( _.defaults( {\n\n\t\t/**\n\t\t * Current builder state\n\t\t * @type {String}\n\t\t */\n\t\tstate: 'builder', // [builder|editor]\n\n\t\t/**\n\t\t * Current Subviews\n\t\t * @type {Object}\n\t\t */\n\t\tviews: {\n\t\t\telements: {\n\t\t\t\tclass: Elements,\n\t\t\t\tinstance: null,\n\t\t\t\tstate: 'builder',\n\t\t\t},\n\t\t\tutilities: {\n\t\t\t\tclass: Utilities,\n\t\t\t\tinstance: null,\n\t\t\t\tstate: 'builder',\n\t\t\t},\n\t\t\teditor: {\n\t\t\t\tclass: Editor,\n\t\t\t\tinstance: null,\n\t\t\t\tstate: 'editor',\n\t\t\t},\n\t\t},\n\n\t\t/**\n\t\t * HTML element selector\n\t\t * @type {String}\n\t\t */\n\t\tel: '#llms-builder-sidebar',\n\n\t\t/**\n\t\t * DOM events\n\t\t * @type {Object}\n\t\t */\n\t\tevents: {\n\t\t\t'click #llms-save-button': 'save_now',\n\t\t\t'click #llms-exit-button': 'exit_now',\n\t\t\t'click .llms-builder-error': 'clear_errors',\n\t\t},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'aside',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-sidebar-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function( data ) {\n\n\t\t\t// save a reference to the main Course view\n\t\t\tthis.CourseView = data.CourseView;\n\n\t\t\tthis.render();\n\n\t\t\tBackbone.pubSub.on( 'current-save-status', this.changes_made, this );\n\n\t\t\tBackbone.pubSub.on( 'heartbeat-send', this.heartbeat_send, this );\n\t\t\tBackbone.pubSub.on( 'heartbeat-tick', this.heartbeat_tick, this );\n\n\t\t\tBackbone.pubSub.on( 'lesson-selected', this.on_lesson_select, this );\n\t\t\tBackbone.pubSub.on( 'sidebar-editor-close', this.on_editor_close, this );\n\n\t\t\tthis.$saveButton = $( '#llms-save-button' );\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender: function( view_data ) {\n\n\t\t\tview_data = view_data || {};\n\n\t\t\tthis.$el.html( this.template() );\n\n\t\t\tthis.render_subviews( _.extend( view_data, {\n\t\t\t\tSidebarView: this,\n\t\t\t} ) );\n\n\t\t\tvar $el = $( '.wrap.lifterlms.llms-builder' );\n\t\t\tif ( 'builder' === this.state ) {\n\t\t\t\t$el.removeClass( 'editor-active' );\n\t\t\t} else {\n\t\t\t\t$el.addClass( 'editor-active' );\n\t\t\t}\n\n\t\t\tthis.$saveButton = this.$el.find( '#llms-save-button' );\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\t/**\n\t\t * Adds error message element\n\t\t * @param {[type]} $err [description]\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tadd_error: function( $err ) {\n\n\t\t\tthis.$el.find( '.llms-builder-save' ).prepend( $err );\n\n\t\t},\n\n\t\t/**\n\t\t * Clear any existing error message elements\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tclear_errors: function() {\n\n\t\t\tthis.$el.find( '.llms-builder-save .llms-builder-error' ).remove();\n\n\t\t},\n\n\t\t/**\n\t\t * Update save status button when changes are detected\n\t\t * runs on an interval to check status of course regularly for unsaved changes\n\t\t * @param obj sync instance of the sync controller\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tchanges_made: function( sync ) {\n\n\t\t\t// if a save is currently running, don't do anything\n\t\t\tif ( sync.saving ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( sync.has_unsaved_changes ) {\n\n\t\t\t\tthis.$saveButton.attr( 'data-status', 'unsaved' );\n\t\t\t\tthis.$saveButton.removeAttr( 'disabled' );\n\n\t\t\t} else {\n\n\t\t\t\tthis.$saveButton.attr( 'data-status', 'saved' );\n\t\t\t\tthis.$saveButton.attr( 'disabled', 'disabled' );\n\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Exit the builder and return to the WP Course Editor\n\t\t * @return void\n\t\t * @since 3.16.7\n\t\t * @version 3.16.7\n\t\t */\n\t\texit_now: function() {\n\n\t\t\twindow.location.href = window.llms_builder.CourseModel.get_edit_post_link();\n\n\t\t},\n\n\t\t/**\n\t\t * Triggered when a heartbeat send event starts containing builder information\n\t\t * @param obj sync instance of the sync controller\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\theartbeat_send: function( sync ) {\n\n\t\t\tif ( sync.saving ) {\n\t\t\t\tLLMS.Spinner.start( this.$saveButton.find( 'i' ), 'small' );\n\t\t\t\tthis.$saveButton.attr( {\n\t\t\t\t\t'data-status': 'saving',\n\t\t\t\t\tdisabled: 'disabled',\n\t\t\t\t} );\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Triggered when a heartbeat tick completes and updates save status or appends errors\n\t\t * @param obj sync instance of the sync controller\n\t\t * @param obj data updated data\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\theartbeat_tick: function( sync, data ) {\n\n\t\t\tif ( ! sync.saving ) {\n\n\t\t\t\tvar status = 'saved';\n\n\t\t\t\tthis.clear_errors();\n\n\t\t\t\tif ( 'error' === data.status ) {\n\n\t\t\t\t\tstatus = 'error';\n\n\t\t\t\t\tvar msg = data.message,\n\t\t\t\t\t\t$err = $( ' ' );\n\n\t\t\t\t\tif ( 'object' === typeof msg ) {\n\t\t\t\t\t\t_.each( msg, function( txt ) {\n\t\t\t\t\t\t\t$err.append( '' + txt + ' ' );\n\t\t\t\t\t\t} );\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$err = $err.append( '' + msg + ' ' );;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.add_error( $err );\n\n\t\t\t\t}\n\n\t\t\t\tthis.$saveButton.find( '.llms-spinning' ).remove();\n\t\t\t\tthis.$saveButton.attr( {\n\t\t\t\t\t'data-status': status,\n\t\t\t\t\tdisabled: 'disabled',\n\t\t\t\t} );\n\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if the editor is the currently active state\n\t\t * @return boolean\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tis_editor_active: function() {\n\n\t\t\treturn ( 'editor' === this.state );\n\n\t\t},\n\n\t\t/**\n\t\t * Triggered when the editor closes, updates state to be the course builder view\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\ton_editor_close: function() {\n\n\t\t\tthis.set_state( 'builder' ).render();\n\n\t\t},\n\n\t\t/**\n\t\t * When a lesson is selected, opens the sidebar to the editor view\n\t\t * @param obj lesson_model instance of the lesson model which was selected\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\ton_lesson_select: function( lesson_model, tab ) {\n\n\t\t\tif ( 'editor' !== this.state ) {\n\t\t\t\tthis.set_state( 'editor' );\n\t\t\t} else {\n\t\t\t\tthis.remove_subview( 'editor' );\n\t\t\t}\n\n\t\t\tthis.render( {\n\t\t\t\tmodel: lesson_model,\n\t\t\t\ttab: tab,\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * Save button click event\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tsave_now: function() {\n\n\t\t\twindow.llms_builder.sync.save_now();\n\n\t\t},\n\n\t}, Subview ) );\n\n} );\n\n","/**\n * LifterLMS JS Builder App Bootstrap\n * @since 3.16.0\n * @version 3.17.8\n */\nrequire( [\n\t'vendor/backbone.collectionView',\n\t'vendor/backbone.trackit',\n\t'Controllers/Construct',\n\t'Controllers/Debug',\n\t'Controllers/Schemas',\n\t'Controllers/Sync',\n\t'Models/loader',\n\t'Views/Course',\n\t'Views/Sidebar'\n], function(\n\tCV,\n\tTrackIt,\n\tConstruct,\n\tDebug,\n\tSchemas,\n\tSync,\n\tModels,\n\tCourseView,\n\tSidebarView\n) {\n\n\twindow.llms_builder.debug = new Debug( window.llms_builder.debug );\n\twindow.llms_builder.construct = new Construct();\n\twindow.llms_builder.schemas = new Schemas( window.llms_builder.schemas );\n\n\t/**\n\t * Compare values, used by _.checked & _.selected mixins\n\t * @param mixed expected expected value, probably a string (the value of a select option or checkbox element)\n\t * @param mixed actual actual value, probably a string (the return of model.get( 'something' ) )\n\t * \t\t\t\t but could be an array like a multiselect\n\t * @return boolean\n\t * @since 3.17.2\n\t * @version 3.17.2\n\t */\n\tfunction value_compare( expected, actual ) {\n\t\treturn ( ( _.isArray( actual ) && -1 !== actual.indexOf( expected ) ) || expected == actual );\n\t};\n\n\t/**\n\t * Underscores templating utilities\n\t * @since 3.17.0\n\t * @version 3.17.8\n\t */\n\t_.mixin( {\n\n\t\t/**\n\t\t * Determine if two values are equal and output checked attribute if they are\n\t\t * Useful for templating checkboxes & radio elements\n\t\t * Like WP Core PHP checked() but in JS\n\t\t * @param mixed expected expected element value\n\t\t * @param mixed actual actual element value\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.2\n\t\t */\n\t\tchecked: function( expected, actual ) {\n\t\t\tif ( value_compare( expected, actual ) ) {\n\t\t\t\treturn ' checked=\"checked\"';\n\t\t\t}\n\t\t\treturn '';\n\t\t},\n\n\t\t/**\n\t\t * Recursively clone an object via _.clone()\n\t\t * @param obj obj object to clone\n\t\t * @return obj\n\t\t * @since 3.17.7\n\t\t * @version 3.17.7\n\t\t */\n\t\tdeepClone: function( obj ) {\n\n\t\t\tvar clone = _.clone( obj );\n\n\t\t\t_.each( clone, function( val, key ) {\n\t\t\t\tif ( ! _.isFunction( val ) && _.isObject( val ) ) {\n\t\t\t\t\tclone[ key ] = _.deepClone( val );\n\t\t\t\t};\n\t\t\t} );\n\n\t\t\treturn clone;\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if two values are equal and output seleted attribute if they are\n\t\t * Useful for templating select elements\n\t\t * Like WP Core PHP selected() but in JS\n\t\t * @param mixed expected expected element value\n\t\t * @param mixed actual actual element value\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.2\n\t\t */\n\t\tselected: function( expected, actual ) {\n\t\t\tif ( value_compare( expected, actual ) ) {\n\t\t\t\treturn ' selected=\"selected\"';\n\t\t\t}\n\t\t\treturn '';\n\t\t},\n\n\t\t/**\n\t\t * Generic function for stripping HTML tags from a string\n\t\t * @param string content raw string\n\t\t * @param array allowed_tags array of allowed HTML tags\n\t\t * @return string\n\t\t * @since 3.17.8\n\t\t * @version 3.17.8\n\t\t */\n\t\tstripFormatting: function( content, allowed_tags ) {\n\n\t\t\tif ( ! allowed_tags ) {\n\t\t\t\tallowed_tags = [ 'b', 'i', 'u', 'strong', 'em' ];\n\t\t\t}\n\n\t\t\tvar $html = $( '' + content + '
' );\n\n\t\t\t$html.find( '*' ).not( allowed_tags.join( ',' ) ).each( function( ) {\n\n\t\t\t\t$( this ).replaceWith( this.innerHTML );\n\n\t\t\t} );\n\n\t\t\treturn $html.html();\n\n\t\t},\n\n\t} );\n\n\tBackbone.pubSub = _.extend( {}, Backbone.Events );\n\n\t$( document ).trigger( 'llms-builder-pre-init' );\n\n\twindow.llms_builder.questions = window.llms_builder.construct.get_collection( 'QuestionTypes', window.llms_builder.questions );\n\n\tvar CourseModel = window.llms_builder.construct.get_model( 'Course', window.llms_builder.course );\n\twindow.llms_builder.CourseModel = CourseModel;\n\n\twindow.llms_builder.sync = new Sync( CourseModel, window.llms_builder.sync );\n\n\tvar Course = new CourseView( {\n\t\tmodel: CourseModel,\n\t} );\n\n\tvar Sidebar = new SidebarView( {\n\t\tCourseView: Course\n\t} );\n\n\t$( document ).trigger( 'llms-builder-init', {\n\t\tcourse: Course,\n\t\tsidebar: Sidebar,\n\t} );\n\n} );\n\ndefine(\"main\", function(){});\n\n","}(jQuery));\n"]}
\ No newline at end of file
+{"version":3,"sources":["../../../config-wrap-start-default.js","vendor/almond.js","underscore.js","backbone.js","jquery.js","vendor/backbone.collectionView.js","vendor/backbone.trackit.js","Models/Image.js","Models/_Relationships.js","Models/QuestionChoice.js","Collections/QuestionChoices.js","Models/QuestionType.js","Models/Question.js","Collections/Questions.js","Models/_Utilities.js","Schemas/Quiz.js","Models/Quiz.js","Schemas/Lesson.js","Models/Lesson.js","Collections/Lessons.js","Collections/QuestionTypes.js","Models/Section.js","Collections/Sections.js","Collections/loader.js","Models/Abstract.js","Models/Course.js","Models/loader.js","Views/_Detachable.js","Views/_Editable.js","Views/_Receivable.js","Views/_Shiftable.js","Views/_Subview.js","Views/_Trashable.js","Views/_loader.js","Controllers/Construct.js","Controllers/Debug.js","Controllers/Schemas.js","Controllers/Sync.js","Views/Lesson.js","Views/LessonList.js","Views/Section.js","Views/SectionList.js","Views/Course.js","Views/SettingsFields.js","Views/LessonEditor.js","Views/Popover.js","Views/PostSearch.js","Views/QuestionType.js","Views/QuestionBank.js","Views/QuestionChoice.js","Views/QuestionChoiceList.js","Views/Question.js","Views/QuestionList.js","Views/Quiz.js","Views/Assignment.js","Views/Editor.js","Views/Elements.js","Views/Utilities.js","Views/Sidebar.js","main.js","../../../config-wrap-end-default.js"],"names":[],"mappings":"AAAA;AACA,ACDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACrbA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACVA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACVA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACVA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC72CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACvMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACvBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACxKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AClGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC9GA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACtJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC1WA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACtEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC3FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC9EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACtOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC5JA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC9QA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC3FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC7CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC1KA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACxDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC7BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACXA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACvKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC3CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC1DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC3nBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC9CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACjFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC5LA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC1DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AClCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACxIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AClFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACnDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC5tBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AClOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AChFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC/PA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACnEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACjJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AClaA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC/GA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC1FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACzIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACzGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACvCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC9HA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACxDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACxSA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC9JA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACxZA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC/TA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACjJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC3KA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACjFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AChUA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AClKA;AACA","file":"llms-builder.js","sourcesContent":["(function($){\n","/**\n * @license almond 0.3.3 Copyright jQuery Foundation and other contributors.\n * Released under MIT license, http://github.com/requirejs/almond/LICENSE\n */\n//Going sloppy to avoid 'use strict' string cost, but strict practices should\n//be followed.\n/*global setTimeout: false */\n\nvar requirejs, require, define;\n(function (undef) {\n\tvar main, req, makeMap, handlers,\n\t\tdefined = {},\n\t\twaiting = {},\n\t\tconfig = {},\n\t\tdefining = {},\n\t\thasOwn = Object.prototype.hasOwnProperty,\n\t\taps = [].slice,\n\t\tjsSuffixRegExp = /\\.js$/;\n\n\tfunction hasProp(obj, prop) {\n\t\treturn hasOwn.call(obj, prop);\n\t}\n\n\t/**\n\t * Given a relative module name, like ./something, normalize it to\n\t * a real name that can be mapped to a path.\n\t * @param {String} name the relative name\n\t * @param {String} baseName a real name that the name arg is relative\n\t * to.\n\t * @returns {String} normalized name\n\t */\n\tfunction normalize(name, baseName) {\n\t\tvar nameParts, nameSegment, mapValue, foundMap, lastIndex,\n\t\t\tfoundI, foundStarMap, starI, i, j, part, normalizedBaseParts,\n\t\t\tbaseParts = baseName && baseName.split(\"/\"),\n\t\t\tmap = config.map,\n\t\t\tstarMap = (map && map['*']) || {};\n\n\t\t//Adjust any relative paths.\n\t\tif (name) {\n\t\t\tname = name.split('/');\n\t\t\tlastIndex = name.length - 1;\n\n\t\t\t// If wanting node ID compatibility, strip .js from end\n\t\t\t// of IDs. Have to do this here, and not in nameToUrl\n\t\t\t// because node allows either .js or non .js to map\n\t\t\t// to same file.\n\t\t\tif (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) {\n\t\t\t\tname[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, '');\n\t\t\t}\n\n\t\t\t// Starts with a '.' so need the baseName\n\t\t\tif (name[0].charAt(0) === '.' && baseParts) {\n\t\t\t\t//Convert baseName to array, and lop off the last part,\n\t\t\t\t//so that . matches that 'directory' and not name of the baseName's\n\t\t\t\t//module. For instance, baseName of 'one/two/three', maps to\n\t\t\t\t//'one/two/three.js', but we want the directory, 'one/two' for\n\t\t\t\t//this normalization.\n\t\t\t\tnormalizedBaseParts = baseParts.slice(0, baseParts.length - 1);\n\t\t\t\tname = normalizedBaseParts.concat(name);\n\t\t\t}\n\n\t\t\t//start trimDots\n\t\t\tfor (i = 0; i < name.length; i++) {\n\t\t\t\tpart = name[i];\n\t\t\t\tif (part === '.') {\n\t\t\t\t\tname.splice(i, 1);\n\t\t\t\t\ti -= 1;\n\t\t\t\t} else if (part === '..') {\n\t\t\t\t\t// If at the start, or previous value is still ..,\n\t\t\t\t\t// keep them so that when converted to a path it may\n\t\t\t\t\t// still work when converted to a path, even though\n\t\t\t\t\t// as an ID it is less than ideal. In larger point\n\t\t\t\t\t// releases, may be better to just kick out an error.\n\t\t\t\t\tif (i === 0 || (i === 1 && name[2] === '..') || name[i - 1] === '..') {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t} else if (i > 0) {\n\t\t\t\t\t\tname.splice(i - 1, 2);\n\t\t\t\t\t\ti -= 2;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t//end trimDots\n\n\t\t\tname = name.join('/');\n\t\t}\n\n\t\t//Apply map config if available.\n\t\tif ((baseParts || starMap) && map) {\n\t\t\tnameParts = name.split('/');\n\n\t\t\tfor (i = nameParts.length; i > 0; i -= 1) {\n\t\t\t\tnameSegment = nameParts.slice(0, i).join(\"/\");\n\n\t\t\t\tif (baseParts) {\n\t\t\t\t\t//Find the longest baseName segment match in the config.\n\t\t\t\t\t//So, do joins on the biggest to smallest lengths of baseParts.\n\t\t\t\t\tfor (j = baseParts.length; j > 0; j -= 1) {\n\t\t\t\t\t\tmapValue = map[baseParts.slice(0, j).join('/')];\n\n\t\t\t\t\t\t//baseName segment has config, find if it has one for\n\t\t\t\t\t\t//this name.\n\t\t\t\t\t\tif (mapValue) {\n\t\t\t\t\t\t\tmapValue = mapValue[nameSegment];\n\t\t\t\t\t\t\tif (mapValue) {\n\t\t\t\t\t\t\t\t//Match, update name to the new value.\n\t\t\t\t\t\t\t\tfoundMap = mapValue;\n\t\t\t\t\t\t\t\tfoundI = i;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (foundMap) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t//Check for a star map match, but just hold on to it,\n\t\t\t\t//if there is a shorter segment match later in a matching\n\t\t\t\t//config, then favor over this star map.\n\t\t\t\tif (!foundStarMap && starMap && starMap[nameSegment]) {\n\t\t\t\t\tfoundStarMap = starMap[nameSegment];\n\t\t\t\t\tstarI = i;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!foundMap && foundStarMap) {\n\t\t\t\tfoundMap = foundStarMap;\n\t\t\t\tfoundI = starI;\n\t\t\t}\n\n\t\t\tif (foundMap) {\n\t\t\t\tnameParts.splice(0, foundI, foundMap);\n\t\t\t\tname = nameParts.join('/');\n\t\t\t}\n\t\t}\n\n\t\treturn name;\n\t}\n\n\tfunction makeRequire(relName, forceSync) {\n\t\treturn function () {\n\t\t\t//A version of a require function that passes a moduleName\n\t\t\t//value for items that may need to\n\t\t\t//look up paths relative to the moduleName\n\t\t\tvar args = aps.call(arguments, 0);\n\n\t\t\t//If first arg is not require('string'), and there is only\n\t\t\t//one arg, it is the array form without a callback. Insert\n\t\t\t//a null so that the following concat is correct.\n\t\t\tif (typeof args[0] !== 'string' && args.length === 1) {\n\t\t\t\targs.push(null);\n\t\t\t}\n\t\t\treturn req.apply(undef, args.concat([relName, forceSync]));\n\t\t};\n\t}\n\n\tfunction makeNormalize(relName) {\n\t\treturn function (name) {\n\t\t\treturn normalize(name, relName);\n\t\t};\n\t}\n\n\tfunction makeLoad(depName) {\n\t\treturn function (value) {\n\t\t\tdefined[depName] = value;\n\t\t};\n\t}\n\n\tfunction callDep(name) {\n\t\tif (hasProp(waiting, name)) {\n\t\t\tvar args = waiting[name];\n\t\t\tdelete waiting[name];\n\t\t\tdefining[name] = true;\n\t\t\tmain.apply(undef, args);\n\t\t}\n\n\t\tif (!hasProp(defined, name) && !hasProp(defining, name)) {\n\t\t\tthrow new Error('No ' + name);\n\t\t}\n\t\treturn defined[name];\n\t}\n\n\t//Turns a plugin!resource to [plugin, resource]\n\t//with the plugin being undefined if the name\n\t//did not have a plugin prefix.\n\tfunction splitPrefix(name) {\n\t\tvar prefix,\n\t\t\tindex = name ? name.indexOf('!') : -1;\n\t\tif (index > -1) {\n\t\t\tprefix = name.substring(0, index);\n\t\t\tname = name.substring(index + 1, name.length);\n\t\t}\n\t\treturn [prefix, name];\n\t}\n\n\t//Creates a parts array for a relName where first part is plugin ID,\n\t//second part is resource ID. Assumes relName has already been normalized.\n\tfunction makeRelParts(relName) {\n\t\treturn relName ? splitPrefix(relName) : [];\n\t}\n\n\t/**\n\t * Makes a name map, normalizing the name, and using a plugin\n\t * for normalization if necessary. Grabs a ref to plugin\n\t * too, as an optimization.\n\t */\n\tmakeMap = function (name, relParts) {\n\t\tvar plugin,\n\t\t\tparts = splitPrefix(name),\n\t\t\tprefix = parts[0],\n\t\t\trelResourceName = relParts[1];\n\n\t\tname = parts[1];\n\n\t\tif (prefix) {\n\t\t\tprefix = normalize(prefix, relResourceName);\n\t\t\tplugin = callDep(prefix);\n\t\t}\n\n\t\t//Normalize according\n\t\tif (prefix) {\n\t\t\tif (plugin && plugin.normalize) {\n\t\t\t\tname = plugin.normalize(name, makeNormalize(relResourceName));\n\t\t\t} else {\n\t\t\t\tname = normalize(name, relResourceName);\n\t\t\t}\n\t\t} else {\n\t\t\tname = normalize(name, relResourceName);\n\t\t\tparts = splitPrefix(name);\n\t\t\tprefix = parts[0];\n\t\t\tname = parts[1];\n\t\t\tif (prefix) {\n\t\t\t\tplugin = callDep(prefix);\n\t\t\t}\n\t\t}\n\n\t\t//Using ridiculous property names for space reasons\n\t\treturn {\n\t\t\tf: prefix ? prefix + '!' + name : name, //fullName\n\t\t\tn: name,\n\t\t\tpr: prefix,\n\t\t\tp: plugin\n\t\t};\n\t};\n\n\tfunction makeConfig(name) {\n\t\treturn function () {\n\t\t\treturn (config && config.config && config.config[name]) || {};\n\t\t};\n\t}\n\n\thandlers = {\n\t\trequire: function (name) {\n\t\t\treturn makeRequire(name);\n\t\t},\n\t\texports: function (name) {\n\t\t\tvar e = defined[name];\n\t\t\tif (typeof e !== 'undefined') {\n\t\t\t\treturn e;\n\t\t\t} else {\n\t\t\t\treturn (defined[name] = {});\n\t\t\t}\n\t\t},\n\t\tmodule: function (name) {\n\t\t\treturn {\n\t\t\t\tid: name,\n\t\t\t\turi: '',\n\t\t\t\texports: defined[name],\n\t\t\t\tconfig: makeConfig(name)\n\t\t\t};\n\t\t}\n\t};\n\n\tmain = function (name, deps, callback, relName) {\n\t\tvar cjsModule, depName, ret, map, i, relParts,\n\t\t\targs = [],\n\t\t\tcallbackType = typeof callback,\n\t\t\tusingExports;\n\n\t\t//Use name if no relName\n\t\trelName = relName || name;\n\t\trelParts = makeRelParts(relName);\n\n\t\t//Call the callback to define the module, if necessary.\n\t\tif (callbackType === 'undefined' || callbackType === 'function') {\n\t\t\t//Pull out the defined dependencies and pass the ordered\n\t\t\t//values to the callback.\n\t\t\t//Default to [require, exports, module] if no deps\n\t\t\tdeps = !deps.length && callback.length ? ['require', 'exports', 'module'] : deps;\n\t\t\tfor (i = 0; i < deps.length; i += 1) {\n\t\t\t\tmap = makeMap(deps[i], relParts);\n\t\t\t\tdepName = map.f;\n\n\t\t\t\t//Fast path CommonJS standard dependencies.\n\t\t\t\tif (depName === \"require\") {\n\t\t\t\t\targs[i] = handlers.require(name);\n\t\t\t\t} else if (depName === \"exports\") {\n\t\t\t\t\t//CommonJS module spec 1.1\n\t\t\t\t\targs[i] = handlers.exports(name);\n\t\t\t\t\tusingExports = true;\n\t\t\t\t} else if (depName === \"module\") {\n\t\t\t\t\t//CommonJS module spec 1.1\n\t\t\t\t\tcjsModule = args[i] = handlers.module(name);\n\t\t\t\t} else if (hasProp(defined, depName) ||\n\t\t\t\t\t\t hasProp(waiting, depName) ||\n\t\t\t\t\t\t hasProp(defining, depName)) {\n\t\t\t\t\targs[i] = callDep(depName);\n\t\t\t\t} else if (map.p) {\n\t\t\t\t\tmap.p.load(map.n, makeRequire(relName, true), makeLoad(depName), {});\n\t\t\t\t\targs[i] = defined[depName];\n\t\t\t\t} else {\n\t\t\t\t\tthrow new Error(name + ' missing ' + depName);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tret = callback ? callback.apply(defined[name], args) : undefined;\n\n\t\t\tif (name) {\n\t\t\t\t//If setting exports via \"module\" is in play,\n\t\t\t\t//favor that over return value and exports. After that,\n\t\t\t\t//favor a non-undefined return value over exports use.\n\t\t\t\tif (cjsModule && cjsModule.exports !== undef &&\n\t\t\t\t\t\tcjsModule.exports !== defined[name]) {\n\t\t\t\t\tdefined[name] = cjsModule.exports;\n\t\t\t\t} else if (ret !== undef || !usingExports) {\n\t\t\t\t\t//Use the return value from the function.\n\t\t\t\t\tdefined[name] = ret;\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (name) {\n\t\t\t//May just be an object definition for the module. Only\n\t\t\t//worry about defining if have a module name.\n\t\t\tdefined[name] = callback;\n\t\t}\n\t};\n\n\trequirejs = require = req = function (deps, callback, relName, forceSync, alt) {\n\t\tif (typeof deps === \"string\") {\n\t\t\tif (handlers[deps]) {\n\t\t\t\t//callback in this case is really relName\n\t\t\t\treturn handlers[deps](callback);\n\t\t\t}\n\t\t\t//Just return the module wanted. In this scenario, the\n\t\t\t//deps arg is the module name, and second arg (if passed)\n\t\t\t//is just the relName.\n\t\t\t//Normalize module name, if it contains . or ..\n\t\t\treturn callDep(makeMap(deps, makeRelParts(callback)).f);\n\t\t} else if (!deps.splice) {\n\t\t\t//deps is a config object, not an array.\n\t\t\tconfig = deps;\n\t\t\tif (config.deps) {\n\t\t\t\treq(config.deps, config.callback);\n\t\t\t}\n\t\t\tif (!callback) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (callback.splice) {\n\t\t\t\t//callback is an array, which means it is a dependency list.\n\t\t\t\t//Adjust args if there are dependencies\n\t\t\t\tdeps = callback;\n\t\t\t\tcallback = relName;\n\t\t\t\trelName = null;\n\t\t\t} else {\n\t\t\t\tdeps = undef;\n\t\t\t}\n\t\t}\n\n\t\t//Support require(['a'])\n\t\tcallback = callback || function () {};\n\n\t\t//If relName is a function, it is an errback handler,\n\t\t//so remove it.\n\t\tif (typeof relName === 'function') {\n\t\t\trelName = forceSync;\n\t\t\tforceSync = alt;\n\t\t}\n\n\t\t//Simulate async callback;\n\t\tif (forceSync) {\n\t\t\tmain(undef, deps, callback, relName);\n\t\t} else {\n\t\t\t//Using a non-zero value because of concern for what old browsers\n\t\t\t//do, and latest browsers \"upgrade\" to 4 if lower value is used:\n\t\t\t//http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#dom-windowtimers-settimeout:\n\t\t\t//If want a value immediately, use require('id') instead -- something\n\t\t\t//that works in almond on the global level, but not guaranteed and\n\t\t\t//unlikely to work in other AMD implementations.\n\t\t\tsetTimeout(function () {\n\t\t\t\tmain(undef, deps, callback, relName);\n\t\t\t}, 4);\n\t\t}\n\n\t\treturn req;\n\t};\n\n\t/**\n\t * Just drops the config on the floor, but returns req in case\n\t * the config return value is used.\n\t */\n\treq.config = function (cfg) {\n\t\treturn req(cfg);\n\t};\n\n\t/**\n\t * Expose module registry for debugging and tooling\n\t */\n\trequirejs._defined = defined;\n\n\tdefine = function (name, deps, callback) {\n\t\tif (typeof name !== 'string') {\n\t\t\tthrow new Error('See almond README: incorrect module build, no module name');\n\t\t}\n\n\t\t//This module may not have dependencies\n\t\tif (!deps.splice) {\n\t\t\t//deps is not an array, so probably means\n\t\t\t//an object literal or factory function for\n\t\t\t//the value. Adjust args.\n\t\t\tcallback = deps;\n\t\t\tdeps = [];\n\t\t}\n\n\t\tif (!hasProp(defined, name) && !hasProp(waiting, name)) {\n\t\t\twaiting[name] = [name, deps, callback];\n\t\t}\n\t};\n\n\tdefine.amd = {\n\t\tjQuery: true\n\t};\n}());\n\ndefine(\"vendor/almond\", function(){});\n\n","/**\n * Returns the WordPress-loaded version of Underscore for use with things that need it and use Require.\n * @return obj\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'underscore',[],function() {\n\treturn _;\n} );\n\n","/**\n * Returns the WordPress-loaded version of Backbone for use with things that need it and use Require.\n * @return obj\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'backbone',[],function() {\n\treturn Backbone;\n} );\n\n","/**\n * Returns the WordPress-loaded version of Underscore for use with things that need it and use Require.\n * @return obj\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'jquery',[],function() {\n\treturn jQuery;\n} );\n\n","/*!\n* Backbone.CollectionView, v1.3.4\n* Copyright (c)2013 Rotunda Software, LLC.\n* Distributed under MIT license\n* http://github.com/rotundasoftware/backbone-collection-view\n*/\n\n( function( root, factory ) {\n\t// UMD wrapper\n\tif ( typeof define === 'function' && define.amd ) {\n\t\t// AMD\n\t\tdefine( 'vendor/backbone.collectionView',[ 'underscore', 'backbone', 'jquery' ], factory );\n\t} else if ( typeof exports !== 'undefined' ) {\n\t\t// Node/CommonJS\n\t\tmodule.exports = factory( require('underscore' ), require( 'backbone' ), require( 'backbone' ).$ );\n\t} else {\n\t\t// Browser globals\n\t\tfactory( root._, root.Backbone, ( root.jQuery || root.Zepto || root.$ ) );\n\t}\n}( this, function( _, Backbone, $ ) {\n\tvar mDefaultModelViewConstructor = Backbone.View;\n\n\tvar kDefaultReferenceBy = \"model\";\n\n\tvar kOptionsRequiringRerendering = [ \"collection\", \"modelView\", \"modelViewOptions\", \"itemTemplate\", \"itemTemplateFunction\", \"detachedRendering\" ];\n\n\tvar kStylesForEmptyListCaption = {\n\t\t\"background\" : \"transparent\",\n\t\t\"border\" : \"none\",\n\t\t\"box-shadow\" : \"none\"\n\t};\n\n\tBackbone.CollectionView = Backbone.View.extend( {\n\n\t\ttagName : \"ul\",\n\n\t\tevents : {\n\t\t\t\"mousedown > li, tbody > tr > td\" : \"_listItem_onMousedown\",\n\t\t\t\"dblclick > li, tbody > tr > td\" : \"_listItem_onDoubleClick\",\n\t\t\t\"click\" : \"_listBackground_onClick\",\n\t\t\t\"click ul.collection-view, table.collection-view\" : \"_listBackground_onClick\",\n\t\t\t\"keydown\" : \"_onKeydown\"\n\t\t},\n\n\t\t// only used if Backbone.Courier is available\n\t\tspawnMessages : {\n\t\t\t\"focus\" : \"focus\"\n\t\t},\n\n\t\t//only used if Backbone.Courier is available\n\t\tpassMessages : { \"*\" : \".\" },\n\n\t\t// viewOption definitions with default values.\n\t\tinitializationOptions : [\n\t\t\t{ \"collection\" : null },\n\t\t\t{ \"modelView\" : null },\n\t\t\t{ \"modelViewOptions\" : {} },\n\t\t\t{ \"itemTemplate\" : null },\n\t\t\t{ \"itemTemplateFunction\" : null },\n\t\t\t{ \"selectable\" : true },\n\t\t\t{ \"clickToSelect\" : true },\n\t\t\t{ \"selectableModelsFilter\" : null },\n\t\t\t{ \"visibleModelsFilter\" : null },\n\t\t\t{ \"sortableModelsFilter\" : null },\n\t\t\t{ \"selectMultiple\" : false },\n\t\t\t{ \"clickToToggle\" : false },\n\t\t\t{ \"processKeyEvents\" : true },\n\t\t\t{ \"sortable\" : false },\n\t\t\t{ \"sortableOptions\" : null },\n\t\t\t{ \"reuseModelViews\" : true },\n\t\t\t{ \"detachedRendering\" : false },\n\t\t\t{ \"emptyListCaption\" : null }\n\t\t],\n\n\t\tinitialize : function( options ) {\n\t\t\tBackbone.ViewOptions.add( this, \"initializationOptions\" ); // setup the ViewOptions functionality.\n\t\t\tthis.setOptions( options ); // and make use of any provided options\n\n\t\t\tif( ! this.collection ) this.collection = new Backbone.Collection();\n\n\t\t\tthis._hasBeenRendered = false;\n\n\t\t\tif( this._isBackboneCourierAvailable() ) {\n\t\t\t\tBackbone.Courier.add( this );\n\t\t\t}\n\n\t\t\tthis.$el.data( \"view\", this ); // needed for connected sortable lists\n\t\t\tthis.$el.addClass( \"collection-view collection-list\" ); // collection-list is in there for legacy purposes\n\t\t\tif( this.selectable ) this.$el.addClass( \"selectable\" );\n\n\t\t\tif( this.selectable && this.processKeyEvents )\n\t\t\t\tthis.$el.attr( \"tabindex\", 0 ); // so we get keyboard events\n\n\t\t\tthis.selectedItems = [];\n\n\t\t\tthis._updateItemTemplate();\n\n\t\t\tif( this.collection )\n\t\t\t\tthis._registerCollectionEvents();\n\n\t\t\tthis.viewManager = new ChildViewContainer();\n\t\t},\n\n\t\t_onOptionsChanged : function( changedOptions, originalOptions ) {\n\t\t\tvar _this = this;\n\t\t\tvar rerender = false;\n\n\t\t\t_.each( _.keys( changedOptions ), function( changedOptionKey ) {\n\t\t\t\tvar newVal = changedOptions[ changedOptionKey ];\n\t\t\t\tvar oldVal = originalOptions[ changedOptionKey ];\n\t\t\t\tswitch( changedOptionKey ) {\n\t\t\t\t\tcase \"collection\" :\n\t\t\t\t\t\tif ( newVal !== oldVal ) {\n\t\t\t\t\t\t\t_this.stopListening( oldVal );\n\t\t\t\t\t\t\t_this._registerCollectionEvents();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"selectMultiple\" :\n\t\t\t\t\t\tif( ! newVal && _this.selectedItems.length > 1 )\n\t\t\t\t\t\t\t_this.setSelectedModel( _.first( _this.selectedItems ), { by : \"cid\" } );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"selectable\" :\n\t\t\t\t\t\tif( ! newVal && _this.selectedItems.length > 0 )\n\t\t\t\t\t\t\t_this.setSelectedModels( [] );\n\n\t\t\t\t\t\tif( newVal && this.processKeyEvents ) _this.$el.attr( \"tabindex\", 0 ); // so we get keyboard events\n\t\t\t\t\t\telse _this.$el.removeAttr( \"tabindex\", 0 );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"sortable\" :\n\t\t\t\t\t\tchangedOptions.sortable ? _this._setupSortable() : _this.$el.sortable( \"destroy\" );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"selectableModelsFilter\" :\n\t\t\t\t\t\t_this.reapplyFilter( 'selectableModels' );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"sortableOptions\" :\n\t\t\t\t\t\t_this.$el.sortable( \"destroy\" );\n\t\t\t\t\t\t_this._setupSortable();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"sortableModelsFilter\" :\n\t\t\t\t\t\t_this.reapplyFilter( 'sortableModels' );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"visibleModelsFilter\" :\n\t\t\t\t\t\t_this.reapplyFilter( 'visibleModels' );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"itemTemplate\" :\n\t\t\t\t\t\t_this._updateItemTemplate();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"processKeyEvents\" :\n\t\t\t\t\t\tif( newVal && this.selectable ) _this.$el.attr( \"tabindex\", 0 ); // so we get keyboard events\n\t\t\t\t\t\telse _this.$el.removeAttr( \"tabindex\", 0 );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"modelView\" :\n\t\t\t\t\t\t//need to remove all old view instances\n\t\t\t\t\t\t_this.viewManager.each( function( view ) {\n\t\t\t\t\t\t\t_this.viewManager.remove( view );\n\t\t\t\t\t\t\t// destroy the View itself\n\t\t\t\t\t\t\tview.remove();\n\t\t\t\t\t\t} );\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif( _.contains( kOptionsRequiringRerendering, changedOptionKey ) ) rerender = true;\n\t\t\t} );\n\n\t\t\tif( this._hasBeenRendered && rerender ) {\n\t\t\t\tthis.render();\n\t\t\t}\n\t\t},\n\n\t\tsetOption : function( optionName, optionValue ) { // now is mearly a wrapper around backbone.viewOptions' setOptions()\n\t\t\tvar optionHash = {};\n\t\t\toptionHash[ optionName ] = optionValue;\n\t\t\tthis.setOptions( optionHash );\n\t\t},\n\n\t\tgetSelectedModel : function( options ) {\n\t\t\treturn this.selectedItems.length ? _.first( this.getSelectedModels( options ) ) : null;\n\t\t},\n\n\t\tgetSelectedModels : function ( options ) {\n\t\t\tvar _this = this;\n\n\t\t\toptions = _.extend( {}, {\n\t\t\t\tby : kDefaultReferenceBy\n\t\t\t}, options );\n\n\t\t\tvar referenceBy = options.by;\n\t\t\tvar items = [];\n\n\t\t\tswitch( referenceBy ) {\n\t\t\t\tcase \"id\" :\n\t\t\t\t\t_.each( this.selectedItems, function ( item ) {\n\t\t\t\t\t\titems.push( _this.collection.get( item ).id );\n\t\t\t\t\t} );\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"cid\" :\n\t\t\t\t\titems = items.concat( this.selectedItems );\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"offset\" :\n\t\t\t\t\tvar curLineNumber = 0;\n\n\t\t\t\t\tvar itemElements = this._getVisibleItemEls();\n\n\t\t\t\t\titemElements.each( function() {\n\t\t\t\t\t\tvar thisItemEl = $( this );\n\t\t\t\t\t\tif( thisItemEl.is( \".selected\" ) )\n\t\t\t\t\t\t\titems.push( curLineNumber );\n\t\t\t\t\t\tcurLineNumber++;\n\t\t\t\t\t} );\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"model\" :\n\t\t\t\t\t_.each( this.selectedItems, function ( item ) {\n\t\t\t\t\t\titems.push( _this.collection.get( item ) );\n\t\t\t\t\t} );\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"view\" :\n\t\t\t\t\t_.each( this.selectedItems, function ( item ) {\n\t\t\t\t\t\titems.push( _this.viewManager.findByModel( _this.collection.get( item ) ) );\n\t\t\t\t\t} );\n\t\t\t\t\tbreak;\n\t\t\t\tdefault :\n\t\t\t\t\tthrow new Error( \"Invalid referenceBy option: \" + referenceBy );\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\treturn items;\n\n\t\t},\n\n\t\tsetSelectedModels : function( newSelectedItems, options ) {\n\t\t\tif( ! _.isArray( newSelectedItems ) ) throw \"Invalid parameter value\";\n\t\t\tif( ! this.selectable && newSelectedItems.length > 0 ) return; // used to throw error, but there are some circumstances in which a list can be selectable at times and not at others, don't want to have to worry about catching errors\n\n\t\t\toptions = _.extend( {}, {\n\t\t\t\tsilent : false,\n\t\t\t\tby : kDefaultReferenceBy\n\t\t\t}, options );\n\n\t\t\tvar referenceBy = options.by;\n\t\t\tvar newSelectedCids = [];\n\n\t\t\tswitch( referenceBy ) {\n\t\t\t\tcase \"cid\" :\n\t\t\t\t\tnewSelectedCids = newSelectedItems;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"id\" :\n\t\t\t\t\tthis.collection.each( function( thisModel ) {\n\t\t\t\t\t\tif( _.contains( newSelectedItems, thisModel.id ) ) newSelectedCids.push( thisModel.cid );\n\t\t\t\t\t} );\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"model\" :\n\t\t\t\t\tnewSelectedCids = _.pluck( newSelectedItems, \"cid\" );\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"view\" :\n\t\t\t\t\t_.each( newSelectedItems, function( item ) {\n\t\t\t\t\t\tnewSelectedCids.push( item.model.cid );\n\t\t\t\t\t} );\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"offset\" :\n\t\t\t\t\tvar curLineNumber = 0;\n\t\t\t\t\tvar selectedItems = [];\n\n\t\t\t\t\tvar itemElements = this._getVisibleItemEls();\n\t\t\t\t\titemElements.each( function() {\n\t\t\t\t\t\tvar thisItemEl = $( this );\n\t\t\t\t\t\tif( _.contains( newSelectedItems, curLineNumber ) )\n\t\t\t\t\t\t\tnewSelectedCids.push( thisItemEl.attr( \"data-model-cid\" ) );\n\t\t\t\t\t\tcurLineNumber++;\n\t\t\t\t\t} );\n\t\t\t\t\tbreak;\n\t\t\t\tdefault :\n\t\t\t\t\tthrow new Error( \"Invalid referenceBy option: \" + referenceBy );\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tvar oldSelectedModels = this.getSelectedModels();\n\t\t\tvar oldSelectedCids = _.clone( this.selectedItems );\n\n\t\t\tthis.selectedItems = this._convertStringsToInts( newSelectedCids );\n\t\t\tthis._validateSelection();\n\n\t\t\tvar newSelectedModels = this.getSelectedModels();\n\n\t\t\tif( ! this._containSameElements( oldSelectedCids, this.selectedItems ) )\n\t\t\t{\n\t\t\t\tthis._addSelectedClassToSelectedItems( oldSelectedCids );\n\n\t\t\t\tif( ! options.silent )\n\t\t\t\t{\n\t\t\t\t\tif( this._isBackboneCourierAvailable() ) {\n\t\t\t\t\t\tthis.spawn( \"selectionChanged\", {\n\t\t\t\t\t\t\tselectedModels : newSelectedModels,\n\t\t\t\t\t\t\toldSelectedModels : oldSelectedModels\n\t\t\t\t\t\t} );\n\t\t\t\t\t} else this.trigger( \"selectionChanged\", newSelectedModels, oldSelectedModels );\n\t\t\t\t}\n\n\t\t\t\tthis.updateDependentControls();\n\t\t\t}\n\t\t},\n\n\t\tsetSelectedModel : function( newSelectedItem, options ) {\n\t\t\tif( ! newSelectedItem && newSelectedItem !== 0 )\n\t\t\t\tthis.setSelectedModels( [], options );\n\t\t\telse\n\t\t\t\tthis.setSelectedModels( [ newSelectedItem ], options );\n\t\t},\n\n\t\tgetView : function( reference, options ) {\n\t\t\toptions = _.extend( {}, {\n\t\t\t\tby : kDefaultReferenceBy\n\t\t\t}, options );\n\n\t\t\tswitch( options.by ) {\n\t\t\t\tcase \"id\" :\n\t\t\t\tcase \"cid\" :\n\t\t\t\t\tvar model = this.collection.get( reference ) || null;\n\t\t\t\t\treturn model && this.viewManager.findByModel( model );\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"offset\" :\n\t\t\t\t\tvar itemElements = this._getVisibleItemEls();\n\t\t\t\t\treturn $( itemElements.get( reference ) );\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"model\" :\n\t\t\t\t\treturn this.viewManager.findByModel( reference );\n\t\t\t\t\tbreak;\n\t\t\t\tdefault :\n\t\t\t\t\tthrow new Error( \"Invalid referenceBy option: \" + referenceBy );\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t},\n\n\t\trender : function() {\n\t\t\tvar _this = this;\n\n\t\t\tthis._hasBeenRendered = true;\n\n\t\t\tif( this.selectable ) this._saveSelection();\n\n\t\t\tvar modelViewContainerEl;\n\n\t\t\t// If collection view element is a table and it has a tbody\n\t\t\t// within it, render the model views inside of the tbody\n\t\t\tmodelViewContainerEl = this._getContainerEl();\n\n\t\t\tvar oldViewManager = this.viewManager;\n\t\t\tthis.viewManager = new ChildViewContainer();\n\n\t\t\t// detach each of our subviews that we have already created to represent models\n\t\t\t// in the collection. We are going to re-use the ones that represent models that\n\t\t\t// are still here, instead of creating new ones, so that we don't loose state\n\t\t\t// information in the views.\n\t\t\toldViewManager.each( function( thisModelView ) {\n\t\t\t\t// to boost performance, only detach those views that will be sticking around.\n\t\t\t\t// we won't need the other ones later, so no need to detach them individually.\n\t\t\t\tif( this.reuseModelViews && this.collection.get( thisModelView.model.cid ) ) {\n\t\t\t\t\tthisModelView.$el.detach();\n\t\t\t\t} else thisModelView.remove();\n\t\t\t}, this );\n\n\t\t\tmodelViewContainerEl.empty();\n\t\t\tvar fragmentContainer;\n\n\t\t\tif( this.detachedRendering )\n\t\t\t\tfragmentContainer = document.createDocumentFragment();\n\n\t\t\tthis.collection.each( function( thisModel ) {\n\t\t\t\tvar thisModelView = oldViewManager.findByModelCid( thisModel.cid );\n\t\t\t\tif( ! this.reuseModelViews || _.isUndefined( thisModelView ) ) {\n\t\t\t\t\t// if the model view has not already been created on a\n\t\t\t\t\t// previous render then create and initialize it now.\n\t\t\t\t\tthisModelView = this._createNewModelView( thisModel, this._getModelViewOptions( thisModel ) );\n\t\t\t\t}\n\n\t\t\t\tthis._insertAndRenderModelView( thisModelView, fragmentContainer || modelViewContainerEl );\n\t\t\t}, this );\n\n\t\t\tif( this.detachedRendering )\n\t\t\t\tmodelViewContainerEl.append( fragmentContainer );\n\n\t\t\tif( this.sortable ) this._setupSortable();\n\n\t\t\tthis._showEmptyListCaptionIfAppropriate();\n\n\t\t\tif( this._isBackboneCourierAvailable() )\n\t\t\t\tthis.spawn( \"render\" );\n\t\t\telse this.trigger( \"render\" );\n\n\t\t\tif( this.selectable ) {\n\t\t\t\tthis._restoreSelection();\n\t\t\t\tthis.updateDependentControls();\n\t\t\t}\n\n\t\t\tthis.forceRerenderOnNextSortEvent = false;\n\t\t},\n\n\t\t_showEmptyListCaptionIfAppropriate : function ( ) {\n\t\t\tthis._removeEmptyListCaption();\n\n\t\t\tif( this.emptyListCaption ) {\n\t\t\t\tvar visibleEls = this._getVisibleItemEls();\n\n\t\t\t\tif( visibleEls.length === 0 ) {\n\t\t\t\t\tvar emptyListString;\n\n\t\t\t\t\tif( _.isFunction( this.emptyListCaption ) )\n\t\t\t\t\t\temptyListString = this.emptyListCaption();\n\t\t\t\t\telse\n\t\t\t\t\t\temptyListString = this.emptyListCaption;\n\n\t\t\t\t\tvar $emptyListCaptionEl;\n\t\t\t\t\tvar $varEl = $( \"\" + emptyListString + \" \" );\n\n\t\t\t\t\t// need to wrap the empty caption to make it fit the rendered list structure (either with an li or a tr td)\n\t\t\t\t\tif( this._isRenderedAsList() )\n\t\t\t\t\t\t$emptyListCaptionEl = $varEl.wrapAll( \" \" ).parent().css( kStylesForEmptyListCaption );\n\t\t\t\t\telse\n\t\t\t\t\t\t$emptyListCaptionEl = $varEl.wrapAll( \" \" ).parent().parent().css( kStylesForEmptyListCaption );\n\n\t\t\t\t\tthis._getContainerEl().append( $emptyListCaptionEl );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t_removeEmptyListCaption : function( ) {\n\t\t\tif( this._isRenderedAsList() )\n\t\t\t\tthis._getContainerEl().find( \"> li > var.empty-list-caption\" ).parent().remove();\n\t\t\telse\n\t\t\t\tthis._getContainerEl().find( \"> tr > td > var.empty-list-caption\" ).parent().parent().remove();\n\t\t},\n\n\t\t// Render a single model view in container object \"parentElOrDocumentFragment\", which is either\n\t\t// a documentFragment or a jquery object. optional arg atIndex is not support for document fragments.\n\t\t_insertAndRenderModelView : function( modelView, parentElOrDocumentFragment, atIndex ) {\n\t\t\tvar thisModelViewWrapped = this._wrapModelView( modelView );\n\n\t\t\tif( parentElOrDocumentFragment.nodeType === 11 ) // if we are inserting into a document fragment, we need to use the DOM appendChild method\n\t\t\t\tparentElOrDocumentFragment.appendChild( thisModelViewWrapped.get( 0 ) );\n\t\t\telse {\n\t\t\t\tvar numberOfModelViewsCurrentlyInDOM = parentElOrDocumentFragment.children().length;\n\t\t\t\tif( ! _.isUndefined( atIndex ) && atIndex >= 0 && atIndex < numberOfModelViewsCurrentlyInDOM )\n\t\t\t\t\t// note this.collection.length might be greater than parentElOrDocumentFragment.children().length here\n\t\t\t\t\tparentElOrDocumentFragment.children().eq( atIndex ).before( thisModelViewWrapped );\n\t\t\t\telse {\n\t\t\t\t\t// if we are attempting to insert a modelView in an position that is beyond what is currently in the\n\t\t\t\t\t// DOM, then make a note that we need to re-render the collection view on the next sort event. If we dont\n\t\t\t\t\t// force this re-render, we can end up with modelViews in the wrong order when the collection defines\n\t\t\t\t\t// a comparator and multiple models are added at once. See https://github.com/rotundasoftware/backbone.collectionView/issues/69\n\t\t\t\t\tif( ! _.isUndefined( atIndex ) && atIndex > numberOfModelViewsCurrentlyInDOM ) this.forceRerenderOnNextSortEvent = true;\n\n\t\t\t\t\tparentElOrDocumentFragment.append( thisModelViewWrapped );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.viewManager.add( modelView );\n\n\t\t\t// we have to render the modelView after it has been put in context, as opposed to in the\n\t\t\t// initialize function of the modelView, because some rendering might be dependent on\n\t\t\t// the modelView's context in the DOM tree. For example, if the modelView stretch()'s itself,\n\t\t\t// it must be in full context in the DOM tree or else the stretch will not behave as intended.\n\t\t\tvar renderResult = modelView.render();\n\n\t\t\t// return false from the view's render function to hide this item\n\t\t\tif( renderResult === false ) {\n\t\t\t\tthisModelViewWrapped.hide();\n\t\t\t\tthisModelViewWrapped.addClass( \"not-visible\" );\n\t\t\t}\n\n\t\t\tvar hideThisModelView = false;\n\t\t\tif( _.isFunction( this.visibleModelsFilter ) )\n\t\t\t\thideThisModelView = ! this.visibleModelsFilter( modelView.model );\n\n\t\t\tif( thisModelViewWrapped.children().length === 1 )\n\t\t\t\tthisModelViewWrapped.toggle( ! hideThisModelView );\n\t\t\telse modelView.$el.toggle( ! hideThisModelView );\n\n\t\t\tthisModelViewWrapped.toggleClass( \"not-visible\", hideThisModelView );\n\n\t\t\tif( ! hideThisModelView && this.emptyListCaption ) this._removeEmptyListCaption();\n\t\t},\n\n\t\tupdateDependentControls : function() {\n\t\t\tif( this._isBackboneCourierAvailable() ) {\n\t\t\t\tthis.spawn( \"updateDependentControls\", {\n\t\t\t\t\tselectedModels : this.getSelectedModels()\n\t\t\t\t} );\n\t\t\t} else this.trigger( \"updateDependentControls\", this.getSelectedModels() );\n\t\t},\n\n\t\t// Override `Backbone.View.remove` to also destroy all Views in `viewManager`\n\t\tremove : function() {\n\t\t\tthis.viewManager.each( function( view ) {\n\t\t\t\tview.remove();\n\t\t\t} );\n\n\t\t\tBackbone.View.prototype.remove.apply( this, arguments );\n\t\t},\n\n\t\treapplyFilter : function( whichFilter ) {\n\t\t\tvar _this = this;\n\n\t\t\tif( ! _.contains( [ \"selectableModels\", \"sortableModels\", \"visibleModels\" ], whichFilter ) ) {\n\t\t\t\tthrow new Error( \"Invalid filter identifier supplied to reapplyFilter: \" + whichFilter );\n\t\t\t}\n\n\t\t\tswitch( whichFilter ) {\n\t\t\t\tcase \"visibleModels\":\n\t\t\t\t\t_this.viewManager.each( function( thisModelView ) {\n\t\t\t\t\t\tvar notVisible = _this.visibleModelsFilter && ! _this.visibleModelsFilter.call( _this, thisModelView.model );\n\n\t\t\t\t\t\tthisModelView.$el.toggleClass( \"not-visible\", notVisible );\n\t\t\t\t\t\tif( _this._modelViewHasWrapperLI( thisModelView ) ) {\n\t\t\t\t\t\t\tthisModelView.$el.closest( \"li\" ).toggleClass( \"not-visible\", notVisible ).toggle( ! notVisible );\n\t\t\t\t\t\t} else thisModelView.$el.toggle( ! notVisible );\n\t\t\t\t\t} );\n\n\t\t\t\t\tthis._showEmptyListCaptionIfAppropriate();\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"sortableModels\":\n\t\t\t\t\t_this.$el.sortable( \"destroy\" );\n\n\t\t\t\t\t_this.viewManager.each( function( thisModelView ) {\n\t\t\t\t\t\tvar notSortable = _this.sortableModelsFilter && ! _this.sortableModelsFilter.call( _this, thisModelView.model );\n\n\t\t\t\t\t\tthisModelView.$el.toggleClass( \"not-sortable\", notSortable );\n\t\t\t\t\t\tif( _this._modelViewHasWrapperLI( thisModelView ) ) {\n\t\t\t\t\t\t\tthisModelView.$el.closest( \"li\" ).toggleClass( \"not-sortable\", notSortable );\n\t\t\t\t\t\t}\n\t\t\t\t\t} );\n\n\t\t\t\t\t_this._setupSortable();\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"selectableModels\":\n\t\t\t\t\t_this.viewManager.each( function( thisModelView ) {\n\t\t\t\t\t\tvar notSelectable = _this.selectableModelsFilter && ! _this.selectableModelsFilter.call( _this, thisModelView.model );\n\n\t\t\t\t\t\tthisModelView.$el.toggleClass( \"not-selectable\", notSelectable );\n\t\t\t\t\t\tif( _this._modelViewHasWrapperLI( thisModelView ) ) {\n\t\t\t\t\t\t\tthisModelView.$el.closest( \"li\" ).toggleClass( \"not-selectable\", notSelectable );\n\t\t\t\t\t\t}\n\t\t\t\t\t} );\n\n\t\t\t\t\t_this._validateSelection();\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t},\n\n\t\t// A method to remove the view relating to model.\n\t\t_removeModelView : function( modelView ) {\n\t\t\tif( this.selectable ) this._saveSelection();\n\n\t\t\tthis.viewManager.remove( modelView ); // Remove the view from the viewManager\n\t\t\tif( this._modelViewHasWrapperLI( modelView ) ) modelView.$el.parent().remove(); // Remove the li wrapper from the DOM\n\t\t\tmodelView.remove(); // Remove the view from the DOM and stop listening to events\n\n\t\t\tif( this.selectable ) this._restoreSelection();\n\n\t\t\tthis._showEmptyListCaptionIfAppropriate();\n\t\t},\n\n\t\t_validateSelectionAndRender : function() {\n\t\t\tthis._validateSelection();\n\t\t\tthis.render();\n\t\t},\n\n\t\t_registerCollectionEvents : function() {\n\n\t\t\tthis.listenTo( this.collection, \"add\", function( model ) {\n\t\t\t\tvar modelView;\n\t\t\t\tif( this._hasBeenRendered ) {\n\t\t\t\t\tmodelView = this._createNewModelView( model, this._getModelViewOptions( model ) );\n\t\t\t\t\tthis._insertAndRenderModelView( modelView, this._getContainerEl(), this.collection.indexOf( model ) );\n\t\t\t\t}\n\n\t\t\t\tif( this._isBackboneCourierAvailable() )\n\t\t\t\t\tthis.spawn( \"add\", modelView );\n\t\t\t\telse this.trigger( \"add\", modelView );\n\t\t\t} );\n\n\t\t\tthis.listenTo( this.collection, \"remove\", function( model ) {\n\t\t\t\tvar modelView;\n\n\t\t\t\tif( this._hasBeenRendered ) {\n\t\t\t\t\tmodelView = this.viewManager.findByModelCid( model.cid );\n\t\t\t\t\tthis._removeModelView( modelView );\n\t\t\t\t}\n\n\t\t\t\tif( this._isBackboneCourierAvailable() )\n\t\t\t\t\tthis.spawn( \"remove\" );\n\t\t\t\telse this.trigger( \"remove\" );\n\t\t\t} );\n\n\t\t\tthis.listenTo( this.collection, \"reset\", function() {\n\t\t\t\tif( this._hasBeenRendered ) this.render();\n\t\t\t\tif( this._isBackboneCourierAvailable() )\n\t\t\t\t\tthis.spawn( \"reset\" );\n\t\t\t\telse this.trigger( \"reset\" );\n\t\t\t} );\n\n\t\t\t// we should not be listening to change events on the model as a default behavior. the models\n\t\t\t// should be responsible for re-rendering themselves if necessary, and if the collection does\n\t\t\t// also need to re-render as a result of a model change, this should be handled by overriding\n\t\t\t// this method. by default the collection view should not re-render in response to model changes\n\t\t\t// this.listenTo( this.collection, \"change\", function( model ) {\n\t\t\t// \tif( this._hasBeenRendered ) this.viewManager.findByModel( model ).render();\n\t\t\t// \tif( this._isBackboneCourierAvailable() )\n\t\t\t// \t\tthis.spawn( \"change\", { model : model } );\n\t\t\t// } );\n\n\t\t\tthis.listenTo( this.collection, \"sort\", function( collection, options ) {\n\t\t\t\tif( this._hasBeenRendered && ( options.add !== true || this.forceRerenderOnNextSortEvent ) ) this.render();\n\t\t\t\tif( this._isBackboneCourierAvailable() )\n\t\t\t\t\tthis.spawn( \"sort\" );\n\t\t\t\telse this.trigger( \"sort\" );\n\t\t\t} );\n\t\t},\n\n\t\t_getContainerEl : function() {\n\t\t\tif ( this._isRenderedAsTable() ) {\n\t\t\t\t// not all tables have a tbody, so we test\n\t\t\t\tvar tbody = this.$el.find( \"> tbody\" );\n\t\t\t\tif ( tbody.length > 0 )\n\t\t\t\t\treturn tbody;\n\t\t\t}\n\t\t\treturn this.$el;\n\t\t},\n\n\t\t_getClickedItemId : function( theEvent ) {\n\t\t\tvar clickedItemId = null;\n\n\t\t\t// important to use currentTarget as opposed to target, since we could be bubbling\n\t\t\t// an event that took place within another collectionList\n\t\t\tvar clickedItemEl = $( theEvent.currentTarget );\n\t\t\tif( clickedItemEl.closest( \".collection-view\" ).get(0) !== this.$el.get(0) ) return;\n\n\t\t\t// determine which list item was clicked. If we clicked in the blank area\n\t\t\t// underneath all the elements, we want to know that too, since in this\n\t\t\t// case we will want to deselect all elements. so check to see if the clicked\n\t\t\t// DOM element is the list itself to find that out.\n\t\t\tvar clickedItem = clickedItemEl.closest( \"[data-model-cid]\" );\n\t\t\tif( clickedItem.length > 0 )\n\t\t\t{\n\t\t\t\tclickedItemId = clickedItem.attr( \"data-model-cid\" );\n\t\t\t\tif( $.isNumeric( clickedItemId ) ) clickedItemId = parseInt( clickedItemId, 10 );\n\t\t\t}\n\n\t\t\treturn clickedItemId;\n\t\t},\n\n\t\t_updateItemTemplate : function() {\n\t\t\tvar itemTemplateHtml;\n\t\t\tif( this.itemTemplate )\n\t\t\t{\n\t\t\t\tif( $( this.itemTemplate ).length === 0 )\n\t\t\t\t\tthrow \"Could not find item template from selector: \" + this.itemTemplate;\n\n\t\t\t\titemTemplateHtml = $( this.itemTemplate ).html();\n\t\t\t}\n\t\t\telse\n\t\t\t\titemTemplateHtml = this.$( \".item-template\" ).html();\n\n\t\t\tif( itemTemplateHtml ) this.itemTemplateFunction = _.template( itemTemplateHtml );\n\n\t\t},\n\n\t\t_validateSelection : function() {\n\t\t\t// note can't use the collection's proxy to underscore because \"cid\" is not an attribute,\n\t\t\t// but an element of the model object itself.\n\t\t\tvar modelReferenceIds = _.pluck( this.collection.models, \"cid\" );\n\t\t\tthis.selectedItems = _.intersection( modelReferenceIds, this.selectedItems );\n\n\t\t\tif( _.isFunction( this.selectableModelsFilter ) )\n\t\t\t{\n\t\t\t\tthis.selectedItems = _.filter( this.selectedItems, function( thisItemId ) {\n\t\t\t\t\treturn this.selectableModelsFilter.call( this, this.collection.get( thisItemId ) );\n\t\t\t\t}, this );\n\t\t\t}\n\t\t},\n\n\t\t_saveSelection : function() {\n\t\t\t// save the current selection. use restoreSelection() to restore the selection to the state it was in the last time saveSelection() was called.\n\t\t\tif( ! this.selectable ) throw \"Attempt to save selection on non-selectable list\";\n\t\t\tthis.savedSelection = {\n\t\t\t\titems : _.clone( this.selectedItems ),\n\t\t\t\toffset : this.getSelectedModel( { by : \"offset\" } )\n\t\t\t};\n\t\t},\n\n\t\t_restoreSelection : function() {\n\t\t\tif( ! this.savedSelection ) throw \"Attempt to restore selection but no selection has been saved!\";\n\n\t\t\t// reset selectedItems to empty so that we \"redraw\" all \"selected\" classes\n\t\t\t// when we set our new selection. We do this because it is likely that our\n\t\t\t// contents have been refreshed, and we have thus lost all old \"selected\" classes.\n\t\t\tthis.setSelectedModels( [], { silent : true } );\n\n\t\t\tif( this.savedSelection.items.length > 0 )\n\t\t\t{\n\t\t\t\t// first try to restore the old selected items using their reference ids.\n\t\t\t\tthis.setSelectedModels( this.savedSelection.items, { by : \"cid\", silent : true } );\n\n\t\t\t\t// all the items with the saved reference ids have been removed from the list.\n\t\t\t\t// ok. try to restore the selection based on the offset that used to be selected.\n\t\t\t\t// this is the expected behavior after a item is deleted from a list (i.e. select\n\t\t\t\t// the line that immediately follows the deleted line).\n\t\t\t\tif( this.selectedItems.length === 0 )\n\t\t\t\t\tthis.setSelectedModel( this.savedSelection.offset, { by : \"offset\" } );\n\n\t\t\t\t// Trigger a selection changed if the previously selected items were not all found\n\t\t\t\tif (this.selectedItems.length !== this.savedSelection.items.length)\n\t\t\t\t{\n\t\t\t\t\tif( this._isBackboneCourierAvailable() ) {\n\t\t\t\t\t\tthis.spawn( \"selectionChanged\", {\n\t\t\t\t\t\t\tselectedModels : this.getSelectedModels(),\n\t\t\t\t\t\t\toldSelectedModels : []\n\t\t\t\t\t\t} );\n\t\t\t\t\t} else this.trigger( \"selectionChanged\", this.getSelectedModels(), [] );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t_addSelectedClassToSelectedItems : function( oldItemsIdsWithSelectedClass ) {\n\t\t\tif( _.isUndefined( oldItemsIdsWithSelectedClass ) ) oldItemsIdsWithSelectedClass = [];\n\n\t\t\t// oldItemsIdsWithSelectedClass is used for optimization purposes only. If this info is supplied then we\n\t\t\t// only have to add / remove the \"selected\" class from those items that \"selected\" state has changed.\n\n\t\t\tvar itemsIdsFromWhichSelectedClassNeedsToBeRemoved = oldItemsIdsWithSelectedClass;\n\t\t\titemsIdsFromWhichSelectedClassNeedsToBeRemoved = _.without( itemsIdsFromWhichSelectedClassNeedsToBeRemoved, this.selectedItems );\n\n\t\t\t_.each( itemsIdsFromWhichSelectedClassNeedsToBeRemoved, function( thisItemId ) {\n\t\t\t\tthis._getContainerEl().find( \"[data-model-cid=\" + thisItemId + \"]\" ).removeClass( \"selected\" );\n\n\t\t\t\tif( this._isRenderedAsList() ) {\n\t\t\t\t\tthis._getContainerEl().find( \"li[data-model-cid=\" + thisItemId + \"] > *\" ).removeClass( \"selected\" );\n\t\t\t\t}\n\t\t\t}, this );\n\n\t\t\tvar itemsIdsFromWhichSelectedClassNeedsToBeAdded = this.selectedItems;\n\t\t\titemsIdsFromWhichSelectedClassNeedsToBeAdded = _.without( itemsIdsFromWhichSelectedClassNeedsToBeAdded, oldItemsIdsWithSelectedClass );\n\n\t\t\t_.each( itemsIdsFromWhichSelectedClassNeedsToBeAdded, function( thisItemId ) {\n\t\t\t\tthis._getContainerEl().find( \"[data-model-cid=\" + thisItemId + \"]\" ).addClass( \"selected\" );\n\n\t\t\t\tif( this._isRenderedAsList() ) {\n\t\t\t\t\tthis._getContainerEl().find( \"li[data-model-cid=\" + thisItemId + \"] > *\" ).addClass( \"selected\" );\n\t\t\t\t}\n\t\t\t}, this );\n\t\t},\n\n\t\t_reorderCollectionBasedOnHTML : function() {\n\n\t\t\tvar _this = this;\n\n\t\t\tthis._getContainerEl().children().each( function() {\n\t\t\t\tvar thisModelCid = $( this ).attr( \"data-model-cid\" );\n\n\t\t\t\tif( thisModelCid )\n\t\t\t\t{\n\t\t\t\t\t// remove the current model and then add it back (at the end of the collection).\n\t\t\t\t\t// When we are done looping through all models, they will be in the correct order.\n\t\t\t\t\tvar thisModel = _this.collection.get( thisModelCid );\n\t\t\t\t\tif( thisModel )\n\t\t\t\t\t{\n\t\t\t\t\t\t_this.collection.remove( thisModel, { silent : true } );\n\t\t\t\t\t\t_this.collection.add( thisModel, { silent : true, sort : ! _this.collection.comparator } );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\tif( this._isBackboneCourierAvailable() ) this.spawn( \"reorder\" );\n\t\t\telse this.collection.trigger( \"reorder\" );\n\n\t\t\tif( this.collection.comparator ) this.collection.sort();\n\n\t\t},\n\n\t\t_getModelViewConstructor : function( thisModel ) {\n\t\t\treturn this.modelView || mDefaultModelViewConstructor;\n\t\t},\n\n\t\t_getModelViewOptions : function( thisModel ) {\n\t\t\tvar modelViewOptions = this.modelViewOptions;\n\t\t\tif( _.isFunction( modelViewOptions ) ) modelViewOptions = modelViewOptions( thisModel );\n\n\t\t\treturn _.extend( { model : thisModel }, modelViewOptions );\n\t\t},\n\n\t\t_createNewModelView : function( model, modelViewOptions ) {\n\t\t\tvar modelViewConstructor = this._getModelViewConstructor( model );\n\t\t\tif( _.isUndefined( modelViewConstructor ) ) throw \"Could not find modelView constructor for model\";\n\n\t\t\tvar newModelView = new( modelViewConstructor )( modelViewOptions );\n\t\t\tnewModelView.collectionListView = newModelView.collectionView = this; // collectionListView for legacy\n\n\t\t\treturn newModelView;\n\t\t},\n\n\t\t_wrapModelView : function( modelView ) {\n\t\t\tvar _this = this;\n\n\t\t\t// we use items client ids as opposed to real ids, since we may not have a representation\n\t\t\t// of these models on the server\n\t\t\tvar modelViewWrapperEl;\n\n\t\t\tif( this._isRenderedAsTable() ) {\n\t\t\t\t// if we are rendering the collection in a table, the template $el is a tr so we just need to set the data-model-cid\n\t\t\t\tmodelViewWrapperEl = modelView.$el;\n\t\t\t\tmodelView.$el.attr( \"data-model-cid\", modelView.model.cid );\n\t\t\t}\n\t\t\telse if( this._isRenderedAsList() ) {\n\t\t\t\t// if we are rendering the collection in a list, we need wrap each item in an (if its not already an )\n\t\t\t\t// and set the data-model-cid\n\t\t\t\tif( modelView.$el.is( \"li\" ) ) {\n\t\t\t\t\tmodelViewWrapperEl = modelView.$el;\n\t\t\t\t\tmodelView.$el.attr( \"data-model-cid\", modelView.model.cid );\n\t\t\t\t} else {\n\t\t\t\t\tmodelViewWrapperEl = modelView.$el.wrapAll( \" \" ).parent();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif( _.isFunction( this.sortableModelsFilter ) )\n\t\t\t\tif( ! this.sortableModelsFilter.call( _this, modelView.model ) ) {\n\t\t\t\t\tmodelViewWrapperEl.addClass( \"not-sortable\" );\n\t\t\t\t\tmodelView.$el.addClass( \"not-selectable\" );\n\t\t\t\t}\n\n\t\t\tif( _.isFunction( this.selectableModelsFilter ) )\n\t\t\t\tif( ! this.selectableModelsFilter.call( _this, modelView.model ) ) {\n\t\t\t\t\tmodelViewWrapperEl.addClass( \"not-selectable\" );\n\t\t\t\t\tmodelView.$el.addClass( \"not-selectable\" );\n\t\t\t\t}\n\n\t\t\treturn modelViewWrapperEl;\n\t\t},\n\n\t\t_convertStringsToInts : function( theArray ) {\n\t\t\treturn _.map( theArray, function( thisEl ) {\n\t\t\t\tif( ! _.isString( thisEl ) ) return thisEl;\n\t\t\t\tvar thisElAsNumber = parseInt( thisEl, 10 );\n\t\t\t\treturn( thisElAsNumber == thisEl ? thisElAsNumber : thisEl );\n\t\t\t} );\n\t\t},\n\n\t\t_containSameElements : function( arrayA, arrayB ) {\n\t\t\tif( arrayA.length != arrayB.length ) return false;\n\t\t\tvar intersectionSize = _.intersection( arrayA, arrayB ).length;\n\t\t\treturn intersectionSize == arrayA.length; // and must also equal arrayB.length, since arrayA.length == arrayB.length\n\t\t},\n\n\t\t_isRenderedAsTable : function() {\n\t\t\treturn this.$el.prop( \"tagName\" ).toLowerCase() === \"table\";\n\t\t},\n\n\t\t_isRenderedAsList : function() {\n\t\t\treturn ! this._isRenderedAsTable();\n\t\t},\n\n\t\t_modelViewHasWrapperLI : function( modelView ) {\n\t\t\treturn this._isRenderedAsList() && ! modelView.$el.is( \"li\" );\n\t\t},\n\n\t\t// Returns the wrapper HTML element for each visible modelView.\n\t\t// When rendering in a table context, the returned elements are the $el of each modelView.\n\t\t// When rendering in a list context,\n\t\t// If the $el of the modelView is an , the returned elements are the $el of each modelView.\n\t\t// Otherwise, the returned elements are the 's the collectionView wrapped around each modelView $el.\n\t\t_getVisibleItemEls : function() {\n\t\t\tvar itemElements = [];\n\t\t\titemElements = this._getContainerEl().find( \"> [data-model-cid]:not(.not-visible)\" );\n\n\t\t\treturn itemElements;\n\t\t},\n\n\t\t_charCodes : {\n\t\t\tupArrow : 38,\n\t\t\tdownArrow : 40\n\t\t},\n\n\t\t_isBackboneCourierAvailable : function() {\n\t\t\treturn !_.isUndefined( Backbone.Courier );\n\t\t},\n\n\t\t_setupSortable : function() {\n\t\t\tvar sortableOptions = _.extend( {\n\t\t\t\taxis : \"y\",\n\t\t\t\tdistance : 10,\n\t\t\t\tforcePlaceholderSize : true,\n\t\t\t\titems : this._isRenderedAsTable() ? \"> tbody > tr:not(.not-sortable)\" : \"> li:not(.not-sortable)\",\n\t\t\t\tstart : _.bind( this._sortStart, this ),\n\t\t\t\tchange : _.bind( this._sortChange, this ),\n\t\t\t\tstop : _.bind( this._sortStop, this ),\n\t\t\t\treceive : _.bind( this._receive, this ),\n\t\t\t\tover : _.bind( this._over, this )\n\t\t\t}, _.result( this, \"sortableOptions\" ) );\n\n\t\t\tthis.$el = this.$el.sortable( sortableOptions );\n\t\t\t//this.$el.sortable( \"enable\" ); // in case it was disabled previously\n\t\t},\n\n\t\t_sortStart : function( event, ui ) {\n\t\t\tvar modelBeingSorted = this.collection.get( ui.item.attr( \"data-model-cid\" ) );\n\t\t\tif( this._isBackboneCourierAvailable() )\n\t\t\t\tthis.spawn( \"sortStart\", { modelBeingSorted : modelBeingSorted } );\n\t\t\telse this.trigger( \"sortStart\", modelBeingSorted );\n\t\t},\n\n\t\t_sortChange : function( event, ui ) {\n\t\t\tvar modelBeingSorted = this.collection.get( ui.item.attr( \"data-model-cid\" ) );\n\n\t\t\tif( this._isBackboneCourierAvailable() )\n\t\t\t\tthis.spawn( \"sortChange\", { modelBeingSorted : modelBeingSorted } );\n\t\t\telse this.trigger( \"sortChange\", modelBeingSorted );\n\t\t},\n\n\t\t_sortStop : function( event, ui ) {\n\t\t\tvar modelBeingSorted = this.collection.get( ui.item.attr( \"data-model-cid\" ) );\n\t\t\tvar modelViewContainerEl = this._getContainerEl();\n\t\t\tvar newIndex = modelViewContainerEl.children().index( ui.item );\n\n\t\t\tif( newIndex == -1 && modelBeingSorted ) {\n\t\t\t\t// the element was removed from this list. can happen if this sortable is connected\n\t\t\t\t// to another sortable, and the item was dropped into the other sortable.\n\t\t\t\tthis.collection.remove( modelBeingSorted );\n\t\t\t}\n\n\t\t\tif( ! modelBeingSorted ) return; // something is wacky. we don't mess with this case, preferring to guarantee that we can always provide a reference to the model\n\n\t\t\tthis._reorderCollectionBasedOnHTML();\n\t\t\tthis.updateDependentControls();\n\n\t\t\tif( this._isBackboneCourierAvailable() )\n\t\t\t\tthis.spawn( \"sortStop\", { modelBeingSorted : modelBeingSorted, newIndex : newIndex } );\n\t\t\telse this.trigger( \"sortStop\", modelBeingSorted, newIndex );\n\t\t},\n\n\t\t_receive : function( event, ui ) {\n\n\t\t\tvar senderListEl = ui.sender;\n\t\t\tvar senderCollectionListView = senderListEl.data( \"view\" );\n\t\t\tif( ! senderCollectionListView || ! senderCollectionListView.collection ) return;\n\n\t\t\tvar newIndex = this._getContainerEl().children().index( ui.item );\n\t\t\tvar modelReceived = senderCollectionListView.collection.get( ui.item.attr( \"data-model-cid\" ) );\n\t\t\tsenderCollectionListView.collection.remove( modelReceived );\n\t\t\tthis.collection.add( modelReceived, { at : newIndex } );\n\t\t\tmodelReceived.collection = this.collection; // otherwise will not get properly set, since modelReceived.collection might already have a value.\n\t\t\tthis.setSelectedModel( modelReceived );\n\t\t},\n\n\t\t_over : function( event, ui ) {\n\t\t\t// when an item is being dragged into the sortable,\n\t\t\t// hide the empty list caption if it exists\n\t\t\tthis._getContainerEl().find( \"> var.empty-list-caption\" ).hide();\n\t\t},\n\n\t\t_onKeydown : function( event ) {\n\t\t\tif( ! this.processKeyEvents ) return true;\n\n\t\t\tvar trap = false;\n\n\t\t\tif( this.getSelectedModels( { by : \"offset\" } ).length == 1 )\n\t\t\t{\n\t\t\t\t// need to trap down and up arrows or else the browser\n\t\t\t\t// will end up scrolling a autoscroll div.\n\n\t\t\t\tvar currentOffset = this.getSelectedModel( { by : \"offset\" } );\n\t\t\t\tif( event.which === this._charCodes.upArrow && currentOffset !== 0 )\n\t\t\t\t{\n\t\t\t\t\tthis.setSelectedModel( currentOffset - 1, { by : \"offset\" } );\n\t\t\t\t\ttrap = true;\n\t\t\t\t}\n\t\t\t\telse if( event.which === this._charCodes.downArrow && currentOffset !== this.collection.length - 1 )\n\t\t\t\t{\n\t\t\t\t\tthis.setSelectedModel( currentOffset + 1, { by : \"offset\" } );\n\t\t\t\t\ttrap = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn ! trap;\n\t\t},\n\n\t\t_listItem_onMousedown : function( theEvent ) {\n\t\t\tvar clickedItemId = this._getClickedItemId( theEvent );\n\n\t\t\tif( clickedItemId ) {\n\t\t\t\tvar clickedModel = this.collection.get( clickedItemId );\n\t\t\t\tif( this._isBackboneCourierAvailable() ) {\n\t\t\t\t\tvar data = {\n\t\t\t\t\t\tclickedModel : clickedModel,\n\t\t\t\t\t\tmetaKeyPressed : theEvent.ctrlKey || theEvent.metaKey\n\t\t\t\t\t};\n\n\t\t\t\t\t_.each( [ 'preventDefault', 'stopPropagation', 'stopImmediatePropagation' ], function( thisMethod ) {\n\t\t\t\t\t\tdata[ thisMethod ] = function() {\n\t\t\t\t\t\t\ttheEvent[ thisMethod ]();\n\t\t\t\t\t\t};\n\t\t\t\t\t} );\n\n\t\t\t\t\tthis.spawn( \"click\", data );\n\t\t\t\t}\n\t\t\t\telse this.trigger( \"click\", clickedModel );\n\t\t\t}\n\n\t\t\tif( ! this.selectable || ! this.clickToSelect ) return;\n\n\t\t\tif( clickedItemId )\n\t\t\t{\n\t\t\t\t// Exit if an unselectable item was clicked\n\t\t\t\tif( _.isFunction( this.selectableModelsFilter ) &&\n\t\t\t\t\t! this.selectableModelsFilter.call( this, this.collection.get( clickedItemId ) ) )\n\t\t\t\t{\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// a selectable list item was clicked\n\t\t\t\tif( this.selectMultiple && theEvent.shiftKey )\n\t\t\t\t{\n\t\t\t\t\tvar firstSelectedItemIndex = -1;\n\n\t\t\t\t\tif( this.selectedItems.length > 0 )\n\t\t\t\t\t{\n\t\t\t\t\t\tthis.collection.find( function( thisItemModel ) {\n\t\t\t\t\t\t\tfirstSelectedItemIndex++;\n\n\t\t\t\t\t\t\t// exit when we find our first selected element\n\t\t\t\t\t\t\treturn _.contains( this.selectedItems, thisItemModel.cid );\n\t\t\t\t\t\t}, this );\n\t\t\t\t\t}\n\n\t\t\t\t\tvar clickedItemIndex = -1;\n\t\t\t\t\tthis.collection.find( function( thisItemModel ) {\n\t\t\t\t\t\tclickedItemIndex++;\n\n\t\t\t\t\t\t// exit when we find the clicked element\n\t\t\t\t\t\treturn thisItemModel.cid == clickedItemId;\n\t\t\t\t\t}, this );\n\n\t\t\t\t\tvar shiftKeyRootSelectedItemIndex = firstSelectedItemIndex == -1 ? clickedItemIndex : firstSelectedItemIndex;\n\t\t\t\t\tvar minSelectedItemIndex = Math.min( clickedItemIndex, shiftKeyRootSelectedItemIndex );\n\t\t\t\t\tvar maxSelectedItemIndex = Math.max( clickedItemIndex, shiftKeyRootSelectedItemIndex );\n\n\t\t\t\t\tvar newSelectedItems = [];\n\t\t\t\t\tfor( var thisIndex = minSelectedItemIndex; thisIndex <= maxSelectedItemIndex; thisIndex ++ )\n\t\t\t\t\t\tnewSelectedItems.push( this.collection.at( thisIndex ).cid );\n\t\t\t\t\tthis.setSelectedModels( newSelectedItems, { by : \"cid\" } );\n\n\t\t\t\t\t// shift clicking will usually highlight selectable text, which we do not want.\n\t\t\t\t\t// this is a cross browser (hopefully) snippet that deselects all text selection.\n\t\t\t\t\tif( document.selection && document.selection.empty )\n\t\t\t\t\t\tdocument.selection.empty();\n\t\t\t\t\telse if(window.getSelection) {\n\t\t\t\t\t\tvar sel = window.getSelection();\n\t\t\t\t\t\tif( sel && sel.removeAllRanges )\n\t\t\t\t\t\t\tsel.removeAllRanges();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if( ( this.selectMultiple || _.contains( this.selectedItems, clickedItemId ) ) && ( this.clickToToggle || theEvent.metaKey || theEvent.ctrlKey ) )\n\t\t\t\t{\n\t\t\t\t\tif( _.contains( this.selectedItems, clickedItemId ) )\n\t\t\t\t\t\tthis.setSelectedModels( _.without( this.selectedItems, clickedItemId ), { by : \"cid\" } );\n\t\t\t\t\telse this.setSelectedModels( _.union( this.selectedItems, [clickedItemId] ), { by : \"cid\" } );\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tthis.setSelectedModels( [ clickedItemId ], { by : \"cid\" } );\n\t\t\t}\n\t\t\telse\n\t\t\t\t// the blank area of the list was clicked\n\t\t\t\tthis.setSelectedModels( [] );\n\n\t\t},\n\n\t\t_listItem_onDoubleClick : function( theEvent ) {\n\n\t\t\tvar clickedItemId = this._getClickedItemId( theEvent );\n\n\t\t\tif( clickedItemId )\n\t\t\t{\n\t\t\t\tvar clickedModel = this.collection.get( clickedItemId );\n\n\t\t\t\tif( this._isBackboneCourierAvailable() )\n\t\t\t\t\tthis.spawn( \"doubleClick\", { clickedModel : clickedModel, metaKeyPressed : theEvent.ctrlKey || theEvent.metaKey } );\n\t\t\t\telse this.trigger( \"doubleClick\", clickedModel );\n\t\t\t}\n\t\t},\n\n\t\t_listBackground_onClick : function( theEvent ) {\n\t\t\tif( ! this.selectable || ! this.clickToSelect ) return;\n\t\t\tif( ! $( theEvent.target ).is( \".collection-view\" ) ) return;\n\n\t\t\tthis.setSelectedModels( [] );\n\t\t}\n\n\t}, {\n\t\tsetDefaultModelViewConstructor : function( theConstructor ) {\n\t\t\tmDefaultModelViewConstructor = theConstructor;\n\t\t}\n\t});\n\n\t/*\n\t* Backbone.ViewOptions, v0.2.4\n\t* Copyright (c)2014 Rotunda Software, LLC.\n\t* Distributed under MIT license\n\t* http://github.com/rotundasoftware/backbone.viewOptions\n\t*/\n\n\tBackbone.ViewOptions = {};\n\n\tBackbone.ViewOptions.add = function( view, optionsDeclarationsProperty ) {\n\t\tif( _.isUndefined( optionsDeclarationsProperty ) ) optionsDeclarationsProperty = \"options\";\n\n\t\t// ****************** Public methods added to view ******************\n\n\t\tview.setOptions = function( options ) {\n\t\t\tvar _this = this;\n\t\t\tvar optionsThatWereChanged = {};\n\t\t\tvar optionsThatWereChangedPreviousValues = {};\n\n\t\t\tvar optionDeclarations = _.result( this, optionsDeclarationsProperty );\n\n\t\t\tif( ! _.isUndefined( optionDeclarations ) ) {\n\t\t\t\tvar normalizedOptionDeclarations = _normalizeOptionDeclarations( optionDeclarations );\n\n\t\t\t\t_.each( normalizedOptionDeclarations, function( thisOptionProperties, thisOptionName ) {\n\t\t\t\t\tvar thisOptionRequired = thisOptionProperties.required;\n\t\t\t\t\tvar thisOptionDefaultValue = thisOptionProperties.defaultValue;\n\n\t\t\t\t\tif( thisOptionRequired ) {\n\t\t\t\t\t\t// note we do not throw an error if a required option is not supplied, but it is\n\t\t\t\t\t\t// found on the object itself (due to a prior call of view.setOptions, most likely)\n\n\t\t\t\t\t\tif( ( ! options || ! _.contains( _.keys( options ), thisOptionName ) ) && _.isUndefined( _this[ thisOptionName ] ) )\n\t\t\t\t\t\t\tthrow new Error( \"Required option \\\"\" + thisOptionName + \"\\\" was not supplied.\" );\n\n\t\t\t\t\t\tif( options && _.contains( _.keys( options ), thisOptionName ) && _.isUndefined( options[ thisOptionName ] ) )\n\t\t\t\t\t\t\tthrow new Error( \"Required option \\\"\" + thisOptionName + \"\\\" can not be set to undefined.\" );\n\t\t\t\t\t}\n\n\t\t\t\t\t// attach the supplied value of this option, or the appropriate default value, to the view object\n\t\t\t\t\tif( options && thisOptionName in options && ! _.isUndefined( options[ thisOptionName ] ) ) {\n\t\t\t\t\t\tvar oldValue = _this[ thisOptionName ];\n\t\t\t\t\t\tvar newValue = options[ thisOptionName ];\n\t\t\t\t\t\t// if this option already exists on the view, and the new value is different,\n\t\t\t\t\t\t// make a note that we will be changing it\n\t\t\t\t\t\tif( ! _.isUndefined( oldValue ) && oldValue !== newValue ) {\n\t\t\t\t\t\t\toptionsThatWereChangedPreviousValues[ thisOptionName ] = oldValue;\n\t\t\t\t\t\t\toptionsThatWereChanged[ thisOptionName ] = newValue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t_this[ thisOptionName ] = newValue;\n\t\t\t\t\t\t// note we do NOT delete the option off the options object here so that\n\t\t\t\t\t\t// multiple views can be passed the same options object without issue.\n\t\t\t\t\t}\n\t\t\t\t\telse if( _.isUndefined( _this[ thisOptionName ] ) ) {\n\t\t\t\t\t\t// note defaults do not write over any existing properties on the view itself.\n\t\t\t\t\t\t_this[ thisOptionName ] = thisOptionDefaultValue;\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\tif( _.keys( optionsThatWereChanged ).length > 0 ) {\n\t\t\t\tif( _.isFunction( _this.onOptionsChanged ) )\n\t\t\t\t\t_this.onOptionsChanged( optionsThatWereChanged, optionsThatWereChangedPreviousValues );\n\t\t\t\telse if( _.isFunction( _this._onOptionsChanged ) )\n\t\t\t\t\t_this._onOptionsChanged( optionsThatWereChanged, optionsThatWereChangedPreviousValues );\n\t\t\t}\n\t\t};\n\n\t\tview.getOptions = function() {\n\t\t\tvar optionDeclarations = _.result( this, optionsDeclarationsProperty );\n\t\t\tif( _.isUndefined( optionDeclarations ) ) return {};\n\n\t\t\tvar normalizedOptionDeclarations = _normalizeOptionDeclarations( optionDeclarations );\n\t\t\tvar optionsNames = _.keys( normalizedOptionDeclarations );\n\n\t\t\treturn _.pick( this, optionsNames );\n\t\t};\n\t};\n\n\t// ****************** Private Utility Functions ******************\n\n\tfunction _normalizeOptionDeclarations( optionDeclarations ) {\n\t\t// convert our short-hand option syntax (with exclamation marks, etc.)\n\t\t// to a simple array of standard option declaration objects.\n\n\t\tvar normalizedOptionDeclarations = {};\n\n\t\tif( ! _.isArray( optionDeclarations ) ) throw new Error( \"Option declarations must be an array.\" );\n\n\t\t_.each( optionDeclarations, function( thisOptionDeclaration ) {\n\t\t\tvar thisOptionName, thisOptionRequired, thisOptionDefaultValue;\n\n\t\t\tthisOptionRequired = false;\n\t\t\tthisOptionDefaultValue = undefined;\n\n\t\t\tif( _.isString( thisOptionDeclaration ) )\n\t\t\t\tthisOptionName = thisOptionDeclaration;\n\t\t\telse if( _.isObject( thisOptionDeclaration ) ) {\n\t\t\t\tthisOptionName = _.first( _.keys( thisOptionDeclaration ) );\n\t\t\t\tif( _.isFunction( thisOptionDeclaration[ thisOptionName ] ) )\n\t\t\t\t\tthisOptionDefaultValue = thisOptionDeclaration[ thisOptionName ];\n\t\t\t\telse\n\t\t\t\t\tthisOptionDefaultValue = _.clone( thisOptionDeclaration[ thisOptionName ] );\n\t\t\t}\n\t\t\telse throw new Error( \"Each element in the option declarations array must be either a string or an object.\" );\n\n\t\t\tif( thisOptionName[ thisOptionName.length - 1 ] === \"!\" ) {\n\t\t\t\tthisOptionRequired = true;\n\t\t\t\tthisOptionName = thisOptionName.slice( 0, thisOptionName.length - 1 );\n\t\t\t}\n\n\t\t\tnormalizedOptionDeclarations[ thisOptionName ] = normalizedOptionDeclarations[ thisOptionName ] || {};\n\t\t\tnormalizedOptionDeclarations[ thisOptionName ].required = thisOptionRequired;\n\t\t\tif( ! _.isUndefined( thisOptionDefaultValue ) ) normalizedOptionDeclarations[ thisOptionName ].defaultValue = thisOptionDefaultValue;\n\t\t} );\n\n\t\treturn normalizedOptionDeclarations;\n\t}\n\n\n\t// Backbone.BabySitter\n\t// -------------------\n\t// v0.0.6\n\t//\n\t// Copyright (c)2013 Derick Bailey, Muted Solutions, LLC.\n\t// Distributed under MIT license\n\t//\n\t// http://github.com/babysitterjs/backbone.babysitter\n\n\t// Backbone.ChildViewContainer\n\t// ---------------------------\n\t//\n\t// Provide a container to store, retrieve and\n\t// shut down child views.\n\n\tChildViewContainer = (function(Backbone, _){\n\n\t\t// Container Constructor\n\t\t// ---------------------\n\n\t\tvar Container = function(views){\n\t\t\tthis._views = {};\n\t\t\tthis._indexByModel = {};\n\t\t\tthis._indexByCustom = {};\n\t\t\tthis._updateLength();\n\n\t\t\t_.each(views, this.add, this);\n\t\t};\n\n\t\t// Container Methods\n\t\t// -----------------\n\n\t\t_.extend(Container.prototype, {\n\n\t\t\t// Add a view to this container. Stores the view\n\t\t\t// by `cid` and makes it searchable by the model\n\t\t\t// cid (and model itself). Optionally specify\n\t\t\t// a custom key to store an retrieve the view.\n\t\t\tadd: function(view, customIndex){\n\t\t\t\tvar viewCid = view.cid;\n\n\t\t\t\t// store the view\n\t\t\t\tthis._views[viewCid] = view;\n\n\t\t\t\t// index it by model\n\t\t\t\tif (view.model){\n\t\t\t\t\tthis._indexByModel[view.model.cid] = viewCid;\n\t\t\t\t}\n\n\t\t\t\t// index by custom\n\t\t\t\tif (customIndex){\n\t\t\t\t\tthis._indexByCustom[customIndex] = viewCid;\n\t\t\t\t}\n\n\t\t\t\tthis._updateLength();\n\t\t\t},\n\n\t\t\t// Find a view by the model that was attached to\n\t\t\t// it. Uses the model's `cid` to find it.\n\t\t\tfindByModel: function(model){\n\t\t\t\treturn this.findByModelCid(model.cid);\n\t\t\t},\n\n\t\t\t// Find a view by the `cid` of the model that was attached to\n\t\t\t// it. Uses the model's `cid` to find the view `cid` and\n\t\t\t// retrieve the view using it.\n\t\t\tfindByModelCid: function(modelCid){\n\t\t\t\tvar viewCid = this._indexByModel[modelCid];\n\t\t\t\treturn this.findByCid(viewCid);\n\t\t\t},\n\n\t\t\t// Find a view by a custom indexer.\n\t\t\tfindByCustom: function(index){\n\t\t\t\tvar viewCid = this._indexByCustom[index];\n\t\t\t\treturn this.findByCid(viewCid);\n\t\t\t},\n\n\t\t\t// Find by index. This is not guaranteed to be a\n\t\t\t// stable index.\n\t\t\tfindByIndex: function(index){\n\t\t\t\treturn _.values(this._views)[index];\n\t\t\t},\n\n\t\t\t// retrieve a view by it's `cid` directly\n\t\t\tfindByCid: function(cid){\n\t\t\t\treturn this._views[cid];\n\t\t\t},\n\n\t\t\tfindIndexByCid : function( cid ) {\n\t\t\t\tvar index = -1;\n\t\t\t\tvar view = _.find( this._views, function ( view ) {\n\t\t\t\t\tindex++;\n\t\t\t\t\tif( view.model.cid == cid )\n\t\t\t\t\t\treturn view;\n\t\t\t\t} );\n\t\t\t\treturn ( view ) ? index : -1;\n\t\t\t},\n\n\t\t\t// Remove a view\n\t\t\tremove: function(view){\n\t\t\t\tvar viewCid = view.cid;\n\n\t\t\t\t// delete model index\n\t\t\t\tif (view.model){\n\t\t\t\t\tdelete this._indexByModel[view.model.cid];\n\t\t\t\t}\n\n\t\t\t\t// delete custom index\n\t\t\t\t_.any(this._indexByCustom, function(cid, key) {\n\t\t\t\t\tif (cid === viewCid) {\n\t\t\t\t\t\tdelete this._indexByCustom[key];\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}, this);\n\n\t\t\t\t// remove the view from the container\n\t\t\t\tdelete this._views[viewCid];\n\n\t\t\t\t// update the length\n\t\t\t\tthis._updateLength();\n\t\t\t},\n\n\t\t\t// Call a method on every view in the container,\n\t\t\t// passing parameters to the call method one at a\n\t\t\t// time, like `function.call`.\n\t\t\tcall: function(method){\n\t\t\t\tthis.apply(method, _.tail(arguments));\n\t\t\t},\n\n\t\t\t// Apply a method on every view in the container,\n\t\t\t// passing parameters to the call method one at a\n\t\t\t// time, like `function.apply`.\n\t\t\tapply: function(method, args){\n\t\t\t\t_.each(this._views, function(view){\n\t\t\t\t\tif (_.isFunction(view[method])){\n\t\t\t\t\t\tview[method].apply(view, args || []);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t},\n\n\t\t\t// Update the `.length` attribute on this container\n\t\t\t_updateLength: function(){\n\t\t\t\tthis.length = _.size(this._views);\n\t\t\t}\n\t\t});\n\n\t\t// Borrowing this code from Backbone.Collection:\n\t\t// http://backbonejs.org/docs/backbone.html#section-106\n\t\t//\n\t\t// Mix in methods from Underscore, for iteration, and other\n\t\t// collection related features.\n\t\tvar methods = ['forEach', 'each', 'map', 'find', 'detect', 'filter',\n\t\t\t 'select', 'reject', 'every', 'all', 'some', 'any', 'include',\n\t\t\t 'contains', 'invoke', 'toArray', 'first', 'initial', 'rest',\n\t\t\t 'last', 'without', 'isEmpty', 'pluck'];\n\n\t\t_.each(methods, function(method) {\n\t\t\tContainer.prototype[method] = function() {\n\t\t\t\tvar views = _.values(this._views);\n\t\t\t\tvar args = [views].concat(_.toArray(arguments));\n\t\t\t\treturn _[method].apply(_, args);\n\t\t\t};\n\t\t});\n\n\t\t// return the public API\n\t\treturn Container;\n\t})(Backbone, _);\n\n\treturn Backbone.CollectionView;\n} ) );\n\n","//\n// backbone.trackit - 0.1.0\n// The MIT License\n// Copyright (c) 2013 The New York Times, CMS Group, Matthew DeLambo \n//\n(function() {\n\n\t// Unsaved Record Keeping\n\t// ----------------------\n\n\t// Collection of all models in an app that have unsaved changes.\n\tvar unsavedModels = [];\n\n\t// If the given model has unsaved changes then add it to\n\t// the `unsavedModels` collection, otherwise remove it.\n\tvar updateUnsavedModels = function(model) {\n\t\tif (!_.isEmpty(model._unsavedChanges)) {\n\t\t\tif (!_.findWhere(unsavedModels, {cid:model.cid})) unsavedModels.push(model);\n\t\t} else {\n\t\t\tunsavedModels = _.filter(unsavedModels, function(m) { return model.cid != m.cid; });\n\t\t}\n\t};\n\n\t// Unload Handlers\n\t// ---------------\n\n\t// Helper which returns a prompt message for an unload handler.\n\t// Uses the given function name (one of the callback names\n\t// from the `model.unsaved` configuration hash) to evaluate\n\t// whether a prompt is needed/returned.\n\tvar getPrompt = function(fnName) {\n\t\tvar prompt, args = _.rest(arguments);\n\t\t// Evaluate and return a boolean result. The given `fn` may be a\n\t\t// boolean value, a function, or the name of a function on the model.\n\t\tvar evaluateModelFn = function(model, fn) {\n\t\t\tif (_.isBoolean(fn)) return fn;\n\t\t\treturn (_.isString(fn) ? model[fn] : fn).apply(model, args);\n\t\t};\n\t\t_.each(unsavedModels, function(model) {\n\t\t\tif (!prompt && evaluateModelFn(model, model._unsavedConfig[fnName]))\n\t\t\t\tprompt = model._unsavedConfig.prompt;\n\t\t});\n\t\treturn prompt;\n\t};\n\n\t// Wrap Backbone.History.navigate so that in-app routing\n\t// (`router.navigate('/path')`) can be intercepted with a\n\t// confirmation if there are any unsaved models.\n\tBackbone.History.prototype.navigate = _.wrap(Backbone.History.prototype.navigate, function(oldNav, fragment, options) {\n\t\tvar prompt = getPrompt('unloadRouterPrompt', fragment, options);\n\t\tif (prompt) {\n\t\t\tif (confirm(prompt + ' \\n\\nAre you sure you want to leave this page?')) {\n\t\t\t\toldNav.call(this, fragment, options);\n\t\t\t}\n\t\t} else {\n\t\t\toldNav.call(this, fragment, options);\n\t\t}\n\t});\n\n\t// Create a browser unload handler which is triggered\n\t// on the refresh, back, or forward button.\n\twindow.onbeforeunload = function(e) {\n\t\treturn getPrompt('unloadWindowPrompt', e);\n\t};\n\n\t// Backbone.Model API\n\t// ------------------\n\n\t_.extend(Backbone.Model.prototype, {\n\n\t\tunsaved: {},\n\t\t_trackingChanges: false,\n\t\t_originalAttrs: {},\n\t\t_unsavedChanges: {},\n\n\t\t// Opt in to tracking attribute changes\n\t\t// between saves.\n\t\tstartTracking: function() {\n\t\t\tthis._unsavedConfig = _.extend({}, {\n\t\t\t\tprompt: 'You have unsaved changes!',\n\t\t\t\tunloadRouterPrompt: false,\n\t\t\t\tunloadWindowPrompt: false\n\t\t\t}, this.unsaved || {});\n\t\t\tthis._trackingChanges = true;\n\t\t\tthis._resetTracking();\n\t\t\tthis._triggerUnsavedChanges();\n\t\t\treturn this;\n\t\t},\n\n\t\t// Resets the default tracking values\n\t\t// and stops tracking attribute changes.\n\t\tstopTracking: function() {\n\t\t\tthis._trackingChanges = false;\n\t\t\tthis._originalAttrs = {};\n\t\t\tthis._unsavedChanges = {};\n\t\t\tthis._triggerUnsavedChanges();\n\t\t\treturn this;\n\t\t},\n\n\t\t// Gets rid of accrued changes and\n\t\t// resets state.\n\t\trestartTracking: function() {\n\t\t\tthis._resetTracking();\n\t\t\tthis._triggerUnsavedChanges();\n\t\t\treturn this;\n\t\t},\n\n\t\t// Restores this model's attributes to\n\t\t// their original values since tracking\n\t\t// started, the last save, or last restart.\n\t\tresetAttributes: function() {\n\t\t\tif (!this._trackingChanges) return;\n\t\t\tthis.attributes = this._originalAttrs;\n\t\t\tthis._resetTracking();\n\t\t\tthis._triggerUnsavedChanges();\n\t\t\treturn this;\n\t\t},\n\n\t\t// Symmetric to Backbone's `model.changedAttributes()`,\n\t\t// except that this returns a hash of the model's attributes that\n\t\t// have changed since the last save, or `false` if there are none.\n\t\t// Like `changedAttributes`, an external attributes hash can be\n\t\t// passed in, returning the attributes in that hash which differ\n\t\t// from the model.\n\t\tunsavedAttributes: function(attrs) {\n\t\t\tif (!attrs) return _.isEmpty(this._unsavedChanges) ? false : _.clone(this._unsavedChanges);\n\t\t\tvar val, changed = false, old = this._unsavedChanges;\n\t\t\tfor (var attr in attrs) {\n\t\t\t\tif (_.isEqual(old[attr], (val = attrs[attr]))) continue;\n\t\t\t\t(changed || (changed = {}))[attr] = val;\n\t\t\t}\n\t\t\treturn changed;\n\t\t},\n\n\t\t_resetTracking: function() {\n\t\t\tthis._originalAttrs = _.clone(this.attributes);\n\t\t\tthis._unsavedChanges = {};\n\t\t},\n\n\t\t// Trigger an `unsavedChanges` event on this model,\n\t\t// supplying the result of whether there are unsaved\n\t\t// changes and a changed attributes hash.\n\t\t_triggerUnsavedChanges: function() {\n\t\t\tthis.trigger('unsavedChanges', !_.isEmpty(this._unsavedChanges), _.clone(this._unsavedChanges));\n\t\t\tif (this.unsaved) updateUnsavedModels(this);\n\t\t}\n\t});\n\n\t// Wrap `model.set()` and update the internal\n\t// unsaved changes record keeping.\n\tBackbone.Model.prototype.set = _.wrap(Backbone.Model.prototype.set, function(oldSet, key, val, options) {\n\t\tvar attrs, ret;\n\t\tif (key == null) return this;\n\t\t// Handle both `\"key\", value` and `{key: value}` -style arguments.\n\t\tif (typeof key === 'object') {\n\t\t\tattrs = key;\n\t\t\toptions = val;\n\t\t} else {\n\t\t\t(attrs = {})[key] = val;\n\t\t}\n\t\toptions || (options = {});\n\n\t\t// Delegate to Backbone's set.\n\t\tret = oldSet.call(this, attrs, options);\n\n\t\tif (this._trackingChanges && !options.silent) {\n\t\t\t_.each(attrs, _.bind(function(val, key) {\n\t\t\t\tif (_.isEqual(this._originalAttrs[key], val))\n\t\t\t\t\tdelete this._unsavedChanges[key];\n\t\t\t\telse\n\t\t\t\t\tthis._unsavedChanges[key] = val;\n\t\t\t}, this));\n\t\t\tthis._triggerUnsavedChanges();\n\t\t}\n\t\treturn ret;\n\t});\n\n\t// Intercept `model.save()` and reset tracking/unsaved\n\t// changes if it was successful.\n\tBackbone.sync = _.wrap(Backbone.sync, function(oldSync, method, model, options) {\n\t\toptions || (options = {});\n\n\t\tif (method == 'update') {\n\t\t\toptions.success = _.wrap(options.success, _.bind(function(oldSuccess, data, textStatus, jqXHR) {\n\t\t\t\tvar ret;\n\t\t\t\tif (oldSuccess) ret = oldSuccess.call(this, data, textStatus, jqXHR);\n\t\t\t\tif (model._trackingChanges) {\n\t\t\t\t\tmodel._resetTracking();\n\t\t\t\t\tmodel._triggerUnsavedChanges();\n\t\t\t\t}\n\t\t\t\treturn ret;\n\t\t\t}, this));\n\t\t}\n\t\treturn oldSync(method, model, options);\n\t});\n\n})();\ndefine(\"vendor/backbone.trackit\", function(){});\n\n","/**\n * Image object model for use in various models for the 'image' attribute\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Models/Image',[], function() {\n\n\treturn Backbone.Model.extend( {\n\n\t\tdefaults: {\n\t\t\tenabled: 'no',\n\t\t\tid: '',\n\t\t\tsize: 'full',\n\t\t\tsrc: '',\n\t\t},\n\n\t\tinitialize: function() {\n\t\t\tthis.startTracking();\n\t\t},\n\n\t} );\n} );\n\n","/**\n * Model relationships mixin\n * @since 3.16.0\n * @version 3.16.11\n */\ndefine( 'Models/_Relationships',[], function() {\n\n\treturn {\n\n\t\t/**\n\t\t * Default relationship settings object\n\t\t * @type {Object}\n\t\t */\n\t\trelationship_defaults: {\n\t\t\tparent: {},\n\t\t\tchildren: {},\n\t\t},\n\n\t\t/**\n\t\t * Relationship settings object\n\t\t * Should be overriden in the model\n\t\t * @type {Object}\n\t\t */\n\t\trelationships: {},\n\n\t\t/**\n\t\t * Initialize all parent and child relationships\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinit_relationships: function( options ) {\n\n\t\t\tvar rels = this.get_relationships();\n\n\t\t\t// initialize parent relaxtionships\n\t\t\t// useful when adding a model to ensure parent is initialized\n\t\t\tif ( rels.parent && options && options.parent ) {\n\t\t\t\tthis.set_parent( options.parent );\n\t\t\t}\n\n\t\t\t// initialize all children relationships\n\t\t\t_.each( rels.children, function( child_data, child_key ) {\n\n\t\t\t\tif ( ! child_data.conditional || true === child_data.conditional( this ) ) {\n\n\t\t\t\t\tvar child_val = this.get( child_key ),\n\t\t\t\t\t\tchild;\n\n\t\t\t\t\tif ( child_data.lookup ) {\n\t\t\t\t\t\tchild = child_data.lookup( child_val );\n\t\t\t\t\t} else if ( 'model' === child_data.type ) {\n\t\t\t\t\t\tchild = window.llms_builder.construct.get_model( child_data.class, child_val );\n\t\t\t\t\t} else if ( 'collection' === child_data.type ) {\n\t\t\t\t\t\tchild = window.llms_builder.construct.get_collection( child_data.class, child_val );\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.set( child_key, child );\n\n\t\t\t\t\t// if the child defines a parent, save a reference to the parent on the child\n\t\t\t\t\tif ( 'model' === child_data.type ) {\n\t\t\t\t\t\tthis._maybe_set_parent_reference( child );\n\n\t\t\t\t\t// save directly to each model in the collection\n\t\t\t\t\t} else if ( 'collection' === child_data.type ) {\n\n\t\t\t\t\t\tchild.parent = this;\n\t\t\t\t\t\tchild.each( function( child_model ) {\n\n\t\t\t\t\t\t\tthis._maybe_set_parent_reference( child_model );\n\n\t\t\t\t\t\t}, this );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t}, this );\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the property names for all children of the model\n\t\t * @return array\n\t\t * @since 3.16.11\n\t\t * @version 3.16.11\n\t\t */\n\t\tget_child_props: function() {\n\n\t\t\tvar props = [];\n\n\t\t\t_.each( this.get_relationships().children, function( data, key ) {\n\n\t\t\t\tif ( ! data.conditional || true === data.conditional( this ) ) {\n\t\t\t\t\tprops.push( key );\n\t\t\t\t}\n\n\t\t\t}, this );\n\n\t\t\treturn props;\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the model's parent (if set)\n\t\t * @return obj|false\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_parent: function() {\n\n\t\t\tvar rels = this.get_relationships();\n\n\t\t\tif ( rels.parent ) {\n\t\t\t\treturn rels.parent.reference;\n\t\t\t}\n\n\t\t\treturn false;\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve relationships for the model\n\t\t * Extends with defaults\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_relationships: function() {\n\n\t\t\treturn $.extend( true, this.relationships, this.relationship_defaults );\n\n\t\t},\n\n\t\t/**\n\t\t * Set the parent reference for the given model\n\t\t * @param obj obj parent model obj\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tset_parent: function( obj ) {\n\t\t\tthis.relationships.parent.reference = obj;\n\t\t},\n\n\t\t/**\n\t\t * Set up the parent relationships for qualifying children during relationship initialization\n\t\t * @param obj model child model\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\t_maybe_set_parent_reference: function( model ) {\n\n\t\t\tif ( ! model || ! model.get_relationships ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar rels = model.get_relationships();\n\t\t\tif ( rels.parent && rels.parent.model === this.get( 'type' ) ) {\n\t\t\t\tmodel.set_parent( this );\n\t\t\t}\n\n\t\t},\n\n\t};\n\n} );\n\n","/**\n * Quiz Question Choice\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Models/QuestionChoice',[ 'Models/Image', 'Models/_Relationships' ], function( Image, Relationships ) {\n\n\treturn Backbone.Model.extend( _.defaults( {\n\n\t\t/**\n\t\t * Model relationships\n\t\t * @type {Object}\n\t\t */\n\t\trelationships: {\n\t\t\tparent: {\n\t\t\t\tmodel: 'llms_question',\n\t\t\t\ttype: 'model',\n\t\t\t},\n\t\t\tchildren: {\n\t\t\t\tchoice: {\n\t\t\t\t\tconditional: function( model ) {\n\t\t\t\t\t\treturn ( 'image' === model.get( 'choice_type' ) );\n\t\t\t\t\t},\n\t\t\t\t\tclass: 'Image',\n\t\t\t\t\tmodel: 'image',\n\t\t\t\t\ttype: 'model',\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\n\t\t/**\n\t\t * Model defaults\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tdefaults: function() {\n\t\t\treturn {\n\t\t\t\tid: _.uniqueId( 'temp_' ),\n\t\t\t\tchoice: '',\n\t\t\t\tchoice_type: 'text',\n\t\t\t\tcorrect: false,\n\t\t\t\tmarker: 'A',\n\t\t\t\tquestion_id: '',\n\t\t\t\ttype: 'choice',\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Initializer\n\t\t * @param obj data object of model attributes\n\t\t * @param obj options additional options\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function( data, options ) {\n\n\t\t\tthis.startTracking();\n\t\t\tthis.init_relationships( options );\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the choice's parent question\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_parent: function() {\n\t\t\treturn this.collection.parent;\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the ID used when trashing the model\n\t\t * @return string\n\t\t * @since 3.17.1\n\t\t * @version 3.17.1\n\t\t */\n\t\tget_trash_id: function() {\n\t\t\treturn this.get( 'question_id' ) + ':' + this.get( 'id' );\n\t\t},\n\n\t\t/**\n\t\t * Determine if \"selection\" is enabled for the question type\n\t\t * Choice type questions are selectable by reorder type questions are not but still use choices\n\t\t * @return {Boolean}\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tis_selectable: function() {\n\t\t\treturn this.get_parent().get( 'question_type' ).get_choice_selectable();\n\t\t},\n\n\t}, Relationships ) );\n\n} );\n\n","/**\n * Question Choice Collection\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Collections/QuestionChoices',[ 'Models/QuestionChoice' ], function( model ) {\n\n\treturn Backbone.Collection.extend( {\n\n\t\t/**\n\t\t * Model for collection items\n\t\t * @type obj\n\t\t */\n\t\tmodel: model,\n\n\t\tinitialize: function() {\n\n\t\t\t// reorder called by QuestionList view when sortable drops occur\n\t\t\tthis.on( 'reorder', this.update_order );\n\n\t\t\t// when a choice is added or removed, update order\n\t\t\tthis.on( 'add', this.update_order );\n\t\t\tthis.on( 'remove', this.update_order );\n\n\t\t\t// when a choice is added or remove, ensure min/max correct answers exist\n\t\t\tthis.on( 'add', this.update_correct );\n\t\t\tthis.on( 'remove', this.update_correct );\n\n\t\t\t// when a choice is toggled, ensure min/max correct exist\n\t\t\tthis.on( 'correct-update', this.update_correct );\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the number of correct choices in the collection\n\t\t * @return int\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tcount_correct: function() {\n\n\t\t\treturn _.size( this.get_correct() );\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the collection reduced to only correct choices\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_correct: function() {\n\t\t\treturn this.filter( function( choice ) {\n\t\t\t\treturn choice.get( 'correct' );\n\t\t\t} );\n\t\t},\n\n\t\t/**\n\t\t * Ensure min/max correct choices exist in the collection based on the question's settings\n\t\t * @param obj choice model of the choice that was toggled\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tupdate_correct: function( choice ) {\n\n\t\t\tif ( ! this.parent.get( 'question_type' ).get_choice_selectable() ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar siblings = this.without( choice ), // exclude the toggled choice from loops\n\t\t\t\tquestion = this.parent;\n\n\t\t\t// if multiple choices aren't enabled turn all other choices to incorrect\n\t\t\tif ( 'no' === question.get( 'multi_choices' ) ) {\n\t\t\t\t_.each( siblings, function( model ) {\n\t\t\t\t\tmodel.set( 'correct', false );\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\t// if we don't have a single corret answer & the question has points, set one\n\t\t\t// allows users to create quizzes / questions with no points and therefore no correct answers are allowed\n\t\t\tif ( 0 === this.count_correct() && question.get( 'points' ) > 0 ) {\n\t\t\t\tvar models = 1 === this.size() ? this.models : siblings;\n\t\t\t\t_.first( models ).set( 'correct', true );\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Update the marker attr of each choice in the list to reflect the order of the collection\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tupdate_order: function() {\n\n\t\t\tvar self = this,\n\t\t\t\tquestion = this.parent;\n\n\t\t\tthis.each( function( choice ) {\n\t\t\t\tchoice.set( 'marker', question.get( 'question_type' ).get_choice_markers()[ self.indexOf( choice ) ] );\n\t\t\t} );\n\n\t\t},\n\n\t} );\n\n} );\n\n","/**\n * Quiz Question Type\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Models/QuestionType',[], function() {\n\n\treturn Backbone.Model.extend( {\n\n\t\t/**\n\t\t * Get model default attributes\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tdefaults: function() {\n\t\t\treturn {\n\t\t\t\tchoices: false,\n\t\t\t\tclarifications: true,\n\t\t\t\tdefault_choices: [],\n\t\t\t\tdescription: true,\n\t\t\t\ticon: 'question',\n\t\t\t\tid: 'generic',\n\t\t\t\timage: true,\n\t\t\t\tkeywords: [],\n\t\t\t\tname: 'Generic',\n\t\t\t\tplaceholder: '',\n\t\t\t\tpoints: true,\n\t\t\t\tvideo: true,\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Retrieve an array of keywords for the question type\n\t\t * Used for filtering questions by search term in the quiz builder\n\t\t * @return array\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_keywords: function() {\n\n\t\t\tvar name = this.get( 'name' ),\n\t\t\t\twords = [ name ];\n\n\t\t\treturn words.concat( this.get( 'keywords' ) ).concat( name.split( ' ' ) );\n\n\t\t},\n\n\t\t/**\n\t\t * Get marker array for the question choices\n\t\t * @return array\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_choice_markers: function() {\n\n\t\t\treturn this._get_choice_option( 'markers' );\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if the question's choices are selectable\n\t\t * @return bool\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_choice_selectable: function() {\n\n\t\t\treturn this._get_choice_option( 'selectable' );\n\n\t\t},\n\n\t\t/**\n\t\t * Get the choice type (text,image)\n\t\t * @return string\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_choice_type: function() {\n\n\t\t\treturn this._get_choice_option( 'type' );\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve defined min. choices\n\t\t * @return int\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_min_choices: function() {\n\n\t\t\treturn this._get_choice_option( 'min' );\n\n\t\t},\n\n\t\t/**\n\t\t * Get type-defined max choices\n\t\t * @return string\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_max_choices: function() {\n\n\t\t\treturn this._get_choice_option( 'max' );\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if multi-choice selection is enabled\n\t\t * @return bool\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_multi_choices: function() {\n\n\t\t\tvar choices = this.get( 'choices' );\n\n\t\t\tif ( ! choices ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\treturn this._get_choice_option( 'multi' );\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve data from the type's \"choices\" attribute\n\t\t * Allows quick handling of types with no choice definitions w/o additional checks\n\t\t * @param string option name of the choice option to retrieve\n\t\t * @return mixed\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\t_get_choice_option: function( option ) {\n\n\t\t\tvar choices = this.get( 'choices' );\n\n\t\t\tif ( ! choices || ! choices[ option ] ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\treturn choices[ option ];\n\n\t\t},\n\n\t} );\n\n} );\n\n","/**\n * Quiz Question\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Models/Question',[\n\t\t'Models/Image',\n\t\t'Collections/Questions',\n\t\t'Collections/QuestionChoices',\n\t\t'Models/QuestionType',\n\t\t'Models/_Relationships'\n\t], function(\n\t\tImage,\n\t\tQuestions,\n\t\tQuestionChoices,\n\t\tQuestionType,\n\t\tRelationships\n\t) {\n\n\treturn Backbone.Model.extend( _.defaults( {\n\n\t\t/**\n\t\t * Model relationships\n\t\t * @type {Object}\n\t\t */\n\t\trelationships: {\n\t\t\tparent: {\n\t\t\t\tmodel: 'llms_quiz',\n\t\t\t\ttype: 'model',\n\t\t\t},\n\t\t\tchildren: {\n\t\t\t\tchoices: {\n\t\t\t\t\tclass: 'QuestionChoices',\n\t\t\t\t\tmodel: 'choice',\n\t\t\t\t\ttype: 'collection',\n\t\t\t\t},\n\t\t\t\timage: {\n\t\t\t\t\tclass: 'Image',\n\t\t\t\t\tmodel: 'image',\n\t\t\t\t\ttype: 'model',\n\t\t\t\t},\n\t\t\t\tquestions: {\n\t\t\t\t\tclass: 'Questions',\n\t\t\t\t\tconditional: function( model ) {\n\t\t\t\t\t\tvar type = model.get( 'question_type' ),\n\t\t\t\t\t\t\ttype_id = _.isString( type ) ? type : type.get( 'id' );\n\t\t\t\t\t\treturn ( 'group' === type_id );\n\t\t\t\t\t},\n\t\t\t\t\tmodel: 'llms_question',\n\t\t\t\t\ttype: 'collection',\n\t\t\t\t},\n\t\t\t\tquestion_type: {\n\t\t\t\t\tclass: 'QuestionType',\n\t\t\t\t\tlookup: function( val ) {\n\t\t\t\t\t\tif ( _.isString( val ) ) {\n\t\t\t\t\t\t\treturn window.llms_builder.questions.get( val );\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn val;\n\t\t\t\t\t},\n\t\t\t\t\tmodel: 'question_type',\n\t\t\t\t\ttype: 'model',\n\t\t\t\t},\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Model defaults\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tdefaults: function() {\n\t\t\treturn {\n\t\t\t\tid: _.uniqueId( 'temp_' ),\n\t\t\t\tchoices: [],\n\t\t\t\tcontent: '',\n\t\t\t\tdescription_enabled: 'no',\n\t\t\t\timage: {},\n\t\t\t\tmulti_choices: 'no',\n\t\t\t\tmenu_order: 1,\n\t\t\t\tpoints: 1,\n\t\t\t\tquestion_type: 'generic',\n\t\t\t\tquestions: [], // for question groups\n\t\t\t\tparent_id: '',\n\t\t\t\ttitle: '',\n\t\t\t\ttype: 'llms_question',\n\t\t\t\tvideo_enabled: 'no',\n\t\t\t\tvideo_src: '',\n\n\t\t\t\t_expanded: false,\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Initializer\n\t\t * @param obj data object of data for the model\n\t\t * @param obj options additional options\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function( data, options ) {\n\n\t\t\tvar self = this;\n\n\t\t\tthis.startTracking();\n\t\t\tthis.init_relationships( options );\n\n\t\t\tif ( false !== this.get( 'question_type' ).choices ) {\n\n\t\t\t\tthis._ensure_min_choices();\n\n\t\t\t\t// when a choice is removed, maybe add back some defaults so we always have the minimum\n\t\t\t\tthis.listenTo( this.get( 'choices' ), 'remove', function() {\n\t\t\t\t\t// new itmes are added at index 0 when there's only 1 item in the collection, not sure why exactly...\n\t\t\t\t\tsetTimeout( function() {\n\t\t\t\t\t\tself._ensure_min_choices();\n\t\t\t\t\t}, 0 );\n\t\t\t\t} );\n\n\t\t\t}\n\n\t\t\t// ensure question types that don't support points don't record default 1 point in database\n\t\t\tif ( ! this.get( 'question_type' ).get( 'points' ) ) {\n\t\t\t\tthis.set( 'points', 0 );\n\t\t\t}\n\n\t\t\t_.delay( function( self ) {\n\t\t\t\tself.on( 'change:points', self.get_parent().update_points, self.get_parent() );\n\t\t\t}, 1, this );\n\n\t\t},\n\n\t\t/**\n\t\t * Add a new question choice\n\t\t * @param obj data object of choice data\n\t\t * @param obj options additional options\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tadd_choice: function( data, options ) {\n\n\t\t\tvar max = this.get( 'question_type' ).get_max_choices();\n\t\t\tif ( this.get( 'choices' ).size() >= max ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tdata = data || {};\n\t\t\toptions = options || {};\n\n\t\t\tdata.choice_type = this.get( 'question_type' ).get_choice_type();\n\t\t\tdata.question_id = this.get( 'id' );\n\t\t\toptions.parent = this;\n\n\t\t\tvar choice = this.get( 'choices' ).add( data, options );\n\n\t\t\tBackbone.pubSub.trigger( 'question-add-choice', choice, this );\n\n\t\t},\n\n\t\t/**\n\t\t * Collapse question_type attribute during full syncs to save to database\n\t\t * Not needed because question types cannot be adjusted after question creation\n\t\t * Called from sync controller\n\t\t * @param obj atts flat object of attributes to be saved to db\n\t\t * @param string sync_type full or partial\n\t\t * full indicates a force resync or that the model isn't persisted yet\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tbefore_save: function( atts, sync_type ) {\n\t\t\tif ( 'full' === sync_type ) {\n\t\t\t\tatts.question_type = this.get( 'question_type' ).get( 'id' );\n\t\t\t}\n\t\t\treturn atts;\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the model's parent (if set)\n\t\t * @return obj|false\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_parent: function() {\n\n\t\t\tvar rels = this.get_relationships();\n\n\t\t\tif ( rels.parent ) {\n\t\t\t\tif ( this.collection && this.collection.parent ) {\n\t\t\t\t\treturn this.collection.parent;\n\t\t\t\t} else if ( rels.parent.reference ) {\n\t\t\t\t\treturn rels.parent.reference;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false;\n\n\t\t},\n\n\t\t/**\n\t\t * Gets the index of the question within it's parent\n\t\t * Question numbers skip content elements\n\t\t * & content elements skip questions\n\t\t * @return int\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_type_index: function() {\n\n\t\t\t// current models type, used to check the predicate in the filter function below\n\t\t\tvar curr_type = this.get( 'question_type' ).get( 'id' ),\n\t\t\t\tquestions;\n\n\t\t\tquestions = this.collection.filter( function( question ) {\n\n\t\t\t\tvar type = question.get( 'question_type' ).get( 'id' );\n\n\t\t\t\t// if current model is not content, return all non-content questions\n\t\t\t\tif ( curr_type !== 'content' ) {\n\t\t\t\t\treturn ( 'content' !== type );\n\t\t\t\t}\n\n\t\t\t\t// current model is content, return only content questions\n\t\t\t\treturn 'content' === type;\n\n\t\t\t} );\n\n\t\t\treturn questions.indexOf( this );\n\n\t\t},\n\n\t\t/**\n\t\t * Gets iterator for the given type\n\t\t * Questions use numbers and content uses alphabet\n\t\t * @return mixed\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_type_iterator: function() {\n\n\t\t\tvar index = this.get_type_index();\n\n\t\t\tif ( -1 === index ) {\n\t\t\t\treturn '';\n\t\t\t}\n\n\t\t\tif ( 'content' === this.get( 'question_type' ).get( 'id' ) ) {\n\t\t\t\tvar alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split( '' );\n\t\t\t\treturn alphabet[ index ];\n\t\t\t}\n\n\t\t\treturn index + 1;\n\n\t\t},\n\n\n\t\tget_qid: function() {\n\n\t\t\tvar parent = this.get_parent_question(),\n\t\t\t\tprefix = '';\n\n\t\t\tif ( parent ) {\n\n\t\t\t\tprefix = parent.get_qid() + '.';\n\n\t\t\t}\n\n\t\t\t// return short_id + this.get_type_iterator();\n\t\t\treturn prefix + this.get_type_iterator();\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the parent question (if the question is in a question group)\n\t\t * @return obj|false\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_parent_question: function() {\n\n\t\t\tif ( this.is_in_group() ) {\n\n\t\t\t\treturn this.collection.parent;\n\n\t\t\t}\n\n\t\t\treturn false;\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the parent quiz\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_parent_quiz: function() {\n\t\t\treturn this.get_parent();\n\t\t},\n\n\t\t/**\n\t\t * Points getter\n\t\t * ensures that 0 is always returned if the question type doesn't support points\n\t\t * @return int\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_points: function() {\n\n\t\t\tif ( ! this.get( 'question_type' ).get( 'points' ) ) {\n\t\t\t\treturn 0;\n\t\t\t}\n\n\t\t\treturn this.get( 'points' );\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the questions percentage value within the quiz\n\t\t * @return string\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_points_percentage: function() {\n\n\t\t\tvar total = this.get_parent().get( '_points' ),\n\t\t\t\tpoints = this.get( 'points' );\n\n\t\t\tif ( 0 === total ) {\n\t\t\t\treturn '0%';\n\t\t\t}\n\n\t\t\treturn ( ( points / total ) * 100 ).toFixed( 2 ) + '%';\n\n\t\t},\n\n\t\t/**\n\t\t * Deterine if the question belongs to a question group\n\t\t * @return {Boolean}\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tis_in_group: function() {\n\n\t\t\treturn ( 'question' === this.collection.parent.get( 'type' ) );\n\n\t\t},\n\n\t\t_ensure_min_choices: function() {\n\n\t\t\tvar choices = this.get( 'choices' );\n\t\t\twhile ( choices.size() < this.get( 'question_type' ).get_min_choices() ) {\n\t\t\t\tthis.add_choice();\n\t\t\t}\n\n\t\t},\n\n\t}, Relationships ) );\n\n} );\n\n","/**\n * Questions Collection\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Collections/Questions',[ 'Models/Question' ], function( model ) {\n\n\treturn Backbone.Collection.extend( {\n\n\t\t/**\n\t\t * Model for collection items\n\t\t * @type obj\n\t\t */\n\t\tmodel: model,\n\n\t\t/**\n\t\t * Initialize\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\t// reorder called by QuestionList view when sortable drops occur\n\t\t\tthis.on( 'reorder', this.update_order );\n\n\t\t\t// when a question is added or removed, update order\n\t\t\tthis.on( 'add', this.update_order );\n\t\t\tthis.on( 'remove', this.update_order );\n\n\t\t\tthis.on( 'add', this.update_parent );\n\n\t\t},\n\n\t\t/**\n\t\t * Update the order attr of each question in the list to reflect the order of the collection\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tupdate_order: function() {\n\n\t\t\tvar self = this;\n\n\t\t\tthis.each( function( question ) {\n\n\t\t\t\tquestion.set( 'menu_order', self.indexOf( question ) + 1 );\n\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * When adding a question to a question list, update the question's parent\n\t\t * Will ensure that questions moved into and out of groups always have the corerct parent_id\n\t\t * @param obj model instance of the question model\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tupdate_parent: function( model ) {\n\n\t\t\tmodel.set( 'parent_id', this.parent.get( 'id' ) );\n\n\t\t},\n\n\t} );\n\n} );\n\n","/**\n * Utility functions for Models\n * @since 3.16.0\n * @version 3.17.1\n */\ndefine( 'Models/_Utilities',[], function() {\n\n\treturn {\n\n\t\tfields: [],\n\n\t\t/**\n\t\t * Retrieve the edit post link for the current model\n\t\t * @return string\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_edit_post_link: function() {\n\n\t\t\tif ( this.has_temp_id() ) {\n\t\t\t\treturn '';\n\t\t\t}\n\n\t\t\treturn window.llms_builder.admin_url + 'post.php?post=' + this.get( 'id' ) + '&action=edit';\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve schema fields defined for the model\n\t\t * @return object\n\t\t * @since 3.17.0\n\t\t * @version 3.17.1\n\t\t */\n\t\tget_settings_fields: function() {\n\n\t\t\tvar schema = this.schema || {};\n\t\t\treturn window.llms_builder.schemas.get( schema, this.get( 'type' ).replace( 'llms_', '' ), this );\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if the model has a temporary ID\n\t\t * @return {Boolean}\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\thas_temp_id: function() {\n\n\t\t\treturn ( ! _.isNumber( this.get( 'id' ) ) && 0 === this.get( 'id' ).indexOf( 'temp_' ) );\n\n\t\t},\n\n\t\t/**\n\t\t * Initializes 3rd party custom schema (field) data for a model\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tinit_custom_schema: function() {\n\n\t\t\tvar groups = _.filter( this.get_settings_fields(), function( group ) {\n\t\t\t\treturn ( group.custom );\n\t\t\t} );\n\n\t\t\t_.each( groups, function( group ) {\n\t\t\t\t_.each( _.flatten( group.fields ), function( field ) {\n\n\n\t\t\t\t\tvar keys = [ field.attribute ],\n\t\t\t\t\t\tcustoms = this.get( 'custom' );\n\n\t\t\t\t\tif ( field.switch_attribute ) {\n\t\t\t\t\t\tkeys.push( field.switch_attribute );\n\t\t\t\t\t}\n\n\t\t\t\t\t_.each( keys, function( key ) {\n\t\t\t\t\t\tvar attr = field.attribute_prefix ? field.attribute_prefix + key : key;\n\t\t\t\t\t\tif ( customs && customs[ attr ] ) {\n\t\t\t\t\t\t\tthis.set( key, customs[ attr ][0] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}, this );\n\n\t\t\t\t}, this );\n\t\t\t}, this );\n\n\t\t},\n\n\t};\n\n} );\n\n","/**\n * Quiz Schema\n * @since 3.17.6\n * @version 3.17.6\n */\ndefine( 'Schemas/Quiz',[], function() {\n\n\treturn {\n\n\t\tdefault: {\n\t\t\ttitle: LLMS.l10n.translate( 'General Settings' ),\n\t\t\ttoggleable: true,\n\t\t\tfields: [\n\t\t\t\t[\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'permalink',\n\t\t\t\t\t\tid: 'permalink',\n\t\t\t\t\t\ttype: 'permalink',\n\t\t\t\t\t},\n\t\t\t\t], [\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'content',\n\t\t\t\t\t\tid: 'description',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Description' ),\n\t\t\t\t\t\ttype: 'editor',\n\t\t\t\t\t},\n\t\t\t\t], [\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'passing_percent',\n\t\t\t\t\t\tid: 'passing-percent',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Passing Percentage' ),\n\t\t\t\t\t\tmin: 0,\n\t\t\t\t\t\tmax: 100,\n\t\t\t\t\t\ttip: LLMS.l10n.translate( 'Minimum percentage of total points required to pass the quiz' ),\n\t\t\t\t\t\ttype: 'number',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'allowed_attempts',\n\t\t\t\t\t\tid: 'allowed-attempts',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Limit Attempts' ),\n\t\t\t\t\t\tswitch_attribute: 'limit_attempts',\n\t\t\t\t\t\ttip: LLMS.l10n.translate( 'Limit the maximum number of times a student can take this quiz' ),\n\t\t\t\t\t\ttype: 'switch-number',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'time_limit',\n\t\t\t\t\t\tid: 'time-limit',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Time Limit' ),\n\t\t\t\t\t\tmin: 1,\n\t\t\t\t\t\tmax: 360,\n\t\t\t\t\t\tswitch_attribute: 'limit_time',\n\t\t\t\t\t\ttip: LLMS.l10n.translate( 'Enforce a maximum number of minutes a student can spend on each attempt' ),\n\t\t\t\t\t\ttype: 'switch-number',\n\t\t\t\t\t},\n\t\t\t\t], [\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'show_correct_answer',\n\t\t\t\t\t\tid: 'show-correct-answer',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Show Correct Answers' ),\n\t\t\t\t\t\ttip: LLMS.l10n.translate( 'When enabled, students will be shown the correct answer to any question they answered incorrectly.' ),\n\t\t\t\t\t\ttype: 'switch',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'random_questions',\n\t\t\t\t\t\tid: 'random-questions',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Randomize Question Order' ),\n\t\t\t\t\t\ttip: LLMS.l10n.translate( 'Display questions in a random order for each attempt. Content questions are locked into their defined positions.' ),\n\t\t\t\t\t\ttype: 'switch',\n\t\t\t\t\t},\n\t\t\t\t],\n\n\t\t\t],\n\t\t},\n\n\t};\n\n} );\n\n","/**\n * Quiz Model\n * @since 3.16.0\n * @version 3.19.2\n */\ndefine( 'Models/Quiz',[\n\t\t'Collections/Questions',\n\t\t'Models/Lesson',\n\t\t'Models/Question',\n\t\t'Models/_Relationships',\n\t\t'Models/_Utilities',\n\t\t'Schemas/Quiz',\n\t], function(\n\t\tQuestions,\n\t\tLesson,\n\t\tQuestion,\n\t\tRelationships,\n\t\tUtilities,\n\t\tQuizSchema\n\t) {\n\n\treturn Backbone.Model.extend( _.defaults( {\n\n\t\t/**\n\t\t * model relationships\n\t\t * @type {Object}\n\t\t */\n\t\trelationships: {\n\t\t\tparent: {\n\t\t\t\tmodel: 'lesson',\n\t\t\t\ttype: 'model',\n\t\t\t},\n\t\t\tchildren: {\n\t\t\t\tquestions: {\n\t\t\t\t\tclass: 'Questions',\n\t\t\t\t\tmodel: 'llms_question',\n\t\t\t\t\ttype: 'collection',\n\t\t\t\t},\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Lesson Settings Schema\n\t\t * @type {Object}\n\t\t */\n\t\tschema: QuizSchema,\n\n\t\t/**\n\t\t * New lesson defaults\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.6\n\t\t */\n\t\tdefaults: function() {\n\n\t\t\treturn {\n\t\t\t\tid: _.uniqueId( 'temp_' ),\n\t\t\t\ttitle: LLMS.l10n.translate( 'New Quiz' ),\n\t\t\t\ttype: 'llms_quiz',\n\t\t\t\tlesson_id: '',\n\n\t\t\t\tstatus: 'draft',\n\n\t\t\t\t// editable fields\n\t\t\t\tcontent: '',\n\t\t\t\tallowed_attempts: 5,\n\t\t\t\tlimit_attempts: 'no',\n\t\t\t\tlimit_time: 'no',\n\t\t\t\tpassing_percent: 65,\n\t\t\t\tname: '',\n\t\t\t\trandom_answers: 'no',\n\t\t\t\ttime_limit: 30,\n\t\t\t\tshow_correct_answer: 'no',\n\n\t\t\t\tquestions: [],\n\n\t\t\t\t// calculated\n\t\t\t\t_points: 0,\n\n\t\t\t\t// display\n\t\t\t\tpermalink: '',\n\t\t\t\t_show_settings: false,\n\t\t\t\t_questions_loaded: false,\n\t\t\t};\n\n\t\t},\n\n\t\t/**\n\t\t * Initializer\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.17.6\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\tthis.init_custom_schema();\n\t\t\tthis.startTracking();\n\t\t\tthis.init_relationships();\n\n\t\t\tthis.listenTo( this.get( 'questions' ), 'add', this.update_points );\n\t\t\tthis.listenTo( this.get( 'questions' ), 'remove', this.update_points );\n\n\t\t\tthis.set( '_points', this.get_total_points() );\n\n\t\t\t// when a quiz is published, ensure the parent lesson is marked as \"Enabled\" for quizzing\n\t\t\tthis.on( 'change:status', function() {\n\t\t\t\tif ( 'publish' === this.get( 'status' ) ) {\n\t\t\t\t\tthis.get_parent().set( 'quiz_enabled', 'yes' );\n\t\t\t\t}\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * Add a new question to the quiz\n\t\t * @param obj data question data\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tadd_question: function( data ) {\n\n\t\t\tdata.parent_id = this.get( 'id' );\n\t\t\tvar question = this.get( 'questions' ).add( data, {\n\t\t\t\tparent: this,\n\t\t\t} );\n\t\t\tBackbone.pubSub.trigger( 'quiz-add-question', question, this );\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the translated post type name for the model's type\n\t\t * @param bool plural if true, returns the plural, otherwise returns singular\n\t\t * @return string\n\t\t * @since 3.16.12\n\t\t * @version 3.16.12\n\t\t */\n\t\tget_l10n_type: function( plural ) {\n\n\t\t\tif ( plural ) {\n\t\t\t\treturn LLMS.l10n.translate( 'quizzes' );\n\t\t\t}\n\n\t\t\treturn LLMS.l10n.translate( 'quiz' );\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the quiz's total points\n\t\t * @return int\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_total_points: function() {\n\n\t\t\tvar points = 0;\n\n\t\t\tthis.get( 'questions' ).each( function( question ) {\n\t\t\t\tpoints += question.get_points();\n\t\t\t} );\n\n\t\t\treturn points;\n\n\t\t},\n\n\t\t/**\n\t\t * Lazy load questions via AJAX\n\t\t * @param {Function} cb callback function\n\t\t * @return void\n\t\t * @since 3.19.2\n\t\t * @version 3.19.2\n\t\t */\n\t\tload_questions: function( cb ) {\n\n\t\t\tif ( this.get( '_questions_loaded' ) ) {\n\n\t\t\t\tcb();\n\n\t\t\t} else {\n\n\t\t\t\tvar self = this;\n\n\t\t\t\tLLMS.Ajax.call( {\n\t\t\t\t\tdata: {\n\t\t\t\t\t\taction: 'llms_builder',\n\t\t\t\t\t\taction_type: 'lazy_load',\n\t\t\t\t\t\tcourse_id: window.llms_builder.CourseModel.get( 'id' ),\n\t\t\t\t\t\tload_id: this.get( 'id' ),\n\t\t\t\t\t},\n\t\t\t\t\terror: function( xhr, status, error ) {\n\n\t\t\t\t\t\tconsole.log( xhr, status, error );\n\t\t\t\t\t\twindow.llms_builder.debug.log( '==== start load_questions error ====', xhr, status, error, '==== finish load_questions error ====' );\n\t\t\t\t\t\tcb( true );\n\n\t\t\t\t\t},\n\t\t\t\t\tsuccess: function( res ) {\n\t\t\t\t\t\tif ( res && res.questions ) {\n\t\t\t\t\t\t\tself.set( '_questions_loaded', true );\n\t\t\t\t\t\t\tif ( res.questions ) {\n\t\t\t\t\t\t\t\t_.each( res.questions, self.add_question, self );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcb();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tcb( true );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t} );\n\n\t\t\t}\n\n\n\t\t},\n\n\t\t/**\n\t\t * Update total number of points calculated property\n\t\t * @return int\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tupdate_points: function() {\n\n\t\t\tthis.set( '_points', this.get_total_points() );\n\n\t\t},\n\n\t}, Relationships, Utilities ) );\n\n} );\n\n","/**\n * Lesson Schemas\n * @since 3.17.0\n * @version 3.17.1\n */\ndefine( 'Schemas/Lesson',[], function() {\n\n\treturn {\n\n\t\tdefault: {\n\t\t\ttitle: LLMS.l10n.translate( 'General Settings' ),\n\t\t\ttoggleable: true,\n\t\t\tfields: [\n\t\t\t\t[\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'permalink',\n\t\t\t\t\t\tid: 'permalink',\n\t\t\t\t\t\ttype: 'permalink',\n\t\t\t\t\t},\n\t\t\t\t], [\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'video_embed',\n\t\t\t\t\t\tid: 'video-embed',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Video Embed URL' ),\n\t\t\t\t\t\ttype: 'video_embed',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'audio_embed',\n\t\t\t\t\t\tid: 'audio-embed',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Audio Embed URL' ),\n\t\t\t\t\t\ttype: 'audio_embed',\n\t\t\t\t\t},\n\t\t\t\t], [\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'free_lesson',\n\t\t\t\t\t\tid: 'free-lesson',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Free Lesson' ),\n\t\t\t\t\t\ttip: LLMS.l10n.translate( \"Free lessons can be accessed without enrollment.\" ),\n\t\t\t\t\t\ttype: 'switch',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'require_passing_grade',\n\t\t\t\t\t\tid: 'require-passing-grade',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Require Passing Grade on Quiz' ),\n\t\t\t\t\t\ttip: LLMS.l10n.translate( \"When enabled, students must pass this lesson's quiz before the lesson can be completed.\" ),\n\t\t\t\t\t\ttype: 'switch',\n\t\t\t\t\t\tcondition: function() {\n\t\t\t\t\t\t\treturn ( 'yes' === this.get( 'quiz_enabled' ) );\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'require_assignment_passing_grade',\n\t\t\t\t\t\tid: 'require-assignment-passing-grade',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Require Passing Grade on Assignment' ),\n\t\t\t\t\t\ttip: LLMS.l10n.translate( \"When enabled, students must pass this lesson's assignment before the lesson can be completed.\" ),\n\t\t\t\t\t\ttype: 'switch',\n\t\t\t\t\t\tcondition: function() {\n\t\t\t\t\t\t\treturn ( 'undefined' !== window.llms_builder.assignments && 'yes' === this.get( 'assignment_enabled' ) );\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t], [\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'prerequisite',\n\t\t\t\t\t\tcondition: function() {\n\t\t\t\t\t\t\treturn ( false === this.is_first_in_course() );\n\t\t\t\t\t\t},\n\t\t\t\t\t\tid: 'prerequisite',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Prerequisite' ),\n\t\t\t\t\t\tswitch_attribute: 'has_prerequisite',\n\t\t\t\t\t\ttype: 'switch-select',\n\t\t\t\t\t\toptions: function() {\n\t\t\t\t\t\t\treturn this.get_available_prereq_options();\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t], [\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'drip_method',\n\t\t\t\t\t\tid: 'drip-method',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Drip Method' ),\n\t\t\t\t\t\tswitch_attribute: 'drip_method',\n\t\t\t\t\t\ttype: 'select',\n\t\t\t\t\t\toptions: function() {\n\n\t\t\t\t\t\t\tvar options = [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tkey: '',\n\t\t\t\t\t\t\t\t\tval: LLMS.l10n.translate( 'None' ),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tkey: 'date',\n\t\t\t\t\t\t\t\t\tval: LLMS.l10n.translate( 'On a specific date' ),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tkey: 'enrollment',\n\t\t\t\t\t\t\t\t\tval: LLMS.l10n.translate( '# of days after course enrollment' ),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t];\n\n\t\t\t\t\t\t\tif ( this.get_course().get( 'start_date' ) ) {\n\t\t\t\t\t\t\t\toptions.push( {\n\t\t\t\t\t\t\t\t\tkey: 'start',\n\t\t\t\t\t\t\t\t\tval: LLMS.l10n.translate( '# of days after course start date' ),\n\t\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif ( 'yes' === this.get( 'has_prerequisite' ) ) {\n\t\t\t\t\t\t\t\toptions.push( {\n\t\t\t\t\t\t\t\t\tkey: 'prerequisite',\n\t\t\t\t\t\t\t\t\tval: LLMS.l10n.translate( '# of days after prerequisite lesson completion' ),\n\t\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\treturn options;\n\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'days_before_available',\n\t\t\t\t\t\tcondition: function() {\n\t\t\t\t\t\t\treturn ( -1 !== [ 'enrollment', 'start', 'prerequisite' ].indexOf( this.get( 'drip_method' ) ) );\n\t\t\t\t\t\t},\n\t\t\t\t\t\tid: 'days-before-available',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( '# of days' ),\n\t\t\t\t\t\tmin: 0,\n\t\t\t\t\t\ttype: 'number',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'date_available',\n\t\t\t\t\t\tdate_format: 'Y-m-d',\n\t\t\t\t\t\tcondition: function() {\n\t\t\t\t\t\t\treturn ( 'date' === this.get( 'drip_method' ) );\n\t\t\t\t\t\t},\n\t\t\t\t\t\tid: 'date-available',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Date' ),\n\t\t\t\t\t\ttimepicker: 'false',\n\t\t\t\t\t\ttype: 'datepicker',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'time_available',\n\t\t\t\t\t\tcondition: function() {\n\t\t\t\t\t\t\treturn ( 'date' === this.get( 'drip_method' ) );\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdatepicker: 'false',\n\t\t\t\t\t\tdate_format: 'h:i A',\n\t\t\t\t\t\tid: 'time-available',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Time' ),\n\t\t\t\t\t\ttype: 'datepicker',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t],\n\t\t},\n\n\t};\n\n} );\n\n","/**\n * Lesson Model\n * @since 3.13.0\n * @version 3.19.3\n */\ndefine( 'Models/Lesson',[ 'Models/Quiz', 'Models/_Relationships', 'Models/_Utilities', 'Schemas/Lesson' ], function( Quiz, Relationships, Utilities, LessonSchema ) {\n\n\treturn Backbone.Model.extend( _.defaults( {\n\n\t\t/**\n\t\t * Model relationships\n\t\t * @type {Object}\n\t\t */\n\t\trelationships: {\n\t\t\tparents: {\n\t\t\t\tmodel: 'section',\n\t\t\t\ttype: 'model',\n\t\t\t},\n\t\t\tchildren: {\n\t\t\t\tquiz: {\n\t\t\t\t\tclass: 'Quiz',\n\t\t\t\t\tconditional: function( model ) {\n\t\t\t\t\t\t// if quiz is enabled OR not enabled but we have some quiz data as an obj\n\t\t\t\t\t\treturn ( 'yes' === model.get( 'quiz_enabled' ) || ! _.isEmpty( model.get( 'quiz' ) ) );\n\t\t\t\t\t},\n\t\t\t\t\tmodel: 'llms_quiz',\n\t\t\t\t\ttype: 'model',\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\n\t\t/**\n\t\t * Lesson Settings Schema\n\t\t * @type {Object}\n\t\t */\n\t\tschema: LessonSchema,\n\n\t\t/**\n\t\t * New lesson defaults\n\t\t * @return obj\n\t\t * @since 3.13.0\n\t\t * @version 3.17.1\n\t\t */\n\t\tdefaults: function() {\n\t\t\treturn {\n\t\t\t\tid: _.uniqueId( 'temp_' ),\n\t\t\t\ttitle: LLMS.l10n.translate( 'New Lesson' ),\n\t\t\t\ttype: 'lesson',\n\t\t\t\torder: this.collection ? this.collection.length + 1 : 1,\n\t\t\t\tparent_course: window.llms_builder.course.id,\n\t\t\t\tparent_section: '',\n\n\t\t\t\t// urls\n\t\t\t\tedit_url: '',\n\t\t\t\tview_url: '',\n\n\t\t\t\t// editable fields\n\t\t\t\tcontent: '',\n\t\t\t\taudio_embed: '',\n\t\t\t\thas_prerequisite: 'no',\n\t\t\t\trequire_passing_grade: 'yes',\n\t\t\t\trequire_assignment_passing_grade: 'yes',\n\t\t\t\tvideo_embed: '',\n\t\t\t\tfree_lesson: '',\n\n\t\t\t\t// other fields\n\t\t\t\tassignment: {}, // assignment model/data\n\t\t\t\tassignment_enabled: 'no',\n\n\t\t\t\tquiz: {}, // quiz model/data\n\t\t\t\tquiz_enabled: 'no',\n\n\t\t\t\t_forceSync: false,\n\n\t\t\t};\n\t\t},\n\n\t\t/**\n\t\t * Initializer\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\tthis.init_custom_schema();\n\t\t\tthis.startTracking();\n\t\t\tthis.maybe_init_assignments();\n\t\t\tthis.init_relationships();\n\n\t\t\t// if the lesson ID isn't set on a quiz, set it\n\t\t\tvar quiz = this.get( 'quiz' );\n\t\t\tif ( ! _.isEmpty( quiz ) && ! quiz.get( 'lesson_id' ) ) {\n\t\t\t\tquiz.set( 'lesson_id', this.get( 'id' ) );\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve a reference to the parent course of the lesson\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_course: function() {\n\t\t\treturn this.get_parent().get_parent();\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the translated post type name for the model's type\n\t\t * @param bool plural if true, returns the plural, otherwise returns singular\n\t\t * @return string\n\t\t * @since 3.16.12\n\t\t * @version 3.16.12\n\t\t */\n\t\tget_l10n_type: function( plural ) {\n\n\t\t\tif ( plural ) {\n\t\t\t\treturn LLMS.l10n.translate( 'lessons' );\n\t\t\t}\n\n\t\t\treturn LLMS.l10n.translate( 'lesson' );\n\t\t},\n\n\t\t/**\n\t\t * Override default get_parent to grab from collection if models parent isn't set\n\t\t * @return obj\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tget_parent: function() {\n\n\t\t\tvar rels = this.get_relationships();\n\t\t\tif ( rels.parent && rels.parent.reference ) {\n\t\t\t\treturn rels.parent.reference;\n\t\t\t} else if ( this.collection && this.collection.parent ) {\n\t\t\t\treturn this.collection.parent;\n\t\t\t}\n\t\t\treturn false;\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve an array of prerequisite options available for the current lesson\n\t\t * @return obj\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tget_available_prereq_options: function() {\n\n\t\t\tvar parent_section_index = this.get_parent().collection.indexOf( this.get_parent() ),\n\t\t\t\tlesson_index_in_section = this.collection.indexOf( this ),\n\t\t\t\toptions = [];\n\n\t\t\tthis.get_course().get( 'sections' ).each( function( section, curr_sec_index ) {\n\t\t\t\tif ( curr_sec_index <= parent_section_index ) {\n\t\t\t\t\tvar group = {\n\t\t\t\t\t\t\t/* translators: %1$d = section order number, %2$s = section title */\n\t\t\t\t\t\t\tlabel: LLMS.l10n.replace( 'Section %1$d: %2$s', {\n\t\t\t\t\t\t\t\t'%1$d': section.get( 'order' ),\n\t\t\t\t\t\t\t\t'%2$s': section.get( 'title' )\n\t\t\t\t\t\t\t} ),\n\t\t\t\t\t\t\toptions: [],\n\t\t\t\t\t\t};\n\n\t\t\t\t\tsection.get( 'lessons' ).each( function( lesson, curr_les_index ) {\n\t\t\t\t\t\tif ( curr_sec_index !== parent_section_index || curr_les_index < lesson_index_in_section ) {\n\t\t\t\t\t\t\t/* translators: %1$d = lesson order number, %2$s = lesson title */\n\t\t\t\t\t\t\tgroup.options.push( {\n\t\t\t\t\t\t\t\tkey: lesson.get( 'id' ),\n\t\t\t\t\t\t\t\tval: LLMS.l10n.replace( 'Lesson %1$d: %2$s', {\n\t\t\t\t\t\t\t\t\t'%1$d': lesson.get( 'order' ),\n\t\t\t\t\t\t\t\t\t'%2$s': lesson.get( 'title' )\n\t\t\t\t\t\t\t\t} ),\n\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t}\n\t\t\t\t\t}, this );\n\n\t\t\t\t\toptions.push( group );\n\t\t\t\t}\n\t\t\t}, this );\n\n\t\t\treturn options;\n\n\t\t},\n\n\t\t/**\n\t\t * Add a new quiz to the lesson\n\t\t * @param obj data object of quiz data used to construct a new quiz model\n\t\t * @return obj model for the created quiz\n\t\t * @since 3.16.0\n\t\t * @version 3.19.3\n\t\t */\n\t\tadd_quiz: function( data ) {\n\n\t\t\tdata = data || {};\n\n\t\t\tdata.lesson_id = this.id;\n\t\t\tdata._questions_loaded = true;\n\n\t\t\tif ( ! data.title ) {\n\n\t\t\t\tdata.title = LLMS.l10n.replace( '%1$s Quiz', {\n\t\t\t\t\t'%1$s': this.get( 'title' ),\n\t\t\t\t} );\n\n\t\t\t}\n\n\t\t\tthis.set( 'quiz', data );\n\t\t\tthis.init_relationships();\n\n\t\t\tvar quiz = this.get( 'quiz' );\n\t\t\tthis.set( 'quiz_enabled', 'yes' );\n\n\t\t\treturn quiz;\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if this is the first lesson\n\t\t * @return {Boolean}\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tis_first_in_course: function() {\n\n\t\t\t// if it's not the first item in the section it cant be the first lesson\n\t\t\tif ( this.collection.indexOf( this ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// if it's not the first section it cant' be first lesson\n\t\t\tvar section = this.get_parent();\n\t\t\tif ( section.collection.indexOf( section ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// it's first lesson in first section\n\t\t\treturn true;\n\n\t\t},\n\n\t\t/**\n\t\t * Initialize lesson assignments *if* the assignments addon is availalbe and enabled\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tmaybe_init_assignments: function() {\n\n\t\t\tif ( ! window.llms_builder.assignments ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis.relationships.children.assignment = {\n\t\t\t\tclass: 'Assignment',\n\t\t\t\tconditional: function( model ) {\n\t\t\t\t\t// if assignment is enabled OR not enabled but we have some assignment data as an obj\n\t\t\t\t\treturn ( 'yes' === model.get( 'assignment_enabled' ) || ! _.isEmpty( model.get( 'assignment' ) ) );\n\t\t\t\t},\n\t\t\t\tmodel: 'llms_assignment',\n\t\t\t\ttype: 'model',\n\t\t\t};\n\n\t\t},\n\n\t}, Relationships, Utilities ) );\n\n} );\n\n","/**\n * Lessons Collection\n * @since 3.13.0\n * @version 3.17.0\n */\ndefine( 'Collections/Lessons',[ 'Models/Lesson' ], function( model ) {\n\n\treturn Backbone.Collection.extend( {\n\n\t\t/**\n\t\t * Model for collection items\n\t\t * @type obj\n\t\t */\n\t\tmodel: model,\n\n\t\t/**\n\t\t * Initializer\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\t// reorder called by LessonList view when sortable drops occur\n\t\t\tthis.on( 'reorder', this.on_reorder );\n\n\t\t\t// when a lesson is added or removed, update order\n\t\t\tthis.on( 'add', this.on_reorder );\n\t\t\tthis.on( 'remove', this.on_reorder );\n\n\t\t},\n\n\t\t/**\n\t\t * On lesson reorder callback\n\t\t *\n\t\t * Update the order attr of each lesson to reflect the new lesson order\n\t\t * Validate prerequisite (if set) and unset it if it's no longer a valid prereq\n\t\t *\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\ton_reorder: function() {\n\t\t\tthis.update_order();\n\t\t\tthis.validate_prereqs();\n\t\t},\n\n\t\t/**\n\t\t * Update lesson order attribute of all lessons when lessons are reordered\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tupdate_order: function() {\n\n\t\t\tthis.each( function( lesson ) {\n\t\t\t\tlesson.set( 'order', this.indexOf( lesson ) + 1 );\n\t\t\t}, this );\n\n\t\t},\n\n\n\t\t/**\n\t\t * Validate prerequisite (if set) and unset it if it's no longer a valid prereq\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tvalidate_prereqs: function() {\n\n\t\t\tthis.each( function( lesson ) {\n\n\t\t\t\t// validate prereqs\n\t\t\t\tif ( 'yes' === lesson.get( 'has_prerequisite' ) ) {\n\t\t\t\t\tvar valid = _.pluck( _.flatten( _.pluck( lesson.get_available_prereq_options(), 'options' ) ), 'key' );\n\t\t\t\t\tif ( -1 === valid.indexOf( lesson.get( 'prerequisite' ) * 1 ) ) {\n\t\t\t\t\t\tlesson.set( {\n\t\t\t\t\t\t\tprerequisite: 0,\n\t\t\t\t\t\t\thas_prerequisite: 'no',\n\t\t\t\t\t\t} );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t}, this );\n\n\t\t},\n\n\t} );\n\n} );\n\n","/**\n * Quiz Question Type Collection\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Collections/QuestionTypes',[ 'Models/QuestionType' ], function( model ) {\n\n\treturn Backbone.Collection.extend( {\n\n\t\t/**\n\t\t * Model for collection items\n\t\t * @type obj\n\t\t */\n\t\tmodel: model,\n\n\t\t/**\n\t\t * Initializer\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\tthis.on( 'add', this.comparator );\n\t\t\tthis.on( 'remove', this.comparator );\n\n\t\t},\n\n\t\t/**\n\t\t * Comparator (sorts collection)\n\t\t * @param obj model QuestionType model\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tcomparator: function( model ) {\n\n\t\t\treturn model.get( 'group' ).order;\n\n\t\t},\n\n\t} );\n\n} );\n\n","/**\n * Section Model\n * @since 3.16.0\n * @version 3.16.12\n */\ndefine( 'Models/Section',[ 'Collections/Lessons', 'Models/_Relationships' ], function( Lessons, Relationships ) {\n\n\treturn Backbone.Model.extend( _.defaults( {\n\n\t\trelationships: {\n\t\t\tparent: {\n\t\t\t\tmodel: 'course',\n\t\t\t\ttype: 'model',\n\t\t\t},\n\t\t\tchildren: {\n\t\t\t\tlessons: {\n\t\t\t\t\tclass: 'Lessons',\n\t\t\t\t\tmodel: 'lesson',\n\t\t\t\t\ttype: 'collection',\n\t\t\t\t},\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * New section defaults\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tdefaults: function() {\n\t\t\treturn {\n\t\t\t\tid: _.uniqueId( 'temp_' ),\n\t\t\t\tlessons: [],\n\t\t\t\torder: this.collection ? this.collection.length + 1 : 1,\n\t\t\t\tparent_course: window.llms_builder.course.id,\n\t\t\t\ttitle: LLMS.l10n.translate( 'New Section' ),\n\t\t\t\ttype: 'section',\n\n\t\t\t\t_expanded: false,\n\t\t\t\t_selected: false,\n\t\t\t};\n\t\t},\n\n\t\t/**\n\t\t * Initialize\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\tthis.startTracking();\n\t\t\tthis.init_relationships();\n\n\t\t},\n\n\t\t/**\n\t\t * Add a lesson to the section\n\t\t * @param obj data hash of lesson data (creates new lesson)\n\t\t * or existing lesson as a Backbone.Model\n\t\t * @param obj options has of options\n\t\t * @return obj Backbone.Model of the new/updated lesson\n\t\t * @since 3.16.0\n\t\t * @version 3.16.11\n\t\t */\n\t\tadd_lesson: function( data, options ) {\n\n\t\t\tdata = data || {};\n\t\t\toptions = options || {};\n\n\t\t\tif ( data instanceof Backbone.Model ) {\n\t\t\t\tdata.set( 'parent_section', this.get( 'id' ) );\n\t\t\t\tdata.set_parent( this );\n\t\t\t} else {\n\t\t\t\tdata.parent_section = this.get( 'id' );\n\t\t\t}\n\n\t\t\treturn this.get( 'lessons' ).add( data, options );\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the translated post type name for the model's type\n\t\t * @param bool plural if true, returns the plural, otherwise returns singular\n\t\t * @return string\n\t\t * @since 3.16.12\n\t\t * @version 3.16.12\n\t\t */\n\t\tget_l10n_type: function( plural ) {\n\n\t\t\tif ( plural ) {\n\t\t\t\treturn LLMS.l10n.translate( 'sections' );\n\t\t\t}\n\n\t\t\treturn LLMS.l10n.translate( 'section' );\n\t\t},\n\n\t\t/**\n\t\t * Get next section in the collection\n\t\t * @param bool circular if true handles the collection in a circle\n\t\t * \tif current is the last section, returns the first section\n\t\t * \tif current is the first section, returns the last section\n\t\t * @return obj|false\n\t\t * @since 3.16.11\n\t\t * @version 3.16.11\n\t\t */\n\t\tget_next: function( circular ) {\n\t\t\treturn this._get_sibling( 'next', circular );\n\t\t},\n\n\t\t/**\n\t\t * Get prev section in the collection\n\t\t * @param bool circular if true handles the collection in a circle\n\t\t * \tif current is the last section, returns the first section\n\t\t * \tif current is the first section, returns the last section\n\t\t * @return obj|false\n\t\t * @since 3.16.11\n\t\t * @version 3.16.11\n\t\t */\n\t\tget_prev: function( circular ) {\n\t\t\treturn this._get_sibling( 'prev', circular );\n\t\t},\n\n\t\t/**\n\t\t * Get a sibling section\n\t\t * @param string direction siblings direction [next|prev]\n\t\t * @param bool circular if true handles the collection in a circle\n\t\t * \tif current is the last section, returns the first section\n\t\t * \tif current is the first section, returns the last section\n\t\t * @return obj|false\n\t\t * @since 3.16.11\n\t\t * @version 3.16.11\n\t\t */\n\t\t_get_sibling: function( direction, circular ) {\n\n\t\t\tcircular = ( 'undefined' === circular ) ? true : circular;\n\n\t\t\tvar max = this.collection.size() - 1,\n\t\t\t\tindex = this.collection.indexOf( this ),\n\t\t\t\tsibling_index;\n\n\t\t\tif ( 'next' === direction ) {\n\t\t\t\tsibling_index = index + 1;\n\t\t\t} else if ( 'prev' === direction ) {\n\t\t\t\tsibling_index = index - 1;\n\t\t\t}\n\n\t\t\t// dont retrieve greater than max or less than min\n\t\t\tif ( sibling_index <= max || sibling_index <= 0 ) {\n\n\t\t\t\treturn this.collection.at( sibling_index );\n\n\t\t\t} else if ( circular ) {\n\n\t\t\t\tif ( 'next' === direction ) {\n\t\t\t\t\treturn this.collection.first();\n\t\t\t\t} else if ( 'prev' === direction ) {\n\t\t\t\t\treturn this.collection.last();\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn false;\n\n\t\t},\n\n\t}, Relationships ) );\n\n} );\n\n","/**\n * Sections Collection\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Collections/Sections',[ 'Models/Section' ], function( model ) {\n\n\treturn Backbone.Collection.extend( {\n\n\t\t/**\n\t\t * Model for collection items\n\t\t * @type obj\n\t\t */\n\t\tmodel: model,\n\n\t\t/**\n\t\t * Initialize\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\tvar self = this;\n\n\t\t\t// reorder called by SectionList view when sortable drops occur\n\t\t\tthis.on( 'reorder', this.update_order );\n\n\t\t\t// when a section is added or removed, update order\n\t\t\tthis.on( 'add', this.update_order );\n\t\t\tthis.on( 'remove', this.update_order );\n\n\t\t},\n\n\t\t/**\n\t\t * Update the order attr of each section in the list to reflect the order of the collection\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tupdate_order: function() {\n\n\t\t\tvar self = this;\n\n\t\t\tthis.each( function( section ) {\n\n\t\t\t\tsection.set( 'order', self.indexOf( section ) + 1 );\n\n\t\t\t} );\n\n\t\t},\n\n\t} );\n\n} );\n\n","/**\n * Lessons Collection\n * @since 3.13.0\n * @version 3.16.0\n */\ndefine( 'Collections/loader',[\n\t\t'Collections/Lessons',\n\t\t'Collections/QuestionChoices',\n\t\t'Collections/Questions',\n\t\t'Collections/QuestionTypes',\n\t\t'Collections/Sections'\n\t], function(\n\t\tLessons,\n\t\tQuestionChoices,\n\t\tQuestions,\n\t\tQuestionTypes,\n\t\tSections\n\t) {\n\n\treturn {\n\t\tLessons: Lessons,\n\t\tQuestionChoices: QuestionChoices,\n\t\tQuestions: Questions,\n\t\tQuestionTypes: QuestionTypes,\n\t\tSections: Sections,\n\t};\n\n} );\n\n","/**\n * Abstract LifterLMS Model\n * @since 3.17.0\n * @version 3.17.0\n */\ndefine( 'Models/Abstract',[ 'Models/_Relationships', 'Models/_Utilities' ], function( Relationships, Utilities ) {\n\n\treturn Backbone.Model.extend( _.defaults( {}, Relationships, Utilities ) );\n\n} );\n\n","/**\n * Course Model\n * @since 3.16.0\n * @version 3.16.11\n */\ndefine( 'Models/Course',[ 'Collections/Sections', 'Models/_Relationships', 'Models/_Utilities' ], function( Sections, Relationships, Utilities ) {\n\n\treturn Backbone.Model.extend( _.defaults( {\n\n\t\trelationships: {\n\t\t\tchildren: {\n\t\t\t\tsections: {\n\t\t\t\t\tclass: 'Sections',\n\t\t\t\t\tmodel: 'section',\n\t\t\t\t\ttype: 'collection',\n\t\t\t\t},\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * New Course Defaults\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tdefaults: function() {\n\t\t\treturn {\n\t\t\t\tedit_url: '',\n\t\t\t\tsections: [],\n\t\t\t\ttitle: 'New Course',\n\t\t\t\ttype: 'course',\n\t\t\t\tview_url: '',\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Init\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\tthis.startTracking();\n\t\t\tthis.init_relationships();\n\n\t\t\t// Sidebar \"New Section\" button broadcast\n\t\t\tBackbone.pubSub.on( 'add-new-section', this.add_section, this );\n\n\t\t\t// Sidebar \"New Lesson\" button broadcast\n\t\t\tBackbone.pubSub.on( 'add-new-lesson', this.add_lesson, this );\n\n\t\t\tBackbone.pubSub.on( 'lesson-search-select', this.add_existing_lesson, this );\n\n\t\t},\n\n\t\t/**\n\t\t * Add an existing lesson to the course\n\t\t * Duplicate a lesson from this or another course or attach an orphaned lesson\n\t\t * @param obj lesson lesson data obj\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.11\n\t\t */\n\t\tadd_existing_lesson: function( lesson ) {\n\n\t\t\tvar data = lesson.data;\n\n\t\t\tif ( 'clone' === lesson.action ) {\n\n\t\t\t\tdelete data.id;\n\t\t\t\tif ( data.quiz ) {\n\t\t\t\t\tdelete data.quiz;\n\t\t\t\t\tdata.quiz_enabled = 'no';\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\tdata._forceSync = true;\n\n\t\t\t}\n\n\t\t\tdelete data.order;\n\t\t\tdelete data.parent_course;\n\t\t\tdelete data.parent_section;\n\n\t\t\tthis.add_lesson( data );\n\n\t\t},\n\n\t\t/**\n\t\t * Add a new lesson to the course\n\t\t * @param obj data lesson data\n\t\t * @return obj Backbone.Model of the lesson\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tadd_lesson: function( data ) {\n\n\t\t\tdata = data || {};\n\t\t\tvar options = {},\n\t\t\t\tsection;\n\n\t\t\tif ( ! data.parent_section ) {\n\t\t\t\tsection = this.get_selected_section();\n\t\t\t\tif ( ! section ) {\n\t\t\t\t\tsection = this.get( 'sections' ).last();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tsection = this.get( 'sections' ).get( data.parent_section );\n\t\t\t}\n\n\t\t\tdata._selected = true;\n\n\t\t\tdata.parent_course = this.get( 'id' );\n\n\t\t\tvar lesson = section.add_lesson( data, options );\n\t\t\tBackbone.pubSub.trigger( 'new-lesson-added', lesson );\n\n\t\t\t// expand the section\n\t\t\tsection.set( '_expanded', true );\n\n\t\t\treturn lesson;\n\n\t\t},\n\n\t\t/**\n\t\t * Add a new section to the course\n\t\t * @param obj data section data\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tadd_section: function( data ) {\n\n\t\t\tdata = data || {};\n\t\t\tvar sections = this.get( 'sections' ),\n\t\t\t\toptions = {},\n\t\t\t\tselected = this.get_selected_section();\n\n\t\t\t// if a section is selected, add the new section after the currently selected one\n\t\t\tif ( selected ) {\n\t\t\t\toptions.at = sections.indexOf( selected ) + 1;\n\t\t\t}\n\n\t\t\tsections.add( data, options );\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the currently selected section in the course\n\t\t * @return obj|undefined\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_selected_section: function() {\n\n\t\t\treturn this.get( 'sections' ).find( function( model ) {\n\t\t\t\treturn model.get( '_selected' );\n\t\t\t} );\n\n\t\t},\n\n\t}, Relationships, Utilities ) );\n\n} );\n\n","/**\n * Load all models\n * @return obj\n * @since 3.16.0\n * @version 3.17.0\n */\ndefine( 'Models/loader',[\n\t\t'Models/Abstract',\n\t\t'Models/Course',\n\t\t'Models/Image',\n\t\t'Models/Lesson',\n\t\t'Models/Question',\n\t\t'Models/QuestionChoice',\n\t\t'Models/QuestionType',\n\t\t'Models/Quiz',\n\t\t'Models/Section'\n\t],\n\tfunction(\n\t\tAbstract,\n\t\tCourse,\n\t\tImage,\n\t\tLesson,\n\t\tQuestion,\n\t\tQuestionChoice,\n\t\tQuestionType,\n\t\tQuiz,\n\t\tSection\n\t) {\n\n\treturn {\n\t\tAbstract: Abstract,\n\t\tCourse: Course,\n\t\tImage: Image,\n\t\tLesson: Lesson,\n\t\tQuestion: Question,\n\t\tQuestionChoice: QuestionChoice,\n\t\tQuestionType: QuestionType,\n\t\tQuiz: Quiz,\n\t\tSection: Section,\n\t};\n\n} );\n\n","/**\n * Detachable model\n * @type {Object}\n * @since 3.16.12\n * @version 3.16.12\n */\ndefine( 'Views/_Detachable',[], function() {\n\n\treturn {\n\n\t\t/**\n\t\t * DOM Events\n\t\t * @type {Object}\n\t\t * @since 3.16.12\n\t\t * @version 3.16.12\n\t\t */\n\t\tevents: {\n\t\t\t'click a[href=\"#llms-detach-model\"]': 'detach_model',\n\t\t},\n\n\t\t/**\n\t\t * Detaches a model from it's parent (doesn't delete)\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.16.12\n\t\t * @version 3.16.12\n\t\t */\n\t\tdetach_model: function( event ) {\n\n\t\t\tif ( event ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tevent.stopPropagation();\n\t\t\t}\n\n\t\t\tvar msg = LLMS.l10n.replace( 'Are you sure you want to detach this %s?', {\n\t\t\t\t'%s': this.model.get_l10n_type(),\n\t\t\t} );\n\n\t\t\tif ( window.confirm( msg ) ) {\n\n\t\t\t\tif ( this.model.collection ) {\n\t\t\t\t\tthis.model.collection.remove( this.model );\n\t\t\t\t}\n\n\t\t\t\t// publish global event\n\t\t\t\tBackbone.pubSub.trigger( 'model-detached', this.model );\n\n\t\t\t\t// trigger local event so extending views can run other actions where necessary\n\t\t\t\tthis.trigger( 'model-trashed', this.model );\n\n\t\t\t}\n\n\t\t},\n\n\t}\n\n} );\n\n","/**\n * Handles UX and Events for inline editing of views\n * Use with a Model's View\n * Allows editing model.title field via .llms-editable-title elements\n * @type {Object}\n * @since 3.16.0\n * @version 3.17.8\n */\ndefine( 'Views/_Editable',[], function() {\n\n\treturn {\n\n\t\tmedia_lib: null,\n\n\t\t/**\n\t\t * DOM Events\n\t\t * @type {Object}\n\t\t * @since 3.16.0\n\t\t * @version 3.17.8\n\t\t */\n\t\tevents: {\n\t\t\t'click .llms-add-image': 'open_media_lib',\n\t\t\t'click a[href=\"#llms-edit-slug\"]': 'make_slug_editable',\n\t\t\t'click a[href=\"#llms-remove-image\"]': 'remove_image',\n\t\t\t'change .llms-editable-select select': 'on_select',\n\t\t\t'change .llms-switch input[type=\"checkbox\"]': 'toggle_switch',\n\t\t\t'change .llms-editable-radio input': 'on_radio_select',\n\t\t\t'focusin .llms-input': 'on_focus',\n\t\t\t'focusout .llms-input': 'on_blur',\n\t\t\t'keydown .llms-input': 'on_keydown',\n\t\t\t'input .llms-input[type=\"number\"]': 'on_blur',\n\t\t\t'paste .llms-input[data-formatting]': 'on_paste',\n\t\t},\n\n\t\t/**\n\t\t * Retrieve a list of allowed tags for a given element\n\t\t * @param obj $el jQuery selector for the element\n\t\t * @return array\n\t\t * @since 3.16.0\n\t\t * @version 3.17.8\n\t\t */\n\t\tget_allowed_tags: function( $el ) {\n\n\t\t\tif ( $el.attr( 'data-formatting' ) ) {\n\t\t\t\treturn _.map( $el.attr( 'data-formatting' ).split( ',' ), function( tag ) {\n\t\t\t\t\treturn tag.trim();\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\treturn [ 'b', 'i', 'u', 'strong', 'em' ];\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the content of an element\n\t\t * @param obj $el jQuery object of the element\n\t\t * @return string\n\t\t * @since 3.16.0\n\t\t * @version 3.17.8\n\t\t */\n\t\tget_content: function( $el ) {\n\n\t\t\tif ( 'INPUT' === $el[0].tagName ) {\n\t\t\t\treturn $el.val();\n\t\t\t}\n\n\t\t\tif ( ! $el.attr( 'data-formatting' ) && ! $el.hasClass( 'ql-editor' ) ) {\n\t\t\t\treturn $el.text();\n\t\t\t}\n\n\t\t\treturn _.stripFormatting( $el.html(), this.get_allowed_tags( $el ) );\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if changes have been made to the element\n\t\t * @param {[obj]} event js event object\n\t\t * @return {Boolean} true when changes have been made, false otherwise\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\thas_changed: function( event ) {\n\t\t\tvar $el = $( event.target );\n\t\t\treturn ( $el.attr( 'data-original-content' ) !== this.get_content( $el ) );\n\t\t},\n\n\t\t/**\n\t\t * Ensure that new content is at least 1 character long\n\t\t * @param obj event js event object\n\t\t * @return boolean\n\t\t * @since 3.16.0\n\t\t * @version 3.17.2\n\t\t */\n\t\tis_valid: function( event ) {\n\n\t\t\tvar self = this,\n\t\t\t\t$el = $( event.target ),\n\t\t\t\tcontent = this.get_content( $el ),\n\t\t\t\ttype = $el.attr( 'data-type' );\n\n\t\t\tif ( ( $el.attr( 'required' ) || $el.attr( 'data-required' ) ) && content.length < 1 ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tif ( 'url' === type || 'video' === type ) {\n\t\t\t\tif ( ! this._validate_url( this.get_content( $el ) ) ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t} else if ( 'permalink' === type ) {\n\n\t\t\t\tLLMS.Ajax.call( {\n\t\t\t\t\tdata: {\n\t\t\t\t\t\taction: 'llms_builder',\n\t\t\t\t\t\taction_type: 'get_permalink',\n\t\t\t\t\t\tcourse_id: window.llms_builder.CourseModel.get( 'id' ),\n\t\t\t\t\t\tid: self.model.get( 'id' ),\n\t\t\t\t\t\ttitle: self.model.get( 'title' ),\n\t\t\t\t\t\tslug: content,\n\t\t\t\t\t},\n\t\t\t\t\tbeforeSend: function() {\n\t\t\t\t\t\tLLMS.Spinner.start( $el.closest( '.llms-editable-toggle-group' ), 'small' );\n\t\t\t\t\t},\n\t\t\t\t\tsuccess: function( r ) {\n\n\t\t\t\t\t\tif ( r.permalink && r.slug ) {\n\t\t\t\t\t\t\tself.model.set( 'permalink', r.permalink );\n\t\t\t\t\t\t\tself.model.set( 'name', r.slug );\n\t\t\t\t\t\t\tself.render();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\t\t\t\t} );\n\n\t\t\t}\n\n\t\t\treturn true;\n\n\t\t},\n\n\t\t/**\n\t\t * Initialize datepicker elements\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tinit_datepickers: function() {\n\n\t\t\tthis.$el.find( '.llms-editable-date input' ).each( function() {\n\n\t\t\t\t$( this ).datetimepicker( {\n\t\t\t\t\tformat: $( this ).attr( 'data-date-format' ) || 'Y-m-d h:i A',\n\t\t\t\t\tdatepicker: ( undefined === $( this ).attr( 'data-date-datepicker' ) ) ? true : ( 'true' == $( this ).attr( 'data-date-datepicker' ) ),\n\t\t\t\t\ttimepicker: ( undefined === $( this ).attr( 'data-date-timepicker' ) ) ? true : ( 'true' == $( this ).attr( 'data-date-timepicker' ) ),\n\t\t\t\t\tonClose: function( current_time, $input ) {\n\t\t\t\t\t\t$input.blur();\n\t\t\t\t\t}\n\t\t\t\t} );\n\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * Initialize elements that allow inline formatting\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinit_formatting_els: function() {\n\n\t\t\tvar self = this;\n\n\t\t\tthis.$el.find( '.llms-input-formatting[data-formatting]' ).each( function() {\n\n\t\t\t\tvar formatting = $( this ).attr( 'data-formatting' ).split( ',' ),\n\t\t\t\t\tattr = $( this ).attr( 'data-attribute' );\n\n\t\t\t\tvar ed = new Quill( this, {\n\t\t\t\t\tmodules: {\n\t\t\t\t\t\ttoolbar: [ formatting ],\n\t\t\t\t\t\tkeyboard: {\n\t\t\t\t\t\t\tbindings: {\n\t\t\t\t\t\t\t\ttab: {\n\t\t\t\t\t\t\t\t\tkey: 9,\n\t\t\t\t\t\t\t\t\thandler: function( range, context ) {\n\t\t\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t13: {\n\t\t\t\t\t\t\t\t\tkey: 13,\n\t\t\t\t\t\t\t\t\thandler: function( range, context ) {\n\t\t\t\t\t\t\t\t\t\ted.root.blur();\n\t\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tplaceholder: $( this ).attr( 'data-placeholder' ),\n\t\t\t\t\ttheme: 'bubble',\n\t\t\t\t} );\n\n\t\t\t\ted.on( 'text-change', function( delta, oldDelta, source ) {\n\t\t\t\t\tself.model.set( attr, self.get_content( $( ed.root ) ) );\n\t\t\t\t} );\n\n\t\t\t\tBackbone.pubSub.trigger( 'formatting-ed-init', ed, $( this ), self );\n\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * Initialize editable select elements\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinit_selects: function() {\n\n\t\t\tthis.$el.find( '.llms-editable-select select' ).llmsSelect2( {\n\t\t\t\twidth: '100%',\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * Blur/focusout function for .llms-editable-title elements\n\t\t * Automatically saves changes if changes have been made\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.6\n\t\t */\n\t\ton_blur: function( event ) {\n\n\t\t\tevent.stopPropagation();\n\n\t\t\tthis.model.set( '_has_focus', false, { silent: true } );\n\n\t\t\tvar self = this,\n\t\t\t\t$el = $( event.target ),\n\t\t\t\tchanged = this.has_changed( event );\n\n\t\t\tif ( changed ) {\n\n\t\t\t\tif ( ! self.is_valid( event ) ) {\n\t\t\t\t\tself.revert_edits( event );\n\t\t\t\t} else {\n\t\t\t\t\tthis.save_edits( event );\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Focus event for editable inputs\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.16.6\n\t\t * @version 3.16.6\n\t\t */\n\t\ton_focus: function( event ) {\n\n\t\t\tevent.stopPropagation();\n\t\t\tthis.model.set( '_has_focus', true, { silent: true } );\n\n\t\t},\n\n\t\t/**\n\t\t * Handle content pasted into contenteditable fields\n\t\t * This will ensure that HTML from RTF editors isn't pasted into the dom\n\t\t * @param obj event js event obj\n\t\t * @return void\n\t\t * @since 3.17.8\n\t\t * @version 3.17.8\n\t\t */\n\t\ton_paste: function( event ) {\n\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\n\t\t\tvar text = ( event.originalEvent || event ).clipboardData.getData( 'text/plain' );\n\t\t\twindow.document.execCommand( 'insertText', false, text );\n\n\t\t},\n\n\t\t/**\n\t\t * Change event for selectables\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\ton_select: function( event ) {\n\n\t\t\tvar $el = $( event.target ),\n\t\t\t\tmulti = ( $el.attr( 'multiple' ) ),\n\t\t\t\tattr = $el.attr( 'name' ),\n\t\t\t\t$selected = $el.find( 'option:selected' ),\n\t\t\t\tval;\n\n\t\t\tif ( multi ) {\n\t\t\t\tval = [];\n\t\t\t\tval = $selected.map( function() {\n\t\t\t\t\treturn this.value;\n\t\t\t\t} ).get();\n\t\t\t} else {\n\t\t\t\tval = $selected[0].value;\n\t\t\t}\n\n\t\t\tthis.model.set( attr, val );\n\n\t\t},\n\n\t\t/**\n\t\t * Change event for radio element groups\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.17.6\n\t\t * @version 3.17.6\n\t\t */\n\t\ton_radio_select: function( event ) {\n\n\t\t\tvar $el = $( event.target ),\n\t\t\t\tattr = $el.attr( 'name' ),\n\t\t\t\tval = $el.val();\n\n\t\t\tthis.model.set( attr, val );\n\n\t\t},\n\n\t\t/**\n\t\t * Keydown function for .llms-editable-title elements\n\t\t * Blurs\n\t\t * @param {obj} event js event object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.17.8\n\t\t */\n\t\ton_keydown: function( event ) {\n\n\t\t\tevent.stopPropagation();\n\n\t\t\tvar self = this,\n\t\t\t\tkey = event.which || event.keyCode,\n\t\t\t\tshift = event.shiftKey;\n\t\t\t\t// ctrl = event.metaKey || event.ctrlKey;\n\n\t\t\tswitch ( key ) {\n\n\t\t\t\tcase 13: // enter\n\t\t\t\t\t// shift + enter should add a return\n\t\t\t\t\tif ( ! shift ) {\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\tevent.target.blur();\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t\tcase 27: // escape\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tthis.revert_edits( event );\n\t\t\t\t\tevent.target.blur();\n\t\t\t\tbreak;\n\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Open the WP media lib\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.6\n\t\t */\n\t\topen_media_lib: function( event ) {\n\n\t\t\tevent.stopPropagation();\n\n\t\t\tvar self = this,\n\t\t\t\t$el = $( event.currentTarget );\n\n\t\t\tif ( self.media_lib ) {\n\n\t\t\t\tself.media_lib.uploader.uploader.param( 'post_id' );\n\n\t\t\t} else {\n\n\t\t\t\tself.media_lib = wp.media.frames.file_frame = wp.media( {\n\t\t\t\t\ttitle: LLMS.l10n.translate( 'Select an image' ),\n\t\t\t\t\tbutton: {\n\t\t\t\t\t\ttext: LLMS.l10n.translate( 'Use this image' ),\n\t\t\t\t\t},\n\t\t\t\t\tmultiple: false\t// Set to true to allow multiple files to be selected\n\t\t\t\t} );\n\n\t\t\t\tself.media_lib.on( 'select', function() {\n\n\t\t\t\t\tvar size = $el.attr( 'data-image-size' ),\n\t\t\t\t\t\tattachment = self.media_lib.state().get( 'selection' ).first().toJSON(),\n\t\t\t\t\t\timage = self.model.get( $el.attr( 'data-attribute' ) ),\n\t\t\t\t\t\turl;\n\n\t\t\t\t\tif ( size && attachment.sizes[ size ] ) {\n\t\t\t\t\t\turl = attachment.sizes[ size ].url;\n\t\t\t\t\t} else {\n\t\t\t\t\t\turl = attachment.url;\n\t\t\t\t\t}\n\n\t\t\t\t\timage.set( {\n\t\t\t\t\t\tid: attachment.id,\n\t\t\t\t\t\tsrc: url,\n\t\t\t\t\t} );\n\n\t\t\t\t} );\n\n\t\t\t}\n\n\t\t\tself.media_lib.open();\n\n\n\t\t},\n\n\t\t/**\n\t\t * Click event to remove an image\n\t\t * @param obj event js event obj\n\t\t * @return voids\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tremove_image: function( event ) {\n\n\t\t\tevent.preventDefault();\n\n\t\t\tthis.model.get( $( event.currentTarget ).attr( 'data-attribute' ) ).set( {\n\t\t\t\tid: '',\n\t\t\t\tsrc: '',\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * Helper to undo changes\n\t\t * Bound to \"escape\" key via on_keydwon function\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trevert_edits: function( event ) {\n\t\t\tvar $el = $( event.target ),\n\t\t\t\tval = $el.attr( 'data-original-content' );\n\t\t\t$el.html( val );\n\t\t},\n\n\t\t/**\n\t\t * Sync chages to the model and DB\n\t\t * @param {obj} event js event object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tsave_edits: function( event ) {\n\n\t\t\tvar $el = $( event.target ),\n\t\t\t\tval = this.get_content( $el );\n\n\t\t\tthis.model.set( $el.attr( 'data-attribute' ), val );\n\n\t\t},\n\n\t\t/**\n\t\t * Change event for a switch element\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.17.0\n\t\t */\n\t\ttoggle_switch: function( event ) {\n\n\t\t\tevent.stopPropagation();\n\t\t\tvar $el = $( event.target ),\n\t\t\t\tattr = $el.attr( 'name' ),\n\t\t\t\trerender = $el.attr( 'data-rerender' ),\n\t\t\t\tval;\n\n\t\t\tif ( $el.is( ':checked' ) ) {\n\t\t\t\tval = $el.attr( 'data-on' ) ? $el.attr( 'data-on' ) : 'yes';\n\t\t\t} else {\n\t\t\t\tval = $el.attr( 'data-off' ) ? $el.attr( 'data-off' ) : 'no';\n\t\t\t}\n\n\t\t\tif ( -1 !== attr.indexOf( '.' ) ) {\n\n\t\t\t\tvar split = attr.split( '.' );\n\n\t\t\t\tif ( 'parent' === split[0] ) {\n\t\t\t\t\tthis.model.get_parent().set( split[1], val );\n\t\t\t\t} else {\n\t\t\t\t\tthis.model.get( split[0] ).set( split[1], val );\n\t\t\t\t}\n\n\n\t\t\t} else {\n\n\t\t\t\tthis.model.set( attr, val );\n\n\t\t\t}\n\n\t\t\tthis.trigger( attr.replace( '.', '-' ) + '_toggle', val );\n\n\t\t\tif ( ! rerender || 'yes' === rerender ) {\n\t\t\t\tvar self = this;\n\t\t\t\tsetTimeout( function() {\n\t\t\t\t\tself.render();\n\t\t\t\t}, 100 );\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Initializes a WP Editor on a textarea\n\t\t * @param string id CSS ID of the editor (don't include #)\n\t\t * @param obj settings optional object of settings to pass to wp.editor.initialize()\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinit_editor: function( id, settings ) {\n\n\t\t\tsettings = settings || {};\n\n\t\t\twp.editor.remove( id );\n\n\t\t\twp.editor.initialize( id, $.extend( true, wp.editor.getDefaultSettings(), {\n\t\t\t\tmediaButtons: true,\n\t\t\t\ttinymce: {\n\t\t\t\t\ttoolbar1: 'bold,italic,strikethrough,bullist,numlist,blockquote,hr,alignleft,aligncenter,alignright,link,unlink,wp_adv',\n\t\t\t\t\ttoolbar2: 'formatselect,underline,alignjustify,forecolor,pastetext,removeformat,charmap,outdent,indent,undo,redo,wp_help',\n\t\t\t\t\tsetup: _.bind( this.on_editor_ready, this ),\n\t\t\t\t}\n\t\t\t}, settings ) );\n\n\t\t},\n\n\t\t/**\n\t\t * Setup a permalink editor to allow editing of a permalink\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.16.6\n\t\t * @version 3.16.6\n\t\t */\n\t\tmake_slug_editable: function( event ) {\n\n\t\t\tvar self = this,\n\t\t\t\t$btn = $( event.currentTarget ),\n\t\t\t\t$link = $btn.prevAll( 'a' ),\n\t\t\t\t$input = $btn.prev( 'input.permalink' ),\n\t\t\t\tfull_url = $link.attr( 'href' ),\n\t\t\t\tslug = $input.val(),\n\t\t\t\tshort_url = full_url.replace( slug, '' );\n\n\t\t\t// hide the button\n\t\t\t$btn.hide();\n\n\t\t\t// make the link not clickable\n\t\t\t$link.css( {\n\t\t\t\tcolor: '#999',\n\t\t\t\t'pointer-events': 'none',\n\t\t\t\t'text-decoration': 'none',\n\t\t\t} );\n\n\t\t\t// remove the current slug & trailing slash from the URL\n\t\t\t$link.text( short_url.substring( 0, short_url.length - 1 ) );\n\n\t\t\t// focus in on the field\n\t\t\t$input.show().focus();\n\n\t\t},\n\n\t\t/**\n\t\t * Callback function called after initialization of an editor\n\t\t * Updates UI if a label is present\n\t\t * Binds a change event to ensure editor changes are saved to the model\n\t\t * @param obj editor wp.editor instance\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.17.1\n\t\t */\n\t\ton_editor_ready: function( editor ) {\n\n\t\t\tvar self = this,\n\t\t\t\t$ed = $( '#' + editor.id ),\n\t\t\t\t$parent = $ed.closest( '.llms-editable-editor' ),\n\t\t\t\t$label = $parent.find( '.llms-label' ),\n\t\t\t\tprop = $ed.attr( 'data-attribute' )\n\n\t\t\tif ( $label.length ) {\n\t\t\t\t$label.prependTo( $parent.find( '.wp-editor-tools' ) );\n\t\t\t}\n\n\t\t\t// save changes to the model via Visual ed\n\t\t\teditor.on( 'change', function( event ) {\n\t\t\t\tself.model.set( prop, wp.editor.getContent( editor.id ) );\n\t\t\t} );\n\n\t\t\t// save changes via Text ed\n\t\t\t$ed.on( 'input', function( event ) {\n\t\t\t\tself.model.set( prop, $ed.val() );\n\t\t\t} );\n\n\t\t\t// trigger an input on the Text ed when quicktags buttons are clicked\n\t\t\t$parent.on( 'click', '.quicktags-toolbar .ed_button', function() {\n\t\t\t\tsetTimeout( function() {\n\t\t\t\t\t$ed.trigger( 'input' );\n\t\t\t\t}, 10 );\n\t\t\t} );\n\n\t\t},\n\n\t\t_validate_url: function( str ) {\n\n\t\t\tvar a = document.createElement( 'a' );\n\t\t\ta.href = str;\n\t\t\treturn ( a.host && a.host !== window.location.host );\n\n\t\t}\n\n\t};\n\n} );\n\n","/**\n * _receive override for Backbone.CollectionView core\n * enables connection with jQuery UI draggable buttons\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Views/_Receivable',[], function() {\n\n\treturn {\n\n\t\t/**\n\t\t * Overloads the function from Backbone.CollectionView core because it doesn't properly handle\n\t\t * receieves from a jQuery UI draggable object\n\t\t * @param obj event js event object\n\t\t * @param obj ui jQuery UI object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\t_receive : function( event, ui ) {\n\n\t\t\t// came from sidebar drag\n\t\t\tif ( ui.sender.hasClass( 'ui-draggable' ) ) {\n\t\t\t\tvar index = this._getContainerEl().children().index( ui.helper );\n\t\t\t\tui.helper.remove(); // remove the helper\n\t\t\t\tthis.collection.add( {}, { at: index } );\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar senderListEl = ui.sender;\n\t\t\tvar senderCollectionListView = senderListEl.data( 'view' );\n\t\t\tif( ! senderCollectionListView || ! senderCollectionListView.collection ) return;\n\n\t\t\tvar newIndex = this._getContainerEl().children().index( ui.item );\n\t\t\tvar modelReceived = senderCollectionListView.collection.get( ui.item.attr( 'data-model-cid' ) );\n\t\t\tsenderCollectionListView.collection.remove( modelReceived );\n\t\t\tthis.collection.add( modelReceived, { at : newIndex } );\n\t\t\tmodelReceived.collection = this.collection; // otherwise will not get properly set, since modelReceived.collection might already have a value.\n\t\t\tthis.setSelectedModel( modelReceived );\n\t\t},\n\n\t}\n\n} );\n\n\n","/**\n * Shiftable view mixin function\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Views/_Shiftable',[], function() {\n\n\treturn {\n\n\t\t/**\n\t\t * Conditionally hide action buttons based on section position in collection\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tmaybe_hide_shiftable_buttons: function() {\n\n\t\t\tif ( ! this.model.collection ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar type = this.model.get( 'type' );\n\n\t\t\tif ( this.model.collection.first() === this.model ) {\n\t\t\t\tthis.$el.find( '.shift-up--' + type ).hide();\n\t\t\t} else if ( this.model.collection.last() === this.model ) {\n\t\t\t\tthis.$el.find( '.shift-down--' + type ).hide();\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Move an item in a collection from one position to another\n\t\t * @param int old_index current (old) index within the collection\n\t\t * @param int new_index desired (new) index within the collection\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tshift: function( old_index, new_index ) {\n\n\t\t\tvar collection = this.model.collection;\n\n\t\t\tcollection.remove( this.model );\n\t\t\tcollection.add( this.model, { at: new_index } );\n\t\t\tcollection.trigger( 'reorder' );\n\n\t\t},\n\n\t\t/**\n\t\t * Move an item down the tree one position\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tshift_down: function( e ) {\n\n\t\t\te.preventDefault();\n\t\t\tvar index = this.model.collection.indexOf( this.model );\n\t\t\tthis.shift( index, index + 1 );\n\n\t\t},\n\n\t\t/**\n\t\t * Move an item up the tree one position\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tshift_up: function( e ) {\n\n\t\t\te.preventDefault();\n\t\t\tvar index = this.model.collection.indexOf( this.model );\n\t\t\tthis.shift( index, index - 1 );\n\n\t\t},\n\n\t};\n\n} );\n\n","/**\n * Subview utility mixin\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Views/_Subview',[], function() {\n\n\treturn {\n\n\t\tsubscriptions: {},\n\n\t\t/**\n\t\t * Name of the current subview\n\t\t * @type {String}\n\t\t */\n\t\tstate: '',\n\n\t\t/**\n\t\t * Object of subview data\n\t\t * @type {Object}\n\t\t */\n\t\tviews: {},\n\n\t\t/**\n\t\t * Retrieve a subview by name from this.views\n\t\t * @param string name name of the subview\n\t\t * @return obl|false\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_subview: function( name ) {\n\n\t\t\tif ( this.views[ name ] ) {\n\t\t\t\treturn this.views[ name ];\n\t\t\t}\n\n\t\t\treturn false;\n\n\t\t},\n\n\t\tevents_subscribe: function( events ) {\n\n\t\t\t_.each( events, function( func, event ) {\n\n\t\t\t\tthis.subscriptions[ event ] = func;\n\t\t\t\tBackbone.pubSub.on( event, func, this );\n\n\t\t\t}, this );\n\n\t\t},\n\n\t\tevents_unsubscribe: function() {\n\n\t\t\t_.each( this.subscriptions, function( func, event ) {\n\n\t\t\t\tBackbone.pubSub.off( event, func, this );\n\t\t\t\tdelete this.subscriptions[ event ];\n\n\t\t\t}, this );\n\n\t\t},\n\n\t\t/**\n\t\t * Remove a single subview (and all it's subviews) by name\n\t\t * @param string name name of the subview\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tremove_subview: function( name ) {\n\n\t\t\tvar view = this.get_subview( name );\n\n\t\t\tif ( ! view ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( view.instance ) {\n\n\t\t\t\t// remove the subviews if the view has subviews\n\t\t\t\tif ( ! _.isEmpty( view.instance.views ) ) {\n\t\t\t\t\tview.instance.events_unsubscribe();\n\t\t\t\t\tview.instance.remove_subviews();\n\t\t\t\t}\n\n\t\t\t\tview.instance.off();\n\t\t\t\tview.instance.off( null, null, null );\n\t\t\t\tview.instance.remove();\n\t\t\t\tview.instance.undelegateEvents();\n\n\t\t\t\t// _.each( view.instance, function( val, key ) {\n\t\t\t\t// \tdelete view.instance[ key ];\n\t\t\t\t// } );\n\n\t\t\t\tview.instance = null;\n\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Remove all subviews (and all the subviews of those subviews)\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tremove_subviews: function() {\n\n\t\t\t_.each( this.views, function( data, name ) {\n\n\t\t\t\tthis.remove_subview( name );\n\n\t\t\t}, this );\n\n\t\t},\n\n\t\t/**\n\t\t * Render subviews based on current state\n\t\t * @param obj view_data additional data to pass to the subviews\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender_subviews: function( view_data ) {\n\n\t\t\tview_data = view_data || {};\n\n\t\t\t_.each( this.views, function( data, name ) {\n\n\t\t\t\tif ( this.state === data.state ) {\n\n\t\t\t\t\tthis.render_subview( name, view_data );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tthis.remove_subview( name );\n\n\t\t\t\t}\n\n\t\t\t}, this );\n\n\t\t},\n\n\t\t/**\n\t\t * Render a single subview by name\n\t\t * @param string name name of the subview\n\t\t * @param obj view_data additional data to pass to the subview initializer\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender_subview: function( name, view_data ) {\n\n\t\t\tvar view = this.get_subview( name );\n\n\t\t\tif ( ! view ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis.remove_subview( name );\n\n\t\t\tif ( ! view.instance ) {\n\t\t\t\tview.instance = new view.class( view_data );\n\t\t\t}\n\n\t\t\tview.instance.render();\n\n\t\t},\n\n\t\t/**\n\t\t * Set the current subview\n\t\t * Must call render after!\n\t\t * @param string state name of the state [builder|editor]\n\t\t * @return obj this for chaining\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tset_state: function ( state ) {\n\n\t\t\tthis.state = state;\n\t\t\treturn this;\n\n\t\t},\n\n\t}\n\n} );\n\n","/**\n * Trashable model\n * @type {Object}\n * @since 3.16.12\n * @version 3.16.12\n */\ndefine( 'Views/_Trashable',[], function() {\n\n\treturn {\n\n\t\t/**\n\t\t * DOM Events\n\t\t * @type {Object}\n\t\t * @since 3.16.12\n\t\t * @version 3.16.12\n\t\t */\n\t\tevents: {\n\t\t\t'click a[href=\"#llms-trash-model\"]': 'trash_model',\n\t\t},\n\n\t\t/**\n\t\t * Remove a model from it's parent and delete it\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.16.12\n\t\t * @version 3.16.12\n\t\t */\n\t\ttrash_model: function( event ) {\n\n\t\t\tif ( event ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tevent.stopPropagation();\n\t\t\t}\n\n\t\t\tvar msg = LLMS.l10n.replace( 'Are you sure you want to move this %s to the trash?', {\n\t\t\t\t'%s': this.model.get_l10n_type(),\n\t\t\t} );\n\n\t\t\tif ( window.confirm( msg ) ) {\n\n\t\t\t\tif ( this.model.collection ) {\n\t\t\t\t\tthis.model.collection.remove( this.model );\n\t\t\t\t}\n\n\t\t\t\t// publish event\n\t\t\t\tBackbone.pubSub.trigger( 'model-trashed', this.model );\n\n\t\t\t\t// trigger local event so extending views can run other actions where necessary\n\t\t\t\tthis.trigger( 'model-trashed', this.model );\n\n\t\t\t}\n\n\t\t},\n\n\t}\n\n} );\n\n","/**\n * Load view mixins\n * @return obj\n * @since 3.17.1\n * @version 3.17.1\n */\ndefine( 'Views/_loader',[\n\t\t'Views/_Detachable',\n\t\t'Views/_Editable',\n\t\t'Views/_Receivable',\n\t\t'Views/_Shiftable',\n\t\t'Views/_Subview',\n\t\t'Views/_Trashable'\n\t],\n\tfunction(\n\t\tDetachable,\n\t\tEditable,\n\t\tReceivable,\n\t\tShiftable,\n\t\tSubview,\n\t\tTrashable\n\t) {\n\n\treturn {\n\t\tDetachable: Detachable,\n\t\tEditable: Editable,\n\t\tReceivable: Receivable,\n\t\tShiftable: Shiftable,\n\t\tSubview: Subview,\n\t\tTrashable: Trashable,\n\t};\n\n} );\n\n","/**\n * Constructor functions for constructing models, views, and collections\n * @since 3.16.0\n * @version 3.17.1\n */\ndefine( 'Controllers/Construct',[\n\t\t'Collections/loader',\n\t\t'Models/loader',\n\t\t'Views/_loader'\n\t], function(\n\t\tCollections,\n\t\tModels,\n\t\tViews\n\t) {\n\n\treturn function() {\n\n\t\t/**\n\t\t * Internal getter\n\t\t * Constructs new Collections, Models, and Views\n\t\t * @param obj type type of object to construct [Collection,Model,View]\n\t\t * @param string name name of the object to construct\n\t\t * @param obj data object data to pass into the object's constructor\n\t\t * @param obj options object options to pass into the constructor\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tfunction get( type, name, data, options ) {\n\n\t\t\tif ( ! type[ name ] ) {\n\t\t\t\tconsole.log( '\"' + name + '\" not found.' );\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\treturn new type[ name ]( data, options );\n\n\t\t}\n\n\t\t/**\n\t\t * Instantiate a collection\n\t\t * @param string name Collection class name (EG: \"Sections\")\n\t\t * @param array data Array of model objects to pass to the constructor\n\t\t * @param obj options Object of options to pass to the constructor\n\t\t * @return obj\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tthis.get_collection = function( name, data, options ) {\n\n\t\t\treturn get( Collections, name, data, options );\n\n\t\t};\n\n\t\t/**\n\t\t * Instantiate a model\n\t\t * @param string name Model class name (EG: \"Section\")\n\t\t * @param obj data Object of model attributes to pass to the constructor\n\t\t * @param obj options Object of options to pass to the constructor\n\t\t * @return obj\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tthis.get_model = function( name, data, options ) {\n\n\t\t\treturn get( Models, name, data, options );\n\n\t\t};\n\n\t\t/**\n\t\t * Let 3rd parties extend a view using any of the mixin (_) views\n\t\t * @param {obj} view base object used for the view\n\t\t * @param... {string} extends any number of strings that should be mixed into the view\n\t\t * @return obj\n\t\t * @since 3.17.1\n\t\t * @version 3.17.1\n\t\t */\n\t\tthis.extend_view = function() {\n\n\t\t\tvar view = arguments[0],\n\t\t\t\ti = 1;\n\n\t\t\twhile ( arguments[ i ] ) {\n\n\t\t\t\tvar classname = arguments[ i ];\n\t\t\t\tif ( Views[ classname ] ) {\n\n\t\t\t\t\tif ( view.events && Views[ classname ].events ) {\n\t\t\t\t\t\tview.events = _.defaults( view.events, Views[ classname ].events );\n\t\t\t\t\t}\n\n\t\t\t\t\tview = _.defaults( view, Views[ classname ] );\n\n\t\t\t\t}\n\n\t\t\t\ti++;\n\t\t\t}\n\n\t\t\treturn Backbone.View.extend( view );\n\n\t\t};\n\n\t\t/**\n\t\t * Allows custom collection registration by extending the default BackBone collection\n\t\t * @param string name model name\n\t\t * @param obj props properties to extend the collection with\n\t\t * @return void\n\t\t * @since 3.17.1\n\t\t * @version 3.17.1\n\t\t */\n\t\tthis.register_collection = function( name, props ) {\n\n\t\t\tCollections[ name ] = Backbone.Collection.extend( props );\n\n\t\t};\n\n\t\t/**\n\t\t * Allows custom model registration by extending the default abstract model\n\t\t * @param string name model name\n\t\t * @param obj props properties to extend the abstract model with\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tthis.register_model = function( name, props ) {\n\n\t\t\tModels[ name ] = Models['Abstract'].extend( props );\n\n\t\t};\n\n\t\treturn this;\n\n\t};\n\n} );\n\n","/**\n * LifterLMS Builder Debugging suite\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Controllers/Debug',[], function() {\n\n \treturn function( settings ) {\n\n \t\tvar self = this,\n \t\t\tenabled = settings.enabled || false;\n\n\t\t/**\n\t\t * Disable debugging\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n \t\tthis.disable = function() {\n\n \t\t\tself.log( 'LifterLMS Builder debugging disabled' );\n \t\t\tenabled = false;\n\n \t\t};\n\n\t\t/**\n\t\t * Enable debugging\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n \t\tthis.enable = function() {\n\n \t\t\tenabled = true;\n \t\t\tself.log( 'LifterLMS Builder debugging enabled' );\n\n \t\t};\n\n \t\t/**\n \t\t * General logging function\n \t\t * Logs to the js console only if logging is enabled\n \t\t * @return void\n \t\t * @since 3.16.0\n \t\t * @version 3.16.0\n \t\t */\n \t\tthis.log = function() {\n\n\t\t\tif ( ! enabled ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t_.each( arguments, function( data ) {\n\t\t\t\tconsole.log( data );\n\t\t\t} );\n\n \t\t};\n\n \t\t/**\n \t\t * Toggles current state of the logger on or off\n \t\t * @return void\n \t\t * @since 3.16.0\n \t\t * @version 3.16.0\n \t\t */\n \t\tthis.toggle = function() {\n\n\t\t\tif ( enabled ) {\n\t\t\t\tself.disable();\n\t\t\t} else {\n\t\t\t\tself.enable();\n\t\t\t}\n\n \t\t};\n\n \t\t// on startup, log a message if logging is enabled\n \t\tif ( enabled ) {\n \t\t\tself.enable();\n \t\t}\n\n \t}\n\n } );\n\n","/**\n * Model schema functions\n * @since 3.17.0\n * @version 3.17.0\n */\ndefine( 'Controllers/Schemas',[], function() {\n\n\t/**\n\t * Main Schemas class\n\t * @param obj schemas schemas definitions initialized via PHP filters\n\t * @return obj\n\t * @since 3.17.0\n\t * @version 3.17.0\n\t */\n\treturn function( schemas ) {\n\n\t\t// initialize any custom schemas defined via PHP\n\t\tvar custom_schemas = schemas;\n\t\t_.each( custom_schemas, function( type ) {\n\t\t\t_.each( type, function( schema ) {\n\t\t\t\tschema.custom = true;\n\t\t\t} );\n\t\t} );\n\n\t\t/**\n\t\t * Retrieve a schema for a given model by type\n\t\t * Extends default schemas definitions with custom 3rd party definitions\n\t\t * @param obj schema default schema definition from the model (or empty object if none defined)\n\t\t * @param string model_type the model type ('lesson', 'quiz', etc)\n\t\t * @param obj model Instance of the Backbone.Model for the given model\n\t\t * @return obj\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tthis.get = function( schema, model_type, model ) {\n\n\t\t\t// extend the default schema with custom php schemas for the type if they exist\n\t\t\tif ( custom_schemas[ model_type ] ) {\n\t\t\t\tschema = _.extend( schema, custom_schemas[ model_type ] );\n\t\t\t}\n\n\t\t\treturn schema;\n\n\t\t};\n\n\t\treturn this;\n\n\t};\n\n} );\n\n","/**\n * Sync builder data to the server\n * @since 3.16.0\n * @version 3.17.1\n */\ndefine( 'Controllers/Sync',[], function() {\n\n \treturn function( Course, settings ) {\n\n \t\tthis.saving = false;\n\n \t\tvar self = this,\n \t\t\tautosave = true,\n \t\t\tcheck_interval = null,\n \t\t\tcheck_interval_ms = settings.check_interval_ms || 10000,\n \t\t\tdetached = new Backbone.Collection(),\n \t\t\ttrashed = new Backbone.Collection();\n\n\t\t/**\n\t\t * init\n\t\t * @return void\n\t\t * @since 3.16.7\n\t\t * @version 3.16.7\n\t\t */\n \t\tfunction init() {\n\n \t\t\t// determine if autosaving is possible\n \t\t\tif ( 'undefined' === typeof wp.heartbeat ) {\n\n \t\t\t\twindow.llms_builder.debug.log( 'WordPress Heartbeat disabled. Autosaving is disabled!' );\n \t\t\t\tautosave = false;\n\n \t\t\t}\n\n\t\t\t// setup the check interval\n\t\t\tif ( check_interval_ms ) {\n\t\t\t\tself.set_check_interval( check_interval_ms );\n\t\t\t}\n\n\t\t\t// warn when users attempt to leave the page\n\t\t\t$( window ).on( 'beforeunload', function() {\n\n\t\t\t\tif ( self.has_unsaved_changes() ) {\n\t\t\t\t\tcheck_for_changes();\n\t\t\t\t\treturn 'Are you sure you want to abandon your changes?';\n\t\t\t\t}\n\n\t\t\t} );\n\n \t\t};\n\n \t\t/*\n \t\t\t /$$ /$$ /$$ /$$\n \t\t\t|__/ | $$ | $$ |__/\n \t\t\t /$$ /$$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$$ /$$$$$$ | $$ /$$$$$$ /$$$$$$ /$$\n \t\t\t| $$| $$__ $$|_ $$_/ /$$__ $$ /$$__ $$| $$__ $$ |____ $$| $$ |____ $$ /$$__ $$| $$\n \t\t\t| $$| $$ \\ $$ | $$ | $$$$$$$$| $$ \\__/| $$ \\ $$ /$$$$$$$| $$ /$$$$$$$| $$ \\ $$| $$\n \t\t\t| $$| $$ | $$ | $$ /$$| $$_____/| $$ | $$ | $$ /$$__ $$| $$ /$$__ $$| $$ | $$| $$\n \t\t\t| $$| $$ | $$ | $$$$/| $$$$$$$| $$ | $$ | $$| $$$$$$$| $$ | $$$$$$$| $$$$$$$/| $$\n \t\t\t|__/|__/ |__/ \\___/ \\_______/|__/ |__/ |__/ \\_______/|__/ \\_______/| $$____/ |__/\n \t\t\t | $$\n \t\t\t | $$\n \t\t\t |__/\n \t\t*/\n\n \t\t/**\n \t\t * Adds error message(s) to the data object returned by heartbeat-tick\n \t\t * @param obj data llms_builder data object from heartbeat-tick\n \t\t * @param string|array err error messages array or string\n \t\t * @return obj\n \t\t * @since 3.16.0\n \t\t * @version 3.16.0\n \t\t */\n\t\tfunction add_error_msg( data, err ) {\n\n\t\t\tif ( 'success' === data.status ) {\n\t\t\t\tdata.message = [];\n\t\t\t}\n\n\t\t\tdata.status = 'error';\n\t\t\tif ( 'string' === typeof err ) {\n\t\t\t\terr = [ err ];\n\t\t\t}\n\t\t\tdata.message = data.message.concat( err );\n\n\t\t\treturn data;\n\n\t\t};\n\n\t\t/**\n\t\t * Publish sync status so other areas of the application can see what's happening here\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tfunction check_for_changes() {\n\n\t\t\tvar data = {};\n\t\t\tdata.changes = self.get_unsaved_changes();\n\t\t\tdata.has_unsaved_changes = self.has_unsaved_changes( data.changes );\n\t\t\tdata.saving = self.saving;\n\n\t\t\twindow.llms_builder.debug.log( '==== start changes check ====', data, '==== finish changes check ====' );\n\n\t\t\tBackbone.pubSub.trigger( 'current-save-status', data );\n\n\t\t};\n\n\t\t/**\n\t\t * Manually Save data via Admin AJAX when the heartbeat API has been disabled\n\t\t * @return void\n\t\t * @since 3.16.7\n\t\t * @version 3.16.7\n\t\t */\n\t\tfunction do_ajax_save() {\n\n\t\t\t// prevent simultaneous saves\n\t\t\tif ( self.saving ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar changes = self.get_unsaved_changes();\n\n\t\t\t// only send data if we have data to send\n\t\t\tif ( self.has_unsaved_changes( changes ) ) {\n\n\t\t\t\tchanges.id = Course.get( 'id' );\n\n\t\t\t\tLLMS.Ajax.call( {\n\t\t\t\t\tdata: {\n\t\t\t\t\t\taction: 'llms_builder',\n\t\t\t\t\t\taction_type: 'ajax_save',\n\t\t\t\t\t\tcourse_id: changes.id,\n\t\t\t\t\t\tllms_builder: JSON.stringify( changes ),\n\t\t\t\t\t},\n\t\t\t\t\tbeforeSend: function() {\n\n\t\t\t\t\t\twindow.llms_builder.debug.log( '==== start do_ajax_save before ====', changes, '==== finish do_ajax_save before ====' );\n\n\t\t\t\t\t\tself.saving = true;\n\n\t\t\t\t\t\tBackbone.pubSub.trigger( 'heartbeat-send', self );\n\n\t\t\t\t\t},\n\t\t\t\t\terror: function( xhr, status, error ) {\n\n\t\t\t\t\t\twindow.llms_builder.debug.log( '==== start do_ajax_save error ====', data, '==== finish do_ajax_save error ====' );\n\n\t\t\t\t\t\tself.saving = false;\n\n\t\t\t\t\t\tBackbone.pubSub.trigger( 'heartbeat-tick', self, {\n\t\t\t\t\t\t\tstatus: 'error',\n\t\t\t\t\t\t\tmessage: xhr.responseText + ' (' + error + ' ' + status +')',\n\t\t\t\t\t\t} );\n\n\t\t\t\t\t},\n\t\t\t\t\tsuccess: function( res ) {\n\n\t\t\t\t\t\tif ( ! res.llms_builder ) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\twindow.llms_builder.debug.log( '==== start do_ajax_save success ====', res, '==== finish do_ajax_save success ====' );\n\n\t\t\t\t\t\tres.llms_builder = process_removals( res.llms_builder );\n\t\t\t\t\t\tres.llms_builder = process_updates( res.llms_builder );\n\n\t\t\t\t\t\tself.saving = false;\n\n\t\t\t\t\t\tBackbone.pubSub.trigger( 'heartbeat-tick', self, res.llms_builder );\n\n\t\t\t\t\t}\n\n\t\t\t\t} );\n\n\t\t\t}\n\n\n\t\t};\n\n\t\t/**\n\t\t * Retrieve all the attributes changed on a model since the last sync\n\t\t *\n\t\t * For a new model (a model with a temp ID) or a model where _forceSync has been defined ALL atts will be returned\n\t\t * For an existing model (without a temp ID) only retrieves changed attributes as tracked by Backbone.TrackIt\n\t\t *\n\t\t * This function excludes any attributes defined as child attributes via the models relationship settings\n\t\t *\n\t\t * @param obj model instance of a Backbone.Model\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.6\n\t\t */\n\t\tfunction get_changed_attributes( model ) {\n\n\t\t\tvar atts = {},\n\t\t\t\tsync_type;\n\n\t\t\t// don't save mid editing\n\t\t\tif ( model.get( '_has_focus' ) ) {\n\t\t\t\treturn atts;\n\t\t\t}\n\n\t\t\t// model hasn't been persisted to the database to get a real ID yet\n\t\t\t// send *all* of it's atts\n\t\t\tif ( has_temp_id( model ) || true === model.get( '_forceSync' ) ) {\n\n\t\t\t\tatts = _.clone( model.attributes );\n\t\t\t\tsync_type = 'full';\n\n\t\t\t// only send the changed atts\n\t\t\t} else {\n\n\t\t\t\tatts = model.unsavedAttributes();\n\t\t\t\tsync_type = 'partial';\n\n\t\t\t}\n\n\t\t\tvar exclude = ( model.get_relationships ) ? model.get_child_props() : [];\n\t\t\tatts = _.omit( atts, function( val, key ) {\n\n\t\t\t\t// exclude keys that start with an underscore which are used by the\n\t\t\t\t// application but don't need to be stored in the database\n\t\t\t\tif ( 0 === key.indexOf( '_' ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t} else if ( -1 !== exclude.indexOf( key ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\treturn false;\n\n\t\t\t} );\n\n\t\t\tif ( model.before_save ) {\n\t\t\t\tatts = model.before_save( atts, sync_type );\n\t\t\t}\n\n\t\t\treturn atts;\n\n\t\t};\n\n\t\t/**\n\t\t * Get all the changes to an object (either a Model or a Collection of models)\n\t\t * Returns only changes to models and the IDs of that model (should changes exist)\n\t\t * Uses get_changed_attributes() to determine if all atts or only changed atts are needed\n\t\t * Processes children intelligently to only return changed children rather than the entire collection of children\n\t\t *\n\t\t * @param obj object instance of a Backbone.Model or Backbone.Collection\n\t\t * @return obj|array\t \t\tif object is a model, returns an object\n\t\t * \tif object is a collection, returns an array of objects\n\t\t * @since 3.16.0\n\t\t * @version 3.16.11\n\t\t */\n\t\tfunction get_changes_to_object( object ) {\n\n\t\t\tvar changed_atts;\n\n\t\t\tif ( object instanceof Backbone.Model ) {\n\n\t\t\t\tchanged_atts = get_changed_attributes( object );\n\n\t\t\t\tif ( object.get_relationships ) {\n\n\t\t\t\t\t_.each( object.get_child_props(), function( prop ) {\n\n\t\t\t\t\t\tvar children = get_changes_to_object( object.get( prop ) );\n\t\t\t\t\t\tif ( ! _.isEmpty( children ) ) {\n\t\t\t\t\t\t\tchanged_atts[ prop ] = children;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} );\n\n\t\t\t\t}\n\n\t\t\t\t// if we have any data, add the id to the model\n\t\t\t\tif ( ! _.isEmpty( changed_atts ) ) {\n\t\t\t\t\tchanged_atts.id = object.get( 'id' );\n\t\t\t\t}\n\n\t\t\t} else if ( object instanceof Backbone.Collection ) {\n\n\t\t\t\tchanged_atts = [];\n\t\t\t\tobject.each( function( model ) {\n\t\t\t\t\tvar model_changes = get_changes_to_object( model );\n\t\t\t\t\tif ( ! _.isEmpty( model_changes ) ) {\n\t\t\t\t\t\tchanged_atts.push( model_changes );\n\t\t\t\t\t}\n\t\t\t\t} );\n\n\t\t\t}\n\n\t\t\treturn changed_atts;\n\n\t\t};\n\n\t\t/**\n\t\t * Determines if a model has a temporary ID or a real persisted ID\n\t\t * @param obj model instance of a model\n\t\t * @return boolean\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tfunction has_temp_id( model ) {\n\n\t\t\treturn ( ! _.isNumber( model.id ) && 0 === model.id.indexOf( 'temp_' ) );\n\n\t\t};\n\n\t\t/**\n\t\t * Compares changes synced to the server against current model and restarts\n\t\t * tracking on elements that haven't changed since the last sync\n\t\t * @param obj model instance of a Backbone.Model\n\t\t * @param obj data data set that was processed by the server\n\t\t * @return void\n\t\t * @since 3.16.11\n\t\t * @version 3.16.6\n\t\t */\n\t\tfunction maybe_restart_tracking( model, data ) {\n\n\t\t\tBackbone.pubSub.trigger( model.get( 'type' ) + '-maybe-restart-tracking', model, data );\n\n\t\t\tvar omit = [ 'id', 'orig_id' ];\n\n\t\t\tif ( model.get_relationships ) {\n\t\t\t\tomit.concat( model.get_child_props() );\n\t\t\t}\n\n\t\t\t_.each( _.omit( data, omit ), function( val, prop ) {\n\n\t\t\t\tif ( _.isEqual( model.get( prop ), val ) ) {\n\t\t\t\t\tdelete model._unsavedChanges[ prop ];\n\t\t\t\t\tmodel._originalAttrs[ prop ] = val;\n\t\t\t\t}\n\n\t\t\t} );\n\n\t\t\t// if syncing was forced, allow tracking to move forward as normal moving forward\n\t\t\tmodel.unset( '_forceSync' );\n\n\t\t};\n\n\t\t/**\n\t\t * Processes response data from heartbeat-tick related to trashing & detaching models\n\t\t * On success, removes from local removal collection\n\t\t * On error, appends error messages to the data object returned to UI for on-screen feedback\n\t\t * @param obj data data.llms_builder object from heartbeat-tick response\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.17.1\n\t\t */\n\t\tfunction process_removals( data ) {\n\n\t\t\t// check removals for errors\n\t\t\tvar removals = {\n\t\t\t\tdetach: detached,\n\t\t\t\ttrash: trashed,\n\t\t\t};\n\n\t\t\t_.each( removals, function( coll, key ) {\n\n\t\t\t\tif ( data[ key ] ) {\n\n\t\t\t\t\tvar errors = [];\n\n\t\t\t\t\t_.each( data[ key ] , function( info ) {\n\n\t\t\t\t\t\t// succesfully detached, remove it from the detached collection\n\t\t\t\t\t\tif ( ! info.error ) {\n\n\t\t\t\t\t\t\tcoll.remove( info.id );\n\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\terrors.push( info.error );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} );\n\n\t\t\t\t\tif ( errors.length ) {\n\t\t\t\t\t\t_.extend( data, add_error_msg( data, errors ) );\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t} );\n\n\t\t\treturn data;\n\t\t}\n\n\t\t/**\n\t\t * Processes response data from heartbeat-tick related to creating / updating a single object\n\t\t * Handles both collections and models as a recursive function\n\t\t * @param {[type]} data [description]\n\t\t * @param {[type]} type [description]\n\t\t * @param {[type]} parent [description]\n\t\t * @param {[type]} main_data [description]\n\t\t * @return {[type]}\n\t\t * @since 3.16.0\n\t\t * @version 3.16.11\n\t\t */\n\t\tfunction process_object_updates( data, type, parent, main_data ) {\n\n\t\t\tif ( ! data[ type ] ) {\n\t\t\t\treturn data;\n\t\t\t}\n\n\t\t\tif ( parent.get( type ) instanceof Backbone.Model ) {\n\n\t\t\t\tvar info = data[ type ];\n\n\t\t\t\tif ( info.error ) {\n\n\t\t\t\t\t_.extend( main_data, add_error_msg( main_data, info.error ) );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tvar model = parent.get( type );\n\n\t\t\t\t\t// update temp ids with the real id\n\t\t\t\t\tif ( info.id != info.orig_id ) {\n\t\t\t\t\t\tmodel.set( 'id', info.id );\n\t\t\t\t\t\tdelete model._unsavedChanges.id;\n\t\t\t\t\t}\n\t\t\t\t\tmaybe_restart_tracking( model, info );\n\n\t\t\t\t\t// check children\n\t\t\t\t\tif ( model.get_relationships ) {\n\n\t\t\t\t\t\t_.each( model.get_child_props(), function( child_key ) {\n\t\t\t\t\t\t\t_.extend( data[ type ], process_object_updates( data[ type ], child_key, model, main_data ) );\n\t\t\t\t\t\t} );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t} else if ( parent.get( type ) instanceof Backbone.Collection ) {\n\n\t\t\t\t_.each( data[ type ], function( info, index ) {\n\n\t\t\t\t\tif ( info.error ) {\n\n\t\t\t\t\t\t_.extend( main_data, add_error_msg( main_data, info.error ) );\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tvar model = parent.get( type ).get( info.orig_id );\n\n\t\t\t\t\t\t// update temp ids with the real id\n\t\t\t\t\t\tif ( info.id != info.orig_id ) {\n\t\t\t\t\t\t\tmodel.set( 'id', info.id );\n\t\t\t\t\t\t\tdelete model._unsavedChanges.id;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmaybe_restart_tracking( model, info );\n\n\t\t\t\t\t\t// check children\n\t\t\t\t\t\tif ( model.get_relationships ) {\n\n\t\t\t\t\t\t\t_.each( model.get_child_props(), function( child_key ) {\n\t\t\t\t\t\t\t\t_.extend( data[ type ], process_object_updates( data[ type ][ index ], child_key, model, main_data ) );\n\t\t\t\t\t\t\t} );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t} );\n\n\t\t\t}\n\n\t\t\treturn main_data;\n\n\t\t};\n\n\t\t/**\n\t\t * Processes response data from heartbeat-tick related to updating & creating new models\n\t\t * On success, removes from local removal collection\n\t\t * On error, appends error messages to the data object returned to UI for on-screen feedback\n\t\t * @param obj data data.llms_builder object from heartbeat-tick response\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tfunction process_updates( data ) {\n\n\t\t\t// only mess with updates data\n\t\t\tif ( ! data.updates ) {\n\t\t\t\treturn data;\n\t\t\t}\n\n\t\t\tif ( data.updates ) {\n\t\t\t\tdata = process_object_updates( data.updates, 'sections', Course, data );\n\t\t\t}\n\n\t\t\treturn data;\n\n\t\t};\n\n\t\t/*\n\t\t\t /$$ /$$ /$$ /$$\n\t\t\t | $$ | $$|__/ |__/\n\t\t\t /$$$$$$ /$$ /$$| $$$$$$$ | $$ /$$ /$$$$$$$ /$$$$$$ /$$$$$$ /$$\n\t\t\t /$$__ $$| $$ | $$| $$__ $$| $$| $$ /$$_____/ |____ $$ /$$__ $$| $$\n\t\t\t| $$ \\ $$| $$ | $$| $$ \\ $$| $$| $$| $$ /$$$$$$$| $$ \\ $$| $$\n\t\t\t| $$ | $$| $$ | $$| $$ | $$| $$| $$| $$ /$$__ $$| $$ | $$| $$\n\t\t\t| $$$$$$$/| $$$$$$/| $$$$$$$/| $$| $$| $$$$$$$ | $$$$$$$| $$$$$$$/| $$\n\t\t\t| $$____/ \\______/ |_______/ |__/|__/ \\_______/ \\_______/| $$____/ |__/\n\t\t\t| $$ | $$\n\t\t\t| $$ | $$\n\t\t\t|__/ |__/\n\t\t*/\n\n\t\t/**\n\t\t * Retrieve all unsaved changes for the builder instance\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.17.1\n\t\t */\n\t\tthis.get_unsaved_changes = function() {\n\n\t\t\treturn {\n\t\t\t\tdetach: detached.pluck( 'id' ),\n\t\t\t\ttrash: trashed.pluck( 'id' ),\n\t\t\t\tupdates: get_changes_to_object( Course ),\n\n\t\t\t}\n\t\t};\n\n\t\t/**\n\t\t * Check if the builder instance has unsaved changes\n\t\t * @param obj changes optionally pass in an object from the return of this.get_unsaved_changes()\n\t\t * save some resources by not running the check twice during heartbeats\n\t\t * @return boolean\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tthis.has_unsaved_changes = function( changes ) {\n\n\t\t\tif ( 'undefined' === typeof changes ) {\n\t\t\t\tchanges = self.get_unsaved_changes();\n\t\t\t}\n\n\t\t\t// check all possible keys, once we find one with content we have some changes to persist\n\t\t\tvar found = _.find( changes, function( data ) {\n\n\t\t\t\treturn ( false === _.isEmpty( data ) );\n\n\t\t\t} );\n\n\t\t\treturn found ? true : false;\n\n\t\t};\n\n\t\t/**\n\t\t * Save changes right now.\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.7\n\t\t */\n\t\tthis.save_now = function() {\n\t\t\tif ( autosave ) {\n\t\t\t\twp.heartbeat.connectNow();\n\t\t\t} else {\n\t\t\t\tdo_ajax_save();\n\t\t\t}\n\t\t};\n\n\t\t/**\n\t\t * Update the interval that checks for changes to the builder instance\n\t\t * @param int ms time (in milliseconds) to run the check on\n\t\t * pass 0 to disable the check\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tthis.set_check_interval = function( ms ) {\n\t\t\tcheck_interval_ms = ms;\n\t\t\tif ( check_interval ) {\n\t\t\t\tclearInterval( check_interval );\n\t\t\t}\n\t\t\tif ( check_interval_ms ) {\n\t\t\t\tcheck_interval = setInterval( check_for_changes, check_interval_ms );\n\t\t\t}\n\t\t};\n\n\t\t/*\n\t\t\t /$$ /$$ /$$\n\t\t\t| $$|__/ | $$\n\t\t\t| $$ /$$ /$$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$$\n\t\t\t| $$| $$ /$$_____/|_ $$_/ /$$__ $$| $$__ $$ /$$__ $$ /$$__ $$ /$$_____/\n\t\t\t| $$| $$| $$$$$$ | $$ | $$$$$$$$| $$ \\ $$| $$$$$$$$| $$ \\__/| $$$$$$\n\t\t\t| $$| $$ \\____ $$ | $$ /$$| $$_____/| $$ | $$| $$_____/| $$ \\____ $$\n\t\t\t| $$| $$ /$$$$$$$/ | $$$$/| $$$$$$$| $$ | $$| $$$$$$$| $$ /$$$$$$$/\n\t\t\t|__/|__/|_______/ \\___/ \\_______/|__/ |__/ \\_______/|__/ |_______/\n\t\t*/\n\n\t\t/**\n\t\t * Listen for detached models and send them to the server for persistence\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tBackbone.pubSub.on( 'model-detached', function( model ) {\n\n\t\t\t// detached models with temp ids haven't been persisted so we don't care\n\t\t\tif ( has_temp_id( model ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tdetached.add( _.clone( model.attributes ) );\n\n\t\t} );\n\n\t\t/**\n\t\t * Listen for trashed models and send them to the server for deletion\n\t\t * @since 3.16.0\n\t\t * @version 3.17.1\n\t\t */\n\t\tBackbone.pubSub.on( 'model-trashed', function( model ) {\n\n\t\t\t// if the model has a temp ID we don't have to persist the deletion\n\t\t\tif ( has_temp_id( model ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar data = _.clone( model.attributes );\n\n\t\t\tif ( model.get_trash_id ) {\n\t\t\t\tdata.id = model.get_trash_id();\n\t\t\t}\n\n\t\t\ttrashed.add( data );\n\n\t\t} );\n\n\t\t/*\n\t\t\t /$$ /$$ /$$ /$$\n\t\t\t| $$ | $$ | $$ | $$\n\t\t\t| $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ | $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$\n\t\t\t| $$__ $$ /$$__ $$ |____ $$ /$$__ $$|_ $$_/ | $$__ $$ /$$__ $$ |____ $$|_ $$_/\n\t\t\t| $$ \\ $$| $$$$$$$$ /$$$$$$$| $$ \\__/ | $$ | $$ \\ $$| $$$$$$$$ /$$$$$$$ | $$\n\t\t\t| $$ | $$| $$_____/ /$$__ $$| $$ | $$ /$$| $$ | $$| $$_____/ /$$__ $$ | $$ /$$\n\t\t\t| $$ | $$| $$$$$$$| $$$$$$$| $$ | $$$$/| $$$$$$$/| $$$$$$$| $$$$$$$ | $$$$/\n\t\t\t|__/ |__/ \\_______/ \\_______/|__/ \\___/ |_______/ \\_______/ \\_______/ \\___/\n\t\t*/\n\n\t\t/**\n\t\t * Add data to the WP heartbeat to persist new models, changes, and deletions to the DB\n\t\t * @since 3.16.0\n\t\t * @version 3.16.7\n\t\t */\n\t\t$( document ).on( 'heartbeat-send', function( event, data ) {\n\n\t\t\t// prevent simultaneous saves\n\t\t\tif ( self.saving ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar changes = self.get_unsaved_changes();\n\n\t\t\t// only send data if we have data to send\n\t\t\tif ( self.has_unsaved_changes( changes ) ) {\n\n\t\t\t\tchanges.id = Course.get( 'id' );\n\t\t\t\tself.saving = true;\n\t\t\t\tdata.llms_builder = JSON.stringify( changes );\n\n\t\t\t}\n\n\t\t\twindow.llms_builder.debug.log( '==== start heartbeat-send ====', data, '==== finish heartbeat-send ====' );\n\n\t\t\tBackbone.pubSub.trigger( 'heartbeat-send', self );\n\n\t\t} );\n\n\t\t/**\n\t\t * Confirm detachments & deletions and replace temp IDs with new persisted IDs\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\t$( document ).on( 'heartbeat-tick', function( event, data ) {\n\n\t\t\tif ( ! data.llms_builder ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\twindow.llms_builder.debug.log( '==== start heartbeat-tick ====', data, '==== finish heartbeat-tick ====' );\n\n\t\t\tdata.llms_builder = process_removals( data.llms_builder );\n\t\t\tdata.llms_builder = process_updates( data.llms_builder );\n\n\t\t\tself.saving = false;\n\n\t\t\tBackbone.pubSub.trigger( 'heartbeat-tick', self, data.llms_builder );\n\n\t\t} );\n\n\t\t/**\n\t\t * On heartbeat errors publish an error to the main builder application\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\t$( document ).on( 'heartbeat-error', function( event, data ) {\n\n\t\t\twindow.llms_builder.debug.log( '==== start heartbeat-error ====', data, '==== finish heartbeat-error ====' );\n\n\t\t\tself.saving = false;\n\n\t\t\tBackbone.pubSub.trigger( 'heartbeat-tick', self, {\n\t\t\t\tstatus: 'error',\n\t\t\t\tmessage: data.responseText + ' (' + data.status + ' ' + data.statusText +')',\n\t\t\t} );\n\n\t\t} );\n\n\t\t/*\n\t\t\t /$$ /$$ /$$\n\t\t\t|__/ |__/ | $$\n\t\t\t /$$ /$$$$$$$ /$$ /$$$$$$\n\t\t\t| $$| $$__ $$| $$|_ $$_/\n\t\t\t| $$| $$ \\ $$| $$ | $$\n\t\t\t| $$| $$ | $$| $$ | $$ /$$\n\t\t\t| $$| $$ | $$| $$ | $$$$/\n\t\t\t|__/|__/ |__/|__/ \\___/\n\t\t*/\n\t\tinit();\n\n\t\treturn this;\n\n\t};\n\n} );\n\n","/**\n * Single Lesson View\n * @since 3.16.0\n * @version 3.17.0\n */\ndefine( 'Views/Lesson',[\n\t\t'Views/_Detachable',\n\t\t'Views/_Editable',\n\t\t'Views/_Shiftable',\n\t\t'Views/_Trashable'\n\t], function(\n\t\tDetachable,\n\t\tEditable,\n\t\tShiftable,\n\t\tTrashable\n\t) {\n\n\treturn Backbone.View.extend( _.defaults( {\n\n\t\t/**\n\t\t * Get default attributes for the html wrapper element\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tattributes: function() {\n\t\t\treturn {\n\t\t\t\t'data-id': this.model.id,\n\t\t\t\t'data-section-id': this.model.get( 'parent_section' ),\n\t\t\t};\n\t\t},\n\n\t\t/**\n\t\t * HTML class names\n\t\t * @type {String}\n\t\t */\n\t\tclassName: 'llms-builder-item llms-lesson',\n\n\t\t/**\n\t\t * Events\n\t\t * @type {Object}\n\t\t * @since 3.16.0\n\t\t * @version 3.16.12\n\t\t */\n\t\tevents: _.defaults( {\n\t\t\t'click .edit-lesson': 'open_lesson_editor',\n\t\t\t'click .edit-quiz': 'open_quiz_editor',\n\t\t\t'click .edit-assignment': 'open_assignment_editor',\n\t\t\t'click .section-prev': 'section_prev',\n\t\t\t'click .section-next': 'section_next',\n\t\t\t'click .shift-up--lesson': 'shift_up',\n\t\t\t'click .shift-down--lesson': 'shift_down',\n\t\t}, Detachable.events, Editable.events, Trashable.events ),\n\n\t\t/**\n\t\t * HTML element wrapper ID attribute\n\t\t * @return string\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tid: function() {\n\t\t\treturn 'llms-lesson-' + this.model.id;\n\t\t},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'li',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-lesson-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.14.1\n\t\t * @version 3.14.1\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\tthis.render();\n\n\t\t\tthis.listenTo( this.model, 'change', this.render );\n\n\t\t\tBackbone.pubSub.on( 'lesson-selected', this.on_select, this );\n\t\t\tBackbone.pubSub.on( 'new-lesson-added', this.on_select, this );\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender: function() {\n\n\t\t\tthis.$el.html( this.template( this.model ) );\n\t\t\tthis.maybe_hide_shiftable_buttons();\n\t\t\tif ( this.model.get( '_selected' ) ) {\n\t\t\t\tthis.$el.addClass( 'selected' );\n\t\t\t} else {\n\t\t\t\tthis.$el.removeClass( 'selected' );\n\t\t\t}\n\t\t\treturn this;\n\n\t\t},\n\n\t\t/**\n\t\t * Click event for the assignment editor action icon\n\t\t * Opens sidebar to the assignment editor tab\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\topen_assignment_editor: function() {\n\n\t\t\tBackbone.pubSub.trigger( 'lesson-selected', this.model, 'assignment' );\n\t\t\tthis.model.set( '_selected', true );\n\n\t\t},\n\n\t\t/**\n\t\t * Click event for lesson settings action icon\n\t\t * Opens sidebar to the lesson editor tab\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\topen_lesson_editor: function() {\n\n\t\t\tBackbone.pubSub.trigger( 'lesson-selected', this.model, 'lesson' );\n\t\t\tthis.model.set( '_selected', true );\n\n\t\t},\n\n\t\t/**\n\t\t * Click event for the quiz editor action icon\n\t\t * Opens sidebar to the quiz editor tab\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\topen_quiz_editor: function() {\n\n\t\t\tBackbone.pubSub.trigger( 'lesson-selected', this.model, 'quiz' );\n\t\t\tthis.model.set( '_selected', true );\n\n\t\t},\n\n\t\t/**\n\t\t * When a lesson is selected mark it as selected in the hidden prop\n\t\t * Allows views to re-render and reflect current state properly\n\t\t * @param obj model lesson model that's been selected\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\ton_select: function( model ) {\n\n\t\t\tif ( this.model.id !== model.id ) {\n\t\t\t\tthis.model.set( '_selected', false );\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Click event for the \"Next Section\" button\n\t\t * @param obj event js event obj\n\t\t * @return void\n\t\t * @since 3.16.11\n\t\t * @version 3.16.11\n\t\t */\n\t\tsection_next: function( event ) {\n\t\t\tevent.preventDefault();\n\t\t\tthis._move_to_section( 'next' );\n\t\t},\n\n\t\t/**\n\t\t * Click event for the \"Previous Section\" button\n\t\t * @param obj event js event obj\n\t\t * @return void\n\t\t * @since 3.16.11\n\t\t * @version 3.16.11\n\t\t */\n\t\tsection_prev: function( event ) {\n\t\t\tevent.preventDefault();\n\t\t\tthis._move_to_section( 'prev' );\n\t\t},\n\n\t\t/**\n\t\t * Move the lesson into a new section\n\t\t * @param string direction direction [prev|next]\n\t\t * @return void\n\t\t * @since 3.16.11\n\t\t * @version 3.16.11\n\t\t */\n\t\t_move_to_section: function( direction ) {\n\n\t\t\tvar from_coll = this.model.collection,\n\t\t\t\tto_section;\n\n\t\t\tif ( 'next' === direction ) {\n\t\t\t\tto_section = from_coll.parent.get_next();\n\t\t\t} else if ( 'prev' === direction ) {\n\t\t\t\tto_section = from_coll.parent.get_prev();\n\t\t\t}\n\n\t\t\tif ( to_section ) {\n\n\t\t\t\tfrom_coll.remove( this.model );\n\t\t\t\tto_section.add_lesson( this.model );\n\t\t\t\tto_section.set( '_expanded', true );\n\n\t\t\t}\n\n\t\t},\n\n\t}, Detachable, Editable, Shiftable, Trashable ) );\n\n} );\n\n","/**\n * Single Section View\n * @since 3.13.0\n * @version 3.16.0\n */\ndefine( 'Views/LessonList',[ 'Views/Lesson', 'Views/_Receivable' ], function( LessonView, Receivable ) {\n\n\treturn Backbone.CollectionView.extend( _.defaults( {\n\n\t\tclassName: 'llms-lessons',\n\n\t\t/**\n\t\t * Section model\n\t\t * @type {[type]}\n\t\t */\n\t\tmodelView: LessonView,\n\n\t\t/**\n\t\t * Are sections selectable?\n\t\t * @type {Bool}\n\t\t */\n\t\tselectable: false,\n\n\t\t/**\n\t\t * Are sections sortable?\n\t\t * @type {Bool}\n\t\t */\n\t\tsortable: true,\n\n\t\tsortableOptions: {\n\t\t\taxis: false,\n\t\t\tconnectWith: '.llms-lessons',\n\t\t\tcursor: 'move',\n\t\t\thandle: '.drag-lesson',\n\t\t\titems: '.llms-lesson',\n\t\t\tplaceholder: 'llms-lesson llms-sortable-placeholder',\n\t\t},\n\n\t\tsortable_start: function( collection ) {\n\t\t\t$( '.llms-lessons' ).addClass( 'dragging' );\n\t\t},\n\n\t\tsortable_stop: function( collection ) {\n\t\t\t$( '.llms-lessons' ).removeClass( 'dragging' );\n\t\t},\n\n\t\t/**\n\t\t * Overloads the function from Backbone.CollectionView core because it doesn't send stop events\n\t\t * if moving from one sortable to another... :-(\n\t\t * @param obj event js event object\n\t\t * @param obj ui jQuery UI object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\t_sortStop : function( event, ui ) {\n\n\t\t\tvar modelBeingSorted = this.collection.get( ui.item.attr( 'data-model-cid' ) ),\n\t\t\t\tmodelViewContainerEl = this._getContainerEl(),\n\t\t\t\tnewIndex = modelViewContainerEl.children().index( ui.item );\n\n\t\t\tif ( newIndex == -1 && modelBeingSorted ) {\n\t\t\t\tthis.collection.remove( modelBeingSorted );\n\t\t\t}\n\n\t\t\tthis._reorderCollectionBasedOnHTML();\n\t\t\tthis.updateDependentControls();\n\n\t\t\tif( this._isBackboneCourierAvailable() ) {\n\t\t\t\tthis.spawn( 'sortStop', { modelBeingSorted : modelBeingSorted, newIndex : newIndex } );\n\t\t\t} else {\n\t\t\t\tthis.trigger( 'sortStop', modelBeingSorted, newIndex );\n\t\t\t}\n\n\t\t},\n\n\t}, Receivable ) );\n\n} );\n\n","/**\n * Single Section View\n * @since 3.13.0\n * @version 3.16.12\n */\ndefine( 'Views/Section',[\n\t\t'Views/LessonList',\n\t\t'Views/_Editable',\n\t\t'Views/_Shiftable',\n\t\t'Views/_Trashable'\n\t], function(\n\t\tLessonListView,\n\t\tEditable,\n\t\tShiftable,\n\t\tTrashable\n\t) {\n\n\treturn Backbone.View.extend( _.defaults( {\n\n\t\t/**\n\t\t * Get default attributes for the html wrapper element\n\t\t * @return obj\n\t\t * @since 3.13.0\n\t\t * @version 3.13.0\n\t\t */\n\t\tattributes: function() {\n\t\t\treturn {\n\t\t\t\t'data-id': this.model.id,\n\t\t\t};\n\t\t},\n\n\t\t/**\n\t\t * Element classnames\n\t\t * @type {String}\n\t\t */\n\t\tclassName: 'llms-builder-item llms-section',\n\n\t\t/**\n\t\t * Events\n\t\t * @type {Object}\n\t\t * @since 3.16.0\n\t\t * @version 3.16.12\n\t\t */\n\t\tevents: _.defaults( {\n\n\t\t\t'click': 'select',\n\t\t\t'click .expand': 'expand',\n\t\t\t'click .collapse': 'collapse',\n\t\t\t'click .shift-up--section': 'shift_up',\n\t\t\t'click .shift-down--section': 'shift_down',\n\n\t\t\t'mouseenter .llms-lessons': 'on_mouseenter',\n\n\t\t}, Editable.events, Trashable.events ),\n\n\t\t/**\n\t\t * HTML element wrapper ID attribute\n\t\t * @return string\n\t\t * @since 3.13.0\n\t\t * @version 3.13.0\n\t\t */\n\t\tid: function() {\n\t\t\treturn 'llms-section-' + this.model.id;\n\t\t},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'li',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-section-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.13.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\tthis.render();\n\t\t\tthis.listenTo( this.model, 'change', this.render );\n\t\t\tthis.listenTo( this.model, 'change:_expanded', this.toggle_expanded );\n\t\t\tthis.lessonListView.collection.on( 'add', this.on_lesson_add, this );\n\n\t\t\tthis.dragTimeout = null;\n\n\t\t\tBackbone.pubSub.on( 'expand-all', this.expand, this );\n\t\t\tBackbone.pubSub.on( 'collapse-all', this.collapse, this );\n\n\t\t},\n\n\t\t/**\n\t\t * Render the section\n\t\t * Initalizes a new collection and views for all lessons in the section\n\t\t * @return void\n\t\t * @since 3.13.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender: function() {\n\n\t\t\tthis.$el.html( this.template( this.model.toJSON() ) );\n\n\t\t\tthis.maybe_hide_shiftable_buttons();\n\n\t\t\tthis.lessonListView = new LessonListView( {\n\t\t\t\tel: this.$el.find( '.llms-lessons' ),\n\t\t\t\tcollection: this.model.get( 'lessons' ),\n\t\t\t} );\n\t\t\tthis.lessonListView.render();\n\t\t\tthis.lessonListView.on( 'sortStart', this.lessonListView.sortable_start );\n\t\t\tthis.lessonListView.on( 'sortStop', this.lessonListView.sortable_stop );\n\n\t\t\t// selection changes\n\t\t\tthis.lessonListView.on( 'selectionChanged', this.active_lesson_change, this );\n\n\t\t\tthis.maybe_hide_trash_button();\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\tactive_lesson_change: function( current, previous ) {\n\n\t\t\tBackbone.pubSub.trigger( 'active-lesson-change', {\n\t\t\t\tcurrent: current,\n\t\t\t\tprevious: previous,\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * Collapse lessons within the section\n\t\t * @param obj event js event object\n\t\t * @param bool update if true, updates the model to reflect the new state\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tcollapse: function( event, update ) {\n\n\t\t\tif ( 'undefined' === typeof update ) {\n\t\t\t\tupdate = true;\n\t\t\t}\n\n\t\t\tif ( event ) {\n\t\t\t\tevent.stopPropagation();\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\n\t\t\tthis.$el.removeClass( 'expanded' ).find( '.drag-expanded' ).removeClass( 'drag-expanded' );\n\t\t\tif ( update ) {\n\t\t\t\tthis.model.set( '_expanded', false );\n\t\t\t}\n\t\t\tBackbone.pubSub.trigger( 'section-toggle', this.model );\n\n\t\t},\n\n\t\t/**\n\t\t * Expand lessons within the section\n\t\t * @param obj event js event object\n\t\t * @param bool update if true, updates the model to reflect the new state\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\texpand: function( event, update ) {\n\n\t\t\tif ( 'undefined' === typeof update ) {\n\t\t\t\tupdate = true;\n\t\t\t}\n\n\t\t\tif ( event ) {\n\t\t\t\tevent.stopPropagation();\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\n\t\t\tthis.$el.addClass( 'expanded' );\n\t\t\tif ( update ) {\n\t\t\t\tthis.model.set( '_expanded', true );\n\t\t\t}\n\t\t\tBackbone.pubSub.trigger( 'section-toggle', this.model );\n\n\t\t},\n\n\t\tmaybe_hide_trash_button: function() {\n\n\t\t\tvar $btn = this.$el.find( '.trash--section' );\n\n\t\t\tif ( this.model.get( 'lessons' ).isEmpty() ) {\n\n\t\t\t\t$btn.show();\n\n\t\t\t} else {\n\n\t\t\t\t$btn.hide()\n\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * When a lesson is added to the section trigger a collection reorder & update the lesson's id\n\t\t * @param obj model Lesson model\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\ton_lesson_add: function( model ) {\n\n\t\t\tthis.lessonListView.collection.trigger( 'reorder' );\n\t\t\tmodel.set( 'parent_section', this.model.get( 'id' ) );\n\t\t\tthis.expand();\n\n\t\t},\n\n\t\ton_mouseenter: function( event ) {\n\n\n\t\t\tif ( $( event.target ).hasClass( 'dragging' ) ) {\n\n\t\t\t\t$( '.drag-expanded' ).removeClass( 'drag-expanded' );\n\t\t\t\t$( event.target ).addClass( 'drag-expanded' );\n\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Expand\n\t\t * @param {[type]} model [description]\n\t\t * @param {[type]} value [description]\n\t\t * @return {[type]}\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\ttoggle_expanded: function( model, value ) {\n\n\t\t\tif ( value ) {\n\t\t\t\tthis.expand( null, false );\n\t\t\t} else {\n\t\t\t\tthis.collapse( null, false );\n\t\t\t}\n\n\t\t},\n\n\t}, Editable, Shiftable, Trashable ) );\n\n} );\n\n","/**\n * Single Section View\n * @since 3.13.0\n * @version 3.16.0\n */\ndefine( 'Views/SectionList',[ 'Views/Section', 'Views/_Receivable' ], function( SectionView, Receivable ) {\n\n\treturn Backbone.CollectionView.extend( _.defaults( {\n\n\t\t/**\n\t\t * Parent element\n\t\t * @type {String}\n\t\t */\n\t\tel: '#llms-sections',\n\n\t\tevents : {\n\t\t\t'mousedown > li.llms-section > .llms-builder-header .llms-headline' : '_listItem_onMousedown',\n\t\t\t// 'dblclick > li, tbody > tr > td' : '_listItem_onDoubleClick',\n\t\t\t'click' : '_listBackground_onClick',\n\t\t\t'click ul.collection-view' : '_listBackground_onClick',\n\t\t\t'keydown' : '_onKeydown'\n\t\t},\n\n\t\t/**\n\t\t * Section model\n\t\t * @type {[type]}\n\t\t */\n\t\tmodelView: SectionView,\n\n\t\t/**\n\t\t * Enable keyboard events\n\t\t * @type {Bool}\n\t\t */\n\t\tprocessKeyEvents: false,\n\n\t\t/**\n\t\t * Are sections selectable?\n\t\t * @type {Bool}\n\t\t */\n\t\tselectable: true,\n\n\t\t/**\n\t\t * Are sections sortable?\n\t\t * @type {Bool}\n\t\t */\n\t\tsortable: true,\n\n\t\tsortableOptions: {\n\t\t\taxis: false,\n\t\t\tcursor: 'move',\n\t\t\thandle: '.drag-section',\n\t\t\titems: '.llms-section',\n\t\t\tplaceholder: 'llms-section llms-sortable-placeholder',\n\t\t},\n\n\t\tsortable_start: function( collection ) {\n\t\t\tthis.$el.addClass( 'dragging' );\n\t\t},\n\n\t\tsortable_stop: function( collection ) {\n\t\t\tthis.$el.removeClass( 'dragging' );\n\t\t},\n\n\t}, Receivable ) );\n\n} );\n\n","/**\n * Single Course View\n * @since 3.13.0\n * @version 3.16.0\n */\ndefine( 'Views/Course',[ 'Views/SectionList', 'Views/_Editable' ], function( SectionListView, Editable ) {\n\n\treturn Backbone.View.extend( _.defaults( {\n\n\t\t/**\n\t\t * Get default attributes for the html wrapper element\n\t\t * @return obj\n\t\t * @since 3.13.0\n\t\t * @version 3.13.0\n\t\t */\n\t\tattributes: function() {\n\t\t\treturn {\n\t\t\t\t'data-id': this.model.id,\n\t\t\t};\n\t\t},\n\n\t\t/**\n\t\t * HTML element selector\n\t\t * @type {String}\n\t\t */\n\t\tel: '#llms-builder-main',\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'div',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-course-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.13.0\n\t\t * @version 3.13.0\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\tvar self = this;\n\n\t\t\t// this.listenTo( this.model, 'sync', this.render );\n\t\t\tthis.render();\n\n\t\t\tthis.sectionListView = new SectionListView( {\n\t\t\t\tcollection: this.model.get( 'sections' ),\n\t\t\t} );\n\t\t\tthis.sectionListView.render();\n\t\t\t// drag and drop start\n\t\t\tthis.sectionListView.on( 'sortStart', this.sectionListView.sortable_start );\n\t\t\t// drag and drop stop\n\t\t\tthis.sectionListView.on( 'sortStop', this.sectionListView.sortable_stop );\n\t\t\t// selection changes\n\t\t\tthis.sectionListView.on( 'selectionChanged', this.active_section_change );\n\t\t\t// \"select\" a section when it's added to the course\n\t\t\tthis.listenTo( this.model.get( 'sections'), 'add', this.on_section_add );\n\n\t\t\tBackbone.pubSub.on( 'section-toggle', this.on_section_toggle, this );\n\n\t\t\tBackbone.pubSub.on( 'expand-section', this.expand_section, this );\n\n\t\t\tBackbone.pubSub.on( 'lesson-selected', this.active_lesson_change, this );\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.13.0\n\t\t * @version 3.13.0\n\t\t */\n\t\trender: function() {\n\t\t\tthis.$el.html( this.template( this.model ) );\n\t\t\treturn this;\n\t\t},\n\n\t\tactive_lesson_change: function( model ) {\n\n\t\t\t// set parent section to be active\n\t\t\tvar section = this.model.get( 'sections' ).get( model.get( 'parent_section' ) );\n\t\t\tthis.sectionListView.setSelectedModel( section );\n\n\t\t},\n\n\t\t/**\n\t\t * When a section \"selection\" changes in the list\n\t\t * Update each section model so we can figure out which one is selected from other views\n\t\t * @param array current array of selected models\n\t\t * @param array previous array of previously selected models\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tactive_section_change: function( current, previous ) {\n\n\t\t\t_.each( current, function( model ) {\n\t\t\t\tmodel.set( '_selected', true );\n\t\t\t} );\n\n\t\t\t_.each( previous, function( model ) {\n\t\t\t\tmodel.set( '_selected', false );\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * \"Selects\" the new section when it's added to the course\n\t\t * @param obj model Section model that's just been added\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\ton_section_add: function( model ) {\n\n\t\t\tthis.sectionListView.setSelectedModel( model );\n\n\t\t},\n\n\t\t/**\n\t\t * When expanding/collapsing sections\n\t\t * if collapsing, unselect, if expanding, select\n\t\t * @param obj model toggled section\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\ton_section_toggle: function( model ) {\n\n\t\t\tvar selected = model.get( '_expanded' ) ? [ model ] : [];\n\t\t\tthis.sectionListView.setSelectedModels( selected );\n\n\t\t}\n\n\t}, Editable ) );\n\n} );\n\n","/**\n * Model settings fields view\n * @since 3.17.0\n * @version 3.17.7\n */\ndefine( 'Views/SettingsFields',[], function() {\n\n\treturn Backbone.View.extend( _.defaults( {\n\n\t\t/**\n\t\t * DOM events\n\t\t * @type {Object}\n\t\t */\n\t\tevents: {\n\t\t\t'click .llms-settings-group-toggle': 'toggle_group',\n\t\t},\n\n\t\t/**\n\t\t * Processed fields data\n\t\t * Allows access by ID without traversing the schema\n\t\t * @type {Object}\n\t\t */\n\t\tfields: {},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'div',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-settings-fields-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\t// initialize: function() {},\n\n\t\t/**\n\t\t * Retrieve an array of all editor fields in all groups\n\t\t * @return array\n\t\t * @since 3.17.1\n\t\t * @version 3.17.1\n\t\t */\n\t\tget_editor_fields: function() {\n\t\t\treturn _.filter( this.fields, function( field ) {\n\t\t\t\treturn this.is_editor_field( field.type );\n\t\t\t}, this );\n\t\t},\n\n\t\t/**\n\t\t * Get settings group data from a model\n\t\t * @return {[type]}\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tget_groups: function() {\n\n\t\t\treturn this.model.get_settings_fields();\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if a settings group is hidden in localStorage\n\t\t * @param string group_id id of the group\n\t\t * @return {Boolean}\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tis_group_hidden: function( group_id ) {\n\n\t\t\tvar id = 'llms-' + this.model.get( 'type' ) + '-settings-group--' + group_id;\n\n\t\t\tif ( 'undefined' !== window.localStorage ) {\n\t\t\t\treturn ( 'hidden' === window.localStorage.getItem( id ) );\n\t\t\t}\n\n\t\t\treturn false;\n\n\t\t},\n\n\t\t/**\n\t\t * Get the switch attribute for a field with switches\n\t\t * @param obj field field data obj\n\t\t * @return string\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tget_switch_attribute: function( field ) {\n\n\t\t\treturn field.switch_attribute ? field.switch_attribute : field.attribute;\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if a field has a switch\n\t\t * @param string type field type string\n\t\t * @return {Boolean}\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\thas_switch: function( type ) {\n\t\t\treturn ( -1 !== type.indexOf( 'switch' ) );\n\t\t},\n\n\t\t/**\n\t\t * Determine if a field is a default (text) field\n\t\t * @param string type field type string\n\t\t * @return {Boolean}\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tis_default_field: function( type ) {\n\n\t\t\tvar types = [ 'audio_embed', 'datepicker', 'number', 'text', 'video_embed' ];\n\t\t\treturn ( -1 !== types.indexOf( type.replace( 'switch-', '' ) ) );\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if a field is a WYSIWYG editor field\n\t\t * @param string type field type string\n\t\t * @return {Boolean}\n\t\t * @since 3.17.1\n\t\t * @version 3.17.1\n\t\t */\n\t\tis_editor_field: function( type ) {\n\n\t\t\tvar types = [ 'editor', 'switch-editor' ];\n\t\t\treturn ( -1 !== types.indexOf( type.replace( 'switch-', '' ) ) );\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if a switch is enabled for a field\n\t\t * @param obj field field data object\n\t\t * @return {Boolean}\n\t\t * @since 3.17.0\n\t\t * @version 3.17.6\n\t\t */\n\t\tis_switch_condition_met: function( field ) {\n\n\t\t\treturn ( field.switch_on === this.model.get( field.switch_attribute ) );\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.17.0\n\t\t * @version 3.17.1\n\t\t */\n\t\trender: function() {\n\n\t\t\tthis.$el.html( this.template( this ) );\n\n\t\t\t// if editors exist, render them\n\t\t\t_.each( this.get_editor_fields(), function( field ) {\n\t\t\t\tthis.render_editor( field );\n\t\t\t}, this );\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\t/**\n\t\t * Renders an editor field\n\t\t * @param obj field field data object\n\t\t * @return void\n\t\t * @since 3.17.1\n\t\t * @version 3.17.1\n\t\t */\n\t\trender_editor: function( field ) {\n\n\t\t\tvar self = this;\n\n\t\t\twp.editor.remove( field.id );\n\t\t\tfield.settings.tinymce.setup = function( editor ) {\n\n\t\t\t\tvar $ed = $( '#' + editor.id ),\n\t\t\t\t\t$parent = $ed.closest( '.llms-editable-editor' ),\n\t\t\t\t\t$label = $parent.find( '.llms-label' ),\n\t\t\t\t\tprop = $ed.attr( 'data-attribute' )\n\n\t\t\t\tif ( $label.length ) {\n\t\t\t\t\t$label.prependTo( $parent.find( '.wp-editor-tools' ) );\n\t\t\t\t}\n\n\t\t\t\t// save changes to the model via Visual ed\n\t\t\t\teditor.on( 'change', function( event ) {\n\t\t\t\t\tself.model.set( prop, wp.editor.getContent( editor.id ) );\n\t\t\t\t} );\n\n\t\t\t\t// save changes via Text ed\n\t\t\t\t$ed.on( 'input', function( event ) {\n\t\t\t\t\tself.model.set( prop, $ed.val() );\n\t\t\t\t} );\n\n\t\t\t\t// trigger an input on the Text ed when quicktags buttons are clicked\n\t\t\t\t$parent.on( 'click', '.quicktags-toolbar .ed_button', function() {\n\t\t\t\t\tsetTimeout( function() {\n\t\t\t\t\t\t$ed.trigger( 'input' );\n\t\t\t\t\t}, 10 );\n\t\t\t\t} );\n\t\t\t};\n\n\t\t\twp.editor.initialize( field.id, field.settings );\n\n\t\t},\n\n\t\t/**\n\t\t * Get the HTML for a select field\n\t\t * @param obj options flat or multi-dimensional options object\n\t\t * @param string attribute name of the select field's attribute\n\t\t * @return string\n\t\t * @since 3.17.0\n\t\t * @version 3.17.2\n\t\t */\n\t\trender_select_options: function( options, attribute ) {\n\n\t\t\tvar html = '',\n\t\t\t\tselected = this.model.get( attribute );\n\n\t\t\tfunction option_html( label, val ) {\n\n\t\t\t\treturn '' + label + ' ';\n\n\t\t\t}\n\n\t\t\t_.each( options, function( option, index ) {\n\n\t\t\t\t// this will be an key:val object\n\t\t\t\tif ( 'string' === typeof option ) {\n\t\t\t\t\thtml += option_html( option, index );\n\t\t\t\t// either option group or array of key,val objects\n\t\t\t\t} else if ( 'object' === typeof option ) {\n\t\t\t\t\t// option group\n\t\t\t\t\tif ( option.label && option.options ) {\n\t\t\t\t\t\thtml += '';\n\t\t\t\t\t\thtml += this.render_select_options( option.options, attribute );\n\t\t\t\t\t} else {\n\t\t\t\t\t\thtml += option_html( option.val, option.key );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t}, this );\n\n\t\t\treturn html;\n\n\t\t},\n\n\t\t/**\n\t\t * Setup and fill fields with default data based on field type\n\t\t * @param obj orig_field original field as defined in the settings\n\t\t * @param int field_index index of the field in the current row\n\t\t * @return obj\n\t\t * @since 3.17.0\n\t\t * @version 3.17.7\n\t\t */\n\t\tsetup_field: function( orig_field, field_index ) {\n\n\t\t\tvar defaults = {\n\t\t\t\tclasses: [],\n\t\t\t\tid: _.uniqueId( orig_field.attribute + '_' ),\n\t\t\t\tinput_type: 'text',\n\t\t\t\tlabel: '',\n\t\t\t\toptions: {},\n\t\t\t\tplaceholder: '',\n\t\t\t\ttip: '',\n\t\t\t\ttip_position: 'top-right',\n\t\t\t\tsettings: {},\n\t\t\t};\n\n\t\t\t// check the field condition if set\n\t\t\tif ( orig_field.condition && false === _.bind( orig_field.condition, this.model )() ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tswitch ( orig_field.type ) {\n\n\t\t\t\tcase 'audio_embed':\n\t\t\t\t\tdefaults.classes.push( 'llms-editable-audio' );\n\t\t\t\t\tdefaults.placeholder = 'https://';\n\t\t\t\t\tdefaults.tip = LLMS.l10n.translate( 'Use SoundCloud or Spotify audio URLS.' );\n\t\t\t\t\tdefaults.input_type = 'url';\n\t\t\t\tbreak;\n\n\t\t\t\tcase 'datepicker':\n\t\t\t\t\tdefaults.classes.push( 'llms-editable-date' );\n\t\t\t\tbreak;\n\n\t\t\t\tcase 'editor':\n\t\t\t\tcase 'switch-editor':\n\t\t\t\t\tvar orig_settings = orig_field.settings || {};\n\t\t\t\t\tdefaults.settings = $.extend( true, wp.editor.getDefaultSettings(), {\n\t\t\t\t\t\tmediaButtons: true,\n\t\t\t\t\t\ttinymce: {\n\t\t\t\t\t\t\ttoolbar1: 'bold,italic,strikethrough,bullist,numlist,blockquote,hr,alignleft,aligncenter,alignright,link,unlink,wp_adv',\n\t\t\t\t\t\t\ttoolbar2: 'formatselect,underline,alignjustify,forecolor,pastetext,removeformat,charmap,outdent,indent,undo,redo,wp_help',\n\t\t\t\t\t\t}\n\t\t\t\t\t}, orig_settings );\n\t\t\t\tbreak;\n\n\t\t\t\tcase 'number':\n\t\t\t\t\tdefaults.input_type = 'number';\n\t\t\t\tbreak;\n\n\t\t\t\tcase 'permalink':\n\t\t\t\t\tdefaults.label = LLMS.l10n.translate( 'Permalink' );\n\t\t\t\tbreak;\n\n\t\t\t\tcase 'video_embed':\n\t\t\t\t\tdefaults.classes.push( 'llms-editable-video' );\n\t\t\t\t\tdefaults.placeholder = 'https://';\n\t\t\t\t\tdefaults.tip = LLMS.l10n.translate( 'Use YouTube, Vimeo, or Wistia video URLS.' );\n\t\t\t\t\tdefaults.input_type = 'url';\n\t\t\t\tbreak;\n\n\t\t\t}\n\n\t\t\tif ( this.has_switch( orig_field.type ) ) {\n\t\t\t\tdefaults.switch_on = 'yes';\n\t\t\t\tdefaults.switch_off = 'no';\n\t\t\t}\n\n\t\t\tvar field = _.defaults( _.deepClone( orig_field ), defaults );\n\n\t\t\t// if options is a function run it\n\t\t\tif ( _.isFunction( field.options ) ) {\n\t\t\t\tfield.options = _.bind( field.options, this.model )();\n\t\t\t}\n\n\t\t\t// if it's a radio field options values can be submitted as images\n\t\t\t// this will transform those images into html\n\t\t\tif ( -1 !== [ 'radio', 'switch-radio' ].indexOf( orig_field.type ) ) {\n\n\t\t\t\tvar has_images = false;\n\t\t\t\t_.each( orig_field.options, function( val, key ) {\n\t\t\t\t\tif ( -1 !== val.indexOf( '.png' ) || -1 !== val.indexOf( '.jpg' ) ) {\n\t\t\t\t\t\tfield.options[key] = ' ';\n\t\t\t\t\t\thas_images = true;\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t\tif ( has_images ) {\n\t\t\t\t\tfield.classes.push( 'has-images' );\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t// add tooltip position classes\n\t\t\tif ( field.tip ) {\n\t\t\t\tfield.classes.push( 'tip--' + field.tip_position );\n\t\t\t}\n\n\t\t\t// transform classes array to a css class string\n\t\t\tif ( field.classes.length ) {\n\t\t\t\tfield.classes = ' ' + field.classes.join( ' ' );\n\t\t\t}\n\n\t\t\tthis.fields[ field.id ] = field;\n\n\t\t\treturn field;\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if toggling a switch select should rerender the view\n\t\t * @param string field_type field type string\n\t\t * @return boolean\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tshould_rerender_on_toggle: function( field_type ) {\n\n\t\t\treturn ( -1 !== field_type.indexOf( 'switch-' ) ) ? 'yes' : 'no';\n\n\t\t},\n\n\t\t/**\n\t\t * Click event for toggling visibility of settings groups\n\t\t * If localStorage is available, persist state\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\ttoggle_group: function( event ) {\n\n\t\t\tevent.preventDefault();\n\n\t\t\tvar $el = $( event.currentTarget ),\n\t\t\t\t$group = $el.closest( '.llms-model-settings' );\n\n\t\t\t$group.toggleClass( 'hidden' );\n\n\t\t\tif ( 'undefined' !== window.localStorage ) {\n\n\t\t\t\tvar id = $group.attr( 'id' );\n\t\t\t\tif ( $group.hasClass( 'hidden' ) ) {\n\t\t\t\t\twindow.localStorage.setItem( id, 'hidden' );\n\t\t\t\t} else {\n\t\t\t\t\twindow.localStorage.removeItem( id );\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t},\n\n\t} ) );\n\n} );\n\n","/**\n * Lesson Editor (Sidebar) View\n * @since 3.17.0\n * @version 3.17.0\n */\ndefine( 'Views/LessonEditor',[\n\t\t'Views/_Detachable',\n\t\t'Views/_Editable',\n\t\t'Views/_Trashable',\n\t\t'Views/_Subview',\n\t\t'Views/SettingsFields'\n\t], function(\n\t\tDetachable,\n\t\tEditable,\n\t\tTrashable,\n\t\tSubview,\n\t\tSettingsFields\n\t) {\n\n\treturn Backbone.View.extend( _.defaults( {\n\n\t\t/**\n\t\t * Current view state\n\t\t * @type {String}\n\t\t */\n\t\tstate: 'default',\n\n\t\t/**\n\t\t * Current Subviews\n\t\t * @type {Object}\n\t\t */\n\t\tviews: {\n\t\t\tsettings: {\n\t\t\t\tclass: SettingsFields,\n\t\t\t\tinstance: null,\n\t\t\t\tstate: 'default',\n\t\t\t},\n\t\t},\n\n\t\tel: '#llms-editor-lesson',\n\n\t\t/**\n\t\t * Events\n\t\t * @type {Object}\n\t\t */\n\t\tevents: _.defaults( {}, Detachable.events, Editable.events, Trashable.events ),\n\n\t\t/**\n\t\t * Template function\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-lesson-settings-template' ),\n\n\t\t/**\n\t\t * Init\n\t\t * @param obj data parent template data\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tinitialize: function( data ) {\n\n\t\t\tthis.model = data.lesson;\n\n\t\t\tvar change_events = [\n\t\t\t\t'change:date_available',\n\t\t\t\t'change:drip_method',\n\t\t\t\t'change:time_available',\n\t\t\t];\n\t\t\t_.each( change_events, function( event ) {\n\t\t\t\tthis.listenTo( this.model, event, this.render );\n\t\t\t}, this );\n\n\t\t\t// when the \"has_prerequisite\" attr is toggled ON\n\t\t\t// trigger the prereq select object to set the default (first available) prereq for the lesson\n\t\t\tthis.listenTo( this.model, 'change:has_prerequisite', function( lesson, val ) {\n\t\t\t\tif ( 'yes' === val ) {\n\t\t\t\t\tthis.$el.find( 'select[name=\"prerequisite\"]' ).trigger( 'change' );\n\t\t\t\t}\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * Render the view\n\t\t * @return obj\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\trender: function() {\n\n\t\t\tthis.$el.html( this.template( this.model ) );\n\n\t\t\tthis.remove_subview( 'settings' );\n\n\t\t\tthis.render_subview( 'settings', {\n\t\t\t\tel: '#llms-lesson-settings-fields',\n\t\t\t\tmodel: this.model,\n\t\t\t} );\n\n\t\t\tthis.init_datepickers();\n\t\t\tthis.init_selects();\n\n\t\t\treturn this;\n\n\t\t},\n\n\t}, Detachable, Editable, Trashable, Subview, SettingsFields ) );\n\n} );\n\n","/**\n * Single Quiz View\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Views/Popover',[], function() {\n\n\treturn Backbone.View.extend( {\n\n\t\tdefaults: {\n\t\t\tplacement: 'auto',\n\t\t\t// container: document.body,\n\t\t\twidth: 'auto',\n\t\t\ttrigger: 'manual',\n\t\t\tstyle: 'light',\n\t\t\tanimation: 'pop',\n\t\t\ttitle: '',\n\t\t\tcontent: '',\n\t\t\tcloseable: false,\n\t\t\tbackdrop: false,\n\t\t\tonShow: function( $el ) {},\n\t\t\tonHide: function( $el ) {},\n\t\t},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'div',\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.14.1\n\t\t * @version 3.14.1\n\t\t */\n\t\tinitialize: function( data ) {\n\n\t\t\tif ( this.$el.length ) {\n\t\t\t\tthis.defaults.container = this.$el.parent();\n\t\t\t}\n\n\t\t\tthis.args = _.defaults( data.args, this.defaults );\n\t\t\tthis.render();\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender: function() {\n\n\t\t\tthis.$el.webuiPopover( this.args );\n\t\t\treturn this;\n\n\t\t},\n\n\t\t/**\n\t\t * Hide the popover\n\t\t * @return self (for chaining)\n\t\t * @since 3.16.0\n\t\t * @version 3.16.12\n\t\t */\n\t\thide: function() {\n\n\t\t\tthis.$el.webuiPopover( 'hide' );\n\t\t\treturn this;\n\n\t\t},\n\n\t\t/**\n\t\t * Show the popover\n\t\t * @return self (for chaining)\n\t\t * @since 3.16.0\n\t\t * @version 3.16.12\n\t\t */\n\t\tshow: function() {\n\n\t\t\tthis.$el.webuiPopover( 'show' );\n\t\t\treturn this;\n\n\t\t},\n\n\t} );\n\n} );\n\n","/**\n * Post Popover Serach content View\n * @since 3.16.0\n * @version 3.17.0\n */\ndefine( 'Views/PostSearch',[], function() {\n\n\treturn Backbone.View.extend( {\n\n\t\t/**\n\t\t * DOM Events\n\t\t * @type obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tevents: {\n\t\t\t'select2:select': 'add_post',\n\t\t},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'select',\n\n\t\t/**\n\t\t * Initializer\n\t\t * @param obj data customize the search box with data\n\t\t * @return void\n\t\t * @since 3.16.12\n\t\t * @version 3.16.12\n\t\t */\n\t\tinitialize: function( data ) {\n\n\t\t\tthis.post_type = data.post_type;\n\t\t\tthis.searching_message = data.searching_message || LLMS.l10n.translate( 'Searching...' );\n\n\t\t},\n\n\t\t/**\n\t\t * Select event, adds the existing lesson to the course\n\t\t * @param obj event select2:select event object\n\t\t * @since 3.16.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tadd_post: function( event ) {\n\n\t\t\tvar type = this.$el.attr( 'data-post-type' );\n\n\t\t\tBackbone.pubSub.trigger( type.replace( 'llms_', '' ) + '-search-select', event.params.data, event );\n\t\t\tthis.$el.val( null ).trigger( 'change' );\n\n\t\t},\n\n\t\t/**\n\t\t * Render the section\n\t\t * Initalizes a new collection and views for all lessons in the section\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.12\n\t\t */\n\t\trender: function() {\n\t\t\tvar self = this;\n\t\t\tsetTimeout( function () {\n\t\t\t\tself.$el.llmsSelect2( {\n\t\t\t\t\tajax: {\n\t\t\t\t\t\tdataType: 'JSON',\n\t\t\t\t\t\tdelay: 250,\n\t\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\t\turl: window.ajaxurl,\n\t\t\t\t\t\tdata: function( params ) {\n\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\taction: 'llms_builder',\n\t\t\t\t\t\t\t\taction_type: 'search',\n\t\t\t\t\t\t\t\tcourse_id: window.llms_builder.course.id,\n\t\t\t\t\t\t\t\tpost_type: self.post_type,\n\t\t\t\t\t\t\t\tterm: params.term,\n\t\t\t\t\t\t\t\tpage: params.page,\n\t\t\t\t\t\t\t\t_ajax_nonce: wp_ajax_data.nonce,\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t},\n\t\t\t\t\t\t// error: function( xhr, status, error ) {\n\t\t\t\t\t\t// \tconsole.log( status, error );\n\t\t\t\t\t\t// },\n\t\t\t\t\t},\n\t\t\t\t\tdropdownParent: $( '.wrap.lifterlms.llms-builder' ),\n\t\t\t\t\t// don't escape html from render_result\n\t\t\t\t\tescapeMarkup: function( markup ) {\n\t\t\t\t\t\treturn markup;\n\t\t\t\t\t},\n\t\t\t\t\tplaceholder: self.searching_message,\n\t\t\t\t\ttemplateResult: self.render_result,\n\t\t\t\t\twidth: '100%',\n\t\t\t\t} );\n\t\t\t\tself.$el.attr( 'data-post-type', self.post_type );\n\t\t\t}, 0 );\n\t\t\treturn this;\n\n\t\t},\n\n\t\t/**\n\t\t * Render a nicer UI for each search result in the in the Select2 search results\n\t\t * @param object res result data\n\t\t * @return string\n\t\t * @since 3.16.0\n\t\t * @version 3.16.12\n\t\t */\n\t\trender_result: function( res ) {\n\n\t\t\tvar $html = $( '
' );\n\n\t\t\tif ( res.loading ) {\n\t\t\t\treturn $html.append( res.text );\n\t\t\t}\n\n\t\t\tvar $side = $( '' ),\n\t\t\t\t$main = $( '
' );\n\t\t\t\ticon = ( 'attach' === res.action ) ? 'paperclip' : 'clone',\n\t\t\t\ttext = ( 'attach' === res.action ) ? LLMS.l10n.translate( 'Attach' ) : LLMS.l10n.translate( 'Clone' );\n\n\t\t\t$side.append( '' + text + ' ' );\n\n\t\t\t$main.append( '' + res.data.title + ' ' );\n\t\t\t$main.append( '' + LLMS.l10n.translate( 'ID' ) + ': ' + res.data.id + ' ' );\n\n\t\t\t_.each( res.parents, function( parent ) {\n\t\t\t\t$main.append( '' + parent + ' ' );\n\t\t\t} );\n\n\t\t\treturn $html.append( $side ).append( $main );\n\n\t\t},\n\n\t} );\n\n} );\n\n","/**\n * Single Lesson View\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Views/QuestionType',[ ], function() {\n\n\treturn Backbone.View.extend( {\n\n\t\t/**\n\t\t * HTML class names\n\t\t * @type {String}\n\t\t */\n\t\tclassName: 'llms-question-type',\n\n\t\tevents: {\n\t\t\t'click .llms-add-question': 'add_question',\n\t\t},\n\n\t\t/**\n\t\t * HTML element wrapper ID attribute\n\t\t * @return string\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tid: function() {\n\t\t\treturn 'llms-question-type-' + this.model.id;\n\t\t},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'li',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-question-type-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\tthis.render();\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender: function() {\n\t\t\tthis.$el.html( this.template( this.model ) );\n\t\t\treturn this;\n\t\t},\n\n\t\t/**\n\t\t * Add a question of the selected type to the current quiz\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tadd_question: function() {\n\n\t\t\tthis.quiz.add_question( {\n\t\t\t\t_expanded: true,\n\t\t\t\tchoices: this.model.get( 'default_choices' ) ? this.model.get( 'default_choices' ) : null,\n\t\t\t\tquestion_type: this.model,\n\t\t\t} );\n\n\t\t\tthis.quiz.trigger( 'new-question-added' );\n\n\t\t},\n\n\t\t// filter: function( term ) {\n\n\t\t// \tvar words = this.model.get_keywords().map( function( word ) {\n\t\t// \t\treturn word.toLowerCase();\n\t\t// \t} );\n\n\t\t// \tterm = term.toLowerCase();\n\n\t\t// \tif ( -1 === words.indexOf( term ) ) {\n\t\t// \t\tthis.$el.addClass( 'filtered' );\n\t\t// \t} else {\n\t\t// \t\tthis.$el.removeClass( 'filtered' );\n\t\t// \t}\n\n\t\t// },\n\n\t\t// clear_filter: function() {\n\t\t// \tthis.$el.removeClass( 'filtered' );\n\t\t// }\n\n\t} );\n\n} );\n\n","/**\n * Quiz question bank view\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Views/QuestionBank',[ 'Views/QuestionType' ], function( QuestionView ) {\n\n\treturn Backbone.CollectionView.extend( {\n\n\t\tclassName: 'llms-question',\n\n\t\t/**\n\t\t * Parent element\n\t\t * @type {String}\n\t\t */\n\t\tel: '#llms-question-bank',\n\n\t\t/**\n\t\t * Section model\n\t\t * @type {[type]}\n\t\t */\n\t\tmodelView: QuestionView,\n\n\t\t/**\n\t\t * Are sections selectable?\n\t\t * @type {Bool}\n\t\t */\n\t\tselectable: false,\n\n\t\t/**\n\t\t * Are sections sortable?\n\t\t * @type {Bool}\n\t\t */\n\t\tsortable: false,\n\n\t} );\n\n} );\n\n","/**\n * Single Question Choice View\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Views/QuestionChoice',[ 'Views/_Editable', ], function( Editable ) {\n\n\treturn Backbone.View.extend( _.defaults( {\n\n\t\t/**\n\t\t * HTML class names\n\t\t * @type {String}\n\t\t */\n\t\tclassName: 'llms-question-choice',\n\n\t\tevents: _.defaults( {\n\t\t\t'change input[name=\"correct\"]': 'toggle_correct',\n\t\t\t'click .llms-action-icon[href=\"#llms-add-choice\"]': 'add_choice',\n\t\t\t'click .llms-action-icon[href=\"#llms-del-choice\"]': 'del_choice',\n\t\t}, Editable.events ),\n\n\t\t/**\n\t\t * HTML element wrapper ID attribute\n\t\t * @return string\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tid: function() {\n\t\t\treturn 'llms-question-choice-' + this.model.id;\n\t\t},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'li',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-question-choice-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.14.1\n\t\t * @version 3.14.1\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\tthis.render();\n\n\t\t\tthis.listenTo( this.model.collection, 'add', this.maybe_disable_buttons );\n\t\t\tthis.listenTo( this.model, 'change', this.render );\n\n\t\t\tif ( 'image' === this.model.get( 'choice_type' ) ) {\n\t\t\t\tthis.listenTo( this.model.get( 'choice' ), 'change', this.render );\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender: function() {\n\t\t\tthis.$el.html( this.template( this.model ) );\n\t\t\treturn this;\n\t\t},\n\n\t\t/**\n\t\t * Add a new choice to the current choice list\n\t\t * Adds *after* the clicked choice\n\t\t * @param obj event JS event object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tadd_choice: function( event ) {\n\n\t\t\tevent.stopPropagation();\n\t\t\tevent.preventDefault();\n\n\t\t\tvar index = this.model.collection.indexOf( this.model );\n\t\t\tthis.model.collection.parent.add_choice( {}, {\n\t\t\t\tat: index + 1,\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * Delete the choice from the choice list & ensure there's at least one correct choice\n\t\t * @param obj event js event obj\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tdel_choice: function( event ) {\n\n\t\t\tevent.preventDefault();\n\t\t\tBackbone.pubSub.trigger( 'model-trashed', this.model );\n\t\t\tthis.model.collection.remove( this.model );\n\n\t\t},\n\n\t\t/**\n\t\t * When the correct answer input changes sync status to model\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\ttoggle_correct: function() {\n\n\t\t\tvar correct = this.$el.find( 'input[name=\"correct\"]' ).is( ':checked' );\n\t\t\tthis.model.set( 'correct', correct );\n\t\t\tthis.model.collection.trigger( 'correct-update', this.model );\n\n\t\t},\n\n\t}, Editable ) );\n\n} );\n\n","/**\n * Quiz question bank view\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Views/QuestionChoiceList',[ 'Views/QuestionChoice' ], function( ChoiceView ) {\n\n\treturn Backbone.CollectionView.extend( {\n\n\t\tclassName: 'llms-quiz-questions',\n\n\t\t/**\n\t\t * Choice model view\n\t\t * @type {[type]}\n\t\t */\n\t\tmodelView: ChoiceView,\n\n\t\t/**\n\t\t * Enable keyboard events\n\t\t * @type {Bool}\n\t\t */\n\t\tprocessKeyEvents: false,\n\n\t\t/**\n\t\t * Are sections selectable?\n\t\t * @type {Bool}\n\t\t */\n\t\tselectable: false,\n\n\t\t/**\n\t\t * Are sections sortable?\n\t\t * @type {Bool}\n\t\t */\n\t\tsortable: true,\n\n\t\tsortableOptions: {\n\t\t\taxis: false,\n\t\t\t// connectWith: '.llms-lessons',\n\t\t\tcursor: 'move',\n\t\t\thandle: '.llms-choice-id',\n\t\t\titems: '.llms-question-choice',\n\t\t\tplaceholder: 'llms-question-choice llms-sortable-placeholder',\n\t\t},\n\n\t\tsortable_start: function( model ) {\n\t\t\tthis.$el.addClass( 'dragging' );\n\t\t},\n\n\t\tsortable_stop: function( model ) {\n\t\t\tthis.$el.removeClass( 'dragging' );\n\t\t},\n\n\t} );\n\n} );\n\n","/**\n * Single Question View\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Views/Question',[\n\t\t'Views/_Editable',\n\t\t'Views/QuestionChoiceList'\n\t], function(\n\t\tEditable,\n\t\tChoiceListView\n\t) {\n\n\treturn Backbone.View.extend( _.defaults( {\n\n\t\t/**\n\t\t * Generate CSS classes for the question\n\t\t * @return string\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tclassName: function() {\n\t\t\treturn 'llms-question qtype--' + this.model.get( 'question_type' ).get( 'id' );\n\t\t},\n\n\t\tevents: _.defaults( {\n\t\t\t'click .clone--question': 'clone',\n\t\t\t'click .delete--question': 'delete',\n\t\t\t'click .expand--question': 'expand',\n\t\t\t'click .collapse--question': 'collapse',\n\t\t\t'change input[name=\"question_points\"]': 'update_points',\n\t\t}, Editable.events ),\n\n\t\t/**\n\t\t * HTML element wrapper ID attribute\n\t\t * @return string\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tid: function() {\n\t\t\treturn 'llms-question-' + this.model.id;\n\t\t},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'li',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-question-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\tvar change_events = [\n\t\t\t\t'change:_expanded',\n\t\t\t\t'change:menu_order',\n\t\t\t];\n\t\t\t_.each( change_events, function( event ) {\n\t\t\t\tthis.listenTo( this.model, event, this.render );\n\t\t\t}, this );\n\n\t\t\tthis.listenTo( this.model.get( 'image' ), 'change', this.render );\n\n\t\t\tthis.listenTo( this.model.get_parent(), 'change:_points', this.render_points_percentage );\n\n\t\t\tthis.on( 'multi_choices_toggle', this.multi_choices_toggle, this );\n\n\t\t\tBackbone.pubSub.on( 'del-question-choice', this.del_choice, this );\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender: function() {\n\n\t\t\tthis.$el.html( this.template( this.model ) );\n\n\t\t\tif ( this.model.get( 'question_type').get( 'choices' ) ) {\n\n\t\t\t\tthis.choiceListView = new ChoiceListView( {\n\t\t\t\t\tel: this.$el.find( '.llms-question-choices' ),\n\t\t\t\t\tcollection: this.model.get( 'choices' ),\n\t\t\t\t} );\n\t\t\t\tthis.choiceListView.render();\n\t\t\t\tthis.choiceListView.on( 'sortStart', this.choiceListView.sortable_start );\n\t\t\t\tthis.choiceListView.on( 'sortStop', this.choiceListView.sortable_stop );\n\n\t\t\t}\n\n\t\t\tif ( 'group' === this.model.get( 'question_type' ).get( 'id' ) ) {\n\n\t\t\t\tvar self = this;\n\t\t\t\tsetTimeout( function() {\n\t\t\t\t\tself.questionListView = self.collectionListView.quiz.get_question_list( {\n\t\t\t\t\t\tel: self.$el.find( '.llms-quiz-questions' ),\n\t\t\t\t\t\tcollection: self.model.get( 'questions' ),\n\t\t\t\t\t} );\n\t\t\t\t\tself.questionListView.render();\n\t\t\t\t\tself.questionListView.on( 'sortStart', self.questionListView.sortable_start );\n\t\t\t\t\tself.questionListView.on( 'sortStop', self.questionListView.sortable_stop );\n\t\t\t\t}, 1 );\n\n\t\t\t}\n\n\t\t\tif ( this.model.get( 'description_enabled' ) ) {\n\t\t\t\tthis.init_editor( 'question-desc--' + this.model.get( 'id' ) );\n\t\t\t}\n\n\t\t\tif ( this.model.get( 'clarifications_enabled' ) ) {\n\t\t\t\tthis.init_editor( 'question-clarifications--' + this.model.get( 'id' ), {\n\t\t\t\t\tmediaButtons: false,\n\t\t\t\t\ttinymce: {\n\t\t\t\t\t\ttoolbar1: 'bold,italic,strikethrough,bullist,numlist,alignleft,aligncenter,alignright',\n\t\t\t\t\t\ttoolbar2: '',\n\t\t\t\t\t\tsetup: _.bind( this.on_editor_ready, this ),\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\tthis.init_formatting_els();\n\t\t\tthis.init_selects();\n\n\t\t\treturn this;\n\t\t},\n\n\t\t/**\n\t\t * rerender points percentage when question points are updated\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender_points_percentage: function() {\n\n\t\t\tthis.$el.find( '.llms-question-points' ).attr( 'data-tip', this.model.get_points_percentage() );\n\n\t\t},\n\n\t\t/**\n\t\t * Click event to duplicate a question within a quiz\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tclone: function( event ) {\n\n\t\t\tevent.stopPropagation();\n\t\t\tevent.preventDefault();\n\t\t\tthis.model.collection.add( this._get_question_clone( this.model ) );\n\n\t\t},\n\n\t\t/**\n\t\t * Recursive clone function which will correctly clone children of a question\n\t\t * @param obj question queston model\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\t_get_question_clone: function( question ) {\n\n\t\t\t// create a duplicate\n\t\t\tvar clone = _.clone( question.attributes );\n\n\t\t\t// remove id (we want the duplicate to have a temp id)\n\t\t\tdelete clone.id;\n\n\t\t\tclone.parent_id = question.get( 'id' );\n\n\t\t\t// set the question type ID\n\t\t\tclone.question_type = question.get( 'question_type' ).get( 'id' );\n\n\t\t\t// clone the image attributes seperately\n\t\t\tclone.image = _.clone( question.get( 'image' ).attributes );\n\n\t\t\t// if it has choices clone all the choices\n\t\t\tif ( question.get( 'choices' ) ) {\n\n\t\t\t\tclone.choices = [];\n\n\t\t\t\tquestion.get( 'choices' ).each( function ( choice ) {\n\n\t\t\t\t\tvar choice_clone = _.clone( choice.attributes );\n\t\t\t\t\tdelete choice_clone.id;\n\t\t\t\t\tdelete choice_clone.question_id;\n\n\t\t\t\t\tclone.choices.push( choice_clone );\n\n\t\t\t\t} );\n\n\t\t\t}\n\n\t\t\tif ( 'group' === question.get( 'question_type' ).get( 'id' ) ) {\n\n\t\t\t\tclone.questions = [];\n\t\t\t\tquestion.get( 'questions' ).each( function( child ) {\n\t\t\t\t\tclone.questions.push( this._get_question_clone( child ) );\n\t\t\t\t}, this );\n\n\t\t\t}\n\n\t\t\treturn clone;\n\n\t\t},\n\n\t\t/**\n\t\t * Collapse a question and hide it's settings\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tcollapse: function() {\n\n\t\t\tthis.model.set( '_expanded', false );\n\n\t\t},\n\n\t\t/**\n\t\t * Delete the question from a quiz / question group\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tdelete: function( event ) {\n\n\t\t\tevent.preventDefault();\n\n\t\t\tif ( window.confirm( LLMS.l10n.translate( 'Are you sure you want to delete this question?' ) ) ) {\n\n\t\t\t\tthis.model.collection.remove( this.model );\n\t\t\t\tBackbone.pubSub.trigger( 'model-trashed', this.model );\n\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Click event to reveal a question's settings & choices\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\texpand: function() {\n\n\t\t\tthis.model.set( '_expanded', true );\n\n\t\t},\n\n\t\t/**\n\t\t * When toggling multiple correct answers *off* remove all correct choices except the first correct choice in the list\n\t\t * @param string val value of the question's `multi_choice` attr [yes|no]\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tmulti_choices_toggle: function( val ) {\n\n\t\t\tif ( 'yes' === val ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis.model.get( 'choices' ).update_correct( _.first( this.model.get( 'choices' ).get_correct() ) );\n\n\t\t},\n\n\t\t/**\n\t\t * Update the model's points when the value of the points input is updated\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tupdate_points: function() {\n\n\t\t\tthis.model.set( 'points', this.$el.find( 'input[name=\"question_points\"]' ).val() * 1 );\n\n\t\t}\n\n\t}, Editable ) );\n\n} );\n\n","/**\n * Quiz question bank view\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Views/QuestionList',[ 'Views/Question' ], function( QuestionView ) {\n\n\treturn Backbone.CollectionView.extend( {\n\n\t\tclassName: 'llms-quiz-questions',\n\n\t\t/**\n\t\t * Parent element\n\t\t * @type {String}\n\t\t */\n\t\t// el: '#llms-quiz-questions',\n\n\t\t/**\n\t\t * Section model\n\t\t * @type {[type]}\n\t\t */\n\t\tmodelView: QuestionView,\n\n\t\t/**\n\t\t * Enable keyboard events\n\t\t * @type {Bool}\n\t\t */\n\t\tprocessKeyEvents: false,\n\n\t\t/**\n\t\t * Are sections selectable?\n\t\t * @type {Bool}\n\t\t */\n\t\tselectable: false,\n\n\t\t/**\n\t\t * Are sections sortable?\n\t\t * @type {Bool}\n\t\t */\n\t\tsortable: true,\n\n\t\tsortableOptions: {\n\t\t\taxis: false,\n\t\t\tconnectWith: '.llms-quiz-questions',\n\t\t\tcursor: 'move',\n\t\t\thandle: '.llms-data-stamp',\n\t\t\titems: '.llms-question',\n\t\t\tplaceholder: 'llms-question llms-sortable-placeholder',\n\t\t},\n\n\t\t/**\n\t\t * Highlight drop areas when dragging starts\n\t\t * @param obj model model being sorted\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tsortable_start: function( model ) {\n\t\t\tvar selector = 'group' === model.get( 'question_type' ).get( 'id' ) ? '.llms-editor-tab > .llms-quiz-questions' : '.llms-quiz-questions';\n\t\t\t$( selector ).addClass( 'dragging' );\n\t\t},\n\n\t\t/**\n\t\t * Remove highlights when dragging stops\n\t\t * @param obj model model being sorted\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tsortable_stop: function() {\n\t\t\t$( '.llms-quiz-questions' ).removeClass( 'dragging' );\n\t\t},\n\n\t\t/**\n\t\t * Overrides receive to ensure that question groups can't be moved into queston groups\n\t\t * @param obj event js event object\n\t\t * @param obj ui jQuery UI Sortable ui object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\t_receive : function( event, ui ) {\n\n\t\t\tevent.stopPropagation();\n\n\t\t\t// prevent moving a question group into a question group\n\t\t\tif ( ui.item.hasClass( 'qtype--group' ) && $( event.target ).closest( '.qtype--group' ).length ) {;\n\t\t\t\tui.sender.sortable( 'cancel' );\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar senderListEl = ui.sender;\n\t\t\tvar senderCollectionListView = senderListEl.data( \"view\" );\n\t\t\tif( ! senderCollectionListView || ! senderCollectionListView.collection ) return;\n\n\t\t\tvar newIndex = this._getContainerEl().children().index( ui.item );\n\t\t\tvar modelReceived = senderCollectionListView.collection.get( ui.item.attr( \"data-model-cid\" ) );\n\t\t\tsenderCollectionListView.collection.remove( modelReceived );\n\t\t\tthis.collection.add( modelReceived, { at : newIndex } );\n\t\t\tmodelReceived.collection = this.collection; // otherwise will not get properly set, since modelReceived.collection might already have a value.\n\t\t\tthis.setSelectedModel( modelReceived );\n\t\t},\n\n\t\t/**\n\t\t * Override to allow manipulatino of placeholder element\n\t\t * @param {[type]} event [description]\n\t\t * @param {[type]} ui [description]\n\t\t * @return {[type]}\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\t_sortStart : function( event, ui ) {\n\n\t\t\tvar modelBeingSorted = this.collection.get( ui.item.attr( \"data-model-cid\" ) );\n\n\t\t\tui.placeholder.addClass( 'qtype--' + modelBeingSorted.get( 'question_type' ).get( 'id' ) );\n\n\t\t\tif( this._isBackboneCourierAvailable() )\n\t\t\t\tthis.spawn( \"sortStart\", { modelBeingSorted : modelBeingSorted } );\n\t\t\telse this.trigger( \"sortStart\", modelBeingSorted );\n\t\t},\n\n\t\t/**\n\t\t * Overloads the function from Backbone.CollectionView core because it doesn't send stop events\n\t\t * if moving from one sortable to another... :-(\n\t\t * @param obj event js event object\n\t\t * @param obj ui jQuery UI object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\t_sortStop : function( event, ui ) {\n\n\t\t\tevent.stopPropagation();\n\n\t\t\tvar modelBeingSorted = this.collection.get( ui.item.attr( 'data-model-cid' ) ),\n\t\t\t\tmodelViewContainerEl = this._getContainerEl(),\n\t\t\t\tnewIndex = modelViewContainerEl.children().index( ui.item );\n\n\t\t\tif ( newIndex == -1 && modelBeingSorted ) {\n\t\t\t\tthis.collection.remove( modelBeingSorted );\n\t\t\t}\n\n\t\t\tthis._reorderCollectionBasedOnHTML();\n\t\t\tthis.updateDependentControls();\n\n\t\t\tif( this._isBackboneCourierAvailable() ) {\n\t\t\t\tthis.spawn( 'sortStop', { modelBeingSorted : modelBeingSorted, newIndex : newIndex } );\n\t\t\t} else {\n\t\t\t\tthis.trigger( 'sortStop', modelBeingSorted, newIndex );\n\t\t\t}\n\n\t\t},\n\n\t} );\n\n} );\n\n","/**\n * Single Quiz View\n * @since 3.16.0\n * @version 3.19.2\n */\ndefine( 'Views/Quiz',[\n\t\t'Models/Quiz',\n\t\t'Views/Popover',\n\t\t'Views/PostSearch',\n\t\t'Views/QuestionBank',\n\t\t'Views/QuestionList',\n\t\t'Views/SettingsFields',\n\t\t'Views/_Detachable',\n\t\t'Views/_Editable',\n\t\t'Views/_Subview',\n\t\t'Views/_Trashable'\n\t], function(\n\t\tQuizModel,\n\t\tPopover,\n\t\tPostSearch,\n\t\tQuestionBank,\n\t\tQuestionList,\n\t\tSettingsFields,\n\t\tDetachable,\n\t\tEditable,\n\t\tSubview,\n\t\tTrashable\n\t) {\n\n\treturn Backbone.View.extend( _.defaults( {\n\n\t\t/**\n\t\t * Current view state\n\t\t * @type {String}\n\t\t */\n\t\tstate: 'default',\n\n\t\t/**\n\t\t * Current Subviews\n\t\t * @type {Object}\n\t\t */\n\t\tviews: {\n\t\t\tsettings: {\n\t\t\t\tclass: SettingsFields,\n\t\t\t\tinstance: null,\n\t\t\t\tstate: 'default',\n\t\t\t},\n\t\t\tbank: {\n\t\t\t\tclass: QuestionBank,\n\t\t\t\tinstance: null,\n\t\t\t\tstate: 'default',\n\t\t\t},\n\t\t\tlist: {\n\t\t\t\tclass: QuestionList,\n\t\t\t\tinstance: null,\n\t\t\t\tstate: 'default',\n\t\t\t},\n\t\t},\n\n\t\tel: '#llms-editor-quiz',\n\n\t\t/**\n\t\t * Events\n\t\t * @type {Object}\n\t\t */\n\t\tevents: _.defaults( {\n\t\t\t'click #llms-existing-quiz': 'add_existing_quiz_click',\n\t\t\t'click #llms-new-quiz': 'add_new_quiz',\n\t\t\t'click #llms-show-question-bank': 'show_tools',\n\t\t\t'click .bulk-toggle': 'bulk_toggle',\n\t\t\t// 'keyup #llms-question-bank-filter': 'filter_question_types',\n\t\t\t// 'search #llms-question-bank-filter': 'filter_question_types',\n\t\t}, Detachable.events, Editable.events, Trashable.events ),\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'div',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-quiz-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.19.2\n\t\t */\n\t\tinitialize: function( data ) {\n\n\t\t\tthis.lesson = data.lesson;\n\n\t\t\t// initialize the model if the quiz is enabled or it's disabled but we still have data for a quiz\n\t\t\tif ( 'yes' === this.lesson.get( 'quiz_enabled' ) || ! _.isEmpty( this.lesson.get( 'quiz' ) ) ) {\n\n\t\t\t\tthis.model = this.lesson.get( 'quiz' );\n\n\t\t\t\t/**\n\t\t\t\t * @todo this is a terrilbe terrible patch\n\t\t\t\t * I've spent nearly 3 days trying to figure out how to not use this line of code\n\t\t\t\t * ISSUE REPRODUCTION:\n\t\t\t\t * Open course builder\n\t\t\t\t * Open a lesson (A) and add a quiz\n\t\t\t\t * Switch to a new lesson (B)\n\t\t\t\t * Add a new quiz\n\t\t\t\t * Return to lesson A and the quizzes parent will be set to LESSON B\n\t\t\t\t * This will happen for *every* quiz in the builder...\n\t\t\t\t * Adding this set_parent on init guarantees that the quizzes correct parent is set\n\t\t\t\t * after adding new quizzes to other lessons\n\t\t\t\t * it's awful and it's gross...\n\t\t\t\t * I'm confused and tired and going to miss release dates again because of it\n\t\t\t\t */\n\t\t\t\tthis.model.set_parent( this.lesson );\n\n\t\t\t\tthis.listenTo( this.model, 'change:_points', this.render_points );\n\n\t\t\t}\n\n\t\t\tthis.on( 'model-trashed', this.on_trashed );\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.16.0\n\t\t * @version 3.19.2\n\t\t */\n\t\trender: function() {\n\n\t\t\tthis.$el.html( this.template( this.model ) );\n\n\t\t\t// render the quiz builder\n\t\t\tif ( this.model ) {\n\n\t\t\t\t// don't allow interaction until questions are lazy loaded\n\t\t\t\tLLMS.Spinner.start( this.$el );\n\n\t\t\t\tthis.render_subview( 'settings', {\n\t\t\t\t\tel: '#llms-quiz-settings-fields',\n\t\t\t\t\tmodel: this.model,\n\t\t\t\t} );\n\n\t\t\t\tthis.init_datepickers();\n\t\t\t\tthis.init_selects();\n\n\t\t\t\tthis.render_subview( 'bank', {\n\t\t\t\t\tcollection: window.llms_builder.questions,\n\t\t\t\t} );\n\n\t\t\t\tvar last_group = null,\n\t\t\t\t\tgroup = null;\n\t\t\t\t// let all the question types reference the quiz for adding questions quickly\n\t\t\t\tthis.get_subview( 'bank' ).instance.viewManager.each( function( view ) {\n\n\t\t\t\t\tview.quiz = this.model;\n\n\t\t\t\t\tgroup = view.model.get( 'group' ).name;\n\n\t\t\t\t\tif ( last_group !== group ) {\n\t\t\t\t\t\tlast_group = group;\n\t\t\t\t\t\tview.$el.before( '' );\n\t\t\t\t\t}\n\n\t\t\t\t}, this );\n\n\t\t\t\tthis.model.load_questions( _.bind( function( err ) {\n\n\t\t\t\t\tif ( err ) {\n\t\t\t\t\t\talert( LLMS.l10n.translate( 'An error occurred while trying to load the questions. Please refresh the page and try again.' ) );\n\t\t\t\t\t\treturn this;\n\t\t\t\t\t}\n\n\t\t\t\t\tLLMS.Spinner.stop( this.$el );\n\t\t\t\t\tthis.render_subview( 'list', {\n\t\t\t\t\t\tel: '#llms-quiz-questions',\n\t\t\t\t\t\tcollection: this.model.get( 'questions' ),\n\t\t\t\t\t} );\n\t\t\t\t\tvar list = this.get_subview( 'list' ).instance;\n\t\t\t\t\tlist.quiz = this;\n\t\t\t\t\tlist.collection.on( 'add', function() {\n\t\t\t\t\t\tlist.collection.trigger( 'reorder' );\n\t\t\t\t\t}, this );\n\t\t\t\t\tlist.on( 'sortStart', list.sortable_start );\n\t\t\t\t\tlist.on( 'sortStop', list.sortable_stop );\n\n\t\t\t\t}, this ) );\n\n\t\t\t\tthis.model.on( 'new-question-added', function() {\n\t\t\t\t\tvar $questions = this.$el.find( '#llms-quiz-questions' );\n\t\t\t\t\t$questions.animate( { scrollTop: $questions.prop( 'scrollHeight' ) }, 200 );\n\t\t\t\t}, this );\n\n\t\t\t}\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\t/**\n\t\t * On quiz points update, update the value of the Total Points area in the header\n\t\t * @param obj quiz Instance of the quiz model\n\t\t * @param int points Updated number of points\n\t\t * @return void\n\t\t * @since 3.17.6\n\t\t * @version 3.17.6\n\t\t */\n\t\trender_points: function( quiz, points ) {\n\n\t\t\tthis.$el.find( '#llms-quiz-total-points' ).text( points );\n\n\t\t},\n\n\t\t/**\n\t\t * Bulk expand / collapse question buttons\n\t\t * @param obj event js event object\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tbulk_toggle: function( event ) {\n\n\t\t\tvar expanded = ( 'expand' === $( event.target ).attr( 'data-action' ) );\n\n\t\t\tthis.model.get( 'questions' ).each( function( question ) {\n\t\t\t\tquestion.set( '_expanded', expanded );\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * Adds a new quiz to a lesson which currently has no quiz associated wlith it\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tadd_new_quiz: function() {\n\n\t\t\tvar quiz = this.lesson.get( 'quiz' );\n\t\t\tif ( _.isEmpty( quiz ) ) {\n\t\t\t\tquiz = this.lesson.add_quiz();\n\t\t\t} else {\n\t\t\t\tthis.lesson.set( 'quiz_enabled', 'yes' );\n\t\t\t}\n\n\t\t\tthis.model = quiz;\n\t\t\tthis.render();\n\n\t\t},\n\n\t\t// come back to this and make sure cloning resets all the IDs\n\t\tadd_existing_quiz: function( event ) {\n\n\t\t\tthis.post_search_popover.hide();\n\n\t\t\tvar quiz = event.data;\n\n\t\t\tif ( 'clone' === event.action ) {\n\n\t\t\t\tdelete quiz.id;\n\n\t\t\t\t_.each( quiz.questions, function( question ) {\n\n\t\t\t\t\tdelete question.parent_id;\n\t\t\t\t\tdelete question.id;\n\n\t\t\t\t\tif ( question.choices ) {\n\n\t\t\t\t\t\t_.each( question.choices, function( choice ) {\n\n\t\t\t\t\t\t\tdelete choice.question_id;\n\t\t\t\t\t\t\tdelete choice.id;\n\n\t\t\t\t\t\t} );\n\n\t\t\t\t\t}\n\n\t\t\t\t} );\n\n\t\t\t} else {\n\n\t\t\t\tquiz._forceSync = true;\n\n\t\t\t}\n\n\t\t\tdelete quiz.lesson_id;\n\n\t\t\tthis.lesson.add_quiz( quiz );\n\t\t\tthis.model = this.lesson.get( 'quiz' );\n\t\t\tthis.render();\n\n\t\t},\n\n\t\t/**\n\t\t * Open add existing quiz popover\n\t\t * @param obj event JS event object\n\t\t * @return void\n\t\t * @since 3.16.12\n\t\t * @version 3.16.12\n\t\t */\n\t\tadd_existing_quiz_click: function( event ) {\n\n\t\t\tevent.preventDefault();\n\n\t\t\tthis.post_search_popover = new Popover( {\n\t\t\t\tel: '#llms-existing-quiz',\n\t\t\t\targs: {\n\t\t\t\t\tbackdrop: true,\n\t\t\t\t\tcloseable: true,\n\t\t\t\t\tcontainer: '.wrap.lifterlms.llms-builder',\n\t\t\t\t\tdismissible: true,\n\t\t\t\t\tplacement: 'left',\n\t\t\t\t\twidth: 480,\n\t\t\t\t\ttitle: LLMS.l10n.translate( 'Add Existing Quiz' ),\n\t\t\t\t\tcontent: new PostSearch( {\n\t\t\t\t\t\tpost_type: 'llms_quiz',\n\t\t\t\t\t\tsearching_message: LLMS.l10n.translate( 'Search for existing quizzes...' ),\n\t\t\t\t\t} ).render().$el,\n\t\t\t\t\tonHide: function() {\n\t\t\t\t\t\tBackbone.pubSub.off( 'quiz-search-select' );\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\tthis.post_search_popover.show();\n\t\t\tBackbone.pubSub.once( 'quiz-search-select', this.add_existing_quiz, this );\n\n\t\t},\n\n\t\t// filter_question_types: _.debounce( function( event ) {\n\n\t\t// \tvar term = $( event.target ).val();\n\n\t\t// \tthis.QuestionBankView.viewManager.each( function( view ) {\n\t\t// \t\tif ( ! term ) {\n\t\t// \t\t\tview.clear_filter();\n\t\t// \t\t} else {\n\t\t// \t\t\tview.filter( term );\n\t\t// \t\t}\n\t\t// \t} );\n\n\n\t\t// }, 300 ),\n\n\t\t/**\n\t\t * Callback function when the quiz has been deleted\n\t\t * @param object quiz Quiz Model\n\t\t * @return void\n\t\t * @since 3.16.6\n\t\t * @version 3.16.6\n\t\t */\n\t\ton_trashed: function( quiz ) {\n\n\t\t\tthis.lesson.set( 'quiz_enabled', 'no' );\n\t\t\tthis.lesson.set( 'quiz', '' );\n\n\t\t\tdelete this.model;\n\n\t\t\tthis.render();\n\n\t\t},\n\n\t\t/**\n\t\t * \"Add Question\" button click event\n\t\t * Creates a popover with question type list interface\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tshow_tools: function() {\n\n\t\t\t// create popover\n\t\t\tvar pop = new Popover( {\n\t\t\t\tel: '#llms-show-question-bank',\n\t\t\t\targs: {\n\t\t\t\t\tbackdrop: true,\n\t\t\t\t\tcloseable: true,\n\t\t\t\t\tcontainer: '#llms-builder-sidebar',\n\t\t\t\t\tdismissible: true,\n\t\t\t\t\tplacement: 'top-left',\n\t\t\t\t\twidth: 'calc( 100% - 40px )',\n\t\t\t\t\ttitle: LLMS.l10n.translate( 'Add a Question' ),\n\t\t\t\t\turl: '#llms-quiz-tools',\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\t// show it\n\t\t\tpop.show();\n\n\t\t\t// if a question is added, hide the popover\n\t\t\tthis.model.on( 'new-question-added', function() {\n\t\t\t\tpop.hide();\n\t\t\t} );\n\n\t\t},\n\n\t\tget_question_list: function( options ) {\n\t\t\treturn new QuestionList( options );\n\t\t}\n\n\t}, Detachable, Editable, Subview, Trashable, SettingsFields ) );\n\n} );\n\n","/**\n * Single Assignment View\n * @since 3.17.0\n * @version 3.17.7\n */\ndefine( 'Views/Assignment',[\n\t\t'Views/Popover',\n\t\t'Views/PostSearch',\n\t\t'Views/_Detachable',\n\t\t'Views/_Editable',\n\t\t'Views/_Trashable',\n\t\t'Views/_Subview',\n\t\t'Views/SettingsFields'\n\t], function(\n\t\tPopover,\n\t\tPostSearch,\n\t\tDetachable,\n\t\tEditable,\n\t\tTrashable,\n\t\tSubview,\n\t\tSettingsFields\n\t) {\n\n\treturn Backbone.View.extend( _.defaults( {\n\n\t\t/**\n\t\t * Current view state\n\t\t * @type {String}\n\t\t */\n\t\tstate: 'default',\n\n\t\t/**\n\t\t * Current Subviews\n\t\t * @type {Object}\n\t\t */\n\t\tviews: {\n\t\t\tsettings: {\n\t\t\t\tclass: SettingsFields,\n\t\t\t\tinstance: null,\n\t\t\t\tstate: 'default',\n\t\t\t},\n\t\t},\n\n\t\tel: '#llms-editor-assignment',\n\n\t\t/**\n\t\t * DOM Events\n\t\t * @return obj\n\t\t * @since 3.17.1\n\t\t * @version 3.17.1\n\t\t */\n\t\tevents: function() {\n\t\t\tvar addon_events = this.is_addon_available() ? window.llms_builder.assignments.get_view_events() : {};\n\t\t\treturn _.defaults( {\n\t\t\t\t'click #llms-existing-assignment': 'add_existing_assignment_click',\n\t\t\t\t'click #llms-new-assignment': 'add_new_assignment',\n\t\t\t}, Detachable.events, Editable.events, Trashable.events, addon_events );\n\t\t},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'div',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-assignment-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.2\n\t\t */\n\t\tinitialize: function( data ) {\n\n\t\t\tthis.lesson = data.lesson;\n\n\t\t\t// initialize the model if the assignment is enabled or it's disabled but we still have data for a assignment\n\t\t\tif ( 'yes' === this.lesson.get( 'assignment_enabled' ) || ! _.isEmpty( this.lesson.get( 'assignment' ) ) ) {\n\n\t\t\t\tthis.model = this.lesson.get( 'assignment' );\n\n\t\t\t\t/**\n\t\t\t\t * @todo this is a terrilbe terrible patch\n\t\t\t\t * I've spent nearly 3 days trying to figure out how to not use this line of code\n\t\t\t\t * ISSUE REPRODUCTION:\n\t\t\t\t * Open course builder\n\t\t\t\t * Open a lesson (A) and add a assignment\n\t\t\t\t * Switch to a new lesson (B)\n\t\t\t\t * Add a new assignment\n\t\t\t\t * Return to lesson A and the assignment's parent will be set to LESSON B\n\t\t\t\t * This will happen for *every* assignment in the builder...\n\t\t\t\t * Adding this set_parent on init guarantees that the assignment's correct parent is set\n\t\t\t\t * after adding new assignment's to other lessons\n\t\t\t\t * it's awful and it's gross...\n\t\t\t\t * I'm confused and tired and going to miss release dates again because of it\n\t\t\t\t */\n\t\t\t\tthis.model.set_parent( this.lesson );\n\n\t\t\t}\n\n\t\t\tthis.on( 'model-trashed', this.on_trashed );\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.17.0\n\t\t * @version 3.17.7\n\t\t */\n\t\trender: function() {\n\n\t\t\tthis.$el.html( this.template( this.model ) );\n\n\t\t\tif ( this.model && this.is_addon_available() ) {\n\n\t\t\t\tthis.stopListening( this.model, 'change:assignment_type', this.render );\n\n\t\t\t\tthis.render_subview( 'settings', {\n\t\t\t\t\tel: '#llms-assignment-settings-fields',\n\t\t\t\t\tmodel: this.model,\n\t\t\t\t} );\n\n\t\t\t\t// this.init_datepickers();\n\t\t\t\tthis.init_selects();\n\n\t\t\t\twindow.llms_builder.assignments.render_editor( this );\n\n\t\t\t\tthis.listenTo( this.model, 'change:assignment_type', this.render );\n\n\t\t\t}\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\t/**\n\t\t * Adds a new assignment to a lesson which currently has no assignment associated wlith it\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tadd_new_assignment: function() {\n\n\t\t\tif ( this.is_addon_available() ) {\n\n\t\t\t\tthis.model = window.llms_builder.assignments.get_assignment( {\n\t\t\t\t\t/* translators: %1$s = associated lesson title */\n\t\t\t\t\ttitle: LLMS.l10n.replace( '%1$s Assignment', {\n\t\t\t\t\t\t'%1$s': this.lesson.get( 'title' ),\n\t\t\t\t\t} ),\n\t\t\t\t\tlesson_id: this.lesson.get( 'id' ),\n\t\t\t\t} );\n\n\t\t\t\tthis.lesson.set( 'assignment_enabled', 'yes' );\n\t\t\t\tthis.lesson.set( 'assignment', this.model );\n\n\t\t\t\tthis.render();\n\n\t\t\t} else {\n\n\t\t\t\tthis.show_ad_popover( '#llms-new-assignment' );\n\n\t\t\t}\n\n\n\t\t},\n\n\t\t/**\n\t\t * When an assignment is selected from the post select popover\n\t\t * instantiate it and add it to the current lesson\n\t\t * @param object event data from the select2 select event\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tadd_existing_assignment: function( event ) {\n\n\t\t\tthis.post_search_popover.hide();\n\n\t\t\tvar assignment = event.data;\n\n\t\t\tif ( 'clone' === event.action ) {\n\n\t\t\t\tdelete assignment.id;\n\n\t\t\t} else {\n\n\t\t\t\tassignment._forceSync = true;\n\n\t\t\t}\n\n\t\t\tassignment.lesson_id = this.lesson.get( 'id' )\n\n\t\t\tassignment = window.llms_builder.construct.get_model( 'Assignment', assignment );\n\n\t\t\tthis.lesson.set( 'assignment_enabled', 'yes' );\n\t\t\tthis.lesson.set( 'assignment', assignment );\n\t\t\tthis.model = assignment;\n\n\t\t\tthis.render();\n\n\t\t},\n\n\t\t/**\n\t\t * Open add existing assignment popover\n\t\t * @param obj event JS event object\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tadd_existing_assignment_click: function( event ) {\n\n\t\t\tevent.preventDefault();\n\n\t\t\tif ( this.is_addon_available() ) {\n\n\t\t\t\tthis.post_search_popover = new Popover( {\n\t\t\t\t\tel: '#llms-existing-assignment',\n\t\t\t\t\targs: {\n\t\t\t\t\t\tbackdrop: true,\n\t\t\t\t\t\tcloseable: true,\n\t\t\t\t\t\tcontainer: '.wrap.lifterlms.llms-builder',\n\t\t\t\t\t\tdismissible: true,\n\t\t\t\t\t\tplacement: 'left',\n\t\t\t\t\t\twidth: 480,\n\t\t\t\t\t\ttitle: LLMS.l10n.translate( 'Add Existing Assignment' ),\n\t\t\t\t\t\tcontent: new PostSearch( {\n\t\t\t\t\t\t\tpost_type: 'llms_assignment',\n\t\t\t\t\t\t\tsearching_message: LLMS.l10n.translate( 'Search for existing assignments...' ),\n\t\t\t\t\t\t} ).render().$el,\n\t\t\t\t\t\tonHide: function() {\n\t\t\t\t\t\t\tBackbone.pubSub.off( 'assignment-search-select' );\n\t\t\t\t\t\t},\n\t\t\t\t\t}\n\t\t\t\t} );\n\n\t\t\t\tthis.post_search_popover.show();\n\t\t\t\tBackbone.pubSub.once( 'assignment-search-select', this.add_existing_assignment, this );\n\n\t\t\t} else {\n\n\t\t\t\tthis.show_ad_popover( '#llms-existing-assignment' );\n\n\t\t\t}\n\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if Assignments addon is available to use\n\t\t * @return {Boolean}\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tis_addon_available: function() {\n\n\t\t\treturn ( window.llms_builder.assignments );\n\n\t\t},\n\n\t\t/**\n\t\t * Called when assignment is trashed\n\t\t * @param obj assignment Assignment model\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\ton_trashed: function( assignment ) {\n\n\t\t\tthis.lesson.set( 'assignment_enabled', 'no' );\n\t\t\tthis.lesson.set( 'assignment', '' );\n\n\t\t\tdelete this.model;\n\n\t\t\tthis.render();\n\n\t\t},\n\n\t\t/**\n\t\t * Shows a dirty dirty ad popoever for advanced assignments\n\t\t * @param string el jQuery selector string\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tshow_ad_popover: function( el ) {\n\n\t\t\tvar h3 = LLMS.l10n.translate( 'Get Your Students Taking Action' ),\n\t\t\t\tp = 'Great learning content is only half of teaching online. When your learners fully engage, they will take your content and move into action. Remove barriers for your learners by telling them what to do to apply what they just learned. Create graded assignments or simply give them a checklist of action items to complete before moving on.',\n\t\t\t\tbtn = LLMS.l10n.translate( 'Get Assignments Now!' ),\n\t\t\t\turl = 'https://lifterlms.com/product/lifterlms-assignments?utm_source=LifterLMS%20Plugin&utm_medium=Assignment%20Builder%20Button&utm_campaign=Assignment%20Addon%20Upsell&utm_content=3.17.0';\n\n\t\t\tthis.ad_popover = new Popover( {\n\t\t\t\tel: el,\n\t\t\t\targs: {\n\t\t\t\t\tbackdrop: true,\n\t\t\t\t\tcloseable: true,\n\t\t\t\t\tcontainer: '.wrap.lifterlms.llms-builder',\n\t\t\t\t\tdismissible: true,\n\t\t\t\t\t// placement: 'left',\n\t\t\t\t\twidth: 380,\n\t\t\t\t\ttitle: LLMS.l10n.translate( 'Unlock LifterLMS Assignments' ),\n\t\t\t\t\tcontent: '' + h3 + ' ' + p + '
' + btn + '
'\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\tthis.ad_popover.show();\n\n\t\t},\n\n\t}, Detachable, Editable, Trashable, Subview, SettingsFields ) );\n\n} );\n\n","/**\n * Sidebar Editor View\n * @since 3.16.0\n * @version 3.17.0\n */\ndefine( 'Views/Editor',[\n\t\t'Views/LessonEditor',\n\t\t'Views/Quiz',\n\t\t'Views/Assignment',\n\t\t'Views/_Subview'\n\t], function(\n\t\tLessonEditor,\n\t\tQuiz,\n\t\tAssignment,\n\t\tSubview\n\t) {\n\n\treturn Backbone.View.extend( _.defaults( {\n\n\t\t/**\n\t\t * Current view state\n\t\t * @type {String}\n\t\t */\n\t\tstate: 'lesson', // [lesson|quiz]\n\n\t\t/**\n\t\t * Current Subviews\n\t\t * @type {Object}\n\t\t */\n\t\tviews: {\n\t\t\tlesson: {\n\t\t\t\tclass: LessonEditor,\n\t\t\t\tinstance: null,\n\t\t\t\tstate: 'lesson',\n\t\t\t},\n\t\t\tassignment: {\n\t\t\t\tclass: Assignment,\n\t\t\t\tinstance: null,\n\t\t\t\tstate: 'assignment',\n\t\t\t},\n\t\t\tquiz: {\n\t\t\t\tclass: Quiz,\n\t\t\t\tinstance: null,\n\t\t\t\tstate: 'quiz',\n\t\t\t},\n\t\t},\n\n\t\t/**\n\t\t * HTML element selector\n\t\t * @type {String}\n\t\t */\n\t\tel: '#llms-editor',\n\n\t\tevents: {\n\t\t\t'click .llms-editor-nav a[href=\"#llms-editor-close\"]': 'close_editor',\n\t\t\t'click .llms-editor-nav a:not([href=\"#llms-editor-close\"])': 'switch_tab',\n\t\t},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'div',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-editor-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function( data ) {\n\n\t\t\tthis.SidebarView = data.SidebarView;\n\t\t\tif ( data.tab ) {\n\t\t\t\tthis.state = data.tab;\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender: function( view_data ) {\n\n\t\t\tview_data = view_data || {};\n\n\t\t\tthis.$el.html( this.template( this ) );\n\n\t\t\tthis.render_subviews( _.extend( view_data, {\n\t\t\t\tlesson: this.model,\n\t\t\t} ) );\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\t/**\n\t\t * Click event for close sidebar editor button\n\t\t * Sends event to main SidebarView to trigger editor closing events\n\t\t * @param obj event js event obj\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tclose_editor: function( event ) {\n\n\t\t\tevent.preventDefault();\n\t\t\tBackbone.pubSub.trigger( 'sidebar-editor-close' );\n\n\t\t},\n\n\t\t/**\n\t\t * Click event for switching tabs in the editor navigation\n\t\t * @param object event js event object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tswitch_tab: function( event ) {\n\n\t\t\tevent.preventDefault();\n\n\t\t\tvar $btn = $( event.target ),\n\t\t\t\tview = $btn.attr( 'data-view' ),\n\t\t\t\t$tab = this.$el.find( $btn.attr( 'href' ) );\n\n\t\t\tthis.set_state( view ).render();\n\n\t\t\t// Backbone.pubSub.trigger( 'editor-tab-activated', $btn.attr( 'href' ).substring( 1 ) );\n\n\t\t},\n\n\t}, Subview ) );\n\n} );\n\n","/**\n * Sidebar Elements View\n * @since 3.16.0\n * @version 3.16.12\n */\ndefine( 'Views/Elements',[ 'Models/Section', 'Views/Section', 'Models/Lesson', 'Views/Lesson', 'Views/Popover', 'Views/PostSearch' ], function( Section, SectionView, Lesson, LessonView, Popover, LessonSearch ) {\n\n\treturn Backbone.View.extend( {\n\n\t\t/**\n\t\t * HTML element selector\n\t\t * @type {String}\n\t\t */\n\t\tel: '#llms-elements',\n\n\t\tevents: {\n\t\t\t'click #llms-new-section': 'add_new_section',\n\t\t\t'click #llms-new-lesson': 'add_new_lesson',\n\t\t\t'click #llms-existing-lesson': 'add_existing_lesson',\n\t\t},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'div',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-elements-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function( data ) {\n\n\t\t\t// save a reference to the main Course view\n\t\t\tthis.SidebarView = data.SidebarView;\n\n\t\t\t// watch course sections and enable/disable lesson buttons conditionally\n\t\t\tthis.listenTo( this.SidebarView.CourseView.model.get( 'sections' ), 'add', this.maybe_disable_buttons );\n\t\t\tthis.listenTo( this.SidebarView.CourseView.model.get( 'sections' ), 'remove', this.maybe_disable_buttons );\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender: function() {\n\n\t\t\tthis.$el.html( this.template() );\n\t\t\tthis.draggable();\n\t\t\tthis.maybe_disable_buttons();\n\n\t\t\treturn this;\n\t\t},\n\n\t\tdraggable: function() {\n\n\t\t\t$( '#llms-new-section' ).draggable( {\n\t\t\t\tappendTo: '#llms-sections',\n\t\t\t\tcancel: false,\n\t\t\t\tconnectToSortable: '.llms-sections',\n\t\t\t\thelper: function() {\n\t\t\t\t\treturn new SectionView( { model: new Section() } ).render().$el;\n\t\t\t\t},\n\t\t\t\tstart: function() {\n\t\t\t\t\t$( '.llms-sections' ).addClass( 'dragging' );\n\t\t\t\t},\n\t\t\t\tstop: function() {\n\t\t\t\t\t$( '.llms-sections' ).removeClass( 'dragging' );\n\t\t\t\t},\n\t\t\t} );\n\n\t\t\t$( '#llms-new-lesson' ).draggable( {\n\t\t\t\t// appendTo: '#llms-sections .llms-section:first-child .llms-lessons',\n\t\t\t\tappendTo: '#llms-sections',\n\t\t\t\tcancel: false,\n\t\t\t\tconnectToSortable: '.llms-lessons',\n\t\t\t\thelper: function() {\n\t\t\t\t\treturn new LessonView( { model: new Lesson() } ).render().$el;\n\t\t\t\t},\n\t\t\t\tstart: function() {\n\n\t\t\t\t\t$( '.llms-lessons' ).addClass( 'dragging' );\n\n\t\t\t\t},\n\t\t\t\tstop: function() {\n\t\t\t\t\t$( '.llms-lessons' ).removeClass( 'dragging' );\n\t\t\t\t\t$( '.drag-expanded' ).removeClass( '.drag-expanded' );\n\t\t\t\t},\n\t\t\t} );\n\n\t\t},\n\n\t\tadd_new_section: function( event ) {\n\n\t\t\tevent.preventDefault();\n\t\t\tBackbone.pubSub.trigger( 'add-new-section' );\n\t\t},\n\n\t\tadd_new_lesson: function( event ) {\n\t\t\tevent.preventDefault();\n\t\t\tBackbone.pubSub.trigger( 'add-new-lesson' );\n\t\t},\n\n\t\t/**\n\t\t * Show the popover to add an existing lessons\n\t\t * @param object event JS Event OBject\n\t\t * @return void\n\t\t * @since 3.16.12\n\t\t * @version 3.16.12\n\t\t */\n\t\tadd_existing_lesson: function( event ) {\n\n\t\t\tevent.preventDefault();\n\n\t\t\tvar pop = new Popover( {\n\t\t\t\tel: '#llms-existing-lesson',\n\t\t\t\targs: {\n\t\t\t\t\tbackdrop: true,\n\t\t\t\t\tcloseable: true,\n\t\t\t\t\tcontainer: '.wrap.lifterlms.llms-builder',\n\t\t\t\t\tdismissible: true,\n\t\t\t\t\tplacement: 'left',\n\t\t\t\t\twidth: 480,\n\t\t\t\t\ttitle: LLMS.l10n.translate( 'Add Existing Lesson' ),\n\t\t\t\t\tcontent: new LessonSearch( {\n\t\t\t\t\t\tpost_type: 'lesson',\n\t\t\t\t\t\tsearching_message: LLMS.l10n.translate( 'Search for existing lessons...' ),\n\t\t\t\t\t} ).render().$el,\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\tpop.show();\n\t\t\tBackbone.pubSub.on( 'lesson-search-select', function() {\n\t\t\t\tpop.hide()\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * Disables lesson add buttons if no sections are available to add a lesson to\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tmaybe_disable_buttons: function() {\n\n\t\t\tvar $els = $( '#llms-new-lesson, #llms-existing-lesson' );\n\n\t\t\tif ( ! this.SidebarView.CourseView.model.get( 'sections' ).length ) {\n\t\t\t\t$els.attr( 'disabled', 'disabled' );\n\t\t\t} else {\n\t\t\t\t$els.removeAttr( 'disabled' );\n\t\t\t}\n\n\t\t},\n\n\t} );\n\n} );\n\n","/**\n * Sidebar Utilities View\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Views/Utilities',[], function() {\n\n\treturn Backbone.View.extend( {\n\n\t\t/**\n\t\t * HTML element selector\n\t\t * @type {String}\n\t\t */\n\t\tel: '#llms-utilities',\n\n\t\tevents: {\n\t\t\t'click #llms-collapse-all': 'collapse_all',\n\t\t\t'click #llms-expand-all': 'expand_all'\n\t\t},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'div',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-utilities-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\t// this.render();\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender: function() {\n\t\t\tthis.$el.html( this.template() );\n\t\t\treturn this;\n\t\t},\n\n\t\t/**\n\t\t * Collapse all sections\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tcollapse_all: function( event ) {\n\t\t\tevent.preventDefault();\n\t\t\tBackbone.pubSub.trigger( 'collapse-all' );\n\t\t},\n\n\t\t/**\n\t\t * Expand all sections\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\texpand_all: function( event ) {\n\t\t\tevent.preventDefault();\n\t\t\tBackbone.pubSub.trigger( 'expand-all' );\n\t\t},\n\n\t} );\n\n} );\n\n","/**\n * Main sidebar view\n * @since 3.16.0\n * @version 3.16.7\n */\ndefine( 'Views/Sidebar',[\n\t\t'Views/Editor',\n\t\t'Views/Elements',\n\t\t'Views/Utilities',\n\t\t'Views/_Subview'\n\t], function(\n\t\tEditor,\n\t\tElements,\n\t\tUtilities,\n\t\tSubview\n\t) {\n\n\treturn Backbone.View.extend( _.defaults( {\n\n\t\t/**\n\t\t * Current builder state\n\t\t * @type {String}\n\t\t */\n\t\tstate: 'builder', // [builder|editor]\n\n\t\t/**\n\t\t * Current Subviews\n\t\t * @type {Object}\n\t\t */\n\t\tviews: {\n\t\t\telements: {\n\t\t\t\tclass: Elements,\n\t\t\t\tinstance: null,\n\t\t\t\tstate: 'builder',\n\t\t\t},\n\t\t\tutilities: {\n\t\t\t\tclass: Utilities,\n\t\t\t\tinstance: null,\n\t\t\t\tstate: 'builder',\n\t\t\t},\n\t\t\teditor: {\n\t\t\t\tclass: Editor,\n\t\t\t\tinstance: null,\n\t\t\t\tstate: 'editor',\n\t\t\t},\n\t\t},\n\n\t\t/**\n\t\t * HTML element selector\n\t\t * @type {String}\n\t\t */\n\t\tel: '#llms-builder-sidebar',\n\n\t\t/**\n\t\t * DOM events\n\t\t * @type {Object}\n\t\t */\n\t\tevents: {\n\t\t\t'click #llms-save-button': 'save_now',\n\t\t\t'click #llms-exit-button': 'exit_now',\n\t\t\t'click .llms-builder-error': 'clear_errors',\n\t\t},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'aside',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-sidebar-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function( data ) {\n\n\t\t\t// save a reference to the main Course view\n\t\t\tthis.CourseView = data.CourseView;\n\n\t\t\tthis.render();\n\n\t\t\tBackbone.pubSub.on( 'current-save-status', this.changes_made, this );\n\n\t\t\tBackbone.pubSub.on( 'heartbeat-send', this.heartbeat_send, this );\n\t\t\tBackbone.pubSub.on( 'heartbeat-tick', this.heartbeat_tick, this );\n\n\t\t\tBackbone.pubSub.on( 'lesson-selected', this.on_lesson_select, this );\n\t\t\tBackbone.pubSub.on( 'sidebar-editor-close', this.on_editor_close, this );\n\n\t\t\tthis.$saveButton = $( '#llms-save-button' );\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender: function( view_data ) {\n\n\t\t\tview_data = view_data || {};\n\n\t\t\tthis.$el.html( this.template() );\n\n\t\t\tthis.render_subviews( _.extend( view_data, {\n\t\t\t\tSidebarView: this,\n\t\t\t} ) );\n\n\t\t\tvar $el = $( '.wrap.lifterlms.llms-builder' );\n\t\t\tif ( 'builder' === this.state ) {\n\t\t\t\t$el.removeClass( 'editor-active' );\n\t\t\t} else {\n\t\t\t\t$el.addClass( 'editor-active' );\n\t\t\t}\n\n\t\t\tthis.$saveButton = this.$el.find( '#llms-save-button' );\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\t/**\n\t\t * Adds error message element\n\t\t * @param {[type]} $err [description]\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tadd_error: function( $err ) {\n\n\t\t\tthis.$el.find( '.llms-builder-save' ).prepend( $err );\n\n\t\t},\n\n\t\t/**\n\t\t * Clear any existing error message elements\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tclear_errors: function() {\n\n\t\t\tthis.$el.find( '.llms-builder-save .llms-builder-error' ).remove();\n\n\t\t},\n\n\t\t/**\n\t\t * Update save status button when changes are detected\n\t\t * runs on an interval to check status of course regularly for unsaved changes\n\t\t * @param obj sync instance of the sync controller\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tchanges_made: function( sync ) {\n\n\t\t\t// if a save is currently running, don't do anything\n\t\t\tif ( sync.saving ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( sync.has_unsaved_changes ) {\n\n\t\t\t\tthis.$saveButton.attr( 'data-status', 'unsaved' );\n\t\t\t\tthis.$saveButton.removeAttr( 'disabled' );\n\n\t\t\t} else {\n\n\t\t\t\tthis.$saveButton.attr( 'data-status', 'saved' );\n\t\t\t\tthis.$saveButton.attr( 'disabled', 'disabled' );\n\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Exit the builder and return to the WP Course Editor\n\t\t * @return void\n\t\t * @since 3.16.7\n\t\t * @version 3.16.7\n\t\t */\n\t\texit_now: function() {\n\n\t\t\twindow.location.href = window.llms_builder.CourseModel.get_edit_post_link();\n\n\t\t},\n\n\t\t/**\n\t\t * Triggered when a heartbeat send event starts containing builder information\n\t\t * @param obj sync instance of the sync controller\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\theartbeat_send: function( sync ) {\n\n\t\t\tif ( sync.saving ) {\n\t\t\t\tLLMS.Spinner.start( this.$saveButton.find( 'i' ), 'small' );\n\t\t\t\tthis.$saveButton.attr( {\n\t\t\t\t\t'data-status': 'saving',\n\t\t\t\t\tdisabled: 'disabled',\n\t\t\t\t} );\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Triggered when a heartbeat tick completes and updates save status or appends errors\n\t\t * @param obj sync instance of the sync controller\n\t\t * @param obj data updated data\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\theartbeat_tick: function( sync, data ) {\n\n\t\t\tif ( ! sync.saving ) {\n\n\t\t\t\tvar status = 'saved';\n\n\t\t\t\tthis.clear_errors();\n\n\t\t\t\tif ( 'error' === data.status ) {\n\n\t\t\t\t\tstatus = 'error';\n\n\t\t\t\t\tvar msg = data.message,\n\t\t\t\t\t\t$err = $( ' ' );\n\n\t\t\t\t\tif ( 'object' === typeof msg ) {\n\t\t\t\t\t\t_.each( msg, function( txt ) {\n\t\t\t\t\t\t\t$err.append( '' + txt + ' ' );\n\t\t\t\t\t\t} );\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$err = $err.append( '' + msg + ' ' );;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.add_error( $err );\n\n\t\t\t\t}\n\n\t\t\t\tthis.$saveButton.find( '.llms-spinning' ).remove();\n\t\t\t\tthis.$saveButton.attr( {\n\t\t\t\t\t'data-status': status,\n\t\t\t\t\tdisabled: 'disabled',\n\t\t\t\t} );\n\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if the editor is the currently active state\n\t\t * @return boolean\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tis_editor_active: function() {\n\n\t\t\treturn ( 'editor' === this.state );\n\n\t\t},\n\n\t\t/**\n\t\t * Triggered when the editor closes, updates state to be the course builder view\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\ton_editor_close: function() {\n\n\t\t\tthis.set_state( 'builder' ).render();\n\n\t\t},\n\n\t\t/**\n\t\t * When a lesson is selected, opens the sidebar to the editor view\n\t\t * @param obj lesson_model instance of the lesson model which was selected\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\ton_lesson_select: function( lesson_model, tab ) {\n\n\t\t\tif ( 'editor' !== this.state ) {\n\t\t\t\tthis.set_state( 'editor' );\n\t\t\t} else {\n\t\t\t\tthis.remove_subview( 'editor' );\n\t\t\t}\n\n\t\t\tthis.render( {\n\t\t\t\tmodel: lesson_model,\n\t\t\t\ttab: tab,\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * Save button click event\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tsave_now: function() {\n\n\t\t\twindow.llms_builder.sync.save_now();\n\n\t\t},\n\n\t}, Subview ) );\n\n} );\n\n","/**\n * LifterLMS JS Builder App Bootstrap\n * @since 3.16.0\n * @version 3.17.8\n */\nrequire( [\n\t'vendor/backbone.collectionView',\n\t'vendor/backbone.trackit',\n\t'Controllers/Construct',\n\t'Controllers/Debug',\n\t'Controllers/Schemas',\n\t'Controllers/Sync',\n\t'Models/loader',\n\t'Views/Course',\n\t'Views/Sidebar'\n], function(\n\tCV,\n\tTrackIt,\n\tConstruct,\n\tDebug,\n\tSchemas,\n\tSync,\n\tModels,\n\tCourseView,\n\tSidebarView\n) {\n\n\twindow.llms_builder.debug = new Debug( window.llms_builder.debug );\n\twindow.llms_builder.construct = new Construct();\n\twindow.llms_builder.schemas = new Schemas( window.llms_builder.schemas );\n\n\t/**\n\t * Compare values, used by _.checked & _.selected mixins\n\t * @param mixed expected expected value, probably a string (the value of a select option or checkbox element)\n\t * @param mixed actual actual value, probably a string (the return of model.get( 'something' ) )\n\t * \t\t\t\t but could be an array like a multiselect\n\t * @return boolean\n\t * @since 3.17.2\n\t * @version 3.17.2\n\t */\n\tfunction value_compare( expected, actual ) {\n\t\treturn ( ( _.isArray( actual ) && -1 !== actual.indexOf( expected ) ) || expected == actual );\n\t};\n\n\t/**\n\t * Underscores templating utilities\n\t * @since 3.17.0\n\t * @version 3.17.8\n\t */\n\t_.mixin( {\n\n\t\t/**\n\t\t * Determine if two values are equal and output checked attribute if they are\n\t\t * Useful for templating checkboxes & radio elements\n\t\t * Like WP Core PHP checked() but in JS\n\t\t * @param mixed expected expected element value\n\t\t * @param mixed actual actual element value\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.2\n\t\t */\n\t\tchecked: function( expected, actual ) {\n\t\t\tif ( value_compare( expected, actual ) ) {\n\t\t\t\treturn ' checked=\"checked\"';\n\t\t\t}\n\t\t\treturn '';\n\t\t},\n\n\t\t/**\n\t\t * Recursively clone an object via _.clone()\n\t\t * @param obj obj object to clone\n\t\t * @return obj\n\t\t * @since 3.17.7\n\t\t * @version 3.17.7\n\t\t */\n\t\tdeepClone: function( obj ) {\n\n\t\t\tvar clone = _.clone( obj );\n\n\t\t\t_.each( clone, function( val, key ) {\n\t\t\t\tif ( ! _.isFunction( val ) && _.isObject( val ) ) {\n\t\t\t\t\tclone[ key ] = _.deepClone( val );\n\t\t\t\t};\n\t\t\t} );\n\n\t\t\treturn clone;\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if two values are equal and output seleted attribute if they are\n\t\t * Useful for templating select elements\n\t\t * Like WP Core PHP selected() but in JS\n\t\t * @param mixed expected expected element value\n\t\t * @param mixed actual actual element value\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.2\n\t\t */\n\t\tselected: function( expected, actual ) {\n\t\t\tif ( value_compare( expected, actual ) ) {\n\t\t\t\treturn ' selected=\"selected\"';\n\t\t\t}\n\t\t\treturn '';\n\t\t},\n\n\t\t/**\n\t\t * Generic function for stripping HTML tags from a string\n\t\t * @param string content raw string\n\t\t * @param array allowed_tags array of allowed HTML tags\n\t\t * @return string\n\t\t * @since 3.17.8\n\t\t * @version 3.17.8\n\t\t */\n\t\tstripFormatting: function( content, allowed_tags ) {\n\n\t\t\tif ( ! allowed_tags ) {\n\t\t\t\tallowed_tags = [ 'b', 'i', 'u', 'strong', 'em' ];\n\t\t\t}\n\n\t\t\tvar $html = $( '' + content + '
' );\n\n\t\t\t$html.find( '*' ).not( allowed_tags.join( ',' ) ).each( function( ) {\n\n\t\t\t\t$( this ).replaceWith( this.innerHTML );\n\n\t\t\t} );\n\n\t\t\treturn $html.html();\n\n\t\t},\n\n\t} );\n\n\tBackbone.pubSub = _.extend( {}, Backbone.Events );\n\n\t$( document ).trigger( 'llms-builder-pre-init' );\n\n\twindow.llms_builder.questions = window.llms_builder.construct.get_collection( 'QuestionTypes', window.llms_builder.questions );\n\n\tvar CourseModel = window.llms_builder.construct.get_model( 'Course', window.llms_builder.course );\n\twindow.llms_builder.CourseModel = CourseModel;\n\n\twindow.llms_builder.sync = new Sync( CourseModel, window.llms_builder.sync );\n\n\tvar Course = new CourseView( {\n\t\tmodel: CourseModel,\n\t} );\n\n\tvar Sidebar = new SidebarView( {\n\t\tCourseView: Course\n\t} );\n\n\t$( document ).trigger( 'llms-builder-init', {\n\t\tcourse: Course,\n\t\tsidebar: Sidebar,\n\t} );\n\n} );\n\ndefine(\"main\", function(){});\n\n","}(jQuery));\n"]}
\ No newline at end of file
diff --git a/assets/js/llms-builder.min.js b/assets/js/llms-builder.min.js
index 8221e0f23f..5e3f7ec834 100644
--- a/assets/js/llms-builder.min.js
+++ b/assets/js/llms-builder.min.js
@@ -1,2 +1,2 @@
-!function(g){var e,t,n,i,s,l,o;!function(_){var o,l,p,m,g={},f={},b={},v={},i=Object.prototype.hasOwnProperty,s=[].slice,w=/\.js$/;function y(e,t){return i.call(e,t)}function a(e,t){var i,s,n,o,l,a,r,c,d,u,h,_=t&&t.split("/"),p=b.map,m=p&&p["*"]||{};if(e){for(l=(e=e.split("/")).length-1,b.nodeIdCompat&&w.test(e[l])&&(e[l]=e[l].replace(w,"")),"."===e[0].charAt(0)&&_&&(e=_.slice(0,_.length-1).concat(e)),d=0;d li, tbody > tr > td":"_listItem_onMousedown","dblclick > li, tbody > tr > td":"_listItem_onDoubleClick",click:"_listBackground_onClick","click ul.collection-view, table.collection-view":"_listBackground_onClick",keydown:"_onKeydown"},spawnMessages:{focus:"focus"},passMessages:{"*":"."},initializationOptions:[{collection:null},{modelView:null},{modelViewOptions:{}},{itemTemplate:null},{itemTemplateFunction:null},{selectable:!0},{clickToSelect:!0},{selectableModelsFilter:null},{visibleModelsFilter:null},{sortableModelsFilter:null},{selectMultiple:!1},{clickToToggle:!1},{processKeyEvents:!0},{sortable:!1},{sortableOptions:null},{reuseModelViews:!0},{detachedRendering:!1},{emptyListCaption:null}],initialize:function(e){t.ViewOptions.add(this,"initializationOptions"),this.setOptions(e),this.collection||(this.collection=new t.Collection),this._hasBeenRendered=!1,this._isBackboneCourierAvailable()&&t.Courier.add(this),this.$el.data("view",this),this.$el.addClass("collection-view collection-list"),this.selectable&&this.$el.addClass("selectable"),this.selectable&&this.processKeyEvents&&this.$el.attr("tabindex",0),this.selectedItems=[],this._updateItemTemplate(),this.collection&&this._registerCollectionEvents(),this.viewManager=new ChildViewContainer},_onOptionsChanged:function(s,n){var o=this,l=!1;h.each(h.keys(s),function(e){var t=s[e],i=n[e];switch(e){case"collection":t!==i&&(o.stopListening(i),o._registerCollectionEvents());break;case"selectMultiple":!t&&1"+e+"");t=this._isRenderedAsList()?i.wrapAll(" ").parent().css(s):i.wrapAll(" ").parent().parent().css(s),this._getContainerEl().append(t)}},_removeEmptyListCaption:function(){this._isRenderedAsList()?this._getContainerEl().find("> li > var.empty-list-caption").parent().remove():this._getContainerEl().find("> tr > td > var.empty-list-caption").parent().parent().remove()},_insertAndRenderModelView:function(e,t,i){var s=this._wrapModelView(e);if(11===t.nodeType)t.appendChild(s.get(0));else{var n=t.children().length;!h.isUndefined(i)&&0<=i&&i tbody");if(0 *").removeClass("selected")},this);var i=this.selectedItems;i=h.without(i,e),h.each(i,function(e){this._getContainerEl().find("[data-model-cid="+e+"]").addClass("selected"),this._isRenderedAsList()&&this._getContainerEl().find("li[data-model-cid="+e+"] > *").addClass("selected")},this)},_reorderCollectionBasedOnHTML:function(){var i=this;this._getContainerEl().children().each(function(){var e=r(this).attr("data-model-cid");if(e){var t=i.collection.get(e);t&&(i.collection.remove(t,{silent:!0}),i.collection.add(t,{silent:!0,sort:!i.collection.comparator}))}}),this._isBackboneCourierAvailable()?this.spawn("reorder"):this.collection.trigger("reorder"),this.collection.comparator&&this.collection.sort()},_getModelViewConstructor:function(e){return this.modelView||i},_getModelViewOptions:function(e){var t=this.modelViewOptions;return h.isFunction(t)&&(t=t(e)),h.extend({model:e},t)},_createNewModelView:function(e,t){var i=this._getModelViewConstructor(e);if(h.isUndefined(i))throw"Could not find modelView constructor for model";var s=new i(t);return s.collectionListView=s.collectionView=this,s},_wrapModelView:function(e){var t;return this._isRenderedAsTable()?(t=e.$el,e.$el.attr("data-model-cid",e.model.cid)):this._isRenderedAsList()&&(e.$el.is("li")?(t=e.$el,e.$el.attr("data-model-cid",e.model.cid)):t=e.$el.wrapAll(" ").parent()),h.isFunction(this.sortableModelsFilter)&&(this.sortableModelsFilter.call(this,e.model)||(t.addClass("not-sortable"),e.$el.addClass("not-selectable"))),h.isFunction(this.selectableModelsFilter)&&(this.selectableModelsFilter.call(this,e.model)||(t.addClass("not-selectable"),e.$el.addClass("not-selectable"))),t},_convertStringsToInts:function(e){return h.map(e,function(e){if(!h.isString(e))return e;var t=parseInt(e,10);return t==e?t:e})},_containSameElements:function(e,t){return e.length==t.length&&h.intersection(e,t).length==e.length},_isRenderedAsTable:function(){return"table"===this.$el.prop("tagName").toLowerCase()},_isRenderedAsList:function(){return!this._isRenderedAsTable()},_modelViewHasWrapperLI:function(e){return this._isRenderedAsList()&&!e.$el.is("li")},_getVisibleItemEls:function(){return this._getContainerEl().find("> [data-model-cid]:not(.not-visible)")},_charCodes:{upArrow:38,downArrow:40},_isBackboneCourierAvailable:function(){return!h.isUndefined(t.Courier)},_setupSortable:function(){var e=h.extend({axis:"y",distance:10,forcePlaceholderSize:!0,items:this._isRenderedAsTable()?"> tbody > tr:not(.not-sortable)":"> li:not(.not-sortable)",start:h.bind(this._sortStart,this),change:h.bind(this._sortChange,this),stop:h.bind(this._sortStop,this),receive:h.bind(this._receive,this),over:h.bind(this._over,this)},h.result(this,"sortableOptions"));this.$el=this.$el.sortable(e)},_sortStart:function(e,t){var i=this.collection.get(t.item.attr("data-model-cid"));this._isBackboneCourierAvailable()?this.spawn("sortStart",{modelBeingSorted:i}):this.trigger("sortStart",i)},_sortChange:function(e,t){var i=this.collection.get(t.item.attr("data-model-cid"));this._isBackboneCourierAvailable()?this.spawn("sortChange",{modelBeingSorted:i}):this.trigger("sortChange",i)},_sortStop:function(e,t){var i=this.collection.get(t.item.attr("data-model-cid")),s=this._getContainerEl().children().index(t.item);-1==s&&i&&this.collection.remove(i),i&&(this._reorderCollectionBasedOnHTML(),this.updateDependentControls(),this._isBackboneCourierAvailable()?this.spawn("sortStop",{modelBeingSorted:i,newIndex:s}):this.trigger("sortStop",i,s))},_receive:function(e,t){var i=t.sender.data("view");if(i&&i.collection){var s=this._getContainerEl().children().index(t.item),n=i.collection.get(t.item.attr("data-model-cid"));i.collection.remove(n),this.collection.add(n,{at:s}),n.collection=this.collection,this.setSelectedModel(n)}},_over:function(e,t){this._getContainerEl().find("> var.empty-list-caption").hide()},_onKeydown:function(e){if(!this.processKeyEvents)return!0;var t=!1;if(1==this.getSelectedModels({by:"offset"}).length){var i=this.getSelectedModel({by:"offset"});e.which===this._charCodes.upArrow&&0!==i?(this.setSelectedModel(i-1,{by:"offset"}),t=!0):e.which===this._charCodes.downArrow&&i!==this.collection.length-1&&(this.setSelectedModel(i+1,{by:"offset"}),t=!0)}return!t},_listItem_onMousedown:function(t){var i=this._getClickedItemId(t);if(i){var e=this.collection.get(i);if(this._isBackboneCourierAvailable()){var s={clickedModel:e,metaKeyPressed:t.ctrlKey||t.metaKey};h.each(["preventDefault","stopPropagation","stopImmediatePropagation"],function(e){s[e]=function(){t[e]()}}),this.spawn("click",s)}else this.trigger("click",e)}if(this.selectable&&this.clickToSelect)if(i){if(h.isFunction(this.selectableModelsFilter)&&!this.selectableModelsFilter.call(this,this.collection.get(i)))return;if(this.selectMultiple&&t.shiftKey){var n=-1;0=i)){t=t||{},(e=e||{}).choice_type=this.get("question_type").get_choice_type(),e.question_id=this.get("id");var s=(t.parent=this).get("choices").add(e,t);Backbone.pubSub.trigger("question-add-choice",s,this)}},before_save:function(e,t){return"full"===t&&(e.question_type=this.get("question_type").get("id")),e},get_parent:function(){var e=this.get_relationships();if(e.parent){if(this.collection&&this.collection.parent)return this.collection.parent;if(e.parent.reference)return e.parent.reference}return!1},get_type_index:function(){var i=this.get("question_type").get("id");return this.collection.filter(function(e){var t=e.get("question_type").get("id");return"content"!==i?"content"!==t:"content"===t}).indexOf(this)},get_type_iterator:function(){var e=this.get_type_index();return-1===e?"":"content"===this.get("question_type").get("id")?"ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("")[e]:e+1},get_qid:function(){var e=this.get_parent_question(),t="";return e&&(t=e.get_qid()+"."),t+this.get_type_iterator()},get_parent_question:function(){return!!this.is_in_group()&&this.collection.parent},get_parent_quiz:function(){return this.get_parent()},get_points:function(){return this.get("question_type").get("points")?this.get("points"):0},get_points_percentage:function(){var e=this.get_parent().get("_points"),t=this.get("points");return 0===e?"0%":(t/e*100).toFixed(2)+"%"},is_in_group:function(){return"question"===this.collection.parent.get("type")},_ensure_min_choices:function(){for(var e=this.get("choices");e.size() li.llms-section > .llms-builder-header .llms-headline":"_listItem_onMousedown",click:"_listBackground_onClick","click ul.collection-view":"_listBackground_onClick",keydown:"_onKeydown"},modelView:e,processKeyEvents:!1,selectable:!0,sortable:!0,sortableOptions:{axis:!1,cursor:"move",handle:".drag-section",items:".llms-section",placeholder:"llms-section llms-sortable-placeholder"},sortable_start:function(e){this.$el.addClass("dragging")},sortable_stop:function(e){this.$el.removeClass("dragging")}},t))}),n("Views/Course",["Views/SectionList","Views/_Editable"],function(e,t){return Backbone.View.extend(_.defaults({attributes:function(){return{"data-id":this.model.id}},el:"#llms-builder-main",tagName:"div",template:wp.template("llms-course-template"),initialize:function(){this.render(),this.sectionListView=new e({collection:this.model.get("sections")}),this.sectionListView.render(),this.sectionListView.on("sortStart",this.sectionListView.sortable_start),this.sectionListView.on("sortStop",this.sectionListView.sortable_stop),this.sectionListView.on("selectionChanged",this.active_section_change),this.listenTo(this.model.get("sections"),"add",this.on_section_add),Backbone.pubSub.on("section-toggle",this.on_section_toggle,this),Backbone.pubSub.on("expand-section",this.expand_section,this),Backbone.pubSub.on("lesson-selected",this.active_lesson_change,this)},render:function(){return this.$el.html(this.template(this.model)),this},active_lesson_change:function(e){var t=this.model.get("sections").get(e.get("parent_section"));this.sectionListView.setSelectedModel(t)},active_section_change:function(e,t){_.each(e,function(e){e.set("_selected",!0)}),_.each(t,function(e){e.set("_selected",!1)})},on_section_add:function(e){this.sectionListView.setSelectedModel(e)},on_section_toggle:function(e){var t=e.get("_expanded")?[e]:[];this.sectionListView.setSelectedModels(t)}},t))}),n("Views/SettingsFields",[],function(){return Backbone.View.extend(_.defaults({events:{"click .llms-settings-group-toggle":"toggle_group"},fields:{},tagName:"div",template:wp.template("llms-settings-fields-template"),get_editor_fields:function(){return _.filter(this.fields,function(e){return this.is_editor_field(e.type)},this)},get_groups:function(){return this.model.get_settings_fields()},is_group_hidden:function(e){var t="llms-"+this.model.get("type")+"-settings-group--"+e;return"undefined"!==window.localStorage&&"hidden"===window.localStorage.getItem(t)},get_switch_attribute:function(e){return e.switch_attribute?e.switch_attribute:e.attribute},has_switch:function(e){return-1!==e.indexOf("switch")},is_default_field:function(e){return-1!==["audio_embed","datepicker","number","text","video_embed"].indexOf(e.replace("switch-",""))},is_editor_field:function(e){return-1!==["editor","switch-editor"].indexOf(e.replace("switch-",""))},is_switch_condition_met:function(e){return e.switch_on===this.model.get(e.switch_attribute)},render:function(){return this.$el.html(this.template(this)),_.each(this.get_editor_fields(),function(e){this.render_editor(e)},this),this},render_editor:function(e){var o=this;wp.editor.remove(e.id),e.settings.tinymce.setup=function(t){var i=g("#"+t.id),e=i.closest(".llms-editable-editor"),s=e.find(".llms-label"),n=i.attr("data-attribute");s.length&&s.prependTo(e.find(".wp-editor-tools")),t.on("change",function(e){o.model.set(n,wp.editor.getContent(t.id))}),i.on("input",function(e){o.model.set(n,i.val())}),e.on("click",".quicktags-toolbar .ed_button",function(){setTimeout(function(){i.trigger("input")},10)})},wp.editor.initialize(e.id,e.settings)},render_select_options:function(e,i){var s="",n=this.model.get(i);function o(e,t){return'"+e+" "}return _.each(e,function(e,t){"string"==typeof e?s+=o(e,t):"object"==typeof e&&(e.label&&e.options?(s+='',s+=this.render_select_options(e.options,i)):s+=o(e.val,e.key))},this),s},setup_field:function(e,t){var i={classes:[],id:_.uniqueId(e.attribute+"_"),input_type:"text",label:"",options:{},placeholder:"",tip:"",tip_position:"top-right",settings:{}};if(e.condition&&!1===_.bind(e.condition,this.model)())return!1;switch(e.type){case"audio_embed":i.classes.push("llms-editable-audio"),i.placeholder="https://",i.tip=LLMS.l10n.translate("Use SoundCloud or Spotify audio URLS."),i.input_type="url";break;case"datepicker":i.classes.push("llms-editable-date");break;case"editor":case"switch-editor":var s=e.settings||{};i.settings=g.extend(!0,wp.editor.getDefaultSettings(),{mediaButtons:!0,tinymce:{toolbar1:"bold,italic,strikethrough,bullist,numlist,blockquote,hr,alignleft,aligncenter,alignright,link,unlink,wp_adv",toolbar2:"formatselect,underline,alignjustify,forecolor,pastetext,removeformat,charmap,outdent,indent,undo,redo,wp_help"}},s);break;case"number":i.input_type="number";break;case"permalink":i.label=LLMS.l10n.translate("Permalink");break;case"video_embed":i.classes.push("llms-editable-video"),i.placeholder="https://",i.tip=LLMS.l10n.translate("Use YouTube, Vimeo, or Wistia video URLS."),i.input_type="url"}this.has_switch(e.type)&&(i.switch_on="yes",i.switch_off="no");var n=_.defaults(_.deepClone(e),i);if(_.isFunction(n.options)&&(n.options=_.bind(n.options,this.model)()),-1!==["radio","switch-radio"].indexOf(e.type)){var o=!1;_.each(e.options,function(e,t){-1===e.indexOf(".png")&&-1===e.indexOf(".jpg")||(n.options[t]=' ',o=!0)}),o&&n.classes.push("has-images")}return n.tip&&n.classes.push("tip--"+n.tip_position),n.classes.length&&(n.classes=" "+n.classes.join(" ")),this.fields[n.id]=n},should_rerender_on_toggle:function(e){return-1!==e.indexOf("switch-")?"yes":"no"},toggle_group:function(e){e.preventDefault();var t=g(e.currentTarget).closest(".llms-model-settings");if(t.toggleClass("hidden"),"undefined"!==window.localStorage){var i=t.attr("id");t.hasClass("hidden")?window.localStorage.setItem(i,"hidden"):window.localStorage.removeItem(i)}}}))}),n("Views/LessonEditor",["Views/_Detachable","Views/_Editable","Views/_Trashable","Views/_Subview","Views/SettingsFields"],function(e,t,i,s,n){return Backbone.View.extend(_.defaults({state:"default",views:{settings:{class:n,instance:null,state:"default"}},el:"#llms-editor-lesson",events:_.defaults({},e.events,t.events,i.events),template:wp.template("llms-lesson-settings-template"),initialize:function(e){this.model=e.lesson;_.each(["change:date_available","change:drip_method","change:time_available"],function(e){this.listenTo(this.model,e,this.render)},this),this.listenTo(this.model,"change:has_prerequisite",function(e,t){"yes"===t&&this.$el.find('select[name="prerequisite"]').trigger("change")})},render:function(){return this.$el.html(this.template(this.model)),this.remove_subview("settings"),this.render_subview("settings",{el:"#llms-lesson-settings-fields",model:this.model}),this.init_datepickers(),this.init_selects(),this}},e,t,i,s,n))}),n("Views/Popover",[],function(){return Backbone.View.extend({defaults:{placement:"auto",width:"auto",trigger:"manual",style:"light",animation:"pop",title:"",content:"",closeable:!1,backdrop:!1,onShow:function(e){},onHide:function(e){}},tagName:"div",initialize:function(e){this.$el.length&&(this.defaults.container=this.$el.parent()),this.args=_.defaults(e.args,this.defaults),this.render()},render:function(){return this.$el.webuiPopover(this.args),this},hide:function(){return this.$el.webuiPopover("hide"),this},show:function(){return this.$el.webuiPopover("show"),this}})}),n("Views/PostSearch",[],function(){return Backbone.View.extend({events:{"select2:select":"add_post"},tagName:"select",initialize:function(e){this.post_type=e.post_type,this.searching_message=e.searching_message||LLMS.l10n.translate("Searching...")},add_post:function(e){var t=this.$el.attr("data-post-type");Backbone.pubSub.trigger(t.replace("llms_","")+"-search-select",e.params.data,e),this.$el.val(null).trigger("change")},render:function(){var t=this;return setTimeout(function(){t.$el.llmsSelect2({ajax:{dataType:"JSON",delay:250,method:"POST",url:window.ajaxurl,data:function(e){return{action:"llms_builder",action_type:"search",course_id:window.llms_builder.course.id,post_type:t.post_type,term:e.term,page:e.page,_ajax_nonce:wp_ajax_data.nonce}}},dropdownParent:g(".wrap.lifterlms.llms-builder"),escapeMarkup:function(e){return e},placeholder:t.searching_message,templateResult:t.render_result,width:"100%"}),t.$el.attr("data-post-type",t.post_type)},0),this},render_result:function(e){var t=g('
');if(e.loading)return t.append(e.text);var i=g(''),s=g('
');return icon="attach"===e.action?"paperclip":"clone",text="attach"===e.action?LLMS.l10n.translate("Attach"):LLMS.l10n.translate("Clone"),i.append(''+text+" "),s.append(""+e.data.title+" "),s.append(""+LLMS.l10n.translate("ID")+": "+e.data.id+" "),_.each(e.parents,function(e){s.append(""+e+" ")}),t.append(i).append(s)}})}),n("Views/QuestionType",[],function(){return Backbone.View.extend({className:"llms-question-type",events:{"click .llms-add-question":"add_question"},id:function(){return"llms-question-type-"+this.model.id},tagName:"li",template:wp.template("llms-question-type-template"),initialize:function(){this.render()},render:function(){return this.$el.html(this.template(this.model)),this},add_question:function(){this.quiz.add_question({_expanded:!0,choices:this.model.get("default_choices")?this.model.get("default_choices"):null,question_type:this.model}),this.quiz.trigger("new-question-added")}})}),n("Views/QuestionBank",["Views/QuestionType"],function(e){return Backbone.CollectionView.extend({className:"llms-question",el:"#llms-question-bank",modelView:e,selectable:!1,sortable:!1})}),n("Views/QuestionChoice",["Views/_Editable"],function(e){return Backbone.View.extend(_.defaults({className:"llms-question-choice",events:_.defaults({'change input[name="correct"]':"toggle_correct",'click .llms-action-icon[href="#llms-add-choice"]':"add_choice",'click .llms-action-icon[href="#llms-del-choice"]':"del_choice"},e.events),id:function(){return"llms-question-choice-"+this.model.id},tagName:"li",template:wp.template("llms-question-choice-template"),initialize:function(){this.render(),this.listenTo(this.model.collection,"add",this.maybe_disable_buttons),this.listenTo(this.model,"change",this.render),"image"===this.model.get("choice_type")&&this.listenTo(this.model.get("choice"),"change",this.render)},render:function(){return this.$el.html(this.template(this.model)),this},add_choice:function(e){e.stopPropagation(),e.preventDefault();var t=this.model.collection.indexOf(this.model);this.model.collection.parent.add_choice({},{at:t+1})},del_choice:function(e){e.preventDefault(),Backbone.pubSub.trigger("model-trashed",this.model),this.model.collection.remove(this.model)},toggle_correct:function(){var e=this.$el.find('input[name="correct"]').is(":checked");this.model.set("correct",e),this.model.collection.trigger("correct-update",this.model)}},e))}),n("Views/QuestionChoiceList",["Views/QuestionChoice"],function(e){return Backbone.CollectionView.extend({className:"llms-quiz-questions",modelView:e,processKeyEvents:!1,selectable:!1,sortable:!0,sortableOptions:{axis:!1,cursor:"move",handle:".llms-choice-id",items:".llms-question-choice",placeholder:"llms-question-choice llms-sortable-placeholder"},sortable_start:function(e){this.$el.addClass("dragging")},sortable_stop:function(e){this.$el.removeClass("dragging")}})}),n("Views/Question",["Views/_Editable","Views/QuestionChoiceList"],function(e,t){return Backbone.View.extend(_.defaults({className:function(){return"llms-question qtype--"+this.model.get("question_type").get("id")},events:_.defaults({"click .clone--question":"clone","click .delete--question":"delete","click .expand--question":"expand","click .collapse--question":"collapse",'change input[name="question_points"]':"update_points"},e.events),id:function(){return"llms-question-"+this.model.id},tagName:"li",template:wp.template("llms-question-template"),initialize:function(){_.each(["change:_expanded","change:menu_order"],function(e){this.listenTo(this.model,e,this.render)},this),this.listenTo(this.model.get("image"),"change",this.render),this.listenTo(this.model.get_parent(),"change:_points",this.render_points_percentage),this.on("multi_choices_toggle",this.multi_choices_toggle,this),Backbone.pubSub.on("del-question-choice",this.del_choice,this)},render:function(){if(this.$el.html(this.template(this.model)),this.model.get("question_type").get("choices")&&(this.choiceListView=new t({el:this.$el.find(".llms-question-choices"),collection:this.model.get("choices")}),this.choiceListView.render(),this.choiceListView.on("sortStart",this.choiceListView.sortable_start),this.choiceListView.on("sortStop",this.choiceListView.sortable_stop)),"group"===this.model.get("question_type").get("id")){var e=this;setTimeout(function(){e.questionListView=e.collectionListView.quiz.get_question_list({el:e.$el.find(".llms-quiz-questions"),collection:e.model.get("questions")}),e.questionListView.render(),e.questionListView.on("sortStart",e.questionListView.sortable_start),e.questionListView.on("sortStop",e.questionListView.sortable_stop)},1)}return this.model.get("description_enabled")&&this.init_editor("question-desc--"+this.model.get("id")),this.model.get("clarifications_enabled")&&this.init_editor("question-clarifications--"+this.model.get("id"),{mediaButtons:!1,tinymce:{toolbar1:"bold,italic,strikethrough,bullist,numlist,alignleft,aligncenter,alignright",toolbar2:"",setup:_.bind(this.on_editor_ready,this)}}),this.init_formatting_els(),this.init_selects(),this},render_points_percentage:function(){this.$el.find(".llms-question-points").attr("data-tip",this.model.get_points_percentage())},clone:function(e){e.stopPropagation(),e.preventDefault(),this.model.collection.add(this._get_question_clone(this.model))},_get_question_clone:function(e){var i=_.clone(e.attributes);return delete i.id,i.parent_id=e.get("id"),i.question_type=e.get("question_type").get("id"),i.image=_.clone(e.get("image").attributes),e.get("choices")&&(i.choices=[],e.get("choices").each(function(e){var t=_.clone(e.attributes);delete t.id,delete t.question_id,i.choices.push(t)})),"group"===e.get("question_type").get("id")&&(i.questions=[],e.get("questions").each(function(e){i.questions.push(this._get_question_clone(e))},this)),i},collapse:function(){this.model.set("_expanded",!1)},delete:function(e){e.preventDefault(),window.confirm(LLMS.l10n.translate("Are you sure you want to delete this question?"))&&(this.model.collection.remove(this.model),Backbone.pubSub.trigger("model-trashed",this.model))},expand:function(){this.model.set("_expanded",!0)},multi_choices_toggle:function(e){"yes"!==e&&this.model.get("choices").update_correct(_.first(this.model.get("choices").get_correct()))},update_points:function(){this.model.set("points",1*this.$el.find('input[name="question_points"]').val())}},e))}),n("Views/QuestionList",["Views/Question"],function(e){return Backbone.CollectionView.extend({className:"llms-quiz-questions",modelView:e,processKeyEvents:!1,selectable:!1,sortable:!0,sortableOptions:{axis:!1,connectWith:".llms-quiz-questions",cursor:"move",handle:".llms-data-stamp",items:".llms-question",placeholder:"llms-question llms-sortable-placeholder"},sortable_start:function(e){var t="group"===e.get("question_type").get("id")?".llms-editor-tab > .llms-quiz-questions":".llms-quiz-questions";g(t).addClass("dragging")},sortable_stop:function(){g(".llms-quiz-questions").removeClass("dragging")},_receive:function(e,t){if(e.stopPropagation(),t.item.hasClass("qtype--group")&&g(e.target).closest(".qtype--group").length)t.sender.sortable("cancel");else{var i=t.sender.data("view");if(i&&i.collection){var s=this._getContainerEl().children().index(t.item),n=i.collection.get(t.item.attr("data-model-cid"));i.collection.remove(n),this.collection.add(n,{at:s}),n.collection=this.collection,this.setSelectedModel(n)}}},_sortStart:function(e,t){var i=this.collection.get(t.item.attr("data-model-cid"));t.placeholder.addClass("qtype--"+i.get("question_type").get("id")),this._isBackboneCourierAvailable()?this.spawn("sortStart",{modelBeingSorted:i}):this.trigger("sortStart",i)},_sortStop:function(e,t){e.stopPropagation();var i=this.collection.get(t.item.attr("data-model-cid")),s=this._getContainerEl().children().index(t.item);-1==s&&i&&this.collection.remove(i),this._reorderCollectionBasedOnHTML(),this.updateDependentControls(),this._isBackboneCourierAvailable()?this.spawn("sortStop",{modelBeingSorted:i,newIndex:s}):this.trigger("sortStop",i,s)}})}),n("Views/Quiz",["Models/Quiz","Views/Popover","Views/PostSearch","Views/QuestionBank","Views/QuestionList","Views/SettingsFields","Views/_Detachable","Views/_Editable","Views/_Subview","Views/_Trashable"],function(e,t,i,s,n,o,l,a,r,c){return Backbone.View.extend(_.defaults({state:"default",views:{settings:{class:o,instance:null,state:"default"},bank:{class:s,instance:null,state:"default"},list:{class:n,instance:null,state:"default"}},el:"#llms-editor-quiz",events:_.defaults({"click #llms-existing-quiz":"add_existing_quiz_click","click #llms-new-quiz":"add_new_quiz","click #llms-show-question-bank":"show_tools","click .bulk-toggle":"bulk_toggle"},l.events,a.events,c.events),tagName:"div",template:wp.template("llms-quiz-template"),initialize:function(e){this.lesson=e.lesson,"yes"!==this.lesson.get("quiz_enabled")&&_.isEmpty(this.lesson.get("quiz"))||(this.model=this.lesson.get("quiz"),this.model.set_parent(this.lesson),this.listenTo(this.model,"change:_points",this.render_points)),this.on("model-trashed",this.on_trashed)},render:function(){if(this.$el.html(this.template(this.model)),this.model){LLMS.Spinner.start(this.$el),this.render_subview("settings",{el:"#llms-quiz-settings-fields",model:this.model}),this.init_datepickers(),this.init_selects(),this.render_subview("bank",{collection:window.llms_builder.questions});var t=null,i=null;this.get_subview("bank").instance.viewManager.each(function(e){e.quiz=this.model,i=e.model.get("group").name,t!==i&&(t=i,e.$el.before('"))},this),this.model.load_questions(_.bind(function(e){if(e)return alert(LLMS.l10n.translate("An error occurred while trying to load the questions. Please refresh the page and try again.")),this;LLMS.Spinner.stop(this.$el),this.render_subview("list",{el:"#llms-quiz-questions",collection:this.model.get("questions")});var t=this.get_subview("list").instance;t.quiz=this,t.collection.on("add",function(){t.collection.trigger("reorder")},this),t.on("sortStart",t.sortable_start),t.on("sortStop",t.sortable_stop)},this)),this.model.on("new-question-added",function(){var e=this.$el.find("#llms-quiz-questions");e.animate({scrollTop:e.prop("scrollHeight")},200)},this)}return this},render_points:function(e,t){this.$el.find("#llms-quiz-total-points").text(t)},bulk_toggle:function(e){var t="expand"===g(e.target).attr("data-action");this.model.get("questions").each(function(e){e.set("_expanded",t)})},add_new_quiz:function(){var e=this.lesson.get("quiz");_.isEmpty(e)?e=this.lesson.add_quiz():this.lesson.set("quiz_enabled","yes"),this.model=e,this.render()},add_existing_quiz:function(e){this.post_search_popover.hide();var t=e.data;"clone"===e.action?(delete t.id,_.each(t.questions,function(e){delete e.parent_id,delete e.id,e.choices&&_.each(e.choices,function(e){delete e.question_id,delete e.id})})):t._forceSync=!0,delete t.lesson_id,this.lesson.add_quiz(t),this.model=this.lesson.get("quiz"),this.render()},add_existing_quiz_click:function(e){e.preventDefault(),this.post_search_popover=new t({el:"#llms-existing-quiz",args:{backdrop:!0,closeable:!0,container:".wrap.lifterlms.llms-builder",dismissible:!0,placement:"left",width:480,title:LLMS.l10n.translate("Add Existing Quiz"),content:new i({post_type:"llms_quiz",searching_message:LLMS.l10n.translate("Search for existing quizzes...")}).render().$el,onHide:function(){Backbone.pubSub.off("quiz-search-select")}}}),this.post_search_popover.show(),Backbone.pubSub.once("quiz-search-select",this.add_existing_quiz,this)},on_trashed:function(e){this.lesson.set("quiz_enabled","no"),this.lesson.set("quiz",""),delete this.model,this.render()},show_tools:function(){var e=new t({el:"#llms-show-question-bank",args:{backdrop:!0,closeable:!0,container:"#llms-builder-sidebar",dismissible:!0,placement:"top-left",width:"calc( 100% - 40px )",title:LLMS.l10n.translate("Add a Question"),url:"#llms-quiz-tools"}});e.show(),this.model.on("new-question-added",function(){e.hide()})},get_question_list:function(e){return new n(e)}},l,a,r,c,o))}),n("Views/Assignment",["Views/Popover","Views/PostSearch","Views/_Detachable","Views/_Editable","Views/_Trashable","Views/_Subview","Views/SettingsFields"],function(s,t,i,n,o,e,l){return Backbone.View.extend(_.defaults({state:"default",views:{settings:{class:l,instance:null,state:"default"}},el:"#llms-editor-assignment",events:function(){var e=this.is_addon_available()?window.llms_builder.assignments.get_view_events():{};return _.defaults({"click #llms-existing-assignment":"add_existing_assignment_click","click #llms-new-assignment":"add_new_assignment"},i.events,n.events,o.events,e)},tagName:"div",template:wp.template("llms-assignment-template"),initialize:function(e){this.lesson=e.lesson,"yes"!==this.lesson.get("assignment_enabled")&&_.isEmpty(this.lesson.get("assignment"))||(this.model=this.lesson.get("assignment"),this.model.set_parent(this.lesson)),this.on("model-trashed",this.on_trashed)},render:function(){return this.$el.html(this.template(this.model)),this.model&&this.is_addon_available()&&(this.stopListening(this.model,"change:assignment_type",this.render),this.render_subview("settings",{el:"#llms-assignment-settings-fields",model:this.model}),this.init_selects(),window.llms_builder.assignments.render_editor(this),this.listenTo(this.model,"change:assignment_type",this.render)),this},add_new_assignment:function(){this.is_addon_available()?(this.model=window.llms_builder.assignments.get_assignment({title:LLMS.l10n.replace("%1$s Assignment",{"%1$s":this.lesson.get("title")}),lesson_id:this.lesson.get("id")}),this.lesson.set("assignment_enabled","yes"),this.lesson.set("assignment",this.model),this.render()):this.show_ad_popover("#llms-new-assignment")},add_existing_assignment:function(e){this.post_search_popover.hide();var t=e.data;"clone"===e.action?delete t.id:t._forceSync=!0,t.lesson_id=this.lesson.get("id"),t=window.llms_builder.construct.get_model("Assignment",t),this.lesson.set("assignment_enabled","yes"),this.lesson.set("assignment",t),this.model=t,this.render()},add_existing_assignment_click:function(e){e.preventDefault(),this.is_addon_available()?(this.post_search_popover=new s({el:"#llms-existing-assignment",args:{backdrop:!0,closeable:!0,container:".wrap.lifterlms.llms-builder",dismissible:!0,placement:"left",width:480,title:LLMS.l10n.translate("Add Existing Assignment"),content:new t({post_type:"llms_assignment",searching_message:LLMS.l10n.translate("Search for existing assignments...")}).render().$el,onHide:function(){Backbone.pubSub.off("assignment-search-select")}}}),this.post_search_popover.show(),Backbone.pubSub.once("assignment-search-select",this.add_existing_assignment,this)):this.show_ad_popover("#llms-existing-assignment")},is_addon_available:function(){return window.llms_builder.assignments},on_trashed:function(e){this.lesson.set("assignment_enabled","no"),this.lesson.set("assignment",""),delete this.model,this.render()},show_ad_popover:function(e){var t=LLMS.l10n.translate("Get Your Students Taking Action"),i=LLMS.l10n.translate("Get Assignments Now!");this.ad_popover=new s({el:e,args:{backdrop:!0,closeable:!0,container:".wrap.lifterlms.llms-builder",dismissible:!0,width:380,title:LLMS.l10n.translate("Unlock LifterLMS Assignments"),content:""+t+' Great learning content is only half of teaching online. When your learners fully engage, they will take your content and move into action. Remove barriers for your learners by telling them what to do to apply what they just learned. Create graded assignments or simply give them a checklist of action items to complete before moving on.
'+i+"
"}}),this.ad_popover.show()}},i,n,o,e,l))}),n("Views/Editor",["Views/LessonEditor","Views/Quiz","Views/Assignment","Views/_Subview"],function(e,t,i,s){return Backbone.View.extend(_.defaults({state:"lesson",views:{lesson:{class:e,instance:null,state:"lesson"},assignment:{class:i,instance:null,state:"assignment"},quiz:{class:t,instance:null,state:"quiz"}},el:"#llms-editor",events:{'click .llms-editor-nav a[href="#llms-editor-close"]':"close_editor",'click .llms-editor-nav a:not([href="#llms-editor-close"])':"switch_tab"},tagName:"div",template:wp.template("llms-editor-template"),initialize:function(e){this.SidebarView=e.SidebarView,e.tab&&(this.state=e.tab)},render:function(e){return e=e||{},this.$el.html(this.template(this)),this.render_subviews(_.extend(e,{lesson:this.model})),this},close_editor:function(e){e.preventDefault(),Backbone.pubSub.trigger("sidebar-editor-close")},switch_tab:function(e){e.preventDefault();var t=g(e.target),i=t.attr("data-view");this.$el.find(t.attr("href"));this.set_state(i).render()}},s))}),n("Views/Elements",["Models/Section","Views/Section","Models/Lesson","Views/Lesson","Views/Popover","Views/PostSearch"],function(e,t,i,s,n,o){return Backbone.View.extend({el:"#llms-elements",events:{"click #llms-new-section":"add_new_section","click #llms-new-lesson":"add_new_lesson","click #llms-existing-lesson":"add_existing_lesson"},tagName:"div",template:wp.template("llms-elements-template"),initialize:function(e){this.SidebarView=e.SidebarView,this.listenTo(this.SidebarView.CourseView.model.get("sections"),"add",this.maybe_disable_buttons),this.listenTo(this.SidebarView.CourseView.model.get("sections"),"remove",this.maybe_disable_buttons)},render:function(){return this.$el.html(this.template()),this.draggable(),this.maybe_disable_buttons(),this},draggable:function(){g("#llms-new-section").draggable({appendTo:"#llms-sections",cancel:!1,connectToSortable:".llms-sections",helper:function(){return new t({model:new e}).render().$el},start:function(){g(".llms-sections").addClass("dragging")},stop:function(){g(".llms-sections").removeClass("dragging")}}),g("#llms-new-lesson").draggable({appendTo:"#llms-sections",cancel:!1,connectToSortable:".llms-lessons",helper:function(){return new s({model:new i}).render().$el},start:function(){g(".llms-lessons").addClass("dragging")},stop:function(){g(".llms-lessons").removeClass("dragging"),g(".drag-expanded").removeClass(".drag-expanded")}})},add_new_section:function(e){e.preventDefault(),Backbone.pubSub.trigger("add-new-section")},add_new_lesson:function(e){e.preventDefault(),Backbone.pubSub.trigger("add-new-lesson")},add_existing_lesson:function(e){e.preventDefault();var t=new n({el:"#llms-existing-lesson",args:{backdrop:!0,closeable:!0,container:".wrap.lifterlms.llms-builder",dismissible:!0,placement:"left",width:480,title:LLMS.l10n.translate("Add Existing Lesson"),content:new o({post_type:"lesson",searching_message:LLMS.l10n.translate("Search for existing lessons...")}).render().$el}});t.show(),Backbone.pubSub.on("lesson-search-select",function(){t.hide()})},maybe_disable_buttons:function(){var e=g("#llms-new-lesson, #llms-existing-lesson");this.SidebarView.CourseView.model.get("sections").length?e.removeAttr("disabled"):e.attr("disabled","disabled")}})}),n("Views/Utilities",[],function(){return Backbone.View.extend({el:"#llms-utilities",events:{"click #llms-collapse-all":"collapse_all","click #llms-expand-all":"expand_all"},tagName:"div",template:wp.template("llms-utilities-template"),initialize:function(){},render:function(){return this.$el.html(this.template()),this},collapse_all:function(e){e.preventDefault(),Backbone.pubSub.trigger("collapse-all")},expand_all:function(e){e.preventDefault(),Backbone.pubSub.trigger("expand-all")}})}),n("Views/Sidebar",["Views/Editor","Views/Elements","Views/Utilities","Views/_Subview"],function(e,t,i,s){return Backbone.View.extend(_.defaults({state:"builder",views:{elements:{class:t,instance:null,state:"builder"},utilities:{class:i,instance:null,state:"builder"},editor:{class:e,instance:null,state:"editor"}},el:"#llms-builder-sidebar",events:{"click #llms-save-button":"save_now","click #llms-exit-button":"exit_now","click .llms-builder-error":"clear_errors"},tagName:"aside",template:wp.template("llms-sidebar-template"),initialize:function(e){this.CourseView=e.CourseView,this.render(),Backbone.pubSub.on("current-save-status",this.changes_made,this),Backbone.pubSub.on("heartbeat-send",this.heartbeat_send,this),Backbone.pubSub.on("heartbeat-tick",this.heartbeat_tick,this),Backbone.pubSub.on("lesson-selected",this.on_lesson_select,this),Backbone.pubSub.on("sidebar-editor-close",this.on_editor_close,this),this.$saveButton=g("#llms-save-button")},render:function(e){e=e||{},this.$el.html(this.template()),this.render_subviews(_.extend(e,{SidebarView:this}));var t=g(".wrap.lifterlms.llms-builder");return"builder"===this.state?t.removeClass("editor-active"):t.addClass("editor-active"),this.$saveButton=this.$el.find("#llms-save-button"),this},add_error:function(e){this.$el.find(".llms-builder-save").prepend(e)},clear_errors:function(){this.$el.find(".llms-builder-save .llms-builder-error").remove()},changes_made:function(e){e.saving||(e.has_unsaved_changes?(this.$saveButton.attr("data-status","unsaved"),this.$saveButton.removeAttr("disabled")):(this.$saveButton.attr("data-status","saved"),this.$saveButton.attr("disabled","disabled")))},exit_now:function(){window.location.href=window.llms_builder.CourseModel.get_edit_post_link()},heartbeat_send:function(e){e.saving&&(LLMS.Spinner.start(this.$saveButton.find("i"),"small"),this.$saveButton.attr({"data-status":"saving",disabled:"disabled"}))},heartbeat_tick:function(e,t){if(!e.saving){var i="saved";if(this.clear_errors(),"error"===t.status){i="error";var s=t.message,n=g(' ');"object"==typeof s?_.each(s,function(e){n.append(""+e+" ")}):n=n.append(""+s+" "),this.add_error(n)}this.$saveButton.find(".llms-spinning").remove(),this.$saveButton.attr({"data-status":i,disabled:"disabled"})}},is_editor_active:function(){return"editor"===this.state},on_editor_close:function(){this.set_state("builder").render()},on_lesson_select:function(e,t){"editor"!==this.state?this.set_state("editor"):this.remove_subview("editor"),this.render({model:e,tab:t})},save_now:function(){window.llms_builder.sync.save_now()}},s))}),t(["vendor/backbone.collectionView","vendor/backbone.trackit","Controllers/Construct","Controllers/Debug","Controllers/Schemas","Controllers/Sync","Models/loader","Views/Course","Views/Sidebar"],function(e,t,i,s,n,o,l,a,r){function c(e,t){return _.isArray(t)&&-1!==t.indexOf(e)||e==t}window.llms_builder.debug=new s(window.llms_builder.debug),window.llms_builder.construct=new i,window.llms_builder.schemas=new n(window.llms_builder.schemas),_.mixin({checked:function(e,t){return c(e,t)?' checked="checked"':""},deepClone:function(e){var i=_.clone(e);return _.each(i,function(e,t){!_.isFunction(e)&&_.isObject(e)&&(i[t]=_.deepClone(e))}),i},selected:function(e,t){return c(e,t)?' selected="selected"':""},stripFormatting:function(e,t){t||(t=["b","i","u","strong","em"]);var i=g(""+e+"
");return i.find("*").not(t.join(",")).each(function(){g(this).replaceWith(this.innerHTML)}),i.html()}}),Backbone.pubSub=_.extend({},Backbone.Events),g(document).trigger("llms-builder-pre-init"),window.llms_builder.questions=window.llms_builder.construct.get_collection("QuestionTypes",window.llms_builder.questions);var d=window.llms_builder.construct.get_model("Course",window.llms_builder.course);window.llms_builder.CourseModel=d,window.llms_builder.sync=new o(d,window.llms_builder.sync);var u=new a({model:d}),h=new r({CourseView:u});g(document).trigger("llms-builder-init",{course:u,sidebar:h})}),n("main",function(){})}(jQuery);
-//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImxsbXMtYnVpbGRlci5qcyJdLCJuYW1lcyI6WyIkIiwicmVxdWlyZWpzIiwicmVxdWlyZSIsImRlZmluZSIsInJvb3QiLCJmYWN0b3J5IiwidW5zYXZlZE1vZGVscyIsImdldFByb21wdCIsInVuZGVmIiwibWFpbiIsInJlcSIsIm1ha2VNYXAiLCJoYW5kbGVycyIsImRlZmluZWQiLCJ3YWl0aW5nIiwiY29uZmlnIiwiZGVmaW5pbmciLCJoYXNPd24iLCJPYmplY3QiLCJwcm90b3R5cGUiLCJoYXNPd25Qcm9wZXJ0eSIsImFwcyIsInNsaWNlIiwianNTdWZmaXhSZWdFeHAiLCJoYXNQcm9wIiwib2JqIiwicHJvcCIsImNhbGwiLCJub3JtYWxpemUiLCJuYW1lIiwiYmFzZU5hbWUiLCJuYW1lUGFydHMiLCJuYW1lU2VnbWVudCIsIm1hcFZhbHVlIiwiZm91bmRNYXAiLCJsYXN0SW5kZXgiLCJmb3VuZEkiLCJmb3VuZFN0YXJNYXAiLCJzdGFySSIsImkiLCJqIiwicGFydCIsImJhc2VQYXJ0cyIsInNwbGl0IiwibWFwIiwic3Rhck1hcCIsImxlbmd0aCIsIm5vZGVJZENvbXBhdCIsInRlc3QiLCJyZXBsYWNlIiwiY2hhckF0IiwiY29uY2F0Iiwic3BsaWNlIiwiam9pbiIsIm1ha2VSZXF1aXJlIiwicmVsTmFtZSIsImZvcmNlU3luYyIsImFyZ3MiLCJhcmd1bWVudHMiLCJwdXNoIiwiYXBwbHkiLCJtYWtlTG9hZCIsImRlcE5hbWUiLCJ2YWx1ZSIsImNhbGxEZXAiLCJFcnJvciIsInNwbGl0UHJlZml4IiwicHJlZml4IiwiaW5kZXgiLCJpbmRleE9mIiwic3Vic3RyaW5nIiwibWFrZVJlbFBhcnRzIiwicmVsUGFydHMiLCJwbHVnaW4iLCJwYXJ0cyIsInJlbFJlc291cmNlTmFtZSIsImYiLCJuIiwicHIiLCJwIiwiZXhwb3J0cyIsImUiLCJtb2R1bGUiLCJpZCIsInVyaSIsImRlcHMiLCJjYWxsYmFjayIsImNqc01vZHVsZSIsInJldCIsInVzaW5nRXhwb3J0cyIsImNhbGxiYWNrVHlwZSIsImxvYWQiLCJ1bmRlZmluZWQiLCJhbHQiLCJzZXRUaW1lb3V0IiwiY2ZnIiwiX2RlZmluZWQiLCJhbWQiLCJqUXVlcnkiLCJfIiwiQmFja2JvbmUiLCJ0aGlzIiwibURlZmF1bHRNb2RlbFZpZXdDb25zdHJ1Y3RvciIsIlZpZXciLCJrRGVmYXVsdFJlZmVyZW5jZUJ5Iiwia09wdGlvbnNSZXF1aXJpbmdSZXJlbmRlcmluZyIsImtTdHlsZXNGb3JFbXB0eUxpc3RDYXB0aW9uIiwiYmFja2dyb3VuZCIsImJvcmRlciIsImJveC1zaGFkb3ciLCJfbm9ybWFsaXplT3B0aW9uRGVjbGFyYXRpb25zIiwib3B0aW9uRGVjbGFyYXRpb25zIiwibm9ybWFsaXplZE9wdGlvbkRlY2xhcmF0aW9ucyIsImlzQXJyYXkiLCJlYWNoIiwidGhpc09wdGlvbkRlY2xhcmF0aW9uIiwidGhpc09wdGlvbk5hbWUiLCJ0aGlzT3B0aW9uUmVxdWlyZWQiLCJ0aGlzT3B0aW9uRGVmYXVsdFZhbHVlIiwiaXNTdHJpbmciLCJpc09iamVjdCIsImZpcnN0Iiwia2V5cyIsImlzRnVuY3Rpb24iLCJjbG9uZSIsInJlcXVpcmVkIiwiaXNVbmRlZmluZWQiLCJkZWZhdWx0VmFsdWUiLCJDb2xsZWN0aW9uVmlldyIsImV4dGVuZCIsInRhZ05hbWUiLCJldmVudHMiLCJtb3VzZWRvd24gPiBsaSwgdGJvZHkgPiB0ciA+IHRkIiwiZGJsY2xpY2sgPiBsaSwgdGJvZHkgPiB0ciA+IHRkIiwiY2xpY2siLCJjbGljayB1bC5jb2xsZWN0aW9uLXZpZXcsIHRhYmxlLmNvbGxlY3Rpb24tdmlldyIsImtleWRvd24iLCJzcGF3bk1lc3NhZ2VzIiwiZm9jdXMiLCJwYXNzTWVzc2FnZXMiLCIqIiwiaW5pdGlhbGl6YXRpb25PcHRpb25zIiwiY29sbGVjdGlvbiIsIm1vZGVsVmlldyIsIm1vZGVsVmlld09wdGlvbnMiLCJpdGVtVGVtcGxhdGUiLCJpdGVtVGVtcGxhdGVGdW5jdGlvbiIsInNlbGVjdGFibGUiLCJjbGlja1RvU2VsZWN0Iiwic2VsZWN0YWJsZU1vZGVsc0ZpbHRlciIsInZpc2libGVNb2RlbHNGaWx0ZXIiLCJzb3J0YWJsZU1vZGVsc0ZpbHRlciIsInNlbGVjdE11bHRpcGxlIiwiY2xpY2tUb1RvZ2dsZSIsInByb2Nlc3NLZXlFdmVudHMiLCJzb3J0YWJsZSIsInNvcnRhYmxlT3B0aW9ucyIsInJldXNlTW9kZWxWaWV3cyIsImRldGFjaGVkUmVuZGVyaW5nIiwiZW1wdHlMaXN0Q2FwdGlvbiIsImluaXRpYWxpemUiLCJvcHRpb25zIiwiVmlld09wdGlvbnMiLCJhZGQiLCJzZXRPcHRpb25zIiwiQ29sbGVjdGlvbiIsIl9oYXNCZWVuUmVuZGVyZWQiLCJfaXNCYWNrYm9uZUNvdXJpZXJBdmFpbGFibGUiLCJDb3VyaWVyIiwiJGVsIiwiZGF0YSIsImFkZENsYXNzIiwiYXR0ciIsInNlbGVjdGVkSXRlbXMiLCJfdXBkYXRlSXRlbVRlbXBsYXRlIiwiX3JlZ2lzdGVyQ29sbGVjdGlvbkV2ZW50cyIsInZpZXdNYW5hZ2VyIiwiQ2hpbGRWaWV3Q29udGFpbmVyIiwiX29uT3B0aW9uc0NoYW5nZWQiLCJjaGFuZ2VkT3B0aW9ucyIsIm9yaWdpbmFsT3B0aW9ucyIsIl90aGlzIiwicmVyZW5kZXIiLCJjaGFuZ2VkT3B0aW9uS2V5IiwibmV3VmFsIiwib2xkVmFsIiwic3RvcExpc3RlbmluZyIsInNldFNlbGVjdGVkTW9kZWwiLCJieSIsInNldFNlbGVjdGVkTW9kZWxzIiwicmVtb3ZlQXR0ciIsIl9zZXR1cFNvcnRhYmxlIiwicmVhcHBseUZpbHRlciIsInZpZXciLCJyZW1vdmUiLCJjb250YWlucyIsInJlbmRlciIsInNldE9wdGlvbiIsIm9wdGlvbk5hbWUiLCJvcHRpb25WYWx1ZSIsIm9wdGlvbkhhc2giLCJnZXRTZWxlY3RlZE1vZGVsIiwiZ2V0U2VsZWN0ZWRNb2RlbHMiLCJyZWZlcmVuY2VCeSIsIml0ZW1zIiwiaXRlbSIsImdldCIsImN1ckxpbmVOdW1iZXIiLCJfZ2V0VmlzaWJsZUl0ZW1FbHMiLCJpcyIsImZpbmRCeU1vZGVsIiwibmV3U2VsZWN0ZWRJdGVtcyIsInNpbGVudCIsIm5ld1NlbGVjdGVkQ2lkcyIsInRoaXNNb2RlbCIsImNpZCIsInBsdWNrIiwibW9kZWwiLCJ0aGlzSXRlbUVsIiwib2xkU2VsZWN0ZWRNb2RlbHMiLCJvbGRTZWxlY3RlZENpZHMiLCJfY29udmVydFN0cmluZ3NUb0ludHMiLCJfdmFsaWRhdGVTZWxlY3Rpb24iLCJuZXdTZWxlY3RlZE1vZGVscyIsIl9jb250YWluU2FtZUVsZW1lbnRzIiwiX2FkZFNlbGVjdGVkQ2xhc3NUb1NlbGVjdGVkSXRlbXMiLCJzcGF3biIsInNlbGVjdGVkTW9kZWxzIiwidHJpZ2dlciIsInVwZGF0ZURlcGVuZGVudENvbnRyb2xzIiwibmV3U2VsZWN0ZWRJdGVtIiwiZ2V0VmlldyIsInJlZmVyZW5jZSIsIml0ZW1FbGVtZW50cyIsIm1vZGVsVmlld0NvbnRhaW5lckVsIiwiX3NhdmVTZWxlY3Rpb24iLCJfZ2V0Q29udGFpbmVyRWwiLCJmcmFnbWVudENvbnRhaW5lciIsIm9sZFZpZXdNYW5hZ2VyIiwidGhpc01vZGVsVmlldyIsImRldGFjaCIsImVtcHR5IiwiZG9jdW1lbnQiLCJjcmVhdGVEb2N1bWVudEZyYWdtZW50IiwiZmluZEJ5TW9kZWxDaWQiLCJfY3JlYXRlTmV3TW9kZWxWaWV3IiwiX2dldE1vZGVsVmlld09wdGlvbnMiLCJfaW5zZXJ0QW5kUmVuZGVyTW9kZWxWaWV3IiwiYXBwZW5kIiwiX3Nob3dFbXB0eUxpc3RDYXB0aW9uSWZBcHByb3ByaWF0ZSIsIl9yZXN0b3JlU2VsZWN0aW9uIiwiZm9yY2VSZXJlbmRlck9uTmV4dFNvcnRFdmVudCIsIl9yZW1vdmVFbXB0eUxpc3RDYXB0aW9uIiwiZW1wdHlMaXN0U3RyaW5nIiwiJGVtcHR5TGlzdENhcHRpb25FbCIsIiR2YXJFbCIsIl9pc1JlbmRlcmVkQXNMaXN0Iiwid3JhcEFsbCIsInBhcmVudCIsImNzcyIsImZpbmQiLCJwYXJlbnRFbE9yRG9jdW1lbnRGcmFnbWVudCIsImF0SW5kZXgiLCJ0aGlzTW9kZWxWaWV3V3JhcHBlZCIsIl93cmFwTW9kZWxWaWV3Iiwibm9kZVR5cGUiLCJhcHBlbmRDaGlsZCIsIm51bWJlck9mTW9kZWxWaWV3c0N1cnJlbnRseUluRE9NIiwiY2hpbGRyZW4iLCJlcSIsImJlZm9yZSIsImhpZGUiLCJoaWRlVGhpc01vZGVsVmlldyIsInRvZ2dsZSIsInRvZ2dsZUNsYXNzIiwid2hpY2hGaWx0ZXIiLCJub3RWaXNpYmxlIiwiX21vZGVsVmlld0hhc1dyYXBwZXJMSSIsImNsb3Nlc3QiLCJub3RTb3J0YWJsZSIsIm5vdFNlbGVjdGFibGUiLCJfcmVtb3ZlTW9kZWxWaWV3IiwiX3ZhbGlkYXRlU2VsZWN0aW9uQW5kUmVuZGVyIiwibGlzdGVuVG8iLCJfaXNSZW5kZXJlZEFzVGFibGUiLCJ0Ym9keSIsIl9nZXRDbGlja2VkSXRlbUlkIiwidGhlRXZlbnQiLCJjbGlja2VkSXRlbUlkIiwiY2xpY2tlZEl0ZW1FbCIsImN1cnJlbnRUYXJnZXQiLCJjbGlja2VkSXRlbSIsImlzTnVtZXJpYyIsInBhcnNlSW50IiwiaXRlbVRlbXBsYXRlSHRtbCIsImh0bWwiLCJ0ZW1wbGF0ZSIsIm1vZGVsUmVmZXJlbmNlSWRzIiwibW9kZWxzIiwiaW50ZXJzZWN0aW9uIiwiZmlsdGVyIiwidGhpc0l0ZW1JZCIsInNhdmVkU2VsZWN0aW9uIiwib2Zmc2V0Iiwib2xkSXRlbXNJZHNXaXRoU2VsZWN0ZWRDbGFzcyIsIml0ZW1zSWRzRnJvbVdoaWNoU2VsZWN0ZWRDbGFzc05lZWRzVG9CZVJlbW92ZWQiLCJ3aXRob3V0IiwicmVtb3ZlQ2xhc3MiLCJpdGVtc0lkc0Zyb21XaGljaFNlbGVjdGVkQ2xhc3NOZWVkc1RvQmVBZGRlZCIsIl9yZW9yZGVyQ29sbGVjdGlvbkJhc2VkT25IVE1MIiwidGhpc01vZGVsQ2lkIiwic29ydCIsImNvbXBhcmF0b3IiLCJfZ2V0TW9kZWxWaWV3Q29uc3RydWN0b3IiLCJtb2RlbFZpZXdDb25zdHJ1Y3RvciIsIm5ld01vZGVsVmlldyIsImNvbGxlY3Rpb25MaXN0VmlldyIsImNvbGxlY3Rpb25WaWV3IiwibW9kZWxWaWV3V3JhcHBlckVsIiwidGhlQXJyYXkiLCJ0aGlzRWwiLCJ0aGlzRWxBc051bWJlciIsImFycmF5QSIsImFycmF5QiIsInRvTG93ZXJDYXNlIiwiX2NoYXJDb2RlcyIsInVwQXJyb3ciLCJkb3duQXJyb3ciLCJheGlzIiwiZGlzdGFuY2UiLCJmb3JjZVBsYWNlaG9sZGVyU2l6ZSIsInN0YXJ0IiwiYmluZCIsIl9zb3J0U3RhcnQiLCJjaGFuZ2UiLCJfc29ydENoYW5nZSIsInN0b3AiLCJfc29ydFN0b3AiLCJyZWNlaXZlIiwiX3JlY2VpdmUiLCJvdmVyIiwiX292ZXIiLCJyZXN1bHQiLCJldmVudCIsInVpIiwibW9kZWxCZWluZ1NvcnRlZCIsIm5ld0luZGV4Iiwic2VuZGVyQ29sbGVjdGlvbkxpc3RWaWV3Iiwic2VuZGVyIiwibW9kZWxSZWNlaXZlZCIsImF0IiwiX29uS2V5ZG93biIsInRyYXAiLCJjdXJyZW50T2Zmc2V0Iiwid2hpY2giLCJfbGlzdEl0ZW1fb25Nb3VzZWRvd24iLCJjbGlja2VkTW9kZWwiLCJtZXRhS2V5UHJlc3NlZCIsImN0cmxLZXkiLCJtZXRhS2V5IiwidGhpc01ldGhvZCIsInNoaWZ0S2V5IiwiZmlyc3RTZWxlY3RlZEl0ZW1JbmRleCIsInRoaXNJdGVtTW9kZWwiLCJjbGlja2VkSXRlbUluZGV4Iiwic2hpZnRLZXlSb290U2VsZWN0ZWRJdGVtSW5kZXgiLCJtaW5TZWxlY3RlZEl0ZW1JbmRleCIsIk1hdGgiLCJtaW4iLCJtYXhTZWxlY3RlZEl0ZW1JbmRleCIsIm1heCIsInRoaXNJbmRleCIsInNlbGVjdGlvbiIsIndpbmRvdyIsImdldFNlbGVjdGlvbiIsInNlbCIsInJlbW92ZUFsbFJhbmdlcyIsInVuaW9uIiwiX2xpc3RJdGVtX29uRG91YmxlQ2xpY2siLCJfbGlzdEJhY2tncm91bmRfb25DbGljayIsInRhcmdldCIsInNldERlZmF1bHRNb2RlbFZpZXdDb25zdHJ1Y3RvciIsInRoZUNvbnN0cnVjdG9yIiwib3B0aW9uc0RlY2xhcmF0aW9uc1Byb3BlcnR5Iiwib3B0aW9uc1RoYXRXZXJlQ2hhbmdlZCIsIm9wdGlvbnNUaGF0V2VyZUNoYW5nZWRQcmV2aW91c1ZhbHVlcyIsInRoaXNPcHRpb25Qcm9wZXJ0aWVzIiwib2xkVmFsdWUiLCJuZXdWYWx1ZSIsIm9uT3B0aW9uc0NoYW5nZWQiLCJnZXRPcHRpb25zIiwib3B0aW9uc05hbWVzIiwicGljayIsIkNvbnRhaW5lciIsInZpZXdzIiwiX3ZpZXdzIiwiX2luZGV4QnlNb2RlbCIsIl9pbmRleEJ5Q3VzdG9tIiwiX3VwZGF0ZUxlbmd0aCIsImN1c3RvbUluZGV4Iiwidmlld0NpZCIsIm1vZGVsQ2lkIiwiZmluZEJ5Q2lkIiwiZmluZEJ5Q3VzdG9tIiwiZmluZEJ5SW5kZXgiLCJ2YWx1ZXMiLCJmaW5kSW5kZXhCeUNpZCIsImFueSIsImtleSIsIm1ldGhvZCIsInRhaWwiLCJzaXplIiwidG9BcnJheSIsIlplcHRvIiwiZm5OYW1lIiwicHJvbXB0IiwicmVzdCIsImZuIiwiX3Vuc2F2ZWRDb25maWciLCJpc0Jvb2xlYW4iLCJIaXN0b3J5IiwibmF2aWdhdGUiLCJ3cmFwIiwib2xkTmF2IiwiZnJhZ21lbnQiLCJjb25maXJtIiwib25iZWZvcmV1bmxvYWQiLCJNb2RlbCIsInVuc2F2ZWQiLCJfdHJhY2tpbmdDaGFuZ2VzIiwiX29yaWdpbmFsQXR0cnMiLCJfdW5zYXZlZENoYW5nZXMiLCJzdGFydFRyYWNraW5nIiwidW5sb2FkUm91dGVyUHJvbXB0IiwidW5sb2FkV2luZG93UHJvbXB0IiwiX3Jlc2V0VHJhY2tpbmciLCJfdHJpZ2dlclVuc2F2ZWRDaGFuZ2VzIiwic3RvcFRyYWNraW5nIiwicmVzdGFydFRyYWNraW5nIiwicmVzZXRBdHRyaWJ1dGVzIiwiYXR0cmlidXRlcyIsInVuc2F2ZWRBdHRyaWJ1dGVzIiwiYXR0cnMiLCJpc0VtcHR5IiwidmFsIiwiY2hhbmdlZCIsIm9sZCIsImlzRXF1YWwiLCJtIiwiZmluZFdoZXJlIiwic2V0Iiwib2xkU2V0Iiwic3luYyIsIm9sZFN5bmMiLCJzdWNjZXNzIiwib2xkU3VjY2VzcyIsInRleHRTdGF0dXMiLCJqcVhIUiIsImRlZmF1bHRzIiwiZW5hYmxlZCIsInNyYyIsInJlbGF0aW9uc2hpcF9kZWZhdWx0cyIsInJlbGF0aW9uc2hpcHMiLCJpbml0X3JlbGF0aW9uc2hpcHMiLCJyZWxzIiwiZ2V0X3JlbGF0aW9uc2hpcHMiLCJzZXRfcGFyZW50IiwiY2hpbGRfZGF0YSIsImNoaWxkX2tleSIsImNvbmRpdGlvbmFsIiwiY2hpbGQiLCJjaGlsZF92YWwiLCJsb29rdXAiLCJ0eXBlIiwibGxtc19idWlsZGVyIiwiY29uc3RydWN0IiwiZ2V0X21vZGVsIiwiY2xhc3MiLCJnZXRfY29sbGVjdGlvbiIsIl9tYXliZV9zZXRfcGFyZW50X3JlZmVyZW5jZSIsImNoaWxkX21vZGVsIiwiZ2V0X2NoaWxkX3Byb3BzIiwicHJvcHMiLCJnZXRfcGFyZW50IiwiSW1hZ2UiLCJSZWxhdGlvbnNoaXBzIiwiY2hvaWNlIiwidW5pcXVlSWQiLCJjaG9pY2VfdHlwZSIsImNvcnJlY3QiLCJtYXJrZXIiLCJxdWVzdGlvbl9pZCIsImdldF90cmFzaF9pZCIsImlzX3NlbGVjdGFibGUiLCJnZXRfY2hvaWNlX3NlbGVjdGFibGUiLCJvbiIsInVwZGF0ZV9vcmRlciIsInVwZGF0ZV9jb3JyZWN0IiwiY291bnRfY29ycmVjdCIsImdldF9jb3JyZWN0Iiwic2libGluZ3MiLCJxdWVzdGlvbiIsInNlbGYiLCJnZXRfY2hvaWNlX21hcmtlcnMiLCJjaG9pY2VzIiwiY2xhcmlmaWNhdGlvbnMiLCJkZWZhdWx0X2Nob2ljZXMiLCJkZXNjcmlwdGlvbiIsImljb24iLCJpbWFnZSIsImtleXdvcmRzIiwicGxhY2Vob2xkZXIiLCJwb2ludHMiLCJ2aWRlbyIsImdldF9rZXl3b3JkcyIsIl9nZXRfY2hvaWNlX29wdGlvbiIsImdldF9jaG9pY2VfdHlwZSIsImdldF9taW5fY2hvaWNlcyIsImdldF9tYXhfY2hvaWNlcyIsImdldF9tdWx0aV9jaG9pY2VzIiwib3B0aW9uIiwiUXVlc3Rpb25zIiwiUXVlc3Rpb25DaG9pY2VzIiwiUXVlc3Rpb25UeXBlIiwicXVlc3Rpb25zIiwicXVlc3Rpb25fdHlwZSIsImNvbnRlbnQiLCJkZXNjcmlwdGlvbl9lbmFibGVkIiwibXVsdGlfY2hvaWNlcyIsIm1lbnVfb3JkZXIiLCJwYXJlbnRfaWQiLCJ0aXRsZSIsInZpZGVvX2VuYWJsZWQiLCJ2aWRlb19zcmMiLCJfZXhwYW5kZWQiLCJfZW5zdXJlX21pbl9jaG9pY2VzIiwiZGVsYXkiLCJ1cGRhdGVfcG9pbnRzIiwiYWRkX2Nob2ljZSIsInB1YlN1YiIsImJlZm9yZV9zYXZlIiwiYXR0cyIsInN5bmNfdHlwZSIsImdldF90eXBlX2luZGV4IiwiY3Vycl90eXBlIiwiZ2V0X3R5cGVfaXRlcmF0b3IiLCJnZXRfcWlkIiwiZ2V0X3BhcmVudF9xdWVzdGlvbiIsImlzX2luX2dyb3VwIiwiZ2V0X3BhcmVudF9xdWl6IiwiZ2V0X3BvaW50cyIsImdldF9wb2ludHNfcGVyY2VudGFnZSIsInRvdGFsIiwidG9GaXhlZCIsInVwZGF0ZV9wYXJlbnQiLCJmaWVsZHMiLCJnZXRfZWRpdF9wb3N0X2xpbmsiLCJoYXNfdGVtcF9pZCIsImFkbWluX3VybCIsImdldF9zZXR0aW5nc19maWVsZHMiLCJzY2hlbWEiLCJzY2hlbWFzIiwiaXNOdW1iZXIiLCJpbml0X2N1c3RvbV9zY2hlbWEiLCJncm91cHMiLCJncm91cCIsImZsYXR0ZW4iLCJmaWVsZCIsImF0dHJpYnV0ZSIsImN1c3RvbXMiLCJzd2l0Y2hfYXR0cmlidXRlIiwiYXR0cmlidXRlX3ByZWZpeCIsImRlZmF1bHQiLCJMTE1TIiwibDEwbiIsInRyYW5zbGF0ZSIsInRvZ2dsZWFibGUiLCJsYWJlbCIsInRpcCIsIkxlc3NvbiIsIlF1ZXN0aW9uIiwiVXRpbGl0aWVzIiwiUXVpelNjaGVtYSIsImxlc3Nvbl9pZCIsInN0YXR1cyIsImFsbG93ZWRfYXR0ZW1wdHMiLCJsaW1pdF9hdHRlbXB0cyIsImxpbWl0X3RpbWUiLCJwYXNzaW5nX3BlcmNlbnQiLCJyYW5kb21fYW5zd2VycyIsInRpbWVfbGltaXQiLCJzaG93X2NvcnJlY3RfYW5zd2VyIiwiX3BvaW50cyIsInBlcm1hbGluayIsIl9zaG93X3NldHRpbmdzIiwiX3F1ZXN0aW9uc19sb2FkZWQiLCJnZXRfdG90YWxfcG9pbnRzIiwiYWRkX3F1ZXN0aW9uIiwiZ2V0X2wxMG5fdHlwZSIsInBsdXJhbCIsImxvYWRfcXVlc3Rpb25zIiwiY2IiLCJBamF4IiwiYWN0aW9uIiwiYWN0aW9uX3R5cGUiLCJjb3Vyc2VfaWQiLCJDb3Vyc2VNb2RlbCIsImxvYWRfaWQiLCJlcnJvciIsInhociIsImNvbnNvbGUiLCJsb2ciLCJkZWJ1ZyIsInJlcyIsImNvbmRpdGlvbiIsImFzc2lnbm1lbnRzIiwiaXNfZmlyc3RfaW5fY291cnNlIiwiZ2V0X2F2YWlsYWJsZV9wcmVyZXFfb3B0aW9ucyIsImdldF9jb3Vyc2UiLCJkYXRlX2Zvcm1hdCIsInRpbWVwaWNrZXIiLCJkYXRlcGlja2VyIiwiUXVpeiIsIkxlc3NvblNjaGVtYSIsInBhcmVudHMiLCJxdWl6Iiwib3JkZXIiLCJwYXJlbnRfY291cnNlIiwiY291cnNlIiwicGFyZW50X3NlY3Rpb24iLCJlZGl0X3VybCIsInZpZXdfdXJsIiwiYXVkaW9fZW1iZWQiLCJoYXNfcHJlcmVxdWlzaXRlIiwicmVxdWlyZV9wYXNzaW5nX2dyYWRlIiwicmVxdWlyZV9hc3NpZ25tZW50X3Bhc3NpbmdfZ3JhZGUiLCJ2aWRlb19lbWJlZCIsImZyZWVfbGVzc29uIiwiYXNzaWdubWVudCIsImFzc2lnbm1lbnRfZW5hYmxlZCIsInF1aXpfZW5hYmxlZCIsIl9mb3JjZVN5bmMiLCJtYXliZV9pbml0X2Fzc2lnbm1lbnRzIiwicGFyZW50X3NlY3Rpb25faW5kZXgiLCJsZXNzb25faW5kZXhfaW5fc2VjdGlvbiIsInNlY3Rpb24iLCJjdXJyX3NlY19pbmRleCIsIiUxJGQiLCIlMiRzIiwibGVzc29uIiwiY3Vycl9sZXNfaW5kZXgiLCJhZGRfcXVpeiIsIiUxJHMiLCJvbl9yZW9yZGVyIiwidmFsaWRhdGVfcHJlcmVxcyIsInByZXJlcXVpc2l0ZSIsIkxlc3NvbnMiLCJsZXNzb25zIiwiX3NlbGVjdGVkIiwiYWRkX2xlc3NvbiIsImdldF9uZXh0IiwiY2lyY3VsYXIiLCJfZ2V0X3NpYmxpbmciLCJnZXRfcHJldiIsImRpcmVjdGlvbiIsInNpYmxpbmdfaW5kZXgiLCJsYXN0IiwiUXVlc3Rpb25UeXBlcyIsIlNlY3Rpb25zIiwic2VjdGlvbnMiLCJhZGRfc2VjdGlvbiIsImFkZF9leGlzdGluZ19sZXNzb24iLCJnZXRfc2VsZWN0ZWRfc2VjdGlvbiIsInNlbGVjdGVkIiwiQWJzdHJhY3QiLCJDb3Vyc2UiLCJRdWVzdGlvbkNob2ljZSIsIlNlY3Rpb24iLCJjbGljayBhW2hyZWY9XCIjbGxtcy1kZXRhY2gtbW9kZWxcIl0iLCJkZXRhY2hfbW9kZWwiLCJwcmV2ZW50RGVmYXVsdCIsInN0b3BQcm9wYWdhdGlvbiIsIm1zZyIsIiVzIiwibWVkaWFfbGliIiwiY2xpY2sgLmxsbXMtYWRkLWltYWdlIiwiY2xpY2sgYVtocmVmPVwiI2xsbXMtZWRpdC1zbHVnXCJdIiwiY2xpY2sgYVtocmVmPVwiI2xsbXMtcmVtb3ZlLWltYWdlXCJdIiwiY2hhbmdlIC5sbG1zLWVkaXRhYmxlLXNlbGVjdCBzZWxlY3QiLCJjaGFuZ2UgLmxsbXMtc3dpdGNoIGlucHV0W3R5cGU9XCJjaGVja2JveFwiXSIsImNoYW5nZSAubGxtcy1lZGl0YWJsZS1yYWRpbyBpbnB1dCIsImZvY3VzaW4gLmxsbXMtaW5wdXQiLCJmb2N1c291dCAubGxtcy1pbnB1dCIsImtleWRvd24gLmxsbXMtaW5wdXQiLCJpbnB1dCAubGxtcy1pbnB1dFt0eXBlPVwibnVtYmVyXCJdIiwicGFzdGUgLmxsbXMtaW5wdXRbZGF0YS1mb3JtYXR0aW5nXSIsImdldF9hbGxvd2VkX3RhZ3MiLCJ0YWciLCJ0cmltIiwiZ2V0X2NvbnRlbnQiLCJoYXNDbGFzcyIsInN0cmlwRm9ybWF0dGluZyIsInRleHQiLCJoYXNfY2hhbmdlZCIsImlzX3ZhbGlkIiwiX3ZhbGlkYXRlX3VybCIsInNsdWciLCJiZWZvcmVTZW5kIiwiU3Bpbm5lciIsInIiLCJpbml0X2RhdGVwaWNrZXJzIiwiZGF0ZXRpbWVwaWNrZXIiLCJmb3JtYXQiLCJvbkNsb3NlIiwiY3VycmVudF90aW1lIiwiJGlucHV0IiwiYmx1ciIsImluaXRfZm9ybWF0dGluZ19lbHMiLCJmb3JtYXR0aW5nIiwiZWQiLCJRdWlsbCIsIm1vZHVsZXMiLCJ0b29sYmFyIiwia2V5Ym9hcmQiLCJiaW5kaW5ncyIsInRhYiIsImhhbmRsZXIiLCJyYW5nZSIsImNvbnRleHQiLCIxMyIsInRoZW1lIiwiZGVsdGEiLCJvbGREZWx0YSIsInNvdXJjZSIsImluaXRfc2VsZWN0cyIsImxsbXNTZWxlY3QyIiwid2lkdGgiLCJvbl9ibHVyIiwic2F2ZV9lZGl0cyIsInJldmVydF9lZGl0cyIsIm9uX2ZvY3VzIiwib25fcGFzdGUiLCJvcmlnaW5hbEV2ZW50IiwiY2xpcGJvYXJkRGF0YSIsImdldERhdGEiLCJleGVjQ29tbWFuZCIsIm9uX3NlbGVjdCIsIm11bHRpIiwiJHNlbGVjdGVkIiwib25fcmFkaW9fc2VsZWN0Iiwib25fa2V5ZG93biIsImtleUNvZGUiLCJzaGlmdCIsIm9wZW5fbWVkaWFfbGliIiwidXBsb2FkZXIiLCJwYXJhbSIsIndwIiwibWVkaWEiLCJmcmFtZXMiLCJmaWxlX2ZyYW1lIiwiYnV0dG9uIiwibXVsdGlwbGUiLCJ1cmwiLCJhdHRhY2htZW50Iiwic3RhdGUiLCJ0b0pTT04iLCJzaXplcyIsIm9wZW4iLCJyZW1vdmVfaW1hZ2UiLCJ0b2dnbGVfc3dpdGNoIiwiaW5pdF9lZGl0b3IiLCJzZXR0aW5ncyIsImVkaXRvciIsImdldERlZmF1bHRTZXR0aW5ncyIsIm1lZGlhQnV0dG9ucyIsInRpbnltY2UiLCJ0b29sYmFyMSIsInRvb2xiYXIyIiwic2V0dXAiLCJvbl9lZGl0b3JfcmVhZHkiLCJtYWtlX3NsdWdfZWRpdGFibGUiLCIkYnRuIiwiJGxpbmsiLCJwcmV2QWxsIiwicHJldiIsImZ1bGxfdXJsIiwic2hvcnRfdXJsIiwiY29sb3IiLCJwb2ludGVyLWV2ZW50cyIsInRleHQtZGVjb3JhdGlvbiIsInNob3ciLCIkZWQiLCIkcGFyZW50IiwiJGxhYmVsIiwicHJlcGVuZFRvIiwiZ2V0Q29udGVudCIsInN0ciIsImEiLCJjcmVhdGVFbGVtZW50IiwiaHJlZiIsImhvc3QiLCJsb2NhdGlvbiIsImhlbHBlciIsIm1heWJlX2hpZGVfc2hpZnRhYmxlX2J1dHRvbnMiLCJvbGRfaW5kZXgiLCJuZXdfaW5kZXgiLCJzaGlmdF9kb3duIiwic2hpZnRfdXAiLCJzdWJzY3JpcHRpb25zIiwiZ2V0X3N1YnZpZXciLCJldmVudHNfc3Vic2NyaWJlIiwiZnVuYyIsImV2ZW50c191bnN1YnNjcmliZSIsIm9mZiIsInJlbW92ZV9zdWJ2aWV3IiwiaW5zdGFuY2UiLCJyZW1vdmVfc3Vidmlld3MiLCJ1bmRlbGVnYXRlRXZlbnRzIiwicmVuZGVyX3N1YnZpZXdzIiwidmlld19kYXRhIiwicmVuZGVyX3N1YnZpZXciLCJzZXRfc3RhdGUiLCJjbGljayBhW2hyZWY9XCIjbGxtcy10cmFzaC1tb2RlbFwiXSIsInRyYXNoX21vZGVsIiwiRGV0YWNoYWJsZSIsIkVkaXRhYmxlIiwiUmVjZWl2YWJsZSIsIlNoaWZ0YWJsZSIsIlN1YnZpZXciLCJUcmFzaGFibGUiLCJDb2xsZWN0aW9ucyIsIk1vZGVscyIsIlZpZXdzIiwiZXh0ZW5kX3ZpZXciLCJjbGFzc25hbWUiLCJyZWdpc3Rlcl9jb2xsZWN0aW9uIiwicmVnaXN0ZXJfbW9kZWwiLCJkaXNhYmxlIiwiZW5hYmxlIiwiY3VzdG9tX3NjaGVtYXMiLCJjdXN0b20iLCJtb2RlbF90eXBlIiwic2F2aW5nIiwiYXV0b3NhdmUiLCJjaGVja19pbnRlcnZhbCIsImNoZWNrX2ludGVydmFsX21zIiwiZGV0YWNoZWQiLCJ0cmFzaGVkIiwiYWRkX2Vycm9yX21zZyIsImVyciIsIm1lc3NhZ2UiLCJjaGVja19mb3JfY2hhbmdlcyIsImNoYW5nZXMiLCJnZXRfdW5zYXZlZF9jaGFuZ2VzIiwiaGFzX3Vuc2F2ZWRfY2hhbmdlcyIsImdldF9jaGFuZ2VzX3RvX29iamVjdCIsIm9iamVjdCIsImNoYW5nZWRfYXR0cyIsImV4Y2x1ZGUiLCJvbWl0IiwiZ2V0X2NoYW5nZWRfYXR0cmlidXRlcyIsIm1vZGVsX2NoYW5nZXMiLCJtYXliZV9yZXN0YXJ0X3RyYWNraW5nIiwidW5zZXQiLCJwcm9jZXNzX3JlbW92YWxzIiwicmVtb3ZhbHMiLCJ0cmFzaCIsImNvbGwiLCJlcnJvcnMiLCJpbmZvIiwicHJvY2Vzc191cGRhdGVzIiwidXBkYXRlcyIsInByb2Nlc3Nfb2JqZWN0X3VwZGF0ZXMiLCJtYWluX2RhdGEiLCJvcmlnX2lkIiwic2F2ZV9ub3ciLCJoZWFydGJlYXQiLCJjb25uZWN0Tm93IiwiSlNPTiIsInN0cmluZ2lmeSIsInJlc3BvbnNlVGV4dCIsImRvX2FqYXhfc2F2ZSIsInNldF9jaGVja19pbnRlcnZhbCIsIm1zIiwiY2xlYXJJbnRlcnZhbCIsInNldEludGVydmFsIiwic3RhdHVzVGV4dCIsImRhdGEtaWQiLCJkYXRhLXNlY3Rpb24taWQiLCJjbGFzc05hbWUiLCJjbGljayAuZWRpdC1sZXNzb24iLCJjbGljayAuZWRpdC1xdWl6IiwiY2xpY2sgLmVkaXQtYXNzaWdubWVudCIsImNsaWNrIC5zZWN0aW9uLXByZXYiLCJjbGljayAuc2VjdGlvbi1uZXh0IiwiY2xpY2sgLnNoaWZ0LXVwLS1sZXNzb24iLCJjbGljayAuc2hpZnQtZG93bi0tbGVzc29uIiwib3Blbl9hc3NpZ25tZW50X2VkaXRvciIsIm9wZW5fbGVzc29uX2VkaXRvciIsIm9wZW5fcXVpel9lZGl0b3IiLCJzZWN0aW9uX25leHQiLCJfbW92ZV90b19zZWN0aW9uIiwic2VjdGlvbl9wcmV2IiwidG9fc2VjdGlvbiIsImZyb21fY29sbCIsIkxlc3NvblZpZXciLCJjb25uZWN0V2l0aCIsImN1cnNvciIsImhhbmRsZSIsInNvcnRhYmxlX3N0YXJ0Iiwic29ydGFibGVfc3RvcCIsIkxlc3Nvbkxpc3RWaWV3IiwiY2xpY2sgLmV4cGFuZCIsImNsaWNrIC5jb2xsYXBzZSIsImNsaWNrIC5zaGlmdC11cC0tc2VjdGlvbiIsImNsaWNrIC5zaGlmdC1kb3duLS1zZWN0aW9uIiwibW91c2VlbnRlciAubGxtcy1sZXNzb25zIiwidG9nZ2xlX2V4cGFuZGVkIiwibGVzc29uTGlzdFZpZXciLCJvbl9sZXNzb25fYWRkIiwiZHJhZ1RpbWVvdXQiLCJleHBhbmQiLCJjb2xsYXBzZSIsImVsIiwiYWN0aXZlX2xlc3Nvbl9jaGFuZ2UiLCJtYXliZV9oaWRlX3RyYXNoX2J1dHRvbiIsImN1cnJlbnQiLCJwcmV2aW91cyIsInVwZGF0ZSIsIm9uX21vdXNlZW50ZXIiLCJTZWN0aW9uVmlldyIsIm1vdXNlZG93biA+IGxpLmxsbXMtc2VjdGlvbiA+IC5sbG1zLWJ1aWxkZXItaGVhZGVyIC5sbG1zLWhlYWRsaW5lIiwiY2xpY2sgdWwuY29sbGVjdGlvbi12aWV3IiwiU2VjdGlvbkxpc3RWaWV3Iiwic2VjdGlvbkxpc3RWaWV3IiwiYWN0aXZlX3NlY3Rpb25fY2hhbmdlIiwib25fc2VjdGlvbl9hZGQiLCJvbl9zZWN0aW9uX3RvZ2dsZSIsImV4cGFuZF9zZWN0aW9uIiwiY2xpY2sgLmxsbXMtc2V0dGluZ3MtZ3JvdXAtdG9nZ2xlIiwiZ2V0X2VkaXRvcl9maWVsZHMiLCJpc19lZGl0b3JfZmllbGQiLCJnZXRfZ3JvdXBzIiwiaXNfZ3JvdXBfaGlkZGVuIiwiZ3JvdXBfaWQiLCJsb2NhbFN0b3JhZ2UiLCJnZXRJdGVtIiwiZ2V0X3N3aXRjaF9hdHRyaWJ1dGUiLCJoYXNfc3dpdGNoIiwiaXNfZGVmYXVsdF9maWVsZCIsImlzX3N3aXRjaF9jb25kaXRpb25fbWV0Iiwic3dpdGNoX29uIiwicmVuZGVyX2VkaXRvciIsInJlbmRlcl9zZWxlY3Rfb3B0aW9ucyIsIm9wdGlvbl9odG1sIiwic2V0dXBfZmllbGQiLCJvcmlnX2ZpZWxkIiwiZmllbGRfaW5kZXgiLCJjbGFzc2VzIiwiaW5wdXRfdHlwZSIsInRpcF9wb3NpdGlvbiIsIm9yaWdfc2V0dGluZ3MiLCJzd2l0Y2hfb2ZmIiwiZGVlcENsb25lIiwiaGFzX2ltYWdlcyIsInNob3VsZF9yZXJlbmRlcl9vbl90b2dnbGUiLCJmaWVsZF90eXBlIiwidG9nZ2xlX2dyb3VwIiwiJGdyb3VwIiwic2V0SXRlbSIsInJlbW92ZUl0ZW0iLCJTZXR0aW5nc0ZpZWxkcyIsInBsYWNlbWVudCIsInN0eWxlIiwiYW5pbWF0aW9uIiwiY2xvc2VhYmxlIiwiYmFja2Ryb3AiLCJvblNob3ciLCJvbkhpZGUiLCJjb250YWluZXIiLCJ3ZWJ1aVBvcG92ZXIiLCJzZWxlY3QyOnNlbGVjdCIsInBvc3RfdHlwZSIsInNlYXJjaGluZ19tZXNzYWdlIiwiYWRkX3Bvc3QiLCJwYXJhbXMiLCJhamF4IiwiZGF0YVR5cGUiLCJhamF4dXJsIiwidGVybSIsInBhZ2UiLCJfYWpheF9ub25jZSIsIndwX2FqYXhfZGF0YSIsIm5vbmNlIiwiZHJvcGRvd25QYXJlbnQiLCJlc2NhcGVNYXJrdXAiLCJtYXJrdXAiLCJ0ZW1wbGF0ZVJlc3VsdCIsInJlbmRlcl9yZXN1bHQiLCIkaHRtbCIsImxvYWRpbmciLCIkc2lkZSIsIiRtYWluIiwiY2xpY2sgLmxsbXMtYWRkLXF1ZXN0aW9uIiwiUXVlc3Rpb25WaWV3IiwiY2hhbmdlIGlucHV0W25hbWU9XCJjb3JyZWN0XCJdIiwiY2xpY2sgLmxsbXMtYWN0aW9uLWljb25baHJlZj1cIiNsbG1zLWFkZC1jaG9pY2VcIl0iLCJjbGljayAubGxtcy1hY3Rpb24taWNvbltocmVmPVwiI2xsbXMtZGVsLWNob2ljZVwiXSIsIm1heWJlX2Rpc2FibGVfYnV0dG9ucyIsImRlbF9jaG9pY2UiLCJ0b2dnbGVfY29ycmVjdCIsIkNob2ljZVZpZXciLCJDaG9pY2VMaXN0VmlldyIsImNsaWNrIC5jbG9uZS0tcXVlc3Rpb24iLCJjbGljayAuZGVsZXRlLS1xdWVzdGlvbiIsImNsaWNrIC5leHBhbmQtLXF1ZXN0aW9uIiwiY2xpY2sgLmNvbGxhcHNlLS1xdWVzdGlvbiIsImNoYW5nZSBpbnB1dFtuYW1lPVwicXVlc3Rpb25fcG9pbnRzXCJdIiwicmVuZGVyX3BvaW50c19wZXJjZW50YWdlIiwibXVsdGlfY2hvaWNlc190b2dnbGUiLCJjaG9pY2VMaXN0VmlldyIsInF1ZXN0aW9uTGlzdFZpZXciLCJnZXRfcXVlc3Rpb25fbGlzdCIsIl9nZXRfcXVlc3Rpb25fY2xvbmUiLCJjaG9pY2VfY2xvbmUiLCJkZWxldGUiLCJzZWxlY3RvciIsIlF1aXpNb2RlbCIsIlBvcG92ZXIiLCJQb3N0U2VhcmNoIiwiUXVlc3Rpb25CYW5rIiwiUXVlc3Rpb25MaXN0IiwiYmFuayIsImxpc3QiLCJjbGljayAjbGxtcy1leGlzdGluZy1xdWl6IiwiY2xpY2sgI2xsbXMtbmV3LXF1aXoiLCJjbGljayAjbGxtcy1zaG93LXF1ZXN0aW9uLWJhbmsiLCJjbGljayAuYnVsay10b2dnbGUiLCJyZW5kZXJfcG9pbnRzIiwib25fdHJhc2hlZCIsImxhc3RfZ3JvdXAiLCJhbGVydCIsIiRxdWVzdGlvbnMiLCJhbmltYXRlIiwic2Nyb2xsVG9wIiwiYnVsa190b2dnbGUiLCJleHBhbmRlZCIsImFkZF9uZXdfcXVpeiIsImFkZF9leGlzdGluZ19xdWl6IiwicG9zdF9zZWFyY2hfcG9wb3ZlciIsImFkZF9leGlzdGluZ19xdWl6X2NsaWNrIiwiZGlzbWlzc2libGUiLCJvbmNlIiwic2hvd190b29scyIsInBvcCIsImFkZG9uX2V2ZW50cyIsImlzX2FkZG9uX2F2YWlsYWJsZSIsImdldF92aWV3X2V2ZW50cyIsImNsaWNrICNsbG1zLWV4aXN0aW5nLWFzc2lnbm1lbnQiLCJjbGljayAjbGxtcy1uZXctYXNzaWdubWVudCIsImFkZF9uZXdfYXNzaWdubWVudCIsImdldF9hc3NpZ25tZW50Iiwic2hvd19hZF9wb3BvdmVyIiwiYWRkX2V4aXN0aW5nX2Fzc2lnbm1lbnQiLCJhZGRfZXhpc3RpbmdfYXNzaWdubWVudF9jbGljayIsImgzIiwiYnRuIiwiYWRfcG9wb3ZlciIsIkxlc3NvbkVkaXRvciIsIkFzc2lnbm1lbnQiLCJjbGljayAubGxtcy1lZGl0b3ItbmF2IGFbaHJlZj1cIiNsbG1zLWVkaXRvci1jbG9zZVwiXSIsImNsaWNrIC5sbG1zLWVkaXRvci1uYXYgYTpub3QoW2hyZWY9XCIjbGxtcy1lZGl0b3ItY2xvc2VcIl0pIiwiU2lkZWJhclZpZXciLCJjbG9zZV9lZGl0b3IiLCJzd2l0Y2hfdGFiIiwiTGVzc29uU2VhcmNoIiwiY2xpY2sgI2xsbXMtbmV3LXNlY3Rpb24iLCJjbGljayAjbGxtcy1uZXctbGVzc29uIiwiY2xpY2sgI2xsbXMtZXhpc3RpbmctbGVzc29uIiwiQ291cnNlVmlldyIsImRyYWdnYWJsZSIsImFwcGVuZFRvIiwiY2FuY2VsIiwiY29ubmVjdFRvU29ydGFibGUiLCJhZGRfbmV3X3NlY3Rpb24iLCJhZGRfbmV3X2xlc3NvbiIsIiRlbHMiLCJjbGljayAjbGxtcy1jb2xsYXBzZS1hbGwiLCJjbGljayAjbGxtcy1leHBhbmQtYWxsIiwiY29sbGFwc2VfYWxsIiwiZXhwYW5kX2FsbCIsIkVkaXRvciIsIkVsZW1lbnRzIiwiZWxlbWVudHMiLCJ1dGlsaXRpZXMiLCJjbGljayAjbGxtcy1zYXZlLWJ1dHRvbiIsImNsaWNrICNsbG1zLWV4aXQtYnV0dG9uIiwiY2xpY2sgLmxsbXMtYnVpbGRlci1lcnJvciIsImNoYW5nZXNfbWFkZSIsImhlYXJ0YmVhdF9zZW5kIiwiaGVhcnRiZWF0X3RpY2siLCJvbl9sZXNzb25fc2VsZWN0Iiwib25fZWRpdG9yX2Nsb3NlIiwiJHNhdmVCdXR0b24iLCJhZGRfZXJyb3IiLCIkZXJyIiwicHJlcGVuZCIsImNsZWFyX2Vycm9ycyIsImV4aXRfbm93IiwiZGF0YS1zdGF0dXMiLCJkaXNhYmxlZCIsInR4dCIsImlzX2VkaXRvcl9hY3RpdmUiLCJsZXNzb25fbW9kZWwiLCJDViIsIlRyYWNrSXQiLCJDb25zdHJ1Y3QiLCJEZWJ1ZyIsIlNjaGVtYXMiLCJTeW5jIiwidmFsdWVfY29tcGFyZSIsImV4cGVjdGVkIiwiYWN0dWFsIiwibWl4aW4iLCJjaGVja2VkIiwiYWxsb3dlZF90YWdzIiwibm90IiwicmVwbGFjZVdpdGgiLCJpbm5lckhUTUwiLCJFdmVudHMiLCJTaWRlYmFyIiwic2lkZWJhciJdLCJtYXBwaW5ncyI6IkNBQUMsU0FBU0EsR0FTVixJQUFJQyxFQUFXQyxFQUFTQyxFQWtkWkMsRUFBTUMsRUFpM0NiQyxFQW1CQUMsR0FyMURKLFNBQVVDLEdBQ1YsSUFBSUMsRUFBTUMsRUFBS0MsRUFBU0MsRUFDdkJDLEVBQVUsR0FDVkMsRUFBVSxHQUNWQyxFQUFTLEdBQ1RDLEVBQVcsR0FDWEMsRUFBU0MsT0FBT0MsVUFBVUMsZUFDMUJDLEVBQU0sR0FBR0MsTUFDVEMsRUFBaUIsUUFFbEIsU0FBU0MsRUFBUUMsRUFBS0MsR0FDckIsT0FBT1QsRUFBT1UsS0FBS0YsRUFBS0MsR0FXekIsU0FBU0UsRUFBVUMsRUFBTUMsR0FDeEIsSUFBSUMsRUFBV0MsRUFBYUMsRUFBVUMsRUFBVUMsRUFDL0NDLEVBQVFDLEVBQWNDLEVBQU9DLEVBQUdDLEVBQUdDLEVBQ25DQyxFQUFZWixHQUFZQSxFQUFTYSxNQUFNLEtBQ3ZDQyxFQUFNN0IsRUFBTzZCLElBQ2JDLEVBQVdELEdBQU9BLEVBQUksTUFBUyxHQUdoQyxHQUFJZixFQUFNLENBd0JULElBdEJBTSxHQURBTixFQUFPQSxFQUFLYyxNQUFNLE1BQ0RHLE9BQVMsRUFNdEIvQixFQUFPZ0MsY0FBZ0J4QixFQUFleUIsS0FBS25CLEVBQUtNLE1BQ25ETixFQUFLTSxHQUFhTixFQUFLTSxHQUFXYyxRQUFRMUIsRUFBZ0IsS0FJakMsTUFBdEJNLEVBQUssR0FBR3FCLE9BQU8sSUFBY1IsSUFPaENiLEVBRHNCYSxFQUFVcEIsTUFBTSxFQUFHb0IsRUFBVUksT0FBUyxHQUNqQ0ssT0FBT3RCLElBSTlCVSxFQUFJLEVBQUdBLEVBQUlWLEVBQUtpQixPQUFRUCxJQUU1QixHQUFhLE9BRGJFLEVBQU9aLEVBQUtVLElBRVhWLEVBQUt1QixPQUFPYixFQUFHLEdBQ2ZBLEdBQUssT0FDQyxHQUFhLE9BQVRFLEVBQWUsQ0FNekIsR0FBVSxJQUFORixHQUFrQixJQUFOQSxHQUF1QixPQUFaVixFQUFLLElBQWdDLE9BQWhCQSxFQUFLVSxFQUFJLEdBQ3hELFNBQ2MsRUFBSkEsSUFDVlYsRUFBS3VCLE9BQU9iLEVBQUksRUFBRyxHQUNuQkEsR0FBSyxHQU1SVixFQUFPQSxFQUFLd0IsS0FBSyxLQUlsQixJQUFLWCxHQUFhRyxJQUFZRCxFQUFLLENBR2xDLElBQUtMLEdBRkxSLEVBQVlGLEVBQUtjLE1BQU0sTUFFSkcsT0FBWSxFQUFKUCxFQUFPQSxHQUFLLEVBQUcsQ0FHekMsR0FGQVAsRUFBY0QsRUFBVVQsTUFBTSxFQUFHaUIsR0FBR2MsS0FBSyxLQUVyQ1gsRUFHSCxJQUFLRixFQUFJRSxFQUFVSSxPQUFZLEVBQUpOLEVBQU9BLEdBQUssRUFLdEMsSUFKQVAsRUFBV1csRUFBSUYsRUFBVXBCLE1BQU0sRUFBR2tCLEdBQUdhLEtBQUssU0FLekNwQixFQUFXQSxFQUFTRCxJQUNOLENBRWJFLEVBQVdELEVBQ1hHLEVBQVNHLEVBQ1QsTUFNSixHQUFJTCxFQUNILE9BTUlHLEdBQWdCUSxHQUFXQSxFQUFRYixLQUN2Q0ssRUFBZVEsRUFBUWIsR0FDdkJNLEVBQVFDLElBSUxMLEdBQVlHLElBQ2hCSCxFQUFXRyxFQUNYRCxFQUFTRSxHQUdOSixJQUNISCxFQUFVcUIsT0FBTyxFQUFHaEIsRUFBUUYsR0FDNUJMLEVBQU9FLEVBQVVzQixLQUFLLE1BSXhCLE9BQU94QixFQUdSLFNBQVN5QixFQUFZQyxFQUFTQyxHQUM3QixPQUFPLFdBSU4sSUFBSUMsRUFBT3BDLEVBQUlNLEtBQUsrQixVQUFXLEdBUS9CLE1BSHVCLGlCQUFaRCxFQUFLLElBQW1DLElBQWhCQSxFQUFLWCxRQUN2Q1csRUFBS0UsS0FBSyxNQUVKakQsRUFBSWtELE1BQU1wRCxFQUFPaUQsRUFBS04sT0FBTyxDQUFDSSxFQUFTQyxNQVVoRCxTQUFTSyxFQUFTQyxHQUNqQixPQUFPLFNBQVVDLEdBQ2hCbEQsRUFBUWlELEdBQVdDLEdBSXJCLFNBQVNDLEVBQVFuQyxHQUNoQixHQUFJTCxFQUFRVixFQUFTZSxHQUFPLENBQzNCLElBQUk0QixFQUFPM0MsRUFBUWUsVUFDWmYsRUFBUWUsR0FDZmIsRUFBU2EsSUFBUSxFQUNqQnBCLEVBQUttRCxNQUFNcEQsRUFBT2lELEdBR25CLElBQUtqQyxFQUFRWCxFQUFTZ0IsS0FBVUwsRUFBUVIsRUFBVWEsR0FDakQsTUFBTSxJQUFJb0MsTUFBTSxNQUFRcEMsR0FFekIsT0FBT2hCLEVBQVFnQixHQU1oQixTQUFTcUMsRUFBWXJDLEdBQ3BCLElBQUlzQyxFQUNIQyxFQUFRdkMsRUFBT0EsRUFBS3dDLFFBQVEsTUFBUSxFQUtyQyxPQUphLEVBQVRELElBQ0hELEVBQVN0QyxFQUFLeUMsVUFBVSxFQUFHRixHQUMzQnZDLEVBQU9BLEVBQUt5QyxVQUFVRixFQUFRLEVBQUd2QyxFQUFLaUIsU0FFaEMsQ0FBQ3FCLEVBQVF0QyxHQUtqQixTQUFTMEMsRUFBYWhCLEdBQ3JCLE9BQU9BLEVBQVVXLEVBQVlYLEdBQVcsR0FRekM1QyxFQUFVLFNBQVVrQixFQUFNMkMsR0FDekIsSUFBSUMsRUFuRGtCbEIsRUFvRHJCbUIsRUFBUVIsRUFBWXJDLEdBQ3BCc0MsRUFBU08sRUFBTSxHQUNmQyxFQUFrQkgsRUFBUyxHQTJCNUIsT0F6QkEzQyxFQUFPNkMsRUFBTSxHQUVUUCxJQUVITSxFQUFTVCxFQURURyxFQUFTdkMsRUFBVXVDLEVBQVFRLEtBS3hCUixFQUVGdEMsRUFERzRDLEdBQVVBLEVBQU83QyxVQUNiNkMsRUFBTzdDLFVBQVVDLEdBbEVKMEIsRUFrRXdCb0IsRUFqRXZDLFNBQVU5QyxHQUNoQixPQUFPRCxFQUFVQyxFQUFNMEIsTUFrRWYzQixFQUFVQyxFQUFNOEMsSUFLeEJSLEdBREFPLEVBQVFSLEVBRFJyQyxFQUFPRCxFQUFVQyxFQUFNOEMsS0FFUixHQUNmOUMsRUFBTzZDLEVBQU0sR0FDVFAsSUFDSE0sRUFBU1QsRUFBUUcsS0FLWixDQUNOUyxFQUFHVCxFQUFTQSxFQUFTLElBQU10QyxFQUFPQSxFQUNsQ2dELEVBQUdoRCxFQUNIaUQsR0FBSVgsRUFDSlksRUFBR04sSUFVTDdELEVBQVcsQ0FDVlYsUUFBUyxTQUFVMkIsR0FDbEIsT0FBT3lCLEVBQVl6QixJQUVwQm1ELFFBQVMsU0FBVW5ELEdBQ2xCLElBQUlvRCxFQUFJcEUsRUFBUWdCLEdBQ2hCLFlBQWlCLElBQU5vRCxFQUNIQSxFQUVDcEUsRUFBUWdCLEdBQVEsSUFHMUJxRCxPQUFRLFNBQVVyRCxHQUNqQixNQUFPLENBQ05zRCxHQUFJdEQsRUFDSnVELElBQUssR0FDTEosUUFBU25FLEVBQVFnQixHQUNqQmQsUUF2QmlCYyxFQXVCRUEsRUF0QmQsV0FDTixPQUFRZCxHQUFVQSxFQUFPQSxRQUFVQSxFQUFPQSxPQUFPYyxJQUFVLE1BRjdELElBQW9CQSxJQTRCcEJwQixFQUFPLFNBQVVvQixFQUFNd0QsRUFBTUMsRUFBVS9CLEdBQ3RDLElBQUlnQyxFQUFXekIsRUFBUzBCLEVBQUs1QyxFQUFLTCxFQUFHaUMsRUFHcENpQixFQUZBaEMsRUFBTyxHQUNQaUMsU0FBc0JKLEVBUXZCLEdBSEFkLEVBQVdELEVBRFhoQixFQUFVQSxHQUFXMUIsR0FJQSxjQUFqQjZELEdBQWlELGFBQWpCQSxFQUE2QixDQUtoRSxJQURBTCxHQUFRQSxFQUFLdkMsUUFBVXdDLEVBQVN4QyxPQUFTLENBQUMsVUFBVyxVQUFXLFVBQVl1QyxFQUN2RTlDLEVBQUksRUFBR0EsRUFBSThDLEVBQUt2QyxPQUFRUCxHQUFLLEVBS2pDLEdBQWdCLGFBSGhCdUIsR0FEQWxCLEVBQU1qQyxFQUFRMEUsRUFBSzlDLEdBQUlpQyxJQUNUSSxHQUlibkIsRUFBS2xCLEdBQUszQixFQUFTVixRQUFRMkIsUUFDckIsR0FBZ0IsWUFBWmlDLEVBRVZMLEVBQUtsQixHQUFLM0IsRUFBU29FLFFBQVFuRCxHQUMzQjRELEdBQWUsT0FDVCxHQUFnQixXQUFaM0IsRUFFVnlCLEVBQVk5QixFQUFLbEIsR0FBSzNCLEVBQVNzRSxPQUFPckQsUUFDaEMsR0FBSUwsRUFBUVgsRUFBU2lELElBQ3ZCdEMsRUFBUVYsRUFBU2dELElBQ2pCdEMsRUFBUVIsRUFBVThDLEdBQ3RCTCxFQUFLbEIsR0FBS3lCLEVBQVFGLE9BQ1osQ0FBQSxJQUFJbEIsRUFBSW1DLEVBSWQsTUFBTSxJQUFJZCxNQUFNcEMsRUFBTyxZQUFjaUMsR0FIckNsQixFQUFJbUMsRUFBRVksS0FBSy9DLEVBQUlpQyxFQUFHdkIsRUFBWUMsR0FBUyxHQUFPTSxFQUFTQyxHQUFVLElBQ2pFTCxFQUFLbEIsR0FBSzFCLEVBQVFpRCxHQU1wQjBCLEVBQU1GLEVBQVdBLEVBQVMxQixNQUFNL0MsRUFBUWdCLEdBQU80QixRQUFRbUMsRUFFbkQvRCxJQUlDMEQsR0FBYUEsRUFBVVAsVUFBWXhFLEdBQ3JDK0UsRUFBVVAsVUFBWW5FLEVBQVFnQixHQUMvQmhCLEVBQVFnQixHQUFRMEQsRUFBVVAsUUFDaEJRLElBQVFoRixHQUFVaUYsSUFFNUI1RSxFQUFRZ0IsR0FBUTJELFNBR1IzRCxJQUdWaEIsRUFBUWdCLEdBQVF5RCxJQUlsQnJGLEVBQVlDLEVBQVVRLEVBQU0sU0FBVTJFLEVBQU1DLEVBQVUvQixFQUFTQyxFQUFXcUMsR0FDekUsR0FBb0IsaUJBQVRSLEVBQ1YsT0FBSXpFLEVBQVN5RSxHQUVMekUsRUFBU3lFLEdBQU1DLEdBTWhCdEIsRUFBUXJELEVBQVEwRSxFQUFNZCxFQUFhZSxJQUFXVixHQUMvQyxJQUFLUyxFQUFLakMsT0FBUSxDQU14QixJQUpBckMsRUFBU3NFLEdBQ0VBLE1BQ1YzRSxFQUFJSyxFQUFPc0UsS0FBTXRFLEVBQU91RSxXQUVwQkEsRUFDSixPQUdHQSxFQUFTbEMsUUFHWmlDLEVBQU9DLEVBQ1BBLEVBQVcvQixFQUNYQSxFQUFVLE1BRVY4QixFQUFPN0UsRUE2QlQsT0F4QkE4RSxFQUFXQSxHQUFZLGFBSUEsbUJBQVovQixJQUNWQSxFQUFVQyxFQUNWQSxFQUFZcUMsR0FJVHJDLEVBQ0gvQyxFQUFLRCxFQUFPNkUsRUFBTUMsRUFBVS9CLEdBUTVCdUMsV0FBVyxXQUNWckYsRUFBS0QsRUFBTzZFLEVBQU1DLEVBQVUvQixJQUMxQixHQUdHN0MsR0FPUkEsRUFBSUssT0FBUyxTQUFVZ0YsR0FDdEIsT0FBT3JGLEVBQUlxRixJQU1aOUYsRUFBVStGLFNBQVduRixHQUVyQlYsRUFBUyxTQUFVMEIsRUFBTXdELEVBQU1DLEdBQzlCLEdBQW9CLGlCQUFUekQsRUFDVixNQUFNLElBQUlvQyxNQUFNLDZEQUlab0IsRUFBS2pDLFNBSVRrQyxFQUFXRCxFQUNYQSxFQUFPLElBR0g3RCxFQUFRWCxFQUFTZ0IsSUFBVUwsRUFBUVYsRUFBU2UsS0FDaERmLEVBQVFlLEdBQVEsQ0FBQ0EsRUFBTXdELEVBQU1DLE1BSXhCVyxJQUFNLENBQ1pDLFFBQVEsR0F0YVYsR0EwYUEvRixFQUFPLGdCQUFpQixjQVF4QkEsRUFBUSxhQUFhLEdBQUcsV0FDdkIsT0FBT2dHLElBU1JoRyxFQUFRLFdBQVcsR0FBRyxXQUNyQixPQUFPaUcsV0FTUmpHLEVBQVEsU0FBUyxHQUFHLFdBQ25CLE9BQU8rRixTQVVJOUYsRUFZVGlHLEtBWmVoRyxFQVlULFNBQVU4RixFQUFHQyxFQUFVcEcsR0FDL0IsSUFBSXNHLEVBQStCRixFQUFTRyxLQUV4Q0MsRUFBc0IsUUFFdEJDLEVBQStCLENBQUUsYUFBYyxZQUFhLG1CQUFvQixlQUFnQix1QkFBd0IscUJBRXhIQyxFQUE2QixDQUNoQ0MsV0FBZSxjQUNmQyxPQUFXLE9BQ1hDLGFBQWUsUUE4bkNoQixTQUFTQyxFQUE4QkMsR0FJdEMsSUFBSUMsRUFBK0IsR0FFbkMsSUFBTWIsRUFBRWMsUUFBU0YsR0FBdUIsTUFBTSxJQUFJOUMsTUFBTyx5Q0E2QnpELE9BM0JBa0MsRUFBRWUsS0FBTUgsRUFBb0IsU0FBVUksR0FDckMsSUFBSUMsRUFBZ0JDLEVBQW9CQyxFQUt4QyxHQUhBRCxHQUFxQixFQUNyQkMsT0FBeUIxQixFQUVyQk8sRUFBRW9CLFNBQVVKLEdBQ2ZDLEVBQWlCRCxNQUNiLENBQUEsSUFBSWhCLEVBQUVxQixTQUFVTCxHQU9oQixNQUFNLElBQUlsRCxNQUFPLHVGQU5yQm1ELEVBQWlCakIsRUFBRXNCLE1BQU90QixFQUFFdUIsS0FBTVAsSUFFakNHLEVBREduQixFQUFFd0IsV0FBWVIsRUFBdUJDLElBQ2ZELEVBQXVCQyxHQUV2QmpCLEVBQUV5QixNQUFPVCxFQUF1QkMsSUFJUCxNQUFoREEsRUFBZ0JBLEVBQWV0RSxPQUFTLEtBQzNDdUUsR0FBcUIsRUFDckJELEVBQWlCQSxFQUFlOUYsTUFBTyxFQUFHOEYsRUFBZXRFLE9BQVMsSUFHbkVrRSxFQUE4QkksR0FBbUJKLEVBQThCSSxJQUFvQixHQUNuR0osRUFBOEJJLEdBQWlCUyxTQUFXUixFQUNwRGxCLEVBQUUyQixZQUFhUixLQUEyQk4sRUFBOEJJLEdBQWlCVyxhQUFlVCxLQUd4R04sRUE0S1IsT0ExMENBWixFQUFTNEIsZUFBaUI1QixFQUFTRyxLQUFLMEIsT0FBUSxDQUUvQ0MsUUFBVSxLQUVWQyxPQUFTLENBQ1JDLGtDQUFvQyx3QkFDcENDLGlDQUFtQywwQkFDbkNDLE1BQVUsMEJBQ1ZDLGtEQUFvRCwwQkFDcERDLFFBQVksY0FJYkMsY0FBZ0IsQ0FDZkMsTUFBVSxTQUlYQyxhQUFlLENBQUVDLElBQU0sS0FHdkJDLHNCQUF3QixDQUN2QixDQUFFQyxXQUFlLE1BQ2pCLENBQUVDLFVBQWMsTUFDaEIsQ0FBRUMsaUJBQXFCLElBQ3ZCLENBQUVDLGFBQWlCLE1BQ25CLENBQUVDLHFCQUF5QixNQUMzQixDQUFFQyxZQUFlLEdBQ2pCLENBQUVDLGVBQWtCLEdBQ3BCLENBQUVDLHVCQUEyQixNQUM3QixDQUFFQyxvQkFBd0IsTUFDMUIsQ0FBRUMscUJBQXlCLE1BQzNCLENBQUVDLGdCQUFtQixHQUNyQixDQUFFQyxlQUFrQixHQUNwQixDQUFFQyxrQkFBcUIsR0FDdkIsQ0FBRUMsVUFBYSxHQUNmLENBQUVDLGdCQUFvQixNQUN0QixDQUFFQyxpQkFBb0IsR0FDdEIsQ0FBRUMsbUJBQXNCLEdBQ3hCLENBQUVDLGlCQUFxQixPQUd4QkMsV0FBYSxTQUFVQyxHQUN0QjdELEVBQVM4RCxZQUFZQyxJQUFLOUQsS0FBTSx5QkFDaENBLEtBQUsrRCxXQUFZSCxHQUVYNUQsS0FBS3lDLGFBQWF6QyxLQUFLeUMsV0FBYSxJQUFJMUMsRUFBU2lFLFlBRXZEaEUsS0FBS2lFLGtCQUFtQixFQUVwQmpFLEtBQUtrRSwrQkFDUm5FLEVBQVNvRSxRQUFRTCxJQUFLOUQsTUFHdkJBLEtBQUtvRSxJQUFJQyxLQUFNLE9BQVFyRSxNQUN2QkEsS0FBS29FLElBQUlFLFNBQVUsbUNBQ2Z0RSxLQUFLOEMsWUFBYTlDLEtBQUtvRSxJQUFJRSxTQUFVLGNBRXJDdEUsS0FBSzhDLFlBQWM5QyxLQUFLcUQsa0JBQzNCckQsS0FBS29FLElBQUlHLEtBQU0sV0FBWSxHQUU1QnZFLEtBQUt3RSxjQUFnQixHQUVyQnhFLEtBQUt5RSxzQkFFRHpFLEtBQUt5QyxZQUNSekMsS0FBSzBFLDRCQUVOMUUsS0FBSzJFLFlBQWMsSUFBSUMsb0JBR3hCQyxrQkFBb0IsU0FBVUMsRUFBZ0JDLEdBQzdDLElBQUlDLEVBQVFoRixLQUNSaUYsR0FBVyxFQUVmbkYsRUFBRWUsS0FBTWYsRUFBRXVCLEtBQU15RCxHQUFrQixTQUFVSSxHQUMzQyxJQUFJQyxFQUFTTCxFQUFnQkksR0FDekJFLEVBQVNMLEVBQWlCRyxHQUM5QixPQUFRQSxHQUNQLElBQUssYUFDQ0MsSUFBV0MsSUFDZkosRUFBTUssY0FBZUQsR0FDckJKLEVBQU1OLDZCQUVQLE1BQ0QsSUFBSyxrQkFDRVMsR0FBdUMsRUFBN0JILEVBQU1SLGNBQWMvSCxRQUNuQ3VJLEVBQU1NLGlCQUFrQnhGLEVBQUVzQixNQUFPNEQsRUFBTVIsZUFBaUIsQ0FBRWUsR0FBSyxRQUNoRSxNQUNELElBQUssY0FDRUosR0FBdUMsRUFBN0JILEVBQU1SLGNBQWMvSCxRQUNuQ3VJLEVBQU1RLGtCQUFtQixJQUV0QkwsR0FBVW5GLEtBQUtxRCxpQkFBbUIyQixFQUFNWixJQUFJRyxLQUFNLFdBQVksR0FDN0RTLEVBQU1aLElBQUlxQixXQUFZLFdBQVksR0FDdkMsTUFDRCxJQUFLLFdBQ0pYLEVBQWV4QixTQUFXMEIsRUFBTVUsaUJBQW1CVixFQUFNWixJQUFJZCxTQUFVLFdBQ3ZFLE1BQ0QsSUFBSyx5QkFDSjBCLEVBQU1XLGNBQWUsb0JBQ3JCLE1BQ0QsSUFBSyxrQkFDSlgsRUFBTVosSUFBSWQsU0FBVSxXQUNwQjBCLEVBQU1VLGlCQUNOLE1BQ0QsSUFBSyx1QkFDSlYsRUFBTVcsY0FBZSxrQkFDckIsTUFDRCxJQUFLLHNCQUNKWCxFQUFNVyxjQUFlLGlCQUNyQixNQUNELElBQUssZUFDSlgsRUFBTVAsc0JBQ04sTUFDRCxJQUFLLG1CQUNBVSxHQUFVbkYsS0FBSzhDLFdBQWFrQyxFQUFNWixJQUFJRyxLQUFNLFdBQVksR0FDdkRTLEVBQU1aLElBQUlxQixXQUFZLFdBQVksR0FDdkMsTUFDRCxJQUFLLFlBRUpULEVBQU1MLFlBQVk5RCxLQUFNLFNBQVUrRSxHQUNqQ1osRUFBTUwsWUFBWWtCLE9BQVFELEdBRTFCQSxFQUFLQyxXQUlKL0YsRUFBRWdHLFNBQVUxRixFQUE4QjhFLEtBQXFCRCxHQUFXLEtBRzNFakYsS0FBS2lFLGtCQUFvQmdCLEdBQzVCakYsS0FBSytGLFVBSVBDLFVBQVksU0FBVUMsRUFBWUMsR0FDakMsSUFBSUMsRUFBYSxHQUNqQkEsRUFBWUYsR0FBZUMsRUFDM0JsRyxLQUFLK0QsV0FBWW9DLElBR2xCQyxpQkFBbUIsU0FBVXhDLEdBQzVCLE9BQU81RCxLQUFLd0UsY0FBYy9ILE9BQVNxRCxFQUFFc0IsTUFBT3BCLEtBQUtxRyxrQkFBbUJ6QyxJQUFjLE1BR25GeUMsa0JBQW9CLFNBQVd6QyxHQUM5QixJQUFJb0IsRUFBUWhGLEtBTVJzRyxHQUpKMUMsRUFBVTlELEVBQUU4QixPQUFRLEdBQUksQ0FDdkIyRCxHQUFLcEYsR0FDSHlELElBRXVCMkIsR0FDdEJnQixFQUFRLEdBRVosT0FBUUQsR0FDUCxJQUFLLEtBQ0p4RyxFQUFFZSxLQUFNYixLQUFLd0UsY0FBZSxTQUFXZ0MsR0FDdENELEVBQU1qSixLQUFNMEgsRUFBTXZDLFdBQVdnRSxJQUFLRCxHQUFPMUgsTUFFMUMsTUFDRCxJQUFLLE1BQ0p5SCxFQUFRQSxFQUFNekosT0FBUWtELEtBQUt3RSxlQUMzQixNQUNELElBQUssU0FDSixJQUFJa0MsRUFBZ0IsRUFFRDFHLEtBQUsyRyxxQkFFWDlGLEtBQU0sV0FDRGxILEVBQUdxRyxNQUNMNEcsR0FBSSxjQUNsQkwsRUFBTWpKLEtBQU1vSixHQUNiQSxNQUVELE1BQ0QsSUFBSyxRQUNKNUcsRUFBRWUsS0FBTWIsS0FBS3dFLGNBQWUsU0FBV2dDLEdBQ3RDRCxFQUFNakosS0FBTTBILEVBQU12QyxXQUFXZ0UsSUFBS0QsTUFFbkMsTUFDRCxJQUFLLE9BQ0oxRyxFQUFFZSxLQUFNYixLQUFLd0UsY0FBZSxTQUFXZ0MsR0FDdENELEVBQU1qSixLQUFNMEgsRUFBTUwsWUFBWWtDLFlBQWE3QixFQUFNdkMsV0FBV2dFLElBQUtELE9BRWxFLE1BQ0QsUUFDQyxNQUFNLElBQUk1SSxNQUFPLCtCQUFpQzBJLEdBSXBELE9BQU9DLEdBSVJmLGtCQUFvQixTQUFVc0IsRUFBa0JsRCxHQUMvQyxJQUFNOUQsRUFBRWMsUUFBU2tHLEdBQXFCLEtBQU0sMEJBQzVDLEdBQU05RyxLQUFLOEMsY0FBd0MsRUFBMUJnRSxFQUFpQnJLLFFBQTFDLENBT0EsSUFBSTZKLEdBTEoxQyxFQUFVOUQsRUFBRThCLE9BQVEsR0FBSSxDQUN2Qm1GLFFBQVMsRUFDVHhCLEdBQUtwRixHQUNIeUQsSUFFdUIyQixHQUN0QnlCLEVBQWtCLEdBRXRCLE9BQVFWLEdBQ1AsSUFBSyxNQUNKVSxFQUFrQkYsRUFDbEIsTUFDRCxJQUFLLEtBQ0o5RyxLQUFLeUMsV0FBVzVCLEtBQU0sU0FBVW9HLEdBQzNCbkgsRUFBRWdHLFNBQVVnQixFQUFrQkcsRUFBVW5JLEtBQU9rSSxFQUFnQjFKLEtBQU0ySixFQUFVQyxPQUVwRixNQUNELElBQUssUUFDSkYsRUFBa0JsSCxFQUFFcUgsTUFBT0wsRUFBa0IsT0FDN0MsTUFDRCxJQUFLLE9BQ0poSCxFQUFFZSxLQUFNaUcsRUFBa0IsU0FBVU4sR0FDbkNRLEVBQWdCMUosS0FBTWtKLEVBQUtZLE1BQU1GLE9BRWxDLE1BQ0QsSUFBSyxTQUNKLElBQUlSLEVBQWdCLEVBR0QxRyxLQUFLMkcscUJBQ1g5RixLQUFNLFdBQ2xCLElBQUl3RyxFQUFhMU4sRUFBR3FHLE1BQ2hCRixFQUFFZ0csU0FBVWdCLEVBQWtCSixJQUNqQ00sRUFBZ0IxSixLQUFNK0osRUFBVzlDLEtBQU0sbUJBQ3hDbUMsTUFFRCxNQUNELFFBQ0MsTUFBTSxJQUFJOUksTUFBTywrQkFBaUMwSSxHQUlwRCxJQUFJZ0IsRUFBb0J0SCxLQUFLcUcsb0JBQ3pCa0IsRUFBa0J6SCxFQUFFeUIsTUFBT3ZCLEtBQUt3RSxlQUVwQ3hFLEtBQUt3RSxjQUFnQnhFLEtBQUt3SCxzQkFBdUJSLEdBQ2pEaEgsS0FBS3lILHFCQUVMLElBQUlDLEVBQW9CMUgsS0FBS3FHLG9CQUV2QnJHLEtBQUsySCxxQkFBc0JKLEVBQWlCdkgsS0FBS3dFLGlCQUV0RHhFLEtBQUs0SCxpQ0FBa0NMLEdBRWpDM0QsRUFBUW1ELFNBRVQvRyxLQUFLa0UsOEJBQ1JsRSxLQUFLNkgsTUFBTyxtQkFBb0IsQ0FDL0JDLGVBQWlCSixFQUNqQkosa0JBQW9CQSxJQUVmdEgsS0FBSytILFFBQVMsbUJBQW9CTCxFQUFtQkosSUFHN0R0SCxLQUFLZ0ksNkJBSVAxQyxpQkFBbUIsU0FBVTJDLEVBQWlCckUsR0FDdkNxRSxHQUF1QyxJQUFwQkEsRUFHeEJqSSxLQUFLd0Ysa0JBQW1CLENBQUV5QyxHQUFtQnJFLEdBRjdDNUQsS0FBS3dGLGtCQUFtQixHQUFJNUIsSUFLOUJzRSxRQUFVLFNBQVVDLEVBQVd2RSxHQUs5QixRQUpBQSxFQUFVOUQsRUFBRThCLE9BQVEsR0FBSSxDQUN2QjJELEdBQUtwRixHQUNIeUQsSUFFYTJCLElBQ2YsSUFBSyxLQUNMLElBQUssTUFDSixJQUFJNkIsRUFBUXBILEtBQUt5QyxXQUFXZ0UsSUFBSzBCLElBQWUsS0FDaEQsT0FBT2YsR0FBU3BILEtBQUsyRSxZQUFZa0MsWUFBYU8sR0FFL0MsSUFBSyxTQUNKLElBQUlnQixFQUFlcEksS0FBSzJHLHFCQUN4QixPQUFPaE4sRUFBR3lPLEVBQWEzQixJQUFLMEIsSUFFN0IsSUFBSyxRQUNKLE9BQU9uSSxLQUFLMkUsWUFBWWtDLFlBQWFzQixHQUV0QyxRQUNDLE1BQU0sSUFBSXZLLE1BQU8sK0JBQWlDMEksZUFLckRQLE9BQVMsV0FDUixJQU1Jc0MsRUFKSnJJLEtBQUtpRSxrQkFBbUIsRUFFcEJqRSxLQUFLOEMsWUFBYTlDLEtBQUtzSSxpQkFNM0JELEVBQXVCckksS0FBS3VJLGtCQUU1QixJQWdCSUMsRUFoQkFDLEVBQWlCekksS0FBSzJFLFlBQzFCM0UsS0FBSzJFLFlBQWMsSUFBSUMsbUJBTXZCNkQsRUFBZTVILEtBQU0sU0FBVTZILEdBRzFCMUksS0FBS3dELGlCQUFtQnhELEtBQUt5QyxXQUFXZ0UsSUFBS2lDLEVBQWN0QixNQUFNRixLQUNwRXdCLEVBQWN0RSxJQUFJdUUsU0FDWkQsRUFBYzdDLFVBQ25CN0YsTUFFSHFJLEVBQXFCTyxRQUdqQjVJLEtBQUt5RCxvQkFDUitFLEVBQW9CSyxTQUFTQywwQkFFOUI5SSxLQUFLeUMsV0FBVzVCLEtBQU0sU0FBVW9HLEdBQy9CLElBQUl5QixFQUFnQkQsRUFBZU0sZUFBZ0I5QixFQUFVQyxLQUN2RGxILEtBQUt3RCxrQkFBbUIxRCxFQUFFMkIsWUFBYWlILEtBRzVDQSxFQUFnQjFJLEtBQUtnSixvQkFBcUIvQixFQUFXakgsS0FBS2lKLHFCQUFzQmhDLEtBR2pGakgsS0FBS2tKLDBCQUEyQlIsRUFBZUYsR0FBcUJILElBQ2xFckksTUFFQ0EsS0FBS3lELG1CQUNSNEUsRUFBcUJjLE9BQVFYLEdBRTFCeEksS0FBS3NELFVBQVd0RCxLQUFLMEYsaUJBRXpCMUYsS0FBS29KLHFDQUVEcEosS0FBS2tFLDhCQUNSbEUsS0FBSzZILE1BQU8sVUFDUjdILEtBQUsrSCxRQUFTLFVBRWYvSCxLQUFLOEMsYUFDUjlDLEtBQUtxSixvQkFDTHJKLEtBQUtnSSwyQkFHTmhJLEtBQUtzSiw4QkFBK0IsR0FHckNGLG1DQUFxQyxXQUdwQyxJQUZBcEosS0FBS3VKLDBCQUVEdkosS0FBSzBELG1CQUdrQixJQUZUMUQsS0FBSzJHLHFCQUVQbEssT0FBZSxDQUM3QixJQUFJK00sRUFPQUMsRUFKSEQsRUFERzFKLEVBQUV3QixXQUFZdEIsS0FBSzBELGtCQUNKMUQsS0FBSzBELG1CQUVMMUQsS0FBSzBELGlCQUd4QixJQUFJZ0csRUFBUy9QLEVBQUcsbUNBQXFDNlAsRUFBa0IsVUFJdEVDLEVBREd6SixLQUFLMkosb0JBQ2NELEVBQU9FLFFBQVMsa0NBQW1DQyxTQUFTQyxJQUFLekosR0FFakVxSixFQUFPRSxRQUFTLDBEQUEyREMsU0FBU0EsU0FBU0MsSUFBS3pKLEdBRXpITCxLQUFLdUksa0JBQWtCWSxPQUFRTSxLQUtsQ0Ysd0JBQTBCLFdBQ3JCdkosS0FBSzJKLG9CQUNSM0osS0FBS3VJLGtCQUFrQndCLEtBQU0saUNBQWtDRixTQUFTaEUsU0FFeEU3RixLQUFLdUksa0JBQWtCd0IsS0FBTSxzQ0FBdUNGLFNBQVNBLFNBQVNoRSxVQUt4RnFELDBCQUE0QixTQUFVeEcsRUFBV3NILEVBQTRCQyxHQUM1RSxJQUFJQyxFQUF1QmxLLEtBQUttSyxlQUFnQnpILEdBRWhELEdBQTRDLEtBQXhDc0gsRUFBMkJJLFNBQzlCSixFQUEyQkssWUFBYUgsRUFBcUJ6RCxJQUFLLFFBQzlELENBQ0osSUFBSTZELEVBQW1DTixFQUEyQk8sV0FBVzlOLFFBQ3ZFcUQsRUFBRTJCLFlBQWF3SSxJQUF3QixHQUFYQSxHQUFnQkEsRUFBVUssRUFFM0ROLEVBQTJCTyxXQUFXQyxHQUFJUCxHQUFVUSxPQUFRUCxLQU10RHBLLEVBQUUyQixZQUFhd0ksSUFBdUJLLEVBQVZMLElBQTZDakssS0FBS3NKLDhCQUErQixHQUVuSFUsRUFBMkJiLE9BQVFlLElBSXJDbEssS0FBSzJFLFlBQVliLElBQUtwQixJQVNELElBSEZBLEVBQVVxRCxXQUk1Qm1FLEVBQXFCUSxPQUNyQlIsRUFBcUI1RixTQUFVLGdCQUdoQyxJQUFJcUcsR0FBb0IsRUFDcEI3SyxFQUFFd0IsV0FBWXRCLEtBQUtpRCx1QkFDdEIwSCxHQUFzQjNLLEtBQUtpRCxvQkFBcUJQLEVBQVUwRSxRQUVaLElBQTNDOEMsRUFBcUJLLFdBQVc5TixPQUNuQ3lOLEVBQXFCVSxRQUFVRCxHQUMzQmpJLEVBQVUwQixJQUFJd0csUUFBVUQsR0FFN0JULEVBQXFCVyxZQUFhLGNBQWVGLElBRTNDQSxHQUFxQjNLLEtBQUswRCxrQkFBbUIxRCxLQUFLdUosMkJBR3pEdkIsd0JBQTBCLFdBQ3JCaEksS0FBS2tFLDhCQUNSbEUsS0FBSzZILE1BQU8sMEJBQTJCLENBQ3RDQyxlQUFpQjlILEtBQUtxRyxzQkFFakJyRyxLQUFLK0gsUUFBUywwQkFBMkIvSCxLQUFLcUcsc0JBSXREUixPQUFTLFdBQ1I3RixLQUFLMkUsWUFBWTlELEtBQU0sU0FBVStFLEdBQ2hDQSxFQUFLQyxXQUdOOUYsRUFBU0csS0FBS3BGLFVBQVUrSyxPQUFPdEksTUFBT3lDLEtBQU0zQyxZQUc3Q3NJLGNBQWdCLFNBQVVtRixHQUN6QixJQUFJOUYsRUFBUWhGLEtBRVosSUFBTUYsRUFBRWdHLFNBQVUsQ0FBRSxtQkFBb0IsaUJBQWtCLGlCQUFtQmdGLEdBQzVFLE1BQU0sSUFBSWxOLE1BQU8sd0RBQTBEa04sR0FHNUUsT0FBUUEsR0FDUCxJQUFLLGdCQUNKOUYsRUFBTUwsWUFBWTlELEtBQU0sU0FBVTZILEdBQ2pDLElBQUlxQyxFQUFhL0YsRUFBTS9CLHNCQUF5QitCLEVBQU0vQixvQkFBb0IzSCxLQUFNMEosRUFBTzBELEVBQWN0QixPQUVyR3NCLEVBQWN0RSxJQUFJeUcsWUFBYSxjQUFlRSxHQUMxQy9GLEVBQU1nRyx1QkFBd0J0QyxHQUNqQ0EsRUFBY3RFLElBQUk2RyxRQUFTLE1BQU9KLFlBQWEsY0FBZUUsR0FBYUgsUUFBVUcsR0FDL0VyQyxFQUFjdEUsSUFBSXdHLFFBQVVHLEtBR3BDL0ssS0FBS29KLHFDQUNMLE1BQ0QsSUFBSyxpQkFDSnBFLEVBQU1aLElBQUlkLFNBQVUsV0FFcEIwQixFQUFNTCxZQUFZOUQsS0FBTSxTQUFVNkgsR0FDakMsSUFBSXdDLEVBQWNsRyxFQUFNOUIsdUJBQTBCOEIsRUFBTTlCLHFCQUFxQjVILEtBQU0wSixFQUFPMEQsRUFBY3RCLE9BRXhHc0IsRUFBY3RFLElBQUl5RyxZQUFhLGVBQWdCSyxHQUMzQ2xHLEVBQU1nRyx1QkFBd0J0QyxJQUNqQ0EsRUFBY3RFLElBQUk2RyxRQUFTLE1BQU9KLFlBQWEsZUFBZ0JLLEtBSWpFbEcsRUFBTVUsaUJBQ04sTUFDRCxJQUFLLG1CQUNKVixFQUFNTCxZQUFZOUQsS0FBTSxTQUFVNkgsR0FDakMsSUFBSXlDLEVBQWdCbkcsRUFBTWhDLHlCQUE0QmdDLEVBQU1oQyx1QkFBdUIxSCxLQUFNMEosRUFBTzBELEVBQWN0QixPQUU5R3NCLEVBQWN0RSxJQUFJeUcsWUFBYSxpQkFBa0JNLEdBQzdDbkcsRUFBTWdHLHVCQUF3QnRDLElBQ2pDQSxFQUFjdEUsSUFBSTZHLFFBQVMsTUFBT0osWUFBYSxpQkFBa0JNLEtBSW5FbkcsRUFBTXlDLHVCQU1UMkQsaUJBQW1CLFNBQVUxSSxHQUN4QjFDLEtBQUs4QyxZQUFhOUMsS0FBS3NJLGlCQUUzQnRJLEtBQUsyRSxZQUFZa0IsT0FBUW5ELEdBQ3JCMUMsS0FBS2dMLHVCQUF3QnRJLElBQWNBLEVBQVUwQixJQUFJeUYsU0FBU2hFLFNBQ3RFbkQsRUFBVW1ELFNBRU43RixLQUFLOEMsWUFBYTlDLEtBQUtxSixvQkFFM0JySixLQUFLb0osc0NBR05pQyw0QkFBOEIsV0FDN0JyTCxLQUFLeUgscUJBQ0x6SCxLQUFLK0YsVUFHTnJCLDBCQUE0QixXQUUzQjFFLEtBQUtzTCxTQUFVdEwsS0FBS3lDLFdBQVksTUFBTyxTQUFVMkUsR0FDaEQsSUFBSTFFLEVBQ0ExQyxLQUFLaUUsbUJBQ1J2QixFQUFZMUMsS0FBS2dKLG9CQUFxQjVCLEVBQU9wSCxLQUFLaUoscUJBQXNCN0IsSUFDeEVwSCxLQUFLa0osMEJBQTJCeEcsRUFBVzFDLEtBQUt1SSxrQkFBbUJ2SSxLQUFLeUMsV0FBV3pFLFFBQVNvSixLQUd6RnBILEtBQUtrRSw4QkFDUmxFLEtBQUs2SCxNQUFPLE1BQU9uRixHQUNmMUMsS0FBSytILFFBQVMsTUFBT3JGLEtBRzNCMUMsS0FBS3NMLFNBQVV0TCxLQUFLeUMsV0FBWSxTQUFVLFNBQVUyRSxHQUNuRCxJQUFJMUUsRUFFQTFDLEtBQUtpRSxtQkFDUnZCLEVBQVkxQyxLQUFLMkUsWUFBWW9FLGVBQWdCM0IsRUFBTUYsS0FDbkRsSCxLQUFLb0wsaUJBQWtCMUksSUFHcEIxQyxLQUFLa0UsOEJBQ1JsRSxLQUFLNkgsTUFBTyxVQUNSN0gsS0FBSytILFFBQVMsWUFHcEIvSCxLQUFLc0wsU0FBVXRMLEtBQUt5QyxXQUFZLFFBQVMsV0FDcEN6QyxLQUFLaUUsa0JBQW1CakUsS0FBSytGLFNBQzdCL0YsS0FBS2tFLDhCQUNSbEUsS0FBSzZILE1BQU8sU0FDUjdILEtBQUsrSCxRQUFTLFdBYXBCL0gsS0FBS3NMLFNBQVV0TCxLQUFLeUMsV0FBWSxPQUFRLFNBQVVBLEVBQVltQixHQUN6RDVELEtBQUtpRSxvQkFBc0MsSUFBaEJMLEVBQVFFLEtBQWdCOUQsS0FBS3NKLCtCQUFpQ3RKLEtBQUsrRixTQUM5Ri9GLEtBQUtrRSw4QkFDUmxFLEtBQUs2SCxNQUFPLFFBQ1I3SCxLQUFLK0gsUUFBUyxXQUlyQlEsZ0JBQWtCLFdBQ2pCLEdBQUt2SSxLQUFLdUwscUJBQXVCLENBRWhDLElBQUlDLEVBQVF4TCxLQUFLb0UsSUFBSTJGLEtBQU0sV0FDM0IsR0FBb0IsRUFBZnlCLEVBQU0vTyxPQUNWLE9BQU8rTyxFQUVULE9BQU94TCxLQUFLb0UsS0FHYnFILGtCQUFvQixTQUFVQyxHQUM3QixJQUFJQyxFQUFnQixLQUloQkMsRUFBZ0JqUyxFQUFHK1IsRUFBU0csZUFDaEMsR0FBSUQsRUFBY1gsUUFBUyxvQkFBcUJ4RSxJQUFJLEtBQU96RyxLQUFLb0UsSUFBSXFDLElBQUksR0FBeEUsQ0FNQSxJQUFJcUYsRUFBY0YsRUFBY1gsUUFBUyxvQkFPekMsT0FOeUIsRUFBckJhLEVBQVlyUCxTQUVma1AsRUFBZ0JHLEVBQVl2SCxLQUFNLGtCQUM5QjVLLEVBQUVvUyxVQUFXSixLQUFrQkEsRUFBZ0JLLFNBQVVMLEVBQWUsTUFHdEVBLElBR1JsSCxvQkFBc0IsV0FDckIsSUFBSXdILEVBQ0osR0FBSWpNLEtBQUs0QyxhQUNULENBQ0MsR0FBc0MsSUFBbENqSixFQUFHcUcsS0FBSzRDLGNBQWVuRyxPQUMxQixLQUFNLCtDQUFpRHVELEtBQUs0QyxhQUU3RHFKLEVBQW1CdFMsRUFBR3FHLEtBQUs0QyxjQUFlc0osWUFHMUNELEVBQW1Cak0sS0FBS3JHLEVBQUcsa0JBQW1CdVMsT0FFM0NELElBQW1Cak0sS0FBSzZDLHFCQUF1Qi9DLEVBQUVxTSxTQUFVRixLQUloRXhFLG1CQUFxQixXQUdwQixJQUFJMkUsRUFBb0J0TSxFQUFFcUgsTUFBT25ILEtBQUt5QyxXQUFXNEosT0FBUSxPQUN6RHJNLEtBQUt3RSxjQUFnQjFFLEVBQUV3TSxhQUFjRixFQUFtQnBNLEtBQUt3RSxlQUV6RDFFLEVBQUV3QixXQUFZdEIsS0FBS2dELDBCQUV0QmhELEtBQUt3RSxjQUFnQjFFLEVBQUV5TSxPQUFRdk0sS0FBS3dFLGNBQWUsU0FBVWdJLEdBQzVELE9BQU94TSxLQUFLZ0QsdUJBQXVCMUgsS0FBTTBFLEtBQU1BLEtBQUt5QyxXQUFXZ0UsSUFBSytGLEtBQ2xFeE0sUUFJTHNJLGVBQWlCLFdBRWhCLElBQU10SSxLQUFLOEMsV0FBYSxLQUFNLG1EQUM5QjlDLEtBQUt5TSxlQUFpQixDQUNyQmxHLE1BQVF6RyxFQUFFeUIsTUFBT3ZCLEtBQUt3RSxlQUN0QmtJLE9BQVMxTSxLQUFLb0csaUJBQWtCLENBQUViLEdBQUssYUFJekM4RCxrQkFBb0IsV0FDbkIsSUFBTXJKLEtBQUt5TSxlQUFpQixLQUFNLGdFQUtsQ3pNLEtBQUt3RixrQkFBbUIsR0FBSSxDQUFFdUIsUUFBUyxJQUVBLEVBQW5DL0csS0FBS3lNLGVBQWVsRyxNQUFNOUosU0FHN0J1RCxLQUFLd0Ysa0JBQW1CeEYsS0FBS3lNLGVBQWVsRyxNQUFPLENBQUVoQixHQUFLLE1BQU93QixRQUFTLElBTXhDLElBQTlCL0csS0FBS3dFLGNBQWMvSCxRQUN0QnVELEtBQUtzRixpQkFBa0J0RixLQUFLeU0sZUFBZUMsT0FBUSxDQUFFbkgsR0FBSyxXQUd2RHZGLEtBQUt3RSxjQUFjL0gsU0FBV3VELEtBQUt5TSxlQUFlbEcsTUFBTTlKLFNBRXZEdUQsS0FBS2tFLDhCQUNSbEUsS0FBSzZILE1BQU8sbUJBQW9CLENBQy9CQyxlQUFpQjlILEtBQUtxRyxvQkFDdEJpQixrQkFBb0IsS0FFZnRILEtBQUsrSCxRQUFTLG1CQUFvQi9ILEtBQUtxRyxvQkFBcUIsT0FLdEV1QixpQ0FBbUMsU0FBVStFLEdBQ3hDN00sRUFBRTJCLFlBQWFrTCxLQUFpQ0EsRUFBK0IsSUFLbkYsSUFBSUMsRUFBaURELEVBQ3JEQyxFQUFpRDlNLEVBQUUrTSxRQUFTRCxFQUFnRDVNLEtBQUt3RSxlQUVqSDFFLEVBQUVlLEtBQU0rTCxFQUFnRCxTQUFVSixHQUNqRXhNLEtBQUt1SSxrQkFBa0J3QixLQUFNLG1CQUFxQnlDLEVBQWEsS0FBTU0sWUFBYSxZQUU5RTlNLEtBQUsySixxQkFDUjNKLEtBQUt1SSxrQkFBa0J3QixLQUFNLHFCQUF1QnlDLEVBQWEsU0FBVU0sWUFBYSxhQUV2RjlNLE1BRUgsSUFBSStNLEVBQStDL00sS0FBS3dFLGNBQ3hEdUksRUFBK0NqTixFQUFFK00sUUFBU0UsRUFBOENKLEdBRXhHN00sRUFBRWUsS0FBTWtNLEVBQThDLFNBQVVQLEdBQy9EeE0sS0FBS3VJLGtCQUFrQndCLEtBQU0sbUJBQXFCeUMsRUFBYSxLQUFNbEksU0FBVSxZQUUzRXRFLEtBQUsySixxQkFDUjNKLEtBQUt1SSxrQkFBa0J3QixLQUFNLHFCQUF1QnlDLEVBQWEsU0FBVWxJLFNBQVUsYUFFcEZ0RSxPQUdKZ04sOEJBQWdDLFdBRS9CLElBQUloSSxFQUFRaEYsS0FFWkEsS0FBS3VJLGtCQUFrQmdDLFdBQVcxSixLQUFNLFdBQ3ZDLElBQUlvTSxFQUFldFQsRUFBR3FHLE1BQU91RSxLQUFNLGtCQUVuQyxHQUFJMEksRUFDSixDQUdDLElBQUloRyxFQUFZakMsRUFBTXZDLFdBQVdnRSxJQUFLd0csR0FDbENoRyxJQUVIakMsRUFBTXZDLFdBQVdvRCxPQUFRb0IsRUFBVyxDQUFFRixRQUFTLElBQy9DL0IsRUFBTXZDLFdBQVdxQixJQUFLbUQsRUFBVyxDQUFFRixRQUFTLEVBQU1tRyxNQUFTbEksRUFBTXZDLFdBQVcwSyxpQkFLM0VuTixLQUFLa0UsOEJBQWdDbEUsS0FBSzZILE1BQU8sV0FDaEQ3SCxLQUFLeUMsV0FBV3NGLFFBQVMsV0FFMUIvSCxLQUFLeUMsV0FBVzBLLFlBQWFuTixLQUFLeUMsV0FBV3lLLFFBSWxERSx5QkFBMkIsU0FBVW5HLEdBQ3BDLE9BQU9qSCxLQUFLMEMsV0FBYXpDLEdBRzFCZ0oscUJBQXVCLFNBQVVoQyxHQUNoQyxJQUFJdEUsRUFBbUIzQyxLQUFLMkMsaUJBRzVCLE9BRkk3QyxFQUFFd0IsV0FBWXFCLEtBQXFCQSxFQUFtQkEsRUFBa0JzRSxJQUVyRW5ILEVBQUU4QixPQUFRLENBQUV3RixNQUFRSCxHQUFhdEUsSUFHekNxRyxvQkFBc0IsU0FBVTVCLEVBQU96RSxHQUN0QyxJQUFJMEssRUFBdUJyTixLQUFLb04seUJBQTBCaEcsR0FDMUQsR0FBSXRILEVBQUUyQixZQUFhNEwsR0FBeUIsS0FBTSxpREFFbEQsSUFBSUMsRUFBZSxJQUFHLEVBQTBCM0ssR0FHaEQsT0FGQTJLLEVBQWFDLG1CQUFxQkQsRUFBYUUsZUFBaUJ4TixLQUV6RHNOLEdBR1JuRCxlQUFpQixTQUFVekgsR0FDMUIsSUFJSStLLEVBOEJKLE9BNUJJek4sS0FBS3VMLHNCQUVSa0MsRUFBcUIvSyxFQUFVMEIsSUFDL0IxQixFQUFVMEIsSUFBSUcsS0FBTSxpQkFBa0I3QixFQUFVMEUsTUFBTUYsTUFFOUNsSCxLQUFLMkosc0JBR1RqSCxFQUFVMEIsSUFBSXdDLEdBQUksT0FDckI2RyxFQUFxQi9LLEVBQVUwQixJQUMvQjFCLEVBQVUwQixJQUFJRyxLQUFNLGlCQUFrQjdCLEVBQVUwRSxNQUFNRixNQUV0RHVHLEVBQXFCL0ssRUFBVTBCLElBQUl3RixRQUFTLHVCQUF5QmxILEVBQVUwRSxNQUFNRixJQUFNLFdBQVkyQyxVQUlyRy9KLEVBQUV3QixXQUFZdEIsS0FBS2tELHdCQUNoQmxELEtBQUtrRCxxQkFBcUI1SCxLQXZCckIwRSxLQXVCa0MwQyxFQUFVMEUsU0FDdERxRyxFQUFtQm5KLFNBQVUsZ0JBQzdCNUIsRUFBVTBCLElBQUlFLFNBQVUsb0JBR3RCeEUsRUFBRXdCLFdBQVl0QixLQUFLZ0QsMEJBQ2hCaEQsS0FBS2dELHVCQUF1QjFILEtBN0J2QjBFLEtBNkJvQzBDLEVBQVUwRSxTQUN4RHFHLEVBQW1CbkosU0FBVSxrQkFDN0I1QixFQUFVMEIsSUFBSUUsU0FBVSxvQkFHbkJtSixHQUdSakcsc0JBQXdCLFNBQVVrRyxHQUNqQyxPQUFPNU4sRUFBRXZELElBQUttUixFQUFVLFNBQVVDLEdBQ2pDLElBQU03TixFQUFFb0IsU0FBVXlNLEdBQVcsT0FBT0EsRUFDcEMsSUFBSUMsRUFBaUI1QixTQUFVMkIsRUFBUSxJQUN2QyxPQUFRQyxHQUFrQkQsRUFBU0MsRUFBaUJELEtBSXREaEcscUJBQXVCLFNBQVVrRyxFQUFRQyxHQUN4QyxPQUFJRCxFQUFPcFIsUUFBVXFSLEVBQU9yUixRQUNMcUQsRUFBRXdNLGFBQWN1QixFQUFRQyxHQUFTclIsUUFDN0JvUixFQUFPcFIsUUFHbkM4TyxtQkFBcUIsV0FDcEIsTUFBb0QsVUFBN0N2TCxLQUFLb0UsSUFBSS9JLEtBQU0sV0FBWTBTLGVBR25DcEUsa0JBQW9CLFdBQ25CLE9BQVMzSixLQUFLdUwsc0JBR2ZQLHVCQUF5QixTQUFVdEksR0FDbEMsT0FBTzFDLEtBQUsySixzQkFBeUJqSCxFQUFVMEIsSUFBSXdDLEdBQUksT0FReERELG1CQUFxQixXQUlwQixPQUZlM0csS0FBS3VJLGtCQUFrQndCLEtBQU0seUNBSzdDaUUsV0FBYSxDQUNaQyxRQUFVLEdBQ1ZDLFVBQVksSUFHYmhLLDRCQUE4QixXQUM3QixPQUFRcEUsRUFBRTJCLFlBQWExQixFQUFTb0UsVUFHakN1QixlQUFpQixXQUNoQixJQUFJbkMsRUFBa0J6RCxFQUFFOEIsT0FBUSxDQUMvQnVNLEtBQU8sSUFDUEMsU0FBVyxHQUNYQyxzQkFBdUIsRUFDdkI5SCxNQUFRdkcsS0FBS3VMLHFCQUF1QixrQ0FBb0MsMEJBQ3hFK0MsTUFBUXhPLEVBQUV5TyxLQUFNdk8sS0FBS3dPLFdBQVl4TyxNQUNqQ3lPLE9BQVMzTyxFQUFFeU8sS0FBTXZPLEtBQUswTyxZQUFhMU8sTUFDbkMyTyxLQUFPN08sRUFBRXlPLEtBQU12TyxLQUFLNE8sVUFBVzVPLE1BQy9CNk8sUUFBVS9PLEVBQUV5TyxLQUFNdk8sS0FBSzhPLFNBQVU5TyxNQUNqQytPLEtBQU9qUCxFQUFFeU8sS0FBTXZPLEtBQUtnUCxNQUFPaFAsT0FDekJGLEVBQUVtUCxPQUFRalAsS0FBTSxvQkFFbkJBLEtBQUtvRSxJQUFNcEUsS0FBS29FLElBQUlkLFNBQVVDLElBSS9CaUwsV0FBYSxTQUFVVSxFQUFPQyxHQUM3QixJQUFJQyxFQUFtQnBQLEtBQUt5QyxXQUFXZ0UsSUFBSzBJLEVBQUczSSxLQUFLakMsS0FBTSxtQkFDdER2RSxLQUFLa0UsOEJBQ1JsRSxLQUFLNkgsTUFBTyxZQUFhLENBQUV1SCxpQkFBbUJBLElBQzFDcFAsS0FBSytILFFBQVMsWUFBYXFILElBR2pDVixZQUFjLFNBQVVRLEVBQU9DLEdBQzlCLElBQUlDLEVBQW1CcFAsS0FBS3lDLFdBQVdnRSxJQUFLMEksRUFBRzNJLEtBQUtqQyxLQUFNLG1CQUV0RHZFLEtBQUtrRSw4QkFDUmxFLEtBQUs2SCxNQUFPLGFBQWMsQ0FBRXVILGlCQUFtQkEsSUFDM0NwUCxLQUFLK0gsUUFBUyxhQUFjcUgsSUFHbENSLFVBQVksU0FBVU0sRUFBT0MsR0FDNUIsSUFBSUMsRUFBbUJwUCxLQUFLeUMsV0FBV2dFLElBQUswSSxFQUFHM0ksS0FBS2pDLEtBQU0sbUJBRXREOEssRUFEdUJyUCxLQUFLdUksa0JBQ0lnQyxXQUFXeE0sTUFBT29SLEVBQUczSSxPQUV4QyxHQUFiNkksR0FBa0JELEdBR3JCcFAsS0FBS3lDLFdBQVdvRCxPQUFRdUosR0FHbkJBLElBRU5wUCxLQUFLZ04sZ0NBQ0xoTixLQUFLZ0ksMEJBRURoSSxLQUFLa0UsOEJBQ1JsRSxLQUFLNkgsTUFBTyxXQUFZLENBQUV1SCxpQkFBbUJBLEVBQWtCQyxTQUFXQSxJQUN0RXJQLEtBQUsrSCxRQUFTLFdBQVlxSCxFQUFrQkMsS0FHbERQLFNBQVcsU0FBVUksRUFBT0MsR0FFM0IsSUFDSUcsRUFEZUgsRUFBR0ksT0FDc0JsTCxLQUFNLFFBQ2xELEdBQU1pTCxHQUE4QkEsRUFBeUI3TSxXQUE3RCxDQUVBLElBQUk0TSxFQUFXclAsS0FBS3VJLGtCQUFrQmdDLFdBQVd4TSxNQUFPb1IsRUFBRzNJLE1BQ3ZEZ0osRUFBZ0JGLEVBQXlCN00sV0FBV2dFLElBQUswSSxFQUFHM0ksS0FBS2pDLEtBQU0sbUJBQzNFK0ssRUFBeUI3TSxXQUFXb0QsT0FBUTJKLEdBQzVDeFAsS0FBS3lDLFdBQVdxQixJQUFLMEwsRUFBZSxDQUFFQyxHQUFLSixJQUMzQ0csRUFBYy9NLFdBQWF6QyxLQUFLeUMsV0FDaEN6QyxLQUFLc0YsaUJBQWtCa0ssS0FHeEJSLE1BQVEsU0FBVUUsRUFBT0MsR0FHeEJuUCxLQUFLdUksa0JBQWtCd0IsS0FBTSw0QkFBNkJXLFFBRzNEZ0YsV0FBYSxTQUFVUixHQUN0QixJQUFNbFAsS0FBS3FELGlCQUFtQixPQUFPLEVBRXJDLElBQUlzTSxHQUFPLEVBRVgsR0FBMEQsR0FBdEQzUCxLQUFLcUcsa0JBQW1CLENBQUVkLEdBQUssV0FBYTlJLE9BQ2hELENBSUMsSUFBSW1ULEVBQWdCNVAsS0FBS29HLGlCQUFrQixDQUFFYixHQUFLLFdBQzlDMkosRUFBTVcsUUFBVTdQLEtBQUtnTyxXQUFXQyxTQUE2QixJQUFsQjJCLEdBRTlDNVAsS0FBS3NGLGlCQUFrQnNLLEVBQWdCLEVBQUcsQ0FBRXJLLEdBQUssV0FDakRvSyxHQUFPLEdBRUNULEVBQU1XLFFBQVU3UCxLQUFLZ08sV0FBV0UsV0FBYTBCLElBQWtCNVAsS0FBS3lDLFdBQVdoRyxPQUFTLElBRWhHdUQsS0FBS3NGLGlCQUFrQnNLLEVBQWdCLEVBQUcsQ0FBRXJLLEdBQUssV0FDakRvSyxHQUFPLEdBSVQsT0FBU0EsR0FHVkcsc0JBQXdCLFNBQVVwRSxHQUNqQyxJQUFJQyxFQUFnQjNMLEtBQUt5TCxrQkFBbUJDLEdBRTVDLEdBQUlDLEVBQWdCLENBQ25CLElBQUlvRSxFQUFlL1AsS0FBS3lDLFdBQVdnRSxJQUFLa0YsR0FDeEMsR0FBSTNMLEtBQUtrRSw4QkFBZ0MsQ0FDeEMsSUFBSUcsRUFBTyxDQUNWMEwsYUFBZUEsRUFDZkMsZUFBaUJ0RSxFQUFTdUUsU0FBV3ZFLEVBQVN3RSxTQUcvQ3BRLEVBQUVlLEtBQU0sQ0FBRSxpQkFBa0Isa0JBQW1CLDRCQUE4QixTQUFVc1AsR0FDdEY5TCxFQUFNOEwsR0FBZSxXQUNwQnpFLEVBQVV5RSxRQUlablEsS0FBSzZILE1BQU8sUUFBU3hELFFBRWpCckUsS0FBSytILFFBQVMsUUFBU2dJLEdBRzdCLEdBQU0vUCxLQUFLOEMsWUFBZ0I5QyxLQUFLK0MsY0FFaEMsR0FBSTRJLEVBQ0osQ0FFQyxHQUFJN0wsRUFBRXdCLFdBQVl0QixLQUFLZ0QsMEJBQ3BCaEQsS0FBS2dELHVCQUF1QjFILEtBQU0wRSxLQUFNQSxLQUFLeUMsV0FBV2dFLElBQUtrRixJQUUvRCxPQUlELEdBQUkzTCxLQUFLbUQsZ0JBQWtCdUksRUFBUzBFLFNBQ3BDLENBQ0MsSUFBSUMsR0FBMEIsRUFFRSxFQUE1QnJRLEtBQUt3RSxjQUFjL0gsUUFFdEJ1RCxLQUFLeUMsV0FBV3NILEtBQU0sU0FBVXVHLEdBSS9CLE9BSEFELElBR092USxFQUFFZ0csU0FBVTlGLEtBQUt3RSxjQUFlOEwsRUFBY3BKLE1BQ25EbEgsTUFHSixJQUFJdVEsR0FBb0IsRUFDeEJ2USxLQUFLeUMsV0FBV3NILEtBQU0sU0FBVXVHLEdBSS9CLE9BSEFDLElBR09ELEVBQWNwSixLQUFPeUUsR0FDMUIzTCxNQU9ILElBTEEsSUFBSXdRLEdBQTJELEdBQTNCSCxFQUErQkUsRUFBbUJGLEVBQ2xGSSxFQUF1QkMsS0FBS0MsSUFBS0osRUFBa0JDLEdBQ25ESSxFQUF1QkYsS0FBS0csSUFBS04sRUFBa0JDLEdBRW5EMUosRUFBbUIsR0FDZGdLLEVBQVlMLEVBQXNCSyxHQUFhRixFQUFzQkUsSUFDN0VoSyxFQUFpQnhKLEtBQU0wQyxLQUFLeUMsV0FBV2dOLEdBQUlxQixHQUFZNUosS0FLeEQsR0FKQWxILEtBQUt3RixrQkFBbUJzQixFQUFrQixDQUFFdkIsR0FBSyxRQUk3Q3NELFNBQVNrSSxXQUFhbEksU0FBU2tJLFVBQVVuSSxNQUM1Q0MsU0FBU2tJLFVBQVVuSSxhQUNmLEdBQUdvSSxPQUFPQyxhQUFjLENBQzVCLElBQUlDLEVBQU1GLE9BQU9DLGVBQ2JDLEdBQU9BLEVBQUlDLGlCQUNkRCxFQUFJQyx3QkFHSW5SLEtBQUttRCxnQkFBa0JyRCxFQUFFZ0csU0FBVTlGLEtBQUt3RSxjQUFlbUgsTUFBdUIzTCxLQUFLb0QsZUFBaUJzSSxFQUFTd0UsU0FBV3hFLEVBQVN1RSxTQUV2SW5RLEVBQUVnRyxTQUFVOUYsS0FBS3dFLGNBQWVtSCxHQUNuQzNMLEtBQUt3RixrQkFBbUIxRixFQUFFK00sUUFBUzdNLEtBQUt3RSxjQUFlbUgsR0FBaUIsQ0FBRXBHLEdBQUssUUFDM0V2RixLQUFLd0Ysa0JBQW1CMUYsRUFBRXNSLE1BQU9wUixLQUFLd0UsY0FBZSxDQUFDbUgsSUFBa0IsQ0FBRXBHLEdBQUssUUFHcEZ2RixLQUFLd0Ysa0JBQW1CLENBQUVtRyxHQUFpQixDQUFFcEcsR0FBSyxhQUluRHZGLEtBQUt3RixrQkFBbUIsS0FJMUI2TCx3QkFBMEIsU0FBVTNGLEdBRW5DLElBQUlDLEVBQWdCM0wsS0FBS3lMLGtCQUFtQkMsR0FFNUMsR0FBSUMsRUFDSixDQUNDLElBQUlvRSxFQUFlL1AsS0FBS3lDLFdBQVdnRSxJQUFLa0YsR0FFcEMzTCxLQUFLa0UsOEJBQ1JsRSxLQUFLNkgsTUFBTyxjQUFlLENBQUVrSSxhQUFlQSxFQUFjQyxlQUFpQnRFLEVBQVN1RSxTQUFXdkUsRUFBU3dFLFVBQ3BHbFEsS0FBSytILFFBQVMsY0FBZWdJLEtBSXBDdUIsd0JBQTBCLFNBQVU1RixHQUM3QjFMLEtBQUs4QyxZQUFnQjlDLEtBQUsrQyxlQUMxQnBKLEVBQUcrUixFQUFTNkYsUUFBUzNLLEdBQUkscUJBRS9CNUcsS0FBS3dGLGtCQUFtQixNQUd2QixDQUNGZ00sK0JBQWlDLFNBQVVDLEdBQzFDeFIsRUFBK0J3UixLQVdqQzFSLEVBQVM4RCxZQUFjLEdBRXZCOUQsRUFBUzhELFlBQVlDLElBQU0sU0FBVThCLEVBQU04TCxHQUN0QzVSLEVBQUUyQixZQUFhaVEsS0FBZ0NBLEVBQThCLFdBSWpGOUwsRUFBSzdCLFdBQWEsU0FBVUgsR0FDM0IsSUFBSW9CLEVBQVFoRixLQUNSMlIsRUFBeUIsR0FDekJDLEVBQXVDLEdBRXZDbFIsRUFBcUJaLEVBQUVtUCxPQUFRalAsS0FBTTBSLEdBRXpDLElBQU01UixFQUFFMkIsWUFBYWYsR0FBdUIsQ0FDM0MsSUFBSUMsRUFBK0JGLEVBQThCQyxHQUVqRVosRUFBRWUsS0FBTUYsRUFBOEIsU0FBVWtSLEVBQXNCOVEsR0FDckUsSUFBSUMsRUFBcUI2USxFQUFxQnJRLFNBQzFDUCxFQUF5QjRRLEVBQXFCblEsYUFFbEQsR0FBSVYsRUFBcUIsQ0FJeEIsS0FBUTRDLElBQWE5RCxFQUFFZ0csU0FBVWhHLEVBQUV1QixLQUFNdUMsR0FBVzdDLEtBQXNCakIsRUFBRTJCLFlBQWF1RCxFQUFPakUsSUFDL0YsTUFBTSxJQUFJbkQsTUFBTyxvQkFBdUJtRCxFQUFpQix1QkFFMUQsR0FBSTZDLEdBQVc5RCxFQUFFZ0csU0FBVWhHLEVBQUV1QixLQUFNdUMsR0FBVzdDLElBQW9CakIsRUFBRTJCLFlBQWFtQyxFQUFTN0MsSUFDekYsTUFBTSxJQUFJbkQsTUFBTyxvQkFBdUJtRCxFQUFpQixrQ0FJM0QsR0FBSTZDLEdBQVc3QyxLQUFrQjZDLElBQWE5RCxFQUFFMkIsWUFBYW1DLEVBQVM3QyxJQUFxQixDQUMxRixJQUFJK1EsRUFBVzlNLEVBQU9qRSxHQUNsQmdSLEVBQVduTyxFQUFTN0MsR0FHbEJqQixFQUFFMkIsWUFBYXFRLElBQWNBLElBQWFDLElBQy9DSCxFQUFzQzdRLEdBQW1CK1EsRUFDekRILEVBQXdCNVEsR0FBbUJnUixHQUU1Qy9NLEVBQU9qRSxHQUFtQmdSLE9BSWxCalMsRUFBRTJCLFlBQWF1RCxFQUFPakUsTUFFOUJpRSxFQUFPakUsR0FBbUJFLEtBS2lCLEVBQTFDbkIsRUFBRXVCLEtBQU1zUSxHQUF5QmxWLFNBQ2hDcUQsRUFBRXdCLFdBQVkwRCxFQUFNZ04sa0JBQ3ZCaE4sRUFBTWdOLGlCQUFrQkwsRUFBd0JDLEdBQ3hDOVIsRUFBRXdCLFdBQVkwRCxFQUFNSCxvQkFDNUJHLEVBQU1ILGtCQUFtQjhNLEVBQXdCQyxLQUlwRGhNLEVBQUtxTSxXQUFhLFdBQ2pCLElBQUl2UixFQUFxQlosRUFBRW1QLE9BQVFqUCxLQUFNMFIsR0FDekMsR0FBSTVSLEVBQUUyQixZQUFhZixHQUF1QixNQUFPLEdBRWpELElBQUlDLEVBQStCRixFQUE4QkMsR0FDN0R3UixFQUFlcFMsRUFBRXVCLEtBQU1WLEdBRTNCLE9BQU9iLEVBQUVxUyxLQUFNblMsS0FBTWtTLEtBNER2QnROLG1CQUFxQixTQUFVN0UsRUFBVUQsR0FLeEMsSUFBSXNTLEVBQVksU0FBU0MsR0FDeEJyUyxLQUFLc1MsT0FBUyxHQUNkdFMsS0FBS3VTLGNBQWdCLEdBQ3JCdlMsS0FBS3dTLGVBQWlCLEdBQ3RCeFMsS0FBS3lTLGdCQUVMM1MsRUFBRWUsS0FBS3dSLEVBQU9yUyxLQUFLOEQsSUFBSzlELE9BTXpCRixFQUFFOEIsT0FBT3dRLEVBQVV0WCxVQUFXLENBTTdCZ0osSUFBSyxTQUFTOEIsRUFBTThNLEdBQ25CLElBQUlDLEVBQVUvTSxFQUFLc0IsS0FHbkJsSCxLQUFLc1MsT0FBT0ssR0FBVy9NLEdBR2R3QixRQUNScEgsS0FBS3VTLGNBQWMzTSxFQUFLd0IsTUFBTUYsS0FBT3lMLEdBSWxDRCxJQUNIMVMsS0FBS3dTLGVBQWVFLEdBQWVDLEdBR3BDM1MsS0FBS3lTLGlCQUtONUwsWUFBYSxTQUFTTyxHQUNyQixPQUFPcEgsS0FBSytJLGVBQWUzQixFQUFNRixNQU1sQzZCLGVBQWdCLFNBQVM2SixHQUN4QixJQUFJRCxFQUFVM1MsS0FBS3VTLGNBQWNLLEdBQ2pDLE9BQU81UyxLQUFLNlMsVUFBVUYsSUFJdkJHLGFBQWMsU0FBUy9VLEdBQ3RCLElBQUk0VSxFQUFVM1MsS0FBS3dTLGVBQWV6VSxHQUNsQyxPQUFPaUMsS0FBSzZTLFVBQVVGLElBS3ZCSSxZQUFhLFNBQVNoVixHQUNyQixPQUFPK0IsRUFBRWtULE9BQU9oVCxLQUFLc1MsUUFBUXZVLElBSTlCOFUsVUFBVyxTQUFTM0wsR0FDbkIsT0FBT2xILEtBQUtzUyxPQUFPcEwsSUFHcEIrTCxlQUFpQixTQUFVL0wsR0FDMUIsSUFBSW5KLEdBQVMsRUFNYixPQUxXK0IsRUFBRWlLLEtBQU0vSixLQUFLc1MsT0FBUSxTQUFXMU0sR0FFMUMsR0FEQTdILElBQ0k2SCxFQUFLd0IsTUFBTUYsS0FBT0EsRUFDckIsT0FBT3RCLElBRVM3SCxHQUFTLEdBSTVCOEgsT0FBUSxTQUFTRCxHQUNoQixJQUFJK00sRUFBVS9NLEVBQUtzQixJQUdmdEIsRUFBS3dCLGNBQ0RwSCxLQUFLdVMsY0FBYzNNLEVBQUt3QixNQUFNRixLQUl0Q3BILEVBQUVvVCxJQUFJbFQsS0FBS3dTLGVBQWdCLFNBQVN0TCxFQUFLaU0sR0FDeEMsR0FBSWpNLElBQVF5TCxFQUVYLGNBRE8zUyxLQUFLd1MsZUFBZVcsSUFDcEIsR0FFTm5ULGFBR0lBLEtBQUtzUyxPQUFPSyxHQUduQjNTLEtBQUt5UyxpQkFNTm5YLEtBQU0sU0FBUzhYLEdBQ2RwVCxLQUFLekMsTUFBTTZWLEVBQVF0VCxFQUFFdVQsS0FBS2hXLGFBTTNCRSxNQUFPLFNBQVM2VixFQUFRaFcsR0FDdkIwQyxFQUFFZSxLQUFLYixLQUFLc1MsT0FBUSxTQUFTMU0sR0FDeEI5RixFQUFFd0IsV0FBV3NFLEVBQUt3TixLQUNyQnhOLEVBQUt3TixHQUFRN1YsTUFBTXFJLEVBQU14SSxHQUFRLE9BTXBDcVYsY0FBZSxXQUNkelMsS0FBS3ZELE9BQVNxRCxFQUFFd1QsS0FBS3RULEtBQUtzUyxXQXVCNUIsT0FUQXhTLEVBQUVlLEtBTFksQ0FBQyxVQUFXLE9BQVEsTUFBTyxPQUFRLFNBQVUsU0FDbkQsU0FBVSxTQUFVLFFBQVMsTUFBTyxPQUFRLE1BQU8sVUFDbkQsV0FBWSxTQUFVLFVBQVcsUUFBUyxVQUFXLE9BQ3JELE9BQVEsVUFBVyxVQUFXLFNBRXRCLFNBQVN1UyxHQUN4QmhCLEVBQVV0WCxVQUFVc1ksR0FBVSxXQUM3QixJQUNJaFcsRUFBTyxDQURDMEMsRUFBRWtULE9BQU9oVCxLQUFLc1MsU0FDUHhWLE9BQU9nRCxFQUFFeVQsUUFBUWxXLFlBQ3BDLE9BQU95QyxFQUFFc1QsR0FBUTdWLE1BQU11QyxFQUFHMUMsTUFLckJnVixFQXRKYSxDQXVKbEJyUyxFQUFVRCxHQUVOQyxFQUFTNEIsZ0JBajJDTyxtQkFBWDdILEdBQXlCQSxFQUFPOEYsSUFFM0M5RixFQUFRLGlDQUFpQyxDQUFFLGFBQWMsV0FBWSxVQUFZRSxHQUNuRCxvQkFBWjJFLFFBRWxCRSxPQUFPRixRQUFVM0UsRUFBU0gsRUFBUSxjQUFnQkEsRUFBUyxZQUFjQSxFQUFTLFlBQWFGLEdBRy9GSyxFQUFTRCxFQUFLK0YsRUFBRy9GLEVBQUtnRyxTQUFZaEcsRUFBSzhGLFFBQVU5RixFQUFLeVosT0FBU3paLEVBQUtKLEdBdTJDakVNLEVBQWdCLEdBbUJoQkMsRUFBWSxTQUFTdVosR0FDeEIsSUFBSUMsRUFBUXRXLEVBQU8wQyxFQUFFNlQsS0FBS3RXLFdBVzFCLE9BSkF5QyxFQUFFZSxLQUFLNUcsRUFBZSxTQUFTbU4sR0FKVCxJQUFTQSxFQUFPd00sR0FLaENGLElBTGdDRSxHQUFQeE0sRUFLQ0EsR0FBYXlNLGVBQWVKLEdBSnZEM1QsRUFBRWdVLFVBQVVGLEdBQVlBLEdBQ3BCOVQsRUFBRW9CLFNBQVMwUyxHQUFNeE0sRUFBTXdNLEdBQU1BLEdBQUlyVyxNQUFNNkosRUFBT2hLLE1BSXJEc1csRUFBU3RNLEVBQU15TSxlQUFlSCxVQUV6QkEsR0FNUjNULFNBQVNnVSxRQUFRalosVUFBVWtaLFNBQVdsVSxFQUFFbVUsS0FBS2xVLFNBQVNnVSxRQUFRalosVUFBVWtaLFNBQVUsU0FBU0UsRUFBUUMsRUFBVXZRLEdBQzVHLElBQUk4UCxFQUFTeFosRUFBVSxxQkFBc0JpYSxFQUFVdlEsR0FDbkQ4UCxFQUNDVSxRQUFRVixFQUFTLG1EQUNwQlEsRUFBTzVZLEtBQUswRSxLQUFNbVUsRUFBVXZRLEdBRzdCc1EsRUFBTzVZLEtBQUswRSxLQUFNbVUsRUFBVXZRLEtBTTlCb04sT0FBT3FELGVBQWlCLFNBQVN6VixHQUNoQyxPQUFPMUUsRUFBVSxxQkFBc0IwRSxJQU14Q2tCLEVBQUU4QixPQUFPN0IsU0FBU3VVLE1BQU14WixVQUFXLENBRWxDeVosUUFBUyxHQUNUQyxrQkFBa0IsRUFDbEJDLGVBQWdCLEdBQ2hCQyxnQkFBaUIsR0FJakJDLGNBQWUsV0FTZCxPQVJBM1UsS0FBSzZULGVBQWlCL1QsRUFBRThCLE9BQU8sR0FBSSxDQUNsQzhSLE9BQVEsNEJBQ1JrQixvQkFBb0IsRUFDcEJDLG9CQUFvQixHQUNsQjdVLEtBQUt1VSxTQUFXLElBQ25CdlUsS0FBS3dVLGtCQUFtQixFQUN4QnhVLEtBQUs4VSxpQkFDTDlVLEtBQUsrVSx5QkFDRS9VLE1BS1JnVixhQUFjLFdBS2IsT0FKQWhWLEtBQUt3VSxrQkFBbUIsRUFDeEJ4VSxLQUFLeVUsZUFBaUIsR0FDdEJ6VSxLQUFLMFUsZ0JBQWtCLEdBQ3ZCMVUsS0FBSytVLHlCQUNFL1UsTUFLUmlWLGdCQUFpQixXQUdoQixPQUZBalYsS0FBSzhVLGlCQUNMOVUsS0FBSytVLHlCQUNFL1UsTUFNUmtWLGdCQUFpQixXQUNoQixHQUFLbFYsS0FBS3dVLGlCQUlWLE9BSEF4VSxLQUFLbVYsV0FBYW5WLEtBQUt5VSxlQUN2QnpVLEtBQUs4VSxpQkFDTDlVLEtBQUsrVSx5QkFDRS9VLE1BU1JvVixrQkFBbUIsU0FBU0MsR0FDM0IsSUFBS0EsRUFBTyxPQUFPdlYsRUFBRXdWLFFBQVF0VixLQUFLMFUsa0JBQTJCNVUsRUFBRXlCLE1BQU12QixLQUFLMFUsaUJBQzFFLElBQUlhLEVBQUtDLEdBQVUsRUFBT0MsRUFBTXpWLEtBQUswVSxnQkFDckMsSUFBSyxJQUFJblEsS0FBUThRLEVBQ1p2VixFQUFFNFYsUUFBUUQsRUFBSWxSLEdBQVFnUixFQUFNRixFQUFNOVEsT0FDckNpUixJQUFZQSxFQUFVLEtBQUtqUixHQUFRZ1IsR0FFckMsT0FBT0MsR0FHUlYsZUFBZ0IsV0FDZjlVLEtBQUt5VSxlQUFpQjNVLEVBQUV5QixNQUFNdkIsS0FBS21WLFlBQ25DblYsS0FBSzBVLGdCQUFrQixJQU14QkssdUJBQXdCLFdBL0hDLElBQVMzTixFQWdJakNwSCxLQUFLK0gsUUFBUSxrQkFBbUJqSSxFQUFFd1YsUUFBUXRWLEtBQUswVSxpQkFBa0I1VSxFQUFFeUIsTUFBTXZCLEtBQUswVSxrQkFDMUUxVSxLQUFLdVUsVUFqSXdCbk4sRUFpSUtwSCxLQWhJbENGLEVBQUV3VixRQUFRbE8sRUFBTXNOLGlCQUdwQnphLEVBQWdCNkYsRUFBRXlNLE9BQU90UyxFQUFlLFNBQVMwYixHQUFLLE9BQU92TyxFQUFNRixLQUFPeU8sRUFBRXpPLE1BRnZFcEgsRUFBRThWLFVBQVUzYixFQUFlLENBQUNpTixJQUFJRSxFQUFNRixPQUFPak4sRUFBY3FELEtBQUs4SixPQXFJdkVySCxTQUFTdVUsTUFBTXhaLFVBQVUrYSxJQUFNL1YsRUFBRW1VLEtBQUtsVSxTQUFTdVUsTUFBTXhaLFVBQVUrYSxJQUFLLFNBQVNDLEVBQVEzQyxFQUFLb0MsRUFBSzNSLEdBQzlGLElBQUl5UixFQUFPbFcsRUFDWCxPQUFXLE1BQVBnVSxFQUFvQm5ULE1BRUwsaUJBQVJtVCxHQUNWa0MsRUFBUWxDLEVBQ1J2UCxFQUFVMlIsSUFFVEYsRUFBUSxJQUFJbEMsR0FBT29DLEVBRXJCM1IsSUFBWUEsRUFBVSxJQUd0QnpFLEVBQU0yVyxFQUFPeGEsS0FBSzBFLEtBQU1xVixFQUFPelIsR0FFM0I1RCxLQUFLd1UsbUJBQXFCNVEsRUFBUW1ELFNBQ3JDakgsRUFBRWUsS0FBS3dVLEVBQU92VixFQUFFeU8sS0FBSyxTQUFTZ0gsRUFBS3BDLEdBQzlCclQsRUFBRTRWLFFBQVExVixLQUFLeVUsZUFBZXRCLEdBQU1vQyxVQUNoQ3ZWLEtBQUswVSxnQkFBZ0J2QixHQUU1Qm5ULEtBQUswVSxnQkFBZ0J2QixHQUFPb0MsR0FDM0J2VixPQUNIQSxLQUFLK1UsMEJBRUM1VixLQUtSWSxTQUFTZ1csS0FBT2pXLEVBQUVtVSxLQUFLbFUsU0FBU2dXLEtBQU0sU0FBU0MsRUFBUzVDLEVBQVFoTSxFQUFPeEQsR0FjdEUsT0FiQUEsSUFBWUEsRUFBVSxJQUVSLFVBQVZ3UCxJQUNIeFAsRUFBUXFTLFFBQVVuVyxFQUFFbVUsS0FBS3JRLEVBQVFxUyxRQUFTblcsRUFBRXlPLEtBQUssU0FBUzJILEVBQVk3UixFQUFNOFIsRUFBWUMsR0FDdkYsSUFBSWpYLEVBTUosT0FMSStXLElBQVkvVyxFQUFNK1csRUFBVzVhLEtBQUswRSxLQUFNcUUsRUFBTThSLEVBQVlDLElBQzFEaFAsRUFBTW9OLG1CQUNUcE4sRUFBTTBOLGlCQUNOMU4sRUFBTTJOLDBCQUVBNVYsR0FDTGEsUUFFR2dXLEVBQVE1QyxFQUFRaE0sRUFBT3hELEtBSWhDOUosRUFBTywwQkFBMkIsY0FPbENBLEVBQVEsZUFBZSxHQUFJLFdBRTFCLE9BQU9pRyxTQUFTdVUsTUFBTTFTLE9BQVEsQ0FFN0J5VSxTQUFVLENBQ1RDLFFBQVMsS0FDVHhYLEdBQUksR0FDSndVLEtBQU0sT0FDTmlELElBQUssSUFHTjVTLFdBQVksV0FDWDNELEtBQUsyVSxxQkFXUjdhLEVBQVEsd0JBQXdCLEdBQUksV0FFbkMsTUFBTyxDQU1OMGMsc0JBQXVCLENBQ3RCM00sT0FBUSxHQUNSVSxTQUFVLElBUVhrTSxjQUFlLEdBUWZDLG1CQUFvQixTQUFVOVMsR0FFN0IsSUFBSStTLEVBQU8zVyxLQUFLNFcsb0JBSVhELEVBQUs5TSxRQUFVakcsR0FBV0EsRUFBUWlHLFFBQ3RDN0osS0FBSzZXLFdBQVlqVCxFQUFRaUcsUUFJMUIvSixFQUFFZSxLQUFNOFYsRUFBS3BNLFNBQVUsU0FBVXVNLEVBQVlDLEdBRTVDLElBQU9ELEVBQVdFLGNBQWUsSUFBU0YsRUFBV0UsWUFBYWhYLE1BQVMsQ0FFMUUsSUFDQ2lYLEVBREdDLEVBQVlsWCxLQUFLeUcsSUFBS3NRLEdBR3JCRCxFQUFXSyxPQUNmRixFQUFRSCxFQUFXSyxPQUFRRCxHQUNoQixVQUFZSixFQUFXTSxLQUNsQ0gsRUFBUWpHLE9BQU9xRyxhQUFhQyxVQUFVQyxVQUFXVCxFQUFXVSxNQUFPTixHQUN4RCxlQUFpQkosRUFBV00sT0FDdkNILEVBQVFqRyxPQUFPcUcsYUFBYUMsVUFBVUcsZUFBZ0JYLEVBQVdVLE1BQU9OLElBR3pFbFgsS0FBSzZWLElBQUtrQixFQUFXRSxHQUdoQixVQUFZSCxFQUFXTSxLQUMzQnBYLEtBQUswWCw0QkFBNkJULEdBR3ZCLGVBQWlCSCxFQUFXTSxPQUV2Q0gsRUFBTXBOLE9BQVM3SixLQUNmaVgsRUFBTXBXLEtBQU0sU0FBVThXLEdBRXJCM1gsS0FBSzBYLDRCQUE2QkMsSUFFaEMzWCxTQU1IQSxPQVVKNFgsZ0JBQWlCLFdBRWhCLElBQUlDLEVBQVEsR0FVWixPQVJBL1gsRUFBRWUsS0FBTWIsS0FBSzRXLG9CQUFvQnJNLFNBQVUsU0FBVWxHLEVBQU04TyxHQUVuRDlPLEVBQUsyUyxjQUFlLElBQVMzUyxFQUFLMlMsWUFBYWhYLE9BQ3JENlgsRUFBTXZhLEtBQU02VixJQUdYblQsTUFFSTZYLEdBVVJDLFdBQVksV0FFWCxJQUFJbkIsRUFBTzNXLEtBQUs0VyxvQkFFaEIsUUFBS0QsRUFBSzlNLFFBQ0Y4TSxFQUFLOU0sT0FBTzFCLFdBY3JCeU8sa0JBQW1CLFdBRWxCLE9BQU9qZCxFQUFFaUksUUFBUSxFQUFNNUIsS0FBS3lXLGNBQWV6VyxLQUFLd1csd0JBV2pESyxXQUFZLFNBQVV6YixHQUNyQjRFLEtBQUt5VyxjQUFjNU0sT0FBTzFCLFVBQVkvTSxHQVV2Q3NjLDRCQUE2QixTQUFVdFEsR0FFdEMsR0FBT0EsR0FBV0EsRUFBTXdQLGtCQUF4QixDQUdBLElBQUlELEVBQU92UCxFQUFNd1Asb0JBQ1pELEVBQUs5TSxRQUFVOE0sRUFBSzlNLE9BQU96QyxRQUFVcEgsS0FBS3lHLElBQUssU0FDbkRXLEVBQU15UCxXQUFZN1csV0FjdEJsRyxFQUFRLHdCQUF3QixDQUFFLGVBQWdCLHlCQUEyQixTQUFVaWUsRUFBT0MsR0FFN0YsT0FBT2pZLFNBQVN1VSxNQUFNMVMsT0FBUTlCLEVBQUV1VyxTQUFVLENBTXpDSSxjQUFlLENBQ2Q1TSxPQUFRLENBQ1B6QyxNQUFPLGdCQUNQZ1EsS0FBTSxTQUVQN00sU0FBVSxDQUNUME4sT0FBUSxDQUNQakIsWUFBYSxTQUFVNVAsR0FDdEIsTUFBUyxVQUFZQSxFQUFNWCxJQUFLLGdCQUVqQytRLE1BQU8sUUFDUHBRLE1BQU8sUUFDUGdRLEtBQU0sV0FXVGYsU0FBVSxXQUNULE1BQU8sQ0FDTnZYLEdBQUlnQixFQUFFb1ksU0FBVSxTQUNoQkQsT0FBUSxHQUNSRSxZQUFhLE9BQ2JDLFNBQVMsRUFDVEMsT0FBUSxJQUNSQyxZQUFhLEdBQ2JsQixLQUFNLFdBWVJ6VCxXQUFZLFNBQVVVLEVBQU1ULEdBRTNCNUQsS0FBSzJVLGdCQUNMM1UsS0FBSzBXLG1CQUFvQjlTLElBVTFCa1UsV0FBWSxXQUNYLE9BQU85WCxLQUFLeUMsV0FBV29ILFFBU3hCME8sYUFBYyxXQUNiLE9BQU92WSxLQUFLeUcsSUFBSyxlQUFrQixJQUFNekcsS0FBS3lHLElBQUssT0FVcEQrUixjQUFlLFdBQ2QsT0FBT3hZLEtBQUs4WCxhQUFhclIsSUFBSyxpQkFBa0JnUywwQkFHL0NULE1BU0psZSxFQUFRLDhCQUE4QixDQUFFLHlCQUEyQixTQUFVc04sR0FFNUUsT0FBT3JILFNBQVNpRSxXQUFXcEMsT0FBUSxDQU1sQ3dGLE1BQU9BLEVBRVB6RCxXQUFZLFdBR1gzRCxLQUFLMFksR0FBSSxVQUFXMVksS0FBSzJZLGNBR3pCM1ksS0FBSzBZLEdBQUksTUFBTzFZLEtBQUsyWSxjQUNyQjNZLEtBQUswWSxHQUFJLFNBQVUxWSxLQUFLMlksY0FHeEIzWSxLQUFLMFksR0FBSSxNQUFPMVksS0FBSzRZLGdCQUNyQjVZLEtBQUswWSxHQUFJLFNBQVUxWSxLQUFLNFksZ0JBR3hCNVksS0FBSzBZLEdBQUksaUJBQWtCMVksS0FBSzRZLGlCQVVqQ0MsY0FBZSxXQUVkLE9BQU8vWSxFQUFFd1QsS0FBTXRULEtBQUs4WSxnQkFVckJBLFlBQWEsV0FDWixPQUFPOVksS0FBS3VNLE9BQVEsU0FBVTBMLEdBQzdCLE9BQU9BLEVBQU94UixJQUFLLGNBV3JCbVMsZUFBZ0IsU0FBVVgsR0FFekIsR0FBT2pZLEtBQUs2SixPQUFPcEQsSUFBSyxpQkFBa0JnUyx3QkFBMUMsQ0FJQSxJQUFJTSxFQUFXL1ksS0FBSzZNLFFBQVNvTCxHQUM1QmUsRUFBV2haLEtBQUs2SixPQVdqQixHQVJLLE9BQVNtUCxFQUFTdlMsSUFBSyxrQkFDM0IzRyxFQUFFZSxLQUFNa1ksRUFBVSxTQUFVM1IsR0FDM0JBLEVBQU15TyxJQUFLLFdBQVcsS0FNbkIsSUFBTTdWLEtBQUs2WSxpQkFBOEMsRUFBM0JHLEVBQVN2UyxJQUFLLFVBQWlCLENBQ2pFLElBQUk0RixFQUFTLElBQU1yTSxLQUFLc1QsT0FBU3RULEtBQUtxTSxPQUFTME0sRUFDL0NqWixFQUFFc0IsTUFBT2lMLEdBQVN3SixJQUFLLFdBQVcsTUFXcEM4QyxhQUFjLFdBRWIsSUFBSU0sRUFBT2paLEtBQ1ZnWixFQUFXaFosS0FBSzZKLE9BRWpCN0osS0FBS2EsS0FBTSxTQUFVb1gsR0FDcEJBLEVBQU9wQyxJQUFLLFNBQVVtRCxFQUFTdlMsSUFBSyxpQkFBa0J5UyxxQkFBc0JELEVBQUtqYixRQUFTaWEsWUFjOUZuZSxFQUFRLHNCQUFzQixHQUFJLFdBRWpDLE9BQU9pRyxTQUFTdVUsTUFBTTFTLE9BQVEsQ0FRN0J5VSxTQUFVLFdBQ1QsTUFBTyxDQUNOOEMsU0FBUyxFQUNUQyxnQkFBZ0IsRUFDaEJDLGdCQUFpQixHQUNqQkMsYUFBYSxFQUNiQyxLQUFNLFdBQ056YSxHQUFJLFVBQ0owYSxPQUFPLEVBQ1BDLFNBQVUsR0FDVmplLEtBQU0sVUFDTmtlLFlBQWEsR0FDYkMsUUFBUSxFQUNSQyxPQUFPLElBV1RDLGFBQWMsV0FFYixJQUFJcmUsRUFBT3dFLEtBQUt5RyxJQUFLLFFBR3JCLE1BRlMsQ0FBRWpMLEdBRUVzQixPQUFRa0QsS0FBS3lHLElBQUssYUFBZTNKLE9BQVF0QixFQUFLYyxNQUFPLE9BVW5FNGMsbUJBQW9CLFdBRW5CLE9BQU9sWixLQUFLOFosbUJBQW9CLFlBVWpDckIsc0JBQXVCLFdBRXRCLE9BQU96WSxLQUFLOFosbUJBQW9CLGVBVWpDQyxnQkFBaUIsV0FFaEIsT0FBTy9aLEtBQUs4WixtQkFBb0IsU0FVakNFLGdCQUFpQixXQUVoQixPQUFPaGEsS0FBSzhaLG1CQUFvQixRQVVqQ0csZ0JBQWlCLFdBRWhCLE9BQU9qYSxLQUFLOFosbUJBQW9CLFFBVWpDSSxrQkFBbUIsV0FJbEIsUUFGY2xhLEtBQUt5RyxJQUFLLFlBTWpCekcsS0FBSzhaLG1CQUFvQixVQVlqQ0EsbUJBQW9CLFNBQVVLLEdBRTdCLElBQUloQixFQUFVblosS0FBS3lHLElBQUssV0FFeEIsU0FBTzBTLElBQWFBLEVBQVNnQixLQUl0QmhCLEVBQVNnQixRQWFuQnJnQixFQUFRLGtCQUFrQixDQUN4QixlQUNBLHdCQUNBLDhCQUNBLHNCQUNBLHlCQUNFLFNBQ0ZpZSxFQUNBcUMsRUFDQUMsRUFDQUMsRUFDQXRDLEdBR0QsT0FBT2pZLFNBQVN1VSxNQUFNMVMsT0FBUTlCLEVBQUV1VyxTQUFVLENBTXpDSSxjQUFlLENBQ2Q1TSxPQUFRLENBQ1B6QyxNQUFPLFlBQ1BnUSxLQUFNLFNBRVA3TSxTQUFVLENBQ1Q0TyxRQUFTLENBQ1IzQixNQUFPLGtCQUNQcFEsTUFBTyxTQUNQZ1EsS0FBTSxjQUVQb0MsTUFBTyxDQUNOaEMsTUFBTyxRQUNQcFEsTUFBTyxRQUNQZ1EsS0FBTSxTQUVQbUQsVUFBVyxDQUNWL0MsTUFBTyxZQUNQUixZQUFhLFNBQVU1UCxHQUN0QixJQUFJZ1EsRUFBT2hRLEVBQU1YLElBQUssaUJBRXRCLE1BQVMsV0FERTNHLEVBQUVvQixTQUFVa1csR0FBU0EsRUFBT0EsRUFBSzNRLElBQUssUUFHbERXLE1BQU8sZ0JBQ1BnUSxLQUFNLGNBRVBvRCxjQUFlLENBQ2RoRCxNQUFPLGVBQ1BMLE9BQVEsU0FBVTVCLEdBQ2pCLE9BQUt6VixFQUFFb0IsU0FBVXFVLEdBQ1R2RSxPQUFPcUcsYUFBYWtELFVBQVU5VCxJQUFLOE8sR0FFcENBLEdBRVJuTyxNQUFPLGdCQUNQZ1EsS0FBTSxXQVdUZixTQUFVLFdBQ1QsTUFBTyxDQUNOdlgsR0FBSWdCLEVBQUVvWSxTQUFVLFNBQ2hCaUIsUUFBUyxHQUNUc0IsUUFBUyxHQUNUQyxvQkFBcUIsS0FDckJsQixNQUFPLEdBQ1BtQixjQUFlLEtBQ2ZDLFdBQVksRUFDWmpCLE9BQVEsRUFDUmEsY0FBZSxVQUNmRCxVQUFXLEdBQ1hNLFVBQVcsR0FDWEMsTUFBTyxHQUNQMUQsS0FBTSxnQkFDTjJELGNBQWUsS0FDZkMsVUFBVyxHQUVYQyxXQUFXLElBWWJ0WCxXQUFZLFNBQVVVLEVBQU1ULEdBRTNCLElBQUlxVixFQUFPalosS0FFWEEsS0FBSzJVLGdCQUNMM1UsS0FBSzBXLG1CQUFvQjlTLElBRXBCLElBQVU1RCxLQUFLeUcsSUFBSyxpQkFBa0IwUyxVQUUxQ25aLEtBQUtrYixzQkFHTGxiLEtBQUtzTCxTQUFVdEwsS0FBS3lHLElBQUssV0FBYSxTQUFVLFdBRS9DaEgsV0FBWSxXQUNYd1osRUFBS2lDLHVCQUNILE1BTUVsYixLQUFLeUcsSUFBSyxpQkFBa0JBLElBQUssV0FDdkN6RyxLQUFLNlYsSUFBSyxTQUFVLEdBR3JCL1YsRUFBRXFiLE1BQU8sU0FBVWxDLEdBQ2xCQSxFQUFLUCxHQUFJLGdCQUFpQk8sRUFBS25CLGFBQWFzRCxjQUFlbkMsRUFBS25CLGVBQzlELEVBQUc5WCxPQVdQcWIsV0FBWSxTQUFVaFgsRUFBTVQsR0FFM0IsSUFBSWlOLEVBQU03USxLQUFLeUcsSUFBSyxpQkFBa0J3VCxrQkFDdEMsS0FBS2phLEtBQUt5RyxJQUFLLFdBQVk2TSxRQUFVekMsR0FBckMsQ0FLQWpOLEVBQVVBLEdBQVcsSUFEckJTLEVBQU9BLEdBQVEsSUFHVjhULFlBQWNuWSxLQUFLeUcsSUFBSyxpQkFBa0JzVCxrQkFDL0MxVixFQUFLaVUsWUFBY3RZLEtBQUt5RyxJQUFLLE1BRzdCLElBQUl3UixHQUZKclUsRUFBUWlHLE9BQVM3SixNQUVDeUcsSUFBSyxXQUFZM0MsSUFBS08sRUFBTVQsR0FFOUM3RCxTQUFTdWIsT0FBT3ZULFFBQVMsc0JBQXVCa1EsRUFBUWpZLFFBZXpEdWIsWUFBYSxTQUFVQyxFQUFNQyxHQUk1QixNQUhLLFNBQVdBLElBQ2ZELEVBQUtoQixjQUFnQnhhLEtBQUt5RyxJQUFLLGlCQUFrQkEsSUFBSyxPQUVoRCtVLEdBU1IxRCxXQUFZLFdBRVgsSUFBSW5CLEVBQU8zVyxLQUFLNFcsb0JBRWhCLEdBQUtELEVBQUs5TSxPQUFTLENBQ2xCLEdBQUs3SixLQUFLeUMsWUFBY3pDLEtBQUt5QyxXQUFXb0gsT0FDdkMsT0FBTzdKLEtBQUt5QyxXQUFXb0gsT0FDakIsR0FBSzhNLEVBQUs5TSxPQUFPMUIsVUFDdkIsT0FBT3dPLEVBQUs5TSxPQUFPMUIsVUFJckIsT0FBTyxHQVlSdVQsZUFBZ0IsV0FHZixJQUFJQyxFQUFZM2IsS0FBS3lHLElBQUssaUJBQWtCQSxJQUFLLE1BaUJqRCxPQWRZekcsS0FBS3lDLFdBQVc4SixPQUFRLFNBQVV5TSxHQUU3QyxJQUFJNUIsRUFBTzRCLEVBQVN2UyxJQUFLLGlCQUFrQkEsSUFBSyxNQUdoRCxNQUFtQixZQUFka1YsRUFDSyxZQUFjdkUsRUFJakIsWUFBY0EsSUFJTHBaLFFBQVNnQyxPQVczQjRiLGtCQUFtQixXQUVsQixJQUFJN2QsRUFBUWlDLEtBQUswYixpQkFFakIsT0FBTSxJQUFNM2QsRUFDSixHQUdILFlBQWNpQyxLQUFLeUcsSUFBSyxpQkFBa0JBLElBQUssTUFDcEMsNkJBQTZCbkssTUFBTyxJQUNsQ3lCLEdBR1hBLEVBQVEsR0FLaEI4ZCxRQUFTLFdBRVIsSUFBSWhTLEVBQVM3SixLQUFLOGIsc0JBQ2pCaGUsRUFBUyxHQVNWLE9BUEsrTCxJQUVKL0wsRUFBUytMLEVBQU9nUyxVQUFZLEtBS3RCL2QsRUFBU2tDLEtBQUs0YixxQkFVdEJFLG9CQUFxQixXQUVwQixRQUFLOWIsS0FBSytiLGVBRUYvYixLQUFLeUMsV0FBV29ILFFBY3pCbVMsZ0JBQWlCLFdBQ2hCLE9BQU9oYyxLQUFLOFgsY0FVYm1FLFdBQVksV0FFWCxPQUFPamMsS0FBS3lHLElBQUssaUJBQWtCQSxJQUFLLFVBSWpDekcsS0FBS3lHLElBQUssVUFIVCxHQWFUeVYsc0JBQXVCLFdBRXRCLElBQUlDLEVBQVFuYyxLQUFLOFgsYUFBYXJSLElBQUssV0FDbENrVCxFQUFTM1osS0FBS3lHLElBQUssVUFFcEIsT0FBSyxJQUFNMFYsRUFDSCxNQUdHeEMsRUFBU3dDLEVBQVUsS0FBTUMsUUFBUyxHQUFNLEtBVXBETCxZQUFhLFdBRVosTUFBUyxhQUFlL2IsS0FBS3lDLFdBQVdvSCxPQUFPcEQsSUFBSyxTQUlyRHlVLG9CQUFxQixXQUdwQixJQURBLElBQUkvQixFQUFVblosS0FBS3lHLElBQUssV0FDaEIwUyxFQUFRN0YsT0FBU3RULEtBQUt5RyxJQUFLLGlCQUFrQnVULG1CQUNwRGhhLEtBQUtxYixlQUtMckQsTUFTSmxlLEVBQVEsd0JBQXdCLENBQUUsbUJBQXFCLFNBQVVzTixHQUVoRSxPQUFPckgsU0FBU2lFLFdBQVdwQyxPQUFRLENBTWxDd0YsTUFBT0EsRUFRUHpELFdBQVksV0FHWDNELEtBQUswWSxHQUFJLFVBQVcxWSxLQUFLMlksY0FHekIzWSxLQUFLMFksR0FBSSxNQUFPMVksS0FBSzJZLGNBQ3JCM1ksS0FBSzBZLEdBQUksU0FBVTFZLEtBQUsyWSxjQUV4QjNZLEtBQUswWSxHQUFJLE1BQU8xWSxLQUFLcWMsZ0JBVXRCMUQsYUFBYyxXQUViLElBQUlNLEVBQU9qWixLQUVYQSxLQUFLYSxLQUFNLFNBQVVtWSxHQUVwQkEsRUFBU25ELElBQUssYUFBY29ELEVBQUtqYixRQUFTZ2IsR0FBYSxNQWN6RHFELGNBQWUsU0FBVWpWLEdBRXhCQSxFQUFNeU8sSUFBSyxZQUFhN1YsS0FBSzZKLE9BQU9wRCxJQUFLLFlBYTVDM00sRUFBUSxvQkFBb0IsR0FBSSxXQUUvQixNQUFPLENBRU53aUIsT0FBUSxHQVFSQyxtQkFBb0IsV0FFbkIsT0FBS3ZjLEtBQUt3YyxjQUNGLEdBR0R4TCxPQUFPcUcsYUFBYW9GLFVBQVksaUJBQW1CemMsS0FBS3lHLElBQUssTUFBUyxnQkFVOUVpVyxvQkFBcUIsV0FFcEIsSUFBSUMsRUFBUzNjLEtBQUsyYyxRQUFVLEdBQzVCLE9BQU8zTCxPQUFPcUcsYUFBYXVGLFFBQVFuVyxJQUFLa1csRUFBUTNjLEtBQUt5RyxJQUFLLFFBQVM3SixRQUFTLFFBQVMsSUFBTW9ELE9BVTVGd2MsWUFBYSxXQUVaLE9BQVcxYyxFQUFFK2MsU0FBVTdjLEtBQUt5RyxJQUFLLFFBQVksSUFBTXpHLEtBQUt5RyxJQUFLLE1BQU96SSxRQUFTLFVBVTlFOGUsbUJBQW9CLFdBRW5CLElBQUlDLEVBQVNqZCxFQUFFeU0sT0FBUXZNLEtBQUswYyxzQkFBdUIsU0FBVU0sR0FDNUQsT0FBU0EsRUFBYSxTQUd2QmxkLEVBQUVlLEtBQU1rYyxFQUFRLFNBQVVDLEdBQ3pCbGQsRUFBRWUsS0FBTWYsRUFBRW1kLFFBQVVELEVBQU1WLFFBQVUsU0FBVVksR0FHN0MsSUFBSTdiLEVBQU8sQ0FBRTZiLEVBQU1DLFdBQ2xCQyxFQUFVcGQsS0FBS3lHLElBQUssVUFFaEJ5VyxFQUFNRyxrQkFDVmhjLEVBQUsvRCxLQUFNNGYsRUFBTUcsa0JBR2xCdmQsRUFBRWUsS0FBTVEsRUFBTSxTQUFVOFIsR0FDdkIsSUFBSTVPLEVBQU8yWSxFQUFNSSxpQkFBbUJKLEVBQU1JLGlCQUFtQm5LLEVBQU1BLEVBQzlEaUssR0FBV0EsRUFBUzdZLElBQ3hCdkUsS0FBSzZWLElBQUsxQyxFQUFLaUssRUFBUzdZLEdBQU8sS0FFOUJ2RSxPQUVEQSxPQUNEQSxVQWFObEcsRUFBUSxlQUFlLEdBQUksV0FFMUIsTUFBTyxDQUVOeWpCLFFBQVMsQ0FDUnpDLE1BQU8wQyxLQUFLQyxLQUFLQyxVQUFXLG9CQUM1QkMsWUFBWSxFQUNackIsT0FBUSxDQUNQLENBQ0MsQ0FDQ2EsVUFBVyxZQUNYcmUsR0FBSSxZQUNKc1ksS0FBTSxjQUVMLENBQ0YsQ0FDQytGLFVBQVcsVUFDWHJlLEdBQUksY0FDSjhlLE1BQU9KLEtBQUtDLEtBQUtDLFVBQVcsZUFDNUJ0RyxLQUFNLFdBRUwsQ0FDRixDQUNDK0YsVUFBVyxrQkFDWHJlLEdBQUksa0JBQ0o4ZSxNQUFPSixLQUFLQyxLQUFLQyxVQUFXLHNCQUM1Qi9NLElBQUssRUFDTEUsSUFBSyxJQUNMZ04sSUFBS0wsS0FBS0MsS0FBS0MsVUFBVyxnRUFDMUJ0RyxLQUFNLFVBRVAsQ0FDQytGLFVBQVcsbUJBQ1hyZSxHQUFJLG1CQUNKOGUsTUFBT0osS0FBS0MsS0FBS0MsVUFBVyxrQkFDNUJMLGlCQUFrQixpQkFDbEJRLElBQUtMLEtBQUtDLEtBQUtDLFVBQVcsa0VBQzFCdEcsS0FBTSxpQkFFUCxDQUNDK0YsVUFBVyxhQUNYcmUsR0FBSSxhQUNKOGUsTUFBT0osS0FBS0MsS0FBS0MsVUFBVyxjQUM1Qi9NLElBQUssRUFDTEUsSUFBSyxJQUNMd00saUJBQWtCLGFBQ2xCUSxJQUFLTCxLQUFLQyxLQUFLQyxVQUFXLDJFQUMxQnRHLEtBQU0sa0JBRUwsQ0FDRixDQUNDK0YsVUFBVyxzQkFDWHJlLEdBQUksc0JBQ0o4ZSxNQUFPSixLQUFLQyxLQUFLQyxVQUFXLHdCQUM1QkcsSUFBS0wsS0FBS0MsS0FBS0MsVUFBVyxzR0FDMUJ0RyxLQUFNLFVBRVAsQ0FDQytGLFVBQVcsbUJBQ1hyZSxHQUFJLG1CQUNKOGUsTUFBT0osS0FBS0MsS0FBS0MsVUFBVyw0QkFDNUJHLElBQUtMLEtBQUtDLEtBQUtDLFVBQVcsb0hBQzFCdEcsS0FBTSxnQkFnQlp0ZCxFQUFRLGNBQWMsQ0FDcEIsd0JBQ0EsZ0JBQ0Esa0JBQ0Esd0JBQ0Esb0JBQ0EsZ0JBQ0UsU0FDRnNnQixFQUNBMEQsRUFDQUMsRUFDQS9GLEVBQ0FnRyxFQUNBQyxHQUdELE9BQU9sZSxTQUFTdVUsTUFBTTFTLE9BQVE5QixFQUFFdVcsU0FBVSxDQU16Q0ksY0FBZSxDQUNkNU0sT0FBUSxDQUNQekMsTUFBTyxTQUNQZ1EsS0FBTSxTQUVQN00sU0FBVSxDQUNUZ1EsVUFBVyxDQUNWL0MsTUFBTyxZQUNQcFEsTUFBTyxnQkFDUGdRLEtBQU0sZ0JBU1R1RixPQUFRc0IsRUFRUjVILFNBQVUsV0FFVCxNQUFPLENBQ052WCxHQUFJZ0IsRUFBRW9ZLFNBQVUsU0FDaEI0QyxNQUFPMEMsS0FBS0MsS0FBS0MsVUFBVyxZQUM1QnRHLEtBQU0sWUFDTjhHLFVBQVcsR0FFWEMsT0FBUSxRQUdSMUQsUUFBUyxHQUNUMkQsaUJBQWtCLEVBQ2xCQyxlQUFnQixLQUNoQkMsV0FBWSxLQUNaQyxnQkFBaUIsR0FDakIvaUIsS0FBTSxHQUNOZ2pCLGVBQWdCLEtBQ2hCQyxXQUFZLEdBQ1pDLG9CQUFxQixLQUVyQm5FLFVBQVcsR0FHWG9FLFFBQVMsRUFHVEMsVUFBVyxHQUNYQyxnQkFBZ0IsRUFDaEJDLG1CQUFtQixJQVdyQm5iLFdBQVksV0FFWDNELEtBQUs4YyxxQkFDTDljLEtBQUsyVSxnQkFDTDNVLEtBQUswVyxxQkFFTDFXLEtBQUtzTCxTQUFVdEwsS0FBS3lHLElBQUssYUFBZSxNQUFPekcsS0FBS29iLGVBQ3BEcGIsS0FBS3NMLFNBQVV0TCxLQUFLeUcsSUFBSyxhQUFlLFNBQVV6RyxLQUFLb2IsZUFFdkRwYixLQUFLNlYsSUFBSyxVQUFXN1YsS0FBSytlLG9CQUcxQi9lLEtBQUswWSxHQUFJLGdCQUFpQixXQUNwQixZQUFjMVksS0FBS3lHLElBQUssV0FDNUJ6RyxLQUFLOFgsYUFBYWpDLElBQUssZUFBZ0IsVUFhMUNtSixhQUFjLFNBQVUzYSxHQUV2QkEsRUFBS3dXLFVBQVk3YSxLQUFLeUcsSUFBSyxNQUMzQixJQUFJdVMsRUFBV2haLEtBQUt5RyxJQUFLLGFBQWMzQyxJQUFLTyxFQUFNLENBQ2pEd0YsT0FBUTdKLE9BRVRELFNBQVN1YixPQUFPdlQsUUFBUyxvQkFBcUJpUixFQUFVaFosT0FXekRpZixjQUFlLFNBQVVDLEdBRXhCLE9BQUtBLEVBQ0cxQixLQUFLQyxLQUFLQyxVQUFXLFdBR3RCRixLQUFLQyxLQUFLQyxVQUFXLFNBUzdCcUIsaUJBQWtCLFdBRWpCLElBQUlwRixFQUFTLEVBTWIsT0FKQTNaLEtBQUt5RyxJQUFLLGFBQWM1RixLQUFNLFNBQVVtWSxHQUN2Q1csR0FBVVgsRUFBU2lELGVBR2J0QyxHQVdSd0YsZUFBZ0IsU0FBVUMsR0FFekIsR0FBS3BmLEtBQUt5RyxJQUFLLHFCQUVkMlksUUFFTSxDQUVOLElBQUluRyxFQUFPalosS0FFWHdkLEtBQUs2QixLQUFLL2pCLEtBQU0sQ0FDZitJLEtBQU0sQ0FDTGliLE9BQVEsZUFDUkMsWUFBYSxZQUNiQyxVQUFXeE8sT0FBT3FHLGFBQWFvSSxZQUFZaFosSUFBSyxNQUNoRGlaLFFBQVMxZixLQUFLeUcsSUFBSyxPQUVwQmtaLE1BQU8sU0FBVUMsRUFBS3pCLEVBQVF3QixHQUU3QkUsUUFBUUMsSUFBS0YsRUFBS3pCLEVBQVF3QixHQUMxQjNPLE9BQU9xRyxhQUFhMEksTUFBTUQsSUFBSyx1Q0FBd0NGLEVBQUt6QixFQUFRd0IsRUFBTyx5Q0FDM0ZQLEdBQUksSUFHTG5KLFFBQVMsU0FBVStKLEdBQ2JBLEdBQU9BLEVBQUl6RixXQUNmdEIsRUFBS3BELElBQUsscUJBQXFCLEdBQzFCbUssRUFBSXpGLFdBQ1J6YSxFQUFFZSxLQUFNbWYsRUFBSXpGLFVBQVd0QixFQUFLK0YsYUFBYy9GLEdBRTNDbUcsS0FFQUEsR0FBSSxRQWlCVGhFLGNBQWUsV0FFZHBiLEtBQUs2VixJQUFLLFVBQVc3VixLQUFLK2Usc0JBSXpCL0csRUFBZWdHLE1BU25CbGtCLEVBQVEsaUJBQWlCLEdBQUksV0FFNUIsTUFBTyxDQUVOeWpCLFFBQVMsQ0FDUnpDLE1BQU8wQyxLQUFLQyxLQUFLQyxVQUFXLG9CQUM1QkMsWUFBWSxFQUNackIsT0FBUSxDQUNQLENBQ0MsQ0FDQ2EsVUFBVyxZQUNYcmUsR0FBSSxZQUNKc1ksS0FBTSxjQUVMLENBQ0YsQ0FDQytGLFVBQVcsY0FDWHJlLEdBQUksY0FDSjhlLE1BQU9KLEtBQUtDLEtBQUtDLFVBQVcsbUJBQzVCdEcsS0FBTSxlQUVQLENBQ0MrRixVQUFXLGNBQ1hyZSxHQUFJLGNBQ0o4ZSxNQUFPSixLQUFLQyxLQUFLQyxVQUFXLG1CQUM1QnRHLEtBQU0sZ0JBRUwsQ0FDRixDQUNDK0YsVUFBVyxjQUNYcmUsR0FBSSxjQUNKOGUsTUFBT0osS0FBS0MsS0FBS0MsVUFBVyxlQUM1QkcsSUFBS0wsS0FBS0MsS0FBS0MsVUFBVyxvREFDMUJ0RyxLQUFNLFVBRVAsQ0FDQytGLFVBQVcsd0JBQ1hyZSxHQUFJLHdCQUNKOGUsTUFBT0osS0FBS0MsS0FBS0MsVUFBVyxpQ0FDNUJHLElBQUtMLEtBQUtDLEtBQUtDLFVBQVcsMkZBQzFCdEcsS0FBTSxTQUNONkksVUFBVyxXQUNWLE1BQVMsUUFBVWpnQixLQUFLeUcsSUFBSyxrQkFHL0IsQ0FDQzBXLFVBQVcsbUNBQ1hyZSxHQUFJLG1DQUNKOGUsTUFBT0osS0FBS0MsS0FBS0MsVUFBVyx1Q0FDNUJHLElBQUtMLEtBQUtDLEtBQUtDLFVBQVcsaUdBQzFCdEcsS0FBTSxTQUNONkksVUFBVyxXQUNWLE1BQVMsY0FBZ0JqUCxPQUFPcUcsYUFBYTZJLGFBQWUsUUFBVWxnQixLQUFLeUcsSUFBSyx5QkFHaEYsQ0FDRixDQUNDMFcsVUFBVyxlQUNYOEMsVUFBVyxXQUNWLE9BQVMsSUFBVWpnQixLQUFLbWdCLHNCQUV6QnJoQixHQUFJLGVBQ0o4ZSxNQUFPSixLQUFLQyxLQUFLQyxVQUFXLGdCQUM1QkwsaUJBQWtCLG1CQUNsQmpHLEtBQU0sZ0JBQ054VCxRQUFTLFdBQ1IsT0FBTzVELEtBQUtvZ0Isa0NBR1osQ0FDRixDQUNDakQsVUFBVyxjQUNYcmUsR0FBSSxjQUNKOGUsTUFBT0osS0FBS0MsS0FBS0MsVUFBVyxlQUM1QkwsaUJBQWtCLGNBQ2xCakcsS0FBTSxTQUNOeFQsUUFBUyxXQUVSLElBQUlBLEVBQVUsQ0FDYixDQUNDdVAsSUFBSyxHQUNMb0MsSUFBS2lJLEtBQUtDLEtBQUtDLFVBQVcsU0FFM0IsQ0FDQ3ZLLElBQUssT0FDTG9DLElBQUtpSSxLQUFLQyxLQUFLQyxVQUFXLHVCQUUzQixDQUNDdkssSUFBSyxhQUNMb0MsSUFBS2lJLEtBQUtDLEtBQUtDLFVBQVcsdUNBa0I1QixPQWRLMWQsS0FBS3FnQixhQUFhNVosSUFBSyxlQUMzQjdDLEVBQVF0RyxLQUFNLENBQ2I2VixJQUFLLFFBQ0xvQyxJQUFLaUksS0FBS0MsS0FBS0MsVUFBVyx1Q0FJdkIsUUFBVTFkLEtBQUt5RyxJQUFLLHFCQUN4QjdDLEVBQVF0RyxLQUFNLENBQ2I2VixJQUFLLGVBQ0xvQyxJQUFLaUksS0FBS0MsS0FBS0MsVUFBVyxvREFJckI5WixJQUlULENBQ0N1WixVQUFXLHdCQUNYOEMsVUFBVyxXQUNWLE9BQVUsSUFBTSxDQUFFLGFBQWMsUUFBUyxnQkFBaUJqaUIsUUFBU2dDLEtBQUt5RyxJQUFLLGlCQUU5RTNILEdBQUksd0JBQ0o4ZSxNQUFPSixLQUFLQyxLQUFLQyxVQUFXLGFBQzVCL00sSUFBSyxFQUNMeUcsS0FBTSxVQUVQLENBQ0MrRixVQUFXLGlCQUNYbUQsWUFBYSxRQUNiTCxVQUFXLFdBQ1YsTUFBUyxTQUFXamdCLEtBQUt5RyxJQUFLLGdCQUUvQjNILEdBQUksaUJBQ0o4ZSxNQUFPSixLQUFLQyxLQUFLQyxVQUFXLFFBQzVCNkMsV0FBWSxRQUNabkosS0FBTSxjQUVQLENBQ0MrRixVQUFXLGlCQUNYOEMsVUFBVyxXQUNWLE1BQVMsU0FBV2pnQixLQUFLeUcsSUFBSyxnQkFFL0IrWixXQUFZLFFBQ1pGLFlBQWEsUUFDYnhoQixHQUFJLGlCQUNKOGUsTUFBT0osS0FBS0MsS0FBS0MsVUFBVyxRQUM1QnRHLEtBQU0sb0JBZVp0ZCxFQUFRLGdCQUFnQixDQUFFLGNBQWUsd0JBQXlCLG9CQUFxQixrQkFBb0IsU0FBVTJtQixFQUFNekksRUFBZWdHLEVBQVcwQyxHQUVwSixPQUFPM2dCLFNBQVN1VSxNQUFNMVMsT0FBUTlCLEVBQUV1VyxTQUFVLENBTXpDSSxjQUFlLENBQ2RrSyxRQUFTLENBQ1J2WixNQUFPLFVBQ1BnUSxLQUFNLFNBRVA3TSxTQUFVLENBQ1RxVyxLQUFNLENBQ0xwSixNQUFPLE9BQ1BSLFlBQWEsU0FBVTVQLEdBRXRCLE1BQVMsUUFBVUEsRUFBTVgsSUFBSyxrQkFBc0IzRyxFQUFFd1YsUUFBU2xPLEVBQU1YLElBQUssVUFFM0VXLE1BQU8sWUFDUGdRLEtBQU0sV0FTVHVGLE9BQVErRCxFQVFSckssU0FBVSxXQUNULE1BQU8sQ0FDTnZYLEdBQUlnQixFQUFFb1ksU0FBVSxTQUNoQjRDLE1BQU8wQyxLQUFLQyxLQUFLQyxVQUFXLGNBQzVCdEcsS0FBTSxTQUNOeUosTUFBTzdnQixLQUFLeUMsV0FBYXpDLEtBQUt5QyxXQUFXaEcsT0FBUyxFQUFJLEVBQ3REcWtCLGNBQWU5UCxPQUFPcUcsYUFBYTBKLE9BQU9qaUIsR0FDMUNraUIsZUFBZ0IsR0FHaEJDLFNBQVUsR0FDVkMsU0FBVSxHQUdWekcsUUFBUyxHQUNUMEcsWUFBYSxHQUNiQyxpQkFBa0IsS0FDbEJDLHNCQUF1QixNQUN2QkMsaUNBQWtDLE1BQ2xDQyxZQUFhLEdBQ2JDLFlBQWEsR0FHYkMsV0FBWSxHQUNaQyxtQkFBb0IsS0FFcEJkLEtBQU0sR0FDTmUsYUFBYyxLQUVkQyxZQUFZLElBV2RqZSxXQUFZLFdBRVgzRCxLQUFLOGMscUJBQ0w5YyxLQUFLMlUsZ0JBQ0wzVSxLQUFLNmhCLHlCQUNMN2hCLEtBQUswVyxxQkFHTCxJQUFJa0ssRUFBTzVnQixLQUFLeUcsSUFBSyxRQUNkM0csRUFBRXdWLFFBQVNzTCxJQUFZQSxFQUFLbmEsSUFBSyxjQUN2Q21hLEVBQUsvSyxJQUFLLFlBQWE3VixLQUFLeUcsSUFBSyxRQVduQzRaLFdBQVksV0FDWCxPQUFPcmdCLEtBQUs4WCxhQUFhQSxjQVUxQm1ILGNBQWUsU0FBVUMsR0FFeEIsT0FBS0EsRUFDRzFCLEtBQUtDLEtBQUtDLFVBQVcsV0FHdEJGLEtBQUtDLEtBQUtDLFVBQVcsV0FTN0I1RixXQUFZLFdBRVgsSUFBSW5CLEVBQU8zVyxLQUFLNFcsb0JBQ2hCLE9BQUtELEVBQUs5TSxRQUFVOE0sRUFBSzlNLE9BQU8xQixVQUN4QndPLEVBQUs5TSxPQUFPMUIsYUFDUm5JLEtBQUt5QyxhQUFjekMsS0FBS3lDLFdBQVdvSCxTQUN2QzdKLEtBQUt5QyxXQUFXb0gsUUFZekJ1Vyw2QkFBOEIsV0FFN0IsSUFBSTBCLEVBQXVCOWhCLEtBQUs4WCxhQUFhclYsV0FBV3pFLFFBQVNnQyxLQUFLOFgsY0FDckVpSyxFQUEwQi9oQixLQUFLeUMsV0FBV3pFLFFBQVNnQyxNQUNuRDRELEVBQVUsR0E4QlgsT0E1QkE1RCxLQUFLcWdCLGFBQWE1WixJQUFLLFlBQWE1RixLQUFNLFNBQVVtaEIsRUFBU0MsR0FDNUQsR0FBS0EsR0FBa0JILEVBQXVCLENBQzdDLElBQUk5RSxFQUFRLENBRVZZLE1BQU9KLEtBQUtDLEtBQUs3Z0IsUUFBUyxxQkFBc0IsQ0FDL0NzbEIsT0FBUUYsRUFBUXZiLElBQUssU0FDckIwYixPQUFRSCxFQUFRdmIsSUFBSyxXQUV0QjdDLFFBQVMsSUFHWG9lLEVBQVF2YixJQUFLLFdBQVk1RixLQUFNLFNBQVV1aEIsRUFBUUMsSUFDM0NKLElBQW1CSCxHQUF3Qk8sRUFBaUJOLElBRWhFL0UsRUFBTXBaLFFBQVF0RyxLQUFNLENBQ25CNlYsSUFBS2lQLEVBQU8zYixJQUFLLE1BQ2pCOE8sSUFBS2lJLEtBQUtDLEtBQUs3Z0IsUUFBUyxvQkFBcUIsQ0FDNUNzbEIsT0FBUUUsRUFBTzNiLElBQUssU0FDcEIwYixPQUFRQyxFQUFPM2IsSUFBSyxjQUlyQnpHLE1BRUg0RCxFQUFRdEcsS0FBTTBmLEtBRWJoZCxNQUVJNEQsR0FXUjBlLFNBQVUsU0FBVWplLElBRW5CQSxFQUFPQSxHQUFRLElBRVY2WixVQUFZbGUsS0FBS2xCLEdBQ3RCdUYsRUFBS3lhLG1CQUFvQixFQUVsQnphLEVBQUt5VyxRQUVYelcsRUFBS3lXLE1BQVEwQyxLQUFLQyxLQUFLN2dCLFFBQVMsWUFBYSxDQUM1QzJsQixPQUFRdmlCLEtBQUt5RyxJQUFLLFlBS3BCekcsS0FBSzZWLElBQUssT0FBUXhSLEdBQ2xCckUsS0FBSzBXLHFCQUVMLElBQUlrSyxFQUFPNWdCLEtBQUt5RyxJQUFLLFFBR3JCLE9BRkF6RyxLQUFLNlYsSUFBSyxlQUFnQixPQUVuQitLLEdBVVJULG1CQUFvQixXQUduQixHQUFLbmdCLEtBQUt5QyxXQUFXekUsUUFBU2dDLE1BQzdCLE9BQU8sRUFJUixJQUFJZ2lCLEVBQVVoaUIsS0FBSzhYLGFBQ25CLE9BQUtrSyxFQUFRdmYsV0FBV3pFLFFBQVNna0IsSUFlbENILHVCQUF3QixXQUVoQjdRLE9BQU9xRyxhQUFhNkksY0FJM0JsZ0IsS0FBS3lXLGNBQWNsTSxTQUFTa1gsV0FBYSxDQUN4Q2pLLE1BQU8sYUFDUFIsWUFBYSxTQUFVNVAsR0FFdEIsTUFBUyxRQUFVQSxFQUFNWCxJQUFLLHdCQUE0QjNHLEVBQUV3VixRQUFTbE8sRUFBTVgsSUFBSyxnQkFFakZXLE1BQU8sa0JBQ1BnUSxLQUFNLFlBS05ZLEVBQWVnRyxNQVNuQmxrQixFQUFRLHNCQUFzQixDQUFFLGlCQUFtQixTQUFVc04sR0FFNUQsT0FBT3JILFNBQVNpRSxXQUFXcEMsT0FBUSxDQU1sQ3dGLE1BQU9BLEVBUVB6RCxXQUFZLFdBR1gzRCxLQUFLMFksR0FBSSxVQUFXMVksS0FBS3dpQixZQUd6QnhpQixLQUFLMFksR0FBSSxNQUFPMVksS0FBS3dpQixZQUNyQnhpQixLQUFLMFksR0FBSSxTQUFVMVksS0FBS3dpQixhQWN6QkEsV0FBWSxXQUNYeGlCLEtBQUsyWSxlQUNMM1ksS0FBS3lpQixvQkFTTjlKLGFBQWMsV0FFYjNZLEtBQUthLEtBQU0sU0FBVXVoQixHQUNwQkEsRUFBT3ZNLElBQUssUUFBUzdWLEtBQUtoQyxRQUFTb2tCLEdBQVcsSUFDNUNwaUIsT0FXSnlpQixpQkFBa0IsV0FFakJ6aUIsS0FBS2EsS0FBTSxTQUFVdWhCLEdBR2YsUUFBVUEsRUFBTzNiLElBQUssdUJBRXBCLElBRE0zRyxFQUFFcUgsTUFBT3JILEVBQUVtZCxRQUFTbmQsRUFBRXFILE1BQU9pYixFQUFPaEMsK0JBQWdDLFlBQWUsT0FDN0VwaUIsUUFBd0MsRUFBL0Jva0IsRUFBTzNiLElBQUssa0JBQ3RDMmIsRUFBT3ZNLElBQUssQ0FDWDZNLGFBQWMsRUFDZHRCLGlCQUFrQixTQUtuQnBoQixXQWFObEcsRUFBUSw0QkFBNEIsQ0FBRSx1QkFBeUIsU0FBVXNOLEdBRXhFLE9BQU9ySCxTQUFTaUUsV0FBV3BDLE9BQVEsQ0FNbEN3RixNQUFPQSxFQVFQekQsV0FBWSxXQUVYM0QsS0FBSzBZLEdBQUksTUFBTzFZLEtBQUttTixZQUNyQm5OLEtBQUswWSxHQUFJLFNBQVUxWSxLQUFLbU4sYUFXekJBLFdBQVksU0FBVS9GLEdBRXJCLE9BQU9BLEVBQU1YLElBQUssU0FBVW9hLFdBYS9CL21CLEVBQVEsaUJBQWlCLENBQUUsc0JBQXVCLHlCQUEyQixTQUFVNm9CLEVBQVMzSyxHQUUvRixPQUFPalksU0FBU3VVLE1BQU0xUyxPQUFROUIsRUFBRXVXLFNBQVUsQ0FFekNJLGNBQWUsQ0FDZDVNLE9BQVEsQ0FDUHpDLE1BQU8sU0FDUGdRLEtBQU0sU0FFUDdNLFNBQVUsQ0FDVHFZLFFBQVMsQ0FDUnBMLE1BQU8sVUFDUHBRLE1BQU8sU0FDUGdRLEtBQU0sZ0JBV1RmLFNBQVUsV0FDVCxNQUFPLENBQ052WCxHQUFJZ0IsRUFBRW9ZLFNBQVUsU0FDaEIwSyxRQUFTLEdBQ1QvQixNQUFPN2dCLEtBQUt5QyxXQUFhekMsS0FBS3lDLFdBQVdoRyxPQUFTLEVBQUksRUFDdERxa0IsY0FBZTlQLE9BQU9xRyxhQUFhMEosT0FBT2ppQixHQUMxQ2djLE1BQU8wQyxLQUFLQyxLQUFLQyxVQUFXLGVBQzVCdEcsS0FBTSxVQUVONkQsV0FBVyxFQUNYNEgsV0FBVyxJQVVibGYsV0FBWSxXQUVYM0QsS0FBSzJVLGdCQUNMM1UsS0FBSzBXLHNCQWFOb00sV0FBWSxTQUFVemUsRUFBTVQsR0FZM0IsT0FUQUEsRUFBVUEsR0FBVyxJQURyQlMsRUFBT0EsR0FBUSxjQUdNdEUsU0FBU3VVLE9BQzdCalEsRUFBS3dSLElBQUssaUJBQWtCN1YsS0FBS3lHLElBQUssT0FDdENwQyxFQUFLd1MsV0FBWTdXLE9BRWpCcUUsRUFBSzJjLGVBQWlCaGhCLEtBQUt5RyxJQUFLLE1BRzFCekcsS0FBS3lHLElBQUssV0FBWTNDLElBQUtPLEVBQU1ULElBV3pDcWIsY0FBZSxTQUFVQyxHQUV4QixPQUFLQSxFQUNHMUIsS0FBS0MsS0FBS0MsVUFBVyxZQUd0QkYsS0FBS0MsS0FBS0MsVUFBVyxZQVk3QnFGLFNBQVUsU0FBVUMsR0FDbkIsT0FBT2hqQixLQUFLaWpCLGFBQWMsT0FBUUQsSUFZbkNFLFNBQVUsU0FBVUYsR0FDbkIsT0FBT2hqQixLQUFLaWpCLGFBQWMsT0FBUUQsSUFhbkNDLGFBQWMsU0FBVUUsRUFBV0gsR0FFbENBLEVBQWEsY0FBZ0JBLEdBQW9CQSxFQUVqRCxJQUVDSSxFQUZHdlMsRUFBTTdRLEtBQUt5QyxXQUFXNlEsT0FBUyxFQUNsQ3ZWLEVBQVFpQyxLQUFLeUMsV0FBV3pFLFFBQVNnQyxNQVVsQyxHQVBLLFNBQVdtakIsRUFDZkMsRUFBZ0JybEIsRUFBUSxFQUNiLFNBQVdvbEIsSUFDdEJDLEVBQWdCcmxCLEVBQVEsR0FJcEJxbEIsR0FBaUJ2UyxHQUFPdVMsR0FBaUIsRUFFN0MsT0FBT3BqQixLQUFLeUMsV0FBV2dOLEdBQUkyVCxHQUVyQixHQUFLSixFQUFXLENBRXRCLEdBQUssU0FBV0csRUFDZixPQUFPbmpCLEtBQUt5QyxXQUFXckIsUUFDakIsR0FBSyxTQUFXK2hCLEVBQ3RCLE9BQU9uakIsS0FBS3lDLFdBQVc0Z0IsT0FLekIsT0FBTyxJQUlOckwsTUFTSmxlLEVBQVEsdUJBQXVCLENBQUUsa0JBQW9CLFNBQVVzTixHQUU5RCxPQUFPckgsU0FBU2lFLFdBQVdwQyxPQUFRLENBTWxDd0YsTUFBT0EsRUFRUHpELFdBQVksV0FLWDNELEtBQUswWSxHQUFJLFVBQVcxWSxLQUFLMlksY0FHekIzWSxLQUFLMFksR0FBSSxNQUFPMVksS0FBSzJZLGNBQ3JCM1ksS0FBSzBZLEdBQUksU0FBVTFZLEtBQUsyWSxlQVV6QkEsYUFBYyxXQUViLElBQUlNLEVBQU9qWixLQUVYQSxLQUFLYSxLQUFNLFNBQVVtaEIsR0FFcEJBLEVBQVFuTSxJQUFLLFFBQVNvRCxFQUFLamIsUUFBU2drQixHQUFZLFVBZXBEbG9CLEVBQVEscUJBQXFCLENBQzNCLHNCQUNBLDhCQUNBLHdCQUNBLDRCQUNBLHdCQUNFLFNBQ0Y2b0IsRUFDQXRJLEVBQ0FELEVBQ0FrSixFQUNBQyxHQUdELE1BQU8sQ0FDTlosUUFBU0EsRUFDVHRJLGdCQUFpQkEsRUFDakJELFVBQVdBLEVBQ1hrSixjQUFlQSxFQUNmQyxTQUFVQSxLQVVaenBCLEVBQVEsa0JBQWtCLENBQUUsd0JBQXlCLHFCQUF1QixTQUFVa2UsRUFBZWdHLEdBRXBHLE9BQU9qZSxTQUFTdVUsTUFBTTFTLE9BQVE5QixFQUFFdVcsU0FBVSxHQUFJMkIsRUFBZWdHLE1BUzlEbGtCLEVBQVEsZ0JBQWdCLENBQUUsdUJBQXdCLHdCQUF5QixxQkFBdUIsU0FBVXlwQixFQUFVdkwsRUFBZWdHLEdBRXBJLE9BQU9qZSxTQUFTdVUsTUFBTTFTLE9BQVE5QixFQUFFdVcsU0FBVSxDQUV6Q0ksY0FBZSxDQUNkbE0sU0FBVSxDQUNUaVosU0FBVSxDQUNUaE0sTUFBTyxXQUNQcFEsTUFBTyxVQUNQZ1EsS0FBTSxnQkFXVGYsU0FBVSxXQUNULE1BQU8sQ0FDTjRLLFNBQVUsR0FDVnVDLFNBQVUsR0FDVjFJLE1BQU8sYUFDUDFELEtBQU0sU0FDTjhKLFNBQVUsS0FVWnZkLFdBQVksV0FFWDNELEtBQUsyVSxnQkFDTDNVLEtBQUswVyxxQkFHTDNXLFNBQVN1YixPQUFPNUMsR0FBSSxrQkFBbUIxWSxLQUFLeWpCLFlBQWF6akIsTUFHekRELFNBQVN1YixPQUFPNUMsR0FBSSxpQkFBa0IxWSxLQUFLOGlCLFdBQVk5aUIsTUFFdkRELFNBQVN1YixPQUFPNUMsR0FBSSx1QkFBd0IxWSxLQUFLMGpCLG9CQUFxQjFqQixPQVl2RTBqQixvQkFBcUIsU0FBVXRCLEdBRTlCLElBQUkvZCxFQUFPK2QsRUFBTy9kLEtBRWIsVUFBWStkLEVBQU85QyxlQUVoQmpiLEVBQUt2RixHQUNQdUYsRUFBS3VjLGNBQ0Z2YyxFQUFLdWMsS0FDWnZjLEVBQUtzZCxhQUFlLE9BS3JCdGQsRUFBS3VkLFlBQWEsU0FJWnZkLEVBQUt3YyxhQUNMeGMsRUFBS3ljLHFCQUNMemMsRUFBSzJjLGVBRVpoaEIsS0FBSzhpQixXQUFZemUsSUFXbEJ5ZSxXQUFZLFNBQVV6ZSxHQUdyQixJQUNDMmQsR0FGRDNkLEVBQU9BLEdBQVEsSUFJSDJjLGVBTVhnQixFQUFVaGlCLEtBQUt5RyxJQUFLLFlBQWFBLElBQUtwQyxFQUFLMmMsaUJBTDNDZ0IsRUFBVWhpQixLQUFLMmpCLDBCQUVkM0IsRUFBVWhpQixLQUFLeUcsSUFBSyxZQUFhNGMsUUFNbkNoZixFQUFLd2UsV0FBWSxFQUVqQnhlLEVBQUt5YyxjQUFnQjlnQixLQUFLeUcsSUFBSyxNQUUvQixJQUFJMmIsRUFBU0osRUFBUWMsV0FBWXplLEVBaEJuQixJQXNCZCxPQUxBdEUsU0FBU3ViLE9BQU92VCxRQUFTLG1CQUFvQnFhLEdBRzdDSixFQUFRbk0sSUFBSyxhQUFhLEdBRW5CdU0sR0FXUnFCLFlBQWEsU0FBVXBmLEdBRXRCQSxFQUFPQSxHQUFRLEdBQ2YsSUFBSW1mLEVBQVd4akIsS0FBS3lHLElBQUssWUFDeEI3QyxFQUFVLEdBQ1ZnZ0IsRUFBVzVqQixLQUFLMmpCLHVCQUdaQyxJQUNKaGdCLEVBQVE2TCxHQUFLK1QsRUFBU3hsQixRQUFTNGxCLEdBQWEsR0FHN0NKLEVBQVMxZixJQUFLTyxFQUFNVCxJQVVyQitmLHFCQUFzQixXQUVyQixPQUFPM2pCLEtBQUt5RyxJQUFLLFlBQWFzRCxLQUFNLFNBQVUzQyxHQUM3QyxPQUFPQSxFQUFNWCxJQUFLLGlCQUtsQnVSLEVBQWVnRyxNQVVuQmxrQixFQUFRLGdCQUFnQixDQUN0QixrQkFDQSxnQkFDQSxlQUNBLGdCQUNBLGtCQUNBLHdCQUNBLHNCQUNBLGNBQ0Esa0JBRUQsU0FDQytwQixFQUNBQyxFQUNBL0wsRUFDQStGLEVBQ0FDLEVBQ0FnRyxFQUNBekosRUFDQW1HLEVBQ0F1RCxHQUdELE1BQU8sQ0FDTkgsU0FBVUEsRUFDVkMsT0FBUUEsRUFDUi9MLE1BQU9BLEVBQ1ArRixPQUFRQSxFQUNSQyxTQUFVQSxFQUNWZ0csZUFBZ0JBLEVBQ2hCekosYUFBY0EsRUFDZG1HLEtBQU1BLEVBQ051RCxRQUFTQSxLQVdYbHFCLEVBQVEsb0JBQW9CLEdBQUksV0FFL0IsTUFBTyxDQVFOZ0ksT0FBUSxDQUNQbWlCLHFDQUFzQyxnQkFVdkNDLGFBQWMsU0FBVWhWLEdBRWxCQSxJQUNKQSxFQUFNaVYsaUJBQ05qVixFQUFNa1YsbUJBR1AsSUFBSUMsRUFBTTdHLEtBQUtDLEtBQUs3Z0IsUUFBUywyQ0FBNEMsQ0FDeEUwbkIsS0FBTXRrQixLQUFLb0gsTUFBTTZYLGtCQUdiak8sT0FBT29ELFFBQVNpUSxLQUVmcmtCLEtBQUtvSCxNQUFNM0UsWUFDZnpDLEtBQUtvSCxNQUFNM0UsV0FBV29ELE9BQVE3RixLQUFLb0gsT0FJcENySCxTQUFTdWIsT0FBT3ZULFFBQVMsaUJBQWtCL0gsS0FBS29ILE9BR2hEcEgsS0FBSytILFFBQVMsZ0JBQWlCL0gsS0FBS29ILFlBa0J4Q3ROLEVBQVEsa0JBQWtCLEdBQUksV0FFN0IsTUFBTyxDQUVOeXFCLFVBQVcsS0FRWHppQixPQUFRLENBQ1AwaUIsd0JBQXlCLGlCQUN6QkMsa0NBQW1DLHFCQUNuQ0MscUNBQXNDLGVBQ3RDQyxzQ0FBdUMsWUFDdkNDLDZDQUE4QyxnQkFDOUNDLG9DQUFxQyxrQkFDckNDLHNCQUF1QixXQUN2QkMsdUJBQXdCLFVBQ3hCQyxzQkFBdUIsYUFDdkJDLG1DQUFvQyxVQUNwQ0MscUNBQXNDLFlBVXZDQyxpQkFBa0IsU0FBVS9nQixHQUUzQixPQUFLQSxFQUFJRyxLQUFNLG1CQUNQekUsRUFBRXZELElBQUs2SCxFQUFJRyxLQUFNLG1CQUFvQmpJLE1BQU8sS0FBTyxTQUFVOG9CLEdBQ25FLE9BQU9BLEVBQUlDLFNBSU4sQ0FBRSxJQUFLLElBQUssSUFBSyxTQUFVLE9BV25DQyxZQUFhLFNBQVVsaEIsR0FFdEIsTUFBSyxVQUFZQSxFQUFJLEdBQUd2QyxRQUNoQnVDLEVBQUltUixNQUdMblIsRUFBSUcsS0FBTSxvQkFBeUJILEVBQUltaEIsU0FBVSxhQUlqRHpsQixFQUFFMGxCLGdCQUFpQnBoQixFQUFJOEgsT0FBUWxNLEtBQUttbEIsaUJBQWtCL2dCLElBSHJEQSxFQUFJcWhCLFFBY2JDLFlBQWEsU0FBVXhXLEdBQ3RCLElBQUk5SyxFQUFNekssRUFBR3VWLEVBQU1xQyxRQUNuQixPQUFTbk4sRUFBSUcsS0FBTSwyQkFBOEJ2RSxLQUFLc2xCLFlBQWFsaEIsSUFVcEV1aEIsU0FBVSxTQUFVelcsR0FFbkIsSUFBSStKLEVBQU9qWixLQUNWb0UsRUFBTXpLLEVBQUd1VixFQUFNcUMsUUFDZmtKLEVBQVV6YSxLQUFLc2xCLFlBQWFsaEIsR0FDNUJnVCxFQUFPaFQsRUFBSUcsS0FBTSxhQUVsQixJQUFPSCxFQUFJRyxLQUFNLGFBQWdCSCxFQUFJRyxLQUFNLG1CQUF1QmtXLEVBQVFoZSxPQUFTLEVBQ2xGLE9BQU8sRUFHUixHQUFLLFFBQVUyYSxHQUFRLFVBQVlBLEdBQ2xDLElBQU9wWCxLQUFLNGxCLGNBQWU1bEIsS0FBS3NsQixZQUFhbGhCLElBQzVDLE9BQU8sTUFHRyxjQUFnQmdULEdBRTNCb0csS0FBSzZCLEtBQUsvakIsS0FBTSxDQUNmK0ksS0FBTSxDQUNMaWIsT0FBUSxlQUNSQyxZQUFhLGdCQUNiQyxVQUFXeE8sT0FBT3FHLGFBQWFvSSxZQUFZaFosSUFBSyxNQUNoRDNILEdBQUltYSxFQUFLN1IsTUFBTVgsSUFBSyxNQUNwQnFVLE1BQU83QixFQUFLN1IsTUFBTVgsSUFBSyxTQUN2Qm9mLEtBQU1wTCxHQUVQcUwsV0FBWSxXQUNYdEksS0FBS3VJLFFBQVF6WCxNQUFPbEssRUFBSTZHLFFBQVMsK0JBQWlDLFVBRW5FZ0wsUUFBUyxTQUFVK1AsR0FFYkEsRUFBRXBILFdBQWFvSCxFQUFFSCxPQUNyQjVNLEVBQUs3UixNQUFNeU8sSUFBSyxZQUFhbVEsRUFBRXBILFdBQy9CM0YsRUFBSzdSLE1BQU15TyxJQUFLLE9BQVFtUSxFQUFFSCxNQUMxQjVNLEVBQUtsVCxhQVFULE9BQU8sR0FVUmtnQixpQkFBa0IsV0FFakJqbUIsS0FBS29FLElBQUkyRixLQUFNLDZCQUE4QmxKLEtBQU0sV0FFbERsSCxFQUFHcUcsTUFBT2ttQixlQUFnQixDQUN6QkMsT0FBUXhzQixFQUFHcUcsTUFBT3VFLEtBQU0scUJBQXdCLGNBQ2hEaWMsZ0JBQWNqaEIsSUFBYzVGLEVBQUdxRyxNQUFPdUUsS0FBTSx5QkFBc0MsUUFBVTVLLEVBQUdxRyxNQUFPdUUsS0FBTSx3QkFDNUdnYyxnQkFBY2hoQixJQUFjNUYsRUFBR3FHLE1BQU91RSxLQUFNLHlCQUFzQyxRQUFVNUssRUFBR3FHLE1BQU91RSxLQUFNLHdCQUM1RzZoQixRQUFTLFNBQVVDLEVBQWNDLEdBQ2hDQSxFQUFPQyxhQWNYQyxvQkFBcUIsV0FFcEIsSUFBSXZOLEVBQU9qWixLQUVYQSxLQUFLb0UsSUFBSTJGLEtBQU0sMkNBQTRDbEosS0FBTSxXQUVoRSxJQUFJNGxCLEVBQWE5c0IsRUFBR3FHLE1BQU91RSxLQUFNLG1CQUFvQmpJLE1BQU8sS0FDM0RpSSxFQUFPNUssRUFBR3FHLE1BQU91RSxLQUFNLGtCQUVwQm1pQixFQUFLLElBQUlDLE1BQU8zbUIsS0FBTSxDQUN6QjRtQixRQUFTLENBQ1JDLFFBQVMsQ0FBRUosR0FDWEssU0FBVSxDQUNUQyxTQUFVLENBQ1RDLElBQUssQ0FDSjdULElBQUssRUFDTDhULFFBQVMsU0FBVUMsRUFBT0MsR0FDekIsT0FBTyxJQUdUQyxHQUFJLENBQ0hqVSxJQUFLLEdBQ0w4VCxRQUFTLFNBQVVDLEVBQU9DLEdBRXpCLE9BREFULEVBQUczc0IsS0FBS3dzQixRQUNELE9BTVo3TSxZQUFhL2YsRUFBR3FHLE1BQU91RSxLQUFNLG9CQUM3QjhpQixNQUFPLFdBR1JYLEVBQUdoTyxHQUFJLGNBQWUsU0FBVTRPLEVBQU9DLEVBQVVDLEdBQ2hEdk8sRUFBSzdSLE1BQU15TyxJQUFLdFIsRUFBTTBVLEVBQUtxTSxZQUFhM3JCLEVBQUcrc0IsRUFBRzNzQixVQUcvQ2dHLFNBQVN1YixPQUFPdlQsUUFBUyxxQkFBc0IyZSxFQUFJL3NCLEVBQUdxRyxNQUFRaVosTUFZaEV3TyxhQUFjLFdBRWJ6bkIsS0FBS29FLElBQUkyRixLQUFNLGdDQUFpQzJkLFlBQWEsQ0FDNURDLE1BQU8sVUFhVEMsUUFBUyxTQUFVMVksR0FFbEJBLEVBQU1rVixrQkFFTnBrQixLQUFLb0gsTUFBTXlPLElBQUssY0FBYyxFQUFPLENBQUU5TyxRQUFRLElBR3hDcE4sRUFBR3VWLEVBQU1xQyxRQUNMdlIsS0FBSzBsQixZQUFheFcsS0FGbEJsUCxLQU1FMmxCLFNBQVV6VyxHQUdyQmxQLEtBQUs2bkIsV0FBWTNZLEdBVFJsUCxLQU9KOG5CLGFBQWM1WSxLQWdCdEI2WSxTQUFVLFNBQVU3WSxHQUVuQkEsRUFBTWtWLGtCQUNOcGtCLEtBQUtvSCxNQUFNeU8sSUFBSyxjQUFjLEVBQU0sQ0FBRTlPLFFBQVEsS0FZL0NpaEIsU0FBVSxTQUFVOVksR0FFbkJBLEVBQU1pVixpQkFDTmpWLEVBQU1rVixrQkFFTixJQUFJcUIsR0FBU3ZXLEVBQU0rWSxlQUFpQi9ZLEdBQVFnWixjQUFjQyxRQUFTLGNBQ25FblgsT0FBT25JLFNBQVN1ZixZQUFhLGNBQWMsRUFBTzNDLElBV25ENEMsVUFBVyxTQUFVblosR0FFcEIsSUFJQ3FHLEVBSkduUixFQUFNekssRUFBR3VWLEVBQU1xQyxRQUNsQitXLEVBQVVsa0IsRUFBSUcsS0FBTSxZQUNwQkEsRUFBT0gsRUFBSUcsS0FBTSxRQUNqQmdrQixFQUFZbmtCLEVBQUkyRixLQUFNLG1CQUdsQnVlLEdBQ0ovUyxFQUFNLEdBQ05BLEVBQU1nVCxFQUFVaHNCLElBQUssV0FDcEIsT0FBT3lELEtBQUt0QyxRQUNUK0ksT0FFSjhPLEVBQU1nVCxFQUFVLEdBQUc3cUIsTUFHcEJzQyxLQUFLb0gsTUFBTXlPLElBQUt0UixFQUFNZ1IsSUFXdkJpVCxnQkFBaUIsU0FBVXRaLEdBRTFCLElBQUk5SyxFQUFNekssRUFBR3VWLEVBQU1xQyxRQUNsQmhOLEVBQU9ILEVBQUlHLEtBQU0sUUFDakJnUixFQUFNblIsRUFBSW1SLE1BRVh2VixLQUFLb0gsTUFBTXlPLElBQUt0UixFQUFNZ1IsSUFZdkJrVCxXQUFZLFNBQVV2WixHQUVyQkEsRUFBTWtWLGtCQUVOLElBQ0NqUixFQUFNakUsRUFBTVcsT0FBU1gsRUFBTXdaLFFBQzNCQyxFQUFRelosRUFBTWtCLFNBR2YsT0FBUytDLEdBRVIsS0FBSyxHQUVHd1YsSUFDTnpaLEVBQU1pVixpQkFDTmpWLEVBQU1xQyxPQUFPZ1YsUUFFZixNQUVBLEtBQUssR0FDSnJYLEVBQU1pVixpQkFDTm5rQixLQUFLOG5CLGFBQWM1WSxHQUNuQkEsRUFBTXFDLE9BQU9nVixTQWNoQnFDLGVBQWdCLFNBQVUxWixHQUV6QkEsRUFBTWtWLGtCQUVOLElBQUluTCxFQUFPalosS0FDVm9FLEVBQU16SyxFQUFHdVYsRUFBTXJELGVBRVhvTixFQUFLc0wsVUFFVHRMLEVBQUtzTCxVQUFVc0UsU0FBU0EsU0FBU0MsTUFBTyxZQUl4QzdQLEVBQUtzTCxVQUFZd0UsR0FBR0MsTUFBTUMsT0FBT0MsV0FBYUgsR0FBR0MsTUFBTyxDQUN2RGxPLE1BQU8wQyxLQUFLQyxLQUFLQyxVQUFXLG1CQUM1QnlMLE9BQVEsQ0FDUDFELEtBQU1qSSxLQUFLQyxLQUFLQyxVQUFXLG1CQUU1QjBMLFVBQVUsSUFHWG5RLEVBQUtzTCxVQUFVN0wsR0FBSSxTQUFVLFdBRTVCLElBR0MyUSxFQUhHL1YsRUFBT2xQLEVBQUlHLEtBQU0sbUJBQ3BCK2tCLEVBQWFyUSxFQUFLc0wsVUFBVWdGLFFBQVE5aUIsSUFBSyxhQUFjckYsUUFBUW9vQixTQUMvRGhRLEVBQVFQLEVBQUs3UixNQUFNWCxJQUFLckMsRUFBSUcsS0FBTSxtQkFJbEM4a0IsRUFESS9WLEdBQVFnVyxFQUFXRyxNQUFPblcsR0FDeEJnVyxFQUFXRyxNQUFPblcsR0FBTytWLElBRXpCQyxFQUFXRCxJQUdsQjdQLEVBQU0zRCxJQUFLLENBQ1YvVyxHQUFJd3FCLEVBQVd4cUIsR0FDZnlYLElBQUs4UyxPQU9ScFEsRUFBS3NMLFVBQVVtRixRQVloQkMsYUFBYyxTQUFVemEsR0FFdkJBLEVBQU1pVixpQkFFTm5rQixLQUFLb0gsTUFBTVgsSUFBSzlNLEVBQUd1VixFQUFNckQsZUFBZ0J0SCxLQUFNLG1CQUFxQnNSLElBQUssQ0FDeEUvVyxHQUFJLEdBQ0p5WCxJQUFLLE1BYVB1UixhQUFjLFNBQVU1WSxHQUN2QixJQUFJOUssRUFBTXpLLEVBQUd1VixFQUFNcUMsUUFDbEJnRSxFQUFNblIsRUFBSUcsS0FBTSx5QkFDakJILEVBQUk4SCxLQUFNcUosSUFVWHNTLFdBQVksU0FBVTNZLEdBRXJCLElBQUk5SyxFQUFNekssRUFBR3VWLEVBQU1xQyxRQUNsQmdFLEVBQU12VixLQUFLc2xCLFlBQWFsaEIsR0FFekJwRSxLQUFLb0gsTUFBTXlPLElBQUt6UixFQUFJRyxLQUFNLGtCQUFvQmdSLElBVy9DcVUsY0FBZSxTQUFVMWEsR0FFeEJBLEVBQU1rVixrQkFDTixJQUdDN08sRUFIR25SLEVBQU16SyxFQUFHdVYsRUFBTXFDLFFBQ2xCaE4sRUFBT0gsRUFBSUcsS0FBTSxRQUNqQlUsRUFBV2IsRUFBSUcsS0FBTSxpQkFTdEIsR0FMQ2dSLEVBREluUixFQUFJd0MsR0FBSSxZQUNOeEMsRUFBSUcsS0FBTSxXQUFjSCxFQUFJRyxLQUFNLFdBQWMsTUFFaERILEVBQUlHLEtBQU0sWUFBZUgsRUFBSUcsS0FBTSxZQUFlLE1BR25ELElBQU1BLEVBQUt2RyxRQUFTLEtBQVEsQ0FFakMsSUFBSTFCLEVBQVFpSSxFQUFLakksTUFBTyxLQUVuQixXQUFhQSxFQUFNLEdBQ3ZCMEQsS0FBS29ILE1BQU0wUSxhQUFhakMsSUFBS3ZaLEVBQU0sR0FBSWlaLEdBRXZDdlYsS0FBS29ILE1BQU1YLElBQUtuSyxFQUFNLElBQUt1WixJQUFLdlosRUFBTSxHQUFJaVosUUFNM0N2VixLQUFLb0gsTUFBTXlPLElBQUt0UixFQUFNZ1IsR0FNdkIsR0FGQXZWLEtBQUsrSCxRQUFTeEQsRUFBSzNILFFBQVMsSUFBSyxLQUFRLFVBQVcyWSxJQUU3Q3RRLEdBQVksUUFBVUEsRUFBVyxDQUN2QyxJQUFJZ1UsRUFBT2paLEtBQ1hQLFdBQVksV0FDWHdaLEVBQUtsVCxVQUNILE9BYUw4akIsWUFBYSxTQUFVL3FCLEVBQUlnckIsR0FFMUJBLEVBQVdBLEdBQVksR0FFdkJmLEdBQUdnQixPQUFPbGtCLE9BQVEvRyxHQUVsQmlxQixHQUFHZ0IsT0FBT3BtQixXQUFZN0UsRUFBSW5GLEVBQUVpSSxRQUFRLEVBQU1tbkIsR0FBR2dCLE9BQU9DLHFCQUFzQixDQUN6RUMsY0FBYyxFQUNkQyxRQUFTLENBQ1JDLFNBQVUsOEdBQ1ZDLFNBQVUsZ0hBQ1ZDLE1BQU92cUIsRUFBRXlPLEtBQU12TyxLQUFLc3FCLGdCQUFpQnRxQixRQUVwQzhwQixLQVdKUyxtQkFBb0IsU0FBVXJiLEdBRTdCLElBQ0NzYixFQUFPN3dCLEVBQUd1VixFQUFNckQsZUFDaEI0ZSxFQUFRRCxFQUFLRSxRQUFTLEtBQ3RCcEUsRUFBU2tFLEVBQUtHLEtBQU0sbUJBQ3BCQyxFQUFXSCxFQUFNbG1CLEtBQU0sUUFDdkJzaEIsRUFBT1MsRUFBTy9RLE1BQ2RzVixFQUFZRCxFQUFTaHVCLFFBQVNpcEIsRUFBTSxJQUdyQzJFLEVBQUs5ZixPQUdMK2YsRUFBTTNnQixJQUFLLENBQ1ZnaEIsTUFBTyxPQUNQQyxpQkFBa0IsT0FDbEJDLGtCQUFtQixTQUlwQlAsRUFBTWhGLEtBQU1vRixFQUFVNXNCLFVBQVcsRUFBRzRzQixFQUFVcHVCLE9BQVMsSUFHdkQ2cEIsRUFBTzJFLE9BQU81b0IsU0FhZmlvQixnQkFBaUIsU0FBVVAsR0FFMUIsSUFBSTlRLEVBQU9qWixLQUNWa3JCLEVBQU12eEIsRUFBRyxJQUFNb3dCLEVBQU9qckIsSUFDdEJxc0IsRUFBVUQsRUFBSWpnQixRQUFTLHlCQUN2Qm1nQixFQUFTRCxFQUFRcGhCLEtBQU0sZUFDdkIxTyxFQUFPNnZCLEVBQUkzbUIsS0FBTSxrQkFFYjZtQixFQUFPM3VCLFFBQ1gydUIsRUFBT0MsVUFBV0YsRUFBUXBoQixLQUFNLHFCQUlqQ2dnQixFQUFPclIsR0FBSSxTQUFVLFNBQVV4SixHQUM5QitKLEVBQUs3UixNQUFNeU8sSUFBS3hhLEVBQU0wdEIsR0FBR2dCLE9BQU91QixXQUFZdkIsRUFBT2pyQixPQUlwRG9zQixFQUFJeFMsR0FBSSxRQUFTLFNBQVV4SixHQUMxQitKLEVBQUs3UixNQUFNeU8sSUFBS3hhLEVBQU02dkIsRUFBSTNWLFNBSTNCNFYsRUFBUXpTLEdBQUksUUFBUyxnQ0FBaUMsV0FDckRqWixXQUFZLFdBQ1h5ckIsRUFBSW5qQixRQUFTLFVBQ1gsT0FLTDZkLGNBQWUsU0FBVTJGLEdBRXhCLElBQUlDLEVBQUkzaUIsU0FBUzRpQixjQUFlLEtBRWhDLE9BREFELEVBQUVFLEtBQU9ILEVBQ0FDLEVBQUVHLE1BQVFILEVBQUVHLE9BQVMzYSxPQUFPNGEsU0FBU0QsU0FjakQ3eEIsRUFBUSxvQkFBb0IsR0FBSSxXQUUvQixNQUFPLENBV05nVixTQUFXLFNBQVVJLEVBQU9DLEdBRzNCLEdBQUtBLEVBQUdJLE9BQU9nVyxTQUFVLGdCQUFtQixDQUMzQyxJQUFJeG5CLEVBQVFpQyxLQUFLdUksa0JBQWtCZ0MsV0FBV3hNLE1BQU9vUixFQUFHMGMsUUFHeEQsT0FGQTFjLEVBQUcwYyxPQUFPaG1CLGNBQ1Y3RixLQUFLeUMsV0FBV3FCLElBQUssR0FBSSxDQUFFMkwsR0FBSTFSLElBSWhDLElBQ0l1UixFQURlSCxFQUFHSSxPQUNzQmxMLEtBQU0sUUFDbEQsR0FBTWlMLEdBQThCQSxFQUF5QjdNLFdBQTdELENBRUEsSUFBSTRNLEVBQVdyUCxLQUFLdUksa0JBQWtCZ0MsV0FBV3hNLE1BQU9vUixFQUFHM0ksTUFDdkRnSixFQUFnQkYsRUFBeUI3TSxXQUFXZ0UsSUFBSzBJLEVBQUczSSxLQUFLakMsS0FBTSxtQkFDM0UrSyxFQUF5QjdNLFdBQVdvRCxPQUFRMkosR0FDNUN4UCxLQUFLeUMsV0FBV3FCLElBQUswTCxFQUFlLENBQUVDLEdBQUtKLElBQzNDRyxFQUFjL00sV0FBYXpDLEtBQUt5QyxXQUNoQ3pDLEtBQUtzRixpQkFBa0JrSyxRQWExQjFWLEVBQVEsbUJBQW1CLEdBQUksV0FFOUIsTUFBTyxDQVFOZ3lCLDZCQUE4QixXQUU3QixHQUFPOXJCLEtBQUtvSCxNQUFNM0UsV0FBbEIsQ0FJQSxJQUFJMlUsRUFBT3BYLEtBQUtvSCxNQUFNWCxJQUFLLFFBRXRCekcsS0FBS29ILE1BQU0zRSxXQUFXckIsVUFBWXBCLEtBQUtvSCxNQUMzQ3BILEtBQUtvRSxJQUFJMkYsS0FBTSxjQUFnQnFOLEdBQU8xTSxPQUMzQjFLLEtBQUtvSCxNQUFNM0UsV0FBVzRnQixTQUFXcmpCLEtBQUtvSCxPQUNqRHBILEtBQUtvRSxJQUFJMkYsS0FBTSxnQkFBa0JxTixHQUFPMU0sU0FhMUNpZSxNQUFPLFNBQVVvRCxFQUFXQyxHQUUzQixJQUFJdnBCLEVBQWF6QyxLQUFLb0gsTUFBTTNFLFdBRTVCQSxFQUFXb0QsT0FBUTdGLEtBQUtvSCxPQUN4QjNFLEVBQVdxQixJQUFLOUQsS0FBS29ILE1BQU8sQ0FBRXFJLEdBQUl1YyxJQUNsQ3ZwQixFQUFXc0YsUUFBUyxZQVVyQmtrQixXQUFZLFNBQVVydEIsR0FFckJBLEVBQUV1bEIsaUJBQ0YsSUFBSXBtQixFQUFRaUMsS0FBS29ILE1BQU0zRSxXQUFXekUsUUFBU2dDLEtBQUtvSCxPQUNoRHBILEtBQUsyb0IsTUFBTzVxQixFQUFPQSxFQUFRLElBVTVCbXVCLFNBQVUsU0FBVXR0QixHQUVuQkEsRUFBRXVsQixpQkFDRixJQUFJcG1CLEVBQVFpQyxLQUFLb0gsTUFBTTNFLFdBQVd6RSxRQUFTZ0MsS0FBS29ILE9BQ2hEcEgsS0FBSzJvQixNQUFPNXFCLEVBQU9BLEVBQVEsT0FhOUJqRSxFQUFRLGlCQUFpQixHQUFJLFdBRTVCLE1BQU8sQ0FFTnF5QixjQUFlLEdBTWY1QyxNQUFPLEdBTVBsWCxNQUFPLEdBU1ArWixZQUFhLFNBQVU1d0IsR0FFdEIsUUFBS3dFLEtBQUtxUyxNQUFPN1csSUFDVHdFLEtBQUtxUyxNQUFPN1csSUFPckI2d0IsaUJBQWtCLFNBQVV2cUIsR0FFM0JoQyxFQUFFZSxLQUFNaUIsRUFBUSxTQUFVd3FCLEVBQU1wZCxHQUUvQmxQLEtBQUttc0IsY0FBZWpkLEdBQVVvZCxFQUM5QnZzQixTQUFTdWIsT0FBTzVDLEdBQUl4SixFQUFPb2QsRUFBTXRzQixPQUUvQkEsT0FJSnVzQixtQkFBb0IsV0FFbkJ6c0IsRUFBRWUsS0FBTWIsS0FBS21zQixjQUFlLFNBQVVHLEVBQU1wZCxHQUUzQ25QLFNBQVN1YixPQUFPa1IsSUFBS3RkLEVBQU9vZCxFQUFNdHNCLGFBQzNCQSxLQUFLbXNCLGNBQWVqZCxJQUV6QmxQLE9BV0p5c0IsZUFBZ0IsU0FBVWp4QixHQUV6QixJQUFJb0ssRUFBTzVGLEtBQUtvc0IsWUFBYTV3QixHQUV0Qm9LLEdBSUZBLEVBQUs4bUIsV0FHRjVzQixFQUFFd1YsUUFBUzFQLEVBQUs4bUIsU0FBU3JhLFNBQy9Cek0sRUFBSzhtQixTQUFTSCxxQkFDZDNtQixFQUFLOG1CLFNBQVNDLG1CQUdmL21CLEVBQUs4bUIsU0FBU0YsTUFDZDVtQixFQUFLOG1CLFNBQVNGLElBQUssS0FBTSxLQUFNLE1BQy9CNW1CLEVBQUs4bUIsU0FBUzdtQixTQUNkRCxFQUFLOG1CLFNBQVNFLG1CQU1kaG5CLEVBQUs4bUIsU0FBVyxPQVlsQkMsZ0JBQWlCLFdBRWhCN3NCLEVBQUVlLEtBQU1iLEtBQUtxUyxNQUFPLFNBQVVoTyxFQUFNN0ksR0FFbkN3RSxLQUFLeXNCLGVBQWdCanhCLElBRW5Cd0UsT0FXSjZzQixnQkFBaUIsU0FBVUMsR0FFMUJBLEVBQVlBLEdBQWEsR0FFekJodEIsRUFBRWUsS0FBTWIsS0FBS3FTLE1BQU8sU0FBVWhPLEVBQU03SSxHQUU5QndFLEtBQUt1cEIsUUFBVWxsQixFQUFLa2xCLE1BRXhCdnBCLEtBQUsrc0IsZUFBZ0J2eEIsRUFBTXN4QixHQUkzQjlzQixLQUFLeXNCLGVBQWdCanhCLElBSXBCd0UsT0FZSitzQixlQUFnQixTQUFVdnhCLEVBQU1zeEIsR0FFL0IsSUFBSWxuQixFQUFPNUYsS0FBS29zQixZQUFhNXdCLEdBRXRCb0ssSUFJUDVGLEtBQUt5c0IsZUFBZ0JqeEIsR0FFZG9LLEVBQUs4bUIsV0FDWDltQixFQUFLOG1CLFNBQVcsSUFBSTltQixFQUFLNFIsTUFBT3NWLElBR2pDbG5CLEVBQUs4bUIsU0FBUzNtQixXQVlmaW5CLFVBQVcsU0FBV3pELEdBR3JCLE9BREF2cEIsS0FBS3VwQixNQUFRQSxFQUNOdnBCLFNBY1ZsRyxFQUFRLG1CQUFtQixHQUFJLFdBRTlCLE1BQU8sQ0FRTmdJLE9BQVEsQ0FDUG1yQixvQ0FBcUMsZUFVdENDLFlBQWEsU0FBVWhlLEdBRWpCQSxJQUNKQSxFQUFNaVYsaUJBQ05qVixFQUFNa1YsbUJBR1AsSUFBSUMsRUFBTTdHLEtBQUtDLEtBQUs3Z0IsUUFBUyxzREFBdUQsQ0FDbkYwbkIsS0FBTXRrQixLQUFLb0gsTUFBTTZYLGtCQUdiak8sT0FBT29ELFFBQVNpUSxLQUVmcmtCLEtBQUtvSCxNQUFNM0UsWUFDZnpDLEtBQUtvSCxNQUFNM0UsV0FBV29ELE9BQVE3RixLQUFLb0gsT0FJcENySCxTQUFTdWIsT0FBT3ZULFFBQVMsZ0JBQWlCL0gsS0FBS29ILE9BRy9DcEgsS0FBSytILFFBQVMsZ0JBQWlCL0gsS0FBS29ILFlBZ0J4Q3ROLEVBQVEsZ0JBQWdCLENBQ3RCLG9CQUNBLGtCQUNBLG9CQUNBLG1CQUNBLGlCQUNBLG9CQUVELFNBQ0NxekIsRUFDQUMsRUFDQUMsRUFDQUMsRUFDQUMsRUFDQUMsR0FHRCxNQUFPLENBQ05MLFdBQVlBLEVBQ1pDLFNBQVVBLEVBQ1ZDLFdBQVlBLEVBQ1pDLFVBQVdBLEVBQ1hDLFFBQVNBLEVBQ1RDLFVBQVdBLEtBVWIxekIsRUFBUSx3QkFBd0IsQ0FDOUIscUJBQ0EsZ0JBQ0EsaUJBQ0UsU0FDRjJ6QixFQUNBQyxFQUNBQyxHQUdELE9BQU8sV0FhTixTQUFTbG5CLEVBQUsyUSxFQUFNNWIsRUFBTTZJLEVBQU1ULEdBRS9CLE9BQU93VCxFQUFNNWIsR0FLTixJQUFJNGIsRUFBTTViLEdBQVE2SSxFQUFNVCxJQUo5QmljLFFBQVFDLElBQUssSUFBTXRrQixFQUFPLGlCQUNuQixHQWtHVCxPQWxGQXdFLEtBQUt5WCxlQUFpQixTQUFVamMsRUFBTTZJLEVBQU1ULEdBRTNDLE9BQU82QyxFQUFLZ25CLEVBQWFqeUIsRUFBTTZJLEVBQU1ULElBYXRDNUQsS0FBS3VYLFVBQVksU0FBVS9iLEVBQU02SSxFQUFNVCxHQUV0QyxPQUFPNkMsRUFBS2luQixFQUFRbHlCLEVBQU02SSxFQUFNVCxJQVlqQzVELEtBQUs0dEIsWUFBYyxXQUtsQixJQUhBLElBQUlob0IsRUFBT3ZJLFVBQVUsR0FDcEJuQixFQUFJLEVBRUdtQixVQUFXbkIsSUFBTSxDQUV4QixJQUFJMnhCLEVBQVl4d0IsVUFBV25CLEdBQ3RCeXhCLEVBQU9FLEtBRU5qb0IsRUFBSzlELFFBQVU2ckIsRUFBT0UsR0FBWS9yQixTQUN0QzhELEVBQUs5RCxPQUFTaEMsRUFBRXVXLFNBQVV6USxFQUFLOUQsT0FBUTZyQixFQUFPRSxHQUFZL3JCLFNBRzNEOEQsRUFBTzlGLEVBQUV1VyxTQUFVelEsRUFBTStuQixFQUFPRSxLQUlqQzN4QixJQUdELE9BQU82RCxTQUFTRyxLQUFLMEIsT0FBUWdFLElBWTlCNUYsS0FBSzh0QixvQkFBc0IsU0FBVXR5QixFQUFNcWMsR0FFMUM0VixFQUFhanlCLEdBQVN1RSxTQUFTaUUsV0FBV3BDLE9BQVFpVyxJQVluRDdYLEtBQUsrdEIsZUFBaUIsU0FBVXZ5QixFQUFNcWMsR0FFckM2VixFQUFRbHlCLEdBQVNreUIsRUFBaUIsU0FBRTlyQixPQUFRaVcsSUFJdEM3WCxRQVdUbEcsRUFBUSxvQkFBb0IsR0FBSSxXQUU5QixPQUFPLFNBQVVnd0IsR0FFaEIsSUFBSTdRLEVBQU9qWixLQUNWc1csRUFBVXdULEVBQVN4VCxVQUFXLEVBUS9CdFcsS0FBS2d1QixRQUFVLFdBRWQvVSxFQUFLNkcsSUFBSyx3Q0FDVnhKLEdBQVUsR0FVWHRXLEtBQUtpdUIsT0FBUyxXQUViM1gsR0FBVSxFQUNWMkMsRUFBSzZHLElBQUssd0NBV1g5ZixLQUFLOGYsSUFBTSxXQUVKeEosR0FJUHhXLEVBQUVlLEtBQU14RCxVQUFXLFNBQVVnSCxHQUM1QndiLFFBQVFDLElBQUt6YixNQVdkckUsS0FBSzRLLE9BQVMsV0FFVDBMLEVBQ0oyQyxFQUFLK1UsVUFFTC9VLEVBQUtnVixVQU1EM1gsR0FDSjJDLEVBQUtnVixZQVlUbjBCLEVBQVEsc0JBQXNCLEdBQUksV0FTakMsT0FBTyxTQUFVOGlCLEdBR2hCLElBQUlzUixFQUFpQnRSLEVBNEJyQixPQTNCQTljLEVBQUVlLEtBQU1xdEIsRUFBZ0IsU0FBVTlXLEdBQ2pDdFgsRUFBRWUsS0FBTXVXLEVBQU0sU0FBVXVGLEdBQ3ZCQSxFQUFPd1IsUUFBUyxNQWNsQm51QixLQUFLeUcsSUFBTSxTQUFVa1csRUFBUXlSLEVBQVlobkIsR0FPeEMsT0FKSzhtQixFQUFnQkUsS0FDcEJ6UixFQUFTN2MsRUFBRThCLE9BQVErYSxFQUFRdVIsRUFBZ0JFLEtBR3JDelIsR0FJRDNjLFFBV1RsRyxFQUFRLG1CQUFtQixHQUFJLFdBRTdCLE9BQU8sU0FBVWdxQixFQUFRZ0csR0FFeEI5cEIsS0FBS3F1QixRQUFTLEVBRWQsSUFBSXBWLEVBQU9qWixLQUNWc3VCLEdBQVcsRUFDWEMsRUFBaUIsS0FDakJDLEVBQW9CMUUsRUFBUzBFLG1CQUFxQixJQUNsREMsRUFBVyxJQUFJMXVCLFNBQVNpRSxXQUN4QjBxQixFQUFVLElBQUkzdUIsU0FBU2lFLFdBeUR6QixTQUFTMnFCLEVBQWV0cUIsRUFBTXVxQixHQVk3QixNQVZLLFlBQWN2cUIsRUFBSzhaLFNBQ3ZCOVosRUFBS3dxQixRQUFVLElBR2hCeHFCLEVBQUs4WixPQUFTLFFBQ1QsaUJBQW9CeVEsSUFDeEJBLEVBQU0sQ0FBRUEsSUFFVHZxQixFQUFLd3FCLFFBQVV4cUIsRUFBS3dxQixRQUFRL3hCLE9BQVE4eEIsR0FFN0J2cUIsRUFVUixTQUFTeXFCLElBRVIsSUFBSXpxQixFQUFPLEdBQ1hBLEVBQUswcUIsUUFBVTlWLEVBQUsrVixzQkFDcEIzcUIsRUFBSzRxQixvQkFBc0JoVyxFQUFLZ1csb0JBQXFCNXFCLEVBQUswcUIsU0FDMUQxcUIsRUFBS2dxQixPQUFTcFYsRUFBS29WLE9BRW5CcmQsT0FBT3FHLGFBQWEwSSxNQUFNRCxJQUFLLGdDQUFpQ3piLEVBQU0sa0NBRXRFdEUsU0FBU3ViLE9BQU92VCxRQUFTLHNCQUF1QjFELEdBb0pqRCxTQUFTNnFCLEVBQXVCQyxHQUUvQixJQUFJQyxFQW9DSixPQWxDS0QsYUFBa0JwdkIsU0FBU3VVLE9BRS9COGEsRUFqRUYsU0FBaUNob0IsR0FFaEMsSUFDQ3FVLEVBREdELEVBQU8sR0FJWCxHQUFLcFUsRUFBTVgsSUFBSyxjQUNmLE9BQU8rVSxFQUtIZ0IsRUFBYXBWLEtBQVcsSUFBU0EsRUFBTVgsSUFBSyxlQUVoRCtVLEVBQU8xYixFQUFFeUIsTUFBTzZGLEVBQU0rTixZQUN0QnNHLEVBQVksU0FLWkQsRUFBT3BVLEVBQU1nTyxvQkFDYnFHLEVBQVksV0FJYixJQUFJNFQsRUFBWWpvQixFQUF3QixrQkFBSUEsRUFBTXdRLGtCQUFvQixHQWtCdEUsT0FqQkE0RCxFQUFPMWIsRUFBRXd2QixLQUFNOVQsRUFBTSxTQUFVakcsRUFBS3BDLEdBSW5DLE9BQUssSUFBTUEsRUFBSW5WLFFBQVMsT0FFWCxJQUFNcXhCLEVBQVFyeEIsUUFBU21WLEtBT2hDL0wsRUFBTW1VLGNBQ1ZDLEVBQU9wVSxFQUFNbVUsWUFBYUMsRUFBTUMsSUFHMUJELEVBc0JTK1QsQ0FBd0JKLEdBRWxDQSxFQUFPdlksbUJBRVg5VyxFQUFFZSxLQUFNc3VCLEVBQU92WCxrQkFBbUIsU0FBVXZjLEdBRTNDLElBQUlrUCxFQUFXMmtCLEVBQXVCQyxFQUFPMW9CLElBQUtwTCxJQUMzQ3lFLEVBQUV3VixRQUFTL0ssS0FDakI2a0IsRUFBYy96QixHQUFTa1AsS0FRbkJ6SyxFQUFFd1YsUUFBUzhaLEtBQ2pCQSxFQUFhdHdCLEdBQUtxd0IsRUFBTzFvQixJQUFLLFFBR3BCMG9CLGFBQWtCcHZCLFNBQVNpRSxhQUV0Q29yQixFQUFlLEdBQ2ZELEVBQU90dUIsS0FBTSxTQUFVdUcsR0FDdEIsSUFBSW9vQixFQUFnQk4sRUFBdUI5bkIsR0FDcEN0SCxFQUFFd1YsUUFBU2thLElBQ2pCSixFQUFhOXhCLEtBQU1reUIsTUFNZkosRUFXUixTQUFTNVMsRUFBYXBWLEdBRXJCLE9BQVd0SCxFQUFFK2MsU0FBVXpWLEVBQU10SSxLQUFRLElBQU1zSSxFQUFNdEksR0FBR2QsUUFBUyxTQWE5RCxTQUFTeXhCLEVBQXdCcm9CLEVBQU8vQyxHQUV2QyxJQUFJaXJCLEVBQU8sQ0FBRSxLQUFNLFdBRWRsb0IsRUFBTXdQLG1CQUNWMFksRUFBS3h5QixPQUFRc0ssRUFBTXdRLG1CQUdwQjlYLEVBQUVlLEtBQU1mLEVBQUV3dkIsS0FBTWpyQixFQUFNaXJCLEdBQVEsU0FBVS9aLEVBQUtsYSxHQUV2Q3lFLEVBQUU0VixRQUFTdE8sRUFBTVgsSUFBS3BMLEdBQVFrYSxZQUMzQm5PLEVBQU1zTixnQkFBaUJyWixHQUM5QitMLEVBQU1xTixlQUFnQnBaLEdBQVNrYSxLQU1qQ25PLEVBQU1zb0IsTUFBTyxjQWFkLFNBQVNDLEVBQWtCdHJCLEdBRzFCLElBQUl1ckIsRUFBVyxDQUNkam5CLE9BQVE4bEIsRUFDUm9CLE1BQU9uQixHQWdDUixPQTdCQTV1QixFQUFFZSxLQUFNK3VCLEVBQVUsU0FBVUUsRUFBTTNjLEdBRWpDLEdBQUs5TyxFQUFNOE8sR0FBUSxDQUVsQixJQUFJNGMsRUFBUyxHQUViandCLEVBQUVlLEtBQU13RCxFQUFNOE8sR0FBUSxTQUFVNmMsR0FHeEJBLEVBQUtyUSxNQU1Yb1EsRUFBT3p5QixLQUFNMHlCLEVBQUtyUSxPQUpsQm1RLEVBQUtqcUIsT0FBUW1xQixFQUFLbHhCLE1BVWZpeEIsRUFBT3R6QixRQUNYcUQsRUFBRThCLE9BQVF5QyxFQUFNc3FCLEVBQWV0cUIsRUFBTTByQixPQU9qQzFyQixFQWlHUixTQUFTNHJCLEVBQWlCNXJCLEdBR3pCLE9BQU9BLEVBQUs2ckIsU0FJUDdyQixFQUFLNnJCLFVBQ1Q3ckIsRUEzRkYsU0FBUzhyQixFQUF3QjlyQixFQUFNK1MsRUFBTXZOLEVBQVF1bUIsR0FFcEQsSUFBTy9yQixFQUFNK1MsR0FDWixPQUFPL1MsRUFHUixHQUFLd0YsRUFBT3BELElBQUsyUSxhQUFrQnJYLFNBQVN1VSxNQUFRLENBRW5ELElBQUkwYixFQUFPM3JCLEVBQU0rUyxHQUVqQixHQUFLNFksRUFBS3JRLE1BRVQ3ZixFQUFFOEIsT0FBUXd1QixFQUFXekIsRUFBZXlCLEVBQVdKLEVBQUtyUSxZQUU5QyxDQUVOLElBQUl2WSxFQUFReUMsRUFBT3BELElBQUsyUSxHQUduQjRZLEVBQUtseEIsSUFBTWt4QixFQUFLSyxVQUNwQmpwQixFQUFNeU8sSUFBSyxLQUFNbWEsRUFBS2x4QixXQUNmc0ksRUFBTXNOLGdCQUFnQjVWLElBRTlCMndCLEVBQXdCcm9CLEVBQU80b0IsR0FHMUI1b0IsRUFBTXdQLG1CQUVWOVcsRUFBRWUsS0FBTXVHLEVBQU13USxrQkFBbUIsU0FBVWIsR0FDMUNqWCxFQUFFOEIsT0FBUXlDLEVBQU0rUyxHQUFRK1ksRUFBd0I5ckIsRUFBTStTLEdBQVFMLEVBQVczUCxFQUFPZ3BCLFlBT3hFdm1CLEVBQU9wRCxJQUFLMlEsYUFBa0JyWCxTQUFTaUUsWUFFbERsRSxFQUFFZSxLQUFNd0QsRUFBTStTLEdBQVEsU0FBVTRZLEVBQU1qeUIsR0FFckMsR0FBS2l5QixFQUFLclEsTUFFVDdmLEVBQUU4QixPQUFRd3VCLEVBQVd6QixFQUFleUIsRUFBV0osRUFBS3JRLFlBRTlDLENBRU4sSUFBSXZZLEVBQVF5QyxFQUFPcEQsSUFBSzJRLEdBQU8zUSxJQUFLdXBCLEVBQUtLLFNBR3BDTCxFQUFLbHhCLElBQU1reEIsRUFBS0ssVUFDcEJqcEIsRUFBTXlPLElBQUssS0FBTW1hLEVBQUtseEIsV0FDZnNJLEVBQU1zTixnQkFBZ0I1VixJQUU5QjJ3QixFQUF3QnJvQixFQUFPNG9CLEdBRzFCNW9CLEVBQU13UCxtQkFFVjlXLEVBQUVlLEtBQU11RyxFQUFNd1Esa0JBQW1CLFNBQVViLEdBQzFDalgsRUFBRThCLE9BQVF5QyxFQUFNK1MsR0FBUStZLEVBQXdCOXJCLEVBQU0rUyxHQUFRclosR0FBU2daLEVBQVczUCxFQUFPZ3BCLFNBVzlGLE9BQU9BLEVBcUJDRCxDQUF3QjlyQixFQUFLNnJCLFFBQVMsV0FBWXBNLEVBQVF6ZixJQUczREEsRUF3T1IsT0FoTkFyRSxLQUFLZ3ZCLG9CQUFzQixXQUUxQixNQUFPLENBQ05ybUIsT0FBUThsQixFQUFTdG5CLE1BQU8sTUFDeEIwb0IsTUFBT25CLEVBQVF2bkIsTUFBTyxNQUN0QitvQixRQUFTaEIsRUFBdUJwTCxLQWFsQzlqQixLQUFLaXZCLG9CQUFzQixTQUFVRixHQWFwQyxZQVhLLElBQXVCQSxJQUMzQkEsRUFBVTlWLEVBQUsrVix5QkFJSmx2QixFQUFFaUssS0FBTWdsQixFQUFTLFNBQVUxcUIsR0FFdEMsT0FBUyxJQUFVdkUsRUFBRXdWLFFBQVNqUixNQWNoQ3JFLEtBQUtzd0IsU0FBVyxXQUNWaEMsRUFDSnZGLEdBQUd3SCxVQUFVQyxhQTdiZixXQUdDLElBQUt2WCxFQUFLb1YsT0FBVixDQUlBLElBQUlVLEVBQVU5VixFQUFLK1Ysc0JBR2QvVixFQUFLZ1csb0JBQXFCRixLQUU5QkEsRUFBUWp3QixHQUFLZ2xCLEVBQU9yZCxJQUFLLE1BRXpCK1csS0FBSzZCLEtBQUsvakIsS0FBTSxDQUNmK0ksS0FBTSxDQUNMaWIsT0FBUSxlQUNSQyxZQUFhLFlBQ2JDLFVBQVd1UCxFQUFRandCLEdBQ25CdVksYUFBY29aLEtBQUtDLFVBQVczQixJQUUvQmpKLFdBQVksV0FFWDlVLE9BQU9xRyxhQUFhMEksTUFBTUQsSUFBSyxzQ0FBdUNpUCxFQUFTLHdDQUUvRTlWLEVBQUtvVixRQUFTLEVBRWR0dUIsU0FBU3ViLE9BQU92VCxRQUFTLGlCQUFrQmtSLElBRzVDMEcsTUFBTyxTQUFVQyxFQUFLekIsRUFBUXdCLEdBRTdCM08sT0FBT3FHLGFBQWEwSSxNQUFNRCxJQUFLLHFDQUFzQ3piLEtBQU0sdUNBRTNFNFUsRUFBS29WLFFBQVMsRUFFZHR1QixTQUFTdWIsT0FBT3ZULFFBQVMsaUJBQWtCa1IsRUFBTSxDQUNoRGtGLE9BQVEsUUFDUjBRLFFBQVNqUCxFQUFJK1EsYUFBZSxLQUFPaFIsRUFBUSxJQUFNeEIsRUFBUSxPQUkzRGxJLFFBQVMsU0FBVStKLEdBRVhBLEVBQUkzSSxlQUlYckcsT0FBT3FHLGFBQWEwSSxNQUFNRCxJQUFLLHVDQUF3Q0UsRUFBSyx5Q0FFNUVBLEVBQUkzSSxhQUFlc1ksRUFBa0IzUCxFQUFJM0ksY0FDekMySSxFQUFJM0ksYUFBZTRZLEVBQWlCalEsRUFBSTNJLGNBRXhDNEIsRUFBS29WLFFBQVMsRUFFZHR1QixTQUFTdWIsT0FBT3ZULFFBQVMsaUJBQWtCa1IsRUFBTStHLEVBQUkzSSxvQkF3WXZEdVosSUFZRjV3QixLQUFLNndCLG1CQUFxQixTQUFVQyxHQUNuQ3RDLEVBQW9Cc0MsRUFDZnZDLEdBQ0p3QyxjQUFleEMsR0FFWEMsSUFDSkQsRUFBaUJ5QyxZQUFhbEMsRUFBbUJOLEtBb0JuRHp1QixTQUFTdWIsT0FBTzVDLEdBQUksaUJBQWtCLFNBQVV0UixHQUcxQ29WLEVBQWFwVixJQUlsQnFuQixFQUFTM3FCLElBQUtoRSxFQUFFeUIsTUFBTzZGLEVBQU0rTixlQVM5QnBWLFNBQVN1YixPQUFPNUMsR0FBSSxnQkFBaUIsU0FBVXRSLEdBRzlDLElBQUtvVixFQUFhcFYsR0FBbEIsQ0FJQSxJQUFJL0MsRUFBT3ZFLEVBQUV5QixNQUFPNkYsRUFBTStOLFlBRXJCL04sRUFBTW1SLGVBQ1ZsVSxFQUFLdkYsR0FBS3NJLEVBQU1tUixnQkFHakJtVyxFQUFRNXFCLElBQUtPLE1Bb0JkMUssRUFBR2tQLFVBQVc2UCxHQUFJLGlCQUFrQixTQUFVeEosRUFBTzdLLEdBR3BELElBQUs0VSxFQUFLb1YsT0FBVixDQUlBLElBQUlVLEVBQVU5VixFQUFLK1Ysc0JBR2QvVixFQUFLZ1csb0JBQXFCRixLQUU5QkEsRUFBUWp3QixHQUFLZ2xCLEVBQU9yZCxJQUFLLE1BQ3pCd1MsRUFBS29WLFFBQVMsRUFDZGhxQixFQUFLZ1QsYUFBZW9aLEtBQUtDLFVBQVczQixJQUlyQy9kLE9BQU9xRyxhQUFhMEksTUFBTUQsSUFBSyxpQ0FBa0N6YixFQUFNLG1DQUV2RXRFLFNBQVN1YixPQUFPdlQsUUFBUyxpQkFBa0JrUixNQVM1Q3RmLEVBQUdrUCxVQUFXNlAsR0FBSSxpQkFBa0IsU0FBVXhKLEVBQU83SyxHQUU3Q0EsRUFBS2dULGVBSVpyRyxPQUFPcUcsYUFBYTBJLE1BQU1ELElBQUssaUNBQWtDemIsRUFBTSxtQ0FFdkVBLEVBQUtnVCxhQUFlc1ksRUFBa0J0ckIsRUFBS2dULGNBQzNDaFQsRUFBS2dULGFBQWU0WSxFQUFpQjVyQixFQUFLZ1QsY0FFMUM0QixFQUFLb1YsUUFBUyxFQUVkdHVCLFNBQVN1YixPQUFPdlQsUUFBUyxpQkFBa0JrUixFQUFNNVUsRUFBS2dULGlCQVN2RDFkLEVBQUdrUCxVQUFXNlAsR0FBSSxrQkFBbUIsU0FBVXhKLEVBQU83SyxHQUVyRDJNLE9BQU9xRyxhQUFhMEksTUFBTUQsSUFBSyxrQ0FBbUN6YixFQUFNLG9DQUV4RTRVLEVBQUtvVixRQUFTLEVBRWR0dUIsU0FBU3ViLE9BQU92VCxRQUFTLGlCQUFrQmtSLEVBQU0sQ0FDaERrRixPQUFRLFFBQ1IwUSxRQUFTeHFCLEVBQUtzc0IsYUFBZSxLQUFPdHNCLEVBQUs4WixPQUFTLElBQU05WixFQUFLNHNCLFdBQVksYUF4cUJwRSxJQUF1QmxJLEdBQUd3SCxZQUU5QnZmLE9BQU9xRyxhQUFhMEksTUFBTUQsSUFBSyx5REFDL0J3TyxHQUFXLEdBS1JFLEdBQ0p2VixFQUFLNFgsbUJBQW9CckMsR0FJMUI3MEIsRUFBR3FYLFFBQVMwSCxHQUFJLGVBQWdCLFdBRS9CLEdBQUtPLEVBQUtnVyxzQkFFVCxPQURBSCxJQUNPLG1EQXdxQkg5dUIsUUFXVGxHLEVBQVEsZUFBZSxDQUNyQixvQkFDQSxrQkFDQSxtQkFDQSxvQkFDRSxTQUNGcXpCLEVBQ0FDLEVBQ0FFLEVBQ0FFLEdBR0QsT0FBT3p0QixTQUFTRyxLQUFLMEIsT0FBUTlCLEVBQUV1VyxTQUFVLENBUXhDbEIsV0FBWSxXQUNYLE1BQU8sQ0FDTitiLFVBQVdseEIsS0FBS29ILE1BQU10SSxHQUN0QnF5QixrQkFBbUJueEIsS0FBS29ILE1BQU1YLElBQUssb0JBUXJDMnFCLFVBQVcsZ0NBUVh0dkIsT0FBUWhDLEVBQUV1VyxTQUFVLENBQ25CZ2IscUJBQXNCLHFCQUN0QkMsbUJBQW9CLG1CQUNwQkMseUJBQTBCLHlCQUMxQkMsc0JBQXVCLGVBQ3ZCQyxzQkFBdUIsZUFDdkJDLDBCQUEyQixXQUMzQkMsNEJBQTZCLGNBQzNCeEUsRUFBV3JyQixPQUFRc3JCLEVBQVN0ckIsT0FBUTByQixFQUFVMXJCLFFBUWpEaEQsR0FBSSxXQUNILE1BQU8sZUFBaUJrQixLQUFLb0gsTUFBTXRJLElBT3BDK0MsUUFBUyxLQU1Uc0ssU0FBVTRjLEdBQUc1YyxTQUFVLHdCQVF2QnhJLFdBQVksV0FFWDNELEtBQUsrRixTQUVML0YsS0FBS3NMLFNBQVV0TCxLQUFLb0gsTUFBTyxTQUFVcEgsS0FBSytGLFFBRTFDaEcsU0FBU3ViLE9BQU81QyxHQUFLLGtCQUFtQjFZLEtBQUtxb0IsVUFBV3JvQixNQUN4REQsU0FBU3ViLE9BQU81QyxHQUFLLG1CQUFvQjFZLEtBQUtxb0IsVUFBV3JvQixPQVUxRCtGLE9BQVEsV0FTUCxPQVBBL0YsS0FBS29FLElBQUk4SCxLQUFNbE0sS0FBS21NLFNBQVVuTSxLQUFLb0gsUUFDbkNwSCxLQUFLOHJCLCtCQUNBOXJCLEtBQUtvSCxNQUFNWCxJQUFLLGFBQ3BCekcsS0FBS29FLElBQUlFLFNBQVUsWUFFbkJ0RSxLQUFLb0UsSUFBSTBJLFlBQWEsWUFFaEI5TSxNQVdSNHhCLHVCQUF3QixXQUV2Qjd4QixTQUFTdWIsT0FBT3ZULFFBQVMsa0JBQW1CL0gsS0FBS29ILE1BQU8sY0FDeERwSCxLQUFLb0gsTUFBTXlPLElBQUssYUFBYSxJQVc5QmdjLG1CQUFvQixXQUVuQjl4QixTQUFTdWIsT0FBT3ZULFFBQVMsa0JBQW1CL0gsS0FBS29ILE1BQU8sVUFDeERwSCxLQUFLb0gsTUFBTXlPLElBQUssYUFBYSxJQVc5QmljLGlCQUFrQixXQUVqQi94QixTQUFTdWIsT0FBT3ZULFFBQVMsa0JBQW1CL0gsS0FBS29ILE1BQU8sUUFDeERwSCxLQUFLb0gsTUFBTXlPLElBQUssYUFBYSxJQVk5QndTLFVBQVcsU0FBVWpoQixHQUVmcEgsS0FBS29ILE1BQU10SSxLQUFPc0ksRUFBTXRJLElBQzVCa0IsS0FBS29ILE1BQU15TyxJQUFLLGFBQWEsSUFZL0JrYyxhQUFjLFNBQVU3aUIsR0FDdkJBLEVBQU1pVixpQkFDTm5rQixLQUFLZ3lCLGlCQUFrQixTQVV4QkMsYUFBYyxTQUFVL2lCLEdBQ3ZCQSxFQUFNaVYsaUJBQ05ua0IsS0FBS2d5QixpQkFBa0IsU0FVeEJBLGlCQUFrQixTQUFVN08sR0FFM0IsSUFDQytPLEVBREdDLEVBQVlueUIsS0FBS29ILE1BQU0zRSxXQUd0QixTQUFXMGdCLEVBQ2YrTyxFQUFhQyxFQUFVdG9CLE9BQU9rWixXQUNuQixTQUFXSSxJQUN0QitPLEVBQWFDLEVBQVV0b0IsT0FBT3FaLFlBRzFCZ1AsSUFFSkMsRUFBVXRzQixPQUFRN0YsS0FBS29ILE9BQ3ZCOHFCLEVBQVdwUCxXQUFZOWlCLEtBQUtvSCxPQUM1QjhxQixFQUFXcmMsSUFBSyxhQUFhLE1BTTdCc1gsRUFBWUMsRUFBVUUsRUFBV0UsTUFTckMxekIsRUFBUSxtQkFBbUIsQ0FBRSxlQUFnQixxQkFBdUIsU0FBVXM0QixFQUFZL0UsR0FFekYsT0FBT3R0QixTQUFTNEIsZUFBZUMsT0FBUTlCLEVBQUV1VyxTQUFVLENBRWxEK2EsVUFBVyxlQU1YMXVCLFVBQVcwdkIsRUFNWHR2QixZQUFZLEVBTVpRLFVBQVUsRUFFVkMsZ0JBQWlCLENBQ2hCNEssTUFBTSxFQUNOa2tCLFlBQWEsZ0JBQ2JDLE9BQVEsT0FDUkMsT0FBUSxlQUNSaHNCLE1BQU8sZUFDUG1ULFlBQWEseUNBR2Q4WSxlQUFnQixTQUFVL3ZCLEdBQ3pCOUksRUFBRyxpQkFBa0IySyxTQUFVLGFBR2hDbXVCLGNBQWUsU0FBVWh3QixHQUN4QjlJLEVBQUcsaUJBQWtCbVQsWUFBYSxhQVluQzhCLFVBQVksU0FBVU0sRUFBT0MsR0FFNUIsSUFBSUMsRUFBbUJwUCxLQUFLeUMsV0FBV2dFLElBQUswSSxFQUFHM0ksS0FBS2pDLEtBQU0sbUJBRXpEOEssRUFEdUJyUCxLQUFLdUksa0JBQ0lnQyxXQUFXeE0sTUFBT29SLEVBQUczSSxPQUVwQyxHQUFiNkksR0FBa0JELEdBQ3RCcFAsS0FBS3lDLFdBQVdvRCxPQUFRdUosR0FHekJwUCxLQUFLZ04sZ0NBQ0xoTixLQUFLZ0ksMEJBRURoSSxLQUFLa0UsOEJBQ1JsRSxLQUFLNkgsTUFBTyxXQUFZLENBQUV1SCxpQkFBbUJBLEVBQWtCQyxTQUFXQSxJQUUxRXJQLEtBQUsrSCxRQUFTLFdBQVlxSCxFQUFrQkMsS0FLNUNnZSxNQVNKdnpCLEVBQVEsZ0JBQWdCLENBQ3RCLG1CQUNBLGtCQUNBLG1CQUNBLG9CQUNFLFNBQ0Y0NEIsRUFDQXRGLEVBQ0FFLEVBQ0FFLEdBR0QsT0FBT3p0QixTQUFTRyxLQUFLMEIsT0FBUTlCLEVBQUV1VyxTQUFVLENBUXhDbEIsV0FBWSxXQUNYLE1BQU8sQ0FDTitiLFVBQVdseEIsS0FBS29ILE1BQU10SSxLQVF4QnN5QixVQUFXLGlDQVFYdHZCLE9BQVFoQyxFQUFFdVcsU0FBVSxDQUVuQnBVLE1BQVMsU0FDVDB3QixnQkFBaUIsU0FDakJDLGtCQUFtQixXQUNuQkMsMkJBQTRCLFdBQzVCQyw2QkFBOEIsYUFFOUJDLDJCQUE0QixpQkFFMUIzRixFQUFTdHJCLE9BQVEwckIsRUFBVTFyQixRQVE5QmhELEdBQUksV0FDSCxNQUFPLGdCQUFrQmtCLEtBQUtvSCxNQUFNdEksSUFPckMrQyxRQUFTLEtBTVRzSyxTQUFVNGMsR0FBRzVjLFNBQVUseUJBUXZCeEksV0FBWSxXQUVYM0QsS0FBSytGLFNBQ0wvRixLQUFLc0wsU0FBVXRMLEtBQUtvSCxNQUFPLFNBQVVwSCxLQUFLK0YsUUFDMUMvRixLQUFLc0wsU0FBVXRMLEtBQUtvSCxNQUFPLG1CQUFvQnBILEtBQUtnekIsaUJBQ3BEaHpCLEtBQUtpekIsZUFBZXh3QixXQUFXaVcsR0FBSSxNQUFPMVksS0FBS2t6QixjQUFlbHpCLE1BRTlEQSxLQUFLbXpCLFlBQWMsS0FFbkJwekIsU0FBU3ViLE9BQU81QyxHQUFJLGFBQWMxWSxLQUFLb3pCLE9BQVFwekIsTUFDL0NELFNBQVN1YixPQUFPNUMsR0FBSSxlQUFnQjFZLEtBQUtxekIsU0FBVXJ6QixPQVdwRCtGLE9BQVEsV0FtQlAsT0FqQkEvRixLQUFLb0UsSUFBSThILEtBQU1sTSxLQUFLbU0sU0FBVW5NLEtBQUtvSCxNQUFNb2lCLFdBRXpDeHBCLEtBQUs4ckIsK0JBRUw5ckIsS0FBS2l6QixlQUFpQixJQUFJUCxFQUFnQixDQUN6Q1ksR0FBSXR6QixLQUFLb0UsSUFBSTJGLEtBQU0saUJBQ25CdEgsV0FBWXpDLEtBQUtvSCxNQUFNWCxJQUFLLGFBRTdCekcsS0FBS2l6QixlQUFlbHRCLFNBQ3BCL0YsS0FBS2l6QixlQUFldmEsR0FBSSxZQUFhMVksS0FBS2l6QixlQUFlVCxnQkFDekR4eUIsS0FBS2l6QixlQUFldmEsR0FBSSxXQUFZMVksS0FBS2l6QixlQUFlUixlQUd4RHp5QixLQUFLaXpCLGVBQWV2YSxHQUFJLG1CQUFvQjFZLEtBQUt1ekIscUJBQXNCdnpCLE1BRXZFQSxLQUFLd3pCLDBCQUVFeHpCLE1BSVJ1ekIscUJBQXNCLFNBQVVFLEVBQVNDLEdBRXhDM3pCLFNBQVN1YixPQUFPdlQsUUFBUyx1QkFBd0IsQ0FDaEQwckIsUUFBU0EsRUFDVEMsU0FBVUEsS0FhWkwsU0FBVSxTQUFVbmtCLEVBQU95a0IsUUFFckIsSUFBdUJBLElBQzNCQSxHQUFTLEdBR0x6a0IsSUFDSkEsRUFBTWtWLGtCQUNObFYsRUFBTWlWLGtCQUdQbmtCLEtBQUtvRSxJQUFJMEksWUFBYSxZQUFhL0MsS0FBTSxrQkFBbUIrQyxZQUFhLGlCQUNwRTZtQixHQUNKM3pCLEtBQUtvSCxNQUFNeU8sSUFBSyxhQUFhLEdBRTlCOVYsU0FBU3ViLE9BQU92VCxRQUFTLGlCQUFrQi9ILEtBQUtvSCxRQVlqRGdzQixPQUFRLFNBQVVsa0IsRUFBT3lrQixRQUVuQixJQUF1QkEsSUFDM0JBLEdBQVMsR0FHTHprQixJQUNKQSxFQUFNa1Ysa0JBQ05sVixFQUFNaVYsa0JBR1Bua0IsS0FBS29FLElBQUlFLFNBQVUsWUFDZHF2QixHQUNKM3pCLEtBQUtvSCxNQUFNeU8sSUFBSyxhQUFhLEdBRTlCOVYsU0FBU3ViLE9BQU92VCxRQUFTLGlCQUFrQi9ILEtBQUtvSCxRQUlqRG9zQix3QkFBeUIsV0FFeEIsSUFBSWhKLEVBQU94cUIsS0FBS29FLElBQUkyRixLQUFNLG1CQUVyQi9KLEtBQUtvSCxNQUFNWCxJQUFLLFdBQVk2TyxVQUVoQ2tWLEVBQUtTLE9BSUxULEVBQUs5ZixRQWFQd29CLGNBQWUsU0FBVTlyQixHQUV4QnBILEtBQUtpekIsZUFBZXh3QixXQUFXc0YsUUFBUyxXQUN4Q1gsRUFBTXlPLElBQUssaUJBQWtCN1YsS0FBS29ILE1BQU1YLElBQUssT0FDN0N6RyxLQUFLb3pCLFVBSU5RLGNBQWUsU0FBVTFrQixHQUduQnZWLEVBQUd1VixFQUFNcUMsUUFBU2dVLFNBQVUsY0FFaEM1ckIsRUFBRyxrQkFBbUJtVCxZQUFhLGlCQUNuQ25ULEVBQUd1VixFQUFNcUMsUUFBU2pOLFNBQVUsbUJBYzlCMHVCLGdCQUFpQixTQUFVNXJCLEVBQU8xSixHQUU1QkEsRUFDSnNDLEtBQUtvekIsT0FBUSxNQUFNLEdBRW5CcHpCLEtBQUtxekIsU0FBVSxNQUFNLEtBS3JCakcsRUFBVUUsRUFBV0UsTUFTekIxekIsRUFBUSxvQkFBb0IsQ0FBRSxnQkFBaUIscUJBQXVCLFNBQVUrNUIsRUFBYXhHLEdBRTVGLE9BQU90dEIsU0FBUzRCLGVBQWVDLE9BQVE5QixFQUFFdVcsU0FBVSxDQU1sRGlkLEdBQUksaUJBRUp4eEIsT0FBUyxDQUNSZ3lCLG9FQUFzRSx3QkFFdEU3eEIsTUFBVSwwQkFDVjh4QiwyQkFBNkIsMEJBQzdCNXhCLFFBQVksY0FPYk8sVUFBV214QixFQU1YeHdCLGtCQUFrQixFQU1sQlAsWUFBWSxFQU1aUSxVQUFVLEVBRVZDLGdCQUFpQixDQUNoQjRLLE1BQU0sRUFDTm1rQixPQUFRLE9BQ1JDLE9BQVEsZ0JBQ1Joc0IsTUFBTyxnQkFDUG1ULFlBQWEsMENBR2Q4WSxlQUFnQixTQUFVL3ZCLEdBQ3pCekMsS0FBS29FLElBQUlFLFNBQVUsYUFHcEJtdUIsY0FBZSxTQUFVaHdCLEdBQ3hCekMsS0FBS29FLElBQUkwSSxZQUFhLGNBR3JCdWdCLE1BU0p2ekIsRUFBUSxlQUFlLENBQUUsb0JBQXFCLG1CQUFxQixTQUFVazZCLEVBQWlCNUcsR0FFN0YsT0FBT3J0QixTQUFTRyxLQUFLMEIsT0FBUTlCLEVBQUV1VyxTQUFVLENBUXhDbEIsV0FBWSxXQUNYLE1BQU8sQ0FDTitiLFVBQVdseEIsS0FBS29ILE1BQU10SSxLQVF4QncwQixHQUFJLHFCQU1KenhCLFFBQVMsTUFNVHNLLFNBQVU0YyxHQUFHNWMsU0FBVSx3QkFRdkJ4SSxXQUFZLFdBS1gzRCxLQUFLK0YsU0FFTC9GLEtBQUtpMEIsZ0JBQWtCLElBQUlELEVBQWlCLENBQzNDdnhCLFdBQVl6QyxLQUFLb0gsTUFBTVgsSUFBSyxjQUU3QnpHLEtBQUtpMEIsZ0JBQWdCbHVCLFNBRXJCL0YsS0FBS2kwQixnQkFBZ0J2YixHQUFJLFlBQWExWSxLQUFLaTBCLGdCQUFnQnpCLGdCQUUzRHh5QixLQUFLaTBCLGdCQUFnQnZiLEdBQUksV0FBWTFZLEtBQUtpMEIsZ0JBQWdCeEIsZUFFMUR6eUIsS0FBS2kwQixnQkFBZ0J2YixHQUFJLG1CQUFvQjFZLEtBQUtrMEIsdUJBRWxEbDBCLEtBQUtzTCxTQUFVdEwsS0FBS29ILE1BQU1YLElBQUssWUFBYSxNQUFPekcsS0FBS20wQixnQkFFeERwMEIsU0FBU3ViLE9BQU81QyxHQUFJLGlCQUFrQjFZLEtBQUtvMEIsa0JBQW1CcDBCLE1BRTlERCxTQUFTdWIsT0FBTzVDLEdBQUksaUJBQWtCMVksS0FBS3EwQixlQUFnQnIwQixNQUUzREQsU0FBU3ViLE9BQU81QyxHQUFJLGtCQUFtQjFZLEtBQUt1ekIscUJBQXNCdnpCLE9BVW5FK0YsT0FBUSxXQUVQLE9BREEvRixLQUFLb0UsSUFBSThILEtBQU1sTSxLQUFLbU0sU0FBVW5NLEtBQUtvSCxRQUM1QnBILE1BR1J1ekIscUJBQXNCLFNBQVVuc0IsR0FHL0IsSUFBSTRhLEVBQVVoaUIsS0FBS29ILE1BQU1YLElBQUssWUFBYUEsSUFBS1csRUFBTVgsSUFBSyxtQkFDM0R6RyxLQUFLaTBCLGdCQUFnQjN1QixpQkFBa0IwYyxJQWF4Q2tTLHNCQUF1QixTQUFVVCxFQUFTQyxHQUV6QzV6QixFQUFFZSxLQUFNNHlCLEVBQVMsU0FBVXJzQixHQUMxQkEsRUFBTXlPLElBQUssYUFBYSxLQUd6Qi9WLEVBQUVlLEtBQU02eUIsRUFBVSxTQUFVdHNCLEdBQzNCQSxFQUFNeU8sSUFBSyxhQUFhLE1BWTFCc2UsZUFBZ0IsU0FBVS9zQixHQUV6QnBILEtBQUtpMEIsZ0JBQWdCM3VCLGlCQUFrQjhCLElBWXhDZ3RCLGtCQUFtQixTQUFVaHRCLEdBRTVCLElBQUl3YyxFQUFXeGMsRUFBTVgsSUFBSyxhQUFnQixDQUFFVyxHQUFVLEdBQ3REcEgsS0FBS2kwQixnQkFBZ0J6dUIsa0JBQW1Cb2UsS0FJdkN3SixNQVNKdHpCLEVBQVEsdUJBQXVCLEdBQUksV0FFbEMsT0FBT2lHLFNBQVNHLEtBQUswQixPQUFROUIsRUFBRXVXLFNBQVUsQ0FNeEN2VSxPQUFRLENBQ1B3eUIsb0NBQXFDLGdCQVF0Q2hZLE9BQVEsR0FNUnphLFFBQVMsTUFNVHNLLFNBQVU0YyxHQUFHNWMsU0FBVSxpQ0FnQnZCb29CLGtCQUFtQixXQUNsQixPQUFPejBCLEVBQUV5TSxPQUFRdk0sS0FBS3NjLE9BQVEsU0FBVVksR0FDdkMsT0FBT2xkLEtBQUt3MEIsZ0JBQWlCdFgsRUFBTTlGLE9BQ2pDcFgsT0FTSnkwQixXQUFZLFdBRVgsT0FBT3owQixLQUFLb0gsTUFBTXNWLHVCQVduQmdZLGdCQUFpQixTQUFVQyxHQUUxQixJQUFJNzFCLEVBQUssUUFBVWtCLEtBQUtvSCxNQUFNWCxJQUFLLFFBQVcsb0JBQXNCa3VCLEVBRXBFLE1BQUssY0FBZ0IzakIsT0FBTzRqQixjQUNsQixXQUFhNWpCLE9BQU80akIsYUFBYUMsUUFBUy8xQixJQWNyRGcyQixxQkFBc0IsU0FBVTVYLEdBRS9CLE9BQU9BLEVBQU1HLGlCQUFtQkgsRUFBTUcsaUJBQW1CSCxFQUFNQyxXQVdoRTRYLFdBQVksU0FBVTNkLEdBQ3JCLE9BQVUsSUFBTUEsRUFBS3BaLFFBQVMsV0FVL0JnM0IsaUJBQWtCLFNBQVU1ZCxHQUczQixPQUFVLElBREUsQ0FBRSxjQUFlLGFBQWMsU0FBVSxPQUFRLGVBQ3ZDcFosUUFBU29aLEVBQUt4YSxRQUFTLFVBQVcsTUFXekQ0M0IsZ0JBQWlCLFNBQVVwZCxHQUcxQixPQUFVLElBREUsQ0FBRSxTQUFVLGlCQUNGcFosUUFBU29aLEVBQUt4YSxRQUFTLFVBQVcsTUFXekRxNEIsd0JBQXlCLFNBQVUvWCxHQUVsQyxPQUFTQSxFQUFNZ1ksWUFBY2wxQixLQUFLb0gsTUFBTVgsSUFBS3lXLEVBQU1HLG1CQVVwRHRYLE9BQVEsV0FTUCxPQVBBL0YsS0FBS29FLElBQUk4SCxLQUFNbE0sS0FBS21NLFNBQVVuTSxPQUc5QkYsRUFBRWUsS0FBTWIsS0FBS3UwQixvQkFBcUIsU0FBVXJYLEdBQzNDbGQsS0FBS20xQixjQUFlalksSUFDbEJsZCxNQUVJQSxNQVdSbTFCLGNBQWUsU0FBVWpZLEdBRXhCLElBQUlqRSxFQUFPalosS0FFWCtvQixHQUFHZ0IsT0FBT2xrQixPQUFRcVgsRUFBTXBlLElBQ3hCb2UsRUFBTTRNLFNBQVNJLFFBQVFHLE1BQVEsU0FBVU4sR0FFeEMsSUFBSW1CLEVBQU12eEIsRUFBRyxJQUFNb3dCLEVBQU9qckIsSUFDekJxc0IsRUFBVUQsRUFBSWpnQixRQUFTLHlCQUN2Qm1nQixFQUFTRCxFQUFRcGhCLEtBQU0sZUFDdkIxTyxFQUFPNnZCLEVBQUkzbUIsS0FBTSxrQkFFYjZtQixFQUFPM3VCLFFBQ1gydUIsRUFBT0MsVUFBV0YsRUFBUXBoQixLQUFNLHFCQUlqQ2dnQixFQUFPclIsR0FBSSxTQUFVLFNBQVV4SixHQUM5QitKLEVBQUs3UixNQUFNeU8sSUFBS3hhLEVBQU0wdEIsR0FBR2dCLE9BQU91QixXQUFZdkIsRUFBT2pyQixPQUlwRG9zQixFQUFJeFMsR0FBSSxRQUFTLFNBQVV4SixHQUMxQitKLEVBQUs3UixNQUFNeU8sSUFBS3hhLEVBQU02dkIsRUFBSTNWLFNBSTNCNFYsRUFBUXpTLEdBQUksUUFBUyxnQ0FBaUMsV0FDckRqWixXQUFZLFdBQ1h5ckIsRUFBSW5qQixRQUFTLFVBQ1gsT0FJTGdoQixHQUFHZ0IsT0FBT3BtQixXQUFZdVosRUFBTXBlLEdBQUlvZSxFQUFNNE0sV0FZdkNzTCxzQkFBdUIsU0FBVXh4QixFQUFTdVosR0FFekMsSUFBSWpSLEVBQU8sR0FDVjBYLEVBQVc1akIsS0FBS29ILE1BQU1YLElBQUswVyxHQUU1QixTQUFTa1ksRUFBYXpYLEVBQU9ySSxHQUU1QixNQUFPLGtCQUFvQkEsRUFBTSxJQUFNelYsRUFBRThqQixTQUFVck8sRUFBS3FPLEdBQWEsSUFBTWhHLEVBQVEsWUFzQnBGLE9BbEJBOWQsRUFBRWUsS0FBTStDLEVBQVMsU0FBVXVXLEVBQVFwYyxHQUc3QixpQkFBb0JvYyxFQUN4QmpPLEdBQVFtcEIsRUFBYWxiLEVBQVFwYyxHQUVsQixpQkFBb0JvYyxJQUUxQkEsRUFBT3lELE9BQVN6RCxFQUFPdlcsU0FDM0JzSSxHQUFRLG9CQUFzQmlPLEVBQU95RCxNQUFRLEtBQzdDMVIsR0FBUWxNLEtBQUtvMUIsc0JBQXVCamIsRUFBT3ZXLFFBQVN1WixJQUVwRGpSLEdBQVFtcEIsRUFBYWxiLEVBQU81RSxJQUFLNEUsRUFBT2hILE9BSXhDblQsTUFFSWtNLEdBWVJvcEIsWUFBYSxTQUFVQyxFQUFZQyxHQUVsQyxJQUFJbmYsRUFBVyxDQUNkb2YsUUFBUyxHQUNUMzJCLEdBQUlnQixFQUFFb1ksU0FBVXFkLEVBQVdwWSxVQUFZLEtBQ3ZDdVksV0FBWSxPQUNaOVgsTUFBTyxHQUNQaGEsUUFBUyxHQUNUOFYsWUFBYSxHQUNibUUsSUFBSyxHQUNMOFgsYUFBYyxZQUNkN0wsU0FBVSxJQUlYLEdBQUt5TCxFQUFXdFYsWUFBYSxJQUFVbmdCLEVBQUV5TyxLQUFNZ25CLEVBQVd0VixVQUFXamdCLEtBQUtvSCxNQUFuQ3RILEdBQ3RDLE9BQU8sRUFHUixPQUFTeTFCLEVBQVduZSxNQUVuQixJQUFLLGNBQ0pmLEVBQVNvZixRQUFRbjRCLEtBQU0sdUJBQ3ZCK1ksRUFBU3FELFlBQWMsV0FDdkJyRCxFQUFTd0gsSUFBTUwsS0FBS0MsS0FBS0MsVUFBVyx5Q0FDcENySCxFQUFTcWYsV0FBYSxNQUN2QixNQUVBLElBQUssYUFDSnJmLEVBQVNvZixRQUFRbjRCLEtBQU0sc0JBQ3hCLE1BRUEsSUFBSyxTQUNMLElBQUssZ0JBQ0osSUFBSXM0QixFQUFnQkwsRUFBV3pMLFVBQVksR0FDM0N6VCxFQUFTeVQsU0FBV253QixFQUFFaUksUUFBUSxFQUFNbW5CLEdBQUdnQixPQUFPQyxxQkFBc0IsQ0FDbkVDLGNBQWMsRUFDZEMsUUFBUyxDQUNSQyxTQUFVLDhHQUNWQyxTQUFVLGtIQUVUd0wsR0FDSixNQUVBLElBQUssU0FDSnZmLEVBQVNxZixXQUFhLFNBQ3ZCLE1BRUEsSUFBSyxZQUNKcmYsRUFBU3VILE1BQVFKLEtBQUtDLEtBQUtDLFVBQVcsYUFDdkMsTUFFQSxJQUFLLGNBQ0pySCxFQUFTb2YsUUFBUW40QixLQUFNLHVCQUN2QitZLEVBQVNxRCxZQUFjLFdBQ3ZCckQsRUFBU3dILElBQU1MLEtBQUtDLEtBQUtDLFVBQVcsNkNBQ3BDckgsRUFBU3FmLFdBQWEsTUFLbkIxMUIsS0FBSyswQixXQUFZUSxFQUFXbmUsUUFDaENmLEVBQVM2ZSxVQUFZLE1BQ3JCN2UsRUFBU3dmLFdBQWEsTUFHdkIsSUFBSTNZLEVBQVFwZCxFQUFFdVcsU0FBVXZXLEVBQUVnMkIsVUFBV1AsR0FBY2xmLEdBU25ELEdBTkt2VyxFQUFFd0IsV0FBWTRiLEVBQU10WixXQUN4QnNaLEVBQU10WixRQUFVOUQsRUFBRXlPLEtBQU0yTyxFQUFNdFosUUFBUzVELEtBQUtvSCxNQUE1QnRILEtBS1gsSUFBTSxDQUFFLFFBQVMsZ0JBQWlCOUIsUUFBU3UzQixFQUFXbmUsTUFBUyxDQUVwRSxJQUFJMmUsR0FBYSxFQUNqQmoyQixFQUFFZSxLQUFNMDBCLEVBQVczeEIsUUFBUyxTQUFVMlIsRUFBS3BDLElBQ3BDLElBQU1vQyxFQUFJdlgsUUFBUyxVQUFhLElBQU11WCxFQUFJdlgsUUFBUyxVQUN4RGtmLEVBQU10WixRQUFRdVAsR0FBTyxtQkFBcUJvQyxFQUFNLFlBQ2hEd2dCLEdBQWEsS0FHVkEsR0FDSjdZLEVBQU11WSxRQUFRbjRCLEtBQU0sY0FpQnRCLE9BWEs0ZixFQUFNVyxLQUNWWCxFQUFNdVksUUFBUW40QixLQUFNLFFBQVU0ZixFQUFNeVksY0FJaEN6WSxFQUFNdVksUUFBUWg1QixTQUNsQnlnQixFQUFNdVksUUFBVSxJQUFNdlksRUFBTXVZLFFBQVF6NEIsS0FBTSxNQUczQ2dELEtBQUtzYyxPQUFRWSxFQUFNcGUsSUFBT29lLEdBYTNCOFksMEJBQTJCLFNBQVVDLEdBRXBDLE9BQVUsSUFBTUEsRUFBV2o0QixRQUFTLFdBQWdCLE1BQVEsTUFZN0RrNEIsYUFBYyxTQUFVaG5CLEdBRXZCQSxFQUFNaVYsaUJBRU4sSUFDQ2dTLEVBRFN4OEIsRUFBR3VWLEVBQU1yRCxlQUNMWixRQUFTLHdCQUl2QixHQUZBa3JCLEVBQU90ckIsWUFBYSxVQUVmLGNBQWdCbUcsT0FBTzRqQixhQUFlLENBRTFDLElBQUk5MUIsRUFBS3EzQixFQUFPNXhCLEtBQU0sTUFDakI0eEIsRUFBTzVRLFNBQVUsVUFDckJ2VSxPQUFPNGpCLGFBQWF3QixRQUFTdDNCLEVBQUksVUFFakNrUyxPQUFPNGpCLGFBQWF5QixXQUFZdjNCLFVBZ0JyQ2hGLEVBQVEscUJBQXFCLENBQzNCLG9CQUNBLGtCQUNBLG1CQUNBLGlCQUNBLHdCQUNFLFNBQ0ZxekIsRUFDQUMsRUFDQUksRUFDQUQsRUFDQStJLEdBR0QsT0FBT3YyQixTQUFTRyxLQUFLMEIsT0FBUTlCLEVBQUV1VyxTQUFVLENBTXhDa1QsTUFBTyxVQU1QbFgsTUFBTyxDQUNOeVgsU0FBVSxDQUNUdFMsTUFBTzhlLEVBQ1A1SixTQUFVLEtBQ1ZuRCxNQUFPLFlBSVQrSixHQUFJLHNCQU1KeHhCLE9BQVFoQyxFQUFFdVcsU0FBVSxHQUFJOFcsRUFBV3JyQixPQUFRc3JCLEVBQVN0ckIsT0FBUTByQixFQUFVMXJCLFFBTXRFcUssU0FBVTRjLEdBQUc1YyxTQUFVLGlDQVN2QnhJLFdBQVksU0FBVVUsR0FFckJyRSxLQUFLb0gsTUFBUS9DLEVBQUsrZCxPQU9sQnRpQixFQUFFZSxLQUxrQixDQUNuQix3QkFDQSxxQkFDQSx5QkFFc0IsU0FBVXFPLEdBQ2hDbFAsS0FBS3NMLFNBQVV0TCxLQUFLb0gsTUFBTzhILEVBQU9sUCxLQUFLK0YsU0FDckMvRixNQUlIQSxLQUFLc0wsU0FBVXRMLEtBQUtvSCxNQUFPLDBCQUEyQixTQUFVZ2IsRUFBUTdNLEdBQ2xFLFFBQVVBLEdBQ2R2VixLQUFLb0UsSUFBSTJGLEtBQU0sK0JBQWdDaEMsUUFBUyxhQVkzRGhDLE9BQVEsV0FjUCxPQVpBL0YsS0FBS29FLElBQUk4SCxLQUFNbE0sS0FBS21NLFNBQVVuTSxLQUFLb0gsUUFFbkNwSCxLQUFLeXNCLGVBQWdCLFlBRXJCenNCLEtBQUsrc0IsZUFBZ0IsV0FBWSxDQUNoQ3VHLEdBQUksK0JBQ0psc0IsTUFBT3BILEtBQUtvSCxRQUdicEgsS0FBS2ltQixtQkFDTGptQixLQUFLeW5CLGVBRUV6bkIsT0FJTm10QixFQUFZQyxFQUFVSSxFQUFXRCxFQUFTK0ksTUFTOUN4OEIsRUFBUSxnQkFBZ0IsR0FBSSxXQUUzQixPQUFPaUcsU0FBU0csS0FBSzBCLE9BQVEsQ0FFNUJ5VSxTQUFVLENBQ1RrZ0IsVUFBVyxPQUVYNU8sTUFBTyxPQUNQNWYsUUFBUyxTQUNUeXVCLE1BQU8sUUFDUEMsVUFBVyxNQUNYM2IsTUFBTyxHQUNQTCxRQUFTLEdBQ1RpYyxXQUFXLEVBQ1hDLFVBQVUsRUFDVkMsT0FBUSxTQUFVeHlCLEtBQ2xCeXlCLE9BQVEsU0FBVXp5QixNQU9uQnZDLFFBQVMsTUFRVDhCLFdBQVksU0FBVVUsR0FFaEJyRSxLQUFLb0UsSUFBSTNILFNBQ2J1RCxLQUFLcVcsU0FBU3lnQixVQUFZOTJCLEtBQUtvRSxJQUFJeUYsVUFHcEM3SixLQUFLNUMsS0FBTzBDLEVBQUV1VyxTQUFVaFMsRUFBS2pILEtBQU00QyxLQUFLcVcsVUFDeENyVyxLQUFLK0YsVUFVTkEsT0FBUSxXQUdQLE9BREEvRixLQUFLb0UsSUFBSTJ5QixhQUFjLzJCLEtBQUs1QyxNQUNyQjRDLE1BVVIwSyxLQUFNLFdBR0wsT0FEQTFLLEtBQUtvRSxJQUFJMnlCLGFBQWMsUUFDaEIvMkIsTUFVUmlyQixLQUFNLFdBR0wsT0FEQWpyQixLQUFLb0UsSUFBSTJ5QixhQUFjLFFBQ2hCLzJCLFVBYVZsRyxFQUFRLG1CQUFtQixHQUFJLFdBRTlCLE9BQU9pRyxTQUFTRyxLQUFLMEIsT0FBUSxDQVE1QkUsT0FBUSxDQUNQazFCLGlCQUFrQixZQU9uQm4xQixRQUFTLFNBU1Q4QixXQUFZLFNBQVVVLEdBRXJCckUsS0FBS2kzQixVQUFZNXlCLEVBQUs0eUIsVUFDdEJqM0IsS0FBS2szQixrQkFBb0I3eUIsRUFBSzZ5QixtQkFBcUIxWixLQUFLQyxLQUFLQyxVQUFXLGlCQVV6RXlaLFNBQVUsU0FBVWpvQixHQUVuQixJQUFJa0ksRUFBT3BYLEtBQUtvRSxJQUFJRyxLQUFNLGtCQUUxQnhFLFNBQVN1YixPQUFPdlQsUUFBU3FQLEVBQUt4YSxRQUFTLFFBQVMsSUFBTyxpQkFBa0JzUyxFQUFNa29CLE9BQU8veUIsS0FBTTZLLEdBQzVGbFAsS0FBS29FLElBQUltUixJQUFLLE1BQU94TixRQUFTLFdBVy9CaEMsT0FBUSxXQUNQLElBQUlrVCxFQUFPalosS0FrQ1gsT0FqQ0FQLFdBQVksV0FDWHdaLEVBQUs3VSxJQUFJc2pCLFlBQWEsQ0FDckIyUCxLQUFNLENBQ0xDLFNBQVUsT0FDVm5jLE1BQU8sSUFDUC9ILE9BQVEsT0FDUmlXLElBQUtyWSxPQUFPdW1CLFFBQ1psekIsS0FBTSxTQUFVK3lCLEdBQ2YsTUFBTyxDQUNOOVgsT0FBUSxlQUNSQyxZQUFhLFNBQ2JDLFVBQVd4TyxPQUFPcUcsYUFBYTBKLE9BQU9qaUIsR0FDdENtNEIsVUFBV2hlLEVBQUtnZSxVQUNoQk8sS0FBTUosRUFBT0ksS0FDYkMsS0FBTUwsRUFBT0ssS0FDYkMsWUFBYUMsYUFBYUMsU0FPN0JDLGVBQWdCbCtCLEVBQUcsZ0NBRW5CbStCLGFBQWMsU0FBVUMsR0FDdkIsT0FBT0EsR0FFUnJlLFlBQWFULEVBQUtpZSxrQkFDbEJjLGVBQWdCL2UsRUFBS2dmLGNBQ3JCdFEsTUFBTyxTQUVSMU8sRUFBSzdVLElBQUlHLEtBQU0saUJBQWtCMFUsRUFBS2dlLFlBQ3BDLEdBQ0lqM0IsTUFXUmk0QixjQUFlLFNBQVVqWSxHQUV4QixJQUFJa1ksRUFBUXYrQixFQUFHLCtDQUVmLEdBQUtxbUIsRUFBSW1ZLFFBQ1IsT0FBT0QsRUFBTS91QixPQUFRNlcsRUFBSXlGLE1BRzFCLElBQUkyUyxFQUFReitCLEVBQUcsMENBQ2QwK0IsRUFBUTErQixFQUFHLHNDQWFaLE9BWkM0ZixLQUFTLFdBQWF5RyxFQUFJVixPQUFXLFlBQWMsUUFDbkRtRyxLQUFTLFdBQWF6RixFQUFJVixPQUFXOUIsS0FBS0MsS0FBS0MsVUFBVyxVQUFhRixLQUFLQyxLQUFLQyxVQUFXLFNBRTdGMGEsRUFBTWp2QixPQUFRLG1CQUFxQm9RLEtBQU8sbUNBQXFDa00sS0FBTyxZQUV0RjRTLEVBQU1sdkIsT0FBUSxPQUFTNlcsRUFBSTNiLEtBQUt5VyxNQUFRLFNBQ3hDdWQsRUFBTWx2QixPQUFRLE9BQVNxVSxLQUFLQyxLQUFLQyxVQUFXLE1BQVMsU0FBV3NDLEVBQUkzYixLQUFLdkYsR0FBSyxjQUU5RWdCLEVBQUVlLEtBQU1tZixFQUFJVyxRQUFTLFNBQVU5VyxHQUM5Qnd1QixFQUFNbHZCLE9BQVEsT0FBU1UsRUFBUyxnQkFHMUJxdUIsRUFBTS91QixPQUFRaXZCLEdBQVFqdkIsT0FBUWt2QixRQWF4Q3YrQixFQUFRLHFCQUFxQixHQUFLLFdBRWpDLE9BQU9pRyxTQUFTRyxLQUFLMEIsT0FBUSxDQU01Qnd2QixVQUFXLHFCQUVYdHZCLE9BQVEsQ0FDUHcyQiwyQkFBNEIsZ0JBUzdCeDVCLEdBQUksV0FDSCxNQUFPLHNCQUF3QmtCLEtBQUtvSCxNQUFNdEksSUFPM0MrQyxRQUFTLEtBTVRzSyxTQUFVNGMsR0FBRzVjLFNBQVUsK0JBUXZCeEksV0FBWSxXQUVYM0QsS0FBSytGLFVBVU5BLE9BQVEsV0FFUCxPQURBL0YsS0FBS29FLElBQUk4SCxLQUFNbE0sS0FBS21NLFNBQVVuTSxLQUFLb0gsUUFDNUJwSCxNQVFSZ2YsYUFBYyxXQUViaGYsS0FBSzRnQixLQUFLNUIsYUFBYyxDQUN2Qi9ELFdBQVcsRUFDWDlCLFFBQVNuWixLQUFLb0gsTUFBTVgsSUFBSyxtQkFBc0J6RyxLQUFLb0gsTUFBTVgsSUFBSyxtQkFBc0IsS0FDckYrVCxjQUFleGEsS0FBS29ILFFBR3JCcEgsS0FBSzRnQixLQUFLN1ksUUFBUywyQkFpQ3RCak8sRUFBUSxxQkFBcUIsQ0FBRSxzQkFBd0IsU0FBVXkrQixHQUVoRSxPQUFPeDRCLFNBQVM0QixlQUFlQyxPQUFRLENBRXRDd3ZCLFVBQVcsZ0JBTVhrQyxHQUFJLHNCQU1KNXdCLFVBQVc2MUIsRUFNWHoxQixZQUFZLEVBTVpRLFVBQVUsTUFXWnhKLEVBQVEsdUJBQXVCLENBQUUsbUJBQXNCLFNBQVVzekIsR0FFaEUsT0FBT3J0QixTQUFTRyxLQUFLMEIsT0FBUTlCLEVBQUV1VyxTQUFVLENBTXhDK2EsVUFBVyx1QkFFWHR2QixPQUFRaEMsRUFBRXVXLFNBQVUsQ0FDbkJtaUIsK0JBQWdDLGlCQUNoQ0MsbURBQW9ELGFBQ3BEQyxtREFBb0QsY0FDbER0TCxFQUFTdHJCLFFBUVpoRCxHQUFJLFdBQ0gsTUFBTyx3QkFBMEJrQixLQUFLb0gsTUFBTXRJLElBTzdDK0MsUUFBUyxLQU1Uc0ssU0FBVTRjLEdBQUc1YyxTQUFVLGlDQVF2QnhJLFdBQVksV0FFWDNELEtBQUsrRixTQUVML0YsS0FBS3NMLFNBQVV0TCxLQUFLb0gsTUFBTTNFLFdBQVksTUFBT3pDLEtBQUsyNEIsdUJBQ2xEMzRCLEtBQUtzTCxTQUFVdEwsS0FBS29ILE1BQU8sU0FBVXBILEtBQUsrRixRQUVyQyxVQUFZL0YsS0FBS29ILE1BQU1YLElBQUssZ0JBQ2hDekcsS0FBS3NMLFNBQVV0TCxLQUFLb0gsTUFBTVgsSUFBSyxVQUFZLFNBQVV6RyxLQUFLK0YsU0FXNURBLE9BQVEsV0FFUCxPQURBL0YsS0FBS29FLElBQUk4SCxLQUFNbE0sS0FBS21NLFNBQVVuTSxLQUFLb0gsUUFDNUJwSCxNQVdScWIsV0FBWSxTQUFVbk0sR0FFckJBLEVBQU1rVixrQkFDTmxWLEVBQU1pVixpQkFFTixJQUFJcG1CLEVBQVFpQyxLQUFLb0gsTUFBTTNFLFdBQVd6RSxRQUFTZ0MsS0FBS29ILE9BQ2hEcEgsS0FBS29ILE1BQU0zRSxXQUFXb0gsT0FBT3dSLFdBQVksR0FBSSxDQUM1QzVMLEdBQUkxUixFQUFRLEtBWWQ2NkIsV0FBWSxTQUFVMXBCLEdBRXJCQSxFQUFNaVYsaUJBQ05wa0IsU0FBU3ViLE9BQU92VCxRQUFTLGdCQUFpQi9ILEtBQUtvSCxPQUMvQ3BILEtBQUtvSCxNQUFNM0UsV0FBV29ELE9BQVE3RixLQUFLb0gsUUFVcEN5eEIsZUFBZ0IsV0FFZixJQUFJemdCLEVBQVVwWSxLQUFLb0UsSUFBSTJGLEtBQU0seUJBQTBCbkQsR0FBSSxZQUMzRDVHLEtBQUtvSCxNQUFNeU8sSUFBSyxVQUFXdUMsR0FDM0JwWSxLQUFLb0gsTUFBTTNFLFdBQVdzRixRQUFTLGlCQUFrQi9ILEtBQUtvSCxTQUlyRGdtQixNQVNKdHpCLEVBQVEsMkJBQTJCLENBQUUsd0JBQTBCLFNBQVVnL0IsR0FFeEUsT0FBTy80QixTQUFTNEIsZUFBZUMsT0FBUSxDQUV0Q3d2QixVQUFXLHNCQU1YMXVCLFVBQVdvMkIsRUFNWHoxQixrQkFBa0IsRUFNbEJQLFlBQVksRUFNWlEsVUFBVSxFQUVWQyxnQkFBaUIsQ0FDaEI0SyxNQUFNLEVBRU5ta0IsT0FBUSxPQUNSQyxPQUFRLGtCQUNSaHNCLE1BQU8sd0JBQ1BtVCxZQUFhLGtEQUdkOFksZUFBZ0IsU0FBVXByQixHQUN6QnBILEtBQUtvRSxJQUFJRSxTQUFVLGFBR3BCbXVCLGNBQWUsU0FBVXJyQixHQUN4QnBILEtBQUtvRSxJQUFJMEksWUFBYSxpQkFZekJoVCxFQUFRLGlCQUFpQixDQUN2QixrQkFDQSw0QkFDRSxTQUNGc3pCLEVBQ0EyTCxHQUdELE9BQU9oNUIsU0FBU0csS0FBSzBCLE9BQVE5QixFQUFFdVcsU0FBVSxDQVF4QythLFVBQVcsV0FDVixNQUFPLHdCQUEwQnB4QixLQUFLb0gsTUFBTVgsSUFBSyxpQkFBa0JBLElBQUssT0FHekUzRSxPQUFRaEMsRUFBRXVXLFNBQVUsQ0FDbkIyaUIseUJBQTBCLFFBQzFCQywwQkFBMkIsU0FDM0JDLDBCQUEyQixTQUMzQkMsNEJBQTZCLFdBQzdCQyx1Q0FBd0MsaUJBQ3RDaE0sRUFBU3RyQixRQVFaaEQsR0FBSSxXQUNILE1BQU8saUJBQW1Ca0IsS0FBS29ILE1BQU10SSxJQU90QytDLFFBQVMsS0FNVHNLLFNBQVU0YyxHQUFHNWMsU0FBVSwwQkFRdkJ4SSxXQUFZLFdBTVg3RCxFQUFFZSxLQUprQixDQUNuQixtQkFDQSxxQkFFc0IsU0FBVXFPLEdBQ2hDbFAsS0FBS3NMLFNBQVV0TCxLQUFLb0gsTUFBTzhILEVBQU9sUCxLQUFLK0YsU0FDckMvRixNQUVIQSxLQUFLc0wsU0FBVXRMLEtBQUtvSCxNQUFNWCxJQUFLLFNBQVcsU0FBVXpHLEtBQUsrRixRQUV6RC9GLEtBQUtzTCxTQUFVdEwsS0FBS29ILE1BQU0wUSxhQUFjLGlCQUFrQjlYLEtBQUtxNUIsMEJBRS9EcjVCLEtBQUswWSxHQUFJLHVCQUF3QjFZLEtBQUtzNUIscUJBQXNCdDVCLE1BRTVERCxTQUFTdWIsT0FBTzVDLEdBQUksc0JBQXVCMVksS0FBSzQ0QixXQUFZNTRCLE9BVTdEK0YsT0FBUSxXQWdCUCxHQWRBL0YsS0FBS29FLElBQUk4SCxLQUFNbE0sS0FBS21NLFNBQVVuTSxLQUFLb0gsUUFFOUJwSCxLQUFLb0gsTUFBTVgsSUFBSyxpQkFBaUJBLElBQUssYUFFMUN6RyxLQUFLdTVCLGVBQWlCLElBQUlSLEVBQWdCLENBQ3pDekYsR0FBSXR6QixLQUFLb0UsSUFBSTJGLEtBQU0sMEJBQ25CdEgsV0FBWXpDLEtBQUtvSCxNQUFNWCxJQUFLLGFBRTdCekcsS0FBS3U1QixlQUFleHpCLFNBQ3BCL0YsS0FBS3U1QixlQUFlN2dCLEdBQUksWUFBYTFZLEtBQUt1NUIsZUFBZS9HLGdCQUN6RHh5QixLQUFLdTVCLGVBQWU3Z0IsR0FBSSxXQUFZMVksS0FBS3U1QixlQUFlOUcsZ0JBSXBELFVBQVl6eUIsS0FBS29ILE1BQU1YLElBQUssaUJBQWtCQSxJQUFLLE1BQVMsQ0FFaEUsSUFBSXdTLEVBQU9qWixLQUNYUCxXQUFZLFdBQ1h3WixFQUFLdWdCLGlCQUFtQnZnQixFQUFLMUwsbUJBQW1CcVQsS0FBSzZZLGtCQUFtQixDQUN2RW5HLEdBQUlyYSxFQUFLN1UsSUFBSTJGLEtBQU0sd0JBQ25CdEgsV0FBWXdXLEVBQUs3UixNQUFNWCxJQUFLLGVBRTdCd1MsRUFBS3VnQixpQkFBaUJ6ekIsU0FDdEJrVCxFQUFLdWdCLGlCQUFpQjlnQixHQUFJLFlBQWFPLEVBQUt1Z0IsaUJBQWlCaEgsZ0JBQzdEdlosRUFBS3VnQixpQkFBaUI5Z0IsR0FBSSxXQUFZTyxFQUFLdWdCLGlCQUFpQi9HLGdCQUMxRCxHQXNCSixPQWxCS3p5QixLQUFLb0gsTUFBTVgsSUFBSyx3QkFDcEJ6RyxLQUFLNnBCLFlBQWEsa0JBQW9CN3BCLEtBQUtvSCxNQUFNWCxJQUFLLE9BR2xEekcsS0FBS29ILE1BQU1YLElBQUssMkJBQ3BCekcsS0FBSzZwQixZQUFhLDRCQUE4QjdwQixLQUFLb0gsTUFBTVgsSUFBSyxNQUFRLENBQ3ZFd2pCLGNBQWMsRUFDZEMsUUFBUyxDQUNSQyxTQUFVLDZFQUNWQyxTQUFVLEdBQ1ZDLE1BQU92cUIsRUFBRXlPLEtBQU12TyxLQUFLc3FCLGdCQUFpQnRxQixTQUt4Q0EsS0FBS3dtQixzQkFDTHhtQixLQUFLeW5CLGVBRUV6bkIsTUFTUnE1Qix5QkFBMEIsV0FFekJyNUIsS0FBS29FLElBQUkyRixLQUFNLHlCQUEwQnhGLEtBQU0sV0FBWXZFLEtBQUtvSCxNQUFNOFUsMEJBV3ZFM2EsTUFBTyxTQUFVMk4sR0FFaEJBLEVBQU1rVixrQkFDTmxWLEVBQU1pVixpQkFDTm5rQixLQUFLb0gsTUFBTTNFLFdBQVdxQixJQUFLOUQsS0FBSzA1QixvQkFBcUIxNUIsS0FBS29ILFNBVzNEc3lCLG9CQUFxQixTQUFVMWdCLEdBRzlCLElBQUl6WCxFQUFRekIsRUFBRXlCLE1BQU95WCxFQUFTN0QsWUF1QzlCLGNBcENPNVQsRUFBTXpDLEdBRWJ5QyxFQUFNc1osVUFBWTdCLEVBQVN2UyxJQUFLLE1BR2hDbEYsRUFBTWlaLGNBQWdCeEIsRUFBU3ZTLElBQUssaUJBQWtCQSxJQUFLLE1BRzNEbEYsRUFBTWlZLE1BQVExWixFQUFFeUIsTUFBT3lYLEVBQVN2UyxJQUFLLFNBQVUwTyxZQUcxQzZELEVBQVN2UyxJQUFLLGFBRWxCbEYsRUFBTTRYLFFBQVUsR0FFaEJILEVBQVN2UyxJQUFLLFdBQVk1RixLQUFNLFNBQVdvWCxHQUUxQyxJQUFJMGhCLEVBQWU3NUIsRUFBRXlCLE1BQU8wVyxFQUFPOUMsbUJBQzVCd2tCLEVBQWE3NkIsVUFDYjY2QixFQUFhcmhCLFlBRXBCL1csRUFBTTRYLFFBQVE3YixLQUFNcThCLE1BTWpCLFVBQVkzZ0IsRUFBU3ZTLElBQUssaUJBQWtCQSxJQUFLLFFBRXJEbEYsRUFBTWdaLFVBQVksR0FDbEJ2QixFQUFTdlMsSUFBSyxhQUFjNUYsS0FBTSxTQUFVb1csR0FDM0MxVixFQUFNZ1osVUFBVWpkLEtBQU0wQyxLQUFLMDVCLG9CQUFxQnppQixLQUM5Q2pYLE9BSUd1QixHQVVSOHhCLFNBQVUsV0FFVHJ6QixLQUFLb0gsTUFBTXlPLElBQUssYUFBYSxJQVc5QitqQixPQUFRLFNBQVUxcUIsR0FFakJBLEVBQU1pVixpQkFFRG5ULE9BQU9vRCxRQUFTb0osS0FBS0MsS0FBS0MsVUFBVyxxREFFekMxZCxLQUFLb0gsTUFBTTNFLFdBQVdvRCxPQUFRN0YsS0FBS29ILE9BQ25DckgsU0FBU3ViLE9BQU92VCxRQUFTLGdCQUFpQi9ILEtBQUtvSCxTQVlqRGdzQixPQUFRLFdBRVBwekIsS0FBS29ILE1BQU15TyxJQUFLLGFBQWEsSUFXOUJ5akIscUJBQXNCLFNBQVUvakIsR0FFMUIsUUFBVUEsR0FJZnZWLEtBQUtvSCxNQUFNWCxJQUFLLFdBQVltUyxlQUFnQjlZLEVBQUVzQixNQUFPcEIsS0FBS29ILE1BQU1YLElBQUssV0FBWXFTLGlCQVVsRnNDLGNBQWUsV0FFZHBiLEtBQUtvSCxNQUFNeU8sSUFBSyxTQUFtRSxFQUF6RDdWLEtBQUtvRSxJQUFJMkYsS0FBTSxpQ0FBa0N3TCxTQUkxRTZYLE1BU0p0ekIsRUFBUSxxQkFBcUIsQ0FBRSxrQkFBb0IsU0FBVXkrQixHQUU1RCxPQUFPeDRCLFNBQVM0QixlQUFlQyxPQUFRLENBRXRDd3ZCLFVBQVcsc0JBWVgxdUIsVUFBVzYxQixFQU1YbDFCLGtCQUFrQixFQU1sQlAsWUFBWSxFQU1aUSxVQUFVLEVBRVZDLGdCQUFpQixDQUNoQjRLLE1BQU0sRUFDTmtrQixZQUFhLHVCQUNiQyxPQUFRLE9BQ1JDLE9BQVEsbUJBQ1Joc0IsTUFBTyxpQkFDUG1ULFlBQWEsMkNBVWQ4WSxlQUFnQixTQUFVcHJCLEdBQ3pCLElBQUl5eUIsRUFBVyxVQUFZenlCLEVBQU1YLElBQUssaUJBQWtCQSxJQUFLLE1BQVMsMENBQTRDLHVCQUNsSDlNLEVBQUdrZ0MsR0FBV3YxQixTQUFVLGFBVXpCbXVCLGNBQWUsV0FDZDk0QixFQUFHLHdCQUF5Qm1ULFlBQWEsYUFXMUNnQyxTQUFXLFNBQVVJLEVBQU9DLEdBSzNCLEdBSEFELEVBQU1rVixrQkFHRGpWLEVBQUczSSxLQUFLK2UsU0FBVSxpQkFBb0I1ckIsRUFBR3VWLEVBQU1xQyxRQUFTdEcsUUFBUyxpQkFBa0J4TyxPQUN2RjBTLEVBQUdJLE9BQU9qTSxTQUFVLGNBRHJCLENBS0EsSUFDSWdNLEVBRGVILEVBQUdJLE9BQ3NCbEwsS0FBTSxRQUNsRCxHQUFNaUwsR0FBOEJBLEVBQXlCN00sV0FBN0QsQ0FFQSxJQUFJNE0sRUFBV3JQLEtBQUt1SSxrQkFBa0JnQyxXQUFXeE0sTUFBT29SLEVBQUczSSxNQUN2RGdKLEVBQWdCRixFQUF5QjdNLFdBQVdnRSxJQUFLMEksRUFBRzNJLEtBQUtqQyxLQUFNLG1CQUMzRStLLEVBQXlCN00sV0FBV29ELE9BQVEySixHQUM1Q3hQLEtBQUt5QyxXQUFXcUIsSUFBSzBMLEVBQWUsQ0FBRUMsR0FBS0osSUFDM0NHLEVBQWMvTSxXQUFhekMsS0FBS3lDLFdBQ2hDekMsS0FBS3NGLGlCQUFrQmtLLE1BV3hCaEIsV0FBYSxTQUFVVSxFQUFPQyxHQUU3QixJQUFJQyxFQUFtQnBQLEtBQUt5QyxXQUFXZ0UsSUFBSzBJLEVBQUczSSxLQUFLakMsS0FBTSxtQkFFMUQ0SyxFQUFHdUssWUFBWXBWLFNBQVUsVUFBWThLLEVBQWlCM0ksSUFBSyxpQkFBa0JBLElBQUssT0FFOUV6RyxLQUFLa0UsOEJBQ1JsRSxLQUFLNkgsTUFBTyxZQUFhLENBQUV1SCxpQkFBbUJBLElBQzFDcFAsS0FBSytILFFBQVMsWUFBYXFILElBWWpDUixVQUFZLFNBQVVNLEVBQU9DLEdBRTVCRCxFQUFNa1Ysa0JBRU4sSUFBSWhWLEVBQW1CcFAsS0FBS3lDLFdBQVdnRSxJQUFLMEksRUFBRzNJLEtBQUtqQyxLQUFNLG1CQUV6RDhLLEVBRHVCclAsS0FBS3VJLGtCQUNJZ0MsV0FBV3hNLE1BQU9vUixFQUFHM0ksT0FFcEMsR0FBYjZJLEdBQWtCRCxHQUN0QnBQLEtBQUt5QyxXQUFXb0QsT0FBUXVKLEdBR3pCcFAsS0FBS2dOLGdDQUNMaE4sS0FBS2dJLDBCQUVEaEksS0FBS2tFLDhCQUNSbEUsS0FBSzZILE1BQU8sV0FBWSxDQUFFdUgsaUJBQW1CQSxFQUFrQkMsU0FBV0EsSUFFMUVyUCxLQUFLK0gsUUFBUyxXQUFZcUgsRUFBa0JDLFFBY2hEdlYsRUFBUSxhQUFhLENBQ25CLGNBQ0EsZ0JBQ0EsbUJBQ0EscUJBQ0EscUJBQ0EsdUJBQ0Esb0JBQ0Esa0JBQ0EsaUJBQ0Esb0JBQ0UsU0FDRmdnQyxFQUNBQyxFQUNBQyxFQUNBQyxFQUNBQyxFQUNBNUQsRUFDQW5KLEVBQ0FDLEVBQ0FHLEVBQ0FDLEdBR0QsT0FBT3p0QixTQUFTRyxLQUFLMEIsT0FBUTlCLEVBQUV1VyxTQUFVLENBTXhDa1QsTUFBTyxVQU1QbFgsTUFBTyxDQUNOeVgsU0FBVSxDQUNUdFMsTUFBTzhlLEVBQ1A1SixTQUFVLEtBQ1ZuRCxNQUFPLFdBRVI0USxLQUFNLENBQ0wzaUIsTUFBT3lpQixFQUNQdk4sU0FBVSxLQUNWbkQsTUFBTyxXQUVSNlEsS0FBTSxDQUNMNWlCLE1BQU8waUIsRUFDUHhOLFNBQVUsS0FDVm5ELE1BQU8sWUFJVCtKLEdBQUksb0JBTUp4eEIsT0FBUWhDLEVBQUV1VyxTQUFVLENBQ25CZ2tCLDRCQUE2QiwwQkFDN0JDLHVCQUF3QixlQUN4QkMsaUNBQWtDLGFBQ2xDQyxxQkFBc0IsZUFHcEJyTixFQUFXcnJCLE9BQVFzckIsRUFBU3RyQixPQUFRMHJCLEVBQVUxckIsUUFNakRELFFBQVMsTUFNVHNLLFNBQVU0YyxHQUFHNWMsU0FBVSxzQkFRdkJ4SSxXQUFZLFNBQVVVLEdBRXJCckUsS0FBS29pQixPQUFTL2QsRUFBSytkLE9BR2QsUUFBVXBpQixLQUFLb2lCLE9BQU8zYixJQUFLLGlCQUFzQjNHLEVBQUV3VixRQUFTdFYsS0FBS29pQixPQUFPM2IsSUFBSyxXQUVqRnpHLEtBQUtvSCxNQUFRcEgsS0FBS29pQixPQUFPM2IsSUFBSyxRQWlCOUJ6RyxLQUFLb0gsTUFBTXlQLFdBQVk3VyxLQUFLb2lCLFFBRTVCcGlCLEtBQUtzTCxTQUFVdEwsS0FBS29ILE1BQU8saUJBQWtCcEgsS0FBS3k2QixnQkFJbkR6NkIsS0FBSzBZLEdBQUksZ0JBQWlCMVksS0FBSzA2QixhQVVoQzMwQixPQUFRLFdBS1AsR0FIQS9GLEtBQUtvRSxJQUFJOEgsS0FBTWxNLEtBQUttTSxTQUFVbk0sS0FBS29ILFFBRzlCcEgsS0FBS29ILE1BQVEsQ0FHakJvVyxLQUFLdUksUUFBUXpYLE1BQU90TyxLQUFLb0UsS0FFekJwRSxLQUFLK3NCLGVBQWdCLFdBQVksQ0FDaEN1RyxHQUFJLDZCQUNKbHNCLE1BQU9wSCxLQUFLb0gsUUFHYnBILEtBQUtpbUIsbUJBQ0xqbUIsS0FBS3luQixlQUVMem5CLEtBQUsrc0IsZUFBZ0IsT0FBUSxDQUM1QnRxQixXQUFZdU8sT0FBT3FHLGFBQWFrRCxZQUdqQyxJQUFJb2dCLEVBQWEsS0FDaEIzZCxFQUFRLEtBRVRoZCxLQUFLb3NCLFlBQWEsUUFBU00sU0FBUy9uQixZQUFZOUQsS0FBTSxTQUFVK0UsR0FFL0RBLEVBQUtnYixLQUFPNWdCLEtBQUtvSCxNQUVqQjRWLEVBQVFwWCxFQUFLd0IsTUFBTVgsSUFBSyxTQUFVakwsS0FFN0JtL0IsSUFBZTNkLElBQ25CMmQsRUFBYTNkLEVBQ2JwWCxFQUFLeEIsSUFBSXFHLE9BQVEsNkNBQStDdVMsRUFBUSxnQkFHdkVoZCxNQUVIQSxLQUFLb0gsTUFBTStYLGVBQWdCcmYsRUFBRXlPLEtBQU0sU0FBVXFnQixHQUU1QyxHQUFLQSxFQUVKLE9BREFnTSxNQUFPcGQsS0FBS0MsS0FBS0MsVUFBVyxpR0FDckIxZCxLQUdSd2QsS0FBS3VJLFFBQVFwWCxLQUFNM08sS0FBS29FLEtBQ3hCcEUsS0FBSytzQixlQUFnQixPQUFRLENBQzVCdUcsR0FBSSx1QkFDSjd3QixXQUFZekMsS0FBS29ILE1BQU1YLElBQUssZUFFN0IsSUFBSTJ6QixFQUFPcDZCLEtBQUtvc0IsWUFBYSxRQUFTTSxTQUN0QzBOLEVBQUt4WixLQUFPNWdCLEtBQ1pvNkIsRUFBSzMzQixXQUFXaVcsR0FBSSxNQUFPLFdBQzFCMGhCLEVBQUszM0IsV0FBV3NGLFFBQVMsWUFDdkIvSCxNQUNIbzZCLEVBQUsxaEIsR0FBSSxZQUFhMGhCLEVBQUs1SCxnQkFDM0I0SCxFQUFLMWhCLEdBQUksV0FBWTBoQixFQUFLM0gsZ0JBRXhCenlCLE9BRUhBLEtBQUtvSCxNQUFNc1IsR0FBSSxxQkFBc0IsV0FDcEMsSUFBSW1pQixFQUFhNzZCLEtBQUtvRSxJQUFJMkYsS0FBTSx3QkFDaEM4d0IsRUFBV0MsUUFBUyxDQUFFQyxVQUFXRixFQUFXeC9CLEtBQU0saUJBQW9CLE1BQ3BFMkUsTUFJSixPQUFPQSxNQVlSeTZCLGNBQWUsU0FBVTdaLEVBQU1qSCxHQUU5QjNaLEtBQUtvRSxJQUFJMkYsS0FBTSwyQkFBNEIwYixLQUFNOUwsSUFXbERxaEIsWUFBYSxTQUFVOXJCLEdBRXRCLElBQUkrckIsRUFBYSxXQUFhdGhDLEVBQUd1VixFQUFNcUMsUUFBU2hOLEtBQU0sZUFFdER2RSxLQUFLb0gsTUFBTVgsSUFBSyxhQUFjNUYsS0FBTSxTQUFVbVksR0FDN0NBLEVBQVNuRCxJQUFLLFlBQWFvbEIsTUFXN0JDLGFBQWMsV0FFYixJQUFJdGEsRUFBTzVnQixLQUFLb2lCLE9BQU8zYixJQUFLLFFBQ3ZCM0csRUFBRXdWLFFBQVNzTCxHQUNmQSxFQUFPNWdCLEtBQUtvaUIsT0FBT0UsV0FFbkJ0aUIsS0FBS29pQixPQUFPdk0sSUFBSyxlQUFnQixPQUdsQzdWLEtBQUtvSCxNQUFRd1osRUFDYjVnQixLQUFLK0YsVUFLTm8xQixrQkFBbUIsU0FBVWpzQixHQUU1QmxQLEtBQUtvN0Isb0JBQW9CMXdCLE9BRXpCLElBQUlrVyxFQUFPMVIsRUFBTTdLLEtBRVosVUFBWTZLLEVBQU1vUSxlQUVmc0IsRUFBSzloQixHQUVaZ0IsRUFBRWUsS0FBTStmLEVBQUtyRyxVQUFXLFNBQVV2QixVQUUxQkEsRUFBUzZCLGlCQUNUN0IsRUFBU2xhLEdBRVhrYSxFQUFTRyxTQUViclosRUFBRWUsS0FBTW1ZLEVBQVNHLFFBQVMsU0FBVWxCLFVBRTVCQSxFQUFPSyxtQkFDUEwsRUFBT25aLFFBVWpCOGhCLEVBQUtnQixZQUFhLFNBSVpoQixFQUFLMUMsVUFFWmxlLEtBQUtvaUIsT0FBT0UsU0FBVTFCLEdBQ3RCNWdCLEtBQUtvSCxNQUFRcEgsS0FBS29pQixPQUFPM2IsSUFBSyxRQUM5QnpHLEtBQUsrRixVQVdOczFCLHdCQUF5QixTQUFVbnNCLEdBRWxDQSxFQUFNaVYsaUJBRU5ua0IsS0FBS283QixvQkFBc0IsSUFBSXJCLEVBQVMsQ0FDdkN6RyxHQUFJLHNCQUNKbDJCLEtBQU0sQ0FDTHU1QixVQUFVLEVBQ1ZELFdBQVcsRUFDWEksVUFBVywrQkFDWHdFLGFBQWEsRUFDYi9FLFVBQVcsT0FDWDVPLE1BQU8sSUFDUDdNLE1BQU8wQyxLQUFLQyxLQUFLQyxVQUFXLHFCQUM1QmpELFFBQVMsSUFBSXVmLEVBQVksQ0FDeEIvQyxVQUFXLFlBQ1hDLGtCQUFtQjFaLEtBQUtDLEtBQUtDLFVBQVcsb0NBQ3JDM1gsU0FBUzNCLElBQ2J5eUIsT0FBUSxXQUNQOTJCLFNBQVN1YixPQUFPa1IsSUFBSywwQkFLeEJ4c0IsS0FBS283QixvQkFBb0JuUSxPQUN6QmxyQixTQUFTdWIsT0FBT2lnQixLQUFNLHFCQUFzQnY3QixLQUFLbTdCLGtCQUFtQm43QixPQTBCckUwNkIsV0FBWSxTQUFVOVosR0FFckI1Z0IsS0FBS29pQixPQUFPdk0sSUFBSyxlQUFnQixNQUNqQzdWLEtBQUtvaUIsT0FBT3ZNLElBQUssT0FBUSxXQUVsQjdWLEtBQUtvSCxNQUVacEgsS0FBSytGLFVBV055MUIsV0FBWSxXQUdYLElBQUlDLEVBQU0sSUFBSTFCLEVBQVMsQ0FDdEJ6RyxHQUFJLDJCQUNKbDJCLEtBQU0sQ0FDTHU1QixVQUFVLEVBQ1ZELFdBQVcsRUFDWEksVUFBVyx3QkFDWHdFLGFBQWEsRUFDYi9FLFVBQVcsV0FDWDVPLE1BQU8sc0JBQ1A3TSxNQUFPMEMsS0FBS0MsS0FBS0MsVUFBVyxrQkFDNUIyTCxJQUFLLHNCQUtQb1MsRUFBSXhRLE9BR0pqckIsS0FBS29ILE1BQU1zUixHQUFJLHFCQUFzQixXQUNwQytpQixFQUFJL3dCLFVBS04rdUIsa0JBQW1CLFNBQVU3MUIsR0FDNUIsT0FBTyxJQUFJczJCLEVBQWN0MkIsS0FHeEJ1cEIsRUFBWUMsRUFBVUcsRUFBU0MsRUFBVzhJLE1BUzlDeDhCLEVBQVEsbUJBQW1CLENBQ3pCLGdCQUNBLG1CQUNBLG9CQUNBLGtCQUNBLG1CQUNBLGlCQUNBLHdCQUNFLFNBQ0ZpZ0MsRUFDQUMsRUFDQTdNLEVBQ0FDLEVBQ0FJLEVBQ0FELEVBQ0ErSSxHQUdELE9BQU92MkIsU0FBU0csS0FBSzBCLE9BQVE5QixFQUFFdVcsU0FBVSxDQU14Q2tULE1BQU8sVUFNUGxYLE1BQU8sQ0FDTnlYLFNBQVUsQ0FDVHRTLE1BQU84ZSxFQUNQNUosU0FBVSxLQUNWbkQsTUFBTyxZQUlUK0osR0FBSSwwQkFRSnh4QixPQUFRLFdBQ1AsSUFBSTQ1QixFQUFlMTdCLEtBQUsyN0IscUJBQXVCM3FCLE9BQU9xRyxhQUFhNkksWUFBWTBiLGtCQUFvQixHQUNuRyxPQUFPOTdCLEVBQUV1VyxTQUFVLENBQ2xCd2xCLGtDQUFtQyxnQ0FDbkNDLDZCQUE4QixzQkFDNUIzTyxFQUFXcnJCLE9BQVFzckIsRUFBU3RyQixPQUFRMHJCLEVBQVUxckIsT0FBUTQ1QixJQU8xRDc1QixRQUFTLE1BTVRzSyxTQUFVNGMsR0FBRzVjLFNBQVUsNEJBUXZCeEksV0FBWSxTQUFVVSxHQUVyQnJFLEtBQUtvaUIsT0FBUy9kLEVBQUsrZCxPQUdkLFFBQVVwaUIsS0FBS29pQixPQUFPM2IsSUFBSyx1QkFBNEIzRyxFQUFFd1YsUUFBU3RWLEtBQUtvaUIsT0FBTzNiLElBQUssaUJBRXZGekcsS0FBS29ILE1BQVFwSCxLQUFLb2lCLE9BQU8zYixJQUFLLGNBaUI5QnpHLEtBQUtvSCxNQUFNeVAsV0FBWTdXLEtBQUtvaUIsU0FJN0JwaUIsS0FBSzBZLEdBQUksZ0JBQWlCMVksS0FBSzA2QixhQVVoQzMwQixPQUFRLFdBc0JQLE9BcEJBL0YsS0FBS29FLElBQUk4SCxLQUFNbE0sS0FBS21NLFNBQVVuTSxLQUFLb0gsUUFFOUJwSCxLQUFLb0gsT0FBU3BILEtBQUsyN0IsdUJBRXZCMzdCLEtBQUtxRixjQUFlckYsS0FBS29ILE1BQU8seUJBQTBCcEgsS0FBSytGLFFBRS9EL0YsS0FBSytzQixlQUFnQixXQUFZLENBQ2hDdUcsR0FBSSxtQ0FDSmxzQixNQUFPcEgsS0FBS29ILFFBSWJwSCxLQUFLeW5CLGVBRUx6VyxPQUFPcUcsYUFBYTZJLFlBQVlpVixjQUFlbjFCLE1BRS9DQSxLQUFLc0wsU0FBVXRMLEtBQUtvSCxNQUFPLHlCQUEwQnBILEtBQUsrRixTQUlwRC9GLE1BVVIrN0IsbUJBQW9CLFdBRWQvN0IsS0FBSzI3QixzQkFFVDM3QixLQUFLb0gsTUFBUTRKLE9BQU9xRyxhQUFhNkksWUFBWThiLGVBQWdCLENBRTVEbGhCLE1BQU8wQyxLQUFLQyxLQUFLN2dCLFFBQVMsa0JBQW1CLENBQzVDMmxCLE9BQVF2aUIsS0FBS29pQixPQUFPM2IsSUFBSyxXQUUxQnlYLFVBQVdsZSxLQUFLb2lCLE9BQU8zYixJQUFLLFFBRzdCekcsS0FBS29pQixPQUFPdk0sSUFBSyxxQkFBc0IsT0FDdkM3VixLQUFLb2lCLE9BQU92TSxJQUFLLGFBQWM3VixLQUFLb0gsT0FFcENwSCxLQUFLK0YsVUFJTC9GLEtBQUtpOEIsZ0JBQWlCLHlCQWN4QkMsd0JBQXlCLFNBQVVodEIsR0FFbENsUCxLQUFLbzdCLG9CQUFvQjF3QixPQUV6QixJQUFJK1csRUFBYXZTLEVBQU03SyxLQUVsQixVQUFZNkssRUFBTW9RLGNBRWZtQyxFQUFXM2lCLEdBSWxCMmlCLEVBQVdHLFlBQWEsRUFJekJILEVBQVd2RCxVQUFZbGUsS0FBS29pQixPQUFPM2IsSUFBSyxNQUV4Q2diLEVBQWF6USxPQUFPcUcsYUFBYUMsVUFBVUMsVUFBVyxhQUFja0ssR0FFcEV6aEIsS0FBS29pQixPQUFPdk0sSUFBSyxxQkFBc0IsT0FDdkM3VixLQUFLb2lCLE9BQU92TSxJQUFLLGFBQWM0TCxHQUMvQnpoQixLQUFLb0gsTUFBUXFhLEVBRWJ6aEIsS0FBSytGLFVBV05vMkIsOEJBQStCLFNBQVVqdEIsR0FFeENBLEVBQU1pVixpQkFFRG5rQixLQUFLMjdCLHNCQUVUMzdCLEtBQUtvN0Isb0JBQXNCLElBQUlyQixFQUFTLENBQ3ZDekcsR0FBSSw0QkFDSmwyQixLQUFNLENBQ0x1NUIsVUFBVSxFQUNWRCxXQUFXLEVBQ1hJLFVBQVcsK0JBQ1h3RSxhQUFhLEVBQ2IvRSxVQUFXLE9BQ1g1TyxNQUFPLElBQ1A3TSxNQUFPMEMsS0FBS0MsS0FBS0MsVUFBVywyQkFDNUJqRCxRQUFTLElBQUl1ZixFQUFZLENBQ3hCL0MsVUFBVyxrQkFDWEMsa0JBQW1CMVosS0FBS0MsS0FBS0MsVUFBVyx3Q0FDckMzWCxTQUFTM0IsSUFDYnl5QixPQUFRLFdBQ1A5MkIsU0FBU3ViLE9BQU9rUixJQUFLLGdDQUt4QnhzQixLQUFLbzdCLG9CQUFvQm5RLE9BQ3pCbHJCLFNBQVN1YixPQUFPaWdCLEtBQU0sMkJBQTRCdjdCLEtBQUtrOEIsd0JBQXlCbDhCLE9BSWhGQSxLQUFLaThCLGdCQUFpQiw4QkFheEJOLG1CQUFvQixXQUVuQixPQUFTM3FCLE9BQU9xRyxhQUF5QixhQVcxQ3FqQixXQUFZLFNBQVVqWixHQUVyQnpoQixLQUFLb2lCLE9BQU92TSxJQUFLLHFCQUFzQixNQUN2QzdWLEtBQUtvaUIsT0FBT3ZNLElBQUssYUFBYyxXQUV4QjdWLEtBQUtvSCxNQUVacEgsS0FBSytGLFVBV05rMkIsZ0JBQWlCLFNBQVUzSSxHQUUxQixJQUFJOEksRUFBSzVlLEtBQUtDLEtBQUtDLFVBQVcsbUNBRTdCMmUsRUFBTTdlLEtBQUtDLEtBQUtDLFVBQVcsd0JBRzVCMWQsS0FBS3M4QixXQUFhLElBQUl2QyxFQUFTLENBQzlCekcsR0FBSUEsRUFDSmwyQixLQUFNLENBQ0x1NUIsVUFBVSxFQUNWRCxXQUFXLEVBQ1hJLFVBQVcsK0JBQ1h3RSxhQUFhLEVBRWIzVCxNQUFPLElBQ1A3TSxNQUFPMEMsS0FBS0MsS0FBS0MsVUFBVyxnQ0FDNUJqRCxRQUFTLE9BQVMyaEIsRUFBSyxtbEJBQW1HQyxFQUFNLGNBSWxJcjhCLEtBQUtzOEIsV0FBV3JSLFNBSWZrQyxFQUFZQyxFQUFVSSxFQUFXRCxFQUFTK0ksTUFTOUN4OEIsRUFBUSxlQUFlLENBQ3JCLHFCQUNBLGFBQ0EsbUJBQ0Esa0JBQ0UsU0FDRnlpQyxFQUNBOWIsRUFDQStiLEVBQ0FqUCxHQUdELE9BQU94dEIsU0FBU0csS0FBSzBCLE9BQVE5QixFQUFFdVcsU0FBVSxDQU14Q2tULE1BQU8sU0FNUGxYLE1BQU8sQ0FDTitQLE9BQVEsQ0FDUDVLLE1BQU8ra0IsRUFDUDdQLFNBQVUsS0FDVm5ELE1BQU8sVUFFUjlILFdBQVksQ0FDWGpLLE1BQU9nbEIsRUFDUDlQLFNBQVUsS0FDVm5ELE1BQU8sY0FFUjNJLEtBQU0sQ0FDTHBKLE1BQU9pSixFQUNQaU0sU0FBVSxLQUNWbkQsTUFBTyxTQVFUK0osR0FBSSxlQUVKeHhCLE9BQVEsQ0FDUDI2QixzREFBdUQsZUFDdkRDLDREQUE2RCxjQU85RDc2QixRQUFTLE1BTVRzSyxTQUFVNGMsR0FBRzVjLFNBQVUsd0JBUXZCeEksV0FBWSxTQUFVVSxHQUVyQnJFLEtBQUsyOEIsWUFBY3Q0QixFQUFLczRCLFlBQ25CdDRCLEVBQUsyaUIsTUFDVGhuQixLQUFLdXBCLE1BQVFsbEIsRUFBSzJpQixNQVdwQmpoQixPQUFRLFNBQVUrbUIsR0FVakIsT0FSQUEsRUFBWUEsR0FBYSxHQUV6QjlzQixLQUFLb0UsSUFBSThILEtBQU1sTSxLQUFLbU0sU0FBVW5NLE9BRTlCQSxLQUFLNnNCLGdCQUFpQi9zQixFQUFFOEIsT0FBUWtyQixFQUFXLENBQzFDMUssT0FBUXBpQixLQUFLb0gsU0FHUHBILE1BWVI0OEIsYUFBYyxTQUFVMXRCLEdBRXZCQSxFQUFNaVYsaUJBQ05wa0IsU0FBU3ViLE9BQU92VCxRQUFTLHlCQVcxQjgwQixXQUFZLFNBQVUzdEIsR0FFckJBLEVBQU1pVixpQkFFTixJQUFJcUcsRUFBTzd3QixFQUFHdVYsRUFBTXFDLFFBQ25CM0wsRUFBTzRrQixFQUFLam1CLEtBQU0sYUFDWHZFLEtBQUtvRSxJQUFJMkYsS0FBTXlnQixFQUFLam1CLEtBQU0sU0FFbEN2RSxLQUFLZ3RCLFVBQVdwbkIsR0FBT0csV0FNdEJ3bkIsTUFTSnp6QixFQUFRLGlCQUFpQixDQUFFLGlCQUFrQixnQkFBaUIsZ0JBQWlCLGVBQWdCLGdCQUFpQixvQkFBc0IsU0FBVWtxQixFQUFTNlAsRUFBYS9WLEVBQVFzVSxFQUFZMkgsRUFBUytDLEdBRWxNLE9BQU8vOEIsU0FBU0csS0FBSzBCLE9BQVEsQ0FNNUIweEIsR0FBSSxpQkFFSnh4QixPQUFRLENBQ1BpN0IsMEJBQTJCLGtCQUMzQkMseUJBQTBCLGlCQUMxQkMsOEJBQStCLHVCQU9oQ3A3QixRQUFTLE1BTVRzSyxTQUFVNGMsR0FBRzVjLFNBQVUsMEJBUXZCeEksV0FBWSxTQUFVVSxHQUdyQnJFLEtBQUsyOEIsWUFBY3Q0QixFQUFLczRCLFlBR3hCMzhCLEtBQUtzTCxTQUFVdEwsS0FBSzI4QixZQUFZTyxXQUFXOTFCLE1BQU1YLElBQUssWUFBYyxNQUFPekcsS0FBSzI0Qix1QkFDaEYzNEIsS0FBS3NMLFNBQVV0TCxLQUFLMjhCLFlBQVlPLFdBQVc5MUIsTUFBTVgsSUFBSyxZQUFjLFNBQVV6RyxLQUFLMjRCLHdCQVVwRjV5QixPQUFRLFdBTVAsT0FKQS9GLEtBQUtvRSxJQUFJOEgsS0FBTWxNLEtBQUttTSxZQUNwQm5NLEtBQUttOUIsWUFDTG45QixLQUFLMjRCLHdCQUVFMzRCLE1BR1JtOUIsVUFBVyxXQUVWeGpDLEVBQUcscUJBQXNCd2pDLFVBQVcsQ0FDbkNDLFNBQVUsaUJBQ1ZDLFFBQVEsRUFDUkMsa0JBQW1CLGlCQUNuQnpSLE9BQVEsV0FDUCxPQUFPLElBQUlnSSxFQUFhLENBQUV6c0IsTUFBTyxJQUFJNGMsSUFBY2plLFNBQVMzQixLQUU3RGtLLE1BQU8sV0FDTjNVLEVBQUcsa0JBQW1CMkssU0FBVSxhQUVqQ3FLLEtBQU0sV0FDTGhWLEVBQUcsa0JBQW1CbVQsWUFBYSxlQUlyQ25ULEVBQUcsb0JBQXFCd2pDLFVBQVcsQ0FFbENDLFNBQVUsaUJBQ1ZDLFFBQVEsRUFDUkMsa0JBQW1CLGdCQUNuQnpSLE9BQVEsV0FDUCxPQUFPLElBQUl1RyxFQUFZLENBQUVockIsTUFBTyxJQUFJMFcsSUFBYS9YLFNBQVMzQixLQUUzRGtLLE1BQU8sV0FFTjNVLEVBQUcsaUJBQWtCMkssU0FBVSxhQUdoQ3FLLEtBQU0sV0FDTGhWLEVBQUcsaUJBQWtCbVQsWUFBYSxZQUNsQ25ULEVBQUcsa0JBQW1CbVQsWUFBYSxzQkFNdEN5d0IsZ0JBQWlCLFNBQVVydUIsR0FFMUJBLEVBQU1pVixpQkFDTnBrQixTQUFTdWIsT0FBT3ZULFFBQVMsb0JBRzFCeTFCLGVBQWdCLFNBQVV0dUIsR0FDekJBLEVBQU1pVixpQkFDTnBrQixTQUFTdWIsT0FBT3ZULFFBQVMsbUJBVTFCMmIsb0JBQXFCLFNBQVV4VSxHQUU5QkEsRUFBTWlWLGlCQUVOLElBQUlzWCxFQUFNLElBQUkxQixFQUFTLENBQ3RCekcsR0FBSSx3QkFDSmwyQixLQUFNLENBQ0x1NUIsVUFBVSxFQUNWRCxXQUFXLEVBQ1hJLFVBQVcsK0JBQ1h3RSxhQUFhLEVBQ2IvRSxVQUFXLE9BQ1g1TyxNQUFPLElBQ1A3TSxNQUFPMEMsS0FBS0MsS0FBS0MsVUFBVyx1QkFDNUJqRCxRQUFTLElBQUlxaUIsRUFBYyxDQUMxQjdGLFVBQVcsU0FDWEMsa0JBQW1CMVosS0FBS0MsS0FBS0MsVUFBVyxvQ0FDckMzWCxTQUFTM0IsT0FJZnEzQixFQUFJeFEsT0FDSmxyQixTQUFTdWIsT0FBTzVDLEdBQUksdUJBQXdCLFdBQzNDK2lCLEVBQUkvd0IsVUFXTml1QixzQkFBdUIsV0FFdEIsSUFBSThFLEVBQU85akMsRUFBRywyQ0FFUHFHLEtBQUsyOEIsWUFBWU8sV0FBVzkxQixNQUFNWCxJQUFLLFlBQWFoSyxPQUcxRGdoQyxFQUFLaDRCLFdBQVksWUFGakJnNEIsRUFBS2w1QixLQUFNLFdBQVksaUJBZ0IzQnpLLEVBQVEsa0JBQWtCLEdBQUksV0FFN0IsT0FBT2lHLFNBQVNHLEtBQUswQixPQUFRLENBTTVCMHhCLEdBQUksa0JBRUp4eEIsT0FBUSxDQUNQNDdCLDJCQUE0QixlQUM1QkMseUJBQTBCLGNBTzNCOTdCLFFBQVMsTUFNVHNLLFNBQVU0YyxHQUFHNWMsU0FBVSwyQkFRdkJ4SSxXQUFZLGFBWVpvQyxPQUFRLFdBRVAsT0FEQS9GLEtBQUtvRSxJQUFJOEgsS0FBTWxNLEtBQUttTSxZQUNibk0sTUFTUjQ5QixhQUFjLFNBQVUxdUIsR0FDdkJBLEVBQU1pVixpQkFDTnBrQixTQUFTdWIsT0FBT3ZULFFBQVMsaUJBUzFCODFCLFdBQVksU0FBVTN1QixHQUNyQkEsRUFBTWlWLGlCQUNOcGtCLFNBQVN1YixPQUFPdlQsUUFBUyxtQkFZNUJqTyxFQUFRLGdCQUFnQixDQUN0QixlQUNBLGlCQUNBLGtCQUNBLGtCQUNFLFNBQ0Zna0MsRUFDQUMsRUFDQS9mLEVBQ0F1UCxHQUdELE9BQU94dEIsU0FBU0csS0FBSzBCLE9BQVE5QixFQUFFdVcsU0FBVSxDQU14Q2tULE1BQU8sVUFNUGxYLE1BQU8sQ0FDTjJyQixTQUFVLENBQ1R4bUIsTUFBT3VtQixFQUNQclIsU0FBVSxLQUNWbkQsTUFBTyxXQUVSMFUsVUFBVyxDQUNWem1CLE1BQU93RyxFQUNQME8sU0FBVSxLQUNWbkQsTUFBTyxXQUVSUSxPQUFRLENBQ1B2UyxNQUFPc21CLEVBQ1BwUixTQUFVLEtBQ1ZuRCxNQUFPLFdBUVQrSixHQUFJLHdCQU1KeHhCLE9BQVEsQ0FDUG84QiwwQkFBMkIsV0FDM0JDLDBCQUEyQixXQUMzQkMsNEJBQTZCLGdCQU85QnY4QixRQUFTLFFBTVRzSyxTQUFVNGMsR0FBRzVjLFNBQVUseUJBUXZCeEksV0FBWSxTQUFVVSxHQUdyQnJFLEtBQUtrOUIsV0FBYTc0QixFQUFLNjRCLFdBRXZCbDlCLEtBQUsrRixTQUVMaEcsU0FBU3ViLE9BQU81QyxHQUFJLHNCQUF1QjFZLEtBQUtxK0IsYUFBY3IrQixNQUU5REQsU0FBU3ViLE9BQU81QyxHQUFJLGlCQUFrQjFZLEtBQUtzK0IsZUFBZ0J0K0IsTUFDM0RELFNBQVN1YixPQUFPNUMsR0FBSSxpQkFBa0IxWSxLQUFLdStCLGVBQWdCditCLE1BRTNERCxTQUFTdWIsT0FBTzVDLEdBQUksa0JBQW1CMVksS0FBS3crQixpQkFBa0J4K0IsTUFDOURELFNBQVN1YixPQUFPNUMsR0FBSSx1QkFBd0IxWSxLQUFLeStCLGdCQUFpQnorQixNQUVsRUEsS0FBSzArQixZQUFjL2tDLEVBQUcsc0JBVXZCb00sT0FBUSxTQUFVK21CLEdBRWpCQSxFQUFZQSxHQUFhLEdBRXpCOXNCLEtBQUtvRSxJQUFJOEgsS0FBTWxNLEtBQUttTSxZQUVwQm5NLEtBQUs2c0IsZ0JBQWlCL3NCLEVBQUU4QixPQUFRa3JCLEVBQVcsQ0FDMUM2UCxZQUFhMzhCLFFBR2QsSUFBSW9FLEVBQU16SyxFQUFHLGdDQVNiLE1BUkssWUFBY3FHLEtBQUt1cEIsTUFDdkJubEIsRUFBSTBJLFlBQWEsaUJBRWpCMUksRUFBSUUsU0FBVSxpQkFHZnRFLEtBQUswK0IsWUFBYzErQixLQUFLb0UsSUFBSTJGLEtBQU0scUJBRTNCL0osTUFVUjIrQixVQUFXLFNBQVVDLEdBRXBCNStCLEtBQUtvRSxJQUFJMkYsS0FBTSxzQkFBdUI4MEIsUUFBU0QsSUFVaERFLGFBQWMsV0FFYjkrQixLQUFLb0UsSUFBSTJGLEtBQU0sMENBQTJDbEUsVUFZM0R3NEIsYUFBYyxTQUFVdG9CLEdBR2xCQSxFQUFLc1ksU0FJTHRZLEVBQUtrWixxQkFFVGp2QixLQUFLMCtCLFlBQVluNkIsS0FBTSxjQUFlLFdBQ3RDdkUsS0FBSzArQixZQUFZajVCLFdBQVksY0FJN0J6RixLQUFLMCtCLFlBQVluNkIsS0FBTSxjQUFlLFNBQ3RDdkUsS0FBSzArQixZQUFZbjZCLEtBQU0sV0FBWSxlQVlyQ3c2QixTQUFVLFdBRVQvdEIsT0FBTzRhLFNBQVNGLEtBQU8xYSxPQUFPcUcsYUFBYW9JLFlBQVlsRCxzQkFXeEQraEIsZUFBZ0IsU0FBVXZvQixHQUVwQkEsRUFBS3NZLFNBQ1Q3USxLQUFLdUksUUFBUXpYLE1BQU90TyxLQUFLMCtCLFlBQVkzMEIsS0FBTSxLQUFPLFNBQ2xEL0osS0FBSzArQixZQUFZbjZCLEtBQU0sQ0FDdEJ5NkIsY0FBZSxTQUNmQyxTQUFVLGVBY2JWLGVBQWdCLFNBQVV4b0IsRUFBTTFSLEdBRS9CLElBQU8wUixFQUFLc1ksT0FBUyxDQUVwQixJQUFJbFEsRUFBUyxRQUliLEdBRkFuZSxLQUFLOCtCLGVBRUEsVUFBWXo2QixFQUFLOFosT0FBUyxDQUU5QkEsRUFBUyxRQUVULElBQUlrRyxFQUFNaGdCLEVBQUt3cUIsUUFDZCtQLEVBQU9qbEMsRUFBRyxxQ0FFTixpQkFBb0IwcUIsRUFDeEJ2a0IsRUFBRWUsS0FBTXdqQixFQUFLLFNBQVU2YSxHQUN0Qk4sRUFBS3oxQixPQUFRLE9BQVMrMUIsRUFBTSxXQUc3Qk4sRUFBT0EsRUFBS3oxQixPQUFRLE9BQVNrYixFQUFNLFNBR3BDcmtCLEtBQUsyK0IsVUFBV0MsR0FJakI1K0IsS0FBSzArQixZQUFZMzBCLEtBQU0sa0JBQW1CbEUsU0FDMUM3RixLQUFLMCtCLFlBQVluNkIsS0FBTSxDQUN0Qnk2QixjQUFlN2dCLEVBQ2Y4Z0IsU0FBVSxlQWFiRSxpQkFBa0IsV0FFakIsTUFBUyxXQUFhbi9CLEtBQUt1cEIsT0FVNUJrVixnQkFBaUIsV0FFaEJ6K0IsS0FBS2d0QixVQUFXLFdBQVlqbkIsVUFXN0J5NEIsaUJBQWtCLFNBQVVZLEVBQWNwWSxHQUVwQyxXQUFhaG5CLEtBQUt1cEIsTUFDdEJ2cEIsS0FBS2d0QixVQUFXLFVBRWhCaHRCLEtBQUt5c0IsZUFBZ0IsVUFHdEJ6c0IsS0FBSytGLE9BQVEsQ0FDWnFCLE1BQU9nNEIsRUFDUHBZLElBQUtBLEtBV1BzSixTQUFVLFdBRVR0ZixPQUFPcUcsYUFBYXRCLEtBQUt1YSxhQUl4Qi9DLE1BU0oxekIsRUFBUyxDQUNSLGlDQUNBLDBCQUNBLHdCQUNBLG9CQUNBLHNCQUNBLG1CQUNBLGdCQUNBLGVBQ0EsaUJBQ0UsU0FDRndsQyxFQUNBQyxFQUNBQyxFQUNBQyxFQUNBQyxFQUNBQyxFQUNBaFMsRUFDQXdQLEVBQ0FQLEdBZ0JBLFNBQVNnRCxFQUFlQyxFQUFVQyxHQUNqQyxPQUFXLy9CLEVBQUVjLFFBQVNpL0IsS0FBYSxJQUFNQSxFQUFPN2hDLFFBQVM0aEMsSUFBZ0JBLEdBQVlDLEVBZHRGN3VCLE9BQU9xRyxhQUFhMEksTUFBUSxJQUFJeWYsRUFBT3h1QixPQUFPcUcsYUFBYTBJLE9BQzNEL08sT0FBT3FHLGFBQWFDLFVBQVksSUFBSWlvQixFQUNwQ3Z1QixPQUFPcUcsYUFBYXVGLFFBQVUsSUFBSTZpQixFQUFTenVCLE9BQU9xRyxhQUFhdUYsU0FvQi9EOWMsRUFBRWdnQyxNQUFPLENBWVJDLFFBQVMsU0FBVUgsRUFBVUMsR0FDNUIsT0FBS0YsRUFBZUMsRUFBVUMsR0FDdEIscUJBRUQsSUFVUi9KLFVBQVcsU0FBVTE2QixHQUVwQixJQUFJbUcsRUFBUXpCLEVBQUV5QixNQUFPbkcsR0FRckIsT0FOQTBFLEVBQUVlLEtBQU1VLEVBQU8sU0FBVWdVLEVBQUtwQyxJQUN0QnJULEVBQUV3QixXQUFZaVUsSUFBU3pWLEVBQUVxQixTQUFVb1UsS0FDekNoVSxFQUFPNFIsR0FBUXJULEVBQUVnMkIsVUFBV3ZnQixNQUl2QmhVLEdBY1JxaUIsU0FBVSxTQUFVZ2MsRUFBVUMsR0FDN0IsT0FBS0YsRUFBZUMsRUFBVUMsR0FDdEIsdUJBRUQsSUFXUnJhLGdCQUFpQixTQUFVL0ssRUFBU3VsQixHQUU1QkEsSUFDTkEsRUFBZSxDQUFFLElBQUssSUFBSyxJQUFLLFNBQVUsT0FHM0MsSUFBSTlILEVBQVF2K0IsRUFBRyxRQUFVOGdCLEVBQVUsVUFRbkMsT0FOQXlkLEVBQU1udUIsS0FBTSxLQUFNazJCLElBQUtELEVBQWFoakMsS0FBTSxNQUFRNkQsS0FBTSxXQUV2RGxILEVBQUdxRyxNQUFPa2dDLFlBQWFsZ0MsS0FBS21nQyxhQUl0QmpJLEVBQU1oc0IsVUFNZm5NLFNBQVN1YixPQUFTeGIsRUFBRThCLE9BQVEsR0FBSTdCLFNBQVNxZ0MsUUFFekN6bUMsRUFBR2tQLFVBQVdkLFFBQVMseUJBRXZCaUosT0FBT3FHLGFBQWFrRCxVQUFZdkosT0FBT3FHLGFBQWFDLFVBQVVHLGVBQWdCLGdCQUFpQnpHLE9BQU9xRyxhQUFha0QsV0FFbkgsSUFBSWtGLEVBQWN6TyxPQUFPcUcsYUFBYUMsVUFBVUMsVUFBVyxTQUFVdkcsT0FBT3FHLGFBQWEwSixRQUN6Ri9QLE9BQU9xRyxhQUFhb0ksWUFBY0EsRUFFbEN6TyxPQUFPcUcsYUFBYXRCLEtBQU8sSUFBSTJwQixFQUFNamdCLEVBQWF6TyxPQUFPcUcsYUFBYXRCLE1BRXRFLElBQUkrTixFQUFTLElBQUlvWixFQUFZLENBQzVCOTFCLE1BQU9xWSxJQUdKNGdCLEVBQVUsSUFBSTFELEVBQWEsQ0FDOUJPLFdBQVlwWixJQUdibnFCLEVBQUdrUCxVQUFXZCxRQUFTLG9CQUFxQixDQUMzQ2daLE9BQVErQyxFQUNSd2MsUUFBU0QsTUFLWHZtQyxFQUFPLE9BQVEsY0F0dlVmLENBd3ZVRStGIiwiZmlsZSI6ImxsbXMtYnVpbGRlci5taW4uanMiLCJzb3VyY2VzQ29udGVudCI6WyIoZnVuY3Rpb24oJCl7XG4vKipcbiAqIEBsaWNlbnNlIGFsbW9uZCAwLjMuMyBDb3B5cmlnaHQgalF1ZXJ5IEZvdW5kYXRpb24gYW5kIG90aGVyIGNvbnRyaWJ1dG9ycy5cbiAqIFJlbGVhc2VkIHVuZGVyIE1JVCBsaWNlbnNlLCBodHRwOi8vZ2l0aHViLmNvbS9yZXF1aXJlanMvYWxtb25kL0xJQ0VOU0VcbiAqL1xuLy9Hb2luZyBzbG9wcHkgdG8gYXZvaWQgJ3VzZSBzdHJpY3QnIHN0cmluZyBjb3N0LCBidXQgc3RyaWN0IHByYWN0aWNlcyBzaG91bGRcbi8vYmUgZm9sbG93ZWQuXG4vKmdsb2JhbCBzZXRUaW1lb3V0OiBmYWxzZSAqL1xuXG52YXIgcmVxdWlyZWpzLCByZXF1aXJlLCBkZWZpbmU7XG4oZnVuY3Rpb24gKHVuZGVmKSB7XG5cdHZhciBtYWluLCByZXEsIG1ha2VNYXAsIGhhbmRsZXJzLFxuXHRcdGRlZmluZWQgPSB7fSxcblx0XHR3YWl0aW5nID0ge30sXG5cdFx0Y29uZmlnID0ge30sXG5cdFx0ZGVmaW5pbmcgPSB7fSxcblx0XHRoYXNPd24gPSBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LFxuXHRcdGFwcyA9IFtdLnNsaWNlLFxuXHRcdGpzU3VmZml4UmVnRXhwID0gL1xcLmpzJC87XG5cblx0ZnVuY3Rpb24gaGFzUHJvcChvYmosIHByb3ApIHtcblx0XHRyZXR1cm4gaGFzT3duLmNhbGwob2JqLCBwcm9wKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBHaXZlbiBhIHJlbGF0aXZlIG1vZHVsZSBuYW1lLCBsaWtlIC4vc29tZXRoaW5nLCBub3JtYWxpemUgaXQgdG9cblx0ICogYSByZWFsIG5hbWUgdGhhdCBjYW4gYmUgbWFwcGVkIHRvIGEgcGF0aC5cblx0ICogQHBhcmFtIHtTdHJpbmd9IG5hbWUgdGhlIHJlbGF0aXZlIG5hbWVcblx0ICogQHBhcmFtIHtTdHJpbmd9IGJhc2VOYW1lIGEgcmVhbCBuYW1lIHRoYXQgdGhlIG5hbWUgYXJnIGlzIHJlbGF0aXZlXG5cdCAqIHRvLlxuXHQgKiBAcmV0dXJucyB7U3RyaW5nfSBub3JtYWxpemVkIG5hbWVcblx0ICovXG5cdGZ1bmN0aW9uIG5vcm1hbGl6ZShuYW1lLCBiYXNlTmFtZSkge1xuXHRcdHZhciBuYW1lUGFydHMsIG5hbWVTZWdtZW50LCBtYXBWYWx1ZSwgZm91bmRNYXAsIGxhc3RJbmRleCxcblx0XHRcdGZvdW5kSSwgZm91bmRTdGFyTWFwLCBzdGFySSwgaSwgaiwgcGFydCwgbm9ybWFsaXplZEJhc2VQYXJ0cyxcblx0XHRcdGJhc2VQYXJ0cyA9IGJhc2VOYW1lICYmIGJhc2VOYW1lLnNwbGl0KFwiL1wiKSxcblx0XHRcdG1hcCA9IGNvbmZpZy5tYXAsXG5cdFx0XHRzdGFyTWFwID0gKG1hcCAmJiBtYXBbJyonXSkgfHwge307XG5cblx0XHQvL0FkanVzdCBhbnkgcmVsYXRpdmUgcGF0aHMuXG5cdFx0aWYgKG5hbWUpIHtcblx0XHRcdG5hbWUgPSBuYW1lLnNwbGl0KCcvJyk7XG5cdFx0XHRsYXN0SW5kZXggPSBuYW1lLmxlbmd0aCAtIDE7XG5cblx0XHRcdC8vIElmIHdhbnRpbmcgbm9kZSBJRCBjb21wYXRpYmlsaXR5LCBzdHJpcCAuanMgZnJvbSBlbmRcblx0XHRcdC8vIG9mIElEcy4gSGF2ZSB0byBkbyB0aGlzIGhlcmUsIGFuZCBub3QgaW4gbmFtZVRvVXJsXG5cdFx0XHQvLyBiZWNhdXNlIG5vZGUgYWxsb3dzIGVpdGhlciAuanMgb3Igbm9uIC5qcyB0byBtYXBcblx0XHRcdC8vIHRvIHNhbWUgZmlsZS5cblx0XHRcdGlmIChjb25maWcubm9kZUlkQ29tcGF0ICYmIGpzU3VmZml4UmVnRXhwLnRlc3QobmFtZVtsYXN0SW5kZXhdKSkge1xuXHRcdFx0XHRuYW1lW2xhc3RJbmRleF0gPSBuYW1lW2xhc3RJbmRleF0ucmVwbGFjZShqc1N1ZmZpeFJlZ0V4cCwgJycpO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBTdGFydHMgd2l0aCBhICcuJyBzbyBuZWVkIHRoZSBiYXNlTmFtZVxuXHRcdFx0aWYgKG5hbWVbMF0uY2hhckF0KDApID09PSAnLicgJiYgYmFzZVBhcnRzKSB7XG5cdFx0XHRcdC8vQ29udmVydCBiYXNlTmFtZSB0byBhcnJheSwgYW5kIGxvcCBvZmYgdGhlIGxhc3QgcGFydCxcblx0XHRcdFx0Ly9zbyB0aGF0IC4gbWF0Y2hlcyB0aGF0ICdkaXJlY3RvcnknIGFuZCBub3QgbmFtZSBvZiB0aGUgYmFzZU5hbWUnc1xuXHRcdFx0XHQvL21vZHVsZS4gRm9yIGluc3RhbmNlLCBiYXNlTmFtZSBvZiAnb25lL3R3by90aHJlZScsIG1hcHMgdG9cblx0XHRcdFx0Ly8nb25lL3R3by90aHJlZS5qcycsIGJ1dCB3ZSB3YW50IHRoZSBkaXJlY3RvcnksICdvbmUvdHdvJyBmb3Jcblx0XHRcdFx0Ly90aGlzIG5vcm1hbGl6YXRpb24uXG5cdFx0XHRcdG5vcm1hbGl6ZWRCYXNlUGFydHMgPSBiYXNlUGFydHMuc2xpY2UoMCwgYmFzZVBhcnRzLmxlbmd0aCAtIDEpO1xuXHRcdFx0XHRuYW1lID0gbm9ybWFsaXplZEJhc2VQYXJ0cy5jb25jYXQobmFtZSk7XG5cdFx0XHR9XG5cblx0XHRcdC8vc3RhcnQgdHJpbURvdHNcblx0XHRcdGZvciAoaSA9IDA7IGkgPCBuYW1lLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRcdHBhcnQgPSBuYW1lW2ldO1xuXHRcdFx0XHRpZiAocGFydCA9PT0gJy4nKSB7XG5cdFx0XHRcdFx0bmFtZS5zcGxpY2UoaSwgMSk7XG5cdFx0XHRcdFx0aSAtPSAxO1xuXHRcdFx0XHR9IGVsc2UgaWYgKHBhcnQgPT09ICcuLicpIHtcblx0XHRcdFx0XHQvLyBJZiBhdCB0aGUgc3RhcnQsIG9yIHByZXZpb3VzIHZhbHVlIGlzIHN0aWxsIC4uLFxuXHRcdFx0XHRcdC8vIGtlZXAgdGhlbSBzbyB0aGF0IHdoZW4gY29udmVydGVkIHRvIGEgcGF0aCBpdCBtYXlcblx0XHRcdFx0XHQvLyBzdGlsbCB3b3JrIHdoZW4gY29udmVydGVkIHRvIGEgcGF0aCwgZXZlbiB0aG91Z2hcblx0XHRcdFx0XHQvLyBhcyBhbiBJRCBpdCBpcyBsZXNzIHRoYW4gaWRlYWwuIEluIGxhcmdlciBwb2ludFxuXHRcdFx0XHRcdC8vIHJlbGVhc2VzLCBtYXkgYmUgYmV0dGVyIHRvIGp1c3Qga2ljayBvdXQgYW4gZXJyb3IuXG5cdFx0XHRcdFx0aWYgKGkgPT09IDAgfHwgKGkgPT09IDEgJiYgbmFtZVsyXSA9PT0gJy4uJykgfHwgbmFtZVtpIC0gMV0gPT09ICcuLicpIHtcblx0XHRcdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0XHRcdH0gZWxzZSBpZiAoaSA+IDApIHtcblx0XHRcdFx0XHRcdG5hbWUuc3BsaWNlKGkgLSAxLCAyKTtcblx0XHRcdFx0XHRcdGkgLT0gMjtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdC8vZW5kIHRyaW1Eb3RzXG5cblx0XHRcdG5hbWUgPSBuYW1lLmpvaW4oJy8nKTtcblx0XHR9XG5cblx0XHQvL0FwcGx5IG1hcCBjb25maWcgaWYgYXZhaWxhYmxlLlxuXHRcdGlmICgoYmFzZVBhcnRzIHx8IHN0YXJNYXApICYmIG1hcCkge1xuXHRcdFx0bmFtZVBhcnRzID0gbmFtZS5zcGxpdCgnLycpO1xuXG5cdFx0XHRmb3IgKGkgPSBuYW1lUGFydHMubGVuZ3RoOyBpID4gMDsgaSAtPSAxKSB7XG5cdFx0XHRcdG5hbWVTZWdtZW50ID0gbmFtZVBhcnRzLnNsaWNlKDAsIGkpLmpvaW4oXCIvXCIpO1xuXG5cdFx0XHRcdGlmIChiYXNlUGFydHMpIHtcblx0XHRcdFx0XHQvL0ZpbmQgdGhlIGxvbmdlc3QgYmFzZU5hbWUgc2VnbWVudCBtYXRjaCBpbiB0aGUgY29uZmlnLlxuXHRcdFx0XHRcdC8vU28sIGRvIGpvaW5zIG9uIHRoZSBiaWdnZXN0IHRvIHNtYWxsZXN0IGxlbmd0aHMgb2YgYmFzZVBhcnRzLlxuXHRcdFx0XHRcdGZvciAoaiA9IGJhc2VQYXJ0cy5sZW5ndGg7IGogPiAwOyBqIC09IDEpIHtcblx0XHRcdFx0XHRcdG1hcFZhbHVlID0gbWFwW2Jhc2VQYXJ0cy5zbGljZSgwLCBqKS5qb2luKCcvJyldO1xuXG5cdFx0XHRcdFx0XHQvL2Jhc2VOYW1lIHNlZ21lbnQgaGFzICBjb25maWcsIGZpbmQgaWYgaXQgaGFzIG9uZSBmb3Jcblx0XHRcdFx0XHRcdC8vdGhpcyBuYW1lLlxuXHRcdFx0XHRcdFx0aWYgKG1hcFZhbHVlKSB7XG5cdFx0XHRcdFx0XHRcdG1hcFZhbHVlID0gbWFwVmFsdWVbbmFtZVNlZ21lbnRdO1xuXHRcdFx0XHRcdFx0XHRpZiAobWFwVmFsdWUpIHtcblx0XHRcdFx0XHRcdFx0XHQvL01hdGNoLCB1cGRhdGUgbmFtZSB0byB0aGUgbmV3IHZhbHVlLlxuXHRcdFx0XHRcdFx0XHRcdGZvdW5kTWFwID0gbWFwVmFsdWU7XG5cdFx0XHRcdFx0XHRcdFx0Zm91bmRJID0gaTtcblx0XHRcdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmIChmb3VuZE1hcCkge1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly9DaGVjayBmb3IgYSBzdGFyIG1hcCBtYXRjaCwgYnV0IGp1c3QgaG9sZCBvbiB0byBpdCxcblx0XHRcdFx0Ly9pZiB0aGVyZSBpcyBhIHNob3J0ZXIgc2VnbWVudCBtYXRjaCBsYXRlciBpbiBhIG1hdGNoaW5nXG5cdFx0XHRcdC8vY29uZmlnLCB0aGVuIGZhdm9yIG92ZXIgdGhpcyBzdGFyIG1hcC5cblx0XHRcdFx0aWYgKCFmb3VuZFN0YXJNYXAgJiYgc3Rhck1hcCAmJiBzdGFyTWFwW25hbWVTZWdtZW50XSkge1xuXHRcdFx0XHRcdGZvdW5kU3Rhck1hcCA9IHN0YXJNYXBbbmFtZVNlZ21lbnRdO1xuXHRcdFx0XHRcdHN0YXJJID0gaTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIWZvdW5kTWFwICYmIGZvdW5kU3Rhck1hcCkge1xuXHRcdFx0XHRmb3VuZE1hcCA9IGZvdW5kU3Rhck1hcDtcblx0XHRcdFx0Zm91bmRJID0gc3Rhckk7XG5cdFx0XHR9XG5cblx0XHRcdGlmIChmb3VuZE1hcCkge1xuXHRcdFx0XHRuYW1lUGFydHMuc3BsaWNlKDAsIGZvdW5kSSwgZm91bmRNYXApO1xuXHRcdFx0XHRuYW1lID0gbmFtZVBhcnRzLmpvaW4oJy8nKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gbmFtZTtcblx0fVxuXG5cdGZ1bmN0aW9uIG1ha2VSZXF1aXJlKHJlbE5hbWUsIGZvcmNlU3luYykge1xuXHRcdHJldHVybiBmdW5jdGlvbiAoKSB7XG5cdFx0XHQvL0EgdmVyc2lvbiBvZiBhIHJlcXVpcmUgZnVuY3Rpb24gdGhhdCBwYXNzZXMgYSBtb2R1bGVOYW1lXG5cdFx0XHQvL3ZhbHVlIGZvciBpdGVtcyB0aGF0IG1heSBuZWVkIHRvXG5cdFx0XHQvL2xvb2sgdXAgcGF0aHMgcmVsYXRpdmUgdG8gdGhlIG1vZHVsZU5hbWVcblx0XHRcdHZhciBhcmdzID0gYXBzLmNhbGwoYXJndW1lbnRzLCAwKTtcblxuXHRcdFx0Ly9JZiBmaXJzdCBhcmcgaXMgbm90IHJlcXVpcmUoJ3N0cmluZycpLCBhbmQgdGhlcmUgaXMgb25seVxuXHRcdFx0Ly9vbmUgYXJnLCBpdCBpcyB0aGUgYXJyYXkgZm9ybSB3aXRob3V0IGEgY2FsbGJhY2suIEluc2VydFxuXHRcdFx0Ly9hIG51bGwgc28gdGhhdCB0aGUgZm9sbG93aW5nIGNvbmNhdCBpcyBjb3JyZWN0LlxuXHRcdFx0aWYgKHR5cGVvZiBhcmdzWzBdICE9PSAnc3RyaW5nJyAmJiBhcmdzLmxlbmd0aCA9PT0gMSkge1xuXHRcdFx0XHRhcmdzLnB1c2gobnVsbCk7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gcmVxLmFwcGx5KHVuZGVmLCBhcmdzLmNvbmNhdChbcmVsTmFtZSwgZm9yY2VTeW5jXSkpO1xuXHRcdH07XG5cdH1cblxuXHRmdW5jdGlvbiBtYWtlTm9ybWFsaXplKHJlbE5hbWUpIHtcblx0XHRyZXR1cm4gZnVuY3Rpb24gKG5hbWUpIHtcblx0XHRcdHJldHVybiBub3JtYWxpemUobmFtZSwgcmVsTmFtZSk7XG5cdFx0fTtcblx0fVxuXG5cdGZ1bmN0aW9uIG1ha2VMb2FkKGRlcE5hbWUpIHtcblx0XHRyZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG5cdFx0XHRkZWZpbmVkW2RlcE5hbWVdID0gdmFsdWU7XG5cdFx0fTtcblx0fVxuXG5cdGZ1bmN0aW9uIGNhbGxEZXAobmFtZSkge1xuXHRcdGlmIChoYXNQcm9wKHdhaXRpbmcsIG5hbWUpKSB7XG5cdFx0XHR2YXIgYXJncyA9IHdhaXRpbmdbbmFtZV07XG5cdFx0XHRkZWxldGUgd2FpdGluZ1tuYW1lXTtcblx0XHRcdGRlZmluaW5nW25hbWVdID0gdHJ1ZTtcblx0XHRcdG1haW4uYXBwbHkodW5kZWYsIGFyZ3MpO1xuXHRcdH1cblxuXHRcdGlmICghaGFzUHJvcChkZWZpbmVkLCBuYW1lKSAmJiAhaGFzUHJvcChkZWZpbmluZywgbmFtZSkpIHtcblx0XHRcdHRocm93IG5ldyBFcnJvcignTm8gJyArIG5hbWUpO1xuXHRcdH1cblx0XHRyZXR1cm4gZGVmaW5lZFtuYW1lXTtcblx0fVxuXG5cdC8vVHVybnMgYSBwbHVnaW4hcmVzb3VyY2UgdG8gW3BsdWdpbiwgcmVzb3VyY2VdXG5cdC8vd2l0aCB0aGUgcGx1Z2luIGJlaW5nIHVuZGVmaW5lZCBpZiB0aGUgbmFtZVxuXHQvL2RpZCBub3QgaGF2ZSBhIHBsdWdpbiBwcmVmaXguXG5cdGZ1bmN0aW9uIHNwbGl0UHJlZml4KG5hbWUpIHtcblx0XHR2YXIgcHJlZml4LFxuXHRcdFx0aW5kZXggPSBuYW1lID8gbmFtZS5pbmRleE9mKCchJykgOiAtMTtcblx0XHRpZiAoaW5kZXggPiAtMSkge1xuXHRcdFx0cHJlZml4ID0gbmFtZS5zdWJzdHJpbmcoMCwgaW5kZXgpO1xuXHRcdFx0bmFtZSA9IG5hbWUuc3Vic3RyaW5nKGluZGV4ICsgMSwgbmFtZS5sZW5ndGgpO1xuXHRcdH1cblx0XHRyZXR1cm4gW3ByZWZpeCwgbmFtZV07XG5cdH1cblxuXHQvL0NyZWF0ZXMgYSBwYXJ0cyBhcnJheSBmb3IgYSByZWxOYW1lIHdoZXJlIGZpcnN0IHBhcnQgaXMgcGx1Z2luIElELFxuXHQvL3NlY29uZCBwYXJ0IGlzIHJlc291cmNlIElELiBBc3N1bWVzIHJlbE5hbWUgaGFzIGFscmVhZHkgYmVlbiBub3JtYWxpemVkLlxuXHRmdW5jdGlvbiBtYWtlUmVsUGFydHMocmVsTmFtZSkge1xuXHRcdHJldHVybiByZWxOYW1lID8gc3BsaXRQcmVmaXgocmVsTmFtZSkgOiBbXTtcblx0fVxuXG5cdC8qKlxuXHQgKiBNYWtlcyBhIG5hbWUgbWFwLCBub3JtYWxpemluZyB0aGUgbmFtZSwgYW5kIHVzaW5nIGEgcGx1Z2luXG5cdCAqIGZvciBub3JtYWxpemF0aW9uIGlmIG5lY2Vzc2FyeS4gR3JhYnMgYSByZWYgdG8gcGx1Z2luXG5cdCAqIHRvbywgYXMgYW4gb3B0aW1pemF0aW9uLlxuXHQgKi9cblx0bWFrZU1hcCA9IGZ1bmN0aW9uIChuYW1lLCByZWxQYXJ0cykge1xuXHRcdHZhciBwbHVnaW4sXG5cdFx0XHRwYXJ0cyA9IHNwbGl0UHJlZml4KG5hbWUpLFxuXHRcdFx0cHJlZml4ID0gcGFydHNbMF0sXG5cdFx0XHRyZWxSZXNvdXJjZU5hbWUgPSByZWxQYXJ0c1sxXTtcblxuXHRcdG5hbWUgPSBwYXJ0c1sxXTtcblxuXHRcdGlmIChwcmVmaXgpIHtcblx0XHRcdHByZWZpeCA9IG5vcm1hbGl6ZShwcmVmaXgsIHJlbFJlc291cmNlTmFtZSk7XG5cdFx0XHRwbHVnaW4gPSBjYWxsRGVwKHByZWZpeCk7XG5cdFx0fVxuXG5cdFx0Ly9Ob3JtYWxpemUgYWNjb3JkaW5nXG5cdFx0aWYgKHByZWZpeCkge1xuXHRcdFx0aWYgKHBsdWdpbiAmJiBwbHVnaW4ubm9ybWFsaXplKSB7XG5cdFx0XHRcdG5hbWUgPSBwbHVnaW4ubm9ybWFsaXplKG5hbWUsIG1ha2VOb3JtYWxpemUocmVsUmVzb3VyY2VOYW1lKSk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRuYW1lID0gbm9ybWFsaXplKG5hbWUsIHJlbFJlc291cmNlTmFtZSk7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIHtcblx0XHRcdG5hbWUgPSBub3JtYWxpemUobmFtZSwgcmVsUmVzb3VyY2VOYW1lKTtcblx0XHRcdHBhcnRzID0gc3BsaXRQcmVmaXgobmFtZSk7XG5cdFx0XHRwcmVmaXggPSBwYXJ0c1swXTtcblx0XHRcdG5hbWUgPSBwYXJ0c1sxXTtcblx0XHRcdGlmIChwcmVmaXgpIHtcblx0XHRcdFx0cGx1Z2luID0gY2FsbERlcChwcmVmaXgpO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vVXNpbmcgcmlkaWN1bG91cyBwcm9wZXJ0eSBuYW1lcyBmb3Igc3BhY2UgcmVhc29uc1xuXHRcdHJldHVybiB7XG5cdFx0XHRmOiBwcmVmaXggPyBwcmVmaXggKyAnIScgKyBuYW1lIDogbmFtZSwgLy9mdWxsTmFtZVxuXHRcdFx0bjogbmFtZSxcblx0XHRcdHByOiBwcmVmaXgsXG5cdFx0XHRwOiBwbHVnaW5cblx0XHR9O1xuXHR9O1xuXG5cdGZ1bmN0aW9uIG1ha2VDb25maWcobmFtZSkge1xuXHRcdHJldHVybiBmdW5jdGlvbiAoKSB7XG5cdFx0XHRyZXR1cm4gKGNvbmZpZyAmJiBjb25maWcuY29uZmlnICYmIGNvbmZpZy5jb25maWdbbmFtZV0pIHx8IHt9O1xuXHRcdH07XG5cdH1cblxuXHRoYW5kbGVycyA9IHtcblx0XHRyZXF1aXJlOiBmdW5jdGlvbiAobmFtZSkge1xuXHRcdFx0cmV0dXJuIG1ha2VSZXF1aXJlKG5hbWUpO1xuXHRcdH0sXG5cdFx0ZXhwb3J0czogZnVuY3Rpb24gKG5hbWUpIHtcblx0XHRcdHZhciBlID0gZGVmaW5lZFtuYW1lXTtcblx0XHRcdGlmICh0eXBlb2YgZSAhPT0gJ3VuZGVmaW5lZCcpIHtcblx0XHRcdFx0cmV0dXJuIGU7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRyZXR1cm4gKGRlZmluZWRbbmFtZV0gPSB7fSk7XG5cdFx0XHR9XG5cdFx0fSxcblx0XHRtb2R1bGU6IGZ1bmN0aW9uIChuYW1lKSB7XG5cdFx0XHRyZXR1cm4ge1xuXHRcdFx0XHRpZDogbmFtZSxcblx0XHRcdFx0dXJpOiAnJyxcblx0XHRcdFx0ZXhwb3J0czogZGVmaW5lZFtuYW1lXSxcblx0XHRcdFx0Y29uZmlnOiBtYWtlQ29uZmlnKG5hbWUpXG5cdFx0XHR9O1xuXHRcdH1cblx0fTtcblxuXHRtYWluID0gZnVuY3Rpb24gKG5hbWUsIGRlcHMsIGNhbGxiYWNrLCByZWxOYW1lKSB7XG5cdFx0dmFyIGNqc01vZHVsZSwgZGVwTmFtZSwgcmV0LCBtYXAsIGksIHJlbFBhcnRzLFxuXHRcdFx0YXJncyA9IFtdLFxuXHRcdFx0Y2FsbGJhY2tUeXBlID0gdHlwZW9mIGNhbGxiYWNrLFxuXHRcdFx0dXNpbmdFeHBvcnRzO1xuXG5cdFx0Ly9Vc2UgbmFtZSBpZiBubyByZWxOYW1lXG5cdFx0cmVsTmFtZSA9IHJlbE5hbWUgfHwgbmFtZTtcblx0XHRyZWxQYXJ0cyA9IG1ha2VSZWxQYXJ0cyhyZWxOYW1lKTtcblxuXHRcdC8vQ2FsbCB0aGUgY2FsbGJhY2sgdG8gZGVmaW5lIHRoZSBtb2R1bGUsIGlmIG5lY2Vzc2FyeS5cblx0XHRpZiAoY2FsbGJhY2tUeXBlID09PSAndW5kZWZpbmVkJyB8fCBjYWxsYmFja1R5cGUgPT09ICdmdW5jdGlvbicpIHtcblx0XHRcdC8vUHVsbCBvdXQgdGhlIGRlZmluZWQgZGVwZW5kZW5jaWVzIGFuZCBwYXNzIHRoZSBvcmRlcmVkXG5cdFx0XHQvL3ZhbHVlcyB0byB0aGUgY2FsbGJhY2suXG5cdFx0XHQvL0RlZmF1bHQgdG8gW3JlcXVpcmUsIGV4cG9ydHMsIG1vZHVsZV0gaWYgbm8gZGVwc1xuXHRcdFx0ZGVwcyA9ICFkZXBzLmxlbmd0aCAmJiBjYWxsYmFjay5sZW5ndGggPyBbJ3JlcXVpcmUnLCAnZXhwb3J0cycsICdtb2R1bGUnXSA6IGRlcHM7XG5cdFx0XHRmb3IgKGkgPSAwOyBpIDwgZGVwcy5sZW5ndGg7IGkgKz0gMSkge1xuXHRcdFx0XHRtYXAgPSBtYWtlTWFwKGRlcHNbaV0sIHJlbFBhcnRzKTtcblx0XHRcdFx0ZGVwTmFtZSA9IG1hcC5mO1xuXG5cdFx0XHRcdC8vRmFzdCBwYXRoIENvbW1vbkpTIHN0YW5kYXJkIGRlcGVuZGVuY2llcy5cblx0XHRcdFx0aWYgKGRlcE5hbWUgPT09IFwicmVxdWlyZVwiKSB7XG5cdFx0XHRcdFx0YXJnc1tpXSA9IGhhbmRsZXJzLnJlcXVpcmUobmFtZSk7XG5cdFx0XHRcdH0gZWxzZSBpZiAoZGVwTmFtZSA9PT0gXCJleHBvcnRzXCIpIHtcblx0XHRcdFx0XHQvL0NvbW1vbkpTIG1vZHVsZSBzcGVjIDEuMVxuXHRcdFx0XHRcdGFyZ3NbaV0gPSBoYW5kbGVycy5leHBvcnRzKG5hbWUpO1xuXHRcdFx0XHRcdHVzaW5nRXhwb3J0cyA9IHRydWU7XG5cdFx0XHRcdH0gZWxzZSBpZiAoZGVwTmFtZSA9PT0gXCJtb2R1bGVcIikge1xuXHRcdFx0XHRcdC8vQ29tbW9uSlMgbW9kdWxlIHNwZWMgMS4xXG5cdFx0XHRcdFx0Y2pzTW9kdWxlID0gYXJnc1tpXSA9IGhhbmRsZXJzLm1vZHVsZShuYW1lKTtcblx0XHRcdFx0fSBlbHNlIGlmIChoYXNQcm9wKGRlZmluZWQsIGRlcE5hbWUpIHx8XG5cdFx0XHRcdFx0XHQgICBoYXNQcm9wKHdhaXRpbmcsIGRlcE5hbWUpIHx8XG5cdFx0XHRcdFx0XHQgICBoYXNQcm9wKGRlZmluaW5nLCBkZXBOYW1lKSkge1xuXHRcdFx0XHRcdGFyZ3NbaV0gPSBjYWxsRGVwKGRlcE5hbWUpO1xuXHRcdFx0XHR9IGVsc2UgaWYgKG1hcC5wKSB7XG5cdFx0XHRcdFx0bWFwLnAubG9hZChtYXAubiwgbWFrZVJlcXVpcmUocmVsTmFtZSwgdHJ1ZSksIG1ha2VMb2FkKGRlcE5hbWUpLCB7fSk7XG5cdFx0XHRcdFx0YXJnc1tpXSA9IGRlZmluZWRbZGVwTmFtZV07XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0dGhyb3cgbmV3IEVycm9yKG5hbWUgKyAnIG1pc3NpbmcgJyArIGRlcE5hbWUpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdHJldCA9IGNhbGxiYWNrID8gY2FsbGJhY2suYXBwbHkoZGVmaW5lZFtuYW1lXSwgYXJncykgOiB1bmRlZmluZWQ7XG5cblx0XHRcdGlmIChuYW1lKSB7XG5cdFx0XHRcdC8vSWYgc2V0dGluZyBleHBvcnRzIHZpYSBcIm1vZHVsZVwiIGlzIGluIHBsYXksXG5cdFx0XHRcdC8vZmF2b3IgdGhhdCBvdmVyIHJldHVybiB2YWx1ZSBhbmQgZXhwb3J0cy4gQWZ0ZXIgdGhhdCxcblx0XHRcdFx0Ly9mYXZvciBhIG5vbi11bmRlZmluZWQgcmV0dXJuIHZhbHVlIG92ZXIgZXhwb3J0cyB1c2UuXG5cdFx0XHRcdGlmIChjanNNb2R1bGUgJiYgY2pzTW9kdWxlLmV4cG9ydHMgIT09IHVuZGVmICYmXG5cdFx0XHRcdFx0XHRjanNNb2R1bGUuZXhwb3J0cyAhPT0gZGVmaW5lZFtuYW1lXSkge1xuXHRcdFx0XHRcdGRlZmluZWRbbmFtZV0gPSBjanNNb2R1bGUuZXhwb3J0cztcblx0XHRcdFx0fSBlbHNlIGlmIChyZXQgIT09IHVuZGVmIHx8ICF1c2luZ0V4cG9ydHMpIHtcblx0XHRcdFx0XHQvL1VzZSB0aGUgcmV0dXJuIHZhbHVlIGZyb20gdGhlIGZ1bmN0aW9uLlxuXHRcdFx0XHRcdGRlZmluZWRbbmFtZV0gPSByZXQ7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9IGVsc2UgaWYgKG5hbWUpIHtcblx0XHRcdC8vTWF5IGp1c3QgYmUgYW4gb2JqZWN0IGRlZmluaXRpb24gZm9yIHRoZSBtb2R1bGUuIE9ubHlcblx0XHRcdC8vd29ycnkgYWJvdXQgZGVmaW5pbmcgaWYgaGF2ZSBhIG1vZHVsZSBuYW1lLlxuXHRcdFx0ZGVmaW5lZFtuYW1lXSA9IGNhbGxiYWNrO1xuXHRcdH1cblx0fTtcblxuXHRyZXF1aXJlanMgPSByZXF1aXJlID0gcmVxID0gZnVuY3Rpb24gKGRlcHMsIGNhbGxiYWNrLCByZWxOYW1lLCBmb3JjZVN5bmMsIGFsdCkge1xuXHRcdGlmICh0eXBlb2YgZGVwcyA9PT0gXCJzdHJpbmdcIikge1xuXHRcdFx0aWYgKGhhbmRsZXJzW2RlcHNdKSB7XG5cdFx0XHRcdC8vY2FsbGJhY2sgaW4gdGhpcyBjYXNlIGlzIHJlYWxseSByZWxOYW1lXG5cdFx0XHRcdHJldHVybiBoYW5kbGVyc1tkZXBzXShjYWxsYmFjayk7XG5cdFx0XHR9XG5cdFx0XHQvL0p1c3QgcmV0dXJuIHRoZSBtb2R1bGUgd2FudGVkLiBJbiB0aGlzIHNjZW5hcmlvLCB0aGVcblx0XHRcdC8vZGVwcyBhcmcgaXMgdGhlIG1vZHVsZSBuYW1lLCBhbmQgc2Vjb25kIGFyZyAoaWYgcGFzc2VkKVxuXHRcdFx0Ly9pcyBqdXN0IHRoZSByZWxOYW1lLlxuXHRcdFx0Ly9Ob3JtYWxpemUgbW9kdWxlIG5hbWUsIGlmIGl0IGNvbnRhaW5zIC4gb3IgLi5cblx0XHRcdHJldHVybiBjYWxsRGVwKG1ha2VNYXAoZGVwcywgbWFrZVJlbFBhcnRzKGNhbGxiYWNrKSkuZik7XG5cdFx0fSBlbHNlIGlmICghZGVwcy5zcGxpY2UpIHtcblx0XHRcdC8vZGVwcyBpcyBhIGNvbmZpZyBvYmplY3QsIG5vdCBhbiBhcnJheS5cblx0XHRcdGNvbmZpZyA9IGRlcHM7XG5cdFx0XHRpZiAoY29uZmlnLmRlcHMpIHtcblx0XHRcdFx0cmVxKGNvbmZpZy5kZXBzLCBjb25maWcuY2FsbGJhY2spO1xuXHRcdFx0fVxuXHRcdFx0aWYgKCFjYWxsYmFjaykge1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cblx0XHRcdGlmIChjYWxsYmFjay5zcGxpY2UpIHtcblx0XHRcdFx0Ly9jYWxsYmFjayBpcyBhbiBhcnJheSwgd2hpY2ggbWVhbnMgaXQgaXMgYSBkZXBlbmRlbmN5IGxpc3QuXG5cdFx0XHRcdC8vQWRqdXN0IGFyZ3MgaWYgdGhlcmUgYXJlIGRlcGVuZGVuY2llc1xuXHRcdFx0XHRkZXBzID0gY2FsbGJhY2s7XG5cdFx0XHRcdGNhbGxiYWNrID0gcmVsTmFtZTtcblx0XHRcdFx0cmVsTmFtZSA9IG51bGw7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRkZXBzID0gdW5kZWY7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly9TdXBwb3J0IHJlcXVpcmUoWydhJ10pXG5cdFx0Y2FsbGJhY2sgPSBjYWxsYmFjayB8fCBmdW5jdGlvbiAoKSB7fTtcblxuXHRcdC8vSWYgcmVsTmFtZSBpcyBhIGZ1bmN0aW9uLCBpdCBpcyBhbiBlcnJiYWNrIGhhbmRsZXIsXG5cdFx0Ly9zbyByZW1vdmUgaXQuXG5cdFx0aWYgKHR5cGVvZiByZWxOYW1lID09PSAnZnVuY3Rpb24nKSB7XG5cdFx0XHRyZWxOYW1lID0gZm9yY2VTeW5jO1xuXHRcdFx0Zm9yY2VTeW5jID0gYWx0O1xuXHRcdH1cblxuXHRcdC8vU2ltdWxhdGUgYXN5bmMgY2FsbGJhY2s7XG5cdFx0aWYgKGZvcmNlU3luYykge1xuXHRcdFx0bWFpbih1bmRlZiwgZGVwcywgY2FsbGJhY2ssIHJlbE5hbWUpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQvL1VzaW5nIGEgbm9uLXplcm8gdmFsdWUgYmVjYXVzZSBvZiBjb25jZXJuIGZvciB3aGF0IG9sZCBicm93c2Vyc1xuXHRcdFx0Ly9kbywgYW5kIGxhdGVzdCBicm93c2VycyBcInVwZ3JhZGVcIiB0byA0IGlmIGxvd2VyIHZhbHVlIGlzIHVzZWQ6XG5cdFx0XHQvL2h0dHA6Ly93d3cud2hhdHdnLm9yZy9zcGVjcy93ZWItYXBwcy9jdXJyZW50LXdvcmsvbXVsdGlwYWdlL3RpbWVycy5odG1sI2RvbS13aW5kb3d0aW1lcnMtc2V0dGltZW91dDpcblx0XHRcdC8vSWYgd2FudCBhIHZhbHVlIGltbWVkaWF0ZWx5LCB1c2UgcmVxdWlyZSgnaWQnKSBpbnN0ZWFkIC0tIHNvbWV0aGluZ1xuXHRcdFx0Ly90aGF0IHdvcmtzIGluIGFsbW9uZCBvbiB0aGUgZ2xvYmFsIGxldmVsLCBidXQgbm90IGd1YXJhbnRlZWQgYW5kXG5cdFx0XHQvL3VubGlrZWx5IHRvIHdvcmsgaW4gb3RoZXIgQU1EIGltcGxlbWVudGF0aW9ucy5cblx0XHRcdHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRtYWluKHVuZGVmLCBkZXBzLCBjYWxsYmFjaywgcmVsTmFtZSk7XG5cdFx0XHR9LCA0KTtcblx0XHR9XG5cblx0XHRyZXR1cm4gcmVxO1xuXHR9O1xuXG5cdC8qKlxuXHQgKiBKdXN0IGRyb3BzIHRoZSBjb25maWcgb24gdGhlIGZsb29yLCBidXQgcmV0dXJucyByZXEgaW4gY2FzZVxuXHQgKiB0aGUgY29uZmlnIHJldHVybiB2YWx1ZSBpcyB1c2VkLlxuXHQgKi9cblx0cmVxLmNvbmZpZyA9IGZ1bmN0aW9uIChjZmcpIHtcblx0XHRyZXR1cm4gcmVxKGNmZyk7XG5cdH07XG5cblx0LyoqXG5cdCAqIEV4cG9zZSBtb2R1bGUgcmVnaXN0cnkgZm9yIGRlYnVnZ2luZyBhbmQgdG9vbGluZ1xuXHQgKi9cblx0cmVxdWlyZWpzLl9kZWZpbmVkID0gZGVmaW5lZDtcblxuXHRkZWZpbmUgPSBmdW5jdGlvbiAobmFtZSwgZGVwcywgY2FsbGJhY2spIHtcblx0XHRpZiAodHlwZW9mIG5hbWUgIT09ICdzdHJpbmcnKSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ1NlZSBhbG1vbmQgUkVBRE1FOiBpbmNvcnJlY3QgbW9kdWxlIGJ1aWxkLCBubyBtb2R1bGUgbmFtZScpO1xuXHRcdH1cblxuXHRcdC8vVGhpcyBtb2R1bGUgbWF5IG5vdCBoYXZlIGRlcGVuZGVuY2llc1xuXHRcdGlmICghZGVwcy5zcGxpY2UpIHtcblx0XHRcdC8vZGVwcyBpcyBub3QgYW4gYXJyYXksIHNvIHByb2JhYmx5IG1lYW5zXG5cdFx0XHQvL2FuIG9iamVjdCBsaXRlcmFsIG9yIGZhY3RvcnkgZnVuY3Rpb24gZm9yXG5cdFx0XHQvL3RoZSB2YWx1ZS4gQWRqdXN0IGFyZ3MuXG5cdFx0XHRjYWxsYmFjayA9IGRlcHM7XG5cdFx0XHRkZXBzID0gW107XG5cdFx0fVxuXG5cdFx0aWYgKCFoYXNQcm9wKGRlZmluZWQsIG5hbWUpICYmICFoYXNQcm9wKHdhaXRpbmcsIG5hbWUpKSB7XG5cdFx0XHR3YWl0aW5nW25hbWVdID0gW25hbWUsIGRlcHMsIGNhbGxiYWNrXTtcblx0XHR9XG5cdH07XG5cblx0ZGVmaW5lLmFtZCA9IHtcblx0XHRqUXVlcnk6IHRydWVcblx0fTtcbn0oKSk7XG5cbmRlZmluZShcInZlbmRvci9hbG1vbmRcIiwgZnVuY3Rpb24oKXt9KTtcblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBXb3JkUHJlc3MtbG9hZGVkIHZlcnNpb24gb2YgVW5kZXJzY29yZSBmb3IgdXNlIHdpdGggdGhpbmdzIHRoYXQgbmVlZCBpdCBhbmQgdXNlIFJlcXVpcmUuXG4gKiBAcmV0dXJuICAgb2JqXG4gKiBAc2luY2UgICAgMy4xNi4wXG4gKiBAdmVyc2lvbiAgMy4xNi4wXG4gKi9cbmRlZmluZSggJ3VuZGVyc2NvcmUnLFtdLGZ1bmN0aW9uKCkge1xuXHRyZXR1cm4gXztcbn0gKTtcblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBXb3JkUHJlc3MtbG9hZGVkIHZlcnNpb24gb2YgQmFja2JvbmUgZm9yIHVzZSB3aXRoIHRoaW5ncyB0aGF0IG5lZWQgaXQgYW5kIHVzZSBSZXF1aXJlLlxuICogQHJldHVybiAgIG9ialxuICogQHNpbmNlICAgIDMuMTYuMFxuICogQHZlcnNpb24gIDMuMTYuMFxuICovXG5kZWZpbmUoICdiYWNrYm9uZScsW10sZnVuY3Rpb24oKSB7XG5cdHJldHVybiBCYWNrYm9uZTtcbn0gKTtcblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBXb3JkUHJlc3MtbG9hZGVkIHZlcnNpb24gb2YgVW5kZXJzY29yZSBmb3IgdXNlIHdpdGggdGhpbmdzIHRoYXQgbmVlZCBpdCBhbmQgdXNlIFJlcXVpcmUuXG4gKiBAcmV0dXJuICAgb2JqXG4gKiBAc2luY2UgICAgMy4xNi4wXG4gKiBAdmVyc2lvbiAgMy4xNi4wXG4gKi9cbmRlZmluZSggJ2pxdWVyeScsW10sZnVuY3Rpb24oKSB7XG5cdHJldHVybiBqUXVlcnk7XG59ICk7XG5cbi8qIVxuKiBCYWNrYm9uZS5Db2xsZWN0aW9uVmlldywgdjEuMy40XG4qIENvcHlyaWdodCAoYykyMDEzIFJvdHVuZGEgU29mdHdhcmUsIExMQy5cbiogRGlzdHJpYnV0ZWQgdW5kZXIgTUlUIGxpY2Vuc2VcbiogaHR0cDovL2dpdGh1Yi5jb20vcm90dW5kYXNvZnR3YXJlL2JhY2tib25lLWNvbGxlY3Rpb24tdmlld1xuKi9cblxuKCBmdW5jdGlvbiggcm9vdCwgZmFjdG9yeSApIHtcblx0Ly8gVU1EIHdyYXBwZXJcblx0aWYgKCB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgKSB7XG5cdFx0Ly8gQU1EXG5cdFx0ZGVmaW5lKCAndmVuZG9yL2JhY2tib25lLmNvbGxlY3Rpb25WaWV3JyxbICd1bmRlcnNjb3JlJywgJ2JhY2tib25lJywgJ2pxdWVyeScgXSwgZmFjdG9yeSApO1xuXHR9IGVsc2UgaWYgKCB0eXBlb2YgZXhwb3J0cyAhPT0gJ3VuZGVmaW5lZCcgKSB7XG5cdFx0Ly8gTm9kZS9Db21tb25KU1xuXHRcdG1vZHVsZS5leHBvcnRzID0gZmFjdG9yeSggcmVxdWlyZSgndW5kZXJzY29yZScgKSwgcmVxdWlyZSggJ2JhY2tib25lJyApLCByZXF1aXJlKCAnYmFja2JvbmUnICkuJCApO1xuXHR9IGVsc2Uge1xuXHRcdC8vIEJyb3dzZXIgZ2xvYmFsc1xuXHRcdGZhY3RvcnkoIHJvb3QuXywgcm9vdC5CYWNrYm9uZSwgKCByb290LmpRdWVyeSB8fCByb290LlplcHRvIHx8IHJvb3QuJCApICk7XG5cdH1cbn0oIHRoaXMsIGZ1bmN0aW9uKCBfLCBCYWNrYm9uZSwgJCApIHtcblx0dmFyIG1EZWZhdWx0TW9kZWxWaWV3Q29uc3RydWN0b3IgPSBCYWNrYm9uZS5WaWV3O1xuXG5cdHZhciBrRGVmYXVsdFJlZmVyZW5jZUJ5ID0gXCJtb2RlbFwiO1xuXG5cdHZhciBrT3B0aW9uc1JlcXVpcmluZ1JlcmVuZGVyaW5nID0gWyBcImNvbGxlY3Rpb25cIiwgXCJtb2RlbFZpZXdcIiwgXCJtb2RlbFZpZXdPcHRpb25zXCIsIFwiaXRlbVRlbXBsYXRlXCIsIFwiaXRlbVRlbXBsYXRlRnVuY3Rpb25cIiwgXCJkZXRhY2hlZFJlbmRlcmluZ1wiIF07XG5cblx0dmFyIGtTdHlsZXNGb3JFbXB0eUxpc3RDYXB0aW9uID0ge1xuXHRcdFwiYmFja2dyb3VuZFwiIDogXCJ0cmFuc3BhcmVudFwiLFxuXHRcdFwiYm9yZGVyXCIgOiBcIm5vbmVcIixcblx0XHRcImJveC1zaGFkb3dcIiA6IFwibm9uZVwiXG5cdH07XG5cblx0QmFja2JvbmUuQ29sbGVjdGlvblZpZXcgPSBCYWNrYm9uZS5WaWV3LmV4dGVuZCgge1xuXG5cdFx0dGFnTmFtZSA6IFwidWxcIixcblxuXHRcdGV2ZW50cyA6IHtcblx0XHRcdFwibW91c2Vkb3duID4gbGksIHRib2R5ID4gdHIgPiB0ZFwiIDogXCJfbGlzdEl0ZW1fb25Nb3VzZWRvd25cIixcblx0XHRcdFwiZGJsY2xpY2sgPiBsaSwgdGJvZHkgPiB0ciA+IHRkXCIgOiBcIl9saXN0SXRlbV9vbkRvdWJsZUNsaWNrXCIsXG5cdFx0XHRcImNsaWNrXCIgOiBcIl9saXN0QmFja2dyb3VuZF9vbkNsaWNrXCIsXG5cdFx0XHRcImNsaWNrIHVsLmNvbGxlY3Rpb24tdmlldywgdGFibGUuY29sbGVjdGlvbi12aWV3XCIgOiBcIl9saXN0QmFja2dyb3VuZF9vbkNsaWNrXCIsXG5cdFx0XHRcImtleWRvd25cIiA6IFwiX29uS2V5ZG93blwiXG5cdFx0fSxcblxuXHRcdC8vIG9ubHkgdXNlZCBpZiBCYWNrYm9uZS5Db3VyaWVyIGlzIGF2YWlsYWJsZVxuXHRcdHNwYXduTWVzc2FnZXMgOiB7XG5cdFx0XHRcImZvY3VzXCIgOiBcImZvY3VzXCJcblx0XHR9LFxuXG5cdFx0Ly9vbmx5IHVzZWQgaWYgQmFja2JvbmUuQ291cmllciBpcyBhdmFpbGFibGVcblx0XHRwYXNzTWVzc2FnZXMgOiB7IFwiKlwiIDogXCIuXCIgfSxcblxuXHRcdC8vIHZpZXdPcHRpb24gZGVmaW5pdGlvbnMgd2l0aCBkZWZhdWx0IHZhbHVlcy5cblx0XHRpbml0aWFsaXphdGlvbk9wdGlvbnMgOiBbXG5cdFx0XHR7IFwiY29sbGVjdGlvblwiIDogbnVsbCB9LFxuXHRcdFx0eyBcIm1vZGVsVmlld1wiIDogbnVsbCB9LFxuXHRcdFx0eyBcIm1vZGVsVmlld09wdGlvbnNcIiA6IHt9IH0sXG5cdFx0XHR7IFwiaXRlbVRlbXBsYXRlXCIgOiBudWxsIH0sXG5cdFx0XHR7IFwiaXRlbVRlbXBsYXRlRnVuY3Rpb25cIiA6IG51bGwgfSxcblx0XHRcdHsgXCJzZWxlY3RhYmxlXCIgOiB0cnVlIH0sXG5cdFx0XHR7IFwiY2xpY2tUb1NlbGVjdFwiIDogdHJ1ZSB9LFxuXHRcdFx0eyBcInNlbGVjdGFibGVNb2RlbHNGaWx0ZXJcIiA6IG51bGwgfSxcblx0XHRcdHsgXCJ2aXNpYmxlTW9kZWxzRmlsdGVyXCIgOiBudWxsIH0sXG5cdFx0XHR7IFwic29ydGFibGVNb2RlbHNGaWx0ZXJcIiA6IG51bGwgfSxcblx0XHRcdHsgXCJzZWxlY3RNdWx0aXBsZVwiIDogZmFsc2UgfSxcblx0XHRcdHsgXCJjbGlja1RvVG9nZ2xlXCIgOiBmYWxzZSB9LFxuXHRcdFx0eyBcInByb2Nlc3NLZXlFdmVudHNcIiA6IHRydWUgfSxcblx0XHRcdHsgXCJzb3J0YWJsZVwiIDogZmFsc2UgfSxcblx0XHRcdHsgXCJzb3J0YWJsZU9wdGlvbnNcIiA6IG51bGwgfSxcblx0XHRcdHsgXCJyZXVzZU1vZGVsVmlld3NcIiA6IHRydWUgfSxcblx0XHRcdHsgXCJkZXRhY2hlZFJlbmRlcmluZ1wiIDogZmFsc2UgfSxcblx0XHRcdHsgXCJlbXB0eUxpc3RDYXB0aW9uXCIgOiBudWxsIH1cblx0XHRdLFxuXG5cdFx0aW5pdGlhbGl6ZSA6IGZ1bmN0aW9uKCBvcHRpb25zICkge1xuXHRcdFx0QmFja2JvbmUuVmlld09wdGlvbnMuYWRkKCB0aGlzLCBcImluaXRpYWxpemF0aW9uT3B0aW9uc1wiICk7IC8vIHNldHVwIHRoZSBWaWV3T3B0aW9ucyBmdW5jdGlvbmFsaXR5LlxuXHRcdFx0dGhpcy5zZXRPcHRpb25zKCBvcHRpb25zICk7IC8vIGFuZCBtYWtlIHVzZSBvZiBhbnkgcHJvdmlkZWQgb3B0aW9uc1xuXG5cdFx0XHRpZiggISB0aGlzLmNvbGxlY3Rpb24gKSB0aGlzLmNvbGxlY3Rpb24gPSBuZXcgQmFja2JvbmUuQ29sbGVjdGlvbigpO1xuXG5cdFx0XHR0aGlzLl9oYXNCZWVuUmVuZGVyZWQgPSBmYWxzZTtcblxuXHRcdFx0aWYoIHRoaXMuX2lzQmFja2JvbmVDb3VyaWVyQXZhaWxhYmxlKCkgKSB7XG5cdFx0XHRcdEJhY2tib25lLkNvdXJpZXIuYWRkKCB0aGlzICk7XG5cdFx0XHR9XG5cblx0XHRcdHRoaXMuJGVsLmRhdGEoIFwidmlld1wiLCB0aGlzICk7IC8vIG5lZWRlZCBmb3IgY29ubmVjdGVkIHNvcnRhYmxlIGxpc3RzXG5cdFx0XHR0aGlzLiRlbC5hZGRDbGFzcyggXCJjb2xsZWN0aW9uLXZpZXcgY29sbGVjdGlvbi1saXN0XCIgKTsgLy8gY29sbGVjdGlvbi1saXN0IGlzIGluIHRoZXJlIGZvciBsZWdhY3kgcHVycG9zZXNcblx0XHRcdGlmKCB0aGlzLnNlbGVjdGFibGUgKSB0aGlzLiRlbC5hZGRDbGFzcyggXCJzZWxlY3RhYmxlXCIgKTtcblxuXHRcdFx0aWYoIHRoaXMuc2VsZWN0YWJsZSAmJiB0aGlzLnByb2Nlc3NLZXlFdmVudHMgKVxuXHRcdFx0XHR0aGlzLiRlbC5hdHRyKCBcInRhYmluZGV4XCIsIDAgKTsgLy8gc28gd2UgZ2V0IGtleWJvYXJkIGV2ZW50c1xuXG5cdFx0XHR0aGlzLnNlbGVjdGVkSXRlbXMgPSBbXTtcblxuXHRcdFx0dGhpcy5fdXBkYXRlSXRlbVRlbXBsYXRlKCk7XG5cblx0XHRcdGlmKCB0aGlzLmNvbGxlY3Rpb24gKVxuXHRcdFx0XHR0aGlzLl9yZWdpc3RlckNvbGxlY3Rpb25FdmVudHMoKTtcblxuXHRcdFx0dGhpcy52aWV3TWFuYWdlciA9IG5ldyBDaGlsZFZpZXdDb250YWluZXIoKTtcblx0XHR9LFxuXG5cdFx0X29uT3B0aW9uc0NoYW5nZWQgOiBmdW5jdGlvbiggY2hhbmdlZE9wdGlvbnMsIG9yaWdpbmFsT3B0aW9ucyApIHtcblx0XHRcdHZhciBfdGhpcyA9IHRoaXM7XG5cdFx0XHR2YXIgcmVyZW5kZXIgPSBmYWxzZTtcblxuXHRcdFx0Xy5lYWNoKCBfLmtleXMoIGNoYW5nZWRPcHRpb25zICksIGZ1bmN0aW9uKCBjaGFuZ2VkT3B0aW9uS2V5ICkge1xuXHRcdFx0XHR2YXIgbmV3VmFsID0gY2hhbmdlZE9wdGlvbnNbIGNoYW5nZWRPcHRpb25LZXkgXTtcblx0XHRcdFx0dmFyIG9sZFZhbCA9IG9yaWdpbmFsT3B0aW9uc1sgY2hhbmdlZE9wdGlvbktleSBdO1xuXHRcdFx0XHRzd2l0Y2goIGNoYW5nZWRPcHRpb25LZXkgKSB7XG5cdFx0XHRcdFx0Y2FzZSBcImNvbGxlY3Rpb25cIiA6XG5cdFx0XHRcdFx0XHRpZiAoIG5ld1ZhbCAhPT0gb2xkVmFsICkge1xuXHRcdFx0XHRcdFx0XHRfdGhpcy5zdG9wTGlzdGVuaW5nKCBvbGRWYWwgKTtcblx0XHRcdFx0XHRcdFx0X3RoaXMuX3JlZ2lzdGVyQ29sbGVjdGlvbkV2ZW50cygpO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0Y2FzZSBcInNlbGVjdE11bHRpcGxlXCIgOlxuXHRcdFx0XHRcdFx0aWYoICEgbmV3VmFsICYmIF90aGlzLnNlbGVjdGVkSXRlbXMubGVuZ3RoID4gMSApXG5cdFx0XHRcdFx0XHRcdF90aGlzLnNldFNlbGVjdGVkTW9kZWwoIF8uZmlyc3QoIF90aGlzLnNlbGVjdGVkSXRlbXMgKSwgeyBieSA6IFwiY2lkXCIgfSApO1xuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0Y2FzZSBcInNlbGVjdGFibGVcIiA6XG5cdFx0XHRcdFx0XHRpZiggISBuZXdWYWwgJiYgX3RoaXMuc2VsZWN0ZWRJdGVtcy5sZW5ndGggPiAwIClcblx0XHRcdFx0XHRcdFx0X3RoaXMuc2V0U2VsZWN0ZWRNb2RlbHMoIFtdICk7XG5cblx0XHRcdFx0XHRcdGlmKCBuZXdWYWwgJiYgdGhpcy5wcm9jZXNzS2V5RXZlbnRzICkgX3RoaXMuJGVsLmF0dHIoIFwidGFiaW5kZXhcIiwgMCApOyAvLyBzbyB3ZSBnZXQga2V5Ym9hcmQgZXZlbnRzXG5cdFx0XHRcdFx0XHRlbHNlIF90aGlzLiRlbC5yZW1vdmVBdHRyKCBcInRhYmluZGV4XCIsIDAgKTtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgXCJzb3J0YWJsZVwiIDpcblx0XHRcdFx0XHRcdGNoYW5nZWRPcHRpb25zLnNvcnRhYmxlID8gX3RoaXMuX3NldHVwU29ydGFibGUoKSA6IF90aGlzLiRlbC5zb3J0YWJsZSggXCJkZXN0cm95XCIgKTtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgXCJzZWxlY3RhYmxlTW9kZWxzRmlsdGVyXCIgOlxuXHRcdFx0XHRcdFx0X3RoaXMucmVhcHBseUZpbHRlciggJ3NlbGVjdGFibGVNb2RlbHMnICk7XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRjYXNlIFwic29ydGFibGVPcHRpb25zXCIgOlxuXHRcdFx0XHRcdFx0X3RoaXMuJGVsLnNvcnRhYmxlKCBcImRlc3Ryb3lcIiApO1xuXHRcdFx0XHRcdFx0X3RoaXMuX3NldHVwU29ydGFibGUoKTtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgXCJzb3J0YWJsZU1vZGVsc0ZpbHRlclwiIDpcblx0XHRcdFx0XHRcdF90aGlzLnJlYXBwbHlGaWx0ZXIoICdzb3J0YWJsZU1vZGVscycgKTtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgXCJ2aXNpYmxlTW9kZWxzRmlsdGVyXCIgOlxuXHRcdFx0XHRcdFx0X3RoaXMucmVhcHBseUZpbHRlciggJ3Zpc2libGVNb2RlbHMnICk7XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRjYXNlIFwiaXRlbVRlbXBsYXRlXCIgOlxuXHRcdFx0XHRcdFx0X3RoaXMuX3VwZGF0ZUl0ZW1UZW1wbGF0ZSgpO1xuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0Y2FzZSBcInByb2Nlc3NLZXlFdmVudHNcIiA6XG5cdFx0XHRcdFx0XHRpZiggbmV3VmFsICYmIHRoaXMuc2VsZWN0YWJsZSApIF90aGlzLiRlbC5hdHRyKCBcInRhYmluZGV4XCIsIDAgKTsgLy8gc28gd2UgZ2V0IGtleWJvYXJkIGV2ZW50c1xuXHRcdFx0XHRcdFx0ZWxzZSBfdGhpcy4kZWwucmVtb3ZlQXR0ciggXCJ0YWJpbmRleFwiLCAwICk7XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRjYXNlIFwibW9kZWxWaWV3XCIgOlxuXHRcdFx0XHRcdFx0Ly9uZWVkIHRvIHJlbW92ZSBhbGwgb2xkIHZpZXcgaW5zdGFuY2VzXG5cdFx0XHRcdFx0XHRfdGhpcy52aWV3TWFuYWdlci5lYWNoKCBmdW5jdGlvbiggdmlldyApIHtcblx0XHRcdFx0XHRcdFx0X3RoaXMudmlld01hbmFnZXIucmVtb3ZlKCB2aWV3ICk7XG5cdFx0XHRcdFx0XHRcdC8vIGRlc3Ryb3kgdGhlIFZpZXcgaXRzZWxmXG5cdFx0XHRcdFx0XHRcdHZpZXcucmVtb3ZlKCk7XG5cdFx0XHRcdFx0XHR9ICk7XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0fVxuXHRcdFx0XHRpZiggXy5jb250YWlucygga09wdGlvbnNSZXF1aXJpbmdSZXJlbmRlcmluZywgY2hhbmdlZE9wdGlvbktleSApICkgcmVyZW5kZXIgPSB0cnVlO1xuXHRcdFx0fSApO1xuXG5cdFx0XHRpZiggdGhpcy5faGFzQmVlblJlbmRlcmVkICYmIHJlcmVuZGVyICkge1xuXHRcdFx0XHR0aGlzLnJlbmRlcigpO1xuXHRcdFx0fVxuXHRcdH0sXG5cblx0XHRzZXRPcHRpb24gOiBmdW5jdGlvbiggb3B0aW9uTmFtZSwgb3B0aW9uVmFsdWUgKSB7IC8vIG5vdyBpcyBtZWFybHkgYSB3cmFwcGVyIGFyb3VuZCBiYWNrYm9uZS52aWV3T3B0aW9ucycgc2V0T3B0aW9ucygpXG5cdFx0XHR2YXIgb3B0aW9uSGFzaCA9IHt9O1xuXHRcdFx0b3B0aW9uSGFzaFsgb3B0aW9uTmFtZSBdID0gb3B0aW9uVmFsdWU7XG5cdFx0XHR0aGlzLnNldE9wdGlvbnMoIG9wdGlvbkhhc2ggKTtcblx0XHR9LFxuXG5cdFx0Z2V0U2VsZWN0ZWRNb2RlbCA6IGZ1bmN0aW9uKCBvcHRpb25zICkge1xuXHRcdFx0cmV0dXJuIHRoaXMuc2VsZWN0ZWRJdGVtcy5sZW5ndGggPyBfLmZpcnN0KCB0aGlzLmdldFNlbGVjdGVkTW9kZWxzKCBvcHRpb25zICkgKSA6IG51bGw7XG5cdFx0fSxcblxuXHRcdGdldFNlbGVjdGVkTW9kZWxzIDogZnVuY3Rpb24gKCBvcHRpb25zICkge1xuXHRcdFx0dmFyIF90aGlzID0gdGhpcztcblxuXHRcdFx0b3B0aW9ucyA9IF8uZXh0ZW5kKCB7fSwge1xuXHRcdFx0XHRieSA6IGtEZWZhdWx0UmVmZXJlbmNlQnlcblx0XHRcdH0sIG9wdGlvbnMgKTtcblxuXHRcdFx0dmFyIHJlZmVyZW5jZUJ5ID0gb3B0aW9ucy5ieTtcblx0XHRcdHZhciBpdGVtcyA9IFtdO1xuXG5cdFx0XHRzd2l0Y2goIHJlZmVyZW5jZUJ5ICkge1xuXHRcdFx0XHRjYXNlIFwiaWRcIiA6XG5cdFx0XHRcdFx0Xy5lYWNoKCB0aGlzLnNlbGVjdGVkSXRlbXMsIGZ1bmN0aW9uICggaXRlbSApIHtcblx0XHRcdFx0XHRcdGl0ZW1zLnB1c2goIF90aGlzLmNvbGxlY3Rpb24uZ2V0KCBpdGVtICkuaWQgKTtcblx0XHRcdFx0XHR9ICk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgXCJjaWRcIiA6XG5cdFx0XHRcdFx0aXRlbXMgPSBpdGVtcy5jb25jYXQoIHRoaXMuc2VsZWN0ZWRJdGVtcyApO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlIFwib2Zmc2V0XCIgOlxuXHRcdFx0XHRcdHZhciBjdXJMaW5lTnVtYmVyID0gMDtcblxuXHRcdFx0XHRcdHZhciBpdGVtRWxlbWVudHMgPSB0aGlzLl9nZXRWaXNpYmxlSXRlbUVscygpO1xuXG5cdFx0XHRcdFx0aXRlbUVsZW1lbnRzLmVhY2goIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdFx0dmFyIHRoaXNJdGVtRWwgPSAkKCB0aGlzICk7XG5cdFx0XHRcdFx0XHRpZiggdGhpc0l0ZW1FbC5pcyggXCIuc2VsZWN0ZWRcIiApIClcblx0XHRcdFx0XHRcdFx0aXRlbXMucHVzaCggY3VyTGluZU51bWJlciApO1xuXHRcdFx0XHRcdFx0Y3VyTGluZU51bWJlcisrO1xuXHRcdFx0XHRcdH0gKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSBcIm1vZGVsXCIgOlxuXHRcdFx0XHRcdF8uZWFjaCggdGhpcy5zZWxlY3RlZEl0ZW1zLCBmdW5jdGlvbiAoIGl0ZW0gKSB7XG5cdFx0XHRcdFx0XHRpdGVtcy5wdXNoKCBfdGhpcy5jb2xsZWN0aW9uLmdldCggaXRlbSApICk7XG5cdFx0XHRcdFx0fSApO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlIFwidmlld1wiIDpcblx0XHRcdFx0XHRfLmVhY2goIHRoaXMuc2VsZWN0ZWRJdGVtcywgZnVuY3Rpb24gKCBpdGVtICkge1xuXHRcdFx0XHRcdFx0aXRlbXMucHVzaCggX3RoaXMudmlld01hbmFnZXIuZmluZEJ5TW9kZWwoIF90aGlzLmNvbGxlY3Rpb24uZ2V0KCBpdGVtICkgKSApO1xuXHRcdFx0XHRcdH0gKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0ZGVmYXVsdCA6XG5cdFx0XHRcdFx0dGhyb3cgbmV3IEVycm9yKCBcIkludmFsaWQgcmVmZXJlbmNlQnkgb3B0aW9uOiBcIiArIHJlZmVyZW5jZUJ5ICk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBpdGVtcztcblxuXHRcdH0sXG5cblx0XHRzZXRTZWxlY3RlZE1vZGVscyA6IGZ1bmN0aW9uKCBuZXdTZWxlY3RlZEl0ZW1zLCBvcHRpb25zICkge1xuXHRcdFx0aWYoICEgXy5pc0FycmF5KCBuZXdTZWxlY3RlZEl0ZW1zICkgKSB0aHJvdyBcIkludmFsaWQgcGFyYW1ldGVyIHZhbHVlXCI7XG5cdFx0XHRpZiggISB0aGlzLnNlbGVjdGFibGUgJiYgbmV3U2VsZWN0ZWRJdGVtcy5sZW5ndGggPiAwICkgcmV0dXJuOyAvLyB1c2VkIHRvIHRocm93IGVycm9yLCBidXQgdGhlcmUgYXJlIHNvbWUgY2lyY3Vtc3RhbmNlcyBpbiB3aGljaCBhIGxpc3QgY2FuIGJlIHNlbGVjdGFibGUgYXQgdGltZXMgYW5kIG5vdCBhdCBvdGhlcnMsIGRvbid0IHdhbnQgdG8gaGF2ZSB0byB3b3JyeSBhYm91dCBjYXRjaGluZyBlcnJvcnNcblxuXHRcdFx0b3B0aW9ucyA9IF8uZXh0ZW5kKCB7fSwge1xuXHRcdFx0XHRzaWxlbnQgOiBmYWxzZSxcblx0XHRcdFx0YnkgOiBrRGVmYXVsdFJlZmVyZW5jZUJ5XG5cdFx0XHR9LCBvcHRpb25zICk7XG5cblx0XHRcdHZhciByZWZlcmVuY2VCeSA9IG9wdGlvbnMuYnk7XG5cdFx0XHR2YXIgbmV3U2VsZWN0ZWRDaWRzID0gW107XG5cblx0XHRcdHN3aXRjaCggcmVmZXJlbmNlQnkgKSB7XG5cdFx0XHRcdGNhc2UgXCJjaWRcIiA6XG5cdFx0XHRcdFx0bmV3U2VsZWN0ZWRDaWRzID0gbmV3U2VsZWN0ZWRJdGVtcztcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSBcImlkXCIgOlxuXHRcdFx0XHRcdHRoaXMuY29sbGVjdGlvbi5lYWNoKCBmdW5jdGlvbiggdGhpc01vZGVsICkge1xuXHRcdFx0XHRcdFx0aWYoIF8uY29udGFpbnMoIG5ld1NlbGVjdGVkSXRlbXMsIHRoaXNNb2RlbC5pZCApICkgbmV3U2VsZWN0ZWRDaWRzLnB1c2goIHRoaXNNb2RlbC5jaWQgKTtcblx0XHRcdFx0XHR9ICk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgXCJtb2RlbFwiIDpcblx0XHRcdFx0XHRuZXdTZWxlY3RlZENpZHMgPSBfLnBsdWNrKCBuZXdTZWxlY3RlZEl0ZW1zLCBcImNpZFwiICk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgXCJ2aWV3XCIgOlxuXHRcdFx0XHRcdF8uZWFjaCggbmV3U2VsZWN0ZWRJdGVtcywgZnVuY3Rpb24oIGl0ZW0gKSB7XG5cdFx0XHRcdFx0XHRuZXdTZWxlY3RlZENpZHMucHVzaCggaXRlbS5tb2RlbC5jaWQgKTtcblx0XHRcdFx0XHR9ICk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgXCJvZmZzZXRcIiA6XG5cdFx0XHRcdFx0dmFyIGN1ckxpbmVOdW1iZXIgPSAwO1xuXHRcdFx0XHRcdHZhciBzZWxlY3RlZEl0ZW1zID0gW107XG5cblx0XHRcdFx0XHR2YXIgaXRlbUVsZW1lbnRzID0gdGhpcy5fZ2V0VmlzaWJsZUl0ZW1FbHMoKTtcblx0XHRcdFx0XHRpdGVtRWxlbWVudHMuZWFjaCggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHR2YXIgdGhpc0l0ZW1FbCA9ICQoIHRoaXMgKTtcblx0XHRcdFx0XHRcdGlmKCBfLmNvbnRhaW5zKCBuZXdTZWxlY3RlZEl0ZW1zLCBjdXJMaW5lTnVtYmVyICkgKVxuXHRcdFx0XHRcdFx0XHRuZXdTZWxlY3RlZENpZHMucHVzaCggdGhpc0l0ZW1FbC5hdHRyKCBcImRhdGEtbW9kZWwtY2lkXCIgKSApO1xuXHRcdFx0XHRcdFx0Y3VyTGluZU51bWJlcisrO1xuXHRcdFx0XHRcdH0gKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0ZGVmYXVsdCA6XG5cdFx0XHRcdFx0dGhyb3cgbmV3IEVycm9yKCBcIkludmFsaWQgcmVmZXJlbmNlQnkgb3B0aW9uOiBcIiArIHJlZmVyZW5jZUJ5ICk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHR9XG5cblx0XHRcdHZhciBvbGRTZWxlY3RlZE1vZGVscyA9IHRoaXMuZ2V0U2VsZWN0ZWRNb2RlbHMoKTtcblx0XHRcdHZhciBvbGRTZWxlY3RlZENpZHMgPSBfLmNsb25lKCB0aGlzLnNlbGVjdGVkSXRlbXMgKTtcblxuXHRcdFx0dGhpcy5zZWxlY3RlZEl0ZW1zID0gdGhpcy5fY29udmVydFN0cmluZ3NUb0ludHMoIG5ld1NlbGVjdGVkQ2lkcyApO1xuXHRcdFx0dGhpcy5fdmFsaWRhdGVTZWxlY3Rpb24oKTtcblxuXHRcdFx0dmFyIG5ld1NlbGVjdGVkTW9kZWxzID0gdGhpcy5nZXRTZWxlY3RlZE1vZGVscygpO1xuXG5cdFx0XHRpZiggISB0aGlzLl9jb250YWluU2FtZUVsZW1lbnRzKCBvbGRTZWxlY3RlZENpZHMsIHRoaXMuc2VsZWN0ZWRJdGVtcyApIClcblx0XHRcdHtcblx0XHRcdFx0dGhpcy5fYWRkU2VsZWN0ZWRDbGFzc1RvU2VsZWN0ZWRJdGVtcyggb2xkU2VsZWN0ZWRDaWRzICk7XG5cblx0XHRcdFx0aWYoICEgb3B0aW9ucy5zaWxlbnQgKVxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0aWYoIHRoaXMuX2lzQmFja2JvbmVDb3VyaWVyQXZhaWxhYmxlKCkgKSB7XG5cdFx0XHRcdFx0XHR0aGlzLnNwYXduKCBcInNlbGVjdGlvbkNoYW5nZWRcIiwge1xuXHRcdFx0XHRcdFx0XHRzZWxlY3RlZE1vZGVscyA6IG5ld1NlbGVjdGVkTW9kZWxzLFxuXHRcdFx0XHRcdFx0XHRvbGRTZWxlY3RlZE1vZGVscyA6IG9sZFNlbGVjdGVkTW9kZWxzXG5cdFx0XHRcdFx0XHR9ICk7XG5cdFx0XHRcdFx0fSBlbHNlIHRoaXMudHJpZ2dlciggXCJzZWxlY3Rpb25DaGFuZ2VkXCIsIG5ld1NlbGVjdGVkTW9kZWxzLCBvbGRTZWxlY3RlZE1vZGVscyApO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0dGhpcy51cGRhdGVEZXBlbmRlbnRDb250cm9scygpO1xuXHRcdFx0fVxuXHRcdH0sXG5cblx0XHRzZXRTZWxlY3RlZE1vZGVsIDogZnVuY3Rpb24oIG5ld1NlbGVjdGVkSXRlbSwgb3B0aW9ucyApIHtcblx0XHRcdGlmKCAhIG5ld1NlbGVjdGVkSXRlbSAmJiBuZXdTZWxlY3RlZEl0ZW0gIT09IDAgKVxuXHRcdFx0XHR0aGlzLnNldFNlbGVjdGVkTW9kZWxzKCBbXSwgb3B0aW9ucyApO1xuXHRcdFx0ZWxzZVxuXHRcdFx0XHR0aGlzLnNldFNlbGVjdGVkTW9kZWxzKCBbIG5ld1NlbGVjdGVkSXRlbSBdLCBvcHRpb25zICk7XG5cdFx0fSxcblxuXHRcdGdldFZpZXcgOiBmdW5jdGlvbiggcmVmZXJlbmNlLCBvcHRpb25zICkge1xuXHRcdFx0b3B0aW9ucyA9IF8uZXh0ZW5kKCB7fSwge1xuXHRcdFx0XHRieSA6IGtEZWZhdWx0UmVmZXJlbmNlQnlcblx0XHRcdH0sIG9wdGlvbnMgKTtcblxuXHRcdFx0c3dpdGNoKCBvcHRpb25zLmJ5ICkge1xuXHRcdFx0XHRjYXNlIFwiaWRcIiA6XG5cdFx0XHRcdGNhc2UgXCJjaWRcIiA6XG5cdFx0XHRcdFx0dmFyIG1vZGVsID0gdGhpcy5jb2xsZWN0aW9uLmdldCggcmVmZXJlbmNlICkgfHwgbnVsbDtcblx0XHRcdFx0XHRyZXR1cm4gbW9kZWwgJiYgdGhpcy52aWV3TWFuYWdlci5maW5kQnlNb2RlbCggbW9kZWwgKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSBcIm9mZnNldFwiIDpcblx0XHRcdFx0XHR2YXIgaXRlbUVsZW1lbnRzID0gdGhpcy5fZ2V0VmlzaWJsZUl0ZW1FbHMoKTtcblx0XHRcdFx0XHRyZXR1cm4gJCggaXRlbUVsZW1lbnRzLmdldCggcmVmZXJlbmNlICkgKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSBcIm1vZGVsXCIgOlxuXHRcdFx0XHRcdHJldHVybiB0aGlzLnZpZXdNYW5hZ2VyLmZpbmRCeU1vZGVsKCByZWZlcmVuY2UgKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0ZGVmYXVsdCA6XG5cdFx0XHRcdFx0dGhyb3cgbmV3IEVycm9yKCBcIkludmFsaWQgcmVmZXJlbmNlQnkgb3B0aW9uOiBcIiArIHJlZmVyZW5jZUJ5ICk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHR9XG5cdFx0fSxcblxuXHRcdHJlbmRlciA6IGZ1bmN0aW9uKCkge1xuXHRcdFx0dmFyIF90aGlzID0gdGhpcztcblxuXHRcdFx0dGhpcy5faGFzQmVlblJlbmRlcmVkID0gdHJ1ZTtcblxuXHRcdFx0aWYoIHRoaXMuc2VsZWN0YWJsZSApIHRoaXMuX3NhdmVTZWxlY3Rpb24oKTtcblxuXHRcdFx0dmFyIG1vZGVsVmlld0NvbnRhaW5lckVsO1xuXG5cdFx0XHQvLyBJZiBjb2xsZWN0aW9uIHZpZXcgZWxlbWVudCBpcyBhIHRhYmxlIGFuZCBpdCBoYXMgYSB0Ym9keVxuXHRcdFx0Ly8gd2l0aGluIGl0LCByZW5kZXIgdGhlIG1vZGVsIHZpZXdzIGluc2lkZSBvZiB0aGUgdGJvZHlcblx0XHRcdG1vZGVsVmlld0NvbnRhaW5lckVsID0gdGhpcy5fZ2V0Q29udGFpbmVyRWwoKTtcblxuXHRcdFx0dmFyIG9sZFZpZXdNYW5hZ2VyID0gdGhpcy52aWV3TWFuYWdlcjtcblx0XHRcdHRoaXMudmlld01hbmFnZXIgPSBuZXcgQ2hpbGRWaWV3Q29udGFpbmVyKCk7XG5cblx0XHRcdC8vIGRldGFjaCBlYWNoIG9mIG91ciBzdWJ2aWV3cyB0aGF0IHdlIGhhdmUgYWxyZWFkeSBjcmVhdGVkIHRvIHJlcHJlc2VudCBtb2RlbHNcblx0XHRcdC8vIGluIHRoZSBjb2xsZWN0aW9uLiBXZSBhcmUgZ29pbmcgdG8gcmUtdXNlIHRoZSBvbmVzIHRoYXQgcmVwcmVzZW50IG1vZGVscyB0aGF0XG5cdFx0XHQvLyBhcmUgc3RpbGwgaGVyZSwgaW5zdGVhZCBvZiBjcmVhdGluZyBuZXcgb25lcywgc28gdGhhdCB3ZSBkb24ndCBsb29zZSBzdGF0ZVxuXHRcdFx0Ly8gaW5mb3JtYXRpb24gaW4gdGhlIHZpZXdzLlxuXHRcdFx0b2xkVmlld01hbmFnZXIuZWFjaCggZnVuY3Rpb24oIHRoaXNNb2RlbFZpZXcgKSB7XG5cdFx0XHRcdC8vIHRvIGJvb3N0IHBlcmZvcm1hbmNlLCBvbmx5IGRldGFjaCB0aG9zZSB2aWV3cyB0aGF0IHdpbGwgYmUgc3RpY2tpbmcgYXJvdW5kLlxuXHRcdFx0XHQvLyB3ZSB3b24ndCBuZWVkIHRoZSBvdGhlciBvbmVzIGxhdGVyLCBzbyBubyBuZWVkIHRvIGRldGFjaCB0aGVtIGluZGl2aWR1YWxseS5cblx0XHRcdFx0aWYoIHRoaXMucmV1c2VNb2RlbFZpZXdzICYmIHRoaXMuY29sbGVjdGlvbi5nZXQoIHRoaXNNb2RlbFZpZXcubW9kZWwuY2lkICkgKSB7XG5cdFx0XHRcdFx0dGhpc01vZGVsVmlldy4kZWwuZGV0YWNoKCk7XG5cdFx0XHRcdH0gZWxzZSB0aGlzTW9kZWxWaWV3LnJlbW92ZSgpO1xuXHRcdFx0fSwgdGhpcyApO1xuXG5cdFx0XHRtb2RlbFZpZXdDb250YWluZXJFbC5lbXB0eSgpO1xuXHRcdFx0dmFyIGZyYWdtZW50Q29udGFpbmVyO1xuXG5cdFx0XHRpZiggdGhpcy5kZXRhY2hlZFJlbmRlcmluZyApXG5cdFx0XHRcdGZyYWdtZW50Q29udGFpbmVyID0gZG9jdW1lbnQuY3JlYXRlRG9jdW1lbnRGcmFnbWVudCgpO1xuXG5cdFx0XHR0aGlzLmNvbGxlY3Rpb24uZWFjaCggZnVuY3Rpb24oIHRoaXNNb2RlbCApIHtcblx0XHRcdFx0dmFyIHRoaXNNb2RlbFZpZXcgPSBvbGRWaWV3TWFuYWdlci5maW5kQnlNb2RlbENpZCggdGhpc01vZGVsLmNpZCApO1xuXHRcdFx0XHRpZiggISB0aGlzLnJldXNlTW9kZWxWaWV3cyB8fCBfLmlzVW5kZWZpbmVkKCB0aGlzTW9kZWxWaWV3ICkgKSB7XG5cdFx0XHRcdFx0Ly8gaWYgdGhlIG1vZGVsIHZpZXcgaGFzIG5vdCBhbHJlYWR5IGJlZW4gY3JlYXRlZCBvbiBhXG5cdFx0XHRcdFx0Ly8gcHJldmlvdXMgcmVuZGVyIHRoZW4gY3JlYXRlIGFuZCBpbml0aWFsaXplIGl0IG5vdy5cblx0XHRcdFx0XHR0aGlzTW9kZWxWaWV3ID0gdGhpcy5fY3JlYXRlTmV3TW9kZWxWaWV3KCB0aGlzTW9kZWwsIHRoaXMuX2dldE1vZGVsVmlld09wdGlvbnMoIHRoaXNNb2RlbCApICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHR0aGlzLl9pbnNlcnRBbmRSZW5kZXJNb2RlbFZpZXcoIHRoaXNNb2RlbFZpZXcsIGZyYWdtZW50Q29udGFpbmVyIHx8IG1vZGVsVmlld0NvbnRhaW5lckVsICk7XG5cdFx0XHR9LCB0aGlzICk7XG5cblx0XHRcdGlmKCB0aGlzLmRldGFjaGVkUmVuZGVyaW5nIClcblx0XHRcdFx0bW9kZWxWaWV3Q29udGFpbmVyRWwuYXBwZW5kKCBmcmFnbWVudENvbnRhaW5lciApO1xuXG5cdFx0XHRpZiggdGhpcy5zb3J0YWJsZSApIHRoaXMuX3NldHVwU29ydGFibGUoKTtcblxuXHRcdFx0dGhpcy5fc2hvd0VtcHR5TGlzdENhcHRpb25JZkFwcHJvcHJpYXRlKCk7XG5cblx0XHRcdGlmKCB0aGlzLl9pc0JhY2tib25lQ291cmllckF2YWlsYWJsZSgpIClcblx0XHRcdFx0dGhpcy5zcGF3biggXCJyZW5kZXJcIiApO1xuXHRcdFx0ZWxzZSB0aGlzLnRyaWdnZXIoIFwicmVuZGVyXCIgKTtcblxuXHRcdFx0aWYoIHRoaXMuc2VsZWN0YWJsZSApIHtcblx0XHRcdFx0dGhpcy5fcmVzdG9yZVNlbGVjdGlvbigpO1xuXHRcdFx0XHR0aGlzLnVwZGF0ZURlcGVuZGVudENvbnRyb2xzKCk7XG5cdFx0XHR9XG5cblx0XHRcdHRoaXMuZm9yY2VSZXJlbmRlck9uTmV4dFNvcnRFdmVudCA9IGZhbHNlO1xuXHRcdH0sXG5cblx0XHRfc2hvd0VtcHR5TGlzdENhcHRpb25JZkFwcHJvcHJpYXRlIDogZnVuY3Rpb24gKCApIHtcblx0XHRcdHRoaXMuX3JlbW92ZUVtcHR5TGlzdENhcHRpb24oKTtcblxuXHRcdFx0aWYoIHRoaXMuZW1wdHlMaXN0Q2FwdGlvbiApIHtcblx0XHRcdFx0dmFyIHZpc2libGVFbHMgPSB0aGlzLl9nZXRWaXNpYmxlSXRlbUVscygpO1xuXG5cdFx0XHRcdGlmKCB2aXNpYmxlRWxzLmxlbmd0aCA9PT0gMCApIHtcblx0XHRcdFx0XHR2YXIgZW1wdHlMaXN0U3RyaW5nO1xuXG5cdFx0XHRcdFx0aWYoIF8uaXNGdW5jdGlvbiggdGhpcy5lbXB0eUxpc3RDYXB0aW9uICkgKVxuXHRcdFx0XHRcdFx0ZW1wdHlMaXN0U3RyaW5nID0gdGhpcy5lbXB0eUxpc3RDYXB0aW9uKCk7XG5cdFx0XHRcdFx0ZWxzZVxuXHRcdFx0XHRcdFx0ZW1wdHlMaXN0U3RyaW5nID0gdGhpcy5lbXB0eUxpc3RDYXB0aW9uO1xuXG5cdFx0XHRcdFx0dmFyICRlbXB0eUxpc3RDYXB0aW9uRWw7XG5cdFx0XHRcdFx0dmFyICR2YXJFbCA9ICQoIFwiPHZhciBjbGFzcz0nZW1wdHktbGlzdC1jYXB0aW9uJz5cIiArIGVtcHR5TGlzdFN0cmluZyArIFwiPC92YXI+XCIgKTtcblxuXHRcdFx0XHRcdC8vIG5lZWQgdG8gd3JhcCB0aGUgZW1wdHkgY2FwdGlvbiB0byBtYWtlIGl0IGZpdCB0aGUgcmVuZGVyZWQgbGlzdCBzdHJ1Y3R1cmUgKGVpdGhlciB3aXRoIGFuIGxpIG9yIGEgdHIgdGQpXG5cdFx0XHRcdFx0aWYoIHRoaXMuX2lzUmVuZGVyZWRBc0xpc3QoKSApXG5cdFx0XHRcdFx0XHQkZW1wdHlMaXN0Q2FwdGlvbkVsID0gJHZhckVsLndyYXBBbGwoIFwiPGxpIGNsYXNzPSdub3Qtc29ydGFibGUnPjwvbGk+XCIgKS5wYXJlbnQoKS5jc3MoIGtTdHlsZXNGb3JFbXB0eUxpc3RDYXB0aW9uICk7XG5cdFx0XHRcdFx0ZWxzZVxuXHRcdFx0XHRcdFx0JGVtcHR5TGlzdENhcHRpb25FbCA9ICR2YXJFbC53cmFwQWxsKCBcIjx0ciBjbGFzcz0nbm90LXNvcnRhYmxlJz48dGQgY29sc3Bhbj0nMTAwMCc+PC90ZD48L3RyPlwiICkucGFyZW50KCkucGFyZW50KCkuY3NzKCBrU3R5bGVzRm9yRW1wdHlMaXN0Q2FwdGlvbiApO1xuXG5cdFx0XHRcdFx0dGhpcy5fZ2V0Q29udGFpbmVyRWwoKS5hcHBlbmQoICRlbXB0eUxpc3RDYXB0aW9uRWwgKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0sXG5cblx0XHRfcmVtb3ZlRW1wdHlMaXN0Q2FwdGlvbiA6IGZ1bmN0aW9uKCApIHtcblx0XHRcdGlmKCB0aGlzLl9pc1JlbmRlcmVkQXNMaXN0KCkgKVxuXHRcdFx0XHR0aGlzLl9nZXRDb250YWluZXJFbCgpLmZpbmQoIFwiPiBsaSA+IHZhci5lbXB0eS1saXN0LWNhcHRpb25cIiApLnBhcmVudCgpLnJlbW92ZSgpO1xuXHRcdFx0ZWxzZVxuXHRcdFx0XHR0aGlzLl9nZXRDb250YWluZXJFbCgpLmZpbmQoIFwiPiB0ciA+IHRkID4gdmFyLmVtcHR5LWxpc3QtY2FwdGlvblwiICkucGFyZW50KCkucGFyZW50KCkucmVtb3ZlKCk7XG5cdFx0fSxcblxuXHRcdC8vIFJlbmRlciBhIHNpbmdsZSBtb2RlbCB2aWV3IGluIGNvbnRhaW5lciBvYmplY3QgXCJwYXJlbnRFbE9yRG9jdW1lbnRGcmFnbWVudFwiLCB3aGljaCBpcyBlaXRoZXJcblx0XHQvLyBhIGRvY3VtZW50RnJhZ21lbnQgb3IgYSBqcXVlcnkgb2JqZWN0LiBvcHRpb25hbCBhcmcgYXRJbmRleCBpcyBub3Qgc3VwcG9ydCBmb3IgZG9jdW1lbnQgZnJhZ21lbnRzLlxuXHRcdF9pbnNlcnRBbmRSZW5kZXJNb2RlbFZpZXcgOiBmdW5jdGlvbiggbW9kZWxWaWV3LCBwYXJlbnRFbE9yRG9jdW1lbnRGcmFnbWVudCwgYXRJbmRleCApIHtcblx0XHRcdHZhciB0aGlzTW9kZWxWaWV3V3JhcHBlZCA9IHRoaXMuX3dyYXBNb2RlbFZpZXcoIG1vZGVsVmlldyApO1xuXG5cdFx0XHRpZiggcGFyZW50RWxPckRvY3VtZW50RnJhZ21lbnQubm9kZVR5cGUgPT09IDExICkgLy8gaWYgd2UgYXJlIGluc2VydGluZyBpbnRvIGEgZG9jdW1lbnQgZnJhZ21lbnQsIHdlIG5lZWQgdG8gdXNlIHRoZSBET00gYXBwZW5kQ2hpbGQgbWV0aG9kXG5cdFx0XHRcdHBhcmVudEVsT3JEb2N1bWVudEZyYWdtZW50LmFwcGVuZENoaWxkKCB0aGlzTW9kZWxWaWV3V3JhcHBlZC5nZXQoIDAgKSApO1xuXHRcdFx0ZWxzZSB7XG5cdFx0XHRcdHZhciBudW1iZXJPZk1vZGVsVmlld3NDdXJyZW50bHlJbkRPTSA9IHBhcmVudEVsT3JEb2N1bWVudEZyYWdtZW50LmNoaWxkcmVuKCkubGVuZ3RoO1xuXHRcdFx0XHRpZiggISBfLmlzVW5kZWZpbmVkKCBhdEluZGV4ICkgJiYgYXRJbmRleCA+PSAwICYmIGF0SW5kZXggPCBudW1iZXJPZk1vZGVsVmlld3NDdXJyZW50bHlJbkRPTSApXG5cdFx0XHRcdFx0Ly8gbm90ZSB0aGlzLmNvbGxlY3Rpb24ubGVuZ3RoIG1pZ2h0IGJlIGdyZWF0ZXIgdGhhbiBwYXJlbnRFbE9yRG9jdW1lbnRGcmFnbWVudC5jaGlsZHJlbigpLmxlbmd0aCBoZXJlXG5cdFx0XHRcdFx0cGFyZW50RWxPckRvY3VtZW50RnJhZ21lbnQuY2hpbGRyZW4oKS5lcSggYXRJbmRleCApLmJlZm9yZSggdGhpc01vZGVsVmlld1dyYXBwZWQgKTtcblx0XHRcdFx0ZWxzZSB7XG5cdFx0XHRcdFx0Ly8gaWYgd2UgYXJlIGF0dGVtcHRpbmcgdG8gaW5zZXJ0IGEgbW9kZWxWaWV3IGluIGFuIHBvc2l0aW9uIHRoYXQgaXMgYmV5b25kIHdoYXQgaXMgY3VycmVudGx5IGluIHRoZVxuXHRcdFx0XHRcdC8vIERPTSwgdGhlbiBtYWtlIGEgbm90ZSB0aGF0IHdlIG5lZWQgdG8gcmUtcmVuZGVyIHRoZSBjb2xsZWN0aW9uIHZpZXcgb24gdGhlIG5leHQgc29ydCBldmVudC4gSWYgd2UgZG9udFxuXHRcdFx0XHRcdC8vIGZvcmNlIHRoaXMgcmUtcmVuZGVyLCB3ZSBjYW4gZW5kIHVwIHdpdGggbW9kZWxWaWV3cyBpbiB0aGUgd3Jvbmcgb3JkZXIgd2hlbiB0aGUgY29sbGVjdGlvbiBkZWZpbmVzXG5cdFx0XHRcdFx0Ly8gYSBjb21wYXJhdG9yIGFuZCBtdWx0aXBsZSBtb2RlbHMgYXJlIGFkZGVkIGF0IG9uY2UuIFNlZSBodHRwczovL2dpdGh1Yi5jb20vcm90dW5kYXNvZnR3YXJlL2JhY2tib25lLmNvbGxlY3Rpb25WaWV3L2lzc3Vlcy82OVxuXHRcdFx0XHRcdGlmKCAhIF8uaXNVbmRlZmluZWQoIGF0SW5kZXggKSAmJiBhdEluZGV4ID4gbnVtYmVyT2ZNb2RlbFZpZXdzQ3VycmVudGx5SW5ET00gKSB0aGlzLmZvcmNlUmVyZW5kZXJPbk5leHRTb3J0RXZlbnQgPSB0cnVlO1xuXG5cdFx0XHRcdFx0cGFyZW50RWxPckRvY3VtZW50RnJhZ21lbnQuYXBwZW5kKCB0aGlzTW9kZWxWaWV3V3JhcHBlZCApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdHRoaXMudmlld01hbmFnZXIuYWRkKCBtb2RlbFZpZXcgKTtcblxuXHRcdFx0Ly8gd2UgaGF2ZSB0byByZW5kZXIgdGhlIG1vZGVsVmlldyBhZnRlciBpdCBoYXMgYmVlbiBwdXQgaW4gY29udGV4dCwgYXMgb3Bwb3NlZCB0byBpbiB0aGVcblx0XHRcdC8vIGluaXRpYWxpemUgZnVuY3Rpb24gb2YgdGhlIG1vZGVsVmlldywgYmVjYXVzZSBzb21lIHJlbmRlcmluZyBtaWdodCBiZSBkZXBlbmRlbnQgb25cblx0XHRcdC8vIHRoZSBtb2RlbFZpZXcncyBjb250ZXh0IGluIHRoZSBET00gdHJlZS4gRm9yIGV4YW1wbGUsIGlmIHRoZSBtb2RlbFZpZXcgc3RyZXRjaCgpJ3MgaXRzZWxmLFxuXHRcdFx0Ly8gaXQgbXVzdCBiZSBpbiBmdWxsIGNvbnRleHQgaW4gdGhlIERPTSB0cmVlIG9yIGVsc2UgdGhlIHN0cmV0Y2ggd2lsbCBub3QgYmVoYXZlIGFzIGludGVuZGVkLlxuXHRcdFx0dmFyIHJlbmRlclJlc3VsdCA9IG1vZGVsVmlldy5yZW5kZXIoKTtcblxuXHRcdFx0Ly8gcmV0dXJuIGZhbHNlIGZyb20gdGhlIHZpZXcncyByZW5kZXIgZnVuY3Rpb24gdG8gaGlkZSB0aGlzIGl0ZW1cblx0XHRcdGlmKCByZW5kZXJSZXN1bHQgPT09IGZhbHNlICkge1xuXHRcdFx0XHR0aGlzTW9kZWxWaWV3V3JhcHBlZC5oaWRlKCk7XG5cdFx0XHRcdHRoaXNNb2RlbFZpZXdXcmFwcGVkLmFkZENsYXNzKCBcIm5vdC12aXNpYmxlXCIgKTtcblx0XHRcdH1cblxuXHRcdFx0dmFyIGhpZGVUaGlzTW9kZWxWaWV3ID0gZmFsc2U7XG5cdFx0XHRpZiggXy5pc0Z1bmN0aW9uKCB0aGlzLnZpc2libGVNb2RlbHNGaWx0ZXIgKSApXG5cdFx0XHRcdGhpZGVUaGlzTW9kZWxWaWV3ID0gISB0aGlzLnZpc2libGVNb2RlbHNGaWx0ZXIoIG1vZGVsVmlldy5tb2RlbCApO1xuXG5cdFx0XHRpZiggdGhpc01vZGVsVmlld1dyYXBwZWQuY2hpbGRyZW4oKS5sZW5ndGggPT09IDEgKVxuXHRcdFx0XHR0aGlzTW9kZWxWaWV3V3JhcHBlZC50b2dnbGUoICEgaGlkZVRoaXNNb2RlbFZpZXcgKTtcblx0XHRcdGVsc2UgbW9kZWxWaWV3LiRlbC50b2dnbGUoICEgaGlkZVRoaXNNb2RlbFZpZXcgKTtcblxuXHRcdFx0dGhpc01vZGVsVmlld1dyYXBwZWQudG9nZ2xlQ2xhc3MoIFwibm90LXZpc2libGVcIiwgaGlkZVRoaXNNb2RlbFZpZXcgKTtcblxuXHRcdFx0aWYoICEgaGlkZVRoaXNNb2RlbFZpZXcgJiYgdGhpcy5lbXB0eUxpc3RDYXB0aW9uICkgdGhpcy5fcmVtb3ZlRW1wdHlMaXN0Q2FwdGlvbigpO1xuXHRcdH0sXG5cblx0XHR1cGRhdGVEZXBlbmRlbnRDb250cm9scyA6IGZ1bmN0aW9uKCkge1xuXHRcdFx0aWYoIHRoaXMuX2lzQmFja2JvbmVDb3VyaWVyQXZhaWxhYmxlKCkgKSB7XG5cdFx0XHRcdHRoaXMuc3Bhd24oIFwidXBkYXRlRGVwZW5kZW50Q29udHJvbHNcIiwge1xuXHRcdFx0XHRcdHNlbGVjdGVkTW9kZWxzIDogdGhpcy5nZXRTZWxlY3RlZE1vZGVscygpXG5cdFx0XHRcdH0gKTtcblx0XHRcdH0gZWxzZSB0aGlzLnRyaWdnZXIoIFwidXBkYXRlRGVwZW5kZW50Q29udHJvbHNcIiwgdGhpcy5nZXRTZWxlY3RlZE1vZGVscygpICk7XG5cdFx0fSxcblxuXHRcdC8vIE92ZXJyaWRlIGBCYWNrYm9uZS5WaWV3LnJlbW92ZWAgdG8gYWxzbyBkZXN0cm95IGFsbCBWaWV3cyBpbiBgdmlld01hbmFnZXJgXG5cdFx0cmVtb3ZlIDogZnVuY3Rpb24oKSB7XG5cdFx0XHR0aGlzLnZpZXdNYW5hZ2VyLmVhY2goIGZ1bmN0aW9uKCB2aWV3ICkge1xuXHRcdFx0XHR2aWV3LnJlbW92ZSgpO1xuXHRcdFx0fSApO1xuXG5cdFx0XHRCYWNrYm9uZS5WaWV3LnByb3RvdHlwZS5yZW1vdmUuYXBwbHkoIHRoaXMsIGFyZ3VtZW50cyApO1xuXHRcdH0sXG5cblx0XHRyZWFwcGx5RmlsdGVyIDogZnVuY3Rpb24oIHdoaWNoRmlsdGVyICkge1xuXHRcdFx0dmFyIF90aGlzID0gdGhpcztcblxuXHRcdFx0aWYoICEgXy5jb250YWlucyggWyBcInNlbGVjdGFibGVNb2RlbHNcIiwgXCJzb3J0YWJsZU1vZGVsc1wiLCBcInZpc2libGVNb2RlbHNcIiBdLCB3aGljaEZpbHRlciApICkge1xuXHRcdFx0XHR0aHJvdyBuZXcgRXJyb3IoIFwiSW52YWxpZCBmaWx0ZXIgaWRlbnRpZmllciBzdXBwbGllZCB0byByZWFwcGx5RmlsdGVyOiBcIiArIHdoaWNoRmlsdGVyICk7XG5cdFx0XHR9XG5cblx0XHRcdHN3aXRjaCggd2hpY2hGaWx0ZXIgKSB7XG5cdFx0XHRcdGNhc2UgXCJ2aXNpYmxlTW9kZWxzXCI6XG5cdFx0XHRcdFx0X3RoaXMudmlld01hbmFnZXIuZWFjaCggZnVuY3Rpb24oIHRoaXNNb2RlbFZpZXcgKSB7XG5cdFx0XHRcdFx0XHR2YXIgbm90VmlzaWJsZSA9IF90aGlzLnZpc2libGVNb2RlbHNGaWx0ZXIgJiYgISBfdGhpcy52aXNpYmxlTW9kZWxzRmlsdGVyLmNhbGwoIF90aGlzLCB0aGlzTW9kZWxWaWV3Lm1vZGVsICk7XG5cblx0XHRcdFx0XHRcdHRoaXNNb2RlbFZpZXcuJGVsLnRvZ2dsZUNsYXNzKCBcIm5vdC12aXNpYmxlXCIsIG5vdFZpc2libGUgKTtcblx0XHRcdFx0XHRcdGlmKCBfdGhpcy5fbW9kZWxWaWV3SGFzV3JhcHBlckxJKCB0aGlzTW9kZWxWaWV3ICkgKSB7XG5cdFx0XHRcdFx0XHRcdHRoaXNNb2RlbFZpZXcuJGVsLmNsb3Nlc3QoIFwibGlcIiApLnRvZ2dsZUNsYXNzKCBcIm5vdC12aXNpYmxlXCIsIG5vdFZpc2libGUgKS50b2dnbGUoICEgbm90VmlzaWJsZSApO1xuXHRcdFx0XHRcdFx0fSBlbHNlIHRoaXNNb2RlbFZpZXcuJGVsLnRvZ2dsZSggISBub3RWaXNpYmxlICk7XG5cdFx0XHRcdFx0fSApO1xuXG5cdFx0XHRcdFx0dGhpcy5fc2hvd0VtcHR5TGlzdENhcHRpb25JZkFwcHJvcHJpYXRlKCk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgXCJzb3J0YWJsZU1vZGVsc1wiOlxuXHRcdFx0XHRcdF90aGlzLiRlbC5zb3J0YWJsZSggXCJkZXN0cm95XCIgKTtcblxuXHRcdFx0XHRcdF90aGlzLnZpZXdNYW5hZ2VyLmVhY2goIGZ1bmN0aW9uKCB0aGlzTW9kZWxWaWV3ICkge1xuXHRcdFx0XHRcdFx0dmFyIG5vdFNvcnRhYmxlID0gX3RoaXMuc29ydGFibGVNb2RlbHNGaWx0ZXIgJiYgISBfdGhpcy5zb3J0YWJsZU1vZGVsc0ZpbHRlci5jYWxsKCBfdGhpcywgdGhpc01vZGVsVmlldy5tb2RlbCApO1xuXG5cdFx0XHRcdFx0XHR0aGlzTW9kZWxWaWV3LiRlbC50b2dnbGVDbGFzcyggXCJub3Qtc29ydGFibGVcIiwgbm90U29ydGFibGUgKTtcblx0XHRcdFx0XHRcdGlmKCBfdGhpcy5fbW9kZWxWaWV3SGFzV3JhcHBlckxJKCB0aGlzTW9kZWxWaWV3ICkgKSB7XG5cdFx0XHRcdFx0XHRcdHRoaXNNb2RlbFZpZXcuJGVsLmNsb3Nlc3QoIFwibGlcIiApLnRvZ2dsZUNsYXNzKCBcIm5vdC1zb3J0YWJsZVwiLCBub3RTb3J0YWJsZSApO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH0gKTtcblxuXHRcdFx0XHRcdF90aGlzLl9zZXR1cFNvcnRhYmxlKCk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgXCJzZWxlY3RhYmxlTW9kZWxzXCI6XG5cdFx0XHRcdFx0X3RoaXMudmlld01hbmFnZXIuZWFjaCggZnVuY3Rpb24oIHRoaXNNb2RlbFZpZXcgKSB7XG5cdFx0XHRcdFx0XHR2YXIgbm90U2VsZWN0YWJsZSA9IF90aGlzLnNlbGVjdGFibGVNb2RlbHNGaWx0ZXIgJiYgISBfdGhpcy5zZWxlY3RhYmxlTW9kZWxzRmlsdGVyLmNhbGwoIF90aGlzLCB0aGlzTW9kZWxWaWV3Lm1vZGVsICk7XG5cblx0XHRcdFx0XHRcdHRoaXNNb2RlbFZpZXcuJGVsLnRvZ2dsZUNsYXNzKCBcIm5vdC1zZWxlY3RhYmxlXCIsIG5vdFNlbGVjdGFibGUgKTtcblx0XHRcdFx0XHRcdGlmKCBfdGhpcy5fbW9kZWxWaWV3SGFzV3JhcHBlckxJKCB0aGlzTW9kZWxWaWV3ICkgKSB7XG5cdFx0XHRcdFx0XHRcdHRoaXNNb2RlbFZpZXcuJGVsLmNsb3Nlc3QoIFwibGlcIiApLnRvZ2dsZUNsYXNzKCBcIm5vdC1zZWxlY3RhYmxlXCIsIG5vdFNlbGVjdGFibGUgKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9ICk7XG5cblx0XHRcdFx0XHRfdGhpcy5fdmFsaWRhdGVTZWxlY3Rpb24oKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdH1cblx0XHR9LFxuXG5cdFx0Ly8gQSBtZXRob2QgdG8gcmVtb3ZlIHRoZSB2aWV3IHJlbGF0aW5nIHRvIG1vZGVsLlxuXHRcdF9yZW1vdmVNb2RlbFZpZXcgOiBmdW5jdGlvbiggbW9kZWxWaWV3ICkge1xuXHRcdFx0aWYoIHRoaXMuc2VsZWN0YWJsZSApIHRoaXMuX3NhdmVTZWxlY3Rpb24oKTtcblxuXHRcdFx0dGhpcy52aWV3TWFuYWdlci5yZW1vdmUoIG1vZGVsVmlldyApOyAvLyBSZW1vdmUgdGhlIHZpZXcgZnJvbSB0aGUgdmlld01hbmFnZXJcblx0XHRcdGlmKCB0aGlzLl9tb2RlbFZpZXdIYXNXcmFwcGVyTEkoIG1vZGVsVmlldyApICkgbW9kZWxWaWV3LiRlbC5wYXJlbnQoKS5yZW1vdmUoKTsgLy8gUmVtb3ZlIHRoZSBsaSB3cmFwcGVyIGZyb20gdGhlIERPTVxuXHRcdFx0bW9kZWxWaWV3LnJlbW92ZSgpOyAvLyBSZW1vdmUgdGhlIHZpZXcgZnJvbSB0aGUgRE9NIGFuZCBzdG9wIGxpc3RlbmluZyB0byBldmVudHNcblxuXHRcdFx0aWYoIHRoaXMuc2VsZWN0YWJsZSApIHRoaXMuX3Jlc3RvcmVTZWxlY3Rpb24oKTtcblxuXHRcdFx0dGhpcy5fc2hvd0VtcHR5TGlzdENhcHRpb25JZkFwcHJvcHJpYXRlKCk7XG5cdFx0fSxcblxuXHRcdF92YWxpZGF0ZVNlbGVjdGlvbkFuZFJlbmRlciA6IGZ1bmN0aW9uKCkge1xuXHRcdFx0dGhpcy5fdmFsaWRhdGVTZWxlY3Rpb24oKTtcblx0XHRcdHRoaXMucmVuZGVyKCk7XG5cdFx0fSxcblxuXHRcdF9yZWdpc3RlckNvbGxlY3Rpb25FdmVudHMgOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0dGhpcy5saXN0ZW5UbyggdGhpcy5jb2xsZWN0aW9uLCBcImFkZFwiLCBmdW5jdGlvbiggbW9kZWwgKSB7XG5cdFx0XHRcdHZhciBtb2RlbFZpZXc7XG5cdFx0XHRcdGlmKCB0aGlzLl9oYXNCZWVuUmVuZGVyZWQgKSB7XG5cdFx0XHRcdFx0bW9kZWxWaWV3ID0gdGhpcy5fY3JlYXRlTmV3TW9kZWxWaWV3KCBtb2RlbCwgdGhpcy5fZ2V0TW9kZWxWaWV3T3B0aW9ucyggbW9kZWwgKSApO1xuXHRcdFx0XHRcdHRoaXMuX2luc2VydEFuZFJlbmRlck1vZGVsVmlldyggbW9kZWxWaWV3LCB0aGlzLl9nZXRDb250YWluZXJFbCgpLCB0aGlzLmNvbGxlY3Rpb24uaW5kZXhPZiggbW9kZWwgKSApO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYoIHRoaXMuX2lzQmFja2JvbmVDb3VyaWVyQXZhaWxhYmxlKCkgKVxuXHRcdFx0XHRcdHRoaXMuc3Bhd24oIFwiYWRkXCIsIG1vZGVsVmlldyApO1xuXHRcdFx0XHRlbHNlIHRoaXMudHJpZ2dlciggXCJhZGRcIiwgbW9kZWxWaWV3ICk7XG5cdFx0XHR9ICk7XG5cblx0XHRcdHRoaXMubGlzdGVuVG8oIHRoaXMuY29sbGVjdGlvbiwgXCJyZW1vdmVcIiwgZnVuY3Rpb24oIG1vZGVsICkge1xuXHRcdFx0XHR2YXIgbW9kZWxWaWV3O1xuXG5cdFx0XHRcdGlmKCB0aGlzLl9oYXNCZWVuUmVuZGVyZWQgKSB7XG5cdFx0XHRcdFx0bW9kZWxWaWV3ID0gdGhpcy52aWV3TWFuYWdlci5maW5kQnlNb2RlbENpZCggbW9kZWwuY2lkICk7XG5cdFx0XHRcdFx0dGhpcy5fcmVtb3ZlTW9kZWxWaWV3KCBtb2RlbFZpZXcgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmKCB0aGlzLl9pc0JhY2tib25lQ291cmllckF2YWlsYWJsZSgpIClcblx0XHRcdFx0XHR0aGlzLnNwYXduKCBcInJlbW92ZVwiICk7XG5cdFx0XHRcdGVsc2UgdGhpcy50cmlnZ2VyKCBcInJlbW92ZVwiICk7XG5cdFx0XHR9ICk7XG5cblx0XHRcdHRoaXMubGlzdGVuVG8oIHRoaXMuY29sbGVjdGlvbiwgXCJyZXNldFwiLCBmdW5jdGlvbigpIHtcblx0XHRcdFx0aWYoIHRoaXMuX2hhc0JlZW5SZW5kZXJlZCApIHRoaXMucmVuZGVyKCk7XG5cdFx0XHRcdGlmKCB0aGlzLl9pc0JhY2tib25lQ291cmllckF2YWlsYWJsZSgpIClcblx0XHRcdFx0XHR0aGlzLnNwYXduKCBcInJlc2V0XCIgKTtcblx0XHRcdFx0ZWxzZSB0aGlzLnRyaWdnZXIoIFwicmVzZXRcIiApO1xuXHRcdFx0fSApO1xuXG5cdFx0XHQvLyB3ZSBzaG91bGQgbm90IGJlIGxpc3RlbmluZyB0byBjaGFuZ2UgZXZlbnRzIG9uIHRoZSBtb2RlbCBhcyBhIGRlZmF1bHQgYmVoYXZpb3IuIHRoZSBtb2RlbHNcblx0XHRcdC8vIHNob3VsZCBiZSByZXNwb25zaWJsZSBmb3IgcmUtcmVuZGVyaW5nIHRoZW1zZWx2ZXMgaWYgbmVjZXNzYXJ5LCBhbmQgaWYgdGhlIGNvbGxlY3Rpb24gZG9lc1xuXHRcdFx0Ly8gYWxzbyBuZWVkIHRvIHJlLXJlbmRlciBhcyBhIHJlc3VsdCBvZiBhIG1vZGVsIGNoYW5nZSwgdGhpcyBzaG91bGQgYmUgaGFuZGxlZCBieSBvdmVycmlkaW5nXG5cdFx0XHQvLyB0aGlzIG1ldGhvZC4gYnkgZGVmYXVsdCB0aGUgY29sbGVjdGlvbiB2aWV3IHNob3VsZCBub3QgcmUtcmVuZGVyIGluIHJlc3BvbnNlIHRvIG1vZGVsIGNoYW5nZXNcblx0XHRcdC8vIHRoaXMubGlzdGVuVG8oIHRoaXMuY29sbGVjdGlvbiwgXCJjaGFuZ2VcIiwgZnVuY3Rpb24oIG1vZGVsICkge1xuXHRcdFx0Ly8gXHRpZiggdGhpcy5faGFzQmVlblJlbmRlcmVkICkgdGhpcy52aWV3TWFuYWdlci5maW5kQnlNb2RlbCggbW9kZWwgKS5yZW5kZXIoKTtcblx0XHRcdC8vIFx0aWYoIHRoaXMuX2lzQmFja2JvbmVDb3VyaWVyQXZhaWxhYmxlKCkgKVxuXHRcdFx0Ly8gXHRcdHRoaXMuc3Bhd24oIFwiY2hhbmdlXCIsIHsgbW9kZWwgOiBtb2RlbCB9ICk7XG5cdFx0XHQvLyB9ICk7XG5cblx0XHRcdHRoaXMubGlzdGVuVG8oIHRoaXMuY29sbGVjdGlvbiwgXCJzb3J0XCIsIGZ1bmN0aW9uKCBjb2xsZWN0aW9uLCBvcHRpb25zICkge1xuXHRcdFx0XHRpZiggdGhpcy5faGFzQmVlblJlbmRlcmVkICYmICggb3B0aW9ucy5hZGQgIT09IHRydWUgfHwgdGhpcy5mb3JjZVJlcmVuZGVyT25OZXh0U29ydEV2ZW50ICkgKSB0aGlzLnJlbmRlcigpO1xuXHRcdFx0XHRpZiggdGhpcy5faXNCYWNrYm9uZUNvdXJpZXJBdmFpbGFibGUoKSApXG5cdFx0XHRcdFx0dGhpcy5zcGF3biggXCJzb3J0XCIgKTtcblx0XHRcdFx0ZWxzZSB0aGlzLnRyaWdnZXIoIFwic29ydFwiICk7XG5cdFx0XHR9ICk7XG5cdFx0fSxcblxuXHRcdF9nZXRDb250YWluZXJFbCA6IGZ1bmN0aW9uKCkge1xuXHRcdFx0aWYgKCB0aGlzLl9pc1JlbmRlcmVkQXNUYWJsZSgpICkge1xuXHRcdFx0XHQvLyBub3QgYWxsIHRhYmxlcyBoYXZlIGEgdGJvZHksIHNvIHdlIHRlc3Rcblx0XHRcdFx0dmFyIHRib2R5ID0gdGhpcy4kZWwuZmluZCggXCI+IHRib2R5XCIgKTtcblx0XHRcdFx0aWYgKCB0Ym9keS5sZW5ndGggPiAwIClcblx0XHRcdFx0XHRyZXR1cm4gdGJvZHk7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gdGhpcy4kZWw7XG5cdFx0fSxcblxuXHRcdF9nZXRDbGlja2VkSXRlbUlkIDogZnVuY3Rpb24oIHRoZUV2ZW50ICkge1xuXHRcdFx0dmFyIGNsaWNrZWRJdGVtSWQgPSBudWxsO1xuXG5cdFx0XHQvLyBpbXBvcnRhbnQgdG8gdXNlIGN1cnJlbnRUYXJnZXQgYXMgb3Bwb3NlZCB0byB0YXJnZXQsIHNpbmNlIHdlIGNvdWxkIGJlIGJ1YmJsaW5nXG5cdFx0XHQvLyBhbiBldmVudCB0aGF0IHRvb2sgcGxhY2Ugd2l0aGluIGFub3RoZXIgY29sbGVjdGlvbkxpc3Rcblx0XHRcdHZhciBjbGlja2VkSXRlbUVsID0gJCggdGhlRXZlbnQuY3VycmVudFRhcmdldCApO1xuXHRcdFx0aWYoIGNsaWNrZWRJdGVtRWwuY2xvc2VzdCggXCIuY29sbGVjdGlvbi12aWV3XCIgKS5nZXQoMCkgIT09IHRoaXMuJGVsLmdldCgwKSApIHJldHVybjtcblxuXHRcdFx0Ly8gZGV0ZXJtaW5lIHdoaWNoIGxpc3QgaXRlbSB3YXMgY2xpY2tlZC4gSWYgd2UgY2xpY2tlZCBpbiB0aGUgYmxhbmsgYXJlYVxuXHRcdFx0Ly8gdW5kZXJuZWF0aCBhbGwgdGhlIGVsZW1lbnRzLCB3ZSB3YW50IHRvIGtub3cgdGhhdCB0b28sIHNpbmNlIGluIHRoaXNcblx0XHRcdC8vIGNhc2Ugd2Ugd2lsbCB3YW50IHRvIGRlc2VsZWN0IGFsbCBlbGVtZW50cy4gc28gY2hlY2sgdG8gc2VlIGlmIHRoZSBjbGlja2VkXG5cdFx0XHQvLyBET00gZWxlbWVudCBpcyB0aGUgbGlzdCBpdHNlbGYgdG8gZmluZCB0aGF0IG91dC5cblx0XHRcdHZhciBjbGlja2VkSXRlbSA9IGNsaWNrZWRJdGVtRWwuY2xvc2VzdCggXCJbZGF0YS1tb2RlbC1jaWRdXCIgKTtcblx0XHRcdGlmKCBjbGlja2VkSXRlbS5sZW5ndGggPiAwIClcblx0XHRcdHtcblx0XHRcdFx0Y2xpY2tlZEl0ZW1JZCA9IGNsaWNrZWRJdGVtLmF0dHIoIFwiZGF0YS1tb2RlbC1jaWRcIiApO1xuXHRcdFx0XHRpZiggJC5pc051bWVyaWMoIGNsaWNrZWRJdGVtSWQgKSApIGNsaWNrZWRJdGVtSWQgPSBwYXJzZUludCggY2xpY2tlZEl0ZW1JZCwgMTAgKTtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIGNsaWNrZWRJdGVtSWQ7XG5cdFx0fSxcblxuXHRcdF91cGRhdGVJdGVtVGVtcGxhdGUgOiBmdW5jdGlvbigpIHtcblx0XHRcdHZhciBpdGVtVGVtcGxhdGVIdG1sO1xuXHRcdFx0aWYoIHRoaXMuaXRlbVRlbXBsYXRlIClcblx0XHRcdHtcblx0XHRcdFx0aWYoICQoIHRoaXMuaXRlbVRlbXBsYXRlICkubGVuZ3RoID09PSAwIClcblx0XHRcdFx0XHR0aHJvdyBcIkNvdWxkIG5vdCBmaW5kIGl0ZW0gdGVtcGxhdGUgZnJvbSBzZWxlY3RvcjogXCIgKyB0aGlzLml0ZW1UZW1wbGF0ZTtcblxuXHRcdFx0XHRpdGVtVGVtcGxhdGVIdG1sID0gJCggdGhpcy5pdGVtVGVtcGxhdGUgKS5odG1sKCk7XG5cdFx0XHR9XG5cdFx0XHRlbHNlXG5cdFx0XHRcdGl0ZW1UZW1wbGF0ZUh0bWwgPSB0aGlzLiQoIFwiLml0ZW0tdGVtcGxhdGVcIiApLmh0bWwoKTtcblxuXHRcdFx0aWYoIGl0ZW1UZW1wbGF0ZUh0bWwgKSB0aGlzLml0ZW1UZW1wbGF0ZUZ1bmN0aW9uID0gXy50ZW1wbGF0ZSggaXRlbVRlbXBsYXRlSHRtbCApO1xuXG5cdFx0fSxcblxuXHRcdF92YWxpZGF0ZVNlbGVjdGlvbiA6IGZ1bmN0aW9uKCkge1xuXHRcdFx0Ly8gbm90ZSBjYW4ndCB1c2UgdGhlIGNvbGxlY3Rpb24ncyBwcm94eSB0byB1bmRlcnNjb3JlIGJlY2F1c2UgXCJjaWRcIiBpcyBub3QgYW4gYXR0cmlidXRlLFxuXHRcdFx0Ly8gYnV0IGFuIGVsZW1lbnQgb2YgdGhlIG1vZGVsIG9iamVjdCBpdHNlbGYuXG5cdFx0XHR2YXIgbW9kZWxSZWZlcmVuY2VJZHMgPSBfLnBsdWNrKCB0aGlzLmNvbGxlY3Rpb24ubW9kZWxzLCBcImNpZFwiICk7XG5cdFx0XHR0aGlzLnNlbGVjdGVkSXRlbXMgPSBfLmludGVyc2VjdGlvbiggbW9kZWxSZWZlcmVuY2VJZHMsIHRoaXMuc2VsZWN0ZWRJdGVtcyApO1xuXG5cdFx0XHRpZiggXy5pc0Z1bmN0aW9uKCB0aGlzLnNlbGVjdGFibGVNb2RlbHNGaWx0ZXIgKSApXG5cdFx0XHR7XG5cdFx0XHRcdHRoaXMuc2VsZWN0ZWRJdGVtcyA9IF8uZmlsdGVyKCB0aGlzLnNlbGVjdGVkSXRlbXMsIGZ1bmN0aW9uKCB0aGlzSXRlbUlkICkge1xuXHRcdFx0XHRcdHJldHVybiB0aGlzLnNlbGVjdGFibGVNb2RlbHNGaWx0ZXIuY2FsbCggdGhpcywgdGhpcy5jb2xsZWN0aW9uLmdldCggdGhpc0l0ZW1JZCApICk7XG5cdFx0XHRcdH0sIHRoaXMgKTtcblx0XHRcdH1cblx0XHR9LFxuXG5cdFx0X3NhdmVTZWxlY3Rpb24gOiBmdW5jdGlvbigpIHtcblx0XHRcdC8vIHNhdmUgdGhlIGN1cnJlbnQgc2VsZWN0aW9uLiB1c2UgcmVzdG9yZVNlbGVjdGlvbigpIHRvIHJlc3RvcmUgdGhlIHNlbGVjdGlvbiB0byB0aGUgc3RhdGUgaXQgd2FzIGluIHRoZSBsYXN0IHRpbWUgc2F2ZVNlbGVjdGlvbigpIHdhcyBjYWxsZWQuXG5cdFx0XHRpZiggISB0aGlzLnNlbGVjdGFibGUgKSB0aHJvdyBcIkF0dGVtcHQgdG8gc2F2ZSBzZWxlY3Rpb24gb24gbm9uLXNlbGVjdGFibGUgbGlzdFwiO1xuXHRcdFx0dGhpcy5zYXZlZFNlbGVjdGlvbiA9IHtcblx0XHRcdFx0aXRlbXMgOiBfLmNsb25lKCB0aGlzLnNlbGVjdGVkSXRlbXMgKSxcblx0XHRcdFx0b2Zmc2V0IDogdGhpcy5nZXRTZWxlY3RlZE1vZGVsKCB7IGJ5IDogXCJvZmZzZXRcIiB9IClcblx0XHRcdH07XG5cdFx0fSxcblxuXHRcdF9yZXN0b3JlU2VsZWN0aW9uIDogZnVuY3Rpb24oKSB7XG5cdFx0XHRpZiggISB0aGlzLnNhdmVkU2VsZWN0aW9uICkgdGhyb3cgXCJBdHRlbXB0IHRvIHJlc3RvcmUgc2VsZWN0aW9uIGJ1dCBubyBzZWxlY3Rpb24gaGFzIGJlZW4gc2F2ZWQhXCI7XG5cblx0XHRcdC8vIHJlc2V0IHNlbGVjdGVkSXRlbXMgdG8gZW1wdHkgc28gdGhhdCB3ZSBcInJlZHJhd1wiIGFsbCBcInNlbGVjdGVkXCIgY2xhc3Nlc1xuXHRcdFx0Ly8gd2hlbiB3ZSBzZXQgb3VyIG5ldyBzZWxlY3Rpb24uIFdlIGRvIHRoaXMgYmVjYXVzZSBpdCBpcyBsaWtlbHkgdGhhdCBvdXJcblx0XHRcdC8vIGNvbnRlbnRzIGhhdmUgYmVlbiByZWZyZXNoZWQsIGFuZCB3ZSBoYXZlIHRodXMgbG9zdCBhbGwgb2xkIFwic2VsZWN0ZWRcIiBjbGFzc2VzLlxuXHRcdFx0dGhpcy5zZXRTZWxlY3RlZE1vZGVscyggW10sIHsgc2lsZW50IDogdHJ1ZSB9ICk7XG5cblx0XHRcdGlmKCB0aGlzLnNhdmVkU2VsZWN0aW9uLml0ZW1zLmxlbmd0aCA+IDAgKVxuXHRcdFx0e1xuXHRcdFx0XHQvLyBmaXJzdCB0cnkgdG8gcmVzdG9yZSB0aGUgb2xkIHNlbGVjdGVkIGl0ZW1zIHVzaW5nIHRoZWlyIHJlZmVyZW5jZSBpZHMuXG5cdFx0XHRcdHRoaXMuc2V0U2VsZWN0ZWRNb2RlbHMoIHRoaXMuc2F2ZWRTZWxlY3Rpb24uaXRlbXMsIHsgYnkgOiBcImNpZFwiLCBzaWxlbnQgOiB0cnVlIH0gKTtcblxuXHRcdFx0XHQvLyBhbGwgdGhlIGl0ZW1zIHdpdGggdGhlIHNhdmVkIHJlZmVyZW5jZSBpZHMgaGF2ZSBiZWVuIHJlbW92ZWQgZnJvbSB0aGUgbGlzdC5cblx0XHRcdFx0Ly8gb2suIHRyeSB0byByZXN0b3JlIHRoZSBzZWxlY3Rpb24gYmFzZWQgb24gdGhlIG9mZnNldCB0aGF0IHVzZWQgdG8gYmUgc2VsZWN0ZWQuXG5cdFx0XHRcdC8vIHRoaXMgaXMgdGhlIGV4cGVjdGVkIGJlaGF2aW9yIGFmdGVyIGEgaXRlbSBpcyBkZWxldGVkIGZyb20gYSBsaXN0IChpLmUuIHNlbGVjdFxuXHRcdFx0XHQvLyB0aGUgbGluZSB0aGF0IGltbWVkaWF0ZWx5IGZvbGxvd3MgdGhlIGRlbGV0ZWQgbGluZSkuXG5cdFx0XHRcdGlmKCB0aGlzLnNlbGVjdGVkSXRlbXMubGVuZ3RoID09PSAwIClcblx0XHRcdFx0XHR0aGlzLnNldFNlbGVjdGVkTW9kZWwoIHRoaXMuc2F2ZWRTZWxlY3Rpb24ub2Zmc2V0LCB7IGJ5IDogXCJvZmZzZXRcIiB9ICk7XG5cblx0XHRcdFx0Ly8gVHJpZ2dlciBhIHNlbGVjdGlvbiBjaGFuZ2VkIGlmIHRoZSBwcmV2aW91c2x5IHNlbGVjdGVkIGl0ZW1zIHdlcmUgbm90IGFsbCBmb3VuZFxuXHRcdFx0XHRpZiAodGhpcy5zZWxlY3RlZEl0ZW1zLmxlbmd0aCAhPT0gdGhpcy5zYXZlZFNlbGVjdGlvbi5pdGVtcy5sZW5ndGgpXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRpZiggdGhpcy5faXNCYWNrYm9uZUNvdXJpZXJBdmFpbGFibGUoKSApIHtcblx0XHRcdFx0XHRcdHRoaXMuc3Bhd24oIFwic2VsZWN0aW9uQ2hhbmdlZFwiLCB7XG5cdFx0XHRcdFx0XHRcdHNlbGVjdGVkTW9kZWxzIDogdGhpcy5nZXRTZWxlY3RlZE1vZGVscygpLFxuXHRcdFx0XHRcdFx0XHRvbGRTZWxlY3RlZE1vZGVscyA6IFtdXG5cdFx0XHRcdFx0XHR9ICk7XG5cdFx0XHRcdFx0fSBlbHNlIHRoaXMudHJpZ2dlciggXCJzZWxlY3Rpb25DaGFuZ2VkXCIsIHRoaXMuZ2V0U2VsZWN0ZWRNb2RlbHMoKSwgW10gKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0sXG5cblx0XHRfYWRkU2VsZWN0ZWRDbGFzc1RvU2VsZWN0ZWRJdGVtcyA6IGZ1bmN0aW9uKCBvbGRJdGVtc0lkc1dpdGhTZWxlY3RlZENsYXNzICkge1xuXHRcdFx0aWYoIF8uaXNVbmRlZmluZWQoIG9sZEl0ZW1zSWRzV2l0aFNlbGVjdGVkQ2xhc3MgKSApIG9sZEl0ZW1zSWRzV2l0aFNlbGVjdGVkQ2xhc3MgPSBbXTtcblxuXHRcdFx0Ly8gb2xkSXRlbXNJZHNXaXRoU2VsZWN0ZWRDbGFzcyBpcyB1c2VkIGZvciBvcHRpbWl6YXRpb24gcHVycG9zZXMgb25seS4gSWYgdGhpcyBpbmZvIGlzIHN1cHBsaWVkIHRoZW4gd2Vcblx0XHRcdC8vIG9ubHkgaGF2ZSB0byBhZGQgLyByZW1vdmUgdGhlIFwic2VsZWN0ZWRcIiBjbGFzcyBmcm9tIHRob3NlIGl0ZW1zIHRoYXQgXCJzZWxlY3RlZFwiIHN0YXRlIGhhcyBjaGFuZ2VkLlxuXG5cdFx0XHR2YXIgaXRlbXNJZHNGcm9tV2hpY2hTZWxlY3RlZENsYXNzTmVlZHNUb0JlUmVtb3ZlZCA9IG9sZEl0ZW1zSWRzV2l0aFNlbGVjdGVkQ2xhc3M7XG5cdFx0XHRpdGVtc0lkc0Zyb21XaGljaFNlbGVjdGVkQ2xhc3NOZWVkc1RvQmVSZW1vdmVkID0gXy53aXRob3V0KCBpdGVtc0lkc0Zyb21XaGljaFNlbGVjdGVkQ2xhc3NOZWVkc1RvQmVSZW1vdmVkLCB0aGlzLnNlbGVjdGVkSXRlbXMgKTtcblxuXHRcdFx0Xy5lYWNoKCBpdGVtc0lkc0Zyb21XaGljaFNlbGVjdGVkQ2xhc3NOZWVkc1RvQmVSZW1vdmVkLCBmdW5jdGlvbiggdGhpc0l0ZW1JZCApIHtcblx0XHRcdFx0dGhpcy5fZ2V0Q29udGFpbmVyRWwoKS5maW5kKCBcIltkYXRhLW1vZGVsLWNpZD1cIiArIHRoaXNJdGVtSWQgKyBcIl1cIiApLnJlbW92ZUNsYXNzKCBcInNlbGVjdGVkXCIgKTtcblxuXHRcdFx0XHRpZiggdGhpcy5faXNSZW5kZXJlZEFzTGlzdCgpICkge1xuXHRcdFx0XHRcdHRoaXMuX2dldENvbnRhaW5lckVsKCkuZmluZCggXCJsaVtkYXRhLW1vZGVsLWNpZD1cIiArIHRoaXNJdGVtSWQgKyBcIl0gPiAqXCIgKS5yZW1vdmVDbGFzcyggXCJzZWxlY3RlZFwiICk7XG5cdFx0XHRcdH1cblx0XHRcdH0sIHRoaXMgKTtcblxuXHRcdFx0dmFyIGl0ZW1zSWRzRnJvbVdoaWNoU2VsZWN0ZWRDbGFzc05lZWRzVG9CZUFkZGVkID0gdGhpcy5zZWxlY3RlZEl0ZW1zO1xuXHRcdFx0aXRlbXNJZHNGcm9tV2hpY2hTZWxlY3RlZENsYXNzTmVlZHNUb0JlQWRkZWQgPSBfLndpdGhvdXQoIGl0ZW1zSWRzRnJvbVdoaWNoU2VsZWN0ZWRDbGFzc05lZWRzVG9CZUFkZGVkLCBvbGRJdGVtc0lkc1dpdGhTZWxlY3RlZENsYXNzICk7XG5cblx0XHRcdF8uZWFjaCggaXRlbXNJZHNGcm9tV2hpY2hTZWxlY3RlZENsYXNzTmVlZHNUb0JlQWRkZWQsIGZ1bmN0aW9uKCB0aGlzSXRlbUlkICkge1xuXHRcdFx0XHR0aGlzLl9nZXRDb250YWluZXJFbCgpLmZpbmQoIFwiW2RhdGEtbW9kZWwtY2lkPVwiICsgdGhpc0l0ZW1JZCArIFwiXVwiICkuYWRkQ2xhc3MoIFwic2VsZWN0ZWRcIiApO1xuXG5cdFx0XHRcdGlmKCB0aGlzLl9pc1JlbmRlcmVkQXNMaXN0KCkgKSB7XG5cdFx0XHRcdFx0dGhpcy5fZ2V0Q29udGFpbmVyRWwoKS5maW5kKCBcImxpW2RhdGEtbW9kZWwtY2lkPVwiICsgdGhpc0l0ZW1JZCArIFwiXSA+ICpcIiApLmFkZENsYXNzKCBcInNlbGVjdGVkXCIgKTtcblx0XHRcdFx0fVxuXHRcdFx0fSwgdGhpcyApO1xuXHRcdH0sXG5cblx0XHRfcmVvcmRlckNvbGxlY3Rpb25CYXNlZE9uSFRNTCA6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHR2YXIgX3RoaXMgPSB0aGlzO1xuXG5cdFx0XHR0aGlzLl9nZXRDb250YWluZXJFbCgpLmNoaWxkcmVuKCkuZWFjaCggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdHZhciB0aGlzTW9kZWxDaWQgPSAkKCB0aGlzICkuYXR0ciggXCJkYXRhLW1vZGVsLWNpZFwiICk7XG5cblx0XHRcdFx0aWYoIHRoaXNNb2RlbENpZCApXG5cdFx0XHRcdHtcblx0XHRcdFx0XHQvLyByZW1vdmUgdGhlIGN1cnJlbnQgbW9kZWwgYW5kIHRoZW4gYWRkIGl0IGJhY2sgKGF0IHRoZSBlbmQgb2YgdGhlIGNvbGxlY3Rpb24pLlxuXHRcdFx0XHRcdC8vIFdoZW4gd2UgYXJlIGRvbmUgbG9vcGluZyB0aHJvdWdoIGFsbCBtb2RlbHMsIHRoZXkgd2lsbCBiZSBpbiB0aGUgY29ycmVjdCBvcmRlci5cblx0XHRcdFx0XHR2YXIgdGhpc01vZGVsID0gX3RoaXMuY29sbGVjdGlvbi5nZXQoIHRoaXNNb2RlbENpZCApO1xuXHRcdFx0XHRcdGlmKCB0aGlzTW9kZWwgKVxuXHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdF90aGlzLmNvbGxlY3Rpb24ucmVtb3ZlKCB0aGlzTW9kZWwsIHsgc2lsZW50IDogdHJ1ZSB9ICk7XG5cdFx0XHRcdFx0XHRfdGhpcy5jb2xsZWN0aW9uLmFkZCggdGhpc01vZGVsLCB7IHNpbGVudCA6IHRydWUsIHNvcnQgOiAhIF90aGlzLmNvbGxlY3Rpb24uY29tcGFyYXRvciB9ICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9ICk7XG5cblx0XHRcdGlmKCB0aGlzLl9pc0JhY2tib25lQ291cmllckF2YWlsYWJsZSgpICkgdGhpcy5zcGF3biggXCJyZW9yZGVyXCIgKTtcblx0XHRcdGVsc2UgdGhpcy5jb2xsZWN0aW9uLnRyaWdnZXIoIFwicmVvcmRlclwiICk7XG5cblx0XHRcdGlmKCB0aGlzLmNvbGxlY3Rpb24uY29tcGFyYXRvciApIHRoaXMuY29sbGVjdGlvbi5zb3J0KCk7XG5cblx0XHR9LFxuXG5cdFx0X2dldE1vZGVsVmlld0NvbnN0cnVjdG9yIDogZnVuY3Rpb24oIHRoaXNNb2RlbCApIHtcblx0XHRcdHJldHVybiB0aGlzLm1vZGVsVmlldyB8fCBtRGVmYXVsdE1vZGVsVmlld0NvbnN0cnVjdG9yO1xuXHRcdH0sXG5cblx0XHRfZ2V0TW9kZWxWaWV3T3B0aW9ucyA6IGZ1bmN0aW9uKCB0aGlzTW9kZWwgKSB7XG5cdFx0XHR2YXIgbW9kZWxWaWV3T3B0aW9ucyA9IHRoaXMubW9kZWxWaWV3T3B0aW9ucztcblx0XHRcdGlmKCBfLmlzRnVuY3Rpb24oIG1vZGVsVmlld09wdGlvbnMgKSApIG1vZGVsVmlld09wdGlvbnMgPSBtb2RlbFZpZXdPcHRpb25zKCB0aGlzTW9kZWwgKTtcblxuXHRcdFx0cmV0dXJuIF8uZXh0ZW5kKCB7IG1vZGVsIDogdGhpc01vZGVsIH0sIG1vZGVsVmlld09wdGlvbnMgKTtcblx0XHR9LFxuXG5cdFx0X2NyZWF0ZU5ld01vZGVsVmlldyA6IGZ1bmN0aW9uKCBtb2RlbCwgbW9kZWxWaWV3T3B0aW9ucyApIHtcblx0XHRcdHZhciBtb2RlbFZpZXdDb25zdHJ1Y3RvciA9IHRoaXMuX2dldE1vZGVsVmlld0NvbnN0cnVjdG9yKCBtb2RlbCApO1xuXHRcdFx0aWYoIF8uaXNVbmRlZmluZWQoIG1vZGVsVmlld0NvbnN0cnVjdG9yICkgKSB0aHJvdyBcIkNvdWxkIG5vdCBmaW5kIG1vZGVsVmlldyBjb25zdHJ1Y3RvciBmb3IgbW9kZWxcIjtcblxuXHRcdFx0dmFyIG5ld01vZGVsVmlldyA9IG5ldyggbW9kZWxWaWV3Q29uc3RydWN0b3IgKSggbW9kZWxWaWV3T3B0aW9ucyApO1xuXHRcdFx0bmV3TW9kZWxWaWV3LmNvbGxlY3Rpb25MaXN0VmlldyA9IG5ld01vZGVsVmlldy5jb2xsZWN0aW9uVmlldyA9IHRoaXM7ICAvLyBjb2xsZWN0aW9uTGlzdFZpZXcgZm9yIGxlZ2FjeVxuXG5cdFx0XHRyZXR1cm4gbmV3TW9kZWxWaWV3O1xuXHRcdH0sXG5cblx0XHRfd3JhcE1vZGVsVmlldyA6IGZ1bmN0aW9uKCBtb2RlbFZpZXcgKSB7XG5cdFx0XHR2YXIgX3RoaXMgPSB0aGlzO1xuXG5cdFx0XHQvLyB3ZSB1c2UgaXRlbXMgY2xpZW50IGlkcyBhcyBvcHBvc2VkIHRvIHJlYWwgaWRzLCBzaW5jZSB3ZSBtYXkgbm90IGhhdmUgYSByZXByZXNlbnRhdGlvblxuXHRcdFx0Ly8gb2YgdGhlc2UgbW9kZWxzIG9uIHRoZSBzZXJ2ZXJcblx0XHRcdHZhciBtb2RlbFZpZXdXcmFwcGVyRWw7XG5cblx0XHRcdGlmKCB0aGlzLl9pc1JlbmRlcmVkQXNUYWJsZSgpICkge1xuXHRcdFx0XHQvLyBpZiB3ZSBhcmUgcmVuZGVyaW5nIHRoZSBjb2xsZWN0aW9uIGluIGEgdGFibGUsIHRoZSB0ZW1wbGF0ZSAkZWwgaXMgYSB0ciBzbyB3ZSBqdXN0IG5lZWQgdG8gc2V0IHRoZSBkYXRhLW1vZGVsLWNpZFxuXHRcdFx0XHRtb2RlbFZpZXdXcmFwcGVyRWwgPSBtb2RlbFZpZXcuJGVsO1xuXHRcdFx0XHRtb2RlbFZpZXcuJGVsLmF0dHIoIFwiZGF0YS1tb2RlbC1jaWRcIiwgbW9kZWxWaWV3Lm1vZGVsLmNpZCApO1xuXHRcdFx0fVxuXHRcdFx0ZWxzZSBpZiggdGhpcy5faXNSZW5kZXJlZEFzTGlzdCgpICkge1xuXHRcdFx0XHQvLyBpZiB3ZSBhcmUgcmVuZGVyaW5nIHRoZSBjb2xsZWN0aW9uIGluIGEgbGlzdCwgd2UgbmVlZCB3cmFwIGVhY2ggaXRlbSBpbiBhbiA8bGk+PC9saT4gKGlmIGl0cyBub3QgYWxyZWFkeSBhbiA8bGk+KVxuXHRcdFx0XHQvLyBhbmQgc2V0IHRoZSBkYXRhLW1vZGVsLWNpZFxuXHRcdFx0XHRpZiggbW9kZWxWaWV3LiRlbC5pcyggXCJsaVwiICkgKSB7XG5cdFx0XHRcdFx0bW9kZWxWaWV3V3JhcHBlckVsID0gbW9kZWxWaWV3LiRlbDtcblx0XHRcdFx0XHRtb2RlbFZpZXcuJGVsLmF0dHIoIFwiZGF0YS1tb2RlbC1jaWRcIiwgbW9kZWxWaWV3Lm1vZGVsLmNpZCApO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdG1vZGVsVmlld1dyYXBwZXJFbCA9IG1vZGVsVmlldy4kZWwud3JhcEFsbCggXCI8bGkgZGF0YS1tb2RlbC1jaWQ9J1wiICsgbW9kZWxWaWV3Lm1vZGVsLmNpZCArIFwiJz48L2xpPlwiICkucGFyZW50KCk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0aWYoIF8uaXNGdW5jdGlvbiggdGhpcy5zb3J0YWJsZU1vZGVsc0ZpbHRlciApIClcblx0XHRcdFx0aWYoICEgdGhpcy5zb3J0YWJsZU1vZGVsc0ZpbHRlci5jYWxsKCBfdGhpcywgbW9kZWxWaWV3Lm1vZGVsICkgKSB7XG5cdFx0XHRcdFx0bW9kZWxWaWV3V3JhcHBlckVsLmFkZENsYXNzKCBcIm5vdC1zb3J0YWJsZVwiICk7XG5cdFx0XHRcdFx0bW9kZWxWaWV3LiRlbC5hZGRDbGFzcyggXCJub3Qtc2VsZWN0YWJsZVwiICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0aWYoIF8uaXNGdW5jdGlvbiggdGhpcy5zZWxlY3RhYmxlTW9kZWxzRmlsdGVyICkgKVxuXHRcdFx0XHRpZiggISB0aGlzLnNlbGVjdGFibGVNb2RlbHNGaWx0ZXIuY2FsbCggX3RoaXMsIG1vZGVsVmlldy5tb2RlbCApICkge1xuXHRcdFx0XHRcdG1vZGVsVmlld1dyYXBwZXJFbC5hZGRDbGFzcyggXCJub3Qtc2VsZWN0YWJsZVwiICk7XG5cdFx0XHRcdFx0bW9kZWxWaWV3LiRlbC5hZGRDbGFzcyggXCJub3Qtc2VsZWN0YWJsZVwiICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIG1vZGVsVmlld1dyYXBwZXJFbDtcblx0XHR9LFxuXG5cdFx0X2NvbnZlcnRTdHJpbmdzVG9JbnRzIDogZnVuY3Rpb24oIHRoZUFycmF5ICkge1xuXHRcdFx0cmV0dXJuIF8ubWFwKCB0aGVBcnJheSwgZnVuY3Rpb24oIHRoaXNFbCApIHtcblx0XHRcdFx0aWYoICEgXy5pc1N0cmluZyggdGhpc0VsICkgKSByZXR1cm4gdGhpc0VsO1xuXHRcdFx0XHR2YXIgdGhpc0VsQXNOdW1iZXIgPSBwYXJzZUludCggdGhpc0VsLCAxMCApO1xuXHRcdFx0XHRyZXR1cm4oIHRoaXNFbEFzTnVtYmVyID09IHRoaXNFbCA/IHRoaXNFbEFzTnVtYmVyIDogdGhpc0VsICk7XG5cdFx0XHR9ICk7XG5cdFx0fSxcblxuXHRcdF9jb250YWluU2FtZUVsZW1lbnRzIDogZnVuY3Rpb24oIGFycmF5QSwgYXJyYXlCICkge1xuXHRcdFx0aWYoIGFycmF5QS5sZW5ndGggIT0gYXJyYXlCLmxlbmd0aCApIHJldHVybiBmYWxzZTtcblx0XHRcdHZhciBpbnRlcnNlY3Rpb25TaXplID0gXy5pbnRlcnNlY3Rpb24oIGFycmF5QSwgYXJyYXlCICkubGVuZ3RoO1xuXHRcdFx0cmV0dXJuIGludGVyc2VjdGlvblNpemUgPT0gYXJyYXlBLmxlbmd0aDsgLy8gYW5kIG11c3QgYWxzbyBlcXVhbCBhcnJheUIubGVuZ3RoLCBzaW5jZSBhcnJheUEubGVuZ3RoID09IGFycmF5Qi5sZW5ndGhcblx0XHR9LFxuXG5cdFx0X2lzUmVuZGVyZWRBc1RhYmxlIDogZnVuY3Rpb24oKSB7XG5cdFx0XHRyZXR1cm4gdGhpcy4kZWwucHJvcCggXCJ0YWdOYW1lXCIgKS50b0xvd2VyQ2FzZSgpID09PSBcInRhYmxlXCI7XG5cdFx0fSxcblxuXHRcdF9pc1JlbmRlcmVkQXNMaXN0IDogZnVuY3Rpb24oKSB7XG5cdFx0XHRyZXR1cm4gISB0aGlzLl9pc1JlbmRlcmVkQXNUYWJsZSgpO1xuXHRcdH0sXG5cblx0XHRfbW9kZWxWaWV3SGFzV3JhcHBlckxJIDogZnVuY3Rpb24oIG1vZGVsVmlldyApIHtcblx0XHRcdHJldHVybiB0aGlzLl9pc1JlbmRlcmVkQXNMaXN0KCkgJiYgISBtb2RlbFZpZXcuJGVsLmlzKCBcImxpXCIgKTtcblx0XHR9LFxuXG5cdFx0Ly8gUmV0dXJucyB0aGUgd3JhcHBlciBIVE1MIGVsZW1lbnQgZm9yIGVhY2ggdmlzaWJsZSBtb2RlbFZpZXcuXG5cdFx0Ly8gV2hlbiByZW5kZXJpbmcgaW4gYSB0YWJsZSBjb250ZXh0LCB0aGUgcmV0dXJuZWQgZWxlbWVudHMgYXJlIHRoZSAkZWwgb2YgZWFjaCBtb2RlbFZpZXcuXG5cdFx0Ly8gV2hlbiByZW5kZXJpbmcgaW4gYSBsaXN0IGNvbnRleHQsXG5cdFx0Ly8gICBJZiB0aGUgJGVsIG9mIHRoZSBtb2RlbFZpZXcgaXMgYW4gPGxpPiwgdGhlIHJldHVybmVkIGVsZW1lbnRzIGFyZSB0aGUgJGVsIG9mIGVhY2ggbW9kZWxWaWV3LlxuXHRcdC8vICAgT3RoZXJ3aXNlLCB0aGUgcmV0dXJuZWQgZWxlbWVudHMgYXJlIHRoZSA8bGk+J3MgdGhlIGNvbGxlY3Rpb25WaWV3IHdyYXBwZWQgYXJvdW5kIGVhY2ggbW9kZWxWaWV3ICRlbC5cblx0XHRfZ2V0VmlzaWJsZUl0ZW1FbHMgOiBmdW5jdGlvbigpIHtcblx0XHRcdHZhciBpdGVtRWxlbWVudHMgPSBbXTtcblx0XHRcdGl0ZW1FbGVtZW50cyA9IHRoaXMuX2dldENvbnRhaW5lckVsKCkuZmluZCggXCI+IFtkYXRhLW1vZGVsLWNpZF06bm90KC5ub3QtdmlzaWJsZSlcIiApO1xuXG5cdFx0XHRyZXR1cm4gaXRlbUVsZW1lbnRzO1xuXHRcdH0sXG5cblx0XHRfY2hhckNvZGVzIDoge1xuXHRcdFx0dXBBcnJvdyA6IDM4LFxuXHRcdFx0ZG93bkFycm93IDogNDBcblx0XHR9LFxuXG5cdFx0X2lzQmFja2JvbmVDb3VyaWVyQXZhaWxhYmxlIDogZnVuY3Rpb24oKSB7XG5cdFx0XHRyZXR1cm4gIV8uaXNVbmRlZmluZWQoIEJhY2tib25lLkNvdXJpZXIgKTtcblx0XHR9LFxuXG5cdFx0X3NldHVwU29ydGFibGUgOiBmdW5jdGlvbigpIHtcblx0XHRcdHZhciBzb3J0YWJsZU9wdGlvbnMgPSBfLmV4dGVuZCgge1xuXHRcdFx0XHRheGlzIDogXCJ5XCIsXG5cdFx0XHRcdGRpc3RhbmNlIDogMTAsXG5cdFx0XHRcdGZvcmNlUGxhY2Vob2xkZXJTaXplIDogdHJ1ZSxcblx0XHRcdFx0aXRlbXMgOiB0aGlzLl9pc1JlbmRlcmVkQXNUYWJsZSgpID8gXCI+IHRib2R5ID4gdHI6bm90KC5ub3Qtc29ydGFibGUpXCIgOiBcIj4gbGk6bm90KC5ub3Qtc29ydGFibGUpXCIsXG5cdFx0XHRcdHN0YXJ0IDogXy5iaW5kKCB0aGlzLl9zb3J0U3RhcnQsIHRoaXMgKSxcblx0XHRcdFx0Y2hhbmdlIDogXy5iaW5kKCB0aGlzLl9zb3J0Q2hhbmdlLCB0aGlzICksXG5cdFx0XHRcdHN0b3AgOiBfLmJpbmQoIHRoaXMuX3NvcnRTdG9wLCB0aGlzICksXG5cdFx0XHRcdHJlY2VpdmUgOiBfLmJpbmQoIHRoaXMuX3JlY2VpdmUsIHRoaXMgKSxcblx0XHRcdFx0b3ZlciA6IF8uYmluZCggdGhpcy5fb3ZlciwgdGhpcyApXG5cdFx0XHR9LCBfLnJlc3VsdCggdGhpcywgXCJzb3J0YWJsZU9wdGlvbnNcIiApICk7XG5cblx0XHRcdHRoaXMuJGVsID0gdGhpcy4kZWwuc29ydGFibGUoIHNvcnRhYmxlT3B0aW9ucyApO1xuXHRcdFx0Ly90aGlzLiRlbC5zb3J0YWJsZSggXCJlbmFibGVcIiApOyAvLyBpbiBjYXNlIGl0IHdhcyBkaXNhYmxlZCBwcmV2aW91c2x5XG5cdFx0fSxcblxuXHRcdF9zb3J0U3RhcnQgOiBmdW5jdGlvbiggZXZlbnQsIHVpICkge1xuXHRcdFx0dmFyIG1vZGVsQmVpbmdTb3J0ZWQgPSB0aGlzLmNvbGxlY3Rpb24uZ2V0KCB1aS5pdGVtLmF0dHIoIFwiZGF0YS1tb2RlbC1jaWRcIiApICk7XG5cdFx0XHRpZiggdGhpcy5faXNCYWNrYm9uZUNvdXJpZXJBdmFpbGFibGUoKSApXG5cdFx0XHRcdHRoaXMuc3Bhd24oIFwic29ydFN0YXJ0XCIsIHsgbW9kZWxCZWluZ1NvcnRlZCA6IG1vZGVsQmVpbmdTb3J0ZWQgfSApO1xuXHRcdFx0ZWxzZSB0aGlzLnRyaWdnZXIoIFwic29ydFN0YXJ0XCIsIG1vZGVsQmVpbmdTb3J0ZWQgKTtcblx0XHR9LFxuXG5cdFx0X3NvcnRDaGFuZ2UgOiBmdW5jdGlvbiggZXZlbnQsIHVpICkge1xuXHRcdFx0dmFyIG1vZGVsQmVpbmdTb3J0ZWQgPSB0aGlzLmNvbGxlY3Rpb24uZ2V0KCB1aS5pdGVtLmF0dHIoIFwiZGF0YS1tb2RlbC1jaWRcIiApICk7XG5cblx0XHRcdGlmKCB0aGlzLl9pc0JhY2tib25lQ291cmllckF2YWlsYWJsZSgpIClcblx0XHRcdFx0dGhpcy5zcGF3biggXCJzb3J0Q2hhbmdlXCIsIHsgbW9kZWxCZWluZ1NvcnRlZCA6IG1vZGVsQmVpbmdTb3J0ZWQgfSApO1xuXHRcdFx0ZWxzZSB0aGlzLnRyaWdnZXIoIFwic29ydENoYW5nZVwiLCBtb2RlbEJlaW5nU29ydGVkICk7XG5cdFx0fSxcblxuXHRcdF9zb3J0U3RvcCA6IGZ1bmN0aW9uKCBldmVudCwgdWkgKSB7XG5cdFx0XHR2YXIgbW9kZWxCZWluZ1NvcnRlZCA9IHRoaXMuY29sbGVjdGlvbi5nZXQoIHVpLml0ZW0uYXR0ciggXCJkYXRhLW1vZGVsLWNpZFwiICkgKTtcblx0XHRcdHZhciBtb2RlbFZpZXdDb250YWluZXJFbCA9IHRoaXMuX2dldENvbnRhaW5lckVsKCk7XG5cdFx0XHR2YXIgbmV3SW5kZXggPSBtb2RlbFZpZXdDb250YWluZXJFbC5jaGlsZHJlbigpLmluZGV4KCB1aS5pdGVtICk7XG5cblx0XHRcdGlmKCBuZXdJbmRleCA9PSAtMSAmJiBtb2RlbEJlaW5nU29ydGVkICkge1xuXHRcdFx0XHQvLyB0aGUgZWxlbWVudCB3YXMgcmVtb3ZlZCBmcm9tIHRoaXMgbGlzdC4gY2FuIGhhcHBlbiBpZiB0aGlzIHNvcnRhYmxlIGlzIGNvbm5lY3RlZFxuXHRcdFx0XHQvLyB0byBhbm90aGVyIHNvcnRhYmxlLCBhbmQgdGhlIGl0ZW0gd2FzIGRyb3BwZWQgaW50byB0aGUgb3RoZXIgc29ydGFibGUuXG5cdFx0XHRcdHRoaXMuY29sbGVjdGlvbi5yZW1vdmUoIG1vZGVsQmVpbmdTb3J0ZWQgKTtcblx0XHRcdH1cblxuXHRcdFx0aWYoICEgbW9kZWxCZWluZ1NvcnRlZCApIHJldHVybjsgLy8gc29tZXRoaW5nIGlzIHdhY2t5LiB3ZSBkb24ndCBtZXNzIHdpdGggdGhpcyBjYXNlLCBwcmVmZXJyaW5nIHRvIGd1YXJhbnRlZSB0aGF0IHdlIGNhbiBhbHdheXMgcHJvdmlkZSBhIHJlZmVyZW5jZSB0byB0aGUgbW9kZWxcblxuXHRcdFx0dGhpcy5fcmVvcmRlckNvbGxlY3Rpb25CYXNlZE9uSFRNTCgpO1xuXHRcdFx0dGhpcy51cGRhdGVEZXBlbmRlbnRDb250cm9scygpO1xuXG5cdFx0XHRpZiggdGhpcy5faXNCYWNrYm9uZUNvdXJpZXJBdmFpbGFibGUoKSApXG5cdFx0XHRcdHRoaXMuc3Bhd24oIFwic29ydFN0b3BcIiwgeyBtb2RlbEJlaW5nU29ydGVkIDogbW9kZWxCZWluZ1NvcnRlZCwgbmV3SW5kZXggOiBuZXdJbmRleCB9ICk7XG5cdFx0XHRlbHNlIHRoaXMudHJpZ2dlciggXCJzb3J0U3RvcFwiLCBtb2RlbEJlaW5nU29ydGVkLCBuZXdJbmRleCApO1xuXHRcdH0sXG5cblx0XHRfcmVjZWl2ZSA6IGZ1bmN0aW9uKCBldmVudCwgdWkgKSB7XG5cblx0XHRcdHZhciBzZW5kZXJMaXN0RWwgPSB1aS5zZW5kZXI7XG5cdFx0XHR2YXIgc2VuZGVyQ29sbGVjdGlvbkxpc3RWaWV3ID0gc2VuZGVyTGlzdEVsLmRhdGEoIFwidmlld1wiICk7XG5cdFx0XHRpZiggISBzZW5kZXJDb2xsZWN0aW9uTGlzdFZpZXcgfHwgISBzZW5kZXJDb2xsZWN0aW9uTGlzdFZpZXcuY29sbGVjdGlvbiApIHJldHVybjtcblxuXHRcdFx0dmFyIG5ld0luZGV4ID0gdGhpcy5fZ2V0Q29udGFpbmVyRWwoKS5jaGlsZHJlbigpLmluZGV4KCB1aS5pdGVtICk7XG5cdFx0XHR2YXIgbW9kZWxSZWNlaXZlZCA9IHNlbmRlckNvbGxlY3Rpb25MaXN0Vmlldy5jb2xsZWN0aW9uLmdldCggdWkuaXRlbS5hdHRyKCBcImRhdGEtbW9kZWwtY2lkXCIgKSApO1xuXHRcdFx0c2VuZGVyQ29sbGVjdGlvbkxpc3RWaWV3LmNvbGxlY3Rpb24ucmVtb3ZlKCBtb2RlbFJlY2VpdmVkICk7XG5cdFx0XHR0aGlzLmNvbGxlY3Rpb24uYWRkKCBtb2RlbFJlY2VpdmVkLCB7IGF0IDogbmV3SW5kZXggfSApO1xuXHRcdFx0bW9kZWxSZWNlaXZlZC5jb2xsZWN0aW9uID0gdGhpcy5jb2xsZWN0aW9uOyAvLyBvdGhlcndpc2Ugd2lsbCBub3QgZ2V0IHByb3Blcmx5IHNldCwgc2luY2UgbW9kZWxSZWNlaXZlZC5jb2xsZWN0aW9uIG1pZ2h0IGFscmVhZHkgaGF2ZSBhIHZhbHVlLlxuXHRcdFx0dGhpcy5zZXRTZWxlY3RlZE1vZGVsKCBtb2RlbFJlY2VpdmVkICk7XG5cdFx0fSxcblxuXHRcdF9vdmVyIDogZnVuY3Rpb24oIGV2ZW50LCB1aSApIHtcblx0XHRcdC8vIHdoZW4gYW4gaXRlbSBpcyBiZWluZyBkcmFnZ2VkIGludG8gdGhlIHNvcnRhYmxlLFxuXHRcdFx0Ly8gaGlkZSB0aGUgZW1wdHkgbGlzdCBjYXB0aW9uIGlmIGl0IGV4aXN0c1xuXHRcdFx0dGhpcy5fZ2V0Q29udGFpbmVyRWwoKS5maW5kKCBcIj4gdmFyLmVtcHR5LWxpc3QtY2FwdGlvblwiICkuaGlkZSgpO1xuXHRcdH0sXG5cblx0XHRfb25LZXlkb3duIDogZnVuY3Rpb24oIGV2ZW50ICkge1xuXHRcdFx0aWYoICEgdGhpcy5wcm9jZXNzS2V5RXZlbnRzICkgcmV0dXJuIHRydWU7XG5cblx0XHRcdHZhciB0cmFwID0gZmFsc2U7XG5cblx0XHRcdGlmKCB0aGlzLmdldFNlbGVjdGVkTW9kZWxzKCB7IGJ5IDogXCJvZmZzZXRcIiB9ICkubGVuZ3RoID09IDEgKVxuXHRcdFx0e1xuXHRcdFx0XHQvLyBuZWVkIHRvIHRyYXAgZG93biBhbmQgdXAgYXJyb3dzIG9yIGVsc2UgdGhlIGJyb3dzZXJcblx0XHRcdFx0Ly8gd2lsbCBlbmQgdXAgc2Nyb2xsaW5nIGEgYXV0b3Njcm9sbCBkaXYuXG5cblx0XHRcdFx0dmFyIGN1cnJlbnRPZmZzZXQgPSB0aGlzLmdldFNlbGVjdGVkTW9kZWwoIHsgYnkgOiBcIm9mZnNldFwiIH0gKTtcblx0XHRcdFx0aWYoIGV2ZW50LndoaWNoID09PSB0aGlzLl9jaGFyQ29kZXMudXBBcnJvdyAmJiBjdXJyZW50T2Zmc2V0ICE9PSAwIClcblx0XHRcdFx0e1xuXHRcdFx0XHRcdHRoaXMuc2V0U2VsZWN0ZWRNb2RlbCggY3VycmVudE9mZnNldCAtIDEsIHsgYnkgOiBcIm9mZnNldFwiIH0gKTtcblx0XHRcdFx0XHR0cmFwID0gdHJ1ZTtcblx0XHRcdFx0fVxuXHRcdFx0XHRlbHNlIGlmKCBldmVudC53aGljaCA9PT0gdGhpcy5fY2hhckNvZGVzLmRvd25BcnJvdyAmJiBjdXJyZW50T2Zmc2V0ICE9PSB0aGlzLmNvbGxlY3Rpb24ubGVuZ3RoIC0gMSApXG5cdFx0XHRcdHtcblx0XHRcdFx0XHR0aGlzLnNldFNlbGVjdGVkTW9kZWwoIGN1cnJlbnRPZmZzZXQgKyAxLCB7IGJ5IDogXCJvZmZzZXRcIiB9ICk7XG5cdFx0XHRcdFx0dHJhcCA9IHRydWU7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuICEgdHJhcDtcblx0XHR9LFxuXG5cdFx0X2xpc3RJdGVtX29uTW91c2Vkb3duIDogZnVuY3Rpb24oIHRoZUV2ZW50ICkge1xuXHRcdFx0dmFyIGNsaWNrZWRJdGVtSWQgPSB0aGlzLl9nZXRDbGlja2VkSXRlbUlkKCB0aGVFdmVudCApO1xuXG5cdFx0XHRpZiggY2xpY2tlZEl0ZW1JZCApIHtcblx0XHRcdFx0dmFyIGNsaWNrZWRNb2RlbCA9IHRoaXMuY29sbGVjdGlvbi5nZXQoIGNsaWNrZWRJdGVtSWQgKTtcblx0XHRcdFx0aWYoIHRoaXMuX2lzQmFja2JvbmVDb3VyaWVyQXZhaWxhYmxlKCkgKSB7XG5cdFx0XHRcdFx0dmFyIGRhdGEgPSB7XG5cdFx0XHRcdFx0XHRjbGlja2VkTW9kZWwgOiBjbGlja2VkTW9kZWwsXG5cdFx0XHRcdFx0XHRtZXRhS2V5UHJlc3NlZCA6IHRoZUV2ZW50LmN0cmxLZXkgfHwgdGhlRXZlbnQubWV0YUtleVxuXHRcdFx0XHRcdH07XG5cblx0XHRcdFx0XHRfLmVhY2goIFsgJ3ByZXZlbnREZWZhdWx0JywgJ3N0b3BQcm9wYWdhdGlvbicsICdzdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24nIF0sIGZ1bmN0aW9uKCB0aGlzTWV0aG9kICkge1xuXHRcdFx0XHRcdFx0ZGF0YVsgdGhpc01ldGhvZCBdID0gZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHRcdHRoZUV2ZW50WyB0aGlzTWV0aG9kIF0oKTtcblx0XHRcdFx0XHRcdH07XG5cdFx0XHRcdFx0fSApO1xuXG5cdFx0XHRcdFx0dGhpcy5zcGF3biggXCJjbGlja1wiLCBkYXRhICk7XG5cdFx0XHRcdH1cblx0XHRcdFx0ZWxzZSB0aGlzLnRyaWdnZXIoIFwiY2xpY2tcIiwgY2xpY2tlZE1vZGVsICk7XG5cdFx0XHR9XG5cblx0XHRcdGlmKCAhIHRoaXMuc2VsZWN0YWJsZSB8fCAhIHRoaXMuY2xpY2tUb1NlbGVjdCApIHJldHVybjtcblxuXHRcdFx0aWYoIGNsaWNrZWRJdGVtSWQgKVxuXHRcdFx0e1xuXHRcdFx0XHQvLyBFeGl0IGlmIGFuIHVuc2VsZWN0YWJsZSBpdGVtIHdhcyBjbGlja2VkXG5cdFx0XHRcdGlmKCBfLmlzRnVuY3Rpb24oIHRoaXMuc2VsZWN0YWJsZU1vZGVsc0ZpbHRlciApICYmXG5cdFx0XHRcdFx0ISB0aGlzLnNlbGVjdGFibGVNb2RlbHNGaWx0ZXIuY2FsbCggdGhpcywgdGhpcy5jb2xsZWN0aW9uLmdldCggY2xpY2tlZEl0ZW1JZCApICkgKVxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gYSBzZWxlY3RhYmxlIGxpc3QgaXRlbSB3YXMgY2xpY2tlZFxuXHRcdFx0XHRpZiggdGhpcy5zZWxlY3RNdWx0aXBsZSAmJiB0aGVFdmVudC5zaGlmdEtleSApXG5cdFx0XHRcdHtcblx0XHRcdFx0XHR2YXIgZmlyc3RTZWxlY3RlZEl0ZW1JbmRleCA9IC0xO1xuXG5cdFx0XHRcdFx0aWYoIHRoaXMuc2VsZWN0ZWRJdGVtcy5sZW5ndGggPiAwIClcblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHR0aGlzLmNvbGxlY3Rpb24uZmluZCggZnVuY3Rpb24oIHRoaXNJdGVtTW9kZWwgKSB7XG5cdFx0XHRcdFx0XHRcdGZpcnN0U2VsZWN0ZWRJdGVtSW5kZXgrKztcblxuXHRcdFx0XHRcdFx0XHQvLyBleGl0IHdoZW4gd2UgZmluZCBvdXIgZmlyc3Qgc2VsZWN0ZWQgZWxlbWVudFxuXHRcdFx0XHRcdFx0XHRyZXR1cm4gXy5jb250YWlucyggdGhpcy5zZWxlY3RlZEl0ZW1zLCB0aGlzSXRlbU1vZGVsLmNpZCApO1xuXHRcdFx0XHRcdFx0fSwgdGhpcyApO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdHZhciBjbGlja2VkSXRlbUluZGV4ID0gLTE7XG5cdFx0XHRcdFx0dGhpcy5jb2xsZWN0aW9uLmZpbmQoIGZ1bmN0aW9uKCB0aGlzSXRlbU1vZGVsICkge1xuXHRcdFx0XHRcdFx0Y2xpY2tlZEl0ZW1JbmRleCsrO1xuXG5cdFx0XHRcdFx0XHQvLyBleGl0IHdoZW4gd2UgZmluZCB0aGUgY2xpY2tlZCBlbGVtZW50XG5cdFx0XHRcdFx0XHRyZXR1cm4gdGhpc0l0ZW1Nb2RlbC5jaWQgPT0gY2xpY2tlZEl0ZW1JZDtcblx0XHRcdFx0XHR9LCB0aGlzICk7XG5cblx0XHRcdFx0XHR2YXIgc2hpZnRLZXlSb290U2VsZWN0ZWRJdGVtSW5kZXggPSBmaXJzdFNlbGVjdGVkSXRlbUluZGV4ID09IC0xID8gY2xpY2tlZEl0ZW1JbmRleCA6IGZpcnN0U2VsZWN0ZWRJdGVtSW5kZXg7XG5cdFx0XHRcdFx0dmFyIG1pblNlbGVjdGVkSXRlbUluZGV4ID0gTWF0aC5taW4oIGNsaWNrZWRJdGVtSW5kZXgsIHNoaWZ0S2V5Um9vdFNlbGVjdGVkSXRlbUluZGV4ICk7XG5cdFx0XHRcdFx0dmFyIG1heFNlbGVjdGVkSXRlbUluZGV4ID0gTWF0aC5tYXgoIGNsaWNrZWRJdGVtSW5kZXgsIHNoaWZ0S2V5Um9vdFNlbGVjdGVkSXRlbUluZGV4ICk7XG5cblx0XHRcdFx0XHR2YXIgbmV3U2VsZWN0ZWRJdGVtcyA9IFtdO1xuXHRcdFx0XHRcdGZvciggdmFyIHRoaXNJbmRleCA9IG1pblNlbGVjdGVkSXRlbUluZGV4OyB0aGlzSW5kZXggPD0gbWF4U2VsZWN0ZWRJdGVtSW5kZXg7IHRoaXNJbmRleCArKyApXG5cdFx0XHRcdFx0XHRuZXdTZWxlY3RlZEl0ZW1zLnB1c2goIHRoaXMuY29sbGVjdGlvbi5hdCggdGhpc0luZGV4ICkuY2lkICk7XG5cdFx0XHRcdFx0dGhpcy5zZXRTZWxlY3RlZE1vZGVscyggbmV3U2VsZWN0ZWRJdGVtcywgeyBieSA6IFwiY2lkXCIgfSApO1xuXG5cdFx0XHRcdFx0Ly8gc2hpZnQgY2xpY2tpbmcgd2lsbCB1c3VhbGx5IGhpZ2hsaWdodCBzZWxlY3RhYmxlIHRleHQsIHdoaWNoIHdlIGRvIG5vdCB3YW50LlxuXHRcdFx0XHRcdC8vIHRoaXMgaXMgYSBjcm9zcyBicm93c2VyIChob3BlZnVsbHkpIHNuaXBwZXQgdGhhdCBkZXNlbGVjdHMgYWxsIHRleHQgc2VsZWN0aW9uLlxuXHRcdFx0XHRcdGlmKCBkb2N1bWVudC5zZWxlY3Rpb24gJiYgZG9jdW1lbnQuc2VsZWN0aW9uLmVtcHR5IClcblx0XHRcdFx0XHRcdGRvY3VtZW50LnNlbGVjdGlvbi5lbXB0eSgpO1xuXHRcdFx0XHRcdGVsc2UgaWYod2luZG93LmdldFNlbGVjdGlvbikge1xuXHRcdFx0XHRcdFx0dmFyIHNlbCA9IHdpbmRvdy5nZXRTZWxlY3Rpb24oKTtcblx0XHRcdFx0XHRcdGlmKCBzZWwgJiYgc2VsLnJlbW92ZUFsbFJhbmdlcyApXG5cdFx0XHRcdFx0XHRcdHNlbC5yZW1vdmVBbGxSYW5nZXMoKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdFx0ZWxzZSBpZiggKCB0aGlzLnNlbGVjdE11bHRpcGxlIHx8IF8uY29udGFpbnMoIHRoaXMuc2VsZWN0ZWRJdGVtcywgY2xpY2tlZEl0ZW1JZCApICkgJiYgKCB0aGlzLmNsaWNrVG9Ub2dnbGUgfHwgdGhlRXZlbnQubWV0YUtleSB8fCB0aGVFdmVudC5jdHJsS2V5ICkgKVxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0aWYoIF8uY29udGFpbnMoIHRoaXMuc2VsZWN0ZWRJdGVtcywgY2xpY2tlZEl0ZW1JZCApIClcblx0XHRcdFx0XHRcdHRoaXMuc2V0U2VsZWN0ZWRNb2RlbHMoIF8ud2l0aG91dCggdGhpcy5zZWxlY3RlZEl0ZW1zLCBjbGlja2VkSXRlbUlkICksIHsgYnkgOiBcImNpZFwiIH0gKTtcblx0XHRcdFx0XHRlbHNlIHRoaXMuc2V0U2VsZWN0ZWRNb2RlbHMoIF8udW5pb24oIHRoaXMuc2VsZWN0ZWRJdGVtcywgW2NsaWNrZWRJdGVtSWRdICksIHsgYnkgOiBcImNpZFwiIH0gKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRlbHNlXG5cdFx0XHRcdFx0dGhpcy5zZXRTZWxlY3RlZE1vZGVscyggWyBjbGlja2VkSXRlbUlkIF0sIHsgYnkgOiBcImNpZFwiIH0gKTtcblx0XHRcdH1cblx0XHRcdGVsc2Vcblx0XHRcdFx0Ly8gdGhlIGJsYW5rIGFyZWEgb2YgdGhlIGxpc3Qgd2FzIGNsaWNrZWRcblx0XHRcdFx0dGhpcy5zZXRTZWxlY3RlZE1vZGVscyggW10gKTtcblxuXHRcdH0sXG5cblx0XHRfbGlzdEl0ZW1fb25Eb3VibGVDbGljayA6IGZ1bmN0aW9uKCB0aGVFdmVudCApIHtcblxuXHRcdFx0dmFyIGNsaWNrZWRJdGVtSWQgPSB0aGlzLl9nZXRDbGlja2VkSXRlbUlkKCB0aGVFdmVudCApO1xuXG5cdFx0XHRpZiggY2xpY2tlZEl0ZW1JZCApXG5cdFx0XHR7XG5cdFx0XHRcdHZhciBjbGlja2VkTW9kZWwgPSB0aGlzLmNvbGxlY3Rpb24uZ2V0KCBjbGlja2VkSXRlbUlkICk7XG5cblx0XHRcdFx0aWYoIHRoaXMuX2lzQmFja2JvbmVDb3VyaWVyQXZhaWxhYmxlKCkgKVxuXHRcdFx0XHRcdHRoaXMuc3Bhd24oIFwiZG91YmxlQ2xpY2tcIiwgeyBjbGlja2VkTW9kZWwgOiBjbGlja2VkTW9kZWwsIG1ldGFLZXlQcmVzc2VkIDogdGhlRXZlbnQuY3RybEtleSB8fCB0aGVFdmVudC5tZXRhS2V5IH0gKTtcblx0XHRcdFx0ZWxzZSB0aGlzLnRyaWdnZXIoIFwiZG91YmxlQ2xpY2tcIiwgY2xpY2tlZE1vZGVsICk7XG5cdFx0XHR9XG5cdFx0fSxcblxuXHRcdF9saXN0QmFja2dyb3VuZF9vbkNsaWNrIDogZnVuY3Rpb24oIHRoZUV2ZW50ICkge1xuXHRcdFx0aWYoICEgdGhpcy5zZWxlY3RhYmxlIHx8ICEgdGhpcy5jbGlja1RvU2VsZWN0ICkgcmV0dXJuO1xuXHRcdFx0aWYoICEgJCggdGhlRXZlbnQudGFyZ2V0ICkuaXMoIFwiLmNvbGxlY3Rpb24tdmlld1wiICkgKSByZXR1cm47XG5cblx0XHRcdHRoaXMuc2V0U2VsZWN0ZWRNb2RlbHMoIFtdICk7XG5cdFx0fVxuXG5cdH0sIHtcblx0XHRzZXREZWZhdWx0TW9kZWxWaWV3Q29uc3RydWN0b3IgOiBmdW5jdGlvbiggdGhlQ29uc3RydWN0b3IgKSB7XG5cdFx0XHRtRGVmYXVsdE1vZGVsVmlld0NvbnN0cnVjdG9yID0gdGhlQ29uc3RydWN0b3I7XG5cdFx0fVxuXHR9KTtcblxuXHQvKlxuXHQqIEJhY2tib25lLlZpZXdPcHRpb25zLCB2MC4yLjRcblx0KiBDb3B5cmlnaHQgKGMpMjAxNCBSb3R1bmRhIFNvZnR3YXJlLCBMTEMuXG5cdCogRGlzdHJpYnV0ZWQgdW5kZXIgTUlUIGxpY2Vuc2Vcblx0KiBodHRwOi8vZ2l0aHViLmNvbS9yb3R1bmRhc29mdHdhcmUvYmFja2JvbmUudmlld09wdGlvbnNcblx0Ki9cblxuXHRCYWNrYm9uZS5WaWV3T3B0aW9ucyA9IHt9O1xuXG5cdEJhY2tib25lLlZpZXdPcHRpb25zLmFkZCA9IGZ1bmN0aW9uKCB2aWV3LCBvcHRpb25zRGVjbGFyYXRpb25zUHJvcGVydHkgKSB7XG5cdFx0aWYoIF8uaXNVbmRlZmluZWQoIG9wdGlvbnNEZWNsYXJhdGlvbnNQcm9wZXJ0eSApICkgb3B0aW9uc0RlY2xhcmF0aW9uc1Byb3BlcnR5ID0gXCJvcHRpb25zXCI7XG5cblx0XHQvLyAqKioqKioqKioqKioqKioqKiogUHVibGljIG1ldGhvZHMgYWRkZWQgdG8gdmlldyAqKioqKioqKioqKioqKioqKipcblxuXHRcdHZpZXcuc2V0T3B0aW9ucyA9IGZ1bmN0aW9uKCBvcHRpb25zICkge1xuXHRcdFx0dmFyIF90aGlzID0gdGhpcztcblx0XHRcdHZhciBvcHRpb25zVGhhdFdlcmVDaGFuZ2VkID0ge307XG5cdFx0XHR2YXIgb3B0aW9uc1RoYXRXZXJlQ2hhbmdlZFByZXZpb3VzVmFsdWVzID0ge307XG5cblx0XHRcdHZhciBvcHRpb25EZWNsYXJhdGlvbnMgPSBfLnJlc3VsdCggdGhpcywgb3B0aW9uc0RlY2xhcmF0aW9uc1Byb3BlcnR5ICk7XG5cblx0XHRcdGlmKCAhIF8uaXNVbmRlZmluZWQoIG9wdGlvbkRlY2xhcmF0aW9ucyApICkge1xuXHRcdFx0XHR2YXIgbm9ybWFsaXplZE9wdGlvbkRlY2xhcmF0aW9ucyA9IF9ub3JtYWxpemVPcHRpb25EZWNsYXJhdGlvbnMoIG9wdGlvbkRlY2xhcmF0aW9ucyApO1xuXG5cdFx0XHRcdF8uZWFjaCggbm9ybWFsaXplZE9wdGlvbkRlY2xhcmF0aW9ucywgZnVuY3Rpb24oIHRoaXNPcHRpb25Qcm9wZXJ0aWVzLCB0aGlzT3B0aW9uTmFtZSApIHtcblx0XHRcdFx0XHR2YXIgdGhpc09wdGlvblJlcXVpcmVkID0gdGhpc09wdGlvblByb3BlcnRpZXMucmVxdWlyZWQ7XG5cdFx0XHRcdFx0dmFyIHRoaXNPcHRpb25EZWZhdWx0VmFsdWUgPSB0aGlzT3B0aW9uUHJvcGVydGllcy5kZWZhdWx0VmFsdWU7XG5cblx0XHRcdFx0XHRpZiggdGhpc09wdGlvblJlcXVpcmVkICkge1xuXHRcdFx0XHRcdFx0Ly8gbm90ZSB3ZSBkbyBub3QgdGhyb3cgYW4gZXJyb3IgaWYgYSByZXF1aXJlZCBvcHRpb24gaXMgbm90IHN1cHBsaWVkLCBidXQgaXQgaXNcblx0XHRcdFx0XHRcdC8vIGZvdW5kIG9uIHRoZSBvYmplY3QgaXRzZWxmIChkdWUgdG8gYSBwcmlvciBjYWxsIG9mIHZpZXcuc2V0T3B0aW9ucywgbW9zdCBsaWtlbHkpXG5cblx0XHRcdFx0XHRcdGlmKCAoICEgb3B0aW9ucyB8fCAhIF8uY29udGFpbnMoIF8ua2V5cyggb3B0aW9ucyApLCB0aGlzT3B0aW9uTmFtZSApICkgJiYgXy5pc1VuZGVmaW5lZCggX3RoaXNbIHRoaXNPcHRpb25OYW1lIF0gKSApXG5cdFx0XHRcdFx0XHRcdHRocm93IG5ldyBFcnJvciggXCJSZXF1aXJlZCBvcHRpb24gXFxcIlwiICsgdGhpc09wdGlvbk5hbWUgKyBcIlxcXCIgd2FzIG5vdCBzdXBwbGllZC5cIiApO1xuXG5cdFx0XHRcdFx0XHRpZiggb3B0aW9ucyAmJiBfLmNvbnRhaW5zKCBfLmtleXMoIG9wdGlvbnMgKSwgdGhpc09wdGlvbk5hbWUgKSAmJiBfLmlzVW5kZWZpbmVkKCBvcHRpb25zWyB0aGlzT3B0aW9uTmFtZSBdICkgKVxuXHRcdFx0XHRcdFx0XHR0aHJvdyBuZXcgRXJyb3IoIFwiUmVxdWlyZWQgb3B0aW9uIFxcXCJcIiArIHRoaXNPcHRpb25OYW1lICsgXCJcXFwiIGNhbiBub3QgYmUgc2V0IHRvIHVuZGVmaW5lZC5cIiApO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdC8vIGF0dGFjaCB0aGUgc3VwcGxpZWQgdmFsdWUgb2YgdGhpcyBvcHRpb24sIG9yIHRoZSBhcHByb3ByaWF0ZSBkZWZhdWx0IHZhbHVlLCB0byB0aGUgdmlldyBvYmplY3Rcblx0XHRcdFx0XHRpZiggb3B0aW9ucyAmJiB0aGlzT3B0aW9uTmFtZSBpbiBvcHRpb25zICYmICEgXy5pc1VuZGVmaW5lZCggb3B0aW9uc1sgdGhpc09wdGlvbk5hbWUgXSApICkge1xuXHRcdFx0XHRcdFx0dmFyIG9sZFZhbHVlID0gX3RoaXNbIHRoaXNPcHRpb25OYW1lIF07XG5cdFx0XHRcdFx0XHR2YXIgbmV3VmFsdWUgPSBvcHRpb25zWyB0aGlzT3B0aW9uTmFtZSBdO1xuXHRcdFx0XHRcdFx0Ly8gaWYgdGhpcyBvcHRpb24gYWxyZWFkeSBleGlzdHMgb24gdGhlIHZpZXcsIGFuZCB0aGUgbmV3IHZhbHVlIGlzIGRpZmZlcmVudCxcblx0XHRcdFx0XHRcdC8vIG1ha2UgYSBub3RlIHRoYXQgd2Ugd2lsbCBiZSBjaGFuZ2luZyBpdFxuXHRcdFx0XHRcdFx0aWYoICEgXy5pc1VuZGVmaW5lZCggb2xkVmFsdWUgKSAmJiBvbGRWYWx1ZSAhPT0gbmV3VmFsdWUgKSB7XG5cdFx0XHRcdFx0XHRcdG9wdGlvbnNUaGF0V2VyZUNoYW5nZWRQcmV2aW91c1ZhbHVlc1sgdGhpc09wdGlvbk5hbWUgXSA9IG9sZFZhbHVlO1xuXHRcdFx0XHRcdFx0XHRvcHRpb25zVGhhdFdlcmVDaGFuZ2VkWyB0aGlzT3B0aW9uTmFtZSBdID0gbmV3VmFsdWU7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRfdGhpc1sgdGhpc09wdGlvbk5hbWUgXSA9IG5ld1ZhbHVlO1xuXHRcdFx0XHRcdFx0Ly8gbm90ZSB3ZSBkbyBOT1QgZGVsZXRlIHRoZSBvcHRpb24gb2ZmIHRoZSBvcHRpb25zIG9iamVjdCBoZXJlIHNvIHRoYXRcblx0XHRcdFx0XHRcdC8vIG11bHRpcGxlIHZpZXdzIGNhbiBiZSBwYXNzZWQgdGhlIHNhbWUgb3B0aW9ucyBvYmplY3Qgd2l0aG91dCBpc3N1ZS5cblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0ZWxzZSBpZiggXy5pc1VuZGVmaW5lZCggX3RoaXNbIHRoaXNPcHRpb25OYW1lIF0gKSApIHtcblx0XHRcdFx0XHRcdC8vIG5vdGUgZGVmYXVsdHMgZG8gbm90IHdyaXRlIG92ZXIgYW55IGV4aXN0aW5nIHByb3BlcnRpZXMgb24gdGhlIHZpZXcgaXRzZWxmLlxuXHRcdFx0XHRcdFx0X3RoaXNbIHRoaXNPcHRpb25OYW1lIF0gPSB0aGlzT3B0aW9uRGVmYXVsdFZhbHVlO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSApO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiggXy5rZXlzKCBvcHRpb25zVGhhdFdlcmVDaGFuZ2VkICkubGVuZ3RoID4gMCApIHtcblx0XHRcdFx0aWYoIF8uaXNGdW5jdGlvbiggX3RoaXMub25PcHRpb25zQ2hhbmdlZCApIClcblx0XHRcdFx0XHRfdGhpcy5vbk9wdGlvbnNDaGFuZ2VkKCBvcHRpb25zVGhhdFdlcmVDaGFuZ2VkLCBvcHRpb25zVGhhdFdlcmVDaGFuZ2VkUHJldmlvdXNWYWx1ZXMgKTtcblx0XHRcdFx0ZWxzZSBpZiggXy5pc0Z1bmN0aW9uKCBfdGhpcy5fb25PcHRpb25zQ2hhbmdlZCApIClcblx0XHRcdFx0XHRfdGhpcy5fb25PcHRpb25zQ2hhbmdlZCggb3B0aW9uc1RoYXRXZXJlQ2hhbmdlZCwgb3B0aW9uc1RoYXRXZXJlQ2hhbmdlZFByZXZpb3VzVmFsdWVzICk7XG5cdFx0XHR9XG5cdFx0fTtcblxuXHRcdHZpZXcuZ2V0T3B0aW9ucyA9IGZ1bmN0aW9uKCkge1xuXHRcdFx0dmFyIG9wdGlvbkRlY2xhcmF0aW9ucyA9IF8ucmVzdWx0KCB0aGlzLCBvcHRpb25zRGVjbGFyYXRpb25zUHJvcGVydHkgKTtcblx0XHRcdGlmKCBfLmlzVW5kZWZpbmVkKCBvcHRpb25EZWNsYXJhdGlvbnMgKSApIHJldHVybiB7fTtcblxuXHRcdFx0dmFyIG5vcm1hbGl6ZWRPcHRpb25EZWNsYXJhdGlvbnMgPSBfbm9ybWFsaXplT3B0aW9uRGVjbGFyYXRpb25zKCBvcHRpb25EZWNsYXJhdGlvbnMgKTtcblx0XHRcdHZhciBvcHRpb25zTmFtZXMgPSBfLmtleXMoIG5vcm1hbGl6ZWRPcHRpb25EZWNsYXJhdGlvbnMgKTtcblxuXHRcdFx0cmV0dXJuIF8ucGljayggdGhpcywgb3B0aW9uc05hbWVzICk7XG5cdFx0fTtcblx0fTtcblxuXHQvLyAqKioqKioqKioqKioqKioqKiogUHJpdmF0ZSBVdGlsaXR5IEZ1bmN0aW9ucyAqKioqKioqKioqKioqKioqKipcblxuXHRmdW5jdGlvbiBfbm9ybWFsaXplT3B0aW9uRGVjbGFyYXRpb25zKCBvcHRpb25EZWNsYXJhdGlvbnMgKSB7XG5cdFx0Ly8gY29udmVydCBvdXIgc2hvcnQtaGFuZCBvcHRpb24gc3ludGF4ICh3aXRoIGV4Y2xhbWF0aW9uIG1hcmtzLCBldGMuKVxuXHRcdC8vIHRvIGEgc2ltcGxlIGFycmF5IG9mIHN0YW5kYXJkIG9wdGlvbiBkZWNsYXJhdGlvbiBvYmplY3RzLlxuXG5cdFx0dmFyIG5vcm1hbGl6ZWRPcHRpb25EZWNsYXJhdGlvbnMgPSB7fTtcblxuXHRcdGlmKCAhIF8uaXNBcnJheSggb3B0aW9uRGVjbGFyYXRpb25zICkgKSB0aHJvdyBuZXcgRXJyb3IoIFwiT3B0aW9uIGRlY2xhcmF0aW9ucyBtdXN0IGJlIGFuIGFycmF5LlwiICk7XG5cblx0XHRfLmVhY2goIG9wdGlvbkRlY2xhcmF0aW9ucywgZnVuY3Rpb24oIHRoaXNPcHRpb25EZWNsYXJhdGlvbiApIHtcblx0XHRcdHZhciB0aGlzT3B0aW9uTmFtZSwgdGhpc09wdGlvblJlcXVpcmVkLCB0aGlzT3B0aW9uRGVmYXVsdFZhbHVlO1xuXG5cdFx0XHR0aGlzT3B0aW9uUmVxdWlyZWQgPSBmYWxzZTtcblx0XHRcdHRoaXNPcHRpb25EZWZhdWx0VmFsdWUgPSB1bmRlZmluZWQ7XG5cblx0XHRcdGlmKCBfLmlzU3RyaW5nKCB0aGlzT3B0aW9uRGVjbGFyYXRpb24gKSApXG5cdFx0XHRcdHRoaXNPcHRpb25OYW1lID0gdGhpc09wdGlvbkRlY2xhcmF0aW9uO1xuXHRcdFx0ZWxzZSBpZiggXy5pc09iamVjdCggdGhpc09wdGlvbkRlY2xhcmF0aW9uICkgKSB7XG5cdFx0XHRcdHRoaXNPcHRpb25OYW1lID0gXy5maXJzdCggXy5rZXlzKCB0aGlzT3B0aW9uRGVjbGFyYXRpb24gKSApO1xuXHRcdFx0XHRpZiggXy5pc0Z1bmN0aW9uKCB0aGlzT3B0aW9uRGVjbGFyYXRpb25bIHRoaXNPcHRpb25OYW1lIF0gKSApXG5cdFx0XHRcdFx0dGhpc09wdGlvbkRlZmF1bHRWYWx1ZSA9IHRoaXNPcHRpb25EZWNsYXJhdGlvblsgdGhpc09wdGlvbk5hbWUgXTtcblx0XHRcdFx0ZWxzZVxuXHRcdFx0XHRcdHRoaXNPcHRpb25EZWZhdWx0VmFsdWUgPSBfLmNsb25lKCB0aGlzT3B0aW9uRGVjbGFyYXRpb25bIHRoaXNPcHRpb25OYW1lIF0gKTtcblx0XHRcdH1cblx0XHRcdGVsc2UgdGhyb3cgbmV3IEVycm9yKCBcIkVhY2ggZWxlbWVudCBpbiB0aGUgb3B0aW9uIGRlY2xhcmF0aW9ucyBhcnJheSBtdXN0IGJlIGVpdGhlciBhIHN0cmluZyBvciBhbiBvYmplY3QuXCIgKTtcblxuXHRcdFx0aWYoIHRoaXNPcHRpb25OYW1lWyB0aGlzT3B0aW9uTmFtZS5sZW5ndGggLSAxIF0gPT09IFwiIVwiICkge1xuXHRcdFx0XHR0aGlzT3B0aW9uUmVxdWlyZWQgPSB0cnVlO1xuXHRcdFx0XHR0aGlzT3B0aW9uTmFtZSA9IHRoaXNPcHRpb25OYW1lLnNsaWNlKCAwLCB0aGlzT3B0aW9uTmFtZS5sZW5ndGggLSAxICk7XG5cdFx0XHR9XG5cblx0XHRcdG5vcm1hbGl6ZWRPcHRpb25EZWNsYXJhdGlvbnNbIHRoaXNPcHRpb25OYW1lIF0gPSBub3JtYWxpemVkT3B0aW9uRGVjbGFyYXRpb25zWyB0aGlzT3B0aW9uTmFtZSBdIHx8IHt9O1xuXHRcdFx0bm9ybWFsaXplZE9wdGlvbkRlY2xhcmF0aW9uc1sgdGhpc09wdGlvbk5hbWUgXS5yZXF1aXJlZCA9IHRoaXNPcHRpb25SZXF1aXJlZDtcblx0XHRcdGlmKCAhIF8uaXNVbmRlZmluZWQoIHRoaXNPcHRpb25EZWZhdWx0VmFsdWUgKSApIG5vcm1hbGl6ZWRPcHRpb25EZWNsYXJhdGlvbnNbIHRoaXNPcHRpb25OYW1lIF0uZGVmYXVsdFZhbHVlID0gdGhpc09wdGlvbkRlZmF1bHRWYWx1ZTtcblx0XHR9ICk7XG5cblx0XHRyZXR1cm4gbm9ybWFsaXplZE9wdGlvbkRlY2xhcmF0aW9ucztcblx0fVxuXG5cblx0Ly8gQmFja2JvbmUuQmFieVNpdHRlclxuXHQvLyAtLS0tLS0tLS0tLS0tLS0tLS0tXG5cdC8vIHYwLjAuNlxuXHQvL1xuXHQvLyBDb3B5cmlnaHQgKGMpMjAxMyBEZXJpY2sgQmFpbGV5LCBNdXRlZCBTb2x1dGlvbnMsIExMQy5cblx0Ly8gRGlzdHJpYnV0ZWQgdW5kZXIgTUlUIGxpY2Vuc2Vcblx0Ly9cblx0Ly8gaHR0cDovL2dpdGh1Yi5jb20vYmFieXNpdHRlcmpzL2JhY2tib25lLmJhYnlzaXR0ZXJcblxuXHQvLyBCYWNrYm9uZS5DaGlsZFZpZXdDb250YWluZXJcblx0Ly8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cdC8vXG5cdC8vIFByb3ZpZGUgYSBjb250YWluZXIgdG8gc3RvcmUsIHJldHJpZXZlIGFuZFxuXHQvLyBzaHV0IGRvd24gY2hpbGQgdmlld3MuXG5cblx0Q2hpbGRWaWV3Q29udGFpbmVyID0gKGZ1bmN0aW9uKEJhY2tib25lLCBfKXtcblxuXHRcdC8vIENvbnRhaW5lciBDb25zdHJ1Y3RvclxuXHRcdC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdFx0dmFyIENvbnRhaW5lciA9IGZ1bmN0aW9uKHZpZXdzKXtcblx0XHRcdHRoaXMuX3ZpZXdzID0ge307XG5cdFx0XHR0aGlzLl9pbmRleEJ5TW9kZWwgPSB7fTtcblx0XHRcdHRoaXMuX2luZGV4QnlDdXN0b20gPSB7fTtcblx0XHRcdHRoaXMuX3VwZGF0ZUxlbmd0aCgpO1xuXG5cdFx0XHRfLmVhY2godmlld3MsIHRoaXMuYWRkLCB0aGlzKTtcblx0XHR9O1xuXG5cdFx0Ly8gQ29udGFpbmVyIE1ldGhvZHNcblx0XHQvLyAtLS0tLS0tLS0tLS0tLS0tLVxuXG5cdFx0Xy5leHRlbmQoQ29udGFpbmVyLnByb3RvdHlwZSwge1xuXG5cdFx0XHQvLyBBZGQgYSB2aWV3IHRvIHRoaXMgY29udGFpbmVyLiBTdG9yZXMgdGhlIHZpZXdcblx0XHRcdC8vIGJ5IGBjaWRgIGFuZCBtYWtlcyBpdCBzZWFyY2hhYmxlIGJ5IHRoZSBtb2RlbFxuXHRcdFx0Ly8gY2lkIChhbmQgbW9kZWwgaXRzZWxmKS4gT3B0aW9uYWxseSBzcGVjaWZ5XG5cdFx0XHQvLyBhIGN1c3RvbSBrZXkgdG8gc3RvcmUgYW4gcmV0cmlldmUgdGhlIHZpZXcuXG5cdFx0XHRhZGQ6IGZ1bmN0aW9uKHZpZXcsIGN1c3RvbUluZGV4KXtcblx0XHRcdFx0dmFyIHZpZXdDaWQgPSB2aWV3LmNpZDtcblxuXHRcdFx0XHQvLyBzdG9yZSB0aGUgdmlld1xuXHRcdFx0XHR0aGlzLl92aWV3c1t2aWV3Q2lkXSA9IHZpZXc7XG5cblx0XHRcdFx0Ly8gaW5kZXggaXQgYnkgbW9kZWxcblx0XHRcdFx0aWYgKHZpZXcubW9kZWwpe1xuXHRcdFx0XHRcdHRoaXMuX2luZGV4QnlNb2RlbFt2aWV3Lm1vZGVsLmNpZF0gPSB2aWV3Q2lkO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gaW5kZXggYnkgY3VzdG9tXG5cdFx0XHRcdGlmIChjdXN0b21JbmRleCl7XG5cdFx0XHRcdFx0dGhpcy5faW5kZXhCeUN1c3RvbVtjdXN0b21JbmRleF0gPSB2aWV3Q2lkO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0dGhpcy5fdXBkYXRlTGVuZ3RoKCk7XG5cdFx0XHR9LFxuXG5cdFx0XHQvLyBGaW5kIGEgdmlldyBieSB0aGUgbW9kZWwgdGhhdCB3YXMgYXR0YWNoZWQgdG9cblx0XHRcdC8vIGl0LiBVc2VzIHRoZSBtb2RlbCdzIGBjaWRgIHRvIGZpbmQgaXQuXG5cdFx0XHRmaW5kQnlNb2RlbDogZnVuY3Rpb24obW9kZWwpe1xuXHRcdFx0XHRyZXR1cm4gdGhpcy5maW5kQnlNb2RlbENpZChtb2RlbC5jaWQpO1xuXHRcdFx0fSxcblxuXHRcdFx0Ly8gRmluZCBhIHZpZXcgYnkgdGhlIGBjaWRgIG9mIHRoZSBtb2RlbCB0aGF0IHdhcyBhdHRhY2hlZCB0b1xuXHRcdFx0Ly8gaXQuIFVzZXMgdGhlIG1vZGVsJ3MgYGNpZGAgdG8gZmluZCB0aGUgdmlldyBgY2lkYCBhbmRcblx0XHRcdC8vIHJldHJpZXZlIHRoZSB2aWV3IHVzaW5nIGl0LlxuXHRcdFx0ZmluZEJ5TW9kZWxDaWQ6IGZ1bmN0aW9uKG1vZGVsQ2lkKXtcblx0XHRcdFx0dmFyIHZpZXdDaWQgPSB0aGlzLl9pbmRleEJ5TW9kZWxbbW9kZWxDaWRdO1xuXHRcdFx0XHRyZXR1cm4gdGhpcy5maW5kQnlDaWQodmlld0NpZCk7XG5cdFx0XHR9LFxuXG5cdFx0XHQvLyBGaW5kIGEgdmlldyBieSBhIGN1c3RvbSBpbmRleGVyLlxuXHRcdFx0ZmluZEJ5Q3VzdG9tOiBmdW5jdGlvbihpbmRleCl7XG5cdFx0XHRcdHZhciB2aWV3Q2lkID0gdGhpcy5faW5kZXhCeUN1c3RvbVtpbmRleF07XG5cdFx0XHRcdHJldHVybiB0aGlzLmZpbmRCeUNpZCh2aWV3Q2lkKTtcblx0XHRcdH0sXG5cblx0XHRcdC8vIEZpbmQgYnkgaW5kZXguIFRoaXMgaXMgbm90IGd1YXJhbnRlZWQgdG8gYmUgYVxuXHRcdFx0Ly8gc3RhYmxlIGluZGV4LlxuXHRcdFx0ZmluZEJ5SW5kZXg6IGZ1bmN0aW9uKGluZGV4KXtcblx0XHRcdFx0cmV0dXJuIF8udmFsdWVzKHRoaXMuX3ZpZXdzKVtpbmRleF07XG5cdFx0XHR9LFxuXG5cdFx0XHQvLyByZXRyaWV2ZSBhIHZpZXcgYnkgaXQncyBgY2lkYCBkaXJlY3RseVxuXHRcdFx0ZmluZEJ5Q2lkOiBmdW5jdGlvbihjaWQpe1xuXHRcdFx0XHRyZXR1cm4gdGhpcy5fdmlld3NbY2lkXTtcblx0XHRcdH0sXG5cblx0XHRcdGZpbmRJbmRleEJ5Q2lkIDogZnVuY3Rpb24oIGNpZCApIHtcblx0XHRcdFx0dmFyIGluZGV4ID0gLTE7XG5cdFx0XHRcdHZhciB2aWV3ID0gXy5maW5kKCB0aGlzLl92aWV3cywgZnVuY3Rpb24gKCB2aWV3ICkge1xuXHRcdFx0XHRcdGluZGV4Kys7XG5cdFx0XHRcdFx0aWYoIHZpZXcubW9kZWwuY2lkID09IGNpZCApXG5cdFx0XHRcdFx0XHRyZXR1cm4gdmlldztcblx0XHRcdFx0fSApO1xuXHRcdFx0XHRyZXR1cm4gKCB2aWV3ICkgPyBpbmRleCA6IC0xO1xuXHRcdFx0fSxcblxuXHRcdFx0Ly8gUmVtb3ZlIGEgdmlld1xuXHRcdFx0cmVtb3ZlOiBmdW5jdGlvbih2aWV3KXtcblx0XHRcdFx0dmFyIHZpZXdDaWQgPSB2aWV3LmNpZDtcblxuXHRcdFx0XHQvLyBkZWxldGUgbW9kZWwgaW5kZXhcblx0XHRcdFx0aWYgKHZpZXcubW9kZWwpe1xuXHRcdFx0XHRcdGRlbGV0ZSB0aGlzLl9pbmRleEJ5TW9kZWxbdmlldy5tb2RlbC5jaWRdO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gZGVsZXRlIGN1c3RvbSBpbmRleFxuXHRcdFx0XHRfLmFueSh0aGlzLl9pbmRleEJ5Q3VzdG9tLCBmdW5jdGlvbihjaWQsIGtleSkge1xuXHRcdFx0XHRcdGlmIChjaWQgPT09IHZpZXdDaWQpIHtcblx0XHRcdFx0XHRcdGRlbGV0ZSB0aGlzLl9pbmRleEJ5Q3VzdG9tW2tleV07XG5cdFx0XHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0sIHRoaXMpO1xuXG5cdFx0XHRcdC8vIHJlbW92ZSB0aGUgdmlldyBmcm9tIHRoZSBjb250YWluZXJcblx0XHRcdFx0ZGVsZXRlIHRoaXMuX3ZpZXdzW3ZpZXdDaWRdO1xuXG5cdFx0XHRcdC8vIHVwZGF0ZSB0aGUgbGVuZ3RoXG5cdFx0XHRcdHRoaXMuX3VwZGF0ZUxlbmd0aCgpO1xuXHRcdFx0fSxcblxuXHRcdFx0Ly8gQ2FsbCBhIG1ldGhvZCBvbiBldmVyeSB2aWV3IGluIHRoZSBjb250YWluZXIsXG5cdFx0XHQvLyBwYXNzaW5nIHBhcmFtZXRlcnMgdG8gdGhlIGNhbGwgbWV0aG9kIG9uZSBhdCBhXG5cdFx0XHQvLyB0aW1lLCBsaWtlIGBmdW5jdGlvbi5jYWxsYC5cblx0XHRcdGNhbGw6IGZ1bmN0aW9uKG1ldGhvZCl7XG5cdFx0XHRcdHRoaXMuYXBwbHkobWV0aG9kLCBfLnRhaWwoYXJndW1lbnRzKSk7XG5cdFx0XHR9LFxuXG5cdFx0XHQvLyBBcHBseSBhIG1ldGhvZCBvbiBldmVyeSB2aWV3IGluIHRoZSBjb250YWluZXIsXG5cdFx0XHQvLyBwYXNzaW5nIHBhcmFtZXRlcnMgdG8gdGhlIGNhbGwgbWV0aG9kIG9uZSBhdCBhXG5cdFx0XHQvLyB0aW1lLCBsaWtlIGBmdW5jdGlvbi5hcHBseWAuXG5cdFx0XHRhcHBseTogZnVuY3Rpb24obWV0aG9kLCBhcmdzKXtcblx0XHRcdFx0Xy5lYWNoKHRoaXMuX3ZpZXdzLCBmdW5jdGlvbih2aWV3KXtcblx0XHRcdFx0XHRpZiAoXy5pc0Z1bmN0aW9uKHZpZXdbbWV0aG9kXSkpe1xuXHRcdFx0XHRcdFx0dmlld1ttZXRob2RdLmFwcGx5KHZpZXcsIGFyZ3MgfHwgW10pO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSk7XG5cdFx0XHR9LFxuXG5cdFx0XHQvLyBVcGRhdGUgdGhlIGAubGVuZ3RoYCBhdHRyaWJ1dGUgb24gdGhpcyBjb250YWluZXJcblx0XHRcdF91cGRhdGVMZW5ndGg6IGZ1bmN0aW9uKCl7XG5cdFx0XHRcdHRoaXMubGVuZ3RoID0gXy5zaXplKHRoaXMuX3ZpZXdzKTtcblx0XHRcdH1cblx0XHR9KTtcblxuXHRcdC8vIEJvcnJvd2luZyB0aGlzIGNvZGUgZnJvbSBCYWNrYm9uZS5Db2xsZWN0aW9uOlxuXHRcdC8vIGh0dHA6Ly9iYWNrYm9uZWpzLm9yZy9kb2NzL2JhY2tib25lLmh0bWwjc2VjdGlvbi0xMDZcblx0XHQvL1xuXHRcdC8vIE1peCBpbiBtZXRob2RzIGZyb20gVW5kZXJzY29yZSwgZm9yIGl0ZXJhdGlvbiwgYW5kIG90aGVyXG5cdFx0Ly8gY29sbGVjdGlvbiByZWxhdGVkIGZlYXR1cmVzLlxuXHRcdHZhciBtZXRob2RzID0gWydmb3JFYWNoJywgJ2VhY2gnLCAnbWFwJywgJ2ZpbmQnLCAnZGV0ZWN0JywgJ2ZpbHRlcicsXG5cdFx0XHQgICAgICAgJ3NlbGVjdCcsICdyZWplY3QnLCAnZXZlcnknLCAnYWxsJywgJ3NvbWUnLCAnYW55JywgJ2luY2x1ZGUnLFxuXHRcdFx0ICAgICAgICdjb250YWlucycsICdpbnZva2UnLCAndG9BcnJheScsICdmaXJzdCcsICdpbml0aWFsJywgJ3Jlc3QnLFxuXHRcdFx0ICAgICAgICdsYXN0JywgJ3dpdGhvdXQnLCAnaXNFbXB0eScsICdwbHVjayddO1xuXG5cdFx0Xy5lYWNoKG1ldGhvZHMsIGZ1bmN0aW9uKG1ldGhvZCkge1xuXHRcdFx0Q29udGFpbmVyLnByb3RvdHlwZVttZXRob2RdID0gZnVuY3Rpb24oKSB7XG5cdFx0XHRcdHZhciB2aWV3cyA9IF8udmFsdWVzKHRoaXMuX3ZpZXdzKTtcblx0XHRcdFx0dmFyIGFyZ3MgPSBbdmlld3NdLmNvbmNhdChfLnRvQXJyYXkoYXJndW1lbnRzKSk7XG5cdFx0XHRcdHJldHVybiBfW21ldGhvZF0uYXBwbHkoXywgYXJncyk7XG5cdFx0XHR9O1xuXHRcdH0pO1xuXG5cdFx0Ly8gcmV0dXJuIHRoZSBwdWJsaWMgQVBJXG5cdFx0cmV0dXJuIENvbnRhaW5lcjtcblx0fSkoQmFja2JvbmUsIF8pO1xuXG5cdHJldHVybiBCYWNrYm9uZS5Db2xsZWN0aW9uVmlldztcbn0gKSApO1xuXG4vL1xuLy8gYmFja2JvbmUudHJhY2tpdCAtIDAuMS4wXG4vLyBUaGUgTUlUIExpY2Vuc2Vcbi8vIENvcHlyaWdodCAoYykgMjAxMyBUaGUgTmV3IFlvcmsgVGltZXMsIENNUyBHcm91cCwgTWF0dGhldyBEZUxhbWJvIDxkZWxhbWJvQGdtYWlsLmNvbT5cbi8vXG4oZnVuY3Rpb24oKSB7XG5cblx0Ly8gVW5zYXZlZCBSZWNvcmQgS2VlcGluZ1xuXHQvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblx0Ly8gQ29sbGVjdGlvbiBvZiBhbGwgbW9kZWxzIGluIGFuIGFwcCB0aGF0IGhhdmUgdW5zYXZlZCBjaGFuZ2VzLlxuXHR2YXIgdW5zYXZlZE1vZGVscyA9IFtdO1xuXG5cdC8vIElmIHRoZSBnaXZlbiBtb2RlbCBoYXMgdW5zYXZlZCBjaGFuZ2VzIHRoZW4gYWRkIGl0IHRvXG5cdC8vIHRoZSBgdW5zYXZlZE1vZGVsc2AgY29sbGVjdGlvbiwgb3RoZXJ3aXNlIHJlbW92ZSBpdC5cblx0dmFyIHVwZGF0ZVVuc2F2ZWRNb2RlbHMgPSBmdW5jdGlvbihtb2RlbCkge1xuXHRcdGlmICghXy5pc0VtcHR5KG1vZGVsLl91bnNhdmVkQ2hhbmdlcykpIHtcblx0XHRcdGlmICghXy5maW5kV2hlcmUodW5zYXZlZE1vZGVscywge2NpZDptb2RlbC5jaWR9KSkgdW5zYXZlZE1vZGVscy5wdXNoKG1vZGVsKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dW5zYXZlZE1vZGVscyA9IF8uZmlsdGVyKHVuc2F2ZWRNb2RlbHMsIGZ1bmN0aW9uKG0pIHsgcmV0dXJuIG1vZGVsLmNpZCAhPSBtLmNpZDsgfSk7XG5cdFx0fVxuXHR9O1xuXG5cdC8vIFVubG9hZCBIYW5kbGVyc1xuXHQvLyAtLS0tLS0tLS0tLS0tLS1cblxuXHQvLyBIZWxwZXIgd2hpY2ggcmV0dXJucyBhIHByb21wdCBtZXNzYWdlIGZvciBhbiB1bmxvYWQgaGFuZGxlci5cblx0Ly8gVXNlcyB0aGUgZ2l2ZW4gZnVuY3Rpb24gbmFtZSAob25lIG9mIHRoZSBjYWxsYmFjayBuYW1lc1xuXHQvLyBmcm9tIHRoZSBgbW9kZWwudW5zYXZlZGAgY29uZmlndXJhdGlvbiBoYXNoKSB0byBldmFsdWF0ZVxuXHQvLyB3aGV0aGVyIGEgcHJvbXB0IGlzIG5lZWRlZC9yZXR1cm5lZC5cblx0dmFyIGdldFByb21wdCA9IGZ1bmN0aW9uKGZuTmFtZSkge1xuXHRcdHZhciBwcm9tcHQsIGFyZ3MgPSBfLnJlc3QoYXJndW1lbnRzKTtcblx0XHQvLyBFdmFsdWF0ZSBhbmQgcmV0dXJuIGEgYm9vbGVhbiByZXN1bHQuIFRoZSBnaXZlbiBgZm5gIG1heSBiZSBhXG5cdFx0Ly8gYm9vbGVhbiB2YWx1ZSwgYSBmdW5jdGlvbiwgb3IgdGhlIG5hbWUgb2YgYSBmdW5jdGlvbiBvbiB0aGUgbW9kZWwuXG5cdFx0dmFyIGV2YWx1YXRlTW9kZWxGbiA9IGZ1bmN0aW9uKG1vZGVsLCBmbikge1xuXHRcdFx0aWYgKF8uaXNCb29sZWFuKGZuKSkgcmV0dXJuIGZuO1xuXHRcdFx0cmV0dXJuIChfLmlzU3RyaW5nKGZuKSA/IG1vZGVsW2ZuXSA6IGZuKS5hcHBseShtb2RlbCwgYXJncyk7XG5cdFx0fTtcblx0XHRfLmVhY2godW5zYXZlZE1vZGVscywgZnVuY3Rpb24obW9kZWwpIHtcblx0XHRcdGlmICghcHJvbXB0ICYmIGV2YWx1YXRlTW9kZWxGbihtb2RlbCwgbW9kZWwuX3Vuc2F2ZWRDb25maWdbZm5OYW1lXSkpXG5cdFx0XHRcdHByb21wdCA9IG1vZGVsLl91bnNhdmVkQ29uZmlnLnByb21wdDtcblx0XHR9KTtcblx0XHRyZXR1cm4gcHJvbXB0O1xuXHR9O1xuXG5cdC8vIFdyYXAgQmFja2JvbmUuSGlzdG9yeS5uYXZpZ2F0ZSBzbyB0aGF0IGluLWFwcCByb3V0aW5nXG5cdC8vIChgcm91dGVyLm5hdmlnYXRlKCcvcGF0aCcpYCkgY2FuIGJlIGludGVyY2VwdGVkIHdpdGggYVxuXHQvLyBjb25maXJtYXRpb24gaWYgdGhlcmUgYXJlIGFueSB1bnNhdmVkIG1vZGVscy5cblx0QmFja2JvbmUuSGlzdG9yeS5wcm90b3R5cGUubmF2aWdhdGUgPSBfLndyYXAoQmFja2JvbmUuSGlzdG9yeS5wcm90b3R5cGUubmF2aWdhdGUsIGZ1bmN0aW9uKG9sZE5hdiwgZnJhZ21lbnQsIG9wdGlvbnMpIHtcblx0XHR2YXIgcHJvbXB0ID0gZ2V0UHJvbXB0KCd1bmxvYWRSb3V0ZXJQcm9tcHQnLCBmcmFnbWVudCwgb3B0aW9ucyk7XG5cdFx0aWYgKHByb21wdCkge1xuXHRcdFx0aWYgKGNvbmZpcm0ocHJvbXB0ICsgJyBcXG5cXG5BcmUgeW91IHN1cmUgeW91IHdhbnQgdG8gbGVhdmUgdGhpcyBwYWdlPycpKSB7XG5cdFx0XHRcdG9sZE5hdi5jYWxsKHRoaXMsIGZyYWdtZW50LCBvcHRpb25zKTtcblx0XHRcdH1cblx0XHR9IGVsc2Uge1xuXHRcdFx0b2xkTmF2LmNhbGwodGhpcywgZnJhZ21lbnQsIG9wdGlvbnMpO1xuXHRcdH1cblx0fSk7XG5cblx0Ly8gQ3JlYXRlIGEgYnJvd3NlciB1bmxvYWQgaGFuZGxlciB3aGljaCBpcyB0cmlnZ2VyZWRcblx0Ly8gb24gdGhlIHJlZnJlc2gsIGJhY2ssIG9yIGZvcndhcmQgYnV0dG9uLlxuXHR3aW5kb3cub25iZWZvcmV1bmxvYWQgPSBmdW5jdGlvbihlKSB7XG5cdFx0cmV0dXJuIGdldFByb21wdCgndW5sb2FkV2luZG93UHJvbXB0JywgZSk7XG5cdH07XG5cblx0Ly8gQmFja2JvbmUuTW9kZWwgQVBJXG5cdC8vIC0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdF8uZXh0ZW5kKEJhY2tib25lLk1vZGVsLnByb3RvdHlwZSwge1xuXG5cdFx0dW5zYXZlZDoge30sXG5cdFx0X3RyYWNraW5nQ2hhbmdlczogZmFsc2UsXG5cdFx0X29yaWdpbmFsQXR0cnM6IHt9LFxuXHRcdF91bnNhdmVkQ2hhbmdlczoge30sXG5cblx0XHQvLyBPcHQgaW4gdG8gdHJhY2tpbmcgYXR0cmlidXRlIGNoYW5nZXNcblx0XHQvLyBiZXR3ZWVuIHNhdmVzLlxuXHRcdHN0YXJ0VHJhY2tpbmc6IGZ1bmN0aW9uKCkge1xuXHRcdFx0dGhpcy5fdW5zYXZlZENvbmZpZyA9IF8uZXh0ZW5kKHt9LCB7XG5cdFx0XHRcdHByb21wdDogJ1lvdSBoYXZlIHVuc2F2ZWQgY2hhbmdlcyEnLFxuXHRcdFx0XHR1bmxvYWRSb3V0ZXJQcm9tcHQ6IGZhbHNlLFxuXHRcdFx0XHR1bmxvYWRXaW5kb3dQcm9tcHQ6IGZhbHNlXG5cdFx0XHR9LCB0aGlzLnVuc2F2ZWQgfHwge30pO1xuXHRcdFx0dGhpcy5fdHJhY2tpbmdDaGFuZ2VzID0gdHJ1ZTtcblx0XHRcdHRoaXMuX3Jlc2V0VHJhY2tpbmcoKTtcblx0XHRcdHRoaXMuX3RyaWdnZXJVbnNhdmVkQ2hhbmdlcygpO1xuXHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0fSxcblxuXHRcdC8vIFJlc2V0cyB0aGUgZGVmYXVsdCB0cmFja2luZyB2YWx1ZXNcblx0XHQvLyBhbmQgc3RvcHMgdHJhY2tpbmcgYXR0cmlidXRlIGNoYW5nZXMuXG5cdFx0c3RvcFRyYWNraW5nOiBmdW5jdGlvbigpIHtcblx0XHRcdHRoaXMuX3RyYWNraW5nQ2hhbmdlcyA9IGZhbHNlO1xuXHRcdFx0dGhpcy5fb3JpZ2luYWxBdHRycyA9IHt9O1xuXHRcdFx0dGhpcy5fdW5zYXZlZENoYW5nZXMgPSB7fTtcblx0XHRcdHRoaXMuX3RyaWdnZXJVbnNhdmVkQ2hhbmdlcygpO1xuXHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0fSxcblxuXHRcdC8vIEdldHMgcmlkIG9mIGFjY3J1ZWQgY2hhbmdlcyBhbmRcblx0XHQvLyByZXNldHMgc3RhdGUuXG5cdFx0cmVzdGFydFRyYWNraW5nOiBmdW5jdGlvbigpIHtcblx0XHRcdHRoaXMuX3Jlc2V0VHJhY2tpbmcoKTtcblx0XHRcdHRoaXMuX3RyaWdnZXJVbnNhdmVkQ2hhbmdlcygpO1xuXHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0fSxcblxuXHRcdC8vIFJlc3RvcmVzIHRoaXMgbW9kZWwncyBhdHRyaWJ1dGVzIHRvXG5cdFx0Ly8gdGhlaXIgb3JpZ2luYWwgdmFsdWVzIHNpbmNlIHRyYWNraW5nXG5cdFx0Ly8gc3RhcnRlZCwgdGhlIGxhc3Qgc2F2ZSwgb3IgbGFzdCByZXN0YXJ0LlxuXHRcdHJlc2V0QXR0cmlidXRlczogZnVuY3Rpb24oKSB7XG5cdFx0XHRpZiAoIXRoaXMuX3RyYWNraW5nQ2hhbmdlcykgcmV0dXJuO1xuXHRcdFx0dGhpcy5hdHRyaWJ1dGVzID0gdGhpcy5fb3JpZ2luYWxBdHRycztcblx0XHRcdHRoaXMuX3Jlc2V0VHJhY2tpbmcoKTtcblx0XHRcdHRoaXMuX3RyaWdnZXJVbnNhdmVkQ2hhbmdlcygpO1xuXHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0fSxcblxuXHRcdC8vIFN5bW1ldHJpYyB0byBCYWNrYm9uZSdzIGBtb2RlbC5jaGFuZ2VkQXR0cmlidXRlcygpYCxcblx0XHQvLyBleGNlcHQgdGhhdCB0aGlzIHJldHVybnMgYSBoYXNoIG9mIHRoZSBtb2RlbCdzIGF0dHJpYnV0ZXMgdGhhdFxuXHRcdC8vIGhhdmUgY2hhbmdlZCBzaW5jZSB0aGUgbGFzdCBzYXZlLCBvciBgZmFsc2VgIGlmIHRoZXJlIGFyZSBub25lLlxuXHRcdC8vIExpa2UgYGNoYW5nZWRBdHRyaWJ1dGVzYCwgYW4gZXh0ZXJuYWwgYXR0cmlidXRlcyBoYXNoIGNhbiBiZVxuXHRcdC8vIHBhc3NlZCBpbiwgcmV0dXJuaW5nIHRoZSBhdHRyaWJ1dGVzIGluIHRoYXQgaGFzaCB3aGljaCBkaWZmZXJcblx0XHQvLyBmcm9tIHRoZSBtb2RlbC5cblx0XHR1bnNhdmVkQXR0cmlidXRlczogZnVuY3Rpb24oYXR0cnMpIHtcblx0XHRcdGlmICghYXR0cnMpIHJldHVybiBfLmlzRW1wdHkodGhpcy5fdW5zYXZlZENoYW5nZXMpID8gZmFsc2UgOiBfLmNsb25lKHRoaXMuX3Vuc2F2ZWRDaGFuZ2VzKTtcblx0XHRcdHZhciB2YWwsIGNoYW5nZWQgPSBmYWxzZSwgb2xkID0gdGhpcy5fdW5zYXZlZENoYW5nZXM7XG5cdFx0XHRmb3IgKHZhciBhdHRyIGluIGF0dHJzKSB7XG5cdFx0XHRcdGlmIChfLmlzRXF1YWwob2xkW2F0dHJdLCAodmFsID0gYXR0cnNbYXR0cl0pKSkgY29udGludWU7XG5cdFx0XHRcdChjaGFuZ2VkIHx8IChjaGFuZ2VkID0ge30pKVthdHRyXSA9IHZhbDtcblx0XHRcdH1cblx0XHRcdHJldHVybiBjaGFuZ2VkO1xuXHRcdH0sXG5cblx0XHRfcmVzZXRUcmFja2luZzogZnVuY3Rpb24oKSB7XG5cdFx0XHR0aGlzLl9vcmlnaW5hbEF0dHJzID0gXy5jbG9uZSh0aGlzLmF0dHJpYnV0ZXMpO1xuXHRcdFx0dGhpcy5fdW5zYXZlZENoYW5nZXMgPSB7fTtcblx0XHR9LFxuXG5cdFx0Ly8gVHJpZ2dlciBhbiBgdW5zYXZlZENoYW5nZXNgIGV2ZW50IG9uIHRoaXMgbW9kZWwsXG5cdFx0Ly8gc3VwcGx5aW5nIHRoZSByZXN1bHQgb2Ygd2hldGhlciB0aGVyZSBhcmUgdW5zYXZlZFxuXHRcdC8vIGNoYW5nZXMgYW5kIGEgY2hhbmdlZCBhdHRyaWJ1dGVzIGhhc2guXG5cdFx0X3RyaWdnZXJVbnNhdmVkQ2hhbmdlczogZnVuY3Rpb24oKSB7XG5cdFx0XHR0aGlzLnRyaWdnZXIoJ3Vuc2F2ZWRDaGFuZ2VzJywgIV8uaXNFbXB0eSh0aGlzLl91bnNhdmVkQ2hhbmdlcyksIF8uY2xvbmUodGhpcy5fdW5zYXZlZENoYW5nZXMpKTtcblx0XHRcdGlmICh0aGlzLnVuc2F2ZWQpIHVwZGF0ZVVuc2F2ZWRNb2RlbHModGhpcyk7XG5cdFx0fVxuXHR9KTtcblxuXHQvLyBXcmFwIGBtb2RlbC5zZXQoKWAgYW5kIHVwZGF0ZSB0aGUgaW50ZXJuYWxcblx0Ly8gdW5zYXZlZCBjaGFuZ2VzIHJlY29yZCBrZWVwaW5nLlxuXHRCYWNrYm9uZS5Nb2RlbC5wcm90b3R5cGUuc2V0ID0gXy53cmFwKEJhY2tib25lLk1vZGVsLnByb3RvdHlwZS5zZXQsIGZ1bmN0aW9uKG9sZFNldCwga2V5LCB2YWwsIG9wdGlvbnMpIHtcblx0XHR2YXIgYXR0cnMsIHJldDtcblx0XHRpZiAoa2V5ID09IG51bGwpIHJldHVybiB0aGlzO1xuXHRcdC8vIEhhbmRsZSBib3RoIGBcImtleVwiLCB2YWx1ZWAgYW5kIGB7a2V5OiB2YWx1ZX1gIC1zdHlsZSBhcmd1bWVudHMuXG5cdFx0aWYgKHR5cGVvZiBrZXkgPT09ICdvYmplY3QnKSB7XG5cdFx0XHRhdHRycyA9IGtleTtcblx0XHRcdG9wdGlvbnMgPSB2YWw7XG5cdFx0fSBlbHNlIHtcblx0XHRcdChhdHRycyA9IHt9KVtrZXldID0gdmFsO1xuXHRcdH1cblx0XHRvcHRpb25zIHx8IChvcHRpb25zID0ge30pO1xuXG5cdFx0Ly8gRGVsZWdhdGUgdG8gQmFja2JvbmUncyBzZXQuXG5cdFx0cmV0ID0gb2xkU2V0LmNhbGwodGhpcywgYXR0cnMsIG9wdGlvbnMpO1xuXG5cdFx0aWYgKHRoaXMuX3RyYWNraW5nQ2hhbmdlcyAmJiAhb3B0aW9ucy5zaWxlbnQpIHtcblx0XHRcdF8uZWFjaChhdHRycywgXy5iaW5kKGZ1bmN0aW9uKHZhbCwga2V5KSB7XG5cdFx0XHRcdGlmIChfLmlzRXF1YWwodGhpcy5fb3JpZ2luYWxBdHRyc1trZXldLCB2YWwpKVxuXHRcdFx0XHRcdGRlbGV0ZSB0aGlzLl91bnNhdmVkQ2hhbmdlc1trZXldO1xuXHRcdFx0XHRlbHNlXG5cdFx0XHRcdFx0dGhpcy5fdW5zYXZlZENoYW5nZXNba2V5XSA9IHZhbDtcblx0XHRcdH0sIHRoaXMpKTtcblx0XHRcdHRoaXMuX3RyaWdnZXJVbnNhdmVkQ2hhbmdlcygpO1xuXHRcdH1cblx0XHRyZXR1cm4gcmV0O1xuXHR9KTtcblxuXHQvLyBJbnRlcmNlcHQgYG1vZGVsLnNhdmUoKWAgYW5kIHJlc2V0IHRyYWNraW5nL3Vuc2F2ZWRcblx0Ly8gY2hhbmdlcyBpZiBpdCB3YXMgc3VjY2Vzc2Z1bC5cblx0QmFja2JvbmUuc3luYyA9IF8ud3JhcChCYWNrYm9uZS5zeW5jLCBmdW5jdGlvbihvbGRTeW5jLCBtZXRob2QsIG1vZGVsLCBvcHRpb25zKSB7XG5cdFx0b3B0aW9ucyB8fCAob3B0aW9ucyA9IHt9KTtcblxuXHRcdGlmIChtZXRob2QgPT0gJ3VwZGF0ZScpIHtcblx0XHRcdG9wdGlvbnMuc3VjY2VzcyA9IF8ud3JhcChvcHRpb25zLnN1Y2Nlc3MsIF8uYmluZChmdW5jdGlvbihvbGRTdWNjZXNzLCBkYXRhLCB0ZXh0U3RhdHVzLCBqcVhIUikge1xuXHRcdFx0XHR2YXIgcmV0O1xuXHRcdFx0XHRpZiAob2xkU3VjY2VzcykgcmV0ID0gb2xkU3VjY2Vzcy5jYWxsKHRoaXMsIGRhdGEsIHRleHRTdGF0dXMsIGpxWEhSKTtcblx0XHRcdFx0aWYgKG1vZGVsLl90cmFja2luZ0NoYW5nZXMpIHtcblx0XHRcdFx0XHRtb2RlbC5fcmVzZXRUcmFja2luZygpO1xuXHRcdFx0XHRcdG1vZGVsLl90cmlnZ2VyVW5zYXZlZENoYW5nZXMoKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRyZXR1cm4gcmV0O1xuXHRcdFx0fSwgdGhpcykpO1xuXHRcdH1cblx0XHRyZXR1cm4gb2xkU3luYyhtZXRob2QsIG1vZGVsLCBvcHRpb25zKTtcblx0fSk7XG5cbn0pKCk7XG5kZWZpbmUoXCJ2ZW5kb3IvYmFja2JvbmUudHJhY2tpdFwiLCBmdW5jdGlvbigpe30pO1xuXG4vKipcbiAqIEltYWdlIG9iamVjdCBtb2RlbCBmb3IgdXNlIGluIHZhcmlvdXMgbW9kZWxzIGZvciB0aGUgJ2ltYWdlJyBhdHRyaWJ1dGVcbiAqIEBzaW5jZSAgICAzLjE2LjBcbiAqIEB2ZXJzaW9uICAzLjE2LjBcbiAqL1xuZGVmaW5lKCAnTW9kZWxzL0ltYWdlJyxbXSwgZnVuY3Rpb24oKSB7XG5cblx0cmV0dXJuIEJhY2tib25lLk1vZGVsLmV4dGVuZCgge1xuXG5cdFx0ZGVmYXVsdHM6IHtcblx0XHRcdGVuYWJsZWQ6ICdubycsXG5cdFx0XHRpZDogJycsXG5cdFx0XHRzaXplOiAnZnVsbCcsXG5cdFx0XHRzcmM6ICcnLFxuXHRcdH0sXG5cblx0XHRpbml0aWFsaXplOiBmdW5jdGlvbigpIHtcblx0XHRcdHRoaXMuc3RhcnRUcmFja2luZygpO1xuXHRcdH0sXG5cblx0fSApO1xufSApO1xuXG4vKipcbiAqIE1vZGVsIHJlbGF0aW9uc2hpcHMgbWl4aW5cbiAqIEBzaW5jZSAgICAzLjE2LjBcbiAqIEB2ZXJzaW9uICAzLjE2LjExXG4gKi9cbmRlZmluZSggJ01vZGVscy9fUmVsYXRpb25zaGlwcycsW10sIGZ1bmN0aW9uKCkge1xuXG5cdHJldHVybiB7XG5cblx0XHQvKipcblx0XHQgKiBEZWZhdWx0IHJlbGF0aW9uc2hpcCBzZXR0aW5ncyBvYmplY3Rcblx0XHQgKiBAdHlwZSAge09iamVjdH1cblx0XHQgKi9cblx0XHRyZWxhdGlvbnNoaXBfZGVmYXVsdHM6IHtcblx0XHRcdHBhcmVudDoge30sXG5cdFx0XHRjaGlsZHJlbjoge30sXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFJlbGF0aW9uc2hpcCBzZXR0aW5ncyBvYmplY3Rcblx0XHQgKiBTaG91bGQgYmUgb3ZlcnJpZGVuIGluIHRoZSBtb2RlbFxuXHRcdCAqIEB0eXBlICB7T2JqZWN0fVxuXHRcdCAqL1xuXHRcdHJlbGF0aW9uc2hpcHM6IHt9LFxuXG5cdFx0LyoqXG5cdFx0ICogSW5pdGlhbGl6ZSBhbGwgcGFyZW50IGFuZCBjaGlsZCByZWxhdGlvbnNoaXBzXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGluaXRfcmVsYXRpb25zaGlwczogZnVuY3Rpb24oIG9wdGlvbnMgKSB7XG5cblx0XHRcdHZhciByZWxzID0gdGhpcy5nZXRfcmVsYXRpb25zaGlwcygpO1xuXG5cdFx0XHQvLyBpbml0aWFsaXplIHBhcmVudCByZWxheHRpb25zaGlwc1xuXHRcdFx0Ly8gdXNlZnVsIHdoZW4gYWRkaW5nIGEgbW9kZWwgdG8gZW5zdXJlIHBhcmVudCBpcyBpbml0aWFsaXplZFxuXHRcdFx0aWYgKCByZWxzLnBhcmVudCAmJiBvcHRpb25zICYmIG9wdGlvbnMucGFyZW50ICkge1xuXHRcdFx0XHR0aGlzLnNldF9wYXJlbnQoIG9wdGlvbnMucGFyZW50ICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIGluaXRpYWxpemUgYWxsIGNoaWxkcmVuIHJlbGF0aW9uc2hpcHNcblx0XHRcdF8uZWFjaCggcmVscy5jaGlsZHJlbiwgZnVuY3Rpb24oIGNoaWxkX2RhdGEsIGNoaWxkX2tleSApIHtcblxuXHRcdFx0XHRpZiAoICEgY2hpbGRfZGF0YS5jb25kaXRpb25hbCB8fCB0cnVlID09PSBjaGlsZF9kYXRhLmNvbmRpdGlvbmFsKCB0aGlzICkgKSB7XG5cblx0XHRcdFx0XHR2YXIgY2hpbGRfdmFsID0gdGhpcy5nZXQoIGNoaWxkX2tleSApLFxuXHRcdFx0XHRcdFx0Y2hpbGQ7XG5cblx0XHRcdFx0XHRpZiAoIGNoaWxkX2RhdGEubG9va3VwICkge1xuXHRcdFx0XHRcdFx0Y2hpbGQgPSBjaGlsZF9kYXRhLmxvb2t1cCggY2hpbGRfdmFsICk7XG5cdFx0XHRcdFx0fSBlbHNlIGlmICggJ21vZGVsJyA9PT0gY2hpbGRfZGF0YS50eXBlICkge1xuXHRcdFx0XHRcdFx0Y2hpbGQgPSB3aW5kb3cubGxtc19idWlsZGVyLmNvbnN0cnVjdC5nZXRfbW9kZWwoIGNoaWxkX2RhdGEuY2xhc3MsIGNoaWxkX3ZhbCApO1xuXHRcdFx0XHRcdH0gZWxzZSBpZiAoICdjb2xsZWN0aW9uJyA9PT0gY2hpbGRfZGF0YS50eXBlICkge1xuXHRcdFx0XHRcdFx0Y2hpbGQgPSB3aW5kb3cubGxtc19idWlsZGVyLmNvbnN0cnVjdC5nZXRfY29sbGVjdGlvbiggY2hpbGRfZGF0YS5jbGFzcywgY2hpbGRfdmFsICk7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0dGhpcy5zZXQoIGNoaWxkX2tleSwgY2hpbGQgKTtcblxuXHRcdFx0XHRcdC8vIGlmIHRoZSBjaGlsZCBkZWZpbmVzIGEgcGFyZW50LCBzYXZlIGEgcmVmZXJlbmNlIHRvIHRoZSBwYXJlbnQgb24gdGhlIGNoaWxkXG5cdFx0XHRcdFx0aWYgKCAnbW9kZWwnID09PSBjaGlsZF9kYXRhLnR5cGUgKSB7XG5cdFx0XHRcdFx0XHR0aGlzLl9tYXliZV9zZXRfcGFyZW50X3JlZmVyZW5jZSggY2hpbGQgKTtcblxuXHRcdFx0XHRcdC8vIHNhdmUgZGlyZWN0bHkgdG8gZWFjaCBtb2RlbCBpbiB0aGUgY29sbGVjdGlvblxuXHRcdFx0XHRcdH0gZWxzZSBpZiAoICdjb2xsZWN0aW9uJyA9PT0gY2hpbGRfZGF0YS50eXBlICkge1xuXG5cdFx0XHRcdFx0XHRjaGlsZC5wYXJlbnQgPSB0aGlzO1xuXHRcdFx0XHRcdFx0Y2hpbGQuZWFjaCggZnVuY3Rpb24oIGNoaWxkX21vZGVsICkge1xuXG5cdFx0XHRcdFx0XHRcdHRoaXMuX21heWJlX3NldF9wYXJlbnRfcmVmZXJlbmNlKCBjaGlsZF9tb2RlbCApO1xuXG5cdFx0XHRcdFx0XHR9LCB0aGlzICk7XG5cblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0fVxuXG5cdFx0XHR9LCB0aGlzICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogUmV0cmlldmUgdGhlIHByb3BlcnR5IG5hbWVzIGZvciBhbGwgY2hpbGRyZW4gb2YgdGhlIG1vZGVsXG5cdFx0ICogQHJldHVybiAgIGFycmF5XG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMTFcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4xMVxuXHRcdCAqL1xuXHRcdGdldF9jaGlsZF9wcm9wczogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHZhciBwcm9wcyA9IFtdO1xuXG5cdFx0XHRfLmVhY2goIHRoaXMuZ2V0X3JlbGF0aW9uc2hpcHMoKS5jaGlsZHJlbiwgZnVuY3Rpb24oIGRhdGEsIGtleSApIHtcblxuXHRcdFx0XHRpZiAoICEgZGF0YS5jb25kaXRpb25hbCB8fCB0cnVlID09PSBkYXRhLmNvbmRpdGlvbmFsKCB0aGlzICkgKSB7XG5cdFx0XHRcdFx0cHJvcHMucHVzaCgga2V5ICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0fSwgdGhpcyApO1xuXG5cdFx0XHRyZXR1cm4gcHJvcHM7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogUmV0cmlldmUgdGhlIG1vZGVsJ3MgcGFyZW50IChpZiBzZXQpXG5cdFx0ICogQHJldHVybiAgIG9ianxmYWxzZVxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0Z2V0X3BhcmVudDogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHZhciByZWxzID0gdGhpcy5nZXRfcmVsYXRpb25zaGlwcygpO1xuXG5cdFx0XHRpZiAoIHJlbHMucGFyZW50ICkge1xuXHRcdFx0XHRyZXR1cm4gcmVscy5wYXJlbnQucmVmZXJlbmNlO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogUmV0cmlldmUgcmVsYXRpb25zaGlwcyBmb3IgdGhlIG1vZGVsXG5cdFx0ICogRXh0ZW5kcyB3aXRoIGRlZmF1bHRzXG5cdFx0ICogQHJldHVybiAgIG9ialxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0Z2V0X3JlbGF0aW9uc2hpcHM6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHRyZXR1cm4gJC5leHRlbmQoIHRydWUsIHRoaXMucmVsYXRpb25zaGlwcywgdGhpcy5yZWxhdGlvbnNoaXBfZGVmYXVsdHMgKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBTZXQgdGhlIHBhcmVudCByZWZlcmVuY2UgZm9yIHRoZSBnaXZlbiBtb2RlbFxuXHRcdCAqIEBwYXJhbSAgICBvYmogICBvYmogICBwYXJlbnQgbW9kZWwgb2JqXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdHNldF9wYXJlbnQ6IGZ1bmN0aW9uKCBvYmogKSB7XG5cdFx0XHR0aGlzLnJlbGF0aW9uc2hpcHMucGFyZW50LnJlZmVyZW5jZSA9IG9iajtcblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogU2V0IHVwIHRoZSBwYXJlbnQgcmVsYXRpb25zaGlwcyBmb3IgcXVhbGlmeWluZyBjaGlsZHJlbiBkdXJpbmcgcmVsYXRpb25zaGlwIGluaXRpYWxpemF0aW9uXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIG1vZGVsICBjaGlsZCBtb2RlbFxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRfbWF5YmVfc2V0X3BhcmVudF9yZWZlcmVuY2U6IGZ1bmN0aW9uKCBtb2RlbCApIHtcblxuXHRcdFx0aWYgKCAhIG1vZGVsIHx8ICEgbW9kZWwuZ2V0X3JlbGF0aW9uc2hpcHMgKSB7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblx0XHRcdHZhciByZWxzID0gbW9kZWwuZ2V0X3JlbGF0aW9uc2hpcHMoKTtcblx0XHRcdGlmICggcmVscy5wYXJlbnQgJiYgcmVscy5wYXJlbnQubW9kZWwgPT09IHRoaXMuZ2V0KCAndHlwZScgKSApIHtcblx0XHRcdFx0bW9kZWwuc2V0X3BhcmVudCggdGhpcyApO1xuXHRcdFx0fVxuXG5cdFx0fSxcblxuXHR9O1xuXG59ICk7XG5cbi8qKlxuICogUXVpeiBRdWVzdGlvbiBDaG9pY2VcbiAqIEBzaW5jZSAgICAzLjE2LjBcbiAqIEB2ZXJzaW9uICAzLjE2LjBcbiAqL1xuZGVmaW5lKCAnTW9kZWxzL1F1ZXN0aW9uQ2hvaWNlJyxbICdNb2RlbHMvSW1hZ2UnLCAnTW9kZWxzL19SZWxhdGlvbnNoaXBzJyBdLCBmdW5jdGlvbiggSW1hZ2UsIFJlbGF0aW9uc2hpcHMgKSB7XG5cblx0cmV0dXJuIEJhY2tib25lLk1vZGVsLmV4dGVuZCggXy5kZWZhdWx0cygge1xuXG5cdFx0LyoqXG5cdFx0ICogTW9kZWwgcmVsYXRpb25zaGlwc1xuXHRcdCAqIEB0eXBlICB7T2JqZWN0fVxuXHRcdCAqL1xuXHRcdHJlbGF0aW9uc2hpcHM6IHtcblx0XHRcdHBhcmVudDoge1xuXHRcdFx0XHRtb2RlbDogJ2xsbXNfcXVlc3Rpb24nLFxuXHRcdFx0XHR0eXBlOiAnbW9kZWwnLFxuXHRcdFx0fSxcblx0XHRcdGNoaWxkcmVuOiB7XG5cdFx0XHRcdGNob2ljZToge1xuXHRcdFx0XHRcdGNvbmRpdGlvbmFsOiBmdW5jdGlvbiggbW9kZWwgKSB7XG5cdFx0XHRcdFx0XHRyZXR1cm4gKCAnaW1hZ2UnID09PSBtb2RlbC5nZXQoICdjaG9pY2VfdHlwZScgKSApO1xuXHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0Y2xhc3M6ICdJbWFnZScsXG5cdFx0XHRcdFx0bW9kZWw6ICdpbWFnZScsXG5cdFx0XHRcdFx0dHlwZTogJ21vZGVsJyxcblx0XHRcdFx0fSxcblx0XHRcdH0sXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIE1vZGVsIGRlZmF1bHRzXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGRlZmF1bHRzOiBmdW5jdGlvbigpIHtcblx0XHRcdHJldHVybiB7XG5cdFx0XHRcdGlkOiBfLnVuaXF1ZUlkKCAndGVtcF8nICksXG5cdFx0XHRcdGNob2ljZTogJycsXG5cdFx0XHRcdGNob2ljZV90eXBlOiAndGV4dCcsXG5cdFx0XHRcdGNvcnJlY3Q6IGZhbHNlLFxuXHRcdFx0XHRtYXJrZXI6ICdBJyxcblx0XHRcdFx0cXVlc3Rpb25faWQ6ICcnLFxuXHRcdFx0XHR0eXBlOiAnY2hvaWNlJyxcblx0XHRcdH1cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogSW5pdGlhbGl6ZXJcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgZGF0YSAgICAgb2JqZWN0IG9mIG1vZGVsIGF0dHJpYnV0ZXNcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgb3B0aW9ucyAgYWRkaXRpb25hbCBvcHRpb25zXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGluaXRpYWxpemU6IGZ1bmN0aW9uKCBkYXRhLCBvcHRpb25zICkge1xuXG5cdFx0XHR0aGlzLnN0YXJ0VHJhY2tpbmcoKTtcblx0XHRcdHRoaXMuaW5pdF9yZWxhdGlvbnNoaXBzKCBvcHRpb25zICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogUmV0cmlldmUgdGhlIGNob2ljZSdzIHBhcmVudCBxdWVzdGlvblxuXHRcdCAqIEByZXR1cm4gICBvYmpcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGdldF9wYXJlbnQ6IGZ1bmN0aW9uKCkge1xuXHRcdFx0cmV0dXJuIHRoaXMuY29sbGVjdGlvbi5wYXJlbnQ7XG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFJldHJpZXZlIHRoZSBJRCB1c2VkIHdoZW4gdHJhc2hpbmcgdGhlIG1vZGVsXG5cdFx0ICogQHJldHVybiAgIHN0cmluZ1xuXHRcdCAqIEBzaW5jZSAgICAzLjE3LjFcblx0XHQgKiBAdmVyc2lvbiAgMy4xNy4xXG5cdFx0ICovXG5cdFx0Z2V0X3RyYXNoX2lkOiBmdW5jdGlvbigpIHtcblx0XHRcdHJldHVybiB0aGlzLmdldCggJ3F1ZXN0aW9uX2lkJyApICsgJzonICsgdGhpcy5nZXQoICdpZCcgKTtcblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogRGV0ZXJtaW5lIGlmIFwic2VsZWN0aW9uXCIgaXMgZW5hYmxlZCBmb3IgdGhlIHF1ZXN0aW9uIHR5cGVcblx0XHQgKiBDaG9pY2UgdHlwZSBxdWVzdGlvbnMgYXJlIHNlbGVjdGFibGUgYnkgcmVvcmRlciB0eXBlIHF1ZXN0aW9ucyBhcmUgbm90IGJ1dCBzdGlsbCB1c2UgY2hvaWNlc1xuXHRcdCAqIEByZXR1cm4gICB7Qm9vbGVhbn1cblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGlzX3NlbGVjdGFibGU6IGZ1bmN0aW9uKCkge1xuXHRcdFx0cmV0dXJuIHRoaXMuZ2V0X3BhcmVudCgpLmdldCggJ3F1ZXN0aW9uX3R5cGUnICkuZ2V0X2Nob2ljZV9zZWxlY3RhYmxlKCk7XG5cdFx0fSxcblxuXHR9LCBSZWxhdGlvbnNoaXBzICkgKTtcblxufSApO1xuXG4vKipcbiAqIFF1ZXN0aW9uIENob2ljZSBDb2xsZWN0aW9uXG4gKiBAc2luY2UgICAgMy4xNi4wXG4gKiBAdmVyc2lvbiAgMy4xNi4wXG4gKi9cbmRlZmluZSggJ0NvbGxlY3Rpb25zL1F1ZXN0aW9uQ2hvaWNlcycsWyAnTW9kZWxzL1F1ZXN0aW9uQ2hvaWNlJyBdLCBmdW5jdGlvbiggbW9kZWwgKSB7XG5cblx0cmV0dXJuIEJhY2tib25lLkNvbGxlY3Rpb24uZXh0ZW5kKCB7XG5cblx0XHQvKipcblx0XHQgKiBNb2RlbCBmb3IgY29sbGVjdGlvbiBpdGVtc1xuXHRcdCAqIEB0eXBlICBvYmpcblx0XHQgKi9cblx0XHRtb2RlbDogbW9kZWwsXG5cblx0XHRpbml0aWFsaXplOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0Ly8gcmVvcmRlciBjYWxsZWQgYnkgUXVlc3Rpb25MaXN0IHZpZXcgd2hlbiBzb3J0YWJsZSBkcm9wcyBvY2N1clxuXHRcdFx0dGhpcy5vbiggJ3Jlb3JkZXInLCB0aGlzLnVwZGF0ZV9vcmRlciApO1xuXG5cdFx0XHQvLyB3aGVuIGEgY2hvaWNlIGlzIGFkZGVkIG9yIHJlbW92ZWQsIHVwZGF0ZSBvcmRlclxuXHRcdFx0dGhpcy5vbiggJ2FkZCcsIHRoaXMudXBkYXRlX29yZGVyICk7XG5cdFx0XHR0aGlzLm9uKCAncmVtb3ZlJywgdGhpcy51cGRhdGVfb3JkZXIgKTtcblxuXHRcdFx0Ly8gd2hlbiBhIGNob2ljZSBpcyBhZGRlZCBvciByZW1vdmUsIGVuc3VyZSBtaW4vbWF4IGNvcnJlY3QgYW5zd2VycyBleGlzdFxuXHRcdFx0dGhpcy5vbiggJ2FkZCcsIHRoaXMudXBkYXRlX2NvcnJlY3QgKTtcblx0XHRcdHRoaXMub24oICdyZW1vdmUnLCB0aGlzLnVwZGF0ZV9jb3JyZWN0ICk7XG5cblx0XHRcdC8vIHdoZW4gYSBjaG9pY2UgaXMgdG9nZ2xlZCwgZW5zdXJlIG1pbi9tYXggY29ycmVjdCBleGlzdFxuXHRcdFx0dGhpcy5vbiggJ2NvcnJlY3QtdXBkYXRlJywgdGhpcy51cGRhdGVfY29ycmVjdCApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFJldHJpZXZlIHRoZSBudW1iZXIgb2YgY29ycmVjdCBjaG9pY2VzIGluIHRoZSBjb2xsZWN0aW9uXG5cdFx0ICogQHJldHVybiAgIGludFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0Y291bnRfY29ycmVjdDogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHJldHVybiBfLnNpemUoIHRoaXMuZ2V0X2NvcnJlY3QoKSApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFJldHJpZXZlIHRoZSBjb2xsZWN0aW9uIHJlZHVjZWQgdG8gb25seSBjb3JyZWN0IGNob2ljZXNcblx0XHQgKiBAcmV0dXJuICAgb2JqXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRnZXRfY29ycmVjdDogZnVuY3Rpb24oKSB7XG5cdFx0XHRyZXR1cm4gdGhpcy5maWx0ZXIoIGZ1bmN0aW9uKCBjaG9pY2UgKSB7XG5cdFx0XHRcdHJldHVybiBjaG9pY2UuZ2V0KCAnY29ycmVjdCcgKTtcblx0XHRcdH0gKTtcblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogRW5zdXJlIG1pbi9tYXggY29ycmVjdCBjaG9pY2VzIGV4aXN0IGluIHRoZSBjb2xsZWN0aW9uIGJhc2VkIG9uIHRoZSBxdWVzdGlvbidzIHNldHRpbmdzXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgICAgIGNob2ljZSAgbW9kZWwgb2YgdGhlIGNob2ljZSB0aGF0IHdhcyB0b2dnbGVkXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdHVwZGF0ZV9jb3JyZWN0OiBmdW5jdGlvbiggY2hvaWNlICkge1xuXG5cdFx0XHRpZiAoICEgdGhpcy5wYXJlbnQuZ2V0KCAncXVlc3Rpb25fdHlwZScgKS5nZXRfY2hvaWNlX3NlbGVjdGFibGUoKSApIHtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXG5cdFx0XHR2YXIgc2libGluZ3MgPSB0aGlzLndpdGhvdXQoIGNob2ljZSApLCAvLyBleGNsdWRlIHRoZSB0b2dnbGVkIGNob2ljZSBmcm9tIGxvb3BzXG5cdFx0XHRcdHF1ZXN0aW9uID0gdGhpcy5wYXJlbnQ7XG5cblx0XHRcdC8vIGlmIG11bHRpcGxlIGNob2ljZXMgYXJlbid0IGVuYWJsZWQgdHVybiBhbGwgb3RoZXIgY2hvaWNlcyB0byBpbmNvcnJlY3Rcblx0XHRcdGlmICggJ25vJyA9PT0gcXVlc3Rpb24uZ2V0KCAnbXVsdGlfY2hvaWNlcycgKSApIHtcblx0XHRcdFx0Xy5lYWNoKCBzaWJsaW5ncywgZnVuY3Rpb24oIG1vZGVsICkge1xuXHRcdFx0XHRcdG1vZGVsLnNldCggJ2NvcnJlY3QnLCBmYWxzZSApO1xuXHRcdFx0XHR9ICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIGlmIHdlIGRvbid0IGhhdmUgYSBzaW5nbGUgY29ycmV0IGFuc3dlciAmIHRoZSBxdWVzdGlvbiBoYXMgcG9pbnRzLCBzZXQgb25lXG5cdFx0XHQvLyBhbGxvd3MgdXNlcnMgdG8gY3JlYXRlIHF1aXp6ZXMgLyBxdWVzdGlvbnMgd2l0aCBubyBwb2ludHMgYW5kIHRoZXJlZm9yZSBubyBjb3JyZWN0IGFuc3dlcnMgYXJlIGFsbG93ZWRcblx0XHRcdGlmICggMCA9PT0gdGhpcy5jb3VudF9jb3JyZWN0KCkgJiYgcXVlc3Rpb24uZ2V0KCAncG9pbnRzJyApID4gMCApIHtcblx0XHRcdFx0dmFyIG1vZGVscyA9IDEgPT09IHRoaXMuc2l6ZSgpID8gdGhpcy5tb2RlbHMgOiBzaWJsaW5ncztcblx0XHRcdFx0Xy5maXJzdCggbW9kZWxzICkuc2V0KCAnY29ycmVjdCcsIHRydWUgKTtcblx0XHRcdH1cblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBVcGRhdGUgdGhlIG1hcmtlciBhdHRyIG9mIGVhY2ggY2hvaWNlIGluIHRoZSBsaXN0IHRvIHJlZmxlY3QgdGhlIG9yZGVyIG9mIHRoZSBjb2xsZWN0aW9uXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdHVwZGF0ZV9vcmRlcjogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHZhciBzZWxmID0gdGhpcyxcblx0XHRcdFx0cXVlc3Rpb24gPSB0aGlzLnBhcmVudDtcblxuXHRcdFx0dGhpcy5lYWNoKCBmdW5jdGlvbiggY2hvaWNlICkge1xuXHRcdFx0XHRjaG9pY2Uuc2V0KCAnbWFya2VyJywgcXVlc3Rpb24uZ2V0KCAncXVlc3Rpb25fdHlwZScgKS5nZXRfY2hvaWNlX21hcmtlcnMoKVsgc2VsZi5pbmRleE9mKCBjaG9pY2UgKSBdICk7XG5cdFx0XHR9ICk7XG5cblx0XHR9LFxuXG5cdH0gKTtcblxufSApO1xuXG4vKipcbiAqIFF1aXogUXVlc3Rpb24gVHlwZVxuICogQHNpbmNlICAgIDMuMTYuMFxuICogQHZlcnNpb24gIDMuMTYuMFxuICovXG5kZWZpbmUoICdNb2RlbHMvUXVlc3Rpb25UeXBlJyxbXSwgZnVuY3Rpb24oKSB7XG5cblx0cmV0dXJuIEJhY2tib25lLk1vZGVsLmV4dGVuZCgge1xuXG5cdFx0LyoqXG5cdFx0ICogR2V0IG1vZGVsIGRlZmF1bHQgYXR0cmlidXRlc1xuXHRcdCAqIEByZXR1cm4gICBvYmpcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGRlZmF1bHRzOiBmdW5jdGlvbigpIHtcblx0XHRcdHJldHVybiB7XG5cdFx0XHRcdGNob2ljZXM6IGZhbHNlLFxuXHRcdFx0XHRjbGFyaWZpY2F0aW9uczogdHJ1ZSxcblx0XHRcdFx0ZGVmYXVsdF9jaG9pY2VzOiBbXSxcblx0XHRcdFx0ZGVzY3JpcHRpb246IHRydWUsXG5cdFx0XHRcdGljb246ICdxdWVzdGlvbicsXG5cdFx0XHRcdGlkOiAnZ2VuZXJpYycsXG5cdFx0XHRcdGltYWdlOiB0cnVlLFxuXHRcdFx0XHRrZXl3b3JkczogW10sXG5cdFx0XHRcdG5hbWU6ICdHZW5lcmljJyxcblx0XHRcdFx0cGxhY2Vob2xkZXI6ICcnLFxuXHRcdFx0XHRwb2ludHM6IHRydWUsXG5cdFx0XHRcdHZpZGVvOiB0cnVlLFxuXHRcdFx0fVxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBSZXRyaWV2ZSBhbiBhcnJheSBvZiBrZXl3b3JkcyBmb3IgdGhlIHF1ZXN0aW9uIHR5cGVcblx0XHQgKiBVc2VkIGZvciBmaWx0ZXJpbmcgcXVlc3Rpb25zIGJ5IHNlYXJjaCB0ZXJtIGluIHRoZSBxdWl6IGJ1aWxkZXJcblx0XHQgKiBAcmV0dXJuICAgYXJyYXlcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGdldF9rZXl3b3JkczogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHZhciBuYW1lID0gdGhpcy5nZXQoICduYW1lJyApLFxuXHRcdFx0XHR3b3JkcyA9IFsgbmFtZSBdO1xuXG5cdFx0XHRyZXR1cm4gd29yZHMuY29uY2F0KCB0aGlzLmdldCggJ2tleXdvcmRzJyApICkuY29uY2F0KCBuYW1lLnNwbGl0KCAnICcgKSApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIEdldCBtYXJrZXIgYXJyYXkgZm9yIHRoZSBxdWVzdGlvbiBjaG9pY2VzXG5cdFx0ICogQHJldHVybiAgIGFycmF5XG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRnZXRfY2hvaWNlX21hcmtlcnM6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHRyZXR1cm4gdGhpcy5fZ2V0X2Nob2ljZV9vcHRpb24oICdtYXJrZXJzJyApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIERldGVybWluZSBpZiB0aGUgcXVlc3Rpb24ncyBjaG9pY2VzIGFyZSBzZWxlY3RhYmxlXG5cdFx0ICogQHJldHVybiAgIGJvb2xcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGdldF9jaG9pY2Vfc2VsZWN0YWJsZTogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHJldHVybiB0aGlzLl9nZXRfY2hvaWNlX29wdGlvbiggJ3NlbGVjdGFibGUnICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogR2V0IHRoZSBjaG9pY2UgdHlwZSAodGV4dCxpbWFnZSlcblx0XHQgKiBAcmV0dXJuICAgc3RyaW5nXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRnZXRfY2hvaWNlX3R5cGU6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHRyZXR1cm4gdGhpcy5fZ2V0X2Nob2ljZV9vcHRpb24oICd0eXBlJyApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFJldHJpZXZlIGRlZmluZWQgbWluLiBjaG9pY2VzXG5cdFx0ICogQHJldHVybiAgIGludFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0Z2V0X21pbl9jaG9pY2VzOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0cmV0dXJuIHRoaXMuX2dldF9jaG9pY2Vfb3B0aW9uKCAnbWluJyApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIEdldCB0eXBlLWRlZmluZWQgbWF4IGNob2ljZXNcblx0XHQgKiBAcmV0dXJuICAgc3RyaW5nXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRnZXRfbWF4X2Nob2ljZXM6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHRyZXR1cm4gdGhpcy5fZ2V0X2Nob2ljZV9vcHRpb24oICdtYXgnICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogRGV0ZXJtaW5lIGlmIG11bHRpLWNob2ljZSBzZWxlY3Rpb24gaXMgZW5hYmxlZFxuXHRcdCAqIEByZXR1cm4gICBib29sXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRnZXRfbXVsdGlfY2hvaWNlczogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHZhciBjaG9pY2VzID0gdGhpcy5nZXQoICdjaG9pY2VzJyApO1xuXG5cdFx0XHRpZiAoICEgY2hvaWNlcyAgKSB7XG5cdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIHRoaXMuX2dldF9jaG9pY2Vfb3B0aW9uKCAnbXVsdGknICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogUmV0cmlldmUgZGF0YSBmcm9tIHRoZSB0eXBlJ3MgXCJjaG9pY2VzXCIgYXR0cmlidXRlXG5cdFx0ICogQWxsb3dzIHF1aWNrIGhhbmRsaW5nIG9mIHR5cGVzIHdpdGggbm8gY2hvaWNlIGRlZmluaXRpb25zIHcvbyBhZGRpdGlvbmFsIGNoZWNrc1xuXHRcdCAqIEBwYXJhbSAgICBzdHJpbmcgICBvcHRpb24gIG5hbWUgb2YgdGhlIGNob2ljZSBvcHRpb24gdG8gcmV0cmlldmVcblx0XHQgKiBAcmV0dXJuICAgbWl4ZWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdF9nZXRfY2hvaWNlX29wdGlvbjogZnVuY3Rpb24oIG9wdGlvbiApIHtcblxuXHRcdFx0dmFyIGNob2ljZXMgPSB0aGlzLmdldCggJ2Nob2ljZXMnICk7XG5cblx0XHRcdGlmICggISBjaG9pY2VzIHx8ICEgY2hvaWNlc1sgb3B0aW9uIF0gKSB7XG5cdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIGNob2ljZXNbIG9wdGlvbiBdO1xuXG5cdFx0fSxcblxuXHR9ICk7XG5cbn0gKTtcblxuLyoqXG4gKiBRdWl6IFF1ZXN0aW9uXG4gKiBAc2luY2UgICAgMy4xNi4wXG4gKiBAdmVyc2lvbiAgMy4xNi4wXG4gKi9cbmRlZmluZSggJ01vZGVscy9RdWVzdGlvbicsW1xuXHRcdCdNb2RlbHMvSW1hZ2UnLFxuXHRcdCdDb2xsZWN0aW9ucy9RdWVzdGlvbnMnLFxuXHRcdCdDb2xsZWN0aW9ucy9RdWVzdGlvbkNob2ljZXMnLFxuXHRcdCdNb2RlbHMvUXVlc3Rpb25UeXBlJyxcblx0XHQnTW9kZWxzL19SZWxhdGlvbnNoaXBzJ1xuXHRdLCBmdW5jdGlvbihcblx0XHRJbWFnZSxcblx0XHRRdWVzdGlvbnMsXG5cdFx0UXVlc3Rpb25DaG9pY2VzLFxuXHRcdFF1ZXN0aW9uVHlwZSxcblx0XHRSZWxhdGlvbnNoaXBzXG5cdCkge1xuXG5cdHJldHVybiBCYWNrYm9uZS5Nb2RlbC5leHRlbmQoIF8uZGVmYXVsdHMoIHtcblxuXHRcdC8qKlxuXHRcdCAqIE1vZGVsIHJlbGF0aW9uc2hpcHNcblx0XHQgKiBAdHlwZSAge09iamVjdH1cblx0XHQgKi9cblx0XHRyZWxhdGlvbnNoaXBzOiB7XG5cdFx0XHRwYXJlbnQ6IHtcblx0XHRcdFx0bW9kZWw6ICdsbG1zX3F1aXonLFxuXHRcdFx0XHR0eXBlOiAnbW9kZWwnLFxuXHRcdFx0fSxcblx0XHRcdGNoaWxkcmVuOiB7XG5cdFx0XHRcdGNob2ljZXM6IHtcblx0XHRcdFx0XHRjbGFzczogJ1F1ZXN0aW9uQ2hvaWNlcycsXG5cdFx0XHRcdFx0bW9kZWw6ICdjaG9pY2UnLFxuXHRcdFx0XHRcdHR5cGU6ICdjb2xsZWN0aW9uJyxcblx0XHRcdFx0fSxcblx0XHRcdFx0aW1hZ2U6IHtcblx0XHRcdFx0XHRjbGFzczogJ0ltYWdlJyxcblx0XHRcdFx0XHRtb2RlbDogJ2ltYWdlJyxcblx0XHRcdFx0XHR0eXBlOiAnbW9kZWwnLFxuXHRcdFx0XHR9LFxuXHRcdFx0XHRxdWVzdGlvbnM6IHtcblx0XHRcdFx0XHRjbGFzczogJ1F1ZXN0aW9ucycsXG5cdFx0XHRcdFx0Y29uZGl0aW9uYWw6IGZ1bmN0aW9uKCBtb2RlbCApIHtcblx0XHRcdFx0XHRcdHZhciB0eXBlID0gbW9kZWwuZ2V0KCAncXVlc3Rpb25fdHlwZScgKSxcblx0XHRcdFx0XHRcdFx0dHlwZV9pZCA9IF8uaXNTdHJpbmcoIHR5cGUgKSA/IHR5cGUgOiB0eXBlLmdldCggJ2lkJyApO1xuXHRcdFx0XHRcdFx0cmV0dXJuICggJ2dyb3VwJyA9PT0gdHlwZV9pZCApO1xuXHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0bW9kZWw6ICdsbG1zX3F1ZXN0aW9uJyxcblx0XHRcdFx0XHR0eXBlOiAnY29sbGVjdGlvbicsXG5cdFx0XHRcdH0sXG5cdFx0XHRcdHF1ZXN0aW9uX3R5cGU6IHtcblx0XHRcdFx0XHRjbGFzczogJ1F1ZXN0aW9uVHlwZScsXG5cdFx0XHRcdFx0bG9va3VwOiBmdW5jdGlvbiggdmFsICkge1xuXHRcdFx0XHRcdFx0aWYgKCBfLmlzU3RyaW5nKCB2YWwgKSApIHtcblx0XHRcdFx0XHRcdFx0cmV0dXJuIHdpbmRvdy5sbG1zX2J1aWxkZXIucXVlc3Rpb25zLmdldCggdmFsICk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRyZXR1cm4gdmFsO1xuXHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0bW9kZWw6ICdxdWVzdGlvbl90eXBlJyxcblx0XHRcdFx0XHR0eXBlOiAnbW9kZWwnLFxuXHRcdFx0XHR9LFxuXHRcdFx0fVxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBNb2RlbCBkZWZhdWx0c1xuXHRcdCAqIEByZXR1cm4gICBvYmpcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGRlZmF1bHRzOiBmdW5jdGlvbigpIHtcblx0XHRcdHJldHVybiB7XG5cdFx0XHRcdGlkOiBfLnVuaXF1ZUlkKCAndGVtcF8nICksXG5cdFx0XHRcdGNob2ljZXM6IFtdLFxuXHRcdFx0XHRjb250ZW50OiAnJyxcblx0XHRcdFx0ZGVzY3JpcHRpb25fZW5hYmxlZDogJ25vJyxcblx0XHRcdFx0aW1hZ2U6IHt9LFxuXHRcdFx0XHRtdWx0aV9jaG9pY2VzOiAnbm8nLFxuXHRcdFx0XHRtZW51X29yZGVyOiAxLFxuXHRcdFx0XHRwb2ludHM6IDEsXG5cdFx0XHRcdHF1ZXN0aW9uX3R5cGU6ICdnZW5lcmljJyxcblx0XHRcdFx0cXVlc3Rpb25zOiBbXSwgLy8gZm9yIHF1ZXN0aW9uIGdyb3Vwc1xuXHRcdFx0XHRwYXJlbnRfaWQ6ICcnLFxuXHRcdFx0XHR0aXRsZTogJycsXG5cdFx0XHRcdHR5cGU6ICdsbG1zX3F1ZXN0aW9uJyxcblx0XHRcdFx0dmlkZW9fZW5hYmxlZDogJ25vJyxcblx0XHRcdFx0dmlkZW9fc3JjOiAnJyxcblxuXHRcdFx0XHRfZXhwYW5kZWQ6IGZhbHNlLFxuXHRcdFx0fVxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBJbml0aWFsaXplclxuXHRcdCAqIEBwYXJhbSAgICBvYmogICBkYXRhICAgICBvYmplY3Qgb2YgZGF0YSBmb3IgdGhlIG1vZGVsXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIG9wdGlvbnMgIGFkZGl0aW9uYWwgb3B0aW9uc1xuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRpbml0aWFsaXplOiBmdW5jdGlvbiggZGF0YSwgb3B0aW9ucyApIHtcblxuXHRcdFx0dmFyIHNlbGYgPSB0aGlzO1xuXG5cdFx0XHR0aGlzLnN0YXJ0VHJhY2tpbmcoKTtcblx0XHRcdHRoaXMuaW5pdF9yZWxhdGlvbnNoaXBzKCBvcHRpb25zICk7XG5cblx0XHRcdGlmICggZmFsc2UgIT09IHRoaXMuZ2V0KCAncXVlc3Rpb25fdHlwZScgKS5jaG9pY2VzICkge1xuXG5cdFx0XHRcdHRoaXMuX2Vuc3VyZV9taW5fY2hvaWNlcygpO1xuXG5cdFx0XHRcdC8vIHdoZW4gYSBjaG9pY2UgaXMgcmVtb3ZlZCwgbWF5YmUgYWRkIGJhY2sgc29tZSBkZWZhdWx0cyBzbyB3ZSBhbHdheXMgaGF2ZSB0aGUgbWluaW11bVxuXHRcdFx0XHR0aGlzLmxpc3RlblRvKCB0aGlzLmdldCggJ2Nob2ljZXMnICksICdyZW1vdmUnLCBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHQvLyBuZXcgaXRtZXMgYXJlIGFkZGVkIGF0IGluZGV4IDAgd2hlbiB0aGVyZSdzIG9ubHkgMSBpdGVtIGluIHRoZSBjb2xsZWN0aW9uLCBub3Qgc3VyZSB3aHkgZXhhY3RseS4uLlxuXHRcdFx0XHRcdHNldFRpbWVvdXQoIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdFx0c2VsZi5fZW5zdXJlX21pbl9jaG9pY2VzKCk7XG5cdFx0XHRcdFx0fSwgMCApO1xuXHRcdFx0XHR9ICk7XG5cblx0XHRcdH1cblxuXHRcdFx0Ly8gZW5zdXJlIHF1ZXN0aW9uIHR5cGVzIHRoYXQgZG9uJ3Qgc3VwcG9ydCBwb2ludHMgZG9uJ3QgcmVjb3JkIGRlZmF1bHQgMSBwb2ludCBpbiBkYXRhYmFzZVxuXHRcdFx0aWYgKCAhIHRoaXMuZ2V0KCAncXVlc3Rpb25fdHlwZScgKS5nZXQoICdwb2ludHMnICkgKSB7XG5cdFx0XHRcdHRoaXMuc2V0KCAncG9pbnRzJywgMCApO1xuXHRcdFx0fVxuXG5cdFx0XHRfLmRlbGF5KCBmdW5jdGlvbiggc2VsZiApIHtcblx0XHRcdFx0c2VsZi5vbiggJ2NoYW5nZTpwb2ludHMnLCBzZWxmLmdldF9wYXJlbnQoKS51cGRhdGVfcG9pbnRzLCBzZWxmLmdldF9wYXJlbnQoKSApO1xuXHRcdFx0fSwgMSwgdGhpcyApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIEFkZCBhIG5ldyBxdWVzdGlvbiBjaG9pY2Vcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgZGF0YSAgICAgb2JqZWN0IG9mIGNob2ljZSBkYXRhXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIG9wdGlvbnMgIGFkZGl0aW9uYWwgb3B0aW9uc1xuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0YWRkX2Nob2ljZTogZnVuY3Rpb24oIGRhdGEsIG9wdGlvbnMgKSB7XG5cblx0XHRcdHZhciBtYXggPSB0aGlzLmdldCggJ3F1ZXN0aW9uX3R5cGUnICkuZ2V0X21heF9jaG9pY2VzKCk7XG5cdFx0XHRpZiAoIHRoaXMuZ2V0KCAnY2hvaWNlcycgKS5zaXplKCkgPj0gbWF4ICkge1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cblx0XHRcdGRhdGEgPSBkYXRhIHx8IHt9O1xuXHRcdFx0b3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG5cblx0XHRcdGRhdGEuY2hvaWNlX3R5cGUgPSB0aGlzLmdldCggJ3F1ZXN0aW9uX3R5cGUnICkuZ2V0X2Nob2ljZV90eXBlKCk7XG5cdFx0XHRkYXRhLnF1ZXN0aW9uX2lkID0gdGhpcy5nZXQoICdpZCcgKTtcblx0XHRcdG9wdGlvbnMucGFyZW50ID0gdGhpcztcblxuXHRcdFx0dmFyIGNob2ljZSA9IHRoaXMuZ2V0KCAnY2hvaWNlcycgKS5hZGQoIGRhdGEsIG9wdGlvbnMgKTtcblxuXHRcdFx0QmFja2JvbmUucHViU3ViLnRyaWdnZXIoICdxdWVzdGlvbi1hZGQtY2hvaWNlJywgY2hvaWNlLCB0aGlzICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogQ29sbGFwc2UgcXVlc3Rpb25fdHlwZSBhdHRyaWJ1dGUgZHVyaW5nIGZ1bGwgc3luY3MgdG8gc2F2ZSB0byBkYXRhYmFzZVxuXHRcdCAqIE5vdCBuZWVkZWQgYmVjYXVzZSBxdWVzdGlvbiB0eXBlcyBjYW5ub3QgYmUgYWRqdXN0ZWQgYWZ0ZXIgcXVlc3Rpb24gY3JlYXRpb25cblx0XHQgKiBDYWxsZWQgZnJvbSBzeW5jIGNvbnRyb2xsZXJcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgICAgYXR0cyAgICAgICBmbGF0IG9iamVjdCBvZiBhdHRyaWJ1dGVzIHRvIGJlIHNhdmVkIHRvIGRiXG5cdFx0ICogQHBhcmFtICAgIHN0cmluZyAgIHN5bmNfdHlwZSAgZnVsbCBvciBwYXJ0aWFsXG5cdFx0ICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmdWxsIGluZGljYXRlcyBhIGZvcmNlIHJlc3luYyBvciB0aGF0IHRoZSBtb2RlbCBpc24ndCBwZXJzaXN0ZWQgeWV0XG5cdFx0ICogQHJldHVybiAgIG9ialxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0YmVmb3JlX3NhdmU6IGZ1bmN0aW9uKCBhdHRzLCBzeW5jX3R5cGUgICkge1xuXHRcdFx0aWYgKCAnZnVsbCcgPT09IHN5bmNfdHlwZSApIHtcblx0XHRcdFx0YXR0cy5xdWVzdGlvbl90eXBlID0gdGhpcy5nZXQoICdxdWVzdGlvbl90eXBlJyApLmdldCggJ2lkJyApO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIGF0dHM7XG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFJldHJpZXZlIHRoZSBtb2RlbCdzIHBhcmVudCAoaWYgc2V0KVxuXHRcdCAqIEByZXR1cm4gICBvYmp8ZmFsc2Vcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGdldF9wYXJlbnQ6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHR2YXIgcmVscyA9IHRoaXMuZ2V0X3JlbGF0aW9uc2hpcHMoKTtcblxuXHRcdFx0aWYgKCByZWxzLnBhcmVudCApIHtcblx0XHRcdFx0aWYgKCB0aGlzLmNvbGxlY3Rpb24gJiYgdGhpcy5jb2xsZWN0aW9uLnBhcmVudCApIHtcblx0XHRcdFx0XHRyZXR1cm4gdGhpcy5jb2xsZWN0aW9uLnBhcmVudDtcblx0XHRcdFx0fSBlbHNlIGlmICggcmVscy5wYXJlbnQucmVmZXJlbmNlICkge1xuXHRcdFx0XHRcdHJldHVybiByZWxzLnBhcmVudC5yZWZlcmVuY2U7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIEdldHMgdGhlIGluZGV4IG9mIHRoZSBxdWVzdGlvbiB3aXRoaW4gaXQncyBwYXJlbnRcblx0XHQgKiBRdWVzdGlvbiBudW1iZXJzIHNraXAgY29udGVudCBlbGVtZW50c1xuXHRcdCAqICYgY29udGVudCBlbGVtZW50cyBza2lwIHF1ZXN0aW9uc1xuXHRcdCAqIEByZXR1cm4gICBpbnRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGdldF90eXBlX2luZGV4OiBmdW5jdGlvbigpIHtcblxuXHRcdFx0Ly8gY3VycmVudCBtb2RlbHMgdHlwZSwgdXNlZCB0byBjaGVjayB0aGUgcHJlZGljYXRlIGluIHRoZSBmaWx0ZXIgZnVuY3Rpb24gYmVsb3dcblx0XHRcdHZhciBjdXJyX3R5cGUgPSB0aGlzLmdldCggJ3F1ZXN0aW9uX3R5cGUnICkuZ2V0KCAnaWQnICksXG5cdFx0XHRcdHF1ZXN0aW9ucztcblxuXHRcdFx0cXVlc3Rpb25zID0gdGhpcy5jb2xsZWN0aW9uLmZpbHRlciggZnVuY3Rpb24oIHF1ZXN0aW9uICkge1xuXG5cdFx0XHRcdHZhciB0eXBlID0gcXVlc3Rpb24uZ2V0KCAncXVlc3Rpb25fdHlwZScgKS5nZXQoICdpZCcgKTtcblxuXHRcdFx0XHQvLyBpZiBjdXJyZW50IG1vZGVsIGlzIG5vdCBjb250ZW50LCByZXR1cm4gYWxsIG5vbi1jb250ZW50IHF1ZXN0aW9uc1xuXHRcdFx0XHRpZiAoIGN1cnJfdHlwZSAhPT0gJ2NvbnRlbnQnICkge1xuXHRcdFx0XHRcdHJldHVybiAoICdjb250ZW50JyAhPT0gdHlwZSApO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gY3VycmVudCBtb2RlbCBpcyBjb250ZW50LCByZXR1cm4gb25seSBjb250ZW50IHF1ZXN0aW9uc1xuXHRcdFx0XHRyZXR1cm4gJ2NvbnRlbnQnID09PSB0eXBlO1xuXG5cdFx0XHR9ICk7XG5cblx0XHRcdHJldHVybiBxdWVzdGlvbnMuaW5kZXhPZiggdGhpcyApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIEdldHMgaXRlcmF0b3IgZm9yIHRoZSBnaXZlbiB0eXBlXG5cdFx0ICogUXVlc3Rpb25zIHVzZSBudW1iZXJzIGFuZCBjb250ZW50IHVzZXMgYWxwaGFiZXRcblx0XHQgKiBAcmV0dXJuICAgbWl4ZWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGdldF90eXBlX2l0ZXJhdG9yOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0dmFyIGluZGV4ID0gdGhpcy5nZXRfdHlwZV9pbmRleCgpO1xuXG5cdFx0XHRpZiAoIC0xID09PSBpbmRleCApIHtcblx0XHRcdFx0cmV0dXJuICcnO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoICdjb250ZW50JyA9PT0gdGhpcy5nZXQoICdxdWVzdGlvbl90eXBlJyApLmdldCggJ2lkJyApICkge1xuXHRcdFx0XHR2YXIgYWxwaGFiZXQgPSAnQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVonLnNwbGl0KCAnJyApO1xuXHRcdFx0XHRyZXR1cm4gYWxwaGFiZXRbIGluZGV4IF07XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBpbmRleCArIDE7XG5cblx0XHR9LFxuXG5cblx0XHRnZXRfcWlkOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0dmFyIHBhcmVudCA9IHRoaXMuZ2V0X3BhcmVudF9xdWVzdGlvbigpLFxuXHRcdFx0XHRwcmVmaXggPSAnJztcblxuXHRcdFx0aWYgKCBwYXJlbnQgKSB7XG5cblx0XHRcdFx0cHJlZml4ID0gcGFyZW50LmdldF9xaWQoKSArICcuJztcblxuXHRcdFx0fVxuXG5cdFx0XHQvLyByZXR1cm4gc2hvcnRfaWQgKyB0aGlzLmdldF90eXBlX2l0ZXJhdG9yKCk7XG5cdFx0XHRyZXR1cm4gcHJlZml4ICsgdGhpcy5nZXRfdHlwZV9pdGVyYXRvcigpO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFJldHJpZXZlIHRoZSBwYXJlbnQgcXVlc3Rpb24gKGlmIHRoZSBxdWVzdGlvbiBpcyBpbiBhIHF1ZXN0aW9uIGdyb3VwKVxuXHRcdCAqIEByZXR1cm4gICBvYmp8ZmFsc2Vcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGdldF9wYXJlbnRfcXVlc3Rpb246IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHRpZiAoIHRoaXMuaXNfaW5fZ3JvdXAoKSApIHtcblxuXHRcdFx0XHRyZXR1cm4gdGhpcy5jb2xsZWN0aW9uLnBhcmVudDtcblxuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogUmV0cmlldmUgdGhlIHBhcmVudCBxdWl6XG5cdFx0ICogQHJldHVybiAgIG9ialxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0Z2V0X3BhcmVudF9xdWl6OiBmdW5jdGlvbigpIHtcblx0XHRcdHJldHVybiB0aGlzLmdldF9wYXJlbnQoKTtcblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogUG9pbnRzIGdldHRlclxuXHRcdCAqIGVuc3VyZXMgdGhhdCAwIGlzIGFsd2F5cyByZXR1cm5lZCBpZiB0aGUgcXVlc3Rpb24gdHlwZSBkb2Vzbid0IHN1cHBvcnQgcG9pbnRzXG5cdFx0ICogQHJldHVybiAgIGludFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0Z2V0X3BvaW50czogZnVuY3Rpb24oKSB7XG5cblx0XHRcdGlmICggISB0aGlzLmdldCggJ3F1ZXN0aW9uX3R5cGUnICkuZ2V0KCAncG9pbnRzJyApICkge1xuXHRcdFx0XHRyZXR1cm4gMDtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIHRoaXMuZ2V0KCAncG9pbnRzJyApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFJldHJpZXZlIHRoZSBxdWVzdGlvbnMgcGVyY2VudGFnZSB2YWx1ZSB3aXRoaW4gdGhlIHF1aXpcblx0XHQgKiBAcmV0dXJuICAgc3RyaW5nXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRnZXRfcG9pbnRzX3BlcmNlbnRhZ2U6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHR2YXIgdG90YWwgPSB0aGlzLmdldF9wYXJlbnQoKS5nZXQoICdfcG9pbnRzJyApLFxuXHRcdFx0XHRwb2ludHMgPSB0aGlzLmdldCggJ3BvaW50cycgKTtcblxuXHRcdFx0aWYgKCAwID09PSB0b3RhbCApIHtcblx0XHRcdFx0cmV0dXJuICcwJSc7XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiAoICggcG9pbnRzIC8gdG90YWwgKSAqIDEwMCApLnRvRml4ZWQoIDIgKSArICclJztcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBEZXRlcmluZSBpZiB0aGUgcXVlc3Rpb24gYmVsb25ncyB0byBhIHF1ZXN0aW9uIGdyb3VwXG5cdFx0ICogQHJldHVybiAgIHtCb29sZWFufVxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0aXNfaW5fZ3JvdXA6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHRyZXR1cm4gKCAncXVlc3Rpb24nID09PSB0aGlzLmNvbGxlY3Rpb24ucGFyZW50LmdldCggJ3R5cGUnICkgKTtcblxuXHRcdH0sXG5cblx0XHRfZW5zdXJlX21pbl9jaG9pY2VzOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0dmFyIGNob2ljZXMgPSB0aGlzLmdldCggJ2Nob2ljZXMnICk7XG5cdFx0XHR3aGlsZSAoIGNob2ljZXMuc2l6ZSgpIDwgdGhpcy5nZXQoICdxdWVzdGlvbl90eXBlJyApLmdldF9taW5fY2hvaWNlcygpICkge1xuXHRcdFx0XHR0aGlzLmFkZF9jaG9pY2UoKTtcblx0XHRcdH1cblxuXHRcdH0sXG5cblx0fSwgUmVsYXRpb25zaGlwcyApICk7XG5cbn0gKTtcblxuLyoqXG4gKiBRdWVzdGlvbnMgQ29sbGVjdGlvblxuICogQHNpbmNlICAgIDMuMTYuMFxuICogQHZlcnNpb24gIDMuMTYuMFxuICovXG5kZWZpbmUoICdDb2xsZWN0aW9ucy9RdWVzdGlvbnMnLFsgJ01vZGVscy9RdWVzdGlvbicgXSwgZnVuY3Rpb24oIG1vZGVsICkge1xuXG5cdHJldHVybiBCYWNrYm9uZS5Db2xsZWN0aW9uLmV4dGVuZCgge1xuXG5cdFx0LyoqXG5cdFx0ICogTW9kZWwgZm9yIGNvbGxlY3Rpb24gaXRlbXNcblx0XHQgKiBAdHlwZSAgb2JqXG5cdFx0ICovXG5cdFx0bW9kZWw6IG1vZGVsLFxuXG5cdFx0LyoqXG5cdFx0ICogSW5pdGlhbGl6ZVxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRpbml0aWFsaXplOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0Ly8gcmVvcmRlciBjYWxsZWQgYnkgUXVlc3Rpb25MaXN0IHZpZXcgd2hlbiBzb3J0YWJsZSBkcm9wcyBvY2N1clxuXHRcdFx0dGhpcy5vbiggJ3Jlb3JkZXInLCB0aGlzLnVwZGF0ZV9vcmRlciApO1xuXG5cdFx0XHQvLyB3aGVuIGEgcXVlc3Rpb24gaXMgYWRkZWQgb3IgcmVtb3ZlZCwgdXBkYXRlIG9yZGVyXG5cdFx0XHR0aGlzLm9uKCAnYWRkJywgdGhpcy51cGRhdGVfb3JkZXIgKTtcblx0XHRcdHRoaXMub24oICdyZW1vdmUnLCB0aGlzLnVwZGF0ZV9vcmRlciApO1xuXG5cdFx0XHR0aGlzLm9uKCAnYWRkJywgdGhpcy51cGRhdGVfcGFyZW50ICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogVXBkYXRlIHRoZSBvcmRlciBhdHRyIG9mIGVhY2ggcXVlc3Rpb24gaW4gdGhlIGxpc3QgdG8gcmVmbGVjdCB0aGUgb3JkZXIgb2YgdGhlIGNvbGxlY3Rpb25cblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0dXBkYXRlX29yZGVyOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0dmFyIHNlbGYgPSB0aGlzO1xuXG5cdFx0XHR0aGlzLmVhY2goIGZ1bmN0aW9uKCBxdWVzdGlvbiApIHtcblxuXHRcdFx0XHRxdWVzdGlvbi5zZXQoICdtZW51X29yZGVyJywgc2VsZi5pbmRleE9mKCBxdWVzdGlvbiApICsgMSApO1xuXG5cdFx0XHR9ICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogV2hlbiBhZGRpbmcgYSBxdWVzdGlvbiB0byBhIHF1ZXN0aW9uIGxpc3QsIHVwZGF0ZSB0aGUgcXVlc3Rpb24ncyBwYXJlbnRcblx0XHQgKiBXaWxsIGVuc3VyZSB0aGF0IHF1ZXN0aW9ucyBtb3ZlZCBpbnRvIGFuZCBvdXQgb2YgZ3JvdXBzIGFsd2F5cyBoYXZlIHRoZSBjb3JlcmN0IHBhcmVudF9pZFxuXHRcdCAqIEBwYXJhbSAgICBvYmogICBtb2RlbCAgaW5zdGFuY2Ugb2YgdGhlIHF1ZXN0aW9uIG1vZGVsXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdHVwZGF0ZV9wYXJlbnQ6IGZ1bmN0aW9uKCBtb2RlbCApIHtcblxuXHRcdFx0bW9kZWwuc2V0KCAncGFyZW50X2lkJywgdGhpcy5wYXJlbnQuZ2V0KCAnaWQnICkgKTtcblxuXHRcdH0sXG5cblx0fSApO1xuXG59ICk7XG5cbi8qKlxuICogVXRpbGl0eSBmdW5jdGlvbnMgZm9yIE1vZGVsc1xuICogQHNpbmNlICAgIDMuMTYuMFxuICogQHZlcnNpb24gIDMuMTcuMVxuICovXG5kZWZpbmUoICdNb2RlbHMvX1V0aWxpdGllcycsW10sIGZ1bmN0aW9uKCkge1xuXG5cdHJldHVybiB7XG5cblx0XHRmaWVsZHM6IFtdLFxuXG5cdFx0LyoqXG5cdFx0ICogUmV0cmlldmUgdGhlIGVkaXQgcG9zdCBsaW5rIGZvciB0aGUgY3VycmVudCBtb2RlbFxuXHRcdCAqIEByZXR1cm4gICBzdHJpbmdcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGdldF9lZGl0X3Bvc3RfbGluazogZnVuY3Rpb24oKSB7XG5cblx0XHRcdGlmICggdGhpcy5oYXNfdGVtcF9pZCgpICkge1xuXHRcdFx0XHRyZXR1cm4gJyc7XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiB3aW5kb3cubGxtc19idWlsZGVyLmFkbWluX3VybCArICdwb3N0LnBocD9wb3N0PScgKyB0aGlzLmdldCggJ2lkJyApICsgJyZhY3Rpb249ZWRpdCc7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogUmV0cmlldmUgc2NoZW1hIGZpZWxkcyBkZWZpbmVkIGZvciB0aGUgbW9kZWxcblx0XHQgKiBAcmV0dXJuICAgb2JqZWN0XG5cdFx0ICogQHNpbmNlICAgIDMuMTcuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE3LjFcblx0XHQgKi9cblx0XHRnZXRfc2V0dGluZ3NfZmllbGRzOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0dmFyIHNjaGVtYSA9IHRoaXMuc2NoZW1hIHx8IHt9O1xuXHRcdFx0cmV0dXJuIHdpbmRvdy5sbG1zX2J1aWxkZXIuc2NoZW1hcy5nZXQoIHNjaGVtYSwgdGhpcy5nZXQoICd0eXBlJyApLnJlcGxhY2UoICdsbG1zXycsICcnICksIHRoaXMgKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBEZXRlcm1pbmUgaWYgdGhlIG1vZGVsIGhhcyBhIHRlbXBvcmFyeSBJRFxuXHRcdCAqIEByZXR1cm4gICB7Qm9vbGVhbn1cblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGhhc190ZW1wX2lkOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0cmV0dXJuICggISBfLmlzTnVtYmVyKCB0aGlzLmdldCggJ2lkJyApICkgJiYgMCA9PT0gdGhpcy5nZXQoICdpZCcgKS5pbmRleE9mKCAndGVtcF8nICkgKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBJbml0aWFsaXplcyAzcmQgcGFydHkgY3VzdG9tIHNjaGVtYSAoZmllbGQpIGRhdGEgZm9yIGEgbW9kZWxcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE3LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNy4wXG5cdFx0ICovXG5cdFx0aW5pdF9jdXN0b21fc2NoZW1hOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0dmFyIGdyb3VwcyA9IF8uZmlsdGVyKCB0aGlzLmdldF9zZXR0aW5nc19maWVsZHMoKSwgZnVuY3Rpb24oIGdyb3VwICkge1xuXHRcdFx0XHRyZXR1cm4gKCBncm91cC5jdXN0b20gKTtcblx0XHRcdH0gKTtcblxuXHRcdFx0Xy5lYWNoKCBncm91cHMsIGZ1bmN0aW9uKCBncm91cCApIHtcblx0XHRcdFx0Xy5lYWNoKCBfLmZsYXR0ZW4oICBncm91cC5maWVsZHMgKSwgZnVuY3Rpb24oIGZpZWxkICkge1xuXG5cblx0XHRcdFx0XHR2YXIga2V5cyA9IFsgZmllbGQuYXR0cmlidXRlIF0sXG5cdFx0XHRcdFx0XHRjdXN0b21zID0gdGhpcy5nZXQoICdjdXN0b20nICk7XG5cblx0XHRcdFx0XHRpZiAoIGZpZWxkLnN3aXRjaF9hdHRyaWJ1dGUgKSB7XG5cdFx0XHRcdFx0XHRrZXlzLnB1c2goIGZpZWxkLnN3aXRjaF9hdHRyaWJ1dGUgKTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRfLmVhY2goIGtleXMsIGZ1bmN0aW9uKCBrZXkgKSB7XG5cdFx0XHRcdFx0XHR2YXIgYXR0ciA9IGZpZWxkLmF0dHJpYnV0ZV9wcmVmaXggPyBmaWVsZC5hdHRyaWJ1dGVfcHJlZml4ICsga2V5IDoga2V5O1xuXHRcdFx0XHRcdFx0aWYgKCBjdXN0b21zICYmIGN1c3RvbXNbIGF0dHIgXSApIHtcblx0XHRcdFx0XHRcdFx0dGhpcy5zZXQoIGtleSwgY3VzdG9tc1sgYXR0ciBdWzBdICk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fSwgdGhpcyApO1xuXG5cdFx0XHRcdH0sIHRoaXMgKTtcblx0XHRcdH0sIHRoaXMgKTtcblxuXHRcdH0sXG5cblx0fTtcblxufSApO1xuXG4vKipcbiAqIFF1aXogU2NoZW1hXG4gKiBAc2luY2UgICAgMy4xNy42XG4gKiBAdmVyc2lvbiAgMy4xNy42XG4gKi9cbmRlZmluZSggJ1NjaGVtYXMvUXVpeicsW10sIGZ1bmN0aW9uKCkge1xuXG5cdHJldHVybiB7XG5cblx0XHRkZWZhdWx0OiB7XG5cdFx0XHR0aXRsZTogTExNUy5sMTBuLnRyYW5zbGF0ZSggJ0dlbmVyYWwgU2V0dGluZ3MnICksXG5cdFx0XHR0b2dnbGVhYmxlOiB0cnVlLFxuXHRcdFx0ZmllbGRzOiBbXG5cdFx0XHRcdFtcblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRhdHRyaWJ1dGU6ICdwZXJtYWxpbmsnLFxuXHRcdFx0XHRcdFx0aWQ6ICdwZXJtYWxpbmsnLFxuXHRcdFx0XHRcdFx0dHlwZTogJ3Blcm1hbGluaycsXG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XSwgW1xuXHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdGF0dHJpYnV0ZTogJ2NvbnRlbnQnLFxuXHRcdFx0XHRcdFx0aWQ6ICdkZXNjcmlwdGlvbicsXG5cdFx0XHRcdFx0XHRsYWJlbDogTExNUy5sMTBuLnRyYW5zbGF0ZSggJ0Rlc2NyaXB0aW9uJyApLFxuXHRcdFx0XHRcdFx0dHlwZTogJ2VkaXRvcicsXG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XSwgW1xuXHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdGF0dHJpYnV0ZTogJ3Bhc3NpbmdfcGVyY2VudCcsXG5cdFx0XHRcdFx0XHRpZDogJ3Bhc3NpbmctcGVyY2VudCcsXG5cdFx0XHRcdFx0XHRsYWJlbDogTExNUy5sMTBuLnRyYW5zbGF0ZSggJ1Bhc3NpbmcgUGVyY2VudGFnZScgKSxcblx0XHRcdFx0XHRcdG1pbjogMCxcblx0XHRcdFx0XHRcdG1heDogMTAwLFxuXHRcdFx0XHRcdFx0dGlwOiBMTE1TLmwxMG4udHJhbnNsYXRlKCAnTWluaW11bSBwZXJjZW50YWdlIG9mIHRvdGFsIHBvaW50cyByZXF1aXJlZCB0byBwYXNzIHRoZSBxdWl6JyApLFxuXHRcdFx0XHRcdFx0dHlwZTogJ251bWJlcicsXG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRhdHRyaWJ1dGU6ICdhbGxvd2VkX2F0dGVtcHRzJyxcblx0XHRcdFx0XHRcdGlkOiAnYWxsb3dlZC1hdHRlbXB0cycsXG5cdFx0XHRcdFx0XHRsYWJlbDogTExNUy5sMTBuLnRyYW5zbGF0ZSggJ0xpbWl0IEF0dGVtcHRzJyApLFxuXHRcdFx0XHRcdFx0c3dpdGNoX2F0dHJpYnV0ZTogJ2xpbWl0X2F0dGVtcHRzJyxcblx0XHRcdFx0XHRcdHRpcDogTExNUy5sMTBuLnRyYW5zbGF0ZSggJ0xpbWl0IHRoZSBtYXhpbXVtIG51bWJlciBvZiB0aW1lcyBhIHN0dWRlbnQgY2FuIHRha2UgdGhpcyBxdWl6JyApLFxuXHRcdFx0XHRcdFx0dHlwZTogJ3N3aXRjaC1udW1iZXInLFxuXHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0YXR0cmlidXRlOiAndGltZV9saW1pdCcsXG5cdFx0XHRcdFx0XHRpZDogJ3RpbWUtbGltaXQnLFxuXHRcdFx0XHRcdFx0bGFiZWw6IExMTVMubDEwbi50cmFuc2xhdGUoICdUaW1lIExpbWl0JyApLFxuXHRcdFx0XHRcdFx0bWluOiAxLFxuXHRcdFx0XHRcdFx0bWF4OiAzNjAsXG5cdFx0XHRcdFx0XHRzd2l0Y2hfYXR0cmlidXRlOiAnbGltaXRfdGltZScsXG5cdFx0XHRcdFx0XHR0aXA6IExMTVMubDEwbi50cmFuc2xhdGUoICdFbmZvcmNlIGEgbWF4aW11bSBudW1iZXIgb2YgbWludXRlcyBhIHN0dWRlbnQgY2FuIHNwZW5kIG9uIGVhY2ggYXR0ZW1wdCcgKSxcblx0XHRcdFx0XHRcdHR5cGU6ICdzd2l0Y2gtbnVtYmVyJyxcblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRdLCBbXG5cdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0YXR0cmlidXRlOiAnc2hvd19jb3JyZWN0X2Fuc3dlcicsXG5cdFx0XHRcdFx0XHRpZDogJ3Nob3ctY29ycmVjdC1hbnN3ZXInLFxuXHRcdFx0XHRcdFx0bGFiZWw6IExMTVMubDEwbi50cmFuc2xhdGUoICdTaG93IENvcnJlY3QgQW5zd2VycycgKSxcblx0XHRcdFx0XHRcdHRpcDogTExNUy5sMTBuLnRyYW5zbGF0ZSggJ1doZW4gZW5hYmxlZCwgc3R1ZGVudHMgd2lsbCBiZSBzaG93biB0aGUgY29ycmVjdCBhbnN3ZXIgdG8gYW55IHF1ZXN0aW9uIHRoZXkgYW5zd2VyZWQgaW5jb3JyZWN0bHkuJyApLFxuXHRcdFx0XHRcdFx0dHlwZTogJ3N3aXRjaCcsXG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRhdHRyaWJ1dGU6ICdyYW5kb21fcXVlc3Rpb25zJyxcblx0XHRcdFx0XHRcdGlkOiAncmFuZG9tLXF1ZXN0aW9ucycsXG5cdFx0XHRcdFx0XHRsYWJlbDogTExNUy5sMTBuLnRyYW5zbGF0ZSggJ1JhbmRvbWl6ZSBRdWVzdGlvbiBPcmRlcicgKSxcblx0XHRcdFx0XHRcdHRpcDogTExNUy5sMTBuLnRyYW5zbGF0ZSggJ0Rpc3BsYXkgcXVlc3Rpb25zIGluIGEgcmFuZG9tIG9yZGVyIGZvciBlYWNoIGF0dGVtcHQuIENvbnRlbnQgcXVlc3Rpb25zIGFyZSBsb2NrZWQgaW50byB0aGVpciBkZWZpbmVkIHBvc2l0aW9ucy4nICksXG5cdFx0XHRcdFx0XHR0eXBlOiAnc3dpdGNoJyxcblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRdLFxuXG5cdFx0XHRdLFxuXHRcdH0sXG5cblx0fTtcblxufSApO1xuXG4vKipcbiAqIFF1aXogTW9kZWxcbiAqIEBzaW5jZSAgICAzLjE2LjBcbiAqIEB2ZXJzaW9uICAzLjE5LjJcbiAqL1xuZGVmaW5lKCAnTW9kZWxzL1F1aXonLFtcblx0XHQnQ29sbGVjdGlvbnMvUXVlc3Rpb25zJyxcblx0XHQnTW9kZWxzL0xlc3NvbicsXG5cdFx0J01vZGVscy9RdWVzdGlvbicsXG5cdFx0J01vZGVscy9fUmVsYXRpb25zaGlwcycsXG5cdFx0J01vZGVscy9fVXRpbGl0aWVzJyxcblx0XHQnU2NoZW1hcy9RdWl6Jyxcblx0XSwgZnVuY3Rpb24oXG5cdFx0UXVlc3Rpb25zLFxuXHRcdExlc3Nvbixcblx0XHRRdWVzdGlvbixcblx0XHRSZWxhdGlvbnNoaXBzLFxuXHRcdFV0aWxpdGllcyxcblx0XHRRdWl6U2NoZW1hXG5cdCkge1xuXG5cdHJldHVybiBCYWNrYm9uZS5Nb2RlbC5leHRlbmQoIF8uZGVmYXVsdHMoIHtcblxuXHRcdC8qKlxuXHRcdCAqIG1vZGVsIHJlbGF0aW9uc2hpcHNcblx0XHQgKiBAdHlwZSAge09iamVjdH1cblx0XHQgKi9cblx0XHRyZWxhdGlvbnNoaXBzOiB7XG5cdFx0XHRwYXJlbnQ6IHtcblx0XHRcdFx0bW9kZWw6ICdsZXNzb24nLFxuXHRcdFx0XHR0eXBlOiAnbW9kZWwnLFxuXHRcdFx0fSxcblx0XHRcdGNoaWxkcmVuOiB7XG5cdFx0XHRcdHF1ZXN0aW9uczoge1xuXHRcdFx0XHRcdGNsYXNzOiAnUXVlc3Rpb25zJyxcblx0XHRcdFx0XHRtb2RlbDogJ2xsbXNfcXVlc3Rpb24nLFxuXHRcdFx0XHRcdHR5cGU6ICdjb2xsZWN0aW9uJyxcblx0XHRcdFx0fSxcblx0XHRcdH1cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogTGVzc29uIFNldHRpbmdzIFNjaGVtYVxuXHRcdCAqIEB0eXBlICB7T2JqZWN0fVxuXHRcdCAqL1xuXHRcdHNjaGVtYTogUXVpelNjaGVtYSxcblxuXHRcdC8qKlxuXHRcdCAqIE5ldyBsZXNzb24gZGVmYXVsdHNcblx0XHQgKiBAcmV0dXJuICAgb2JqXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjZcblx0XHQgKi9cblx0XHRkZWZhdWx0czogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHJldHVybiB7XG5cdFx0XHRcdGlkOiBfLnVuaXF1ZUlkKCAndGVtcF8nICksXG5cdFx0XHRcdHRpdGxlOiBMTE1TLmwxMG4udHJhbnNsYXRlKCAnTmV3IFF1aXonICksXG5cdFx0XHRcdHR5cGU6ICdsbG1zX3F1aXonLFxuXHRcdFx0XHRsZXNzb25faWQ6ICcnLFxuXG5cdFx0XHRcdHN0YXR1czogJ2RyYWZ0JyxcblxuXHRcdFx0XHQvLyBlZGl0YWJsZSBmaWVsZHNcblx0XHRcdFx0Y29udGVudDogJycsXG5cdFx0XHRcdGFsbG93ZWRfYXR0ZW1wdHM6IDUsXG5cdFx0XHRcdGxpbWl0X2F0dGVtcHRzOiAnbm8nLFxuXHRcdFx0XHRsaW1pdF90aW1lOiAnbm8nLFxuXHRcdFx0XHRwYXNzaW5nX3BlcmNlbnQ6IDY1LFxuXHRcdFx0XHRuYW1lOiAnJyxcblx0XHRcdFx0cmFuZG9tX2Fuc3dlcnM6ICdubycsXG5cdFx0XHRcdHRpbWVfbGltaXQ6IDMwLFxuXHRcdFx0XHRzaG93X2NvcnJlY3RfYW5zd2VyOiAnbm8nLFxuXG5cdFx0XHRcdHF1ZXN0aW9uczogW10sXG5cblx0XHRcdFx0Ly8gY2FsY3VsYXRlZFxuXHRcdFx0XHRfcG9pbnRzOiAwLFxuXG5cdFx0XHRcdC8vIGRpc3BsYXlcblx0XHRcdFx0cGVybWFsaW5rOiAnJyxcblx0XHRcdFx0X3Nob3dfc2V0dGluZ3M6IGZhbHNlLFxuXHRcdFx0XHRfcXVlc3Rpb25zX2xvYWRlZDogZmFsc2UsXG5cdFx0XHR9O1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIEluaXRpYWxpemVyXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTcuNlxuXHRcdCAqL1xuXHRcdGluaXRpYWxpemU6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHR0aGlzLmluaXRfY3VzdG9tX3NjaGVtYSgpO1xuXHRcdFx0dGhpcy5zdGFydFRyYWNraW5nKCk7XG5cdFx0XHR0aGlzLmluaXRfcmVsYXRpb25zaGlwcygpO1xuXG5cdFx0XHR0aGlzLmxpc3RlblRvKCB0aGlzLmdldCggJ3F1ZXN0aW9ucycgKSwgJ2FkZCcsIHRoaXMudXBkYXRlX3BvaW50cyApO1xuXHRcdFx0dGhpcy5saXN0ZW5UbyggdGhpcy5nZXQoICdxdWVzdGlvbnMnICksICdyZW1vdmUnLCB0aGlzLnVwZGF0ZV9wb2ludHMgKTtcblxuXHRcdFx0dGhpcy5zZXQoICdfcG9pbnRzJywgdGhpcy5nZXRfdG90YWxfcG9pbnRzKCkgKTtcblxuXHRcdFx0Ly8gd2hlbiBhIHF1aXogaXMgcHVibGlzaGVkLCBlbnN1cmUgdGhlIHBhcmVudCBsZXNzb24gaXMgbWFya2VkIGFzIFwiRW5hYmxlZFwiIGZvciBxdWl6emluZ1xuXHRcdFx0dGhpcy5vbiggJ2NoYW5nZTpzdGF0dXMnLCBmdW5jdGlvbigpIHtcblx0XHRcdFx0aWYgKCAncHVibGlzaCcgPT09IHRoaXMuZ2V0KCAnc3RhdHVzJyApICkge1xuXHRcdFx0XHRcdHRoaXMuZ2V0X3BhcmVudCgpLnNldCggJ3F1aXpfZW5hYmxlZCcsICd5ZXMnICk7XG5cdFx0XHRcdH1cblx0XHRcdH0gKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBBZGQgYSBuZXcgcXVlc3Rpb24gdG8gdGhlIHF1aXpcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgZGF0YSAgIHF1ZXN0aW9uIGRhdGFcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0YWRkX3F1ZXN0aW9uOiBmdW5jdGlvbiggZGF0YSApIHtcblxuXHRcdFx0ZGF0YS5wYXJlbnRfaWQgPSB0aGlzLmdldCggJ2lkJyApO1xuXHRcdFx0dmFyIHF1ZXN0aW9uID0gdGhpcy5nZXQoICdxdWVzdGlvbnMnICkuYWRkKCBkYXRhLCB7XG5cdFx0XHRcdHBhcmVudDogdGhpcyxcblx0XHRcdH0gKTtcblx0XHRcdEJhY2tib25lLnB1YlN1Yi50cmlnZ2VyKCAncXVpei1hZGQtcXVlc3Rpb24nLCBxdWVzdGlvbiwgdGhpcyApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFJldHJpZXZlIHRoZSB0cmFuc2xhdGVkIHBvc3QgdHlwZSBuYW1lIGZvciB0aGUgbW9kZWwncyB0eXBlXG5cdFx0ICogQHBhcmFtICAgIGJvb2wgICAgIHBsdXJhbCAgaWYgdHJ1ZSwgcmV0dXJucyB0aGUgcGx1cmFsLCBvdGhlcndpc2UgcmV0dXJucyBzaW5ndWxhclxuXHRcdCAqIEByZXR1cm4gICBzdHJpbmdcblx0XHQgKiBAc2luY2UgICAgMy4xNi4xMlxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjEyXG5cdFx0ICovXG5cdFx0Z2V0X2wxMG5fdHlwZTogZnVuY3Rpb24oIHBsdXJhbCApIHtcblxuXHRcdFx0aWYgKCBwbHVyYWwgKSB7XG5cdFx0XHRcdHJldHVybiBMTE1TLmwxMG4udHJhbnNsYXRlKCAncXVpenplcycgKTtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIExMTVMubDEwbi50cmFuc2xhdGUoICdxdWl6JyApO1xuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBSZXRyaWV2ZSB0aGUgcXVpeidzIHRvdGFsIHBvaW50c1xuXHRcdCAqIEByZXR1cm4gICBpbnRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGdldF90b3RhbF9wb2ludHM6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHR2YXIgcG9pbnRzID0gMDtcblxuXHRcdFx0dGhpcy5nZXQoICdxdWVzdGlvbnMnICkuZWFjaCggZnVuY3Rpb24oIHF1ZXN0aW9uICkge1xuXHRcdFx0XHRwb2ludHMgKz0gcXVlc3Rpb24uZ2V0X3BvaW50cygpO1xuXHRcdFx0fSApO1xuXG5cdFx0XHRyZXR1cm4gcG9pbnRzO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIExhenkgbG9hZCBxdWVzdGlvbnMgdmlhIEFKQVhcblx0XHQgKiBAcGFyYW0gICAge0Z1bmN0aW9ufSAgY2IgIGNhbGxiYWNrIGZ1bmN0aW9uXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xOS4yXG5cdFx0ICogQHZlcnNpb24gIDMuMTkuMlxuXHRcdCAqL1xuXHRcdGxvYWRfcXVlc3Rpb25zOiBmdW5jdGlvbiggY2IgKSB7XG5cblx0XHRcdGlmICggdGhpcy5nZXQoICdfcXVlc3Rpb25zX2xvYWRlZCcgKSApIHtcblxuXHRcdFx0XHRjYigpO1xuXG5cdFx0XHR9IGVsc2Uge1xuXG5cdFx0XHRcdHZhciBzZWxmID0gdGhpcztcblxuXHRcdFx0XHRMTE1TLkFqYXguY2FsbCgge1xuXHRcdFx0XHRcdGRhdGE6IHtcblx0XHRcdFx0XHRcdGFjdGlvbjogJ2xsbXNfYnVpbGRlcicsXG5cdFx0XHRcdFx0XHRhY3Rpb25fdHlwZTogJ2xhenlfbG9hZCcsXG5cdFx0XHRcdFx0XHRjb3Vyc2VfaWQ6IHdpbmRvdy5sbG1zX2J1aWxkZXIuQ291cnNlTW9kZWwuZ2V0KCAnaWQnICksXG5cdFx0XHRcdFx0XHRsb2FkX2lkOiB0aGlzLmdldCggJ2lkJyApLFxuXHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0ZXJyb3I6IGZ1bmN0aW9uKCB4aHIsIHN0YXR1cywgZXJyb3IgKSB7XG5cblx0XHRcdFx0XHRcdGNvbnNvbGUubG9nKCB4aHIsIHN0YXR1cywgZXJyb3IgKTtcblx0XHRcdFx0XHRcdHdpbmRvdy5sbG1zX2J1aWxkZXIuZGVidWcubG9nKCAnPT09PSBzdGFydCBsb2FkX3F1ZXN0aW9ucyBlcnJvciA9PT09JywgeGhyLCBzdGF0dXMsIGVycm9yLCAnPT09PSBmaW5pc2ggbG9hZF9xdWVzdGlvbnMgZXJyb3IgPT09PScgKTtcblx0XHRcdFx0XHRcdGNiKCB0cnVlICk7XG5cblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdHN1Y2Nlc3M6IGZ1bmN0aW9uKCByZXMgKSB7XG5cdFx0XHRcdFx0XHRpZiAoIHJlcyAmJiByZXMucXVlc3Rpb25zICkge1xuXHRcdFx0XHRcdFx0XHRzZWxmLnNldCggJ19xdWVzdGlvbnNfbG9hZGVkJywgdHJ1ZSApO1xuXHRcdFx0XHRcdFx0XHRpZiAoIHJlcy5xdWVzdGlvbnMgKSB7XG5cdFx0XHRcdFx0XHRcdFx0Xy5lYWNoKCByZXMucXVlc3Rpb25zLCBzZWxmLmFkZF9xdWVzdGlvbiwgc2VsZiApO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdGNiKCk7XG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRjYiggdHJ1ZSApO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHR9ICk7XG5cblx0XHRcdH1cblxuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFVwZGF0ZSB0b3RhbCBudW1iZXIgb2YgcG9pbnRzIGNhbGN1bGF0ZWQgcHJvcGVydHlcblx0XHQgKiBAcmV0dXJuICAgaW50XG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHR1cGRhdGVfcG9pbnRzOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0dGhpcy5zZXQoICdfcG9pbnRzJywgdGhpcy5nZXRfdG90YWxfcG9pbnRzKCkgKTtcblxuXHRcdH0sXG5cblx0fSwgUmVsYXRpb25zaGlwcywgVXRpbGl0aWVzICkgKTtcblxufSApO1xuXG4vKipcbiAqIExlc3NvbiBTY2hlbWFzXG4gKiBAc2luY2UgICAgMy4xNy4wXG4gKiBAdmVyc2lvbiAgMy4xNy4xXG4gKi9cbmRlZmluZSggJ1NjaGVtYXMvTGVzc29uJyxbXSwgZnVuY3Rpb24oKSB7XG5cblx0cmV0dXJuIHtcblxuXHRcdGRlZmF1bHQ6IHtcblx0XHRcdHRpdGxlOiBMTE1TLmwxMG4udHJhbnNsYXRlKCAnR2VuZXJhbCBTZXR0aW5ncycgKSxcblx0XHRcdHRvZ2dsZWFibGU6IHRydWUsXG5cdFx0XHRmaWVsZHM6IFtcblx0XHRcdFx0W1xuXHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdGF0dHJpYnV0ZTogJ3Blcm1hbGluaycsXG5cdFx0XHRcdFx0XHRpZDogJ3Blcm1hbGluaycsXG5cdFx0XHRcdFx0XHR0eXBlOiAncGVybWFsaW5rJyxcblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRdLCBbXG5cdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0YXR0cmlidXRlOiAndmlkZW9fZW1iZWQnLFxuXHRcdFx0XHRcdFx0aWQ6ICd2aWRlby1lbWJlZCcsXG5cdFx0XHRcdFx0XHRsYWJlbDogTExNUy5sMTBuLnRyYW5zbGF0ZSggJ1ZpZGVvIEVtYmVkIFVSTCcgKSxcblx0XHRcdFx0XHRcdHR5cGU6ICd2aWRlb19lbWJlZCcsXG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRhdHRyaWJ1dGU6ICdhdWRpb19lbWJlZCcsXG5cdFx0XHRcdFx0XHRpZDogJ2F1ZGlvLWVtYmVkJyxcblx0XHRcdFx0XHRcdGxhYmVsOiBMTE1TLmwxMG4udHJhbnNsYXRlKCAnQXVkaW8gRW1iZWQgVVJMJyApLFxuXHRcdFx0XHRcdFx0dHlwZTogJ2F1ZGlvX2VtYmVkJyxcblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRdLCBbXG5cdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0YXR0cmlidXRlOiAnZnJlZV9sZXNzb24nLFxuXHRcdFx0XHRcdFx0aWQ6ICdmcmVlLWxlc3NvbicsXG5cdFx0XHRcdFx0XHRsYWJlbDogTExNUy5sMTBuLnRyYW5zbGF0ZSggJ0ZyZWUgTGVzc29uJyApLFxuXHRcdFx0XHRcdFx0dGlwOiBMTE1TLmwxMG4udHJhbnNsYXRlKCBcIkZyZWUgbGVzc29ucyBjYW4gYmUgYWNjZXNzZWQgd2l0aG91dCBlbnJvbGxtZW50LlwiICksXG5cdFx0XHRcdFx0XHR0eXBlOiAnc3dpdGNoJyxcblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdGF0dHJpYnV0ZTogJ3JlcXVpcmVfcGFzc2luZ19ncmFkZScsXG5cdFx0XHRcdFx0XHRpZDogJ3JlcXVpcmUtcGFzc2luZy1ncmFkZScsXG5cdFx0XHRcdFx0XHRsYWJlbDogTExNUy5sMTBuLnRyYW5zbGF0ZSggJ1JlcXVpcmUgUGFzc2luZyBHcmFkZSBvbiBRdWl6JyApLFxuXHRcdFx0XHRcdFx0dGlwOiBMTE1TLmwxMG4udHJhbnNsYXRlKCBcIldoZW4gZW5hYmxlZCwgc3R1ZGVudHMgbXVzdCBwYXNzIHRoaXMgbGVzc29uJ3MgcXVpeiBiZWZvcmUgdGhlIGxlc3NvbiBjYW4gYmUgY29tcGxldGVkLlwiICksXG5cdFx0XHRcdFx0XHR0eXBlOiAnc3dpdGNoJyxcblx0XHRcdFx0XHRcdGNvbmRpdGlvbjogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHRcdHJldHVybiAoICd5ZXMnID09PSB0aGlzLmdldCggJ3F1aXpfZW5hYmxlZCcgKSApO1xuXHRcdFx0XHRcdFx0fSxcblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdGF0dHJpYnV0ZTogJ3JlcXVpcmVfYXNzaWdubWVudF9wYXNzaW5nX2dyYWRlJyxcblx0XHRcdFx0XHRcdGlkOiAncmVxdWlyZS1hc3NpZ25tZW50LXBhc3NpbmctZ3JhZGUnLFxuXHRcdFx0XHRcdFx0bGFiZWw6IExMTVMubDEwbi50cmFuc2xhdGUoICdSZXF1aXJlIFBhc3NpbmcgR3JhZGUgb24gQXNzaWdubWVudCcgKSxcblx0XHRcdFx0XHRcdHRpcDogTExNUy5sMTBuLnRyYW5zbGF0ZSggXCJXaGVuIGVuYWJsZWQsIHN0dWRlbnRzIG11c3QgcGFzcyB0aGlzIGxlc3NvbidzIGFzc2lnbm1lbnQgYmVmb3JlIHRoZSBsZXNzb24gY2FuIGJlIGNvbXBsZXRlZC5cIiApLFxuXHRcdFx0XHRcdFx0dHlwZTogJ3N3aXRjaCcsXG5cdFx0XHRcdFx0XHRjb25kaXRpb246IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdFx0XHRyZXR1cm4gKCAndW5kZWZpbmVkJyAhPT0gd2luZG93LmxsbXNfYnVpbGRlci5hc3NpZ25tZW50cyAmJiAneWVzJyA9PT0gdGhpcy5nZXQoICdhc3NpZ25tZW50X2VuYWJsZWQnICkgKTtcblx0XHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XSwgW1xuXHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdGF0dHJpYnV0ZTogJ3ByZXJlcXVpc2l0ZScsXG5cdFx0XHRcdFx0XHRjb25kaXRpb246IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdFx0XHRyZXR1cm4gKCBmYWxzZSA9PT0gdGhpcy5pc19maXJzdF9pbl9jb3Vyc2UoKSApO1xuXHRcdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRcdGlkOiAncHJlcmVxdWlzaXRlJyxcblx0XHRcdFx0XHRcdGxhYmVsOiBMTE1TLmwxMG4udHJhbnNsYXRlKCAnUHJlcmVxdWlzaXRlJyApLFxuXHRcdFx0XHRcdFx0c3dpdGNoX2F0dHJpYnV0ZTogJ2hhc19wcmVyZXF1aXNpdGUnLFxuXHRcdFx0XHRcdFx0dHlwZTogJ3N3aXRjaC1zZWxlY3QnLFxuXHRcdFx0XHRcdFx0b3B0aW9uczogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHRcdHJldHVybiB0aGlzLmdldF9hdmFpbGFibGVfcHJlcmVxX29wdGlvbnMoKTtcblx0XHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XSwgW1xuXHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdGF0dHJpYnV0ZTogJ2RyaXBfbWV0aG9kJyxcblx0XHRcdFx0XHRcdGlkOiAnZHJpcC1tZXRob2QnLFxuXHRcdFx0XHRcdFx0bGFiZWw6IExMTVMubDEwbi50cmFuc2xhdGUoICdEcmlwIE1ldGhvZCcgKSxcblx0XHRcdFx0XHRcdHN3aXRjaF9hdHRyaWJ1dGU6ICdkcmlwX21ldGhvZCcsXG5cdFx0XHRcdFx0XHR0eXBlOiAnc2VsZWN0Jyxcblx0XHRcdFx0XHRcdG9wdGlvbnM6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHRcdFx0XHRcdHZhciBvcHRpb25zID0gW1xuXHRcdFx0XHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdFx0XHRcdGtleTogJycsXG5cdFx0XHRcdFx0XHRcdFx0XHR2YWw6IExMTVMubDEwbi50cmFuc2xhdGUoICdOb25lJyApLFxuXHRcdFx0XHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0XHRcdFx0a2V5OiAnZGF0ZScsXG5cdFx0XHRcdFx0XHRcdFx0XHR2YWw6IExMTVMubDEwbi50cmFuc2xhdGUoICdPbiBhIHNwZWNpZmljIGRhdGUnICksXG5cdFx0XHRcdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRcdFx0XHRrZXk6ICdlbnJvbGxtZW50Jyxcblx0XHRcdFx0XHRcdFx0XHRcdHZhbDogTExNUy5sMTBuLnRyYW5zbGF0ZSggJyMgb2YgZGF5cyBhZnRlciBjb3Vyc2UgZW5yb2xsbWVudCcgKSxcblx0XHRcdFx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdFx0XHRdO1xuXG5cdFx0XHRcdFx0XHRcdGlmICggdGhpcy5nZXRfY291cnNlKCkuZ2V0KCAnc3RhcnRfZGF0ZScgKSApIHtcblx0XHRcdFx0XHRcdFx0XHRvcHRpb25zLnB1c2goIHtcblx0XHRcdFx0XHRcdFx0XHRcdGtleTogJ3N0YXJ0Jyxcblx0XHRcdFx0XHRcdFx0XHRcdHZhbDogTExNUy5sMTBuLnRyYW5zbGF0ZSggJyMgb2YgZGF5cyBhZnRlciBjb3Vyc2Ugc3RhcnQgZGF0ZScgKSxcblx0XHRcdFx0XHRcdFx0XHR9ICk7XG5cdFx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0XHRpZiAoICd5ZXMnID09PSB0aGlzLmdldCggJ2hhc19wcmVyZXF1aXNpdGUnICkgKSB7XG5cdFx0XHRcdFx0XHRcdFx0b3B0aW9ucy5wdXNoKCB7XG5cdFx0XHRcdFx0XHRcdFx0XHRrZXk6ICdwcmVyZXF1aXNpdGUnLFxuXHRcdFx0XHRcdFx0XHRcdFx0dmFsOiBMTE1TLmwxMG4udHJhbnNsYXRlKCAnIyBvZiBkYXlzIGFmdGVyIHByZXJlcXVpc2l0ZSBsZXNzb24gY29tcGxldGlvbicgKSxcblx0XHRcdFx0XHRcdFx0XHR9ICk7XG5cdFx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0XHRyZXR1cm4gb3B0aW9ucztcblxuXHRcdFx0XHRcdFx0fSxcblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdGF0dHJpYnV0ZTogJ2RheXNfYmVmb3JlX2F2YWlsYWJsZScsXG5cdFx0XHRcdFx0XHRjb25kaXRpb246IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdFx0XHRyZXR1cm4gKCAtMSAhPT0gWyAnZW5yb2xsbWVudCcsICdzdGFydCcsICdwcmVyZXF1aXNpdGUnIF0uaW5kZXhPZiggdGhpcy5nZXQoICdkcmlwX21ldGhvZCcgKSApICk7XG5cdFx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdFx0aWQ6ICdkYXlzLWJlZm9yZS1hdmFpbGFibGUnLFxuXHRcdFx0XHRcdFx0bGFiZWw6IExMTVMubDEwbi50cmFuc2xhdGUoICcjIG9mIGRheXMnICksXG5cdFx0XHRcdFx0XHRtaW46IDAsXG5cdFx0XHRcdFx0XHR0eXBlOiAnbnVtYmVyJyxcblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdGF0dHJpYnV0ZTogJ2RhdGVfYXZhaWxhYmxlJyxcblx0XHRcdFx0XHRcdGRhdGVfZm9ybWF0OiAnWS1tLWQnLFxuXHRcdFx0XHRcdFx0Y29uZGl0aW9uOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRcdFx0cmV0dXJuICggJ2RhdGUnID09PSB0aGlzLmdldCggJ2RyaXBfbWV0aG9kJyApICk7XG5cdFx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdFx0aWQ6ICdkYXRlLWF2YWlsYWJsZScsXG5cdFx0XHRcdFx0XHRsYWJlbDogTExNUy5sMTBuLnRyYW5zbGF0ZSggJ0RhdGUnICksXG5cdFx0XHRcdFx0XHR0aW1lcGlja2VyOiAnZmFsc2UnLFxuXHRcdFx0XHRcdFx0dHlwZTogJ2RhdGVwaWNrZXInLFxuXHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0YXR0cmlidXRlOiAndGltZV9hdmFpbGFibGUnLFxuXHRcdFx0XHRcdFx0Y29uZGl0aW9uOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRcdFx0cmV0dXJuICggJ2RhdGUnID09PSB0aGlzLmdldCggJ2RyaXBfbWV0aG9kJyApICk7XG5cdFx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdFx0ZGF0ZXBpY2tlcjogJ2ZhbHNlJyxcblx0XHRcdFx0XHRcdGRhdGVfZm9ybWF0OiAnaDppIEEnLFxuXHRcdFx0XHRcdFx0aWQ6ICd0aW1lLWF2YWlsYWJsZScsXG5cdFx0XHRcdFx0XHRsYWJlbDogTExNUy5sMTBuLnRyYW5zbGF0ZSggJ1RpbWUnICksXG5cdFx0XHRcdFx0XHR0eXBlOiAnZGF0ZXBpY2tlcicsXG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XSxcblx0XHRcdF0sXG5cdFx0fSxcblxuXHR9O1xuXG59ICk7XG5cbi8qKlxuICogTGVzc29uIE1vZGVsXG4gKiBAc2luY2UgICAgMy4xMy4wXG4gKiBAdmVyc2lvbiAgMy4xOS4zXG4gKi9cbmRlZmluZSggJ01vZGVscy9MZXNzb24nLFsgJ01vZGVscy9RdWl6JywgJ01vZGVscy9fUmVsYXRpb25zaGlwcycsICdNb2RlbHMvX1V0aWxpdGllcycsICdTY2hlbWFzL0xlc3NvbicgXSwgZnVuY3Rpb24oIFF1aXosIFJlbGF0aW9uc2hpcHMsIFV0aWxpdGllcywgTGVzc29uU2NoZW1hICkge1xuXG5cdHJldHVybiBCYWNrYm9uZS5Nb2RlbC5leHRlbmQoIF8uZGVmYXVsdHMoIHtcblxuXHRcdC8qKlxuXHRcdCAqIE1vZGVsIHJlbGF0aW9uc2hpcHNcblx0XHQgKiBAdHlwZSAge09iamVjdH1cblx0XHQgKi9cblx0XHRyZWxhdGlvbnNoaXBzOiB7XG5cdFx0XHRwYXJlbnRzOiB7XG5cdFx0XHRcdG1vZGVsOiAnc2VjdGlvbicsXG5cdFx0XHRcdHR5cGU6ICdtb2RlbCcsXG5cdFx0XHR9LFxuXHRcdFx0Y2hpbGRyZW46IHtcblx0XHRcdFx0cXVpejoge1xuXHRcdFx0XHRcdGNsYXNzOiAnUXVpeicsXG5cdFx0XHRcdFx0Y29uZGl0aW9uYWw6IGZ1bmN0aW9uKCBtb2RlbCApIHtcblx0XHRcdFx0XHRcdC8vIGlmIHF1aXogaXMgZW5hYmxlZCBPUiBub3QgZW5hYmxlZCBidXQgd2UgaGF2ZSBzb21lIHF1aXogZGF0YSBhcyBhbiBvYmpcblx0XHRcdFx0XHRcdHJldHVybiAoICd5ZXMnID09PSBtb2RlbC5nZXQoICdxdWl6X2VuYWJsZWQnICkgfHwgISBfLmlzRW1wdHkoIG1vZGVsLmdldCggJ3F1aXonICkgKSApO1xuXHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0bW9kZWw6ICdsbG1zX3F1aXonLFxuXHRcdFx0XHRcdHR5cGU6ICdtb2RlbCcsXG5cdFx0XHRcdH0sXG5cdFx0XHR9LFxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBMZXNzb24gU2V0dGluZ3MgU2NoZW1hXG5cdFx0ICogQHR5cGUgIHtPYmplY3R9XG5cdFx0ICovXG5cdFx0c2NoZW1hOiBMZXNzb25TY2hlbWEsXG5cblx0XHQvKipcblx0XHQgKiBOZXcgbGVzc29uIGRlZmF1bHRzXG5cdFx0ICogQHJldHVybiAgIG9ialxuXHRcdCAqIEBzaW5jZSAgICAzLjEzLjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNy4xXG5cdFx0ICovXG5cdFx0ZGVmYXVsdHM6IGZ1bmN0aW9uKCkge1xuXHRcdFx0cmV0dXJuIHtcblx0XHRcdFx0aWQ6IF8udW5pcXVlSWQoICd0ZW1wXycgKSxcblx0XHRcdFx0dGl0bGU6IExMTVMubDEwbi50cmFuc2xhdGUoICdOZXcgTGVzc29uJyApLFxuXHRcdFx0XHR0eXBlOiAnbGVzc29uJyxcblx0XHRcdFx0b3JkZXI6IHRoaXMuY29sbGVjdGlvbiA/IHRoaXMuY29sbGVjdGlvbi5sZW5ndGggKyAxIDogMSxcblx0XHRcdFx0cGFyZW50X2NvdXJzZTogd2luZG93LmxsbXNfYnVpbGRlci5jb3Vyc2UuaWQsXG5cdFx0XHRcdHBhcmVudF9zZWN0aW9uOiAnJyxcblxuXHRcdFx0XHQvLyB1cmxzXG5cdFx0XHRcdGVkaXRfdXJsOiAnJyxcblx0XHRcdFx0dmlld191cmw6ICcnLFxuXG5cdFx0XHRcdC8vIGVkaXRhYmxlIGZpZWxkc1xuXHRcdFx0XHRjb250ZW50OiAnJyxcblx0XHRcdFx0YXVkaW9fZW1iZWQ6ICcnLFxuXHRcdFx0XHRoYXNfcHJlcmVxdWlzaXRlOiAnbm8nLFxuXHRcdFx0XHRyZXF1aXJlX3Bhc3NpbmdfZ3JhZGU6ICd5ZXMnLFxuXHRcdFx0XHRyZXF1aXJlX2Fzc2lnbm1lbnRfcGFzc2luZ19ncmFkZTogJ3llcycsXG5cdFx0XHRcdHZpZGVvX2VtYmVkOiAnJyxcblx0XHRcdFx0ZnJlZV9sZXNzb246ICcnLFxuXG5cdFx0XHRcdC8vIG90aGVyIGZpZWxkc1xuXHRcdFx0XHRhc3NpZ25tZW50OiB7fSwgLy8gYXNzaWdubWVudCBtb2RlbC9kYXRhXG5cdFx0XHRcdGFzc2lnbm1lbnRfZW5hYmxlZDogJ25vJyxcblxuXHRcdFx0XHRxdWl6OiB7fSwgLy8gcXVpeiBtb2RlbC9kYXRhXG5cdFx0XHRcdHF1aXpfZW5hYmxlZDogJ25vJyxcblxuXHRcdFx0XHRfZm9yY2VTeW5jOiBmYWxzZSxcblxuXHRcdFx0fTtcblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogSW5pdGlhbGl6ZXJcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNy4wXG5cdFx0ICovXG5cdFx0aW5pdGlhbGl6ZTogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHRoaXMuaW5pdF9jdXN0b21fc2NoZW1hKCk7XG5cdFx0XHR0aGlzLnN0YXJ0VHJhY2tpbmcoKTtcblx0XHRcdHRoaXMubWF5YmVfaW5pdF9hc3NpZ25tZW50cygpO1xuXHRcdFx0dGhpcy5pbml0X3JlbGF0aW9uc2hpcHMoKTtcblxuXHRcdFx0Ly8gaWYgdGhlIGxlc3NvbiBJRCBpc24ndCBzZXQgb24gYSBxdWl6LCBzZXQgaXRcblx0XHRcdHZhciBxdWl6ID0gdGhpcy5nZXQoICdxdWl6JyApO1xuXHRcdFx0aWYgKCAhIF8uaXNFbXB0eSggcXVpeiApICYmICEgcXVpei5nZXQoICdsZXNzb25faWQnICkgKSB7XG5cdFx0XHRcdHF1aXouc2V0KCAnbGVzc29uX2lkJywgdGhpcy5nZXQoICdpZCcgKSApO1xuXHRcdFx0fVxuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFJldHJpZXZlIGEgcmVmZXJlbmNlIHRvIHRoZSBwYXJlbnQgY291cnNlIG9mIHRoZSBsZXNzb25cblx0XHQgKiBAcmV0dXJuICAgb2JqXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRnZXRfY291cnNlOiBmdW5jdGlvbigpIHtcblx0XHRcdHJldHVybiB0aGlzLmdldF9wYXJlbnQoKS5nZXRfcGFyZW50KCk7XG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFJldHJpZXZlIHRoZSB0cmFuc2xhdGVkIHBvc3QgdHlwZSBuYW1lIGZvciB0aGUgbW9kZWwncyB0eXBlXG5cdFx0ICogQHBhcmFtICAgIGJvb2wgICAgIHBsdXJhbCAgaWYgdHJ1ZSwgcmV0dXJucyB0aGUgcGx1cmFsLCBvdGhlcndpc2UgcmV0dXJucyBzaW5ndWxhclxuXHRcdCAqIEByZXR1cm4gICBzdHJpbmdcblx0XHQgKiBAc2luY2UgICAgMy4xNi4xMlxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjEyXG5cdFx0ICovXG5cdFx0Z2V0X2wxMG5fdHlwZTogZnVuY3Rpb24oIHBsdXJhbCApIHtcblxuXHRcdFx0aWYgKCBwbHVyYWwgKSB7XG5cdFx0XHRcdHJldHVybiBMTE1TLmwxMG4udHJhbnNsYXRlKCAnbGVzc29ucycgKTtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIExMTVMubDEwbi50cmFuc2xhdGUoICdsZXNzb24nICk7XG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIE92ZXJyaWRlIGRlZmF1bHQgZ2V0X3BhcmVudCB0byBncmFiIGZyb20gY29sbGVjdGlvbiBpZiBtb2RlbHMgcGFyZW50IGlzbid0IHNldFxuXHRcdCAqIEByZXR1cm4gICBvYmpcblx0XHQgKiBAc2luY2UgICAgMy4xNy4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTcuMFxuXHRcdCAqL1xuXHRcdGdldF9wYXJlbnQ6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHR2YXIgcmVscyA9IHRoaXMuZ2V0X3JlbGF0aW9uc2hpcHMoKTtcblx0XHRcdGlmICggcmVscy5wYXJlbnQgJiYgcmVscy5wYXJlbnQucmVmZXJlbmNlICkge1xuXHRcdFx0XHRyZXR1cm4gcmVscy5wYXJlbnQucmVmZXJlbmNlO1xuXHRcdFx0fSBlbHNlIGlmICggdGhpcy5jb2xsZWN0aW9uICYmIHRoaXMuY29sbGVjdGlvbi5wYXJlbnQgKSB7XG5cdFx0XHRcdHJldHVybiB0aGlzLmNvbGxlY3Rpb24ucGFyZW50O1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFJldHJpZXZlIGFuIGFycmF5IG9mIHByZXJlcXVpc2l0ZSBvcHRpb25zIGF2YWlsYWJsZSBmb3IgdGhlIGN1cnJlbnQgbGVzc29uXG5cdFx0ICogQHJldHVybiAgIG9ialxuXHRcdCAqIEBzaW5jZSAgICAzLjE3LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNy4wXG5cdFx0ICovXG5cdFx0Z2V0X2F2YWlsYWJsZV9wcmVyZXFfb3B0aW9uczogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHZhciBwYXJlbnRfc2VjdGlvbl9pbmRleCA9IHRoaXMuZ2V0X3BhcmVudCgpLmNvbGxlY3Rpb24uaW5kZXhPZiggdGhpcy5nZXRfcGFyZW50KCkgKSxcblx0XHRcdFx0bGVzc29uX2luZGV4X2luX3NlY3Rpb24gPSB0aGlzLmNvbGxlY3Rpb24uaW5kZXhPZiggdGhpcyApLFxuXHRcdFx0XHRvcHRpb25zID0gW107XG5cblx0XHRcdHRoaXMuZ2V0X2NvdXJzZSgpLmdldCggJ3NlY3Rpb25zJyApLmVhY2goIGZ1bmN0aW9uKCBzZWN0aW9uLCBjdXJyX3NlY19pbmRleCApIHtcblx0XHRcdFx0aWYgKCBjdXJyX3NlY19pbmRleCA8PSBwYXJlbnRfc2VjdGlvbl9pbmRleCApIHtcblx0XHRcdFx0XHR2YXIgZ3JvdXAgPSB7XG5cdFx0XHRcdFx0XHRcdC8qIHRyYW5zbGF0b3JzOiAlMSRkID0gc2VjdGlvbiBvcmRlciBudW1iZXIsICUyJHMgPSBzZWN0aW9uIHRpdGxlICovXG5cdFx0XHRcdFx0XHRcdGxhYmVsOiBMTE1TLmwxMG4ucmVwbGFjZSggJ1NlY3Rpb24gJTEkZDogJTIkcycsIHtcblx0XHRcdFx0XHRcdFx0XHQnJTEkZCc6IHNlY3Rpb24uZ2V0KCAnb3JkZXInICksXG5cdFx0XHRcdFx0XHRcdFx0JyUyJHMnOiBzZWN0aW9uLmdldCggJ3RpdGxlJyApXG5cdFx0XHRcdFx0XHRcdH0gKSxcblx0XHRcdFx0XHRcdFx0b3B0aW9uczogW10sXG5cdFx0XHRcdFx0XHR9O1xuXG5cdFx0XHRcdFx0c2VjdGlvbi5nZXQoICdsZXNzb25zJyApLmVhY2goIGZ1bmN0aW9uKCBsZXNzb24sIGN1cnJfbGVzX2luZGV4ICkge1xuXHRcdFx0XHRcdFx0aWYgKCBjdXJyX3NlY19pbmRleCAhPT0gcGFyZW50X3NlY3Rpb25faW5kZXggfHwgY3Vycl9sZXNfaW5kZXggPCBsZXNzb25faW5kZXhfaW5fc2VjdGlvbiApIHtcblx0XHRcdFx0XHRcdFx0LyogdHJhbnNsYXRvcnM6ICUxJGQgPSBsZXNzb24gb3JkZXIgbnVtYmVyLCAlMiRzID0gbGVzc29uIHRpdGxlICovXG5cdFx0XHRcdFx0XHRcdGdyb3VwLm9wdGlvbnMucHVzaCgge1xuXHRcdFx0XHRcdFx0XHRcdGtleTogbGVzc29uLmdldCggJ2lkJyApLFxuXHRcdFx0XHRcdFx0XHRcdHZhbDogTExNUy5sMTBuLnJlcGxhY2UoICdMZXNzb24gJTEkZDogJTIkcycsIHtcblx0XHRcdFx0XHRcdFx0XHRcdCclMSRkJzogbGVzc29uLmdldCggJ29yZGVyJyApLFxuXHRcdFx0XHRcdFx0XHRcdFx0JyUyJHMnOiBsZXNzb24uZ2V0KCAndGl0bGUnIClcblx0XHRcdFx0XHRcdFx0XHR9ICksXG5cdFx0XHRcdFx0XHRcdH0gKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9LCB0aGlzICk7XG5cblx0XHRcdFx0XHRvcHRpb25zLnB1c2goIGdyb3VwICk7XG5cdFx0XHRcdH1cblx0XHRcdH0sIHRoaXMgKTtcblxuXHRcdFx0cmV0dXJuIG9wdGlvbnM7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogQWRkIGEgbmV3IHF1aXogdG8gdGhlIGxlc3NvblxuXHRcdCAqIEBwYXJhbSAgICBvYmogICBkYXRhICAgb2JqZWN0IG9mIHF1aXogZGF0YSB1c2VkIHRvIGNvbnN0cnVjdCBhIG5ldyBxdWl6IG1vZGVsXG5cdFx0ICogQHJldHVybiAgIG9iaiAgICAgICAgICBtb2RlbCBmb3IgdGhlIGNyZWF0ZWQgcXVpelxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xOS4zXG5cdFx0ICovXG5cdFx0YWRkX3F1aXo6IGZ1bmN0aW9uKCBkYXRhICkge1xuXG5cdFx0XHRkYXRhID0gZGF0YSB8fCB7fTtcblxuXHRcdFx0ZGF0YS5sZXNzb25faWQgPSB0aGlzLmlkO1xuXHRcdFx0ZGF0YS5fcXVlc3Rpb25zX2xvYWRlZCA9IHRydWU7XG5cblx0XHRcdGlmICggISBkYXRhLnRpdGxlICkge1xuXG5cdFx0XHRcdGRhdGEudGl0bGUgPSBMTE1TLmwxMG4ucmVwbGFjZSggJyUxJHMgUXVpeicsIHtcblx0XHRcdFx0XHQnJTEkcyc6IHRoaXMuZ2V0KCAndGl0bGUnICksXG5cdFx0XHRcdH0gKTtcblxuXHRcdFx0fVxuXG5cdFx0XHR0aGlzLnNldCggJ3F1aXonLCBkYXRhICk7XG5cdFx0XHR0aGlzLmluaXRfcmVsYXRpb25zaGlwcygpO1xuXG5cdFx0XHR2YXIgcXVpeiA9IHRoaXMuZ2V0KCAncXVpeicgKTtcblx0XHRcdHRoaXMuc2V0KCAncXVpel9lbmFibGVkJywgJ3llcycgKTtcblxuXHRcdFx0cmV0dXJuIHF1aXo7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogRGV0ZXJtaW5lIGlmIHRoaXMgaXMgdGhlIGZpcnN0IGxlc3NvblxuXHRcdCAqIEByZXR1cm4gICB7Qm9vbGVhbn1cblx0XHQgKiBAc2luY2UgICAgMy4xNy4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTcuMFxuXHRcdCAqL1xuXHRcdGlzX2ZpcnN0X2luX2NvdXJzZTogZnVuY3Rpb24oKSB7XG5cblx0XHRcdC8vIGlmIGl0J3Mgbm90IHRoZSBmaXJzdCBpdGVtIGluIHRoZSBzZWN0aW9uIGl0IGNhbnQgYmUgdGhlIGZpcnN0IGxlc3NvblxuXHRcdFx0aWYgKCB0aGlzLmNvbGxlY3Rpb24uaW5kZXhPZiggdGhpcyApICkge1xuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHR9XG5cblx0XHRcdC8vIGlmIGl0J3Mgbm90IHRoZSBmaXJzdCBzZWN0aW9uIGl0IGNhbnQnIGJlIGZpcnN0IGxlc3NvblxuXHRcdFx0dmFyIHNlY3Rpb24gPSB0aGlzLmdldF9wYXJlbnQoKTtcblx0XHRcdGlmICggc2VjdGlvbi5jb2xsZWN0aW9uLmluZGV4T2YoIHNlY3Rpb24gKSApIHtcblx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBpdCdzIGZpcnN0IGxlc3NvbiBpbiBmaXJzdCBzZWN0aW9uXG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBJbml0aWFsaXplIGxlc3NvbiBhc3NpZ25tZW50cyAqaWYqIHRoZSBhc3NpZ25tZW50cyBhZGRvbiBpcyBhdmFpbGFsYmUgYW5kIGVuYWJsZWRcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE3LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNy4wXG5cdFx0ICovXG5cdFx0bWF5YmVfaW5pdF9hc3NpZ25tZW50czogZnVuY3Rpb24oKSB7XG5cblx0XHRcdGlmICggISB3aW5kb3cubGxtc19idWlsZGVyLmFzc2lnbm1lbnRzICkge1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cblx0XHRcdHRoaXMucmVsYXRpb25zaGlwcy5jaGlsZHJlbi5hc3NpZ25tZW50ID0ge1xuXHRcdFx0XHRjbGFzczogJ0Fzc2lnbm1lbnQnLFxuXHRcdFx0XHRjb25kaXRpb25hbDogZnVuY3Rpb24oIG1vZGVsICkge1xuXHRcdFx0XHRcdC8vIGlmIGFzc2lnbm1lbnQgaXMgZW5hYmxlZCBPUiBub3QgZW5hYmxlZCBidXQgd2UgaGF2ZSBzb21lIGFzc2lnbm1lbnQgZGF0YSBhcyBhbiBvYmpcblx0XHRcdFx0XHRyZXR1cm4gKCAneWVzJyA9PT0gbW9kZWwuZ2V0KCAnYXNzaWdubWVudF9lbmFibGVkJyApIHx8ICEgXy5pc0VtcHR5KCBtb2RlbC5nZXQoICdhc3NpZ25tZW50JyApICkgKTtcblx0XHRcdFx0fSxcblx0XHRcdFx0bW9kZWw6ICdsbG1zX2Fzc2lnbm1lbnQnLFxuXHRcdFx0XHR0eXBlOiAnbW9kZWwnLFxuXHRcdFx0fTtcblxuXHRcdH0sXG5cblx0fSwgUmVsYXRpb25zaGlwcywgVXRpbGl0aWVzICkgKTtcblxufSApO1xuXG4vKipcbiAqIExlc3NvbnMgQ29sbGVjdGlvblxuICogQHNpbmNlICAgIDMuMTMuMFxuICogQHZlcnNpb24gIDMuMTcuMFxuICovXG5kZWZpbmUoICdDb2xsZWN0aW9ucy9MZXNzb25zJyxbICdNb2RlbHMvTGVzc29uJyBdLCBmdW5jdGlvbiggbW9kZWwgKSB7XG5cblx0cmV0dXJuIEJhY2tib25lLkNvbGxlY3Rpb24uZXh0ZW5kKCB7XG5cblx0XHQvKipcblx0XHQgKiBNb2RlbCBmb3IgY29sbGVjdGlvbiBpdGVtc1xuXHRcdCAqIEB0eXBlICBvYmpcblx0XHQgKi9cblx0XHRtb2RlbDogbW9kZWwsXG5cblx0XHQvKipcblx0XHQgKiBJbml0aWFsaXplclxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE3LjBcblx0XHQgKi9cblx0XHRpbml0aWFsaXplOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0Ly8gcmVvcmRlciBjYWxsZWQgYnkgTGVzc29uTGlzdCB2aWV3IHdoZW4gc29ydGFibGUgZHJvcHMgb2NjdXJcblx0XHRcdHRoaXMub24oICdyZW9yZGVyJywgdGhpcy5vbl9yZW9yZGVyICk7XG5cblx0XHRcdC8vIHdoZW4gYSBsZXNzb24gaXMgYWRkZWQgb3IgcmVtb3ZlZCwgdXBkYXRlIG9yZGVyXG5cdFx0XHR0aGlzLm9uKCAnYWRkJywgdGhpcy5vbl9yZW9yZGVyICk7XG5cdFx0XHR0aGlzLm9uKCAncmVtb3ZlJywgdGhpcy5vbl9yZW9yZGVyICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogT24gbGVzc29uIHJlb3JkZXIgY2FsbGJhY2tcblx0XHQgKlxuXHRcdCAqIFVwZGF0ZSB0aGUgb3JkZXIgYXR0ciBvZiBlYWNoIGxlc3NvbiB0byByZWZsZWN0IHRoZSBuZXcgbGVzc29uIG9yZGVyXG5cdFx0ICogVmFsaWRhdGUgcHJlcmVxdWlzaXRlIChpZiBzZXQpIGFuZCB1bnNldCBpdCBpZiBpdCdzIG5vIGxvbmdlciBhIHZhbGlkIHByZXJlcVxuXHRcdCAqXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNy4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTcuMFxuXHRcdCAqL1xuXHRcdG9uX3Jlb3JkZXI6IGZ1bmN0aW9uKCkge1xuXHRcdFx0dGhpcy51cGRhdGVfb3JkZXIoKTtcblx0XHRcdHRoaXMudmFsaWRhdGVfcHJlcmVxcygpO1xuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBVcGRhdGUgbGVzc29uIG9yZGVyIGF0dHJpYnV0ZSBvZiBhbGwgbGVzc29ucyB3aGVuIGxlc3NvbnMgYXJlIHJlb3JkZXJlZFxuXHRcdCAqIEByZXR1cm4gICAgICB2b2lkXG5cdFx0ICogQHNpbmNlICAgICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAgICAzLjE3LjBcblx0XHQgKi9cblx0XHR1cGRhdGVfb3JkZXI6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHR0aGlzLmVhY2goIGZ1bmN0aW9uKCBsZXNzb24gKSB7XG5cdFx0XHRcdGxlc3Nvbi5zZXQoICdvcmRlcicsIHRoaXMuaW5kZXhPZiggbGVzc29uICkgKyAxICk7XG5cdFx0XHR9LCB0aGlzICk7XG5cblx0XHR9LFxuXG5cblx0XHQvKipcblx0XHQgKiBWYWxpZGF0ZSBwcmVyZXF1aXNpdGUgKGlmIHNldCkgYW5kIHVuc2V0IGl0IGlmIGl0J3Mgbm8gbG9uZ2VyIGEgdmFsaWQgcHJlcmVxXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNy4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTcuMFxuXHRcdCAqL1xuXHRcdHZhbGlkYXRlX3ByZXJlcXM6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHR0aGlzLmVhY2goIGZ1bmN0aW9uKCBsZXNzb24gKSB7XG5cblx0XHRcdFx0Ly8gdmFsaWRhdGUgcHJlcmVxc1xuXHRcdFx0XHRpZiAoICd5ZXMnID09PSBsZXNzb24uZ2V0KCAnaGFzX3ByZXJlcXVpc2l0ZScgKSApIHtcblx0XHRcdFx0XHR2YXIgdmFsaWQgPSBfLnBsdWNrKCBfLmZsYXR0ZW4oIF8ucGx1Y2soIGxlc3Nvbi5nZXRfYXZhaWxhYmxlX3ByZXJlcV9vcHRpb25zKCksICdvcHRpb25zJyApICksICdrZXknICk7XG5cdFx0XHRcdFx0aWYgKCAtMSA9PT0gdmFsaWQuaW5kZXhPZiggbGVzc29uLmdldCggJ3ByZXJlcXVpc2l0ZScgKSAqIDEgKSApIHtcblx0XHRcdFx0XHRcdGxlc3Nvbi5zZXQoIHtcblx0XHRcdFx0XHRcdFx0cHJlcmVxdWlzaXRlOiAwLFxuXHRcdFx0XHRcdFx0XHRoYXNfcHJlcmVxdWlzaXRlOiAnbm8nLFxuXHRcdFx0XHRcdFx0fSApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXG5cdFx0XHR9LCB0aGlzICk7XG5cblx0XHR9LFxuXG5cdH0gKTtcblxufSApO1xuXG4vKipcbiAqIFF1aXogUXVlc3Rpb24gVHlwZSBDb2xsZWN0aW9uXG4gKiBAc2luY2UgICAgMy4xNi4wXG4gKiBAdmVyc2lvbiAgMy4xNi4wXG4gKi9cbmRlZmluZSggJ0NvbGxlY3Rpb25zL1F1ZXN0aW9uVHlwZXMnLFsgJ01vZGVscy9RdWVzdGlvblR5cGUnIF0sIGZ1bmN0aW9uKCBtb2RlbCApIHtcblxuXHRyZXR1cm4gQmFja2JvbmUuQ29sbGVjdGlvbi5leHRlbmQoIHtcblxuXHRcdC8qKlxuXHRcdCAqIE1vZGVsIGZvciBjb2xsZWN0aW9uIGl0ZW1zXG5cdFx0ICogQHR5cGUgIG9ialxuXHRcdCAqL1xuXHRcdG1vZGVsOiBtb2RlbCxcblxuXHRcdC8qKlxuXHRcdCAqIEluaXRpYWxpemVyXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGluaXRpYWxpemU6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHR0aGlzLm9uKCAnYWRkJywgdGhpcy5jb21wYXJhdG9yICk7XG5cdFx0XHR0aGlzLm9uKCAncmVtb3ZlJywgdGhpcy5jb21wYXJhdG9yICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogQ29tcGFyYXRvciAoc29ydHMgY29sbGVjdGlvbilcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgbW9kZWwgIFF1ZXN0aW9uVHlwZSBtb2RlbFxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRjb21wYXJhdG9yOiBmdW5jdGlvbiggbW9kZWwgKSB7XG5cblx0XHRcdHJldHVybiBtb2RlbC5nZXQoICdncm91cCcgKS5vcmRlcjtcblxuXHRcdH0sXG5cblx0fSApO1xuXG59ICk7XG5cbi8qKlxuICogU2VjdGlvbiBNb2RlbFxuICogQHNpbmNlICAgIDMuMTYuMFxuICogQHZlcnNpb24gIDMuMTYuMTJcbiAqL1xuZGVmaW5lKCAnTW9kZWxzL1NlY3Rpb24nLFsgJ0NvbGxlY3Rpb25zL0xlc3NvbnMnLCAnTW9kZWxzL19SZWxhdGlvbnNoaXBzJyBdLCBmdW5jdGlvbiggTGVzc29ucywgUmVsYXRpb25zaGlwcyApIHtcblxuXHRyZXR1cm4gQmFja2JvbmUuTW9kZWwuZXh0ZW5kKCBfLmRlZmF1bHRzKCB7XG5cblx0XHRyZWxhdGlvbnNoaXBzOiB7XG5cdFx0XHRwYXJlbnQ6IHtcblx0XHRcdFx0bW9kZWw6ICdjb3Vyc2UnLFxuXHRcdFx0XHR0eXBlOiAnbW9kZWwnLFxuXHRcdFx0fSxcblx0XHRcdGNoaWxkcmVuOiB7XG5cdFx0XHRcdGxlc3NvbnM6IHtcblx0XHRcdFx0XHRjbGFzczogJ0xlc3NvbnMnLFxuXHRcdFx0XHRcdG1vZGVsOiAnbGVzc29uJyxcblx0XHRcdFx0XHR0eXBlOiAnY29sbGVjdGlvbicsXG5cdFx0XHRcdH0sXG5cdFx0XHR9XG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIE5ldyBzZWN0aW9uIGRlZmF1bHRzXG5cdFx0ICogQHJldHVybiAgIG9ialxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0ZGVmYXVsdHM6IGZ1bmN0aW9uKCkge1xuXHRcdFx0cmV0dXJuIHtcblx0XHRcdFx0aWQ6IF8udW5pcXVlSWQoICd0ZW1wXycgKSxcblx0XHRcdFx0bGVzc29uczogW10sXG5cdFx0XHRcdG9yZGVyOiB0aGlzLmNvbGxlY3Rpb24gPyB0aGlzLmNvbGxlY3Rpb24ubGVuZ3RoICsgMSA6IDEsXG5cdFx0XHRcdHBhcmVudF9jb3Vyc2U6IHdpbmRvdy5sbG1zX2J1aWxkZXIuY291cnNlLmlkLFxuXHRcdFx0XHR0aXRsZTogTExNUy5sMTBuLnRyYW5zbGF0ZSggJ05ldyBTZWN0aW9uJyApLFxuXHRcdFx0XHR0eXBlOiAnc2VjdGlvbicsXG5cblx0XHRcdFx0X2V4cGFuZGVkOiBmYWxzZSxcblx0XHRcdFx0X3NlbGVjdGVkOiBmYWxzZSxcblx0XHRcdH07XG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIEluaXRpYWxpemVcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0aW5pdGlhbGl6ZTogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHRoaXMuc3RhcnRUcmFja2luZygpO1xuXHRcdFx0dGhpcy5pbml0X3JlbGF0aW9uc2hpcHMoKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBBZGQgYSBsZXNzb24gdG8gdGhlIHNlY3Rpb25cblx0XHQgKiBAcGFyYW0gICAgb2JqICAgZGF0YSAgICAgaGFzaCBvZiBsZXNzb24gZGF0YSAoY3JlYXRlcyBuZXcgbGVzc29uKVxuXHRcdCAqICAgICAgICAgICAgICAgICAgICAgICAgICBvciBleGlzdGluZyBsZXNzb24gYXMgYSBCYWNrYm9uZS5Nb2RlbFxuXHRcdCAqIEBwYXJhbSAgICBvYmogICBvcHRpb25zICBoYXMgb2Ygb3B0aW9uc1xuXHRcdCAqIEByZXR1cm4gICBvYmogICAgICAgICAgICBCYWNrYm9uZS5Nb2RlbCBvZiB0aGUgbmV3L3VwZGF0ZWQgbGVzc29uXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjExXG5cdFx0ICovXG5cdFx0YWRkX2xlc3NvbjogZnVuY3Rpb24oIGRhdGEsIG9wdGlvbnMgKSB7XG5cblx0XHRcdGRhdGEgPSBkYXRhIHx8IHt9O1xuXHRcdFx0b3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG5cblx0XHRcdGlmICggZGF0YSBpbnN0YW5jZW9mIEJhY2tib25lLk1vZGVsICkge1xuXHRcdFx0XHRkYXRhLnNldCggJ3BhcmVudF9zZWN0aW9uJywgdGhpcy5nZXQoICdpZCcgKSApO1xuXHRcdFx0XHRkYXRhLnNldF9wYXJlbnQoIHRoaXMgKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGRhdGEucGFyZW50X3NlY3Rpb24gPSB0aGlzLmdldCggJ2lkJyApO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gdGhpcy5nZXQoICdsZXNzb25zJyApLmFkZCggZGF0YSwgb3B0aW9ucyApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFJldHJpZXZlIHRoZSB0cmFuc2xhdGVkIHBvc3QgdHlwZSBuYW1lIGZvciB0aGUgbW9kZWwncyB0eXBlXG5cdFx0ICogQHBhcmFtICAgIGJvb2wgICAgIHBsdXJhbCAgaWYgdHJ1ZSwgcmV0dXJucyB0aGUgcGx1cmFsLCBvdGhlcndpc2UgcmV0dXJucyBzaW5ndWxhclxuXHRcdCAqIEByZXR1cm4gICBzdHJpbmdcblx0XHQgKiBAc2luY2UgICAgMy4xNi4xMlxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjEyXG5cdFx0ICovXG5cdFx0Z2V0X2wxMG5fdHlwZTogZnVuY3Rpb24oIHBsdXJhbCApIHtcblxuXHRcdFx0aWYgKCBwbHVyYWwgKSB7XG5cdFx0XHRcdHJldHVybiBMTE1TLmwxMG4udHJhbnNsYXRlKCAnc2VjdGlvbnMnICk7XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBMTE1TLmwxMG4udHJhbnNsYXRlKCAnc2VjdGlvbicgKTtcblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogR2V0IG5leHQgc2VjdGlvbiBpbiB0aGUgY29sbGVjdGlvblxuXHRcdCAqIEBwYXJhbSAgICBib29sICAgICBjaXJjdWxhciAgIGlmIHRydWUgaGFuZGxlcyB0aGUgY29sbGVjdGlvbiBpbiBhIGNpcmNsZVxuXHRcdCAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFx0aWYgY3VycmVudCBpcyB0aGUgbGFzdCBzZWN0aW9uLCByZXR1cm5zIHRoZSBmaXJzdCBzZWN0aW9uXG5cdFx0ICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXHRpZiBjdXJyZW50IGlzIHRoZSBmaXJzdCBzZWN0aW9uLCByZXR1cm5zIHRoZSBsYXN0IHNlY3Rpb25cblx0XHQgKiBAcmV0dXJuICAgb2JqfGZhbHNlXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMTFcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4xMVxuXHRcdCAqL1xuXHRcdGdldF9uZXh0OiBmdW5jdGlvbiggY2lyY3VsYXIgKSB7XG5cdFx0XHRyZXR1cm4gdGhpcy5fZ2V0X3NpYmxpbmcoICduZXh0JywgY2lyY3VsYXIgKTtcblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogR2V0IHByZXYgc2VjdGlvbiBpbiB0aGUgY29sbGVjdGlvblxuXHRcdCAqIEBwYXJhbSAgICBib29sICAgICBjaXJjdWxhciAgIGlmIHRydWUgaGFuZGxlcyB0aGUgY29sbGVjdGlvbiBpbiBhIGNpcmNsZVxuXHRcdCAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFx0aWYgY3VycmVudCBpcyB0aGUgbGFzdCBzZWN0aW9uLCByZXR1cm5zIHRoZSBmaXJzdCBzZWN0aW9uXG5cdFx0ICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXHRpZiBjdXJyZW50IGlzIHRoZSBmaXJzdCBzZWN0aW9uLCByZXR1cm5zIHRoZSBsYXN0IHNlY3Rpb25cblx0XHQgKiBAcmV0dXJuICAgb2JqfGZhbHNlXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMTFcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4xMVxuXHRcdCAqL1xuXHRcdGdldF9wcmV2OiBmdW5jdGlvbiggY2lyY3VsYXIgKSB7XG5cdFx0XHRyZXR1cm4gdGhpcy5fZ2V0X3NpYmxpbmcoICdwcmV2JywgY2lyY3VsYXIgKTtcblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogR2V0IGEgc2libGluZyBzZWN0aW9uXG5cdFx0ICogQHBhcmFtICAgIHN0cmluZyAgIGRpcmVjdGlvbiAgc2libGluZ3MgZGlyZWN0aW9uIFtuZXh0fHByZXZdXG5cdFx0ICogQHBhcmFtICAgIGJvb2wgICAgIGNpcmN1bGFyICAgaWYgdHJ1ZSBoYW5kbGVzIHRoZSBjb2xsZWN0aW9uIGluIGEgY2lyY2xlXG5cdFx0ICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXHRpZiBjdXJyZW50IGlzIHRoZSBsYXN0IHNlY3Rpb24sIHJldHVybnMgdGhlIGZpcnN0IHNlY3Rpb25cblx0XHQgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcdGlmIGN1cnJlbnQgaXMgdGhlIGZpcnN0IHNlY3Rpb24sIHJldHVybnMgdGhlIGxhc3Qgc2VjdGlvblxuXHRcdCAqIEByZXR1cm4gICBvYmp8ZmFsc2Vcblx0XHQgKiBAc2luY2UgICAgMy4xNi4xMVxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjExXG5cdFx0ICovXG5cdFx0X2dldF9zaWJsaW5nOiBmdW5jdGlvbiggZGlyZWN0aW9uLCBjaXJjdWxhciApIHtcblxuXHRcdFx0Y2lyY3VsYXIgPSAoICd1bmRlZmluZWQnID09PSBjaXJjdWxhciApID8gdHJ1ZSA6IGNpcmN1bGFyO1xuXG5cdFx0XHR2YXIgbWF4ID0gdGhpcy5jb2xsZWN0aW9uLnNpemUoKSAtIDEsXG5cdFx0XHRcdGluZGV4ID0gdGhpcy5jb2xsZWN0aW9uLmluZGV4T2YoIHRoaXMgKSxcblx0XHRcdFx0c2libGluZ19pbmRleDtcblxuXHRcdFx0aWYgKCAnbmV4dCcgPT09IGRpcmVjdGlvbiApIHtcblx0XHRcdFx0c2libGluZ19pbmRleCA9IGluZGV4ICsgMTtcblx0XHRcdH0gZWxzZSBpZiAoICdwcmV2JyA9PT0gZGlyZWN0aW9uICkge1xuXHRcdFx0XHRzaWJsaW5nX2luZGV4ID0gaW5kZXggLSAxO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBkb250IHJldHJpZXZlIGdyZWF0ZXIgdGhhbiBtYXggb3IgbGVzcyB0aGFuIG1pblxuXHRcdFx0aWYgKCBzaWJsaW5nX2luZGV4IDw9IG1heCB8fCBzaWJsaW5nX2luZGV4IDw9IDAgKSB7XG5cblx0XHRcdFx0cmV0dXJuIHRoaXMuY29sbGVjdGlvbi5hdCggc2libGluZ19pbmRleCApO1xuXG5cdFx0XHR9IGVsc2UgaWYgKCBjaXJjdWxhciApIHtcblxuXHRcdFx0XHRpZiAoICduZXh0JyA9PT0gZGlyZWN0aW9uICkge1xuXHRcdFx0XHRcdHJldHVybiB0aGlzLmNvbGxlY3Rpb24uZmlyc3QoKTtcblx0XHRcdFx0fSBlbHNlIGlmICggJ3ByZXYnID09PSBkaXJlY3Rpb24gKSB7XG5cdFx0XHRcdFx0cmV0dXJuIHRoaXMuY29sbGVjdGlvbi5sYXN0KCk7XG5cdFx0XHRcdH1cblxuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cblx0XHR9LFxuXG5cdH0sIFJlbGF0aW9uc2hpcHMgKSApO1xuXG59ICk7XG5cbi8qKlxuICogU2VjdGlvbnMgQ29sbGVjdGlvblxuICogQHNpbmNlICAgIDMuMTYuMFxuICogQHZlcnNpb24gIDMuMTYuMFxuICovXG5kZWZpbmUoICdDb2xsZWN0aW9ucy9TZWN0aW9ucycsWyAnTW9kZWxzL1NlY3Rpb24nIF0sIGZ1bmN0aW9uKCBtb2RlbCApIHtcblxuXHRyZXR1cm4gQmFja2JvbmUuQ29sbGVjdGlvbi5leHRlbmQoIHtcblxuXHRcdC8qKlxuXHRcdCAqIE1vZGVsIGZvciBjb2xsZWN0aW9uIGl0ZW1zXG5cdFx0ICogQHR5cGUgIG9ialxuXHRcdCAqL1xuXHRcdG1vZGVsOiBtb2RlbCxcblxuXHRcdC8qKlxuXHRcdCAqIEluaXRpYWxpemVcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0aW5pdGlhbGl6ZTogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHZhciBzZWxmID0gdGhpcztcblxuXHRcdFx0Ly8gcmVvcmRlciBjYWxsZWQgYnkgU2VjdGlvbkxpc3QgdmlldyB3aGVuIHNvcnRhYmxlIGRyb3BzIG9jY3VyXG5cdFx0XHR0aGlzLm9uKCAncmVvcmRlcicsIHRoaXMudXBkYXRlX29yZGVyICk7XG5cblx0XHRcdC8vIHdoZW4gYSBzZWN0aW9uIGlzIGFkZGVkIG9yIHJlbW92ZWQsIHVwZGF0ZSBvcmRlclxuXHRcdFx0dGhpcy5vbiggJ2FkZCcsIHRoaXMudXBkYXRlX29yZGVyICk7XG5cdFx0XHR0aGlzLm9uKCAncmVtb3ZlJywgdGhpcy51cGRhdGVfb3JkZXIgKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBVcGRhdGUgdGhlIG9yZGVyIGF0dHIgb2YgZWFjaCBzZWN0aW9uIGluIHRoZSBsaXN0IHRvIHJlZmxlY3QgdGhlIG9yZGVyIG9mIHRoZSBjb2xsZWN0aW9uXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdHVwZGF0ZV9vcmRlcjogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHZhciBzZWxmID0gdGhpcztcblxuXHRcdFx0dGhpcy5lYWNoKCBmdW5jdGlvbiggc2VjdGlvbiApIHtcblxuXHRcdFx0XHRzZWN0aW9uLnNldCggJ29yZGVyJywgc2VsZi5pbmRleE9mKCBzZWN0aW9uICkgKyAxICk7XG5cblx0XHRcdH0gKTtcblxuXHRcdH0sXG5cblx0fSApO1xuXG59ICk7XG5cbi8qKlxuICogTGVzc29ucyBDb2xsZWN0aW9uXG4gKiBAc2luY2UgICAgMy4xMy4wXG4gKiBAdmVyc2lvbiAgMy4xNi4wXG4gKi9cbmRlZmluZSggJ0NvbGxlY3Rpb25zL2xvYWRlcicsW1xuXHRcdCdDb2xsZWN0aW9ucy9MZXNzb25zJyxcblx0XHQnQ29sbGVjdGlvbnMvUXVlc3Rpb25DaG9pY2VzJyxcblx0XHQnQ29sbGVjdGlvbnMvUXVlc3Rpb25zJyxcblx0XHQnQ29sbGVjdGlvbnMvUXVlc3Rpb25UeXBlcycsXG5cdFx0J0NvbGxlY3Rpb25zL1NlY3Rpb25zJ1xuXHRdLCBmdW5jdGlvbihcblx0XHRMZXNzb25zLFxuXHRcdFF1ZXN0aW9uQ2hvaWNlcyxcblx0XHRRdWVzdGlvbnMsXG5cdFx0UXVlc3Rpb25UeXBlcyxcblx0XHRTZWN0aW9uc1xuXHQpIHtcblxuXHRyZXR1cm4ge1xuXHRcdExlc3NvbnM6IExlc3NvbnMsXG5cdFx0UXVlc3Rpb25DaG9pY2VzOiBRdWVzdGlvbkNob2ljZXMsXG5cdFx0UXVlc3Rpb25zOiBRdWVzdGlvbnMsXG5cdFx0UXVlc3Rpb25UeXBlczogUXVlc3Rpb25UeXBlcyxcblx0XHRTZWN0aW9uczogU2VjdGlvbnMsXG5cdH07XG5cbn0gKTtcblxuLyoqXG4gKiBBYnN0cmFjdCBMaWZ0ZXJMTVMgTW9kZWxcbiAqIEBzaW5jZSAgICAzLjE3LjBcbiAqIEB2ZXJzaW9uICAzLjE3LjBcbiAqL1xuZGVmaW5lKCAnTW9kZWxzL0Fic3RyYWN0JyxbICdNb2RlbHMvX1JlbGF0aW9uc2hpcHMnLCAnTW9kZWxzL19VdGlsaXRpZXMnIF0sIGZ1bmN0aW9uKCBSZWxhdGlvbnNoaXBzLCBVdGlsaXRpZXMgKSB7XG5cblx0cmV0dXJuIEJhY2tib25lLk1vZGVsLmV4dGVuZCggXy5kZWZhdWx0cygge30sIFJlbGF0aW9uc2hpcHMsIFV0aWxpdGllcyApICk7XG5cbn0gKTtcblxuLyoqXG4gKiBDb3Vyc2UgTW9kZWxcbiAqIEBzaW5jZSAgICAzLjE2LjBcbiAqIEB2ZXJzaW9uICAzLjE2LjExXG4gKi9cbmRlZmluZSggJ01vZGVscy9Db3Vyc2UnLFsgJ0NvbGxlY3Rpb25zL1NlY3Rpb25zJywgJ01vZGVscy9fUmVsYXRpb25zaGlwcycsICdNb2RlbHMvX1V0aWxpdGllcycgXSwgZnVuY3Rpb24oIFNlY3Rpb25zLCBSZWxhdGlvbnNoaXBzLCBVdGlsaXRpZXMgKSB7XG5cblx0cmV0dXJuIEJhY2tib25lLk1vZGVsLmV4dGVuZCggXy5kZWZhdWx0cygge1xuXG5cdFx0cmVsYXRpb25zaGlwczoge1xuXHRcdFx0Y2hpbGRyZW46IHtcblx0XHRcdFx0c2VjdGlvbnM6IHtcblx0XHRcdFx0XHRjbGFzczogJ1NlY3Rpb25zJyxcblx0XHRcdFx0XHRtb2RlbDogJ3NlY3Rpb24nLFxuXHRcdFx0XHRcdHR5cGU6ICdjb2xsZWN0aW9uJyxcblx0XHRcdFx0fSxcblx0XHRcdH1cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogTmV3IENvdXJzZSBEZWZhdWx0c1xuXHRcdCAqIEByZXR1cm4gICBvYmpcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGRlZmF1bHRzOiBmdW5jdGlvbigpIHtcblx0XHRcdHJldHVybiB7XG5cdFx0XHRcdGVkaXRfdXJsOiAnJyxcblx0XHRcdFx0c2VjdGlvbnM6IFtdLFxuXHRcdFx0XHR0aXRsZTogJ05ldyBDb3Vyc2UnLFxuXHRcdFx0XHR0eXBlOiAnY291cnNlJyxcblx0XHRcdFx0dmlld191cmw6ICcnLFxuXHRcdFx0fVxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBJbml0XG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGluaXRpYWxpemU6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHR0aGlzLnN0YXJ0VHJhY2tpbmcoKTtcblx0XHRcdHRoaXMuaW5pdF9yZWxhdGlvbnNoaXBzKCk7XG5cblx0XHRcdC8vIFNpZGViYXIgXCJOZXcgU2VjdGlvblwiIGJ1dHRvbiBicm9hZGNhc3Rcblx0XHRcdEJhY2tib25lLnB1YlN1Yi5vbiggJ2FkZC1uZXctc2VjdGlvbicsIHRoaXMuYWRkX3NlY3Rpb24sIHRoaXMgKTtcblxuXHRcdFx0Ly8gU2lkZWJhciBcIk5ldyBMZXNzb25cIiBidXR0b24gYnJvYWRjYXN0XG5cdFx0XHRCYWNrYm9uZS5wdWJTdWIub24oICdhZGQtbmV3LWxlc3NvbicsIHRoaXMuYWRkX2xlc3NvbiwgdGhpcyApO1xuXG5cdFx0XHRCYWNrYm9uZS5wdWJTdWIub24oICdsZXNzb24tc2VhcmNoLXNlbGVjdCcsIHRoaXMuYWRkX2V4aXN0aW5nX2xlc3NvbiwgdGhpcyApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIEFkZCBhbiBleGlzdGluZyBsZXNzb24gdG8gdGhlIGNvdXJzZVxuXHRcdCAqIER1cGxpY2F0ZSBhIGxlc3NvbiBmcm9tIHRoaXMgb3IgYW5vdGhlciBjb3Vyc2Ugb3IgYXR0YWNoIGFuIG9ycGhhbmVkIGxlc3NvblxuXHRcdCAqIEBwYXJhbSAgICBvYmogICBsZXNzb24gIGxlc3NvbiBkYXRhIG9ialxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjExXG5cdFx0ICovXG5cdFx0YWRkX2V4aXN0aW5nX2xlc3NvbjogZnVuY3Rpb24oIGxlc3NvbiApIHtcblxuXHRcdFx0dmFyIGRhdGEgPSBsZXNzb24uZGF0YTtcblxuXHRcdFx0aWYgKCAnY2xvbmUnID09PSBsZXNzb24uYWN0aW9uICkge1xuXG5cdFx0XHRcdGRlbGV0ZSBkYXRhLmlkO1xuXHRcdFx0XHRpZiAoIGRhdGEucXVpeiApIHtcblx0XHRcdFx0XHRkZWxldGUgZGF0YS5xdWl6O1xuXHRcdFx0XHRcdGRhdGEucXVpel9lbmFibGVkID0gJ25vJztcblx0XHRcdFx0fVxuXG5cdFx0XHR9IGVsc2Uge1xuXG5cdFx0XHRcdGRhdGEuX2ZvcmNlU3luYyA9IHRydWU7XG5cblx0XHRcdH1cblxuXHRcdFx0ZGVsZXRlIGRhdGEub3JkZXI7XG5cdFx0XHRkZWxldGUgZGF0YS5wYXJlbnRfY291cnNlO1xuXHRcdFx0ZGVsZXRlIGRhdGEucGFyZW50X3NlY3Rpb247XG5cblx0XHRcdHRoaXMuYWRkX2xlc3NvbiggZGF0YSApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIEFkZCBhIG5ldyBsZXNzb24gdG8gdGhlIGNvdXJzZVxuXHRcdCAqIEBwYXJhbSAgICBvYmogICBkYXRhICAgbGVzc29uIGRhdGFcblx0XHQgKiBAcmV0dXJuICAgb2JqICAgICAgICAgIEJhY2tib25lLk1vZGVsIG9mIHRoZSBsZXNzb25cblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGFkZF9sZXNzb246IGZ1bmN0aW9uKCBkYXRhICkge1xuXG5cdFx0XHRkYXRhID0gZGF0YSB8fCB7fTtcblx0XHRcdHZhciBvcHRpb25zID0ge30sXG5cdFx0XHRcdHNlY3Rpb247XG5cblx0XHRcdGlmICggISBkYXRhLnBhcmVudF9zZWN0aW9uICkge1xuXHRcdFx0XHRzZWN0aW9uID0gdGhpcy5nZXRfc2VsZWN0ZWRfc2VjdGlvbigpO1xuXHRcdFx0XHRpZiAoICEgc2VjdGlvbiApIHtcblx0XHRcdFx0XHRzZWN0aW9uID0gdGhpcy5nZXQoICdzZWN0aW9ucycgKS5sYXN0KCk7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHNlY3Rpb24gPSB0aGlzLmdldCggJ3NlY3Rpb25zJyApLmdldCggZGF0YS5wYXJlbnRfc2VjdGlvbiApO1xuXHRcdFx0fVxuXG5cdFx0XHRkYXRhLl9zZWxlY3RlZCA9IHRydWU7XG5cblx0XHRcdGRhdGEucGFyZW50X2NvdXJzZSA9IHRoaXMuZ2V0KCAnaWQnICk7XG5cblx0XHRcdHZhciBsZXNzb24gPSBzZWN0aW9uLmFkZF9sZXNzb24oIGRhdGEsIG9wdGlvbnMgKTtcblx0XHRcdEJhY2tib25lLnB1YlN1Yi50cmlnZ2VyKCAnbmV3LWxlc3Nvbi1hZGRlZCcsIGxlc3NvbiApO1xuXG5cdFx0XHQvLyBleHBhbmQgdGhlIHNlY3Rpb25cblx0XHRcdHNlY3Rpb24uc2V0KCAnX2V4cGFuZGVkJywgdHJ1ZSApO1xuXG5cdFx0XHRyZXR1cm4gbGVzc29uO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIEFkZCBhIG5ldyBzZWN0aW9uIHRvIHRoZSBjb3Vyc2Vcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgZGF0YSAgIHNlY3Rpb24gZGF0YVxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRhZGRfc2VjdGlvbjogZnVuY3Rpb24oIGRhdGEgKSB7XG5cblx0XHRcdGRhdGEgPSBkYXRhIHx8IHt9O1xuXHRcdFx0dmFyIHNlY3Rpb25zID0gdGhpcy5nZXQoICdzZWN0aW9ucycgKSxcblx0XHRcdFx0b3B0aW9ucyA9IHt9LFxuXHRcdFx0XHRzZWxlY3RlZCA9IHRoaXMuZ2V0X3NlbGVjdGVkX3NlY3Rpb24oKTtcblxuXHRcdFx0Ly8gaWYgYSBzZWN0aW9uIGlzIHNlbGVjdGVkLCBhZGQgdGhlIG5ldyBzZWN0aW9uIGFmdGVyIHRoZSBjdXJyZW50bHkgc2VsZWN0ZWQgb25lXG5cdFx0XHRpZiAoIHNlbGVjdGVkICkge1xuXHRcdFx0XHRvcHRpb25zLmF0ID0gc2VjdGlvbnMuaW5kZXhPZiggc2VsZWN0ZWQgKSArIDE7XG5cdFx0XHR9XG5cblx0XHRcdHNlY3Rpb25zLmFkZCggZGF0YSwgb3B0aW9ucyApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFJldHJpZXZlIHRoZSBjdXJyZW50bHkgc2VsZWN0ZWQgc2VjdGlvbiBpbiB0aGUgY291cnNlXG5cdFx0ICogQHJldHVybiAgIG9ianx1bmRlZmluZWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGdldF9zZWxlY3RlZF9zZWN0aW9uOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0cmV0dXJuIHRoaXMuZ2V0KCAnc2VjdGlvbnMnICkuZmluZCggZnVuY3Rpb24oIG1vZGVsICkge1xuXHRcdFx0XHRyZXR1cm4gbW9kZWwuZ2V0KCAnX3NlbGVjdGVkJyApO1xuXHRcdFx0fSApO1xuXG5cdFx0fSxcblxuXHR9LCBSZWxhdGlvbnNoaXBzLCBVdGlsaXRpZXMgKSApO1xuXG59ICk7XG5cbi8qKlxuICogTG9hZCBhbGwgbW9kZWxzXG4gKiBAcmV0dXJuICAgb2JqXG4gKiBAc2luY2UgICAgMy4xNi4wXG4gKiBAdmVyc2lvbiAgMy4xNy4wXG4gKi9cbmRlZmluZSggJ01vZGVscy9sb2FkZXInLFtcblx0XHQnTW9kZWxzL0Fic3RyYWN0Jyxcblx0XHQnTW9kZWxzL0NvdXJzZScsXG5cdFx0J01vZGVscy9JbWFnZScsXG5cdFx0J01vZGVscy9MZXNzb24nLFxuXHRcdCdNb2RlbHMvUXVlc3Rpb24nLFxuXHRcdCdNb2RlbHMvUXVlc3Rpb25DaG9pY2UnLFxuXHRcdCdNb2RlbHMvUXVlc3Rpb25UeXBlJyxcblx0XHQnTW9kZWxzL1F1aXonLFxuXHRcdCdNb2RlbHMvU2VjdGlvbidcblx0XSxcblx0ZnVuY3Rpb24oXG5cdFx0QWJzdHJhY3QsXG5cdFx0Q291cnNlLFxuXHRcdEltYWdlLFxuXHRcdExlc3Nvbixcblx0XHRRdWVzdGlvbixcblx0XHRRdWVzdGlvbkNob2ljZSxcblx0XHRRdWVzdGlvblR5cGUsXG5cdFx0UXVpeixcblx0XHRTZWN0aW9uXG5cdCkge1xuXG5cdHJldHVybiB7XG5cdFx0QWJzdHJhY3Q6IEFic3RyYWN0LFxuXHRcdENvdXJzZTogQ291cnNlLFxuXHRcdEltYWdlOiBJbWFnZSxcblx0XHRMZXNzb246IExlc3Nvbixcblx0XHRRdWVzdGlvbjogUXVlc3Rpb24sXG5cdFx0UXVlc3Rpb25DaG9pY2U6IFF1ZXN0aW9uQ2hvaWNlLFxuXHRcdFF1ZXN0aW9uVHlwZTogUXVlc3Rpb25UeXBlLFxuXHRcdFF1aXo6IFF1aXosXG5cdFx0U2VjdGlvbjogU2VjdGlvbixcblx0fTtcblxufSApO1xuXG4vKipcbiAqIERldGFjaGFibGUgbW9kZWxcbiAqIEB0eXBlICAgICB7T2JqZWN0fVxuICogQHNpbmNlICAgIDMuMTYuMTJcbiAqIEB2ZXJzaW9uICAzLjE2LjEyXG4gKi9cbmRlZmluZSggJ1ZpZXdzL19EZXRhY2hhYmxlJyxbXSwgZnVuY3Rpb24oKSB7XG5cblx0cmV0dXJuIHtcblxuXHRcdC8qKlxuXHRcdCAqIERPTSBFdmVudHNcblx0XHQgKiBAdHlwZSAge09iamVjdH1cblx0XHQgKiBAc2luY2UgICAgMy4xNi4xMlxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjEyXG5cdFx0ICovXG5cdFx0ZXZlbnRzOiB7XG5cdFx0XHQnY2xpY2sgYVtocmVmPVwiI2xsbXMtZGV0YWNoLW1vZGVsXCJdJzogJ2RldGFjaF9tb2RlbCcsXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIERldGFjaGVzIGEgbW9kZWwgZnJvbSBpdCdzIHBhcmVudCAoZG9lc24ndCBkZWxldGUpXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIGV2ZW50ICBqcyBldmVudCBvYmplY3Rcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjEyXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMTJcblx0XHQgKi9cblx0XHRkZXRhY2hfbW9kZWw6IGZ1bmN0aW9uKCBldmVudCApIHtcblxuXHRcdFx0aWYgKCBldmVudCApIHtcblx0XHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdFx0ZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cdFx0XHR9XG5cblx0XHRcdHZhciBtc2cgPSBMTE1TLmwxMG4ucmVwbGFjZSggJ0FyZSB5b3Ugc3VyZSB5b3Ugd2FudCB0byBkZXRhY2ggdGhpcyAlcz8nLCB7XG5cdFx0XHRcdCclcyc6IHRoaXMubW9kZWwuZ2V0X2wxMG5fdHlwZSgpLFxuXHRcdFx0fSApO1xuXG5cdFx0XHRpZiAoIHdpbmRvdy5jb25maXJtKCBtc2cgKSApIHtcblxuXHRcdFx0XHRpZiAoIHRoaXMubW9kZWwuY29sbGVjdGlvbiApIHtcblx0XHRcdFx0XHR0aGlzLm1vZGVsLmNvbGxlY3Rpb24ucmVtb3ZlKCB0aGlzLm1vZGVsICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBwdWJsaXNoIGdsb2JhbCBldmVudFxuXHRcdFx0XHRCYWNrYm9uZS5wdWJTdWIudHJpZ2dlciggJ21vZGVsLWRldGFjaGVkJywgdGhpcy5tb2RlbCApO1xuXG5cdFx0XHRcdC8vIHRyaWdnZXIgbG9jYWwgZXZlbnQgc28gZXh0ZW5kaW5nIHZpZXdzIGNhbiBydW4gb3RoZXIgYWN0aW9ucyB3aGVyZSBuZWNlc3Nhcnlcblx0XHRcdFx0dGhpcy50cmlnZ2VyKCAnbW9kZWwtdHJhc2hlZCcsIHRoaXMubW9kZWwgKTtcblxuXHRcdFx0fVxuXG5cdFx0fSxcblxuXHR9XG5cbn0gKTtcblxuLyoqXG4gKiBIYW5kbGVzIFVYIGFuZCBFdmVudHMgZm9yIGlubGluZSBlZGl0aW5nIG9mIHZpZXdzXG4gKiBVc2Ugd2l0aCBhIE1vZGVsJ3MgVmlld1xuICogQWxsb3dzIGVkaXRpbmcgbW9kZWwudGl0bGUgZmllbGQgdmlhIC5sbG1zLWVkaXRhYmxlLXRpdGxlIGVsZW1lbnRzXG4gKiBAdHlwZSAgICAge09iamVjdH1cbiAqIEBzaW5jZSAgICAzLjE2LjBcbiAqIEB2ZXJzaW9uICAzLjE3LjhcbiAqL1xuZGVmaW5lKCAnVmlld3MvX0VkaXRhYmxlJyxbXSwgZnVuY3Rpb24oKSB7XG5cblx0cmV0dXJuIHtcblxuXHRcdG1lZGlhX2xpYjogbnVsbCxcblxuXHRcdC8qKlxuXHRcdCAqIERPTSBFdmVudHNcblx0XHQgKiBAdHlwZSAge09iamVjdH1cblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTcuOFxuXHRcdCAqL1xuXHRcdGV2ZW50czoge1xuXHRcdFx0J2NsaWNrIC5sbG1zLWFkZC1pbWFnZSc6ICdvcGVuX21lZGlhX2xpYicsXG5cdFx0XHQnY2xpY2sgYVtocmVmPVwiI2xsbXMtZWRpdC1zbHVnXCJdJzogJ21ha2Vfc2x1Z19lZGl0YWJsZScsXG5cdFx0XHQnY2xpY2sgYVtocmVmPVwiI2xsbXMtcmVtb3ZlLWltYWdlXCJdJzogJ3JlbW92ZV9pbWFnZScsXG5cdFx0XHQnY2hhbmdlIC5sbG1zLWVkaXRhYmxlLXNlbGVjdCBzZWxlY3QnOiAnb25fc2VsZWN0Jyxcblx0XHRcdCdjaGFuZ2UgLmxsbXMtc3dpdGNoIGlucHV0W3R5cGU9XCJjaGVja2JveFwiXSc6ICd0b2dnbGVfc3dpdGNoJyxcblx0XHRcdCdjaGFuZ2UgLmxsbXMtZWRpdGFibGUtcmFkaW8gaW5wdXQnOiAnb25fcmFkaW9fc2VsZWN0Jyxcblx0XHRcdCdmb2N1c2luIC5sbG1zLWlucHV0JzogJ29uX2ZvY3VzJyxcblx0XHRcdCdmb2N1c291dCAubGxtcy1pbnB1dCc6ICdvbl9ibHVyJyxcblx0XHRcdCdrZXlkb3duIC5sbG1zLWlucHV0JzogJ29uX2tleWRvd24nLFxuXHRcdFx0J2lucHV0IC5sbG1zLWlucHV0W3R5cGU9XCJudW1iZXJcIl0nOiAnb25fYmx1cicsXG5cdFx0XHQncGFzdGUgLmxsbXMtaW5wdXRbZGF0YS1mb3JtYXR0aW5nXSc6ICdvbl9wYXN0ZScsXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFJldHJpZXZlIGEgbGlzdCBvZiBhbGxvd2VkIHRhZ3MgZm9yIGEgZ2l2ZW4gZWxlbWVudFxuXHRcdCAqIEBwYXJhbSAgICBvYmogICAkZWwgIGpRdWVyeSBzZWxlY3RvciBmb3IgdGhlIGVsZW1lbnRcblx0XHQgKiBAcmV0dXJuICAgYXJyYXlcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTcuOFxuXHRcdCAqL1xuXHRcdGdldF9hbGxvd2VkX3RhZ3M6IGZ1bmN0aW9uKCAkZWwgKSB7XG5cblx0XHRcdGlmICggJGVsLmF0dHIoICdkYXRhLWZvcm1hdHRpbmcnICkgKSB7XG5cdFx0XHRcdHJldHVybiBfLm1hcCggJGVsLmF0dHIoICdkYXRhLWZvcm1hdHRpbmcnICkuc3BsaXQoICcsJyApLCBmdW5jdGlvbiggdGFnICkge1xuXHRcdFx0XHRcdHJldHVybiB0YWcudHJpbSgpO1xuXHRcdFx0XHR9ICk7XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBbICdiJywgJ2knLCAndScsICdzdHJvbmcnLCAnZW0nIF07XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogUmV0cmlldmUgdGhlIGNvbnRlbnQgb2YgYW4gZWxlbWVudFxuXHRcdCAqIEBwYXJhbSAgICBvYmogICAkZWwgIGpRdWVyeSBvYmplY3Qgb2YgdGhlIGVsZW1lbnRcblx0XHQgKiBAcmV0dXJuICAgc3RyaW5nXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE3Ljhcblx0XHQgKi9cblx0XHRnZXRfY29udGVudDogZnVuY3Rpb24oICRlbCApIHtcblxuXHRcdFx0aWYgKCAnSU5QVVQnID09PSAkZWxbMF0udGFnTmFtZSApIHtcblx0XHRcdFx0cmV0dXJuICRlbC52YWwoKTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKCAhICRlbC5hdHRyKCAnZGF0YS1mb3JtYXR0aW5nJyApICYmICEgJGVsLmhhc0NsYXNzKCAncWwtZWRpdG9yJyApICkge1xuXHRcdFx0XHRyZXR1cm4gJGVsLnRleHQoKTtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIF8uc3RyaXBGb3JtYXR0aW5nKCAkZWwuaHRtbCgpLCB0aGlzLmdldF9hbGxvd2VkX3RhZ3MoICRlbCApICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogRGV0ZXJtaW5lIGlmIGNoYW5nZXMgaGF2ZSBiZWVuIG1hZGUgdG8gdGhlIGVsZW1lbnRcblx0XHQgKiBAcGFyYW0gICAge1tvYmpdfSAgIGV2ZW50ICBqcyBldmVudCBvYmplY3Rcblx0XHQgKiBAcmV0dXJuICAge0Jvb2xlYW59ICAgICAgICB0cnVlIHdoZW4gY2hhbmdlcyBoYXZlIGJlZW4gbWFkZSwgZmFsc2Ugb3RoZXJ3aXNlXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRoYXNfY2hhbmdlZDogZnVuY3Rpb24oIGV2ZW50ICkge1xuXHRcdFx0dmFyICRlbCA9ICQoIGV2ZW50LnRhcmdldCApO1xuXHRcdFx0cmV0dXJuICggJGVsLmF0dHIoICdkYXRhLW9yaWdpbmFsLWNvbnRlbnQnICkgIT09IHRoaXMuZ2V0X2NvbnRlbnQoICRlbCApICk7XG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIEVuc3VyZSB0aGF0IG5ldyBjb250ZW50IGlzIGF0IGxlYXN0IDEgY2hhcmFjdGVyIGxvbmdcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgZXZlbnQgIGpzIGV2ZW50IG9iamVjdFxuXHRcdCAqIEByZXR1cm4gICBib29sZWFuXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE3LjJcblx0XHQgKi9cblx0XHRpc192YWxpZDogZnVuY3Rpb24oIGV2ZW50ICkge1xuXG5cdFx0XHR2YXIgc2VsZiA9IHRoaXMsXG5cdFx0XHRcdCRlbCA9ICQoIGV2ZW50LnRhcmdldCApLFxuXHRcdFx0XHRjb250ZW50ID0gdGhpcy5nZXRfY29udGVudCggJGVsICksXG5cdFx0XHRcdHR5cGUgPSAkZWwuYXR0ciggJ2RhdGEtdHlwZScgKTtcblxuXHRcdFx0aWYgKCAoICRlbC5hdHRyKCAncmVxdWlyZWQnICkgfHwgJGVsLmF0dHIoICdkYXRhLXJlcXVpcmVkJyApICkgJiYgY29udGVudC5sZW5ndGggPCAxICkge1xuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHR9XG5cblx0XHRcdGlmICggJ3VybCcgPT09IHR5cGUgfHwgJ3ZpZGVvJyA9PT0gdHlwZSApIHtcblx0XHRcdFx0aWYgKCAhIHRoaXMuX3ZhbGlkYXRlX3VybCggdGhpcy5nZXRfY29udGVudCggJGVsICkgKSApIHtcblx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHRcdH1cblxuXHRcdFx0fSBlbHNlIGlmICggJ3Blcm1hbGluaycgPT09IHR5cGUgKSB7XG5cblx0XHRcdFx0TExNUy5BamF4LmNhbGwoIHtcblx0XHRcdFx0XHRkYXRhOiB7XG5cdFx0XHRcdFx0XHRhY3Rpb246ICdsbG1zX2J1aWxkZXInLFxuXHRcdFx0XHRcdFx0YWN0aW9uX3R5cGU6ICdnZXRfcGVybWFsaW5rJyxcblx0XHRcdFx0XHRcdGNvdXJzZV9pZDogd2luZG93LmxsbXNfYnVpbGRlci5Db3Vyc2VNb2RlbC5nZXQoICdpZCcgKSxcblx0XHRcdFx0XHRcdGlkOiBzZWxmLm1vZGVsLmdldCggJ2lkJyApLFxuXHRcdFx0XHRcdFx0dGl0bGU6IHNlbGYubW9kZWwuZ2V0KCAndGl0bGUnICksXG5cdFx0XHRcdFx0XHRzbHVnOiBjb250ZW50LFxuXHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0YmVmb3JlU2VuZDogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHRMTE1TLlNwaW5uZXIuc3RhcnQoICRlbC5jbG9zZXN0KCAnLmxsbXMtZWRpdGFibGUtdG9nZ2xlLWdyb3VwJyApLCAnc21hbGwnICk7XG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRzdWNjZXNzOiBmdW5jdGlvbiggciApIHtcblxuXHRcdFx0XHRcdFx0aWYgKCByLnBlcm1hbGluayAmJiByLnNsdWcgKSB7XG5cdFx0XHRcdFx0XHRcdHNlbGYubW9kZWwuc2V0KCAncGVybWFsaW5rJywgci5wZXJtYWxpbmsgKTtcblx0XHRcdFx0XHRcdFx0c2VsZi5tb2RlbC5zZXQoICduYW1lJywgci5zbHVnICk7XG5cdFx0XHRcdFx0XHRcdHNlbGYucmVuZGVyKCk7XG5cdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0gKTtcblxuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBJbml0aWFsaXplIGRhdGVwaWNrZXIgZWxlbWVudHNcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE3LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNy4wXG5cdFx0ICovXG5cdFx0aW5pdF9kYXRlcGlja2VyczogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHRoaXMuJGVsLmZpbmQoICcubGxtcy1lZGl0YWJsZS1kYXRlIGlucHV0JyApLmVhY2goIGZ1bmN0aW9uKCkge1xuXG5cdFx0XHRcdCQoIHRoaXMgKS5kYXRldGltZXBpY2tlcigge1xuXHRcdFx0XHRcdGZvcm1hdDogJCggdGhpcyApLmF0dHIoICdkYXRhLWRhdGUtZm9ybWF0JyApIHx8ICdZLW0tZCBoOmkgQScsXG5cdFx0XHRcdFx0ZGF0ZXBpY2tlcjogKCB1bmRlZmluZWQgPT09ICQoIHRoaXMgKS5hdHRyKCAnZGF0YS1kYXRlLWRhdGVwaWNrZXInICkgKSA/IHRydWUgOiAoICd0cnVlJyA9PSAkKCB0aGlzICkuYXR0ciggJ2RhdGEtZGF0ZS1kYXRlcGlja2VyJyApICksXG5cdFx0XHRcdFx0dGltZXBpY2tlcjogKCB1bmRlZmluZWQgPT09ICQoIHRoaXMgKS5hdHRyKCAnZGF0YS1kYXRlLXRpbWVwaWNrZXInICkgKSA/IHRydWUgOiAoICd0cnVlJyA9PSAkKCB0aGlzICkuYXR0ciggJ2RhdGEtZGF0ZS10aW1lcGlja2VyJyApICksXG5cdFx0XHRcdFx0b25DbG9zZTogZnVuY3Rpb24oIGN1cnJlbnRfdGltZSwgJGlucHV0ICkge1xuXHRcdFx0XHRcdFx0JGlucHV0LmJsdXIoKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0gKTtcblxuXHRcdFx0fSApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIEluaXRpYWxpemUgZWxlbWVudHMgdGhhdCBhbGxvdyBpbmxpbmUgZm9ybWF0dGluZ1xuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRpbml0X2Zvcm1hdHRpbmdfZWxzOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0dmFyIHNlbGYgPSB0aGlzO1xuXG5cdFx0XHR0aGlzLiRlbC5maW5kKCAnLmxsbXMtaW5wdXQtZm9ybWF0dGluZ1tkYXRhLWZvcm1hdHRpbmddJyApLmVhY2goIGZ1bmN0aW9uKCkge1xuXG5cdFx0XHRcdHZhciBmb3JtYXR0aW5nID0gJCggdGhpcyApLmF0dHIoICdkYXRhLWZvcm1hdHRpbmcnICkuc3BsaXQoICcsJyApLFxuXHRcdFx0XHRcdGF0dHIgPSAkKCB0aGlzICkuYXR0ciggJ2RhdGEtYXR0cmlidXRlJyApO1xuXG5cdFx0XHRcdHZhciBlZCA9IG5ldyBRdWlsbCggdGhpcywge1xuXHRcdFx0XHRcdG1vZHVsZXM6IHtcblx0XHRcdFx0XHRcdHRvb2xiYXI6IFsgZm9ybWF0dGluZyBdLFxuXHRcdFx0XHRcdFx0a2V5Ym9hcmQ6IHtcblx0XHRcdFx0XHRcdFx0YmluZGluZ3M6IHtcblx0XHRcdFx0XHRcdFx0XHR0YWI6IHtcblx0XHRcdFx0XHRcdFx0XHRcdGtleTogOSxcblx0XHRcdFx0XHRcdFx0XHRcdGhhbmRsZXI6IGZ1bmN0aW9uKCByYW5nZSwgY29udGV4dCApIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHRcdFx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0XHRcdFx0MTM6IHtcblx0XHRcdFx0XHRcdFx0XHRcdGtleTogMTMsXG5cdFx0XHRcdFx0XHRcdFx0XHRoYW5kbGVyOiBmdW5jdGlvbiggcmFuZ2UsIGNvbnRleHQgKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdGVkLnJvb3QuYmx1cigpO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHRcdFx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0cGxhY2Vob2xkZXI6ICQoIHRoaXMgKS5hdHRyKCAnZGF0YS1wbGFjZWhvbGRlcicgKSxcblx0XHRcdFx0XHR0aGVtZTogJ2J1YmJsZScsXG5cdFx0XHRcdH0gKTtcblxuXHRcdFx0XHRlZC5vbiggJ3RleHQtY2hhbmdlJywgZnVuY3Rpb24oIGRlbHRhLCBvbGREZWx0YSwgc291cmNlICkge1xuXHRcdFx0XHRcdHNlbGYubW9kZWwuc2V0KCBhdHRyLCBzZWxmLmdldF9jb250ZW50KCAkKCBlZC5yb290ICkgKSApO1xuXHRcdFx0XHR9ICk7XG5cblx0XHRcdFx0QmFja2JvbmUucHViU3ViLnRyaWdnZXIoICdmb3JtYXR0aW5nLWVkLWluaXQnLCBlZCwgJCggdGhpcyApLCBzZWxmICk7XG5cblx0XHRcdH0gKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBJbml0aWFsaXplIGVkaXRhYmxlIHNlbGVjdCBlbGVtZW50c1xuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRpbml0X3NlbGVjdHM6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHR0aGlzLiRlbC5maW5kKCAnLmxsbXMtZWRpdGFibGUtc2VsZWN0IHNlbGVjdCcgKS5sbG1zU2VsZWN0Migge1xuXHRcdFx0XHR3aWR0aDogJzEwMCUnLFxuXHRcdFx0fSApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIEJsdXIvZm9jdXNvdXQgZnVuY3Rpb24gZm9yIC5sbG1zLWVkaXRhYmxlLXRpdGxlIGVsZW1lbnRzXG5cdFx0ICogQXV0b21hdGljYWxseSBzYXZlcyBjaGFuZ2VzIGlmIGNoYW5nZXMgaGF2ZSBiZWVuIG1hZGVcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgZXZlbnQgIGpzIGV2ZW50IG9iamVjdFxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjZcblx0XHQgKi9cblx0XHRvbl9ibHVyOiBmdW5jdGlvbiggZXZlbnQgKSB7XG5cblx0XHRcdGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuXG5cdFx0XHR0aGlzLm1vZGVsLnNldCggJ19oYXNfZm9jdXMnLCBmYWxzZSwgeyBzaWxlbnQ6IHRydWUgfSApO1xuXG5cdFx0XHR2YXIgc2VsZiA9IHRoaXMsXG5cdFx0XHRcdCRlbCA9ICQoIGV2ZW50LnRhcmdldCApLFxuXHRcdFx0XHRjaGFuZ2VkID0gdGhpcy5oYXNfY2hhbmdlZCggZXZlbnQgKTtcblxuXHRcdFx0aWYgKCBjaGFuZ2VkICkge1xuXG5cdFx0XHRcdGlmICggISBzZWxmLmlzX3ZhbGlkKCBldmVudCApICkge1xuXHRcdFx0XHRcdHNlbGYucmV2ZXJ0X2VkaXRzKCBldmVudCApO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHRoaXMuc2F2ZV9lZGl0cyggZXZlbnQgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHR9XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogRm9jdXMgZXZlbnQgZm9yIGVkaXRhYmxlIGlucHV0c1xuXHRcdCAqIEBwYXJhbSAgICBvYmogICBldmVudCAganMgZXZlbnQgb2JqZWN0XG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi42XG5cdFx0ICogQHZlcnNpb24gIDMuMTYuNlxuXHRcdCAqL1xuXHRcdG9uX2ZvY3VzOiBmdW5jdGlvbiggZXZlbnQgKSB7XG5cblx0XHRcdGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuXHRcdFx0dGhpcy5tb2RlbC5zZXQoICdfaGFzX2ZvY3VzJywgdHJ1ZSwgeyBzaWxlbnQ6IHRydWUgfSApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIEhhbmRsZSBjb250ZW50IHBhc3RlZCBpbnRvIGNvbnRlbnRlZGl0YWJsZSBmaWVsZHNcblx0XHQgKiBUaGlzIHdpbGwgZW5zdXJlIHRoYXQgSFRNTCBmcm9tIFJURiBlZGl0b3JzIGlzbid0IHBhc3RlZCBpbnRvIHRoZSBkb21cblx0XHQgKiBAcGFyYW0gICAgb2JqICAgZXZlbnQgIGpzIGV2ZW50IG9ialxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTcuOFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE3Ljhcblx0XHQgKi9cblx0XHRvbl9wYXN0ZTogZnVuY3Rpb24oIGV2ZW50ICkge1xuXG5cdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0ZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cblx0XHRcdHZhciB0ZXh0ID0gKCBldmVudC5vcmlnaW5hbEV2ZW50IHx8IGV2ZW50ICkuY2xpcGJvYXJkRGF0YS5nZXREYXRhKCAndGV4dC9wbGFpbicgKTtcblx0XHRcdHdpbmRvdy5kb2N1bWVudC5leGVjQ29tbWFuZCggJ2luc2VydFRleHQnLCBmYWxzZSwgdGV4dCApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIENoYW5nZSBldmVudCBmb3Igc2VsZWN0YWJsZXNcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgZXZlbnQgIGpzIGV2ZW50IG9iamVjdFxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRvbl9zZWxlY3Q6IGZ1bmN0aW9uKCBldmVudCApIHtcblxuXHRcdFx0dmFyICRlbCA9ICQoIGV2ZW50LnRhcmdldCApLFxuXHRcdFx0XHRtdWx0aSA9ICggJGVsLmF0dHIoICdtdWx0aXBsZScgKSApLFxuXHRcdFx0XHRhdHRyID0gJGVsLmF0dHIoICduYW1lJyApLFxuXHRcdFx0XHQkc2VsZWN0ZWQgPSAkZWwuZmluZCggJ29wdGlvbjpzZWxlY3RlZCcgKSxcblx0XHRcdFx0dmFsO1xuXG5cdFx0XHRpZiAoIG11bHRpICkge1xuXHRcdFx0XHR2YWwgPSBbXTtcblx0XHRcdFx0dmFsID0gJHNlbGVjdGVkLm1hcCggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0cmV0dXJuIHRoaXMudmFsdWU7XG5cdFx0XHRcdH0gKS5nZXQoKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHZhbCA9ICRzZWxlY3RlZFswXS52YWx1ZTtcblx0XHRcdH1cblxuXHRcdFx0dGhpcy5tb2RlbC5zZXQoIGF0dHIsIHZhbCApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIENoYW5nZSBldmVudCBmb3IgcmFkaW8gZWxlbWVudCBncm91cHNcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgZXZlbnQgIGpzIGV2ZW50IG9iamVjdFxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTcuNlxuXHRcdCAqIEB2ZXJzaW9uICAzLjE3LjZcblx0XHQgKi9cblx0XHRvbl9yYWRpb19zZWxlY3Q6IGZ1bmN0aW9uKCBldmVudCApIHtcblxuXHRcdFx0dmFyICRlbCA9ICQoIGV2ZW50LnRhcmdldCApLFxuXHRcdFx0XHRhdHRyID0gJGVsLmF0dHIoICduYW1lJyApLFxuXHRcdFx0XHR2YWwgPSAkZWwudmFsKCk7XG5cblx0XHRcdHRoaXMubW9kZWwuc2V0KCBhdHRyLCB2YWwgKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBLZXlkb3duIGZ1bmN0aW9uIGZvciAubGxtcy1lZGl0YWJsZS10aXRsZSBlbGVtZW50c1xuXHRcdCAqIEJsdXJzXG5cdFx0ICogQHBhcmFtICAgIHtvYmp9ICAgZXZlbnQgIGpzIGV2ZW50IG9iamVjdFxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE3Ljhcblx0XHQgKi9cblx0XHRvbl9rZXlkb3duOiBmdW5jdGlvbiggZXZlbnQgKSB7XG5cblx0XHRcdGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuXG5cdFx0XHR2YXIgc2VsZiA9IHRoaXMsXG5cdFx0XHRcdGtleSA9IGV2ZW50LndoaWNoIHx8IGV2ZW50LmtleUNvZGUsXG5cdFx0XHRcdHNoaWZ0ID0gZXZlbnQuc2hpZnRLZXk7XG5cdFx0XHRcdC8vIGN0cmwgPSBldmVudC5tZXRhS2V5IHx8IGV2ZW50LmN0cmxLZXk7XG5cblx0XHRcdHN3aXRjaCAoIGtleSApIHtcblxuXHRcdFx0XHRjYXNlIDEzOiAvLyBlbnRlclxuXHRcdFx0XHRcdC8vIHNoaWZ0ICsgZW50ZXIgc2hvdWxkIGFkZCBhIHJldHVyblxuXHRcdFx0XHRcdGlmICggISBzaGlmdCApIHtcblx0XHRcdFx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHRcdFx0XHRldmVudC50YXJnZXQuYmx1cigpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0YnJlYWs7XG5cblx0XHRcdFx0Y2FzZSAyNzogLy8gZXNjYXBlXG5cdFx0XHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdFx0XHR0aGlzLnJldmVydF9lZGl0cyggZXZlbnQgKTtcblx0XHRcdFx0XHRldmVudC50YXJnZXQuYmx1cigpO1xuXHRcdFx0XHRicmVhaztcblxuXHRcdFx0fVxuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIE9wZW4gdGhlIFdQIG1lZGlhIGxpYlxuXHRcdCAqIEBwYXJhbSAgICBvYmogICBldmVudCAganMgZXZlbnQgb2JqZWN0XG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuNlxuXHRcdCAqL1xuXHRcdG9wZW5fbWVkaWFfbGliOiBmdW5jdGlvbiggZXZlbnQgKSB7XG5cblx0XHRcdGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuXG5cdFx0XHR2YXIgc2VsZiA9IHRoaXMsXG5cdFx0XHRcdCRlbCA9ICQoIGV2ZW50LmN1cnJlbnRUYXJnZXQgKTtcblxuXHRcdFx0aWYgKCBzZWxmLm1lZGlhX2xpYiApIHtcblxuXHRcdFx0XHRzZWxmLm1lZGlhX2xpYi51cGxvYWRlci51cGxvYWRlci5wYXJhbSggJ3Bvc3RfaWQnICk7XG5cblx0XHRcdH0gZWxzZSB7XG5cblx0XHRcdFx0c2VsZi5tZWRpYV9saWIgPSB3cC5tZWRpYS5mcmFtZXMuZmlsZV9mcmFtZSA9IHdwLm1lZGlhKCB7XG5cdFx0XHRcdFx0dGl0bGU6IExMTVMubDEwbi50cmFuc2xhdGUoICdTZWxlY3QgYW4gaW1hZ2UnICksXG5cdFx0XHRcdFx0YnV0dG9uOiB7XG5cdFx0XHRcdFx0XHR0ZXh0OiBMTE1TLmwxMG4udHJhbnNsYXRlKCAnVXNlIHRoaXMgaW1hZ2UnICksXG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRtdWx0aXBsZTogZmFsc2VcdC8vIFNldCB0byB0cnVlIHRvIGFsbG93IG11bHRpcGxlIGZpbGVzIHRvIGJlIHNlbGVjdGVkXG5cdFx0XHRcdH0gKTtcblxuXHRcdFx0XHRzZWxmLm1lZGlhX2xpYi5vbiggJ3NlbGVjdCcsIGZ1bmN0aW9uKCkge1xuXG5cdFx0XHRcdFx0dmFyIHNpemUgPSAkZWwuYXR0ciggJ2RhdGEtaW1hZ2Utc2l6ZScgKSxcblx0XHRcdFx0XHRcdGF0dGFjaG1lbnQgPSBzZWxmLm1lZGlhX2xpYi5zdGF0ZSgpLmdldCggJ3NlbGVjdGlvbicgKS5maXJzdCgpLnRvSlNPTigpLFxuXHRcdFx0XHRcdFx0aW1hZ2UgPSBzZWxmLm1vZGVsLmdldCggJGVsLmF0dHIoICdkYXRhLWF0dHJpYnV0ZScgKSApLFxuXHRcdFx0XHRcdFx0dXJsO1xuXG5cdFx0XHRcdFx0aWYgKCBzaXplICYmIGF0dGFjaG1lbnQuc2l6ZXNbIHNpemUgXSApIHtcblx0XHRcdFx0XHRcdHVybCA9IGF0dGFjaG1lbnQuc2l6ZXNbIHNpemUgXS51cmw7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdHVybCA9IGF0dGFjaG1lbnQudXJsO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdGltYWdlLnNldCgge1xuXHRcdFx0XHRcdFx0aWQ6IGF0dGFjaG1lbnQuaWQsXG5cdFx0XHRcdFx0XHRzcmM6IHVybCxcblx0XHRcdFx0XHR9ICk7XG5cblx0XHRcdFx0fSApO1xuXG5cdFx0XHR9XG5cblx0XHRcdHNlbGYubWVkaWFfbGliLm9wZW4oKTtcblxuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIENsaWNrIGV2ZW50IHRvIHJlbW92ZSBhbiBpbWFnZVxuXHRcdCAqIEBwYXJhbSAgICBvYmogICBldmVudCAganMgZXZlbnQgb2JqXG5cdFx0ICogQHJldHVybiAgIHZvaWRzXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRyZW1vdmVfaW1hZ2U6IGZ1bmN0aW9uKCBldmVudCApIHtcblxuXHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuXHRcdFx0dGhpcy5tb2RlbC5nZXQoICQoIGV2ZW50LmN1cnJlbnRUYXJnZXQgKS5hdHRyKCAnZGF0YS1hdHRyaWJ1dGUnICkgKS5zZXQoIHtcblx0XHRcdFx0aWQ6ICcnLFxuXHRcdFx0XHRzcmM6ICcnLFxuXHRcdFx0fSApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIEhlbHBlciB0byB1bmRvIGNoYW5nZXNcblx0XHQgKiBCb3VuZCB0byBcImVzY2FwZVwiIGtleSB2aWEgb25fa2V5ZHdvbiBmdW5jdGlvblxuXHRcdCAqIEBwYXJhbSAgICBvYmogICBldmVudCAganMgZXZlbnQgb2JqZWN0XG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdHJldmVydF9lZGl0czogZnVuY3Rpb24oIGV2ZW50ICkge1xuXHRcdFx0dmFyICRlbCA9ICQoIGV2ZW50LnRhcmdldCApLFxuXHRcdFx0XHR2YWwgPSAkZWwuYXR0ciggJ2RhdGEtb3JpZ2luYWwtY29udGVudCcgKTtcblx0XHRcdCRlbC5odG1sKCB2YWwgKTtcblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogU3luYyBjaGFnZXMgdG8gdGhlIG1vZGVsIGFuZCBEQlxuXHRcdCAqIEBwYXJhbSAgICB7b2JqfSAgIGV2ZW50ICBqcyBldmVudCBvYmplY3Rcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0c2F2ZV9lZGl0czogZnVuY3Rpb24oIGV2ZW50ICkge1xuXG5cdFx0XHR2YXIgJGVsID0gJCggZXZlbnQudGFyZ2V0ICksXG5cdFx0XHRcdHZhbCA9IHRoaXMuZ2V0X2NvbnRlbnQoICRlbCApO1xuXG5cdFx0XHR0aGlzLm1vZGVsLnNldCggJGVsLmF0dHIoICdkYXRhLWF0dHJpYnV0ZScgKSwgdmFsICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogQ2hhbmdlIGV2ZW50IGZvciBhIHN3aXRjaCBlbGVtZW50XG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIGV2ZW50ICBqcyBldmVudCBvYmplY3Rcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNy4wXG5cdFx0ICovXG5cdFx0dG9nZ2xlX3N3aXRjaDogZnVuY3Rpb24oIGV2ZW50ICkge1xuXG5cdFx0XHRldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcblx0XHRcdHZhciAkZWwgPSAkKCBldmVudC50YXJnZXQgKSxcblx0XHRcdFx0YXR0ciA9ICRlbC5hdHRyKCAnbmFtZScgKSxcblx0XHRcdFx0cmVyZW5kZXIgPSAkZWwuYXR0ciggJ2RhdGEtcmVyZW5kZXInICksXG5cdFx0XHRcdHZhbDtcblxuXHRcdFx0aWYgKCAkZWwuaXMoICc6Y2hlY2tlZCcgKSApIHtcblx0XHRcdFx0dmFsID0gJGVsLmF0dHIoICdkYXRhLW9uJyApID8gJGVsLmF0dHIoICdkYXRhLW9uJyApIDogJ3llcyc7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR2YWwgPSAkZWwuYXR0ciggJ2RhdGEtb2ZmJyApID8gJGVsLmF0dHIoICdkYXRhLW9mZicgKSA6ICdubyc7XG5cdFx0XHR9XG5cblx0XHRcdGlmICggLTEgIT09IGF0dHIuaW5kZXhPZiggJy4nICkgKSB7XG5cblx0XHRcdFx0dmFyIHNwbGl0ID0gYXR0ci5zcGxpdCggJy4nICk7XG5cblx0XHRcdFx0aWYgKCAncGFyZW50JyA9PT0gc3BsaXRbMF0gKSB7XG5cdFx0XHRcdFx0dGhpcy5tb2RlbC5nZXRfcGFyZW50KCkuc2V0KCBzcGxpdFsxXSwgdmFsICk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0dGhpcy5tb2RlbC5nZXQoIHNwbGl0WzBdICkuc2V0KCBzcGxpdFsxXSwgdmFsICk7XG5cdFx0XHRcdH1cblxuXG5cdFx0XHR9IGVsc2Uge1xuXG5cdFx0XHRcdHRoaXMubW9kZWwuc2V0KCBhdHRyLCB2YWwgKTtcblxuXHRcdFx0fVxuXG5cdFx0XHR0aGlzLnRyaWdnZXIoIGF0dHIucmVwbGFjZSggJy4nLCAnLScgKSArICdfdG9nZ2xlJywgdmFsICk7XG5cblx0XHRcdGlmICggISByZXJlbmRlciB8fCAneWVzJyA9PT0gcmVyZW5kZXIgKSB7XG5cdFx0XHRcdHZhciBzZWxmID0gdGhpcztcblx0XHRcdFx0c2V0VGltZW91dCggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0c2VsZi5yZW5kZXIoKTtcblx0XHRcdFx0fSwgMTAwICk7XG5cdFx0XHR9XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogSW5pdGlhbGl6ZXMgYSBXUCBFZGl0b3Igb24gYSB0ZXh0YXJlYVxuXHRcdCAqIEBwYXJhbSAgICBzdHJpbmcgICBpZCAgICAgICAgQ1NTIElEIG9mIHRoZSBlZGl0b3IgKGRvbid0IGluY2x1ZGUgIylcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgICAgc2V0dGluZ3MgIG9wdGlvbmFsIG9iamVjdCBvZiBzZXR0aW5ncyB0byBwYXNzIHRvIHdwLmVkaXRvci5pbml0aWFsaXplKClcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0aW5pdF9lZGl0b3I6IGZ1bmN0aW9uKCBpZCwgc2V0dGluZ3MgKSB7XG5cblx0XHRcdHNldHRpbmdzID0gc2V0dGluZ3MgfHwge307XG5cblx0XHRcdHdwLmVkaXRvci5yZW1vdmUoIGlkICk7XG5cblx0XHRcdHdwLmVkaXRvci5pbml0aWFsaXplKCBpZCwgJC5leHRlbmQoIHRydWUsIHdwLmVkaXRvci5nZXREZWZhdWx0U2V0dGluZ3MoKSwge1xuXHRcdFx0XHRtZWRpYUJ1dHRvbnM6IHRydWUsXG5cdFx0XHRcdHRpbnltY2U6IHtcblx0XHRcdFx0XHR0b29sYmFyMTogJ2JvbGQsaXRhbGljLHN0cmlrZXRocm91Z2gsYnVsbGlzdCxudW1saXN0LGJsb2NrcXVvdGUsaHIsYWxpZ25sZWZ0LGFsaWduY2VudGVyLGFsaWducmlnaHQsbGluayx1bmxpbmssd3BfYWR2Jyxcblx0XHRcdFx0XHR0b29sYmFyMjogJ2Zvcm1hdHNlbGVjdCx1bmRlcmxpbmUsYWxpZ25qdXN0aWZ5LGZvcmVjb2xvcixwYXN0ZXRleHQscmVtb3ZlZm9ybWF0LGNoYXJtYXAsb3V0ZGVudCxpbmRlbnQsdW5kbyxyZWRvLHdwX2hlbHAnLFxuXHRcdFx0XHRcdHNldHVwOiBfLmJpbmQoIHRoaXMub25fZWRpdG9yX3JlYWR5LCB0aGlzICksXG5cdFx0XHRcdH1cblx0XHRcdH0sIHNldHRpbmdzICkgKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBTZXR1cCBhIHBlcm1hbGluayBlZGl0b3IgdG8gYWxsb3cgZWRpdGluZyBvZiBhIHBlcm1hbGlua1xuXHRcdCAqIEBwYXJhbSAgICBvYmogICBldmVudCAganMgZXZlbnQgb2JqZWN0XG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi42XG5cdFx0ICogQHZlcnNpb24gIDMuMTYuNlxuXHRcdCAqL1xuXHRcdG1ha2Vfc2x1Z19lZGl0YWJsZTogZnVuY3Rpb24oIGV2ZW50ICkge1xuXG5cdFx0XHR2YXIgc2VsZiA9IHRoaXMsXG5cdFx0XHRcdCRidG4gPSAkKCBldmVudC5jdXJyZW50VGFyZ2V0ICksXG5cdFx0XHRcdCRsaW5rID0gJGJ0bi5wcmV2QWxsKCAnYScgKSxcblx0XHRcdFx0JGlucHV0ID0gJGJ0bi5wcmV2KCAnaW5wdXQucGVybWFsaW5rJyApLFxuXHRcdFx0XHRmdWxsX3VybCA9ICRsaW5rLmF0dHIoICdocmVmJyApLFxuXHRcdFx0XHRzbHVnID0gJGlucHV0LnZhbCgpLFxuXHRcdFx0XHRzaG9ydF91cmwgPSBmdWxsX3VybC5yZXBsYWNlKCBzbHVnLCAnJyApO1xuXG5cdFx0XHQvLyBoaWRlIHRoZSBidXR0b25cblx0XHRcdCRidG4uaGlkZSgpO1xuXG5cdFx0XHQvLyBtYWtlIHRoZSBsaW5rIG5vdCBjbGlja2FibGVcblx0XHRcdCRsaW5rLmNzcygge1xuXHRcdFx0XHRjb2xvcjogJyM5OTknLFxuXHRcdFx0XHQncG9pbnRlci1ldmVudHMnOiAnbm9uZScsXG5cdFx0XHRcdCd0ZXh0LWRlY29yYXRpb24nOiAnbm9uZScsXG5cdFx0XHR9ICk7XG5cblx0XHRcdC8vIHJlbW92ZSB0aGUgY3VycmVudCBzbHVnICYgdHJhaWxpbmcgc2xhc2ggZnJvbSB0aGUgVVJMXG5cdFx0XHQkbGluay50ZXh0KCBzaG9ydF91cmwuc3Vic3RyaW5nKCAwLCBzaG9ydF91cmwubGVuZ3RoIC0gMSApICk7XG5cblx0XHRcdC8vIGZvY3VzIGluIG9uIHRoZSBmaWVsZFxuXHRcdFx0JGlucHV0LnNob3coKS5mb2N1cygpO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIENhbGxiYWNrIGZ1bmN0aW9uIGNhbGxlZCBhZnRlciBpbml0aWFsaXphdGlvbiBvZiBhbiBlZGl0b3Jcblx0XHQgKiBVcGRhdGVzIFVJIGlmIGEgbGFiZWwgaXMgcHJlc2VudFxuXHRcdCAqIEJpbmRzIGEgY2hhbmdlIGV2ZW50IHRvIGVuc3VyZSBlZGl0b3IgY2hhbmdlcyBhcmUgc2F2ZWQgdG8gdGhlIG1vZGVsXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIGVkaXRvciAgd3AuZWRpdG9yIGluc3RhbmNlXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTcuMVxuXHRcdCAqL1xuXHRcdG9uX2VkaXRvcl9yZWFkeTogZnVuY3Rpb24oIGVkaXRvciApIHtcblxuXHRcdFx0dmFyIHNlbGYgPSB0aGlzLFxuXHRcdFx0XHQkZWQgPSAkKCAnIycgKyBlZGl0b3IuaWQgKSxcblx0XHRcdFx0JHBhcmVudCA9ICRlZC5jbG9zZXN0KCAnLmxsbXMtZWRpdGFibGUtZWRpdG9yJyApLFxuXHRcdFx0XHQkbGFiZWwgPSAkcGFyZW50LmZpbmQoICcubGxtcy1sYWJlbCcgKSxcblx0XHRcdFx0cHJvcCA9ICRlZC5hdHRyKCAnZGF0YS1hdHRyaWJ1dGUnIClcblxuXHRcdFx0aWYgKCAkbGFiZWwubGVuZ3RoICkge1xuXHRcdFx0XHQkbGFiZWwucHJlcGVuZFRvKCAkcGFyZW50LmZpbmQoICcud3AtZWRpdG9yLXRvb2xzJyApICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIHNhdmUgY2hhbmdlcyB0byB0aGUgbW9kZWwgdmlhIFZpc3VhbCBlZFxuXHRcdFx0ZWRpdG9yLm9uKCAnY2hhbmdlJywgZnVuY3Rpb24oIGV2ZW50ICkge1xuXHRcdFx0XHRzZWxmLm1vZGVsLnNldCggcHJvcCwgd3AuZWRpdG9yLmdldENvbnRlbnQoIGVkaXRvci5pZCApICk7XG5cdFx0XHR9ICk7XG5cblx0XHRcdC8vIHNhdmUgY2hhbmdlcyB2aWEgVGV4dCBlZFxuXHRcdFx0JGVkLm9uKCAnaW5wdXQnLCBmdW5jdGlvbiggZXZlbnQgKSB7XG5cdFx0XHRcdHNlbGYubW9kZWwuc2V0KCBwcm9wLCAkZWQudmFsKCkgKTtcblx0XHRcdH0gKTtcblxuXHRcdFx0Ly8gdHJpZ2dlciBhbiBpbnB1dCBvbiB0aGUgVGV4dCBlZCB3aGVuIHF1aWNrdGFncyBidXR0b25zIGFyZSBjbGlja2VkXG5cdFx0XHQkcGFyZW50Lm9uKCAnY2xpY2snLCAnLnF1aWNrdGFncy10b29sYmFyIC5lZF9idXR0b24nLCBmdW5jdGlvbigpIHtcblx0XHRcdFx0c2V0VGltZW91dCggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0JGVkLnRyaWdnZXIoICdpbnB1dCcgKTtcblx0XHRcdFx0fSwgMTAgKTtcblx0XHRcdH0gKTtcblxuXHRcdH0sXG5cblx0XHRfdmFsaWRhdGVfdXJsOiBmdW5jdGlvbiggc3RyICkge1xuXG5cdFx0XHR2YXIgYSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoICdhJyApO1xuXHRcdFx0YS5ocmVmID0gc3RyO1xuXHRcdFx0cmV0dXJuICggYS5ob3N0ICYmIGEuaG9zdCAhPT0gd2luZG93LmxvY2F0aW9uLmhvc3QgKTtcblxuXHRcdH1cblxuXHR9O1xuXG59ICk7XG5cbi8qKlxuICogX3JlY2VpdmUgb3ZlcnJpZGUgZm9yIEJhY2tib25lLkNvbGxlY3Rpb25WaWV3IGNvcmVcbiAqIGVuYWJsZXMgY29ubmVjdGlvbiB3aXRoIGpRdWVyeSBVSSBkcmFnZ2FibGUgYnV0dG9uc1xuICogQHNpbmNlICAgIDMuMTYuMFxuICogQHZlcnNpb24gIDMuMTYuMFxuICovXG5kZWZpbmUoICdWaWV3cy9fUmVjZWl2YWJsZScsW10sIGZ1bmN0aW9uKCkge1xuXG5cdHJldHVybiB7XG5cblx0XHQvKipcblx0XHQgKiBPdmVybG9hZHMgdGhlIGZ1bmN0aW9uIGZyb20gQmFja2JvbmUuQ29sbGVjdGlvblZpZXcgY29yZSBiZWNhdXNlIGl0IGRvZXNuJ3QgcHJvcGVybHkgaGFuZGxlXG5cdFx0ICogcmVjZWlldmVzIGZyb20gYSBqUXVlcnkgVUkgZHJhZ2dhYmxlIG9iamVjdFxuXHRcdCAqIEBwYXJhbSAgICBvYmogICBldmVudCAganMgZXZlbnQgb2JqZWN0XG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIHVpICAgICBqUXVlcnkgVUkgb2JqZWN0XG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdF9yZWNlaXZlIDogZnVuY3Rpb24oIGV2ZW50LCB1aSApIHtcblxuXHRcdFx0Ly8gY2FtZSBmcm9tIHNpZGViYXIgZHJhZ1xuXHRcdFx0aWYgKCB1aS5zZW5kZXIuaGFzQ2xhc3MoICd1aS1kcmFnZ2FibGUnICkgKSB7XG5cdFx0XHRcdHZhciBpbmRleCA9IHRoaXMuX2dldENvbnRhaW5lckVsKCkuY2hpbGRyZW4oKS5pbmRleCggdWkuaGVscGVyICk7XG5cdFx0XHRcdHVpLmhlbHBlci5yZW1vdmUoKTsgLy8gcmVtb3ZlIHRoZSBoZWxwZXJcblx0XHRcdFx0dGhpcy5jb2xsZWN0aW9uLmFkZCgge30sIHsgYXQ6IGluZGV4IH0gKTtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXG5cdFx0XHR2YXIgc2VuZGVyTGlzdEVsID0gdWkuc2VuZGVyO1xuXHRcdFx0dmFyIHNlbmRlckNvbGxlY3Rpb25MaXN0VmlldyA9IHNlbmRlckxpc3RFbC5kYXRhKCAndmlldycgKTtcblx0XHRcdGlmKCAhIHNlbmRlckNvbGxlY3Rpb25MaXN0VmlldyB8fCAhIHNlbmRlckNvbGxlY3Rpb25MaXN0Vmlldy5jb2xsZWN0aW9uICkgcmV0dXJuO1xuXG5cdFx0XHR2YXIgbmV3SW5kZXggPSB0aGlzLl9nZXRDb250YWluZXJFbCgpLmNoaWxkcmVuKCkuaW5kZXgoIHVpLml0ZW0gKTtcblx0XHRcdHZhciBtb2RlbFJlY2VpdmVkID0gc2VuZGVyQ29sbGVjdGlvbkxpc3RWaWV3LmNvbGxlY3Rpb24uZ2V0KCB1aS5pdGVtLmF0dHIoICdkYXRhLW1vZGVsLWNpZCcgKSApO1xuXHRcdFx0c2VuZGVyQ29sbGVjdGlvbkxpc3RWaWV3LmNvbGxlY3Rpb24ucmVtb3ZlKCBtb2RlbFJlY2VpdmVkICk7XG5cdFx0XHR0aGlzLmNvbGxlY3Rpb24uYWRkKCBtb2RlbFJlY2VpdmVkLCB7IGF0IDogbmV3SW5kZXggfSApO1xuXHRcdFx0bW9kZWxSZWNlaXZlZC5jb2xsZWN0aW9uID0gdGhpcy5jb2xsZWN0aW9uOyAvLyBvdGhlcndpc2Ugd2lsbCBub3QgZ2V0IHByb3Blcmx5IHNldCwgc2luY2UgbW9kZWxSZWNlaXZlZC5jb2xsZWN0aW9uIG1pZ2h0IGFscmVhZHkgaGF2ZSBhIHZhbHVlLlxuXHRcdFx0dGhpcy5zZXRTZWxlY3RlZE1vZGVsKCBtb2RlbFJlY2VpdmVkICk7XG5cdFx0fSxcblxuXHR9XG5cbn0gKTtcblxuXG4vKipcbiAqIFNoaWZ0YWJsZSB2aWV3IG1peGluIGZ1bmN0aW9uXG4gKiBAc2luY2UgICAgMy4xNi4wXG4gKiBAdmVyc2lvbiAgMy4xNi4wXG4gKi9cbmRlZmluZSggJ1ZpZXdzL19TaGlmdGFibGUnLFtdLCBmdW5jdGlvbigpIHtcblxuXHRyZXR1cm4ge1xuXG5cdFx0LyoqXG5cdFx0ICogQ29uZGl0aW9uYWxseSBoaWRlIGFjdGlvbiBidXR0b25zIGJhc2VkIG9uIHNlY3Rpb24gcG9zaXRpb24gaW4gY29sbGVjdGlvblxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRtYXliZV9oaWRlX3NoaWZ0YWJsZV9idXR0b25zOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0aWYgKCAhIHRoaXMubW9kZWwuY29sbGVjdGlvbiApIHtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXG5cdFx0XHR2YXIgdHlwZSA9IHRoaXMubW9kZWwuZ2V0KCAndHlwZScgKTtcblxuXHRcdFx0aWYgKCB0aGlzLm1vZGVsLmNvbGxlY3Rpb24uZmlyc3QoKSA9PT0gdGhpcy5tb2RlbCApIHtcblx0XHRcdFx0dGhpcy4kZWwuZmluZCggJy5zaGlmdC11cC0tJyArIHR5cGUgKS5oaWRlKCk7XG5cdFx0XHR9IGVsc2UgaWYgKCB0aGlzLm1vZGVsLmNvbGxlY3Rpb24ubGFzdCgpID09PSB0aGlzLm1vZGVsICkge1xuXHRcdFx0XHR0aGlzLiRlbC5maW5kKCAnLnNoaWZ0LWRvd24tLScgKyB0eXBlICkuaGlkZSgpO1xuXHRcdFx0fVxuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIE1vdmUgYW4gaXRlbSBpbiBhIGNvbGxlY3Rpb24gZnJvbSBvbmUgcG9zaXRpb24gdG8gYW5vdGhlclxuXHRcdCAqIEBwYXJhbSAgICBpbnQgICBvbGRfaW5kZXggIGN1cnJlbnQgKG9sZCkgaW5kZXggd2l0aGluIHRoZSBjb2xsZWN0aW9uXG5cdFx0ICogQHBhcmFtICAgIGludCAgIG5ld19pbmRleCAgZGVzaXJlZCAobmV3KSBpbmRleCB3aXRoaW4gdGhlIGNvbGxlY3Rpb25cblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0c2hpZnQ6IGZ1bmN0aW9uKCBvbGRfaW5kZXgsIG5ld19pbmRleCApIHtcblxuXHRcdFx0dmFyIGNvbGxlY3Rpb24gPSB0aGlzLm1vZGVsLmNvbGxlY3Rpb247XG5cblx0XHRcdGNvbGxlY3Rpb24ucmVtb3ZlKCB0aGlzLm1vZGVsICk7XG5cdFx0XHRjb2xsZWN0aW9uLmFkZCggdGhpcy5tb2RlbCwgeyBhdDogbmV3X2luZGV4IH0gKTtcblx0XHRcdGNvbGxlY3Rpb24udHJpZ2dlciggJ3Jlb3JkZXInICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogTW92ZSBhbiBpdGVtIGRvd24gdGhlIHRyZWUgb25lIHBvc2l0aW9uXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdHNoaWZ0X2Rvd246IGZ1bmN0aW9uKCBlICkge1xuXG5cdFx0XHRlLnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHR2YXIgaW5kZXggPSB0aGlzLm1vZGVsLmNvbGxlY3Rpb24uaW5kZXhPZiggdGhpcy5tb2RlbCApO1xuXHRcdFx0dGhpcy5zaGlmdCggaW5kZXgsIGluZGV4ICsgMSApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIE1vdmUgYW4gaXRlbSB1cCB0aGUgdHJlZSBvbmUgcG9zaXRpb25cblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0c2hpZnRfdXA6IGZ1bmN0aW9uKCBlICkge1xuXG5cdFx0XHRlLnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHR2YXIgaW5kZXggPSB0aGlzLm1vZGVsLmNvbGxlY3Rpb24uaW5kZXhPZiggdGhpcy5tb2RlbCApO1xuXHRcdFx0dGhpcy5zaGlmdCggaW5kZXgsIGluZGV4IC0gMSApO1xuXG5cdFx0fSxcblxuXHR9O1xuXG59ICk7XG5cbi8qKlxuICogU3VidmlldyB1dGlsaXR5IG1peGluXG4gKiBAc2luY2UgICAgMy4xNi4wXG4gKiBAdmVyc2lvbiAgMy4xNi4wXG4gKi9cbmRlZmluZSggJ1ZpZXdzL19TdWJ2aWV3JyxbXSwgZnVuY3Rpb24oKSB7XG5cblx0cmV0dXJuIHtcblxuXHRcdHN1YnNjcmlwdGlvbnM6IHt9LFxuXG5cdFx0LyoqXG5cdFx0ICogTmFtZSBvZiB0aGUgY3VycmVudCBzdWJ2aWV3XG5cdFx0ICogQHR5cGUgIHtTdHJpbmd9XG5cdFx0ICovXG5cdFx0c3RhdGU6ICcnLFxuXG5cdFx0LyoqXG5cdFx0ICogT2JqZWN0IG9mIHN1YnZpZXcgZGF0YVxuXHRcdCAqIEB0eXBlICB7T2JqZWN0fVxuXHRcdCAqL1xuXHRcdHZpZXdzOiB7fSxcblxuXHRcdC8qKlxuXHRcdCAqIFJldHJpZXZlIGEgc3VidmlldyBieSBuYW1lIGZyb20gdGhpcy52aWV3c1xuXHRcdCAqIEBwYXJhbSAgICBzdHJpbmcgICBuYW1lICAgbmFtZSBvZiB0aGUgc3Vidmlld1xuXHRcdCAqIEByZXR1cm4gICBvYmx8ZmFsc2Vcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGdldF9zdWJ2aWV3OiBmdW5jdGlvbiggbmFtZSApIHtcblxuXHRcdFx0aWYgKCB0aGlzLnZpZXdzWyBuYW1lIF0gKSB7XG5cdFx0XHRcdHJldHVybiB0aGlzLnZpZXdzWyBuYW1lIF07XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBmYWxzZTtcblxuXHRcdH0sXG5cblx0XHRldmVudHNfc3Vic2NyaWJlOiBmdW5jdGlvbiggZXZlbnRzICkge1xuXG5cdFx0XHRfLmVhY2goIGV2ZW50cywgZnVuY3Rpb24oIGZ1bmMsIGV2ZW50ICkge1xuXG5cdFx0XHRcdHRoaXMuc3Vic2NyaXB0aW9uc1sgZXZlbnQgXSA9IGZ1bmM7XG5cdFx0XHRcdEJhY2tib25lLnB1YlN1Yi5vbiggZXZlbnQsIGZ1bmMsIHRoaXMgKTtcblxuXHRcdFx0fSwgdGhpcyApO1xuXG5cdFx0fSxcblxuXHRcdGV2ZW50c191bnN1YnNjcmliZTogZnVuY3Rpb24oKSB7XG5cblx0XHRcdF8uZWFjaCggdGhpcy5zdWJzY3JpcHRpb25zLCBmdW5jdGlvbiggZnVuYywgZXZlbnQgKSB7XG5cblx0XHRcdFx0QmFja2JvbmUucHViU3ViLm9mZiggZXZlbnQsIGZ1bmMsIHRoaXMgKTtcblx0XHRcdFx0ZGVsZXRlIHRoaXMuc3Vic2NyaXB0aW9uc1sgZXZlbnQgXTtcblxuXHRcdFx0fSwgdGhpcyApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFJlbW92ZSBhIHNpbmdsZSBzdWJ2aWV3IChhbmQgYWxsIGl0J3Mgc3Vidmlld3MpIGJ5IG5hbWVcblx0XHQgKiBAcGFyYW0gICAgc3RyaW5nICAgbmFtZSAgIG5hbWUgb2YgdGhlIHN1YnZpZXdcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0cmVtb3ZlX3N1YnZpZXc6IGZ1bmN0aW9uKCBuYW1lICkge1xuXG5cdFx0XHR2YXIgdmlldyA9IHRoaXMuZ2V0X3N1YnZpZXcoIG5hbWUgKTtcblxuXHRcdFx0aWYgKCAhIHZpZXcgKSB7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblxuXHRcdFx0aWYgKCB2aWV3Lmluc3RhbmNlICkge1xuXG5cdFx0XHRcdC8vIHJlbW92ZSB0aGUgc3Vidmlld3MgaWYgdGhlIHZpZXcgaGFzIHN1YnZpZXdzXG5cdFx0XHRcdGlmICggISBfLmlzRW1wdHkoIHZpZXcuaW5zdGFuY2Uudmlld3MgKSApIHtcblx0XHRcdFx0XHR2aWV3Lmluc3RhbmNlLmV2ZW50c191bnN1YnNjcmliZSgpO1xuXHRcdFx0XHRcdHZpZXcuaW5zdGFuY2UucmVtb3ZlX3N1YnZpZXdzKCk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHR2aWV3Lmluc3RhbmNlLm9mZigpO1xuXHRcdFx0XHR2aWV3Lmluc3RhbmNlLm9mZiggbnVsbCwgbnVsbCwgbnVsbCApO1xuXHRcdFx0XHR2aWV3Lmluc3RhbmNlLnJlbW92ZSgpO1xuXHRcdFx0XHR2aWV3Lmluc3RhbmNlLnVuZGVsZWdhdGVFdmVudHMoKTtcblxuXHRcdFx0XHQvLyBfLmVhY2goIHZpZXcuaW5zdGFuY2UsIGZ1bmN0aW9uKCB2YWwsIGtleSApIHtcblx0XHRcdFx0Ly8gXHRkZWxldGUgdmlldy5pbnN0YW5jZVsga2V5IF07XG5cdFx0XHRcdC8vIH0gKTtcblxuXHRcdFx0XHR2aWV3Lmluc3RhbmNlID0gbnVsbDtcblxuXHRcdFx0fVxuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFJlbW92ZSBhbGwgc3Vidmlld3MgKGFuZCBhbGwgdGhlIHN1YnZpZXdzIG9mIHRob3NlIHN1YnZpZXdzKVxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRyZW1vdmVfc3Vidmlld3M6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHRfLmVhY2goIHRoaXMudmlld3MsIGZ1bmN0aW9uKCBkYXRhLCBuYW1lICkge1xuXG5cdFx0XHRcdHRoaXMucmVtb3ZlX3N1YnZpZXcoIG5hbWUgKTtcblxuXHRcdFx0fSwgdGhpcyApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFJlbmRlciBzdWJ2aWV3cyBiYXNlZCBvbiBjdXJyZW50IHN0YXRlXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIHZpZXdfZGF0YSAgYWRkaXRpb25hbCBkYXRhIHRvIHBhc3MgdG8gdGhlIHN1YnZpZXdzXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdHJlbmRlcl9zdWJ2aWV3czogZnVuY3Rpb24oIHZpZXdfZGF0YSApIHtcblxuXHRcdFx0dmlld19kYXRhID0gdmlld19kYXRhIHx8IHt9O1xuXG5cdFx0XHRfLmVhY2goIHRoaXMudmlld3MsIGZ1bmN0aW9uKCBkYXRhLCBuYW1lICkge1xuXG5cdFx0XHRcdGlmICggdGhpcy5zdGF0ZSA9PT0gZGF0YS5zdGF0ZSApIHtcblxuXHRcdFx0XHRcdHRoaXMucmVuZGVyX3N1YnZpZXcoIG5hbWUsIHZpZXdfZGF0YSApO1xuXG5cdFx0XHRcdH0gZWxzZSB7XG5cblx0XHRcdFx0XHR0aGlzLnJlbW92ZV9zdWJ2aWV3KCBuYW1lICk7XG5cblx0XHRcdFx0fVxuXG5cdFx0XHR9LCB0aGlzICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogUmVuZGVyIGEgc2luZ2xlIHN1YnZpZXcgYnkgbmFtZVxuXHRcdCAqIEBwYXJhbSAgICBzdHJpbmcgICBuYW1lICAgICAgIG5hbWUgb2YgdGhlIHN1YnZpZXdcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgICAgdmlld19kYXRhICBhZGRpdGlvbmFsIGRhdGEgdG8gcGFzcyB0byB0aGUgc3VidmlldyBpbml0aWFsaXplclxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRyZW5kZXJfc3VidmlldzogZnVuY3Rpb24oIG5hbWUsIHZpZXdfZGF0YSApIHtcblxuXHRcdFx0dmFyIHZpZXcgPSB0aGlzLmdldF9zdWJ2aWV3KCBuYW1lICk7XG5cblx0XHRcdGlmICggISB2aWV3ICkge1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cblx0XHRcdHRoaXMucmVtb3ZlX3N1YnZpZXcoIG5hbWUgKTtcblxuXHRcdFx0aWYgKCAhIHZpZXcuaW5zdGFuY2UgKSB7XG5cdFx0XHRcdHZpZXcuaW5zdGFuY2UgPSBuZXcgdmlldy5jbGFzcyggdmlld19kYXRhICk7XG5cdFx0XHR9XG5cblx0XHRcdHZpZXcuaW5zdGFuY2UucmVuZGVyKCk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogU2V0IHRoZSBjdXJyZW50IHN1YnZpZXdcblx0XHQgKiBNdXN0IGNhbGwgcmVuZGVyIGFmdGVyIVxuXHRcdCAqIEBwYXJhbSAgICBzdHJpbmcgICBzdGF0ZSAgbmFtZSBvZiB0aGUgc3RhdGUgW2J1aWxkZXJ8ZWRpdG9yXVxuXHRcdCAqIEByZXR1cm4gICBvYmogICAgICAgICAgICAgdGhpcyBmb3IgY2hhaW5pbmdcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdHNldF9zdGF0ZTogZnVuY3Rpb24gKCBzdGF0ZSApIHtcblxuXHRcdFx0dGhpcy5zdGF0ZSA9IHN0YXRlO1xuXHRcdFx0cmV0dXJuIHRoaXM7XG5cblx0XHR9LFxuXG5cdH1cblxufSApO1xuXG4vKipcbiAqIFRyYXNoYWJsZSBtb2RlbFxuICogQHR5cGUgICAgIHtPYmplY3R9XG4gKiBAc2luY2UgICAgMy4xNi4xMlxuICogQHZlcnNpb24gIDMuMTYuMTJcbiAqL1xuZGVmaW5lKCAnVmlld3MvX1RyYXNoYWJsZScsW10sIGZ1bmN0aW9uKCkge1xuXG5cdHJldHVybiB7XG5cblx0XHQvKipcblx0XHQgKiBET00gRXZlbnRzXG5cdFx0ICogQHR5cGUgIHtPYmplY3R9XG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMTJcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4xMlxuXHRcdCAqL1xuXHRcdGV2ZW50czoge1xuXHRcdFx0J2NsaWNrIGFbaHJlZj1cIiNsbG1zLXRyYXNoLW1vZGVsXCJdJzogJ3RyYXNoX21vZGVsJyxcblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogUmVtb3ZlIGEgbW9kZWwgZnJvbSBpdCdzIHBhcmVudCBhbmQgZGVsZXRlIGl0XG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIGV2ZW50ICBqcyBldmVudCBvYmplY3Rcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjEyXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMTJcblx0XHQgKi9cblx0XHR0cmFzaF9tb2RlbDogZnVuY3Rpb24oIGV2ZW50ICkge1xuXG5cdFx0XHRpZiAoIGV2ZW50ICkge1xuXHRcdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0XHRldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcblx0XHRcdH1cblxuXHRcdFx0dmFyIG1zZyA9IExMTVMubDEwbi5yZXBsYWNlKCAnQXJlIHlvdSBzdXJlIHlvdSB3YW50IHRvIG1vdmUgdGhpcyAlcyB0byB0aGUgdHJhc2g/Jywge1xuXHRcdFx0XHQnJXMnOiB0aGlzLm1vZGVsLmdldF9sMTBuX3R5cGUoKSxcblx0XHRcdH0gKTtcblxuXHRcdFx0aWYgKCB3aW5kb3cuY29uZmlybSggbXNnICkgKSB7XG5cblx0XHRcdFx0aWYgKCB0aGlzLm1vZGVsLmNvbGxlY3Rpb24gKSB7XG5cdFx0XHRcdFx0dGhpcy5tb2RlbC5jb2xsZWN0aW9uLnJlbW92ZSggdGhpcy5tb2RlbCApO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gcHVibGlzaCBldmVudFxuXHRcdFx0XHRCYWNrYm9uZS5wdWJTdWIudHJpZ2dlciggJ21vZGVsLXRyYXNoZWQnLCB0aGlzLm1vZGVsICk7XG5cblx0XHRcdFx0Ly8gdHJpZ2dlciBsb2NhbCBldmVudCBzbyBleHRlbmRpbmcgdmlld3MgY2FuIHJ1biBvdGhlciBhY3Rpb25zIHdoZXJlIG5lY2Vzc2FyeVxuXHRcdFx0XHR0aGlzLnRyaWdnZXIoICdtb2RlbC10cmFzaGVkJywgdGhpcy5tb2RlbCApO1xuXG5cdFx0XHR9XG5cblx0XHR9LFxuXG5cdH1cblxufSApO1xuXG4vKipcbiAqIExvYWQgdmlldyBtaXhpbnNcbiAqIEByZXR1cm4gICBvYmpcbiAqIEBzaW5jZSAgICAzLjE3LjFcbiAqIEB2ZXJzaW9uICAzLjE3LjFcbiAqL1xuZGVmaW5lKCAnVmlld3MvX2xvYWRlcicsW1xuXHRcdCdWaWV3cy9fRGV0YWNoYWJsZScsXG5cdFx0J1ZpZXdzL19FZGl0YWJsZScsXG5cdFx0J1ZpZXdzL19SZWNlaXZhYmxlJyxcblx0XHQnVmlld3MvX1NoaWZ0YWJsZScsXG5cdFx0J1ZpZXdzL19TdWJ2aWV3Jyxcblx0XHQnVmlld3MvX1RyYXNoYWJsZSdcblx0XSxcblx0ZnVuY3Rpb24oXG5cdFx0RGV0YWNoYWJsZSxcblx0XHRFZGl0YWJsZSxcblx0XHRSZWNlaXZhYmxlLFxuXHRcdFNoaWZ0YWJsZSxcblx0XHRTdWJ2aWV3LFxuXHRcdFRyYXNoYWJsZVxuXHQpIHtcblxuXHRyZXR1cm4ge1xuXHRcdERldGFjaGFibGU6IERldGFjaGFibGUsXG5cdFx0RWRpdGFibGU6IEVkaXRhYmxlLFxuXHRcdFJlY2VpdmFibGU6IFJlY2VpdmFibGUsXG5cdFx0U2hpZnRhYmxlOiBTaGlmdGFibGUsXG5cdFx0U3VidmlldzogU3Vidmlldyxcblx0XHRUcmFzaGFibGU6IFRyYXNoYWJsZSxcblx0fTtcblxufSApO1xuXG4vKipcbiAqIENvbnN0cnVjdG9yIGZ1bmN0aW9ucyBmb3IgY29uc3RydWN0aW5nIG1vZGVscywgdmlld3MsIGFuZCBjb2xsZWN0aW9uc1xuICogQHNpbmNlICAgIDMuMTYuMFxuICogQHZlcnNpb24gIDMuMTcuMVxuICovXG5kZWZpbmUoICdDb250cm9sbGVycy9Db25zdHJ1Y3QnLFtcblx0XHQnQ29sbGVjdGlvbnMvbG9hZGVyJyxcblx0XHQnTW9kZWxzL2xvYWRlcicsXG5cdFx0J1ZpZXdzL19sb2FkZXInXG5cdF0sIGZ1bmN0aW9uKFxuXHRcdENvbGxlY3Rpb25zLFxuXHRcdE1vZGVscyxcblx0XHRWaWV3c1xuXHQpIHtcblxuXHRyZXR1cm4gZnVuY3Rpb24oKSB7XG5cblx0XHQvKipcblx0XHQgKiBJbnRlcm5hbCBnZXR0ZXJcblx0XHQgKiBDb25zdHJ1Y3RzIG5ldyBDb2xsZWN0aW9ucywgTW9kZWxzLCBhbmQgVmlld3Ncblx0XHQgKiBAcGFyYW0gICAgb2JqICAgICAgdHlwZSAgICAgdHlwZSBvZiBvYmplY3QgdG8gY29uc3RydWN0IFtDb2xsZWN0aW9uLE1vZGVsLFZpZXddXG5cdFx0ICogQHBhcmFtICAgIHN0cmluZyAgIG5hbWUgICAgIG5hbWUgb2YgdGhlIG9iamVjdCB0byBjb25zdHJ1Y3Rcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgICAgZGF0YSAgICAgb2JqZWN0IGRhdGEgdG8gcGFzcyBpbnRvIHRoZSBvYmplY3QncyBjb25zdHJ1Y3RvclxuXHRcdCAqIEBwYXJhbSAgICBvYmogICAgICBvcHRpb25zICBvYmplY3Qgb3B0aW9ucyB0byBwYXNzIGludG8gdGhlIGNvbnN0cnVjdG9yXG5cdFx0ICogQHJldHVybiAgIG9ialxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0ZnVuY3Rpb24gZ2V0KCB0eXBlLCBuYW1lLCBkYXRhLCBvcHRpb25zICkge1xuXG5cdFx0XHRpZiAoICEgdHlwZVsgbmFtZSBdICkge1xuXHRcdFx0XHRjb25zb2xlLmxvZyggJ1wiJyArIG5hbWUgKyAnXCIgbm90IGZvdW5kLicgKTtcblx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gbmV3IHR5cGVbIG5hbWUgXSggZGF0YSwgb3B0aW9ucyApO1xuXG5cdFx0fVxuXG5cdFx0LyoqXG5cdFx0ICogSW5zdGFudGlhdGUgYSBjb2xsZWN0aW9uXG5cdFx0ICogQHBhcmFtICAgIHN0cmluZyAgIG5hbWUgICAgIENvbGxlY3Rpb24gY2xhc3MgbmFtZSAoRUc6IFwiU2VjdGlvbnNcIilcblx0XHQgKiBAcGFyYW0gICAgYXJyYXkgICAgZGF0YSAgICAgQXJyYXkgb2YgbW9kZWwgb2JqZWN0cyB0byBwYXNzIHRvIHRoZSBjb25zdHJ1Y3RvclxuXHRcdCAqIEBwYXJhbSAgICBvYmogICAgICBvcHRpb25zICBPYmplY3Qgb2Ygb3B0aW9ucyB0byBwYXNzIHRvIHRoZSBjb25zdHJ1Y3RvclxuXHRcdCAqIEByZXR1cm4gICBvYmpcblx0XHQgKiBAc2luY2UgICAgMy4xNy4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTcuMFxuXHRcdCAqL1xuXHRcdHRoaXMuZ2V0X2NvbGxlY3Rpb24gPSBmdW5jdGlvbiggbmFtZSwgZGF0YSwgb3B0aW9ucyApIHtcblxuXHRcdFx0cmV0dXJuIGdldCggQ29sbGVjdGlvbnMsIG5hbWUsIGRhdGEsIG9wdGlvbnMgKTtcblxuXHRcdH07XG5cblx0XHQvKipcblx0XHQgKiBJbnN0YW50aWF0ZSBhIG1vZGVsXG5cdFx0ICogQHBhcmFtICAgIHN0cmluZyAgIG5hbWUgICAgIE1vZGVsIGNsYXNzIG5hbWUgKEVHOiBcIlNlY3Rpb25cIilcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgICAgZGF0YSAgICAgT2JqZWN0IG9mIG1vZGVsIGF0dHJpYnV0ZXMgdG8gcGFzcyB0byB0aGUgY29uc3RydWN0b3Jcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgICAgb3B0aW9ucyAgT2JqZWN0IG9mIG9wdGlvbnMgdG8gcGFzcyB0byB0aGUgY29uc3RydWN0b3Jcblx0XHQgKiBAcmV0dXJuICAgb2JqXG5cdFx0ICogQHNpbmNlICAgIDMuMTcuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE3LjBcblx0XHQgKi9cblx0XHR0aGlzLmdldF9tb2RlbCA9IGZ1bmN0aW9uKCBuYW1lLCBkYXRhLCBvcHRpb25zICkge1xuXG5cdFx0XHRyZXR1cm4gZ2V0KCBNb2RlbHMsIG5hbWUsIGRhdGEsIG9wdGlvbnMgKTtcblxuXHRcdH07XG5cblx0XHQvKipcblx0XHQgKiBMZXQgM3JkIHBhcnRpZXMgZXh0ZW5kIGEgdmlldyB1c2luZyBhbnkgb2YgdGhlIG1peGluIChfKSB2aWV3c1xuXHRcdCAqIEBwYXJhbSAgICB7b2JqfSAgICAgdmlldyAgICAgYmFzZSBvYmplY3QgdXNlZCBmb3IgdGhlIHZpZXdcblx0XHQgKiBAcGFyYW0uLi4ge3N0cmluZ30gIGV4dGVuZHMgIGFueSBudW1iZXIgb2Ygc3RyaW5ncyB0aGF0IHNob3VsZCBiZSBtaXhlZCBpbnRvIHRoZSB2aWV3XG5cdFx0ICogQHJldHVybiAgIG9ialxuXHRcdCAqIEBzaW5jZSAgICAzLjE3LjFcblx0XHQgKiBAdmVyc2lvbiAgMy4xNy4xXG5cdFx0ICovXG5cdFx0dGhpcy5leHRlbmRfdmlldyA9IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHR2YXIgdmlldyA9IGFyZ3VtZW50c1swXSxcblx0XHRcdFx0aSA9IDE7XG5cblx0XHRcdHdoaWxlICggYXJndW1lbnRzWyBpIF0gKSB7XG5cblx0XHRcdFx0dmFyIGNsYXNzbmFtZSA9IGFyZ3VtZW50c1sgaSBdO1xuXHRcdFx0XHRpZiAoIFZpZXdzWyBjbGFzc25hbWUgXSApIHtcblxuXHRcdFx0XHRcdGlmICggdmlldy5ldmVudHMgJiYgVmlld3NbIGNsYXNzbmFtZSBdLmV2ZW50cyApIHtcblx0XHRcdFx0XHRcdHZpZXcuZXZlbnRzID0gXy5kZWZhdWx0cyggdmlldy5ldmVudHMsIFZpZXdzWyBjbGFzc25hbWUgXS5ldmVudHMgKTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHR2aWV3ID0gXy5kZWZhdWx0cyggdmlldywgVmlld3NbIGNsYXNzbmFtZSBdICk7XG5cblx0XHRcdFx0fVxuXG5cdFx0XHRcdGkrKztcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIEJhY2tib25lLlZpZXcuZXh0ZW5kKCB2aWV3ICk7XG5cblx0XHR9O1xuXG5cdFx0LyoqXG5cdFx0ICogQWxsb3dzIGN1c3RvbSBjb2xsZWN0aW9uIHJlZ2lzdHJhdGlvbiBieSBleHRlbmRpbmcgdGhlIGRlZmF1bHQgQmFja0JvbmUgY29sbGVjdGlvblxuXHRcdCAqIEBwYXJhbSAgICBzdHJpbmcgICBuYW1lICAgbW9kZWwgbmFtZVxuXHRcdCAqIEBwYXJhbSAgICBvYmogICAgICBwcm9wcyAgcHJvcGVydGllcyB0byBleHRlbmQgdGhlIGNvbGxlY3Rpb24gd2l0aFxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTcuMVxuXHRcdCAqIEB2ZXJzaW9uICAzLjE3LjFcblx0XHQgKi9cblx0XHR0aGlzLnJlZ2lzdGVyX2NvbGxlY3Rpb24gPSBmdW5jdGlvbiggbmFtZSwgcHJvcHMgKSB7XG5cblx0XHRcdENvbGxlY3Rpb25zWyBuYW1lIF0gPSBCYWNrYm9uZS5Db2xsZWN0aW9uLmV4dGVuZCggcHJvcHMgKTtcblxuXHRcdH07XG5cblx0XHQvKipcblx0XHQgKiBBbGxvd3MgY3VzdG9tIG1vZGVsIHJlZ2lzdHJhdGlvbiBieSBleHRlbmRpbmcgdGhlIGRlZmF1bHQgYWJzdHJhY3QgbW9kZWxcblx0XHQgKiBAcGFyYW0gICAgc3RyaW5nICAgbmFtZSAgIG1vZGVsIG5hbWVcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgICAgcHJvcHMgIHByb3BlcnRpZXMgdG8gZXh0ZW5kIHRoZSBhYnN0cmFjdCBtb2RlbCB3aXRoXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNy4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTcuMFxuXHRcdCAqL1xuXHRcdHRoaXMucmVnaXN0ZXJfbW9kZWwgPSBmdW5jdGlvbiggbmFtZSwgcHJvcHMgKSB7XG5cblx0XHRcdE1vZGVsc1sgbmFtZSBdID0gTW9kZWxzWydBYnN0cmFjdCddLmV4dGVuZCggcHJvcHMgKTtcblxuXHRcdH07XG5cblx0XHRyZXR1cm4gdGhpcztcblxuXHR9O1xuXG59ICk7XG5cbi8qKlxuICogTGlmdGVyTE1TIEJ1aWxkZXIgRGVidWdnaW5nIHN1aXRlXG4gKiBAc2luY2UgICAgMy4xNi4wXG4gKiBAdmVyc2lvbiAgMy4xNi4wXG4gKi9cbmRlZmluZSggJ0NvbnRyb2xsZXJzL0RlYnVnJyxbXSwgZnVuY3Rpb24oKSB7XG5cbiBcdHJldHVybiBmdW5jdGlvbiggc2V0dGluZ3MgKSB7XG5cbiBcdFx0dmFyIHNlbGYgPSB0aGlzLFxuIFx0XHRcdGVuYWJsZWQgPSBzZXR0aW5ncy5lbmFibGVkIHx8IGZhbHNlO1xuXG5cdFx0LyoqXG5cdFx0ICogRGlzYWJsZSBkZWJ1Z2dpbmdcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG4gXHRcdHRoaXMuZGlzYWJsZSA9IGZ1bmN0aW9uKCkge1xuXG4gXHRcdFx0c2VsZi5sb2coICdMaWZ0ZXJMTVMgQnVpbGRlciBkZWJ1Z2dpbmcgZGlzYWJsZWQnICk7XG4gXHRcdFx0ZW5hYmxlZCA9IGZhbHNlO1xuXG4gXHRcdH07XG5cblx0XHQvKipcblx0XHQgKiBFbmFibGUgZGVidWdnaW5nXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuIFx0XHR0aGlzLmVuYWJsZSA9IGZ1bmN0aW9uKCkge1xuXG4gXHRcdFx0ZW5hYmxlZCA9IHRydWU7XG4gXHRcdFx0c2VsZi5sb2coICdMaWZ0ZXJMTVMgQnVpbGRlciBkZWJ1Z2dpbmcgZW5hYmxlZCcgKTtcblxuIFx0XHR9O1xuXG4gXHRcdC8qKlxuIFx0XHQgKiBHZW5lcmFsIGxvZ2dpbmcgZnVuY3Rpb25cbiBcdFx0ICogTG9ncyB0byB0aGUganMgY29uc29sZSBvbmx5IGlmIGxvZ2dpbmcgaXMgZW5hYmxlZFxuIFx0XHQgKiBAcmV0dXJuICAgdm9pZFxuIFx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG4gXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcbiBcdFx0ICovXG4gXHRcdHRoaXMubG9nID0gZnVuY3Rpb24oKSB7XG5cblx0XHRcdGlmICggISBlbmFibGVkICkge1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cblx0XHRcdF8uZWFjaCggYXJndW1lbnRzLCBmdW5jdGlvbiggZGF0YSApIHtcblx0XHRcdFx0Y29uc29sZS5sb2coIGRhdGEgKTtcblx0XHRcdH0gKTtcblxuIFx0XHR9O1xuXG4gXHRcdC8qKlxuIFx0XHQgKiBUb2dnbGVzIGN1cnJlbnQgc3RhdGUgb2YgdGhlIGxvZ2dlciBvbiBvciBvZmZcbiBcdFx0ICogQHJldHVybiAgIHZvaWRcbiBcdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuIFx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG4gXHRcdCAqL1xuIFx0XHR0aGlzLnRvZ2dsZSA9IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHRpZiAoIGVuYWJsZWQgKSB7XG5cdFx0XHRcdHNlbGYuZGlzYWJsZSgpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0c2VsZi5lbmFibGUoKTtcblx0XHRcdH1cblxuIFx0XHR9O1xuXG4gXHRcdC8vIG9uIHN0YXJ0dXAsIGxvZyBhIG1lc3NhZ2UgaWYgbG9nZ2luZyBpcyBlbmFibGVkXG4gXHRcdGlmICggZW5hYmxlZCApIHtcbiBcdFx0XHRzZWxmLmVuYWJsZSgpO1xuIFx0XHR9XG5cbiBcdH1cblxuIH0gKTtcblxuLyoqXG4gKiBNb2RlbCBzY2hlbWEgZnVuY3Rpb25zXG4gKiBAc2luY2UgICAgMy4xNy4wXG4gKiBAdmVyc2lvbiAgMy4xNy4wXG4gKi9cbmRlZmluZSggJ0NvbnRyb2xsZXJzL1NjaGVtYXMnLFtdLCBmdW5jdGlvbigpIHtcblxuXHQvKipcblx0ICogTWFpbiBTY2hlbWFzIGNsYXNzXG5cdCAqIEBwYXJhbSAgICBvYmogICBzY2hlbWFzICBzY2hlbWFzIGRlZmluaXRpb25zIGluaXRpYWxpemVkIHZpYSBQSFAgZmlsdGVyc1xuXHQgKiBAcmV0dXJuICAgb2JqXG5cdCAqIEBzaW5jZSAgICAzLjE3LjBcblx0ICogQHZlcnNpb24gIDMuMTcuMFxuXHQgKi9cblx0cmV0dXJuIGZ1bmN0aW9uKCBzY2hlbWFzICkge1xuXG5cdFx0Ly8gaW5pdGlhbGl6ZSBhbnkgY3VzdG9tIHNjaGVtYXMgZGVmaW5lZCB2aWEgUEhQXG5cdFx0dmFyIGN1c3RvbV9zY2hlbWFzID0gc2NoZW1hcztcblx0XHRfLmVhY2goIGN1c3RvbV9zY2hlbWFzLCBmdW5jdGlvbiggdHlwZSApIHtcblx0XHRcdF8uZWFjaCggdHlwZSwgZnVuY3Rpb24oIHNjaGVtYSApIHtcblx0XHRcdFx0c2NoZW1hLmN1c3RvbSA9IHRydWU7XG5cdFx0XHR9ICk7XG5cdFx0fSApO1xuXG5cdFx0LyoqXG5cdFx0ICogUmV0cmlldmUgYSBzY2hlbWEgZm9yIGEgZ2l2ZW4gbW9kZWwgYnkgdHlwZVxuXHRcdCAqIEV4dGVuZHMgZGVmYXVsdCBzY2hlbWFzIGRlZmluaXRpb25zIHdpdGggY3VzdG9tIDNyZCBwYXJ0eSBkZWZpbml0aW9uc1xuXHRcdCAqIEBwYXJhbSAgICBvYmogICAgICBzY2hlbWEgICAgICBkZWZhdWx0IHNjaGVtYSBkZWZpbml0aW9uIGZyb20gdGhlIG1vZGVsIChvciBlbXB0eSBvYmplY3QgaWYgbm9uZSBkZWZpbmVkKVxuXHRcdCAqIEBwYXJhbSAgICBzdHJpbmcgICBtb2RlbF90eXBlICB0aGUgbW9kZWwgdHlwZSAoJ2xlc3NvbicsICdxdWl6JywgZXRjKVxuXHRcdCAqIEBwYXJhbSAgICBvYmogICAgICBtb2RlbCAgICAgICBJbnN0YW5jZSBvZiB0aGUgQmFja2JvbmUuTW9kZWwgZm9yIHRoZSBnaXZlbiBtb2RlbFxuXHRcdCAqIEByZXR1cm4gICBvYmpcblx0XHQgKiBAc2luY2UgICAgMy4xNy4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTcuMFxuXHRcdCAqL1xuXHRcdHRoaXMuZ2V0ID0gZnVuY3Rpb24oIHNjaGVtYSwgbW9kZWxfdHlwZSwgbW9kZWwgKSB7XG5cblx0XHRcdC8vIGV4dGVuZCB0aGUgZGVmYXVsdCBzY2hlbWEgd2l0aCBjdXN0b20gcGhwIHNjaGVtYXMgZm9yIHRoZSB0eXBlIGlmIHRoZXkgZXhpc3Rcblx0XHRcdGlmICggY3VzdG9tX3NjaGVtYXNbIG1vZGVsX3R5cGUgXSApIHtcblx0XHRcdFx0c2NoZW1hID0gXy5leHRlbmQoIHNjaGVtYSwgY3VzdG9tX3NjaGVtYXNbIG1vZGVsX3R5cGUgXSApO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gc2NoZW1hO1xuXG5cdFx0fTtcblxuXHRcdHJldHVybiB0aGlzO1xuXG5cdH07XG5cbn0gKTtcblxuLyoqXG4gKiBTeW5jIGJ1aWxkZXIgZGF0YSB0byB0aGUgc2VydmVyXG4gKiBAc2luY2UgICAgMy4xNi4wXG4gKiBAdmVyc2lvbiAgMy4xNy4xXG4gKi9cbmRlZmluZSggJ0NvbnRyb2xsZXJzL1N5bmMnLFtdLCBmdW5jdGlvbigpIHtcblxuIFx0cmV0dXJuIGZ1bmN0aW9uKCBDb3Vyc2UsIHNldHRpbmdzICkge1xuXG4gXHRcdHRoaXMuc2F2aW5nID0gZmFsc2U7XG5cbiBcdFx0dmFyIHNlbGYgPSB0aGlzLFxuIFx0XHRcdGF1dG9zYXZlID0gdHJ1ZSxcbiBcdFx0XHRjaGVja19pbnRlcnZhbCA9IG51bGwsXG4gXHRcdFx0Y2hlY2tfaW50ZXJ2YWxfbXMgPSBzZXR0aW5ncy5jaGVja19pbnRlcnZhbF9tcyB8fCAxMDAwMCxcbiBcdFx0XHRkZXRhY2hlZCA9IG5ldyBCYWNrYm9uZS5Db2xsZWN0aW9uKCksXG4gXHRcdFx0dHJhc2hlZCA9IG5ldyBCYWNrYm9uZS5Db2xsZWN0aW9uKCk7XG5cblx0XHQvKipcblx0XHQgKiBpbml0XG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi43XG5cdFx0ICogQHZlcnNpb24gIDMuMTYuN1xuXHRcdCAqL1xuIFx0XHRmdW5jdGlvbiBpbml0KCkge1xuXG4gXHRcdFx0Ly8gZGV0ZXJtaW5lIGlmIGF1dG9zYXZpbmcgaXMgcG9zc2libGVcbiBcdFx0XHRpZiAoICd1bmRlZmluZWQnID09PSB0eXBlb2Ygd3AuaGVhcnRiZWF0ICkge1xuXG4gXHRcdFx0XHR3aW5kb3cubGxtc19idWlsZGVyLmRlYnVnLmxvZyggJ1dvcmRQcmVzcyBIZWFydGJlYXQgZGlzYWJsZWQuIEF1dG9zYXZpbmcgaXMgZGlzYWJsZWQhJyApO1xuIFx0XHRcdFx0YXV0b3NhdmUgPSBmYWxzZTtcblxuIFx0XHRcdH1cblxuXHRcdFx0Ly8gc2V0dXAgdGhlIGNoZWNrIGludGVydmFsXG5cdFx0XHRpZiAoIGNoZWNrX2ludGVydmFsX21zICkge1xuXHRcdFx0XHRzZWxmLnNldF9jaGVja19pbnRlcnZhbCggY2hlY2tfaW50ZXJ2YWxfbXMgKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gd2FybiB3aGVuIHVzZXJzIGF0dGVtcHQgdG8gbGVhdmUgdGhlIHBhZ2Vcblx0XHRcdCQoIHdpbmRvdyApLm9uKCAnYmVmb3JldW5sb2FkJywgZnVuY3Rpb24oKSB7XG5cblx0XHRcdFx0aWYgKCBzZWxmLmhhc191bnNhdmVkX2NoYW5nZXMoKSApIHtcblx0XHRcdFx0XHRjaGVja19mb3JfY2hhbmdlcygpO1xuXHRcdFx0XHRcdHJldHVybiAnQXJlIHlvdSBzdXJlIHlvdSB3YW50IHRvIGFiYW5kb24geW91ciBjaGFuZ2VzPyc7XG5cdFx0XHRcdH1cblxuXHRcdFx0fSApO1xuXG4gXHRcdH07XG5cbiBcdFx0LypcbiBcdFx0XHQgLyQkICAgICAgICAgICAgIC8kJCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8kJCAgICAgICAgICAgICAgICAgICAgICAgICAgIC8kJFxuIFx0XHRcdHxfXy8gICAgICAgICAgICB8ICQkICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8ICQkICAgICAgICAgICAgICAgICAgICAgICAgICB8X18vXG4gXHRcdFx0IC8kJCAvJCQkJCQkJCAgLyQkJCQkJCAgICAvJCQkJCQkICAgLyQkJCQkJCAgLyQkJCQkJCQgICAvJCQkJCQkIHwgJCQgICAgICAgIC8kJCQkJCQgICAvJCQkJCQkICAvJCRcbiBcdFx0XHR8ICQkfCAkJF9fICAkJHxfICAkJF8vICAgLyQkX18gICQkIC8kJF9fICAkJHwgJCRfXyAgJCQgfF9fX18gICQkfCAkJCAgICAgICB8X19fXyAgJCQgLyQkX18gICQkfCAkJFxuIFx0XHRcdHwgJCR8ICQkICBcXCAkJCAgfCAkJCAgICB8ICQkJCQkJCQkfCAkJCAgXFxfXy98ICQkICBcXCAkJCAgLyQkJCQkJCR8ICQkICAgICAgICAvJCQkJCQkJHwgJCQgIFxcICQkfCAkJFxuIFx0XHRcdHwgJCR8ICQkICB8ICQkICB8ICQkIC8kJHwgJCRfX19fXy98ICQkICAgICAgfCAkJCAgfCAkJCAvJCRfXyAgJCR8ICQkICAgICAgIC8kJF9fICAkJHwgJCQgIHwgJCR8ICQkXG4gXHRcdFx0fCAkJHwgJCQgIHwgJCQgIHwgICQkJCQvfCAgJCQkJCQkJHwgJCQgICAgICB8ICQkICB8ICQkfCAgJCQkJCQkJHwgJCQgICAgICB8ICAkJCQkJCQkfCAkJCQkJCQkL3wgJCRcbiBcdFx0XHR8X18vfF9fLyAgfF9fLyAgIFxcX19fLyAgIFxcX19fX19fXy98X18vICAgICAgfF9fLyAgfF9fLyBcXF9fX19fX18vfF9fLyAgICAgICBcXF9fX19fX18vfCAkJF9fX18vIHxfXy9cbiBcdFx0XHQgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8ICQkXG4gXHRcdFx0ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCAkJFxuIFx0XHRcdCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHxfXy9cbiBcdFx0Ki9cblxuIFx0XHQvKipcbiBcdFx0ICogQWRkcyBlcnJvciBtZXNzYWdlKHMpIHRvIHRoZSBkYXRhIG9iamVjdCByZXR1cm5lZCBieSBoZWFydGJlYXQtdGlja1xuIFx0XHQgKiBAcGFyYW0gICAgb2JqICAgICAgICAgICAgZGF0YSAgbGxtc19idWlsZGVyIGRhdGEgb2JqZWN0IGZyb20gaGVhcnRiZWF0LXRpY2tcbiBcdFx0ICogQHBhcmFtICAgIHN0cmluZ3xhcnJheSAgIGVyciAgIGVycm9yIG1lc3NhZ2VzIGFycmF5IG9yIHN0cmluZ1xuIFx0XHQgKiBAcmV0dXJuICAgb2JqXG4gXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcbiBcdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuIFx0XHQgKi9cblx0XHRmdW5jdGlvbiBhZGRfZXJyb3JfbXNnKCBkYXRhLCBlcnIgKSB7XG5cblx0XHRcdGlmICggJ3N1Y2Nlc3MnID09PSBkYXRhLnN0YXR1cyApIHtcblx0XHRcdFx0ZGF0YS5tZXNzYWdlID0gW107XG5cdFx0XHR9XG5cblx0XHRcdGRhdGEuc3RhdHVzID0gJ2Vycm9yJztcblx0XHRcdGlmICggJ3N0cmluZycgPT09IHR5cGVvZiBlcnIgKSB7XG5cdFx0XHRcdGVyciA9IFsgZXJyIF07XG5cdFx0XHR9XG5cdFx0XHRkYXRhLm1lc3NhZ2UgPSBkYXRhLm1lc3NhZ2UuY29uY2F0KCBlcnIgKTtcblxuXHRcdFx0cmV0dXJuIGRhdGE7XG5cblx0XHR9O1xuXG5cdFx0LyoqXG5cdFx0ICogUHVibGlzaCBzeW5jIHN0YXR1cyBzbyBvdGhlciBhcmVhcyBvZiB0aGUgYXBwbGljYXRpb24gY2FuIHNlZSB3aGF0J3MgaGFwcGVuaW5nIGhlcmVcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0ZnVuY3Rpb24gY2hlY2tfZm9yX2NoYW5nZXMoKSB7XG5cblx0XHRcdHZhciBkYXRhID0ge307XG5cdFx0XHRkYXRhLmNoYW5nZXMgPSBzZWxmLmdldF91bnNhdmVkX2NoYW5nZXMoKTtcblx0XHRcdGRhdGEuaGFzX3Vuc2F2ZWRfY2hhbmdlcyA9IHNlbGYuaGFzX3Vuc2F2ZWRfY2hhbmdlcyggZGF0YS5jaGFuZ2VzICk7XG5cdFx0XHRkYXRhLnNhdmluZyA9IHNlbGYuc2F2aW5nO1xuXG5cdFx0XHR3aW5kb3cubGxtc19idWlsZGVyLmRlYnVnLmxvZyggJz09PT0gc3RhcnQgY2hhbmdlcyBjaGVjayA9PT09JywgZGF0YSwgJz09PT0gZmluaXNoIGNoYW5nZXMgY2hlY2sgPT09PScgKTtcblxuXHRcdFx0QmFja2JvbmUucHViU3ViLnRyaWdnZXIoICdjdXJyZW50LXNhdmUtc3RhdHVzJywgZGF0YSApO1xuXG5cdFx0fTtcblxuXHRcdC8qKlxuXHRcdCAqIE1hbnVhbGx5IFNhdmUgZGF0YSB2aWEgQWRtaW4gQUpBWCB3aGVuIHRoZSBoZWFydGJlYXQgQVBJIGhhcyBiZWVuIGRpc2FibGVkXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi43XG5cdFx0ICogQHZlcnNpb24gIDMuMTYuN1xuXHRcdCAqL1xuXHRcdGZ1bmN0aW9uIGRvX2FqYXhfc2F2ZSgpIHtcblxuXHRcdFx0Ly8gcHJldmVudCBzaW11bHRhbmVvdXMgc2F2ZXNcblx0XHRcdGlmICggc2VsZi5zYXZpbmcgKSB7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblxuXHRcdFx0dmFyIGNoYW5nZXMgPSBzZWxmLmdldF91bnNhdmVkX2NoYW5nZXMoKTtcblxuXHRcdFx0Ly8gb25seSBzZW5kIGRhdGEgaWYgd2UgaGF2ZSBkYXRhIHRvIHNlbmRcblx0XHRcdGlmICggc2VsZi5oYXNfdW5zYXZlZF9jaGFuZ2VzKCBjaGFuZ2VzICkgKSB7XG5cblx0XHRcdFx0Y2hhbmdlcy5pZCA9IENvdXJzZS5nZXQoICdpZCcgKTtcblxuXHRcdFx0XHRMTE1TLkFqYXguY2FsbCgge1xuXHRcdFx0XHRcdGRhdGE6IHtcblx0XHRcdFx0XHRcdGFjdGlvbjogJ2xsbXNfYnVpbGRlcicsXG5cdFx0XHRcdFx0XHRhY3Rpb25fdHlwZTogJ2FqYXhfc2F2ZScsXG5cdFx0XHRcdFx0XHRjb3Vyc2VfaWQ6IGNoYW5nZXMuaWQsXG5cdFx0XHRcdFx0XHRsbG1zX2J1aWxkZXI6IEpTT04uc3RyaW5naWZ5KCBjaGFuZ2VzICksXG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRiZWZvcmVTZW5kOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0XHRcdFx0d2luZG93LmxsbXNfYnVpbGRlci5kZWJ1Zy5sb2coICc9PT09IHN0YXJ0IGRvX2FqYXhfc2F2ZSBiZWZvcmUgPT09PScsIGNoYW5nZXMsICc9PT09IGZpbmlzaCBkb19hamF4X3NhdmUgYmVmb3JlID09PT0nICk7XG5cblx0XHRcdFx0XHRcdHNlbGYuc2F2aW5nID0gdHJ1ZTtcblxuXHRcdFx0XHRcdFx0QmFja2JvbmUucHViU3ViLnRyaWdnZXIoICdoZWFydGJlYXQtc2VuZCcsIHNlbGYgKTtcblxuXHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0ZXJyb3I6IGZ1bmN0aW9uKCB4aHIsIHN0YXR1cywgZXJyb3IgKSB7XG5cblx0XHRcdFx0XHRcdHdpbmRvdy5sbG1zX2J1aWxkZXIuZGVidWcubG9nKCAnPT09PSBzdGFydCBkb19hamF4X3NhdmUgZXJyb3IgPT09PScsIGRhdGEsICc9PT09IGZpbmlzaCBkb19hamF4X3NhdmUgZXJyb3IgPT09PScgKTtcblxuXHRcdFx0XHRcdFx0c2VsZi5zYXZpbmcgPSBmYWxzZTtcblxuXHRcdFx0XHRcdFx0QmFja2JvbmUucHViU3ViLnRyaWdnZXIoICdoZWFydGJlYXQtdGljaycsIHNlbGYsIHtcblx0XHRcdFx0XHRcdFx0c3RhdHVzOiAnZXJyb3InLFxuXHRcdFx0XHRcdFx0XHRtZXNzYWdlOiB4aHIucmVzcG9uc2VUZXh0ICsgJyAoJyArIGVycm9yICsgJyAnICsgc3RhdHVzICsnKScsXG5cdFx0XHRcdFx0XHR9ICk7XG5cblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdHN1Y2Nlc3M6IGZ1bmN0aW9uKCByZXMgKSB7XG5cblx0XHRcdFx0XHRcdGlmICggISByZXMubGxtc19idWlsZGVyICkge1xuXHRcdFx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdHdpbmRvdy5sbG1zX2J1aWxkZXIuZGVidWcubG9nKCAnPT09PSBzdGFydCBkb19hamF4X3NhdmUgc3VjY2VzcyA9PT09JywgcmVzLCAnPT09PSBmaW5pc2ggZG9fYWpheF9zYXZlIHN1Y2Nlc3MgPT09PScgKTtcblxuXHRcdFx0XHRcdFx0cmVzLmxsbXNfYnVpbGRlciA9IHByb2Nlc3NfcmVtb3ZhbHMoIHJlcy5sbG1zX2J1aWxkZXIgKTtcblx0XHRcdFx0XHRcdHJlcy5sbG1zX2J1aWxkZXIgPSBwcm9jZXNzX3VwZGF0ZXMoIHJlcy5sbG1zX2J1aWxkZXIgKTtcblxuXHRcdFx0XHRcdFx0c2VsZi5zYXZpbmcgPSBmYWxzZTtcblxuXHRcdFx0XHRcdFx0QmFja2JvbmUucHViU3ViLnRyaWdnZXIoICdoZWFydGJlYXQtdGljaycsIHNlbGYsIHJlcy5sbG1zX2J1aWxkZXIgKTtcblxuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHR9ICk7XG5cblx0XHRcdH1cblxuXG5cdFx0fTtcblxuXHRcdC8qKlxuXHRcdCAqIFJldHJpZXZlIGFsbCB0aGUgYXR0cmlidXRlcyBjaGFuZ2VkIG9uIGEgbW9kZWwgc2luY2UgdGhlIGxhc3Qgc3luY1xuXHRcdCAqXG5cdFx0ICogRm9yIGEgbmV3IG1vZGVsIChhIG1vZGVsIHdpdGggYSB0ZW1wIElEKSBvciBhIG1vZGVsIHdoZXJlIF9mb3JjZVN5bmMgaGFzIGJlZW4gZGVmaW5lZCBBTEwgYXR0cyB3aWxsIGJlIHJldHVybmVkXG5cdFx0ICogRm9yIGFuIGV4aXN0aW5nIG1vZGVsICh3aXRob3V0IGEgdGVtcCBJRCkgb25seSByZXRyaWV2ZXMgY2hhbmdlZCBhdHRyaWJ1dGVzIGFzIHRyYWNrZWQgYnkgQmFja2JvbmUuVHJhY2tJdFxuXHRcdCAqXG5cdFx0ICogVGhpcyBmdW5jdGlvbiBleGNsdWRlcyBhbnkgYXR0cmlidXRlcyBkZWZpbmVkIGFzIGNoaWxkIGF0dHJpYnV0ZXMgdmlhIHRoZSBtb2RlbHMgcmVsYXRpb25zaGlwIHNldHRpbmdzXG5cdFx0ICpcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgbW9kZWwgIGluc3RhbmNlIG9mIGEgQmFja2JvbmUuTW9kZWxcblx0XHQgKiBAcmV0dXJuICAgb2JqXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjZcblx0XHQgKi9cblx0XHRmdW5jdGlvbiBnZXRfY2hhbmdlZF9hdHRyaWJ1dGVzKCBtb2RlbCApIHtcblxuXHRcdFx0dmFyIGF0dHMgPSB7fSxcblx0XHRcdFx0c3luY190eXBlO1xuXG5cdFx0XHQvLyBkb24ndCBzYXZlIG1pZCBlZGl0aW5nXG5cdFx0XHRpZiAoIG1vZGVsLmdldCggJ19oYXNfZm9jdXMnICkgKSB7XG5cdFx0XHRcdHJldHVybiBhdHRzO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBtb2RlbCBoYXNuJ3QgYmVlbiBwZXJzaXN0ZWQgdG8gdGhlIGRhdGFiYXNlIHRvIGdldCBhIHJlYWwgSUQgeWV0XG5cdFx0XHQvLyBzZW5kICphbGwqIG9mIGl0J3MgYXR0c1xuXHRcdFx0aWYgKCBoYXNfdGVtcF9pZCggbW9kZWwgKSB8fCB0cnVlID09PSBtb2RlbC5nZXQoICdfZm9yY2VTeW5jJyApICkge1xuXG5cdFx0XHRcdGF0dHMgPSBfLmNsb25lKCBtb2RlbC5hdHRyaWJ1dGVzICk7XG5cdFx0XHRcdHN5bmNfdHlwZSA9ICdmdWxsJztcblxuXHRcdFx0Ly8gb25seSBzZW5kIHRoZSBjaGFuZ2VkIGF0dHNcblx0XHRcdH0gZWxzZSB7XG5cblx0XHRcdFx0YXR0cyA9IG1vZGVsLnVuc2F2ZWRBdHRyaWJ1dGVzKCk7XG5cdFx0XHRcdHN5bmNfdHlwZSA9ICdwYXJ0aWFsJztcblxuXHRcdFx0fVxuXG5cdFx0XHR2YXIgZXhjbHVkZSA9ICggbW9kZWwuZ2V0X3JlbGF0aW9uc2hpcHMgKSA/IG1vZGVsLmdldF9jaGlsZF9wcm9wcygpIDogW107XG5cdFx0XHRhdHRzID0gXy5vbWl0KCBhdHRzLCBmdW5jdGlvbiggdmFsLCBrZXkgKSB7XG5cblx0XHRcdFx0Ly8gZXhjbHVkZSBrZXlzIHRoYXQgc3RhcnQgd2l0aCBhbiB1bmRlcnNjb3JlIHdoaWNoIGFyZSB1c2VkIGJ5IHRoZVxuXHRcdFx0XHQvLyBhcHBsaWNhdGlvbiBidXQgZG9uJ3QgbmVlZCB0byBiZSBzdG9yZWQgaW4gdGhlIGRhdGFiYXNlXG5cdFx0XHRcdGlmICggMCA9PT0ga2V5LmluZGV4T2YoICdfJyApICkge1xuXHRcdFx0XHRcdHJldHVybiB0cnVlO1xuXHRcdFx0XHR9IGVsc2UgaWYgKCAtMSAhPT0gZXhjbHVkZS5pbmRleE9mKCBrZXkgKSApIHtcblx0XHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdFx0fVxuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cblx0XHRcdH0gKTtcblxuXHRcdFx0aWYgKCBtb2RlbC5iZWZvcmVfc2F2ZSApIHtcblx0XHRcdFx0YXR0cyA9IG1vZGVsLmJlZm9yZV9zYXZlKCBhdHRzLCBzeW5jX3R5cGUgKTtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIGF0dHM7XG5cblx0XHR9O1xuXG5cdFx0LyoqXG5cdFx0ICogR2V0IGFsbCB0aGUgY2hhbmdlcyB0byBhbiBvYmplY3QgKGVpdGhlciBhIE1vZGVsIG9yIGEgQ29sbGVjdGlvbiBvZiBtb2RlbHMpXG5cdFx0ICogUmV0dXJucyBvbmx5IGNoYW5nZXMgdG8gbW9kZWxzIGFuZCB0aGUgSURzIG9mIHRoYXQgbW9kZWwgKHNob3VsZCBjaGFuZ2VzIGV4aXN0KVxuXHRcdCAqIFVzZXMgZ2V0X2NoYW5nZWRfYXR0cmlidXRlcygpIHRvIGRldGVybWluZSBpZiBhbGwgYXR0cyBvciBvbmx5IGNoYW5nZWQgYXR0cyBhcmUgbmVlZGVkXG5cdFx0ICogUHJvY2Vzc2VzIGNoaWxkcmVuIGludGVsbGlnZW50bHkgdG8gb25seSByZXR1cm4gY2hhbmdlZCBjaGlsZHJlbiByYXRoZXIgdGhhbiB0aGUgZW50aXJlIGNvbGxlY3Rpb24gb2YgY2hpbGRyZW5cblx0XHQgKlxuXHRcdCAqIEBwYXJhbSAgICBvYmogICAgICAgIG9iamVjdCAgaW5zdGFuY2Ugb2YgYSBCYWNrYm9uZS5Nb2RlbCBvciBCYWNrYm9uZS5Db2xsZWN0aW9uXG5cdFx0ICogQHJldHVybiAgIG9ianxhcnJheVx0ICBcdFx0aWYgb2JqZWN0IGlzIGEgbW9kZWwsIHJldHVybnMgYW4gb2JqZWN0XG5cdFx0ICogICAgICAgICAgICAgICAgICAgICAgICAgICAgXHRpZiBvYmplY3QgaXMgYSBjb2xsZWN0aW9uLCByZXR1cm5zIGFuIGFycmF5IG9mIG9iamVjdHNcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMTFcblx0XHQgKi9cblx0XHRmdW5jdGlvbiBnZXRfY2hhbmdlc190b19vYmplY3QoIG9iamVjdCApIHtcblxuXHRcdFx0dmFyIGNoYW5nZWRfYXR0cztcblxuXHRcdFx0aWYgKCBvYmplY3QgaW5zdGFuY2VvZiBCYWNrYm9uZS5Nb2RlbCApIHtcblxuXHRcdFx0XHRjaGFuZ2VkX2F0dHMgPSBnZXRfY2hhbmdlZF9hdHRyaWJ1dGVzKCBvYmplY3QgKTtcblxuXHRcdFx0XHRpZiAoIG9iamVjdC5nZXRfcmVsYXRpb25zaGlwcyApIHtcblxuXHRcdFx0XHRcdF8uZWFjaCggb2JqZWN0LmdldF9jaGlsZF9wcm9wcygpLCBmdW5jdGlvbiggcHJvcCApIHtcblxuXHRcdFx0XHRcdFx0dmFyIGNoaWxkcmVuID0gZ2V0X2NoYW5nZXNfdG9fb2JqZWN0KCBvYmplY3QuZ2V0KCBwcm9wICkgKTtcblx0XHRcdFx0XHRcdGlmICggISBfLmlzRW1wdHkoIGNoaWxkcmVuICkgKSB7XG5cdFx0XHRcdFx0XHRcdGNoYW5nZWRfYXR0c1sgcHJvcCBdID0gY2hpbGRyZW47XG5cdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHR9ICk7XG5cblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIGlmIHdlIGhhdmUgYW55IGRhdGEsIGFkZCB0aGUgaWQgdG8gdGhlIG1vZGVsXG5cdFx0XHRcdGlmICggISBfLmlzRW1wdHkoIGNoYW5nZWRfYXR0cyApICkge1xuXHRcdFx0XHRcdGNoYW5nZWRfYXR0cy5pZCA9IG9iamVjdC5nZXQoICdpZCcgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHR9IGVsc2UgaWYgKCBvYmplY3QgaW5zdGFuY2VvZiBCYWNrYm9uZS5Db2xsZWN0aW9uICkge1xuXG5cdFx0XHRcdGNoYW5nZWRfYXR0cyA9IFtdO1xuXHRcdFx0XHRvYmplY3QuZWFjaCggZnVuY3Rpb24oIG1vZGVsICkge1xuXHRcdFx0XHRcdHZhciBtb2RlbF9jaGFuZ2VzID0gZ2V0X2NoYW5nZXNfdG9fb2JqZWN0KCBtb2RlbCApO1xuXHRcdFx0XHRcdGlmICggISBfLmlzRW1wdHkoIG1vZGVsX2NoYW5nZXMgKSApIHtcblx0XHRcdFx0XHRcdGNoYW5nZWRfYXR0cy5wdXNoKCBtb2RlbF9jaGFuZ2VzICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9ICk7XG5cblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIGNoYW5nZWRfYXR0cztcblxuXHRcdH07XG5cblx0XHQvKipcblx0XHQgKiBEZXRlcm1pbmVzIGlmIGEgbW9kZWwgaGFzIGEgdGVtcG9yYXJ5IElEIG9yIGEgcmVhbCBwZXJzaXN0ZWQgSURcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgbW9kZWwgIGluc3RhbmNlIG9mIGEgbW9kZWxcblx0XHQgKiBAcmV0dXJuICAgYm9vbGVhblxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0ZnVuY3Rpb24gaGFzX3RlbXBfaWQoIG1vZGVsICkge1xuXG5cdFx0XHRyZXR1cm4gKCAhIF8uaXNOdW1iZXIoIG1vZGVsLmlkICkgJiYgMCA9PT0gbW9kZWwuaWQuaW5kZXhPZiggJ3RlbXBfJyApICk7XG5cblx0XHR9O1xuXG5cdFx0LyoqXG5cdFx0ICogQ29tcGFyZXMgY2hhbmdlcyBzeW5jZWQgdG8gdGhlIHNlcnZlciBhZ2FpbnN0IGN1cnJlbnQgbW9kZWwgYW5kIHJlc3RhcnRzXG5cdFx0ICogdHJhY2tpbmcgb24gZWxlbWVudHMgdGhhdCBoYXZlbid0IGNoYW5nZWQgc2luY2UgdGhlIGxhc3Qgc3luY1xuXHRcdCAqIEBwYXJhbSAgICBvYmogICBtb2RlbCAgaW5zdGFuY2Ugb2YgYSBCYWNrYm9uZS5Nb2RlbFxuXHRcdCAqIEBwYXJhbSAgICBvYmogICBkYXRhICAgZGF0YSBzZXQgdGhhdCB3YXMgcHJvY2Vzc2VkIGJ5IHRoZSBzZXJ2ZXJcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjExXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuNlxuXHRcdCAqL1xuXHRcdGZ1bmN0aW9uIG1heWJlX3Jlc3RhcnRfdHJhY2tpbmcoIG1vZGVsLCBkYXRhICkge1xuXG5cdFx0XHR2YXIgb21pdCA9IFsgJ2lkJywgJ29yaWdfaWQnIF07XG5cblx0XHRcdGlmICggbW9kZWwuZ2V0X3JlbGF0aW9uc2hpcHMgKSB7XG5cdFx0XHRcdG9taXQuY29uY2F0KCBtb2RlbC5nZXRfY2hpbGRfcHJvcHMoKSApO1xuXHRcdFx0fVxuXG5cdFx0XHRfLmVhY2goIF8ub21pdCggZGF0YSwgb21pdCApLCBmdW5jdGlvbiggdmFsLCBwcm9wICkge1xuXG5cdFx0XHRcdGlmICggXy5pc0VxdWFsKCBtb2RlbC5nZXQoIHByb3AgKSwgdmFsICkgKSB7XG5cdFx0XHRcdFx0ZGVsZXRlIG1vZGVsLl91bnNhdmVkQ2hhbmdlc1sgcHJvcCBdO1xuXHRcdFx0XHRcdG1vZGVsLl9vcmlnaW5hbEF0dHJzWyBwcm9wIF0gPSB2YWw7XG5cdFx0XHRcdH1cblxuXHRcdFx0fSApO1xuXG5cdFx0XHQvLyBpZiBzeW5jaW5nIHdhcyBmb3JjZWQsIGFsbG93IHRyYWNraW5nIHRvIG1vdmUgZm9yd2FyZCBhcyBub3JtYWwgbW92aW5nIGZvcndhcmRcblx0XHRcdG1vZGVsLnVuc2V0KCAnX2ZvcmNlU3luYycgKTtcblxuXHRcdH07XG5cblx0XHQvKipcblx0XHQgKiBQcm9jZXNzZXMgcmVzcG9uc2UgZGF0YSBmcm9tIGhlYXJ0YmVhdC10aWNrIHJlbGF0ZWQgdG8gdHJhc2hpbmcgJiBkZXRhY2hpbmcgbW9kZWxzXG5cdFx0ICogT24gc3VjY2VzcywgcmVtb3ZlcyBmcm9tIGxvY2FsIHJlbW92YWwgY29sbGVjdGlvblxuXHRcdCAqIE9uIGVycm9yLCBhcHBlbmRzIGVycm9yIG1lc3NhZ2VzIHRvIHRoZSBkYXRhIG9iamVjdCByZXR1cm5lZCB0byBVSSBmb3Igb24tc2NyZWVuIGZlZWRiYWNrXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIGRhdGEgIGRhdGEubGxtc19idWlsZGVyIG9iamVjdCBmcm9tIGhlYXJ0YmVhdC10aWNrIHJlc3BvbnNlXG5cdFx0ICogQHJldHVybiAgIG9ialxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNy4xXG5cdFx0ICovXG5cdFx0ZnVuY3Rpb24gcHJvY2Vzc19yZW1vdmFscyggZGF0YSApIHtcblxuXHRcdFx0Ly8gY2hlY2sgcmVtb3ZhbHMgZm9yIGVycm9yc1xuXHRcdFx0dmFyIHJlbW92YWxzID0ge1xuXHRcdFx0XHRkZXRhY2g6IGRldGFjaGVkLFxuXHRcdFx0XHR0cmFzaDogdHJhc2hlZCxcblx0XHRcdH07XG5cblx0XHRcdF8uZWFjaCggcmVtb3ZhbHMsIGZ1bmN0aW9uKCBjb2xsLCBrZXkgKSB7XG5cblx0XHRcdFx0aWYgKCBkYXRhWyBrZXkgXSApIHtcblxuXHRcdFx0XHRcdHZhciBlcnJvcnMgPSBbXTtcblxuXHRcdFx0XHRcdF8uZWFjaCggZGF0YVsga2V5IF0gLCBmdW5jdGlvbiggaW5mbyApIHtcblxuXHRcdFx0XHRcdFx0Ly8gc3VjY2VzZnVsbHkgZGV0YWNoZWQsIHJlbW92ZSBpdCBmcm9tIHRoZSBkZXRhY2hlZCBjb2xsZWN0aW9uXG5cdFx0XHRcdFx0XHRpZiAoICEgaW5mby5lcnJvciApIHtcblxuXHRcdFx0XHRcdFx0XHRjb2xsLnJlbW92ZSggaW5mby5pZCApO1xuXG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xuXG5cdFx0XHRcdFx0XHRcdGVycm9ycy5wdXNoKCBpbmZvLmVycm9yICk7XG5cblx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdH0gKTtcblxuXHRcdFx0XHRcdGlmICggZXJyb3JzLmxlbmd0aCApIHtcblx0XHRcdFx0XHRcdF8uZXh0ZW5kKCBkYXRhLCBhZGRfZXJyb3JfbXNnKCBkYXRhLCBlcnJvcnMgKSApO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHR9XG5cblx0XHRcdH0gKTtcblxuXHRcdFx0cmV0dXJuIGRhdGE7XG5cdFx0fVxuXG5cdFx0LyoqXG5cdFx0ICogUHJvY2Vzc2VzIHJlc3BvbnNlIGRhdGEgZnJvbSBoZWFydGJlYXQtdGljayByZWxhdGVkIHRvIGNyZWF0aW5nIC8gdXBkYXRpbmcgYSBzaW5nbGUgb2JqZWN0XG5cdFx0ICogSGFuZGxlcyBib3RoIGNvbGxlY3Rpb25zIGFuZCBtb2RlbHMgYXMgYSByZWN1cnNpdmUgZnVuY3Rpb25cblx0XHQgKiBAcGFyYW0gICAge1t0eXBlXX0gICBkYXRhICAgICAgIFtkZXNjcmlwdGlvbl1cblx0XHQgKiBAcGFyYW0gICAge1t0eXBlXX0gICB0eXBlICAgICAgIFtkZXNjcmlwdGlvbl1cblx0XHQgKiBAcGFyYW0gICAge1t0eXBlXX0gICBwYXJlbnQgICAgIFtkZXNjcmlwdGlvbl1cblx0XHQgKiBAcGFyYW0gICAge1t0eXBlXX0gICBtYWluX2RhdGEgIFtkZXNjcmlwdGlvbl1cblx0XHQgKiBAcmV0dXJuICAge1t0eXBlXX1cblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMTFcblx0XHQgKi9cblx0XHRmdW5jdGlvbiBwcm9jZXNzX29iamVjdF91cGRhdGVzKCBkYXRhLCB0eXBlLCBwYXJlbnQsIG1haW5fZGF0YSApIHtcblxuXHRcdFx0aWYgKCAhIGRhdGFbIHR5cGUgXSApIHtcblx0XHRcdFx0cmV0dXJuIGRhdGE7XG5cdFx0XHR9XG5cblx0XHRcdGlmICggcGFyZW50LmdldCggdHlwZSApIGluc3RhbmNlb2YgQmFja2JvbmUuTW9kZWwgKSB7XG5cblx0XHRcdFx0dmFyIGluZm8gPSBkYXRhWyB0eXBlIF07XG5cblx0XHRcdFx0aWYgKCBpbmZvLmVycm9yICkge1xuXG5cdFx0XHRcdFx0Xy5leHRlbmQoIG1haW5fZGF0YSwgYWRkX2Vycm9yX21zZyggbWFpbl9kYXRhLCBpbmZvLmVycm9yICkgKTtcblxuXHRcdFx0XHR9IGVsc2Uge1xuXG5cdFx0XHRcdFx0dmFyIG1vZGVsID0gcGFyZW50LmdldCggdHlwZSApO1xuXG5cdFx0XHRcdFx0Ly8gdXBkYXRlIHRlbXAgaWRzIHdpdGggdGhlIHJlYWwgaWRcblx0XHRcdFx0XHRpZiAoIGluZm8uaWQgIT0gaW5mby5vcmlnX2lkICkge1xuXHRcdFx0XHRcdFx0bW9kZWwuc2V0KCAnaWQnLCBpbmZvLmlkICk7XG5cdFx0XHRcdFx0XHRkZWxldGUgbW9kZWwuX3Vuc2F2ZWRDaGFuZ2VzLmlkO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRtYXliZV9yZXN0YXJ0X3RyYWNraW5nKCBtb2RlbCwgaW5mbyApO1xuXG5cdFx0XHRcdFx0Ly8gY2hlY2sgY2hpbGRyZW5cblx0XHRcdFx0XHRpZiAoIG1vZGVsLmdldF9yZWxhdGlvbnNoaXBzICkge1xuXG5cdFx0XHRcdFx0XHRfLmVhY2goIG1vZGVsLmdldF9jaGlsZF9wcm9wcygpLCBmdW5jdGlvbiggY2hpbGRfa2V5ICkge1xuXHRcdFx0XHRcdFx0XHRfLmV4dGVuZCggZGF0YVsgdHlwZSBdLCBwcm9jZXNzX29iamVjdF91cGRhdGVzKCBkYXRhWyB0eXBlIF0sIGNoaWxkX2tleSwgbW9kZWwsIG1haW5fZGF0YSApICk7XG5cdFx0XHRcdFx0XHR9ICk7XG5cblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0fVxuXG5cdFx0XHR9IGVsc2UgaWYgKCBwYXJlbnQuZ2V0KCB0eXBlICkgaW5zdGFuY2VvZiBCYWNrYm9uZS5Db2xsZWN0aW9uICkge1xuXG5cdFx0XHRcdF8uZWFjaCggZGF0YVsgdHlwZSBdLCBmdW5jdGlvbiggaW5mbywgaW5kZXggKSB7XG5cblx0XHRcdFx0XHRpZiAoIGluZm8uZXJyb3IgKSB7XG5cblx0XHRcdFx0XHRcdF8uZXh0ZW5kKCBtYWluX2RhdGEsIGFkZF9lcnJvcl9tc2coIG1haW5fZGF0YSwgaW5mby5lcnJvciApICk7XG5cblx0XHRcdFx0XHR9IGVsc2Uge1xuXG5cdFx0XHRcdFx0XHR2YXIgbW9kZWwgPSBwYXJlbnQuZ2V0KCB0eXBlICkuZ2V0KCBpbmZvLm9yaWdfaWQgKTtcblxuXHRcdFx0XHRcdFx0Ly8gdXBkYXRlIHRlbXAgaWRzIHdpdGggdGhlIHJlYWwgaWRcblx0XHRcdFx0XHRcdGlmICggaW5mby5pZCAhPSBpbmZvLm9yaWdfaWQgKSB7XG5cdFx0XHRcdFx0XHRcdG1vZGVsLnNldCggJ2lkJywgaW5mby5pZCApO1xuXHRcdFx0XHRcdFx0XHRkZWxldGUgbW9kZWwuX3Vuc2F2ZWRDaGFuZ2VzLmlkO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0bWF5YmVfcmVzdGFydF90cmFja2luZyggbW9kZWwsIGluZm8gKTtcblxuXHRcdFx0XHRcdFx0Ly8gY2hlY2sgY2hpbGRyZW5cblx0XHRcdFx0XHRcdGlmICggbW9kZWwuZ2V0X3JlbGF0aW9uc2hpcHMgKSB7XG5cblx0XHRcdFx0XHRcdFx0Xy5lYWNoKCBtb2RlbC5nZXRfY2hpbGRfcHJvcHMoKSwgZnVuY3Rpb24oIGNoaWxkX2tleSApIHtcblx0XHRcdFx0XHRcdFx0XHRfLmV4dGVuZCggZGF0YVsgdHlwZSBdLCBwcm9jZXNzX29iamVjdF91cGRhdGVzKCBkYXRhWyB0eXBlIF1bIGluZGV4IF0sIGNoaWxkX2tleSwgbW9kZWwsIG1haW5fZGF0YSApICk7XG5cdFx0XHRcdFx0XHRcdH0gKTtcblxuXHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdH0gKTtcblxuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gbWFpbl9kYXRhO1xuXG5cdFx0fTtcblxuXHRcdC8qKlxuXHRcdCAqIFByb2Nlc3NlcyByZXNwb25zZSBkYXRhIGZyb20gaGVhcnRiZWF0LXRpY2sgcmVsYXRlZCB0byB1cGRhdGluZyAmIGNyZWF0aW5nIG5ldyBtb2RlbHNcblx0XHQgKiBPbiBzdWNjZXNzLCByZW1vdmVzIGZyb20gbG9jYWwgcmVtb3ZhbCBjb2xsZWN0aW9uXG5cdFx0ICogT24gZXJyb3IsIGFwcGVuZHMgZXJyb3IgbWVzc2FnZXMgdG8gdGhlIGRhdGEgb2JqZWN0IHJldHVybmVkIHRvIFVJIGZvciBvbi1zY3JlZW4gZmVlZGJhY2tcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgZGF0YSAgZGF0YS5sbG1zX2J1aWxkZXIgb2JqZWN0IGZyb20gaGVhcnRiZWF0LXRpY2sgcmVzcG9uc2Vcblx0XHQgKiBAcmV0dXJuICAgb2JqXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRmdW5jdGlvbiBwcm9jZXNzX3VwZGF0ZXMoIGRhdGEgKSB7XG5cblx0XHRcdC8vIG9ubHkgbWVzcyB3aXRoIHVwZGF0ZXMgZGF0YVxuXHRcdFx0aWYgKCAhIGRhdGEudXBkYXRlcyApIHtcblx0XHRcdFx0cmV0dXJuIGRhdGE7XG5cdFx0XHR9XG5cblx0XHRcdGlmICggZGF0YS51cGRhdGVzICkge1xuXHRcdFx0XHRkYXRhID0gcHJvY2Vzc19vYmplY3RfdXBkYXRlcyggZGF0YS51cGRhdGVzLCAnc2VjdGlvbnMnLCBDb3Vyc2UsIGRhdGEgKTtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIGRhdGE7XG5cblx0XHR9O1xuXG5cdFx0Lypcblx0XHRcdCAgICAgICAgICAgICAgICAgICAgIC8kJCAgICAgICAvJCQgLyQkICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8kJFxuXHRcdFx0ICAgICAgICAgICAgICAgICAgICB8ICQkICAgICAgfCAkJHxfXy8gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8X18vXG5cdFx0XHQgIC8kJCQkJCQgIC8kJCAgIC8kJHwgJCQkJCQkJCB8ICQkIC8kJCAgLyQkJCQkJCQgICAgICAgIC8kJCQkJCQgICAvJCQkJCQkICAvJCRcblx0XHRcdCAvJCRfXyAgJCR8ICQkICB8ICQkfCAkJF9fICAkJHwgJCR8ICQkIC8kJF9fX19fLyAgICAgICB8X19fXyAgJCQgLyQkX18gICQkfCAkJFxuXHRcdFx0fCAkJCAgXFwgJCR8ICQkICB8ICQkfCAkJCAgXFwgJCR8ICQkfCAkJHwgJCQgICAgICAgICAgICAgIC8kJCQkJCQkfCAkJCAgXFwgJCR8ICQkXG5cdFx0XHR8ICQkICB8ICQkfCAkJCAgfCAkJHwgJCQgIHwgJCR8ICQkfCAkJHwgJCQgICAgICAgICAgICAgLyQkX18gICQkfCAkJCAgfCAkJHwgJCRcblx0XHRcdHwgJCQkJCQkJC98ICAkJCQkJCQvfCAkJCQkJCQkL3wgJCR8ICQkfCAgJCQkJCQkJCAgICAgIHwgICQkJCQkJCR8ICQkJCQkJCQvfCAkJFxuXHRcdFx0fCAkJF9fX18vICBcXF9fX19fXy8gfF9fX19fX18vIHxfXy98X18vIFxcX19fX19fXy8gICAgICAgXFxfX19fX19fL3wgJCRfX19fLyB8X18vXG5cdFx0XHR8ICQkICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCAkJFxuXHRcdFx0fCAkJCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgJCRcblx0XHRcdHxfXy8gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8X18vXG5cdFx0Ki9cblxuXHRcdC8qKlxuXHRcdCAqIFJldHJpZXZlIGFsbCB1bnNhdmVkIGNoYW5nZXMgZm9yIHRoZSBidWlsZGVyIGluc3RhbmNlXG5cdFx0ICogQHJldHVybiAgIG9ialxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNy4xXG5cdFx0ICovXG5cdFx0dGhpcy5nZXRfdW5zYXZlZF9jaGFuZ2VzID0gZnVuY3Rpb24oKSB7XG5cblx0XHRcdHJldHVybiB7XG5cdFx0XHRcdGRldGFjaDogZGV0YWNoZWQucGx1Y2soICdpZCcgKSxcblx0XHRcdFx0dHJhc2g6IHRyYXNoZWQucGx1Y2soICdpZCcgKSxcblx0XHRcdFx0dXBkYXRlczogZ2V0X2NoYW5nZXNfdG9fb2JqZWN0KCBDb3Vyc2UgKSxcblxuXHRcdFx0fVxuXHRcdH07XG5cblx0XHQvKipcblx0XHQgKiBDaGVjayBpZiB0aGUgYnVpbGRlciBpbnN0YW5jZSBoYXMgdW5zYXZlZCBjaGFuZ2VzXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgICAgIGNoYW5nZXMgICAgb3B0aW9uYWxseSBwYXNzIGluIGFuIG9iamVjdCBmcm9tIHRoZSByZXR1cm4gb2YgdGhpcy5nZXRfdW5zYXZlZF9jaGFuZ2VzKClcblx0XHQgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYXZlIHNvbWUgcmVzb3VyY2VzIGJ5IG5vdCBydW5uaW5nIHRoZSBjaGVjayB0d2ljZSBkdXJpbmcgaGVhcnRiZWF0c1xuXHRcdCAqIEByZXR1cm4gICBib29sZWFuXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHR0aGlzLmhhc191bnNhdmVkX2NoYW5nZXMgPSBmdW5jdGlvbiggY2hhbmdlcyApIHtcblxuXHRcdFx0aWYgKCAndW5kZWZpbmVkJyA9PT0gdHlwZW9mIGNoYW5nZXMgKSB7XG5cdFx0XHRcdGNoYW5nZXMgPSBzZWxmLmdldF91bnNhdmVkX2NoYW5nZXMoKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gY2hlY2sgYWxsIHBvc3NpYmxlIGtleXMsIG9uY2Ugd2UgZmluZCBvbmUgd2l0aCBjb250ZW50IHdlIGhhdmUgc29tZSBjaGFuZ2VzIHRvIHBlcnNpc3Rcblx0XHRcdHZhciBmb3VuZCA9IF8uZmluZCggY2hhbmdlcywgZnVuY3Rpb24oIGRhdGEgKSB7XG5cblx0XHRcdFx0cmV0dXJuICggZmFsc2UgPT09IF8uaXNFbXB0eSggZGF0YSApICk7XG5cblx0XHRcdH0gKTtcblxuXHRcdFx0cmV0dXJuIGZvdW5kID8gdHJ1ZSA6IGZhbHNlO1xuXG5cdFx0fTtcblxuXHRcdC8qKlxuXHRcdCAqIFNhdmUgY2hhbmdlcyByaWdodCBub3cuXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuN1xuXHRcdCAqL1xuXHRcdHRoaXMuc2F2ZV9ub3cgPSBmdW5jdGlvbigpIHtcblx0XHRcdGlmICggYXV0b3NhdmUgKSB7XG5cdFx0XHRcdHdwLmhlYXJ0YmVhdC5jb25uZWN0Tm93KCk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRkb19hamF4X3NhdmUoKTtcblx0XHRcdH1cblx0XHR9O1xuXG5cdFx0LyoqXG5cdFx0ICogVXBkYXRlIHRoZSBpbnRlcnZhbCB0aGF0IGNoZWNrcyBmb3IgY2hhbmdlcyB0byB0aGUgYnVpbGRlciBpbnN0YW5jZVxuXHRcdCAqIEBwYXJhbSAgICBpbnQgICAgICAgIG1zICAgdGltZSAoaW4gbWlsbGlzZWNvbmRzKSB0byBydW4gdGhlIGNoZWNrIG9uXG5cdFx0ICogICAgICAgICAgICAgICAgICAgICAgICAgICBwYXNzIDAgdG8gZGlzYWJsZSB0aGUgY2hlY2tcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0dGhpcy5zZXRfY2hlY2tfaW50ZXJ2YWwgPSBmdW5jdGlvbiggbXMgKSB7XG5cdFx0XHRjaGVja19pbnRlcnZhbF9tcyA9IG1zO1xuXHRcdFx0aWYgKCBjaGVja19pbnRlcnZhbCApIHtcblx0XHRcdFx0Y2xlYXJJbnRlcnZhbCggY2hlY2tfaW50ZXJ2YWwgKTtcblx0XHRcdH1cblx0XHRcdGlmICggY2hlY2tfaW50ZXJ2YWxfbXMgKSB7XG5cdFx0XHRcdGNoZWNrX2ludGVydmFsID0gc2V0SW50ZXJ2YWwoIGNoZWNrX2Zvcl9jaGFuZ2VzLCBjaGVja19pbnRlcnZhbF9tcyApO1xuXHRcdFx0fVxuXHRcdH07XG5cblx0XHQvKlxuXHRcdFx0IC8kJCAvJCQgICAgICAgICAgICAgLyQkXG5cdFx0XHR8ICQkfF9fLyAgICAgICAgICAgIHwgJCRcblx0XHRcdHwgJCQgLyQkICAvJCQkJCQkJCAvJCQkJCQkICAgIC8kJCQkJCQgIC8kJCQkJCQkICAgLyQkJCQkJCAgIC8kJCQkJCQgICAvJCQkJCQkJFxuXHRcdFx0fCAkJHwgJCQgLyQkX19fX18vfF8gICQkXy8gICAvJCRfXyAgJCR8ICQkX18gICQkIC8kJF9fICAkJCAvJCRfXyAgJCQgLyQkX19fX18vXG5cdFx0XHR8ICQkfCAkJHwgICQkJCQkJCAgIHwgJCQgICAgfCAkJCQkJCQkJHwgJCQgIFxcICQkfCAkJCQkJCQkJHwgJCQgIFxcX18vfCAgJCQkJCQkXG5cdFx0XHR8ICQkfCAkJCBcXF9fX18gICQkICB8ICQkIC8kJHwgJCRfX19fXy98ICQkICB8ICQkfCAkJF9fX19fL3wgJCQgICAgICAgXFxfX19fICAkJFxuXHRcdFx0fCAkJHwgJCQgLyQkJCQkJCQvICB8ICAkJCQkL3wgICQkJCQkJCR8ICQkICB8ICQkfCAgJCQkJCQkJHwgJCQgICAgICAgLyQkJCQkJCQvXG5cdFx0XHR8X18vfF9fL3xfX19fX19fLyAgICBcXF9fXy8gICBcXF9fX19fX18vfF9fLyAgfF9fLyBcXF9fX19fX18vfF9fLyAgICAgIHxfX19fX19fL1xuXHRcdCovXG5cblx0XHQvKipcblx0XHQgKiBMaXN0ZW4gZm9yIGRldGFjaGVkIG1vZGVscyBhbmQgc2VuZCB0aGVtIHRvIHRoZSBzZXJ2ZXIgZm9yIHBlcnNpc3RlbmNlXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRCYWNrYm9uZS5wdWJTdWIub24oICdtb2RlbC1kZXRhY2hlZCcsIGZ1bmN0aW9uKCBtb2RlbCApIHtcblxuXHRcdFx0Ly8gZGV0YWNoZWQgbW9kZWxzIHdpdGggdGVtcCBpZHMgaGF2ZW4ndCBiZWVuIHBlcnNpc3RlZCBzbyB3ZSBkb24ndCBjYXJlXG5cdFx0XHRpZiAoIGhhc190ZW1wX2lkKCBtb2RlbCApICkge1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cblx0XHRcdGRldGFjaGVkLmFkZCggXy5jbG9uZSggbW9kZWwuYXR0cmlidXRlcyApICk7XG5cblx0XHR9ICk7XG5cblx0XHQvKipcblx0XHQgKiBMaXN0ZW4gZm9yIHRyYXNoZWQgbW9kZWxzIGFuZCBzZW5kIHRoZW0gdG8gdGhlIHNlcnZlciBmb3IgZGVsZXRpb25cblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTcuMVxuXHRcdCAqL1xuXHRcdEJhY2tib25lLnB1YlN1Yi5vbiggJ21vZGVsLXRyYXNoZWQnLCBmdW5jdGlvbiggbW9kZWwgKSB7XG5cblx0XHRcdC8vIGlmIHRoZSBtb2RlbCBoYXMgYSB0ZW1wIElEIHdlIGRvbid0IGhhdmUgdG8gcGVyc2lzdCB0aGUgZGVsZXRpb25cblx0XHRcdGlmICggaGFzX3RlbXBfaWQoIG1vZGVsICkgKSB7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblxuXHRcdFx0dmFyIGRhdGEgPSBfLmNsb25lKCBtb2RlbC5hdHRyaWJ1dGVzICk7XG5cblx0XHRcdGlmICggbW9kZWwuZ2V0X3RyYXNoX2lkICkge1xuXHRcdFx0XHRkYXRhLmlkID0gbW9kZWwuZ2V0X3RyYXNoX2lkKCk7XG5cdFx0XHR9XG5cblx0XHRcdHRyYXNoZWQuYWRkKCBkYXRhICk7XG5cblx0XHR9ICk7XG5cblx0XHQvKlxuXHRcdFx0IC8kJCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8kJCAgICAgLyQkICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvJCRcblx0XHRcdHwgJCQgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgJCQgICAgfCAkJCAgICAgICAgICAgICAgICAgICAgICAgICAgICB8ICQkXG5cdFx0XHR8ICQkJCQkJCQgICAvJCQkJCQkICAgLyQkJCQkJCAgIC8kJCQkJCQgIC8kJCQkJCQgIHwgJCQkJCQkJCAgIC8kJCQkJCQgICAvJCQkJCQkICAvJCQkJCQkXG5cdFx0XHR8ICQkX18gICQkIC8kJF9fICAkJCB8X19fXyAgJCQgLyQkX18gICQkfF8gICQkXy8gIHwgJCRfXyAgJCQgLyQkX18gICQkIHxfX19fICAkJHxfICAkJF8vXG5cdFx0XHR8ICQkICBcXCAkJHwgJCQkJCQkJCQgIC8kJCQkJCQkfCAkJCAgXFxfXy8gIHwgJCQgICAgfCAkJCAgXFwgJCR8ICQkJCQkJCQkICAvJCQkJCQkJCAgfCAkJFxuXHRcdFx0fCAkJCAgfCAkJHwgJCRfX19fXy8gLyQkX18gICQkfCAkJCAgICAgICAgfCAkJCAvJCR8ICQkICB8ICQkfCAkJF9fX19fLyAvJCRfXyAgJCQgIHwgJCQgLyQkXG5cdFx0XHR8ICQkICB8ICQkfCAgJCQkJCQkJHwgICQkJCQkJCR8ICQkICAgICAgICB8ICAkJCQkL3wgJCQkJCQkJC98ICAkJCQkJCQkfCAgJCQkJCQkJCAgfCAgJCQkJC9cblx0XHRcdHxfXy8gIHxfXy8gXFxfX19fX19fLyBcXF9fX19fX18vfF9fLyAgICAgICAgIFxcX19fLyAgfF9fX19fX18vICBcXF9fX19fX18vIFxcX19fX19fXy8gICBcXF9fXy9cblx0XHQqL1xuXG5cdFx0LyoqXG5cdFx0ICogQWRkIGRhdGEgdG8gdGhlIFdQIGhlYXJ0YmVhdCB0byBwZXJzaXN0IG5ldyBtb2RlbHMsIGNoYW5nZXMsIGFuZCBkZWxldGlvbnMgdG8gdGhlIERCXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2Ljdcblx0XHQgKi9cblx0XHQkKCBkb2N1bWVudCApLm9uKCAnaGVhcnRiZWF0LXNlbmQnLCBmdW5jdGlvbiggZXZlbnQsIGRhdGEgKSB7XG5cblx0XHRcdC8vIHByZXZlbnQgc2ltdWx0YW5lb3VzIHNhdmVzXG5cdFx0XHRpZiAoIHNlbGYuc2F2aW5nICkge1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cblx0XHRcdHZhciBjaGFuZ2VzID0gc2VsZi5nZXRfdW5zYXZlZF9jaGFuZ2VzKCk7XG5cblx0XHRcdC8vIG9ubHkgc2VuZCBkYXRhIGlmIHdlIGhhdmUgZGF0YSB0byBzZW5kXG5cdFx0XHRpZiAoIHNlbGYuaGFzX3Vuc2F2ZWRfY2hhbmdlcyggY2hhbmdlcyApICkge1xuXG5cdFx0XHRcdGNoYW5nZXMuaWQgPSBDb3Vyc2UuZ2V0KCAnaWQnICk7XG5cdFx0XHRcdHNlbGYuc2F2aW5nID0gdHJ1ZTtcblx0XHRcdFx0ZGF0YS5sbG1zX2J1aWxkZXIgPSBKU09OLnN0cmluZ2lmeSggY2hhbmdlcyApO1xuXG5cdFx0XHR9XG5cblx0XHRcdHdpbmRvdy5sbG1zX2J1aWxkZXIuZGVidWcubG9nKCAnPT09PSBzdGFydCBoZWFydGJlYXQtc2VuZCA9PT09JywgZGF0YSwgJz09PT0gZmluaXNoIGhlYXJ0YmVhdC1zZW5kID09PT0nICk7XG5cblx0XHRcdEJhY2tib25lLnB1YlN1Yi50cmlnZ2VyKCAnaGVhcnRiZWF0LXNlbmQnLCBzZWxmICk7XG5cblx0XHR9ICk7XG5cblx0XHQvKipcblx0XHQgKiBDb25maXJtIGRldGFjaG1lbnRzICYgZGVsZXRpb25zIGFuZCByZXBsYWNlIHRlbXAgSURzIHdpdGggbmV3IHBlcnNpc3RlZCBJRHNcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdCQoIGRvY3VtZW50ICkub24oICdoZWFydGJlYXQtdGljaycsIGZ1bmN0aW9uKCBldmVudCwgZGF0YSApIHtcblxuXHRcdFx0aWYgKCAhIGRhdGEubGxtc19idWlsZGVyICkge1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cblx0XHRcdHdpbmRvdy5sbG1zX2J1aWxkZXIuZGVidWcubG9nKCAnPT09PSBzdGFydCBoZWFydGJlYXQtdGljayA9PT09JywgZGF0YSwgJz09PT0gZmluaXNoIGhlYXJ0YmVhdC10aWNrID09PT0nICk7XG5cblx0XHRcdGRhdGEubGxtc19idWlsZGVyID0gcHJvY2Vzc19yZW1vdmFscyggZGF0YS5sbG1zX2J1aWxkZXIgKTtcblx0XHRcdGRhdGEubGxtc19idWlsZGVyID0gcHJvY2Vzc191cGRhdGVzKCBkYXRhLmxsbXNfYnVpbGRlciApO1xuXG5cdFx0XHRzZWxmLnNhdmluZyA9IGZhbHNlO1xuXG5cdFx0XHRCYWNrYm9uZS5wdWJTdWIudHJpZ2dlciggJ2hlYXJ0YmVhdC10aWNrJywgc2VsZiwgZGF0YS5sbG1zX2J1aWxkZXIgKTtcblxuXHRcdH0gKTtcblxuXHRcdC8qKlxuXHRcdCAqIE9uIGhlYXJ0YmVhdCBlcnJvcnMgcHVibGlzaCBhbiBlcnJvciB0byB0aGUgbWFpbiBidWlsZGVyIGFwcGxpY2F0aW9uXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHQkKCBkb2N1bWVudCApLm9uKCAnaGVhcnRiZWF0LWVycm9yJywgZnVuY3Rpb24oIGV2ZW50LCBkYXRhICkge1xuXG5cdFx0XHR3aW5kb3cubGxtc19idWlsZGVyLmRlYnVnLmxvZyggJz09PT0gc3RhcnQgaGVhcnRiZWF0LWVycm9yID09PT0nLCBkYXRhLCAnPT09PSBmaW5pc2ggaGVhcnRiZWF0LWVycm9yID09PT0nICk7XG5cblx0XHRcdHNlbGYuc2F2aW5nID0gZmFsc2U7XG5cblx0XHRcdEJhY2tib25lLnB1YlN1Yi50cmlnZ2VyKCAnaGVhcnRiZWF0LXRpY2snLCBzZWxmLCB7XG5cdFx0XHRcdHN0YXR1czogJ2Vycm9yJyxcblx0XHRcdFx0bWVzc2FnZTogZGF0YS5yZXNwb25zZVRleHQgKyAnICgnICsgZGF0YS5zdGF0dXMgKyAnICcgKyBkYXRhLnN0YXR1c1RleHQgKycpJyxcblx0XHRcdH0gKTtcblxuXHRcdH0gKTtcblxuXHRcdC8qXG5cdFx0XHQgLyQkICAgICAgICAgICAvJCQgICAvJCRcblx0XHRcdHxfXy8gICAgICAgICAgfF9fLyAgfCAkJFxuXHRcdFx0IC8kJCAvJCQkJCQkJCAgLyQkIC8kJCQkJCRcblx0XHRcdHwgJCR8ICQkX18gICQkfCAkJHxfICAkJF8vXG5cdFx0XHR8ICQkfCAkJCAgXFwgJCR8ICQkICB8ICQkXG5cdFx0XHR8ICQkfCAkJCAgfCAkJHwgJCQgIHwgJCQgLyQkXG5cdFx0XHR8ICQkfCAkJCAgfCAkJHwgJCQgIHwgICQkJCQvXG5cdFx0XHR8X18vfF9fLyAgfF9fL3xfXy8gICBcXF9fXy9cblx0XHQqL1xuXHRcdGluaXQoKTtcblxuXHRcdHJldHVybiB0aGlzO1xuXG5cdH07XG5cbn0gKTtcblxuLyoqXG4gKiBTaW5nbGUgTGVzc29uIFZpZXdcbiAqIEBzaW5jZSAgICAzLjE2LjBcbiAqIEB2ZXJzaW9uICAzLjE3LjBcbiAqL1xuZGVmaW5lKCAnVmlld3MvTGVzc29uJyxbXG5cdFx0J1ZpZXdzL19EZXRhY2hhYmxlJyxcblx0XHQnVmlld3MvX0VkaXRhYmxlJyxcblx0XHQnVmlld3MvX1NoaWZ0YWJsZScsXG5cdFx0J1ZpZXdzL19UcmFzaGFibGUnXG5cdF0sIGZ1bmN0aW9uKFxuXHRcdERldGFjaGFibGUsXG5cdFx0RWRpdGFibGUsXG5cdFx0U2hpZnRhYmxlLFxuXHRcdFRyYXNoYWJsZVxuXHQpIHtcblxuXHRyZXR1cm4gQmFja2JvbmUuVmlldy5leHRlbmQoIF8uZGVmYXVsdHMoIHtcblxuXHRcdC8qKlxuXHRcdCAqIEdldCBkZWZhdWx0IGF0dHJpYnV0ZXMgZm9yIHRoZSBodG1sIHdyYXBwZXIgZWxlbWVudFxuXHRcdCAqIEByZXR1cm4gICBvYmpcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGF0dHJpYnV0ZXM6IGZ1bmN0aW9uKCkge1xuXHRcdFx0cmV0dXJuIHtcblx0XHRcdFx0J2RhdGEtaWQnOiB0aGlzLm1vZGVsLmlkLFxuXHRcdFx0XHQnZGF0YS1zZWN0aW9uLWlkJzogdGhpcy5tb2RlbC5nZXQoICdwYXJlbnRfc2VjdGlvbicgKSxcblx0XHRcdH07XG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIEhUTUwgY2xhc3MgbmFtZXNcblx0XHQgKiBAdHlwZSAge1N0cmluZ31cblx0XHQgKi9cblx0XHRjbGFzc05hbWU6ICdsbG1zLWJ1aWxkZXItaXRlbSBsbG1zLWxlc3NvbicsXG5cblx0XHQvKipcblx0XHQgKiBFdmVudHNcblx0XHQgKiBAdHlwZSAge09iamVjdH1cblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMTJcblx0XHQgKi9cblx0XHRldmVudHM6IF8uZGVmYXVsdHMoIHtcblx0XHRcdCdjbGljayAuZWRpdC1sZXNzb24nOiAnb3Blbl9sZXNzb25fZWRpdG9yJyxcblx0XHRcdCdjbGljayAuZWRpdC1xdWl6JzogJ29wZW5fcXVpel9lZGl0b3InLFxuXHRcdFx0J2NsaWNrIC5lZGl0LWFzc2lnbm1lbnQnOiAnb3Blbl9hc3NpZ25tZW50X2VkaXRvcicsXG5cdFx0XHQnY2xpY2sgLnNlY3Rpb24tcHJldic6ICdzZWN0aW9uX3ByZXYnLFxuXHRcdFx0J2NsaWNrIC5zZWN0aW9uLW5leHQnOiAnc2VjdGlvbl9uZXh0Jyxcblx0XHRcdCdjbGljayAuc2hpZnQtdXAtLWxlc3Nvbic6ICdzaGlmdF91cCcsXG5cdFx0XHQnY2xpY2sgLnNoaWZ0LWRvd24tLWxlc3Nvbic6ICdzaGlmdF9kb3duJyxcblx0XHR9LCBEZXRhY2hhYmxlLmV2ZW50cywgRWRpdGFibGUuZXZlbnRzLCBUcmFzaGFibGUuZXZlbnRzICksXG5cblx0XHQvKipcblx0XHQgKiBIVE1MIGVsZW1lbnQgd3JhcHBlciBJRCBhdHRyaWJ1dGVcblx0XHQgKiBAcmV0dXJuICAgc3RyaW5nXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRpZDogZnVuY3Rpb24oKSB7XG5cdFx0XHRyZXR1cm4gJ2xsbXMtbGVzc29uLScgKyB0aGlzLm1vZGVsLmlkO1xuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBXcmFwcGVyIFRhZyBuYW1lXG5cdFx0ICogQHR5cGUgIHtTdHJpbmd9XG5cdFx0ICovXG5cdFx0dGFnTmFtZTogJ2xpJyxcblxuXHRcdC8qKlxuXHRcdCAqIEdldCB0aGUgdW5kZXJzY29yZSB0ZW1wbGF0ZVxuXHRcdCAqIEB0eXBlICB7W3R5cGVdfVxuXHRcdCAqL1xuXHRcdHRlbXBsYXRlOiB3cC50ZW1wbGF0ZSggJ2xsbXMtbGVzc29uLXRlbXBsYXRlJyApLFxuXG5cdFx0LyoqXG5cdFx0ICogSW5pdGlhbGl6YXRpb24gY2FsbGJhY2sgZnVuYyAocmVuZGVycyB0aGUgZWxlbWVudCBvbiBzY3JlZW4pXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNC4xXG5cdFx0ICogQHZlcnNpb24gIDMuMTQuMVxuXHRcdCAqL1xuXHRcdGluaXRpYWxpemU6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHR0aGlzLnJlbmRlcigpO1xuXG5cdFx0XHR0aGlzLmxpc3RlblRvKCB0aGlzLm1vZGVsLCAnY2hhbmdlJywgdGhpcy5yZW5kZXIgKTtcblxuXHRcdFx0QmFja2JvbmUucHViU3ViLm9uKCAgJ2xlc3Nvbi1zZWxlY3RlZCcsIHRoaXMub25fc2VsZWN0LCB0aGlzICk7XG5cdFx0XHRCYWNrYm9uZS5wdWJTdWIub24oICAnbmV3LWxlc3Nvbi1hZGRlZCcsIHRoaXMub25fc2VsZWN0LCB0aGlzICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogQ29tcGlsZXMgdGhlIHRlbXBsYXRlIGFuZCByZW5kZXJzIHRoZSB2aWV3XG5cdFx0ICogQHJldHVybiAgIHNlbGYgKGZvciBjaGFpbmluZylcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdHJlbmRlcjogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHRoaXMuJGVsLmh0bWwoIHRoaXMudGVtcGxhdGUoIHRoaXMubW9kZWwgKSApO1xuXHRcdFx0dGhpcy5tYXliZV9oaWRlX3NoaWZ0YWJsZV9idXR0b25zKCk7XG5cdFx0XHRpZiAoIHRoaXMubW9kZWwuZ2V0KCAnX3NlbGVjdGVkJyApICkge1xuXHRcdFx0XHR0aGlzLiRlbC5hZGRDbGFzcyggJ3NlbGVjdGVkJyApO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dGhpcy4kZWwucmVtb3ZlQ2xhc3MoICdzZWxlY3RlZCcgKTtcblx0XHRcdH1cblx0XHRcdHJldHVybiB0aGlzO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIENsaWNrIGV2ZW50IGZvciB0aGUgYXNzaWdubWVudCBlZGl0b3IgYWN0aW9uIGljb25cblx0XHQgKiBPcGVucyBzaWRlYmFyIHRvIHRoZSBhc3NpZ25tZW50IGVkaXRvciB0YWJcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE3LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNy4wXG5cdFx0ICovXG5cdFx0b3Blbl9hc3NpZ25tZW50X2VkaXRvcjogZnVuY3Rpb24oKSB7XG5cblx0XHRcdEJhY2tib25lLnB1YlN1Yi50cmlnZ2VyKCAnbGVzc29uLXNlbGVjdGVkJywgdGhpcy5tb2RlbCwgJ2Fzc2lnbm1lbnQnICk7XG5cdFx0XHR0aGlzLm1vZGVsLnNldCggJ19zZWxlY3RlZCcsIHRydWUgKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBDbGljayBldmVudCBmb3IgbGVzc29uIHNldHRpbmdzIGFjdGlvbiBpY29uXG5cdFx0ICogT3BlbnMgc2lkZWJhciB0byB0aGUgbGVzc29uIGVkaXRvciB0YWJcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0b3Blbl9sZXNzb25fZWRpdG9yOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0QmFja2JvbmUucHViU3ViLnRyaWdnZXIoICdsZXNzb24tc2VsZWN0ZWQnLCB0aGlzLm1vZGVsLCAnbGVzc29uJyApO1xuXHRcdFx0dGhpcy5tb2RlbC5zZXQoICdfc2VsZWN0ZWQnLCB0cnVlICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogQ2xpY2sgZXZlbnQgZm9yIHRoZSBxdWl6IGVkaXRvciBhY3Rpb24gaWNvblxuXHRcdCAqIE9wZW5zIHNpZGViYXIgdG8gdGhlIHF1aXogZWRpdG9yIHRhYlxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRvcGVuX3F1aXpfZWRpdG9yOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0QmFja2JvbmUucHViU3ViLnRyaWdnZXIoICdsZXNzb24tc2VsZWN0ZWQnLCB0aGlzLm1vZGVsLCAncXVpeicgKTtcblx0XHRcdHRoaXMubW9kZWwuc2V0KCAnX3NlbGVjdGVkJywgdHJ1ZSApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFdoZW4gYSBsZXNzb24gaXMgc2VsZWN0ZWQgbWFyayBpdCBhcyBzZWxlY3RlZCBpbiB0aGUgaGlkZGVuIHByb3Bcblx0XHQgKiBBbGxvd3Mgdmlld3MgdG8gcmUtcmVuZGVyIGFuZCByZWZsZWN0IGN1cnJlbnQgc3RhdGUgcHJvcGVybHlcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgbW9kZWwgIGxlc3NvbiBtb2RlbCB0aGF0J3MgYmVlbiBzZWxlY3RlZFxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRvbl9zZWxlY3Q6IGZ1bmN0aW9uKCBtb2RlbCApIHtcblxuXHRcdFx0aWYgKCB0aGlzLm1vZGVsLmlkICE9PSBtb2RlbC5pZCApIHtcblx0XHRcdFx0dGhpcy5tb2RlbC5zZXQoICdfc2VsZWN0ZWQnLCBmYWxzZSApO1xuXHRcdFx0fVxuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIENsaWNrIGV2ZW50IGZvciB0aGUgXCJOZXh0IFNlY3Rpb25cIiBidXR0b25cblx0XHQgKiBAcGFyYW0gICAgb2JqICAgZXZlbnQgICBqcyBldmVudCBvYmpcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjExXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMTFcblx0XHQgKi9cblx0XHRzZWN0aW9uX25leHQ6IGZ1bmN0aW9uKCBldmVudCApIHtcblx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHR0aGlzLl9tb3ZlX3RvX3NlY3Rpb24oICduZXh0JyApO1xuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBDbGljayBldmVudCBmb3IgdGhlIFwiUHJldmlvdXMgU2VjdGlvblwiIGJ1dHRvblxuXHRcdCAqIEBwYXJhbSAgICBvYmogICBldmVudCAgIGpzIGV2ZW50IG9ialxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMTFcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4xMVxuXHRcdCAqL1xuXHRcdHNlY3Rpb25fcHJldjogZnVuY3Rpb24oIGV2ZW50ICkge1xuXHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdHRoaXMuX21vdmVfdG9fc2VjdGlvbiggJ3ByZXYnICk7XG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIE1vdmUgdGhlIGxlc3NvbiBpbnRvIGEgbmV3IHNlY3Rpb25cblx0XHQgKiBAcGFyYW0gICAgc3RyaW5nICAgZGlyZWN0aW9uICBkaXJlY3Rpb24gW3ByZXZ8bmV4dF1cblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjExXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMTFcblx0XHQgKi9cblx0XHRfbW92ZV90b19zZWN0aW9uOiBmdW5jdGlvbiggZGlyZWN0aW9uICkge1xuXG5cdFx0XHR2YXIgZnJvbV9jb2xsID0gdGhpcy5tb2RlbC5jb2xsZWN0aW9uLFxuXHRcdFx0XHR0b19zZWN0aW9uO1xuXG5cdFx0XHRpZiAoICduZXh0JyA9PT0gZGlyZWN0aW9uICkge1xuXHRcdFx0XHR0b19zZWN0aW9uID0gZnJvbV9jb2xsLnBhcmVudC5nZXRfbmV4dCgpO1xuXHRcdFx0fSBlbHNlIGlmICggJ3ByZXYnID09PSBkaXJlY3Rpb24gKSB7XG5cdFx0XHRcdHRvX3NlY3Rpb24gPSBmcm9tX2NvbGwucGFyZW50LmdldF9wcmV2KCk7XG5cdFx0XHR9XG5cblx0XHRcdGlmICggdG9fc2VjdGlvbiApIHtcblxuXHRcdFx0XHRmcm9tX2NvbGwucmVtb3ZlKCB0aGlzLm1vZGVsICk7XG5cdFx0XHRcdHRvX3NlY3Rpb24uYWRkX2xlc3NvbiggdGhpcy5tb2RlbCApO1xuXHRcdFx0XHR0b19zZWN0aW9uLnNldCggJ19leHBhbmRlZCcsIHRydWUgKTtcblxuXHRcdFx0fVxuXG5cdFx0fSxcblxuXHR9LCBEZXRhY2hhYmxlLCBFZGl0YWJsZSwgU2hpZnRhYmxlLCBUcmFzaGFibGUgKSApO1xuXG59ICk7XG5cbi8qKlxuICogU2luZ2xlIFNlY3Rpb24gVmlld1xuICogQHNpbmNlICAgIDMuMTMuMFxuICogQHZlcnNpb24gIDMuMTYuMFxuICovXG5kZWZpbmUoICdWaWV3cy9MZXNzb25MaXN0JyxbICdWaWV3cy9MZXNzb24nLCAnVmlld3MvX1JlY2VpdmFibGUnIF0sIGZ1bmN0aW9uKCBMZXNzb25WaWV3LCBSZWNlaXZhYmxlICkge1xuXG5cdHJldHVybiBCYWNrYm9uZS5Db2xsZWN0aW9uVmlldy5leHRlbmQoIF8uZGVmYXVsdHMoIHtcblxuXHRcdGNsYXNzTmFtZTogJ2xsbXMtbGVzc29ucycsXG5cblx0XHQvKipcblx0XHQgKiBTZWN0aW9uIG1vZGVsXG5cdFx0ICogQHR5cGUgIHtbdHlwZV19XG5cdFx0ICovXG5cdFx0bW9kZWxWaWV3OiBMZXNzb25WaWV3LFxuXG5cdFx0LyoqXG5cdFx0ICogQXJlIHNlY3Rpb25zIHNlbGVjdGFibGU/XG5cdFx0ICogQHR5cGUgIHtCb29sfVxuXHRcdCAqL1xuXHRcdHNlbGVjdGFibGU6IGZhbHNlLFxuXG5cdFx0LyoqXG5cdFx0ICogQXJlIHNlY3Rpb25zIHNvcnRhYmxlP1xuXHRcdCAqIEB0eXBlICB7Qm9vbH1cblx0XHQgKi9cblx0XHRzb3J0YWJsZTogdHJ1ZSxcblxuXHRcdHNvcnRhYmxlT3B0aW9uczoge1xuXHRcdFx0YXhpczogZmFsc2UsXG5cdFx0XHRjb25uZWN0V2l0aDogJy5sbG1zLWxlc3NvbnMnLFxuXHRcdFx0Y3Vyc29yOiAnbW92ZScsXG5cdFx0XHRoYW5kbGU6ICcuZHJhZy1sZXNzb24nLFxuXHRcdFx0aXRlbXM6ICcubGxtcy1sZXNzb24nLFxuXHRcdFx0cGxhY2Vob2xkZXI6ICdsbG1zLWxlc3NvbiBsbG1zLXNvcnRhYmxlLXBsYWNlaG9sZGVyJyxcblx0XHR9LFxuXG5cdFx0c29ydGFibGVfc3RhcnQ6IGZ1bmN0aW9uKCBjb2xsZWN0aW9uICkge1xuXHRcdFx0JCggJy5sbG1zLWxlc3NvbnMnICkuYWRkQ2xhc3MoICdkcmFnZ2luZycgKTtcblx0XHR9LFxuXG5cdFx0c29ydGFibGVfc3RvcDogZnVuY3Rpb24oIGNvbGxlY3Rpb24gKSB7XG5cdFx0XHQkKCAnLmxsbXMtbGVzc29ucycgKS5yZW1vdmVDbGFzcyggJ2RyYWdnaW5nJyApO1xuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBPdmVybG9hZHMgdGhlIGZ1bmN0aW9uIGZyb20gQmFja2JvbmUuQ29sbGVjdGlvblZpZXcgY29yZSBiZWNhdXNlIGl0IGRvZXNuJ3Qgc2VuZCBzdG9wIGV2ZW50c1xuXHRcdCAqIGlmIG1vdmluZyBmcm9tIG9uZSBzb3J0YWJsZSB0byBhbm90aGVyLi4uIDotKFxuXHRcdCAqIEBwYXJhbSAgICBvYmogICBldmVudCAganMgZXZlbnQgb2JqZWN0XG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIHVpICAgICBqUXVlcnkgVUkgb2JqZWN0XG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdF9zb3J0U3RvcCA6IGZ1bmN0aW9uKCBldmVudCwgdWkgKSB7XG5cblx0XHRcdHZhciBtb2RlbEJlaW5nU29ydGVkID0gdGhpcy5jb2xsZWN0aW9uLmdldCggdWkuaXRlbS5hdHRyKCAnZGF0YS1tb2RlbC1jaWQnICkgKSxcblx0XHRcdFx0bW9kZWxWaWV3Q29udGFpbmVyRWwgPSB0aGlzLl9nZXRDb250YWluZXJFbCgpLFxuXHRcdFx0XHRuZXdJbmRleCA9IG1vZGVsVmlld0NvbnRhaW5lckVsLmNoaWxkcmVuKCkuaW5kZXgoIHVpLml0ZW0gKTtcblxuXHRcdFx0aWYgKCBuZXdJbmRleCA9PSAtMSAmJiBtb2RlbEJlaW5nU29ydGVkICkge1xuXHRcdFx0XHR0aGlzLmNvbGxlY3Rpb24ucmVtb3ZlKCBtb2RlbEJlaW5nU29ydGVkICk7XG5cdFx0XHR9XG5cblx0XHRcdHRoaXMuX3Jlb3JkZXJDb2xsZWN0aW9uQmFzZWRPbkhUTUwoKTtcblx0XHRcdHRoaXMudXBkYXRlRGVwZW5kZW50Q29udHJvbHMoKTtcblxuXHRcdFx0aWYoIHRoaXMuX2lzQmFja2JvbmVDb3VyaWVyQXZhaWxhYmxlKCkgKSB7XG5cdFx0XHRcdHRoaXMuc3Bhd24oICdzb3J0U3RvcCcsIHsgbW9kZWxCZWluZ1NvcnRlZCA6IG1vZGVsQmVpbmdTb3J0ZWQsIG5ld0luZGV4IDogbmV3SW5kZXggfSApO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dGhpcy50cmlnZ2VyKCAnc29ydFN0b3AnLCBtb2RlbEJlaW5nU29ydGVkLCBuZXdJbmRleCApO1xuXHRcdFx0fVxuXG5cdFx0fSxcblxuXHR9LCBSZWNlaXZhYmxlICkgKTtcblxufSApO1xuXG4vKipcbiAqIFNpbmdsZSBTZWN0aW9uIFZpZXdcbiAqIEBzaW5jZSAgICAzLjEzLjBcbiAqIEB2ZXJzaW9uICAzLjE2LjEyXG4gKi9cbmRlZmluZSggJ1ZpZXdzL1NlY3Rpb24nLFtcblx0XHQnVmlld3MvTGVzc29uTGlzdCcsXG5cdFx0J1ZpZXdzL19FZGl0YWJsZScsXG5cdFx0J1ZpZXdzL19TaGlmdGFibGUnLFxuXHRcdCdWaWV3cy9fVHJhc2hhYmxlJ1xuXHRdLCBmdW5jdGlvbihcblx0XHRMZXNzb25MaXN0Vmlldyxcblx0XHRFZGl0YWJsZSxcblx0XHRTaGlmdGFibGUsXG5cdFx0VHJhc2hhYmxlXG5cdCkge1xuXG5cdHJldHVybiBCYWNrYm9uZS5WaWV3LmV4dGVuZCggXy5kZWZhdWx0cygge1xuXG5cdFx0LyoqXG5cdFx0ICogR2V0IGRlZmF1bHQgYXR0cmlidXRlcyBmb3IgdGhlIGh0bWwgd3JhcHBlciBlbGVtZW50XG5cdFx0ICogQHJldHVybiAgIG9ialxuXHRcdCAqIEBzaW5jZSAgICAzLjEzLjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xMy4wXG5cdFx0ICovXG5cdFx0YXR0cmlidXRlczogZnVuY3Rpb24oKSB7XG5cdFx0XHRyZXR1cm4ge1xuXHRcdFx0XHQnZGF0YS1pZCc6IHRoaXMubW9kZWwuaWQsXG5cdFx0XHR9O1xuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBFbGVtZW50IGNsYXNzbmFtZXNcblx0XHQgKiBAdHlwZSAge1N0cmluZ31cblx0XHQgKi9cblx0XHRjbGFzc05hbWU6ICdsbG1zLWJ1aWxkZXItaXRlbSBsbG1zLXNlY3Rpb24nLFxuXG5cdFx0LyoqXG5cdFx0ICogRXZlbnRzXG5cdFx0ICogQHR5cGUgICAgIHtPYmplY3R9XG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjEyXG5cdFx0ICovXG5cdFx0ZXZlbnRzOiBfLmRlZmF1bHRzKCB7XG5cblx0XHRcdCdjbGljayc6ICdzZWxlY3QnLFxuXHRcdFx0J2NsaWNrIC5leHBhbmQnOiAnZXhwYW5kJyxcblx0XHRcdCdjbGljayAuY29sbGFwc2UnOiAnY29sbGFwc2UnLFxuXHRcdFx0J2NsaWNrIC5zaGlmdC11cC0tc2VjdGlvbic6ICdzaGlmdF91cCcsXG5cdFx0XHQnY2xpY2sgLnNoaWZ0LWRvd24tLXNlY3Rpb24nOiAnc2hpZnRfZG93bicsXG5cblx0XHRcdCdtb3VzZWVudGVyIC5sbG1zLWxlc3NvbnMnOiAnb25fbW91c2VlbnRlcicsXG5cblx0XHR9LCBFZGl0YWJsZS5ldmVudHMsIFRyYXNoYWJsZS5ldmVudHMgKSxcblxuXHRcdC8qKlxuXHRcdCAqIEhUTUwgZWxlbWVudCB3cmFwcGVyIElEIGF0dHJpYnV0ZVxuXHRcdCAqIEByZXR1cm4gICBzdHJpbmdcblx0XHQgKiBAc2luY2UgICAgMy4xMy4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTMuMFxuXHRcdCAqL1xuXHRcdGlkOiBmdW5jdGlvbigpIHtcblx0XHRcdHJldHVybiAnbGxtcy1zZWN0aW9uLScgKyB0aGlzLm1vZGVsLmlkO1xuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBXcmFwcGVyIFRhZyBuYW1lXG5cdFx0ICogQHR5cGUgIHtTdHJpbmd9XG5cdFx0ICovXG5cdFx0dGFnTmFtZTogJ2xpJyxcblxuXHRcdC8qKlxuXHRcdCAqIEdldCB0aGUgdW5kZXJzY29yZSB0ZW1wbGF0ZVxuXHRcdCAqIEB0eXBlICB7W3R5cGVdfVxuXHRcdCAqL1xuXHRcdHRlbXBsYXRlOiB3cC50ZW1wbGF0ZSggJ2xsbXMtc2VjdGlvbi10ZW1wbGF0ZScgKSxcblxuXHRcdC8qKlxuXHRcdCAqIEluaXRpYWxpemF0aW9uIGNhbGxiYWNrIGZ1bmMgKHJlbmRlcnMgdGhlIGVsZW1lbnQgb24gc2NyZWVuKVxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTMuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRpbml0aWFsaXplOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0dGhpcy5yZW5kZXIoKTtcblx0XHRcdHRoaXMubGlzdGVuVG8oIHRoaXMubW9kZWwsICdjaGFuZ2UnLCB0aGlzLnJlbmRlciApO1xuXHRcdFx0dGhpcy5saXN0ZW5UbyggdGhpcy5tb2RlbCwgJ2NoYW5nZTpfZXhwYW5kZWQnLCB0aGlzLnRvZ2dsZV9leHBhbmRlZCApO1xuXHRcdFx0dGhpcy5sZXNzb25MaXN0Vmlldy5jb2xsZWN0aW9uLm9uKCAnYWRkJywgdGhpcy5vbl9sZXNzb25fYWRkLCB0aGlzICk7XG5cblx0XHRcdHRoaXMuZHJhZ1RpbWVvdXQgPSBudWxsO1xuXG5cdFx0XHRCYWNrYm9uZS5wdWJTdWIub24oICdleHBhbmQtYWxsJywgdGhpcy5leHBhbmQsIHRoaXMgKTtcblx0XHRcdEJhY2tib25lLnB1YlN1Yi5vbiggJ2NvbGxhcHNlLWFsbCcsIHRoaXMuY29sbGFwc2UsIHRoaXMgKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBSZW5kZXIgdGhlIHNlY3Rpb25cblx0XHQgKiBJbml0YWxpemVzIGEgbmV3IGNvbGxlY3Rpb24gYW5kIHZpZXdzIGZvciBhbGwgbGVzc29ucyBpbiB0aGUgc2VjdGlvblxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTMuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRyZW5kZXI6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHR0aGlzLiRlbC5odG1sKCB0aGlzLnRlbXBsYXRlKCB0aGlzLm1vZGVsLnRvSlNPTigpICkgKTtcblxuXHRcdFx0dGhpcy5tYXliZV9oaWRlX3NoaWZ0YWJsZV9idXR0b25zKCk7XG5cblx0XHRcdHRoaXMubGVzc29uTGlzdFZpZXcgPSBuZXcgTGVzc29uTGlzdFZpZXcoIHtcblx0XHRcdFx0ZWw6IHRoaXMuJGVsLmZpbmQoICcubGxtcy1sZXNzb25zJyApLFxuXHRcdFx0XHRjb2xsZWN0aW9uOiB0aGlzLm1vZGVsLmdldCggJ2xlc3NvbnMnICksXG5cdFx0XHR9ICk7XG5cdFx0XHR0aGlzLmxlc3Nvbkxpc3RWaWV3LnJlbmRlcigpO1xuXHRcdFx0dGhpcy5sZXNzb25MaXN0Vmlldy5vbiggJ3NvcnRTdGFydCcsIHRoaXMubGVzc29uTGlzdFZpZXcuc29ydGFibGVfc3RhcnQgKTtcblx0XHRcdHRoaXMubGVzc29uTGlzdFZpZXcub24oICdzb3J0U3RvcCcsIHRoaXMubGVzc29uTGlzdFZpZXcuc29ydGFibGVfc3RvcCApO1xuXG5cdFx0XHQvLyBzZWxlY3Rpb24gY2hhbmdlc1xuXHRcdFx0dGhpcy5sZXNzb25MaXN0Vmlldy5vbiggJ3NlbGVjdGlvbkNoYW5nZWQnLCB0aGlzLmFjdGl2ZV9sZXNzb25fY2hhbmdlLCB0aGlzICk7XG5cblx0XHRcdHRoaXMubWF5YmVfaGlkZV90cmFzaF9idXR0b24oKTtcblxuXHRcdFx0cmV0dXJuIHRoaXM7XG5cblx0XHR9LFxuXG5cdFx0YWN0aXZlX2xlc3Nvbl9jaGFuZ2U6IGZ1bmN0aW9uKCBjdXJyZW50LCBwcmV2aW91cyApIHtcblxuXHRcdFx0QmFja2JvbmUucHViU3ViLnRyaWdnZXIoICdhY3RpdmUtbGVzc29uLWNoYW5nZScsIHtcblx0XHRcdFx0Y3VycmVudDogY3VycmVudCxcblx0XHRcdFx0cHJldmlvdXM6IHByZXZpb3VzLFxuXHRcdFx0fSApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIENvbGxhcHNlIGxlc3NvbnMgd2l0aGluIHRoZSBzZWN0aW9uXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIGV2ZW50ICAgIGpzIGV2ZW50IG9iamVjdFxuXHRcdCAqIEBwYXJhbSAgICBib29sICB1cGRhdGUgICBpZiB0cnVlLCB1cGRhdGVzIHRoZSBtb2RlbCB0byByZWZsZWN0IHRoZSBuZXcgc3RhdGVcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0Y29sbGFwc2U6IGZ1bmN0aW9uKCBldmVudCwgdXBkYXRlICkge1xuXG5cdFx0XHRpZiAoICd1bmRlZmluZWQnID09PSB0eXBlb2YgdXBkYXRlICkge1xuXHRcdFx0XHR1cGRhdGUgPSB0cnVlO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIGV2ZW50ICkge1xuXHRcdFx0XHRldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcblx0XHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdH1cblxuXHRcdFx0dGhpcy4kZWwucmVtb3ZlQ2xhc3MoICdleHBhbmRlZCcgKS5maW5kKCAnLmRyYWctZXhwYW5kZWQnICkucmVtb3ZlQ2xhc3MoICdkcmFnLWV4cGFuZGVkJyApO1xuXHRcdFx0aWYgKCB1cGRhdGUgKSB7XG5cdFx0XHRcdHRoaXMubW9kZWwuc2V0KCAnX2V4cGFuZGVkJywgZmFsc2UgKTtcblx0XHRcdH1cblx0XHRcdEJhY2tib25lLnB1YlN1Yi50cmlnZ2VyKCAnc2VjdGlvbi10b2dnbGUnLCB0aGlzLm1vZGVsICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogRXhwYW5kIGxlc3NvbnMgd2l0aGluIHRoZSBzZWN0aW9uXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIGV2ZW50ICAgIGpzIGV2ZW50IG9iamVjdFxuXHRcdCAqIEBwYXJhbSAgICBib29sICB1cGRhdGUgICBpZiB0cnVlLCB1cGRhdGVzIHRoZSBtb2RlbCB0byByZWZsZWN0IHRoZSBuZXcgc3RhdGVcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0ZXhwYW5kOiBmdW5jdGlvbiggZXZlbnQsIHVwZGF0ZSApIHtcblxuXHRcdFx0aWYgKCAndW5kZWZpbmVkJyA9PT0gdHlwZW9mIHVwZGF0ZSApIHtcblx0XHRcdFx0dXBkYXRlID0gdHJ1ZTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKCBldmVudCApIHtcblx0XHRcdFx0ZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cdFx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHR9XG5cblx0XHRcdHRoaXMuJGVsLmFkZENsYXNzKCAnZXhwYW5kZWQnICk7XG5cdFx0XHRpZiAoIHVwZGF0ZSApIHtcblx0XHRcdFx0dGhpcy5tb2RlbC5zZXQoICdfZXhwYW5kZWQnLCB0cnVlICk7XG5cdFx0XHR9XG5cdFx0XHRCYWNrYm9uZS5wdWJTdWIudHJpZ2dlciggJ3NlY3Rpb24tdG9nZ2xlJywgdGhpcy5tb2RlbCApO1xuXG5cdFx0fSxcblxuXHRcdG1heWJlX2hpZGVfdHJhc2hfYnV0dG9uOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0dmFyICRidG4gPSB0aGlzLiRlbC5maW5kKCAnLnRyYXNoLS1zZWN0aW9uJyApO1xuXG5cdFx0XHRpZiAoIHRoaXMubW9kZWwuZ2V0KCAnbGVzc29ucycgKS5pc0VtcHR5KCkgKSB7XG5cblx0XHRcdFx0JGJ0bi5zaG93KCk7XG5cblx0XHRcdH0gZWxzZSB7XG5cblx0XHRcdFx0JGJ0bi5oaWRlKClcblxuXHRcdFx0fVxuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFdoZW4gYSBsZXNzb24gaXMgYWRkZWQgdG8gdGhlIHNlY3Rpb24gdHJpZ2dlciBhIGNvbGxlY3Rpb24gcmVvcmRlciAmIHVwZGF0ZSB0aGUgbGVzc29uJ3MgaWRcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgbW9kZWwgIExlc3NvbiBtb2RlbFxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRvbl9sZXNzb25fYWRkOiBmdW5jdGlvbiggbW9kZWwgKSB7XG5cblx0XHRcdHRoaXMubGVzc29uTGlzdFZpZXcuY29sbGVjdGlvbi50cmlnZ2VyKCAncmVvcmRlcicgKTtcblx0XHRcdG1vZGVsLnNldCggJ3BhcmVudF9zZWN0aW9uJywgdGhpcy5tb2RlbC5nZXQoICdpZCcgKSApO1xuXHRcdFx0dGhpcy5leHBhbmQoKTtcblxuXHRcdH0sXG5cblx0XHRvbl9tb3VzZWVudGVyOiBmdW5jdGlvbiggZXZlbnQgKSB7XG5cblxuXHRcdFx0aWYgKCAkKCBldmVudC50YXJnZXQgKS5oYXNDbGFzcyggJ2RyYWdnaW5nJyApICkge1xuXG5cdFx0XHRcdCQoICcuZHJhZy1leHBhbmRlZCcgKS5yZW1vdmVDbGFzcyggJ2RyYWctZXhwYW5kZWQnICk7XG5cdFx0XHRcdCQoIGV2ZW50LnRhcmdldCApLmFkZENsYXNzKCAnZHJhZy1leHBhbmRlZCcgKTtcblxuXHRcdFx0fVxuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIEV4cGFuZFxuXHRcdCAqIEBwYXJhbSAgICB7W3R5cGVdfSAgIG1vZGVsICBbZGVzY3JpcHRpb25dXG5cdFx0ICogQHBhcmFtICAgIHtbdHlwZV19ICAgdmFsdWUgIFtkZXNjcmlwdGlvbl1cblx0XHQgKiBAcmV0dXJuICAge1t0eXBlXX1cblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdHRvZ2dsZV9leHBhbmRlZDogZnVuY3Rpb24oIG1vZGVsLCB2YWx1ZSApIHtcblxuXHRcdFx0aWYgKCB2YWx1ZSApIHtcblx0XHRcdFx0dGhpcy5leHBhbmQoIG51bGwsIGZhbHNlICk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0aGlzLmNvbGxhcHNlKCBudWxsLCBmYWxzZSApO1xuXHRcdFx0fVxuXG5cdFx0fSxcblxuXHR9LCBFZGl0YWJsZSwgU2hpZnRhYmxlLCBUcmFzaGFibGUgKSApO1xuXG59ICk7XG5cbi8qKlxuICogU2luZ2xlIFNlY3Rpb24gVmlld1xuICogQHNpbmNlICAgIDMuMTMuMFxuICogQHZlcnNpb24gIDMuMTYuMFxuICovXG5kZWZpbmUoICdWaWV3cy9TZWN0aW9uTGlzdCcsWyAnVmlld3MvU2VjdGlvbicsICdWaWV3cy9fUmVjZWl2YWJsZScgXSwgZnVuY3Rpb24oIFNlY3Rpb25WaWV3LCBSZWNlaXZhYmxlICkge1xuXG5cdHJldHVybiBCYWNrYm9uZS5Db2xsZWN0aW9uVmlldy5leHRlbmQoIF8uZGVmYXVsdHMoIHtcblxuXHRcdC8qKlxuXHRcdCAqIFBhcmVudCBlbGVtZW50XG5cdFx0ICogQHR5cGUgIHtTdHJpbmd9XG5cdFx0ICovXG5cdFx0ZWw6ICcjbGxtcy1zZWN0aW9ucycsXG5cblx0XHRldmVudHMgOiB7XG5cdFx0XHQnbW91c2Vkb3duID4gbGkubGxtcy1zZWN0aW9uID4gLmxsbXMtYnVpbGRlci1oZWFkZXIgLmxsbXMtaGVhZGxpbmUnIDogJ19saXN0SXRlbV9vbk1vdXNlZG93bicsXG5cdFx0XHQvLyAnZGJsY2xpY2sgPiBsaSwgdGJvZHkgPiB0ciA+IHRkJyA6ICdfbGlzdEl0ZW1fb25Eb3VibGVDbGljaycsXG5cdFx0XHQnY2xpY2snIDogJ19saXN0QmFja2dyb3VuZF9vbkNsaWNrJyxcblx0XHRcdCdjbGljayB1bC5jb2xsZWN0aW9uLXZpZXcnIDogJ19saXN0QmFja2dyb3VuZF9vbkNsaWNrJyxcblx0XHRcdCdrZXlkb3duJyA6ICdfb25LZXlkb3duJ1xuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBTZWN0aW9uIG1vZGVsXG5cdFx0ICogQHR5cGUgIHtbdHlwZV19XG5cdFx0ICovXG5cdFx0bW9kZWxWaWV3OiBTZWN0aW9uVmlldyxcblxuXHRcdC8qKlxuXHRcdCAqIEVuYWJsZSBrZXlib2FyZCBldmVudHNcblx0XHQgKiBAdHlwZSAge0Jvb2x9XG5cdFx0ICovXG5cdFx0cHJvY2Vzc0tleUV2ZW50czogZmFsc2UsXG5cblx0XHQvKipcblx0XHQgKiBBcmUgc2VjdGlvbnMgc2VsZWN0YWJsZT9cblx0XHQgKiBAdHlwZSAge0Jvb2x9XG5cdFx0ICovXG5cdFx0c2VsZWN0YWJsZTogdHJ1ZSxcblxuXHRcdC8qKlxuXHRcdCAqIEFyZSBzZWN0aW9ucyBzb3J0YWJsZT9cblx0XHQgKiBAdHlwZSAge0Jvb2x9XG5cdFx0ICovXG5cdFx0c29ydGFibGU6IHRydWUsXG5cblx0XHRzb3J0YWJsZU9wdGlvbnM6IHtcblx0XHRcdGF4aXM6IGZhbHNlLFxuXHRcdFx0Y3Vyc29yOiAnbW92ZScsXG5cdFx0XHRoYW5kbGU6ICcuZHJhZy1zZWN0aW9uJyxcblx0XHRcdGl0ZW1zOiAnLmxsbXMtc2VjdGlvbicsXG5cdFx0XHRwbGFjZWhvbGRlcjogJ2xsbXMtc2VjdGlvbiBsbG1zLXNvcnRhYmxlLXBsYWNlaG9sZGVyJyxcblx0XHR9LFxuXG5cdFx0c29ydGFibGVfc3RhcnQ6IGZ1bmN0aW9uKCBjb2xsZWN0aW9uICkge1xuXHRcdFx0dGhpcy4kZWwuYWRkQ2xhc3MoICdkcmFnZ2luZycgKTtcblx0XHR9LFxuXG5cdFx0c29ydGFibGVfc3RvcDogZnVuY3Rpb24oIGNvbGxlY3Rpb24gKSB7XG5cdFx0XHR0aGlzLiRlbC5yZW1vdmVDbGFzcyggJ2RyYWdnaW5nJyApO1xuXHRcdH0sXG5cblx0fSwgUmVjZWl2YWJsZSApICk7XG5cbn0gKTtcblxuLyoqXG4gKiBTaW5nbGUgQ291cnNlIFZpZXdcbiAqIEBzaW5jZSAgICAzLjEzLjBcbiAqIEB2ZXJzaW9uICAzLjE2LjBcbiAqL1xuZGVmaW5lKCAnVmlld3MvQ291cnNlJyxbICdWaWV3cy9TZWN0aW9uTGlzdCcsICdWaWV3cy9fRWRpdGFibGUnIF0sIGZ1bmN0aW9uKCBTZWN0aW9uTGlzdFZpZXcsIEVkaXRhYmxlICkge1xuXG5cdHJldHVybiBCYWNrYm9uZS5WaWV3LmV4dGVuZCggXy5kZWZhdWx0cygge1xuXG5cdFx0LyoqXG5cdFx0ICogR2V0IGRlZmF1bHQgYXR0cmlidXRlcyBmb3IgdGhlIGh0bWwgd3JhcHBlciBlbGVtZW50XG5cdFx0ICogQHJldHVybiAgIG9ialxuXHRcdCAqIEBzaW5jZSAgICAzLjEzLjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xMy4wXG5cdFx0ICovXG5cdFx0YXR0cmlidXRlczogZnVuY3Rpb24oKSB7XG5cdFx0XHRyZXR1cm4ge1xuXHRcdFx0XHQnZGF0YS1pZCc6IHRoaXMubW9kZWwuaWQsXG5cdFx0XHR9O1xuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBIVE1MIGVsZW1lbnQgc2VsZWN0b3Jcblx0XHQgKiBAdHlwZSAge1N0cmluZ31cblx0XHQgKi9cblx0XHRlbDogJyNsbG1zLWJ1aWxkZXItbWFpbicsXG5cblx0XHQvKipcblx0XHQgKiBXcmFwcGVyIFRhZyBuYW1lXG5cdFx0ICogQHR5cGUgIHtTdHJpbmd9XG5cdFx0ICovXG5cdFx0dGFnTmFtZTogJ2RpdicsXG5cblx0XHQvKipcblx0XHQgKiBHZXQgdGhlIHVuZGVyc2NvcmUgdGVtcGxhdGVcblx0XHQgKiBAdHlwZSAge1t0eXBlXX1cblx0XHQgKi9cblx0XHR0ZW1wbGF0ZTogd3AudGVtcGxhdGUoICdsbG1zLWNvdXJzZS10ZW1wbGF0ZScgKSxcblxuXHRcdC8qKlxuXHRcdCAqIEluaXRpYWxpemF0aW9uIGNhbGxiYWNrIGZ1bmMgKHJlbmRlcnMgdGhlIGVsZW1lbnQgb24gc2NyZWVuKVxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTMuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjEzLjBcblx0XHQgKi9cblx0XHRpbml0aWFsaXplOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0dmFyIHNlbGYgPSB0aGlzO1xuXG5cdFx0XHQvLyB0aGlzLmxpc3RlblRvKCB0aGlzLm1vZGVsLCAnc3luYycsIHRoaXMucmVuZGVyICk7XG5cdFx0XHR0aGlzLnJlbmRlcigpO1xuXG5cdFx0XHR0aGlzLnNlY3Rpb25MaXN0VmlldyA9IG5ldyBTZWN0aW9uTGlzdFZpZXcoIHtcblx0XHRcdFx0Y29sbGVjdGlvbjogdGhpcy5tb2RlbC5nZXQoICdzZWN0aW9ucycgKSxcblx0XHRcdH0gKTtcblx0XHRcdHRoaXMuc2VjdGlvbkxpc3RWaWV3LnJlbmRlcigpO1xuXHRcdFx0Ly8gZHJhZyBhbmQgZHJvcCBzdGFydFxuXHRcdFx0dGhpcy5zZWN0aW9uTGlzdFZpZXcub24oICdzb3J0U3RhcnQnLCB0aGlzLnNlY3Rpb25MaXN0Vmlldy5zb3J0YWJsZV9zdGFydCApO1xuXHRcdFx0Ly8gZHJhZyBhbmQgZHJvcCBzdG9wXG5cdFx0XHR0aGlzLnNlY3Rpb25MaXN0Vmlldy5vbiggJ3NvcnRTdG9wJywgdGhpcy5zZWN0aW9uTGlzdFZpZXcuc29ydGFibGVfc3RvcCApO1xuXHRcdFx0Ly8gc2VsZWN0aW9uIGNoYW5nZXNcblx0XHRcdHRoaXMuc2VjdGlvbkxpc3RWaWV3Lm9uKCAnc2VsZWN0aW9uQ2hhbmdlZCcsIHRoaXMuYWN0aXZlX3NlY3Rpb25fY2hhbmdlICk7XG5cdFx0XHQvLyBcInNlbGVjdFwiIGEgc2VjdGlvbiB3aGVuIGl0J3MgYWRkZWQgdG8gdGhlIGNvdXJzZVxuXHRcdFx0dGhpcy5saXN0ZW5UbyggdGhpcy5tb2RlbC5nZXQoICdzZWN0aW9ucycpLCAnYWRkJywgdGhpcy5vbl9zZWN0aW9uX2FkZCApO1xuXG5cdFx0XHRCYWNrYm9uZS5wdWJTdWIub24oICdzZWN0aW9uLXRvZ2dsZScsIHRoaXMub25fc2VjdGlvbl90b2dnbGUsIHRoaXMgKTtcblxuXHRcdFx0QmFja2JvbmUucHViU3ViLm9uKCAnZXhwYW5kLXNlY3Rpb24nLCB0aGlzLmV4cGFuZF9zZWN0aW9uLCB0aGlzICk7XG5cblx0XHRcdEJhY2tib25lLnB1YlN1Yi5vbiggJ2xlc3Nvbi1zZWxlY3RlZCcsIHRoaXMuYWN0aXZlX2xlc3Nvbl9jaGFuZ2UsIHRoaXMgKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBDb21waWxlcyB0aGUgdGVtcGxhdGUgYW5kIHJlbmRlcnMgdGhlIHZpZXdcblx0XHQgKiBAcmV0dXJuICAgc2VsZiAoZm9yIGNoYWluaW5nKVxuXHRcdCAqIEBzaW5jZSAgICAzLjEzLjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xMy4wXG5cdFx0ICovXG5cdFx0cmVuZGVyOiBmdW5jdGlvbigpIHtcblx0XHRcdHRoaXMuJGVsLmh0bWwoIHRoaXMudGVtcGxhdGUoIHRoaXMubW9kZWwgKSApO1xuXHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0fSxcblxuXHRcdGFjdGl2ZV9sZXNzb25fY2hhbmdlOiBmdW5jdGlvbiggbW9kZWwgKSB7XG5cblx0XHRcdC8vIHNldCBwYXJlbnQgc2VjdGlvbiB0byBiZSBhY3RpdmVcblx0XHRcdHZhciBzZWN0aW9uID0gdGhpcy5tb2RlbC5nZXQoICdzZWN0aW9ucycgKS5nZXQoIG1vZGVsLmdldCggJ3BhcmVudF9zZWN0aW9uJyApICk7XG5cdFx0XHR0aGlzLnNlY3Rpb25MaXN0Vmlldy5zZXRTZWxlY3RlZE1vZGVsKCBzZWN0aW9uICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogV2hlbiBhIHNlY3Rpb24gXCJzZWxlY3Rpb25cIiBjaGFuZ2VzIGluIHRoZSBsaXN0XG5cdFx0ICogVXBkYXRlIGVhY2ggc2VjdGlvbiBtb2RlbCBzbyB3ZSBjYW4gZmlndXJlIG91dCB3aGljaCBvbmUgaXMgc2VsZWN0ZWQgZnJvbSBvdGhlciB2aWV3c1xuXHRcdCAqIEBwYXJhbSAgICBhcnJheSAgIGN1cnJlbnQgICBhcnJheSBvZiBzZWxlY3RlZCBtb2RlbHNcblx0XHQgKiBAcGFyYW0gICAgYXJyYXkgICBwcmV2aW91cyAgYXJyYXkgb2YgcHJldmlvdXNseSBzZWxlY3RlZCBtb2RlbHNcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0YWN0aXZlX3NlY3Rpb25fY2hhbmdlOiBmdW5jdGlvbiggY3VycmVudCwgcHJldmlvdXMgKSB7XG5cblx0XHRcdF8uZWFjaCggY3VycmVudCwgZnVuY3Rpb24oIG1vZGVsICkge1xuXHRcdFx0XHRtb2RlbC5zZXQoICdfc2VsZWN0ZWQnLCB0cnVlICk7XG5cdFx0XHR9ICk7XG5cblx0XHRcdF8uZWFjaCggcHJldmlvdXMsIGZ1bmN0aW9uKCBtb2RlbCApIHtcblx0XHRcdFx0bW9kZWwuc2V0KCAnX3NlbGVjdGVkJywgZmFsc2UgKTtcblx0XHRcdH0gKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBcIlNlbGVjdHNcIiB0aGUgbmV3IHNlY3Rpb24gd2hlbiBpdCdzIGFkZGVkIHRvIHRoZSBjb3Vyc2Vcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgbW9kZWwgIFNlY3Rpb24gbW9kZWwgdGhhdCdzIGp1c3QgYmVlbiBhZGRlZFxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRvbl9zZWN0aW9uX2FkZDogZnVuY3Rpb24oIG1vZGVsICkge1xuXG5cdFx0XHR0aGlzLnNlY3Rpb25MaXN0Vmlldy5zZXRTZWxlY3RlZE1vZGVsKCBtb2RlbCApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFdoZW4gZXhwYW5kaW5nL2NvbGxhcHNpbmcgc2VjdGlvbnNcblx0XHQgKiBpZiBjb2xsYXBzaW5nLCB1bnNlbGVjdCwgaWYgZXhwYW5kaW5nLCBzZWxlY3Rcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgbW9kZWwgIHRvZ2dsZWQgc2VjdGlvblxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRvbl9zZWN0aW9uX3RvZ2dsZTogZnVuY3Rpb24oIG1vZGVsICkge1xuXG5cdFx0XHR2YXIgc2VsZWN0ZWQgPSBtb2RlbC5nZXQoICdfZXhwYW5kZWQnICkgPyBbIG1vZGVsIF0gOiBbXTtcblx0XHRcdHRoaXMuc2VjdGlvbkxpc3RWaWV3LnNldFNlbGVjdGVkTW9kZWxzKCBzZWxlY3RlZCApO1xuXG5cdFx0fVxuXG5cdH0sIEVkaXRhYmxlICkgKTtcblxufSApO1xuXG4vKipcbiAqIE1vZGVsIHNldHRpbmdzIGZpZWxkcyB2aWV3XG4gKiBAc2luY2UgICAgMy4xNy4wXG4gKiBAdmVyc2lvbiAgMy4xNy43XG4gKi9cbmRlZmluZSggJ1ZpZXdzL1NldHRpbmdzRmllbGRzJyxbXSwgZnVuY3Rpb24oKSB7XG5cblx0cmV0dXJuIEJhY2tib25lLlZpZXcuZXh0ZW5kKCBfLmRlZmF1bHRzKCB7XG5cblx0XHQvKipcblx0XHQgKiBET00gZXZlbnRzXG5cdFx0ICogQHR5cGUgIHtPYmplY3R9XG5cdFx0ICovXG5cdFx0ZXZlbnRzOiB7XG5cdFx0XHQnY2xpY2sgLmxsbXMtc2V0dGluZ3MtZ3JvdXAtdG9nZ2xlJzogJ3RvZ2dsZV9ncm91cCcsXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFByb2Nlc3NlZCBmaWVsZHMgZGF0YVxuXHRcdCAqIEFsbG93cyBhY2Nlc3MgYnkgSUQgd2l0aG91dCB0cmF2ZXJzaW5nIHRoZSBzY2hlbWFcblx0XHQgKiBAdHlwZSAge09iamVjdH1cblx0XHQgKi9cblx0XHRmaWVsZHM6IHt9LFxuXG5cdFx0LyoqXG5cdFx0ICogV3JhcHBlciBUYWcgbmFtZVxuXHRcdCAqIEB0eXBlICB7U3RyaW5nfVxuXHRcdCAqL1xuXHRcdHRhZ05hbWU6ICdkaXYnLFxuXG5cdFx0LyoqXG5cdFx0ICogR2V0IHRoZSB1bmRlcnNjb3JlIHRlbXBsYXRlXG5cdFx0ICogQHR5cGUgIHtbdHlwZV19XG5cdFx0ICovXG5cdFx0dGVtcGxhdGU6IHdwLnRlbXBsYXRlKCAnbGxtcy1zZXR0aW5ncy1maWVsZHMtdGVtcGxhdGUnICksXG5cblx0XHQvKipcblx0XHQgKiBJbml0aWFsaXphdGlvbiBjYWxsYmFjayBmdW5jIChyZW5kZXJzIHRoZSBlbGVtZW50IG9uIHNjcmVlbilcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE3LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNy4wXG5cdFx0ICovXG5cdFx0Ly8gaW5pdGlhbGl6ZTogZnVuY3Rpb24oKSB7fSxcblxuXHRcdC8qKlxuXHRcdCAqIFJldHJpZXZlIGFuIGFycmF5IG9mIGFsbCBlZGl0b3IgZmllbGRzIGluIGFsbCBncm91cHNcblx0XHQgKiBAcmV0dXJuICAgYXJyYXlcblx0XHQgKiBAc2luY2UgICAgMy4xNy4xXG5cdFx0ICogQHZlcnNpb24gIDMuMTcuMVxuXHRcdCAqL1xuXHRcdGdldF9lZGl0b3JfZmllbGRzOiBmdW5jdGlvbigpIHtcblx0XHRcdHJldHVybiBfLmZpbHRlciggdGhpcy5maWVsZHMsIGZ1bmN0aW9uKCBmaWVsZCApIHtcblx0XHRcdFx0cmV0dXJuIHRoaXMuaXNfZWRpdG9yX2ZpZWxkKCBmaWVsZC50eXBlICk7XG5cdFx0XHR9LCB0aGlzICk7XG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIEdldCBzZXR0aW5ncyBncm91cCBkYXRhIGZyb20gYSBtb2RlbFxuXHRcdCAqIEByZXR1cm4gICB7W3R5cGVdfVxuXHRcdCAqIEBzaW5jZSAgICAzLjE3LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNy4wXG5cdFx0ICovXG5cdFx0Z2V0X2dyb3VwczogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHJldHVybiB0aGlzLm1vZGVsLmdldF9zZXR0aW5nc19maWVsZHMoKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBEZXRlcm1pbmUgaWYgYSBzZXR0aW5ncyBncm91cCBpcyBoaWRkZW4gaW4gbG9jYWxTdG9yYWdlXG5cdFx0ICogQHBhcmFtICAgIHN0cmluZyAgIGdyb3VwX2lkICBpZCBvZiB0aGUgZ3JvdXBcblx0XHQgKiBAcmV0dXJuICAge0Jvb2xlYW59XG5cdFx0ICogQHNpbmNlICAgIDMuMTcuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE3LjBcblx0XHQgKi9cblx0XHRpc19ncm91cF9oaWRkZW46IGZ1bmN0aW9uKCBncm91cF9pZCApIHtcblxuXHRcdFx0dmFyIGlkID0gJ2xsbXMtJyArIHRoaXMubW9kZWwuZ2V0KCAndHlwZScgKSArICctc2V0dGluZ3MtZ3JvdXAtLScgKyBncm91cF9pZDtcblxuXHRcdFx0aWYgKCAndW5kZWZpbmVkJyAhPT0gd2luZG93LmxvY2FsU3RvcmFnZSApIHtcblx0XHRcdFx0cmV0dXJuICggJ2hpZGRlbicgPT09IHdpbmRvdy5sb2NhbFN0b3JhZ2UuZ2V0SXRlbSggaWQgKSApO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogR2V0IHRoZSBzd2l0Y2ggYXR0cmlidXRlIGZvciBhIGZpZWxkIHdpdGggc3dpdGNoZXNcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgZmllbGQgIGZpZWxkIGRhdGEgb2JqXG5cdFx0ICogQHJldHVybiAgIHN0cmluZ1xuXHRcdCAqIEBzaW5jZSAgICAzLjE3LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNy4wXG5cdFx0ICovXG5cdFx0Z2V0X3N3aXRjaF9hdHRyaWJ1dGU6IGZ1bmN0aW9uKCBmaWVsZCApIHtcblxuXHRcdFx0cmV0dXJuIGZpZWxkLnN3aXRjaF9hdHRyaWJ1dGUgPyBmaWVsZC5zd2l0Y2hfYXR0cmlidXRlIDogZmllbGQuYXR0cmlidXRlO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIERldGVybWluZSBpZiBhIGZpZWxkIGhhcyBhIHN3aXRjaFxuXHRcdCAqIEBwYXJhbSAgICBzdHJpbmcgICB0eXBlICBmaWVsZCB0eXBlIHN0cmluZ1xuXHRcdCAqIEByZXR1cm4gICB7Qm9vbGVhbn1cblx0XHQgKiBAc2luY2UgICAgMy4xNy4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTcuMFxuXHRcdCAqL1xuXHRcdGhhc19zd2l0Y2g6IGZ1bmN0aW9uKCB0eXBlICkge1xuXHRcdFx0cmV0dXJuICggLTEgIT09IHR5cGUuaW5kZXhPZiggJ3N3aXRjaCcgKSApO1xuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBEZXRlcm1pbmUgaWYgYSBmaWVsZCBpcyBhIGRlZmF1bHQgKHRleHQpIGZpZWxkXG5cdFx0ICogQHBhcmFtICAgIHN0cmluZyAgIHR5cGUgIGZpZWxkIHR5cGUgc3RyaW5nXG5cdFx0ICogQHJldHVybiAgIHtCb29sZWFufVxuXHRcdCAqIEBzaW5jZSAgICAzLjE3LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNy4wXG5cdFx0ICovXG5cdFx0aXNfZGVmYXVsdF9maWVsZDogZnVuY3Rpb24oIHR5cGUgKSB7XG5cblx0XHRcdHZhciB0eXBlcyA9IFsgJ2F1ZGlvX2VtYmVkJywgJ2RhdGVwaWNrZXInLCAnbnVtYmVyJywgJ3RleHQnLCAndmlkZW9fZW1iZWQnIF07XG5cdFx0XHRyZXR1cm4gKCAtMSAhPT0gdHlwZXMuaW5kZXhPZiggdHlwZS5yZXBsYWNlKCAnc3dpdGNoLScsICcnICkgKSApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIERldGVybWluZSBpZiBhIGZpZWxkIGlzIGEgV1lTSVdZRyBlZGl0b3IgZmllbGRcblx0XHQgKiBAcGFyYW0gICAgc3RyaW5nICAgdHlwZSAgZmllbGQgdHlwZSBzdHJpbmdcblx0XHQgKiBAcmV0dXJuICAge0Jvb2xlYW59XG5cdFx0ICogQHNpbmNlICAgIDMuMTcuMVxuXHRcdCAqIEB2ZXJzaW9uICAzLjE3LjFcblx0XHQgKi9cblx0XHRpc19lZGl0b3JfZmllbGQ6IGZ1bmN0aW9uKCB0eXBlICkge1xuXG5cdFx0XHR2YXIgdHlwZXMgPSBbICdlZGl0b3InLCAnc3dpdGNoLWVkaXRvcicgXTtcblx0XHRcdHJldHVybiAoIC0xICE9PSB0eXBlcy5pbmRleE9mKCB0eXBlLnJlcGxhY2UoICdzd2l0Y2gtJywgJycgKSApICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogRGV0ZXJtaW5lIGlmIGEgc3dpdGNoIGlzIGVuYWJsZWQgZm9yIGEgZmllbGRcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgZmllbGQgIGZpZWxkIGRhdGEgb2JqZWN0XG5cdFx0ICogQHJldHVybiAgIHtCb29sZWFufVxuXHRcdCAqIEBzaW5jZSAgICAzLjE3LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNy42XG5cdFx0ICovXG5cdFx0aXNfc3dpdGNoX2NvbmRpdGlvbl9tZXQ6IGZ1bmN0aW9uKCBmaWVsZCApIHtcblxuXHRcdFx0cmV0dXJuICggZmllbGQuc3dpdGNoX29uID09PSB0aGlzLm1vZGVsLmdldCggZmllbGQuc3dpdGNoX2F0dHJpYnV0ZSApICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogQ29tcGlsZXMgdGhlIHRlbXBsYXRlIGFuZCByZW5kZXJzIHRoZSB2aWV3XG5cdFx0ICogQHJldHVybiAgIHNlbGYgKGZvciBjaGFpbmluZylcblx0XHQgKiBAc2luY2UgICAgMy4xNy4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTcuMVxuXHRcdCAqL1xuXHRcdHJlbmRlcjogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHRoaXMuJGVsLmh0bWwoIHRoaXMudGVtcGxhdGUoIHRoaXMgKSApO1xuXG5cdFx0XHQvLyBpZiBlZGl0b3JzIGV4aXN0LCByZW5kZXIgdGhlbVxuXHRcdFx0Xy5lYWNoKCB0aGlzLmdldF9lZGl0b3JfZmllbGRzKCksIGZ1bmN0aW9uKCBmaWVsZCApIHtcblx0XHRcdFx0dGhpcy5yZW5kZXJfZWRpdG9yKCBmaWVsZCApO1xuXHRcdFx0fSwgdGhpcyApO1xuXG5cdFx0XHRyZXR1cm4gdGhpcztcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBSZW5kZXJzIGFuIGVkaXRvciBmaWVsZFxuXHRcdCAqIEBwYXJhbSAgICBvYmogICBmaWVsZCAgZmllbGQgZGF0YSBvYmplY3Rcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE3LjFcblx0XHQgKiBAdmVyc2lvbiAgMy4xNy4xXG5cdFx0ICovXG5cdFx0cmVuZGVyX2VkaXRvcjogZnVuY3Rpb24oIGZpZWxkICkge1xuXG5cdFx0XHR2YXIgc2VsZiA9IHRoaXM7XG5cblx0XHRcdHdwLmVkaXRvci5yZW1vdmUoIGZpZWxkLmlkICk7XG5cdFx0XHRmaWVsZC5zZXR0aW5ncy50aW55bWNlLnNldHVwID0gZnVuY3Rpb24oIGVkaXRvciApIHtcblxuXHRcdFx0XHR2YXIgJGVkID0gJCggJyMnICsgZWRpdG9yLmlkICksXG5cdFx0XHRcdFx0JHBhcmVudCA9ICRlZC5jbG9zZXN0KCAnLmxsbXMtZWRpdGFibGUtZWRpdG9yJyApLFxuXHRcdFx0XHRcdCRsYWJlbCA9ICRwYXJlbnQuZmluZCggJy5sbG1zLWxhYmVsJyApLFxuXHRcdFx0XHRcdHByb3AgPSAkZWQuYXR0ciggJ2RhdGEtYXR0cmlidXRlJyApXG5cblx0XHRcdFx0aWYgKCAkbGFiZWwubGVuZ3RoICkge1xuXHRcdFx0XHRcdCRsYWJlbC5wcmVwZW5kVG8oICRwYXJlbnQuZmluZCggJy53cC1lZGl0b3ItdG9vbHMnICkgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIHNhdmUgY2hhbmdlcyB0byB0aGUgbW9kZWwgdmlhIFZpc3VhbCBlZFxuXHRcdFx0XHRlZGl0b3Iub24oICdjaGFuZ2UnLCBmdW5jdGlvbiggZXZlbnQgKSB7XG5cdFx0XHRcdFx0c2VsZi5tb2RlbC5zZXQoIHByb3AsIHdwLmVkaXRvci5nZXRDb250ZW50KCBlZGl0b3IuaWQgKSApO1xuXHRcdFx0XHR9ICk7XG5cblx0XHRcdFx0Ly8gc2F2ZSBjaGFuZ2VzIHZpYSBUZXh0IGVkXG5cdFx0XHRcdCRlZC5vbiggJ2lucHV0JywgZnVuY3Rpb24oIGV2ZW50ICkge1xuXHRcdFx0XHRcdHNlbGYubW9kZWwuc2V0KCBwcm9wLCAkZWQudmFsKCkgKTtcblx0XHRcdFx0fSApO1xuXG5cdFx0XHRcdC8vIHRyaWdnZXIgYW4gaW5wdXQgb24gdGhlIFRleHQgZWQgd2hlbiBxdWlja3RhZ3MgYnV0dG9ucyBhcmUgY2xpY2tlZFxuXHRcdFx0XHQkcGFyZW50Lm9uKCAnY2xpY2snLCAnLnF1aWNrdGFncy10b29sYmFyIC5lZF9idXR0b24nLCBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRzZXRUaW1lb3V0KCBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRcdCRlZC50cmlnZ2VyKCAnaW5wdXQnICk7XG5cdFx0XHRcdFx0fSwgMTAgKTtcblx0XHRcdFx0fSApO1xuXHRcdFx0fTtcblxuXHRcdFx0d3AuZWRpdG9yLmluaXRpYWxpemUoIGZpZWxkLmlkLCBmaWVsZC5zZXR0aW5ncyApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIEdldCB0aGUgSFRNTCBmb3IgYSBzZWxlY3QgZmllbGRcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgICAgb3B0aW9ucyAgICBmbGF0IG9yIG11bHRpLWRpbWVuc2lvbmFsIG9wdGlvbnMgb2JqZWN0XG5cdFx0ICogQHBhcmFtICAgIHN0cmluZyAgIGF0dHJpYnV0ZSAgbmFtZSBvZiB0aGUgc2VsZWN0IGZpZWxkJ3MgYXR0cmlidXRlXG5cdFx0ICogQHJldHVybiAgIHN0cmluZ1xuXHRcdCAqIEBzaW5jZSAgICAzLjE3LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNy4yXG5cdFx0ICovXG5cdFx0cmVuZGVyX3NlbGVjdF9vcHRpb25zOiBmdW5jdGlvbiggb3B0aW9ucywgYXR0cmlidXRlICkge1xuXG5cdFx0XHR2YXIgaHRtbCA9ICcnLFxuXHRcdFx0XHRzZWxlY3RlZCA9IHRoaXMubW9kZWwuZ2V0KCBhdHRyaWJ1dGUgKTtcblxuXHRcdFx0ZnVuY3Rpb24gb3B0aW9uX2h0bWwoIGxhYmVsLCB2YWwgKSB7XG5cblx0XHRcdFx0cmV0dXJuICc8b3B0aW9uIHZhbHVlPVwiJyArIHZhbCArICdcIicgKyBfLnNlbGVjdGVkKCB2YWwsIHNlbGVjdGVkICkgKyAnPicgKyBsYWJlbCArICc8L29wdGlvbj4nO1xuXG5cdFx0XHR9XG5cblx0XHRcdF8uZWFjaCggb3B0aW9ucywgZnVuY3Rpb24oIG9wdGlvbiwgaW5kZXggKSB7XG5cblx0XHRcdFx0Ly8gdGhpcyB3aWxsIGJlIGFuIGtleTp2YWwgb2JqZWN0XG5cdFx0XHRcdGlmICggJ3N0cmluZycgPT09IHR5cGVvZiBvcHRpb24gKSB7XG5cdFx0XHRcdFx0aHRtbCArPSBvcHRpb25faHRtbCggb3B0aW9uLCBpbmRleCApO1xuXHRcdFx0XHQvLyBlaXRoZXIgb3B0aW9uIGdyb3VwIG9yIGFycmF5IG9mIGtleSx2YWwgb2JqZWN0c1xuXHRcdFx0XHR9IGVsc2UgaWYgKCAnb2JqZWN0JyA9PT0gdHlwZW9mIG9wdGlvbiApIHtcblx0XHRcdFx0XHQvLyBvcHRpb24gZ3JvdXBcblx0XHRcdFx0XHRpZiAoIG9wdGlvbi5sYWJlbCAmJiBvcHRpb24ub3B0aW9ucyApIHtcblx0XHRcdFx0XHRcdGh0bWwgKz0gJzxvcHRncm91cCBsYWJlbD1cIicgKyBvcHRpb24ubGFiZWwgKyAnXCI+Jztcblx0XHRcdFx0XHRcdGh0bWwgKz0gdGhpcy5yZW5kZXJfc2VsZWN0X29wdGlvbnMoIG9wdGlvbi5vcHRpb25zLCBhdHRyaWJ1dGUgKTtcblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0aHRtbCArPSBvcHRpb25faHRtbCggb3B0aW9uLnZhbCwgb3B0aW9uLmtleSApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXG5cdFx0XHR9LCB0aGlzICk7XG5cblx0XHRcdHJldHVybiBodG1sO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFNldHVwIGFuZCBmaWxsIGZpZWxkcyB3aXRoIGRlZmF1bHQgZGF0YSBiYXNlZCBvbiBmaWVsZCB0eXBlXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIG9yaWdfZmllbGQgICBvcmlnaW5hbCBmaWVsZCBhcyBkZWZpbmVkIGluIHRoZSBzZXR0aW5nc1xuXHRcdCAqIEBwYXJhbSAgICBpbnQgICBmaWVsZF9pbmRleCAgaW5kZXggb2YgdGhlIGZpZWxkIGluIHRoZSBjdXJyZW50IHJvd1xuXHRcdCAqIEByZXR1cm4gICBvYmpcblx0XHQgKiBAc2luY2UgICAgMy4xNy4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTcuN1xuXHRcdCAqL1xuXHRcdHNldHVwX2ZpZWxkOiBmdW5jdGlvbiggb3JpZ19maWVsZCwgZmllbGRfaW5kZXggKSB7XG5cblx0XHRcdHZhciBkZWZhdWx0cyA9IHtcblx0XHRcdFx0Y2xhc3NlczogW10sXG5cdFx0XHRcdGlkOiBfLnVuaXF1ZUlkKCBvcmlnX2ZpZWxkLmF0dHJpYnV0ZSArICdfJyApLFxuXHRcdFx0XHRpbnB1dF90eXBlOiAndGV4dCcsXG5cdFx0XHRcdGxhYmVsOiAnJyxcblx0XHRcdFx0b3B0aW9uczoge30sXG5cdFx0XHRcdHBsYWNlaG9sZGVyOiAnJyxcblx0XHRcdFx0dGlwOiAnJyxcblx0XHRcdFx0dGlwX3Bvc2l0aW9uOiAndG9wLXJpZ2h0Jyxcblx0XHRcdFx0c2V0dGluZ3M6IHt9LFxuXHRcdFx0fTtcblxuXHRcdFx0Ly8gY2hlY2sgdGhlIGZpZWxkIGNvbmRpdGlvbiBpZiBzZXRcblx0XHRcdGlmICggb3JpZ19maWVsZC5jb25kaXRpb24gJiYgZmFsc2UgPT09IF8uYmluZCggb3JpZ19maWVsZC5jb25kaXRpb24sIHRoaXMubW9kZWwgKSgpICkge1xuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHR9XG5cblx0XHRcdHN3aXRjaCAoIG9yaWdfZmllbGQudHlwZSApIHtcblxuXHRcdFx0XHRjYXNlICdhdWRpb19lbWJlZCc6XG5cdFx0XHRcdFx0ZGVmYXVsdHMuY2xhc3Nlcy5wdXNoKCAnbGxtcy1lZGl0YWJsZS1hdWRpbycgKTtcblx0XHRcdFx0XHRkZWZhdWx0cy5wbGFjZWhvbGRlciA9ICdodHRwczovLyc7XG5cdFx0XHRcdFx0ZGVmYXVsdHMudGlwID0gTExNUy5sMTBuLnRyYW5zbGF0ZSggJ1VzZSBTb3VuZENsb3VkIG9yIFNwb3RpZnkgYXVkaW8gVVJMUy4nICk7XG5cdFx0XHRcdFx0ZGVmYXVsdHMuaW5wdXRfdHlwZSA9ICd1cmwnO1xuXHRcdFx0XHRicmVhaztcblxuXHRcdFx0XHRjYXNlICdkYXRlcGlja2VyJzpcblx0XHRcdFx0XHRkZWZhdWx0cy5jbGFzc2VzLnB1c2goICdsbG1zLWVkaXRhYmxlLWRhdGUnICk7XG5cdFx0XHRcdGJyZWFrO1xuXG5cdFx0XHRcdGNhc2UgJ2VkaXRvcic6XG5cdFx0XHRcdGNhc2UgJ3N3aXRjaC1lZGl0b3InOlxuXHRcdFx0XHRcdHZhciBvcmlnX3NldHRpbmdzID0gb3JpZ19maWVsZC5zZXR0aW5ncyB8fCB7fTtcblx0XHRcdFx0XHRkZWZhdWx0cy5zZXR0aW5ncyA9ICQuZXh0ZW5kKCB0cnVlLCB3cC5lZGl0b3IuZ2V0RGVmYXVsdFNldHRpbmdzKCksIHtcblx0XHRcdFx0XHRcdG1lZGlhQnV0dG9uczogdHJ1ZSxcblx0XHRcdFx0XHRcdHRpbnltY2U6IHtcblx0XHRcdFx0XHRcdFx0dG9vbGJhcjE6ICdib2xkLGl0YWxpYyxzdHJpa2V0aHJvdWdoLGJ1bGxpc3QsbnVtbGlzdCxibG9ja3F1b3RlLGhyLGFsaWdubGVmdCxhbGlnbmNlbnRlcixhbGlnbnJpZ2h0LGxpbmssdW5saW5rLHdwX2FkdicsXG5cdFx0XHRcdFx0XHRcdHRvb2xiYXIyOiAnZm9ybWF0c2VsZWN0LHVuZGVybGluZSxhbGlnbmp1c3RpZnksZm9yZWNvbG9yLHBhc3RldGV4dCxyZW1vdmVmb3JtYXQsY2hhcm1hcCxvdXRkZW50LGluZGVudCx1bmRvLHJlZG8sd3BfaGVscCcsXG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fSwgb3JpZ19zZXR0aW5ncyApO1xuXHRcdFx0XHRicmVhaztcblxuXHRcdFx0XHRjYXNlICdudW1iZXInOlxuXHRcdFx0XHRcdGRlZmF1bHRzLmlucHV0X3R5cGUgPSAnbnVtYmVyJztcblx0XHRcdFx0YnJlYWs7XG5cblx0XHRcdFx0Y2FzZSAncGVybWFsaW5rJzpcblx0XHRcdFx0XHRkZWZhdWx0cy5sYWJlbCA9IExMTVMubDEwbi50cmFuc2xhdGUoICdQZXJtYWxpbmsnICk7XG5cdFx0XHRcdGJyZWFrO1xuXG5cdFx0XHRcdGNhc2UgJ3ZpZGVvX2VtYmVkJzpcblx0XHRcdFx0XHRkZWZhdWx0cy5jbGFzc2VzLnB1c2goICdsbG1zLWVkaXRhYmxlLXZpZGVvJyApO1xuXHRcdFx0XHRcdGRlZmF1bHRzLnBsYWNlaG9sZGVyID0gJ2h0dHBzOi8vJztcblx0XHRcdFx0XHRkZWZhdWx0cy50aXAgPSBMTE1TLmwxMG4udHJhbnNsYXRlKCAnVXNlIFlvdVR1YmUsIFZpbWVvLCBvciBXaXN0aWEgdmlkZW8gVVJMUy4nICk7XG5cdFx0XHRcdFx0ZGVmYXVsdHMuaW5wdXRfdHlwZSA9ICd1cmwnO1xuXHRcdFx0XHRicmVhaztcblxuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIHRoaXMuaGFzX3N3aXRjaCggb3JpZ19maWVsZC50eXBlICkgKSB7XG5cdFx0XHRcdGRlZmF1bHRzLnN3aXRjaF9vbiA9ICd5ZXMnO1xuXHRcdFx0XHRkZWZhdWx0cy5zd2l0Y2hfb2ZmID0gJ25vJztcblx0XHRcdH1cblxuXHRcdFx0dmFyIGZpZWxkID0gXy5kZWZhdWx0cyggXy5kZWVwQ2xvbmUoIG9yaWdfZmllbGQgKSwgZGVmYXVsdHMgKTtcblxuXHRcdFx0Ly8gaWYgb3B0aW9ucyBpcyBhIGZ1bmN0aW9uIHJ1biBpdFxuXHRcdFx0aWYgKCBfLmlzRnVuY3Rpb24oIGZpZWxkLm9wdGlvbnMgKSApIHtcblx0XHRcdFx0ZmllbGQub3B0aW9ucyA9IF8uYmluZCggZmllbGQub3B0aW9ucywgdGhpcy5tb2RlbCApKCk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIGlmIGl0J3MgYSByYWRpbyBmaWVsZCBvcHRpb25zIHZhbHVlcyBjYW4gYmUgc3VibWl0dGVkIGFzIGltYWdlc1xuXHRcdFx0Ly8gdGhpcyB3aWxsIHRyYW5zZm9ybSB0aG9zZSBpbWFnZXMgaW50byA8aW1nPiBodG1sXG5cdFx0XHRpZiAoIC0xICE9PSBbICdyYWRpbycsICdzd2l0Y2gtcmFkaW8nIF0uaW5kZXhPZiggb3JpZ19maWVsZC50eXBlICkgKSB7XG5cblx0XHRcdFx0dmFyIGhhc19pbWFnZXMgPSBmYWxzZTtcblx0XHRcdFx0Xy5lYWNoKCBvcmlnX2ZpZWxkLm9wdGlvbnMsIGZ1bmN0aW9uKCB2YWwsIGtleSApIHtcblx0XHRcdFx0XHRpZiAoIC0xICE9PSB2YWwuaW5kZXhPZiggJy5wbmcnICkgfHwgLTEgIT09IHZhbC5pbmRleE9mKCAnLmpwZycgKSApIHtcblx0XHRcdFx0XHRcdGZpZWxkLm9wdGlvbnNba2V5XSA9ICc8c3Bhbj48aW1nIHNyYz1cIicgKyB2YWwgKyAnXCI+PC9zcGFuPic7XG5cdFx0XHRcdFx0XHRoYXNfaW1hZ2VzID0gdHJ1ZTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0gKTtcblx0XHRcdFx0aWYgKCBoYXNfaW1hZ2VzICkge1xuXHRcdFx0XHRcdGZpZWxkLmNsYXNzZXMucHVzaCggJ2hhcy1pbWFnZXMnICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0fVxuXG5cdFx0XHQvLyBhZGQgdG9vbHRpcCBwb3NpdGlvbiBjbGFzc2VzXG5cdFx0XHRpZiAoIGZpZWxkLnRpcCApIHtcblx0XHRcdFx0ZmllbGQuY2xhc3Nlcy5wdXNoKCAndGlwLS0nICsgZmllbGQudGlwX3Bvc2l0aW9uICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIHRyYW5zZm9ybSBjbGFzc2VzIGFycmF5IHRvIGEgY3NzIGNsYXNzIHN0cmluZ1xuXHRcdFx0aWYgKCBmaWVsZC5jbGFzc2VzLmxlbmd0aCApIHtcblx0XHRcdFx0ZmllbGQuY2xhc3NlcyA9ICcgJyArIGZpZWxkLmNsYXNzZXMuam9pbiggJyAnICk7XG5cdFx0XHR9XG5cblx0XHRcdHRoaXMuZmllbGRzWyBmaWVsZC5pZCBdID0gZmllbGQ7XG5cblx0XHRcdHJldHVybiBmaWVsZDtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBEZXRlcm1pbmUgaWYgdG9nZ2xpbmcgYSBzd2l0Y2ggc2VsZWN0IHNob3VsZCByZXJlbmRlciB0aGUgdmlld1xuXHRcdCAqIEBwYXJhbSAgICBzdHJpbmcgICBmaWVsZF90eXBlICBmaWVsZCB0eXBlIHN0cmluZ1xuXHRcdCAqIEByZXR1cm4gICBib29sZWFuXG5cdFx0ICogQHNpbmNlICAgIDMuMTcuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE3LjBcblx0XHQgKi9cblx0XHRzaG91bGRfcmVyZW5kZXJfb25fdG9nZ2xlOiBmdW5jdGlvbiggZmllbGRfdHlwZSApIHtcblxuXHRcdFx0cmV0dXJuICggLTEgIT09IGZpZWxkX3R5cGUuaW5kZXhPZiggJ3N3aXRjaC0nICkgKSA/ICd5ZXMnIDogJ25vJztcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBDbGljayBldmVudCBmb3IgdG9nZ2xpbmcgdmlzaWJpbGl0eSBvZiBzZXR0aW5ncyBncm91cHNcblx0XHQgKiBJZiBsb2NhbFN0b3JhZ2UgaXMgYXZhaWxhYmxlLCBwZXJzaXN0IHN0YXRlXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIGV2ZW50ICBqcyBldmVudCBvYmplY3Rcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE3LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNy4wXG5cdFx0ICovXG5cdFx0dG9nZ2xlX2dyb3VwOiBmdW5jdGlvbiggZXZlbnQgKSB7XG5cblx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cblx0XHRcdHZhciAkZWwgPSAkKCBldmVudC5jdXJyZW50VGFyZ2V0ICksXG5cdFx0XHRcdCRncm91cCA9ICRlbC5jbG9zZXN0KCAnLmxsbXMtbW9kZWwtc2V0dGluZ3MnICk7XG5cblx0XHRcdCRncm91cC50b2dnbGVDbGFzcyggJ2hpZGRlbicgKTtcblxuXHRcdFx0aWYgKCAndW5kZWZpbmVkJyAhPT0gd2luZG93LmxvY2FsU3RvcmFnZSApIHtcblxuXHRcdFx0XHR2YXIgaWQgPSAkZ3JvdXAuYXR0ciggJ2lkJyApO1xuXHRcdFx0XHRpZiAoICRncm91cC5oYXNDbGFzcyggJ2hpZGRlbicgKSApIHtcblx0XHRcdFx0XHR3aW5kb3cubG9jYWxTdG9yYWdlLnNldEl0ZW0oIGlkLCAnaGlkZGVuJyApO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHdpbmRvdy5sb2NhbFN0b3JhZ2UucmVtb3ZlSXRlbSggaWQgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHR9XG5cblx0XHR9LFxuXG5cdH0gKSApO1xuXG59ICk7XG5cbi8qKlxuICogTGVzc29uIEVkaXRvciAoU2lkZWJhcikgVmlld1xuICogQHNpbmNlICAgIDMuMTcuMFxuICogQHZlcnNpb24gIDMuMTcuMFxuICovXG5kZWZpbmUoICdWaWV3cy9MZXNzb25FZGl0b3InLFtcblx0XHQnVmlld3MvX0RldGFjaGFibGUnLFxuXHRcdCdWaWV3cy9fRWRpdGFibGUnLFxuXHRcdCdWaWV3cy9fVHJhc2hhYmxlJyxcblx0XHQnVmlld3MvX1N1YnZpZXcnLFxuXHRcdCdWaWV3cy9TZXR0aW5nc0ZpZWxkcydcblx0XSwgZnVuY3Rpb24oXG5cdFx0RGV0YWNoYWJsZSxcblx0XHRFZGl0YWJsZSxcblx0XHRUcmFzaGFibGUsXG5cdFx0U3Vidmlldyxcblx0XHRTZXR0aW5nc0ZpZWxkc1xuXHQpIHtcblxuXHRyZXR1cm4gQmFja2JvbmUuVmlldy5leHRlbmQoIF8uZGVmYXVsdHMoIHtcblxuXHRcdC8qKlxuXHRcdCAqIEN1cnJlbnQgdmlldyBzdGF0ZVxuXHRcdCAqIEB0eXBlICB7U3RyaW5nfVxuXHRcdCAqL1xuXHRcdHN0YXRlOiAnZGVmYXVsdCcsXG5cblx0XHQvKipcblx0XHQgKiBDdXJyZW50IFN1YnZpZXdzXG5cdFx0ICogQHR5cGUgIHtPYmplY3R9XG5cdFx0ICovXG5cdFx0dmlld3M6IHtcblx0XHRcdHNldHRpbmdzOiB7XG5cdFx0XHRcdGNsYXNzOiBTZXR0aW5nc0ZpZWxkcyxcblx0XHRcdFx0aW5zdGFuY2U6IG51bGwsXG5cdFx0XHRcdHN0YXRlOiAnZGVmYXVsdCcsXG5cdFx0XHR9LFxuXHRcdH0sXG5cblx0XHRlbDogJyNsbG1zLWVkaXRvci1sZXNzb24nLFxuXG5cdFx0LyoqXG5cdFx0ICogRXZlbnRzXG5cdFx0ICogQHR5cGUgIHtPYmplY3R9XG5cdFx0ICovXG5cdFx0ZXZlbnRzOiBfLmRlZmF1bHRzKCB7fSwgRGV0YWNoYWJsZS5ldmVudHMsIEVkaXRhYmxlLmV2ZW50cywgVHJhc2hhYmxlLmV2ZW50cyApLFxuXG5cdFx0LyoqXG5cdFx0ICogVGVtcGxhdGUgZnVuY3Rpb25cblx0XHQgKiBAdHlwZSAge1t0eXBlXX1cblx0XHQgKi9cblx0XHR0ZW1wbGF0ZTogd3AudGVtcGxhdGUoICdsbG1zLWxlc3Nvbi1zZXR0aW5ncy10ZW1wbGF0ZScgKSxcblxuXHRcdC8qKlxuXHRcdCAqIEluaXRcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgZGF0YSAgcGFyZW50IHRlbXBsYXRlIGRhdGFcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE3LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNy4wXG5cdFx0ICovXG5cdFx0aW5pdGlhbGl6ZTogZnVuY3Rpb24oIGRhdGEgKSB7XG5cblx0XHRcdHRoaXMubW9kZWwgPSBkYXRhLmxlc3NvbjtcblxuXHRcdFx0dmFyIGNoYW5nZV9ldmVudHMgPSBbXG5cdFx0XHRcdCdjaGFuZ2U6ZGF0ZV9hdmFpbGFibGUnLFxuXHRcdFx0XHQnY2hhbmdlOmRyaXBfbWV0aG9kJyxcblx0XHRcdFx0J2NoYW5nZTp0aW1lX2F2YWlsYWJsZScsXG5cdFx0XHRdO1xuXHRcdFx0Xy5lYWNoKCBjaGFuZ2VfZXZlbnRzLCBmdW5jdGlvbiggZXZlbnQgKSB7XG5cdFx0XHRcdHRoaXMubGlzdGVuVG8oIHRoaXMubW9kZWwsIGV2ZW50LCB0aGlzLnJlbmRlciApO1xuXHRcdFx0fSwgdGhpcyApO1xuXG5cdFx0XHQvLyB3aGVuIHRoZSBcImhhc19wcmVyZXF1aXNpdGVcIiBhdHRyIGlzIHRvZ2dsZWQgT05cblx0XHRcdC8vIHRyaWdnZXIgdGhlIHByZXJlcSBzZWxlY3Qgb2JqZWN0IHRvIHNldCB0aGUgZGVmYXVsdCAoZmlyc3QgYXZhaWxhYmxlKSBwcmVyZXEgZm9yIHRoZSBsZXNzb25cblx0XHRcdHRoaXMubGlzdGVuVG8oIHRoaXMubW9kZWwsICdjaGFuZ2U6aGFzX3ByZXJlcXVpc2l0ZScsIGZ1bmN0aW9uKCBsZXNzb24sIHZhbCApIHtcblx0XHRcdFx0aWYgKCAneWVzJyA9PT0gdmFsICkge1xuXHRcdFx0XHRcdHRoaXMuJGVsLmZpbmQoICdzZWxlY3RbbmFtZT1cInByZXJlcXVpc2l0ZVwiXScgKS50cmlnZ2VyKCAnY2hhbmdlJyApO1xuXHRcdFx0XHR9XG5cdFx0XHR9ICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogUmVuZGVyIHRoZSB2aWV3XG5cdFx0ICogQHJldHVybiAgIG9ialxuXHRcdCAqIEBzaW5jZSAgICAzLjE3LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNy4wXG5cdFx0ICovXG5cdFx0cmVuZGVyOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0dGhpcy4kZWwuaHRtbCggdGhpcy50ZW1wbGF0ZSggdGhpcy5tb2RlbCApICk7XG5cblx0XHRcdHRoaXMucmVtb3ZlX3N1YnZpZXcoICdzZXR0aW5ncycgKTtcblxuXHRcdFx0dGhpcy5yZW5kZXJfc3VidmlldyggJ3NldHRpbmdzJywge1xuXHRcdFx0XHRlbDogJyNsbG1zLWxlc3Nvbi1zZXR0aW5ncy1maWVsZHMnLFxuXHRcdFx0XHRtb2RlbDogdGhpcy5tb2RlbCxcblx0XHRcdH0gKTtcblxuXHRcdFx0dGhpcy5pbml0X2RhdGVwaWNrZXJzKCk7XG5cdFx0XHR0aGlzLmluaXRfc2VsZWN0cygpO1xuXG5cdFx0XHRyZXR1cm4gdGhpcztcblxuXHRcdH0sXG5cblx0fSwgRGV0YWNoYWJsZSwgRWRpdGFibGUsIFRyYXNoYWJsZSwgU3VidmlldywgU2V0dGluZ3NGaWVsZHMgKSApO1xuXG59ICk7XG5cbi8qKlxuICogU2luZ2xlIFF1aXogVmlld1xuICogQHNpbmNlICAgIDMuMTYuMFxuICogQHZlcnNpb24gIDMuMTYuMFxuICovXG5kZWZpbmUoICdWaWV3cy9Qb3BvdmVyJyxbXSwgZnVuY3Rpb24oKSB7XG5cblx0cmV0dXJuIEJhY2tib25lLlZpZXcuZXh0ZW5kKCB7XG5cblx0XHRkZWZhdWx0czoge1xuXHRcdFx0cGxhY2VtZW50OiAnYXV0bycsXG5cdFx0XHQvLyBjb250YWluZXI6IGRvY3VtZW50LmJvZHksXG5cdFx0XHR3aWR0aDogJ2F1dG8nLFxuXHRcdFx0dHJpZ2dlcjogJ21hbnVhbCcsXG5cdFx0XHRzdHlsZTogJ2xpZ2h0Jyxcblx0XHRcdGFuaW1hdGlvbjogJ3BvcCcsXG5cdFx0XHR0aXRsZTogJycsXG5cdFx0XHRjb250ZW50OiAnJyxcblx0XHRcdGNsb3NlYWJsZTogZmFsc2UsXG5cdFx0XHRiYWNrZHJvcDogZmFsc2UsXG5cdFx0XHRvblNob3c6IGZ1bmN0aW9uKCAkZWwgKSB7fSxcblx0XHRcdG9uSGlkZTogZnVuY3Rpb24oICRlbCApIHt9LFxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBXcmFwcGVyIFRhZyBuYW1lXG5cdFx0ICogQHR5cGUgIHtTdHJpbmd9XG5cdFx0ICovXG5cdFx0dGFnTmFtZTogJ2RpdicsXG5cblx0XHQvKipcblx0XHQgKiBJbml0aWFsaXphdGlvbiBjYWxsYmFjayBmdW5jIChyZW5kZXJzIHRoZSBlbGVtZW50IG9uIHNjcmVlbilcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE0LjFcblx0XHQgKiBAdmVyc2lvbiAgMy4xNC4xXG5cdFx0ICovXG5cdFx0aW5pdGlhbGl6ZTogZnVuY3Rpb24oIGRhdGEgKSB7XG5cblx0XHRcdGlmICggdGhpcy4kZWwubGVuZ3RoICkge1xuXHRcdFx0XHR0aGlzLmRlZmF1bHRzLmNvbnRhaW5lciA9IHRoaXMuJGVsLnBhcmVudCgpO1xuXHRcdFx0fVxuXG5cdFx0XHR0aGlzLmFyZ3MgPSBfLmRlZmF1bHRzKCBkYXRhLmFyZ3MsIHRoaXMuZGVmYXVsdHMgKTtcblx0XHRcdHRoaXMucmVuZGVyKCk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogQ29tcGlsZXMgdGhlIHRlbXBsYXRlIGFuZCByZW5kZXJzIHRoZSB2aWV3XG5cdFx0ICogQHJldHVybiAgIHNlbGYgKGZvciBjaGFpbmluZylcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdHJlbmRlcjogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHRoaXMuJGVsLndlYnVpUG9wb3ZlciggdGhpcy5hcmdzICk7XG5cdFx0XHRyZXR1cm4gdGhpcztcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBIaWRlIHRoZSBwb3BvdmVyXG5cdFx0ICogQHJldHVybiAgIHNlbGYgKGZvciBjaGFpbmluZylcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMTJcblx0XHQgKi9cblx0XHRoaWRlOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0dGhpcy4kZWwud2VidWlQb3BvdmVyKCAnaGlkZScgKTtcblx0XHRcdHJldHVybiB0aGlzO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFNob3cgdGhlIHBvcG92ZXJcblx0XHQgKiBAcmV0dXJuICAgc2VsZiAoZm9yIGNoYWluaW5nKVxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4xMlxuXHRcdCAqL1xuXHRcdHNob3c6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHR0aGlzLiRlbC53ZWJ1aVBvcG92ZXIoICdzaG93JyApO1xuXHRcdFx0cmV0dXJuIHRoaXM7XG5cblx0XHR9LFxuXG5cdH0gKTtcblxufSApO1xuXG4vKipcbiAqIFBvc3QgUG9wb3ZlciBTZXJhY2ggY29udGVudCBWaWV3XG4gKiBAc2luY2UgICAgMy4xNi4wXG4gKiBAdmVyc2lvbiAgMy4xNy4wXG4gKi9cbmRlZmluZSggJ1ZpZXdzL1Bvc3RTZWFyY2gnLFtdLCBmdW5jdGlvbigpIHtcblxuXHRyZXR1cm4gQmFja2JvbmUuVmlldy5leHRlbmQoIHtcblxuXHRcdC8qKlxuXHRcdCAqIERPTSBFdmVudHNcblx0XHQgKiBAdHlwZSAgICAgb2JqXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRldmVudHM6IHtcblx0XHRcdCdzZWxlY3QyOnNlbGVjdCc6ICdhZGRfcG9zdCcsXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFdyYXBwZXIgVGFnIG5hbWVcblx0XHQgKiBAdHlwZSAge1N0cmluZ31cblx0XHQgKi9cblx0XHR0YWdOYW1lOiAnc2VsZWN0JyxcblxuXHRcdC8qKlxuXHRcdCAqIEluaXRpYWxpemVyXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIGRhdGEgIGN1c3RvbWl6ZSB0aGUgc2VhcmNoIGJveCB3aXRoIGRhdGFcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjEyXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMTJcblx0XHQgKi9cblx0XHRpbml0aWFsaXplOiBmdW5jdGlvbiggZGF0YSApIHtcblxuXHRcdFx0dGhpcy5wb3N0X3R5cGUgPSBkYXRhLnBvc3RfdHlwZTtcblx0XHRcdHRoaXMuc2VhcmNoaW5nX21lc3NhZ2UgPSBkYXRhLnNlYXJjaGluZ19tZXNzYWdlIHx8IExMTVMubDEwbi50cmFuc2xhdGUoICdTZWFyY2hpbmcuLi4nICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogU2VsZWN0IGV2ZW50LCBhZGRzIHRoZSBleGlzdGluZyBsZXNzb24gdG8gdGhlIGNvdXJzZVxuXHRcdCAqIEBwYXJhbSAgICBvYmogICBldmVudCAgc2VsZWN0MjpzZWxlY3QgZXZlbnQgb2JqZWN0XG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE3LjBcblx0XHQgKi9cblx0XHRhZGRfcG9zdDogZnVuY3Rpb24oIGV2ZW50ICkge1xuXG5cdFx0XHR2YXIgdHlwZSA9IHRoaXMuJGVsLmF0dHIoICdkYXRhLXBvc3QtdHlwZScgKTtcblxuXHRcdFx0QmFja2JvbmUucHViU3ViLnRyaWdnZXIoIHR5cGUucmVwbGFjZSggJ2xsbXNfJywgJycgKSArICctc2VhcmNoLXNlbGVjdCcsIGV2ZW50LnBhcmFtcy5kYXRhLCBldmVudCApO1xuXHRcdFx0dGhpcy4kZWwudmFsKCBudWxsICkudHJpZ2dlciggJ2NoYW5nZScgKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBSZW5kZXIgdGhlIHNlY3Rpb25cblx0XHQgKiBJbml0YWxpemVzIGEgbmV3IGNvbGxlY3Rpb24gYW5kIHZpZXdzIGZvciBhbGwgbGVzc29ucyBpbiB0aGUgc2VjdGlvblxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjEyXG5cdFx0ICovXG5cdFx0cmVuZGVyOiBmdW5jdGlvbigpIHtcblx0XHRcdHZhciBzZWxmID0gdGhpcztcblx0XHRcdHNldFRpbWVvdXQoIGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0c2VsZi4kZWwubGxtc1NlbGVjdDIoIHtcblx0XHRcdFx0XHRhamF4OiB7XG5cdFx0XHRcdFx0XHRkYXRhVHlwZTogJ0pTT04nLFxuXHRcdFx0XHRcdFx0ZGVsYXk6IDI1MCxcblx0XHRcdFx0XHRcdG1ldGhvZDogJ1BPU1QnLFxuXHRcdFx0XHRcdFx0dXJsOiB3aW5kb3cuYWpheHVybCxcblx0XHRcdFx0XHRcdGRhdGE6IGZ1bmN0aW9uKCBwYXJhbXMgKSB7XG5cdFx0XHRcdFx0XHRcdHJldHVybiB7XG5cdFx0XHRcdFx0XHRcdFx0YWN0aW9uOiAnbGxtc19idWlsZGVyJyxcblx0XHRcdFx0XHRcdFx0XHRhY3Rpb25fdHlwZTogJ3NlYXJjaCcsXG5cdFx0XHRcdFx0XHRcdFx0Y291cnNlX2lkOiB3aW5kb3cubGxtc19idWlsZGVyLmNvdXJzZS5pZCxcblx0XHRcdFx0XHRcdFx0XHRwb3N0X3R5cGU6IHNlbGYucG9zdF90eXBlLFxuXHRcdFx0XHRcdFx0XHRcdHRlcm06IHBhcmFtcy50ZXJtLFxuXHRcdFx0XHRcdFx0XHRcdHBhZ2U6IHBhcmFtcy5wYWdlLFxuXHRcdFx0XHRcdFx0XHRcdF9hamF4X25vbmNlOiB3cF9hamF4X2RhdGEubm9uY2UsXG5cdFx0XHRcdFx0XHRcdH07XG5cdFx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdFx0Ly8gZXJyb3I6IGZ1bmN0aW9uKCB4aHIsIHN0YXR1cywgZXJyb3IgKSB7XG5cdFx0XHRcdFx0XHQvLyBcdGNvbnNvbGUubG9nKCBzdGF0dXMsIGVycm9yICk7XG5cdFx0XHRcdFx0XHQvLyB9LFxuXHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0ZHJvcGRvd25QYXJlbnQ6ICQoICcud3JhcC5saWZ0ZXJsbXMubGxtcy1idWlsZGVyJyApLFxuXHRcdFx0XHRcdC8vIGRvbid0IGVzY2FwZSBodG1sIGZyb20gcmVuZGVyX3Jlc3VsdFxuXHRcdFx0XHRcdGVzY2FwZU1hcmt1cDogZnVuY3Rpb24oIG1hcmt1cCApIHtcblx0XHRcdFx0XHRcdHJldHVybiBtYXJrdXA7XG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRwbGFjZWhvbGRlcjogc2VsZi5zZWFyY2hpbmdfbWVzc2FnZSxcblx0XHRcdFx0XHR0ZW1wbGF0ZVJlc3VsdDogc2VsZi5yZW5kZXJfcmVzdWx0LFxuXHRcdFx0XHRcdHdpZHRoOiAnMTAwJScsXG5cdFx0XHRcdH0gKTtcblx0XHRcdFx0c2VsZi4kZWwuYXR0ciggJ2RhdGEtcG9zdC10eXBlJywgc2VsZi5wb3N0X3R5cGUgKTtcblx0XHRcdH0sIDAgKTtcblx0XHRcdHJldHVybiB0aGlzO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFJlbmRlciBhIG5pY2VyIFVJIGZvciBlYWNoIHNlYXJjaCByZXN1bHQgaW4gdGhlIGluIHRoZSBTZWxlY3QyIHNlYXJjaCByZXN1bHRzXG5cdFx0ICogQHBhcmFtICAgIG9iamVjdCAgIHJlcyAgcmVzdWx0IGRhdGFcblx0XHQgKiBAcmV0dXJuICAgc3RyaW5nXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjEyXG5cdFx0ICovXG5cdFx0cmVuZGVyX3Jlc3VsdDogZnVuY3Rpb24oIHJlcyApIHtcblxuXHRcdFx0dmFyICRodG1sID0gJCggJzxkaXYgY2xhc3M9XCJsbG1zLWV4aXN0aW5nLWxlc3Nvbi1yZXN1bHRcIiAvPicgKTtcblxuXHRcdFx0aWYgKCByZXMubG9hZGluZyApIHtcblx0XHRcdFx0cmV0dXJuICRodG1sLmFwcGVuZCggcmVzLnRleHQgKTtcblx0XHRcdH1cblxuXHRcdFx0dmFyICRzaWRlID0gJCggJzxhc2lkZSBjbGFzcz1cImxsbXMtZXhpc3RpbmctYWN0aW9uXCIgLz4nICksXG5cdFx0XHRcdCRtYWluID0gJCggJzxkaXYgY2xhc3M9XCJsbG1zLWV4aXN0aW5nLWluZm9cIiAvPicgKTtcblx0XHRcdFx0aWNvbiA9ICggJ2F0dGFjaCcgPT09IHJlcy5hY3Rpb24gKSA/ICdwYXBlcmNsaXAnIDogJ2Nsb25lJyxcblx0XHRcdFx0dGV4dCA9ICggJ2F0dGFjaCcgPT09IHJlcy5hY3Rpb24gKSA/IExMTVMubDEwbi50cmFuc2xhdGUoICdBdHRhY2gnICkgOiBMTE1TLmwxMG4udHJhbnNsYXRlKCAnQ2xvbmUnICk7XG5cblx0XHRcdCRzaWRlLmFwcGVuZCggJzxpIGNsYXNzPVwiZmEgZmEtJyArIGljb24gKyAnXCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPjxzbWFsbD4nICsgdGV4dCArICc8L3NtYWxsPicgKTtcblxuXHRcdFx0JG1haW4uYXBwZW5kKCAnPGg0PicgKyByZXMuZGF0YS50aXRsZSArICc8L2g0PicgKTtcblx0XHRcdCRtYWluLmFwcGVuZCggJzxoNT4nICsgTExNUy5sMTBuLnRyYW5zbGF0ZSggJ0lEJyApICsgJzogPGVtPicgKyByZXMuZGF0YS5pZCArICc8L2VtPjwvaDU+JyApO1xuXG5cdFx0XHRfLmVhY2goIHJlcy5wYXJlbnRzLCBmdW5jdGlvbiggcGFyZW50ICkge1xuXHRcdFx0XHQkbWFpbi5hcHBlbmQoICc8aDU+JyArIHBhcmVudCArICc8L2VtPjwvaDU+JyApO1xuXHRcdFx0fSApO1xuXG5cdFx0XHRyZXR1cm4gJGh0bWwuYXBwZW5kKCAkc2lkZSApLmFwcGVuZCggJG1haW4gKTtcblxuXHRcdH0sXG5cblx0fSApO1xuXG59ICk7XG5cbi8qKlxuICogU2luZ2xlIExlc3NvbiBWaWV3XG4gKiBAc2luY2UgICAgMy4xNi4wXG4gKiBAdmVyc2lvbiAgMy4xNi4wXG4gKi9cbmRlZmluZSggJ1ZpZXdzL1F1ZXN0aW9uVHlwZScsWyBdLCBmdW5jdGlvbigpIHtcblxuXHRyZXR1cm4gQmFja2JvbmUuVmlldy5leHRlbmQoIHtcblxuXHRcdC8qKlxuXHRcdCAqIEhUTUwgY2xhc3MgbmFtZXNcblx0XHQgKiBAdHlwZSAge1N0cmluZ31cblx0XHQgKi9cblx0XHRjbGFzc05hbWU6ICdsbG1zLXF1ZXN0aW9uLXR5cGUnLFxuXG5cdFx0ZXZlbnRzOiB7XG5cdFx0XHQnY2xpY2sgLmxsbXMtYWRkLXF1ZXN0aW9uJzogJ2FkZF9xdWVzdGlvbicsXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIEhUTUwgZWxlbWVudCB3cmFwcGVyIElEIGF0dHJpYnV0ZVxuXHRcdCAqIEByZXR1cm4gICBzdHJpbmdcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGlkOiBmdW5jdGlvbigpIHtcblx0XHRcdHJldHVybiAnbGxtcy1xdWVzdGlvbi10eXBlLScgKyB0aGlzLm1vZGVsLmlkO1xuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBXcmFwcGVyIFRhZyBuYW1lXG5cdFx0ICogQHR5cGUgIHtTdHJpbmd9XG5cdFx0ICovXG5cdFx0dGFnTmFtZTogJ2xpJyxcblxuXHRcdC8qKlxuXHRcdCAqIEdldCB0aGUgdW5kZXJzY29yZSB0ZW1wbGF0ZVxuXHRcdCAqIEB0eXBlICB7W3R5cGVdfVxuXHRcdCAqL1xuXHRcdHRlbXBsYXRlOiB3cC50ZW1wbGF0ZSggJ2xsbXMtcXVlc3Rpb24tdHlwZS10ZW1wbGF0ZScgKSxcblxuXHRcdC8qKlxuXHRcdCAqIEluaXRpYWxpemF0aW9uIGNhbGxiYWNrIGZ1bmMgKHJlbmRlcnMgdGhlIGVsZW1lbnQgb24gc2NyZWVuKVxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRpbml0aWFsaXplOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0dGhpcy5yZW5kZXIoKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBDb21waWxlcyB0aGUgdGVtcGxhdGUgYW5kIHJlbmRlcnMgdGhlIHZpZXdcblx0XHQgKiBAcmV0dXJuICAgc2VsZiAoZm9yIGNoYWluaW5nKVxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0cmVuZGVyOiBmdW5jdGlvbigpIHtcblx0XHRcdHRoaXMuJGVsLmh0bWwoIHRoaXMudGVtcGxhdGUoIHRoaXMubW9kZWwgKSApO1xuXHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIEFkZCBhIHF1ZXN0aW9uIG9mIHRoZSBzZWxlY3RlZCB0eXBlIHRvIHRoZSBjdXJyZW50IHF1aXpcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGFkZF9xdWVzdGlvbjogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHRoaXMucXVpei5hZGRfcXVlc3Rpb24oIHtcblx0XHRcdFx0X2V4cGFuZGVkOiB0cnVlLFxuXHRcdFx0XHRjaG9pY2VzOiB0aGlzLm1vZGVsLmdldCggJ2RlZmF1bHRfY2hvaWNlcycgKSA/IHRoaXMubW9kZWwuZ2V0KCAnZGVmYXVsdF9jaG9pY2VzJyApIDogbnVsbCxcblx0XHRcdFx0cXVlc3Rpb25fdHlwZTogdGhpcy5tb2RlbCxcblx0XHRcdH0gKTtcblxuXHRcdFx0dGhpcy5xdWl6LnRyaWdnZXIoICduZXctcXVlc3Rpb24tYWRkZWQnICk7XG5cblx0XHR9LFxuXG5cdFx0Ly8gZmlsdGVyOiBmdW5jdGlvbiggdGVybSApIHtcblxuXHRcdC8vIFx0dmFyIHdvcmRzID0gdGhpcy5tb2RlbC5nZXRfa2V5d29yZHMoKS5tYXAoIGZ1bmN0aW9uKCB3b3JkICkge1xuXHRcdC8vIFx0XHRyZXR1cm4gd29yZC50b0xvd2VyQ2FzZSgpO1xuXHRcdC8vIFx0fSApO1xuXG5cdFx0Ly8gXHR0ZXJtID0gdGVybS50b0xvd2VyQ2FzZSgpO1xuXG5cdFx0Ly8gXHRpZiAoIC0xID09PSB3b3Jkcy5pbmRleE9mKCB0ZXJtICkgKSB7XG5cdFx0Ly8gXHRcdHRoaXMuJGVsLmFkZENsYXNzKCAnZmlsdGVyZWQnICk7XG5cdFx0Ly8gXHR9IGVsc2Uge1xuXHRcdC8vIFx0XHR0aGlzLiRlbC5yZW1vdmVDbGFzcyggJ2ZpbHRlcmVkJyApO1xuXHRcdC8vIFx0fVxuXG5cdFx0Ly8gfSxcblxuXHRcdC8vIGNsZWFyX2ZpbHRlcjogZnVuY3Rpb24oKSB7XG5cdFx0Ly8gXHR0aGlzLiRlbC5yZW1vdmVDbGFzcyggJ2ZpbHRlcmVkJyApO1xuXHRcdC8vIH1cblxuXHR9ICk7XG5cbn0gKTtcblxuLyoqXG4gKiBRdWl6IHF1ZXN0aW9uIGJhbmsgdmlld1xuICogQHNpbmNlICAgIDMuMTYuMFxuICogQHZlcnNpb24gIDMuMTYuMFxuICovXG5kZWZpbmUoICdWaWV3cy9RdWVzdGlvbkJhbmsnLFsgJ1ZpZXdzL1F1ZXN0aW9uVHlwZScgXSwgZnVuY3Rpb24oIFF1ZXN0aW9uVmlldyApIHtcblxuXHRyZXR1cm4gQmFja2JvbmUuQ29sbGVjdGlvblZpZXcuZXh0ZW5kKCB7XG5cblx0XHRjbGFzc05hbWU6ICdsbG1zLXF1ZXN0aW9uJyxcblxuXHRcdC8qKlxuXHRcdCAqIFBhcmVudCBlbGVtZW50XG5cdFx0ICogQHR5cGUgIHtTdHJpbmd9XG5cdFx0ICovXG5cdFx0ZWw6ICcjbGxtcy1xdWVzdGlvbi1iYW5rJyxcblxuXHRcdC8qKlxuXHRcdCAqIFNlY3Rpb24gbW9kZWxcblx0XHQgKiBAdHlwZSAge1t0eXBlXX1cblx0XHQgKi9cblx0XHRtb2RlbFZpZXc6IFF1ZXN0aW9uVmlldyxcblxuXHRcdC8qKlxuXHRcdCAqIEFyZSBzZWN0aW9ucyBzZWxlY3RhYmxlP1xuXHRcdCAqIEB0eXBlICB7Qm9vbH1cblx0XHQgKi9cblx0XHRzZWxlY3RhYmxlOiBmYWxzZSxcblxuXHRcdC8qKlxuXHRcdCAqIEFyZSBzZWN0aW9ucyBzb3J0YWJsZT9cblx0XHQgKiBAdHlwZSAge0Jvb2x9XG5cdFx0ICovXG5cdFx0c29ydGFibGU6IGZhbHNlLFxuXG5cdH0gKTtcblxufSApO1xuXG4vKipcbiAqIFNpbmdsZSBRdWVzdGlvbiBDaG9pY2UgVmlld1xuICogQHNpbmNlICAgIDMuMTYuMFxuICogQHZlcnNpb24gIDMuMTYuMFxuICovXG5kZWZpbmUoICdWaWV3cy9RdWVzdGlvbkNob2ljZScsWyAnVmlld3MvX0VkaXRhYmxlJywgXSwgZnVuY3Rpb24oIEVkaXRhYmxlICkge1xuXG5cdHJldHVybiBCYWNrYm9uZS5WaWV3LmV4dGVuZCggXy5kZWZhdWx0cygge1xuXG5cdFx0LyoqXG5cdFx0ICogSFRNTCBjbGFzcyBuYW1lc1xuXHRcdCAqIEB0eXBlICB7U3RyaW5nfVxuXHRcdCAqL1xuXHRcdGNsYXNzTmFtZTogJ2xsbXMtcXVlc3Rpb24tY2hvaWNlJyxcblxuXHRcdGV2ZW50czogXy5kZWZhdWx0cygge1xuXHRcdFx0J2NoYW5nZSBpbnB1dFtuYW1lPVwiY29ycmVjdFwiXSc6ICd0b2dnbGVfY29ycmVjdCcsXG5cdFx0XHQnY2xpY2sgLmxsbXMtYWN0aW9uLWljb25baHJlZj1cIiNsbG1zLWFkZC1jaG9pY2VcIl0nOiAnYWRkX2Nob2ljZScsXG5cdFx0XHQnY2xpY2sgLmxsbXMtYWN0aW9uLWljb25baHJlZj1cIiNsbG1zLWRlbC1jaG9pY2VcIl0nOiAnZGVsX2Nob2ljZScsXG5cdFx0fSwgRWRpdGFibGUuZXZlbnRzICksXG5cblx0XHQvKipcblx0XHQgKiBIVE1MIGVsZW1lbnQgd3JhcHBlciBJRCBhdHRyaWJ1dGVcblx0XHQgKiBAcmV0dXJuICAgc3RyaW5nXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRpZDogZnVuY3Rpb24oKSB7XG5cdFx0XHRyZXR1cm4gJ2xsbXMtcXVlc3Rpb24tY2hvaWNlLScgKyB0aGlzLm1vZGVsLmlkO1xuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBXcmFwcGVyIFRhZyBuYW1lXG5cdFx0ICogQHR5cGUgIHtTdHJpbmd9XG5cdFx0ICovXG5cdFx0dGFnTmFtZTogJ2xpJyxcblxuXHRcdC8qKlxuXHRcdCAqIEdldCB0aGUgdW5kZXJzY29yZSB0ZW1wbGF0ZVxuXHRcdCAqIEB0eXBlICB7W3R5cGVdfVxuXHRcdCAqL1xuXHRcdHRlbXBsYXRlOiB3cC50ZW1wbGF0ZSggJ2xsbXMtcXVlc3Rpb24tY2hvaWNlLXRlbXBsYXRlJyApLFxuXG5cdFx0LyoqXG5cdFx0ICogSW5pdGlhbGl6YXRpb24gY2FsbGJhY2sgZnVuYyAocmVuZGVycyB0aGUgZWxlbWVudCBvbiBzY3JlZW4pXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNC4xXG5cdFx0ICogQHZlcnNpb24gIDMuMTQuMVxuXHRcdCAqL1xuXHRcdGluaXRpYWxpemU6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHR0aGlzLnJlbmRlcigpO1xuXG5cdFx0XHR0aGlzLmxpc3RlblRvKCB0aGlzLm1vZGVsLmNvbGxlY3Rpb24sICdhZGQnLCB0aGlzLm1heWJlX2Rpc2FibGVfYnV0dG9ucyApO1xuXHRcdFx0dGhpcy5saXN0ZW5UbyggdGhpcy5tb2RlbCwgJ2NoYW5nZScsIHRoaXMucmVuZGVyICk7XG5cblx0XHRcdGlmICggJ2ltYWdlJyA9PT0gdGhpcy5tb2RlbC5nZXQoICdjaG9pY2VfdHlwZScgKSApIHtcblx0XHRcdFx0dGhpcy5saXN0ZW5UbyggdGhpcy5tb2RlbC5nZXQoICdjaG9pY2UnICksICdjaGFuZ2UnLCB0aGlzLnJlbmRlciApO1xuXHRcdFx0fVxuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIENvbXBpbGVzIHRoZSB0ZW1wbGF0ZSBhbmQgcmVuZGVycyB0aGUgdmlld1xuXHRcdCAqIEByZXR1cm4gICBzZWxmIChmb3IgY2hhaW5pbmcpXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRyZW5kZXI6IGZ1bmN0aW9uKCkge1xuXHRcdFx0dGhpcy4kZWwuaHRtbCggdGhpcy50ZW1wbGF0ZSggdGhpcy5tb2RlbCApICk7XG5cdFx0XHRyZXR1cm4gdGhpcztcblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogQWRkIGEgbmV3IGNob2ljZSB0byB0aGUgY3VycmVudCBjaG9pY2UgbGlzdFxuXHRcdCAqIEFkZHMgKmFmdGVyKiB0aGUgY2xpY2tlZCBjaG9pY2Vcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgZXZlbnQgIEpTIGV2ZW50IG9iamVjdFxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRhZGRfY2hvaWNlOiBmdW5jdGlvbiggZXZlbnQgKSB7XG5cblx0XHRcdGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuXHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuXHRcdFx0dmFyIGluZGV4ID0gdGhpcy5tb2RlbC5jb2xsZWN0aW9uLmluZGV4T2YoIHRoaXMubW9kZWwgKTtcblx0XHRcdHRoaXMubW9kZWwuY29sbGVjdGlvbi5wYXJlbnQuYWRkX2Nob2ljZSgge30sIHtcblx0XHRcdFx0YXQ6IGluZGV4ICsgMSxcblx0XHRcdH0gKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBEZWxldGUgdGhlIGNob2ljZSBmcm9tIHRoZSBjaG9pY2UgbGlzdCAmIGVuc3VyZSB0aGVyZSdzIGF0IGxlYXN0IG9uZSBjb3JyZWN0IGNob2ljZVxuXHRcdCAqIEBwYXJhbSAgICBvYmogICBldmVudCAganMgZXZlbnQgb2JqXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGRlbF9jaG9pY2U6IGZ1bmN0aW9uKCBldmVudCApIHtcblxuXHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdEJhY2tib25lLnB1YlN1Yi50cmlnZ2VyKCAnbW9kZWwtdHJhc2hlZCcsIHRoaXMubW9kZWwgKTtcblx0XHRcdHRoaXMubW9kZWwuY29sbGVjdGlvbi5yZW1vdmUoIHRoaXMubW9kZWwgKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBXaGVuIHRoZSBjb3JyZWN0IGFuc3dlciBpbnB1dCBjaGFuZ2VzIHN5bmMgc3RhdHVzIHRvIG1vZGVsXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdHRvZ2dsZV9jb3JyZWN0OiBmdW5jdGlvbigpIHtcblxuXHRcdFx0dmFyIGNvcnJlY3QgPSB0aGlzLiRlbC5maW5kKCAnaW5wdXRbbmFtZT1cImNvcnJlY3RcIl0nICkuaXMoICc6Y2hlY2tlZCcgKTtcblx0XHRcdHRoaXMubW9kZWwuc2V0KCAnY29ycmVjdCcsIGNvcnJlY3QgKTtcblx0XHRcdHRoaXMubW9kZWwuY29sbGVjdGlvbi50cmlnZ2VyKCAnY29ycmVjdC11cGRhdGUnLCB0aGlzLm1vZGVsICk7XG5cblx0XHR9LFxuXG5cdH0sIEVkaXRhYmxlICkgKTtcblxufSApO1xuXG4vKipcbiAqIFF1aXogcXVlc3Rpb24gYmFuayB2aWV3XG4gKiBAc2luY2UgICAgMy4xNi4wXG4gKiBAdmVyc2lvbiAgMy4xNi4wXG4gKi9cbmRlZmluZSggJ1ZpZXdzL1F1ZXN0aW9uQ2hvaWNlTGlzdCcsWyAnVmlld3MvUXVlc3Rpb25DaG9pY2UnIF0sIGZ1bmN0aW9uKCBDaG9pY2VWaWV3ICkge1xuXG5cdHJldHVybiBCYWNrYm9uZS5Db2xsZWN0aW9uVmlldy5leHRlbmQoIHtcblxuXHRcdGNsYXNzTmFtZTogJ2xsbXMtcXVpei1xdWVzdGlvbnMnLFxuXG5cdFx0LyoqXG5cdFx0ICogQ2hvaWNlIG1vZGVsIHZpZXdcblx0XHQgKiBAdHlwZSAge1t0eXBlXX1cblx0XHQgKi9cblx0XHRtb2RlbFZpZXc6IENob2ljZVZpZXcsXG5cblx0XHQvKipcblx0XHQgKiBFbmFibGUga2V5Ym9hcmQgZXZlbnRzXG5cdFx0ICogQHR5cGUgIHtCb29sfVxuXHRcdCAqL1xuXHRcdHByb2Nlc3NLZXlFdmVudHM6IGZhbHNlLFxuXG5cdFx0LyoqXG5cdFx0ICogQXJlIHNlY3Rpb25zIHNlbGVjdGFibGU/XG5cdFx0ICogQHR5cGUgIHtCb29sfVxuXHRcdCAqL1xuXHRcdHNlbGVjdGFibGU6IGZhbHNlLFxuXG5cdFx0LyoqXG5cdFx0ICogQXJlIHNlY3Rpb25zIHNvcnRhYmxlP1xuXHRcdCAqIEB0eXBlICB7Qm9vbH1cblx0XHQgKi9cblx0XHRzb3J0YWJsZTogdHJ1ZSxcblxuXHRcdHNvcnRhYmxlT3B0aW9uczoge1xuXHRcdFx0YXhpczogZmFsc2UsXG5cdFx0XHQvLyBjb25uZWN0V2l0aDogJy5sbG1zLWxlc3NvbnMnLFxuXHRcdFx0Y3Vyc29yOiAnbW92ZScsXG5cdFx0XHRoYW5kbGU6ICcubGxtcy1jaG9pY2UtaWQnLFxuXHRcdFx0aXRlbXM6ICcubGxtcy1xdWVzdGlvbi1jaG9pY2UnLFxuXHRcdFx0cGxhY2Vob2xkZXI6ICdsbG1zLXF1ZXN0aW9uLWNob2ljZSBsbG1zLXNvcnRhYmxlLXBsYWNlaG9sZGVyJyxcblx0XHR9LFxuXG5cdFx0c29ydGFibGVfc3RhcnQ6IGZ1bmN0aW9uKCBtb2RlbCApIHtcblx0XHRcdHRoaXMuJGVsLmFkZENsYXNzKCAnZHJhZ2dpbmcnICk7XG5cdFx0fSxcblxuXHRcdHNvcnRhYmxlX3N0b3A6IGZ1bmN0aW9uKCBtb2RlbCApIHtcblx0XHRcdHRoaXMuJGVsLnJlbW92ZUNsYXNzKCAnZHJhZ2dpbmcnICk7XG5cdFx0fSxcblxuXHR9ICk7XG5cbn0gKTtcblxuLyoqXG4gKiBTaW5nbGUgUXVlc3Rpb24gVmlld1xuICogQHNpbmNlICAgIDMuMTYuMFxuICogQHZlcnNpb24gIDMuMTYuMFxuICovXG5kZWZpbmUoICdWaWV3cy9RdWVzdGlvbicsW1xuXHRcdCdWaWV3cy9fRWRpdGFibGUnLFxuXHRcdCdWaWV3cy9RdWVzdGlvbkNob2ljZUxpc3QnXG5cdF0sIGZ1bmN0aW9uKFxuXHRcdEVkaXRhYmxlLFxuXHRcdENob2ljZUxpc3RWaWV3XG5cdCkge1xuXG5cdHJldHVybiBCYWNrYm9uZS5WaWV3LmV4dGVuZCggXy5kZWZhdWx0cygge1xuXG5cdFx0LyoqXG5cdFx0ICogR2VuZXJhdGUgQ1NTIGNsYXNzZXMgZm9yIHRoZSBxdWVzdGlvblxuXHRcdCAqIEByZXR1cm4gICBzdHJpbmdcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGNsYXNzTmFtZTogZnVuY3Rpb24oKSB7XG5cdFx0XHRyZXR1cm4gJ2xsbXMtcXVlc3Rpb24gcXR5cGUtLScgKyB0aGlzLm1vZGVsLmdldCggJ3F1ZXN0aW9uX3R5cGUnICkuZ2V0KCAnaWQnICk7XG5cdFx0fSxcblxuXHRcdGV2ZW50czogXy5kZWZhdWx0cygge1xuXHRcdFx0J2NsaWNrIC5jbG9uZS0tcXVlc3Rpb24nOiAnY2xvbmUnLFxuXHRcdFx0J2NsaWNrIC5kZWxldGUtLXF1ZXN0aW9uJzogJ2RlbGV0ZScsXG5cdFx0XHQnY2xpY2sgLmV4cGFuZC0tcXVlc3Rpb24nOiAnZXhwYW5kJyxcblx0XHRcdCdjbGljayAuY29sbGFwc2UtLXF1ZXN0aW9uJzogJ2NvbGxhcHNlJyxcblx0XHRcdCdjaGFuZ2UgaW5wdXRbbmFtZT1cInF1ZXN0aW9uX3BvaW50c1wiXSc6ICd1cGRhdGVfcG9pbnRzJyxcblx0XHR9LCBFZGl0YWJsZS5ldmVudHMgKSxcblxuXHRcdC8qKlxuXHRcdCAqIEhUTUwgZWxlbWVudCB3cmFwcGVyIElEIGF0dHJpYnV0ZVxuXHRcdCAqIEByZXR1cm4gICBzdHJpbmdcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGlkOiBmdW5jdGlvbigpIHtcblx0XHRcdHJldHVybiAnbGxtcy1xdWVzdGlvbi0nICsgdGhpcy5tb2RlbC5pZDtcblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogV3JhcHBlciBUYWcgbmFtZVxuXHRcdCAqIEB0eXBlICB7U3RyaW5nfVxuXHRcdCAqL1xuXHRcdHRhZ05hbWU6ICdsaScsXG5cblx0XHQvKipcblx0XHQgKiBHZXQgdGhlIHVuZGVyc2NvcmUgdGVtcGxhdGVcblx0XHQgKiBAdHlwZSAge1t0eXBlXX1cblx0XHQgKi9cblx0XHR0ZW1wbGF0ZTogd3AudGVtcGxhdGUoICdsbG1zLXF1ZXN0aW9uLXRlbXBsYXRlJyApLFxuXG5cdFx0LyoqXG5cdFx0ICogSW5pdGlhbGl6YXRpb24gY2FsbGJhY2sgZnVuYyAocmVuZGVycyB0aGUgZWxlbWVudCBvbiBzY3JlZW4pXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGluaXRpYWxpemU6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHR2YXIgY2hhbmdlX2V2ZW50cyA9IFtcblx0XHRcdFx0J2NoYW5nZTpfZXhwYW5kZWQnLFxuXHRcdFx0XHQnY2hhbmdlOm1lbnVfb3JkZXInLFxuXHRcdFx0XTtcblx0XHRcdF8uZWFjaCggY2hhbmdlX2V2ZW50cywgZnVuY3Rpb24oIGV2ZW50ICkge1xuXHRcdFx0XHR0aGlzLmxpc3RlblRvKCB0aGlzLm1vZGVsLCBldmVudCwgdGhpcy5yZW5kZXIgKTtcblx0XHRcdH0sIHRoaXMgKTtcblxuXHRcdFx0dGhpcy5saXN0ZW5UbyggdGhpcy5tb2RlbC5nZXQoICdpbWFnZScgKSwgJ2NoYW5nZScsIHRoaXMucmVuZGVyICk7XG5cblx0XHRcdHRoaXMubGlzdGVuVG8oIHRoaXMubW9kZWwuZ2V0X3BhcmVudCgpLCAnY2hhbmdlOl9wb2ludHMnLCB0aGlzLnJlbmRlcl9wb2ludHNfcGVyY2VudGFnZSApO1xuXG5cdFx0XHR0aGlzLm9uKCAnbXVsdGlfY2hvaWNlc190b2dnbGUnLCB0aGlzLm11bHRpX2Nob2ljZXNfdG9nZ2xlLCB0aGlzICk7XG5cblx0XHRcdEJhY2tib25lLnB1YlN1Yi5vbiggJ2RlbC1xdWVzdGlvbi1jaG9pY2UnLCB0aGlzLmRlbF9jaG9pY2UsIHRoaXMgKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBDb21waWxlcyB0aGUgdGVtcGxhdGUgYW5kIHJlbmRlcnMgdGhlIHZpZXdcblx0XHQgKiBAcmV0dXJuICAgc2VsZiAoZm9yIGNoYWluaW5nKVxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0cmVuZGVyOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0dGhpcy4kZWwuaHRtbCggdGhpcy50ZW1wbGF0ZSggdGhpcy5tb2RlbCApICk7XG5cblx0XHRcdGlmICggdGhpcy5tb2RlbC5nZXQoICdxdWVzdGlvbl90eXBlJykuZ2V0KCAnY2hvaWNlcycgKSApIHtcblxuXHRcdFx0XHR0aGlzLmNob2ljZUxpc3RWaWV3ID0gbmV3IENob2ljZUxpc3RWaWV3KCB7XG5cdFx0XHRcdFx0ZWw6IHRoaXMuJGVsLmZpbmQoICcubGxtcy1xdWVzdGlvbi1jaG9pY2VzJyApLFxuXHRcdFx0XHRcdGNvbGxlY3Rpb246IHRoaXMubW9kZWwuZ2V0KCAnY2hvaWNlcycgKSxcblx0XHRcdFx0fSApO1xuXHRcdFx0XHR0aGlzLmNob2ljZUxpc3RWaWV3LnJlbmRlcigpO1xuXHRcdFx0XHR0aGlzLmNob2ljZUxpc3RWaWV3Lm9uKCAnc29ydFN0YXJ0JywgdGhpcy5jaG9pY2VMaXN0Vmlldy5zb3J0YWJsZV9zdGFydCApO1xuXHRcdFx0XHR0aGlzLmNob2ljZUxpc3RWaWV3Lm9uKCAnc29ydFN0b3AnLCB0aGlzLmNob2ljZUxpc3RWaWV3LnNvcnRhYmxlX3N0b3AgKTtcblxuXHRcdFx0fVxuXG5cdFx0XHRpZiAoICdncm91cCcgPT09IHRoaXMubW9kZWwuZ2V0KCAncXVlc3Rpb25fdHlwZScgKS5nZXQoICdpZCcgKSApIHtcblxuXHRcdFx0XHR2YXIgc2VsZiA9IHRoaXM7XG5cdFx0XHRcdHNldFRpbWVvdXQoIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdHNlbGYucXVlc3Rpb25MaXN0VmlldyA9IHNlbGYuY29sbGVjdGlvbkxpc3RWaWV3LnF1aXouZ2V0X3F1ZXN0aW9uX2xpc3QoIHtcblx0XHRcdFx0XHRcdGVsOiBzZWxmLiRlbC5maW5kKCAnLmxsbXMtcXVpei1xdWVzdGlvbnMnICksXG5cdFx0XHRcdFx0XHRjb2xsZWN0aW9uOiBzZWxmLm1vZGVsLmdldCggJ3F1ZXN0aW9ucycgKSxcblx0XHRcdFx0XHR9ICk7XG5cdFx0XHRcdFx0c2VsZi5xdWVzdGlvbkxpc3RWaWV3LnJlbmRlcigpO1xuXHRcdFx0XHRcdHNlbGYucXVlc3Rpb25MaXN0Vmlldy5vbiggJ3NvcnRTdGFydCcsIHNlbGYucXVlc3Rpb25MaXN0Vmlldy5zb3J0YWJsZV9zdGFydCApO1xuXHRcdFx0XHRcdHNlbGYucXVlc3Rpb25MaXN0Vmlldy5vbiggJ3NvcnRTdG9wJywgc2VsZi5xdWVzdGlvbkxpc3RWaWV3LnNvcnRhYmxlX3N0b3AgKTtcblx0XHRcdFx0fSwgMSApO1xuXG5cdFx0XHR9XG5cblx0XHRcdGlmICggdGhpcy5tb2RlbC5nZXQoICdkZXNjcmlwdGlvbl9lbmFibGVkJyApICkge1xuXHRcdFx0XHR0aGlzLmluaXRfZWRpdG9yKCAncXVlc3Rpb24tZGVzYy0tJyArIHRoaXMubW9kZWwuZ2V0KCAnaWQnICkgKTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKCB0aGlzLm1vZGVsLmdldCggJ2NsYXJpZmljYXRpb25zX2VuYWJsZWQnICkgKSB7XG5cdFx0XHRcdHRoaXMuaW5pdF9lZGl0b3IoICdxdWVzdGlvbi1jbGFyaWZpY2F0aW9ucy0tJyArIHRoaXMubW9kZWwuZ2V0KCAnaWQnICksIHtcblx0XHRcdFx0XHRtZWRpYUJ1dHRvbnM6IGZhbHNlLFxuXHRcdFx0XHRcdHRpbnltY2U6IHtcblx0XHRcdFx0XHRcdHRvb2xiYXIxOiAnYm9sZCxpdGFsaWMsc3RyaWtldGhyb3VnaCxidWxsaXN0LG51bWxpc3QsYWxpZ25sZWZ0LGFsaWduY2VudGVyLGFsaWducmlnaHQnLFxuXHRcdFx0XHRcdFx0dG9vbGJhcjI6ICcnLFxuXHRcdFx0XHRcdFx0c2V0dXA6IF8uYmluZCggdGhpcy5vbl9lZGl0b3JfcmVhZHksIHRoaXMgKSxcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0gKTtcblx0XHRcdH1cblxuXHRcdFx0dGhpcy5pbml0X2Zvcm1hdHRpbmdfZWxzKCk7XG5cdFx0XHR0aGlzLmluaXRfc2VsZWN0cygpO1xuXG5cdFx0XHRyZXR1cm4gdGhpcztcblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogcmVyZW5kZXIgcG9pbnRzIHBlcmNlbnRhZ2Ugd2hlbiBxdWVzdGlvbiBwb2ludHMgYXJlIHVwZGF0ZWRcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0cmVuZGVyX3BvaW50c19wZXJjZW50YWdlOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0dGhpcy4kZWwuZmluZCggJy5sbG1zLXF1ZXN0aW9uLXBvaW50cycgKS5hdHRyKCAnZGF0YS10aXAnLCB0aGlzLm1vZGVsLmdldF9wb2ludHNfcGVyY2VudGFnZSgpICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogQ2xpY2sgZXZlbnQgdG8gZHVwbGljYXRlIGEgcXVlc3Rpb24gd2l0aGluIGEgcXVpelxuXHRcdCAqIEBwYXJhbSAgICBvYmogICBldmVudCAganMgZXZlbnQgb2JqZWN0XG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGNsb25lOiBmdW5jdGlvbiggZXZlbnQgKSB7XG5cblx0XHRcdGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuXHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdHRoaXMubW9kZWwuY29sbGVjdGlvbi5hZGQoIHRoaXMuX2dldF9xdWVzdGlvbl9jbG9uZSggdGhpcy5tb2RlbCApICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogUmVjdXJzaXZlIGNsb25lIGZ1bmN0aW9uIHdoaWNoIHdpbGwgY29ycmVjdGx5IGNsb25lIGNoaWxkcmVuIG9mIGEgcXVlc3Rpb25cblx0XHQgKiBAcGFyYW0gICAgb2JqICAgcXVlc3Rpb24gIHF1ZXN0b24gbW9kZWxcblx0XHQgKiBAcmV0dXJuICAgb2JqXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRfZ2V0X3F1ZXN0aW9uX2Nsb25lOiBmdW5jdGlvbiggcXVlc3Rpb24gKSB7XG5cblx0XHRcdC8vIGNyZWF0ZSBhIGR1cGxpY2F0ZVxuXHRcdFx0dmFyIGNsb25lID0gXy5jbG9uZSggcXVlc3Rpb24uYXR0cmlidXRlcyApO1xuXG5cdFx0XHQvLyByZW1vdmUgaWQgKHdlIHdhbnQgdGhlIGR1cGxpY2F0ZSB0byBoYXZlIGEgdGVtcCBpZClcblx0XHRcdGRlbGV0ZSBjbG9uZS5pZDtcblxuXHRcdFx0Y2xvbmUucGFyZW50X2lkID0gcXVlc3Rpb24uZ2V0KCAnaWQnICk7XG5cblx0XHRcdC8vIHNldCB0aGUgcXVlc3Rpb24gdHlwZSBJRFxuXHRcdFx0Y2xvbmUucXVlc3Rpb25fdHlwZSA9IHF1ZXN0aW9uLmdldCggJ3F1ZXN0aW9uX3R5cGUnICkuZ2V0KCAnaWQnICk7XG5cblx0XHRcdC8vIGNsb25lIHRoZSBpbWFnZSBhdHRyaWJ1dGVzIHNlcGVyYXRlbHlcblx0XHRcdGNsb25lLmltYWdlID0gXy5jbG9uZSggcXVlc3Rpb24uZ2V0KCAnaW1hZ2UnICkuYXR0cmlidXRlcyApO1xuXG5cdFx0XHQvLyBpZiBpdCBoYXMgY2hvaWNlcyBjbG9uZSBhbGwgdGhlIGNob2ljZXNcblx0XHRcdGlmICggcXVlc3Rpb24uZ2V0KCAnY2hvaWNlcycgKSApIHtcblxuXHRcdFx0XHRjbG9uZS5jaG9pY2VzID0gW107XG5cblx0XHRcdFx0cXVlc3Rpb24uZ2V0KCAnY2hvaWNlcycgKS5lYWNoKCBmdW5jdGlvbiAoIGNob2ljZSApIHtcblxuXHRcdFx0XHRcdHZhciBjaG9pY2VfY2xvbmUgPSBfLmNsb25lKCBjaG9pY2UuYXR0cmlidXRlcyApO1xuXHRcdFx0XHRcdGRlbGV0ZSBjaG9pY2VfY2xvbmUuaWQ7XG5cdFx0XHRcdFx0ZGVsZXRlIGNob2ljZV9jbG9uZS5xdWVzdGlvbl9pZDtcblxuXHRcdFx0XHRcdGNsb25lLmNob2ljZXMucHVzaCggY2hvaWNlX2Nsb25lICk7XG5cblx0XHRcdFx0fSApO1xuXG5cdFx0XHR9XG5cblx0XHRcdGlmICggJ2dyb3VwJyA9PT0gcXVlc3Rpb24uZ2V0KCAncXVlc3Rpb25fdHlwZScgKS5nZXQoICdpZCcgKSApIHtcblxuXHRcdFx0XHRjbG9uZS5xdWVzdGlvbnMgPSBbXTtcblx0XHRcdFx0cXVlc3Rpb24uZ2V0KCAncXVlc3Rpb25zJyApLmVhY2goIGZ1bmN0aW9uKCBjaGlsZCApIHtcblx0XHRcdFx0XHRjbG9uZS5xdWVzdGlvbnMucHVzaCggdGhpcy5fZ2V0X3F1ZXN0aW9uX2Nsb25lKCBjaGlsZCApICk7XG5cdFx0XHRcdH0sIHRoaXMgKTtcblxuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gY2xvbmU7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogQ29sbGFwc2UgYSBxdWVzdGlvbiBhbmQgaGlkZSBpdCdzIHNldHRpbmdzXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGNvbGxhcHNlOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0dGhpcy5tb2RlbC5zZXQoICdfZXhwYW5kZWQnLCBmYWxzZSApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIERlbGV0ZSB0aGUgcXVlc3Rpb24gZnJvbSBhIHF1aXogLyBxdWVzdGlvbiBncm91cFxuXHRcdCAqIEBwYXJhbSAgICBvYmogICBldmVudCAganMgZXZlbnQgb2JqZWN0XG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGRlbGV0ZTogZnVuY3Rpb24oIGV2ZW50ICkge1xuXG5cdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG5cdFx0XHRpZiAoIHdpbmRvdy5jb25maXJtKCBMTE1TLmwxMG4udHJhbnNsYXRlKCAnQXJlIHlvdSBzdXJlIHlvdSB3YW50IHRvIGRlbGV0ZSB0aGlzIHF1ZXN0aW9uPycgKSApICkge1xuXG5cdFx0XHRcdHRoaXMubW9kZWwuY29sbGVjdGlvbi5yZW1vdmUoIHRoaXMubW9kZWwgKTtcblx0XHRcdFx0QmFja2JvbmUucHViU3ViLnRyaWdnZXIoICdtb2RlbC10cmFzaGVkJywgdGhpcy5tb2RlbCApO1xuXG5cdFx0XHR9XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogQ2xpY2sgZXZlbnQgdG8gcmV2ZWFsIGEgcXVlc3Rpb24ncyBzZXR0aW5ncyAmIGNob2ljZXNcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0ZXhwYW5kOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0dGhpcy5tb2RlbC5zZXQoICdfZXhwYW5kZWQnLCB0cnVlICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogV2hlbiB0b2dnbGluZyBtdWx0aXBsZSBjb3JyZWN0IGFuc3dlcnMgKm9mZiogcmVtb3ZlIGFsbCBjb3JyZWN0IGNob2ljZXMgZXhjZXB0IHRoZSBmaXJzdCBjb3JyZWN0IGNob2ljZSBpbiB0aGUgbGlzdFxuXHRcdCAqIEBwYXJhbSAgICBzdHJpbmcgICB2YWwgIHZhbHVlIG9mIHRoZSBxdWVzdGlvbidzIGBtdWx0aV9jaG9pY2VgIGF0dHIgW3llc3xub11cblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0bXVsdGlfY2hvaWNlc190b2dnbGU6IGZ1bmN0aW9uKCB2YWwgKSB7XG5cblx0XHRcdGlmICggJ3llcycgPT09IHZhbCApIHtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXG5cdFx0XHR0aGlzLm1vZGVsLmdldCggJ2Nob2ljZXMnICkudXBkYXRlX2NvcnJlY3QoIF8uZmlyc3QoIHRoaXMubW9kZWwuZ2V0KCAnY2hvaWNlcycgKS5nZXRfY29ycmVjdCgpICkgKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBVcGRhdGUgdGhlIG1vZGVsJ3MgcG9pbnRzIHdoZW4gdGhlIHZhbHVlIG9mIHRoZSBwb2ludHMgaW5wdXQgaXMgdXBkYXRlZFxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHR1cGRhdGVfcG9pbnRzOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0dGhpcy5tb2RlbC5zZXQoICdwb2ludHMnLCB0aGlzLiRlbC5maW5kKCAnaW5wdXRbbmFtZT1cInF1ZXN0aW9uX3BvaW50c1wiXScgKS52YWwoKSAqIDEgKTtcblxuXHRcdH1cblxuXHR9LCBFZGl0YWJsZSApICk7XG5cbn0gKTtcblxuLyoqXG4gKiBRdWl6IHF1ZXN0aW9uIGJhbmsgdmlld1xuICogQHNpbmNlICAgIDMuMTYuMFxuICogQHZlcnNpb24gIDMuMTYuMFxuICovXG5kZWZpbmUoICdWaWV3cy9RdWVzdGlvbkxpc3QnLFsgJ1ZpZXdzL1F1ZXN0aW9uJyBdLCBmdW5jdGlvbiggUXVlc3Rpb25WaWV3ICkge1xuXG5cdHJldHVybiBCYWNrYm9uZS5Db2xsZWN0aW9uVmlldy5leHRlbmQoIHtcblxuXHRcdGNsYXNzTmFtZTogJ2xsbXMtcXVpei1xdWVzdGlvbnMnLFxuXG5cdFx0LyoqXG5cdFx0ICogUGFyZW50IGVsZW1lbnRcblx0XHQgKiBAdHlwZSAge1N0cmluZ31cblx0XHQgKi9cblx0XHQvLyBlbDogJyNsbG1zLXF1aXotcXVlc3Rpb25zJyxcblxuXHRcdC8qKlxuXHRcdCAqIFNlY3Rpb24gbW9kZWxcblx0XHQgKiBAdHlwZSAge1t0eXBlXX1cblx0XHQgKi9cblx0XHRtb2RlbFZpZXc6IFF1ZXN0aW9uVmlldyxcblxuXHRcdC8qKlxuXHRcdCAqIEVuYWJsZSBrZXlib2FyZCBldmVudHNcblx0XHQgKiBAdHlwZSAge0Jvb2x9XG5cdFx0ICovXG5cdFx0cHJvY2Vzc0tleUV2ZW50czogZmFsc2UsXG5cblx0XHQvKipcblx0XHQgKiBBcmUgc2VjdGlvbnMgc2VsZWN0YWJsZT9cblx0XHQgKiBAdHlwZSAge0Jvb2x9XG5cdFx0ICovXG5cdFx0c2VsZWN0YWJsZTogZmFsc2UsXG5cblx0XHQvKipcblx0XHQgKiBBcmUgc2VjdGlvbnMgc29ydGFibGU/XG5cdFx0ICogQHR5cGUgIHtCb29sfVxuXHRcdCAqL1xuXHRcdHNvcnRhYmxlOiB0cnVlLFxuXG5cdFx0c29ydGFibGVPcHRpb25zOiB7XG5cdFx0XHRheGlzOiBmYWxzZSxcblx0XHRcdGNvbm5lY3RXaXRoOiAnLmxsbXMtcXVpei1xdWVzdGlvbnMnLFxuXHRcdFx0Y3Vyc29yOiAnbW92ZScsXG5cdFx0XHRoYW5kbGU6ICcubGxtcy1kYXRhLXN0YW1wJyxcblx0XHRcdGl0ZW1zOiAnLmxsbXMtcXVlc3Rpb24nLFxuXHRcdFx0cGxhY2Vob2xkZXI6ICdsbG1zLXF1ZXN0aW9uIGxsbXMtc29ydGFibGUtcGxhY2Vob2xkZXInLFxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBIaWdobGlnaHQgZHJvcCBhcmVhcyB3aGVuIGRyYWdnaW5nIHN0YXJ0c1xuXHRcdCAqIEBwYXJhbSAgICBvYmogICBtb2RlbCAgbW9kZWwgYmVpbmcgc29ydGVkXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdHNvcnRhYmxlX3N0YXJ0OiBmdW5jdGlvbiggbW9kZWwgKSB7XG5cdFx0XHR2YXIgc2VsZWN0b3IgPSAnZ3JvdXAnID09PSBtb2RlbC5nZXQoICdxdWVzdGlvbl90eXBlJyApLmdldCggJ2lkJyApID8gJy5sbG1zLWVkaXRvci10YWIgPiAubGxtcy1xdWl6LXF1ZXN0aW9ucycgOiAnLmxsbXMtcXVpei1xdWVzdGlvbnMnO1xuXHRcdFx0JCggc2VsZWN0b3IgKS5hZGRDbGFzcyggJ2RyYWdnaW5nJyApO1xuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBSZW1vdmUgaGlnaGxpZ2h0cyB3aGVuIGRyYWdnaW5nIHN0b3BzXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIG1vZGVsICBtb2RlbCBiZWluZyBzb3J0ZWRcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0c29ydGFibGVfc3RvcDogZnVuY3Rpb24oKSB7XG5cdFx0XHQkKCAnLmxsbXMtcXVpei1xdWVzdGlvbnMnICkucmVtb3ZlQ2xhc3MoICdkcmFnZ2luZycgKTtcblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogT3ZlcnJpZGVzIHJlY2VpdmUgdG8gZW5zdXJlIHRoYXQgcXVlc3Rpb24gZ3JvdXBzIGNhbid0IGJlIG1vdmVkIGludG8gcXVlc3RvbiBncm91cHNcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgZXZlbnQgIGpzIGV2ZW50IG9iamVjdFxuXHRcdCAqIEBwYXJhbSAgICBvYmogICB1aSAgICAgalF1ZXJ5IFVJIFNvcnRhYmxlIHVpIG9iamVjdFxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRfcmVjZWl2ZSA6IGZ1bmN0aW9uKCBldmVudCwgdWkgKSB7XG5cblx0XHRcdGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuXG5cdFx0XHQvLyBwcmV2ZW50IG1vdmluZyBhIHF1ZXN0aW9uIGdyb3VwIGludG8gYSBxdWVzdGlvbiBncm91cFxuXHRcdFx0aWYgKCB1aS5pdGVtLmhhc0NsYXNzKCAncXR5cGUtLWdyb3VwJyApICYmICQoIGV2ZW50LnRhcmdldCApLmNsb3Nlc3QoICcucXR5cGUtLWdyb3VwJyApLmxlbmd0aCApIHs7XG5cdFx0XHRcdHVpLnNlbmRlci5zb3J0YWJsZSggJ2NhbmNlbCcgKTtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXG5cdFx0XHR2YXIgc2VuZGVyTGlzdEVsID0gdWkuc2VuZGVyO1xuXHRcdFx0dmFyIHNlbmRlckNvbGxlY3Rpb25MaXN0VmlldyA9IHNlbmRlckxpc3RFbC5kYXRhKCBcInZpZXdcIiApO1xuXHRcdFx0aWYoICEgc2VuZGVyQ29sbGVjdGlvbkxpc3RWaWV3IHx8ICEgc2VuZGVyQ29sbGVjdGlvbkxpc3RWaWV3LmNvbGxlY3Rpb24gKSByZXR1cm47XG5cblx0XHRcdHZhciBuZXdJbmRleCA9IHRoaXMuX2dldENvbnRhaW5lckVsKCkuY2hpbGRyZW4oKS5pbmRleCggdWkuaXRlbSApO1xuXHRcdFx0dmFyIG1vZGVsUmVjZWl2ZWQgPSBzZW5kZXJDb2xsZWN0aW9uTGlzdFZpZXcuY29sbGVjdGlvbi5nZXQoIHVpLml0ZW0uYXR0ciggXCJkYXRhLW1vZGVsLWNpZFwiICkgKTtcblx0XHRcdHNlbmRlckNvbGxlY3Rpb25MaXN0Vmlldy5jb2xsZWN0aW9uLnJlbW92ZSggbW9kZWxSZWNlaXZlZCApO1xuXHRcdFx0dGhpcy5jb2xsZWN0aW9uLmFkZCggbW9kZWxSZWNlaXZlZCwgeyBhdCA6IG5ld0luZGV4IH0gKTtcblx0XHRcdG1vZGVsUmVjZWl2ZWQuY29sbGVjdGlvbiA9IHRoaXMuY29sbGVjdGlvbjsgLy8gb3RoZXJ3aXNlIHdpbGwgbm90IGdldCBwcm9wZXJseSBzZXQsIHNpbmNlIG1vZGVsUmVjZWl2ZWQuY29sbGVjdGlvbiBtaWdodCBhbHJlYWR5IGhhdmUgYSB2YWx1ZS5cblx0XHRcdHRoaXMuc2V0U2VsZWN0ZWRNb2RlbCggbW9kZWxSZWNlaXZlZCApO1xuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBPdmVycmlkZSB0byBhbGxvdyBtYW5pcHVsYXRpbm8gb2YgcGxhY2Vob2xkZXIgZWxlbWVudFxuXHRcdCAqIEBwYXJhbSAgICB7W3R5cGVdfSAgIGV2ZW50ICBbZGVzY3JpcHRpb25dXG5cdFx0ICogQHBhcmFtICAgIHtbdHlwZV19ICAgdWkgICAgIFtkZXNjcmlwdGlvbl1cblx0XHQgKiBAcmV0dXJuICAge1t0eXBlXX1cblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdF9zb3J0U3RhcnQgOiBmdW5jdGlvbiggZXZlbnQsIHVpICkge1xuXG5cdFx0XHR2YXIgbW9kZWxCZWluZ1NvcnRlZCA9IHRoaXMuY29sbGVjdGlvbi5nZXQoIHVpLml0ZW0uYXR0ciggXCJkYXRhLW1vZGVsLWNpZFwiICkgKTtcblxuXHRcdFx0dWkucGxhY2Vob2xkZXIuYWRkQ2xhc3MoICdxdHlwZS0tJyArIG1vZGVsQmVpbmdTb3J0ZWQuZ2V0KCAncXVlc3Rpb25fdHlwZScgKS5nZXQoICdpZCcgKSApO1xuXG5cdFx0XHRpZiggdGhpcy5faXNCYWNrYm9uZUNvdXJpZXJBdmFpbGFibGUoKSApXG5cdFx0XHRcdHRoaXMuc3Bhd24oIFwic29ydFN0YXJ0XCIsIHsgbW9kZWxCZWluZ1NvcnRlZCA6IG1vZGVsQmVpbmdTb3J0ZWQgfSApO1xuXHRcdFx0ZWxzZSB0aGlzLnRyaWdnZXIoIFwic29ydFN0YXJ0XCIsIG1vZGVsQmVpbmdTb3J0ZWQgKTtcblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogT3ZlcmxvYWRzIHRoZSBmdW5jdGlvbiBmcm9tIEJhY2tib25lLkNvbGxlY3Rpb25WaWV3IGNvcmUgYmVjYXVzZSBpdCBkb2Vzbid0IHNlbmQgc3RvcCBldmVudHNcblx0XHQgKiBpZiBtb3ZpbmcgZnJvbSBvbmUgc29ydGFibGUgdG8gYW5vdGhlci4uLiA6LShcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgZXZlbnQgIGpzIGV2ZW50IG9iamVjdFxuXHRcdCAqIEBwYXJhbSAgICBvYmogICB1aSAgICAgalF1ZXJ5IFVJIG9iamVjdFxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRfc29ydFN0b3AgOiBmdW5jdGlvbiggZXZlbnQsIHVpICkge1xuXG5cdFx0XHRldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcblxuXHRcdFx0dmFyIG1vZGVsQmVpbmdTb3J0ZWQgPSB0aGlzLmNvbGxlY3Rpb24uZ2V0KCB1aS5pdGVtLmF0dHIoICdkYXRhLW1vZGVsLWNpZCcgKSApLFxuXHRcdFx0XHRtb2RlbFZpZXdDb250YWluZXJFbCA9IHRoaXMuX2dldENvbnRhaW5lckVsKCksXG5cdFx0XHRcdG5ld0luZGV4ID0gbW9kZWxWaWV3Q29udGFpbmVyRWwuY2hpbGRyZW4oKS5pbmRleCggdWkuaXRlbSApO1xuXG5cdFx0XHRpZiAoIG5ld0luZGV4ID09IC0xICYmIG1vZGVsQmVpbmdTb3J0ZWQgKSB7XG5cdFx0XHRcdHRoaXMuY29sbGVjdGlvbi5yZW1vdmUoIG1vZGVsQmVpbmdTb3J0ZWQgKTtcblx0XHRcdH1cblxuXHRcdFx0dGhpcy5fcmVvcmRlckNvbGxlY3Rpb25CYXNlZE9uSFRNTCgpO1xuXHRcdFx0dGhpcy51cGRhdGVEZXBlbmRlbnRDb250cm9scygpO1xuXG5cdFx0XHRpZiggdGhpcy5faXNCYWNrYm9uZUNvdXJpZXJBdmFpbGFibGUoKSApIHtcblx0XHRcdFx0dGhpcy5zcGF3biggJ3NvcnRTdG9wJywgeyBtb2RlbEJlaW5nU29ydGVkIDogbW9kZWxCZWluZ1NvcnRlZCwgbmV3SW5kZXggOiBuZXdJbmRleCB9ICk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0aGlzLnRyaWdnZXIoICdzb3J0U3RvcCcsIG1vZGVsQmVpbmdTb3J0ZWQsIG5ld0luZGV4ICk7XG5cdFx0XHR9XG5cblx0XHR9LFxuXG5cdH0gKTtcblxufSApO1xuXG4vKipcbiAqIFNpbmdsZSBRdWl6IFZpZXdcbiAqIEBzaW5jZSAgICAzLjE2LjBcbiAqIEB2ZXJzaW9uICAzLjE5LjJcbiAqL1xuZGVmaW5lKCAnVmlld3MvUXVpeicsW1xuXHRcdCdNb2RlbHMvUXVpeicsXG5cdFx0J1ZpZXdzL1BvcG92ZXInLFxuXHRcdCdWaWV3cy9Qb3N0U2VhcmNoJyxcblx0XHQnVmlld3MvUXVlc3Rpb25CYW5rJyxcblx0XHQnVmlld3MvUXVlc3Rpb25MaXN0Jyxcblx0XHQnVmlld3MvU2V0dGluZ3NGaWVsZHMnLFxuXHRcdCdWaWV3cy9fRGV0YWNoYWJsZScsXG5cdFx0J1ZpZXdzL19FZGl0YWJsZScsXG5cdFx0J1ZpZXdzL19TdWJ2aWV3Jyxcblx0XHQnVmlld3MvX1RyYXNoYWJsZSdcblx0XSwgZnVuY3Rpb24oXG5cdFx0UXVpek1vZGVsLFxuXHRcdFBvcG92ZXIsXG5cdFx0UG9zdFNlYXJjaCxcblx0XHRRdWVzdGlvbkJhbmssXG5cdFx0UXVlc3Rpb25MaXN0LFxuXHRcdFNldHRpbmdzRmllbGRzLFxuXHRcdERldGFjaGFibGUsXG5cdFx0RWRpdGFibGUsXG5cdFx0U3Vidmlldyxcblx0XHRUcmFzaGFibGVcblx0KSB7XG5cblx0cmV0dXJuIEJhY2tib25lLlZpZXcuZXh0ZW5kKCBfLmRlZmF1bHRzKCB7XG5cblx0XHQvKipcblx0XHQgKiBDdXJyZW50IHZpZXcgc3RhdGVcblx0XHQgKiBAdHlwZSAge1N0cmluZ31cblx0XHQgKi9cblx0XHRzdGF0ZTogJ2RlZmF1bHQnLFxuXG5cdFx0LyoqXG5cdFx0ICogQ3VycmVudCBTdWJ2aWV3c1xuXHRcdCAqIEB0eXBlICB7T2JqZWN0fVxuXHRcdCAqL1xuXHRcdHZpZXdzOiB7XG5cdFx0XHRzZXR0aW5nczoge1xuXHRcdFx0XHRjbGFzczogU2V0dGluZ3NGaWVsZHMsXG5cdFx0XHRcdGluc3RhbmNlOiBudWxsLFxuXHRcdFx0XHRzdGF0ZTogJ2RlZmF1bHQnLFxuXHRcdFx0fSxcblx0XHRcdGJhbms6IHtcblx0XHRcdFx0Y2xhc3M6IFF1ZXN0aW9uQmFuayxcblx0XHRcdFx0aW5zdGFuY2U6IG51bGwsXG5cdFx0XHRcdHN0YXRlOiAnZGVmYXVsdCcsXG5cdFx0XHR9LFxuXHRcdFx0bGlzdDoge1xuXHRcdFx0XHRjbGFzczogUXVlc3Rpb25MaXN0LFxuXHRcdFx0XHRpbnN0YW5jZTogbnVsbCxcblx0XHRcdFx0c3RhdGU6ICdkZWZhdWx0Jyxcblx0XHRcdH0sXG5cdFx0fSxcblxuXHRcdGVsOiAnI2xsbXMtZWRpdG9yLXF1aXonLFxuXG5cdFx0LyoqXG5cdFx0ICogRXZlbnRzXG5cdFx0ICogQHR5cGUgIHtPYmplY3R9XG5cdFx0ICovXG5cdFx0ZXZlbnRzOiBfLmRlZmF1bHRzKCB7XG5cdFx0XHQnY2xpY2sgI2xsbXMtZXhpc3RpbmctcXVpeic6ICdhZGRfZXhpc3RpbmdfcXVpel9jbGljaycsXG5cdFx0XHQnY2xpY2sgI2xsbXMtbmV3LXF1aXonOiAnYWRkX25ld19xdWl6Jyxcblx0XHRcdCdjbGljayAjbGxtcy1zaG93LXF1ZXN0aW9uLWJhbmsnOiAnc2hvd190b29scycsXG5cdFx0XHQnY2xpY2sgLmJ1bGstdG9nZ2xlJzogJ2J1bGtfdG9nZ2xlJyxcblx0XHRcdC8vICdrZXl1cCAjbGxtcy1xdWVzdGlvbi1iYW5rLWZpbHRlcic6ICdmaWx0ZXJfcXVlc3Rpb25fdHlwZXMnLFxuXHRcdFx0Ly8gJ3NlYXJjaCAjbGxtcy1xdWVzdGlvbi1iYW5rLWZpbHRlcic6ICdmaWx0ZXJfcXVlc3Rpb25fdHlwZXMnLFxuXHRcdH0sIERldGFjaGFibGUuZXZlbnRzLCBFZGl0YWJsZS5ldmVudHMsIFRyYXNoYWJsZS5ldmVudHMgKSxcblxuXHRcdC8qKlxuXHRcdCAqIFdyYXBwZXIgVGFnIG5hbWVcblx0XHQgKiBAdHlwZSAge1N0cmluZ31cblx0XHQgKi9cblx0XHR0YWdOYW1lOiAnZGl2JyxcblxuXHRcdC8qKlxuXHRcdCAqIEdldCB0aGUgdW5kZXJzY29yZSB0ZW1wbGF0ZVxuXHRcdCAqIEB0eXBlICB7W3R5cGVdfVxuXHRcdCAqL1xuXHRcdHRlbXBsYXRlOiB3cC50ZW1wbGF0ZSggJ2xsbXMtcXVpei10ZW1wbGF0ZScgKSxcblxuXHRcdC8qKlxuXHRcdCAqIEluaXRpYWxpemF0aW9uIGNhbGxiYWNrIGZ1bmMgKHJlbmRlcnMgdGhlIGVsZW1lbnQgb24gc2NyZWVuKVxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE5LjJcblx0XHQgKi9cblx0XHRpbml0aWFsaXplOiBmdW5jdGlvbiggZGF0YSApIHtcblxuXHRcdFx0dGhpcy5sZXNzb24gPSBkYXRhLmxlc3NvbjtcblxuXHRcdFx0Ly8gaW5pdGlhbGl6ZSB0aGUgbW9kZWwgaWYgdGhlIHF1aXogaXMgZW5hYmxlZCBvciBpdCdzIGRpc2FibGVkIGJ1dCB3ZSBzdGlsbCBoYXZlIGRhdGEgZm9yIGEgcXVpelxuXHRcdFx0aWYgKCAneWVzJyA9PT0gdGhpcy5sZXNzb24uZ2V0KCAncXVpel9lbmFibGVkJyApIHx8ICEgXy5pc0VtcHR5KCB0aGlzLmxlc3Nvbi5nZXQoICdxdWl6JyApICkgKSB7XG5cblx0XHRcdFx0dGhpcy5tb2RlbCA9IHRoaXMubGVzc29uLmdldCggJ3F1aXonICk7XG5cblx0XHRcdFx0LyoqXG5cdFx0XHRcdCAqIEB0b2RvICB0aGlzIGlzIGEgdGVycmlsYmUgdGVycmlibGUgcGF0Y2hcblx0XHRcdFx0ICogICAgICAgIEkndmUgc3BlbnQgbmVhcmx5IDMgZGF5cyB0cnlpbmcgdG8gZmlndXJlIG91dCBob3cgdG8gbm90IHVzZSB0aGlzIGxpbmUgb2YgY29kZVxuXHRcdFx0XHQgKiAgICAgICAgSVNTVUUgUkVQUk9EVUNUSU9OOlxuXHRcdFx0XHQgKiAgICAgICAgT3BlbiBjb3Vyc2UgYnVpbGRlclxuXHRcdFx0XHQgKiAgICAgICAgT3BlbiBhIGxlc3NvbiAoQSkgYW5kIGFkZCBhIHF1aXpcblx0XHRcdFx0ICogICAgICAgIFN3aXRjaCB0byBhIG5ldyBsZXNzb24gKEIpXG5cdFx0XHRcdCAqICAgICAgICBBZGQgYSBuZXcgcXVpelxuXHRcdFx0XHQgKiAgICAgICAgUmV0dXJuIHRvIGxlc3NvbiBBIGFuZCB0aGUgcXVpenplcyBwYXJlbnQgd2lsbCBiZSBzZXQgdG8gTEVTU09OIEJcblx0XHRcdFx0ICogICAgICAgIFRoaXMgd2lsbCBoYXBwZW4gZm9yICpldmVyeSogcXVpeiBpbiB0aGUgYnVpbGRlci4uLlxuXHRcdFx0XHQgKiAgICAgICAgQWRkaW5nIHRoaXMgc2V0X3BhcmVudCBvbiBpbml0IGd1YXJhbnRlZXMgdGhhdCB0aGUgcXVpenplcyBjb3JyZWN0IHBhcmVudCBpcyBzZXRcblx0XHRcdFx0ICogICAgICAgIGFmdGVyIGFkZGluZyBuZXcgcXVpenplcyB0byBvdGhlciBsZXNzb25zXG5cdFx0XHRcdCAqICAgICAgICBpdCdzIGF3ZnVsIGFuZCBpdCdzIGdyb3NzLi4uXG5cdFx0XHRcdCAqICAgICAgICBJJ20gY29uZnVzZWQgYW5kIHRpcmVkIGFuZCBnb2luZyB0byBtaXNzIHJlbGVhc2UgZGF0ZXMgYWdhaW4gYmVjYXVzZSBvZiBpdFxuXHRcdFx0XHQgKi9cblx0XHRcdFx0dGhpcy5tb2RlbC5zZXRfcGFyZW50KCB0aGlzLmxlc3NvbiApO1xuXG5cdFx0XHRcdHRoaXMubGlzdGVuVG8oIHRoaXMubW9kZWwsICdjaGFuZ2U6X3BvaW50cycsIHRoaXMucmVuZGVyX3BvaW50cyApO1xuXG5cdFx0XHR9XG5cblx0XHRcdHRoaXMub24oICdtb2RlbC10cmFzaGVkJywgdGhpcy5vbl90cmFzaGVkICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogQ29tcGlsZXMgdGhlIHRlbXBsYXRlIGFuZCByZW5kZXJzIHRoZSB2aWV3XG5cdFx0ICogQHJldHVybiAgIHNlbGYgKGZvciBjaGFpbmluZylcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTkuMlxuXHRcdCAqL1xuXHRcdHJlbmRlcjogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHRoaXMuJGVsLmh0bWwoIHRoaXMudGVtcGxhdGUoIHRoaXMubW9kZWwgKSApO1xuXG5cdFx0XHQvLyByZW5kZXIgdGhlIHF1aXogYnVpbGRlclxuXHRcdFx0aWYgKCB0aGlzLm1vZGVsICkge1xuXG5cdFx0XHRcdC8vIGRvbid0IGFsbG93IGludGVyYWN0aW9uIHVudGlsIHF1ZXN0aW9ucyBhcmUgbGF6eSBsb2FkZWRcblx0XHRcdFx0TExNUy5TcGlubmVyLnN0YXJ0KCB0aGlzLiRlbCApO1xuXG5cdFx0XHRcdHRoaXMucmVuZGVyX3N1YnZpZXcoICdzZXR0aW5ncycsIHtcblx0XHRcdFx0XHRlbDogJyNsbG1zLXF1aXotc2V0dGluZ3MtZmllbGRzJyxcblx0XHRcdFx0XHRtb2RlbDogdGhpcy5tb2RlbCxcblx0XHRcdFx0fSApO1xuXG5cdFx0XHRcdHRoaXMuaW5pdF9kYXRlcGlja2VycygpO1xuXHRcdFx0XHR0aGlzLmluaXRfc2VsZWN0cygpO1xuXG5cdFx0XHRcdHRoaXMucmVuZGVyX3N1YnZpZXcoICdiYW5rJywge1xuXHRcdFx0XHRcdGNvbGxlY3Rpb246IHdpbmRvdy5sbG1zX2J1aWxkZXIucXVlc3Rpb25zLFxuXHRcdFx0XHR9ICk7XG5cblx0XHRcdFx0dmFyIGxhc3RfZ3JvdXAgPSBudWxsLFxuXHRcdFx0XHRcdGdyb3VwID0gbnVsbDtcblx0XHRcdFx0Ly8gbGV0IGFsbCB0aGUgcXVlc3Rpb24gdHlwZXMgcmVmZXJlbmNlIHRoZSBxdWl6IGZvciBhZGRpbmcgcXVlc3Rpb25zIHF1aWNrbHlcblx0XHRcdFx0dGhpcy5nZXRfc3VidmlldyggJ2JhbmsnICkuaW5zdGFuY2Uudmlld01hbmFnZXIuZWFjaCggZnVuY3Rpb24oIHZpZXcgKSB7XG5cblx0XHRcdFx0XHR2aWV3LnF1aXogPSB0aGlzLm1vZGVsO1xuXG5cdFx0XHRcdFx0Z3JvdXAgPSB2aWV3Lm1vZGVsLmdldCggJ2dyb3VwJyApLm5hbWU7XG5cblx0XHRcdFx0XHRpZiAoIGxhc3RfZ3JvdXAgIT09IGdyb3VwICkge1xuXHRcdFx0XHRcdFx0bGFzdF9ncm91cCA9IGdyb3VwO1xuXHRcdFx0XHRcdFx0dmlldy4kZWwuYmVmb3JlKCAnPGxpIGNsYXNzPVwibGxtcy1xdWVzdGlvbi1iYW5rLWhlYWRlclwiPjxoND4nICsgZ3JvdXAgKyAnPC9oND48L2xpPicgKTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0fSwgdGhpcyApO1xuXG5cdFx0XHRcdHRoaXMubW9kZWwubG9hZF9xdWVzdGlvbnMoIF8uYmluZCggZnVuY3Rpb24oIGVyciApIHtcblxuXHRcdFx0XHRcdGlmICggZXJyICkge1xuXHRcdFx0XHRcdFx0YWxlcnQoIExMTVMubDEwbi50cmFuc2xhdGUoICdBbiBlcnJvciBvY2N1cnJlZCB3aGlsZSB0cnlpbmcgdG8gbG9hZCB0aGUgcXVlc3Rpb25zLiBQbGVhc2UgcmVmcmVzaCB0aGUgcGFnZSBhbmQgdHJ5IGFnYWluLicgKSApO1xuXHRcdFx0XHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0TExNUy5TcGlubmVyLnN0b3AoIHRoaXMuJGVsICk7XG5cdFx0XHRcdFx0dGhpcy5yZW5kZXJfc3VidmlldyggJ2xpc3QnLCB7XG5cdFx0XHRcdFx0XHRlbDogJyNsbG1zLXF1aXotcXVlc3Rpb25zJyxcblx0XHRcdFx0XHRcdGNvbGxlY3Rpb246IHRoaXMubW9kZWwuZ2V0KCAncXVlc3Rpb25zJyApLFxuXHRcdFx0XHRcdH0gKTtcblx0XHRcdFx0XHR2YXIgbGlzdCA9IHRoaXMuZ2V0X3N1YnZpZXcoICdsaXN0JyApLmluc3RhbmNlO1xuXHRcdFx0XHRcdGxpc3QucXVpeiA9IHRoaXM7XG5cdFx0XHRcdFx0bGlzdC5jb2xsZWN0aW9uLm9uKCAnYWRkJywgZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHRsaXN0LmNvbGxlY3Rpb24udHJpZ2dlciggJ3Jlb3JkZXInICk7XG5cdFx0XHRcdFx0fSwgdGhpcyApO1xuXHRcdFx0XHRcdGxpc3Qub24oICdzb3J0U3RhcnQnLCBsaXN0LnNvcnRhYmxlX3N0YXJ0ICk7XG5cdFx0XHRcdFx0bGlzdC5vbiggJ3NvcnRTdG9wJywgbGlzdC5zb3J0YWJsZV9zdG9wICk7XG5cblx0XHRcdFx0fSwgdGhpcyApICk7XG5cblx0XHRcdFx0dGhpcy5tb2RlbC5vbiggJ25ldy1xdWVzdGlvbi1hZGRlZCcsIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdHZhciAkcXVlc3Rpb25zID0gdGhpcy4kZWwuZmluZCggJyNsbG1zLXF1aXotcXVlc3Rpb25zJyApO1xuXHRcdFx0XHRcdCRxdWVzdGlvbnMuYW5pbWF0ZSggeyBzY3JvbGxUb3A6ICRxdWVzdGlvbnMucHJvcCggJ3Njcm9sbEhlaWdodCcgKSB9LCAyMDAgKTtcblx0XHRcdFx0fSwgdGhpcyApO1xuXG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiB0aGlzO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIE9uIHF1aXogcG9pbnRzIHVwZGF0ZSwgdXBkYXRlIHRoZSB2YWx1ZSBvZiB0aGUgVG90YWwgUG9pbnRzIGFyZWEgaW4gdGhlIGhlYWRlclxuXHRcdCAqIEBwYXJhbSAgICBvYmogICBxdWl6ICAgIEluc3RhbmNlIG9mIHRoZSBxdWl6IG1vZGVsXG5cdFx0ICogQHBhcmFtICAgIGludCAgIHBvaW50cyAgVXBkYXRlZCBudW1iZXIgb2YgcG9pbnRzXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNy42XG5cdFx0ICogQHZlcnNpb24gIDMuMTcuNlxuXHRcdCAqL1xuXHRcdHJlbmRlcl9wb2ludHM6IGZ1bmN0aW9uKCBxdWl6LCBwb2ludHMgKSB7XG5cblx0XHRcdHRoaXMuJGVsLmZpbmQoICcjbGxtcy1xdWl6LXRvdGFsLXBvaW50cycgKS50ZXh0KCBwb2ludHMgKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBCdWxrIGV4cGFuZCAvIGNvbGxhcHNlIHF1ZXN0aW9uIGJ1dHRvbnNcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgZXZlbnQgIGpzIGV2ZW50IG9iamVjdFxuXHRcdCAqIEByZXR1cm4gICBvYmpcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGJ1bGtfdG9nZ2xlOiBmdW5jdGlvbiggZXZlbnQgKSB7XG5cblx0XHRcdHZhciBleHBhbmRlZCA9ICggJ2V4cGFuZCcgPT09ICQoIGV2ZW50LnRhcmdldCApLmF0dHIoICdkYXRhLWFjdGlvbicgKSApO1xuXG5cdFx0XHR0aGlzLm1vZGVsLmdldCggJ3F1ZXN0aW9ucycgKS5lYWNoKCBmdW5jdGlvbiggcXVlc3Rpb24gKSB7XG5cdFx0XHRcdHF1ZXN0aW9uLnNldCggJ19leHBhbmRlZCcsIGV4cGFuZGVkICk7XG5cdFx0XHR9ICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogQWRkcyBhIG5ldyBxdWl6IHRvIGEgbGVzc29uIHdoaWNoIGN1cnJlbnRseSBoYXMgbm8gcXVpeiBhc3NvY2lhdGVkIHdsaXRoIGl0XG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGFkZF9uZXdfcXVpejogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHZhciBxdWl6ID0gdGhpcy5sZXNzb24uZ2V0KCAncXVpeicgKTtcblx0XHRcdGlmICggXy5pc0VtcHR5KCBxdWl6ICkgKSB7XG5cdFx0XHRcdHF1aXogPSB0aGlzLmxlc3Nvbi5hZGRfcXVpeigpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dGhpcy5sZXNzb24uc2V0KCAncXVpel9lbmFibGVkJywgJ3llcycgKTtcblx0XHRcdH1cblxuXHRcdFx0dGhpcy5tb2RlbCA9IHF1aXo7XG5cdFx0XHR0aGlzLnJlbmRlcigpO1xuXG5cdFx0fSxcblxuXHRcdC8vIGNvbWUgYmFjayB0byB0aGlzIGFuZCBtYWtlIHN1cmUgY2xvbmluZyByZXNldHMgYWxsIHRoZSBJRHNcblx0XHRhZGRfZXhpc3RpbmdfcXVpejogZnVuY3Rpb24oIGV2ZW50ICkge1xuXG5cdFx0XHR0aGlzLnBvc3Rfc2VhcmNoX3BvcG92ZXIuaGlkZSgpO1xuXG5cdFx0XHR2YXIgcXVpeiA9IGV2ZW50LmRhdGE7XG5cblx0XHRcdGlmICggJ2Nsb25lJyA9PT0gZXZlbnQuYWN0aW9uICkge1xuXG5cdFx0XHRcdGRlbGV0ZSBxdWl6LmlkO1xuXG5cdFx0XHRcdF8uZWFjaCggcXVpei5xdWVzdGlvbnMsIGZ1bmN0aW9uKCBxdWVzdGlvbiApIHtcblxuXHRcdFx0XHRcdGRlbGV0ZSBxdWVzdGlvbi5wYXJlbnRfaWQ7XG5cdFx0XHRcdFx0ZGVsZXRlIHF1ZXN0aW9uLmlkO1xuXG5cdFx0XHRcdFx0aWYgKCBxdWVzdGlvbi5jaG9pY2VzICkge1xuXG5cdFx0XHRcdFx0XHRfLmVhY2goIHF1ZXN0aW9uLmNob2ljZXMsIGZ1bmN0aW9uKCBjaG9pY2UgKSB7XG5cblx0XHRcdFx0XHRcdFx0ZGVsZXRlIGNob2ljZS5xdWVzdGlvbl9pZDtcblx0XHRcdFx0XHRcdFx0ZGVsZXRlIGNob2ljZS5pZDtcblxuXHRcdFx0XHRcdFx0fSApO1xuXG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdH0gKTtcblxuXHRcdFx0fSBlbHNlIHtcblxuXHRcdFx0XHRxdWl6Ll9mb3JjZVN5bmMgPSB0cnVlO1xuXG5cdFx0XHR9XG5cblx0XHRcdGRlbGV0ZSBxdWl6Lmxlc3Nvbl9pZDtcblxuXHRcdFx0dGhpcy5sZXNzb24uYWRkX3F1aXooIHF1aXogKTtcblx0XHRcdHRoaXMubW9kZWwgPSB0aGlzLmxlc3Nvbi5nZXQoICdxdWl6JyApO1xuXHRcdFx0dGhpcy5yZW5kZXIoKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBPcGVuIGFkZCBleGlzdGluZyBxdWl6IHBvcG92ZXJcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgZXZlbnQgIEpTIGV2ZW50IG9iamVjdFxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMTJcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4xMlxuXHRcdCAqL1xuXHRcdGFkZF9leGlzdGluZ19xdWl6X2NsaWNrOiBmdW5jdGlvbiggZXZlbnQgKSB7XG5cblx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cblx0XHRcdHRoaXMucG9zdF9zZWFyY2hfcG9wb3ZlciA9IG5ldyBQb3BvdmVyKCB7XG5cdFx0XHRcdGVsOiAnI2xsbXMtZXhpc3RpbmctcXVpeicsXG5cdFx0XHRcdGFyZ3M6IHtcblx0XHRcdFx0XHRiYWNrZHJvcDogdHJ1ZSxcblx0XHRcdFx0XHRjbG9zZWFibGU6IHRydWUsXG5cdFx0XHRcdFx0Y29udGFpbmVyOiAnLndyYXAubGlmdGVybG1zLmxsbXMtYnVpbGRlcicsXG5cdFx0XHRcdFx0ZGlzbWlzc2libGU6IHRydWUsXG5cdFx0XHRcdFx0cGxhY2VtZW50OiAnbGVmdCcsXG5cdFx0XHRcdFx0d2lkdGg6IDQ4MCxcblx0XHRcdFx0XHR0aXRsZTogTExNUy5sMTBuLnRyYW5zbGF0ZSggJ0FkZCBFeGlzdGluZyBRdWl6JyApLFxuXHRcdFx0XHRcdGNvbnRlbnQ6IG5ldyBQb3N0U2VhcmNoKCB7XG5cdFx0XHRcdFx0XHRwb3N0X3R5cGU6ICdsbG1zX3F1aXonLFxuXHRcdFx0XHRcdFx0c2VhcmNoaW5nX21lc3NhZ2U6IExMTVMubDEwbi50cmFuc2xhdGUoICdTZWFyY2ggZm9yIGV4aXN0aW5nIHF1aXp6ZXMuLi4nICksXG5cdFx0XHRcdFx0fSApLnJlbmRlcigpLiRlbCxcblx0XHRcdFx0XHRvbkhpZGU6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdFx0QmFja2JvbmUucHViU3ViLm9mZiggJ3F1aXotc2VhcmNoLXNlbGVjdCcgKTtcblx0XHRcdFx0XHR9LFxuXHRcdFx0XHR9XG5cdFx0XHR9ICk7XG5cblx0XHRcdHRoaXMucG9zdF9zZWFyY2hfcG9wb3Zlci5zaG93KCk7XG5cdFx0XHRCYWNrYm9uZS5wdWJTdWIub25jZSggJ3F1aXotc2VhcmNoLXNlbGVjdCcsIHRoaXMuYWRkX2V4aXN0aW5nX3F1aXosIHRoaXMgKTtcblxuXHRcdH0sXG5cblx0XHQvLyBmaWx0ZXJfcXVlc3Rpb25fdHlwZXM6IF8uZGVib3VuY2UoIGZ1bmN0aW9uKCBldmVudCApIHtcblxuXHRcdC8vIFx0dmFyIHRlcm0gPSAkKCBldmVudC50YXJnZXQgKS52YWwoKTtcblxuXHRcdC8vIFx0dGhpcy5RdWVzdGlvbkJhbmtWaWV3LnZpZXdNYW5hZ2VyLmVhY2goIGZ1bmN0aW9uKCB2aWV3ICkge1xuXHRcdC8vIFx0XHRpZiAoICEgdGVybSApIHtcblx0XHQvLyBcdFx0XHR2aWV3LmNsZWFyX2ZpbHRlcigpO1xuXHRcdC8vIFx0XHR9IGVsc2Uge1xuXHRcdC8vIFx0XHRcdHZpZXcuZmlsdGVyKCB0ZXJtICk7XG5cdFx0Ly8gXHRcdH1cblx0XHQvLyBcdH0gKTtcblxuXG5cdFx0Ly8gfSwgMzAwICksXG5cblx0XHQvKipcblx0XHQgKiBDYWxsYmFjayBmdW5jdGlvbiB3aGVuIHRoZSBxdWl6IGhhcyBiZWVuIGRlbGV0ZWRcblx0XHQgKiBAcGFyYW0gICAgb2JqZWN0ICAgcXVpeiAgUXVpeiBNb2RlbFxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuNlxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjZcblx0XHQgKi9cblx0XHRvbl90cmFzaGVkOiBmdW5jdGlvbiggcXVpeiApIHtcblxuXHRcdFx0dGhpcy5sZXNzb24uc2V0KCAncXVpel9lbmFibGVkJywgJ25vJyApO1xuXHRcdFx0dGhpcy5sZXNzb24uc2V0KCAncXVpeicsICcnICk7XG5cblx0XHRcdGRlbGV0ZSB0aGlzLm1vZGVsO1xuXG5cdFx0XHR0aGlzLnJlbmRlcigpO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFwiQWRkIFF1ZXN0aW9uXCIgYnV0dG9uIGNsaWNrIGV2ZW50XG5cdFx0ICogQ3JlYXRlcyBhIHBvcG92ZXIgd2l0aCBxdWVzdGlvbiB0eXBlIGxpc3QgaW50ZXJmYWNlXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdHNob3dfdG9vbHM6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHQvLyBjcmVhdGUgcG9wb3ZlclxuXHRcdFx0dmFyIHBvcCA9IG5ldyBQb3BvdmVyKCB7XG5cdFx0XHRcdGVsOiAnI2xsbXMtc2hvdy1xdWVzdGlvbi1iYW5rJyxcblx0XHRcdFx0YXJnczoge1xuXHRcdFx0XHRcdGJhY2tkcm9wOiB0cnVlLFxuXHRcdFx0XHRcdGNsb3NlYWJsZTogdHJ1ZSxcblx0XHRcdFx0XHRjb250YWluZXI6ICcjbGxtcy1idWlsZGVyLXNpZGViYXInLFxuXHRcdFx0XHRcdGRpc21pc3NpYmxlOiB0cnVlLFxuXHRcdFx0XHRcdHBsYWNlbWVudDogJ3RvcC1sZWZ0Jyxcblx0XHRcdFx0XHR3aWR0aDogJ2NhbGMoIDEwMCUgLSA0MHB4ICknLFxuXHRcdFx0XHRcdHRpdGxlOiBMTE1TLmwxMG4udHJhbnNsYXRlKCAnQWRkIGEgUXVlc3Rpb24nICksXG5cdFx0XHRcdFx0dXJsOiAnI2xsbXMtcXVpei10b29scycsXG5cdFx0XHRcdH1cblx0XHRcdH0gKTtcblxuXHRcdFx0Ly8gc2hvdyBpdFxuXHRcdFx0cG9wLnNob3coKTtcblxuXHRcdFx0Ly8gaWYgYSBxdWVzdGlvbiBpcyBhZGRlZCwgaGlkZSB0aGUgcG9wb3ZlclxuXHRcdFx0dGhpcy5tb2RlbC5vbiggJ25ldy1xdWVzdGlvbi1hZGRlZCcsIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRwb3AuaGlkZSgpO1xuXHRcdFx0fSApO1xuXG5cdFx0fSxcblxuXHRcdGdldF9xdWVzdGlvbl9saXN0OiBmdW5jdGlvbiggb3B0aW9ucyApIHtcblx0XHRcdHJldHVybiBuZXcgUXVlc3Rpb25MaXN0KCBvcHRpb25zICk7XG5cdFx0fVxuXG5cdH0sIERldGFjaGFibGUsIEVkaXRhYmxlLCBTdWJ2aWV3LCBUcmFzaGFibGUsIFNldHRpbmdzRmllbGRzICkgKTtcblxufSApO1xuXG4vKipcbiAqIFNpbmdsZSBBc3NpZ25tZW50IFZpZXdcbiAqIEBzaW5jZSAgICAzLjE3LjBcbiAqIEB2ZXJzaW9uICAzLjE3LjdcbiAqL1xuZGVmaW5lKCAnVmlld3MvQXNzaWdubWVudCcsW1xuXHRcdCdWaWV3cy9Qb3BvdmVyJyxcblx0XHQnVmlld3MvUG9zdFNlYXJjaCcsXG5cdFx0J1ZpZXdzL19EZXRhY2hhYmxlJyxcblx0XHQnVmlld3MvX0VkaXRhYmxlJyxcblx0XHQnVmlld3MvX1RyYXNoYWJsZScsXG5cdFx0J1ZpZXdzL19TdWJ2aWV3Jyxcblx0XHQnVmlld3MvU2V0dGluZ3NGaWVsZHMnXG5cdF0sIGZ1bmN0aW9uKFxuXHRcdFBvcG92ZXIsXG5cdFx0UG9zdFNlYXJjaCxcblx0XHREZXRhY2hhYmxlLFxuXHRcdEVkaXRhYmxlLFxuXHRcdFRyYXNoYWJsZSxcblx0XHRTdWJ2aWV3LFxuXHRcdFNldHRpbmdzRmllbGRzXG5cdCkge1xuXG5cdHJldHVybiBCYWNrYm9uZS5WaWV3LmV4dGVuZCggXy5kZWZhdWx0cygge1xuXG5cdFx0LyoqXG5cdFx0ICogQ3VycmVudCB2aWV3IHN0YXRlXG5cdFx0ICogQHR5cGUgIHtTdHJpbmd9XG5cdFx0ICovXG5cdFx0c3RhdGU6ICdkZWZhdWx0JyxcblxuXHRcdC8qKlxuXHRcdCAqIEN1cnJlbnQgU3Vidmlld3Ncblx0XHQgKiBAdHlwZSAge09iamVjdH1cblx0XHQgKi9cblx0XHR2aWV3czoge1xuXHRcdFx0c2V0dGluZ3M6IHtcblx0XHRcdFx0Y2xhc3M6IFNldHRpbmdzRmllbGRzLFxuXHRcdFx0XHRpbnN0YW5jZTogbnVsbCxcblx0XHRcdFx0c3RhdGU6ICdkZWZhdWx0Jyxcblx0XHRcdH0sXG5cdFx0fSxcblxuXHRcdGVsOiAnI2xsbXMtZWRpdG9yLWFzc2lnbm1lbnQnLFxuXG5cdFx0LyoqXG5cdFx0ICogRE9NIEV2ZW50c1xuXHRcdCAqIEByZXR1cm4gICBvYmpcblx0XHQgKiBAc2luY2UgICAgMy4xNy4xXG5cdFx0ICogQHZlcnNpb24gIDMuMTcuMVxuXHRcdCAqL1xuXHRcdGV2ZW50czogZnVuY3Rpb24oKSB7XG5cdFx0XHR2YXIgYWRkb25fZXZlbnRzID0gdGhpcy5pc19hZGRvbl9hdmFpbGFibGUoKSA/IHdpbmRvdy5sbG1zX2J1aWxkZXIuYXNzaWdubWVudHMuZ2V0X3ZpZXdfZXZlbnRzKCkgOiB7fTtcblx0XHRcdHJldHVybiBfLmRlZmF1bHRzKCB7XG5cdFx0XHRcdCdjbGljayAjbGxtcy1leGlzdGluZy1hc3NpZ25tZW50JzogJ2FkZF9leGlzdGluZ19hc3NpZ25tZW50X2NsaWNrJyxcblx0XHRcdFx0J2NsaWNrICNsbG1zLW5ldy1hc3NpZ25tZW50JzogJ2FkZF9uZXdfYXNzaWdubWVudCcsXG5cdFx0XHR9LCBEZXRhY2hhYmxlLmV2ZW50cywgRWRpdGFibGUuZXZlbnRzLCBUcmFzaGFibGUuZXZlbnRzLCBhZGRvbl9ldmVudHMgKTtcblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogV3JhcHBlciBUYWcgbmFtZVxuXHRcdCAqIEB0eXBlICB7U3RyaW5nfVxuXHRcdCAqL1xuXHRcdHRhZ05hbWU6ICdkaXYnLFxuXG5cdFx0LyoqXG5cdFx0ICogR2V0IHRoZSB1bmRlcnNjb3JlIHRlbXBsYXRlXG5cdFx0ICogQHR5cGUgIHtbdHlwZV19XG5cdFx0ICovXG5cdFx0dGVtcGxhdGU6IHdwLnRlbXBsYXRlKCAnbGxtcy1hc3NpZ25tZW50LXRlbXBsYXRlJyApLFxuXG5cdFx0LyoqXG5cdFx0ICogSW5pdGlhbGl6YXRpb24gY2FsbGJhY2sgZnVuYyAocmVuZGVycyB0aGUgZWxlbWVudCBvbiBzY3JlZW4pXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNy4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTcuMlxuXHRcdCAqL1xuXHRcdGluaXRpYWxpemU6IGZ1bmN0aW9uKCBkYXRhICkge1xuXG5cdFx0XHR0aGlzLmxlc3NvbiA9IGRhdGEubGVzc29uO1xuXG5cdFx0XHQvLyBpbml0aWFsaXplIHRoZSBtb2RlbCBpZiB0aGUgYXNzaWdubWVudCBpcyBlbmFibGVkIG9yIGl0J3MgZGlzYWJsZWQgYnV0IHdlIHN0aWxsIGhhdmUgZGF0YSBmb3IgYSBhc3NpZ25tZW50XG5cdFx0XHRpZiAoICd5ZXMnID09PSB0aGlzLmxlc3Nvbi5nZXQoICdhc3NpZ25tZW50X2VuYWJsZWQnICkgfHwgISBfLmlzRW1wdHkoIHRoaXMubGVzc29uLmdldCggJ2Fzc2lnbm1lbnQnICkgKSApIHtcblxuXHRcdFx0XHR0aGlzLm1vZGVsID0gdGhpcy5sZXNzb24uZ2V0KCAnYXNzaWdubWVudCcgKTtcblxuXHRcdFx0XHQvKipcblx0XHRcdFx0ICogQHRvZG8gIHRoaXMgaXMgYSB0ZXJyaWxiZSB0ZXJyaWJsZSBwYXRjaFxuXHRcdFx0XHQgKiAgICAgICAgSSd2ZSBzcGVudCBuZWFybHkgMyBkYXlzIHRyeWluZyB0byBmaWd1cmUgb3V0IGhvdyB0byBub3QgdXNlIHRoaXMgbGluZSBvZiBjb2RlXG5cdFx0XHRcdCAqICAgICAgICBJU1NVRSBSRVBST0RVQ1RJT046XG5cdFx0XHRcdCAqICAgICAgICBPcGVuIGNvdXJzZSBidWlsZGVyXG5cdFx0XHRcdCAqICAgICAgICBPcGVuIGEgbGVzc29uIChBKSBhbmQgYWRkIGEgYXNzaWdubWVudFxuXHRcdFx0XHQgKiAgICAgICAgU3dpdGNoIHRvIGEgbmV3IGxlc3NvbiAoQilcblx0XHRcdFx0ICogICAgICAgIEFkZCBhIG5ldyBhc3NpZ25tZW50XG5cdFx0XHRcdCAqICAgICAgICBSZXR1cm4gdG8gbGVzc29uIEEgYW5kIHRoZSBhc3NpZ25tZW50J3MgcGFyZW50IHdpbGwgYmUgc2V0IHRvIExFU1NPTiBCXG5cdFx0XHRcdCAqICAgICAgICBUaGlzIHdpbGwgaGFwcGVuIGZvciAqZXZlcnkqIGFzc2lnbm1lbnQgaW4gdGhlIGJ1aWxkZXIuLi5cblx0XHRcdFx0ICogICAgICAgIEFkZGluZyB0aGlzIHNldF9wYXJlbnQgb24gaW5pdCBndWFyYW50ZWVzIHRoYXQgdGhlIGFzc2lnbm1lbnQncyBjb3JyZWN0IHBhcmVudCBpcyBzZXRcblx0XHRcdFx0ICogICAgICAgIGFmdGVyIGFkZGluZyBuZXcgYXNzaWdubWVudCdzIHRvIG90aGVyIGxlc3NvbnNcblx0XHRcdFx0ICogICAgICAgIGl0J3MgYXdmdWwgYW5kIGl0J3MgZ3Jvc3MuLi5cblx0XHRcdFx0ICogICAgICAgIEknbSBjb25mdXNlZCBhbmQgdGlyZWQgYW5kIGdvaW5nIHRvIG1pc3MgcmVsZWFzZSBkYXRlcyBhZ2FpbiBiZWNhdXNlIG9mIGl0XG5cdFx0XHRcdCAqL1xuXHRcdFx0XHR0aGlzLm1vZGVsLnNldF9wYXJlbnQoIHRoaXMubGVzc29uICk7XG5cblx0XHRcdH1cblxuXHRcdFx0dGhpcy5vbiggJ21vZGVsLXRyYXNoZWQnLCB0aGlzLm9uX3RyYXNoZWQgKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBDb21waWxlcyB0aGUgdGVtcGxhdGUgYW5kIHJlbmRlcnMgdGhlIHZpZXdcblx0XHQgKiBAcmV0dXJuICAgc2VsZiAoZm9yIGNoYWluaW5nKVxuXHRcdCAqIEBzaW5jZSAgICAzLjE3LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNy43XG5cdFx0ICovXG5cdFx0cmVuZGVyOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0dGhpcy4kZWwuaHRtbCggdGhpcy50ZW1wbGF0ZSggdGhpcy5tb2RlbCApICk7XG5cblx0XHRcdGlmICggdGhpcy5tb2RlbCAmJiB0aGlzLmlzX2FkZG9uX2F2YWlsYWJsZSgpICkge1xuXG5cdFx0XHRcdHRoaXMuc3RvcExpc3RlbmluZyggdGhpcy5tb2RlbCwgJ2NoYW5nZTphc3NpZ25tZW50X3R5cGUnLCB0aGlzLnJlbmRlciApO1xuXG5cdFx0XHRcdHRoaXMucmVuZGVyX3N1YnZpZXcoICdzZXR0aW5ncycsIHtcblx0XHRcdFx0XHRlbDogJyNsbG1zLWFzc2lnbm1lbnQtc2V0dGluZ3MtZmllbGRzJyxcblx0XHRcdFx0XHRtb2RlbDogdGhpcy5tb2RlbCxcblx0XHRcdFx0fSApO1xuXG5cdFx0XHRcdC8vIHRoaXMuaW5pdF9kYXRlcGlja2VycygpO1xuXHRcdFx0XHR0aGlzLmluaXRfc2VsZWN0cygpO1xuXG5cdFx0XHRcdHdpbmRvdy5sbG1zX2J1aWxkZXIuYXNzaWdubWVudHMucmVuZGVyX2VkaXRvciggdGhpcyApO1xuXG5cdFx0XHRcdHRoaXMubGlzdGVuVG8oIHRoaXMubW9kZWwsICdjaGFuZ2U6YXNzaWdubWVudF90eXBlJywgdGhpcy5yZW5kZXIgKTtcblxuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gdGhpcztcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBBZGRzIGEgbmV3IGFzc2lnbm1lbnQgdG8gYSBsZXNzb24gd2hpY2ggY3VycmVudGx5IGhhcyBubyBhc3NpZ25tZW50IGFzc29jaWF0ZWQgd2xpdGggaXRcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE3LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNy4wXG5cdFx0ICovXG5cdFx0YWRkX25ld19hc3NpZ25tZW50OiBmdW5jdGlvbigpIHtcblxuXHRcdFx0aWYgKCB0aGlzLmlzX2FkZG9uX2F2YWlsYWJsZSgpICkge1xuXG5cdFx0XHRcdHRoaXMubW9kZWwgPSB3aW5kb3cubGxtc19idWlsZGVyLmFzc2lnbm1lbnRzLmdldF9hc3NpZ25tZW50KCB7XG5cdFx0XHRcdFx0LyogdHJhbnNsYXRvcnM6ICUxJHMgPSBhc3NvY2lhdGVkIGxlc3NvbiB0aXRsZSAqL1xuXHRcdFx0XHRcdHRpdGxlOiBMTE1TLmwxMG4ucmVwbGFjZSggJyUxJHMgQXNzaWdubWVudCcsIHtcblx0XHRcdFx0XHRcdCclMSRzJzogdGhpcy5sZXNzb24uZ2V0KCAndGl0bGUnICksXG5cdFx0XHRcdFx0fSApLFxuXHRcdFx0XHRcdGxlc3Nvbl9pZDogdGhpcy5sZXNzb24uZ2V0KCAnaWQnICksXG5cdFx0XHRcdH0gKTtcblxuXHRcdFx0XHR0aGlzLmxlc3Nvbi5zZXQoICdhc3NpZ25tZW50X2VuYWJsZWQnLCAneWVzJyApO1xuXHRcdFx0XHR0aGlzLmxlc3Nvbi5zZXQoICdhc3NpZ25tZW50JywgdGhpcy5tb2RlbCApO1xuXG5cdFx0XHRcdHRoaXMucmVuZGVyKCk7XG5cblx0XHRcdH0gZWxzZSB7XG5cblx0XHRcdFx0dGhpcy5zaG93X2FkX3BvcG92ZXIoICcjbGxtcy1uZXctYXNzaWdubWVudCcgKTtcblxuXHRcdFx0fVxuXG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogV2hlbiBhbiBhc3NpZ25tZW50IGlzIHNlbGVjdGVkIGZyb20gdGhlIHBvc3Qgc2VsZWN0IHBvcG92ZXJcblx0XHQgKiBpbnN0YW50aWF0ZSBpdCBhbmQgYWRkIGl0IHRvIHRoZSBjdXJyZW50IGxlc3NvblxuXHRcdCAqIEBwYXJhbSAgICBvYmplY3QgICBldmVudCAgZGF0YSBmcm9tIHRoZSBzZWxlY3QyIHNlbGVjdCBldmVudFxuXHRcdCAqIEBzaW5jZSAgICAzLjE3LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNy4wXG5cdFx0ICovXG5cdFx0YWRkX2V4aXN0aW5nX2Fzc2lnbm1lbnQ6IGZ1bmN0aW9uKCBldmVudCApIHtcblxuXHRcdFx0dGhpcy5wb3N0X3NlYXJjaF9wb3BvdmVyLmhpZGUoKTtcblxuXHRcdFx0dmFyIGFzc2lnbm1lbnQgPSBldmVudC5kYXRhO1xuXG5cdFx0XHRpZiAoICdjbG9uZScgPT09IGV2ZW50LmFjdGlvbiApIHtcblxuXHRcdFx0XHRkZWxldGUgYXNzaWdubWVudC5pZDtcblxuXHRcdFx0fSBlbHNlIHtcblxuXHRcdFx0XHRhc3NpZ25tZW50Ll9mb3JjZVN5bmMgPSB0cnVlO1xuXG5cdFx0XHR9XG5cblx0XHRcdGFzc2lnbm1lbnQubGVzc29uX2lkID0gdGhpcy5sZXNzb24uZ2V0KCAnaWQnIClcblxuXHRcdFx0YXNzaWdubWVudCA9IHdpbmRvdy5sbG1zX2J1aWxkZXIuY29uc3RydWN0LmdldF9tb2RlbCggJ0Fzc2lnbm1lbnQnLCBhc3NpZ25tZW50ICk7XG5cblx0XHRcdHRoaXMubGVzc29uLnNldCggJ2Fzc2lnbm1lbnRfZW5hYmxlZCcsICd5ZXMnICk7XG5cdFx0XHR0aGlzLmxlc3Nvbi5zZXQoICdhc3NpZ25tZW50JywgYXNzaWdubWVudCApO1xuXHRcdFx0dGhpcy5tb2RlbCA9IGFzc2lnbm1lbnQ7XG5cblx0XHRcdHRoaXMucmVuZGVyKCk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogT3BlbiBhZGQgZXhpc3RpbmcgYXNzaWdubWVudCBwb3BvdmVyXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIGV2ZW50ICBKUyBldmVudCBvYmplY3Rcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE3LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNy4wXG5cdFx0ICovXG5cdFx0YWRkX2V4aXN0aW5nX2Fzc2lnbm1lbnRfY2xpY2s6IGZ1bmN0aW9uKCBldmVudCApIHtcblxuXHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuXHRcdFx0aWYgKCB0aGlzLmlzX2FkZG9uX2F2YWlsYWJsZSgpICkge1xuXG5cdFx0XHRcdHRoaXMucG9zdF9zZWFyY2hfcG9wb3ZlciA9IG5ldyBQb3BvdmVyKCB7XG5cdFx0XHRcdFx0ZWw6ICcjbGxtcy1leGlzdGluZy1hc3NpZ25tZW50Jyxcblx0XHRcdFx0XHRhcmdzOiB7XG5cdFx0XHRcdFx0XHRiYWNrZHJvcDogdHJ1ZSxcblx0XHRcdFx0XHRcdGNsb3NlYWJsZTogdHJ1ZSxcblx0XHRcdFx0XHRcdGNvbnRhaW5lcjogJy53cmFwLmxpZnRlcmxtcy5sbG1zLWJ1aWxkZXInLFxuXHRcdFx0XHRcdFx0ZGlzbWlzc2libGU6IHRydWUsXG5cdFx0XHRcdFx0XHRwbGFjZW1lbnQ6ICdsZWZ0Jyxcblx0XHRcdFx0XHRcdHdpZHRoOiA0ODAsXG5cdFx0XHRcdFx0XHR0aXRsZTogTExNUy5sMTBuLnRyYW5zbGF0ZSggJ0FkZCBFeGlzdGluZyBBc3NpZ25tZW50JyApLFxuXHRcdFx0XHRcdFx0Y29udGVudDogbmV3IFBvc3RTZWFyY2goIHtcblx0XHRcdFx0XHRcdFx0cG9zdF90eXBlOiAnbGxtc19hc3NpZ25tZW50Jyxcblx0XHRcdFx0XHRcdFx0c2VhcmNoaW5nX21lc3NhZ2U6IExMTVMubDEwbi50cmFuc2xhdGUoICdTZWFyY2ggZm9yIGV4aXN0aW5nIGFzc2lnbm1lbnRzLi4uJyApLFxuXHRcdFx0XHRcdFx0fSApLnJlbmRlcigpLiRlbCxcblx0XHRcdFx0XHRcdG9uSGlkZTogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHRcdEJhY2tib25lLnB1YlN1Yi5vZmYoICdhc3NpZ25tZW50LXNlYXJjaC1zZWxlY3QnICk7XG5cdFx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSApO1xuXG5cdFx0XHRcdHRoaXMucG9zdF9zZWFyY2hfcG9wb3Zlci5zaG93KCk7XG5cdFx0XHRcdEJhY2tib25lLnB1YlN1Yi5vbmNlKCAnYXNzaWdubWVudC1zZWFyY2gtc2VsZWN0JywgdGhpcy5hZGRfZXhpc3RpbmdfYXNzaWdubWVudCwgdGhpcyApO1xuXG5cdFx0XHR9IGVsc2Uge1xuXG5cdFx0XHRcdHRoaXMuc2hvd19hZF9wb3BvdmVyKCAnI2xsbXMtZXhpc3RpbmctYXNzaWdubWVudCcgKTtcblxuXHRcdFx0fVxuXG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogRGV0ZXJtaW5lIGlmIEFzc2lnbm1lbnRzIGFkZG9uIGlzIGF2YWlsYWJsZSB0byB1c2Vcblx0XHQgKiBAcmV0dXJuICAge0Jvb2xlYW59XG5cdFx0ICogQHNpbmNlICAgIDMuMTcuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE3LjBcblx0XHQgKi9cblx0XHRpc19hZGRvbl9hdmFpbGFibGU6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHRyZXR1cm4gKCB3aW5kb3cubGxtc19idWlsZGVyLmFzc2lnbm1lbnRzICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogQ2FsbGVkIHdoZW4gYXNzaWdubWVudCBpcyB0cmFzaGVkXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIGFzc2lnbm1lbnQgIEFzc2lnbm1lbnQgbW9kZWxcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE3LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNy4wXG5cdFx0ICovXG5cdFx0b25fdHJhc2hlZDogZnVuY3Rpb24oIGFzc2lnbm1lbnQgKSB7XG5cblx0XHRcdHRoaXMubGVzc29uLnNldCggJ2Fzc2lnbm1lbnRfZW5hYmxlZCcsICdubycgKTtcblx0XHRcdHRoaXMubGVzc29uLnNldCggJ2Fzc2lnbm1lbnQnLCAnJyApO1xuXG5cdFx0XHRkZWxldGUgdGhpcy5tb2RlbDtcblxuXHRcdFx0dGhpcy5yZW5kZXIoKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBTaG93cyBhIGRpcnR5IGRpcnR5IGFkIHBvcG9ldmVyIGZvciBhZHZhbmNlZCBhc3NpZ25tZW50c1xuXHRcdCAqIEBwYXJhbSAgICBzdHJpbmcgICBlbCAgalF1ZXJ5IHNlbGVjdG9yIHN0cmluZ1xuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTcuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE3LjBcblx0XHQgKi9cblx0XHRzaG93X2FkX3BvcG92ZXI6IGZ1bmN0aW9uKCBlbCApIHtcblxuXHRcdFx0dmFyIGgzID0gTExNUy5sMTBuLnRyYW5zbGF0ZSggJ0dldCBZb3VyIFN0dWRlbnRzIFRha2luZyBBY3Rpb24nICksXG5cdFx0XHRcdHAgPSAnR3JlYXQgbGVhcm5pbmcgY29udGVudCBpcyBvbmx5IGhhbGYgb2YgdGVhY2hpbmcgb25saW5lLiBXaGVuIHlvdXIgbGVhcm5lcnMgZnVsbHkgZW5nYWdlLCB0aGV5IHdpbGwgdGFrZSB5b3VyIGNvbnRlbnQgYW5kIG1vdmUgaW50byBhY3Rpb24uIFJlbW92ZSBiYXJyaWVycyBmb3IgeW91ciBsZWFybmVycyBieSB0ZWxsaW5nIHRoZW0gd2hhdCB0byBkbyB0byBhcHBseSB3aGF0IHRoZXkganVzdCBsZWFybmVkLiBDcmVhdGUgZ3JhZGVkIGFzc2lnbm1lbnRzIG9yIHNpbXBseSBnaXZlIHRoZW0gYSBjaGVja2xpc3Qgb2YgYWN0aW9uIGl0ZW1zIHRvIGNvbXBsZXRlIGJlZm9yZSBtb3Zpbmcgb24uJyxcblx0XHRcdFx0YnRuID0gTExNUy5sMTBuLnRyYW5zbGF0ZSggJ0dldCBBc3NpZ25tZW50cyBOb3chJyApLFxuXHRcdFx0XHR1cmwgPSAnaHR0cHM6Ly9saWZ0ZXJsbXMuY29tL3Byb2R1Y3QvbGlmdGVybG1zLWFzc2lnbm1lbnRzP3V0bV9zb3VyY2U9TGlmdGVyTE1TJTIwUGx1Z2luJnV0bV9tZWRpdW09QXNzaWdubWVudCUyMEJ1aWxkZXIlMjBCdXR0b24mdXRtX2NhbXBhaWduPUFzc2lnbm1lbnQlMjBBZGRvbiUyMFVwc2VsbCZ1dG1fY29udGVudD0zLjE3LjAnO1xuXG5cdFx0XHR0aGlzLmFkX3BvcG92ZXIgPSBuZXcgUG9wb3Zlcigge1xuXHRcdFx0XHRlbDogZWwsXG5cdFx0XHRcdGFyZ3M6IHtcblx0XHRcdFx0XHRiYWNrZHJvcDogdHJ1ZSxcblx0XHRcdFx0XHRjbG9zZWFibGU6IHRydWUsXG5cdFx0XHRcdFx0Y29udGFpbmVyOiAnLndyYXAubGlmdGVybG1zLmxsbXMtYnVpbGRlcicsXG5cdFx0XHRcdFx0ZGlzbWlzc2libGU6IHRydWUsXG5cdFx0XHRcdFx0Ly8gcGxhY2VtZW50OiAnbGVmdCcsXG5cdFx0XHRcdFx0d2lkdGg6IDM4MCxcblx0XHRcdFx0XHR0aXRsZTogTExNUy5sMTBuLnRyYW5zbGF0ZSggJ1VubG9jayBMaWZ0ZXJMTVMgQXNzaWdubWVudHMnICksXG5cdFx0XHRcdFx0Y29udGVudDogJzxoMz4nICsgaDMgKyAnPC9oMz48cD4nICsgcCArICc8L3A+PGJyPjxwPjxhIGNsYXNzPVwibGxtcy1idXR0b24tcHJpbWFyeVwiIGhyZWY9XCInICsgdXJsICsgJ1wiIHRhcmdldD1cIl9ibGFua1wiPicgKyBidG4gKyAnPC9hPjwvcD4nXG5cdFx0XHRcdH1cblx0XHRcdH0gKTtcblxuXHRcdFx0dGhpcy5hZF9wb3BvdmVyLnNob3coKTtcblxuXHRcdH0sXG5cblx0fSwgRGV0YWNoYWJsZSwgRWRpdGFibGUsIFRyYXNoYWJsZSwgU3VidmlldywgU2V0dGluZ3NGaWVsZHMgKSApO1xuXG59ICk7XG5cbi8qKlxuICogU2lkZWJhciBFZGl0b3IgVmlld1xuICogQHNpbmNlICAgIDMuMTYuMFxuICogQHZlcnNpb24gIDMuMTcuMFxuICovXG5kZWZpbmUoICdWaWV3cy9FZGl0b3InLFtcblx0XHQnVmlld3MvTGVzc29uRWRpdG9yJyxcblx0XHQnVmlld3MvUXVpeicsXG5cdFx0J1ZpZXdzL0Fzc2lnbm1lbnQnLFxuXHRcdCdWaWV3cy9fU3Vidmlldydcblx0XSwgZnVuY3Rpb24oXG5cdFx0TGVzc29uRWRpdG9yLFxuXHRcdFF1aXosXG5cdFx0QXNzaWdubWVudCxcblx0XHRTdWJ2aWV3XG5cdCkge1xuXG5cdHJldHVybiBCYWNrYm9uZS5WaWV3LmV4dGVuZCggXy5kZWZhdWx0cygge1xuXG5cdFx0LyoqXG5cdFx0ICogQ3VycmVudCB2aWV3IHN0YXRlXG5cdFx0ICogQHR5cGUgIHtTdHJpbmd9XG5cdFx0ICovXG5cdFx0c3RhdGU6ICdsZXNzb24nLCAvLyBbbGVzc29ufHF1aXpdXG5cblx0XHQvKipcblx0XHQgKiBDdXJyZW50IFN1YnZpZXdzXG5cdFx0ICogQHR5cGUgIHtPYmplY3R9XG5cdFx0ICovXG5cdFx0dmlld3M6IHtcblx0XHRcdGxlc3Nvbjoge1xuXHRcdFx0XHRjbGFzczogTGVzc29uRWRpdG9yLFxuXHRcdFx0XHRpbnN0YW5jZTogbnVsbCxcblx0XHRcdFx0c3RhdGU6ICdsZXNzb24nLFxuXHRcdFx0fSxcblx0XHRcdGFzc2lnbm1lbnQ6IHtcblx0XHRcdFx0Y2xhc3M6IEFzc2lnbm1lbnQsXG5cdFx0XHRcdGluc3RhbmNlOiBudWxsLFxuXHRcdFx0XHRzdGF0ZTogJ2Fzc2lnbm1lbnQnLFxuXHRcdFx0fSxcblx0XHRcdHF1aXo6IHtcblx0XHRcdFx0Y2xhc3M6IFF1aXosXG5cdFx0XHRcdGluc3RhbmNlOiBudWxsLFxuXHRcdFx0XHRzdGF0ZTogJ3F1aXonLFxuXHRcdFx0fSxcblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogSFRNTCBlbGVtZW50IHNlbGVjdG9yXG5cdFx0ICogQHR5cGUgIHtTdHJpbmd9XG5cdFx0ICovXG5cdFx0ZWw6ICcjbGxtcy1lZGl0b3InLFxuXG5cdFx0ZXZlbnRzOiB7XG5cdFx0XHQnY2xpY2sgLmxsbXMtZWRpdG9yLW5hdiBhW2hyZWY9XCIjbGxtcy1lZGl0b3ItY2xvc2VcIl0nOiAnY2xvc2VfZWRpdG9yJyxcblx0XHRcdCdjbGljayAubGxtcy1lZGl0b3ItbmF2IGE6bm90KFtocmVmPVwiI2xsbXMtZWRpdG9yLWNsb3NlXCJdKSc6ICdzd2l0Y2hfdGFiJyxcblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogV3JhcHBlciBUYWcgbmFtZVxuXHRcdCAqIEB0eXBlICB7U3RyaW5nfVxuXHRcdCAqL1xuXHRcdHRhZ05hbWU6ICdkaXYnLFxuXG5cdFx0LyoqXG5cdFx0ICogR2V0IHRoZSB1bmRlcnNjb3JlIHRlbXBsYXRlXG5cdFx0ICogQHR5cGUgIHtbdHlwZV19XG5cdFx0ICovXG5cdFx0dGVtcGxhdGU6IHdwLnRlbXBsYXRlKCAnbGxtcy1lZGl0b3ItdGVtcGxhdGUnICksXG5cblx0XHQvKipcblx0XHQgKiBJbml0aWFsaXphdGlvbiBjYWxsYmFjayBmdW5jIChyZW5kZXJzIHRoZSBlbGVtZW50IG9uIHNjcmVlbilcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0aW5pdGlhbGl6ZTogZnVuY3Rpb24oIGRhdGEgKSB7XG5cblx0XHRcdHRoaXMuU2lkZWJhclZpZXcgPSBkYXRhLlNpZGViYXJWaWV3O1xuXHRcdFx0aWYgKCBkYXRhLnRhYiApIHtcblx0XHRcdFx0dGhpcy5zdGF0ZSA9IGRhdGEudGFiO1xuXHRcdFx0fVxuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIENvbXBpbGVzIHRoZSB0ZW1wbGF0ZSBhbmQgcmVuZGVycyB0aGUgdmlld1xuXHRcdCAqIEByZXR1cm4gICBzZWxmIChmb3IgY2hhaW5pbmcpXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRyZW5kZXI6IGZ1bmN0aW9uKCB2aWV3X2RhdGEgKSB7XG5cblx0XHRcdHZpZXdfZGF0YSA9IHZpZXdfZGF0YSB8fCB7fTtcblxuXHRcdFx0dGhpcy4kZWwuaHRtbCggdGhpcy50ZW1wbGF0ZSggdGhpcyApICk7XG5cblx0XHRcdHRoaXMucmVuZGVyX3N1YnZpZXdzKCBfLmV4dGVuZCggdmlld19kYXRhLCB7XG5cdFx0XHRcdGxlc3NvbjogdGhpcy5tb2RlbCxcblx0XHRcdH0gKSApO1xuXG5cdFx0XHRyZXR1cm4gdGhpcztcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBDbGljayBldmVudCBmb3IgY2xvc2Ugc2lkZWJhciBlZGl0b3IgYnV0dG9uXG5cdFx0ICogU2VuZHMgZXZlbnQgdG8gbWFpbiBTaWRlYmFyVmlldyB0byB0cmlnZ2VyIGVkaXRvciBjbG9zaW5nIGV2ZW50c1xuXHRcdCAqIEBwYXJhbSAgICBvYmogICBldmVudCAganMgZXZlbnQgb2JqXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGNsb3NlX2VkaXRvcjogZnVuY3Rpb24oIGV2ZW50ICkge1xuXG5cdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0QmFja2JvbmUucHViU3ViLnRyaWdnZXIoICdzaWRlYmFyLWVkaXRvci1jbG9zZScgKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBDbGljayBldmVudCBmb3Igc3dpdGNoaW5nIHRhYnMgaW4gdGhlIGVkaXRvciBuYXZpZ2F0aW9uXG5cdFx0ICogQHBhcmFtICAgIG9iamVjdCAgZXZlbnQgIGpzIGV2ZW50IG9iamVjdFxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRzd2l0Y2hfdGFiOiBmdW5jdGlvbiggZXZlbnQgKSB7XG5cblx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cblx0XHRcdHZhciAkYnRuID0gJCggZXZlbnQudGFyZ2V0ICksXG5cdFx0XHRcdHZpZXcgPSAkYnRuLmF0dHIoICdkYXRhLXZpZXcnICksXG5cdFx0XHRcdCR0YWIgPSB0aGlzLiRlbC5maW5kKCAkYnRuLmF0dHIoICdocmVmJyApICk7XG5cblx0XHRcdHRoaXMuc2V0X3N0YXRlKCB2aWV3ICkucmVuZGVyKCk7XG5cblx0XHRcdC8vIEJhY2tib25lLnB1YlN1Yi50cmlnZ2VyKCAnZWRpdG9yLXRhYi1hY3RpdmF0ZWQnLCAkYnRuLmF0dHIoICdocmVmJyApLnN1YnN0cmluZyggMSApICk7XG5cblx0XHR9LFxuXG5cdH0sIFN1YnZpZXcgKSApO1xuXG59ICk7XG5cbi8qKlxuICogU2lkZWJhciBFbGVtZW50cyBWaWV3XG4gKiBAc2luY2UgICAgMy4xNi4wXG4gKiBAdmVyc2lvbiAgMy4xNi4xMlxuICovXG5kZWZpbmUoICdWaWV3cy9FbGVtZW50cycsWyAnTW9kZWxzL1NlY3Rpb24nLCAnVmlld3MvU2VjdGlvbicsICdNb2RlbHMvTGVzc29uJywgJ1ZpZXdzL0xlc3NvbicsICdWaWV3cy9Qb3BvdmVyJywgJ1ZpZXdzL1Bvc3RTZWFyY2gnIF0sIGZ1bmN0aW9uKCBTZWN0aW9uLCBTZWN0aW9uVmlldywgTGVzc29uLCBMZXNzb25WaWV3LCBQb3BvdmVyLCBMZXNzb25TZWFyY2ggKSB7XG5cblx0cmV0dXJuIEJhY2tib25lLlZpZXcuZXh0ZW5kKCB7XG5cblx0XHQvKipcblx0XHQgKiBIVE1MIGVsZW1lbnQgc2VsZWN0b3Jcblx0XHQgKiBAdHlwZSAge1N0cmluZ31cblx0XHQgKi9cblx0XHRlbDogJyNsbG1zLWVsZW1lbnRzJyxcblxuXHRcdGV2ZW50czoge1xuXHRcdFx0J2NsaWNrICNsbG1zLW5ldy1zZWN0aW9uJzogJ2FkZF9uZXdfc2VjdGlvbicsXG5cdFx0XHQnY2xpY2sgI2xsbXMtbmV3LWxlc3Nvbic6ICdhZGRfbmV3X2xlc3NvbicsXG5cdFx0XHQnY2xpY2sgI2xsbXMtZXhpc3RpbmctbGVzc29uJzogJ2FkZF9leGlzdGluZ19sZXNzb24nLFxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBXcmFwcGVyIFRhZyBuYW1lXG5cdFx0ICogQHR5cGUgIHtTdHJpbmd9XG5cdFx0ICovXG5cdFx0dGFnTmFtZTogJ2RpdicsXG5cblx0XHQvKipcblx0XHQgKiBHZXQgdGhlIHVuZGVyc2NvcmUgdGVtcGxhdGVcblx0XHQgKiBAdHlwZSAge1t0eXBlXX1cblx0XHQgKi9cblx0XHR0ZW1wbGF0ZTogd3AudGVtcGxhdGUoICdsbG1zLWVsZW1lbnRzLXRlbXBsYXRlJyApLFxuXG5cdFx0LyoqXG5cdFx0ICogSW5pdGlhbGl6YXRpb24gY2FsbGJhY2sgZnVuYyAocmVuZGVycyB0aGUgZWxlbWVudCBvbiBzY3JlZW4pXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGluaXRpYWxpemU6IGZ1bmN0aW9uKCBkYXRhICkge1xuXG5cdFx0XHQvLyBzYXZlIGEgcmVmZXJlbmNlIHRvIHRoZSBtYWluIENvdXJzZSB2aWV3XG5cdFx0XHR0aGlzLlNpZGViYXJWaWV3ID0gZGF0YS5TaWRlYmFyVmlldztcblxuXHRcdFx0Ly8gd2F0Y2ggY291cnNlIHNlY3Rpb25zIGFuZCBlbmFibGUvZGlzYWJsZSBsZXNzb24gYnV0dG9ucyBjb25kaXRpb25hbGx5XG5cdFx0XHR0aGlzLmxpc3RlblRvKCB0aGlzLlNpZGViYXJWaWV3LkNvdXJzZVZpZXcubW9kZWwuZ2V0KCAnc2VjdGlvbnMnICksICdhZGQnLCB0aGlzLm1heWJlX2Rpc2FibGVfYnV0dG9ucyApO1xuXHRcdFx0dGhpcy5saXN0ZW5UbyggdGhpcy5TaWRlYmFyVmlldy5Db3Vyc2VWaWV3Lm1vZGVsLmdldCggJ3NlY3Rpb25zJyApLCAncmVtb3ZlJywgdGhpcy5tYXliZV9kaXNhYmxlX2J1dHRvbnMgKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBDb21waWxlcyB0aGUgdGVtcGxhdGUgYW5kIHJlbmRlcnMgdGhlIHZpZXdcblx0XHQgKiBAcmV0dXJuICAgc2VsZiAoZm9yIGNoYWluaW5nKVxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0cmVuZGVyOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0dGhpcy4kZWwuaHRtbCggdGhpcy50ZW1wbGF0ZSgpICk7XG5cdFx0XHR0aGlzLmRyYWdnYWJsZSgpO1xuXHRcdFx0dGhpcy5tYXliZV9kaXNhYmxlX2J1dHRvbnMoKTtcblxuXHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0fSxcblxuXHRcdGRyYWdnYWJsZTogZnVuY3Rpb24oKSB7XG5cblx0XHRcdCQoICcjbGxtcy1uZXctc2VjdGlvbicgKS5kcmFnZ2FibGUoIHtcblx0XHRcdFx0YXBwZW5kVG86ICcjbGxtcy1zZWN0aW9ucycsXG5cdFx0XHRcdGNhbmNlbDogZmFsc2UsXG5cdFx0XHRcdGNvbm5lY3RUb1NvcnRhYmxlOiAnLmxsbXMtc2VjdGlvbnMnLFxuXHRcdFx0XHRoZWxwZXI6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdHJldHVybiBuZXcgU2VjdGlvblZpZXcoIHsgbW9kZWw6IG5ldyBTZWN0aW9uKCkgfSApLnJlbmRlcigpLiRlbDtcblx0XHRcdFx0fSxcblx0XHRcdFx0c3RhcnQ6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdCQoICcubGxtcy1zZWN0aW9ucycgKS5hZGRDbGFzcyggJ2RyYWdnaW5nJyApO1xuXHRcdFx0XHR9LFxuXHRcdFx0XHRzdG9wOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHQkKCAnLmxsbXMtc2VjdGlvbnMnICkucmVtb3ZlQ2xhc3MoICdkcmFnZ2luZycgKTtcblx0XHRcdFx0fSxcblx0XHRcdH0gKTtcblxuXHRcdFx0JCggJyNsbG1zLW5ldy1sZXNzb24nICkuZHJhZ2dhYmxlKCB7XG5cdFx0XHRcdC8vIGFwcGVuZFRvOiAnI2xsbXMtc2VjdGlvbnMgLmxsbXMtc2VjdGlvbjpmaXJzdC1jaGlsZCAubGxtcy1sZXNzb25zJyxcblx0XHRcdFx0YXBwZW5kVG86ICcjbGxtcy1zZWN0aW9ucycsXG5cdFx0XHRcdGNhbmNlbDogZmFsc2UsXG5cdFx0XHRcdGNvbm5lY3RUb1NvcnRhYmxlOiAnLmxsbXMtbGVzc29ucycsXG5cdFx0XHRcdGhlbHBlcjogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0cmV0dXJuIG5ldyBMZXNzb25WaWV3KCB7IG1vZGVsOiBuZXcgTGVzc29uKCkgfSApLnJlbmRlcigpLiRlbDtcblx0XHRcdFx0fSxcblx0XHRcdFx0c3RhcnQ6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHRcdFx0JCggJy5sbG1zLWxlc3NvbnMnICkuYWRkQ2xhc3MoICdkcmFnZ2luZycgKTtcblxuXHRcdFx0XHR9LFxuXHRcdFx0XHRzdG9wOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHQkKCAnLmxsbXMtbGVzc29ucycgKS5yZW1vdmVDbGFzcyggJ2RyYWdnaW5nJyApO1xuXHRcdFx0XHRcdCQoICcuZHJhZy1leHBhbmRlZCcgKS5yZW1vdmVDbGFzcyggJy5kcmFnLWV4cGFuZGVkJyApO1xuXHRcdFx0XHR9LFxuXHRcdFx0fSApO1xuXG5cdFx0fSxcblxuXHRcdGFkZF9uZXdfc2VjdGlvbjogZnVuY3Rpb24oIGV2ZW50ICkge1xuXG5cdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0QmFja2JvbmUucHViU3ViLnRyaWdnZXIoICdhZGQtbmV3LXNlY3Rpb24nICk7XG5cdFx0fSxcblxuXHRcdGFkZF9uZXdfbGVzc29uOiBmdW5jdGlvbiggZXZlbnQgKSB7XG5cdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0QmFja2JvbmUucHViU3ViLnRyaWdnZXIoICdhZGQtbmV3LWxlc3NvbicgKTtcblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogU2hvdyB0aGUgcG9wb3ZlciB0byBhZGQgYW4gZXhpc3RpbmcgbGVzc29uc1xuXHRcdCAqIEBwYXJhbSAgICBvYmplY3QgICBldmVudCAgSlMgRXZlbnQgT0JqZWN0XG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4xMlxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjEyXG5cdFx0ICovXG5cdFx0YWRkX2V4aXN0aW5nX2xlc3NvbjogZnVuY3Rpb24oIGV2ZW50ICkge1xuXG5cdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG5cdFx0XHR2YXIgcG9wID0gbmV3IFBvcG92ZXIoIHtcblx0XHRcdFx0ZWw6ICcjbGxtcy1leGlzdGluZy1sZXNzb24nLFxuXHRcdFx0XHRhcmdzOiB7XG5cdFx0XHRcdFx0YmFja2Ryb3A6IHRydWUsXG5cdFx0XHRcdFx0Y2xvc2VhYmxlOiB0cnVlLFxuXHRcdFx0XHRcdGNvbnRhaW5lcjogJy53cmFwLmxpZnRlcmxtcy5sbG1zLWJ1aWxkZXInLFxuXHRcdFx0XHRcdGRpc21pc3NpYmxlOiB0cnVlLFxuXHRcdFx0XHRcdHBsYWNlbWVudDogJ2xlZnQnLFxuXHRcdFx0XHRcdHdpZHRoOiA0ODAsXG5cdFx0XHRcdFx0dGl0bGU6IExMTVMubDEwbi50cmFuc2xhdGUoICdBZGQgRXhpc3RpbmcgTGVzc29uJyApLFxuXHRcdFx0XHRcdGNvbnRlbnQ6IG5ldyBMZXNzb25TZWFyY2goIHtcblx0XHRcdFx0XHRcdHBvc3RfdHlwZTogJ2xlc3NvbicsXG5cdFx0XHRcdFx0XHRzZWFyY2hpbmdfbWVzc2FnZTogTExNUy5sMTBuLnRyYW5zbGF0ZSggJ1NlYXJjaCBmb3IgZXhpc3RpbmcgbGVzc29ucy4uLicgKSxcblx0XHRcdFx0XHR9ICkucmVuZGVyKCkuJGVsLFxuXHRcdFx0XHR9XG5cdFx0XHR9ICk7XG5cblx0XHRcdHBvcC5zaG93KCk7XG5cdFx0XHRCYWNrYm9uZS5wdWJTdWIub24oICdsZXNzb24tc2VhcmNoLXNlbGVjdCcsIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRwb3AuaGlkZSgpXG5cdFx0XHR9ICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogRGlzYWJsZXMgbGVzc29uIGFkZCBidXR0b25zIGlmIG5vIHNlY3Rpb25zIGFyZSBhdmFpbGFibGUgdG8gYWRkIGEgbGVzc29uIHRvXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdG1heWJlX2Rpc2FibGVfYnV0dG9uczogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHZhciAkZWxzID0gJCggJyNsbG1zLW5ldy1sZXNzb24sICNsbG1zLWV4aXN0aW5nLWxlc3NvbicgKTtcblxuXHRcdFx0aWYgKCAhIHRoaXMuU2lkZWJhclZpZXcuQ291cnNlVmlldy5tb2RlbC5nZXQoICdzZWN0aW9ucycgKS5sZW5ndGggKSB7XG5cdFx0XHRcdCRlbHMuYXR0ciggJ2Rpc2FibGVkJywgJ2Rpc2FibGVkJyApO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0JGVscy5yZW1vdmVBdHRyKCAnZGlzYWJsZWQnICk7XG5cdFx0XHR9XG5cblx0XHR9LFxuXG5cdH0gKTtcblxufSApO1xuXG4vKipcbiAqIFNpZGViYXIgVXRpbGl0aWVzIFZpZXdcbiAqIEBzaW5jZSAgICAzLjE2LjBcbiAqIEB2ZXJzaW9uICAzLjE2LjBcbiAqL1xuZGVmaW5lKCAnVmlld3MvVXRpbGl0aWVzJyxbXSwgZnVuY3Rpb24oKSB7XG5cblx0cmV0dXJuIEJhY2tib25lLlZpZXcuZXh0ZW5kKCB7XG5cblx0XHQvKipcblx0XHQgKiBIVE1MIGVsZW1lbnQgc2VsZWN0b3Jcblx0XHQgKiBAdHlwZSAge1N0cmluZ31cblx0XHQgKi9cblx0XHRlbDogJyNsbG1zLXV0aWxpdGllcycsXG5cblx0XHRldmVudHM6IHtcblx0XHRcdCdjbGljayAjbGxtcy1jb2xsYXBzZS1hbGwnOiAnY29sbGFwc2VfYWxsJyxcblx0XHRcdCdjbGljayAjbGxtcy1leHBhbmQtYWxsJzogJ2V4cGFuZF9hbGwnXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFdyYXBwZXIgVGFnIG5hbWVcblx0XHQgKiBAdHlwZSAge1N0cmluZ31cblx0XHQgKi9cblx0XHR0YWdOYW1lOiAnZGl2JyxcblxuXHRcdC8qKlxuXHRcdCAqIEdldCB0aGUgdW5kZXJzY29yZSB0ZW1wbGF0ZVxuXHRcdCAqIEB0eXBlICB7W3R5cGVdfVxuXHRcdCAqL1xuXHRcdHRlbXBsYXRlOiB3cC50ZW1wbGF0ZSggJ2xsbXMtdXRpbGl0aWVzLXRlbXBsYXRlJyApLFxuXG5cdFx0LyoqXG5cdFx0ICogSW5pdGlhbGl6YXRpb24gY2FsbGJhY2sgZnVuYyAocmVuZGVycyB0aGUgZWxlbWVudCBvbiBzY3JlZW4pXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGluaXRpYWxpemU6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHQvLyB0aGlzLnJlbmRlcigpO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIENvbXBpbGVzIHRoZSB0ZW1wbGF0ZSBhbmQgcmVuZGVycyB0aGUgdmlld1xuXHRcdCAqIEByZXR1cm4gICBzZWxmIChmb3IgY2hhaW5pbmcpXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRyZW5kZXI6IGZ1bmN0aW9uKCkge1xuXHRcdFx0dGhpcy4kZWwuaHRtbCggdGhpcy50ZW1wbGF0ZSgpICk7XG5cdFx0XHRyZXR1cm4gdGhpcztcblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogQ29sbGFwc2UgYWxsIHNlY3Rpb25zXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGNvbGxhcHNlX2FsbDogZnVuY3Rpb24oIGV2ZW50ICkge1xuXHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdEJhY2tib25lLnB1YlN1Yi50cmlnZ2VyKCAnY29sbGFwc2UtYWxsJyApO1xuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBFeHBhbmQgYWxsIHNlY3Rpb25zXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGV4cGFuZF9hbGw6IGZ1bmN0aW9uKCBldmVudCApIHtcblx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHRCYWNrYm9uZS5wdWJTdWIudHJpZ2dlciggJ2V4cGFuZC1hbGwnICk7XG5cdFx0fSxcblxuXHR9ICk7XG5cbn0gKTtcblxuLyoqXG4gKiBNYWluIHNpZGViYXIgdmlld1xuICogQHNpbmNlICAgIDMuMTYuMFxuICogQHZlcnNpb24gIDMuMTYuN1xuICovXG5kZWZpbmUoICdWaWV3cy9TaWRlYmFyJyxbXG5cdFx0J1ZpZXdzL0VkaXRvcicsXG5cdFx0J1ZpZXdzL0VsZW1lbnRzJyxcblx0XHQnVmlld3MvVXRpbGl0aWVzJyxcblx0XHQnVmlld3MvX1N1YnZpZXcnXG5cdF0sIGZ1bmN0aW9uKFxuXHRcdEVkaXRvcixcblx0XHRFbGVtZW50cyxcblx0XHRVdGlsaXRpZXMsXG5cdFx0U3Vidmlld1xuXHQpIHtcblxuXHRyZXR1cm4gQmFja2JvbmUuVmlldy5leHRlbmQoIF8uZGVmYXVsdHMoIHtcblxuXHRcdC8qKlxuXHRcdCAqIEN1cnJlbnQgYnVpbGRlciBzdGF0ZVxuXHRcdCAqIEB0eXBlICB7U3RyaW5nfVxuXHRcdCAqL1xuXHRcdHN0YXRlOiAnYnVpbGRlcicsIC8vIFtidWlsZGVyfGVkaXRvcl1cblxuXHRcdC8qKlxuXHRcdCAqIEN1cnJlbnQgU3Vidmlld3Ncblx0XHQgKiBAdHlwZSAge09iamVjdH1cblx0XHQgKi9cblx0XHR2aWV3czoge1xuXHRcdFx0ZWxlbWVudHM6IHtcblx0XHRcdFx0Y2xhc3M6IEVsZW1lbnRzLFxuXHRcdFx0XHRpbnN0YW5jZTogbnVsbCxcblx0XHRcdFx0c3RhdGU6ICdidWlsZGVyJyxcblx0XHRcdH0sXG5cdFx0XHR1dGlsaXRpZXM6IHtcblx0XHRcdFx0Y2xhc3M6IFV0aWxpdGllcyxcblx0XHRcdFx0aW5zdGFuY2U6IG51bGwsXG5cdFx0XHRcdHN0YXRlOiAnYnVpbGRlcicsXG5cdFx0XHR9LFxuXHRcdFx0ZWRpdG9yOiB7XG5cdFx0XHRcdGNsYXNzOiBFZGl0b3IsXG5cdFx0XHRcdGluc3RhbmNlOiBudWxsLFxuXHRcdFx0XHRzdGF0ZTogJ2VkaXRvcicsXG5cdFx0XHR9LFxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBIVE1MIGVsZW1lbnQgc2VsZWN0b3Jcblx0XHQgKiBAdHlwZSAge1N0cmluZ31cblx0XHQgKi9cblx0XHRlbDogJyNsbG1zLWJ1aWxkZXItc2lkZWJhcicsXG5cblx0XHQvKipcblx0XHQgKiBET00gZXZlbnRzXG5cdFx0ICogQHR5cGUgIHtPYmplY3R9XG5cdFx0ICovXG5cdFx0ZXZlbnRzOiB7XG5cdFx0XHQnY2xpY2sgI2xsbXMtc2F2ZS1idXR0b24nOiAnc2F2ZV9ub3cnLFxuXHRcdFx0J2NsaWNrICNsbG1zLWV4aXQtYnV0dG9uJzogJ2V4aXRfbm93Jyxcblx0XHRcdCdjbGljayAubGxtcy1idWlsZGVyLWVycm9yJzogJ2NsZWFyX2Vycm9ycycsXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFdyYXBwZXIgVGFnIG5hbWVcblx0XHQgKiBAdHlwZSAge1N0cmluZ31cblx0XHQgKi9cblx0XHR0YWdOYW1lOiAnYXNpZGUnLFxuXG5cdFx0LyoqXG5cdFx0ICogR2V0IHRoZSB1bmRlcnNjb3JlIHRlbXBsYXRlXG5cdFx0ICogQHR5cGUgIHtbdHlwZV19XG5cdFx0ICovXG5cdFx0dGVtcGxhdGU6IHdwLnRlbXBsYXRlKCAnbGxtcy1zaWRlYmFyLXRlbXBsYXRlJyApLFxuXG5cdFx0LyoqXG5cdFx0ICogSW5pdGlhbGl6YXRpb24gY2FsbGJhY2sgZnVuYyAocmVuZGVycyB0aGUgZWxlbWVudCBvbiBzY3JlZW4pXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGluaXRpYWxpemU6IGZ1bmN0aW9uKCBkYXRhICkge1xuXG5cdFx0XHQvLyBzYXZlIGEgcmVmZXJlbmNlIHRvIHRoZSBtYWluIENvdXJzZSB2aWV3XG5cdFx0XHR0aGlzLkNvdXJzZVZpZXcgPSBkYXRhLkNvdXJzZVZpZXc7XG5cblx0XHRcdHRoaXMucmVuZGVyKCk7XG5cblx0XHRcdEJhY2tib25lLnB1YlN1Yi5vbiggJ2N1cnJlbnQtc2F2ZS1zdGF0dXMnLCB0aGlzLmNoYW5nZXNfbWFkZSwgdGhpcyApO1xuXG5cdFx0XHRCYWNrYm9uZS5wdWJTdWIub24oICdoZWFydGJlYXQtc2VuZCcsIHRoaXMuaGVhcnRiZWF0X3NlbmQsIHRoaXMgKTtcblx0XHRcdEJhY2tib25lLnB1YlN1Yi5vbiggJ2hlYXJ0YmVhdC10aWNrJywgdGhpcy5oZWFydGJlYXRfdGljaywgdGhpcyApO1xuXG5cdFx0XHRCYWNrYm9uZS5wdWJTdWIub24oICdsZXNzb24tc2VsZWN0ZWQnLCB0aGlzLm9uX2xlc3Nvbl9zZWxlY3QsIHRoaXMgKTtcblx0XHRcdEJhY2tib25lLnB1YlN1Yi5vbiggJ3NpZGViYXItZWRpdG9yLWNsb3NlJywgdGhpcy5vbl9lZGl0b3JfY2xvc2UsIHRoaXMgKTtcblxuXHRcdFx0dGhpcy4kc2F2ZUJ1dHRvbiA9ICQoICcjbGxtcy1zYXZlLWJ1dHRvbicgKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBDb21waWxlcyB0aGUgdGVtcGxhdGUgYW5kIHJlbmRlcnMgdGhlIHZpZXdcblx0XHQgKiBAcmV0dXJuICAgc2VsZiAoZm9yIGNoYWluaW5nKVxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0cmVuZGVyOiBmdW5jdGlvbiggdmlld19kYXRhICkge1xuXG5cdFx0XHR2aWV3X2RhdGEgPSB2aWV3X2RhdGEgfHwge307XG5cblx0XHRcdHRoaXMuJGVsLmh0bWwoIHRoaXMudGVtcGxhdGUoKSApO1xuXG5cdFx0XHR0aGlzLnJlbmRlcl9zdWJ2aWV3cyggXy5leHRlbmQoIHZpZXdfZGF0YSwge1xuXHRcdFx0XHRTaWRlYmFyVmlldzogdGhpcyxcblx0XHRcdH0gKSApO1xuXG5cdFx0XHR2YXIgJGVsID0gJCggJy53cmFwLmxpZnRlcmxtcy5sbG1zLWJ1aWxkZXInICk7XG5cdFx0XHRpZiAoICdidWlsZGVyJyA9PT0gdGhpcy5zdGF0ZSApIHtcblx0XHRcdFx0JGVsLnJlbW92ZUNsYXNzKCAnZWRpdG9yLWFjdGl2ZScgKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdCRlbC5hZGRDbGFzcyggJ2VkaXRvci1hY3RpdmUnICk7XG5cdFx0XHR9XG5cblx0XHRcdHRoaXMuJHNhdmVCdXR0b24gPSB0aGlzLiRlbC5maW5kKCAnI2xsbXMtc2F2ZS1idXR0b24nICk7XG5cblx0XHRcdHJldHVybiB0aGlzO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIEFkZHMgZXJyb3IgbWVzc2FnZSBlbGVtZW50XG5cdFx0ICogQHBhcmFtICAgIHtbdHlwZV19ICAgJGVyciAgW2Rlc2NyaXB0aW9uXVxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0YWRkX2Vycm9yOiBmdW5jdGlvbiggJGVyciApIHtcblxuXHRcdFx0dGhpcy4kZWwuZmluZCggJy5sbG1zLWJ1aWxkZXItc2F2ZScgKS5wcmVwZW5kKCAkZXJyICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogQ2xlYXIgYW55IGV4aXN0aW5nIGVycm9yIG1lc3NhZ2UgZWxlbWVudHNcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0Y2xlYXJfZXJyb3JzOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0dGhpcy4kZWwuZmluZCggJy5sbG1zLWJ1aWxkZXItc2F2ZSAubGxtcy1idWlsZGVyLWVycm9yJyApLnJlbW92ZSgpO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFVwZGF0ZSBzYXZlIHN0YXR1cyBidXR0b24gd2hlbiBjaGFuZ2VzIGFyZSBkZXRlY3RlZFxuXHRcdCAqIHJ1bnMgb24gYW4gaW50ZXJ2YWwgdG8gY2hlY2sgc3RhdHVzIG9mIGNvdXJzZSByZWd1bGFybHkgZm9yIHVuc2F2ZWQgY2hhbmdlc1xuXHRcdCAqIEBwYXJhbSAgICBvYmogICBzeW5jICBpbnN0YW5jZSBvZiB0aGUgc3luYyBjb250cm9sbGVyXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGNoYW5nZXNfbWFkZTogZnVuY3Rpb24oIHN5bmMgKSB7XG5cblx0XHRcdC8vIGlmIGEgc2F2ZSBpcyBjdXJyZW50bHkgcnVubmluZywgZG9uJ3QgZG8gYW55dGhpbmdcblx0XHRcdGlmICggc3luYy5zYXZpbmcgKSB7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblxuXHRcdFx0aWYgKCBzeW5jLmhhc191bnNhdmVkX2NoYW5nZXMgKSB7XG5cblx0XHRcdFx0dGhpcy4kc2F2ZUJ1dHRvbi5hdHRyKCAnZGF0YS1zdGF0dXMnLCAndW5zYXZlZCcgKTtcblx0XHRcdFx0dGhpcy4kc2F2ZUJ1dHRvbi5yZW1vdmVBdHRyKCAnZGlzYWJsZWQnICk7XG5cblx0XHRcdH0gZWxzZSB7XG5cblx0XHRcdFx0dGhpcy4kc2F2ZUJ1dHRvbi5hdHRyKCAnZGF0YS1zdGF0dXMnLCAnc2F2ZWQnICk7XG5cdFx0XHRcdHRoaXMuJHNhdmVCdXR0b24uYXR0ciggJ2Rpc2FibGVkJywgJ2Rpc2FibGVkJyApO1xuXG5cdFx0XHR9XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogRXhpdCB0aGUgYnVpbGRlciBhbmQgcmV0dXJuIHRvIHRoZSBXUCBDb3Vyc2UgRWRpdG9yXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi43XG5cdFx0ICogQHZlcnNpb24gIDMuMTYuN1xuXHRcdCAqL1xuXHRcdGV4aXRfbm93OiBmdW5jdGlvbigpIHtcblxuXHRcdFx0d2luZG93LmxvY2F0aW9uLmhyZWYgPSB3aW5kb3cubGxtc19idWlsZGVyLkNvdXJzZU1vZGVsLmdldF9lZGl0X3Bvc3RfbGluaygpO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFRyaWdnZXJlZCB3aGVuIGEgaGVhcnRiZWF0IHNlbmQgZXZlbnQgc3RhcnRzIGNvbnRhaW5pbmcgYnVpbGRlciBpbmZvcm1hdGlvblxuXHRcdCAqIEBwYXJhbSAgICBvYmogICBzeW5jICBpbnN0YW5jZSBvZiB0aGUgc3luYyBjb250cm9sbGVyXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGhlYXJ0YmVhdF9zZW5kOiBmdW5jdGlvbiggc3luYyApIHtcblxuXHRcdFx0aWYgKCBzeW5jLnNhdmluZyApIHtcblx0XHRcdFx0TExNUy5TcGlubmVyLnN0YXJ0KCB0aGlzLiRzYXZlQnV0dG9uLmZpbmQoICdpJyApLCAnc21hbGwnICk7XG5cdFx0XHRcdHRoaXMuJHNhdmVCdXR0b24uYXR0cigge1xuXHRcdFx0XHRcdCdkYXRhLXN0YXR1cyc6ICdzYXZpbmcnLFxuXHRcdFx0XHRcdGRpc2FibGVkOiAnZGlzYWJsZWQnLFxuXHRcdFx0XHR9ICk7XG5cdFx0XHR9XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogVHJpZ2dlcmVkIHdoZW4gYSBoZWFydGJlYXQgdGljayBjb21wbGV0ZXMgYW5kIHVwZGF0ZXMgc2F2ZSBzdGF0dXMgb3IgYXBwZW5kcyBlcnJvcnNcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgc3luYyAgaW5zdGFuY2Ugb2YgdGhlIHN5bmMgY29udHJvbGxlclxuXHRcdCAqIEBwYXJhbSAgICBvYmogICBkYXRhICB1cGRhdGVkIGRhdGFcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0aGVhcnRiZWF0X3RpY2s6IGZ1bmN0aW9uKCBzeW5jLCBkYXRhICkge1xuXG5cdFx0XHRpZiAoICEgc3luYy5zYXZpbmcgKSB7XG5cblx0XHRcdFx0dmFyIHN0YXR1cyA9ICdzYXZlZCc7XG5cblx0XHRcdFx0dGhpcy5jbGVhcl9lcnJvcnMoKTtcblxuXHRcdFx0XHRpZiAoICdlcnJvcicgPT09IGRhdGEuc3RhdHVzICkge1xuXG5cdFx0XHRcdFx0c3RhdHVzID0gJ2Vycm9yJztcblxuXHRcdFx0XHRcdHZhciBtc2cgPSBkYXRhLm1lc3NhZ2UsXG5cdFx0XHRcdFx0XHQkZXJyID0gJCggJzxvbCBjbGFzcz1cImxsbXMtYnVpbGRlci1lcnJvclwiIC8+JyApO1xuXG5cdFx0XHRcdFx0aWYgKCAnb2JqZWN0JyA9PT0gdHlwZW9mIG1zZyApIHtcblx0XHRcdFx0XHRcdF8uZWFjaCggbXNnLCBmdW5jdGlvbiggdHh0ICkge1xuXHRcdFx0XHRcdFx0XHQkZXJyLmFwcGVuZCggJzxsaT4nICsgdHh0ICsgJzwvbGk+JyApO1xuXHRcdFx0XHRcdFx0fSApO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHQkZXJyID0gJGVyci5hcHBlbmQoICc8bGk+JyArIG1zZyArICc8L2xpPicgKTs7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0dGhpcy5hZGRfZXJyb3IoICRlcnIgKTtcblxuXHRcdFx0XHR9XG5cblx0XHRcdFx0dGhpcy4kc2F2ZUJ1dHRvbi5maW5kKCAnLmxsbXMtc3Bpbm5pbmcnICkucmVtb3ZlKCk7XG5cdFx0XHRcdHRoaXMuJHNhdmVCdXR0b24uYXR0cigge1xuXHRcdFx0XHRcdCdkYXRhLXN0YXR1cyc6IHN0YXR1cyxcblx0XHRcdFx0XHRkaXNhYmxlZDogJ2Rpc2FibGVkJyxcblx0XHRcdFx0fSApO1xuXG5cdFx0XHR9XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogRGV0ZXJtaW5lIGlmIHRoZSBlZGl0b3IgaXMgdGhlIGN1cnJlbnRseSBhY3RpdmUgc3RhdGVcblx0XHQgKiBAcmV0dXJuICAgYm9vbGVhblxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0aXNfZWRpdG9yX2FjdGl2ZTogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHJldHVybiAoICdlZGl0b3InID09PSB0aGlzLnN0YXRlICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogVHJpZ2dlcmVkIHdoZW4gdGhlIGVkaXRvciBjbG9zZXMsIHVwZGF0ZXMgc3RhdGUgdG8gYmUgdGhlIGNvdXJzZSBidWlsZGVyIHZpZXdcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0b25fZWRpdG9yX2Nsb3NlOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0dGhpcy5zZXRfc3RhdGUoICdidWlsZGVyJyApLnJlbmRlcigpO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFdoZW4gYSBsZXNzb24gaXMgc2VsZWN0ZWQsIG9wZW5zIHRoZSBzaWRlYmFyIHRvIHRoZSBlZGl0b3Igdmlld1xuXHRcdCAqIEBwYXJhbSAgICBvYmogICBsZXNzb25fbW9kZWwgIGluc3RhbmNlIG9mIHRoZSBsZXNzb24gbW9kZWwgd2hpY2ggd2FzIHNlbGVjdGVkXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdG9uX2xlc3Nvbl9zZWxlY3Q6IGZ1bmN0aW9uKCBsZXNzb25fbW9kZWwsIHRhYiApIHtcblxuXHRcdFx0aWYgKCAnZWRpdG9yJyAhPT0gdGhpcy5zdGF0ZSApIHtcblx0XHRcdFx0dGhpcy5zZXRfc3RhdGUoICdlZGl0b3InICk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0aGlzLnJlbW92ZV9zdWJ2aWV3KCAnZWRpdG9yJyApO1xuXHRcdFx0fVxuXG5cdFx0XHR0aGlzLnJlbmRlcigge1xuXHRcdFx0XHRtb2RlbDogbGVzc29uX21vZGVsLFxuXHRcdFx0XHR0YWI6IHRhYixcblx0XHRcdH0gKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBTYXZlIGJ1dHRvbiBjbGljayBldmVudFxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRzYXZlX25vdzogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHdpbmRvdy5sbG1zX2J1aWxkZXIuc3luYy5zYXZlX25vdygpO1xuXG5cdFx0fSxcblxuXHR9LCBTdWJ2aWV3ICkgKTtcblxufSApO1xuXG4vKipcbiAqIExpZnRlckxNUyBKUyBCdWlsZGVyIEFwcCBCb290c3RyYXBcbiAqIEBzaW5jZSAgICAzLjE2LjBcbiAqIEB2ZXJzaW9uICAzLjE3LjhcbiAqL1xucmVxdWlyZSggW1xuXHQndmVuZG9yL2JhY2tib25lLmNvbGxlY3Rpb25WaWV3Jyxcblx0J3ZlbmRvci9iYWNrYm9uZS50cmFja2l0Jyxcblx0J0NvbnRyb2xsZXJzL0NvbnN0cnVjdCcsXG5cdCdDb250cm9sbGVycy9EZWJ1ZycsXG5cdCdDb250cm9sbGVycy9TY2hlbWFzJyxcblx0J0NvbnRyb2xsZXJzL1N5bmMnLFxuXHQnTW9kZWxzL2xvYWRlcicsXG5cdCdWaWV3cy9Db3Vyc2UnLFxuXHQnVmlld3MvU2lkZWJhcidcbl0sIGZ1bmN0aW9uKFxuXHRDVixcblx0VHJhY2tJdCxcblx0Q29uc3RydWN0LFxuXHREZWJ1Zyxcblx0U2NoZW1hcyxcblx0U3luYyxcblx0TW9kZWxzLFxuXHRDb3Vyc2VWaWV3LFxuXHRTaWRlYmFyVmlld1xuKSB7XG5cblx0d2luZG93LmxsbXNfYnVpbGRlci5kZWJ1ZyA9IG5ldyBEZWJ1Zyggd2luZG93LmxsbXNfYnVpbGRlci5kZWJ1ZyApO1xuXHR3aW5kb3cubGxtc19idWlsZGVyLmNvbnN0cnVjdCA9IG5ldyBDb25zdHJ1Y3QoKTtcblx0d2luZG93LmxsbXNfYnVpbGRlci5zY2hlbWFzID0gbmV3IFNjaGVtYXMoIHdpbmRvdy5sbG1zX2J1aWxkZXIuc2NoZW1hcyApO1xuXG5cdC8qKlxuXHQgKiBDb21wYXJlIHZhbHVlcywgdXNlZCBieSBfLmNoZWNrZWQgJiBfLnNlbGVjdGVkIG1peGluc1xuXHQgKiBAcGFyYW0gICAgbWl4ZWQgICBleHBlY3RlZCAgZXhwZWN0ZWQgdmFsdWUsIHByb2JhYmx5IGEgc3RyaW5nICh0aGUgdmFsdWUgb2YgYSBzZWxlY3Qgb3B0aW9uIG9yIGNoZWNrYm94IGVsZW1lbnQpXG5cdCAqIEBwYXJhbSAgICBtaXhlZCAgIGFjdHVhbCAgICBhY3R1YWwgdmFsdWUsIHByb2JhYmx5IGEgc3RyaW5nICh0aGUgcmV0dXJuIG9mIG1vZGVsLmdldCggJ3NvbWV0aGluZycgKSApXG5cdCAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcdFx0XHRcdCBidXQgY291bGQgYmUgYW4gYXJyYXkgbGlrZSBhIG11bHRpc2VsZWN0XG5cdCAqIEByZXR1cm4gICBib29sZWFuXG5cdCAqIEBzaW5jZSAgICAzLjE3LjJcblx0ICogQHZlcnNpb24gIDMuMTcuMlxuXHQgKi9cblx0ZnVuY3Rpb24gdmFsdWVfY29tcGFyZSggZXhwZWN0ZWQsIGFjdHVhbCApIHtcblx0XHRyZXR1cm4gKCAoIF8uaXNBcnJheSggYWN0dWFsICkgJiYgLTEgIT09IGFjdHVhbC5pbmRleE9mKCBleHBlY3RlZCApICkgfHwgZXhwZWN0ZWQgPT0gYWN0dWFsICk7XG5cdH07XG5cblx0LyoqXG5cdCAqIFVuZGVyc2NvcmVzIHRlbXBsYXRpbmcgdXRpbGl0aWVzXG5cdCAqIEBzaW5jZSAgICAzLjE3LjBcblx0ICogQHZlcnNpb24gIDMuMTcuOFxuXHQgKi9cblx0Xy5taXhpbigge1xuXG5cdFx0LyoqXG5cdFx0ICogRGV0ZXJtaW5lIGlmIHR3byB2YWx1ZXMgYXJlIGVxdWFsIGFuZCBvdXRwdXQgY2hlY2tlZCBhdHRyaWJ1dGUgaWYgdGhleSBhcmVcblx0XHQgKiBVc2VmdWwgZm9yIHRlbXBsYXRpbmcgY2hlY2tib3hlcyAmIHJhZGlvIGVsZW1lbnRzXG5cdFx0ICogTGlrZSBXUCBDb3JlIFBIUCBjaGVja2VkKCkgYnV0IGluIEpTXG5cdFx0ICogQHBhcmFtICAgIG1peGVkICAgZXhwZWN0ZWQgIGV4cGVjdGVkIGVsZW1lbnQgdmFsdWVcblx0XHQgKiBAcGFyYW0gICAgbWl4ZWQgICBhY3R1YWwgICAgYWN0dWFsIGVsZW1lbnQgdmFsdWVcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE3LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNy4yXG5cdFx0ICovXG5cdFx0Y2hlY2tlZDogZnVuY3Rpb24oIGV4cGVjdGVkLCBhY3R1YWwgKSB7XG5cdFx0XHRpZiAoIHZhbHVlX2NvbXBhcmUoIGV4cGVjdGVkLCBhY3R1YWwgKSApIHtcblx0XHRcdFx0cmV0dXJuICcgY2hlY2tlZD1cImNoZWNrZWRcIic7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gJyc7XG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFJlY3Vyc2l2ZWx5IGNsb25lIGFuIG9iamVjdCB2aWEgXy5jbG9uZSgpXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIG9iaiAgb2JqZWN0IHRvIGNsb25lXG5cdFx0ICogQHJldHVybiAgIG9ialxuXHRcdCAqIEBzaW5jZSAgICAzLjE3Ljdcblx0XHQgKiBAdmVyc2lvbiAgMy4xNy43XG5cdFx0ICovXG5cdFx0ZGVlcENsb25lOiBmdW5jdGlvbiggb2JqICkge1xuXG5cdFx0XHR2YXIgY2xvbmUgPSBfLmNsb25lKCBvYmogKTtcblxuXHRcdFx0Xy5lYWNoKCBjbG9uZSwgZnVuY3Rpb24oIHZhbCwga2V5ICkge1xuXHRcdFx0XHRpZiAoICEgXy5pc0Z1bmN0aW9uKCB2YWwgKSAmJiBfLmlzT2JqZWN0KCB2YWwgKSApIHtcblx0XHRcdFx0XHRjbG9uZVsga2V5IF0gPSBfLmRlZXBDbG9uZSggdmFsICk7XG5cdFx0XHRcdH07XG5cdFx0XHR9ICk7XG5cblx0XHRcdHJldHVybiBjbG9uZTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBEZXRlcm1pbmUgaWYgdHdvIHZhbHVlcyBhcmUgZXF1YWwgYW5kIG91dHB1dCBzZWxldGVkIGF0dHJpYnV0ZSBpZiB0aGV5IGFyZVxuXHRcdCAqIFVzZWZ1bCBmb3IgdGVtcGxhdGluZyBzZWxlY3QgZWxlbWVudHNcblx0XHQgKiBMaWtlIFdQIENvcmUgUEhQIHNlbGVjdGVkKCkgYnV0IGluIEpTXG5cdFx0ICogQHBhcmFtICAgIG1peGVkICAgZXhwZWN0ZWQgIGV4cGVjdGVkIGVsZW1lbnQgdmFsdWVcblx0XHQgKiBAcGFyYW0gICAgbWl4ZWQgICBhY3R1YWwgICAgYWN0dWFsIGVsZW1lbnQgdmFsdWVcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE3LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNy4yXG5cdFx0ICovXG5cdFx0c2VsZWN0ZWQ6IGZ1bmN0aW9uKCBleHBlY3RlZCwgYWN0dWFsICkge1xuXHRcdFx0aWYgKCB2YWx1ZV9jb21wYXJlKCBleHBlY3RlZCwgYWN0dWFsICkgKSB7XG5cdFx0XHRcdHJldHVybiAnIHNlbGVjdGVkPVwic2VsZWN0ZWRcIic7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gJyc7XG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIEdlbmVyaWMgZnVuY3Rpb24gZm9yIHN0cmlwcGluZyBIVE1MIHRhZ3MgZnJvbSBhIHN0cmluZ1xuXHRcdCAqIEBwYXJhbSAgICBzdHJpbmcgICBjb250ZW50ICAgICAgIHJhdyBzdHJpbmdcblx0XHQgKiBAcGFyYW0gICAgYXJyYXkgICBhbGxvd2VkX3RhZ3MgIGFycmF5IG9mIGFsbG93ZWQgSFRNTCB0YWdzXG5cdFx0ICogQHJldHVybiAgIHN0cmluZ1xuXHRcdCAqIEBzaW5jZSAgICAzLjE3Ljhcblx0XHQgKiBAdmVyc2lvbiAgMy4xNy44XG5cdFx0ICovXG5cdFx0c3RyaXBGb3JtYXR0aW5nOiBmdW5jdGlvbiggY29udGVudCwgYWxsb3dlZF90YWdzICkge1xuXG5cdFx0XHRpZiAoICEgYWxsb3dlZF90YWdzICkge1xuXHRcdFx0XHRhbGxvd2VkX3RhZ3MgPSBbICdiJywgJ2knLCAndScsICdzdHJvbmcnLCAnZW0nIF07XG5cdFx0XHR9XG5cblx0XHRcdHZhciAkaHRtbCA9ICQoICc8ZGl2PicgKyBjb250ZW50ICsgJzwvZGl2PicgKTtcblxuXHRcdFx0JGh0bWwuZmluZCggJyonICkubm90KCBhbGxvd2VkX3RhZ3Muam9pbiggJywnICkgKS5lYWNoKCBmdW5jdGlvbiggKSB7XG5cblx0XHRcdFx0JCggdGhpcyApLnJlcGxhY2VXaXRoKCB0aGlzLmlubmVySFRNTCApO1xuXG5cdFx0XHR9ICk7XG5cblx0XHRcdHJldHVybiAkaHRtbC5odG1sKCk7XG5cblx0XHR9LFxuXG5cdH0gKTtcblxuXHRCYWNrYm9uZS5wdWJTdWIgPSBfLmV4dGVuZCgge30sIEJhY2tib25lLkV2ZW50cyApO1xuXG5cdCQoIGRvY3VtZW50ICkudHJpZ2dlciggJ2xsbXMtYnVpbGRlci1wcmUtaW5pdCcgKTtcblxuXHR3aW5kb3cubGxtc19idWlsZGVyLnF1ZXN0aW9ucyA9IHdpbmRvdy5sbG1zX2J1aWxkZXIuY29uc3RydWN0LmdldF9jb2xsZWN0aW9uKCAnUXVlc3Rpb25UeXBlcycsIHdpbmRvdy5sbG1zX2J1aWxkZXIucXVlc3Rpb25zICk7XG5cblx0dmFyIENvdXJzZU1vZGVsID0gd2luZG93LmxsbXNfYnVpbGRlci5jb25zdHJ1Y3QuZ2V0X21vZGVsKCAnQ291cnNlJywgd2luZG93LmxsbXNfYnVpbGRlci5jb3Vyc2UgKTtcblx0d2luZG93LmxsbXNfYnVpbGRlci5Db3Vyc2VNb2RlbCA9IENvdXJzZU1vZGVsO1xuXG5cdHdpbmRvdy5sbG1zX2J1aWxkZXIuc3luYyA9IG5ldyBTeW5jKCBDb3Vyc2VNb2RlbCwgd2luZG93LmxsbXNfYnVpbGRlci5zeW5jICk7XG5cblx0dmFyIENvdXJzZSA9IG5ldyBDb3Vyc2VWaWV3KCB7XG5cdFx0bW9kZWw6IENvdXJzZU1vZGVsLFxuXHR9ICk7XG5cblx0dmFyIFNpZGViYXIgPSBuZXcgU2lkZWJhclZpZXcoIHtcblx0XHRDb3Vyc2VWaWV3OiBDb3Vyc2Vcblx0fSApO1xuXG5cdCQoIGRvY3VtZW50ICkudHJpZ2dlciggJ2xsbXMtYnVpbGRlci1pbml0Jywge1xuXHRcdGNvdXJzZTogQ291cnNlLFxuXHRcdHNpZGViYXI6IFNpZGViYXIsXG5cdH0gKTtcblxufSApO1xuXG5kZWZpbmUoXCJtYWluXCIsIGZ1bmN0aW9uKCl7fSk7XG5cbn0oalF1ZXJ5KSk7XG5cbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWxsbXMtYnVpbGRlci5qcy5tYXBcbiJdfQ==
+!function(g){var e,t,n,i,s,l,o;!function(_){var o,l,p,m,g={},f={},b={},v={},i=Object.prototype.hasOwnProperty,s=[].slice,w=/\.js$/;function y(e,t){return i.call(e,t)}function a(e,t){var i,s,n,o,l,a,r,c,d,u,h,_=t&&t.split("/"),p=b.map,m=p&&p["*"]||{};if(e){for(l=(e=e.split("/")).length-1,b.nodeIdCompat&&w.test(e[l])&&(e[l]=e[l].replace(w,"")),"."===e[0].charAt(0)&&_&&(e=_.slice(0,_.length-1).concat(e)),d=0;d li, tbody > tr > td":"_listItem_onMousedown","dblclick > li, tbody > tr > td":"_listItem_onDoubleClick",click:"_listBackground_onClick","click ul.collection-view, table.collection-view":"_listBackground_onClick",keydown:"_onKeydown"},spawnMessages:{focus:"focus"},passMessages:{"*":"."},initializationOptions:[{collection:null},{modelView:null},{modelViewOptions:{}},{itemTemplate:null},{itemTemplateFunction:null},{selectable:!0},{clickToSelect:!0},{selectableModelsFilter:null},{visibleModelsFilter:null},{sortableModelsFilter:null},{selectMultiple:!1},{clickToToggle:!1},{processKeyEvents:!0},{sortable:!1},{sortableOptions:null},{reuseModelViews:!0},{detachedRendering:!1},{emptyListCaption:null}],initialize:function(e){t.ViewOptions.add(this,"initializationOptions"),this.setOptions(e),this.collection||(this.collection=new t.Collection),this._hasBeenRendered=!1,this._isBackboneCourierAvailable()&&t.Courier.add(this),this.$el.data("view",this),this.$el.addClass("collection-view collection-list"),this.selectable&&this.$el.addClass("selectable"),this.selectable&&this.processKeyEvents&&this.$el.attr("tabindex",0),this.selectedItems=[],this._updateItemTemplate(),this.collection&&this._registerCollectionEvents(),this.viewManager=new ChildViewContainer},_onOptionsChanged:function(s,n){var o=this,l=!1;h.each(h.keys(s),function(e){var t=s[e],i=n[e];switch(e){case"collection":t!==i&&(o.stopListening(i),o._registerCollectionEvents());break;case"selectMultiple":!t&&1"+e+"");t=this._isRenderedAsList()?i.wrapAll(" ").parent().css(s):i.wrapAll(" ").parent().parent().css(s),this._getContainerEl().append(t)}},_removeEmptyListCaption:function(){this._isRenderedAsList()?this._getContainerEl().find("> li > var.empty-list-caption").parent().remove():this._getContainerEl().find("> tr > td > var.empty-list-caption").parent().parent().remove()},_insertAndRenderModelView:function(e,t,i){var s=this._wrapModelView(e);if(11===t.nodeType)t.appendChild(s.get(0));else{var n=t.children().length;!h.isUndefined(i)&&0<=i&&i tbody");if(0 *").removeClass("selected")},this);var i=this.selectedItems;i=h.without(i,e),h.each(i,function(e){this._getContainerEl().find("[data-model-cid="+e+"]").addClass("selected"),this._isRenderedAsList()&&this._getContainerEl().find("li[data-model-cid="+e+"] > *").addClass("selected")},this)},_reorderCollectionBasedOnHTML:function(){var i=this;this._getContainerEl().children().each(function(){var e=r(this).attr("data-model-cid");if(e){var t=i.collection.get(e);t&&(i.collection.remove(t,{silent:!0}),i.collection.add(t,{silent:!0,sort:!i.collection.comparator}))}}),this._isBackboneCourierAvailable()?this.spawn("reorder"):this.collection.trigger("reorder"),this.collection.comparator&&this.collection.sort()},_getModelViewConstructor:function(e){return this.modelView||i},_getModelViewOptions:function(e){var t=this.modelViewOptions;return h.isFunction(t)&&(t=t(e)),h.extend({model:e},t)},_createNewModelView:function(e,t){var i=this._getModelViewConstructor(e);if(h.isUndefined(i))throw"Could not find modelView constructor for model";var s=new i(t);return s.collectionListView=s.collectionView=this,s},_wrapModelView:function(e){var t;return this._isRenderedAsTable()?(t=e.$el,e.$el.attr("data-model-cid",e.model.cid)):this._isRenderedAsList()&&(e.$el.is("li")?(t=e.$el,e.$el.attr("data-model-cid",e.model.cid)):t=e.$el.wrapAll(" ").parent()),h.isFunction(this.sortableModelsFilter)&&(this.sortableModelsFilter.call(this,e.model)||(t.addClass("not-sortable"),e.$el.addClass("not-selectable"))),h.isFunction(this.selectableModelsFilter)&&(this.selectableModelsFilter.call(this,e.model)||(t.addClass("not-selectable"),e.$el.addClass("not-selectable"))),t},_convertStringsToInts:function(e){return h.map(e,function(e){if(!h.isString(e))return e;var t=parseInt(e,10);return t==e?t:e})},_containSameElements:function(e,t){return e.length==t.length&&h.intersection(e,t).length==e.length},_isRenderedAsTable:function(){return"table"===this.$el.prop("tagName").toLowerCase()},_isRenderedAsList:function(){return!this._isRenderedAsTable()},_modelViewHasWrapperLI:function(e){return this._isRenderedAsList()&&!e.$el.is("li")},_getVisibleItemEls:function(){return this._getContainerEl().find("> [data-model-cid]:not(.not-visible)")},_charCodes:{upArrow:38,downArrow:40},_isBackboneCourierAvailable:function(){return!h.isUndefined(t.Courier)},_setupSortable:function(){var e=h.extend({axis:"y",distance:10,forcePlaceholderSize:!0,items:this._isRenderedAsTable()?"> tbody > tr:not(.not-sortable)":"> li:not(.not-sortable)",start:h.bind(this._sortStart,this),change:h.bind(this._sortChange,this),stop:h.bind(this._sortStop,this),receive:h.bind(this._receive,this),over:h.bind(this._over,this)},h.result(this,"sortableOptions"));this.$el=this.$el.sortable(e)},_sortStart:function(e,t){var i=this.collection.get(t.item.attr("data-model-cid"));this._isBackboneCourierAvailable()?this.spawn("sortStart",{modelBeingSorted:i}):this.trigger("sortStart",i)},_sortChange:function(e,t){var i=this.collection.get(t.item.attr("data-model-cid"));this._isBackboneCourierAvailable()?this.spawn("sortChange",{modelBeingSorted:i}):this.trigger("sortChange",i)},_sortStop:function(e,t){var i=this.collection.get(t.item.attr("data-model-cid")),s=this._getContainerEl().children().index(t.item);-1==s&&i&&this.collection.remove(i),i&&(this._reorderCollectionBasedOnHTML(),this.updateDependentControls(),this._isBackboneCourierAvailable()?this.spawn("sortStop",{modelBeingSorted:i,newIndex:s}):this.trigger("sortStop",i,s))},_receive:function(e,t){var i=t.sender.data("view");if(i&&i.collection){var s=this._getContainerEl().children().index(t.item),n=i.collection.get(t.item.attr("data-model-cid"));i.collection.remove(n),this.collection.add(n,{at:s}),n.collection=this.collection,this.setSelectedModel(n)}},_over:function(e,t){this._getContainerEl().find("> var.empty-list-caption").hide()},_onKeydown:function(e){if(!this.processKeyEvents)return!0;var t=!1;if(1==this.getSelectedModels({by:"offset"}).length){var i=this.getSelectedModel({by:"offset"});e.which===this._charCodes.upArrow&&0!==i?(this.setSelectedModel(i-1,{by:"offset"}),t=!0):e.which===this._charCodes.downArrow&&i!==this.collection.length-1&&(this.setSelectedModel(i+1,{by:"offset"}),t=!0)}return!t},_listItem_onMousedown:function(t){var i=this._getClickedItemId(t);if(i){var e=this.collection.get(i);if(this._isBackboneCourierAvailable()){var s={clickedModel:e,metaKeyPressed:t.ctrlKey||t.metaKey};h.each(["preventDefault","stopPropagation","stopImmediatePropagation"],function(e){s[e]=function(){t[e]()}}),this.spawn("click",s)}else this.trigger("click",e)}if(this.selectable&&this.clickToSelect)if(i){if(h.isFunction(this.selectableModelsFilter)&&!this.selectableModelsFilter.call(this,this.collection.get(i)))return;if(this.selectMultiple&&t.shiftKey){var n=-1;0=i)){t=t||{},(e=e||{}).choice_type=this.get("question_type").get_choice_type(),e.question_id=this.get("id");var s=(t.parent=this).get("choices").add(e,t);Backbone.pubSub.trigger("question-add-choice",s,this)}},before_save:function(e,t){return"full"===t&&(e.question_type=this.get("question_type").get("id")),e},get_parent:function(){var e=this.get_relationships();if(e.parent){if(this.collection&&this.collection.parent)return this.collection.parent;if(e.parent.reference)return e.parent.reference}return!1},get_type_index:function(){var i=this.get("question_type").get("id");return this.collection.filter(function(e){var t=e.get("question_type").get("id");return"content"!==i?"content"!==t:"content"===t}).indexOf(this)},get_type_iterator:function(){var e=this.get_type_index();return-1===e?"":"content"===this.get("question_type").get("id")?"ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("")[e]:e+1},get_qid:function(){var e=this.get_parent_question(),t="";return e&&(t=e.get_qid()+"."),t+this.get_type_iterator()},get_parent_question:function(){return!!this.is_in_group()&&this.collection.parent},get_parent_quiz:function(){return this.get_parent()},get_points:function(){return this.get("question_type").get("points")?this.get("points"):0},get_points_percentage:function(){var e=this.get_parent().get("_points"),t=this.get("points");return 0===e?"0%":(t/e*100).toFixed(2)+"%"},is_in_group:function(){return"question"===this.collection.parent.get("type")},_ensure_min_choices:function(){for(var e=this.get("choices");e.size() li.llms-section > .llms-builder-header .llms-headline":"_listItem_onMousedown",click:"_listBackground_onClick","click ul.collection-view":"_listBackground_onClick",keydown:"_onKeydown"},modelView:e,processKeyEvents:!1,selectable:!0,sortable:!0,sortableOptions:{axis:!1,cursor:"move",handle:".drag-section",items:".llms-section",placeholder:"llms-section llms-sortable-placeholder"},sortable_start:function(e){this.$el.addClass("dragging")},sortable_stop:function(e){this.$el.removeClass("dragging")}},t))}),n("Views/Course",["Views/SectionList","Views/_Editable"],function(e,t){return Backbone.View.extend(_.defaults({attributes:function(){return{"data-id":this.model.id}},el:"#llms-builder-main",tagName:"div",template:wp.template("llms-course-template"),initialize:function(){this.render(),this.sectionListView=new e({collection:this.model.get("sections")}),this.sectionListView.render(),this.sectionListView.on("sortStart",this.sectionListView.sortable_start),this.sectionListView.on("sortStop",this.sectionListView.sortable_stop),this.sectionListView.on("selectionChanged",this.active_section_change),this.listenTo(this.model.get("sections"),"add",this.on_section_add),Backbone.pubSub.on("section-toggle",this.on_section_toggle,this),Backbone.pubSub.on("expand-section",this.expand_section,this),Backbone.pubSub.on("lesson-selected",this.active_lesson_change,this)},render:function(){return this.$el.html(this.template(this.model)),this},active_lesson_change:function(e){var t=this.model.get("sections").get(e.get("parent_section"));this.sectionListView.setSelectedModel(t)},active_section_change:function(e,t){_.each(e,function(e){e.set("_selected",!0)}),_.each(t,function(e){e.set("_selected",!1)})},on_section_add:function(e){this.sectionListView.setSelectedModel(e)},on_section_toggle:function(e){var t=e.get("_expanded")?[e]:[];this.sectionListView.setSelectedModels(t)}},t))}),n("Views/SettingsFields",[],function(){return Backbone.View.extend(_.defaults({events:{"click .llms-settings-group-toggle":"toggle_group"},fields:{},tagName:"div",template:wp.template("llms-settings-fields-template"),get_editor_fields:function(){return _.filter(this.fields,function(e){return this.is_editor_field(e.type)},this)},get_groups:function(){return this.model.get_settings_fields()},is_group_hidden:function(e){var t="llms-"+this.model.get("type")+"-settings-group--"+e;return"undefined"!==window.localStorage&&"hidden"===window.localStorage.getItem(t)},get_switch_attribute:function(e){return e.switch_attribute?e.switch_attribute:e.attribute},has_switch:function(e){return-1!==e.indexOf("switch")},is_default_field:function(e){return-1!==["audio_embed","datepicker","number","text","video_embed"].indexOf(e.replace("switch-",""))},is_editor_field:function(e){return-1!==["editor","switch-editor"].indexOf(e.replace("switch-",""))},is_switch_condition_met:function(e){return e.switch_on===this.model.get(e.switch_attribute)},render:function(){return this.$el.html(this.template(this)),_.each(this.get_editor_fields(),function(e){this.render_editor(e)},this),this},render_editor:function(e){var o=this;wp.editor.remove(e.id),e.settings.tinymce.setup=function(t){var i=g("#"+t.id),e=i.closest(".llms-editable-editor"),s=e.find(".llms-label"),n=i.attr("data-attribute");s.length&&s.prependTo(e.find(".wp-editor-tools")),t.on("change",function(e){o.model.set(n,wp.editor.getContent(t.id))}),i.on("input",function(e){o.model.set(n,i.val())}),e.on("click",".quicktags-toolbar .ed_button",function(){setTimeout(function(){i.trigger("input")},10)})},wp.editor.initialize(e.id,e.settings)},render_select_options:function(e,i){var s="",n=this.model.get(i);function o(e,t){return'"+e+" "}return _.each(e,function(e,t){"string"==typeof e?s+=o(e,t):"object"==typeof e&&(e.label&&e.options?(s+='',s+=this.render_select_options(e.options,i)):s+=o(e.val,e.key))},this),s},setup_field:function(e,t){var i={classes:[],id:_.uniqueId(e.attribute+"_"),input_type:"text",label:"",options:{},placeholder:"",tip:"",tip_position:"top-right",settings:{}};if(e.condition&&!1===_.bind(e.condition,this.model)())return!1;switch(e.type){case"audio_embed":i.classes.push("llms-editable-audio"),i.placeholder="https://",i.tip=LLMS.l10n.translate("Use SoundCloud or Spotify audio URLS."),i.input_type="url";break;case"datepicker":i.classes.push("llms-editable-date");break;case"editor":case"switch-editor":var s=e.settings||{};i.settings=g.extend(!0,wp.editor.getDefaultSettings(),{mediaButtons:!0,tinymce:{toolbar1:"bold,italic,strikethrough,bullist,numlist,blockquote,hr,alignleft,aligncenter,alignright,link,unlink,wp_adv",toolbar2:"formatselect,underline,alignjustify,forecolor,pastetext,removeformat,charmap,outdent,indent,undo,redo,wp_help"}},s);break;case"number":i.input_type="number";break;case"permalink":i.label=LLMS.l10n.translate("Permalink");break;case"video_embed":i.classes.push("llms-editable-video"),i.placeholder="https://",i.tip=LLMS.l10n.translate("Use YouTube, Vimeo, or Wistia video URLS."),i.input_type="url"}this.has_switch(e.type)&&(i.switch_on="yes",i.switch_off="no");var n=_.defaults(_.deepClone(e),i);if(_.isFunction(n.options)&&(n.options=_.bind(n.options,this.model)()),-1!==["radio","switch-radio"].indexOf(e.type)){var o=!1;_.each(e.options,function(e,t){-1===e.indexOf(".png")&&-1===e.indexOf(".jpg")||(n.options[t]=' ',o=!0)}),o&&n.classes.push("has-images")}return n.tip&&n.classes.push("tip--"+n.tip_position),n.classes.length&&(n.classes=" "+n.classes.join(" ")),this.fields[n.id]=n},should_rerender_on_toggle:function(e){return-1!==e.indexOf("switch-")?"yes":"no"},toggle_group:function(e){e.preventDefault();var t=g(e.currentTarget).closest(".llms-model-settings");if(t.toggleClass("hidden"),"undefined"!==window.localStorage){var i=t.attr("id");t.hasClass("hidden")?window.localStorage.setItem(i,"hidden"):window.localStorage.removeItem(i)}}}))}),n("Views/LessonEditor",["Views/_Detachable","Views/_Editable","Views/_Trashable","Views/_Subview","Views/SettingsFields"],function(e,t,i,s,n){return Backbone.View.extend(_.defaults({state:"default",views:{settings:{class:n,instance:null,state:"default"}},el:"#llms-editor-lesson",events:_.defaults({},e.events,t.events,i.events),template:wp.template("llms-lesson-settings-template"),initialize:function(e){this.model=e.lesson;_.each(["change:date_available","change:drip_method","change:time_available"],function(e){this.listenTo(this.model,e,this.render)},this),this.listenTo(this.model,"change:has_prerequisite",function(e,t){"yes"===t&&this.$el.find('select[name="prerequisite"]').trigger("change")})},render:function(){return this.$el.html(this.template(this.model)),this.remove_subview("settings"),this.render_subview("settings",{el:"#llms-lesson-settings-fields",model:this.model}),this.init_datepickers(),this.init_selects(),this}},e,t,i,s,n))}),n("Views/Popover",[],function(){return Backbone.View.extend({defaults:{placement:"auto",width:"auto",trigger:"manual",style:"light",animation:"pop",title:"",content:"",closeable:!1,backdrop:!1,onShow:function(e){},onHide:function(e){}},tagName:"div",initialize:function(e){this.$el.length&&(this.defaults.container=this.$el.parent()),this.args=_.defaults(e.args,this.defaults),this.render()},render:function(){return this.$el.webuiPopover(this.args),this},hide:function(){return this.$el.webuiPopover("hide"),this},show:function(){return this.$el.webuiPopover("show"),this}})}),n("Views/PostSearch",[],function(){return Backbone.View.extend({events:{"select2:select":"add_post"},tagName:"select",initialize:function(e){this.post_type=e.post_type,this.searching_message=e.searching_message||LLMS.l10n.translate("Searching...")},add_post:function(e){var t=this.$el.attr("data-post-type");Backbone.pubSub.trigger(t.replace("llms_","")+"-search-select",e.params.data,e),this.$el.val(null).trigger("change")},render:function(){var t=this;return setTimeout(function(){t.$el.llmsSelect2({ajax:{dataType:"JSON",delay:250,method:"POST",url:window.ajaxurl,data:function(e){return{action:"llms_builder",action_type:"search",course_id:window.llms_builder.course.id,post_type:t.post_type,term:e.term,page:e.page,_ajax_nonce:wp_ajax_data.nonce}}},dropdownParent:g(".wrap.lifterlms.llms-builder"),escapeMarkup:function(e){return e},placeholder:t.searching_message,templateResult:t.render_result,width:"100%"}),t.$el.attr("data-post-type",t.post_type)},0),this},render_result:function(e){var t=g('
');if(e.loading)return t.append(e.text);var i=g(''),s=g('
');return icon="attach"===e.action?"paperclip":"clone",text="attach"===e.action?LLMS.l10n.translate("Attach"):LLMS.l10n.translate("Clone"),i.append(''+text+" "),s.append(""+e.data.title+" "),s.append(""+LLMS.l10n.translate("ID")+": "+e.data.id+" "),_.each(e.parents,function(e){s.append(""+e+" ")}),t.append(i).append(s)}})}),n("Views/QuestionType",[],function(){return Backbone.View.extend({className:"llms-question-type",events:{"click .llms-add-question":"add_question"},id:function(){return"llms-question-type-"+this.model.id},tagName:"li",template:wp.template("llms-question-type-template"),initialize:function(){this.render()},render:function(){return this.$el.html(this.template(this.model)),this},add_question:function(){this.quiz.add_question({_expanded:!0,choices:this.model.get("default_choices")?this.model.get("default_choices"):null,question_type:this.model}),this.quiz.trigger("new-question-added")}})}),n("Views/QuestionBank",["Views/QuestionType"],function(e){return Backbone.CollectionView.extend({className:"llms-question",el:"#llms-question-bank",modelView:e,selectable:!1,sortable:!1})}),n("Views/QuestionChoice",["Views/_Editable"],function(e){return Backbone.View.extend(_.defaults({className:"llms-question-choice",events:_.defaults({'change input[name="correct"]':"toggle_correct",'click .llms-action-icon[href="#llms-add-choice"]':"add_choice",'click .llms-action-icon[href="#llms-del-choice"]':"del_choice"},e.events),id:function(){return"llms-question-choice-"+this.model.id},tagName:"li",template:wp.template("llms-question-choice-template"),initialize:function(){this.render(),this.listenTo(this.model.collection,"add",this.maybe_disable_buttons),this.listenTo(this.model,"change",this.render),"image"===this.model.get("choice_type")&&this.listenTo(this.model.get("choice"),"change",this.render)},render:function(){return this.$el.html(this.template(this.model)),this},add_choice:function(e){e.stopPropagation(),e.preventDefault();var t=this.model.collection.indexOf(this.model);this.model.collection.parent.add_choice({},{at:t+1})},del_choice:function(e){e.preventDefault(),Backbone.pubSub.trigger("model-trashed",this.model),this.model.collection.remove(this.model)},toggle_correct:function(){var e=this.$el.find('input[name="correct"]').is(":checked");this.model.set("correct",e),this.model.collection.trigger("correct-update",this.model)}},e))}),n("Views/QuestionChoiceList",["Views/QuestionChoice"],function(e){return Backbone.CollectionView.extend({className:"llms-quiz-questions",modelView:e,processKeyEvents:!1,selectable:!1,sortable:!0,sortableOptions:{axis:!1,cursor:"move",handle:".llms-choice-id",items:".llms-question-choice",placeholder:"llms-question-choice llms-sortable-placeholder"},sortable_start:function(e){this.$el.addClass("dragging")},sortable_stop:function(e){this.$el.removeClass("dragging")}})}),n("Views/Question",["Views/_Editable","Views/QuestionChoiceList"],function(e,t){return Backbone.View.extend(_.defaults({className:function(){return"llms-question qtype--"+this.model.get("question_type").get("id")},events:_.defaults({"click .clone--question":"clone","click .delete--question":"delete","click .expand--question":"expand","click .collapse--question":"collapse",'change input[name="question_points"]':"update_points"},e.events),id:function(){return"llms-question-"+this.model.id},tagName:"li",template:wp.template("llms-question-template"),initialize:function(){_.each(["change:_expanded","change:menu_order"],function(e){this.listenTo(this.model,e,this.render)},this),this.listenTo(this.model.get("image"),"change",this.render),this.listenTo(this.model.get_parent(),"change:_points",this.render_points_percentage),this.on("multi_choices_toggle",this.multi_choices_toggle,this),Backbone.pubSub.on("del-question-choice",this.del_choice,this)},render:function(){if(this.$el.html(this.template(this.model)),this.model.get("question_type").get("choices")&&(this.choiceListView=new t({el:this.$el.find(".llms-question-choices"),collection:this.model.get("choices")}),this.choiceListView.render(),this.choiceListView.on("sortStart",this.choiceListView.sortable_start),this.choiceListView.on("sortStop",this.choiceListView.sortable_stop)),"group"===this.model.get("question_type").get("id")){var e=this;setTimeout(function(){e.questionListView=e.collectionListView.quiz.get_question_list({el:e.$el.find(".llms-quiz-questions"),collection:e.model.get("questions")}),e.questionListView.render(),e.questionListView.on("sortStart",e.questionListView.sortable_start),e.questionListView.on("sortStop",e.questionListView.sortable_stop)},1)}return this.model.get("description_enabled")&&this.init_editor("question-desc--"+this.model.get("id")),this.model.get("clarifications_enabled")&&this.init_editor("question-clarifications--"+this.model.get("id"),{mediaButtons:!1,tinymce:{toolbar1:"bold,italic,strikethrough,bullist,numlist,alignleft,aligncenter,alignright",toolbar2:"",setup:_.bind(this.on_editor_ready,this)}}),this.init_formatting_els(),this.init_selects(),this},render_points_percentage:function(){this.$el.find(".llms-question-points").attr("data-tip",this.model.get_points_percentage())},clone:function(e){e.stopPropagation(),e.preventDefault(),this.model.collection.add(this._get_question_clone(this.model))},_get_question_clone:function(e){var i=_.clone(e.attributes);return delete i.id,i.parent_id=e.get("id"),i.question_type=e.get("question_type").get("id"),i.image=_.clone(e.get("image").attributes),e.get("choices")&&(i.choices=[],e.get("choices").each(function(e){var t=_.clone(e.attributes);delete t.id,delete t.question_id,i.choices.push(t)})),"group"===e.get("question_type").get("id")&&(i.questions=[],e.get("questions").each(function(e){i.questions.push(this._get_question_clone(e))},this)),i},collapse:function(){this.model.set("_expanded",!1)},delete:function(e){e.preventDefault(),window.confirm(LLMS.l10n.translate("Are you sure you want to delete this question?"))&&(this.model.collection.remove(this.model),Backbone.pubSub.trigger("model-trashed",this.model))},expand:function(){this.model.set("_expanded",!0)},multi_choices_toggle:function(e){"yes"!==e&&this.model.get("choices").update_correct(_.first(this.model.get("choices").get_correct()))},update_points:function(){this.model.set("points",1*this.$el.find('input[name="question_points"]').val())}},e))}),n("Views/QuestionList",["Views/Question"],function(e){return Backbone.CollectionView.extend({className:"llms-quiz-questions",modelView:e,processKeyEvents:!1,selectable:!1,sortable:!0,sortableOptions:{axis:!1,connectWith:".llms-quiz-questions",cursor:"move",handle:".llms-data-stamp",items:".llms-question",placeholder:"llms-question llms-sortable-placeholder"},sortable_start:function(e){var t="group"===e.get("question_type").get("id")?".llms-editor-tab > .llms-quiz-questions":".llms-quiz-questions";g(t).addClass("dragging")},sortable_stop:function(){g(".llms-quiz-questions").removeClass("dragging")},_receive:function(e,t){if(e.stopPropagation(),t.item.hasClass("qtype--group")&&g(e.target).closest(".qtype--group").length)t.sender.sortable("cancel");else{var i=t.sender.data("view");if(i&&i.collection){var s=this._getContainerEl().children().index(t.item),n=i.collection.get(t.item.attr("data-model-cid"));i.collection.remove(n),this.collection.add(n,{at:s}),n.collection=this.collection,this.setSelectedModel(n)}}},_sortStart:function(e,t){var i=this.collection.get(t.item.attr("data-model-cid"));t.placeholder.addClass("qtype--"+i.get("question_type").get("id")),this._isBackboneCourierAvailable()?this.spawn("sortStart",{modelBeingSorted:i}):this.trigger("sortStart",i)},_sortStop:function(e,t){e.stopPropagation();var i=this.collection.get(t.item.attr("data-model-cid")),s=this._getContainerEl().children().index(t.item);-1==s&&i&&this.collection.remove(i),this._reorderCollectionBasedOnHTML(),this.updateDependentControls(),this._isBackboneCourierAvailable()?this.spawn("sortStop",{modelBeingSorted:i,newIndex:s}):this.trigger("sortStop",i,s)}})}),n("Views/Quiz",["Models/Quiz","Views/Popover","Views/PostSearch","Views/QuestionBank","Views/QuestionList","Views/SettingsFields","Views/_Detachable","Views/_Editable","Views/_Subview","Views/_Trashable"],function(e,t,i,s,n,o,l,a,r,c){return Backbone.View.extend(_.defaults({state:"default",views:{settings:{class:o,instance:null,state:"default"},bank:{class:s,instance:null,state:"default"},list:{class:n,instance:null,state:"default"}},el:"#llms-editor-quiz",events:_.defaults({"click #llms-existing-quiz":"add_existing_quiz_click","click #llms-new-quiz":"add_new_quiz","click #llms-show-question-bank":"show_tools","click .bulk-toggle":"bulk_toggle"},l.events,a.events,c.events),tagName:"div",template:wp.template("llms-quiz-template"),initialize:function(e){this.lesson=e.lesson,"yes"!==this.lesson.get("quiz_enabled")&&_.isEmpty(this.lesson.get("quiz"))||(this.model=this.lesson.get("quiz"),this.model.set_parent(this.lesson),this.listenTo(this.model,"change:_points",this.render_points)),this.on("model-trashed",this.on_trashed)},render:function(){if(this.$el.html(this.template(this.model)),this.model){LLMS.Spinner.start(this.$el),this.render_subview("settings",{el:"#llms-quiz-settings-fields",model:this.model}),this.init_datepickers(),this.init_selects(),this.render_subview("bank",{collection:window.llms_builder.questions});var t=null,i=null;this.get_subview("bank").instance.viewManager.each(function(e){e.quiz=this.model,i=e.model.get("group").name,t!==i&&(t=i,e.$el.before('"))},this),this.model.load_questions(_.bind(function(e){if(e)return alert(LLMS.l10n.translate("An error occurred while trying to load the questions. Please refresh the page and try again.")),this;LLMS.Spinner.stop(this.$el),this.render_subview("list",{el:"#llms-quiz-questions",collection:this.model.get("questions")});var t=this.get_subview("list").instance;t.quiz=this,t.collection.on("add",function(){t.collection.trigger("reorder")},this),t.on("sortStart",t.sortable_start),t.on("sortStop",t.sortable_stop)},this)),this.model.on("new-question-added",function(){var e=this.$el.find("#llms-quiz-questions");e.animate({scrollTop:e.prop("scrollHeight")},200)},this)}return this},render_points:function(e,t){this.$el.find("#llms-quiz-total-points").text(t)},bulk_toggle:function(e){var t="expand"===g(e.target).attr("data-action");this.model.get("questions").each(function(e){e.set("_expanded",t)})},add_new_quiz:function(){var e=this.lesson.get("quiz");_.isEmpty(e)?e=this.lesson.add_quiz():this.lesson.set("quiz_enabled","yes"),this.model=e,this.render()},add_existing_quiz:function(e){this.post_search_popover.hide();var t=e.data;"clone"===e.action?(delete t.id,_.each(t.questions,function(e){delete e.parent_id,delete e.id,e.choices&&_.each(e.choices,function(e){delete e.question_id,delete e.id})})):t._forceSync=!0,delete t.lesson_id,this.lesson.add_quiz(t),this.model=this.lesson.get("quiz"),this.render()},add_existing_quiz_click:function(e){e.preventDefault(),this.post_search_popover=new t({el:"#llms-existing-quiz",args:{backdrop:!0,closeable:!0,container:".wrap.lifterlms.llms-builder",dismissible:!0,placement:"left",width:480,title:LLMS.l10n.translate("Add Existing Quiz"),content:new i({post_type:"llms_quiz",searching_message:LLMS.l10n.translate("Search for existing quizzes...")}).render().$el,onHide:function(){Backbone.pubSub.off("quiz-search-select")}}}),this.post_search_popover.show(),Backbone.pubSub.once("quiz-search-select",this.add_existing_quiz,this)},on_trashed:function(e){this.lesson.set("quiz_enabled","no"),this.lesson.set("quiz",""),delete this.model,this.render()},show_tools:function(){var e=new t({el:"#llms-show-question-bank",args:{backdrop:!0,closeable:!0,container:"#llms-builder-sidebar",dismissible:!0,placement:"top-left",width:"calc( 100% - 40px )",title:LLMS.l10n.translate("Add a Question"),url:"#llms-quiz-tools"}});e.show(),this.model.on("new-question-added",function(){e.hide()})},get_question_list:function(e){return new n(e)}},l,a,r,c,o))}),n("Views/Assignment",["Views/Popover","Views/PostSearch","Views/_Detachable","Views/_Editable","Views/_Trashable","Views/_Subview","Views/SettingsFields"],function(s,t,i,n,o,e,l){return Backbone.View.extend(_.defaults({state:"default",views:{settings:{class:l,instance:null,state:"default"}},el:"#llms-editor-assignment",events:function(){var e=this.is_addon_available()?window.llms_builder.assignments.get_view_events():{};return _.defaults({"click #llms-existing-assignment":"add_existing_assignment_click","click #llms-new-assignment":"add_new_assignment"},i.events,n.events,o.events,e)},tagName:"div",template:wp.template("llms-assignment-template"),initialize:function(e){this.lesson=e.lesson,"yes"!==this.lesson.get("assignment_enabled")&&_.isEmpty(this.lesson.get("assignment"))||(this.model=this.lesson.get("assignment"),this.model.set_parent(this.lesson)),this.on("model-trashed",this.on_trashed)},render:function(){return this.$el.html(this.template(this.model)),this.model&&this.is_addon_available()&&(this.stopListening(this.model,"change:assignment_type",this.render),this.render_subview("settings",{el:"#llms-assignment-settings-fields",model:this.model}),this.init_selects(),window.llms_builder.assignments.render_editor(this),this.listenTo(this.model,"change:assignment_type",this.render)),this},add_new_assignment:function(){this.is_addon_available()?(this.model=window.llms_builder.assignments.get_assignment({title:LLMS.l10n.replace("%1$s Assignment",{"%1$s":this.lesson.get("title")}),lesson_id:this.lesson.get("id")}),this.lesson.set("assignment_enabled","yes"),this.lesson.set("assignment",this.model),this.render()):this.show_ad_popover("#llms-new-assignment")},add_existing_assignment:function(e){this.post_search_popover.hide();var t=e.data;"clone"===e.action?delete t.id:t._forceSync=!0,t.lesson_id=this.lesson.get("id"),t=window.llms_builder.construct.get_model("Assignment",t),this.lesson.set("assignment_enabled","yes"),this.lesson.set("assignment",t),this.model=t,this.render()},add_existing_assignment_click:function(e){e.preventDefault(),this.is_addon_available()?(this.post_search_popover=new s({el:"#llms-existing-assignment",args:{backdrop:!0,closeable:!0,container:".wrap.lifterlms.llms-builder",dismissible:!0,placement:"left",width:480,title:LLMS.l10n.translate("Add Existing Assignment"),content:new t({post_type:"llms_assignment",searching_message:LLMS.l10n.translate("Search for existing assignments...")}).render().$el,onHide:function(){Backbone.pubSub.off("assignment-search-select")}}}),this.post_search_popover.show(),Backbone.pubSub.once("assignment-search-select",this.add_existing_assignment,this)):this.show_ad_popover("#llms-existing-assignment")},is_addon_available:function(){return window.llms_builder.assignments},on_trashed:function(e){this.lesson.set("assignment_enabled","no"),this.lesson.set("assignment",""),delete this.model,this.render()},show_ad_popover:function(e){var t=LLMS.l10n.translate("Get Your Students Taking Action"),i=LLMS.l10n.translate("Get Assignments Now!");this.ad_popover=new s({el:e,args:{backdrop:!0,closeable:!0,container:".wrap.lifterlms.llms-builder",dismissible:!0,width:380,title:LLMS.l10n.translate("Unlock LifterLMS Assignments"),content:""+t+' Great learning content is only half of teaching online. When your learners fully engage, they will take your content and move into action. Remove barriers for your learners by telling them what to do to apply what they just learned. Create graded assignments or simply give them a checklist of action items to complete before moving on.
'+i+"
"}}),this.ad_popover.show()}},i,n,o,e,l))}),n("Views/Editor",["Views/LessonEditor","Views/Quiz","Views/Assignment","Views/_Subview"],function(e,t,i,s){return Backbone.View.extend(_.defaults({state:"lesson",views:{lesson:{class:e,instance:null,state:"lesson"},assignment:{class:i,instance:null,state:"assignment"},quiz:{class:t,instance:null,state:"quiz"}},el:"#llms-editor",events:{'click .llms-editor-nav a[href="#llms-editor-close"]':"close_editor",'click .llms-editor-nav a:not([href="#llms-editor-close"])':"switch_tab"},tagName:"div",template:wp.template("llms-editor-template"),initialize:function(e){this.SidebarView=e.SidebarView,e.tab&&(this.state=e.tab)},render:function(e){return e=e||{},this.$el.html(this.template(this)),this.render_subviews(_.extend(e,{lesson:this.model})),this},close_editor:function(e){e.preventDefault(),Backbone.pubSub.trigger("sidebar-editor-close")},switch_tab:function(e){e.preventDefault();var t=g(e.target),i=t.attr("data-view");this.$el.find(t.attr("href"));this.set_state(i).render()}},s))}),n("Views/Elements",["Models/Section","Views/Section","Models/Lesson","Views/Lesson","Views/Popover","Views/PostSearch"],function(e,t,i,s,n,o){return Backbone.View.extend({el:"#llms-elements",events:{"click #llms-new-section":"add_new_section","click #llms-new-lesson":"add_new_lesson","click #llms-existing-lesson":"add_existing_lesson"},tagName:"div",template:wp.template("llms-elements-template"),initialize:function(e){this.SidebarView=e.SidebarView,this.listenTo(this.SidebarView.CourseView.model.get("sections"),"add",this.maybe_disable_buttons),this.listenTo(this.SidebarView.CourseView.model.get("sections"),"remove",this.maybe_disable_buttons)},render:function(){return this.$el.html(this.template()),this.draggable(),this.maybe_disable_buttons(),this},draggable:function(){g("#llms-new-section").draggable({appendTo:"#llms-sections",cancel:!1,connectToSortable:".llms-sections",helper:function(){return new t({model:new e}).render().$el},start:function(){g(".llms-sections").addClass("dragging")},stop:function(){g(".llms-sections").removeClass("dragging")}}),g("#llms-new-lesson").draggable({appendTo:"#llms-sections",cancel:!1,connectToSortable:".llms-lessons",helper:function(){return new s({model:new i}).render().$el},start:function(){g(".llms-lessons").addClass("dragging")},stop:function(){g(".llms-lessons").removeClass("dragging"),g(".drag-expanded").removeClass(".drag-expanded")}})},add_new_section:function(e){e.preventDefault(),Backbone.pubSub.trigger("add-new-section")},add_new_lesson:function(e){e.preventDefault(),Backbone.pubSub.trigger("add-new-lesson")},add_existing_lesson:function(e){e.preventDefault();var t=new n({el:"#llms-existing-lesson",args:{backdrop:!0,closeable:!0,container:".wrap.lifterlms.llms-builder",dismissible:!0,placement:"left",width:480,title:LLMS.l10n.translate("Add Existing Lesson"),content:new o({post_type:"lesson",searching_message:LLMS.l10n.translate("Search for existing lessons...")}).render().$el}});t.show(),Backbone.pubSub.on("lesson-search-select",function(){t.hide()})},maybe_disable_buttons:function(){var e=g("#llms-new-lesson, #llms-existing-lesson");this.SidebarView.CourseView.model.get("sections").length?e.removeAttr("disabled"):e.attr("disabled","disabled")}})}),n("Views/Utilities",[],function(){return Backbone.View.extend({el:"#llms-utilities",events:{"click #llms-collapse-all":"collapse_all","click #llms-expand-all":"expand_all"},tagName:"div",template:wp.template("llms-utilities-template"),initialize:function(){},render:function(){return this.$el.html(this.template()),this},collapse_all:function(e){e.preventDefault(),Backbone.pubSub.trigger("collapse-all")},expand_all:function(e){e.preventDefault(),Backbone.pubSub.trigger("expand-all")}})}),n("Views/Sidebar",["Views/Editor","Views/Elements","Views/Utilities","Views/_Subview"],function(e,t,i,s){return Backbone.View.extend(_.defaults({state:"builder",views:{elements:{class:t,instance:null,state:"builder"},utilities:{class:i,instance:null,state:"builder"},editor:{class:e,instance:null,state:"editor"}},el:"#llms-builder-sidebar",events:{"click #llms-save-button":"save_now","click #llms-exit-button":"exit_now","click .llms-builder-error":"clear_errors"},tagName:"aside",template:wp.template("llms-sidebar-template"),initialize:function(e){this.CourseView=e.CourseView,this.render(),Backbone.pubSub.on("current-save-status",this.changes_made,this),Backbone.pubSub.on("heartbeat-send",this.heartbeat_send,this),Backbone.pubSub.on("heartbeat-tick",this.heartbeat_tick,this),Backbone.pubSub.on("lesson-selected",this.on_lesson_select,this),Backbone.pubSub.on("sidebar-editor-close",this.on_editor_close,this),this.$saveButton=g("#llms-save-button")},render:function(e){e=e||{},this.$el.html(this.template()),this.render_subviews(_.extend(e,{SidebarView:this}));var t=g(".wrap.lifterlms.llms-builder");return"builder"===this.state?t.removeClass("editor-active"):t.addClass("editor-active"),this.$saveButton=this.$el.find("#llms-save-button"),this},add_error:function(e){this.$el.find(".llms-builder-save").prepend(e)},clear_errors:function(){this.$el.find(".llms-builder-save .llms-builder-error").remove()},changes_made:function(e){e.saving||(e.has_unsaved_changes?(this.$saveButton.attr("data-status","unsaved"),this.$saveButton.removeAttr("disabled")):(this.$saveButton.attr("data-status","saved"),this.$saveButton.attr("disabled","disabled")))},exit_now:function(){window.location.href=window.llms_builder.CourseModel.get_edit_post_link()},heartbeat_send:function(e){e.saving&&(LLMS.Spinner.start(this.$saveButton.find("i"),"small"),this.$saveButton.attr({"data-status":"saving",disabled:"disabled"}))},heartbeat_tick:function(e,t){if(!e.saving){var i="saved";if(this.clear_errors(),"error"===t.status){i="error";var s=t.message,n=g(' ');"object"==typeof s?_.each(s,function(e){n.append(""+e+" ")}):n=n.append(""+s+" "),this.add_error(n)}this.$saveButton.find(".llms-spinning").remove(),this.$saveButton.attr({"data-status":i,disabled:"disabled"})}},is_editor_active:function(){return"editor"===this.state},on_editor_close:function(){this.set_state("builder").render()},on_lesson_select:function(e,t){"editor"!==this.state?this.set_state("editor"):this.remove_subview("editor"),this.render({model:e,tab:t})},save_now:function(){window.llms_builder.sync.save_now()}},s))}),t(["vendor/backbone.collectionView","vendor/backbone.trackit","Controllers/Construct","Controllers/Debug","Controllers/Schemas","Controllers/Sync","Models/loader","Views/Course","Views/Sidebar"],function(e,t,i,s,n,o,l,a,r){function c(e,t){return _.isArray(t)&&-1!==t.indexOf(e)||e==t}window.llms_builder.debug=new s(window.llms_builder.debug),window.llms_builder.construct=new i,window.llms_builder.schemas=new n(window.llms_builder.schemas),_.mixin({checked:function(e,t){return c(e,t)?' checked="checked"':""},deepClone:function(e){var i=_.clone(e);return _.each(i,function(e,t){!_.isFunction(e)&&_.isObject(e)&&(i[t]=_.deepClone(e))}),i},selected:function(e,t){return c(e,t)?' selected="selected"':""},stripFormatting:function(e,t){t||(t=["b","i","u","strong","em"]);var i=g(""+e+"
");return i.find("*").not(t.join(",")).each(function(){g(this).replaceWith(this.innerHTML)}),i.html()}}),Backbone.pubSub=_.extend({},Backbone.Events),g(document).trigger("llms-builder-pre-init"),window.llms_builder.questions=window.llms_builder.construct.get_collection("QuestionTypes",window.llms_builder.questions);var d=window.llms_builder.construct.get_model("Course",window.llms_builder.course);window.llms_builder.CourseModel=d,window.llms_builder.sync=new o(d,window.llms_builder.sync);var u=new a({model:d}),h=new r({CourseView:u});g(document).trigger("llms-builder-init",{course:u,sidebar:h})}),n("main",function(){})}(jQuery);
+//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImxsbXMtYnVpbGRlci5qcyJdLCJuYW1lcyI6WyIkIiwicmVxdWlyZWpzIiwicmVxdWlyZSIsImRlZmluZSIsInJvb3QiLCJmYWN0b3J5IiwidW5zYXZlZE1vZGVscyIsImdldFByb21wdCIsInVuZGVmIiwibWFpbiIsInJlcSIsIm1ha2VNYXAiLCJoYW5kbGVycyIsImRlZmluZWQiLCJ3YWl0aW5nIiwiY29uZmlnIiwiZGVmaW5pbmciLCJoYXNPd24iLCJPYmplY3QiLCJwcm90b3R5cGUiLCJoYXNPd25Qcm9wZXJ0eSIsImFwcyIsInNsaWNlIiwianNTdWZmaXhSZWdFeHAiLCJoYXNQcm9wIiwib2JqIiwicHJvcCIsImNhbGwiLCJub3JtYWxpemUiLCJuYW1lIiwiYmFzZU5hbWUiLCJuYW1lUGFydHMiLCJuYW1lU2VnbWVudCIsIm1hcFZhbHVlIiwiZm91bmRNYXAiLCJsYXN0SW5kZXgiLCJmb3VuZEkiLCJmb3VuZFN0YXJNYXAiLCJzdGFySSIsImkiLCJqIiwicGFydCIsImJhc2VQYXJ0cyIsInNwbGl0IiwibWFwIiwic3Rhck1hcCIsImxlbmd0aCIsIm5vZGVJZENvbXBhdCIsInRlc3QiLCJyZXBsYWNlIiwiY2hhckF0IiwiY29uY2F0Iiwic3BsaWNlIiwiam9pbiIsIm1ha2VSZXF1aXJlIiwicmVsTmFtZSIsImZvcmNlU3luYyIsImFyZ3MiLCJhcmd1bWVudHMiLCJwdXNoIiwiYXBwbHkiLCJtYWtlTG9hZCIsImRlcE5hbWUiLCJ2YWx1ZSIsImNhbGxEZXAiLCJFcnJvciIsInNwbGl0UHJlZml4IiwicHJlZml4IiwiaW5kZXgiLCJpbmRleE9mIiwic3Vic3RyaW5nIiwibWFrZVJlbFBhcnRzIiwicmVsUGFydHMiLCJwbHVnaW4iLCJwYXJ0cyIsInJlbFJlc291cmNlTmFtZSIsImYiLCJuIiwicHIiLCJwIiwiZXhwb3J0cyIsImUiLCJtb2R1bGUiLCJpZCIsInVyaSIsImRlcHMiLCJjYWxsYmFjayIsImNqc01vZHVsZSIsInJldCIsInVzaW5nRXhwb3J0cyIsImNhbGxiYWNrVHlwZSIsImxvYWQiLCJ1bmRlZmluZWQiLCJhbHQiLCJzZXRUaW1lb3V0IiwiY2ZnIiwiX2RlZmluZWQiLCJhbWQiLCJqUXVlcnkiLCJfIiwiQmFja2JvbmUiLCJ0aGlzIiwibURlZmF1bHRNb2RlbFZpZXdDb25zdHJ1Y3RvciIsIlZpZXciLCJrRGVmYXVsdFJlZmVyZW5jZUJ5Iiwia09wdGlvbnNSZXF1aXJpbmdSZXJlbmRlcmluZyIsImtTdHlsZXNGb3JFbXB0eUxpc3RDYXB0aW9uIiwiYmFja2dyb3VuZCIsImJvcmRlciIsImJveC1zaGFkb3ciLCJfbm9ybWFsaXplT3B0aW9uRGVjbGFyYXRpb25zIiwib3B0aW9uRGVjbGFyYXRpb25zIiwibm9ybWFsaXplZE9wdGlvbkRlY2xhcmF0aW9ucyIsImlzQXJyYXkiLCJlYWNoIiwidGhpc09wdGlvbkRlY2xhcmF0aW9uIiwidGhpc09wdGlvbk5hbWUiLCJ0aGlzT3B0aW9uUmVxdWlyZWQiLCJ0aGlzT3B0aW9uRGVmYXVsdFZhbHVlIiwiaXNTdHJpbmciLCJpc09iamVjdCIsImZpcnN0Iiwia2V5cyIsImlzRnVuY3Rpb24iLCJjbG9uZSIsInJlcXVpcmVkIiwiaXNVbmRlZmluZWQiLCJkZWZhdWx0VmFsdWUiLCJDb2xsZWN0aW9uVmlldyIsImV4dGVuZCIsInRhZ05hbWUiLCJldmVudHMiLCJtb3VzZWRvd24gPiBsaSwgdGJvZHkgPiB0ciA+IHRkIiwiZGJsY2xpY2sgPiBsaSwgdGJvZHkgPiB0ciA+IHRkIiwiY2xpY2siLCJjbGljayB1bC5jb2xsZWN0aW9uLXZpZXcsIHRhYmxlLmNvbGxlY3Rpb24tdmlldyIsImtleWRvd24iLCJzcGF3bk1lc3NhZ2VzIiwiZm9jdXMiLCJwYXNzTWVzc2FnZXMiLCIqIiwiaW5pdGlhbGl6YXRpb25PcHRpb25zIiwiY29sbGVjdGlvbiIsIm1vZGVsVmlldyIsIm1vZGVsVmlld09wdGlvbnMiLCJpdGVtVGVtcGxhdGUiLCJpdGVtVGVtcGxhdGVGdW5jdGlvbiIsInNlbGVjdGFibGUiLCJjbGlja1RvU2VsZWN0Iiwic2VsZWN0YWJsZU1vZGVsc0ZpbHRlciIsInZpc2libGVNb2RlbHNGaWx0ZXIiLCJzb3J0YWJsZU1vZGVsc0ZpbHRlciIsInNlbGVjdE11bHRpcGxlIiwiY2xpY2tUb1RvZ2dsZSIsInByb2Nlc3NLZXlFdmVudHMiLCJzb3J0YWJsZSIsInNvcnRhYmxlT3B0aW9ucyIsInJldXNlTW9kZWxWaWV3cyIsImRldGFjaGVkUmVuZGVyaW5nIiwiZW1wdHlMaXN0Q2FwdGlvbiIsImluaXRpYWxpemUiLCJvcHRpb25zIiwiVmlld09wdGlvbnMiLCJhZGQiLCJzZXRPcHRpb25zIiwiQ29sbGVjdGlvbiIsIl9oYXNCZWVuUmVuZGVyZWQiLCJfaXNCYWNrYm9uZUNvdXJpZXJBdmFpbGFibGUiLCJDb3VyaWVyIiwiJGVsIiwiZGF0YSIsImFkZENsYXNzIiwiYXR0ciIsInNlbGVjdGVkSXRlbXMiLCJfdXBkYXRlSXRlbVRlbXBsYXRlIiwiX3JlZ2lzdGVyQ29sbGVjdGlvbkV2ZW50cyIsInZpZXdNYW5hZ2VyIiwiQ2hpbGRWaWV3Q29udGFpbmVyIiwiX29uT3B0aW9uc0NoYW5nZWQiLCJjaGFuZ2VkT3B0aW9ucyIsIm9yaWdpbmFsT3B0aW9ucyIsIl90aGlzIiwicmVyZW5kZXIiLCJjaGFuZ2VkT3B0aW9uS2V5IiwibmV3VmFsIiwib2xkVmFsIiwic3RvcExpc3RlbmluZyIsInNldFNlbGVjdGVkTW9kZWwiLCJieSIsInNldFNlbGVjdGVkTW9kZWxzIiwicmVtb3ZlQXR0ciIsIl9zZXR1cFNvcnRhYmxlIiwicmVhcHBseUZpbHRlciIsInZpZXciLCJyZW1vdmUiLCJjb250YWlucyIsInJlbmRlciIsInNldE9wdGlvbiIsIm9wdGlvbk5hbWUiLCJvcHRpb25WYWx1ZSIsIm9wdGlvbkhhc2giLCJnZXRTZWxlY3RlZE1vZGVsIiwiZ2V0U2VsZWN0ZWRNb2RlbHMiLCJyZWZlcmVuY2VCeSIsIml0ZW1zIiwiaXRlbSIsImdldCIsImN1ckxpbmVOdW1iZXIiLCJfZ2V0VmlzaWJsZUl0ZW1FbHMiLCJpcyIsImZpbmRCeU1vZGVsIiwibmV3U2VsZWN0ZWRJdGVtcyIsInNpbGVudCIsIm5ld1NlbGVjdGVkQ2lkcyIsInRoaXNNb2RlbCIsImNpZCIsInBsdWNrIiwibW9kZWwiLCJ0aGlzSXRlbUVsIiwib2xkU2VsZWN0ZWRNb2RlbHMiLCJvbGRTZWxlY3RlZENpZHMiLCJfY29udmVydFN0cmluZ3NUb0ludHMiLCJfdmFsaWRhdGVTZWxlY3Rpb24iLCJuZXdTZWxlY3RlZE1vZGVscyIsIl9jb250YWluU2FtZUVsZW1lbnRzIiwiX2FkZFNlbGVjdGVkQ2xhc3NUb1NlbGVjdGVkSXRlbXMiLCJzcGF3biIsInNlbGVjdGVkTW9kZWxzIiwidHJpZ2dlciIsInVwZGF0ZURlcGVuZGVudENvbnRyb2xzIiwibmV3U2VsZWN0ZWRJdGVtIiwiZ2V0VmlldyIsInJlZmVyZW5jZSIsIml0ZW1FbGVtZW50cyIsIm1vZGVsVmlld0NvbnRhaW5lckVsIiwiX3NhdmVTZWxlY3Rpb24iLCJfZ2V0Q29udGFpbmVyRWwiLCJmcmFnbWVudENvbnRhaW5lciIsIm9sZFZpZXdNYW5hZ2VyIiwidGhpc01vZGVsVmlldyIsImRldGFjaCIsImVtcHR5IiwiZG9jdW1lbnQiLCJjcmVhdGVEb2N1bWVudEZyYWdtZW50IiwiZmluZEJ5TW9kZWxDaWQiLCJfY3JlYXRlTmV3TW9kZWxWaWV3IiwiX2dldE1vZGVsVmlld09wdGlvbnMiLCJfaW5zZXJ0QW5kUmVuZGVyTW9kZWxWaWV3IiwiYXBwZW5kIiwiX3Nob3dFbXB0eUxpc3RDYXB0aW9uSWZBcHByb3ByaWF0ZSIsIl9yZXN0b3JlU2VsZWN0aW9uIiwiZm9yY2VSZXJlbmRlck9uTmV4dFNvcnRFdmVudCIsIl9yZW1vdmVFbXB0eUxpc3RDYXB0aW9uIiwiZW1wdHlMaXN0U3RyaW5nIiwiJGVtcHR5TGlzdENhcHRpb25FbCIsIiR2YXJFbCIsIl9pc1JlbmRlcmVkQXNMaXN0Iiwid3JhcEFsbCIsInBhcmVudCIsImNzcyIsImZpbmQiLCJwYXJlbnRFbE9yRG9jdW1lbnRGcmFnbWVudCIsImF0SW5kZXgiLCJ0aGlzTW9kZWxWaWV3V3JhcHBlZCIsIl93cmFwTW9kZWxWaWV3Iiwibm9kZVR5cGUiLCJhcHBlbmRDaGlsZCIsIm51bWJlck9mTW9kZWxWaWV3c0N1cnJlbnRseUluRE9NIiwiY2hpbGRyZW4iLCJlcSIsImJlZm9yZSIsImhpZGUiLCJoaWRlVGhpc01vZGVsVmlldyIsInRvZ2dsZSIsInRvZ2dsZUNsYXNzIiwid2hpY2hGaWx0ZXIiLCJub3RWaXNpYmxlIiwiX21vZGVsVmlld0hhc1dyYXBwZXJMSSIsImNsb3Nlc3QiLCJub3RTb3J0YWJsZSIsIm5vdFNlbGVjdGFibGUiLCJfcmVtb3ZlTW9kZWxWaWV3IiwiX3ZhbGlkYXRlU2VsZWN0aW9uQW5kUmVuZGVyIiwibGlzdGVuVG8iLCJfaXNSZW5kZXJlZEFzVGFibGUiLCJ0Ym9keSIsIl9nZXRDbGlja2VkSXRlbUlkIiwidGhlRXZlbnQiLCJjbGlja2VkSXRlbUlkIiwiY2xpY2tlZEl0ZW1FbCIsImN1cnJlbnRUYXJnZXQiLCJjbGlja2VkSXRlbSIsImlzTnVtZXJpYyIsInBhcnNlSW50IiwiaXRlbVRlbXBsYXRlSHRtbCIsImh0bWwiLCJ0ZW1wbGF0ZSIsIm1vZGVsUmVmZXJlbmNlSWRzIiwibW9kZWxzIiwiaW50ZXJzZWN0aW9uIiwiZmlsdGVyIiwidGhpc0l0ZW1JZCIsInNhdmVkU2VsZWN0aW9uIiwib2Zmc2V0Iiwib2xkSXRlbXNJZHNXaXRoU2VsZWN0ZWRDbGFzcyIsIml0ZW1zSWRzRnJvbVdoaWNoU2VsZWN0ZWRDbGFzc05lZWRzVG9CZVJlbW92ZWQiLCJ3aXRob3V0IiwicmVtb3ZlQ2xhc3MiLCJpdGVtc0lkc0Zyb21XaGljaFNlbGVjdGVkQ2xhc3NOZWVkc1RvQmVBZGRlZCIsIl9yZW9yZGVyQ29sbGVjdGlvbkJhc2VkT25IVE1MIiwidGhpc01vZGVsQ2lkIiwic29ydCIsImNvbXBhcmF0b3IiLCJfZ2V0TW9kZWxWaWV3Q29uc3RydWN0b3IiLCJtb2RlbFZpZXdDb25zdHJ1Y3RvciIsIm5ld01vZGVsVmlldyIsImNvbGxlY3Rpb25MaXN0VmlldyIsImNvbGxlY3Rpb25WaWV3IiwibW9kZWxWaWV3V3JhcHBlckVsIiwidGhlQXJyYXkiLCJ0aGlzRWwiLCJ0aGlzRWxBc051bWJlciIsImFycmF5QSIsImFycmF5QiIsInRvTG93ZXJDYXNlIiwiX2NoYXJDb2RlcyIsInVwQXJyb3ciLCJkb3duQXJyb3ciLCJheGlzIiwiZGlzdGFuY2UiLCJmb3JjZVBsYWNlaG9sZGVyU2l6ZSIsInN0YXJ0IiwiYmluZCIsIl9zb3J0U3RhcnQiLCJjaGFuZ2UiLCJfc29ydENoYW5nZSIsInN0b3AiLCJfc29ydFN0b3AiLCJyZWNlaXZlIiwiX3JlY2VpdmUiLCJvdmVyIiwiX292ZXIiLCJyZXN1bHQiLCJldmVudCIsInVpIiwibW9kZWxCZWluZ1NvcnRlZCIsIm5ld0luZGV4Iiwic2VuZGVyQ29sbGVjdGlvbkxpc3RWaWV3Iiwic2VuZGVyIiwibW9kZWxSZWNlaXZlZCIsImF0IiwiX29uS2V5ZG93biIsInRyYXAiLCJjdXJyZW50T2Zmc2V0Iiwid2hpY2giLCJfbGlzdEl0ZW1fb25Nb3VzZWRvd24iLCJjbGlja2VkTW9kZWwiLCJtZXRhS2V5UHJlc3NlZCIsImN0cmxLZXkiLCJtZXRhS2V5IiwidGhpc01ldGhvZCIsInNoaWZ0S2V5IiwiZmlyc3RTZWxlY3RlZEl0ZW1JbmRleCIsInRoaXNJdGVtTW9kZWwiLCJjbGlja2VkSXRlbUluZGV4Iiwic2hpZnRLZXlSb290U2VsZWN0ZWRJdGVtSW5kZXgiLCJtaW5TZWxlY3RlZEl0ZW1JbmRleCIsIk1hdGgiLCJtaW4iLCJtYXhTZWxlY3RlZEl0ZW1JbmRleCIsIm1heCIsInRoaXNJbmRleCIsInNlbGVjdGlvbiIsIndpbmRvdyIsImdldFNlbGVjdGlvbiIsInNlbCIsInJlbW92ZUFsbFJhbmdlcyIsInVuaW9uIiwiX2xpc3RJdGVtX29uRG91YmxlQ2xpY2siLCJfbGlzdEJhY2tncm91bmRfb25DbGljayIsInRhcmdldCIsInNldERlZmF1bHRNb2RlbFZpZXdDb25zdHJ1Y3RvciIsInRoZUNvbnN0cnVjdG9yIiwib3B0aW9uc0RlY2xhcmF0aW9uc1Byb3BlcnR5Iiwib3B0aW9uc1RoYXRXZXJlQ2hhbmdlZCIsIm9wdGlvbnNUaGF0V2VyZUNoYW5nZWRQcmV2aW91c1ZhbHVlcyIsInRoaXNPcHRpb25Qcm9wZXJ0aWVzIiwib2xkVmFsdWUiLCJuZXdWYWx1ZSIsIm9uT3B0aW9uc0NoYW5nZWQiLCJnZXRPcHRpb25zIiwib3B0aW9uc05hbWVzIiwicGljayIsIkNvbnRhaW5lciIsInZpZXdzIiwiX3ZpZXdzIiwiX2luZGV4QnlNb2RlbCIsIl9pbmRleEJ5Q3VzdG9tIiwiX3VwZGF0ZUxlbmd0aCIsImN1c3RvbUluZGV4Iiwidmlld0NpZCIsIm1vZGVsQ2lkIiwiZmluZEJ5Q2lkIiwiZmluZEJ5Q3VzdG9tIiwiZmluZEJ5SW5kZXgiLCJ2YWx1ZXMiLCJmaW5kSW5kZXhCeUNpZCIsImFueSIsImtleSIsIm1ldGhvZCIsInRhaWwiLCJzaXplIiwidG9BcnJheSIsIlplcHRvIiwiZm5OYW1lIiwicHJvbXB0IiwicmVzdCIsImZuIiwiX3Vuc2F2ZWRDb25maWciLCJpc0Jvb2xlYW4iLCJIaXN0b3J5IiwibmF2aWdhdGUiLCJ3cmFwIiwib2xkTmF2IiwiZnJhZ21lbnQiLCJjb25maXJtIiwib25iZWZvcmV1bmxvYWQiLCJNb2RlbCIsInVuc2F2ZWQiLCJfdHJhY2tpbmdDaGFuZ2VzIiwiX29yaWdpbmFsQXR0cnMiLCJfdW5zYXZlZENoYW5nZXMiLCJzdGFydFRyYWNraW5nIiwidW5sb2FkUm91dGVyUHJvbXB0IiwidW5sb2FkV2luZG93UHJvbXB0IiwiX3Jlc2V0VHJhY2tpbmciLCJfdHJpZ2dlclVuc2F2ZWRDaGFuZ2VzIiwic3RvcFRyYWNraW5nIiwicmVzdGFydFRyYWNraW5nIiwicmVzZXRBdHRyaWJ1dGVzIiwiYXR0cmlidXRlcyIsInVuc2F2ZWRBdHRyaWJ1dGVzIiwiYXR0cnMiLCJpc0VtcHR5IiwidmFsIiwiY2hhbmdlZCIsIm9sZCIsImlzRXF1YWwiLCJtIiwiZmluZFdoZXJlIiwic2V0Iiwib2xkU2V0Iiwic3luYyIsIm9sZFN5bmMiLCJzdWNjZXNzIiwib2xkU3VjY2VzcyIsInRleHRTdGF0dXMiLCJqcVhIUiIsImRlZmF1bHRzIiwiZW5hYmxlZCIsInNyYyIsInJlbGF0aW9uc2hpcF9kZWZhdWx0cyIsInJlbGF0aW9uc2hpcHMiLCJpbml0X3JlbGF0aW9uc2hpcHMiLCJyZWxzIiwiZ2V0X3JlbGF0aW9uc2hpcHMiLCJzZXRfcGFyZW50IiwiY2hpbGRfZGF0YSIsImNoaWxkX2tleSIsImNvbmRpdGlvbmFsIiwiY2hpbGQiLCJjaGlsZF92YWwiLCJsb29rdXAiLCJ0eXBlIiwibGxtc19idWlsZGVyIiwiY29uc3RydWN0IiwiZ2V0X21vZGVsIiwiY2xhc3MiLCJnZXRfY29sbGVjdGlvbiIsIl9tYXliZV9zZXRfcGFyZW50X3JlZmVyZW5jZSIsImNoaWxkX21vZGVsIiwiZ2V0X2NoaWxkX3Byb3BzIiwicHJvcHMiLCJnZXRfcGFyZW50IiwiSW1hZ2UiLCJSZWxhdGlvbnNoaXBzIiwiY2hvaWNlIiwidW5pcXVlSWQiLCJjaG9pY2VfdHlwZSIsImNvcnJlY3QiLCJtYXJrZXIiLCJxdWVzdGlvbl9pZCIsImdldF90cmFzaF9pZCIsImlzX3NlbGVjdGFibGUiLCJnZXRfY2hvaWNlX3NlbGVjdGFibGUiLCJvbiIsInVwZGF0ZV9vcmRlciIsInVwZGF0ZV9jb3JyZWN0IiwiY291bnRfY29ycmVjdCIsImdldF9jb3JyZWN0Iiwic2libGluZ3MiLCJxdWVzdGlvbiIsInNlbGYiLCJnZXRfY2hvaWNlX21hcmtlcnMiLCJjaG9pY2VzIiwiY2xhcmlmaWNhdGlvbnMiLCJkZWZhdWx0X2Nob2ljZXMiLCJkZXNjcmlwdGlvbiIsImljb24iLCJpbWFnZSIsImtleXdvcmRzIiwicGxhY2Vob2xkZXIiLCJwb2ludHMiLCJ2aWRlbyIsImdldF9rZXl3b3JkcyIsIl9nZXRfY2hvaWNlX29wdGlvbiIsImdldF9jaG9pY2VfdHlwZSIsImdldF9taW5fY2hvaWNlcyIsImdldF9tYXhfY2hvaWNlcyIsImdldF9tdWx0aV9jaG9pY2VzIiwib3B0aW9uIiwiUXVlc3Rpb25zIiwiUXVlc3Rpb25DaG9pY2VzIiwiUXVlc3Rpb25UeXBlIiwicXVlc3Rpb25zIiwicXVlc3Rpb25fdHlwZSIsImNvbnRlbnQiLCJkZXNjcmlwdGlvbl9lbmFibGVkIiwibXVsdGlfY2hvaWNlcyIsIm1lbnVfb3JkZXIiLCJwYXJlbnRfaWQiLCJ0aXRsZSIsInZpZGVvX2VuYWJsZWQiLCJ2aWRlb19zcmMiLCJfZXhwYW5kZWQiLCJfZW5zdXJlX21pbl9jaG9pY2VzIiwiZGVsYXkiLCJ1cGRhdGVfcG9pbnRzIiwiYWRkX2Nob2ljZSIsInB1YlN1YiIsImJlZm9yZV9zYXZlIiwiYXR0cyIsInN5bmNfdHlwZSIsImdldF90eXBlX2luZGV4IiwiY3Vycl90eXBlIiwiZ2V0X3R5cGVfaXRlcmF0b3IiLCJnZXRfcWlkIiwiZ2V0X3BhcmVudF9xdWVzdGlvbiIsImlzX2luX2dyb3VwIiwiZ2V0X3BhcmVudF9xdWl6IiwiZ2V0X3BvaW50cyIsImdldF9wb2ludHNfcGVyY2VudGFnZSIsInRvdGFsIiwidG9GaXhlZCIsInVwZGF0ZV9wYXJlbnQiLCJmaWVsZHMiLCJnZXRfZWRpdF9wb3N0X2xpbmsiLCJoYXNfdGVtcF9pZCIsImFkbWluX3VybCIsImdldF9zZXR0aW5nc19maWVsZHMiLCJzY2hlbWEiLCJzY2hlbWFzIiwiaXNOdW1iZXIiLCJpbml0X2N1c3RvbV9zY2hlbWEiLCJncm91cHMiLCJncm91cCIsImZsYXR0ZW4iLCJmaWVsZCIsImF0dHJpYnV0ZSIsImN1c3RvbXMiLCJzd2l0Y2hfYXR0cmlidXRlIiwiYXR0cmlidXRlX3ByZWZpeCIsImRlZmF1bHQiLCJMTE1TIiwibDEwbiIsInRyYW5zbGF0ZSIsInRvZ2dsZWFibGUiLCJsYWJlbCIsInRpcCIsIkxlc3NvbiIsIlF1ZXN0aW9uIiwiVXRpbGl0aWVzIiwiUXVpelNjaGVtYSIsImxlc3Nvbl9pZCIsInN0YXR1cyIsImFsbG93ZWRfYXR0ZW1wdHMiLCJsaW1pdF9hdHRlbXB0cyIsImxpbWl0X3RpbWUiLCJwYXNzaW5nX3BlcmNlbnQiLCJyYW5kb21fYW5zd2VycyIsInRpbWVfbGltaXQiLCJzaG93X2NvcnJlY3RfYW5zd2VyIiwiX3BvaW50cyIsInBlcm1hbGluayIsIl9zaG93X3NldHRpbmdzIiwiX3F1ZXN0aW9uc19sb2FkZWQiLCJnZXRfdG90YWxfcG9pbnRzIiwiYWRkX3F1ZXN0aW9uIiwiZ2V0X2wxMG5fdHlwZSIsInBsdXJhbCIsImxvYWRfcXVlc3Rpb25zIiwiY2IiLCJBamF4IiwiYWN0aW9uIiwiYWN0aW9uX3R5cGUiLCJjb3Vyc2VfaWQiLCJDb3Vyc2VNb2RlbCIsImxvYWRfaWQiLCJlcnJvciIsInhociIsImNvbnNvbGUiLCJsb2ciLCJkZWJ1ZyIsInJlcyIsImNvbmRpdGlvbiIsImFzc2lnbm1lbnRzIiwiaXNfZmlyc3RfaW5fY291cnNlIiwiZ2V0X2F2YWlsYWJsZV9wcmVyZXFfb3B0aW9ucyIsImdldF9jb3Vyc2UiLCJkYXRlX2Zvcm1hdCIsInRpbWVwaWNrZXIiLCJkYXRlcGlja2VyIiwiUXVpeiIsIkxlc3NvblNjaGVtYSIsInBhcmVudHMiLCJxdWl6Iiwib3JkZXIiLCJwYXJlbnRfY291cnNlIiwiY291cnNlIiwicGFyZW50X3NlY3Rpb24iLCJlZGl0X3VybCIsInZpZXdfdXJsIiwiYXVkaW9fZW1iZWQiLCJoYXNfcHJlcmVxdWlzaXRlIiwicmVxdWlyZV9wYXNzaW5nX2dyYWRlIiwicmVxdWlyZV9hc3NpZ25tZW50X3Bhc3NpbmdfZ3JhZGUiLCJ2aWRlb19lbWJlZCIsImZyZWVfbGVzc29uIiwiYXNzaWdubWVudCIsImFzc2lnbm1lbnRfZW5hYmxlZCIsInF1aXpfZW5hYmxlZCIsIl9mb3JjZVN5bmMiLCJtYXliZV9pbml0X2Fzc2lnbm1lbnRzIiwicGFyZW50X3NlY3Rpb25faW5kZXgiLCJsZXNzb25faW5kZXhfaW5fc2VjdGlvbiIsInNlY3Rpb24iLCJjdXJyX3NlY19pbmRleCIsIiUxJGQiLCIlMiRzIiwibGVzc29uIiwiY3Vycl9sZXNfaW5kZXgiLCJhZGRfcXVpeiIsIiUxJHMiLCJvbl9yZW9yZGVyIiwidmFsaWRhdGVfcHJlcmVxcyIsInByZXJlcXVpc2l0ZSIsIkxlc3NvbnMiLCJsZXNzb25zIiwiX3NlbGVjdGVkIiwiYWRkX2xlc3NvbiIsImdldF9uZXh0IiwiY2lyY3VsYXIiLCJfZ2V0X3NpYmxpbmciLCJnZXRfcHJldiIsImRpcmVjdGlvbiIsInNpYmxpbmdfaW5kZXgiLCJsYXN0IiwiUXVlc3Rpb25UeXBlcyIsIlNlY3Rpb25zIiwic2VjdGlvbnMiLCJhZGRfc2VjdGlvbiIsImFkZF9leGlzdGluZ19sZXNzb24iLCJnZXRfc2VsZWN0ZWRfc2VjdGlvbiIsInNlbGVjdGVkIiwiQWJzdHJhY3QiLCJDb3Vyc2UiLCJRdWVzdGlvbkNob2ljZSIsIlNlY3Rpb24iLCJjbGljayBhW2hyZWY9XCIjbGxtcy1kZXRhY2gtbW9kZWxcIl0iLCJkZXRhY2hfbW9kZWwiLCJwcmV2ZW50RGVmYXVsdCIsInN0b3BQcm9wYWdhdGlvbiIsIm1zZyIsIiVzIiwibWVkaWFfbGliIiwiY2xpY2sgLmxsbXMtYWRkLWltYWdlIiwiY2xpY2sgYVtocmVmPVwiI2xsbXMtZWRpdC1zbHVnXCJdIiwiY2xpY2sgYVtocmVmPVwiI2xsbXMtcmVtb3ZlLWltYWdlXCJdIiwiY2hhbmdlIC5sbG1zLWVkaXRhYmxlLXNlbGVjdCBzZWxlY3QiLCJjaGFuZ2UgLmxsbXMtc3dpdGNoIGlucHV0W3R5cGU9XCJjaGVja2JveFwiXSIsImNoYW5nZSAubGxtcy1lZGl0YWJsZS1yYWRpbyBpbnB1dCIsImZvY3VzaW4gLmxsbXMtaW5wdXQiLCJmb2N1c291dCAubGxtcy1pbnB1dCIsImtleWRvd24gLmxsbXMtaW5wdXQiLCJpbnB1dCAubGxtcy1pbnB1dFt0eXBlPVwibnVtYmVyXCJdIiwicGFzdGUgLmxsbXMtaW5wdXRbZGF0YS1mb3JtYXR0aW5nXSIsImdldF9hbGxvd2VkX3RhZ3MiLCJ0YWciLCJ0cmltIiwiZ2V0X2NvbnRlbnQiLCJoYXNDbGFzcyIsInN0cmlwRm9ybWF0dGluZyIsInRleHQiLCJoYXNfY2hhbmdlZCIsImlzX3ZhbGlkIiwiX3ZhbGlkYXRlX3VybCIsInNsdWciLCJiZWZvcmVTZW5kIiwiU3Bpbm5lciIsInIiLCJpbml0X2RhdGVwaWNrZXJzIiwiZGF0ZXRpbWVwaWNrZXIiLCJmb3JtYXQiLCJvbkNsb3NlIiwiY3VycmVudF90aW1lIiwiJGlucHV0IiwiYmx1ciIsImluaXRfZm9ybWF0dGluZ19lbHMiLCJmb3JtYXR0aW5nIiwiZWQiLCJRdWlsbCIsIm1vZHVsZXMiLCJ0b29sYmFyIiwia2V5Ym9hcmQiLCJiaW5kaW5ncyIsInRhYiIsImhhbmRsZXIiLCJyYW5nZSIsImNvbnRleHQiLCIxMyIsInRoZW1lIiwiZGVsdGEiLCJvbGREZWx0YSIsInNvdXJjZSIsImluaXRfc2VsZWN0cyIsImxsbXNTZWxlY3QyIiwid2lkdGgiLCJvbl9ibHVyIiwic2F2ZV9lZGl0cyIsInJldmVydF9lZGl0cyIsIm9uX2ZvY3VzIiwib25fcGFzdGUiLCJvcmlnaW5hbEV2ZW50IiwiY2xpcGJvYXJkRGF0YSIsImdldERhdGEiLCJleGVjQ29tbWFuZCIsIm9uX3NlbGVjdCIsIm11bHRpIiwiJHNlbGVjdGVkIiwib25fcmFkaW9fc2VsZWN0Iiwib25fa2V5ZG93biIsImtleUNvZGUiLCJzaGlmdCIsIm9wZW5fbWVkaWFfbGliIiwidXBsb2FkZXIiLCJwYXJhbSIsIndwIiwibWVkaWEiLCJmcmFtZXMiLCJmaWxlX2ZyYW1lIiwiYnV0dG9uIiwibXVsdGlwbGUiLCJ1cmwiLCJhdHRhY2htZW50Iiwic3RhdGUiLCJ0b0pTT04iLCJzaXplcyIsIm9wZW4iLCJyZW1vdmVfaW1hZ2UiLCJ0b2dnbGVfc3dpdGNoIiwiaW5pdF9lZGl0b3IiLCJzZXR0aW5ncyIsImVkaXRvciIsImdldERlZmF1bHRTZXR0aW5ncyIsIm1lZGlhQnV0dG9ucyIsInRpbnltY2UiLCJ0b29sYmFyMSIsInRvb2xiYXIyIiwic2V0dXAiLCJvbl9lZGl0b3JfcmVhZHkiLCJtYWtlX3NsdWdfZWRpdGFibGUiLCIkYnRuIiwiJGxpbmsiLCJwcmV2QWxsIiwicHJldiIsImZ1bGxfdXJsIiwic2hvcnRfdXJsIiwiY29sb3IiLCJwb2ludGVyLWV2ZW50cyIsInRleHQtZGVjb3JhdGlvbiIsInNob3ciLCIkZWQiLCIkcGFyZW50IiwiJGxhYmVsIiwicHJlcGVuZFRvIiwiZ2V0Q29udGVudCIsInN0ciIsImEiLCJjcmVhdGVFbGVtZW50IiwiaHJlZiIsImhvc3QiLCJsb2NhdGlvbiIsImhlbHBlciIsIm1heWJlX2hpZGVfc2hpZnRhYmxlX2J1dHRvbnMiLCJvbGRfaW5kZXgiLCJuZXdfaW5kZXgiLCJzaGlmdF9kb3duIiwic2hpZnRfdXAiLCJzdWJzY3JpcHRpb25zIiwiZ2V0X3N1YnZpZXciLCJldmVudHNfc3Vic2NyaWJlIiwiZnVuYyIsImV2ZW50c191bnN1YnNjcmliZSIsIm9mZiIsInJlbW92ZV9zdWJ2aWV3IiwiaW5zdGFuY2UiLCJyZW1vdmVfc3Vidmlld3MiLCJ1bmRlbGVnYXRlRXZlbnRzIiwicmVuZGVyX3N1YnZpZXdzIiwidmlld19kYXRhIiwicmVuZGVyX3N1YnZpZXciLCJzZXRfc3RhdGUiLCJjbGljayBhW2hyZWY9XCIjbGxtcy10cmFzaC1tb2RlbFwiXSIsInRyYXNoX21vZGVsIiwiRGV0YWNoYWJsZSIsIkVkaXRhYmxlIiwiUmVjZWl2YWJsZSIsIlNoaWZ0YWJsZSIsIlN1YnZpZXciLCJUcmFzaGFibGUiLCJDb2xsZWN0aW9ucyIsIk1vZGVscyIsIlZpZXdzIiwiZXh0ZW5kX3ZpZXciLCJjbGFzc25hbWUiLCJyZWdpc3Rlcl9jb2xsZWN0aW9uIiwicmVnaXN0ZXJfbW9kZWwiLCJkaXNhYmxlIiwiZW5hYmxlIiwiY3VzdG9tX3NjaGVtYXMiLCJjdXN0b20iLCJtb2RlbF90eXBlIiwic2F2aW5nIiwiYXV0b3NhdmUiLCJjaGVja19pbnRlcnZhbCIsImNoZWNrX2ludGVydmFsX21zIiwiZGV0YWNoZWQiLCJ0cmFzaGVkIiwiYWRkX2Vycm9yX21zZyIsImVyciIsIm1lc3NhZ2UiLCJjaGVja19mb3JfY2hhbmdlcyIsImNoYW5nZXMiLCJnZXRfdW5zYXZlZF9jaGFuZ2VzIiwiaGFzX3Vuc2F2ZWRfY2hhbmdlcyIsImdldF9jaGFuZ2VzX3RvX29iamVjdCIsIm9iamVjdCIsImNoYW5nZWRfYXR0cyIsImV4Y2x1ZGUiLCJvbWl0IiwiZ2V0X2NoYW5nZWRfYXR0cmlidXRlcyIsIm1vZGVsX2NoYW5nZXMiLCJtYXliZV9yZXN0YXJ0X3RyYWNraW5nIiwidW5zZXQiLCJwcm9jZXNzX3JlbW92YWxzIiwicmVtb3ZhbHMiLCJ0cmFzaCIsImNvbGwiLCJlcnJvcnMiLCJpbmZvIiwicHJvY2Vzc191cGRhdGVzIiwidXBkYXRlcyIsInByb2Nlc3Nfb2JqZWN0X3VwZGF0ZXMiLCJtYWluX2RhdGEiLCJvcmlnX2lkIiwic2F2ZV9ub3ciLCJoZWFydGJlYXQiLCJjb25uZWN0Tm93IiwiSlNPTiIsInN0cmluZ2lmeSIsInJlc3BvbnNlVGV4dCIsImRvX2FqYXhfc2F2ZSIsInNldF9jaGVja19pbnRlcnZhbCIsIm1zIiwiY2xlYXJJbnRlcnZhbCIsInNldEludGVydmFsIiwic3RhdHVzVGV4dCIsImRhdGEtaWQiLCJkYXRhLXNlY3Rpb24taWQiLCJjbGFzc05hbWUiLCJjbGljayAuZWRpdC1sZXNzb24iLCJjbGljayAuZWRpdC1xdWl6IiwiY2xpY2sgLmVkaXQtYXNzaWdubWVudCIsImNsaWNrIC5zZWN0aW9uLXByZXYiLCJjbGljayAuc2VjdGlvbi1uZXh0IiwiY2xpY2sgLnNoaWZ0LXVwLS1sZXNzb24iLCJjbGljayAuc2hpZnQtZG93bi0tbGVzc29uIiwib3Blbl9hc3NpZ25tZW50X2VkaXRvciIsIm9wZW5fbGVzc29uX2VkaXRvciIsIm9wZW5fcXVpel9lZGl0b3IiLCJzZWN0aW9uX25leHQiLCJfbW92ZV90b19zZWN0aW9uIiwic2VjdGlvbl9wcmV2IiwidG9fc2VjdGlvbiIsImZyb21fY29sbCIsIkxlc3NvblZpZXciLCJjb25uZWN0V2l0aCIsImN1cnNvciIsImhhbmRsZSIsInNvcnRhYmxlX3N0YXJ0Iiwic29ydGFibGVfc3RvcCIsIkxlc3Nvbkxpc3RWaWV3IiwiY2xpY2sgLmV4cGFuZCIsImNsaWNrIC5jb2xsYXBzZSIsImNsaWNrIC5zaGlmdC11cC0tc2VjdGlvbiIsImNsaWNrIC5zaGlmdC1kb3duLS1zZWN0aW9uIiwibW91c2VlbnRlciAubGxtcy1sZXNzb25zIiwidG9nZ2xlX2V4cGFuZGVkIiwibGVzc29uTGlzdFZpZXciLCJvbl9sZXNzb25fYWRkIiwiZHJhZ1RpbWVvdXQiLCJleHBhbmQiLCJjb2xsYXBzZSIsImVsIiwiYWN0aXZlX2xlc3Nvbl9jaGFuZ2UiLCJtYXliZV9oaWRlX3RyYXNoX2J1dHRvbiIsImN1cnJlbnQiLCJwcmV2aW91cyIsInVwZGF0ZSIsIm9uX21vdXNlZW50ZXIiLCJTZWN0aW9uVmlldyIsIm1vdXNlZG93biA+IGxpLmxsbXMtc2VjdGlvbiA+IC5sbG1zLWJ1aWxkZXItaGVhZGVyIC5sbG1zLWhlYWRsaW5lIiwiY2xpY2sgdWwuY29sbGVjdGlvbi12aWV3IiwiU2VjdGlvbkxpc3RWaWV3Iiwic2VjdGlvbkxpc3RWaWV3IiwiYWN0aXZlX3NlY3Rpb25fY2hhbmdlIiwib25fc2VjdGlvbl9hZGQiLCJvbl9zZWN0aW9uX3RvZ2dsZSIsImV4cGFuZF9zZWN0aW9uIiwiY2xpY2sgLmxsbXMtc2V0dGluZ3MtZ3JvdXAtdG9nZ2xlIiwiZ2V0X2VkaXRvcl9maWVsZHMiLCJpc19lZGl0b3JfZmllbGQiLCJnZXRfZ3JvdXBzIiwiaXNfZ3JvdXBfaGlkZGVuIiwiZ3JvdXBfaWQiLCJsb2NhbFN0b3JhZ2UiLCJnZXRJdGVtIiwiZ2V0X3N3aXRjaF9hdHRyaWJ1dGUiLCJoYXNfc3dpdGNoIiwiaXNfZGVmYXVsdF9maWVsZCIsImlzX3N3aXRjaF9jb25kaXRpb25fbWV0Iiwic3dpdGNoX29uIiwicmVuZGVyX2VkaXRvciIsInJlbmRlcl9zZWxlY3Rfb3B0aW9ucyIsIm9wdGlvbl9odG1sIiwic2V0dXBfZmllbGQiLCJvcmlnX2ZpZWxkIiwiZmllbGRfaW5kZXgiLCJjbGFzc2VzIiwiaW5wdXRfdHlwZSIsInRpcF9wb3NpdGlvbiIsIm9yaWdfc2V0dGluZ3MiLCJzd2l0Y2hfb2ZmIiwiZGVlcENsb25lIiwiaGFzX2ltYWdlcyIsInNob3VsZF9yZXJlbmRlcl9vbl90b2dnbGUiLCJmaWVsZF90eXBlIiwidG9nZ2xlX2dyb3VwIiwiJGdyb3VwIiwic2V0SXRlbSIsInJlbW92ZUl0ZW0iLCJTZXR0aW5nc0ZpZWxkcyIsInBsYWNlbWVudCIsInN0eWxlIiwiYW5pbWF0aW9uIiwiY2xvc2VhYmxlIiwiYmFja2Ryb3AiLCJvblNob3ciLCJvbkhpZGUiLCJjb250YWluZXIiLCJ3ZWJ1aVBvcG92ZXIiLCJzZWxlY3QyOnNlbGVjdCIsInBvc3RfdHlwZSIsInNlYXJjaGluZ19tZXNzYWdlIiwiYWRkX3Bvc3QiLCJwYXJhbXMiLCJhamF4IiwiZGF0YVR5cGUiLCJhamF4dXJsIiwidGVybSIsInBhZ2UiLCJfYWpheF9ub25jZSIsIndwX2FqYXhfZGF0YSIsIm5vbmNlIiwiZHJvcGRvd25QYXJlbnQiLCJlc2NhcGVNYXJrdXAiLCJtYXJrdXAiLCJ0ZW1wbGF0ZVJlc3VsdCIsInJlbmRlcl9yZXN1bHQiLCIkaHRtbCIsImxvYWRpbmciLCIkc2lkZSIsIiRtYWluIiwiY2xpY2sgLmxsbXMtYWRkLXF1ZXN0aW9uIiwiUXVlc3Rpb25WaWV3IiwiY2hhbmdlIGlucHV0W25hbWU9XCJjb3JyZWN0XCJdIiwiY2xpY2sgLmxsbXMtYWN0aW9uLWljb25baHJlZj1cIiNsbG1zLWFkZC1jaG9pY2VcIl0iLCJjbGljayAubGxtcy1hY3Rpb24taWNvbltocmVmPVwiI2xsbXMtZGVsLWNob2ljZVwiXSIsIm1heWJlX2Rpc2FibGVfYnV0dG9ucyIsImRlbF9jaG9pY2UiLCJ0b2dnbGVfY29ycmVjdCIsIkNob2ljZVZpZXciLCJDaG9pY2VMaXN0VmlldyIsImNsaWNrIC5jbG9uZS0tcXVlc3Rpb24iLCJjbGljayAuZGVsZXRlLS1xdWVzdGlvbiIsImNsaWNrIC5leHBhbmQtLXF1ZXN0aW9uIiwiY2xpY2sgLmNvbGxhcHNlLS1xdWVzdGlvbiIsImNoYW5nZSBpbnB1dFtuYW1lPVwicXVlc3Rpb25fcG9pbnRzXCJdIiwicmVuZGVyX3BvaW50c19wZXJjZW50YWdlIiwibXVsdGlfY2hvaWNlc190b2dnbGUiLCJjaG9pY2VMaXN0VmlldyIsInF1ZXN0aW9uTGlzdFZpZXciLCJnZXRfcXVlc3Rpb25fbGlzdCIsIl9nZXRfcXVlc3Rpb25fY2xvbmUiLCJjaG9pY2VfY2xvbmUiLCJkZWxldGUiLCJzZWxlY3RvciIsIlF1aXpNb2RlbCIsIlBvcG92ZXIiLCJQb3N0U2VhcmNoIiwiUXVlc3Rpb25CYW5rIiwiUXVlc3Rpb25MaXN0IiwiYmFuayIsImxpc3QiLCJjbGljayAjbGxtcy1leGlzdGluZy1xdWl6IiwiY2xpY2sgI2xsbXMtbmV3LXF1aXoiLCJjbGljayAjbGxtcy1zaG93LXF1ZXN0aW9uLWJhbmsiLCJjbGljayAuYnVsay10b2dnbGUiLCJyZW5kZXJfcG9pbnRzIiwib25fdHJhc2hlZCIsImxhc3RfZ3JvdXAiLCJhbGVydCIsIiRxdWVzdGlvbnMiLCJhbmltYXRlIiwic2Nyb2xsVG9wIiwiYnVsa190b2dnbGUiLCJleHBhbmRlZCIsImFkZF9uZXdfcXVpeiIsImFkZF9leGlzdGluZ19xdWl6IiwicG9zdF9zZWFyY2hfcG9wb3ZlciIsImFkZF9leGlzdGluZ19xdWl6X2NsaWNrIiwiZGlzbWlzc2libGUiLCJvbmNlIiwic2hvd190b29scyIsInBvcCIsImFkZG9uX2V2ZW50cyIsImlzX2FkZG9uX2F2YWlsYWJsZSIsImdldF92aWV3X2V2ZW50cyIsImNsaWNrICNsbG1zLWV4aXN0aW5nLWFzc2lnbm1lbnQiLCJjbGljayAjbGxtcy1uZXctYXNzaWdubWVudCIsImFkZF9uZXdfYXNzaWdubWVudCIsImdldF9hc3NpZ25tZW50Iiwic2hvd19hZF9wb3BvdmVyIiwiYWRkX2V4aXN0aW5nX2Fzc2lnbm1lbnQiLCJhZGRfZXhpc3RpbmdfYXNzaWdubWVudF9jbGljayIsImgzIiwiYnRuIiwiYWRfcG9wb3ZlciIsIkxlc3NvbkVkaXRvciIsIkFzc2lnbm1lbnQiLCJjbGljayAubGxtcy1lZGl0b3ItbmF2IGFbaHJlZj1cIiNsbG1zLWVkaXRvci1jbG9zZVwiXSIsImNsaWNrIC5sbG1zLWVkaXRvci1uYXYgYTpub3QoW2hyZWY9XCIjbGxtcy1lZGl0b3ItY2xvc2VcIl0pIiwiU2lkZWJhclZpZXciLCJjbG9zZV9lZGl0b3IiLCJzd2l0Y2hfdGFiIiwiTGVzc29uU2VhcmNoIiwiY2xpY2sgI2xsbXMtbmV3LXNlY3Rpb24iLCJjbGljayAjbGxtcy1uZXctbGVzc29uIiwiY2xpY2sgI2xsbXMtZXhpc3RpbmctbGVzc29uIiwiQ291cnNlVmlldyIsImRyYWdnYWJsZSIsImFwcGVuZFRvIiwiY2FuY2VsIiwiY29ubmVjdFRvU29ydGFibGUiLCJhZGRfbmV3X3NlY3Rpb24iLCJhZGRfbmV3X2xlc3NvbiIsIiRlbHMiLCJjbGljayAjbGxtcy1jb2xsYXBzZS1hbGwiLCJjbGljayAjbGxtcy1leHBhbmQtYWxsIiwiY29sbGFwc2VfYWxsIiwiZXhwYW5kX2FsbCIsIkVkaXRvciIsIkVsZW1lbnRzIiwiZWxlbWVudHMiLCJ1dGlsaXRpZXMiLCJjbGljayAjbGxtcy1zYXZlLWJ1dHRvbiIsImNsaWNrICNsbG1zLWV4aXQtYnV0dG9uIiwiY2xpY2sgLmxsbXMtYnVpbGRlci1lcnJvciIsImNoYW5nZXNfbWFkZSIsImhlYXJ0YmVhdF9zZW5kIiwiaGVhcnRiZWF0X3RpY2siLCJvbl9sZXNzb25fc2VsZWN0Iiwib25fZWRpdG9yX2Nsb3NlIiwiJHNhdmVCdXR0b24iLCJhZGRfZXJyb3IiLCIkZXJyIiwicHJlcGVuZCIsImNsZWFyX2Vycm9ycyIsImV4aXRfbm93IiwiZGF0YS1zdGF0dXMiLCJkaXNhYmxlZCIsInR4dCIsImlzX2VkaXRvcl9hY3RpdmUiLCJsZXNzb25fbW9kZWwiLCJDViIsIlRyYWNrSXQiLCJDb25zdHJ1Y3QiLCJEZWJ1ZyIsIlNjaGVtYXMiLCJTeW5jIiwidmFsdWVfY29tcGFyZSIsImV4cGVjdGVkIiwiYWN0dWFsIiwibWl4aW4iLCJjaGVja2VkIiwiYWxsb3dlZF90YWdzIiwibm90IiwicmVwbGFjZVdpdGgiLCJpbm5lckhUTUwiLCJF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bWdDLGFBSXRCakksRUFBTWhzQixVQU1mbk0sU0FBU3ViLE9BQVN4YixFQUFFOEIsT0FBUSxHQUFJN0IsU0FBU3FnQyxRQUV6Q3ptQyxFQUFHa1AsVUFBV2QsUUFBUyx5QkFFdkJpSixPQUFPcUcsYUFBYWtELFVBQVl2SixPQUFPcUcsYUFBYUMsVUFBVUcsZUFBZ0IsZ0JBQWlCekcsT0FBT3FHLGFBQWFrRCxXQUVuSCxJQUFJa0YsRUFBY3pPLE9BQU9xRyxhQUFhQyxVQUFVQyxVQUFXLFNBQVV2RyxPQUFPcUcsYUFBYTBKLFFBQ3pGL1AsT0FBT3FHLGFBQWFvSSxZQUFjQSxFQUVsQ3pPLE9BQU9xRyxhQUFhdEIsS0FBTyxJQUFJMnBCLEVBQU1qZ0IsRUFBYXpPLE9BQU9xRyxhQUFhdEIsTUFFdEUsSUFBSStOLEVBQVMsSUFBSW9aLEVBQVksQ0FDNUI5MUIsTUFBT3FZLElBR0o0Z0IsRUFBVSxJQUFJMUQsRUFBYSxDQUM5Qk8sV0FBWXBaLElBR2JucUIsRUFBR2tQLFVBQVdkLFFBQVMsb0JBQXFCLENBQzNDZ1osT0FBUStDLEVBQ1J3YyxRQUFTRCxNQUtYdm1DLEVBQU8sT0FBUSxjQXh2VWYsQ0EwdlVFK0YiLCJmaWxlIjoibGxtcy1idWlsZGVyLm1pbi5qcyIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbigkKXtcbi8qKlxuICogQGxpY2Vuc2UgYWxtb25kIDAuMy4zIENvcHlyaWdodCBqUXVlcnkgRm91bmRhdGlvbiBhbmQgb3RoZXIgY29udHJpYnV0b3JzLlxuICogUmVsZWFzZWQgdW5kZXIgTUlUIGxpY2Vuc2UsIGh0dHA6Ly9naXRodWIuY29tL3JlcXVpcmVqcy9hbG1vbmQvTElDRU5TRVxuICovXG4vL0dvaW5nIHNsb3BweSB0byBhdm9pZCAndXNlIHN0cmljdCcgc3RyaW5nIGNvc3QsIGJ1dCBzdHJpY3QgcHJhY3RpY2VzIHNob3VsZFxuLy9iZSBmb2xsb3dlZC5cbi8qZ2xvYmFsIHNldFRpbWVvdXQ6IGZhbHNlICovXG5cbnZhciByZXF1aXJlanMsIHJlcXVpcmUsIGRlZmluZTtcbihmdW5jdGlvbiAodW5kZWYpIHtcblx0dmFyIG1haW4sIHJlcSwgbWFrZU1hcCwgaGFuZGxlcnMsXG5cdFx0ZGVmaW5lZCA9IHt9LFxuXHRcdHdhaXRpbmcgPSB7fSxcblx0XHRjb25maWcgPSB7fSxcblx0XHRkZWZpbmluZyA9IHt9LFxuXHRcdGhhc093biA9IE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHksXG5cdFx0YXBzID0gW10uc2xpY2UsXG5cdFx0anNTdWZmaXhSZWdFeHAgPSAvXFwuanMkLztcblxuXHRmdW5jdGlvbiBoYXNQcm9wKG9iaiwgcHJvcCkge1xuXHRcdHJldHVybiBoYXNPd24uY2FsbChvYmosIHByb3ApO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdpdmVuIGEgcmVsYXRpdmUgbW9kdWxlIG5hbWUsIGxpa2UgLi9zb21ldGhpbmcsIG5vcm1hbGl6ZSBpdCB0b1xuXHQgKiBhIHJlYWwgbmFtZSB0aGF0IGNhbiBiZSBtYXBwZWQgdG8gYSBwYXRoLlxuXHQgKiBAcGFyYW0ge1N0cmluZ30gbmFtZSB0aGUgcmVsYXRpdmUgbmFtZVxuXHQgKiBAcGFyYW0ge1N0cmluZ30gYmFzZU5hbWUgYSByZWFsIG5hbWUgdGhhdCB0aGUgbmFtZSBhcmcgaXMgcmVsYXRpdmVcblx0ICogdG8uXG5cdCAqIEByZXR1cm5zIHtTdHJpbmd9IG5vcm1hbGl6ZWQgbmFtZVxuXHQgKi9cblx0ZnVuY3Rpb24gbm9ybWFsaXplKG5hbWUsIGJhc2VOYW1lKSB7XG5cdFx0dmFyIG5hbWVQYXJ0cywgbmFtZVNlZ21lbnQsIG1hcFZhbHVlLCBmb3VuZE1hcCwgbGFzdEluZGV4LFxuXHRcdFx0Zm91bmRJLCBmb3VuZFN0YXJNYXAsIHN0YXJJLCBpLCBqLCBwYXJ0LCBub3JtYWxpemVkQmFzZVBhcnRzLFxuXHRcdFx0YmFzZVBhcnRzID0gYmFzZU5hbWUgJiYgYmFzZU5hbWUuc3BsaXQoXCIvXCIpLFxuXHRcdFx0bWFwID0gY29uZmlnLm1hcCxcblx0XHRcdHN0YXJNYXAgPSAobWFwICYmIG1hcFsnKiddKSB8fCB7fTtcblxuXHRcdC8vQWRqdXN0IGFueSByZWxhdGl2ZSBwYXRocy5cblx0XHRpZiAobmFtZSkge1xuXHRcdFx0bmFtZSA9IG5hbWUuc3BsaXQoJy8nKTtcblx0XHRcdGxhc3RJbmRleCA9IG5hbWUubGVuZ3RoIC0gMTtcblxuXHRcdFx0Ly8gSWYgd2FudGluZyBub2RlIElEIGNvbXBhdGliaWxpdHksIHN0cmlwIC5qcyBmcm9tIGVuZFxuXHRcdFx0Ly8gb2YgSURzLiBIYXZlIHRvIGRvIHRoaXMgaGVyZSwgYW5kIG5vdCBpbiBuYW1lVG9Vcmxcblx0XHRcdC8vIGJlY2F1c2Ugbm9kZSBhbGxvd3MgZWl0aGVyIC5qcyBvciBub24gLmpzIHRvIG1hcFxuXHRcdFx0Ly8gdG8gc2FtZSBmaWxlLlxuXHRcdFx0aWYgKGNvbmZpZy5ub2RlSWRDb21wYXQgJiYganNTdWZmaXhSZWdFeHAudGVzdChuYW1lW2xhc3RJbmRleF0pKSB7XG5cdFx0XHRcdG5hbWVbbGFzdEluZGV4XSA9IG5hbWVbbGFzdEluZGV4XS5yZXBsYWNlKGpzU3VmZml4UmVnRXhwLCAnJyk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIFN0YXJ0cyB3aXRoIGEgJy4nIHNvIG5lZWQgdGhlIGJhc2VOYW1lXG5cdFx0XHRpZiAobmFtZVswXS5jaGFyQXQoMCkgPT09ICcuJyAmJiBiYXNlUGFydHMpIHtcblx0XHRcdFx0Ly9Db252ZXJ0IGJhc2VOYW1lIHRvIGFycmF5LCBhbmQgbG9wIG9mZiB0aGUgbGFzdCBwYXJ0LFxuXHRcdFx0XHQvL3NvIHRoYXQgLiBtYXRjaGVzIHRoYXQgJ2RpcmVjdG9yeScgYW5kIG5vdCBuYW1lIG9mIHRoZSBiYXNlTmFtZSdzXG5cdFx0XHRcdC8vbW9kdWxlLiBGb3IgaW5zdGFuY2UsIGJhc2VOYW1lIG9mICdvbmUvdHdvL3RocmVlJywgbWFwcyB0b1xuXHRcdFx0XHQvLydvbmUvdHdvL3RocmVlLmpzJywgYnV0IHdlIHdhbnQgdGhlIGRpcmVjdG9yeSwgJ29uZS90d28nIGZvclxuXHRcdFx0XHQvL3RoaXMgbm9ybWFsaXphdGlvbi5cblx0XHRcdFx0bm9ybWFsaXplZEJhc2VQYXJ0cyA9IGJhc2VQYXJ0cy5zbGljZSgwLCBiYXNlUGFydHMubGVuZ3RoIC0gMSk7XG5cdFx0XHRcdG5hbWUgPSBub3JtYWxpemVkQmFzZVBhcnRzLmNvbmNhdChuYW1lKTtcblx0XHRcdH1cblxuXHRcdFx0Ly9zdGFydCB0cmltRG90c1xuXHRcdFx0Zm9yIChpID0gMDsgaSA8IG5hbWUubGVuZ3RoOyBpKyspIHtcblx0XHRcdFx0cGFydCA9IG5hbWVbaV07XG5cdFx0XHRcdGlmIChwYXJ0ID09PSAnLicpIHtcblx0XHRcdFx0XHRuYW1lLnNwbGljZShpLCAxKTtcblx0XHRcdFx0XHRpIC09IDE7XG5cdFx0XHRcdH0gZWxzZSBpZiAocGFydCA9PT0gJy4uJykge1xuXHRcdFx0XHRcdC8vIElmIGF0IHRoZSBzdGFydCwgb3IgcHJldmlvdXMgdmFsdWUgaXMgc3RpbGwgLi4sXG5cdFx0XHRcdFx0Ly8ga2VlcCB0aGVtIHNvIHRoYXQgd2hlbiBjb252ZXJ0ZWQgdG8gYSBwYXRoIGl0IG1heVxuXHRcdFx0XHRcdC8vIHN0aWxsIHdvcmsgd2hlbiBjb252ZXJ0ZWQgdG8gYSBwYXRoLCBldmVuIHRob3VnaFxuXHRcdFx0XHRcdC8vIGFzIGFuIElEIGl0IGlzIGxlc3MgdGhhbiBpZGVhbC4gSW4gbGFyZ2VyIHBvaW50XG5cdFx0XHRcdFx0Ly8gcmVsZWFzZXMsIG1heSBiZSBiZXR0ZXIgdG8ganVzdCBraWNrIG91dCBhbiBlcnJvci5cblx0XHRcdFx0XHRpZiAoaSA9PT0gMCB8fCAoaSA9PT0gMSAmJiBuYW1lWzJdID09PSAnLi4nKSB8fCBuYW1lW2kgLSAxXSA9PT0gJy4uJykge1xuXHRcdFx0XHRcdFx0Y29udGludWU7XG5cdFx0XHRcdFx0fSBlbHNlIGlmIChpID4gMCkge1xuXHRcdFx0XHRcdFx0bmFtZS5zcGxpY2UoaSAtIDEsIDIpO1xuXHRcdFx0XHRcdFx0aSAtPSAyO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0Ly9lbmQgdHJpbURvdHNcblxuXHRcdFx0bmFtZSA9IG5hbWUuam9pbignLycpO1xuXHRcdH1cblxuXHRcdC8vQXBwbHkgbWFwIGNvbmZpZyBpZiBhdmFpbGFibGUuXG5cdFx0aWYgKChiYXNlUGFydHMgfHwgc3Rhck1hcCkgJiYgbWFwKSB7XG5cdFx0XHRuYW1lUGFydHMgPSBuYW1lLnNwbGl0KCcvJyk7XG5cblx0XHRcdGZvciAoaSA9IG5hbWVQYXJ0cy5sZW5ndGg7IGkgPiAwOyBpIC09IDEpIHtcblx0XHRcdFx0bmFtZVNlZ21lbnQgPSBuYW1lUGFydHMuc2xpY2UoMCwgaSkuam9pbihcIi9cIik7XG5cblx0XHRcdFx0aWYgKGJhc2VQYXJ0cykge1xuXHRcdFx0XHRcdC8vRmluZCB0aGUgbG9uZ2VzdCBiYXNlTmFtZSBzZWdtZW50IG1hdGNoIGluIHRoZSBjb25maWcuXG5cdFx0XHRcdFx0Ly9TbywgZG8gam9pbnMgb24gdGhlIGJpZ2dlc3QgdG8gc21hbGxlc3QgbGVuZ3RocyBvZiBiYXNlUGFydHMuXG5cdFx0XHRcdFx0Zm9yIChqID0gYmFzZVBhcnRzLmxlbmd0aDsgaiA+IDA7IGogLT0gMSkge1xuXHRcdFx0XHRcdFx0bWFwVmFsdWUgPSBtYXBbYmFzZVBhcnRzLnNsaWNlKDAsIGopLmpvaW4oJy8nKV07XG5cblx0XHRcdFx0XHRcdC8vYmFzZU5hbWUgc2VnbWVudCBoYXMgIGNvbmZpZywgZmluZCBpZiBpdCBoYXMgb25lIGZvclxuXHRcdFx0XHRcdFx0Ly90aGlzIG5hbWUuXG5cdFx0XHRcdFx0XHRpZiAobWFwVmFsdWUpIHtcblx0XHRcdFx0XHRcdFx0bWFwVmFsdWUgPSBtYXBWYWx1ZVtuYW1lU2VnbWVudF07XG5cdFx0XHRcdFx0XHRcdGlmIChtYXBWYWx1ZSkge1xuXHRcdFx0XHRcdFx0XHRcdC8vTWF0Y2gsIHVwZGF0ZSBuYW1lIHRvIHRoZSBuZXcgdmFsdWUuXG5cdFx0XHRcdFx0XHRcdFx0Zm91bmRNYXAgPSBtYXBWYWx1ZTtcblx0XHRcdFx0XHRcdFx0XHRmb3VuZEkgPSBpO1xuXHRcdFx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYgKGZvdW5kTWFwKSB7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvL0NoZWNrIGZvciBhIHN0YXIgbWFwIG1hdGNoLCBidXQganVzdCBob2xkIG9uIHRvIGl0LFxuXHRcdFx0XHQvL2lmIHRoZXJlIGlzIGEgc2hvcnRlciBzZWdtZW50IG1hdGNoIGxhdGVyIGluIGEgbWF0Y2hpbmdcblx0XHRcdFx0Ly9jb25maWcsIHRoZW4gZmF2b3Igb3ZlciB0aGlzIHN0YXIgbWFwLlxuXHRcdFx0XHRpZiAoIWZvdW5kU3Rhck1hcCAmJiBzdGFyTWFwICYmIHN0YXJNYXBbbmFtZVNlZ21lbnRdKSB7XG5cdFx0XHRcdFx0Zm91bmRTdGFyTWFwID0gc3Rhck1hcFtuYW1lU2VnbWVudF07XG5cdFx0XHRcdFx0c3RhckkgPSBpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdGlmICghZm91bmRNYXAgJiYgZm91bmRTdGFyTWFwKSB7XG5cdFx0XHRcdGZvdW5kTWFwID0gZm91bmRTdGFyTWFwO1xuXHRcdFx0XHRmb3VuZEkgPSBzdGFySTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKGZvdW5kTWFwKSB7XG5cdFx0XHRcdG5hbWVQYXJ0cy5zcGxpY2UoMCwgZm91bmRJLCBmb3VuZE1hcCk7XG5cdFx0XHRcdG5hbWUgPSBuYW1lUGFydHMuam9pbignLycpO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHJldHVybiBuYW1lO1xuXHR9XG5cblx0ZnVuY3Rpb24gbWFrZVJlcXVpcmUocmVsTmFtZSwgZm9yY2VTeW5jKSB7XG5cdFx0cmV0dXJuIGZ1bmN0aW9uICgpIHtcblx0XHRcdC8vQSB2ZXJzaW9uIG9mIGEgcmVxdWlyZSBmdW5jdGlvbiB0aGF0IHBhc3NlcyBhIG1vZHVsZU5hbWVcblx0XHRcdC8vdmFsdWUgZm9yIGl0ZW1zIHRoYXQgbWF5IG5lZWQgdG9cblx0XHRcdC8vbG9vayB1cCBwYXRocyByZWxhdGl2ZSB0byB0aGUgbW9kdWxlTmFtZVxuXHRcdFx0dmFyIGFyZ3MgPSBhcHMuY2FsbChhcmd1bWVudHMsIDApO1xuXG5cdFx0XHQvL0lmIGZpcnN0IGFyZyBpcyBub3QgcmVxdWlyZSgnc3RyaW5nJyksIGFuZCB0aGVyZSBpcyBvbmx5XG5cdFx0XHQvL29uZSBhcmcsIGl0IGlzIHRoZSBhcnJheSBmb3JtIHdpdGhvdXQgYSBjYWxsYmFjay4gSW5zZXJ0XG5cdFx0XHQvL2EgbnVsbCBzbyB0aGF0IHRoZSBmb2xsb3dpbmcgY29uY2F0IGlzIGNvcnJlY3QuXG5cdFx0XHRpZiAodHlwZW9mIGFyZ3NbMF0gIT09ICdzdHJpbmcnICYmIGFyZ3MubGVuZ3RoID09PSAxKSB7XG5cdFx0XHRcdGFyZ3MucHVzaChudWxsKTtcblx0XHRcdH1cblx0XHRcdHJldHVybiByZXEuYXBwbHkodW5kZWYsIGFyZ3MuY29uY2F0KFtyZWxOYW1lLCBmb3JjZVN5bmNdKSk7XG5cdFx0fTtcblx0fVxuXG5cdGZ1bmN0aW9uIG1ha2VOb3JtYWxpemUocmVsTmFtZSkge1xuXHRcdHJldHVybiBmdW5jdGlvbiAobmFtZSkge1xuXHRcdFx0cmV0dXJuIG5vcm1hbGl6ZShuYW1lLCByZWxOYW1lKTtcblx0XHR9O1xuXHR9XG5cblx0ZnVuY3Rpb24gbWFrZUxvYWQoZGVwTmFtZSkge1xuXHRcdHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcblx0XHRcdGRlZmluZWRbZGVwTmFtZV0gPSB2YWx1ZTtcblx0XHR9O1xuXHR9XG5cblx0ZnVuY3Rpb24gY2FsbERlcChuYW1lKSB7XG5cdFx0aWYgKGhhc1Byb3Aod2FpdGluZywgbmFtZSkpIHtcblx0XHRcdHZhciBhcmdzID0gd2FpdGluZ1tuYW1lXTtcblx0XHRcdGRlbGV0ZSB3YWl0aW5nW25hbWVdO1xuXHRcdFx0ZGVmaW5pbmdbbmFtZV0gPSB0cnVlO1xuXHRcdFx0bWFpbi5hcHBseSh1bmRlZiwgYXJncyk7XG5cdFx0fVxuXG5cdFx0aWYgKCFoYXNQcm9wKGRlZmluZWQsIG5hbWUpICYmICFoYXNQcm9wKGRlZmluaW5nLCBuYW1lKSkge1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKCdObyAnICsgbmFtZSk7XG5cdFx0fVxuXHRcdHJldHVybiBkZWZpbmVkW25hbWVdO1xuXHR9XG5cblx0Ly9UdXJucyBhIHBsdWdpbiFyZXNvdXJjZSB0byBbcGx1Z2luLCByZXNvdXJjZV1cblx0Ly93aXRoIHRoZSBwbHVnaW4gYmVpbmcgdW5kZWZpbmVkIGlmIHRoZSBuYW1lXG5cdC8vZGlkIG5vdCBoYXZlIGEgcGx1Z2luIHByZWZpeC5cblx0ZnVuY3Rpb24gc3BsaXRQcmVmaXgobmFtZSkge1xuXHRcdHZhciBwcmVmaXgsXG5cdFx0XHRpbmRleCA9IG5hbWUgPyBuYW1lLmluZGV4T2YoJyEnKSA6IC0xO1xuXHRcdGlmIChpbmRleCA+IC0xKSB7XG5cdFx0XHRwcmVmaXggPSBuYW1lLnN1YnN0cmluZygwLCBpbmRleCk7XG5cdFx0XHRuYW1lID0gbmFtZS5zdWJzdHJpbmcoaW5kZXggKyAxLCBuYW1lLmxlbmd0aCk7XG5cdFx0fVxuXHRcdHJldHVybiBbcHJlZml4LCBuYW1lXTtcblx0fVxuXG5cdC8vQ3JlYXRlcyBhIHBhcnRzIGFycmF5IGZvciBhIHJlbE5hbWUgd2hlcmUgZmlyc3QgcGFydCBpcyBwbHVnaW4gSUQsXG5cdC8vc2Vjb25kIHBhcnQgaXMgcmVzb3VyY2UgSUQuIEFzc3VtZXMgcmVsTmFtZSBoYXMgYWxyZWFkeSBiZWVuIG5vcm1hbGl6ZWQuXG5cdGZ1bmN0aW9uIG1ha2VSZWxQYXJ0cyhyZWxOYW1lKSB7XG5cdFx0cmV0dXJuIHJlbE5hbWUgPyBzcGxpdFByZWZpeChyZWxOYW1lKSA6IFtdO1xuXHR9XG5cblx0LyoqXG5cdCAqIE1ha2VzIGEgbmFtZSBtYXAsIG5vcm1hbGl6aW5nIHRoZSBuYW1lLCBhbmQgdXNpbmcgYSBwbHVnaW5cblx0ICogZm9yIG5vcm1hbGl6YXRpb24gaWYgbmVjZXNzYXJ5LiBHcmFicyBhIHJlZiB0byBwbHVnaW5cblx0ICogdG9vLCBhcyBhbiBvcHRpbWl6YXRpb24uXG5cdCAqL1xuXHRtYWtlTWFwID0gZnVuY3Rpb24gKG5hbWUsIHJlbFBhcnRzKSB7XG5cdFx0dmFyIHBsdWdpbixcblx0XHRcdHBhcnRzID0gc3BsaXRQcmVmaXgobmFtZSksXG5cdFx0XHRwcmVmaXggPSBwYXJ0c1swXSxcblx0XHRcdHJlbFJlc291cmNlTmFtZSA9IHJlbFBhcnRzWzFdO1xuXG5cdFx0bmFtZSA9IHBhcnRzWzFdO1xuXG5cdFx0aWYgKHByZWZpeCkge1xuXHRcdFx0cHJlZml4ID0gbm9ybWFsaXplKHByZWZpeCwgcmVsUmVzb3VyY2VOYW1lKTtcblx0XHRcdHBsdWdpbiA9IGNhbGxEZXAocHJlZml4KTtcblx0XHR9XG5cblx0XHQvL05vcm1hbGl6ZSBhY2NvcmRpbmdcblx0XHRpZiAocHJlZml4KSB7XG5cdFx0XHRpZiAocGx1Z2luICYmIHBsdWdpbi5ub3JtYWxpemUpIHtcblx0XHRcdFx0bmFtZSA9IHBsdWdpbi5ub3JtYWxpemUobmFtZSwgbWFrZU5vcm1hbGl6ZShyZWxSZXNvdXJjZU5hbWUpKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdG5hbWUgPSBub3JtYWxpemUobmFtZSwgcmVsUmVzb3VyY2VOYW1lKTtcblx0XHRcdH1cblx0XHR9IGVsc2Uge1xuXHRcdFx0bmFtZSA9IG5vcm1hbGl6ZShuYW1lLCByZWxSZXNvdXJjZU5hbWUpO1xuXHRcdFx0cGFydHMgPSBzcGxpdFByZWZpeChuYW1lKTtcblx0XHRcdHByZWZpeCA9IHBhcnRzWzBdO1xuXHRcdFx0bmFtZSA9IHBhcnRzWzFdO1xuXHRcdFx0aWYgKHByZWZpeCkge1xuXHRcdFx0XHRwbHVnaW4gPSBjYWxsRGVwKHByZWZpeCk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly9Vc2luZyByaWRpY3Vsb3VzIHByb3BlcnR5IG5hbWVzIGZvciBzcGFjZSByZWFzb25zXG5cdFx0cmV0dXJuIHtcblx0XHRcdGY6IHByZWZpeCA/IHByZWZpeCArICchJyArIG5hbWUgOiBuYW1lLCAvL2Z1bGxOYW1lXG5cdFx0XHRuOiBuYW1lLFxuXHRcdFx0cHI6IHByZWZpeCxcblx0XHRcdHA6IHBsdWdpblxuXHRcdH07XG5cdH07XG5cblx0ZnVuY3Rpb24gbWFrZUNvbmZpZyhuYW1lKSB7XG5cdFx0cmV0dXJuIGZ1bmN0aW9uICgpIHtcblx0XHRcdHJldHVybiAoY29uZmlnICYmIGNvbmZpZy5jb25maWcgJiYgY29uZmlnLmNvbmZpZ1tuYW1lXSkgfHwge307XG5cdFx0fTtcblx0fVxuXG5cdGhhbmRsZXJzID0ge1xuXHRcdHJlcXVpcmU6IGZ1bmN0aW9uIChuYW1lKSB7XG5cdFx0XHRyZXR1cm4gbWFrZVJlcXVpcmUobmFtZSk7XG5cdFx0fSxcblx0XHRleHBvcnRzOiBmdW5jdGlvbiAobmFtZSkge1xuXHRcdFx0dmFyIGUgPSBkZWZpbmVkW25hbWVdO1xuXHRcdFx0aWYgKHR5cGVvZiBlICE9PSAndW5kZWZpbmVkJykge1xuXHRcdFx0XHRyZXR1cm4gZTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHJldHVybiAoZGVmaW5lZFtuYW1lXSA9IHt9KTtcblx0XHRcdH1cblx0XHR9LFxuXHRcdG1vZHVsZTogZnVuY3Rpb24gKG5hbWUpIHtcblx0XHRcdHJldHVybiB7XG5cdFx0XHRcdGlkOiBuYW1lLFxuXHRcdFx0XHR1cmk6ICcnLFxuXHRcdFx0XHRleHBvcnRzOiBkZWZpbmVkW25hbWVdLFxuXHRcdFx0XHRjb25maWc6IG1ha2VDb25maWcobmFtZSlcblx0XHRcdH07XG5cdFx0fVxuXHR9O1xuXG5cdG1haW4gPSBmdW5jdGlvbiAobmFtZSwgZGVwcywgY2FsbGJhY2ssIHJlbE5hbWUpIHtcblx0XHR2YXIgY2pzTW9kdWxlLCBkZXBOYW1lLCByZXQsIG1hcCwgaSwgcmVsUGFydHMsXG5cdFx0XHRhcmdzID0gW10sXG5cdFx0XHRjYWxsYmFja1R5cGUgPSB0eXBlb2YgY2FsbGJhY2ssXG5cdFx0XHR1c2luZ0V4cG9ydHM7XG5cblx0XHQvL1VzZSBuYW1lIGlmIG5vIHJlbE5hbWVcblx0XHRyZWxOYW1lID0gcmVsTmFtZSB8fCBuYW1lO1xuXHRcdHJlbFBhcnRzID0gbWFrZVJlbFBhcnRzKHJlbE5hbWUpO1xuXG5cdFx0Ly9DYWxsIHRoZSBjYWxsYmFjayB0byBkZWZpbmUgdGhlIG1vZHVsZSwgaWYgbmVjZXNzYXJ5LlxuXHRcdGlmIChjYWxsYmFja1R5cGUgPT09ICd1bmRlZmluZWQnIHx8IGNhbGxiYWNrVHlwZSA9PT0gJ2Z1bmN0aW9uJykge1xuXHRcdFx0Ly9QdWxsIG91dCB0aGUgZGVmaW5lZCBkZXBlbmRlbmNpZXMgYW5kIHBhc3MgdGhlIG9yZGVyZWRcblx0XHRcdC8vdmFsdWVzIHRvIHRoZSBjYWxsYmFjay5cblx0XHRcdC8vRGVmYXVsdCB0byBbcmVxdWlyZSwgZXhwb3J0cywgbW9kdWxlXSBpZiBubyBkZXBzXG5cdFx0XHRkZXBzID0gIWRlcHMubGVuZ3RoICYmIGNhbGxiYWNrLmxlbmd0aCA/IFsncmVxdWlyZScsICdleHBvcnRzJywgJ21vZHVsZSddIDogZGVwcztcblx0XHRcdGZvciAoaSA9IDA7IGkgPCBkZXBzLmxlbmd0aDsgaSArPSAxKSB7XG5cdFx0XHRcdG1hcCA9IG1ha2VNYXAoZGVwc1tpXSwgcmVsUGFydHMpO1xuXHRcdFx0XHRkZXBOYW1lID0gbWFwLmY7XG5cblx0XHRcdFx0Ly9GYXN0IHBhdGggQ29tbW9uSlMgc3RhbmRhcmQgZGVwZW5kZW5jaWVzLlxuXHRcdFx0XHRpZiAoZGVwTmFtZSA9PT0gXCJyZXF1aXJlXCIpIHtcblx0XHRcdFx0XHRhcmdzW2ldID0gaGFuZGxlcnMucmVxdWlyZShuYW1lKTtcblx0XHRcdFx0fSBlbHNlIGlmIChkZXBOYW1lID09PSBcImV4cG9ydHNcIikge1xuXHRcdFx0XHRcdC8vQ29tbW9uSlMgbW9kdWxlIHNwZWMgMS4xXG5cdFx0XHRcdFx0YXJnc1tpXSA9IGhhbmRsZXJzLmV4cG9ydHMobmFtZSk7XG5cdFx0XHRcdFx0dXNpbmdFeHBvcnRzID0gdHJ1ZTtcblx0XHRcdFx0fSBlbHNlIGlmIChkZXBOYW1lID09PSBcIm1vZHVsZVwiKSB7XG5cdFx0XHRcdFx0Ly9Db21tb25KUyBtb2R1bGUgc3BlYyAxLjFcblx0XHRcdFx0XHRjanNNb2R1bGUgPSBhcmdzW2ldID0gaGFuZGxlcnMubW9kdWxlKG5hbWUpO1xuXHRcdFx0XHR9IGVsc2UgaWYgKGhhc1Byb3AoZGVmaW5lZCwgZGVwTmFtZSkgfHxcblx0XHRcdFx0XHRcdCAgIGhhc1Byb3Aod2FpdGluZywgZGVwTmFtZSkgfHxcblx0XHRcdFx0XHRcdCAgIGhhc1Byb3AoZGVmaW5pbmcsIGRlcE5hbWUpKSB7XG5cdFx0XHRcdFx0YXJnc1tpXSA9IGNhbGxEZXAoZGVwTmFtZSk7XG5cdFx0XHRcdH0gZWxzZSBpZiAobWFwLnApIHtcblx0XHRcdFx0XHRtYXAucC5sb2FkKG1hcC5uLCBtYWtlUmVxdWlyZShyZWxOYW1lLCB0cnVlKSwgbWFrZUxvYWQoZGVwTmFtZSksIHt9KTtcblx0XHRcdFx0XHRhcmdzW2ldID0gZGVmaW5lZFtkZXBOYW1lXTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHR0aHJvdyBuZXcgRXJyb3IobmFtZSArICcgbWlzc2luZyAnICsgZGVwTmFtZSk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0cmV0ID0gY2FsbGJhY2sgPyBjYWxsYmFjay5hcHBseShkZWZpbmVkW25hbWVdLCBhcmdzKSA6IHVuZGVmaW5lZDtcblxuXHRcdFx0aWYgKG5hbWUpIHtcblx0XHRcdFx0Ly9JZiBzZXR0aW5nIGV4cG9ydHMgdmlhIFwibW9kdWxlXCIgaXMgaW4gcGxheSxcblx0XHRcdFx0Ly9mYXZvciB0aGF0IG92ZXIgcmV0dXJuIHZhbHVlIGFuZCBleHBvcnRzLiBBZnRlciB0aGF0LFxuXHRcdFx0XHQvL2Zhdm9yIGEgbm9uLXVuZGVmaW5lZCByZXR1cm4gdmFsdWUgb3ZlciBleHBvcnRzIHVzZS5cblx0XHRcdFx0aWYgKGNqc01vZHVsZSAmJiBjanNNb2R1bGUuZXhwb3J0cyAhPT0gdW5kZWYgJiZcblx0XHRcdFx0XHRcdGNqc01vZHVsZS5leHBvcnRzICE9PSBkZWZpbmVkW25hbWVdKSB7XG5cdFx0XHRcdFx0ZGVmaW5lZFtuYW1lXSA9IGNqc01vZHVsZS5leHBvcnRzO1xuXHRcdFx0XHR9IGVsc2UgaWYgKHJldCAhPT0gdW5kZWYgfHwgIXVzaW5nRXhwb3J0cykge1xuXHRcdFx0XHRcdC8vVXNlIHRoZSByZXR1cm4gdmFsdWUgZnJvbSB0aGUgZnVuY3Rpb24uXG5cdFx0XHRcdFx0ZGVmaW5lZFtuYW1lXSA9IHJldDtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0gZWxzZSBpZiAobmFtZSkge1xuXHRcdFx0Ly9NYXkganVzdCBiZSBhbiBvYmplY3QgZGVmaW5pdGlvbiBmb3IgdGhlIG1vZHVsZS4gT25seVxuXHRcdFx0Ly93b3JyeSBhYm91dCBkZWZpbmluZyBpZiBoYXZlIGEgbW9kdWxlIG5hbWUuXG5cdFx0XHRkZWZpbmVkW25hbWVdID0gY2FsbGJhY2s7XG5cdFx0fVxuXHR9O1xuXG5cdHJlcXVpcmVqcyA9IHJlcXVpcmUgPSByZXEgPSBmdW5jdGlvbiAoZGVwcywgY2FsbGJhY2ssIHJlbE5hbWUsIGZvcmNlU3luYywgYWx0KSB7XG5cdFx0aWYgKHR5cGVvZiBkZXBzID09PSBcInN0cmluZ1wiKSB7XG5cdFx0XHRpZiAoaGFuZGxlcnNbZGVwc10pIHtcblx0XHRcdFx0Ly9jYWxsYmFjayBpbiB0aGlzIGNhc2UgaXMgcmVhbGx5IHJlbE5hbWVcblx0XHRcdFx0cmV0dXJuIGhhbmRsZXJzW2RlcHNdKGNhbGxiYWNrKTtcblx0XHRcdH1cblx0XHRcdC8vSnVzdCByZXR1cm4gdGhlIG1vZHVsZSB3YW50ZWQuIEluIHRoaXMgc2NlbmFyaW8sIHRoZVxuXHRcdFx0Ly9kZXBzIGFyZyBpcyB0aGUgbW9kdWxlIG5hbWUsIGFuZCBzZWNvbmQgYXJnIChpZiBwYXNzZWQpXG5cdFx0XHQvL2lzIGp1c3QgdGhlIHJlbE5hbWUuXG5cdFx0XHQvL05vcm1hbGl6ZSBtb2R1bGUgbmFtZSwgaWYgaXQgY29udGFpbnMgLiBvciAuLlxuXHRcdFx0cmV0dXJuIGNhbGxEZXAobWFrZU1hcChkZXBzLCBtYWtlUmVsUGFydHMoY2FsbGJhY2spKS5mKTtcblx0XHR9IGVsc2UgaWYgKCFkZXBzLnNwbGljZSkge1xuXHRcdFx0Ly9kZXBzIGlzIGEgY29uZmlnIG9iamVjdCwgbm90IGFuIGFycmF5LlxuXHRcdFx0Y29uZmlnID0gZGVwcztcblx0XHRcdGlmIChjb25maWcuZGVwcykge1xuXHRcdFx0XHRyZXEoY29uZmlnLmRlcHMsIGNvbmZpZy5jYWxsYmFjayk7XG5cdFx0XHR9XG5cdFx0XHRpZiAoIWNhbGxiYWNrKSB7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblxuXHRcdFx0aWYgKGNhbGxiYWNrLnNwbGljZSkge1xuXHRcdFx0XHQvL2NhbGxiYWNrIGlzIGFuIGFycmF5LCB3aGljaCBtZWFucyBpdCBpcyBhIGRlcGVuZGVuY3kgbGlzdC5cblx0XHRcdFx0Ly9BZGp1c3QgYXJncyBpZiB0aGVyZSBhcmUgZGVwZW5kZW5jaWVzXG5cdFx0XHRcdGRlcHMgPSBjYWxsYmFjaztcblx0XHRcdFx0Y2FsbGJhY2sgPSByZWxOYW1lO1xuXHRcdFx0XHRyZWxOYW1lID0gbnVsbDtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGRlcHMgPSB1bmRlZjtcblx0XHRcdH1cblx0XHR9XG5cblx0XHQvL1N1cHBvcnQgcmVxdWlyZShbJ2EnXSlcblx0XHRjYWxsYmFjayA9IGNhbGxiYWNrIHx8IGZ1bmN0aW9uICgpIHt9O1xuXG5cdFx0Ly9JZiByZWxOYW1lIGlzIGEgZnVuY3Rpb24sIGl0IGlzIGFuIGVycmJhY2sgaGFuZGxlcixcblx0XHQvL3NvIHJlbW92ZSBpdC5cblx0XHRpZiAodHlwZW9mIHJlbE5hbWUgPT09ICdmdW5jdGlvbicpIHtcblx0XHRcdHJlbE5hbWUgPSBmb3JjZVN5bmM7XG5cdFx0XHRmb3JjZVN5bmMgPSBhbHQ7XG5cdFx0fVxuXG5cdFx0Ly9TaW11bGF0ZSBhc3luYyBjYWxsYmFjaztcblx0XHRpZiAoZm9yY2VTeW5jKSB7XG5cdFx0XHRtYWluKHVuZGVmLCBkZXBzLCBjYWxsYmFjaywgcmVsTmFtZSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdC8vVXNpbmcgYSBub24temVybyB2YWx1ZSBiZWNhdXNlIG9mIGNvbmNlcm4gZm9yIHdoYXQgb2xkIGJyb3dzZXJzXG5cdFx0XHQvL2RvLCBhbmQgbGF0ZXN0IGJyb3dzZXJzIFwidXBncmFkZVwiIHRvIDQgaWYgbG93ZXIgdmFsdWUgaXMgdXNlZDpcblx0XHRcdC8vaHR0cDovL3d3dy53aGF0d2cub3JnL3NwZWNzL3dlYi1hcHBzL2N1cnJlbnQtd29yay9tdWx0aXBhZ2UvdGltZXJzLmh0bWwjZG9tLXdpbmRvd3RpbWVycy1zZXR0aW1lb3V0OlxuXHRcdFx0Ly9JZiB3YW50IGEgdmFsdWUgaW1tZWRpYXRlbHksIHVzZSByZXF1aXJlKCdpZCcpIGluc3RlYWQgLS0gc29tZXRoaW5nXG5cdFx0XHQvL3RoYXQgd29ya3MgaW4gYWxtb25kIG9uIHRoZSBnbG9iYWwgbGV2ZWwsIGJ1dCBub3QgZ3VhcmFudGVlZCBhbmRcblx0XHRcdC8vdW5saWtlbHkgdG8gd29yayBpbiBvdGhlciBBTUQgaW1wbGVtZW50YXRpb25zLlxuXHRcdFx0c2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdG1haW4odW5kZWYsIGRlcHMsIGNhbGxiYWNrLCByZWxOYW1lKTtcblx0XHRcdH0sIDQpO1xuXHRcdH1cblxuXHRcdHJldHVybiByZXE7XG5cdH07XG5cblx0LyoqXG5cdCAqIEp1c3QgZHJvcHMgdGhlIGNvbmZpZyBvbiB0aGUgZmxvb3IsIGJ1dCByZXR1cm5zIHJlcSBpbiBjYXNlXG5cdCAqIHRoZSBjb25maWcgcmV0dXJuIHZhbHVlIGlzIHVzZWQuXG5cdCAqL1xuXHRyZXEuY29uZmlnID0gZnVuY3Rpb24gKGNmZykge1xuXHRcdHJldHVybiByZXEoY2ZnKTtcblx0fTtcblxuXHQvKipcblx0ICogRXhwb3NlIG1vZHVsZSByZWdpc3RyeSBmb3IgZGVidWdnaW5nIGFuZCB0b29saW5nXG5cdCAqL1xuXHRyZXF1aXJlanMuX2RlZmluZWQgPSBkZWZpbmVkO1xuXG5cdGRlZmluZSA9IGZ1bmN0aW9uIChuYW1lLCBkZXBzLCBjYWxsYmFjaykge1xuXHRcdGlmICh0eXBlb2YgbmFtZSAhPT0gJ3N0cmluZycpIHtcblx0XHRcdHRocm93IG5ldyBFcnJvcignU2VlIGFsbW9uZCBSRUFETUU6IGluY29ycmVjdCBtb2R1bGUgYnVpbGQsIG5vIG1vZHVsZSBuYW1lJyk7XG5cdFx0fVxuXG5cdFx0Ly9UaGlzIG1vZHVsZSBtYXkgbm90IGhhdmUgZGVwZW5kZW5jaWVzXG5cdFx0aWYgKCFkZXBzLnNwbGljZSkge1xuXHRcdFx0Ly9kZXBzIGlzIG5vdCBhbiBhcnJheSwgc28gcHJvYmFibHkgbWVhbnNcblx0XHRcdC8vYW4gb2JqZWN0IGxpdGVyYWwgb3IgZmFjdG9yeSBmdW5jdGlvbiBmb3Jcblx0XHRcdC8vdGhlIHZhbHVlLiBBZGp1c3QgYXJncy5cblx0XHRcdGNhbGxiYWNrID0gZGVwcztcblx0XHRcdGRlcHMgPSBbXTtcblx0XHR9XG5cblx0XHRpZiAoIWhhc1Byb3AoZGVmaW5lZCwgbmFtZSkgJiYgIWhhc1Byb3Aod2FpdGluZywgbmFtZSkpIHtcblx0XHRcdHdhaXRpbmdbbmFtZV0gPSBbbmFtZSwgZGVwcywgY2FsbGJhY2tdO1xuXHRcdH1cblx0fTtcblxuXHRkZWZpbmUuYW1kID0ge1xuXHRcdGpRdWVyeTogdHJ1ZVxuXHR9O1xufSgpKTtcblxuZGVmaW5lKFwidmVuZG9yL2FsbW9uZFwiLCBmdW5jdGlvbigpe30pO1xuXG4vKipcbiAqIFJldHVybnMgdGhlIFdvcmRQcmVzcy1sb2FkZWQgdmVyc2lvbiBvZiBVbmRlcnNjb3JlIGZvciB1c2Ugd2l0aCB0aGluZ3MgdGhhdCBuZWVkIGl0IGFuZCB1c2UgUmVxdWlyZS5cbiAqIEByZXR1cm4gICBvYmpcbiAqIEBzaW5jZSAgICAzLjE2LjBcbiAqIEB2ZXJzaW9uICAzLjE2LjBcbiAqL1xuZGVmaW5lKCAndW5kZXJzY29yZScsW10sZnVuY3Rpb24oKSB7XG5cdHJldHVybiBfO1xufSApO1xuXG4vKipcbiAqIFJldHVybnMgdGhlIFdvcmRQcmVzcy1sb2FkZWQgdmVyc2lvbiBvZiBCYWNrYm9uZSBmb3IgdXNlIHdpdGggdGhpbmdzIHRoYXQgbmVlZCBpdCBhbmQgdXNlIFJlcXVpcmUuXG4gKiBAcmV0dXJuICAgb2JqXG4gKiBAc2luY2UgICAgMy4xNi4wXG4gKiBAdmVyc2lvbiAgMy4xNi4wXG4gKi9cbmRlZmluZSggJ2JhY2tib25lJyxbXSxmdW5jdGlvbigpIHtcblx0cmV0dXJuIEJhY2tib25lO1xufSApO1xuXG4vKipcbiAqIFJldHVybnMgdGhlIFdvcmRQcmVzcy1sb2FkZWQgdmVyc2lvbiBvZiBVbmRlcnNjb3JlIGZvciB1c2Ugd2l0aCB0aGluZ3MgdGhhdCBuZWVkIGl0IGFuZCB1c2UgUmVxdWlyZS5cbiAqIEByZXR1cm4gICBvYmpcbiAqIEBzaW5jZSAgICAzLjE2LjBcbiAqIEB2ZXJzaW9uICAzLjE2LjBcbiAqL1xuZGVmaW5lKCAnanF1ZXJ5JyxbXSxmdW5jdGlvbigpIHtcblx0cmV0dXJuIGpRdWVyeTtcbn0gKTtcblxuLyohXG4qIEJhY2tib25lLkNvbGxlY3Rpb25WaWV3LCB2MS4zLjRcbiogQ29weXJpZ2h0IChjKTIwMTMgUm90dW5kYSBTb2Z0d2FyZSwgTExDLlxuKiBEaXN0cmlidXRlZCB1bmRlciBNSVQgbGljZW5zZVxuKiBodHRwOi8vZ2l0aHViLmNvbS9yb3R1bmRhc29mdHdhcmUvYmFja2JvbmUtY29sbGVjdGlvbi12aWV3XG4qL1xuXG4oIGZ1bmN0aW9uKCByb290LCBmYWN0b3J5ICkge1xuXHQvLyBVTUQgd3JhcHBlclxuXHRpZiAoIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCApIHtcblx0XHQvLyBBTURcblx0XHRkZWZpbmUoICd2ZW5kb3IvYmFja2JvbmUuY29sbGVjdGlvblZpZXcnLFsgJ3VuZGVyc2NvcmUnLCAnYmFja2JvbmUnLCAnanF1ZXJ5JyBdLCBmYWN0b3J5ICk7XG5cdH0gZWxzZSBpZiAoIHR5cGVvZiBleHBvcnRzICE9PSAndW5kZWZpbmVkJyApIHtcblx0XHQvLyBOb2RlL0NvbW1vbkpTXG5cdFx0bW9kdWxlLmV4cG9ydHMgPSBmYWN0b3J5KCByZXF1aXJlKCd1bmRlcnNjb3JlJyApLCByZXF1aXJlKCAnYmFja2JvbmUnICksIHJlcXVpcmUoICdiYWNrYm9uZScgKS4kICk7XG5cdH0gZWxzZSB7XG5cdFx0Ly8gQnJvd3NlciBnbG9iYWxzXG5cdFx0ZmFjdG9yeSggcm9vdC5fLCByb290LkJhY2tib25lLCAoIHJvb3QualF1ZXJ5IHx8IHJvb3QuWmVwdG8gfHwgcm9vdC4kICkgKTtcblx0fVxufSggdGhpcywgZnVuY3Rpb24oIF8sIEJhY2tib25lLCAkICkge1xuXHR2YXIgbURlZmF1bHRNb2RlbFZpZXdDb25zdHJ1Y3RvciA9IEJhY2tib25lLlZpZXc7XG5cblx0dmFyIGtEZWZhdWx0UmVmZXJlbmNlQnkgPSBcIm1vZGVsXCI7XG5cblx0dmFyIGtPcHRpb25zUmVxdWlyaW5nUmVyZW5kZXJpbmcgPSBbIFwiY29sbGVjdGlvblwiLCBcIm1vZGVsVmlld1wiLCBcIm1vZGVsVmlld09wdGlvbnNcIiwgXCJpdGVtVGVtcGxhdGVcIiwgXCJpdGVtVGVtcGxhdGVGdW5jdGlvblwiLCBcImRldGFjaGVkUmVuZGVyaW5nXCIgXTtcblxuXHR2YXIga1N0eWxlc0ZvckVtcHR5TGlzdENhcHRpb24gPSB7XG5cdFx0XCJiYWNrZ3JvdW5kXCIgOiBcInRyYW5zcGFyZW50XCIsXG5cdFx0XCJib3JkZXJcIiA6IFwibm9uZVwiLFxuXHRcdFwiYm94LXNoYWRvd1wiIDogXCJub25lXCJcblx0fTtcblxuXHRCYWNrYm9uZS5Db2xsZWN0aW9uVmlldyA9IEJhY2tib25lLlZpZXcuZXh0ZW5kKCB7XG5cblx0XHR0YWdOYW1lIDogXCJ1bFwiLFxuXG5cdFx0ZXZlbnRzIDoge1xuXHRcdFx0XCJtb3VzZWRvd24gPiBsaSwgdGJvZHkgPiB0ciA+IHRkXCIgOiBcIl9saXN0SXRlbV9vbk1vdXNlZG93blwiLFxuXHRcdFx0XCJkYmxjbGljayA+IGxpLCB0Ym9keSA+IHRyID4gdGRcIiA6IFwiX2xpc3RJdGVtX29uRG91YmxlQ2xpY2tcIixcblx0XHRcdFwiY2xpY2tcIiA6IFwiX2xpc3RCYWNrZ3JvdW5kX29uQ2xpY2tcIixcblx0XHRcdFwiY2xpY2sgdWwuY29sbGVjdGlvbi12aWV3LCB0YWJsZS5jb2xsZWN0aW9uLXZpZXdcIiA6IFwiX2xpc3RCYWNrZ3JvdW5kX29uQ2xpY2tcIixcblx0XHRcdFwia2V5ZG93blwiIDogXCJfb25LZXlkb3duXCJcblx0XHR9LFxuXG5cdFx0Ly8gb25seSB1c2VkIGlmIEJhY2tib25lLkNvdXJpZXIgaXMgYXZhaWxhYmxlXG5cdFx0c3Bhd25NZXNzYWdlcyA6IHtcblx0XHRcdFwiZm9jdXNcIiA6IFwiZm9jdXNcIlxuXHRcdH0sXG5cblx0XHQvL29ubHkgdXNlZCBpZiBCYWNrYm9uZS5Db3VyaWVyIGlzIGF2YWlsYWJsZVxuXHRcdHBhc3NNZXNzYWdlcyA6IHsgXCIqXCIgOiBcIi5cIiB9LFxuXG5cdFx0Ly8gdmlld09wdGlvbiBkZWZpbml0aW9ucyB3aXRoIGRlZmF1bHQgdmFsdWVzLlxuXHRcdGluaXRpYWxpemF0aW9uT3B0aW9ucyA6IFtcblx0XHRcdHsgXCJjb2xsZWN0aW9uXCIgOiBudWxsIH0sXG5cdFx0XHR7IFwibW9kZWxWaWV3XCIgOiBudWxsIH0sXG5cdFx0XHR7IFwibW9kZWxWaWV3T3B0aW9uc1wiIDoge30gfSxcblx0XHRcdHsgXCJpdGVtVGVtcGxhdGVcIiA6IG51bGwgfSxcblx0XHRcdHsgXCJpdGVtVGVtcGxhdGVGdW5jdGlvblwiIDogbnVsbCB9LFxuXHRcdFx0eyBcInNlbGVjdGFibGVcIiA6IHRydWUgfSxcblx0XHRcdHsgXCJjbGlja1RvU2VsZWN0XCIgOiB0cnVlIH0sXG5cdFx0XHR7IFwic2VsZWN0YWJsZU1vZGVsc0ZpbHRlclwiIDogbnVsbCB9LFxuXHRcdFx0eyBcInZpc2libGVNb2RlbHNGaWx0ZXJcIiA6IG51bGwgfSxcblx0XHRcdHsgXCJzb3J0YWJsZU1vZGVsc0ZpbHRlclwiIDogbnVsbCB9LFxuXHRcdFx0eyBcInNlbGVjdE11bHRpcGxlXCIgOiBmYWxzZSB9LFxuXHRcdFx0eyBcImNsaWNrVG9Ub2dnbGVcIiA6IGZhbHNlIH0sXG5cdFx0XHR7IFwicHJvY2Vzc0tleUV2ZW50c1wiIDogdHJ1ZSB9LFxuXHRcdFx0eyBcInNvcnRhYmxlXCIgOiBmYWxzZSB9LFxuXHRcdFx0eyBcInNvcnRhYmxlT3B0aW9uc1wiIDogbnVsbCB9LFxuXHRcdFx0eyBcInJldXNlTW9kZWxWaWV3c1wiIDogdHJ1ZSB9LFxuXHRcdFx0eyBcImRldGFjaGVkUmVuZGVyaW5nXCIgOiBmYWxzZSB9LFxuXHRcdFx0eyBcImVtcHR5TGlzdENhcHRpb25cIiA6IG51bGwgfVxuXHRcdF0sXG5cblx0XHRpbml0aWFsaXplIDogZnVuY3Rpb24oIG9wdGlvbnMgKSB7XG5cdFx0XHRCYWNrYm9uZS5WaWV3T3B0aW9ucy5hZGQoIHRoaXMsIFwiaW5pdGlhbGl6YXRpb25PcHRpb25zXCIgKTsgLy8gc2V0dXAgdGhlIFZpZXdPcHRpb25zIGZ1bmN0aW9uYWxpdHkuXG5cdFx0XHR0aGlzLnNldE9wdGlvbnMoIG9wdGlvbnMgKTsgLy8gYW5kIG1ha2UgdXNlIG9mIGFueSBwcm92aWRlZCBvcHRpb25zXG5cblx0XHRcdGlmKCAhIHRoaXMuY29sbGVjdGlvbiApIHRoaXMuY29sbGVjdGlvbiA9IG5ldyBCYWNrYm9uZS5Db2xsZWN0aW9uKCk7XG5cblx0XHRcdHRoaXMuX2hhc0JlZW5SZW5kZXJlZCA9IGZhbHNlO1xuXG5cdFx0XHRpZiggdGhpcy5faXNCYWNrYm9uZUNvdXJpZXJBdmFpbGFibGUoKSApIHtcblx0XHRcdFx0QmFja2JvbmUuQ291cmllci5hZGQoIHRoaXMgKTtcblx0XHRcdH1cblxuXHRcdFx0dGhpcy4kZWwuZGF0YSggXCJ2aWV3XCIsIHRoaXMgKTsgLy8gbmVlZGVkIGZvciBjb25uZWN0ZWQgc29ydGFibGUgbGlzdHNcblx0XHRcdHRoaXMuJGVsLmFkZENsYXNzKCBcImNvbGxlY3Rpb24tdmlldyBjb2xsZWN0aW9uLWxpc3RcIiApOyAvLyBjb2xsZWN0aW9uLWxpc3QgaXMgaW4gdGhlcmUgZm9yIGxlZ2FjeSBwdXJwb3Nlc1xuXHRcdFx0aWYoIHRoaXMuc2VsZWN0YWJsZSApIHRoaXMuJGVsLmFkZENsYXNzKCBcInNlbGVjdGFibGVcIiApO1xuXG5cdFx0XHRpZiggdGhpcy5zZWxlY3RhYmxlICYmIHRoaXMucHJvY2Vzc0tleUV2ZW50cyApXG5cdFx0XHRcdHRoaXMuJGVsLmF0dHIoIFwidGFiaW5kZXhcIiwgMCApOyAvLyBzbyB3ZSBnZXQga2V5Ym9hcmQgZXZlbnRzXG5cblx0XHRcdHRoaXMuc2VsZWN0ZWRJdGVtcyA9IFtdO1xuXG5cdFx0XHR0aGlzLl91cGRhdGVJdGVtVGVtcGxhdGUoKTtcblxuXHRcdFx0aWYoIHRoaXMuY29sbGVjdGlvbiApXG5cdFx0XHRcdHRoaXMuX3JlZ2lzdGVyQ29sbGVjdGlvbkV2ZW50cygpO1xuXG5cdFx0XHR0aGlzLnZpZXdNYW5hZ2VyID0gbmV3IENoaWxkVmlld0NvbnRhaW5lcigpO1xuXHRcdH0sXG5cblx0XHRfb25PcHRpb25zQ2hhbmdlZCA6IGZ1bmN0aW9uKCBjaGFuZ2VkT3B0aW9ucywgb3JpZ2luYWxPcHRpb25zICkge1xuXHRcdFx0dmFyIF90aGlzID0gdGhpcztcblx0XHRcdHZhciByZXJlbmRlciA9IGZhbHNlO1xuXG5cdFx0XHRfLmVhY2goIF8ua2V5cyggY2hhbmdlZE9wdGlvbnMgKSwgZnVuY3Rpb24oIGNoYW5nZWRPcHRpb25LZXkgKSB7XG5cdFx0XHRcdHZhciBuZXdWYWwgPSBjaGFuZ2VkT3B0aW9uc1sgY2hhbmdlZE9wdGlvbktleSBdO1xuXHRcdFx0XHR2YXIgb2xkVmFsID0gb3JpZ2luYWxPcHRpb25zWyBjaGFuZ2VkT3B0aW9uS2V5IF07XG5cdFx0XHRcdHN3aXRjaCggY2hhbmdlZE9wdGlvbktleSApIHtcblx0XHRcdFx0XHRjYXNlIFwiY29sbGVjdGlvblwiIDpcblx0XHRcdFx0XHRcdGlmICggbmV3VmFsICE9PSBvbGRWYWwgKSB7XG5cdFx0XHRcdFx0XHRcdF90aGlzLnN0b3BMaXN0ZW5pbmcoIG9sZFZhbCApO1xuXHRcdFx0XHRcdFx0XHRfdGhpcy5fcmVnaXN0ZXJDb2xsZWN0aW9uRXZlbnRzKCk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRjYXNlIFwic2VsZWN0TXVsdGlwbGVcIiA6XG5cdFx0XHRcdFx0XHRpZiggISBuZXdWYWwgJiYgX3RoaXMuc2VsZWN0ZWRJdGVtcy5sZW5ndGggPiAxIClcblx0XHRcdFx0XHRcdFx0X3RoaXMuc2V0U2VsZWN0ZWRNb2RlbCggXy5maXJzdCggX3RoaXMuc2VsZWN0ZWRJdGVtcyApLCB7IGJ5IDogXCJjaWRcIiB9ICk7XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRjYXNlIFwic2VsZWN0YWJsZVwiIDpcblx0XHRcdFx0XHRcdGlmKCAhIG5ld1ZhbCAmJiBfdGhpcy5zZWxlY3RlZEl0ZW1zLmxlbmd0aCA+IDAgKVxuXHRcdFx0XHRcdFx0XHRfdGhpcy5zZXRTZWxlY3RlZE1vZGVscyggW10gKTtcblxuXHRcdFx0XHRcdFx0aWYoIG5ld1ZhbCAmJiB0aGlzLnByb2Nlc3NLZXlFdmVudHMgKSBfdGhpcy4kZWwuYXR0ciggXCJ0YWJpbmRleFwiLCAwICk7IC8vIHNvIHdlIGdldCBrZXlib2FyZCBldmVudHNcblx0XHRcdFx0XHRcdGVsc2UgX3RoaXMuJGVsLnJlbW92ZUF0dHIoIFwidGFiaW5kZXhcIiwgMCApO1xuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0Y2FzZSBcInNvcnRhYmxlXCIgOlxuXHRcdFx0XHRcdFx0Y2hhbmdlZE9wdGlvbnMuc29ydGFibGUgPyBfdGhpcy5fc2V0dXBTb3J0YWJsZSgpIDogX3RoaXMuJGVsLnNvcnRhYmxlKCBcImRlc3Ryb3lcIiApO1xuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0Y2FzZSBcInNlbGVjdGFibGVNb2RlbHNGaWx0ZXJcIiA6XG5cdFx0XHRcdFx0XHRfdGhpcy5yZWFwcGx5RmlsdGVyKCAnc2VsZWN0YWJsZU1vZGVscycgKTtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgXCJzb3J0YWJsZU9wdGlvbnNcIiA6XG5cdFx0XHRcdFx0XHRfdGhpcy4kZWwuc29ydGFibGUoIFwiZGVzdHJveVwiICk7XG5cdFx0XHRcdFx0XHRfdGhpcy5fc2V0dXBTb3J0YWJsZSgpO1xuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0Y2FzZSBcInNvcnRhYmxlTW9kZWxzRmlsdGVyXCIgOlxuXHRcdFx0XHRcdFx0X3RoaXMucmVhcHBseUZpbHRlciggJ3NvcnRhYmxlTW9kZWxzJyApO1xuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0Y2FzZSBcInZpc2libGVNb2RlbHNGaWx0ZXJcIiA6XG5cdFx0XHRcdFx0XHRfdGhpcy5yZWFwcGx5RmlsdGVyKCAndmlzaWJsZU1vZGVscycgKTtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgXCJpdGVtVGVtcGxhdGVcIiA6XG5cdFx0XHRcdFx0XHRfdGhpcy5fdXBkYXRlSXRlbVRlbXBsYXRlKCk7XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRjYXNlIFwicHJvY2Vzc0tleUV2ZW50c1wiIDpcblx0XHRcdFx0XHRcdGlmKCBuZXdWYWwgJiYgdGhpcy5zZWxlY3RhYmxlICkgX3RoaXMuJGVsLmF0dHIoIFwidGFiaW5kZXhcIiwgMCApOyAvLyBzbyB3ZSBnZXQga2V5Ym9hcmQgZXZlbnRzXG5cdFx0XHRcdFx0XHRlbHNlIF90aGlzLiRlbC5yZW1vdmVBdHRyKCBcInRhYmluZGV4XCIsIDAgKTtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgXCJtb2RlbFZpZXdcIiA6XG5cdFx0XHRcdFx0XHQvL25lZWQgdG8gcmVtb3ZlIGFsbCBvbGQgdmlldyBpbnN0YW5jZXNcblx0XHRcdFx0XHRcdF90aGlzLnZpZXdNYW5hZ2VyLmVhY2goIGZ1bmN0aW9uKCB2aWV3ICkge1xuXHRcdFx0XHRcdFx0XHRfdGhpcy52aWV3TWFuYWdlci5yZW1vdmUoIHZpZXcgKTtcblx0XHRcdFx0XHRcdFx0Ly8gZGVzdHJveSB0aGUgVmlldyBpdHNlbGZcblx0XHRcdFx0XHRcdFx0dmlldy5yZW1vdmUoKTtcblx0XHRcdFx0XHRcdH0gKTtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGlmKCBfLmNvbnRhaW5zKCBrT3B0aW9uc1JlcXVpcmluZ1JlcmVuZGVyaW5nLCBjaGFuZ2VkT3B0aW9uS2V5ICkgKSByZXJlbmRlciA9IHRydWU7XG5cdFx0XHR9ICk7XG5cblx0XHRcdGlmKCB0aGlzLl9oYXNCZWVuUmVuZGVyZWQgJiYgcmVyZW5kZXIgKSB7XG5cdFx0XHRcdHRoaXMucmVuZGVyKCk7XG5cdFx0XHR9XG5cdFx0fSxcblxuXHRcdHNldE9wdGlvbiA6IGZ1bmN0aW9uKCBvcHRpb25OYW1lLCBvcHRpb25WYWx1ZSApIHsgLy8gbm93IGlzIG1lYXJseSBhIHdyYXBwZXIgYXJvdW5kIGJhY2tib25lLnZpZXdPcHRpb25zJyBzZXRPcHRpb25zKClcblx0XHRcdHZhciBvcHRpb25IYXNoID0ge307XG5cdFx0XHRvcHRpb25IYXNoWyBvcHRpb25OYW1lIF0gPSBvcHRpb25WYWx1ZTtcblx0XHRcdHRoaXMuc2V0T3B0aW9ucyggb3B0aW9uSGFzaCApO1xuXHRcdH0sXG5cblx0XHRnZXRTZWxlY3RlZE1vZGVsIDogZnVuY3Rpb24oIG9wdGlvbnMgKSB7XG5cdFx0XHRyZXR1cm4gdGhpcy5zZWxlY3RlZEl0ZW1zLmxlbmd0aCA/IF8uZmlyc3QoIHRoaXMuZ2V0U2VsZWN0ZWRNb2RlbHMoIG9wdGlvbnMgKSApIDogbnVsbDtcblx0XHR9LFxuXG5cdFx0Z2V0U2VsZWN0ZWRNb2RlbHMgOiBmdW5jdGlvbiAoIG9wdGlvbnMgKSB7XG5cdFx0XHR2YXIgX3RoaXMgPSB0aGlzO1xuXG5cdFx0XHRvcHRpb25zID0gXy5leHRlbmQoIHt9LCB7XG5cdFx0XHRcdGJ5IDoga0RlZmF1bHRSZWZlcmVuY2VCeVxuXHRcdFx0fSwgb3B0aW9ucyApO1xuXG5cdFx0XHR2YXIgcmVmZXJlbmNlQnkgPSBvcHRpb25zLmJ5O1xuXHRcdFx0dmFyIGl0ZW1zID0gW107XG5cblx0XHRcdHN3aXRjaCggcmVmZXJlbmNlQnkgKSB7XG5cdFx0XHRcdGNhc2UgXCJpZFwiIDpcblx0XHRcdFx0XHRfLmVhY2goIHRoaXMuc2VsZWN0ZWRJdGVtcywgZnVuY3Rpb24gKCBpdGVtICkge1xuXHRcdFx0XHRcdFx0aXRlbXMucHVzaCggX3RoaXMuY29sbGVjdGlvbi5nZXQoIGl0ZW0gKS5pZCApO1xuXHRcdFx0XHRcdH0gKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSBcImNpZFwiIDpcblx0XHRcdFx0XHRpdGVtcyA9IGl0ZW1zLmNvbmNhdCggdGhpcy5zZWxlY3RlZEl0ZW1zICk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgXCJvZmZzZXRcIiA6XG5cdFx0XHRcdFx0dmFyIGN1ckxpbmVOdW1iZXIgPSAwO1xuXG5cdFx0XHRcdFx0dmFyIGl0ZW1FbGVtZW50cyA9IHRoaXMuX2dldFZpc2libGVJdGVtRWxzKCk7XG5cblx0XHRcdFx0XHRpdGVtRWxlbWVudHMuZWFjaCggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHR2YXIgdGhpc0l0ZW1FbCA9ICQoIHRoaXMgKTtcblx0XHRcdFx0XHRcdGlmKCB0aGlzSXRlbUVsLmlzKCBcIi5zZWxlY3RlZFwiICkgKVxuXHRcdFx0XHRcdFx0XHRpdGVtcy5wdXNoKCBjdXJMaW5lTnVtYmVyICk7XG5cdFx0XHRcdFx0XHRjdXJMaW5lTnVtYmVyKys7XG5cdFx0XHRcdFx0fSApO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlIFwibW9kZWxcIiA6XG5cdFx0XHRcdFx0Xy5lYWNoKCB0aGlzLnNlbGVjdGVkSXRlbXMsIGZ1bmN0aW9uICggaXRlbSApIHtcblx0XHRcdFx0XHRcdGl0ZW1zLnB1c2goIF90aGlzLmNvbGxlY3Rpb24uZ2V0KCBpdGVtICkgKTtcblx0XHRcdFx0XHR9ICk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgXCJ2aWV3XCIgOlxuXHRcdFx0XHRcdF8uZWFjaCggdGhpcy5zZWxlY3RlZEl0ZW1zLCBmdW5jdGlvbiAoIGl0ZW0gKSB7XG5cdFx0XHRcdFx0XHRpdGVtcy5wdXNoKCBfdGhpcy52aWV3TWFuYWdlci5maW5kQnlNb2RlbCggX3RoaXMuY29sbGVjdGlvbi5nZXQoIGl0ZW0gKSApICk7XG5cdFx0XHRcdFx0fSApO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRkZWZhdWx0IDpcblx0XHRcdFx0XHR0aHJvdyBuZXcgRXJyb3IoIFwiSW52YWxpZCByZWZlcmVuY2VCeSBvcHRpb246IFwiICsgcmVmZXJlbmNlQnkgKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIGl0ZW1zO1xuXG5cdFx0fSxcblxuXHRcdHNldFNlbGVjdGVkTW9kZWxzIDogZnVuY3Rpb24oIG5ld1NlbGVjdGVkSXRlbXMsIG9wdGlvbnMgKSB7XG5cdFx0XHRpZiggISBfLmlzQXJyYXkoIG5ld1NlbGVjdGVkSXRlbXMgKSApIHRocm93IFwiSW52YWxpZCBwYXJhbWV0ZXIgdmFsdWVcIjtcblx0XHRcdGlmKCAhIHRoaXMuc2VsZWN0YWJsZSAmJiBuZXdTZWxlY3RlZEl0ZW1zLmxlbmd0aCA+IDAgKSByZXR1cm47IC8vIHVzZWQgdG8gdGhyb3cgZXJyb3IsIGJ1dCB0aGVyZSBhcmUgc29tZSBjaXJjdW1zdGFuY2VzIGluIHdoaWNoIGEgbGlzdCBjYW4gYmUgc2VsZWN0YWJsZSBhdCB0aW1lcyBhbmQgbm90IGF0IG90aGVycywgZG9uJ3Qgd2FudCB0byBoYXZlIHRvIHdvcnJ5IGFib3V0IGNhdGNoaW5nIGVycm9yc1xuXG5cdFx0XHRvcHRpb25zID0gXy5leHRlbmQoIHt9LCB7XG5cdFx0XHRcdHNpbGVudCA6IGZhbHNlLFxuXHRcdFx0XHRieSA6IGtEZWZhdWx0UmVmZXJlbmNlQnlcblx0XHRcdH0sIG9wdGlvbnMgKTtcblxuXHRcdFx0dmFyIHJlZmVyZW5jZUJ5ID0gb3B0aW9ucy5ieTtcblx0XHRcdHZhciBuZXdTZWxlY3RlZENpZHMgPSBbXTtcblxuXHRcdFx0c3dpdGNoKCByZWZlcmVuY2VCeSApIHtcblx0XHRcdFx0Y2FzZSBcImNpZFwiIDpcblx0XHRcdFx0XHRuZXdTZWxlY3RlZENpZHMgPSBuZXdTZWxlY3RlZEl0ZW1zO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlIFwiaWRcIiA6XG5cdFx0XHRcdFx0dGhpcy5jb2xsZWN0aW9uLmVhY2goIGZ1bmN0aW9uKCB0aGlzTW9kZWwgKSB7XG5cdFx0XHRcdFx0XHRpZiggXy5jb250YWlucyggbmV3U2VsZWN0ZWRJdGVtcywgdGhpc01vZGVsLmlkICkgKSBuZXdTZWxlY3RlZENpZHMucHVzaCggdGhpc01vZGVsLmNpZCApO1xuXHRcdFx0XHRcdH0gKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSBcIm1vZGVsXCIgOlxuXHRcdFx0XHRcdG5ld1NlbGVjdGVkQ2lkcyA9IF8ucGx1Y2soIG5ld1NlbGVjdGVkSXRlbXMsIFwiY2lkXCIgKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSBcInZpZXdcIiA6XG5cdFx0XHRcdFx0Xy5lYWNoKCBuZXdTZWxlY3RlZEl0ZW1zLCBmdW5jdGlvbiggaXRlbSApIHtcblx0XHRcdFx0XHRcdG5ld1NlbGVjdGVkQ2lkcy5wdXNoKCBpdGVtLm1vZGVsLmNpZCApO1xuXHRcdFx0XHRcdH0gKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSBcIm9mZnNldFwiIDpcblx0XHRcdFx0XHR2YXIgY3VyTGluZU51bWJlciA9IDA7XG5cdFx0XHRcdFx0dmFyIHNlbGVjdGVkSXRlbXMgPSBbXTtcblxuXHRcdFx0XHRcdHZhciBpdGVtRWxlbWVudHMgPSB0aGlzLl9nZXRWaXNpYmxlSXRlbUVscygpO1xuXHRcdFx0XHRcdGl0ZW1FbGVtZW50cy5lYWNoKCBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRcdHZhciB0aGlzSXRlbUVsID0gJCggdGhpcyApO1xuXHRcdFx0XHRcdFx0aWYoIF8uY29udGFpbnMoIG5ld1NlbGVjdGVkSXRlbXMsIGN1ckxpbmVOdW1iZXIgKSApXG5cdFx0XHRcdFx0XHRcdG5ld1NlbGVjdGVkQ2lkcy5wdXNoKCB0aGlzSXRlbUVsLmF0dHIoIFwiZGF0YS1tb2RlbC1jaWRcIiApICk7XG5cdFx0XHRcdFx0XHRjdXJMaW5lTnVtYmVyKys7XG5cdFx0XHRcdFx0fSApO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRkZWZhdWx0IDpcblx0XHRcdFx0XHR0aHJvdyBuZXcgRXJyb3IoIFwiSW52YWxpZCByZWZlcmVuY2VCeSBvcHRpb246IFwiICsgcmVmZXJlbmNlQnkgKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdH1cblxuXHRcdFx0dmFyIG9sZFNlbGVjdGVkTW9kZWxzID0gdGhpcy5nZXRTZWxlY3RlZE1vZGVscygpO1xuXHRcdFx0dmFyIG9sZFNlbGVjdGVkQ2lkcyA9IF8uY2xvbmUoIHRoaXMuc2VsZWN0ZWRJdGVtcyApO1xuXG5cdFx0XHR0aGlzLnNlbGVjdGVkSXRlbXMgPSB0aGlzLl9jb252ZXJ0U3RyaW5nc1RvSW50cyggbmV3U2VsZWN0ZWRDaWRzICk7XG5cdFx0XHR0aGlzLl92YWxpZGF0ZVNlbGVjdGlvbigpO1xuXG5cdFx0XHR2YXIgbmV3U2VsZWN0ZWRNb2RlbHMgPSB0aGlzLmdldFNlbGVjdGVkTW9kZWxzKCk7XG5cblx0XHRcdGlmKCAhIHRoaXMuX2NvbnRhaW5TYW1lRWxlbWVudHMoIG9sZFNlbGVjdGVkQ2lkcywgdGhpcy5zZWxlY3RlZEl0ZW1zICkgKVxuXHRcdFx0e1xuXHRcdFx0XHR0aGlzLl9hZGRTZWxlY3RlZENsYXNzVG9TZWxlY3RlZEl0ZW1zKCBvbGRTZWxlY3RlZENpZHMgKTtcblxuXHRcdFx0XHRpZiggISBvcHRpb25zLnNpbGVudCApXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRpZiggdGhpcy5faXNCYWNrYm9uZUNvdXJpZXJBdmFpbGFibGUoKSApIHtcblx0XHRcdFx0XHRcdHRoaXMuc3Bhd24oIFwic2VsZWN0aW9uQ2hhbmdlZFwiLCB7XG5cdFx0XHRcdFx0XHRcdHNlbGVjdGVkTW9kZWxzIDogbmV3U2VsZWN0ZWRNb2RlbHMsXG5cdFx0XHRcdFx0XHRcdG9sZFNlbGVjdGVkTW9kZWxzIDogb2xkU2VsZWN0ZWRNb2RlbHNcblx0XHRcdFx0XHRcdH0gKTtcblx0XHRcdFx0XHR9IGVsc2UgdGhpcy50cmlnZ2VyKCBcInNlbGVjdGlvbkNoYW5nZWRcIiwgbmV3U2VsZWN0ZWRNb2RlbHMsIG9sZFNlbGVjdGVkTW9kZWxzICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHR0aGlzLnVwZGF0ZURlcGVuZGVudENvbnRyb2xzKCk7XG5cdFx0XHR9XG5cdFx0fSxcblxuXHRcdHNldFNlbGVjdGVkTW9kZWwgOiBmdW5jdGlvbiggbmV3U2VsZWN0ZWRJdGVtLCBvcHRpb25zICkge1xuXHRcdFx0aWYoICEgbmV3U2VsZWN0ZWRJdGVtICYmIG5ld1NlbGVjdGVkSXRlbSAhPT0gMCApXG5cdFx0XHRcdHRoaXMuc2V0U2VsZWN0ZWRNb2RlbHMoIFtdLCBvcHRpb25zICk7XG5cdFx0XHRlbHNlXG5cdFx0XHRcdHRoaXMuc2V0U2VsZWN0ZWRNb2RlbHMoIFsgbmV3U2VsZWN0ZWRJdGVtIF0sIG9wdGlvbnMgKTtcblx0XHR9LFxuXG5cdFx0Z2V0VmlldyA6IGZ1bmN0aW9uKCByZWZlcmVuY2UsIG9wdGlvbnMgKSB7XG5cdFx0XHRvcHRpb25zID0gXy5leHRlbmQoIHt9LCB7XG5cdFx0XHRcdGJ5IDoga0RlZmF1bHRSZWZlcmVuY2VCeVxuXHRcdFx0fSwgb3B0aW9ucyApO1xuXG5cdFx0XHRzd2l0Y2goIG9wdGlvbnMuYnkgKSB7XG5cdFx0XHRcdGNhc2UgXCJpZFwiIDpcblx0XHRcdFx0Y2FzZSBcImNpZFwiIDpcblx0XHRcdFx0XHR2YXIgbW9kZWwgPSB0aGlzLmNvbGxlY3Rpb24uZ2V0KCByZWZlcmVuY2UgKSB8fCBudWxsO1xuXHRcdFx0XHRcdHJldHVybiBtb2RlbCAmJiB0aGlzLnZpZXdNYW5hZ2VyLmZpbmRCeU1vZGVsKCBtb2RlbCApO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlIFwib2Zmc2V0XCIgOlxuXHRcdFx0XHRcdHZhciBpdGVtRWxlbWVudHMgPSB0aGlzLl9nZXRWaXNpYmxlSXRlbUVscygpO1xuXHRcdFx0XHRcdHJldHVybiAkKCBpdGVtRWxlbWVudHMuZ2V0KCByZWZlcmVuY2UgKSApO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlIFwibW9kZWxcIiA6XG5cdFx0XHRcdFx0cmV0dXJuIHRoaXMudmlld01hbmFnZXIuZmluZEJ5TW9kZWwoIHJlZmVyZW5jZSApO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRkZWZhdWx0IDpcblx0XHRcdFx0XHR0aHJvdyBuZXcgRXJyb3IoIFwiSW52YWxpZCByZWZlcmVuY2VCeSBvcHRpb246IFwiICsgcmVmZXJlbmNlQnkgKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdH1cblx0XHR9LFxuXG5cdFx0cmVuZGVyIDogZnVuY3Rpb24oKSB7XG5cdFx0XHR2YXIgX3RoaXMgPSB0aGlzO1xuXG5cdFx0XHR0aGlzLl9oYXNCZWVuUmVuZGVyZWQgPSB0cnVlO1xuXG5cdFx0XHRpZiggdGhpcy5zZWxlY3RhYmxlICkgdGhpcy5fc2F2ZVNlbGVjdGlvbigpO1xuXG5cdFx0XHR2YXIgbW9kZWxWaWV3Q29udGFpbmVyRWw7XG5cblx0XHRcdC8vIElmIGNvbGxlY3Rpb24gdmlldyBlbGVtZW50IGlzIGEgdGFibGUgYW5kIGl0IGhhcyBhIHRib2R5XG5cdFx0XHQvLyB3aXRoaW4gaXQsIHJlbmRlciB0aGUgbW9kZWwgdmlld3MgaW5zaWRlIG9mIHRoZSB0Ym9keVxuXHRcdFx0bW9kZWxWaWV3Q29udGFpbmVyRWwgPSB0aGlzLl9nZXRDb250YWluZXJFbCgpO1xuXG5cdFx0XHR2YXIgb2xkVmlld01hbmFnZXIgPSB0aGlzLnZpZXdNYW5hZ2VyO1xuXHRcdFx0dGhpcy52aWV3TWFuYWdlciA9IG5ldyBDaGlsZFZpZXdDb250YWluZXIoKTtcblxuXHRcdFx0Ly8gZGV0YWNoIGVhY2ggb2Ygb3VyIHN1YnZpZXdzIHRoYXQgd2UgaGF2ZSBhbHJlYWR5IGNyZWF0ZWQgdG8gcmVwcmVzZW50IG1vZGVsc1xuXHRcdFx0Ly8gaW4gdGhlIGNvbGxlY3Rpb24uIFdlIGFyZSBnb2luZyB0byByZS11c2UgdGhlIG9uZXMgdGhhdCByZXByZXNlbnQgbW9kZWxzIHRoYXRcblx0XHRcdC8vIGFyZSBzdGlsbCBoZXJlLCBpbnN0ZWFkIG9mIGNyZWF0aW5nIG5ldyBvbmVzLCBzbyB0aGF0IHdlIGRvbid0IGxvb3NlIHN0YXRlXG5cdFx0XHQvLyBpbmZvcm1hdGlvbiBpbiB0aGUgdmlld3MuXG5cdFx0XHRvbGRWaWV3TWFuYWdlci5lYWNoKCBmdW5jdGlvbiggdGhpc01vZGVsVmlldyApIHtcblx0XHRcdFx0Ly8gdG8gYm9vc3QgcGVyZm9ybWFuY2UsIG9ubHkgZGV0YWNoIHRob3NlIHZpZXdzIHRoYXQgd2lsbCBiZSBzdGlja2luZyBhcm91bmQuXG5cdFx0XHRcdC8vIHdlIHdvbid0IG5lZWQgdGhlIG90aGVyIG9uZXMgbGF0ZXIsIHNvIG5vIG5lZWQgdG8gZGV0YWNoIHRoZW0gaW5kaXZpZHVhbGx5LlxuXHRcdFx0XHRpZiggdGhpcy5yZXVzZU1vZGVsVmlld3MgJiYgdGhpcy5jb2xsZWN0aW9uLmdldCggdGhpc01vZGVsVmlldy5tb2RlbC5jaWQgKSApIHtcblx0XHRcdFx0XHR0aGlzTW9kZWxWaWV3LiRlbC5kZXRhY2goKTtcblx0XHRcdFx0fSBlbHNlIHRoaXNNb2RlbFZpZXcucmVtb3ZlKCk7XG5cdFx0XHR9LCB0aGlzICk7XG5cblx0XHRcdG1vZGVsVmlld0NvbnRhaW5lckVsLmVtcHR5KCk7XG5cdFx0XHR2YXIgZnJhZ21lbnRDb250YWluZXI7XG5cblx0XHRcdGlmKCB0aGlzLmRldGFjaGVkUmVuZGVyaW5nIClcblx0XHRcdFx0ZnJhZ21lbnRDb250YWluZXIgPSBkb2N1bWVudC5jcmVhdGVEb2N1bWVudEZyYWdtZW50KCk7XG5cblx0XHRcdHRoaXMuY29sbGVjdGlvbi5lYWNoKCBmdW5jdGlvbiggdGhpc01vZGVsICkge1xuXHRcdFx0XHR2YXIgdGhpc01vZGVsVmlldyA9IG9sZFZpZXdNYW5hZ2VyLmZpbmRCeU1vZGVsQ2lkKCB0aGlzTW9kZWwuY2lkICk7XG5cdFx0XHRcdGlmKCAhIHRoaXMucmV1c2VNb2RlbFZpZXdzIHx8IF8uaXNVbmRlZmluZWQoIHRoaXNNb2RlbFZpZXcgKSApIHtcblx0XHRcdFx0XHQvLyBpZiB0aGUgbW9kZWwgdmlldyBoYXMgbm90IGFscmVhZHkgYmVlbiBjcmVhdGVkIG9uIGFcblx0XHRcdFx0XHQvLyBwcmV2aW91cyByZW5kZXIgdGhlbiBjcmVhdGUgYW5kIGluaXRpYWxpemUgaXQgbm93LlxuXHRcdFx0XHRcdHRoaXNNb2RlbFZpZXcgPSB0aGlzLl9jcmVhdGVOZXdNb2RlbFZpZXcoIHRoaXNNb2RlbCwgdGhpcy5fZ2V0TW9kZWxWaWV3T3B0aW9ucyggdGhpc01vZGVsICkgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHRoaXMuX2luc2VydEFuZFJlbmRlck1vZGVsVmlldyggdGhpc01vZGVsVmlldywgZnJhZ21lbnRDb250YWluZXIgfHwgbW9kZWxWaWV3Q29udGFpbmVyRWwgKTtcblx0XHRcdH0sIHRoaXMgKTtcblxuXHRcdFx0aWYoIHRoaXMuZGV0YWNoZWRSZW5kZXJpbmcgKVxuXHRcdFx0XHRtb2RlbFZpZXdDb250YWluZXJFbC5hcHBlbmQoIGZyYWdtZW50Q29udGFpbmVyICk7XG5cblx0XHRcdGlmKCB0aGlzLnNvcnRhYmxlICkgdGhpcy5fc2V0dXBTb3J0YWJsZSgpO1xuXG5cdFx0XHR0aGlzLl9zaG93RW1wdHlMaXN0Q2FwdGlvbklmQXBwcm9wcmlhdGUoKTtcblxuXHRcdFx0aWYoIHRoaXMuX2lzQmFja2JvbmVDb3VyaWVyQXZhaWxhYmxlKCkgKVxuXHRcdFx0XHR0aGlzLnNwYXduKCBcInJlbmRlclwiICk7XG5cdFx0XHRlbHNlIHRoaXMudHJpZ2dlciggXCJyZW5kZXJcIiApO1xuXG5cdFx0XHRpZiggdGhpcy5zZWxlY3RhYmxlICkge1xuXHRcdFx0XHR0aGlzLl9yZXN0b3JlU2VsZWN0aW9uKCk7XG5cdFx0XHRcdHRoaXMudXBkYXRlRGVwZW5kZW50Q29udHJvbHMoKTtcblx0XHRcdH1cblxuXHRcdFx0dGhpcy5mb3JjZVJlcmVuZGVyT25OZXh0U29ydEV2ZW50ID0gZmFsc2U7XG5cdFx0fSxcblxuXHRcdF9zaG93RW1wdHlMaXN0Q2FwdGlvbklmQXBwcm9wcmlhdGUgOiBmdW5jdGlvbiAoICkge1xuXHRcdFx0dGhpcy5fcmVtb3ZlRW1wdHlMaXN0Q2FwdGlvbigpO1xuXG5cdFx0XHRpZiggdGhpcy5lbXB0eUxpc3RDYXB0aW9uICkge1xuXHRcdFx0XHR2YXIgdmlzaWJsZUVscyA9IHRoaXMuX2dldFZpc2libGVJdGVtRWxzKCk7XG5cblx0XHRcdFx0aWYoIHZpc2libGVFbHMubGVuZ3RoID09PSAwICkge1xuXHRcdFx0XHRcdHZhciBlbXB0eUxpc3RTdHJpbmc7XG5cblx0XHRcdFx0XHRpZiggXy5pc0Z1bmN0aW9uKCB0aGlzLmVtcHR5TGlzdENhcHRpb24gKSApXG5cdFx0XHRcdFx0XHRlbXB0eUxpc3RTdHJpbmcgPSB0aGlzLmVtcHR5TGlzdENhcHRpb24oKTtcblx0XHRcdFx0XHRlbHNlXG5cdFx0XHRcdFx0XHRlbXB0eUxpc3RTdHJpbmcgPSB0aGlzLmVtcHR5TGlzdENhcHRpb247XG5cblx0XHRcdFx0XHR2YXIgJGVtcHR5TGlzdENhcHRpb25FbDtcblx0XHRcdFx0XHR2YXIgJHZhckVsID0gJCggXCI8dmFyIGNsYXNzPSdlbXB0eS1saXN0LWNhcHRpb24nPlwiICsgZW1wdHlMaXN0U3RyaW5nICsgXCI8L3Zhcj5cIiApO1xuXG5cdFx0XHRcdFx0Ly8gbmVlZCB0byB3cmFwIHRoZSBlbXB0eSBjYXB0aW9uIHRvIG1ha2UgaXQgZml0IHRoZSByZW5kZXJlZCBsaXN0IHN0cnVjdHVyZSAoZWl0aGVyIHdpdGggYW4gbGkgb3IgYSB0ciB0ZClcblx0XHRcdFx0XHRpZiggdGhpcy5faXNSZW5kZXJlZEFzTGlzdCgpIClcblx0XHRcdFx0XHRcdCRlbXB0eUxpc3RDYXB0aW9uRWwgPSAkdmFyRWwud3JhcEFsbCggXCI8bGkgY2xhc3M9J25vdC1zb3J0YWJsZSc+PC9saT5cIiApLnBhcmVudCgpLmNzcygga1N0eWxlc0ZvckVtcHR5TGlzdENhcHRpb24gKTtcblx0XHRcdFx0XHRlbHNlXG5cdFx0XHRcdFx0XHQkZW1wdHlMaXN0Q2FwdGlvbkVsID0gJHZhckVsLndyYXBBbGwoIFwiPHRyIGNsYXNzPSdub3Qtc29ydGFibGUnPjx0ZCBjb2xzcGFuPScxMDAwJz48L3RkPjwvdHI+XCIgKS5wYXJlbnQoKS5wYXJlbnQoKS5jc3MoIGtTdHlsZXNGb3JFbXB0eUxpc3RDYXB0aW9uICk7XG5cblx0XHRcdFx0XHR0aGlzLl9nZXRDb250YWluZXJFbCgpLmFwcGVuZCggJGVtcHR5TGlzdENhcHRpb25FbCApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fSxcblxuXHRcdF9yZW1vdmVFbXB0eUxpc3RDYXB0aW9uIDogZnVuY3Rpb24oICkge1xuXHRcdFx0aWYoIHRoaXMuX2lzUmVuZGVyZWRBc0xpc3QoKSApXG5cdFx0XHRcdHRoaXMuX2dldENvbnRhaW5lckVsKCkuZmluZCggXCI+IGxpID4gdmFyLmVtcHR5LWxpc3QtY2FwdGlvblwiICkucGFyZW50KCkucmVtb3ZlKCk7XG5cdFx0XHRlbHNlXG5cdFx0XHRcdHRoaXMuX2dldENvbnRhaW5lckVsKCkuZmluZCggXCI+IHRyID4gdGQgPiB2YXIuZW1wdHktbGlzdC1jYXB0aW9uXCIgKS5wYXJlbnQoKS5wYXJlbnQoKS5yZW1vdmUoKTtcblx0XHR9LFxuXG5cdFx0Ly8gUmVuZGVyIGEgc2luZ2xlIG1vZGVsIHZpZXcgaW4gY29udGFpbmVyIG9iamVjdCBcInBhcmVudEVsT3JEb2N1bWVudEZyYWdtZW50XCIsIHdoaWNoIGlzIGVpdGhlclxuXHRcdC8vIGEgZG9jdW1lbnRGcmFnbWVudCBvciBhIGpxdWVyeSBvYmplY3QuIG9wdGlvbmFsIGFyZyBhdEluZGV4IGlzIG5vdCBzdXBwb3J0IGZvciBkb2N1bWVudCBmcmFnbWVudHMuXG5cdFx0X2luc2VydEFuZFJlbmRlck1vZGVsVmlldyA6IGZ1bmN0aW9uKCBtb2RlbFZpZXcsIHBhcmVudEVsT3JEb2N1bWVudEZyYWdtZW50LCBhdEluZGV4ICkge1xuXHRcdFx0dmFyIHRoaXNNb2RlbFZpZXdXcmFwcGVkID0gdGhpcy5fd3JhcE1vZGVsVmlldyggbW9kZWxWaWV3ICk7XG5cblx0XHRcdGlmKCBwYXJlbnRFbE9yRG9jdW1lbnRGcmFnbWVudC5ub2RlVHlwZSA9PT0gMTEgKSAvLyBpZiB3ZSBhcmUgaW5zZXJ0aW5nIGludG8gYSBkb2N1bWVudCBmcmFnbWVudCwgd2UgbmVlZCB0byB1c2UgdGhlIERPTSBhcHBlbmRDaGlsZCBtZXRob2Rcblx0XHRcdFx0cGFyZW50RWxPckRvY3VtZW50RnJhZ21lbnQuYXBwZW5kQ2hpbGQoIHRoaXNNb2RlbFZpZXdXcmFwcGVkLmdldCggMCApICk7XG5cdFx0XHRlbHNlIHtcblx0XHRcdFx0dmFyIG51bWJlck9mTW9kZWxWaWV3c0N1cnJlbnRseUluRE9NID0gcGFyZW50RWxPckRvY3VtZW50RnJhZ21lbnQuY2hpbGRyZW4oKS5sZW5ndGg7XG5cdFx0XHRcdGlmKCAhIF8uaXNVbmRlZmluZWQoIGF0SW5kZXggKSAmJiBhdEluZGV4ID49IDAgJiYgYXRJbmRleCA8IG51bWJlck9mTW9kZWxWaWV3c0N1cnJlbnRseUluRE9NIClcblx0XHRcdFx0XHQvLyBub3RlIHRoaXMuY29sbGVjdGlvbi5sZW5ndGggbWlnaHQgYmUgZ3JlYXRlciB0aGFuIHBhcmVudEVsT3JEb2N1bWVudEZyYWdtZW50LmNoaWxkcmVuKCkubGVuZ3RoIGhlcmVcblx0XHRcdFx0XHRwYXJlbnRFbE9yRG9jdW1lbnRGcmFnbWVudC5jaGlsZHJlbigpLmVxKCBhdEluZGV4ICkuYmVmb3JlKCB0aGlzTW9kZWxWaWV3V3JhcHBlZCApO1xuXHRcdFx0XHRlbHNlIHtcblx0XHRcdFx0XHQvLyBpZiB3ZSBhcmUgYXR0ZW1wdGluZyB0byBpbnNlcnQgYSBtb2RlbFZpZXcgaW4gYW4gcG9zaXRpb24gdGhhdCBpcyBiZXlvbmQgd2hhdCBpcyBjdXJyZW50bHkgaW4gdGhlXG5cdFx0XHRcdFx0Ly8gRE9NLCB0aGVuIG1ha2UgYSBub3RlIHRoYXQgd2UgbmVlZCB0byByZS1yZW5kZXIgdGhlIGNvbGxlY3Rpb24gdmlldyBvbiB0aGUgbmV4dCBzb3J0IGV2ZW50LiBJZiB3ZSBkb250XG5cdFx0XHRcdFx0Ly8gZm9yY2UgdGhpcyByZS1yZW5kZXIsIHdlIGNhbiBlbmQgdXAgd2l0aCBtb2RlbFZpZXdzIGluIHRoZSB3cm9uZyBvcmRlciB3aGVuIHRoZSBjb2xsZWN0aW9uIGRlZmluZXNcblx0XHRcdFx0XHQvLyBhIGNvbXBhcmF0b3IgYW5kIG11bHRpcGxlIG1vZGVscyBhcmUgYWRkZWQgYXQgb25jZS4gU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9yb3R1bmRhc29mdHdhcmUvYmFja2JvbmUuY29sbGVjdGlvblZpZXcvaXNzdWVzLzY5XG5cdFx0XHRcdFx0aWYoICEgXy5pc1VuZGVmaW5lZCggYXRJbmRleCApICYmIGF0SW5kZXggPiBudW1iZXJPZk1vZGVsVmlld3NDdXJyZW50bHlJbkRPTSApIHRoaXMuZm9yY2VSZXJlbmRlck9uTmV4dFNvcnRFdmVudCA9IHRydWU7XG5cblx0XHRcdFx0XHRwYXJlbnRFbE9yRG9jdW1lbnRGcmFnbWVudC5hcHBlbmQoIHRoaXNNb2RlbFZpZXdXcmFwcGVkICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0dGhpcy52aWV3TWFuYWdlci5hZGQoIG1vZGVsVmlldyApO1xuXG5cdFx0XHQvLyB3ZSBoYXZlIHRvIHJlbmRlciB0aGUgbW9kZWxWaWV3IGFmdGVyIGl0IGhhcyBiZWVuIHB1dCBpbiBjb250ZXh0LCBhcyBvcHBvc2VkIHRvIGluIHRoZVxuXHRcdFx0Ly8gaW5pdGlhbGl6ZSBmdW5jdGlvbiBvZiB0aGUgbW9kZWxWaWV3LCBiZWNhdXNlIHNvbWUgcmVuZGVyaW5nIG1pZ2h0IGJlIGRlcGVuZGVudCBvblxuXHRcdFx0Ly8gdGhlIG1vZGVsVmlldydzIGNvbnRleHQgaW4gdGhlIERPTSB0cmVlLiBGb3IgZXhhbXBsZSwgaWYgdGhlIG1vZGVsVmlldyBzdHJldGNoKCkncyBpdHNlbGYsXG5cdFx0XHQvLyBpdCBtdXN0IGJlIGluIGZ1bGwgY29udGV4dCBpbiB0aGUgRE9NIHRyZWUgb3IgZWxzZSB0aGUgc3RyZXRjaCB3aWxsIG5vdCBiZWhhdmUgYXMgaW50ZW5kZWQuXG5cdFx0XHR2YXIgcmVuZGVyUmVzdWx0ID0gbW9kZWxWaWV3LnJlbmRlcigpO1xuXG5cdFx0XHQvLyByZXR1cm4gZmFsc2UgZnJvbSB0aGUgdmlldydzIHJlbmRlciBmdW5jdGlvbiB0byBoaWRlIHRoaXMgaXRlbVxuXHRcdFx0aWYoIHJlbmRlclJlc3VsdCA9PT0gZmFsc2UgKSB7XG5cdFx0XHRcdHRoaXNNb2RlbFZpZXdXcmFwcGVkLmhpZGUoKTtcblx0XHRcdFx0dGhpc01vZGVsVmlld1dyYXBwZWQuYWRkQ2xhc3MoIFwibm90LXZpc2libGVcIiApO1xuXHRcdFx0fVxuXG5cdFx0XHR2YXIgaGlkZVRoaXNNb2RlbFZpZXcgPSBmYWxzZTtcblx0XHRcdGlmKCBfLmlzRnVuY3Rpb24oIHRoaXMudmlzaWJsZU1vZGVsc0ZpbHRlciApIClcblx0XHRcdFx0aGlkZVRoaXNNb2RlbFZpZXcgPSAhIHRoaXMudmlzaWJsZU1vZGVsc0ZpbHRlciggbW9kZWxWaWV3Lm1vZGVsICk7XG5cblx0XHRcdGlmKCB0aGlzTW9kZWxWaWV3V3JhcHBlZC5jaGlsZHJlbigpLmxlbmd0aCA9PT0gMSApXG5cdFx0XHRcdHRoaXNNb2RlbFZpZXdXcmFwcGVkLnRvZ2dsZSggISBoaWRlVGhpc01vZGVsVmlldyApO1xuXHRcdFx0ZWxzZSBtb2RlbFZpZXcuJGVsLnRvZ2dsZSggISBoaWRlVGhpc01vZGVsVmlldyApO1xuXG5cdFx0XHR0aGlzTW9kZWxWaWV3V3JhcHBlZC50b2dnbGVDbGFzcyggXCJub3QtdmlzaWJsZVwiLCBoaWRlVGhpc01vZGVsVmlldyApO1xuXG5cdFx0XHRpZiggISBoaWRlVGhpc01vZGVsVmlldyAmJiB0aGlzLmVtcHR5TGlzdENhcHRpb24gKSB0aGlzLl9yZW1vdmVFbXB0eUxpc3RDYXB0aW9uKCk7XG5cdFx0fSxcblxuXHRcdHVwZGF0ZURlcGVuZGVudENvbnRyb2xzIDogZnVuY3Rpb24oKSB7XG5cdFx0XHRpZiggdGhpcy5faXNCYWNrYm9uZUNvdXJpZXJBdmFpbGFibGUoKSApIHtcblx0XHRcdFx0dGhpcy5zcGF3biggXCJ1cGRhdGVEZXBlbmRlbnRDb250cm9sc1wiLCB7XG5cdFx0XHRcdFx0c2VsZWN0ZWRNb2RlbHMgOiB0aGlzLmdldFNlbGVjdGVkTW9kZWxzKClcblx0XHRcdFx0fSApO1xuXHRcdFx0fSBlbHNlIHRoaXMudHJpZ2dlciggXCJ1cGRhdGVEZXBlbmRlbnRDb250cm9sc1wiLCB0aGlzLmdldFNlbGVjdGVkTW9kZWxzKCkgKTtcblx0XHR9LFxuXG5cdFx0Ly8gT3ZlcnJpZGUgYEJhY2tib25lLlZpZXcucmVtb3ZlYCB0byBhbHNvIGRlc3Ryb3kgYWxsIFZpZXdzIGluIGB2aWV3TWFuYWdlcmBcblx0XHRyZW1vdmUgOiBmdW5jdGlvbigpIHtcblx0XHRcdHRoaXMudmlld01hbmFnZXIuZWFjaCggZnVuY3Rpb24oIHZpZXcgKSB7XG5cdFx0XHRcdHZpZXcucmVtb3ZlKCk7XG5cdFx0XHR9ICk7XG5cblx0XHRcdEJhY2tib25lLlZpZXcucHJvdG90eXBlLnJlbW92ZS5hcHBseSggdGhpcywgYXJndW1lbnRzICk7XG5cdFx0fSxcblxuXHRcdHJlYXBwbHlGaWx0ZXIgOiBmdW5jdGlvbiggd2hpY2hGaWx0ZXIgKSB7XG5cdFx0XHR2YXIgX3RoaXMgPSB0aGlzO1xuXG5cdFx0XHRpZiggISBfLmNvbnRhaW5zKCBbIFwic2VsZWN0YWJsZU1vZGVsc1wiLCBcInNvcnRhYmxlTW9kZWxzXCIsIFwidmlzaWJsZU1vZGVsc1wiIF0sIHdoaWNoRmlsdGVyICkgKSB7XG5cdFx0XHRcdHRocm93IG5ldyBFcnJvciggXCJJbnZhbGlkIGZpbHRlciBpZGVudGlmaWVyIHN1cHBsaWVkIHRvIHJlYXBwbHlGaWx0ZXI6IFwiICsgd2hpY2hGaWx0ZXIgKTtcblx0XHRcdH1cblxuXHRcdFx0c3dpdGNoKCB3aGljaEZpbHRlciApIHtcblx0XHRcdFx0Y2FzZSBcInZpc2libGVNb2RlbHNcIjpcblx0XHRcdFx0XHRfdGhpcy52aWV3TWFuYWdlci5lYWNoKCBmdW5jdGlvbiggdGhpc01vZGVsVmlldyApIHtcblx0XHRcdFx0XHRcdHZhciBub3RWaXNpYmxlID0gX3RoaXMudmlzaWJsZU1vZGVsc0ZpbHRlciAmJiAhIF90aGlzLnZpc2libGVNb2RlbHNGaWx0ZXIuY2FsbCggX3RoaXMsIHRoaXNNb2RlbFZpZXcubW9kZWwgKTtcblxuXHRcdFx0XHRcdFx0dGhpc01vZGVsVmlldy4kZWwudG9nZ2xlQ2xhc3MoIFwibm90LXZpc2libGVcIiwgbm90VmlzaWJsZSApO1xuXHRcdFx0XHRcdFx0aWYoIF90aGlzLl9tb2RlbFZpZXdIYXNXcmFwcGVyTEkoIHRoaXNNb2RlbFZpZXcgKSApIHtcblx0XHRcdFx0XHRcdFx0dGhpc01vZGVsVmlldy4kZWwuY2xvc2VzdCggXCJsaVwiICkudG9nZ2xlQ2xhc3MoIFwibm90LXZpc2libGVcIiwgbm90VmlzaWJsZSApLnRvZ2dsZSggISBub3RWaXNpYmxlICk7XG5cdFx0XHRcdFx0XHR9IGVsc2UgdGhpc01vZGVsVmlldy4kZWwudG9nZ2xlKCAhIG5vdFZpc2libGUgKTtcblx0XHRcdFx0XHR9ICk7XG5cblx0XHRcdFx0XHR0aGlzLl9zaG93RW1wdHlMaXN0Q2FwdGlvbklmQXBwcm9wcmlhdGUoKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSBcInNvcnRhYmxlTW9kZWxzXCI6XG5cdFx0XHRcdFx0X3RoaXMuJGVsLnNvcnRhYmxlKCBcImRlc3Ryb3lcIiApO1xuXG5cdFx0XHRcdFx0X3RoaXMudmlld01hbmFnZXIuZWFjaCggZnVuY3Rpb24oIHRoaXNNb2RlbFZpZXcgKSB7XG5cdFx0XHRcdFx0XHR2YXIgbm90U29ydGFibGUgPSBfdGhpcy5zb3J0YWJsZU1vZGVsc0ZpbHRlciAmJiAhIF90aGlzLnNvcnRhYmxlTW9kZWxzRmlsdGVyLmNhbGwoIF90aGlzLCB0aGlzTW9kZWxWaWV3Lm1vZGVsICk7XG5cblx0XHRcdFx0XHRcdHRoaXNNb2RlbFZpZXcuJGVsLnRvZ2dsZUNsYXNzKCBcIm5vdC1zb3J0YWJsZVwiLCBub3RTb3J0YWJsZSApO1xuXHRcdFx0XHRcdFx0aWYoIF90aGlzLl9tb2RlbFZpZXdIYXNXcmFwcGVyTEkoIHRoaXNNb2RlbFZpZXcgKSApIHtcblx0XHRcdFx0XHRcdFx0dGhpc01vZGVsVmlldy4kZWwuY2xvc2VzdCggXCJsaVwiICkudG9nZ2xlQ2xhc3MoIFwibm90LXNvcnRhYmxlXCIsIG5vdFNvcnRhYmxlICk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fSApO1xuXG5cdFx0XHRcdFx0X3RoaXMuX3NldHVwU29ydGFibGUoKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSBcInNlbGVjdGFibGVNb2RlbHNcIjpcblx0XHRcdFx0XHRfdGhpcy52aWV3TWFuYWdlci5lYWNoKCBmdW5jdGlvbiggdGhpc01vZGVsVmlldyApIHtcblx0XHRcdFx0XHRcdHZhciBub3RTZWxlY3RhYmxlID0gX3RoaXMuc2VsZWN0YWJsZU1vZGVsc0ZpbHRlciAmJiAhIF90aGlzLnNlbGVjdGFibGVNb2RlbHNGaWx0ZXIuY2FsbCggX3RoaXMsIHRoaXNNb2RlbFZpZXcubW9kZWwgKTtcblxuXHRcdFx0XHRcdFx0dGhpc01vZGVsVmlldy4kZWwudG9nZ2xlQ2xhc3MoIFwibm90LXNlbGVjdGFibGVcIiwgbm90U2VsZWN0YWJsZSApO1xuXHRcdFx0XHRcdFx0aWYoIF90aGlzLl9tb2RlbFZpZXdIYXNXcmFwcGVyTEkoIHRoaXNNb2RlbFZpZXcgKSApIHtcblx0XHRcdFx0XHRcdFx0dGhpc01vZGVsVmlldy4kZWwuY2xvc2VzdCggXCJsaVwiICkudG9nZ2xlQ2xhc3MoIFwibm90LXNlbGVjdGFibGVcIiwgbm90U2VsZWN0YWJsZSApO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH0gKTtcblxuXHRcdFx0XHRcdF90aGlzLl92YWxpZGF0ZVNlbGVjdGlvbigpO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXHRcdH0sXG5cblx0XHQvLyBBIG1ldGhvZCB0byByZW1vdmUgdGhlIHZpZXcgcmVsYXRpbmcgdG8gbW9kZWwuXG5cdFx0X3JlbW92ZU1vZGVsVmlldyA6IGZ1bmN0aW9uKCBtb2RlbFZpZXcgKSB7XG5cdFx0XHRpZiggdGhpcy5zZWxlY3RhYmxlICkgdGhpcy5fc2F2ZVNlbGVjdGlvbigpO1xuXG5cdFx0XHR0aGlzLnZpZXdNYW5hZ2VyLnJlbW92ZSggbW9kZWxWaWV3ICk7IC8vIFJlbW92ZSB0aGUgdmlldyBmcm9tIHRoZSB2aWV3TWFuYWdlclxuXHRcdFx0aWYoIHRoaXMuX21vZGVsVmlld0hhc1dyYXBwZXJMSSggbW9kZWxWaWV3ICkgKSBtb2RlbFZpZXcuJGVsLnBhcmVudCgpLnJlbW92ZSgpOyAvLyBSZW1vdmUgdGhlIGxpIHdyYXBwZXIgZnJvbSB0aGUgRE9NXG5cdFx0XHRtb2RlbFZpZXcucmVtb3ZlKCk7IC8vIFJlbW92ZSB0aGUgdmlldyBmcm9tIHRoZSBET00gYW5kIHN0b3AgbGlzdGVuaW5nIHRvIGV2ZW50c1xuXG5cdFx0XHRpZiggdGhpcy5zZWxlY3RhYmxlICkgdGhpcy5fcmVzdG9yZVNlbGVjdGlvbigpO1xuXG5cdFx0XHR0aGlzLl9zaG93RW1wdHlMaXN0Q2FwdGlvbklmQXBwcm9wcmlhdGUoKTtcblx0XHR9LFxuXG5cdFx0X3ZhbGlkYXRlU2VsZWN0aW9uQW5kUmVuZGVyIDogZnVuY3Rpb24oKSB7XG5cdFx0XHR0aGlzLl92YWxpZGF0ZVNlbGVjdGlvbigpO1xuXHRcdFx0dGhpcy5yZW5kZXIoKTtcblx0XHR9LFxuXG5cdFx0X3JlZ2lzdGVyQ29sbGVjdGlvbkV2ZW50cyA6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHR0aGlzLmxpc3RlblRvKCB0aGlzLmNvbGxlY3Rpb24sIFwiYWRkXCIsIGZ1bmN0aW9uKCBtb2RlbCApIHtcblx0XHRcdFx0dmFyIG1vZGVsVmlldztcblx0XHRcdFx0aWYoIHRoaXMuX2hhc0JlZW5SZW5kZXJlZCApIHtcblx0XHRcdFx0XHRtb2RlbFZpZXcgPSB0aGlzLl9jcmVhdGVOZXdNb2RlbFZpZXcoIG1vZGVsLCB0aGlzLl9nZXRNb2RlbFZpZXdPcHRpb25zKCBtb2RlbCApICk7XG5cdFx0XHRcdFx0dGhpcy5faW5zZXJ0QW5kUmVuZGVyTW9kZWxWaWV3KCBtb2RlbFZpZXcsIHRoaXMuX2dldENvbnRhaW5lckVsKCksIHRoaXMuY29sbGVjdGlvbi5pbmRleE9mKCBtb2RlbCApICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiggdGhpcy5faXNCYWNrYm9uZUNvdXJpZXJBdmFpbGFibGUoKSApXG5cdFx0XHRcdFx0dGhpcy5zcGF3biggXCJhZGRcIiwgbW9kZWxWaWV3ICk7XG5cdFx0XHRcdGVsc2UgdGhpcy50cmlnZ2VyKCBcImFkZFwiLCBtb2RlbFZpZXcgKTtcblx0XHRcdH0gKTtcblxuXHRcdFx0dGhpcy5saXN0ZW5UbyggdGhpcy5jb2xsZWN0aW9uLCBcInJlbW92ZVwiLCBmdW5jdGlvbiggbW9kZWwgKSB7XG5cdFx0XHRcdHZhciBtb2RlbFZpZXc7XG5cblx0XHRcdFx0aWYoIHRoaXMuX2hhc0JlZW5SZW5kZXJlZCApIHtcblx0XHRcdFx0XHRtb2RlbFZpZXcgPSB0aGlzLnZpZXdNYW5hZ2VyLmZpbmRCeU1vZGVsQ2lkKCBtb2RlbC5jaWQgKTtcblx0XHRcdFx0XHR0aGlzLl9yZW1vdmVNb2RlbFZpZXcoIG1vZGVsVmlldyApO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYoIHRoaXMuX2lzQmFja2JvbmVDb3VyaWVyQXZhaWxhYmxlKCkgKVxuXHRcdFx0XHRcdHRoaXMuc3Bhd24oIFwicmVtb3ZlXCIgKTtcblx0XHRcdFx0ZWxzZSB0aGlzLnRyaWdnZXIoIFwicmVtb3ZlXCIgKTtcblx0XHRcdH0gKTtcblxuXHRcdFx0dGhpcy5saXN0ZW5UbyggdGhpcy5jb2xsZWN0aW9uLCBcInJlc2V0XCIsIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRpZiggdGhpcy5faGFzQmVlblJlbmRlcmVkICkgdGhpcy5yZW5kZXIoKTtcblx0XHRcdFx0aWYoIHRoaXMuX2lzQmFja2JvbmVDb3VyaWVyQXZhaWxhYmxlKCkgKVxuXHRcdFx0XHRcdHRoaXMuc3Bhd24oIFwicmVzZXRcIiApO1xuXHRcdFx0XHRlbHNlIHRoaXMudHJpZ2dlciggXCJyZXNldFwiICk7XG5cdFx0XHR9ICk7XG5cblx0XHRcdC8vIHdlIHNob3VsZCBub3QgYmUgbGlzdGVuaW5nIHRvIGNoYW5nZSBldmVudHMgb24gdGhlIG1vZGVsIGFzIGEgZGVmYXVsdCBiZWhhdmlvci4gdGhlIG1vZGVsc1xuXHRcdFx0Ly8gc2hvdWxkIGJlIHJlc3BvbnNpYmxlIGZvciByZS1yZW5kZXJpbmcgdGhlbXNlbHZlcyBpZiBuZWNlc3NhcnksIGFuZCBpZiB0aGUgY29sbGVjdGlvbiBkb2VzXG5cdFx0XHQvLyBhbHNvIG5lZWQgdG8gcmUtcmVuZGVyIGFzIGEgcmVzdWx0IG9mIGEgbW9kZWwgY2hhbmdlLCB0aGlzIHNob3VsZCBiZSBoYW5kbGVkIGJ5IG92ZXJyaWRpbmdcblx0XHRcdC8vIHRoaXMgbWV0aG9kLiBieSBkZWZhdWx0IHRoZSBjb2xsZWN0aW9uIHZpZXcgc2hvdWxkIG5vdCByZS1yZW5kZXIgaW4gcmVzcG9uc2UgdG8gbW9kZWwgY2hhbmdlc1xuXHRcdFx0Ly8gdGhpcy5saXN0ZW5UbyggdGhpcy5jb2xsZWN0aW9uLCBcImNoYW5nZVwiLCBmdW5jdGlvbiggbW9kZWwgKSB7XG5cdFx0XHQvLyBcdGlmKCB0aGlzLl9oYXNCZWVuUmVuZGVyZWQgKSB0aGlzLnZpZXdNYW5hZ2VyLmZpbmRCeU1vZGVsKCBtb2RlbCApLnJlbmRlcigpO1xuXHRcdFx0Ly8gXHRpZiggdGhpcy5faXNCYWNrYm9uZUNvdXJpZXJBdmFpbGFibGUoKSApXG5cdFx0XHQvLyBcdFx0dGhpcy5zcGF3biggXCJjaGFuZ2VcIiwgeyBtb2RlbCA6IG1vZGVsIH0gKTtcblx0XHRcdC8vIH0gKTtcblxuXHRcdFx0dGhpcy5saXN0ZW5UbyggdGhpcy5jb2xsZWN0aW9uLCBcInNvcnRcIiwgZnVuY3Rpb24oIGNvbGxlY3Rpb24sIG9wdGlvbnMgKSB7XG5cdFx0XHRcdGlmKCB0aGlzLl9oYXNCZWVuUmVuZGVyZWQgJiYgKCBvcHRpb25zLmFkZCAhPT0gdHJ1ZSB8fCB0aGlzLmZvcmNlUmVyZW5kZXJPbk5leHRTb3J0RXZlbnQgKSApIHRoaXMucmVuZGVyKCk7XG5cdFx0XHRcdGlmKCB0aGlzLl9pc0JhY2tib25lQ291cmllckF2YWlsYWJsZSgpIClcblx0XHRcdFx0XHR0aGlzLnNwYXduKCBcInNvcnRcIiApO1xuXHRcdFx0XHRlbHNlIHRoaXMudHJpZ2dlciggXCJzb3J0XCIgKTtcblx0XHRcdH0gKTtcblx0XHR9LFxuXG5cdFx0X2dldENvbnRhaW5lckVsIDogZnVuY3Rpb24oKSB7XG5cdFx0XHRpZiAoIHRoaXMuX2lzUmVuZGVyZWRBc1RhYmxlKCkgKSB7XG5cdFx0XHRcdC8vIG5vdCBhbGwgdGFibGVzIGhhdmUgYSB0Ym9keSwgc28gd2UgdGVzdFxuXHRcdFx0XHR2YXIgdGJvZHkgPSB0aGlzLiRlbC5maW5kKCBcIj4gdGJvZHlcIiApO1xuXHRcdFx0XHRpZiAoIHRib2R5Lmxlbmd0aCA+IDAgKVxuXHRcdFx0XHRcdHJldHVybiB0Ym9keTtcblx0XHRcdH1cblx0XHRcdHJldHVybiB0aGlzLiRlbDtcblx0XHR9LFxuXG5cdFx0X2dldENsaWNrZWRJdGVtSWQgOiBmdW5jdGlvbiggdGhlRXZlbnQgKSB7XG5cdFx0XHR2YXIgY2xpY2tlZEl0ZW1JZCA9IG51bGw7XG5cblx0XHRcdC8vIGltcG9ydGFudCB0byB1c2UgY3VycmVudFRhcmdldCBhcyBvcHBvc2VkIHRvIHRhcmdldCwgc2luY2Ugd2UgY291bGQgYmUgYnViYmxpbmdcblx0XHRcdC8vIGFuIGV2ZW50IHRoYXQgdG9vayBwbGFjZSB3aXRoaW4gYW5vdGhlciBjb2xsZWN0aW9uTGlzdFxuXHRcdFx0dmFyIGNsaWNrZWRJdGVtRWwgPSAkKCB0aGVFdmVudC5jdXJyZW50VGFyZ2V0ICk7XG5cdFx0XHRpZiggY2xpY2tlZEl0ZW1FbC5jbG9zZXN0KCBcIi5jb2xsZWN0aW9uLXZpZXdcIiApLmdldCgwKSAhPT0gdGhpcy4kZWwuZ2V0KDApICkgcmV0dXJuO1xuXG5cdFx0XHQvLyBkZXRlcm1pbmUgd2hpY2ggbGlzdCBpdGVtIHdhcyBjbGlja2VkLiBJZiB3ZSBjbGlja2VkIGluIHRoZSBibGFuayBhcmVhXG5cdFx0XHQvLyB1bmRlcm5lYXRoIGFsbCB0aGUgZWxlbWVudHMsIHdlIHdhbnQgdG8ga25vdyB0aGF0IHRvbywgc2luY2UgaW4gdGhpc1xuXHRcdFx0Ly8gY2FzZSB3ZSB3aWxsIHdhbnQgdG8gZGVzZWxlY3QgYWxsIGVsZW1lbnRzLiBzbyBjaGVjayB0byBzZWUgaWYgdGhlIGNsaWNrZWRcblx0XHRcdC8vIERPTSBlbGVtZW50IGlzIHRoZSBsaXN0IGl0c2VsZiB0byBmaW5kIHRoYXQgb3V0LlxuXHRcdFx0dmFyIGNsaWNrZWRJdGVtID0gY2xpY2tlZEl0ZW1FbC5jbG9zZXN0KCBcIltkYXRhLW1vZGVsLWNpZF1cIiApO1xuXHRcdFx0aWYoIGNsaWNrZWRJdGVtLmxlbmd0aCA+IDAgKVxuXHRcdFx0e1xuXHRcdFx0XHRjbGlja2VkSXRlbUlkID0gY2xpY2tlZEl0ZW0uYXR0ciggXCJkYXRhLW1vZGVsLWNpZFwiICk7XG5cdFx0XHRcdGlmKCAkLmlzTnVtZXJpYyggY2xpY2tlZEl0ZW1JZCApICkgY2xpY2tlZEl0ZW1JZCA9IHBhcnNlSW50KCBjbGlja2VkSXRlbUlkLCAxMCApO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gY2xpY2tlZEl0ZW1JZDtcblx0XHR9LFxuXG5cdFx0X3VwZGF0ZUl0ZW1UZW1wbGF0ZSA6IGZ1bmN0aW9uKCkge1xuXHRcdFx0dmFyIGl0ZW1UZW1wbGF0ZUh0bWw7XG5cdFx0XHRpZiggdGhpcy5pdGVtVGVtcGxhdGUgKVxuXHRcdFx0e1xuXHRcdFx0XHRpZiggJCggdGhpcy5pdGVtVGVtcGxhdGUgKS5sZW5ndGggPT09IDAgKVxuXHRcdFx0XHRcdHRocm93IFwiQ291bGQgbm90IGZpbmQgaXRlbSB0ZW1wbGF0ZSBmcm9tIHNlbGVjdG9yOiBcIiArIHRoaXMuaXRlbVRlbXBsYXRlO1xuXG5cdFx0XHRcdGl0ZW1UZW1wbGF0ZUh0bWwgPSAkKCB0aGlzLml0ZW1UZW1wbGF0ZSApLmh0bWwoKTtcblx0XHRcdH1cblx0XHRcdGVsc2Vcblx0XHRcdFx0aXRlbVRlbXBsYXRlSHRtbCA9IHRoaXMuJCggXCIuaXRlbS10ZW1wbGF0ZVwiICkuaHRtbCgpO1xuXG5cdFx0XHRpZiggaXRlbVRlbXBsYXRlSHRtbCApIHRoaXMuaXRlbVRlbXBsYXRlRnVuY3Rpb24gPSBfLnRlbXBsYXRlKCBpdGVtVGVtcGxhdGVIdG1sICk7XG5cblx0XHR9LFxuXG5cdFx0X3ZhbGlkYXRlU2VsZWN0aW9uIDogZnVuY3Rpb24oKSB7XG5cdFx0XHQvLyBub3RlIGNhbid0IHVzZSB0aGUgY29sbGVjdGlvbidzIHByb3h5IHRvIHVuZGVyc2NvcmUgYmVjYXVzZSBcImNpZFwiIGlzIG5vdCBhbiBhdHRyaWJ1dGUsXG5cdFx0XHQvLyBidXQgYW4gZWxlbWVudCBvZiB0aGUgbW9kZWwgb2JqZWN0IGl0c2VsZi5cblx0XHRcdHZhciBtb2RlbFJlZmVyZW5jZUlkcyA9IF8ucGx1Y2soIHRoaXMuY29sbGVjdGlvbi5tb2RlbHMsIFwiY2lkXCIgKTtcblx0XHRcdHRoaXMuc2VsZWN0ZWRJdGVtcyA9IF8uaW50ZXJzZWN0aW9uKCBtb2RlbFJlZmVyZW5jZUlkcywgdGhpcy5zZWxlY3RlZEl0ZW1zICk7XG5cblx0XHRcdGlmKCBfLmlzRnVuY3Rpb24oIHRoaXMuc2VsZWN0YWJsZU1vZGVsc0ZpbHRlciApIClcblx0XHRcdHtcblx0XHRcdFx0dGhpcy5zZWxlY3RlZEl0ZW1zID0gXy5maWx0ZXIoIHRoaXMuc2VsZWN0ZWRJdGVtcywgZnVuY3Rpb24oIHRoaXNJdGVtSWQgKSB7XG5cdFx0XHRcdFx0cmV0dXJuIHRoaXMuc2VsZWN0YWJsZU1vZGVsc0ZpbHRlci5jYWxsKCB0aGlzLCB0aGlzLmNvbGxlY3Rpb24uZ2V0KCB0aGlzSXRlbUlkICkgKTtcblx0XHRcdFx0fSwgdGhpcyApO1xuXHRcdFx0fVxuXHRcdH0sXG5cblx0XHRfc2F2ZVNlbGVjdGlvbiA6IGZ1bmN0aW9uKCkge1xuXHRcdFx0Ly8gc2F2ZSB0aGUgY3VycmVudCBzZWxlY3Rpb24uIHVzZSByZXN0b3JlU2VsZWN0aW9uKCkgdG8gcmVzdG9yZSB0aGUgc2VsZWN0aW9uIHRvIHRoZSBzdGF0ZSBpdCB3YXMgaW4gdGhlIGxhc3QgdGltZSBzYXZlU2VsZWN0aW9uKCkgd2FzIGNhbGxlZC5cblx0XHRcdGlmKCAhIHRoaXMuc2VsZWN0YWJsZSApIHRocm93IFwiQXR0ZW1wdCB0byBzYXZlIHNlbGVjdGlvbiBvbiBub24tc2VsZWN0YWJsZSBsaXN0XCI7XG5cdFx0XHR0aGlzLnNhdmVkU2VsZWN0aW9uID0ge1xuXHRcdFx0XHRpdGVtcyA6IF8uY2xvbmUoIHRoaXMuc2VsZWN0ZWRJdGVtcyApLFxuXHRcdFx0XHRvZmZzZXQgOiB0aGlzLmdldFNlbGVjdGVkTW9kZWwoIHsgYnkgOiBcIm9mZnNldFwiIH0gKVxuXHRcdFx0fTtcblx0XHR9LFxuXG5cdFx0X3Jlc3RvcmVTZWxlY3Rpb24gOiBmdW5jdGlvbigpIHtcblx0XHRcdGlmKCAhIHRoaXMuc2F2ZWRTZWxlY3Rpb24gKSB0aHJvdyBcIkF0dGVtcHQgdG8gcmVzdG9yZSBzZWxlY3Rpb24gYnV0IG5vIHNlbGVjdGlvbiBoYXMgYmVlbiBzYXZlZCFcIjtcblxuXHRcdFx0Ly8gcmVzZXQgc2VsZWN0ZWRJdGVtcyB0byBlbXB0eSBzbyB0aGF0IHdlIFwicmVkcmF3XCIgYWxsIFwic2VsZWN0ZWRcIiBjbGFzc2VzXG5cdFx0XHQvLyB3aGVuIHdlIHNldCBvdXIgbmV3IHNlbGVjdGlvbi4gV2UgZG8gdGhpcyBiZWNhdXNlIGl0IGlzIGxpa2VseSB0aGF0IG91clxuXHRcdFx0Ly8gY29udGVudHMgaGF2ZSBiZWVuIHJlZnJlc2hlZCwgYW5kIHdlIGhhdmUgdGh1cyBsb3N0IGFsbCBvbGQgXCJzZWxlY3RlZFwiIGNsYXNzZXMuXG5cdFx0XHR0aGlzLnNldFNlbGVjdGVkTW9kZWxzKCBbXSwgeyBzaWxlbnQgOiB0cnVlIH0gKTtcblxuXHRcdFx0aWYoIHRoaXMuc2F2ZWRTZWxlY3Rpb24uaXRlbXMubGVuZ3RoID4gMCApXG5cdFx0XHR7XG5cdFx0XHRcdC8vIGZpcnN0IHRyeSB0byByZXN0b3JlIHRoZSBvbGQgc2VsZWN0ZWQgaXRlbXMgdXNpbmcgdGhlaXIgcmVmZXJlbmNlIGlkcy5cblx0XHRcdFx0dGhpcy5zZXRTZWxlY3RlZE1vZGVscyggdGhpcy5zYXZlZFNlbGVjdGlvbi5pdGVtcywgeyBieSA6IFwiY2lkXCIsIHNpbGVudCA6IHRydWUgfSApO1xuXG5cdFx0XHRcdC8vIGFsbCB0aGUgaXRlbXMgd2l0aCB0aGUgc2F2ZWQgcmVmZXJlbmNlIGlkcyBoYXZlIGJlZW4gcmVtb3ZlZCBmcm9tIHRoZSBsaXN0LlxuXHRcdFx0XHQvLyBvay4gdHJ5IHRvIHJlc3RvcmUgdGhlIHNlbGVjdGlvbiBiYXNlZCBvbiB0aGUgb2Zmc2V0IHRoYXQgdXNlZCB0byBiZSBzZWxlY3RlZC5cblx0XHRcdFx0Ly8gdGhpcyBpcyB0aGUgZXhwZWN0ZWQgYmVoYXZpb3IgYWZ0ZXIgYSBpdGVtIGlzIGRlbGV0ZWQgZnJvbSBhIGxpc3QgKGkuZS4gc2VsZWN0XG5cdFx0XHRcdC8vIHRoZSBsaW5lIHRoYXQgaW1tZWRpYXRlbHkgZm9sbG93cyB0aGUgZGVsZXRlZCBsaW5lKS5cblx0XHRcdFx0aWYoIHRoaXMuc2VsZWN0ZWRJdGVtcy5sZW5ndGggPT09IDAgKVxuXHRcdFx0XHRcdHRoaXMuc2V0U2VsZWN0ZWRNb2RlbCggdGhpcy5zYXZlZFNlbGVjdGlvbi5vZmZzZXQsIHsgYnkgOiBcIm9mZnNldFwiIH0gKTtcblxuXHRcdFx0XHQvLyBUcmlnZ2VyIGEgc2VsZWN0aW9uIGNoYW5nZWQgaWYgdGhlIHByZXZpb3VzbHkgc2VsZWN0ZWQgaXRlbXMgd2VyZSBub3QgYWxsIGZvdW5kXG5cdFx0XHRcdGlmICh0aGlzLnNlbGVjdGVkSXRlbXMubGVuZ3RoICE9PSB0aGlzLnNhdmVkU2VsZWN0aW9uLml0ZW1zLmxlbmd0aClcblx0XHRcdFx0e1xuXHRcdFx0XHRcdGlmKCB0aGlzLl9pc0JhY2tib25lQ291cmllckF2YWlsYWJsZSgpICkge1xuXHRcdFx0XHRcdFx0dGhpcy5zcGF3biggXCJzZWxlY3Rpb25DaGFuZ2VkXCIsIHtcblx0XHRcdFx0XHRcdFx0c2VsZWN0ZWRNb2RlbHMgOiB0aGlzLmdldFNlbGVjdGVkTW9kZWxzKCksXG5cdFx0XHRcdFx0XHRcdG9sZFNlbGVjdGVkTW9kZWxzIDogW11cblx0XHRcdFx0XHRcdH0gKTtcblx0XHRcdFx0XHR9IGVsc2UgdGhpcy50cmlnZ2VyKCBcInNlbGVjdGlvbkNoYW5nZWRcIiwgdGhpcy5nZXRTZWxlY3RlZE1vZGVscygpLCBbXSApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fSxcblxuXHRcdF9hZGRTZWxlY3RlZENsYXNzVG9TZWxlY3RlZEl0ZW1zIDogZnVuY3Rpb24oIG9sZEl0ZW1zSWRzV2l0aFNlbGVjdGVkQ2xhc3MgKSB7XG5cdFx0XHRpZiggXy5pc1VuZGVmaW5lZCggb2xkSXRlbXNJZHNXaXRoU2VsZWN0ZWRDbGFzcyApICkgb2xkSXRlbXNJZHNXaXRoU2VsZWN0ZWRDbGFzcyA9IFtdO1xuXG5cdFx0XHQvLyBvbGRJdGVtc0lkc1dpdGhTZWxlY3RlZENsYXNzIGlzIHVzZWQgZm9yIG9wdGltaXphdGlvbiBwdXJwb3NlcyBvbmx5LiBJZiB0aGlzIGluZm8gaXMgc3VwcGxpZWQgdGhlbiB3ZVxuXHRcdFx0Ly8gb25seSBoYXZlIHRvIGFkZCAvIHJlbW92ZSB0aGUgXCJzZWxlY3RlZFwiIGNsYXNzIGZyb20gdGhvc2UgaXRlbXMgdGhhdCBcInNlbGVjdGVkXCIgc3RhdGUgaGFzIGNoYW5nZWQuXG5cblx0XHRcdHZhciBpdGVtc0lkc0Zyb21XaGljaFNlbGVjdGVkQ2xhc3NOZWVkc1RvQmVSZW1vdmVkID0gb2xkSXRlbXNJZHNXaXRoU2VsZWN0ZWRDbGFzcztcblx0XHRcdGl0ZW1zSWRzRnJvbVdoaWNoU2VsZWN0ZWRDbGFzc05lZWRzVG9CZVJlbW92ZWQgPSBfLndpdGhvdXQoIGl0ZW1zSWRzRnJvbVdoaWNoU2VsZWN0ZWRDbGFzc05lZWRzVG9CZVJlbW92ZWQsIHRoaXMuc2VsZWN0ZWRJdGVtcyApO1xuXG5cdFx0XHRfLmVhY2goIGl0ZW1zSWRzRnJvbVdoaWNoU2VsZWN0ZWRDbGFzc05lZWRzVG9CZVJlbW92ZWQsIGZ1bmN0aW9uKCB0aGlzSXRlbUlkICkge1xuXHRcdFx0XHR0aGlzLl9nZXRDb250YWluZXJFbCgpLmZpbmQoIFwiW2RhdGEtbW9kZWwtY2lkPVwiICsgdGhpc0l0ZW1JZCArIFwiXVwiICkucmVtb3ZlQ2xhc3MoIFwic2VsZWN0ZWRcIiApO1xuXG5cdFx0XHRcdGlmKCB0aGlzLl9pc1JlbmRlcmVkQXNMaXN0KCkgKSB7XG5cdFx0XHRcdFx0dGhpcy5fZ2V0Q29udGFpbmVyRWwoKS5maW5kKCBcImxpW2RhdGEtbW9kZWwtY2lkPVwiICsgdGhpc0l0ZW1JZCArIFwiXSA+ICpcIiApLnJlbW92ZUNsYXNzKCBcInNlbGVjdGVkXCIgKTtcblx0XHRcdFx0fVxuXHRcdFx0fSwgdGhpcyApO1xuXG5cdFx0XHR2YXIgaXRlbXNJZHNGcm9tV2hpY2hTZWxlY3RlZENsYXNzTmVlZHNUb0JlQWRkZWQgPSB0aGlzLnNlbGVjdGVkSXRlbXM7XG5cdFx0XHRpdGVtc0lkc0Zyb21XaGljaFNlbGVjdGVkQ2xhc3NOZWVkc1RvQmVBZGRlZCA9IF8ud2l0aG91dCggaXRlbXNJZHNGcm9tV2hpY2hTZWxlY3RlZENsYXNzTmVlZHNUb0JlQWRkZWQsIG9sZEl0ZW1zSWRzV2l0aFNlbGVjdGVkQ2xhc3MgKTtcblxuXHRcdFx0Xy5lYWNoKCBpdGVtc0lkc0Zyb21XaGljaFNlbGVjdGVkQ2xhc3NOZWVkc1RvQmVBZGRlZCwgZnVuY3Rpb24oIHRoaXNJdGVtSWQgKSB7XG5cdFx0XHRcdHRoaXMuX2dldENvbnRhaW5lckVsKCkuZmluZCggXCJbZGF0YS1tb2RlbC1jaWQ9XCIgKyB0aGlzSXRlbUlkICsgXCJdXCIgKS5hZGRDbGFzcyggXCJzZWxlY3RlZFwiICk7XG5cblx0XHRcdFx0aWYoIHRoaXMuX2lzUmVuZGVyZWRBc0xpc3QoKSApIHtcblx0XHRcdFx0XHR0aGlzLl9nZXRDb250YWluZXJFbCgpLmZpbmQoIFwibGlbZGF0YS1tb2RlbC1jaWQ9XCIgKyB0aGlzSXRlbUlkICsgXCJdID4gKlwiICkuYWRkQ2xhc3MoIFwic2VsZWN0ZWRcIiApO1xuXHRcdFx0XHR9XG5cdFx0XHR9LCB0aGlzICk7XG5cdFx0fSxcblxuXHRcdF9yZW9yZGVyQ29sbGVjdGlvbkJhc2VkT25IVE1MIDogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHZhciBfdGhpcyA9IHRoaXM7XG5cblx0XHRcdHRoaXMuX2dldENvbnRhaW5lckVsKCkuY2hpbGRyZW4oKS5lYWNoKCBmdW5jdGlvbigpIHtcblx0XHRcdFx0dmFyIHRoaXNNb2RlbENpZCA9ICQoIHRoaXMgKS5hdHRyKCBcImRhdGEtbW9kZWwtY2lkXCIgKTtcblxuXHRcdFx0XHRpZiggdGhpc01vZGVsQ2lkIClcblx0XHRcdFx0e1xuXHRcdFx0XHRcdC8vIHJlbW92ZSB0aGUgY3VycmVudCBtb2RlbCBhbmQgdGhlbiBhZGQgaXQgYmFjayAoYXQgdGhlIGVuZCBvZiB0aGUgY29sbGVjdGlvbikuXG5cdFx0XHRcdFx0Ly8gV2hlbiB3ZSBhcmUgZG9uZSBsb29waW5nIHRocm91Z2ggYWxsIG1vZGVscywgdGhleSB3aWxsIGJlIGluIHRoZSBjb3JyZWN0IG9yZGVyLlxuXHRcdFx0XHRcdHZhciB0aGlzTW9kZWwgPSBfdGhpcy5jb2xsZWN0aW9uLmdldCggdGhpc01vZGVsQ2lkICk7XG5cdFx0XHRcdFx0aWYoIHRoaXNNb2RlbCApXG5cdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0X3RoaXMuY29sbGVjdGlvbi5yZW1vdmUoIHRoaXNNb2RlbCwgeyBzaWxlbnQgOiB0cnVlIH0gKTtcblx0XHRcdFx0XHRcdF90aGlzLmNvbGxlY3Rpb24uYWRkKCB0aGlzTW9kZWwsIHsgc2lsZW50IDogdHJ1ZSwgc29ydCA6ICEgX3RoaXMuY29sbGVjdGlvbi5jb21wYXJhdG9yIH0gKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH0gKTtcblxuXHRcdFx0aWYoIHRoaXMuX2lzQmFja2JvbmVDb3VyaWVyQXZhaWxhYmxlKCkgKSB0aGlzLnNwYXduKCBcInJlb3JkZXJcIiApO1xuXHRcdFx0ZWxzZSB0aGlzLmNvbGxlY3Rpb24udHJpZ2dlciggXCJyZW9yZGVyXCIgKTtcblxuXHRcdFx0aWYoIHRoaXMuY29sbGVjdGlvbi5jb21wYXJhdG9yICkgdGhpcy5jb2xsZWN0aW9uLnNvcnQoKTtcblxuXHRcdH0sXG5cblx0XHRfZ2V0TW9kZWxWaWV3Q29uc3RydWN0b3IgOiBmdW5jdGlvbiggdGhpc01vZGVsICkge1xuXHRcdFx0cmV0dXJuIHRoaXMubW9kZWxWaWV3IHx8IG1EZWZhdWx0TW9kZWxWaWV3Q29uc3RydWN0b3I7XG5cdFx0fSxcblxuXHRcdF9nZXRNb2RlbFZpZXdPcHRpb25zIDogZnVuY3Rpb24oIHRoaXNNb2RlbCApIHtcblx0XHRcdHZhciBtb2RlbFZpZXdPcHRpb25zID0gdGhpcy5tb2RlbFZpZXdPcHRpb25zO1xuXHRcdFx0aWYoIF8uaXNGdW5jdGlvbiggbW9kZWxWaWV3T3B0aW9ucyApICkgbW9kZWxWaWV3T3B0aW9ucyA9IG1vZGVsVmlld09wdGlvbnMoIHRoaXNNb2RlbCApO1xuXG5cdFx0XHRyZXR1cm4gXy5leHRlbmQoIHsgbW9kZWwgOiB0aGlzTW9kZWwgfSwgbW9kZWxWaWV3T3B0aW9ucyApO1xuXHRcdH0sXG5cblx0XHRfY3JlYXRlTmV3TW9kZWxWaWV3IDogZnVuY3Rpb24oIG1vZGVsLCBtb2RlbFZpZXdPcHRpb25zICkge1xuXHRcdFx0dmFyIG1vZGVsVmlld0NvbnN0cnVjdG9yID0gdGhpcy5fZ2V0TW9kZWxWaWV3Q29uc3RydWN0b3IoIG1vZGVsICk7XG5cdFx0XHRpZiggXy5pc1VuZGVmaW5lZCggbW9kZWxWaWV3Q29uc3RydWN0b3IgKSApIHRocm93IFwiQ291bGQgbm90IGZpbmQgbW9kZWxWaWV3IGNvbnN0cnVjdG9yIGZvciBtb2RlbFwiO1xuXG5cdFx0XHR2YXIgbmV3TW9kZWxWaWV3ID0gbmV3KCBtb2RlbFZpZXdDb25zdHJ1Y3RvciApKCBtb2RlbFZpZXdPcHRpb25zICk7XG5cdFx0XHRuZXdNb2RlbFZpZXcuY29sbGVjdGlvbkxpc3RWaWV3ID0gbmV3TW9kZWxWaWV3LmNvbGxlY3Rpb25WaWV3ID0gdGhpczsgIC8vIGNvbGxlY3Rpb25MaXN0VmlldyBmb3IgbGVnYWN5XG5cblx0XHRcdHJldHVybiBuZXdNb2RlbFZpZXc7XG5cdFx0fSxcblxuXHRcdF93cmFwTW9kZWxWaWV3IDogZnVuY3Rpb24oIG1vZGVsVmlldyApIHtcblx0XHRcdHZhciBfdGhpcyA9IHRoaXM7XG5cblx0XHRcdC8vIHdlIHVzZSBpdGVtcyBjbGllbnQgaWRzIGFzIG9wcG9zZWQgdG8gcmVhbCBpZHMsIHNpbmNlIHdlIG1heSBub3QgaGF2ZSBhIHJlcHJlc2VudGF0aW9uXG5cdFx0XHQvLyBvZiB0aGVzZSBtb2RlbHMgb24gdGhlIHNlcnZlclxuXHRcdFx0dmFyIG1vZGVsVmlld1dyYXBwZXJFbDtcblxuXHRcdFx0aWYoIHRoaXMuX2lzUmVuZGVyZWRBc1RhYmxlKCkgKSB7XG5cdFx0XHRcdC8vIGlmIHdlIGFyZSByZW5kZXJpbmcgdGhlIGNvbGxlY3Rpb24gaW4gYSB0YWJsZSwgdGhlIHRlbXBsYXRlICRlbCBpcyBhIHRyIHNvIHdlIGp1c3QgbmVlZCB0byBzZXQgdGhlIGRhdGEtbW9kZWwtY2lkXG5cdFx0XHRcdG1vZGVsVmlld1dyYXBwZXJFbCA9IG1vZGVsVmlldy4kZWw7XG5cdFx0XHRcdG1vZGVsVmlldy4kZWwuYXR0ciggXCJkYXRhLW1vZGVsLWNpZFwiLCBtb2RlbFZpZXcubW9kZWwuY2lkICk7XG5cdFx0XHR9XG5cdFx0XHRlbHNlIGlmKCB0aGlzLl9pc1JlbmRlcmVkQXNMaXN0KCkgKSB7XG5cdFx0XHRcdC8vIGlmIHdlIGFyZSByZW5kZXJpbmcgdGhlIGNvbGxlY3Rpb24gaW4gYSBsaXN0LCB3ZSBuZWVkIHdyYXAgZWFjaCBpdGVtIGluIGFuIDxsaT48L2xpPiAoaWYgaXRzIG5vdCBhbHJlYWR5IGFuIDxsaT4pXG5cdFx0XHRcdC8vIGFuZCBzZXQgdGhlIGRhdGEtbW9kZWwtY2lkXG5cdFx0XHRcdGlmKCBtb2RlbFZpZXcuJGVsLmlzKCBcImxpXCIgKSApIHtcblx0XHRcdFx0XHRtb2RlbFZpZXdXcmFwcGVyRWwgPSBtb2RlbFZpZXcuJGVsO1xuXHRcdFx0XHRcdG1vZGVsVmlldy4kZWwuYXR0ciggXCJkYXRhLW1vZGVsLWNpZFwiLCBtb2RlbFZpZXcubW9kZWwuY2lkICk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0bW9kZWxWaWV3V3JhcHBlckVsID0gbW9kZWxWaWV3LiRlbC53cmFwQWxsKCBcIjxsaSBkYXRhLW1vZGVsLWNpZD0nXCIgKyBtb2RlbFZpZXcubW9kZWwuY2lkICsgXCInPjwvbGk+XCIgKS5wYXJlbnQoKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHRpZiggXy5pc0Z1bmN0aW9uKCB0aGlzLnNvcnRhYmxlTW9kZWxzRmlsdGVyICkgKVxuXHRcdFx0XHRpZiggISB0aGlzLnNvcnRhYmxlTW9kZWxzRmlsdGVyLmNhbGwoIF90aGlzLCBtb2RlbFZpZXcubW9kZWwgKSApIHtcblx0XHRcdFx0XHRtb2RlbFZpZXdXcmFwcGVyRWwuYWRkQ2xhc3MoIFwibm90LXNvcnRhYmxlXCIgKTtcblx0XHRcdFx0XHRtb2RlbFZpZXcuJGVsLmFkZENsYXNzKCBcIm5vdC1zZWxlY3RhYmxlXCIgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRpZiggXy5pc0Z1bmN0aW9uKCB0aGlzLnNlbGVjdGFibGVNb2RlbHNGaWx0ZXIgKSApXG5cdFx0XHRcdGlmKCAhIHRoaXMuc2VsZWN0YWJsZU1vZGVsc0ZpbHRlci5jYWxsKCBfdGhpcywgbW9kZWxWaWV3Lm1vZGVsICkgKSB7XG5cdFx0XHRcdFx0bW9kZWxWaWV3V3JhcHBlckVsLmFkZENsYXNzKCBcIm5vdC1zZWxlY3RhYmxlXCIgKTtcblx0XHRcdFx0XHRtb2RlbFZpZXcuJGVsLmFkZENsYXNzKCBcIm5vdC1zZWxlY3RhYmxlXCIgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gbW9kZWxWaWV3V3JhcHBlckVsO1xuXHRcdH0sXG5cblx0XHRfY29udmVydFN0cmluZ3NUb0ludHMgOiBmdW5jdGlvbiggdGhlQXJyYXkgKSB7XG5cdFx0XHRyZXR1cm4gXy5tYXAoIHRoZUFycmF5LCBmdW5jdGlvbiggdGhpc0VsICkge1xuXHRcdFx0XHRpZiggISBfLmlzU3RyaW5nKCB0aGlzRWwgKSApIHJldHVybiB0aGlzRWw7XG5cdFx0XHRcdHZhciB0aGlzRWxBc051bWJlciA9IHBhcnNlSW50KCB0aGlzRWwsIDEwICk7XG5cdFx0XHRcdHJldHVybiggdGhpc0VsQXNOdW1iZXIgPT0gdGhpc0VsID8gdGhpc0VsQXNOdW1iZXIgOiB0aGlzRWwgKTtcblx0XHRcdH0gKTtcblx0XHR9LFxuXG5cdFx0X2NvbnRhaW5TYW1lRWxlbWVudHMgOiBmdW5jdGlvbiggYXJyYXlBLCBhcnJheUIgKSB7XG5cdFx0XHRpZiggYXJyYXlBLmxlbmd0aCAhPSBhcnJheUIubGVuZ3RoICkgcmV0dXJuIGZhbHNlO1xuXHRcdFx0dmFyIGludGVyc2VjdGlvblNpemUgPSBfLmludGVyc2VjdGlvbiggYXJyYXlBLCBhcnJheUIgKS5sZW5ndGg7XG5cdFx0XHRyZXR1cm4gaW50ZXJzZWN0aW9uU2l6ZSA9PSBhcnJheUEubGVuZ3RoOyAvLyBhbmQgbXVzdCBhbHNvIGVxdWFsIGFycmF5Qi5sZW5ndGgsIHNpbmNlIGFycmF5QS5sZW5ndGggPT0gYXJyYXlCLmxlbmd0aFxuXHRcdH0sXG5cblx0XHRfaXNSZW5kZXJlZEFzVGFibGUgOiBmdW5jdGlvbigpIHtcblx0XHRcdHJldHVybiB0aGlzLiRlbC5wcm9wKCBcInRhZ05hbWVcIiApLnRvTG93ZXJDYXNlKCkgPT09IFwidGFibGVcIjtcblx0XHR9LFxuXG5cdFx0X2lzUmVuZGVyZWRBc0xpc3QgOiBmdW5jdGlvbigpIHtcblx0XHRcdHJldHVybiAhIHRoaXMuX2lzUmVuZGVyZWRBc1RhYmxlKCk7XG5cdFx0fSxcblxuXHRcdF9tb2RlbFZpZXdIYXNXcmFwcGVyTEkgOiBmdW5jdGlvbiggbW9kZWxWaWV3ICkge1xuXHRcdFx0cmV0dXJuIHRoaXMuX2lzUmVuZGVyZWRBc0xpc3QoKSAmJiAhIG1vZGVsVmlldy4kZWwuaXMoIFwibGlcIiApO1xuXHRcdH0sXG5cblx0XHQvLyBSZXR1cm5zIHRoZSB3cmFwcGVyIEhUTUwgZWxlbWVudCBmb3IgZWFjaCB2aXNpYmxlIG1vZGVsVmlldy5cblx0XHQvLyBXaGVuIHJlbmRlcmluZyBpbiBhIHRhYmxlIGNvbnRleHQsIHRoZSByZXR1cm5lZCBlbGVtZW50cyBhcmUgdGhlICRlbCBvZiBlYWNoIG1vZGVsVmlldy5cblx0XHQvLyBXaGVuIHJlbmRlcmluZyBpbiBhIGxpc3QgY29udGV4dCxcblx0XHQvLyAgIElmIHRoZSAkZWwgb2YgdGhlIG1vZGVsVmlldyBpcyBhbiA8bGk+LCB0aGUgcmV0dXJuZWQgZWxlbWVudHMgYXJlIHRoZSAkZWwgb2YgZWFjaCBtb2RlbFZpZXcuXG5cdFx0Ly8gICBPdGhlcndpc2UsIHRoZSByZXR1cm5lZCBlbGVtZW50cyBhcmUgdGhlIDxsaT4ncyB0aGUgY29sbGVjdGlvblZpZXcgd3JhcHBlZCBhcm91bmQgZWFjaCBtb2RlbFZpZXcgJGVsLlxuXHRcdF9nZXRWaXNpYmxlSXRlbUVscyA6IGZ1bmN0aW9uKCkge1xuXHRcdFx0dmFyIGl0ZW1FbGVtZW50cyA9IFtdO1xuXHRcdFx0aXRlbUVsZW1lbnRzID0gdGhpcy5fZ2V0Q29udGFpbmVyRWwoKS5maW5kKCBcIj4gW2RhdGEtbW9kZWwtY2lkXTpub3QoLm5vdC12aXNpYmxlKVwiICk7XG5cblx0XHRcdHJldHVybiBpdGVtRWxlbWVudHM7XG5cdFx0fSxcblxuXHRcdF9jaGFyQ29kZXMgOiB7XG5cdFx0XHR1cEFycm93IDogMzgsXG5cdFx0XHRkb3duQXJyb3cgOiA0MFxuXHRcdH0sXG5cblx0XHRfaXNCYWNrYm9uZUNvdXJpZXJBdmFpbGFibGUgOiBmdW5jdGlvbigpIHtcblx0XHRcdHJldHVybiAhXy5pc1VuZGVmaW5lZCggQmFja2JvbmUuQ291cmllciApO1xuXHRcdH0sXG5cblx0XHRfc2V0dXBTb3J0YWJsZSA6IGZ1bmN0aW9uKCkge1xuXHRcdFx0dmFyIHNvcnRhYmxlT3B0aW9ucyA9IF8uZXh0ZW5kKCB7XG5cdFx0XHRcdGF4aXMgOiBcInlcIixcblx0XHRcdFx0ZGlzdGFuY2UgOiAxMCxcblx0XHRcdFx0Zm9yY2VQbGFjZWhvbGRlclNpemUgOiB0cnVlLFxuXHRcdFx0XHRpdGVtcyA6IHRoaXMuX2lzUmVuZGVyZWRBc1RhYmxlKCkgPyBcIj4gdGJvZHkgPiB0cjpub3QoLm5vdC1zb3J0YWJsZSlcIiA6IFwiPiBsaTpub3QoLm5vdC1zb3J0YWJsZSlcIixcblx0XHRcdFx0c3RhcnQgOiBfLmJpbmQoIHRoaXMuX3NvcnRTdGFydCwgdGhpcyApLFxuXHRcdFx0XHRjaGFuZ2UgOiBfLmJpbmQoIHRoaXMuX3NvcnRDaGFuZ2UsIHRoaXMgKSxcblx0XHRcdFx0c3RvcCA6IF8uYmluZCggdGhpcy5fc29ydFN0b3AsIHRoaXMgKSxcblx0XHRcdFx0cmVjZWl2ZSA6IF8uYmluZCggdGhpcy5fcmVjZWl2ZSwgdGhpcyApLFxuXHRcdFx0XHRvdmVyIDogXy5iaW5kKCB0aGlzLl9vdmVyLCB0aGlzIClcblx0XHRcdH0sIF8ucmVzdWx0KCB0aGlzLCBcInNvcnRhYmxlT3B0aW9uc1wiICkgKTtcblxuXHRcdFx0dGhpcy4kZWwgPSB0aGlzLiRlbC5zb3J0YWJsZSggc29ydGFibGVPcHRpb25zICk7XG5cdFx0XHQvL3RoaXMuJGVsLnNvcnRhYmxlKCBcImVuYWJsZVwiICk7IC8vIGluIGNhc2UgaXQgd2FzIGRpc2FibGVkIHByZXZpb3VzbHlcblx0XHR9LFxuXG5cdFx0X3NvcnRTdGFydCA6IGZ1bmN0aW9uKCBldmVudCwgdWkgKSB7XG5cdFx0XHR2YXIgbW9kZWxCZWluZ1NvcnRlZCA9IHRoaXMuY29sbGVjdGlvbi5nZXQoIHVpLml0ZW0uYXR0ciggXCJkYXRhLW1vZGVsLWNpZFwiICkgKTtcblx0XHRcdGlmKCB0aGlzLl9pc0JhY2tib25lQ291cmllckF2YWlsYWJsZSgpIClcblx0XHRcdFx0dGhpcy5zcGF3biggXCJzb3J0U3RhcnRcIiwgeyBtb2RlbEJlaW5nU29ydGVkIDogbW9kZWxCZWluZ1NvcnRlZCB9ICk7XG5cdFx0XHRlbHNlIHRoaXMudHJpZ2dlciggXCJzb3J0U3RhcnRcIiwgbW9kZWxCZWluZ1NvcnRlZCApO1xuXHRcdH0sXG5cblx0XHRfc29ydENoYW5nZSA6IGZ1bmN0aW9uKCBldmVudCwgdWkgKSB7XG5cdFx0XHR2YXIgbW9kZWxCZWluZ1NvcnRlZCA9IHRoaXMuY29sbGVjdGlvbi5nZXQoIHVpLml0ZW0uYXR0ciggXCJkYXRhLW1vZGVsLWNpZFwiICkgKTtcblxuXHRcdFx0aWYoIHRoaXMuX2lzQmFja2JvbmVDb3VyaWVyQXZhaWxhYmxlKCkgKVxuXHRcdFx0XHR0aGlzLnNwYXduKCBcInNvcnRDaGFuZ2VcIiwgeyBtb2RlbEJlaW5nU29ydGVkIDogbW9kZWxCZWluZ1NvcnRlZCB9ICk7XG5cdFx0XHRlbHNlIHRoaXMudHJpZ2dlciggXCJzb3J0Q2hhbmdlXCIsIG1vZGVsQmVpbmdTb3J0ZWQgKTtcblx0XHR9LFxuXG5cdFx0X3NvcnRTdG9wIDogZnVuY3Rpb24oIGV2ZW50LCB1aSApIHtcblx0XHRcdHZhciBtb2RlbEJlaW5nU29ydGVkID0gdGhpcy5jb2xsZWN0aW9uLmdldCggdWkuaXRlbS5hdHRyKCBcImRhdGEtbW9kZWwtY2lkXCIgKSApO1xuXHRcdFx0dmFyIG1vZGVsVmlld0NvbnRhaW5lckVsID0gdGhpcy5fZ2V0Q29udGFpbmVyRWwoKTtcblx0XHRcdHZhciBuZXdJbmRleCA9IG1vZGVsVmlld0NvbnRhaW5lckVsLmNoaWxkcmVuKCkuaW5kZXgoIHVpLml0ZW0gKTtcblxuXHRcdFx0aWYoIG5ld0luZGV4ID09IC0xICYmIG1vZGVsQmVpbmdTb3J0ZWQgKSB7XG5cdFx0XHRcdC8vIHRoZSBlbGVtZW50IHdhcyByZW1vdmVkIGZyb20gdGhpcyBsaXN0LiBjYW4gaGFwcGVuIGlmIHRoaXMgc29ydGFibGUgaXMgY29ubmVjdGVkXG5cdFx0XHRcdC8vIHRvIGFub3RoZXIgc29ydGFibGUsIGFuZCB0aGUgaXRlbSB3YXMgZHJvcHBlZCBpbnRvIHRoZSBvdGhlciBzb3J0YWJsZS5cblx0XHRcdFx0dGhpcy5jb2xsZWN0aW9uLnJlbW92ZSggbW9kZWxCZWluZ1NvcnRlZCApO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiggISBtb2RlbEJlaW5nU29ydGVkICkgcmV0dXJuOyAvLyBzb21ldGhpbmcgaXMgd2Fja3kuIHdlIGRvbid0IG1lc3Mgd2l0aCB0aGlzIGNhc2UsIHByZWZlcnJpbmcgdG8gZ3VhcmFudGVlIHRoYXQgd2UgY2FuIGFsd2F5cyBwcm92aWRlIGEgcmVmZXJlbmNlIHRvIHRoZSBtb2RlbFxuXG5cdFx0XHR0aGlzLl9yZW9yZGVyQ29sbGVjdGlvbkJhc2VkT25IVE1MKCk7XG5cdFx0XHR0aGlzLnVwZGF0ZURlcGVuZGVudENvbnRyb2xzKCk7XG5cblx0XHRcdGlmKCB0aGlzLl9pc0JhY2tib25lQ291cmllckF2YWlsYWJsZSgpIClcblx0XHRcdFx0dGhpcy5zcGF3biggXCJzb3J0U3RvcFwiLCB7IG1vZGVsQmVpbmdTb3J0ZWQgOiBtb2RlbEJlaW5nU29ydGVkLCBuZXdJbmRleCA6IG5ld0luZGV4IH0gKTtcblx0XHRcdGVsc2UgdGhpcy50cmlnZ2VyKCBcInNvcnRTdG9wXCIsIG1vZGVsQmVpbmdTb3J0ZWQsIG5ld0luZGV4ICk7XG5cdFx0fSxcblxuXHRcdF9yZWNlaXZlIDogZnVuY3Rpb24oIGV2ZW50LCB1aSApIHtcblxuXHRcdFx0dmFyIHNlbmRlckxpc3RFbCA9IHVpLnNlbmRlcjtcblx0XHRcdHZhciBzZW5kZXJDb2xsZWN0aW9uTGlzdFZpZXcgPSBzZW5kZXJMaXN0RWwuZGF0YSggXCJ2aWV3XCIgKTtcblx0XHRcdGlmKCAhIHNlbmRlckNvbGxlY3Rpb25MaXN0VmlldyB8fCAhIHNlbmRlckNvbGxlY3Rpb25MaXN0Vmlldy5jb2xsZWN0aW9uICkgcmV0dXJuO1xuXG5cdFx0XHR2YXIgbmV3SW5kZXggPSB0aGlzLl9nZXRDb250YWluZXJFbCgpLmNoaWxkcmVuKCkuaW5kZXgoIHVpLml0ZW0gKTtcblx0XHRcdHZhciBtb2RlbFJlY2VpdmVkID0gc2VuZGVyQ29sbGVjdGlvbkxpc3RWaWV3LmNvbGxlY3Rpb24uZ2V0KCB1aS5pdGVtLmF0dHIoIFwiZGF0YS1tb2RlbC1jaWRcIiApICk7XG5cdFx0XHRzZW5kZXJDb2xsZWN0aW9uTGlzdFZpZXcuY29sbGVjdGlvbi5yZW1vdmUoIG1vZGVsUmVjZWl2ZWQgKTtcblx0XHRcdHRoaXMuY29sbGVjdGlvbi5hZGQoIG1vZGVsUmVjZWl2ZWQsIHsgYXQgOiBuZXdJbmRleCB9ICk7XG5cdFx0XHRtb2RlbFJlY2VpdmVkLmNvbGxlY3Rpb24gPSB0aGlzLmNvbGxlY3Rpb247IC8vIG90aGVyd2lzZSB3aWxsIG5vdCBnZXQgcHJvcGVybHkgc2V0LCBzaW5jZSBtb2RlbFJlY2VpdmVkLmNvbGxlY3Rpb24gbWlnaHQgYWxyZWFkeSBoYXZlIGEgdmFsdWUuXG5cdFx0XHR0aGlzLnNldFNlbGVjdGVkTW9kZWwoIG1vZGVsUmVjZWl2ZWQgKTtcblx0XHR9LFxuXG5cdFx0X292ZXIgOiBmdW5jdGlvbiggZXZlbnQsIHVpICkge1xuXHRcdFx0Ly8gd2hlbiBhbiBpdGVtIGlzIGJlaW5nIGRyYWdnZWQgaW50byB0aGUgc29ydGFibGUsXG5cdFx0XHQvLyBoaWRlIHRoZSBlbXB0eSBsaXN0IGNhcHRpb24gaWYgaXQgZXhpc3RzXG5cdFx0XHR0aGlzLl9nZXRDb250YWluZXJFbCgpLmZpbmQoIFwiPiB2YXIuZW1wdHktbGlzdC1jYXB0aW9uXCIgKS5oaWRlKCk7XG5cdFx0fSxcblxuXHRcdF9vbktleWRvd24gOiBmdW5jdGlvbiggZXZlbnQgKSB7XG5cdFx0XHRpZiggISB0aGlzLnByb2Nlc3NLZXlFdmVudHMgKSByZXR1cm4gdHJ1ZTtcblxuXHRcdFx0dmFyIHRyYXAgPSBmYWxzZTtcblxuXHRcdFx0aWYoIHRoaXMuZ2V0U2VsZWN0ZWRNb2RlbHMoIHsgYnkgOiBcIm9mZnNldFwiIH0gKS5sZW5ndGggPT0gMSApXG5cdFx0XHR7XG5cdFx0XHRcdC8vIG5lZWQgdG8gdHJhcCBkb3duIGFuZCB1cCBhcnJvd3Mgb3IgZWxzZSB0aGUgYnJvd3NlclxuXHRcdFx0XHQvLyB3aWxsIGVuZCB1cCBzY3JvbGxpbmcgYSBhdXRvc2Nyb2xsIGRpdi5cblxuXHRcdFx0XHR2YXIgY3VycmVudE9mZnNldCA9IHRoaXMuZ2V0U2VsZWN0ZWRNb2RlbCggeyBieSA6IFwib2Zmc2V0XCIgfSApO1xuXHRcdFx0XHRpZiggZXZlbnQud2hpY2ggPT09IHRoaXMuX2NoYXJDb2Rlcy51cEFycm93ICYmIGN1cnJlbnRPZmZzZXQgIT09IDAgKVxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0dGhpcy5zZXRTZWxlY3RlZE1vZGVsKCBjdXJyZW50T2Zmc2V0IC0gMSwgeyBieSA6IFwib2Zmc2V0XCIgfSApO1xuXHRcdFx0XHRcdHRyYXAgPSB0cnVlO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGVsc2UgaWYoIGV2ZW50LndoaWNoID09PSB0aGlzLl9jaGFyQ29kZXMuZG93bkFycm93ICYmIGN1cnJlbnRPZmZzZXQgIT09IHRoaXMuY29sbGVjdGlvbi5sZW5ndGggLSAxIClcblx0XHRcdFx0e1xuXHRcdFx0XHRcdHRoaXMuc2V0U2VsZWN0ZWRNb2RlbCggY3VycmVudE9mZnNldCArIDEsIHsgYnkgOiBcIm9mZnNldFwiIH0gKTtcblx0XHRcdFx0XHR0cmFwID0gdHJ1ZTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gISB0cmFwO1xuXHRcdH0sXG5cblx0XHRfbGlzdEl0ZW1fb25Nb3VzZWRvd24gOiBmdW5jdGlvbiggdGhlRXZlbnQgKSB7XG5cdFx0XHR2YXIgY2xpY2tlZEl0ZW1JZCA9IHRoaXMuX2dldENsaWNrZWRJdGVtSWQoIHRoZUV2ZW50ICk7XG5cblx0XHRcdGlmKCBjbGlja2VkSXRlbUlkICkge1xuXHRcdFx0XHR2YXIgY2xpY2tlZE1vZGVsID0gdGhpcy5jb2xsZWN0aW9uLmdldCggY2xpY2tlZEl0ZW1JZCApO1xuXHRcdFx0XHRpZiggdGhpcy5faXNCYWNrYm9uZUNvdXJpZXJBdmFpbGFibGUoKSApIHtcblx0XHRcdFx0XHR2YXIgZGF0YSA9IHtcblx0XHRcdFx0XHRcdGNsaWNrZWRNb2RlbCA6IGNsaWNrZWRNb2RlbCxcblx0XHRcdFx0XHRcdG1ldGFLZXlQcmVzc2VkIDogdGhlRXZlbnQuY3RybEtleSB8fCB0aGVFdmVudC5tZXRhS2V5XG5cdFx0XHRcdFx0fTtcblxuXHRcdFx0XHRcdF8uZWFjaCggWyAncHJldmVudERlZmF1bHQnLCAnc3RvcFByb3BhZ2F0aW9uJywgJ3N0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbicgXSwgZnVuY3Rpb24oIHRoaXNNZXRob2QgKSB7XG5cdFx0XHRcdFx0XHRkYXRhWyB0aGlzTWV0aG9kIF0gPSBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRcdFx0dGhlRXZlbnRbIHRoaXNNZXRob2QgXSgpO1xuXHRcdFx0XHRcdFx0fTtcblx0XHRcdFx0XHR9ICk7XG5cblx0XHRcdFx0XHR0aGlzLnNwYXduKCBcImNsaWNrXCIsIGRhdGEgKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRlbHNlIHRoaXMudHJpZ2dlciggXCJjbGlja1wiLCBjbGlja2VkTW9kZWwgKTtcblx0XHRcdH1cblxuXHRcdFx0aWYoICEgdGhpcy5zZWxlY3RhYmxlIHx8ICEgdGhpcy5jbGlja1RvU2VsZWN0ICkgcmV0dXJuO1xuXG5cdFx0XHRpZiggY2xpY2tlZEl0ZW1JZCApXG5cdFx0XHR7XG5cdFx0XHRcdC8vIEV4aXQgaWYgYW4gdW5zZWxlY3RhYmxlIGl0ZW0gd2FzIGNsaWNrZWRcblx0XHRcdFx0aWYoIF8uaXNGdW5jdGlvbiggdGhpcy5zZWxlY3RhYmxlTW9kZWxzRmlsdGVyICkgJiZcblx0XHRcdFx0XHQhIHRoaXMuc2VsZWN0YWJsZU1vZGVsc0ZpbHRlci5jYWxsKCB0aGlzLCB0aGlzLmNvbGxlY3Rpb24uZ2V0KCBjbGlja2VkSXRlbUlkICkgKSApXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBhIHNlbGVjdGFibGUgbGlzdCBpdGVtIHdhcyBjbGlja2VkXG5cdFx0XHRcdGlmKCB0aGlzLnNlbGVjdE11bHRpcGxlICYmIHRoZUV2ZW50LnNoaWZ0S2V5IClcblx0XHRcdFx0e1xuXHRcdFx0XHRcdHZhciBmaXJzdFNlbGVjdGVkSXRlbUluZGV4ID0gLTE7XG5cblx0XHRcdFx0XHRpZiggdGhpcy5zZWxlY3RlZEl0ZW1zLmxlbmd0aCA+IDAgKVxuXHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdHRoaXMuY29sbGVjdGlvbi5maW5kKCBmdW5jdGlvbiggdGhpc0l0ZW1Nb2RlbCApIHtcblx0XHRcdFx0XHRcdFx0Zmlyc3RTZWxlY3RlZEl0ZW1JbmRleCsrO1xuXG5cdFx0XHRcdFx0XHRcdC8vIGV4aXQgd2hlbiB3ZSBmaW5kIG91ciBmaXJzdCBzZWxlY3RlZCBlbGVtZW50XG5cdFx0XHRcdFx0XHRcdHJldHVybiBfLmNvbnRhaW5zKCB0aGlzLnNlbGVjdGVkSXRlbXMsIHRoaXNJdGVtTW9kZWwuY2lkICk7XG5cdFx0XHRcdFx0XHR9LCB0aGlzICk7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0dmFyIGNsaWNrZWRJdGVtSW5kZXggPSAtMTtcblx0XHRcdFx0XHR0aGlzLmNvbGxlY3Rpb24uZmluZCggZnVuY3Rpb24oIHRoaXNJdGVtTW9kZWwgKSB7XG5cdFx0XHRcdFx0XHRjbGlja2VkSXRlbUluZGV4Kys7XG5cblx0XHRcdFx0XHRcdC8vIGV4aXQgd2hlbiB3ZSBmaW5kIHRoZSBjbGlja2VkIGVsZW1lbnRcblx0XHRcdFx0XHRcdHJldHVybiB0aGlzSXRlbU1vZGVsLmNpZCA9PSBjbGlja2VkSXRlbUlkO1xuXHRcdFx0XHRcdH0sIHRoaXMgKTtcblxuXHRcdFx0XHRcdHZhciBzaGlmdEtleVJvb3RTZWxlY3RlZEl0ZW1JbmRleCA9IGZpcnN0U2VsZWN0ZWRJdGVtSW5kZXggPT0gLTEgPyBjbGlja2VkSXRlbUluZGV4IDogZmlyc3RTZWxlY3RlZEl0ZW1JbmRleDtcblx0XHRcdFx0XHR2YXIgbWluU2VsZWN0ZWRJdGVtSW5kZXggPSBNYXRoLm1pbiggY2xpY2tlZEl0ZW1JbmRleCwgc2hpZnRLZXlSb290U2VsZWN0ZWRJdGVtSW5kZXggKTtcblx0XHRcdFx0XHR2YXIgbWF4U2VsZWN0ZWRJdGVtSW5kZXggPSBNYXRoLm1heCggY2xpY2tlZEl0ZW1JbmRleCwgc2hpZnRLZXlSb290U2VsZWN0ZWRJdGVtSW5kZXggKTtcblxuXHRcdFx0XHRcdHZhciBuZXdTZWxlY3RlZEl0ZW1zID0gW107XG5cdFx0XHRcdFx0Zm9yKCB2YXIgdGhpc0luZGV4ID0gbWluU2VsZWN0ZWRJdGVtSW5kZXg7IHRoaXNJbmRleCA8PSBtYXhTZWxlY3RlZEl0ZW1JbmRleDsgdGhpc0luZGV4ICsrIClcblx0XHRcdFx0XHRcdG5ld1NlbGVjdGVkSXRlbXMucHVzaCggdGhpcy5jb2xsZWN0aW9uLmF0KCB0aGlzSW5kZXggKS5jaWQgKTtcblx0XHRcdFx0XHR0aGlzLnNldFNlbGVjdGVkTW9kZWxzKCBuZXdTZWxlY3RlZEl0ZW1zLCB7IGJ5IDogXCJjaWRcIiB9ICk7XG5cblx0XHRcdFx0XHQvLyBzaGlmdCBjbGlja2luZyB3aWxsIHVzdWFsbHkgaGlnaGxpZ2h0IHNlbGVjdGFibGUgdGV4dCwgd2hpY2ggd2UgZG8gbm90IHdhbnQuXG5cdFx0XHRcdFx0Ly8gdGhpcyBpcyBhIGNyb3NzIGJyb3dzZXIgKGhvcGVmdWxseSkgc25pcHBldCB0aGF0IGRlc2VsZWN0cyBhbGwgdGV4dCBzZWxlY3Rpb24uXG5cdFx0XHRcdFx0aWYoIGRvY3VtZW50LnNlbGVjdGlvbiAmJiBkb2N1bWVudC5zZWxlY3Rpb24uZW1wdHkgKVxuXHRcdFx0XHRcdFx0ZG9jdW1lbnQuc2VsZWN0aW9uLmVtcHR5KCk7XG5cdFx0XHRcdFx0ZWxzZSBpZih3aW5kb3cuZ2V0U2VsZWN0aW9uKSB7XG5cdFx0XHRcdFx0XHR2YXIgc2VsID0gd2luZG93LmdldFNlbGVjdGlvbigpO1xuXHRcdFx0XHRcdFx0aWYoIHNlbCAmJiBzZWwucmVtb3ZlQWxsUmFuZ2VzIClcblx0XHRcdFx0XHRcdFx0c2VsLnJlbW92ZUFsbFJhbmdlcygpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0XHRlbHNlIGlmKCAoIHRoaXMuc2VsZWN0TXVsdGlwbGUgfHwgXy5jb250YWlucyggdGhpcy5zZWxlY3RlZEl0ZW1zLCBjbGlja2VkSXRlbUlkICkgKSAmJiAoIHRoaXMuY2xpY2tUb1RvZ2dsZSB8fCB0aGVFdmVudC5tZXRhS2V5IHx8IHRoZUV2ZW50LmN0cmxLZXkgKSApXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRpZiggXy5jb250YWlucyggdGhpcy5zZWxlY3RlZEl0ZW1zLCBjbGlja2VkSXRlbUlkICkgKVxuXHRcdFx0XHRcdFx0dGhpcy5zZXRTZWxlY3RlZE1vZGVscyggXy53aXRob3V0KCB0aGlzLnNlbGVjdGVkSXRlbXMsIGNsaWNrZWRJdGVtSWQgKSwgeyBieSA6IFwiY2lkXCIgfSApO1xuXHRcdFx0XHRcdGVsc2UgdGhpcy5zZXRTZWxlY3RlZE1vZGVscyggXy51bmlvbiggdGhpcy5zZWxlY3RlZEl0ZW1zLCBbY2xpY2tlZEl0ZW1JZF0gKSwgeyBieSA6IFwiY2lkXCIgfSApO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGVsc2Vcblx0XHRcdFx0XHR0aGlzLnNldFNlbGVjdGVkTW9kZWxzKCBbIGNsaWNrZWRJdGVtSWQgXSwgeyBieSA6IFwiY2lkXCIgfSApO1xuXHRcdFx0fVxuXHRcdFx0ZWxzZVxuXHRcdFx0XHQvLyB0aGUgYmxhbmsgYXJlYSBvZiB0aGUgbGlzdCB3YXMgY2xpY2tlZFxuXHRcdFx0XHR0aGlzLnNldFNlbGVjdGVkTW9kZWxzKCBbXSApO1xuXG5cdFx0fSxcblxuXHRcdF9saXN0SXRlbV9vbkRvdWJsZUNsaWNrIDogZnVuY3Rpb24oIHRoZUV2ZW50ICkge1xuXG5cdFx0XHR2YXIgY2xpY2tlZEl0ZW1JZCA9IHRoaXMuX2dldENsaWNrZWRJdGVtSWQoIHRoZUV2ZW50ICk7XG5cblx0XHRcdGlmKCBjbGlja2VkSXRlbUlkIClcblx0XHRcdHtcblx0XHRcdFx0dmFyIGNsaWNrZWRNb2RlbCA9IHRoaXMuY29sbGVjdGlvbi5nZXQoIGNsaWNrZWRJdGVtSWQgKTtcblxuXHRcdFx0XHRpZiggdGhpcy5faXNCYWNrYm9uZUNvdXJpZXJBdmFpbGFibGUoKSApXG5cdFx0XHRcdFx0dGhpcy5zcGF3biggXCJkb3VibGVDbGlja1wiLCB7IGNsaWNrZWRNb2RlbCA6IGNsaWNrZWRNb2RlbCwgbWV0YUtleVByZXNzZWQgOiB0aGVFdmVudC5jdHJsS2V5IHx8IHRoZUV2ZW50Lm1ldGFLZXkgfSApO1xuXHRcdFx0XHRlbHNlIHRoaXMudHJpZ2dlciggXCJkb3VibGVDbGlja1wiLCBjbGlja2VkTW9kZWwgKTtcblx0XHRcdH1cblx0XHR9LFxuXG5cdFx0X2xpc3RCYWNrZ3JvdW5kX29uQ2xpY2sgOiBmdW5jdGlvbiggdGhlRXZlbnQgKSB7XG5cdFx0XHRpZiggISB0aGlzLnNlbGVjdGFibGUgfHwgISB0aGlzLmNsaWNrVG9TZWxlY3QgKSByZXR1cm47XG5cdFx0XHRpZiggISAkKCB0aGVFdmVudC50YXJnZXQgKS5pcyggXCIuY29sbGVjdGlvbi12aWV3XCIgKSApIHJldHVybjtcblxuXHRcdFx0dGhpcy5zZXRTZWxlY3RlZE1vZGVscyggW10gKTtcblx0XHR9XG5cblx0fSwge1xuXHRcdHNldERlZmF1bHRNb2RlbFZpZXdDb25zdHJ1Y3RvciA6IGZ1bmN0aW9uKCB0aGVDb25zdHJ1Y3RvciApIHtcblx0XHRcdG1EZWZhdWx0TW9kZWxWaWV3Q29uc3RydWN0b3IgPSB0aGVDb25zdHJ1Y3Rvcjtcblx0XHR9XG5cdH0pO1xuXG5cdC8qXG5cdCogQmFja2JvbmUuVmlld09wdGlvbnMsIHYwLjIuNFxuXHQqIENvcHlyaWdodCAoYykyMDE0IFJvdHVuZGEgU29mdHdhcmUsIExMQy5cblx0KiBEaXN0cmlidXRlZCB1bmRlciBNSVQgbGljZW5zZVxuXHQqIGh0dHA6Ly9naXRodWIuY29tL3JvdHVuZGFzb2Z0d2FyZS9iYWNrYm9uZS52aWV3T3B0aW9uc1xuXHQqL1xuXG5cdEJhY2tib25lLlZpZXdPcHRpb25zID0ge307XG5cblx0QmFja2JvbmUuVmlld09wdGlvbnMuYWRkID0gZnVuY3Rpb24oIHZpZXcsIG9wdGlvbnNEZWNsYXJhdGlvbnNQcm9wZXJ0eSApIHtcblx0XHRpZiggXy5pc1VuZGVmaW5lZCggb3B0aW9uc0RlY2xhcmF0aW9uc1Byb3BlcnR5ICkgKSBvcHRpb25zRGVjbGFyYXRpb25zUHJvcGVydHkgPSBcIm9wdGlvbnNcIjtcblxuXHRcdC8vICoqKioqKioqKioqKioqKioqKiBQdWJsaWMgbWV0aG9kcyBhZGRlZCB0byB2aWV3ICoqKioqKioqKioqKioqKioqKlxuXG5cdFx0dmlldy5zZXRPcHRpb25zID0gZnVuY3Rpb24oIG9wdGlvbnMgKSB7XG5cdFx0XHR2YXIgX3RoaXMgPSB0aGlzO1xuXHRcdFx0dmFyIG9wdGlvbnNUaGF0V2VyZUNoYW5nZWQgPSB7fTtcblx0XHRcdHZhciBvcHRpb25zVGhhdFdlcmVDaGFuZ2VkUHJldmlvdXNWYWx1ZXMgPSB7fTtcblxuXHRcdFx0dmFyIG9wdGlvbkRlY2xhcmF0aW9ucyA9IF8ucmVzdWx0KCB0aGlzLCBvcHRpb25zRGVjbGFyYXRpb25zUHJvcGVydHkgKTtcblxuXHRcdFx0aWYoICEgXy5pc1VuZGVmaW5lZCggb3B0aW9uRGVjbGFyYXRpb25zICkgKSB7XG5cdFx0XHRcdHZhciBub3JtYWxpemVkT3B0aW9uRGVjbGFyYXRpb25zID0gX25vcm1hbGl6ZU9wdGlvbkRlY2xhcmF0aW9ucyggb3B0aW9uRGVjbGFyYXRpb25zICk7XG5cblx0XHRcdFx0Xy5lYWNoKCBub3JtYWxpemVkT3B0aW9uRGVjbGFyYXRpb25zLCBmdW5jdGlvbiggdGhpc09wdGlvblByb3BlcnRpZXMsIHRoaXNPcHRpb25OYW1lICkge1xuXHRcdFx0XHRcdHZhciB0aGlzT3B0aW9uUmVxdWlyZWQgPSB0aGlzT3B0aW9uUHJvcGVydGllcy5yZXF1aXJlZDtcblx0XHRcdFx0XHR2YXIgdGhpc09wdGlvbkRlZmF1bHRWYWx1ZSA9IHRoaXNPcHRpb25Qcm9wZXJ0aWVzLmRlZmF1bHRWYWx1ZTtcblxuXHRcdFx0XHRcdGlmKCB0aGlzT3B0aW9uUmVxdWlyZWQgKSB7XG5cdFx0XHRcdFx0XHQvLyBub3RlIHdlIGRvIG5vdCB0aHJvdyBhbiBlcnJvciBpZiBhIHJlcXVpcmVkIG9wdGlvbiBpcyBub3Qgc3VwcGxpZWQsIGJ1dCBpdCBpc1xuXHRcdFx0XHRcdFx0Ly8gZm91bmQgb24gdGhlIG9iamVjdCBpdHNlbGYgKGR1ZSB0byBhIHByaW9yIGNhbGwgb2Ygdmlldy5zZXRPcHRpb25zLCBtb3N0IGxpa2VseSlcblxuXHRcdFx0XHRcdFx0aWYoICggISBvcHRpb25zIHx8ICEgXy5jb250YWlucyggXy5rZXlzKCBvcHRpb25zICksIHRoaXNPcHRpb25OYW1lICkgKSAmJiBfLmlzVW5kZWZpbmVkKCBfdGhpc1sgdGhpc09wdGlvbk5hbWUgXSApIClcblx0XHRcdFx0XHRcdFx0dGhyb3cgbmV3IEVycm9yKCBcIlJlcXVpcmVkIG9wdGlvbiBcXFwiXCIgKyB0aGlzT3B0aW9uTmFtZSArIFwiXFxcIiB3YXMgbm90IHN1cHBsaWVkLlwiICk7XG5cblx0XHRcdFx0XHRcdGlmKCBvcHRpb25zICYmIF8uY29udGFpbnMoIF8ua2V5cyggb3B0aW9ucyApLCB0aGlzT3B0aW9uTmFtZSApICYmIF8uaXNVbmRlZmluZWQoIG9wdGlvbnNbIHRoaXNPcHRpb25OYW1lIF0gKSApXG5cdFx0XHRcdFx0XHRcdHRocm93IG5ldyBFcnJvciggXCJSZXF1aXJlZCBvcHRpb24gXFxcIlwiICsgdGhpc09wdGlvbk5hbWUgKyBcIlxcXCIgY2FuIG5vdCBiZSBzZXQgdG8gdW5kZWZpbmVkLlwiICk7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0Ly8gYXR0YWNoIHRoZSBzdXBwbGllZCB2YWx1ZSBvZiB0aGlzIG9wdGlvbiwgb3IgdGhlIGFwcHJvcHJpYXRlIGRlZmF1bHQgdmFsdWUsIHRvIHRoZSB2aWV3IG9iamVjdFxuXHRcdFx0XHRcdGlmKCBvcHRpb25zICYmIHRoaXNPcHRpb25OYW1lIGluIG9wdGlvbnMgJiYgISBfLmlzVW5kZWZpbmVkKCBvcHRpb25zWyB0aGlzT3B0aW9uTmFtZSBdICkgKSB7XG5cdFx0XHRcdFx0XHR2YXIgb2xkVmFsdWUgPSBfdGhpc1sgdGhpc09wdGlvbk5hbWUgXTtcblx0XHRcdFx0XHRcdHZhciBuZXdWYWx1ZSA9IG9wdGlvbnNbIHRoaXNPcHRpb25OYW1lIF07XG5cdFx0XHRcdFx0XHQvLyBpZiB0aGlzIG9wdGlvbiBhbHJlYWR5IGV4aXN0cyBvbiB0aGUgdmlldywgYW5kIHRoZSBuZXcgdmFsdWUgaXMgZGlmZmVyZW50LFxuXHRcdFx0XHRcdFx0Ly8gbWFrZSBhIG5vdGUgdGhhdCB3ZSB3aWxsIGJlIGNoYW5naW5nIGl0XG5cdFx0XHRcdFx0XHRpZiggISBfLmlzVW5kZWZpbmVkKCBvbGRWYWx1ZSApICYmIG9sZFZhbHVlICE9PSBuZXdWYWx1ZSApIHtcblx0XHRcdFx0XHRcdFx0b3B0aW9uc1RoYXRXZXJlQ2hhbmdlZFByZXZpb3VzVmFsdWVzWyB0aGlzT3B0aW9uTmFtZSBdID0gb2xkVmFsdWU7XG5cdFx0XHRcdFx0XHRcdG9wdGlvbnNUaGF0V2VyZUNoYW5nZWRbIHRoaXNPcHRpb25OYW1lIF0gPSBuZXdWYWx1ZTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdF90aGlzWyB0aGlzT3B0aW9uTmFtZSBdID0gbmV3VmFsdWU7XG5cdFx0XHRcdFx0XHQvLyBub3RlIHdlIGRvIE5PVCBkZWxldGUgdGhlIG9wdGlvbiBvZmYgdGhlIG9wdGlvbnMgb2JqZWN0IGhlcmUgc28gdGhhdFxuXHRcdFx0XHRcdFx0Ly8gbXVsdGlwbGUgdmlld3MgY2FuIGJlIHBhc3NlZCB0aGUgc2FtZSBvcHRpb25zIG9iamVjdCB3aXRob3V0IGlzc3VlLlxuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRlbHNlIGlmKCBfLmlzVW5kZWZpbmVkKCBfdGhpc1sgdGhpc09wdGlvbk5hbWUgXSApICkge1xuXHRcdFx0XHRcdFx0Ly8gbm90ZSBkZWZhdWx0cyBkbyBub3Qgd3JpdGUgb3ZlciBhbnkgZXhpc3RpbmcgcHJvcGVydGllcyBvbiB0aGUgdmlldyBpdHNlbGYuXG5cdFx0XHRcdFx0XHRfdGhpc1sgdGhpc09wdGlvbk5hbWUgXSA9IHRoaXNPcHRpb25EZWZhdWx0VmFsdWU7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9ICk7XG5cdFx0XHR9XG5cblx0XHRcdGlmKCBfLmtleXMoIG9wdGlvbnNUaGF0V2VyZUNoYW5nZWQgKS5sZW5ndGggPiAwICkge1xuXHRcdFx0XHRpZiggXy5pc0Z1bmN0aW9uKCBfdGhpcy5vbk9wdGlvbnNDaGFuZ2VkICkgKVxuXHRcdFx0XHRcdF90aGlzLm9uT3B0aW9uc0NoYW5nZWQoIG9wdGlvbnNUaGF0V2VyZUNoYW5nZWQsIG9wdGlvbnNUaGF0V2VyZUNoYW5nZWRQcmV2aW91c1ZhbHVlcyApO1xuXHRcdFx0XHRlbHNlIGlmKCBfLmlzRnVuY3Rpb24oIF90aGlzLl9vbk9wdGlvbnNDaGFuZ2VkICkgKVxuXHRcdFx0XHRcdF90aGlzLl9vbk9wdGlvbnNDaGFuZ2VkKCBvcHRpb25zVGhhdFdlcmVDaGFuZ2VkLCBvcHRpb25zVGhhdFdlcmVDaGFuZ2VkUHJldmlvdXNWYWx1ZXMgKTtcblx0XHRcdH1cblx0XHR9O1xuXG5cdFx0dmlldy5nZXRPcHRpb25zID0gZnVuY3Rpb24oKSB7XG5cdFx0XHR2YXIgb3B0aW9uRGVjbGFyYXRpb25zID0gXy5yZXN1bHQoIHRoaXMsIG9wdGlvbnNEZWNsYXJhdGlvbnNQcm9wZXJ0eSApO1xuXHRcdFx0aWYoIF8uaXNVbmRlZmluZWQoIG9wdGlvbkRlY2xhcmF0aW9ucyApICkgcmV0dXJuIHt9O1xuXG5cdFx0XHR2YXIgbm9ybWFsaXplZE9wdGlvbkRlY2xhcmF0aW9ucyA9IF9ub3JtYWxpemVPcHRpb25EZWNsYXJhdGlvbnMoIG9wdGlvbkRlY2xhcmF0aW9ucyApO1xuXHRcdFx0dmFyIG9wdGlvbnNOYW1lcyA9IF8ua2V5cyggbm9ybWFsaXplZE9wdGlvbkRlY2xhcmF0aW9ucyApO1xuXG5cdFx0XHRyZXR1cm4gXy5waWNrKCB0aGlzLCBvcHRpb25zTmFtZXMgKTtcblx0XHR9O1xuXHR9O1xuXG5cdC8vICoqKioqKioqKioqKioqKioqKiBQcml2YXRlIFV0aWxpdHkgRnVuY3Rpb25zICoqKioqKioqKioqKioqKioqKlxuXG5cdGZ1bmN0aW9uIF9ub3JtYWxpemVPcHRpb25EZWNsYXJhdGlvbnMoIG9wdGlvbkRlY2xhcmF0aW9ucyApIHtcblx0XHQvLyBjb252ZXJ0IG91ciBzaG9ydC1oYW5kIG9wdGlvbiBzeW50YXggKHdpdGggZXhjbGFtYXRpb24gbWFya3MsIGV0Yy4pXG5cdFx0Ly8gdG8gYSBzaW1wbGUgYXJyYXkgb2Ygc3RhbmRhcmQgb3B0aW9uIGRlY2xhcmF0aW9uIG9iamVjdHMuXG5cblx0XHR2YXIgbm9ybWFsaXplZE9wdGlvbkRlY2xhcmF0aW9ucyA9IHt9O1xuXG5cdFx0aWYoICEgXy5pc0FycmF5KCBvcHRpb25EZWNsYXJhdGlvbnMgKSApIHRocm93IG5ldyBFcnJvciggXCJPcHRpb24gZGVjbGFyYXRpb25zIG11c3QgYmUgYW4gYXJyYXkuXCIgKTtcblxuXHRcdF8uZWFjaCggb3B0aW9uRGVjbGFyYXRpb25zLCBmdW5jdGlvbiggdGhpc09wdGlvbkRlY2xhcmF0aW9uICkge1xuXHRcdFx0dmFyIHRoaXNPcHRpb25OYW1lLCB0aGlzT3B0aW9uUmVxdWlyZWQsIHRoaXNPcHRpb25EZWZhdWx0VmFsdWU7XG5cblx0XHRcdHRoaXNPcHRpb25SZXF1aXJlZCA9IGZhbHNlO1xuXHRcdFx0dGhpc09wdGlvbkRlZmF1bHRWYWx1ZSA9IHVuZGVmaW5lZDtcblxuXHRcdFx0aWYoIF8uaXNTdHJpbmcoIHRoaXNPcHRpb25EZWNsYXJhdGlvbiApIClcblx0XHRcdFx0dGhpc09wdGlvbk5hbWUgPSB0aGlzT3B0aW9uRGVjbGFyYXRpb247XG5cdFx0XHRlbHNlIGlmKCBfLmlzT2JqZWN0KCB0aGlzT3B0aW9uRGVjbGFyYXRpb24gKSApIHtcblx0XHRcdFx0dGhpc09wdGlvbk5hbWUgPSBfLmZpcnN0KCBfLmtleXMoIHRoaXNPcHRpb25EZWNsYXJhdGlvbiApICk7XG5cdFx0XHRcdGlmKCBfLmlzRnVuY3Rpb24oIHRoaXNPcHRpb25EZWNsYXJhdGlvblsgdGhpc09wdGlvbk5hbWUgXSApIClcblx0XHRcdFx0XHR0aGlzT3B0aW9uRGVmYXVsdFZhbHVlID0gdGhpc09wdGlvbkRlY2xhcmF0aW9uWyB0aGlzT3B0aW9uTmFtZSBdO1xuXHRcdFx0XHRlbHNlXG5cdFx0XHRcdFx0dGhpc09wdGlvbkRlZmF1bHRWYWx1ZSA9IF8uY2xvbmUoIHRoaXNPcHRpb25EZWNsYXJhdGlvblsgdGhpc09wdGlvbk5hbWUgXSApO1xuXHRcdFx0fVxuXHRcdFx0ZWxzZSB0aHJvdyBuZXcgRXJyb3IoIFwiRWFjaCBlbGVtZW50IGluIHRoZSBvcHRpb24gZGVjbGFyYXRpb25zIGFycmF5IG11c3QgYmUgZWl0aGVyIGEgc3RyaW5nIG9yIGFuIG9iamVjdC5cIiApO1xuXG5cdFx0XHRpZiggdGhpc09wdGlvbk5hbWVbIHRoaXNPcHRpb25OYW1lLmxlbmd0aCAtIDEgXSA9PT0gXCIhXCIgKSB7XG5cdFx0XHRcdHRoaXNPcHRpb25SZXF1aXJlZCA9IHRydWU7XG5cdFx0XHRcdHRoaXNPcHRpb25OYW1lID0gdGhpc09wdGlvbk5hbWUuc2xpY2UoIDAsIHRoaXNPcHRpb25OYW1lLmxlbmd0aCAtIDEgKTtcblx0XHRcdH1cblxuXHRcdFx0bm9ybWFsaXplZE9wdGlvbkRlY2xhcmF0aW9uc1sgdGhpc09wdGlvbk5hbWUgXSA9IG5vcm1hbGl6ZWRPcHRpb25EZWNsYXJhdGlvbnNbIHRoaXNPcHRpb25OYW1lIF0gfHwge307XG5cdFx0XHRub3JtYWxpemVkT3B0aW9uRGVjbGFyYXRpb25zWyB0aGlzT3B0aW9uTmFtZSBdLnJlcXVpcmVkID0gdGhpc09wdGlvblJlcXVpcmVkO1xuXHRcdFx0aWYoICEgXy5pc1VuZGVmaW5lZCggdGhpc09wdGlvbkRlZmF1bHRWYWx1ZSApICkgbm9ybWFsaXplZE9wdGlvbkRlY2xhcmF0aW9uc1sgdGhpc09wdGlvbk5hbWUgXS5kZWZhdWx0VmFsdWUgPSB0aGlzT3B0aW9uRGVmYXVsdFZhbHVlO1xuXHRcdH0gKTtcblxuXHRcdHJldHVybiBub3JtYWxpemVkT3B0aW9uRGVjbGFyYXRpb25zO1xuXHR9XG5cblxuXHQvLyBCYWNrYm9uZS5CYWJ5U2l0dGVyXG5cdC8vIC0tLS0tLS0tLS0tLS0tLS0tLS1cblx0Ly8gdjAuMC42XG5cdC8vXG5cdC8vIENvcHlyaWdodCAoYykyMDEzIERlcmljayBCYWlsZXksIE11dGVkIFNvbHV0aW9ucywgTExDLlxuXHQvLyBEaXN0cmlidXRlZCB1bmRlciBNSVQgbGljZW5zZVxuXHQvL1xuXHQvLyBodHRwOi8vZ2l0aHViLmNvbS9iYWJ5c2l0dGVyanMvYmFja2JvbmUuYmFieXNpdHRlclxuXG5cdC8vIEJhY2tib25lLkNoaWxkVmlld0NvbnRhaW5lclxuXHQvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblx0Ly9cblx0Ly8gUHJvdmlkZSBhIGNvbnRhaW5lciB0byBzdG9yZSwgcmV0cmlldmUgYW5kXG5cdC8vIHNodXQgZG93biBjaGlsZCB2aWV3cy5cblxuXHRDaGlsZFZpZXdDb250YWluZXIgPSAoZnVuY3Rpb24oQmFja2JvbmUsIF8pe1xuXG5cdFx0Ly8gQ29udGFpbmVyIENvbnN0cnVjdG9yXG5cdFx0Ly8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblx0XHR2YXIgQ29udGFpbmVyID0gZnVuY3Rpb24odmlld3Mpe1xuXHRcdFx0dGhpcy5fdmlld3MgPSB7fTtcblx0XHRcdHRoaXMuX2luZGV4QnlNb2RlbCA9IHt9O1xuXHRcdFx0dGhpcy5faW5kZXhCeUN1c3RvbSA9IHt9O1xuXHRcdFx0dGhpcy5fdXBkYXRlTGVuZ3RoKCk7XG5cblx0XHRcdF8uZWFjaCh2aWV3cywgdGhpcy5hZGQsIHRoaXMpO1xuXHRcdH07XG5cblx0XHQvLyBDb250YWluZXIgTWV0aG9kc1xuXHRcdC8vIC0tLS0tLS0tLS0tLS0tLS0tXG5cblx0XHRfLmV4dGVuZChDb250YWluZXIucHJvdG90eXBlLCB7XG5cblx0XHRcdC8vIEFkZCBhIHZpZXcgdG8gdGhpcyBjb250YWluZXIuIFN0b3JlcyB0aGUgdmlld1xuXHRcdFx0Ly8gYnkgYGNpZGAgYW5kIG1ha2VzIGl0IHNlYXJjaGFibGUgYnkgdGhlIG1vZGVsXG5cdFx0XHQvLyBjaWQgKGFuZCBtb2RlbCBpdHNlbGYpLiBPcHRpb25hbGx5IHNwZWNpZnlcblx0XHRcdC8vIGEgY3VzdG9tIGtleSB0byBzdG9yZSBhbiByZXRyaWV2ZSB0aGUgdmlldy5cblx0XHRcdGFkZDogZnVuY3Rpb24odmlldywgY3VzdG9tSW5kZXgpe1xuXHRcdFx0XHR2YXIgdmlld0NpZCA9IHZpZXcuY2lkO1xuXG5cdFx0XHRcdC8vIHN0b3JlIHRoZSB2aWV3XG5cdFx0XHRcdHRoaXMuX3ZpZXdzW3ZpZXdDaWRdID0gdmlldztcblxuXHRcdFx0XHQvLyBpbmRleCBpdCBieSBtb2RlbFxuXHRcdFx0XHRpZiAodmlldy5tb2RlbCl7XG5cdFx0XHRcdFx0dGhpcy5faW5kZXhCeU1vZGVsW3ZpZXcubW9kZWwuY2lkXSA9IHZpZXdDaWQ7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBpbmRleCBieSBjdXN0b21cblx0XHRcdFx0aWYgKGN1c3RvbUluZGV4KXtcblx0XHRcdFx0XHR0aGlzLl9pbmRleEJ5Q3VzdG9tW2N1c3RvbUluZGV4XSA9IHZpZXdDaWQ7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHR0aGlzLl91cGRhdGVMZW5ndGgoKTtcblx0XHRcdH0sXG5cblx0XHRcdC8vIEZpbmQgYSB2aWV3IGJ5IHRoZSBtb2RlbCB0aGF0IHdhcyBhdHRhY2hlZCB0b1xuXHRcdFx0Ly8gaXQuIFVzZXMgdGhlIG1vZGVsJ3MgYGNpZGAgdG8gZmluZCBpdC5cblx0XHRcdGZpbmRCeU1vZGVsOiBmdW5jdGlvbihtb2RlbCl7XG5cdFx0XHRcdHJldHVybiB0aGlzLmZpbmRCeU1vZGVsQ2lkKG1vZGVsLmNpZCk7XG5cdFx0XHR9LFxuXG5cdFx0XHQvLyBGaW5kIGEgdmlldyBieSB0aGUgYGNpZGAgb2YgdGhlIG1vZGVsIHRoYXQgd2FzIGF0dGFjaGVkIHRvXG5cdFx0XHQvLyBpdC4gVXNlcyB0aGUgbW9kZWwncyBgY2lkYCB0byBmaW5kIHRoZSB2aWV3IGBjaWRgIGFuZFxuXHRcdFx0Ly8gcmV0cmlldmUgdGhlIHZpZXcgdXNpbmcgaXQuXG5cdFx0XHRmaW5kQnlNb2RlbENpZDogZnVuY3Rpb24obW9kZWxDaWQpe1xuXHRcdFx0XHR2YXIgdmlld0NpZCA9IHRoaXMuX2luZGV4QnlNb2RlbFttb2RlbENpZF07XG5cdFx0XHRcdHJldHVybiB0aGlzLmZpbmRCeUNpZCh2aWV3Q2lkKTtcblx0XHRcdH0sXG5cblx0XHRcdC8vIEZpbmQgYSB2aWV3IGJ5IGEgY3VzdG9tIGluZGV4ZXIuXG5cdFx0XHRmaW5kQnlDdXN0b206IGZ1bmN0aW9uKGluZGV4KXtcblx0XHRcdFx0dmFyIHZpZXdDaWQgPSB0aGlzLl9pbmRleEJ5Q3VzdG9tW2luZGV4XTtcblx0XHRcdFx0cmV0dXJuIHRoaXMuZmluZEJ5Q2lkKHZpZXdDaWQpO1xuXHRcdFx0fSxcblxuXHRcdFx0Ly8gRmluZCBieSBpbmRleC4gVGhpcyBpcyBub3QgZ3VhcmFudGVlZCB0byBiZSBhXG5cdFx0XHQvLyBzdGFibGUgaW5kZXguXG5cdFx0XHRmaW5kQnlJbmRleDogZnVuY3Rpb24oaW5kZXgpe1xuXHRcdFx0XHRyZXR1cm4gXy52YWx1ZXModGhpcy5fdmlld3MpW2luZGV4XTtcblx0XHRcdH0sXG5cblx0XHRcdC8vIHJldHJpZXZlIGEgdmlldyBieSBpdCdzIGBjaWRgIGRpcmVjdGx5XG5cdFx0XHRmaW5kQnlDaWQ6IGZ1bmN0aW9uKGNpZCl7XG5cdFx0XHRcdHJldHVybiB0aGlzLl92aWV3c1tjaWRdO1xuXHRcdFx0fSxcblxuXHRcdFx0ZmluZEluZGV4QnlDaWQgOiBmdW5jdGlvbiggY2lkICkge1xuXHRcdFx0XHR2YXIgaW5kZXggPSAtMTtcblx0XHRcdFx0dmFyIHZpZXcgPSBfLmZpbmQoIHRoaXMuX3ZpZXdzLCBmdW5jdGlvbiAoIHZpZXcgKSB7XG5cdFx0XHRcdFx0aW5kZXgrKztcblx0XHRcdFx0XHRpZiggdmlldy5tb2RlbC5jaWQgPT0gY2lkIClcblx0XHRcdFx0XHRcdHJldHVybiB2aWV3O1xuXHRcdFx0XHR9ICk7XG5cdFx0XHRcdHJldHVybiAoIHZpZXcgKSA/IGluZGV4IDogLTE7XG5cdFx0XHR9LFxuXG5cdFx0XHQvLyBSZW1vdmUgYSB2aWV3XG5cdFx0XHRyZW1vdmU6IGZ1bmN0aW9uKHZpZXcpe1xuXHRcdFx0XHR2YXIgdmlld0NpZCA9IHZpZXcuY2lkO1xuXG5cdFx0XHRcdC8vIGRlbGV0ZSBtb2RlbCBpbmRleFxuXHRcdFx0XHRpZiAodmlldy5tb2RlbCl7XG5cdFx0XHRcdFx0ZGVsZXRlIHRoaXMuX2luZGV4QnlNb2RlbFt2aWV3Lm1vZGVsLmNpZF07XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBkZWxldGUgY3VzdG9tIGluZGV4XG5cdFx0XHRcdF8uYW55KHRoaXMuX2luZGV4QnlDdXN0b20sIGZ1bmN0aW9uKGNpZCwga2V5KSB7XG5cdFx0XHRcdFx0aWYgKGNpZCA9PT0gdmlld0NpZCkge1xuXHRcdFx0XHRcdFx0ZGVsZXRlIHRoaXMuX2luZGV4QnlDdXN0b21ba2V5XTtcblx0XHRcdFx0XHRcdHJldHVybiB0cnVlO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSwgdGhpcyk7XG5cblx0XHRcdFx0Ly8gcmVtb3ZlIHRoZSB2aWV3IGZyb20gdGhlIGNvbnRhaW5lclxuXHRcdFx0XHRkZWxldGUgdGhpcy5fdmlld3Nbdmlld0NpZF07XG5cblx0XHRcdFx0Ly8gdXBkYXRlIHRoZSBsZW5ndGhcblx0XHRcdFx0dGhpcy5fdXBkYXRlTGVuZ3RoKCk7XG5cdFx0XHR9LFxuXG5cdFx0XHQvLyBDYWxsIGEgbWV0aG9kIG9uIGV2ZXJ5IHZpZXcgaW4gdGhlIGNvbnRhaW5lcixcblx0XHRcdC8vIHBhc3NpbmcgcGFyYW1ldGVycyB0byB0aGUgY2FsbCBtZXRob2Qgb25lIGF0IGFcblx0XHRcdC8vIHRpbWUsIGxpa2UgYGZ1bmN0aW9uLmNhbGxgLlxuXHRcdFx0Y2FsbDogZnVuY3Rpb24obWV0aG9kKXtcblx0XHRcdFx0dGhpcy5hcHBseShtZXRob2QsIF8udGFpbChhcmd1bWVudHMpKTtcblx0XHRcdH0sXG5cblx0XHRcdC8vIEFwcGx5IGEgbWV0aG9kIG9uIGV2ZXJ5IHZpZXcgaW4gdGhlIGNvbnRhaW5lcixcblx0XHRcdC8vIHBhc3NpbmcgcGFyYW1ldGVycyB0byB0aGUgY2FsbCBtZXRob2Qgb25lIGF0IGFcblx0XHRcdC8vIHRpbWUsIGxpa2UgYGZ1bmN0aW9uLmFwcGx5YC5cblx0XHRcdGFwcGx5OiBmdW5jdGlvbihtZXRob2QsIGFyZ3Mpe1xuXHRcdFx0XHRfLmVhY2godGhpcy5fdmlld3MsIGZ1bmN0aW9uKHZpZXcpe1xuXHRcdFx0XHRcdGlmIChfLmlzRnVuY3Rpb24odmlld1ttZXRob2RdKSl7XG5cdFx0XHRcdFx0XHR2aWV3W21ldGhvZF0uYXBwbHkodmlldywgYXJncyB8fCBbXSk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9KTtcblx0XHRcdH0sXG5cblx0XHRcdC8vIFVwZGF0ZSB0aGUgYC5sZW5ndGhgIGF0dHJpYnV0ZSBvbiB0aGlzIGNvbnRhaW5lclxuXHRcdFx0X3VwZGF0ZUxlbmd0aDogZnVuY3Rpb24oKXtcblx0XHRcdFx0dGhpcy5sZW5ndGggPSBfLnNpemUodGhpcy5fdmlld3MpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXG5cdFx0Ly8gQm9ycm93aW5nIHRoaXMgY29kZSBmcm9tIEJhY2tib25lLkNvbGxlY3Rpb246XG5cdFx0Ly8gaHR0cDovL2JhY2tib25lanMub3JnL2RvY3MvYmFja2JvbmUuaHRtbCNzZWN0aW9uLTEwNlxuXHRcdC8vXG5cdFx0Ly8gTWl4IGluIG1ldGhvZHMgZnJvbSBVbmRlcnNjb3JlLCBmb3IgaXRlcmF0aW9uLCBhbmQgb3RoZXJcblx0XHQvLyBjb2xsZWN0aW9uIHJlbGF0ZWQgZmVhdHVyZXMuXG5cdFx0dmFyIG1ldGhvZHMgPSBbJ2ZvckVhY2gnLCAnZWFjaCcsICdtYXAnLCAnZmluZCcsICdkZXRlY3QnLCAnZmlsdGVyJyxcblx0XHRcdCAgICAgICAnc2VsZWN0JywgJ3JlamVjdCcsICdldmVyeScsICdhbGwnLCAnc29tZScsICdhbnknLCAnaW5jbHVkZScsXG5cdFx0XHQgICAgICAgJ2NvbnRhaW5zJywgJ2ludm9rZScsICd0b0FycmF5JywgJ2ZpcnN0JywgJ2luaXRpYWwnLCAncmVzdCcsXG5cdFx0XHQgICAgICAgJ2xhc3QnLCAnd2l0aG91dCcsICdpc0VtcHR5JywgJ3BsdWNrJ107XG5cblx0XHRfLmVhY2gobWV0aG9kcywgZnVuY3Rpb24obWV0aG9kKSB7XG5cdFx0XHRDb250YWluZXIucHJvdG90eXBlW21ldGhvZF0gPSBmdW5jdGlvbigpIHtcblx0XHRcdFx0dmFyIHZpZXdzID0gXy52YWx1ZXModGhpcy5fdmlld3MpO1xuXHRcdFx0XHR2YXIgYXJncyA9IFt2aWV3c10uY29uY2F0KF8udG9BcnJheShhcmd1bWVudHMpKTtcblx0XHRcdFx0cmV0dXJuIF9bbWV0aG9kXS5hcHBseShfLCBhcmdzKTtcblx0XHRcdH07XG5cdFx0fSk7XG5cblx0XHQvLyByZXR1cm4gdGhlIHB1YmxpYyBBUElcblx0XHRyZXR1cm4gQ29udGFpbmVyO1xuXHR9KShCYWNrYm9uZSwgXyk7XG5cblx0cmV0dXJuIEJhY2tib25lLkNvbGxlY3Rpb25WaWV3O1xufSApICk7XG5cbi8vXG4vLyBiYWNrYm9uZS50cmFja2l0IC0gMC4xLjBcbi8vIFRoZSBNSVQgTGljZW5zZVxuLy8gQ29weXJpZ2h0IChjKSAyMDEzIFRoZSBOZXcgWW9yayBUaW1lcywgQ01TIEdyb3VwLCBNYXR0aGV3IERlTGFtYm8gPGRlbGFtYm9AZ21haWwuY29tPlxuLy9cbihmdW5jdGlvbigpIHtcblxuXHQvLyBVbnNhdmVkIFJlY29yZCBLZWVwaW5nXG5cdC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXHQvLyBDb2xsZWN0aW9uIG9mIGFsbCBtb2RlbHMgaW4gYW4gYXBwIHRoYXQgaGF2ZSB1bnNhdmVkIGNoYW5nZXMuXG5cdHZhciB1bnNhdmVkTW9kZWxzID0gW107XG5cblx0Ly8gSWYgdGhlIGdpdmVuIG1vZGVsIGhhcyB1bnNhdmVkIGNoYW5nZXMgdGhlbiBhZGQgaXQgdG9cblx0Ly8gdGhlIGB1bnNhdmVkTW9kZWxzYCBjb2xsZWN0aW9uLCBvdGhlcndpc2UgcmVtb3ZlIGl0LlxuXHR2YXIgdXBkYXRlVW5zYXZlZE1vZGVscyA9IGZ1bmN0aW9uKG1vZGVsKSB7XG5cdFx0aWYgKCFfLmlzRW1wdHkobW9kZWwuX3Vuc2F2ZWRDaGFuZ2VzKSkge1xuXHRcdFx0aWYgKCFfLmZpbmRXaGVyZSh1bnNhdmVkTW9kZWxzLCB7Y2lkOm1vZGVsLmNpZH0pKSB1bnNhdmVkTW9kZWxzLnB1c2gobW9kZWwpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR1bnNhdmVkTW9kZWxzID0gXy5maWx0ZXIodW5zYXZlZE1vZGVscywgZnVuY3Rpb24obSkgeyByZXR1cm4gbW9kZWwuY2lkICE9IG0uY2lkOyB9KTtcblx0XHR9XG5cdH07XG5cblx0Ly8gVW5sb2FkIEhhbmRsZXJzXG5cdC8vIC0tLS0tLS0tLS0tLS0tLVxuXG5cdC8vIEhlbHBlciB3aGljaCByZXR1cm5zIGEgcHJvbXB0IG1lc3NhZ2UgZm9yIGFuIHVubG9hZCBoYW5kbGVyLlxuXHQvLyBVc2VzIHRoZSBnaXZlbiBmdW5jdGlvbiBuYW1lIChvbmUgb2YgdGhlIGNhbGxiYWNrIG5hbWVzXG5cdC8vIGZyb20gdGhlIGBtb2RlbC51bnNhdmVkYCBjb25maWd1cmF0aW9uIGhhc2gpIHRvIGV2YWx1YXRlXG5cdC8vIHdoZXRoZXIgYSBwcm9tcHQgaXMgbmVlZGVkL3JldHVybmVkLlxuXHR2YXIgZ2V0UHJvbXB0ID0gZnVuY3Rpb24oZm5OYW1lKSB7XG5cdFx0dmFyIHByb21wdCwgYXJncyA9IF8ucmVzdChhcmd1bWVudHMpO1xuXHRcdC8vIEV2YWx1YXRlIGFuZCByZXR1cm4gYSBib29sZWFuIHJlc3VsdC4gVGhlIGdpdmVuIGBmbmAgbWF5IGJlIGFcblx0XHQvLyBib29sZWFuIHZhbHVlLCBhIGZ1bmN0aW9uLCBvciB0aGUgbmFtZSBvZiBhIGZ1bmN0aW9uIG9uIHRoZSBtb2RlbC5cblx0XHR2YXIgZXZhbHVhdGVNb2RlbEZuID0gZnVuY3Rpb24obW9kZWwsIGZuKSB7XG5cdFx0XHRpZiAoXy5pc0Jvb2xlYW4oZm4pKSByZXR1cm4gZm47XG5cdFx0XHRyZXR1cm4gKF8uaXNTdHJpbmcoZm4pID8gbW9kZWxbZm5dIDogZm4pLmFwcGx5KG1vZGVsLCBhcmdzKTtcblx0XHR9O1xuXHRcdF8uZWFjaCh1bnNhdmVkTW9kZWxzLCBmdW5jdGlvbihtb2RlbCkge1xuXHRcdFx0aWYgKCFwcm9tcHQgJiYgZXZhbHVhdGVNb2RlbEZuKG1vZGVsLCBtb2RlbC5fdW5zYXZlZENvbmZpZ1tmbk5hbWVdKSlcblx0XHRcdFx0cHJvbXB0ID0gbW9kZWwuX3Vuc2F2ZWRDb25maWcucHJvbXB0O1xuXHRcdH0pO1xuXHRcdHJldHVybiBwcm9tcHQ7XG5cdH07XG5cblx0Ly8gV3JhcCBCYWNrYm9uZS5IaXN0b3J5Lm5hdmlnYXRlIHNvIHRoYXQgaW4tYXBwIHJvdXRpbmdcblx0Ly8gKGByb3V0ZXIubmF2aWdhdGUoJy9wYXRoJylgKSBjYW4gYmUgaW50ZXJjZXB0ZWQgd2l0aCBhXG5cdC8vIGNvbmZpcm1hdGlvbiBpZiB0aGVyZSBhcmUgYW55IHVuc2F2ZWQgbW9kZWxzLlxuXHRCYWNrYm9uZS5IaXN0b3J5LnByb3RvdHlwZS5uYXZpZ2F0ZSA9IF8ud3JhcChCYWNrYm9uZS5IaXN0b3J5LnByb3RvdHlwZS5uYXZpZ2F0ZSwgZnVuY3Rpb24ob2xkTmF2LCBmcmFnbWVudCwgb3B0aW9ucykge1xuXHRcdHZhciBwcm9tcHQgPSBnZXRQcm9tcHQoJ3VubG9hZFJvdXRlclByb21wdCcsIGZyYWdtZW50LCBvcHRpb25zKTtcblx0XHRpZiAocHJvbXB0KSB7XG5cdFx0XHRpZiAoY29uZmlybShwcm9tcHQgKyAnIFxcblxcbkFyZSB5b3Ugc3VyZSB5b3Ugd2FudCB0byBsZWF2ZSB0aGlzIHBhZ2U/JykpIHtcblx0XHRcdFx0b2xkTmF2LmNhbGwodGhpcywgZnJhZ21lbnQsIG9wdGlvbnMpO1xuXHRcdFx0fVxuXHRcdH0gZWxzZSB7XG5cdFx0XHRvbGROYXYuY2FsbCh0aGlzLCBmcmFnbWVudCwgb3B0aW9ucyk7XG5cdFx0fVxuXHR9KTtcblxuXHQvLyBDcmVhdGUgYSBicm93c2VyIHVubG9hZCBoYW5kbGVyIHdoaWNoIGlzIHRyaWdnZXJlZFxuXHQvLyBvbiB0aGUgcmVmcmVzaCwgYmFjaywgb3IgZm9yd2FyZCBidXR0b24uXG5cdHdpbmRvdy5vbmJlZm9yZXVubG9hZCA9IGZ1bmN0aW9uKGUpIHtcblx0XHRyZXR1cm4gZ2V0UHJvbXB0KCd1bmxvYWRXaW5kb3dQcm9tcHQnLCBlKTtcblx0fTtcblxuXHQvLyBCYWNrYm9uZS5Nb2RlbCBBUElcblx0Ly8gLS0tLS0tLS0tLS0tLS0tLS0tXG5cblx0Xy5leHRlbmQoQmFja2JvbmUuTW9kZWwucHJvdG90eXBlLCB7XG5cblx0XHR1bnNhdmVkOiB7fSxcblx0XHRfdHJhY2tpbmdDaGFuZ2VzOiBmYWxzZSxcblx0XHRfb3JpZ2luYWxBdHRyczoge30sXG5cdFx0X3Vuc2F2ZWRDaGFuZ2VzOiB7fSxcblxuXHRcdC8vIE9wdCBpbiB0byB0cmFja2luZyBhdHRyaWJ1dGUgY2hhbmdlc1xuXHRcdC8vIGJldHdlZW4gc2F2ZXMuXG5cdFx0c3RhcnRUcmFja2luZzogZnVuY3Rpb24oKSB7XG5cdFx0XHR0aGlzLl91bnNhdmVkQ29uZmlnID0gXy5leHRlbmQoe30sIHtcblx0XHRcdFx0cHJvbXB0OiAnWW91IGhhdmUgdW5zYXZlZCBjaGFuZ2VzIScsXG5cdFx0XHRcdHVubG9hZFJvdXRlclByb21wdDogZmFsc2UsXG5cdFx0XHRcdHVubG9hZFdpbmRvd1Byb21wdDogZmFsc2Vcblx0XHRcdH0sIHRoaXMudW5zYXZlZCB8fCB7fSk7XG5cdFx0XHR0aGlzLl90cmFja2luZ0NoYW5nZXMgPSB0cnVlO1xuXHRcdFx0dGhpcy5fcmVzZXRUcmFja2luZygpO1xuXHRcdFx0dGhpcy5fdHJpZ2dlclVuc2F2ZWRDaGFuZ2VzKCk7XG5cdFx0XHRyZXR1cm4gdGhpcztcblx0XHR9LFxuXG5cdFx0Ly8gUmVzZXRzIHRoZSBkZWZhdWx0IHRyYWNraW5nIHZhbHVlc1xuXHRcdC8vIGFuZCBzdG9wcyB0cmFja2luZyBhdHRyaWJ1dGUgY2hhbmdlcy5cblx0XHRzdG9wVHJhY2tpbmc6IGZ1bmN0aW9uKCkge1xuXHRcdFx0dGhpcy5fdHJhY2tpbmdDaGFuZ2VzID0gZmFsc2U7XG5cdFx0XHR0aGlzLl9vcmlnaW5hbEF0dHJzID0ge307XG5cdFx0XHR0aGlzLl91bnNhdmVkQ2hhbmdlcyA9IHt9O1xuXHRcdFx0dGhpcy5fdHJpZ2dlclVuc2F2ZWRDaGFuZ2VzKCk7XG5cdFx0XHRyZXR1cm4gdGhpcztcblx0XHR9LFxuXG5cdFx0Ly8gR2V0cyByaWQgb2YgYWNjcnVlZCBjaGFuZ2VzIGFuZFxuXHRcdC8vIHJlc2V0cyBzdGF0ZS5cblx0XHRyZXN0YXJ0VHJhY2tpbmc6IGZ1bmN0aW9uKCkge1xuXHRcdFx0dGhpcy5fcmVzZXRUcmFja2luZygpO1xuXHRcdFx0dGhpcy5fdHJpZ2dlclVuc2F2ZWRDaGFuZ2VzKCk7XG5cdFx0XHRyZXR1cm4gdGhpcztcblx0XHR9LFxuXG5cdFx0Ly8gUmVzdG9yZXMgdGhpcyBtb2RlbCdzIGF0dHJpYnV0ZXMgdG9cblx0XHQvLyB0aGVpciBvcmlnaW5hbCB2YWx1ZXMgc2luY2UgdHJhY2tpbmdcblx0XHQvLyBzdGFydGVkLCB0aGUgbGFzdCBzYXZlLCBvciBsYXN0IHJlc3RhcnQuXG5cdFx0cmVzZXRBdHRyaWJ1dGVzOiBmdW5jdGlvbigpIHtcblx0XHRcdGlmICghdGhpcy5fdHJhY2tpbmdDaGFuZ2VzKSByZXR1cm47XG5cdFx0XHR0aGlzLmF0dHJpYnV0ZXMgPSB0aGlzLl9vcmlnaW5hbEF0dHJzO1xuXHRcdFx0dGhpcy5fcmVzZXRUcmFja2luZygpO1xuXHRcdFx0dGhpcy5fdHJpZ2dlclVuc2F2ZWRDaGFuZ2VzKCk7XG5cdFx0XHRyZXR1cm4gdGhpcztcblx0XHR9LFxuXG5cdFx0Ly8gU3ltbWV0cmljIHRvIEJhY2tib25lJ3MgYG1vZGVsLmNoYW5nZWRBdHRyaWJ1dGVzKClgLFxuXHRcdC8vIGV4Y2VwdCB0aGF0IHRoaXMgcmV0dXJucyBhIGhhc2ggb2YgdGhlIG1vZGVsJ3MgYXR0cmlidXRlcyB0aGF0XG5cdFx0Ly8gaGF2ZSBjaGFuZ2VkIHNpbmNlIHRoZSBsYXN0IHNhdmUsIG9yIGBmYWxzZWAgaWYgdGhlcmUgYXJlIG5vbmUuXG5cdFx0Ly8gTGlrZSBgY2hhbmdlZEF0dHJpYnV0ZXNgLCBhbiBleHRlcm5hbCBhdHRyaWJ1dGVzIGhhc2ggY2FuIGJlXG5cdFx0Ly8gcGFzc2VkIGluLCByZXR1cm5pbmcgdGhlIGF0dHJpYnV0ZXMgaW4gdGhhdCBoYXNoIHdoaWNoIGRpZmZlclxuXHRcdC8vIGZyb20gdGhlIG1vZGVsLlxuXHRcdHVuc2F2ZWRBdHRyaWJ1dGVzOiBmdW5jdGlvbihhdHRycykge1xuXHRcdFx0aWYgKCFhdHRycykgcmV0dXJuIF8uaXNFbXB0eSh0aGlzLl91bnNhdmVkQ2hhbmdlcykgPyBmYWxzZSA6IF8uY2xvbmUodGhpcy5fdW5zYXZlZENoYW5nZXMpO1xuXHRcdFx0dmFyIHZhbCwgY2hhbmdlZCA9IGZhbHNlLCBvbGQgPSB0aGlzLl91bnNhdmVkQ2hhbmdlcztcblx0XHRcdGZvciAodmFyIGF0dHIgaW4gYXR0cnMpIHtcblx0XHRcdFx0aWYgKF8uaXNFcXVhbChvbGRbYXR0cl0sICh2YWwgPSBhdHRyc1thdHRyXSkpKSBjb250aW51ZTtcblx0XHRcdFx0KGNoYW5nZWQgfHwgKGNoYW5nZWQgPSB7fSkpW2F0dHJdID0gdmFsO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIGNoYW5nZWQ7XG5cdFx0fSxcblxuXHRcdF9yZXNldFRyYWNraW5nOiBmdW5jdGlvbigpIHtcblx0XHRcdHRoaXMuX29yaWdpbmFsQXR0cnMgPSBfLmNsb25lKHRoaXMuYXR0cmlidXRlcyk7XG5cdFx0XHR0aGlzLl91bnNhdmVkQ2hhbmdlcyA9IHt9O1xuXHRcdH0sXG5cblx0XHQvLyBUcmlnZ2VyIGFuIGB1bnNhdmVkQ2hhbmdlc2AgZXZlbnQgb24gdGhpcyBtb2RlbCxcblx0XHQvLyBzdXBwbHlpbmcgdGhlIHJlc3VsdCBvZiB3aGV0aGVyIHRoZXJlIGFyZSB1bnNhdmVkXG5cdFx0Ly8gY2hhbmdlcyBhbmQgYSBjaGFuZ2VkIGF0dHJpYnV0ZXMgaGFzaC5cblx0XHRfdHJpZ2dlclVuc2F2ZWRDaGFuZ2VzOiBmdW5jdGlvbigpIHtcblx0XHRcdHRoaXMudHJpZ2dlcigndW5zYXZlZENoYW5nZXMnLCAhXy5pc0VtcHR5KHRoaXMuX3Vuc2F2ZWRDaGFuZ2VzKSwgXy5jbG9uZSh0aGlzLl91bnNhdmVkQ2hhbmdlcykpO1xuXHRcdFx0aWYgKHRoaXMudW5zYXZlZCkgdXBkYXRlVW5zYXZlZE1vZGVscyh0aGlzKTtcblx0XHR9XG5cdH0pO1xuXG5cdC8vIFdyYXAgYG1vZGVsLnNldCgpYCBhbmQgdXBkYXRlIHRoZSBpbnRlcm5hbFxuXHQvLyB1bnNhdmVkIGNoYW5nZXMgcmVjb3JkIGtlZXBpbmcuXG5cdEJhY2tib25lLk1vZGVsLnByb3RvdHlwZS5zZXQgPSBfLndyYXAoQmFja2JvbmUuTW9kZWwucHJvdG90eXBlLnNldCwgZnVuY3Rpb24ob2xkU2V0LCBrZXksIHZhbCwgb3B0aW9ucykge1xuXHRcdHZhciBhdHRycywgcmV0O1xuXHRcdGlmIChrZXkgPT0gbnVsbCkgcmV0dXJuIHRoaXM7XG5cdFx0Ly8gSGFuZGxlIGJvdGggYFwia2V5XCIsIHZhbHVlYCBhbmQgYHtrZXk6IHZhbHVlfWAgLXN0eWxlIGFyZ3VtZW50cy5cblx0XHRpZiAodHlwZW9mIGtleSA9PT0gJ29iamVjdCcpIHtcblx0XHRcdGF0dHJzID0ga2V5O1xuXHRcdFx0b3B0aW9ucyA9IHZhbDtcblx0XHR9IGVsc2Uge1xuXHRcdFx0KGF0dHJzID0ge30pW2tleV0gPSB2YWw7XG5cdFx0fVxuXHRcdG9wdGlvbnMgfHwgKG9wdGlvbnMgPSB7fSk7XG5cblx0XHQvLyBEZWxlZ2F0ZSB0byBCYWNrYm9uZSdzIHNldC5cblx0XHRyZXQgPSBvbGRTZXQuY2FsbCh0aGlzLCBhdHRycywgb3B0aW9ucyk7XG5cblx0XHRpZiAodGhpcy5fdHJhY2tpbmdDaGFuZ2VzICYmICFvcHRpb25zLnNpbGVudCkge1xuXHRcdFx0Xy5lYWNoKGF0dHJzLCBfLmJpbmQoZnVuY3Rpb24odmFsLCBrZXkpIHtcblx0XHRcdFx0aWYgKF8uaXNFcXVhbCh0aGlzLl9vcmlnaW5hbEF0dHJzW2tleV0sIHZhbCkpXG5cdFx0XHRcdFx0ZGVsZXRlIHRoaXMuX3Vuc2F2ZWRDaGFuZ2VzW2tleV07XG5cdFx0XHRcdGVsc2Vcblx0XHRcdFx0XHR0aGlzLl91bnNhdmVkQ2hhbmdlc1trZXldID0gdmFsO1xuXHRcdFx0fSwgdGhpcykpO1xuXHRcdFx0dGhpcy5fdHJpZ2dlclVuc2F2ZWRDaGFuZ2VzKCk7XG5cdFx0fVxuXHRcdHJldHVybiByZXQ7XG5cdH0pO1xuXG5cdC8vIEludGVyY2VwdCBgbW9kZWwuc2F2ZSgpYCBhbmQgcmVzZXQgdHJhY2tpbmcvdW5zYXZlZFxuXHQvLyBjaGFuZ2VzIGlmIGl0IHdhcyBzdWNjZXNzZnVsLlxuXHRCYWNrYm9uZS5zeW5jID0gXy53cmFwKEJhY2tib25lLnN5bmMsIGZ1bmN0aW9uKG9sZFN5bmMsIG1ldGhvZCwgbW9kZWwsIG9wdGlvbnMpIHtcblx0XHRvcHRpb25zIHx8IChvcHRpb25zID0ge30pO1xuXG5cdFx0aWYgKG1ldGhvZCA9PSAndXBkYXRlJykge1xuXHRcdFx0b3B0aW9ucy5zdWNjZXNzID0gXy53cmFwKG9wdGlvbnMuc3VjY2VzcywgXy5iaW5kKGZ1bmN0aW9uKG9sZFN1Y2Nlc3MsIGRhdGEsIHRleHRTdGF0dXMsIGpxWEhSKSB7XG5cdFx0XHRcdHZhciByZXQ7XG5cdFx0XHRcdGlmIChvbGRTdWNjZXNzKSByZXQgPSBvbGRTdWNjZXNzLmNhbGwodGhpcywgZGF0YSwgdGV4dFN0YXR1cywganFYSFIpO1xuXHRcdFx0XHRpZiAobW9kZWwuX3RyYWNraW5nQ2hhbmdlcykge1xuXHRcdFx0XHRcdG1vZGVsLl9yZXNldFRyYWNraW5nKCk7XG5cdFx0XHRcdFx0bW9kZWwuX3RyaWdnZXJVbnNhdmVkQ2hhbmdlcygpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHJldHVybiByZXQ7XG5cdFx0XHR9LCB0aGlzKSk7XG5cdFx0fVxuXHRcdHJldHVybiBvbGRTeW5jKG1ldGhvZCwgbW9kZWwsIG9wdGlvbnMpO1xuXHR9KTtcblxufSkoKTtcbmRlZmluZShcInZlbmRvci9iYWNrYm9uZS50cmFja2l0XCIsIGZ1bmN0aW9uKCl7fSk7XG5cbi8qKlxuICogSW1hZ2Ugb2JqZWN0IG1vZGVsIGZvciB1c2UgaW4gdmFyaW91cyBtb2RlbHMgZm9yIHRoZSAnaW1hZ2UnIGF0dHJpYnV0ZVxuICogQHNpbmNlICAgIDMuMTYuMFxuICogQHZlcnNpb24gIDMuMTYuMFxuICovXG5kZWZpbmUoICdNb2RlbHMvSW1hZ2UnLFtdLCBmdW5jdGlvbigpIHtcblxuXHRyZXR1cm4gQmFja2JvbmUuTW9kZWwuZXh0ZW5kKCB7XG5cblx0XHRkZWZhdWx0czoge1xuXHRcdFx0ZW5hYmxlZDogJ25vJyxcblx0XHRcdGlkOiAnJyxcblx0XHRcdHNpemU6ICdmdWxsJyxcblx0XHRcdHNyYzogJycsXG5cdFx0fSxcblxuXHRcdGluaXRpYWxpemU6IGZ1bmN0aW9uKCkge1xuXHRcdFx0dGhpcy5zdGFydFRyYWNraW5nKCk7XG5cdFx0fSxcblxuXHR9ICk7XG59ICk7XG5cbi8qKlxuICogTW9kZWwgcmVsYXRpb25zaGlwcyBtaXhpblxuICogQHNpbmNlICAgIDMuMTYuMFxuICogQHZlcnNpb24gIDMuMTYuMTFcbiAqL1xuZGVmaW5lKCAnTW9kZWxzL19SZWxhdGlvbnNoaXBzJyxbXSwgZnVuY3Rpb24oKSB7XG5cblx0cmV0dXJuIHtcblxuXHRcdC8qKlxuXHRcdCAqIERlZmF1bHQgcmVsYXRpb25zaGlwIHNldHRpbmdzIG9iamVjdFxuXHRcdCAqIEB0eXBlICB7T2JqZWN0fVxuXHRcdCAqL1xuXHRcdHJlbGF0aW9uc2hpcF9kZWZhdWx0czoge1xuXHRcdFx0cGFyZW50OiB7fSxcblx0XHRcdGNoaWxkcmVuOiB7fSxcblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogUmVsYXRpb25zaGlwIHNldHRpbmdzIG9iamVjdFxuXHRcdCAqIFNob3VsZCBiZSBvdmVycmlkZW4gaW4gdGhlIG1vZGVsXG5cdFx0ICogQHR5cGUgIHtPYmplY3R9XG5cdFx0ICovXG5cdFx0cmVsYXRpb25zaGlwczoge30sXG5cblx0XHQvKipcblx0XHQgKiBJbml0aWFsaXplIGFsbCBwYXJlbnQgYW5kIGNoaWxkIHJlbGF0aW9uc2hpcHNcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0aW5pdF9yZWxhdGlvbnNoaXBzOiBmdW5jdGlvbiggb3B0aW9ucyApIHtcblxuXHRcdFx0dmFyIHJlbHMgPSB0aGlzLmdldF9yZWxhdGlvbnNoaXBzKCk7XG5cblx0XHRcdC8vIGluaXRpYWxpemUgcGFyZW50IHJlbGF4dGlvbnNoaXBzXG5cdFx0XHQvLyB1c2VmdWwgd2hlbiBhZGRpbmcgYSBtb2RlbCB0byBlbnN1cmUgcGFyZW50IGlzIGluaXRpYWxpemVkXG5cdFx0XHRpZiAoIHJlbHMucGFyZW50ICYmIG9wdGlvbnMgJiYgb3B0aW9ucy5wYXJlbnQgKSB7XG5cdFx0XHRcdHRoaXMuc2V0X3BhcmVudCggb3B0aW9ucy5wYXJlbnQgKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gaW5pdGlhbGl6ZSBhbGwgY2hpbGRyZW4gcmVsYXRpb25zaGlwc1xuXHRcdFx0Xy5lYWNoKCByZWxzLmNoaWxkcmVuLCBmdW5jdGlvbiggY2hpbGRfZGF0YSwgY2hpbGRfa2V5ICkge1xuXG5cdFx0XHRcdGlmICggISBjaGlsZF9kYXRhLmNvbmRpdGlvbmFsIHx8IHRydWUgPT09IGNoaWxkX2RhdGEuY29uZGl0aW9uYWwoIHRoaXMgKSApIHtcblxuXHRcdFx0XHRcdHZhciBjaGlsZF92YWwgPSB0aGlzLmdldCggY2hpbGRfa2V5ICksXG5cdFx0XHRcdFx0XHRjaGlsZDtcblxuXHRcdFx0XHRcdGlmICggY2hpbGRfZGF0YS5sb29rdXAgKSB7XG5cdFx0XHRcdFx0XHRjaGlsZCA9IGNoaWxkX2RhdGEubG9va3VwKCBjaGlsZF92YWwgKTtcblx0XHRcdFx0XHR9IGVsc2UgaWYgKCAnbW9kZWwnID09PSBjaGlsZF9kYXRhLnR5cGUgKSB7XG5cdFx0XHRcdFx0XHRjaGlsZCA9IHdpbmRvdy5sbG1zX2J1aWxkZXIuY29uc3RydWN0LmdldF9tb2RlbCggY2hpbGRfZGF0YS5jbGFzcywgY2hpbGRfdmFsICk7XG5cdFx0XHRcdFx0fSBlbHNlIGlmICggJ2NvbGxlY3Rpb24nID09PSBjaGlsZF9kYXRhLnR5cGUgKSB7XG5cdFx0XHRcdFx0XHRjaGlsZCA9IHdpbmRvdy5sbG1zX2J1aWxkZXIuY29uc3RydWN0LmdldF9jb2xsZWN0aW9uKCBjaGlsZF9kYXRhLmNsYXNzLCBjaGlsZF92YWwgKTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHR0aGlzLnNldCggY2hpbGRfa2V5LCBjaGlsZCApO1xuXG5cdFx0XHRcdFx0Ly8gaWYgdGhlIGNoaWxkIGRlZmluZXMgYSBwYXJlbnQsIHNhdmUgYSByZWZlcmVuY2UgdG8gdGhlIHBhcmVudCBvbiB0aGUgY2hpbGRcblx0XHRcdFx0XHRpZiAoICdtb2RlbCcgPT09IGNoaWxkX2RhdGEudHlwZSApIHtcblx0XHRcdFx0XHRcdHRoaXMuX21heWJlX3NldF9wYXJlbnRfcmVmZXJlbmNlKCBjaGlsZCApO1xuXG5cdFx0XHRcdFx0Ly8gc2F2ZSBkaXJlY3RseSB0byBlYWNoIG1vZGVsIGluIHRoZSBjb2xsZWN0aW9uXG5cdFx0XHRcdFx0fSBlbHNlIGlmICggJ2NvbGxlY3Rpb24nID09PSBjaGlsZF9kYXRhLnR5cGUgKSB7XG5cblx0XHRcdFx0XHRcdGNoaWxkLnBhcmVudCA9IHRoaXM7XG5cdFx0XHRcdFx0XHRjaGlsZC5lYWNoKCBmdW5jdGlvbiggY2hpbGRfbW9kZWwgKSB7XG5cblx0XHRcdFx0XHRcdFx0dGhpcy5fbWF5YmVfc2V0X3BhcmVudF9yZWZlcmVuY2UoIGNoaWxkX21vZGVsICk7XG5cblx0XHRcdFx0XHRcdH0sIHRoaXMgKTtcblxuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHR9XG5cblx0XHRcdH0sIHRoaXMgKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBSZXRyaWV2ZSB0aGUgcHJvcGVydHkgbmFtZXMgZm9yIGFsbCBjaGlsZHJlbiBvZiB0aGUgbW9kZWxcblx0XHQgKiBAcmV0dXJuICAgYXJyYXlcblx0XHQgKiBAc2luY2UgICAgMy4xNi4xMVxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjExXG5cdFx0ICovXG5cdFx0Z2V0X2NoaWxkX3Byb3BzOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0dmFyIHByb3BzID0gW107XG5cblx0XHRcdF8uZWFjaCggdGhpcy5nZXRfcmVsYXRpb25zaGlwcygpLmNoaWxkcmVuLCBmdW5jdGlvbiggZGF0YSwga2V5ICkge1xuXG5cdFx0XHRcdGlmICggISBkYXRhLmNvbmRpdGlvbmFsIHx8IHRydWUgPT09IGRhdGEuY29uZGl0aW9uYWwoIHRoaXMgKSApIHtcblx0XHRcdFx0XHRwcm9wcy5wdXNoKCBrZXkgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHR9LCB0aGlzICk7XG5cblx0XHRcdHJldHVybiBwcm9wcztcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBSZXRyaWV2ZSB0aGUgbW9kZWwncyBwYXJlbnQgKGlmIHNldClcblx0XHQgKiBAcmV0dXJuICAgb2JqfGZhbHNlXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRnZXRfcGFyZW50OiBmdW5jdGlvbigpIHtcblxuXHRcdFx0dmFyIHJlbHMgPSB0aGlzLmdldF9yZWxhdGlvbnNoaXBzKCk7XG5cblx0XHRcdGlmICggcmVscy5wYXJlbnQgKSB7XG5cdFx0XHRcdHJldHVybiByZWxzLnBhcmVudC5yZWZlcmVuY2U7XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBmYWxzZTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBSZXRyaWV2ZSByZWxhdGlvbnNoaXBzIGZvciB0aGUgbW9kZWxcblx0XHQgKiBFeHRlbmRzIHdpdGggZGVmYXVsdHNcblx0XHQgKiBAcmV0dXJuICAgb2JqXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRnZXRfcmVsYXRpb25zaGlwczogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHJldHVybiAkLmV4dGVuZCggdHJ1ZSwgdGhpcy5yZWxhdGlvbnNoaXBzLCB0aGlzLnJlbGF0aW9uc2hpcF9kZWZhdWx0cyApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFNldCB0aGUgcGFyZW50IHJlZmVyZW5jZSBmb3IgdGhlIGdpdmVuIG1vZGVsXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIG9iaiAgIHBhcmVudCBtb2RlbCBvYmpcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0c2V0X3BhcmVudDogZnVuY3Rpb24oIG9iaiApIHtcblx0XHRcdHRoaXMucmVsYXRpb25zaGlwcy5wYXJlbnQucmVmZXJlbmNlID0gb2JqO1xuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBTZXQgdXAgdGhlIHBhcmVudCByZWxhdGlvbnNoaXBzIGZvciBxdWFsaWZ5aW5nIGNoaWxkcmVuIGR1cmluZyByZWxhdGlvbnNoaXAgaW5pdGlhbGl6YXRpb25cblx0XHQgKiBAcGFyYW0gICAgb2JqICAgbW9kZWwgIGNoaWxkIG1vZGVsXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdF9tYXliZV9zZXRfcGFyZW50X3JlZmVyZW5jZTogZnVuY3Rpb24oIG1vZGVsICkge1xuXG5cdFx0XHRpZiAoICEgbW9kZWwgfHwgISBtb2RlbC5nZXRfcmVsYXRpb25zaGlwcyApIHtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXHRcdFx0dmFyIHJlbHMgPSBtb2RlbC5nZXRfcmVsYXRpb25zaGlwcygpO1xuXHRcdFx0aWYgKCByZWxzLnBhcmVudCAmJiByZWxzLnBhcmVudC5tb2RlbCA9PT0gdGhpcy5nZXQoICd0eXBlJyApICkge1xuXHRcdFx0XHRtb2RlbC5zZXRfcGFyZW50KCB0aGlzICk7XG5cdFx0XHR9XG5cblx0XHR9LFxuXG5cdH07XG5cbn0gKTtcblxuLyoqXG4gKiBRdWl6IFF1ZXN0aW9uIENob2ljZVxuICogQHNpbmNlICAgIDMuMTYuMFxuICogQHZlcnNpb24gIDMuMTYuMFxuICovXG5kZWZpbmUoICdNb2RlbHMvUXVlc3Rpb25DaG9pY2UnLFsgJ01vZGVscy9JbWFnZScsICdNb2RlbHMvX1JlbGF0aW9uc2hpcHMnIF0sIGZ1bmN0aW9uKCBJbWFnZSwgUmVsYXRpb25zaGlwcyApIHtcblxuXHRyZXR1cm4gQmFja2JvbmUuTW9kZWwuZXh0ZW5kKCBfLmRlZmF1bHRzKCB7XG5cblx0XHQvKipcblx0XHQgKiBNb2RlbCByZWxhdGlvbnNoaXBzXG5cdFx0ICogQHR5cGUgIHtPYmplY3R9XG5cdFx0ICovXG5cdFx0cmVsYXRpb25zaGlwczoge1xuXHRcdFx0cGFyZW50OiB7XG5cdFx0XHRcdG1vZGVsOiAnbGxtc19xdWVzdGlvbicsXG5cdFx0XHRcdHR5cGU6ICdtb2RlbCcsXG5cdFx0XHR9LFxuXHRcdFx0Y2hpbGRyZW46IHtcblx0XHRcdFx0Y2hvaWNlOiB7XG5cdFx0XHRcdFx0Y29uZGl0aW9uYWw6IGZ1bmN0aW9uKCBtb2RlbCApIHtcblx0XHRcdFx0XHRcdHJldHVybiAoICdpbWFnZScgPT09IG1vZGVsLmdldCggJ2Nob2ljZV90eXBlJyApICk7XG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRjbGFzczogJ0ltYWdlJyxcblx0XHRcdFx0XHRtb2RlbDogJ2ltYWdlJyxcblx0XHRcdFx0XHR0eXBlOiAnbW9kZWwnLFxuXHRcdFx0XHR9LFxuXHRcdFx0fSxcblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogTW9kZWwgZGVmYXVsdHNcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0ZGVmYXVsdHM6IGZ1bmN0aW9uKCkge1xuXHRcdFx0cmV0dXJuIHtcblx0XHRcdFx0aWQ6IF8udW5pcXVlSWQoICd0ZW1wXycgKSxcblx0XHRcdFx0Y2hvaWNlOiAnJyxcblx0XHRcdFx0Y2hvaWNlX3R5cGU6ICd0ZXh0Jyxcblx0XHRcdFx0Y29ycmVjdDogZmFsc2UsXG5cdFx0XHRcdG1hcmtlcjogJ0EnLFxuXHRcdFx0XHRxdWVzdGlvbl9pZDogJycsXG5cdFx0XHRcdHR5cGU6ICdjaG9pY2UnLFxuXHRcdFx0fVxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBJbml0aWFsaXplclxuXHRcdCAqIEBwYXJhbSAgICBvYmogICBkYXRhICAgICBvYmplY3Qgb2YgbW9kZWwgYXR0cmlidXRlc1xuXHRcdCAqIEBwYXJhbSAgICBvYmogICBvcHRpb25zICBhZGRpdGlvbmFsIG9wdGlvbnNcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0aW5pdGlhbGl6ZTogZnVuY3Rpb24oIGRhdGEsIG9wdGlvbnMgKSB7XG5cblx0XHRcdHRoaXMuc3RhcnRUcmFja2luZygpO1xuXHRcdFx0dGhpcy5pbml0X3JlbGF0aW9uc2hpcHMoIG9wdGlvbnMgKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBSZXRyaWV2ZSB0aGUgY2hvaWNlJ3MgcGFyZW50IHF1ZXN0aW9uXG5cdFx0ICogQHJldHVybiAgIG9ialxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0Z2V0X3BhcmVudDogZnVuY3Rpb24oKSB7XG5cdFx0XHRyZXR1cm4gdGhpcy5jb2xsZWN0aW9uLnBhcmVudDtcblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogUmV0cmlldmUgdGhlIElEIHVzZWQgd2hlbiB0cmFzaGluZyB0aGUgbW9kZWxcblx0XHQgKiBAcmV0dXJuICAgc3RyaW5nXG5cdFx0ICogQHNpbmNlICAgIDMuMTcuMVxuXHRcdCAqIEB2ZXJzaW9uICAzLjE3LjFcblx0XHQgKi9cblx0XHRnZXRfdHJhc2hfaWQ6IGZ1bmN0aW9uKCkge1xuXHRcdFx0cmV0dXJuIHRoaXMuZ2V0KCAncXVlc3Rpb25faWQnICkgKyAnOicgKyB0aGlzLmdldCggJ2lkJyApO1xuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBEZXRlcm1pbmUgaWYgXCJzZWxlY3Rpb25cIiBpcyBlbmFibGVkIGZvciB0aGUgcXVlc3Rpb24gdHlwZVxuXHRcdCAqIENob2ljZSB0eXBlIHF1ZXN0aW9ucyBhcmUgc2VsZWN0YWJsZSBieSByZW9yZGVyIHR5cGUgcXVlc3Rpb25zIGFyZSBub3QgYnV0IHN0aWxsIHVzZSBjaG9pY2VzXG5cdFx0ICogQHJldHVybiAgIHtCb29sZWFufVxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0aXNfc2VsZWN0YWJsZTogZnVuY3Rpb24oKSB7XG5cdFx0XHRyZXR1cm4gdGhpcy5nZXRfcGFyZW50KCkuZ2V0KCAncXVlc3Rpb25fdHlwZScgKS5nZXRfY2hvaWNlX3NlbGVjdGFibGUoKTtcblx0XHR9LFxuXG5cdH0sIFJlbGF0aW9uc2hpcHMgKSApO1xuXG59ICk7XG5cbi8qKlxuICogUXVlc3Rpb24gQ2hvaWNlIENvbGxlY3Rpb25cbiAqIEBzaW5jZSAgICAzLjE2LjBcbiAqIEB2ZXJzaW9uICAzLjE2LjBcbiAqL1xuZGVmaW5lKCAnQ29sbGVjdGlvbnMvUXVlc3Rpb25DaG9pY2VzJyxbICdNb2RlbHMvUXVlc3Rpb25DaG9pY2UnIF0sIGZ1bmN0aW9uKCBtb2RlbCApIHtcblxuXHRyZXR1cm4gQmFja2JvbmUuQ29sbGVjdGlvbi5leHRlbmQoIHtcblxuXHRcdC8qKlxuXHRcdCAqIE1vZGVsIGZvciBjb2xsZWN0aW9uIGl0ZW1zXG5cdFx0ICogQHR5cGUgIG9ialxuXHRcdCAqL1xuXHRcdG1vZGVsOiBtb2RlbCxcblxuXHRcdGluaXRpYWxpemU6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHQvLyByZW9yZGVyIGNhbGxlZCBieSBRdWVzdGlvbkxpc3QgdmlldyB3aGVuIHNvcnRhYmxlIGRyb3BzIG9jY3VyXG5cdFx0XHR0aGlzLm9uKCAncmVvcmRlcicsIHRoaXMudXBkYXRlX29yZGVyICk7XG5cblx0XHRcdC8vIHdoZW4gYSBjaG9pY2UgaXMgYWRkZWQgb3IgcmVtb3ZlZCwgdXBkYXRlIG9yZGVyXG5cdFx0XHR0aGlzLm9uKCAnYWRkJywgdGhpcy51cGRhdGVfb3JkZXIgKTtcblx0XHRcdHRoaXMub24oICdyZW1vdmUnLCB0aGlzLnVwZGF0ZV9vcmRlciApO1xuXG5cdFx0XHQvLyB3aGVuIGEgY2hvaWNlIGlzIGFkZGVkIG9yIHJlbW92ZSwgZW5zdXJlIG1pbi9tYXggY29ycmVjdCBhbnN3ZXJzIGV4aXN0XG5cdFx0XHR0aGlzLm9uKCAnYWRkJywgdGhpcy51cGRhdGVfY29ycmVjdCApO1xuXHRcdFx0dGhpcy5vbiggJ3JlbW92ZScsIHRoaXMudXBkYXRlX2NvcnJlY3QgKTtcblxuXHRcdFx0Ly8gd2hlbiBhIGNob2ljZSBpcyB0b2dnbGVkLCBlbnN1cmUgbWluL21heCBjb3JyZWN0IGV4aXN0XG5cdFx0XHR0aGlzLm9uKCAnY29ycmVjdC11cGRhdGUnLCB0aGlzLnVwZGF0ZV9jb3JyZWN0ICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogUmV0cmlldmUgdGhlIG51bWJlciBvZiBjb3JyZWN0IGNob2ljZXMgaW4gdGhlIGNvbGxlY3Rpb25cblx0XHQgKiBAcmV0dXJuICAgaW50XG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRjb3VudF9jb3JyZWN0OiBmdW5jdGlvbigpIHtcblxuXHRcdFx0cmV0dXJuIF8uc2l6ZSggdGhpcy5nZXRfY29ycmVjdCgpICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogUmV0cmlldmUgdGhlIGNvbGxlY3Rpb24gcmVkdWNlZCB0byBvbmx5IGNvcnJlY3QgY2hvaWNlc1xuXHRcdCAqIEByZXR1cm4gICBvYmpcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGdldF9jb3JyZWN0OiBmdW5jdGlvbigpIHtcblx0XHRcdHJldHVybiB0aGlzLmZpbHRlciggZnVuY3Rpb24oIGNob2ljZSApIHtcblx0XHRcdFx0cmV0dXJuIGNob2ljZS5nZXQoICdjb3JyZWN0JyApO1xuXHRcdFx0fSApO1xuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBFbnN1cmUgbWluL21heCBjb3JyZWN0IGNob2ljZXMgZXhpc3QgaW4gdGhlIGNvbGxlY3Rpb24gYmFzZWQgb24gdGhlIHF1ZXN0aW9uJ3Mgc2V0dGluZ3Ncblx0XHQgKiBAcGFyYW0gICAgb2JqICAgICAgY2hvaWNlICBtb2RlbCBvZiB0aGUgY2hvaWNlIHRoYXQgd2FzIHRvZ2dsZWRcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0dXBkYXRlX2NvcnJlY3Q6IGZ1bmN0aW9uKCBjaG9pY2UgKSB7XG5cblx0XHRcdGlmICggISB0aGlzLnBhcmVudC5nZXQoICdxdWVzdGlvbl90eXBlJyApLmdldF9jaG9pY2Vfc2VsZWN0YWJsZSgpICkge1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cblx0XHRcdHZhciBzaWJsaW5ncyA9IHRoaXMud2l0aG91dCggY2hvaWNlICksIC8vIGV4Y2x1ZGUgdGhlIHRvZ2dsZWQgY2hvaWNlIGZyb20gbG9vcHNcblx0XHRcdFx0cXVlc3Rpb24gPSB0aGlzLnBhcmVudDtcblxuXHRcdFx0Ly8gaWYgbXVsdGlwbGUgY2hvaWNlcyBhcmVuJ3QgZW5hYmxlZCB0dXJuIGFsbCBvdGhlciBjaG9pY2VzIHRvIGluY29ycmVjdFxuXHRcdFx0aWYgKCAnbm8nID09PSBxdWVzdGlvbi5nZXQoICdtdWx0aV9jaG9pY2VzJyApICkge1xuXHRcdFx0XHRfLmVhY2goIHNpYmxpbmdzLCBmdW5jdGlvbiggbW9kZWwgKSB7XG5cdFx0XHRcdFx0bW9kZWwuc2V0KCAnY29ycmVjdCcsIGZhbHNlICk7XG5cdFx0XHRcdH0gKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gaWYgd2UgZG9uJ3QgaGF2ZSBhIHNpbmdsZSBjb3JyZXQgYW5zd2VyICYgdGhlIHF1ZXN0aW9uIGhhcyBwb2ludHMsIHNldCBvbmVcblx0XHRcdC8vIGFsbG93cyB1c2VycyB0byBjcmVhdGUgcXVpenplcyAvIHF1ZXN0aW9ucyB3aXRoIG5vIHBvaW50cyBhbmQgdGhlcmVmb3JlIG5vIGNvcnJlY3QgYW5zd2VycyBhcmUgYWxsb3dlZFxuXHRcdFx0aWYgKCAwID09PSB0aGlzLmNvdW50X2NvcnJlY3QoKSAmJiBxdWVzdGlvbi5nZXQoICdwb2ludHMnICkgPiAwICkge1xuXHRcdFx0XHR2YXIgbW9kZWxzID0gMSA9PT0gdGhpcy5zaXplKCkgPyB0aGlzLm1vZGVscyA6IHNpYmxpbmdzO1xuXHRcdFx0XHRfLmZpcnN0KCBtb2RlbHMgKS5zZXQoICdjb3JyZWN0JywgdHJ1ZSApO1xuXHRcdFx0fVxuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFVwZGF0ZSB0aGUgbWFya2VyIGF0dHIgb2YgZWFjaCBjaG9pY2UgaW4gdGhlIGxpc3QgdG8gcmVmbGVjdCB0aGUgb3JkZXIgb2YgdGhlIGNvbGxlY3Rpb25cblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0dXBkYXRlX29yZGVyOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0dmFyIHNlbGYgPSB0aGlzLFxuXHRcdFx0XHRxdWVzdGlvbiA9IHRoaXMucGFyZW50O1xuXG5cdFx0XHR0aGlzLmVhY2goIGZ1bmN0aW9uKCBjaG9pY2UgKSB7XG5cdFx0XHRcdGNob2ljZS5zZXQoICdtYXJrZXInLCBxdWVzdGlvbi5nZXQoICdxdWVzdGlvbl90eXBlJyApLmdldF9jaG9pY2VfbWFya2VycygpWyBzZWxmLmluZGV4T2YoIGNob2ljZSApIF0gKTtcblx0XHRcdH0gKTtcblxuXHRcdH0sXG5cblx0fSApO1xuXG59ICk7XG5cbi8qKlxuICogUXVpeiBRdWVzdGlvbiBUeXBlXG4gKiBAc2luY2UgICAgMy4xNi4wXG4gKiBAdmVyc2lvbiAgMy4xNi4wXG4gKi9cbmRlZmluZSggJ01vZGVscy9RdWVzdGlvblR5cGUnLFtdLCBmdW5jdGlvbigpIHtcblxuXHRyZXR1cm4gQmFja2JvbmUuTW9kZWwuZXh0ZW5kKCB7XG5cblx0XHQvKipcblx0XHQgKiBHZXQgbW9kZWwgZGVmYXVsdCBhdHRyaWJ1dGVzXG5cdFx0ICogQHJldHVybiAgIG9ialxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0ZGVmYXVsdHM6IGZ1bmN0aW9uKCkge1xuXHRcdFx0cmV0dXJuIHtcblx0XHRcdFx0Y2hvaWNlczogZmFsc2UsXG5cdFx0XHRcdGNsYXJpZmljYXRpb25zOiB0cnVlLFxuXHRcdFx0XHRkZWZhdWx0X2Nob2ljZXM6IFtdLFxuXHRcdFx0XHRkZXNjcmlwdGlvbjogdHJ1ZSxcblx0XHRcdFx0aWNvbjogJ3F1ZXN0aW9uJyxcblx0XHRcdFx0aWQ6ICdnZW5lcmljJyxcblx0XHRcdFx0aW1hZ2U6IHRydWUsXG5cdFx0XHRcdGtleXdvcmRzOiBbXSxcblx0XHRcdFx0bmFtZTogJ0dlbmVyaWMnLFxuXHRcdFx0XHRwbGFjZWhvbGRlcjogJycsXG5cdFx0XHRcdHBvaW50czogdHJ1ZSxcblx0XHRcdFx0dmlkZW86IHRydWUsXG5cdFx0XHR9XG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFJldHJpZXZlIGFuIGFycmF5IG9mIGtleXdvcmRzIGZvciB0aGUgcXVlc3Rpb24gdHlwZVxuXHRcdCAqIFVzZWQgZm9yIGZpbHRlcmluZyBxdWVzdGlvbnMgYnkgc2VhcmNoIHRlcm0gaW4gdGhlIHF1aXogYnVpbGRlclxuXHRcdCAqIEByZXR1cm4gICBhcnJheVxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0Z2V0X2tleXdvcmRzOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0dmFyIG5hbWUgPSB0aGlzLmdldCggJ25hbWUnICksXG5cdFx0XHRcdHdvcmRzID0gWyBuYW1lIF07XG5cblx0XHRcdHJldHVybiB3b3Jkcy5jb25jYXQoIHRoaXMuZ2V0KCAna2V5d29yZHMnICkgKS5jb25jYXQoIG5hbWUuc3BsaXQoICcgJyApICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogR2V0IG1hcmtlciBhcnJheSBmb3IgdGhlIHF1ZXN0aW9uIGNob2ljZXNcblx0XHQgKiBAcmV0dXJuICAgYXJyYXlcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGdldF9jaG9pY2VfbWFya2VyczogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHJldHVybiB0aGlzLl9nZXRfY2hvaWNlX29wdGlvbiggJ21hcmtlcnMnICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogRGV0ZXJtaW5lIGlmIHRoZSBxdWVzdGlvbidzIGNob2ljZXMgYXJlIHNlbGVjdGFibGVcblx0XHQgKiBAcmV0dXJuICAgYm9vbFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0Z2V0X2Nob2ljZV9zZWxlY3RhYmxlOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0cmV0dXJuIHRoaXMuX2dldF9jaG9pY2Vfb3B0aW9uKCAnc2VsZWN0YWJsZScgKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBHZXQgdGhlIGNob2ljZSB0eXBlICh0ZXh0LGltYWdlKVxuXHRcdCAqIEByZXR1cm4gICBzdHJpbmdcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGdldF9jaG9pY2VfdHlwZTogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHJldHVybiB0aGlzLl9nZXRfY2hvaWNlX29wdGlvbiggJ3R5cGUnICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogUmV0cmlldmUgZGVmaW5lZCBtaW4uIGNob2ljZXNcblx0XHQgKiBAcmV0dXJuICAgaW50XG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRnZXRfbWluX2Nob2ljZXM6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHRyZXR1cm4gdGhpcy5fZ2V0X2Nob2ljZV9vcHRpb24oICdtaW4nICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogR2V0IHR5cGUtZGVmaW5lZCBtYXggY2hvaWNlc1xuXHRcdCAqIEByZXR1cm4gICBzdHJpbmdcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGdldF9tYXhfY2hvaWNlczogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHJldHVybiB0aGlzLl9nZXRfY2hvaWNlX29wdGlvbiggJ21heCcgKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBEZXRlcm1pbmUgaWYgbXVsdGktY2hvaWNlIHNlbGVjdGlvbiBpcyBlbmFibGVkXG5cdFx0ICogQHJldHVybiAgIGJvb2xcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGdldF9tdWx0aV9jaG9pY2VzOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0dmFyIGNob2ljZXMgPSB0aGlzLmdldCggJ2Nob2ljZXMnICk7XG5cblx0XHRcdGlmICggISBjaG9pY2VzICApIHtcblx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gdGhpcy5fZ2V0X2Nob2ljZV9vcHRpb24oICdtdWx0aScgKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBSZXRyaWV2ZSBkYXRhIGZyb20gdGhlIHR5cGUncyBcImNob2ljZXNcIiBhdHRyaWJ1dGVcblx0XHQgKiBBbGxvd3MgcXVpY2sgaGFuZGxpbmcgb2YgdHlwZXMgd2l0aCBubyBjaG9pY2UgZGVmaW5pdGlvbnMgdy9vIGFkZGl0aW9uYWwgY2hlY2tzXG5cdFx0ICogQHBhcmFtICAgIHN0cmluZyAgIG9wdGlvbiAgbmFtZSBvZiB0aGUgY2hvaWNlIG9wdGlvbiB0byByZXRyaWV2ZVxuXHRcdCAqIEByZXR1cm4gICBtaXhlZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0X2dldF9jaG9pY2Vfb3B0aW9uOiBmdW5jdGlvbiggb3B0aW9uICkge1xuXG5cdFx0XHR2YXIgY2hvaWNlcyA9IHRoaXMuZ2V0KCAnY2hvaWNlcycgKTtcblxuXHRcdFx0aWYgKCAhIGNob2ljZXMgfHwgISBjaG9pY2VzWyBvcHRpb24gXSApIHtcblx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gY2hvaWNlc1sgb3B0aW9uIF07XG5cblx0XHR9LFxuXG5cdH0gKTtcblxufSApO1xuXG4vKipcbiAqIFF1aXogUXVlc3Rpb25cbiAqIEBzaW5jZSAgICAzLjE2LjBcbiAqIEB2ZXJzaW9uICAzLjE2LjBcbiAqL1xuZGVmaW5lKCAnTW9kZWxzL1F1ZXN0aW9uJyxbXG5cdFx0J01vZGVscy9JbWFnZScsXG5cdFx0J0NvbGxlY3Rpb25zL1F1ZXN0aW9ucycsXG5cdFx0J0NvbGxlY3Rpb25zL1F1ZXN0aW9uQ2hvaWNlcycsXG5cdFx0J01vZGVscy9RdWVzdGlvblR5cGUnLFxuXHRcdCdNb2RlbHMvX1JlbGF0aW9uc2hpcHMnXG5cdF0sIGZ1bmN0aW9uKFxuXHRcdEltYWdlLFxuXHRcdFF1ZXN0aW9ucyxcblx0XHRRdWVzdGlvbkNob2ljZXMsXG5cdFx0UXVlc3Rpb25UeXBlLFxuXHRcdFJlbGF0aW9uc2hpcHNcblx0KSB7XG5cblx0cmV0dXJuIEJhY2tib25lLk1vZGVsLmV4dGVuZCggXy5kZWZhdWx0cygge1xuXG5cdFx0LyoqXG5cdFx0ICogTW9kZWwgcmVsYXRpb25zaGlwc1xuXHRcdCAqIEB0eXBlICB7T2JqZWN0fVxuXHRcdCAqL1xuXHRcdHJlbGF0aW9uc2hpcHM6IHtcblx0XHRcdHBhcmVudDoge1xuXHRcdFx0XHRtb2RlbDogJ2xsbXNfcXVpeicsXG5cdFx0XHRcdHR5cGU6ICdtb2RlbCcsXG5cdFx0XHR9LFxuXHRcdFx0Y2hpbGRyZW46IHtcblx0XHRcdFx0Y2hvaWNlczoge1xuXHRcdFx0XHRcdGNsYXNzOiAnUXVlc3Rpb25DaG9pY2VzJyxcblx0XHRcdFx0XHRtb2RlbDogJ2Nob2ljZScsXG5cdFx0XHRcdFx0dHlwZTogJ2NvbGxlY3Rpb24nLFxuXHRcdFx0XHR9LFxuXHRcdFx0XHRpbWFnZToge1xuXHRcdFx0XHRcdGNsYXNzOiAnSW1hZ2UnLFxuXHRcdFx0XHRcdG1vZGVsOiAnaW1hZ2UnLFxuXHRcdFx0XHRcdHR5cGU6ICdtb2RlbCcsXG5cdFx0XHRcdH0sXG5cdFx0XHRcdHF1ZXN0aW9uczoge1xuXHRcdFx0XHRcdGNsYXNzOiAnUXVlc3Rpb25zJyxcblx0XHRcdFx0XHRjb25kaXRpb25hbDogZnVuY3Rpb24oIG1vZGVsICkge1xuXHRcdFx0XHRcdFx0dmFyIHR5cGUgPSBtb2RlbC5nZXQoICdxdWVzdGlvbl90eXBlJyApLFxuXHRcdFx0XHRcdFx0XHR0eXBlX2lkID0gXy5pc1N0cmluZyggdHlwZSApID8gdHlwZSA6IHR5cGUuZ2V0KCAnaWQnICk7XG5cdFx0XHRcdFx0XHRyZXR1cm4gKCAnZ3JvdXAnID09PSB0eXBlX2lkICk7XG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRtb2RlbDogJ2xsbXNfcXVlc3Rpb24nLFxuXHRcdFx0XHRcdHR5cGU6ICdjb2xsZWN0aW9uJyxcblx0XHRcdFx0fSxcblx0XHRcdFx0cXVlc3Rpb25fdHlwZToge1xuXHRcdFx0XHRcdGNsYXNzOiAnUXVlc3Rpb25UeXBlJyxcblx0XHRcdFx0XHRsb29rdXA6IGZ1bmN0aW9uKCB2YWwgKSB7XG5cdFx0XHRcdFx0XHRpZiAoIF8uaXNTdHJpbmcoIHZhbCApICkge1xuXHRcdFx0XHRcdFx0XHRyZXR1cm4gd2luZG93LmxsbXNfYnVpbGRlci5xdWVzdGlvbnMuZ2V0KCB2YWwgKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdHJldHVybiB2YWw7XG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRtb2RlbDogJ3F1ZXN0aW9uX3R5cGUnLFxuXHRcdFx0XHRcdHR5cGU6ICdtb2RlbCcsXG5cdFx0XHRcdH0sXG5cdFx0XHR9XG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIE1vZGVsIGRlZmF1bHRzXG5cdFx0ICogQHJldHVybiAgIG9ialxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0ZGVmYXVsdHM6IGZ1bmN0aW9uKCkge1xuXHRcdFx0cmV0dXJuIHtcblx0XHRcdFx0aWQ6IF8udW5pcXVlSWQoICd0ZW1wXycgKSxcblx0XHRcdFx0Y2hvaWNlczogW10sXG5cdFx0XHRcdGNvbnRlbnQ6ICcnLFxuXHRcdFx0XHRkZXNjcmlwdGlvbl9lbmFibGVkOiAnbm8nLFxuXHRcdFx0XHRpbWFnZToge30sXG5cdFx0XHRcdG11bHRpX2Nob2ljZXM6ICdubycsXG5cdFx0XHRcdG1lbnVfb3JkZXI6IDEsXG5cdFx0XHRcdHBvaW50czogMSxcblx0XHRcdFx0cXVlc3Rpb25fdHlwZTogJ2dlbmVyaWMnLFxuXHRcdFx0XHRxdWVzdGlvbnM6IFtdLCAvLyBmb3IgcXVlc3Rpb24gZ3JvdXBzXG5cdFx0XHRcdHBhcmVudF9pZDogJycsXG5cdFx0XHRcdHRpdGxlOiAnJyxcblx0XHRcdFx0dHlwZTogJ2xsbXNfcXVlc3Rpb24nLFxuXHRcdFx0XHR2aWRlb19lbmFibGVkOiAnbm8nLFxuXHRcdFx0XHR2aWRlb19zcmM6ICcnLFxuXG5cdFx0XHRcdF9leHBhbmRlZDogZmFsc2UsXG5cdFx0XHR9XG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIEluaXRpYWxpemVyXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIGRhdGEgICAgIG9iamVjdCBvZiBkYXRhIGZvciB0aGUgbW9kZWxcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgb3B0aW9ucyAgYWRkaXRpb25hbCBvcHRpb25zXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGluaXRpYWxpemU6IGZ1bmN0aW9uKCBkYXRhLCBvcHRpb25zICkge1xuXG5cdFx0XHR2YXIgc2VsZiA9IHRoaXM7XG5cblx0XHRcdHRoaXMuc3RhcnRUcmFja2luZygpO1xuXHRcdFx0dGhpcy5pbml0X3JlbGF0aW9uc2hpcHMoIG9wdGlvbnMgKTtcblxuXHRcdFx0aWYgKCBmYWxzZSAhPT0gdGhpcy5nZXQoICdxdWVzdGlvbl90eXBlJyApLmNob2ljZXMgKSB7XG5cblx0XHRcdFx0dGhpcy5fZW5zdXJlX21pbl9jaG9pY2VzKCk7XG5cblx0XHRcdFx0Ly8gd2hlbiBhIGNob2ljZSBpcyByZW1vdmVkLCBtYXliZSBhZGQgYmFjayBzb21lIGRlZmF1bHRzIHNvIHdlIGFsd2F5cyBoYXZlIHRoZSBtaW5pbXVtXG5cdFx0XHRcdHRoaXMubGlzdGVuVG8oIHRoaXMuZ2V0KCAnY2hvaWNlcycgKSwgJ3JlbW92ZScsIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdC8vIG5ldyBpdG1lcyBhcmUgYWRkZWQgYXQgaW5kZXggMCB3aGVuIHRoZXJlJ3Mgb25seSAxIGl0ZW0gaW4gdGhlIGNvbGxlY3Rpb24sIG5vdCBzdXJlIHdoeSBleGFjdGx5Li4uXG5cdFx0XHRcdFx0c2V0VGltZW91dCggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHRzZWxmLl9lbnN1cmVfbWluX2Nob2ljZXMoKTtcblx0XHRcdFx0XHR9LCAwICk7XG5cdFx0XHRcdH0gKTtcblxuXHRcdFx0fVxuXG5cdFx0XHQvLyBlbnN1cmUgcXVlc3Rpb24gdHlwZXMgdGhhdCBkb24ndCBzdXBwb3J0IHBvaW50cyBkb24ndCByZWNvcmQgZGVmYXVsdCAxIHBvaW50IGluIGRhdGFiYXNlXG5cdFx0XHRpZiAoICEgdGhpcy5nZXQoICdxdWVzdGlvbl90eXBlJyApLmdldCggJ3BvaW50cycgKSApIHtcblx0XHRcdFx0dGhpcy5zZXQoICdwb2ludHMnLCAwICk7XG5cdFx0XHR9XG5cblx0XHRcdF8uZGVsYXkoIGZ1bmN0aW9uKCBzZWxmICkge1xuXHRcdFx0XHRzZWxmLm9uKCAnY2hhbmdlOnBvaW50cycsIHNlbGYuZ2V0X3BhcmVudCgpLnVwZGF0ZV9wb2ludHMsIHNlbGYuZ2V0X3BhcmVudCgpICk7XG5cdFx0XHR9LCAxLCB0aGlzICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogQWRkIGEgbmV3IHF1ZXN0aW9uIGNob2ljZVxuXHRcdCAqIEBwYXJhbSAgICBvYmogICBkYXRhICAgICBvYmplY3Qgb2YgY2hvaWNlIGRhdGFcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgb3B0aW9ucyAgYWRkaXRpb25hbCBvcHRpb25zXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRhZGRfY2hvaWNlOiBmdW5jdGlvbiggZGF0YSwgb3B0aW9ucyApIHtcblxuXHRcdFx0dmFyIG1heCA9IHRoaXMuZ2V0KCAncXVlc3Rpb25fdHlwZScgKS5nZXRfbWF4X2Nob2ljZXMoKTtcblx0XHRcdGlmICggdGhpcy5nZXQoICdjaG9pY2VzJyApLnNpemUoKSA+PSBtYXggKSB7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblxuXHRcdFx0ZGF0YSA9IGRhdGEgfHwge307XG5cdFx0XHRvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcblxuXHRcdFx0ZGF0YS5jaG9pY2VfdHlwZSA9IHRoaXMuZ2V0KCAncXVlc3Rpb25fdHlwZScgKS5nZXRfY2hvaWNlX3R5cGUoKTtcblx0XHRcdGRhdGEucXVlc3Rpb25faWQgPSB0aGlzLmdldCggJ2lkJyApO1xuXHRcdFx0b3B0aW9ucy5wYXJlbnQgPSB0aGlzO1xuXG5cdFx0XHR2YXIgY2hvaWNlID0gdGhpcy5nZXQoICdjaG9pY2VzJyApLmFkZCggZGF0YSwgb3B0aW9ucyApO1xuXG5cdFx0XHRCYWNrYm9uZS5wdWJTdWIudHJpZ2dlciggJ3F1ZXN0aW9uLWFkZC1jaG9pY2UnLCBjaG9pY2UsIHRoaXMgKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBDb2xsYXBzZSBxdWVzdGlvbl90eXBlIGF0dHJpYnV0ZSBkdXJpbmcgZnVsbCBzeW5jcyB0byBzYXZlIHRvIGRhdGFiYXNlXG5cdFx0ICogTm90IG5lZWRlZCBiZWNhdXNlIHF1ZXN0aW9uIHR5cGVzIGNhbm5vdCBiZSBhZGp1c3RlZCBhZnRlciBxdWVzdGlvbiBjcmVhdGlvblxuXHRcdCAqIENhbGxlZCBmcm9tIHN5bmMgY29udHJvbGxlclxuXHRcdCAqIEBwYXJhbSAgICBvYmogICAgICBhdHRzICAgICAgIGZsYXQgb2JqZWN0IG9mIGF0dHJpYnV0ZXMgdG8gYmUgc2F2ZWQgdG8gZGJcblx0XHQgKiBAcGFyYW0gICAgc3RyaW5nICAgc3luY190eXBlICBmdWxsIG9yIHBhcnRpYWxcblx0XHQgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZ1bGwgaW5kaWNhdGVzIGEgZm9yY2UgcmVzeW5jIG9yIHRoYXQgdGhlIG1vZGVsIGlzbid0IHBlcnNpc3RlZCB5ZXRcblx0XHQgKiBAcmV0dXJuICAgb2JqXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRiZWZvcmVfc2F2ZTogZnVuY3Rpb24oIGF0dHMsIHN5bmNfdHlwZSAgKSB7XG5cdFx0XHRpZiAoICdmdWxsJyA9PT0gc3luY190eXBlICkge1xuXHRcdFx0XHRhdHRzLnF1ZXN0aW9uX3R5cGUgPSB0aGlzLmdldCggJ3F1ZXN0aW9uX3R5cGUnICkuZ2V0KCAnaWQnICk7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gYXR0cztcblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogUmV0cmlldmUgdGhlIG1vZGVsJ3MgcGFyZW50IChpZiBzZXQpXG5cdFx0ICogQHJldHVybiAgIG9ianxmYWxzZVxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0Z2V0X3BhcmVudDogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHZhciByZWxzID0gdGhpcy5nZXRfcmVsYXRpb25zaGlwcygpO1xuXG5cdFx0XHRpZiAoIHJlbHMucGFyZW50ICkge1xuXHRcdFx0XHRpZiAoIHRoaXMuY29sbGVjdGlvbiAmJiB0aGlzLmNvbGxlY3Rpb24ucGFyZW50ICkge1xuXHRcdFx0XHRcdHJldHVybiB0aGlzLmNvbGxlY3Rpb24ucGFyZW50O1xuXHRcdFx0XHR9IGVsc2UgaWYgKCByZWxzLnBhcmVudC5yZWZlcmVuY2UgKSB7XG5cdFx0XHRcdFx0cmV0dXJuIHJlbHMucGFyZW50LnJlZmVyZW5jZTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogR2V0cyB0aGUgaW5kZXggb2YgdGhlIHF1ZXN0aW9uIHdpdGhpbiBpdCdzIHBhcmVudFxuXHRcdCAqIFF1ZXN0aW9uIG51bWJlcnMgc2tpcCBjb250ZW50IGVsZW1lbnRzXG5cdFx0ICogJiBjb250ZW50IGVsZW1lbnRzIHNraXAgcXVlc3Rpb25zXG5cdFx0ICogQHJldHVybiAgIGludFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0Z2V0X3R5cGVfaW5kZXg6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHQvLyBjdXJyZW50IG1vZGVscyB0eXBlLCB1c2VkIHRvIGNoZWNrIHRoZSBwcmVkaWNhdGUgaW4gdGhlIGZpbHRlciBmdW5jdGlvbiBiZWxvd1xuXHRcdFx0dmFyIGN1cnJfdHlwZSA9IHRoaXMuZ2V0KCAncXVlc3Rpb25fdHlwZScgKS5nZXQoICdpZCcgKSxcblx0XHRcdFx0cXVlc3Rpb25zO1xuXG5cdFx0XHRxdWVzdGlvbnMgPSB0aGlzLmNvbGxlY3Rpb24uZmlsdGVyKCBmdW5jdGlvbiggcXVlc3Rpb24gKSB7XG5cblx0XHRcdFx0dmFyIHR5cGUgPSBxdWVzdGlvbi5nZXQoICdxdWVzdGlvbl90eXBlJyApLmdldCggJ2lkJyApO1xuXG5cdFx0XHRcdC8vIGlmIGN1cnJlbnQgbW9kZWwgaXMgbm90IGNvbnRlbnQsIHJldHVybiBhbGwgbm9uLWNvbnRlbnQgcXVlc3Rpb25zXG5cdFx0XHRcdGlmICggY3Vycl90eXBlICE9PSAnY29udGVudCcgKSB7XG5cdFx0XHRcdFx0cmV0dXJuICggJ2NvbnRlbnQnICE9PSB0eXBlICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBjdXJyZW50IG1vZGVsIGlzIGNvbnRlbnQsIHJldHVybiBvbmx5IGNvbnRlbnQgcXVlc3Rpb25zXG5cdFx0XHRcdHJldHVybiAnY29udGVudCcgPT09IHR5cGU7XG5cblx0XHRcdH0gKTtcblxuXHRcdFx0cmV0dXJuIHF1ZXN0aW9ucy5pbmRleE9mKCB0aGlzICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogR2V0cyBpdGVyYXRvciBmb3IgdGhlIGdpdmVuIHR5cGVcblx0XHQgKiBRdWVzdGlvbnMgdXNlIG51bWJlcnMgYW5kIGNvbnRlbnQgdXNlcyBhbHBoYWJldFxuXHRcdCAqIEByZXR1cm4gICBtaXhlZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0Z2V0X3R5cGVfaXRlcmF0b3I6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHR2YXIgaW5kZXggPSB0aGlzLmdldF90eXBlX2luZGV4KCk7XG5cblx0XHRcdGlmICggLTEgPT09IGluZGV4ICkge1xuXHRcdFx0XHRyZXR1cm4gJyc7XG5cdFx0XHR9XG5cblx0XHRcdGlmICggJ2NvbnRlbnQnID09PSB0aGlzLmdldCggJ3F1ZXN0aW9uX3R5cGUnICkuZ2V0KCAnaWQnICkgKSB7XG5cdFx0XHRcdHZhciBhbHBoYWJldCA9ICdBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWicuc3BsaXQoICcnICk7XG5cdFx0XHRcdHJldHVybiBhbHBoYWJldFsgaW5kZXggXTtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIGluZGV4ICsgMTtcblxuXHRcdH0sXG5cblxuXHRcdGdldF9xaWQ6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHR2YXIgcGFyZW50ID0gdGhpcy5nZXRfcGFyZW50X3F1ZXN0aW9uKCksXG5cdFx0XHRcdHByZWZpeCA9ICcnO1xuXG5cdFx0XHRpZiAoIHBhcmVudCApIHtcblxuXHRcdFx0XHRwcmVmaXggPSBwYXJlbnQuZ2V0X3FpZCgpICsgJy4nO1xuXG5cdFx0XHR9XG5cblx0XHRcdC8vIHJldHVybiBzaG9ydF9pZCArIHRoaXMuZ2V0X3R5cGVfaXRlcmF0b3IoKTtcblx0XHRcdHJldHVybiBwcmVmaXggKyB0aGlzLmdldF90eXBlX2l0ZXJhdG9yKCk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogUmV0cmlldmUgdGhlIHBhcmVudCBxdWVzdGlvbiAoaWYgdGhlIHF1ZXN0aW9uIGlzIGluIGEgcXVlc3Rpb24gZ3JvdXApXG5cdFx0ICogQHJldHVybiAgIG9ianxmYWxzZVxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0Z2V0X3BhcmVudF9xdWVzdGlvbjogZnVuY3Rpb24oKSB7XG5cblx0XHRcdGlmICggdGhpcy5pc19pbl9ncm91cCgpICkge1xuXG5cdFx0XHRcdHJldHVybiB0aGlzLmNvbGxlY3Rpb24ucGFyZW50O1xuXG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBmYWxzZTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBSZXRyaWV2ZSB0aGUgcGFyZW50IHF1aXpcblx0XHQgKiBAcmV0dXJuICAgb2JqXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRnZXRfcGFyZW50X3F1aXo6IGZ1bmN0aW9uKCkge1xuXHRcdFx0cmV0dXJuIHRoaXMuZ2V0X3BhcmVudCgpO1xuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBQb2ludHMgZ2V0dGVyXG5cdFx0ICogZW5zdXJlcyB0aGF0IDAgaXMgYWx3YXlzIHJldHVybmVkIGlmIHRoZSBxdWVzdGlvbiB0eXBlIGRvZXNuJ3Qgc3VwcG9ydCBwb2ludHNcblx0XHQgKiBAcmV0dXJuICAgaW50XG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRnZXRfcG9pbnRzOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0aWYgKCAhIHRoaXMuZ2V0KCAncXVlc3Rpb25fdHlwZScgKS5nZXQoICdwb2ludHMnICkgKSB7XG5cdFx0XHRcdHJldHVybiAwO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gdGhpcy5nZXQoICdwb2ludHMnICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogUmV0cmlldmUgdGhlIHF1ZXN0aW9ucyBwZXJjZW50YWdlIHZhbHVlIHdpdGhpbiB0aGUgcXVpelxuXHRcdCAqIEByZXR1cm4gICBzdHJpbmdcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGdldF9wb2ludHNfcGVyY2VudGFnZTogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHZhciB0b3RhbCA9IHRoaXMuZ2V0X3BhcmVudCgpLmdldCggJ19wb2ludHMnICksXG5cdFx0XHRcdHBvaW50cyA9IHRoaXMuZ2V0KCAncG9pbnRzJyApO1xuXG5cdFx0XHRpZiAoIDAgPT09IHRvdGFsICkge1xuXHRcdFx0XHRyZXR1cm4gJzAlJztcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuICggKCBwb2ludHMgLyB0b3RhbCApICogMTAwICkudG9GaXhlZCggMiApICsgJyUnO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIERldGVyaW5lIGlmIHRoZSBxdWVzdGlvbiBiZWxvbmdzIHRvIGEgcXVlc3Rpb24gZ3JvdXBcblx0XHQgKiBAcmV0dXJuICAge0Jvb2xlYW59XG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRpc19pbl9ncm91cDogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHJldHVybiAoICdxdWVzdGlvbicgPT09IHRoaXMuY29sbGVjdGlvbi5wYXJlbnQuZ2V0KCAndHlwZScgKSApO1xuXG5cdFx0fSxcblxuXHRcdF9lbnN1cmVfbWluX2Nob2ljZXM6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHR2YXIgY2hvaWNlcyA9IHRoaXMuZ2V0KCAnY2hvaWNlcycgKTtcblx0XHRcdHdoaWxlICggY2hvaWNlcy5zaXplKCkgPCB0aGlzLmdldCggJ3F1ZXN0aW9uX3R5cGUnICkuZ2V0X21pbl9jaG9pY2VzKCkgKSB7XG5cdFx0XHRcdHRoaXMuYWRkX2Nob2ljZSgpO1xuXHRcdFx0fVxuXG5cdFx0fSxcblxuXHR9LCBSZWxhdGlvbnNoaXBzICkgKTtcblxufSApO1xuXG4vKipcbiAqIFF1ZXN0aW9ucyBDb2xsZWN0aW9uXG4gKiBAc2luY2UgICAgMy4xNi4wXG4gKiBAdmVyc2lvbiAgMy4xNi4wXG4gKi9cbmRlZmluZSggJ0NvbGxlY3Rpb25zL1F1ZXN0aW9ucycsWyAnTW9kZWxzL1F1ZXN0aW9uJyBdLCBmdW5jdGlvbiggbW9kZWwgKSB7XG5cblx0cmV0dXJuIEJhY2tib25lLkNvbGxlY3Rpb24uZXh0ZW5kKCB7XG5cblx0XHQvKipcblx0XHQgKiBNb2RlbCBmb3IgY29sbGVjdGlvbiBpdGVtc1xuXHRcdCAqIEB0eXBlICBvYmpcblx0XHQgKi9cblx0XHRtb2RlbDogbW9kZWwsXG5cblx0XHQvKipcblx0XHQgKiBJbml0aWFsaXplXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGluaXRpYWxpemU6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHQvLyByZW9yZGVyIGNhbGxlZCBieSBRdWVzdGlvbkxpc3QgdmlldyB3aGVuIHNvcnRhYmxlIGRyb3BzIG9jY3VyXG5cdFx0XHR0aGlzLm9uKCAncmVvcmRlcicsIHRoaXMudXBkYXRlX29yZGVyICk7XG5cblx0XHRcdC8vIHdoZW4gYSBxdWVzdGlvbiBpcyBhZGRlZCBvciByZW1vdmVkLCB1cGRhdGUgb3JkZXJcblx0XHRcdHRoaXMub24oICdhZGQnLCB0aGlzLnVwZGF0ZV9vcmRlciApO1xuXHRcdFx0dGhpcy5vbiggJ3JlbW92ZScsIHRoaXMudXBkYXRlX29yZGVyICk7XG5cblx0XHRcdHRoaXMub24oICdhZGQnLCB0aGlzLnVwZGF0ZV9wYXJlbnQgKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBVcGRhdGUgdGhlIG9yZGVyIGF0dHIgb2YgZWFjaCBxdWVzdGlvbiBpbiB0aGUgbGlzdCB0byByZWZsZWN0IHRoZSBvcmRlciBvZiB0aGUgY29sbGVjdGlvblxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHR1cGRhdGVfb3JkZXI6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHR2YXIgc2VsZiA9IHRoaXM7XG5cblx0XHRcdHRoaXMuZWFjaCggZnVuY3Rpb24oIHF1ZXN0aW9uICkge1xuXG5cdFx0XHRcdHF1ZXN0aW9uLnNldCggJ21lbnVfb3JkZXInLCBzZWxmLmluZGV4T2YoIHF1ZXN0aW9uICkgKyAxICk7XG5cblx0XHRcdH0gKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBXaGVuIGFkZGluZyBhIHF1ZXN0aW9uIHRvIGEgcXVlc3Rpb24gbGlzdCwgdXBkYXRlIHRoZSBxdWVzdGlvbidzIHBhcmVudFxuXHRcdCAqIFdpbGwgZW5zdXJlIHRoYXQgcXVlc3Rpb25zIG1vdmVkIGludG8gYW5kIG91dCBvZiBncm91cHMgYWx3YXlzIGhhdmUgdGhlIGNvcmVyY3QgcGFyZW50X2lkXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIG1vZGVsICBpbnN0YW5jZSBvZiB0aGUgcXVlc3Rpb24gbW9kZWxcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0dXBkYXRlX3BhcmVudDogZnVuY3Rpb24oIG1vZGVsICkge1xuXG5cdFx0XHRtb2RlbC5zZXQoICdwYXJlbnRfaWQnLCB0aGlzLnBhcmVudC5nZXQoICdpZCcgKSApO1xuXG5cdFx0fSxcblxuXHR9ICk7XG5cbn0gKTtcblxuLyoqXG4gKiBVdGlsaXR5IGZ1bmN0aW9ucyBmb3IgTW9kZWxzXG4gKiBAc2luY2UgICAgMy4xNi4wXG4gKiBAdmVyc2lvbiAgMy4xNy4xXG4gKi9cbmRlZmluZSggJ01vZGVscy9fVXRpbGl0aWVzJyxbXSwgZnVuY3Rpb24oKSB7XG5cblx0cmV0dXJuIHtcblxuXHRcdGZpZWxkczogW10sXG5cblx0XHQvKipcblx0XHQgKiBSZXRyaWV2ZSB0aGUgZWRpdCBwb3N0IGxpbmsgZm9yIHRoZSBjdXJyZW50IG1vZGVsXG5cdFx0ICogQHJldHVybiAgIHN0cmluZ1xuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0Z2V0X2VkaXRfcG9zdF9saW5rOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0aWYgKCB0aGlzLmhhc190ZW1wX2lkKCkgKSB7XG5cdFx0XHRcdHJldHVybiAnJztcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIHdpbmRvdy5sbG1zX2J1aWxkZXIuYWRtaW5fdXJsICsgJ3Bvc3QucGhwP3Bvc3Q9JyArIHRoaXMuZ2V0KCAnaWQnICkgKyAnJmFjdGlvbj1lZGl0JztcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBSZXRyaWV2ZSBzY2hlbWEgZmllbGRzIGRlZmluZWQgZm9yIHRoZSBtb2RlbFxuXHRcdCAqIEByZXR1cm4gICBvYmplY3Rcblx0XHQgKiBAc2luY2UgICAgMy4xNy4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTcuMVxuXHRcdCAqL1xuXHRcdGdldF9zZXR0aW5nc19maWVsZHM6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHR2YXIgc2NoZW1hID0gdGhpcy5zY2hlbWEgfHwge307XG5cdFx0XHRyZXR1cm4gd2luZG93LmxsbXNfYnVpbGRlci5zY2hlbWFzLmdldCggc2NoZW1hLCB0aGlzLmdldCggJ3R5cGUnICkucmVwbGFjZSggJ2xsbXNfJywgJycgKSwgdGhpcyApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIERldGVybWluZSBpZiB0aGUgbW9kZWwgaGFzIGEgdGVtcG9yYXJ5IElEXG5cdFx0ICogQHJldHVybiAgIHtCb29sZWFufVxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0aGFzX3RlbXBfaWQ6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHRyZXR1cm4gKCAhIF8uaXNOdW1iZXIoIHRoaXMuZ2V0KCAnaWQnICkgKSAmJiAwID09PSB0aGlzLmdldCggJ2lkJyApLmluZGV4T2YoICd0ZW1wXycgKSApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIEluaXRpYWxpemVzIDNyZCBwYXJ0eSBjdXN0b20gc2NoZW1hIChmaWVsZCkgZGF0YSBmb3IgYSBtb2RlbFxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTcuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE3LjBcblx0XHQgKi9cblx0XHRpbml0X2N1c3RvbV9zY2hlbWE6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHR2YXIgZ3JvdXBzID0gXy5maWx0ZXIoIHRoaXMuZ2V0X3NldHRpbmdzX2ZpZWxkcygpLCBmdW5jdGlvbiggZ3JvdXAgKSB7XG5cdFx0XHRcdHJldHVybiAoIGdyb3VwLmN1c3RvbSApO1xuXHRcdFx0fSApO1xuXG5cdFx0XHRfLmVhY2goIGdyb3VwcywgZnVuY3Rpb24oIGdyb3VwICkge1xuXHRcdFx0XHRfLmVhY2goIF8uZmxhdHRlbiggIGdyb3VwLmZpZWxkcyApLCBmdW5jdGlvbiggZmllbGQgKSB7XG5cblxuXHRcdFx0XHRcdHZhciBrZXlzID0gWyBmaWVsZC5hdHRyaWJ1dGUgXSxcblx0XHRcdFx0XHRcdGN1c3RvbXMgPSB0aGlzLmdldCggJ2N1c3RvbScgKTtcblxuXHRcdFx0XHRcdGlmICggZmllbGQuc3dpdGNoX2F0dHJpYnV0ZSApIHtcblx0XHRcdFx0XHRcdGtleXMucHVzaCggZmllbGQuc3dpdGNoX2F0dHJpYnV0ZSApO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdF8uZWFjaCgga2V5cywgZnVuY3Rpb24oIGtleSApIHtcblx0XHRcdFx0XHRcdHZhciBhdHRyID0gZmllbGQuYXR0cmlidXRlX3ByZWZpeCA/IGZpZWxkLmF0dHJpYnV0ZV9wcmVmaXggKyBrZXkgOiBrZXk7XG5cdFx0XHRcdFx0XHRpZiAoIGN1c3RvbXMgJiYgY3VzdG9tc1sgYXR0ciBdICkge1xuXHRcdFx0XHRcdFx0XHR0aGlzLnNldCgga2V5LCBjdXN0b21zWyBhdHRyIF1bMF0gKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9LCB0aGlzICk7XG5cblx0XHRcdFx0fSwgdGhpcyApO1xuXHRcdFx0fSwgdGhpcyApO1xuXG5cdFx0fSxcblxuXHR9O1xuXG59ICk7XG5cbi8qKlxuICogUXVpeiBTY2hlbWFcbiAqIEBzaW5jZSAgICAzLjE3LjZcbiAqIEB2ZXJzaW9uICAzLjE3LjZcbiAqL1xuZGVmaW5lKCAnU2NoZW1hcy9RdWl6JyxbXSwgZnVuY3Rpb24oKSB7XG5cblx0cmV0dXJuIHtcblxuXHRcdGRlZmF1bHQ6IHtcblx0XHRcdHRpdGxlOiBMTE1TLmwxMG4udHJhbnNsYXRlKCAnR2VuZXJhbCBTZXR0aW5ncycgKSxcblx0XHRcdHRvZ2dsZWFibGU6IHRydWUsXG5cdFx0XHRmaWVsZHM6IFtcblx0XHRcdFx0W1xuXHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdGF0dHJpYnV0ZTogJ3Blcm1hbGluaycsXG5cdFx0XHRcdFx0XHRpZDogJ3Blcm1hbGluaycsXG5cdFx0XHRcdFx0XHR0eXBlOiAncGVybWFsaW5rJyxcblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRdLCBbXG5cdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0YXR0cmlidXRlOiAnY29udGVudCcsXG5cdFx0XHRcdFx0XHRpZDogJ2Rlc2NyaXB0aW9uJyxcblx0XHRcdFx0XHRcdGxhYmVsOiBMTE1TLmwxMG4udHJhbnNsYXRlKCAnRGVzY3JpcHRpb24nICksXG5cdFx0XHRcdFx0XHR0eXBlOiAnZWRpdG9yJyxcblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRdLCBbXG5cdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0YXR0cmlidXRlOiAncGFzc2luZ19wZXJjZW50Jyxcblx0XHRcdFx0XHRcdGlkOiAncGFzc2luZy1wZXJjZW50Jyxcblx0XHRcdFx0XHRcdGxhYmVsOiBMTE1TLmwxMG4udHJhbnNsYXRlKCAnUGFzc2luZyBQZXJjZW50YWdlJyApLFxuXHRcdFx0XHRcdFx0bWluOiAwLFxuXHRcdFx0XHRcdFx0bWF4OiAxMDAsXG5cdFx0XHRcdFx0XHR0aXA6IExMTVMubDEwbi50cmFuc2xhdGUoICdNaW5pbXVtIHBlcmNlbnRhZ2Ugb2YgdG90YWwgcG9pbnRzIHJlcXVpcmVkIHRvIHBhc3MgdGhlIHF1aXonICksXG5cdFx0XHRcdFx0XHR0eXBlOiAnbnVtYmVyJyxcblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdGF0dHJpYnV0ZTogJ2FsbG93ZWRfYXR0ZW1wdHMnLFxuXHRcdFx0XHRcdFx0aWQ6ICdhbGxvd2VkLWF0dGVtcHRzJyxcblx0XHRcdFx0XHRcdGxhYmVsOiBMTE1TLmwxMG4udHJhbnNsYXRlKCAnTGltaXQgQXR0ZW1wdHMnICksXG5cdFx0XHRcdFx0XHRzd2l0Y2hfYXR0cmlidXRlOiAnbGltaXRfYXR0ZW1wdHMnLFxuXHRcdFx0XHRcdFx0dGlwOiBMTE1TLmwxMG4udHJhbnNsYXRlKCAnTGltaXQgdGhlIG1heGltdW0gbnVtYmVyIG9mIHRpbWVzIGEgc3R1ZGVudCBjYW4gdGFrZSB0aGlzIHF1aXonICksXG5cdFx0XHRcdFx0XHR0eXBlOiAnc3dpdGNoLW51bWJlcicsXG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRhdHRyaWJ1dGU6ICd0aW1lX2xpbWl0Jyxcblx0XHRcdFx0XHRcdGlkOiAndGltZS1saW1pdCcsXG5cdFx0XHRcdFx0XHRsYWJlbDogTExNUy5sMTBuLnRyYW5zbGF0ZSggJ1RpbWUgTGltaXQnICksXG5cdFx0XHRcdFx0XHRtaW46IDEsXG5cdFx0XHRcdFx0XHRtYXg6IDM2MCxcblx0XHRcdFx0XHRcdHN3aXRjaF9hdHRyaWJ1dGU6ICdsaW1pdF90aW1lJyxcblx0XHRcdFx0XHRcdHRpcDogTExNUy5sMTBuLnRyYW5zbGF0ZSggJ0VuZm9yY2UgYSBtYXhpbXVtIG51bWJlciBvZiBtaW51dGVzIGEgc3R1ZGVudCBjYW4gc3BlbmQgb24gZWFjaCBhdHRlbXB0JyApLFxuXHRcdFx0XHRcdFx0dHlwZTogJ3N3aXRjaC1udW1iZXInLFxuXHRcdFx0XHRcdH0sXG5cdFx0XHRcdF0sIFtcblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRhdHRyaWJ1dGU6ICdzaG93X2NvcnJlY3RfYW5zd2VyJyxcblx0XHRcdFx0XHRcdGlkOiAnc2hvdy1jb3JyZWN0LWFuc3dlcicsXG5cdFx0XHRcdFx0XHRsYWJlbDogTExNUy5sMTBuLnRyYW5zbGF0ZSggJ1Nob3cgQ29ycmVjdCBBbnN3ZXJzJyApLFxuXHRcdFx0XHRcdFx0dGlwOiBMTE1TLmwxMG4udHJhbnNsYXRlKCAnV2hlbiBlbmFibGVkLCBzdHVkZW50cyB3aWxsIGJlIHNob3duIHRoZSBjb3JyZWN0IGFuc3dlciB0byBhbnkgcXVlc3Rpb24gdGhleSBhbnN3ZXJlZCBpbmNvcnJlY3RseS4nICksXG5cdFx0XHRcdFx0XHR0eXBlOiAnc3dpdGNoJyxcblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdGF0dHJpYnV0ZTogJ3JhbmRvbV9xdWVzdGlvbnMnLFxuXHRcdFx0XHRcdFx0aWQ6ICdyYW5kb20tcXVlc3Rpb25zJyxcblx0XHRcdFx0XHRcdGxhYmVsOiBMTE1TLmwxMG4udHJhbnNsYXRlKCAnUmFuZG9taXplIFF1ZXN0aW9uIE9yZGVyJyApLFxuXHRcdFx0XHRcdFx0dGlwOiBMTE1TLmwxMG4udHJhbnNsYXRlKCAnRGlzcGxheSBxdWVzdGlvbnMgaW4gYSByYW5kb20gb3JkZXIgZm9yIGVhY2ggYXR0ZW1wdC4gQ29udGVudCBxdWVzdGlvbnMgYXJlIGxvY2tlZCBpbnRvIHRoZWlyIGRlZmluZWQgcG9zaXRpb25zLicgKSxcblx0XHRcdFx0XHRcdHR5cGU6ICdzd2l0Y2gnLFxuXHRcdFx0XHRcdH0sXG5cdFx0XHRcdF0sXG5cblx0XHRcdF0sXG5cdFx0fSxcblxuXHR9O1xuXG59ICk7XG5cbi8qKlxuICogUXVpeiBNb2RlbFxuICogQHNpbmNlICAgIDMuMTYuMFxuICogQHZlcnNpb24gIDMuMTkuMlxuICovXG5kZWZpbmUoICdNb2RlbHMvUXVpeicsW1xuXHRcdCdDb2xsZWN0aW9ucy9RdWVzdGlvbnMnLFxuXHRcdCdNb2RlbHMvTGVzc29uJyxcblx0XHQnTW9kZWxzL1F1ZXN0aW9uJyxcblx0XHQnTW9kZWxzL19SZWxhdGlvbnNoaXBzJyxcblx0XHQnTW9kZWxzL19VdGlsaXRpZXMnLFxuXHRcdCdTY2hlbWFzL1F1aXonLFxuXHRdLCBmdW5jdGlvbihcblx0XHRRdWVzdGlvbnMsXG5cdFx0TGVzc29uLFxuXHRcdFF1ZXN0aW9uLFxuXHRcdFJlbGF0aW9uc2hpcHMsXG5cdFx0VXRpbGl0aWVzLFxuXHRcdFF1aXpTY2hlbWFcblx0KSB7XG5cblx0cmV0dXJuIEJhY2tib25lLk1vZGVsLmV4dGVuZCggXy5kZWZhdWx0cygge1xuXG5cdFx0LyoqXG5cdFx0ICogbW9kZWwgcmVsYXRpb25zaGlwc1xuXHRcdCAqIEB0eXBlICB7T2JqZWN0fVxuXHRcdCAqL1xuXHRcdHJlbGF0aW9uc2hpcHM6IHtcblx0XHRcdHBhcmVudDoge1xuXHRcdFx0XHRtb2RlbDogJ2xlc3NvbicsXG5cdFx0XHRcdHR5cGU6ICdtb2RlbCcsXG5cdFx0XHR9LFxuXHRcdFx0Y2hpbGRyZW46IHtcblx0XHRcdFx0cXVlc3Rpb25zOiB7XG5cdFx0XHRcdFx0Y2xhc3M6ICdRdWVzdGlvbnMnLFxuXHRcdFx0XHRcdG1vZGVsOiAnbGxtc19xdWVzdGlvbicsXG5cdFx0XHRcdFx0dHlwZTogJ2NvbGxlY3Rpb24nLFxuXHRcdFx0XHR9LFxuXHRcdFx0fVxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBMZXNzb24gU2V0dGluZ3MgU2NoZW1hXG5cdFx0ICogQHR5cGUgIHtPYmplY3R9XG5cdFx0ICovXG5cdFx0c2NoZW1hOiBRdWl6U2NoZW1hLFxuXG5cdFx0LyoqXG5cdFx0ICogTmV3IGxlc3NvbiBkZWZhdWx0c1xuXHRcdCAqIEByZXR1cm4gICBvYmpcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuNlxuXHRcdCAqL1xuXHRcdGRlZmF1bHRzOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0cmV0dXJuIHtcblx0XHRcdFx0aWQ6IF8udW5pcXVlSWQoICd0ZW1wXycgKSxcblx0XHRcdFx0dGl0bGU6IExMTVMubDEwbi50cmFuc2xhdGUoICdOZXcgUXVpeicgKSxcblx0XHRcdFx0dHlwZTogJ2xsbXNfcXVpeicsXG5cdFx0XHRcdGxlc3Nvbl9pZDogJycsXG5cblx0XHRcdFx0c3RhdHVzOiAnZHJhZnQnLFxuXG5cdFx0XHRcdC8vIGVkaXRhYmxlIGZpZWxkc1xuXHRcdFx0XHRjb250ZW50OiAnJyxcblx0XHRcdFx0YWxsb3dlZF9hdHRlbXB0czogNSxcblx0XHRcdFx0bGltaXRfYXR0ZW1wdHM6ICdubycsXG5cdFx0XHRcdGxpbWl0X3RpbWU6ICdubycsXG5cdFx0XHRcdHBhc3NpbmdfcGVyY2VudDogNjUsXG5cdFx0XHRcdG5hbWU6ICcnLFxuXHRcdFx0XHRyYW5kb21fYW5zd2VyczogJ25vJyxcblx0XHRcdFx0dGltZV9saW1pdDogMzAsXG5cdFx0XHRcdHNob3dfY29ycmVjdF9hbnN3ZXI6ICdubycsXG5cblx0XHRcdFx0cXVlc3Rpb25zOiBbXSxcblxuXHRcdFx0XHQvLyBjYWxjdWxhdGVkXG5cdFx0XHRcdF9wb2ludHM6IDAsXG5cblx0XHRcdFx0Ly8gZGlzcGxheVxuXHRcdFx0XHRwZXJtYWxpbms6ICcnLFxuXHRcdFx0XHRfc2hvd19zZXR0aW5nczogZmFsc2UsXG5cdFx0XHRcdF9xdWVzdGlvbnNfbG9hZGVkOiBmYWxzZSxcblx0XHRcdH07XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogSW5pdGlhbGl6ZXJcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNy42XG5cdFx0ICovXG5cdFx0aW5pdGlhbGl6ZTogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHRoaXMuaW5pdF9jdXN0b21fc2NoZW1hKCk7XG5cdFx0XHR0aGlzLnN0YXJ0VHJhY2tpbmcoKTtcblx0XHRcdHRoaXMuaW5pdF9yZWxhdGlvbnNoaXBzKCk7XG5cblx0XHRcdHRoaXMubGlzdGVuVG8oIHRoaXMuZ2V0KCAncXVlc3Rpb25zJyApLCAnYWRkJywgdGhpcy51cGRhdGVfcG9pbnRzICk7XG5cdFx0XHR0aGlzLmxpc3RlblRvKCB0aGlzLmdldCggJ3F1ZXN0aW9ucycgKSwgJ3JlbW92ZScsIHRoaXMudXBkYXRlX3BvaW50cyApO1xuXG5cdFx0XHR0aGlzLnNldCggJ19wb2ludHMnLCB0aGlzLmdldF90b3RhbF9wb2ludHMoKSApO1xuXG5cdFx0XHQvLyB3aGVuIGEgcXVpeiBpcyBwdWJsaXNoZWQsIGVuc3VyZSB0aGUgcGFyZW50IGxlc3NvbiBpcyBtYXJrZWQgYXMgXCJFbmFibGVkXCIgZm9yIHF1aXp6aW5nXG5cdFx0XHR0aGlzLm9uKCAnY2hhbmdlOnN0YXR1cycsIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRpZiAoICdwdWJsaXNoJyA9PT0gdGhpcy5nZXQoICdzdGF0dXMnICkgKSB7XG5cdFx0XHRcdFx0dGhpcy5nZXRfcGFyZW50KCkuc2V0KCAncXVpel9lbmFibGVkJywgJ3llcycgKTtcblx0XHRcdFx0fVxuXHRcdFx0fSApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIEFkZCBhIG5ldyBxdWVzdGlvbiB0byB0aGUgcXVpelxuXHRcdCAqIEBwYXJhbSAgICBvYmogICBkYXRhICAgcXVlc3Rpb24gZGF0YVxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRhZGRfcXVlc3Rpb246IGZ1bmN0aW9uKCBkYXRhICkge1xuXG5cdFx0XHRkYXRhLnBhcmVudF9pZCA9IHRoaXMuZ2V0KCAnaWQnICk7XG5cdFx0XHR2YXIgcXVlc3Rpb24gPSB0aGlzLmdldCggJ3F1ZXN0aW9ucycgKS5hZGQoIGRhdGEsIHtcblx0XHRcdFx0cGFyZW50OiB0aGlzLFxuXHRcdFx0fSApO1xuXHRcdFx0QmFja2JvbmUucHViU3ViLnRyaWdnZXIoICdxdWl6LWFkZC1xdWVzdGlvbicsIHF1ZXN0aW9uLCB0aGlzICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogUmV0cmlldmUgdGhlIHRyYW5zbGF0ZWQgcG9zdCB0eXBlIG5hbWUgZm9yIHRoZSBtb2RlbCdzIHR5cGVcblx0XHQgKiBAcGFyYW0gICAgYm9vbCAgICAgcGx1cmFsICBpZiB0cnVlLCByZXR1cm5zIHRoZSBwbHVyYWwsIG90aGVyd2lzZSByZXR1cm5zIHNpbmd1bGFyXG5cdFx0ICogQHJldHVybiAgIHN0cmluZ1xuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjEyXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMTJcblx0XHQgKi9cblx0XHRnZXRfbDEwbl90eXBlOiBmdW5jdGlvbiggcGx1cmFsICkge1xuXG5cdFx0XHRpZiAoIHBsdXJhbCApIHtcblx0XHRcdFx0cmV0dXJuIExMTVMubDEwbi50cmFuc2xhdGUoICdxdWl6emVzJyApO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gTExNUy5sMTBuLnRyYW5zbGF0ZSggJ3F1aXonICk7XG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFJldHJpZXZlIHRoZSBxdWl6J3MgdG90YWwgcG9pbnRzXG5cdFx0ICogQHJldHVybiAgIGludFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0Z2V0X3RvdGFsX3BvaW50czogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHZhciBwb2ludHMgPSAwO1xuXG5cdFx0XHR0aGlzLmdldCggJ3F1ZXN0aW9ucycgKS5lYWNoKCBmdW5jdGlvbiggcXVlc3Rpb24gKSB7XG5cdFx0XHRcdHBvaW50cyArPSBxdWVzdGlvbi5nZXRfcG9pbnRzKCk7XG5cdFx0XHR9ICk7XG5cblx0XHRcdHJldHVybiBwb2ludHM7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogTGF6eSBsb2FkIHF1ZXN0aW9ucyB2aWEgQUpBWFxuXHRcdCAqIEBwYXJhbSAgICB7RnVuY3Rpb259ICBjYiAgY2FsbGJhY2sgZnVuY3Rpb25cblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE5LjJcblx0XHQgKiBAdmVyc2lvbiAgMy4xOS4yXG5cdFx0ICovXG5cdFx0bG9hZF9xdWVzdGlvbnM6IGZ1bmN0aW9uKCBjYiApIHtcblxuXHRcdFx0aWYgKCB0aGlzLmdldCggJ19xdWVzdGlvbnNfbG9hZGVkJyApICkge1xuXG5cdFx0XHRcdGNiKCk7XG5cblx0XHRcdH0gZWxzZSB7XG5cblx0XHRcdFx0dmFyIHNlbGYgPSB0aGlzO1xuXG5cdFx0XHRcdExMTVMuQWpheC5jYWxsKCB7XG5cdFx0XHRcdFx0ZGF0YToge1xuXHRcdFx0XHRcdFx0YWN0aW9uOiAnbGxtc19idWlsZGVyJyxcblx0XHRcdFx0XHRcdGFjdGlvbl90eXBlOiAnbGF6eV9sb2FkJyxcblx0XHRcdFx0XHRcdGNvdXJzZV9pZDogd2luZG93LmxsbXNfYnVpbGRlci5Db3Vyc2VNb2RlbC5nZXQoICdpZCcgKSxcblx0XHRcdFx0XHRcdGxvYWRfaWQ6IHRoaXMuZ2V0KCAnaWQnICksXG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRlcnJvcjogZnVuY3Rpb24oIHhociwgc3RhdHVzLCBlcnJvciApIHtcblxuXHRcdFx0XHRcdFx0Y29uc29sZS5sb2coIHhociwgc3RhdHVzLCBlcnJvciApO1xuXHRcdFx0XHRcdFx0d2luZG93LmxsbXNfYnVpbGRlci5kZWJ1Zy5sb2coICc9PT09IHN0YXJ0IGxvYWRfcXVlc3Rpb25zIGVycm9yID09PT0nLCB4aHIsIHN0YXR1cywgZXJyb3IsICc9PT09IGZpbmlzaCBsb2FkX3F1ZXN0aW9ucyBlcnJvciA9PT09JyApO1xuXHRcdFx0XHRcdFx0Y2IoIHRydWUgKTtcblxuXHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0c3VjY2VzczogZnVuY3Rpb24oIHJlcyApIHtcblx0XHRcdFx0XHRcdGlmICggcmVzICYmIHJlcy5xdWVzdGlvbnMgKSB7XG5cdFx0XHRcdFx0XHRcdHNlbGYuc2V0KCAnX3F1ZXN0aW9uc19sb2FkZWQnLCB0cnVlICk7XG5cdFx0XHRcdFx0XHRcdGlmICggcmVzLnF1ZXN0aW9ucyApIHtcblx0XHRcdFx0XHRcdFx0XHRfLmVhY2goIHJlcy5xdWVzdGlvbnMsIHNlbGYuYWRkX3F1ZXN0aW9uLCBzZWxmICk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0Y2IoKTtcblx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdGNiKCB0cnVlICk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdH0gKTtcblxuXHRcdFx0fVxuXG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogVXBkYXRlIHRvdGFsIG51bWJlciBvZiBwb2ludHMgY2FsY3VsYXRlZCBwcm9wZXJ0eVxuXHRcdCAqIEByZXR1cm4gICBpbnRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdHVwZGF0ZV9wb2ludHM6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHR0aGlzLnNldCggJ19wb2ludHMnLCB0aGlzLmdldF90b3RhbF9wb2ludHMoKSApO1xuXG5cdFx0fSxcblxuXHR9LCBSZWxhdGlvbnNoaXBzLCBVdGlsaXRpZXMgKSApO1xuXG59ICk7XG5cbi8qKlxuICogTGVzc29uIFNjaGVtYXNcbiAqIEBzaW5jZSAgICAzLjE3LjBcbiAqIEB2ZXJzaW9uICAzLjE3LjFcbiAqL1xuZGVmaW5lKCAnU2NoZW1hcy9MZXNzb24nLFtdLCBmdW5jdGlvbigpIHtcblxuXHRyZXR1cm4ge1xuXG5cdFx0ZGVmYXVsdDoge1xuXHRcdFx0dGl0bGU6IExMTVMubDEwbi50cmFuc2xhdGUoICdHZW5lcmFsIFNldHRpbmdzJyApLFxuXHRcdFx0dG9nZ2xlYWJsZTogdHJ1ZSxcblx0XHRcdGZpZWxkczogW1xuXHRcdFx0XHRbXG5cdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0YXR0cmlidXRlOiAncGVybWFsaW5rJyxcblx0XHRcdFx0XHRcdGlkOiAncGVybWFsaW5rJyxcblx0XHRcdFx0XHRcdHR5cGU6ICdwZXJtYWxpbmsnLFxuXHRcdFx0XHRcdH0sXG5cdFx0XHRcdF0sIFtcblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRhdHRyaWJ1dGU6ICd2aWRlb19lbWJlZCcsXG5cdFx0XHRcdFx0XHRpZDogJ3ZpZGVvLWVtYmVkJyxcblx0XHRcdFx0XHRcdGxhYmVsOiBMTE1TLmwxMG4udHJhbnNsYXRlKCAnVmlkZW8gRW1iZWQgVVJMJyApLFxuXHRcdFx0XHRcdFx0dHlwZTogJ3ZpZGVvX2VtYmVkJyxcblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdGF0dHJpYnV0ZTogJ2F1ZGlvX2VtYmVkJyxcblx0XHRcdFx0XHRcdGlkOiAnYXVkaW8tZW1iZWQnLFxuXHRcdFx0XHRcdFx0bGFiZWw6IExMTVMubDEwbi50cmFuc2xhdGUoICdBdWRpbyBFbWJlZCBVUkwnICksXG5cdFx0XHRcdFx0XHR0eXBlOiAnYXVkaW9fZW1iZWQnLFxuXHRcdFx0XHRcdH0sXG5cdFx0XHRcdF0sIFtcblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRhdHRyaWJ1dGU6ICdmcmVlX2xlc3NvbicsXG5cdFx0XHRcdFx0XHRpZDogJ2ZyZWUtbGVzc29uJyxcblx0XHRcdFx0XHRcdGxhYmVsOiBMTE1TLmwxMG4udHJhbnNsYXRlKCAnRnJlZSBMZXNzb24nICksXG5cdFx0XHRcdFx0XHR0aXA6IExMTVMubDEwbi50cmFuc2xhdGUoIFwiRnJlZSBsZXNzb25zIGNhbiBiZSBhY2Nlc3NlZCB3aXRob3V0IGVucm9sbG1lbnQuXCIgKSxcblx0XHRcdFx0XHRcdHR5cGU6ICdzd2l0Y2gnLFxuXHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0YXR0cmlidXRlOiAncmVxdWlyZV9wYXNzaW5nX2dyYWRlJyxcblx0XHRcdFx0XHRcdGlkOiAncmVxdWlyZS1wYXNzaW5nLWdyYWRlJyxcblx0XHRcdFx0XHRcdGxhYmVsOiBMTE1TLmwxMG4udHJhbnNsYXRlKCAnUmVxdWlyZSBQYXNzaW5nIEdyYWRlIG9uIFF1aXonICksXG5cdFx0XHRcdFx0XHR0aXA6IExMTVMubDEwbi50cmFuc2xhdGUoIFwiV2hlbiBlbmFibGVkLCBzdHVkZW50cyBtdXN0IHBhc3MgdGhpcyBsZXNzb24ncyBxdWl6IGJlZm9yZSB0aGUgbGVzc29uIGNhbiBiZSBjb21wbGV0ZWQuXCIgKSxcblx0XHRcdFx0XHRcdHR5cGU6ICdzd2l0Y2gnLFxuXHRcdFx0XHRcdFx0Y29uZGl0aW9uOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRcdFx0cmV0dXJuICggJ3llcycgPT09IHRoaXMuZ2V0KCAncXVpel9lbmFibGVkJyApICk7XG5cdFx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0YXR0cmlidXRlOiAncmVxdWlyZV9hc3NpZ25tZW50X3Bhc3NpbmdfZ3JhZGUnLFxuXHRcdFx0XHRcdFx0aWQ6ICdyZXF1aXJlLWFzc2lnbm1lbnQtcGFzc2luZy1ncmFkZScsXG5cdFx0XHRcdFx0XHRsYWJlbDogTExNUy5sMTBuLnRyYW5zbGF0ZSggJ1JlcXVpcmUgUGFzc2luZyBHcmFkZSBvbiBBc3NpZ25tZW50JyApLFxuXHRcdFx0XHRcdFx0dGlwOiBMTE1TLmwxMG4udHJhbnNsYXRlKCBcIldoZW4gZW5hYmxlZCwgc3R1ZGVudHMgbXVzdCBwYXNzIHRoaXMgbGVzc29uJ3MgYXNzaWdubWVudCBiZWZvcmUgdGhlIGxlc3NvbiBjYW4gYmUgY29tcGxldGVkLlwiICksXG5cdFx0XHRcdFx0XHR0eXBlOiAnc3dpdGNoJyxcblx0XHRcdFx0XHRcdGNvbmRpdGlvbjogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHRcdHJldHVybiAoICd1bmRlZmluZWQnICE9PSB3aW5kb3cubGxtc19idWlsZGVyLmFzc2lnbm1lbnRzICYmICd5ZXMnID09PSB0aGlzLmdldCggJ2Fzc2lnbm1lbnRfZW5hYmxlZCcgKSApO1xuXHRcdFx0XHRcdFx0fSxcblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRdLCBbXG5cdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0YXR0cmlidXRlOiAncHJlcmVxdWlzaXRlJyxcblx0XHRcdFx0XHRcdGNvbmRpdGlvbjogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHRcdHJldHVybiAoIGZhbHNlID09PSB0aGlzLmlzX2ZpcnN0X2luX2NvdXJzZSgpICk7XG5cdFx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdFx0aWQ6ICdwcmVyZXF1aXNpdGUnLFxuXHRcdFx0XHRcdFx0bGFiZWw6IExMTVMubDEwbi50cmFuc2xhdGUoICdQcmVyZXF1aXNpdGUnICksXG5cdFx0XHRcdFx0XHRzd2l0Y2hfYXR0cmlidXRlOiAnaGFzX3ByZXJlcXVpc2l0ZScsXG5cdFx0XHRcdFx0XHR0eXBlOiAnc3dpdGNoLXNlbGVjdCcsXG5cdFx0XHRcdFx0XHRvcHRpb25zOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRcdFx0cmV0dXJuIHRoaXMuZ2V0X2F2YWlsYWJsZV9wcmVyZXFfb3B0aW9ucygpO1xuXHRcdFx0XHRcdFx0fSxcblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRdLCBbXG5cdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0YXR0cmlidXRlOiAnZHJpcF9tZXRob2QnLFxuXHRcdFx0XHRcdFx0aWQ6ICdkcmlwLW1ldGhvZCcsXG5cdFx0XHRcdFx0XHRsYWJlbDogTExNUy5sMTBuLnRyYW5zbGF0ZSggJ0RyaXAgTWV0aG9kJyApLFxuXHRcdFx0XHRcdFx0c3dpdGNoX2F0dHJpYnV0ZTogJ2RyaXBfbWV0aG9kJyxcblx0XHRcdFx0XHRcdHR5cGU6ICdzZWxlY3QnLFxuXHRcdFx0XHRcdFx0b3B0aW9uczogZnVuY3Rpb24oKSB7XG5cblx0XHRcdFx0XHRcdFx0dmFyIG9wdGlvbnMgPSBbXG5cdFx0XHRcdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0XHRcdFx0a2V5OiAnJyxcblx0XHRcdFx0XHRcdFx0XHRcdHZhbDogTExNUy5sMTBuLnRyYW5zbGF0ZSggJ05vbmUnICksXG5cdFx0XHRcdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRcdFx0XHRrZXk6ICdkYXRlJyxcblx0XHRcdFx0XHRcdFx0XHRcdHZhbDogTExNUy5sMTBuLnRyYW5zbGF0ZSggJ09uIGEgc3BlY2lmaWMgZGF0ZScgKSxcblx0XHRcdFx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdFx0XHRcdGtleTogJ2Vucm9sbG1lbnQnLFxuXHRcdFx0XHRcdFx0XHRcdFx0dmFsOiBMTE1TLmwxMG4udHJhbnNsYXRlKCAnIyBvZiBkYXlzIGFmdGVyIGNvdXJzZSBlbnJvbGxtZW50JyApLFxuXHRcdFx0XHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0XHRcdF07XG5cblx0XHRcdFx0XHRcdFx0aWYgKCB0aGlzLmdldF9jb3Vyc2UoKS5nZXQoICdzdGFydF9kYXRlJyApICkge1xuXHRcdFx0XHRcdFx0XHRcdG9wdGlvbnMucHVzaCgge1xuXHRcdFx0XHRcdFx0XHRcdFx0a2V5OiAnc3RhcnQnLFxuXHRcdFx0XHRcdFx0XHRcdFx0dmFsOiBMTE1TLmwxMG4udHJhbnNsYXRlKCAnIyBvZiBkYXlzIGFmdGVyIGNvdXJzZSBzdGFydCBkYXRlJyApLFxuXHRcdFx0XHRcdFx0XHRcdH0gKTtcblx0XHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRcdGlmICggJ3llcycgPT09IHRoaXMuZ2V0KCAnaGFzX3ByZXJlcXVpc2l0ZScgKSApIHtcblx0XHRcdFx0XHRcdFx0XHRvcHRpb25zLnB1c2goIHtcblx0XHRcdFx0XHRcdFx0XHRcdGtleTogJ3ByZXJlcXVpc2l0ZScsXG5cdFx0XHRcdFx0XHRcdFx0XHR2YWw6IExMTVMubDEwbi50cmFuc2xhdGUoICcjIG9mIGRheXMgYWZ0ZXIgcHJlcmVxdWlzaXRlIGxlc3NvbiBjb21wbGV0aW9uJyApLFxuXHRcdFx0XHRcdFx0XHRcdH0gKTtcblx0XHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRcdHJldHVybiBvcHRpb25zO1xuXG5cdFx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0YXR0cmlidXRlOiAnZGF5c19iZWZvcmVfYXZhaWxhYmxlJyxcblx0XHRcdFx0XHRcdGNvbmRpdGlvbjogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHRcdHJldHVybiAoIC0xICE9PSBbICdlbnJvbGxtZW50JywgJ3N0YXJ0JywgJ3ByZXJlcXVpc2l0ZScgXS5pbmRleE9mKCB0aGlzLmdldCggJ2RyaXBfbWV0aG9kJyApICkgKTtcblx0XHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0XHRpZDogJ2RheXMtYmVmb3JlLWF2YWlsYWJsZScsXG5cdFx0XHRcdFx0XHRsYWJlbDogTExNUy5sMTBuLnRyYW5zbGF0ZSggJyMgb2YgZGF5cycgKSxcblx0XHRcdFx0XHRcdG1pbjogMCxcblx0XHRcdFx0XHRcdHR5cGU6ICdudW1iZXInLFxuXHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0YXR0cmlidXRlOiAnZGF0ZV9hdmFpbGFibGUnLFxuXHRcdFx0XHRcdFx0ZGF0ZV9mb3JtYXQ6ICdZLW0tZCcsXG5cdFx0XHRcdFx0XHRjb25kaXRpb246IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdFx0XHRyZXR1cm4gKCAnZGF0ZScgPT09IHRoaXMuZ2V0KCAnZHJpcF9tZXRob2QnICkgKTtcblx0XHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0XHRpZDogJ2RhdGUtYXZhaWxhYmxlJyxcblx0XHRcdFx0XHRcdGxhYmVsOiBMTE1TLmwxMG4udHJhbnNsYXRlKCAnRGF0ZScgKSxcblx0XHRcdFx0XHRcdHRpbWVwaWNrZXI6ICdmYWxzZScsXG5cdFx0XHRcdFx0XHR0eXBlOiAnZGF0ZXBpY2tlcicsXG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRhdHRyaWJ1dGU6ICd0aW1lX2F2YWlsYWJsZScsXG5cdFx0XHRcdFx0XHRjb25kaXRpb246IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdFx0XHRyZXR1cm4gKCAnZGF0ZScgPT09IHRoaXMuZ2V0KCAnZHJpcF9tZXRob2QnICkgKTtcblx0XHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0XHRkYXRlcGlja2VyOiAnZmFsc2UnLFxuXHRcdFx0XHRcdFx0ZGF0ZV9mb3JtYXQ6ICdoOmkgQScsXG5cdFx0XHRcdFx0XHRpZDogJ3RpbWUtYXZhaWxhYmxlJyxcblx0XHRcdFx0XHRcdGxhYmVsOiBMTE1TLmwxMG4udHJhbnNsYXRlKCAnVGltZScgKSxcblx0XHRcdFx0XHRcdHR5cGU6ICdkYXRlcGlja2VyJyxcblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRdLFxuXHRcdFx0XSxcblx0XHR9LFxuXG5cdH07XG5cbn0gKTtcblxuLyoqXG4gKiBMZXNzb24gTW9kZWxcbiAqIEBzaW5jZSAgICAzLjEzLjBcbiAqIEB2ZXJzaW9uICAzLjE5LjNcbiAqL1xuZGVmaW5lKCAnTW9kZWxzL0xlc3NvbicsWyAnTW9kZWxzL1F1aXonLCAnTW9kZWxzL19SZWxhdGlvbnNoaXBzJywgJ01vZGVscy9fVXRpbGl0aWVzJywgJ1NjaGVtYXMvTGVzc29uJyBdLCBmdW5jdGlvbiggUXVpeiwgUmVsYXRpb25zaGlwcywgVXRpbGl0aWVzLCBMZXNzb25TY2hlbWEgKSB7XG5cblx0cmV0dXJuIEJhY2tib25lLk1vZGVsLmV4dGVuZCggXy5kZWZhdWx0cygge1xuXG5cdFx0LyoqXG5cdFx0ICogTW9kZWwgcmVsYXRpb25zaGlwc1xuXHRcdCAqIEB0eXBlICB7T2JqZWN0fVxuXHRcdCAqL1xuXHRcdHJlbGF0aW9uc2hpcHM6IHtcblx0XHRcdHBhcmVudHM6IHtcblx0XHRcdFx0bW9kZWw6ICdzZWN0aW9uJyxcblx0XHRcdFx0dHlwZTogJ21vZGVsJyxcblx0XHRcdH0sXG5cdFx0XHRjaGlsZHJlbjoge1xuXHRcdFx0XHRxdWl6OiB7XG5cdFx0XHRcdFx0Y2xhc3M6ICdRdWl6Jyxcblx0XHRcdFx0XHRjb25kaXRpb25hbDogZnVuY3Rpb24oIG1vZGVsICkge1xuXHRcdFx0XHRcdFx0Ly8gaWYgcXVpeiBpcyBlbmFibGVkIE9SIG5vdCBlbmFibGVkIGJ1dCB3ZSBoYXZlIHNvbWUgcXVpeiBkYXRhIGFzIGFuIG9ialxuXHRcdFx0XHRcdFx0cmV0dXJuICggJ3llcycgPT09IG1vZGVsLmdldCggJ3F1aXpfZW5hYmxlZCcgKSB8fCAhIF8uaXNFbXB0eSggbW9kZWwuZ2V0KCAncXVpeicgKSApICk7XG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRtb2RlbDogJ2xsbXNfcXVpeicsXG5cdFx0XHRcdFx0dHlwZTogJ21vZGVsJyxcblx0XHRcdFx0fSxcblx0XHRcdH0sXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIExlc3NvbiBTZXR0aW5ncyBTY2hlbWFcblx0XHQgKiBAdHlwZSAge09iamVjdH1cblx0XHQgKi9cblx0XHRzY2hlbWE6IExlc3NvblNjaGVtYSxcblxuXHRcdC8qKlxuXHRcdCAqIE5ldyBsZXNzb24gZGVmYXVsdHNcblx0XHQgKiBAcmV0dXJuICAgb2JqXG5cdFx0ICogQHNpbmNlICAgIDMuMTMuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE3LjFcblx0XHQgKi9cblx0XHRkZWZhdWx0czogZnVuY3Rpb24oKSB7XG5cdFx0XHRyZXR1cm4ge1xuXHRcdFx0XHRpZDogXy51bmlxdWVJZCggJ3RlbXBfJyApLFxuXHRcdFx0XHR0aXRsZTogTExNUy5sMTBuLnRyYW5zbGF0ZSggJ05ldyBMZXNzb24nICksXG5cdFx0XHRcdHR5cGU6ICdsZXNzb24nLFxuXHRcdFx0XHRvcmRlcjogdGhpcy5jb2xsZWN0aW9uID8gdGhpcy5jb2xsZWN0aW9uLmxlbmd0aCArIDEgOiAxLFxuXHRcdFx0XHRwYXJlbnRfY291cnNlOiB3aW5kb3cubGxtc19idWlsZGVyLmNvdXJzZS5pZCxcblx0XHRcdFx0cGFyZW50X3NlY3Rpb246ICcnLFxuXG5cdFx0XHRcdC8vIHVybHNcblx0XHRcdFx0ZWRpdF91cmw6ICcnLFxuXHRcdFx0XHR2aWV3X3VybDogJycsXG5cblx0XHRcdFx0Ly8gZWRpdGFibGUgZmllbGRzXG5cdFx0XHRcdGNvbnRlbnQ6ICcnLFxuXHRcdFx0XHRhdWRpb19lbWJlZDogJycsXG5cdFx0XHRcdGhhc19wcmVyZXF1aXNpdGU6ICdubycsXG5cdFx0XHRcdHJlcXVpcmVfcGFzc2luZ19ncmFkZTogJ3llcycsXG5cdFx0XHRcdHJlcXVpcmVfYXNzaWdubWVudF9wYXNzaW5nX2dyYWRlOiAneWVzJyxcblx0XHRcdFx0dmlkZW9fZW1iZWQ6ICcnLFxuXHRcdFx0XHRmcmVlX2xlc3NvbjogJycsXG5cblx0XHRcdFx0Ly8gb3RoZXIgZmllbGRzXG5cdFx0XHRcdGFzc2lnbm1lbnQ6IHt9LCAvLyBhc3NpZ25tZW50IG1vZGVsL2RhdGFcblx0XHRcdFx0YXNzaWdubWVudF9lbmFibGVkOiAnbm8nLFxuXG5cdFx0XHRcdHF1aXo6IHt9LCAvLyBxdWl6IG1vZGVsL2RhdGFcblx0XHRcdFx0cXVpel9lbmFibGVkOiAnbm8nLFxuXG5cdFx0XHRcdF9mb3JjZVN5bmM6IGZhbHNlLFxuXG5cdFx0XHR9O1xuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBJbml0aWFsaXplclxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE3LjBcblx0XHQgKi9cblx0XHRpbml0aWFsaXplOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0dGhpcy5pbml0X2N1c3RvbV9zY2hlbWEoKTtcblx0XHRcdHRoaXMuc3RhcnRUcmFja2luZygpO1xuXHRcdFx0dGhpcy5tYXliZV9pbml0X2Fzc2lnbm1lbnRzKCk7XG5cdFx0XHR0aGlzLmluaXRfcmVsYXRpb25zaGlwcygpO1xuXG5cdFx0XHQvLyBpZiB0aGUgbGVzc29uIElEIGlzbid0IHNldCBvbiBhIHF1aXosIHNldCBpdFxuXHRcdFx0dmFyIHF1aXogPSB0aGlzLmdldCggJ3F1aXonICk7XG5cdFx0XHRpZiAoICEgXy5pc0VtcHR5KCBxdWl6ICkgJiYgISBxdWl6LmdldCggJ2xlc3Nvbl9pZCcgKSApIHtcblx0XHRcdFx0cXVpei5zZXQoICdsZXNzb25faWQnLCB0aGlzLmdldCggJ2lkJyApICk7XG5cdFx0XHR9XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogUmV0cmlldmUgYSByZWZlcmVuY2UgdG8gdGhlIHBhcmVudCBjb3Vyc2Ugb2YgdGhlIGxlc3NvblxuXHRcdCAqIEByZXR1cm4gICBvYmpcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGdldF9jb3Vyc2U6IGZ1bmN0aW9uKCkge1xuXHRcdFx0cmV0dXJuIHRoaXMuZ2V0X3BhcmVudCgpLmdldF9wYXJlbnQoKTtcblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogUmV0cmlldmUgdGhlIHRyYW5zbGF0ZWQgcG9zdCB0eXBlIG5hbWUgZm9yIHRoZSBtb2RlbCdzIHR5cGVcblx0XHQgKiBAcGFyYW0gICAgYm9vbCAgICAgcGx1cmFsICBpZiB0cnVlLCByZXR1cm5zIHRoZSBwbHVyYWwsIG90aGVyd2lzZSByZXR1cm5zIHNpbmd1bGFyXG5cdFx0ICogQHJldHVybiAgIHN0cmluZ1xuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjEyXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMTJcblx0XHQgKi9cblx0XHRnZXRfbDEwbl90eXBlOiBmdW5jdGlvbiggcGx1cmFsICkge1xuXG5cdFx0XHRpZiAoIHBsdXJhbCApIHtcblx0XHRcdFx0cmV0dXJuIExMTVMubDEwbi50cmFuc2xhdGUoICdsZXNzb25zJyApO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gTExNUy5sMTBuLnRyYW5zbGF0ZSggJ2xlc3NvbicgKTtcblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogT3ZlcnJpZGUgZGVmYXVsdCBnZXRfcGFyZW50IHRvIGdyYWIgZnJvbSBjb2xsZWN0aW9uIGlmIG1vZGVscyBwYXJlbnQgaXNuJ3Qgc2V0XG5cdFx0ICogQHJldHVybiAgIG9ialxuXHRcdCAqIEBzaW5jZSAgICAzLjE3LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNy4wXG5cdFx0ICovXG5cdFx0Z2V0X3BhcmVudDogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHZhciByZWxzID0gdGhpcy5nZXRfcmVsYXRpb25zaGlwcygpO1xuXHRcdFx0aWYgKCByZWxzLnBhcmVudCAmJiByZWxzLnBhcmVudC5yZWZlcmVuY2UgKSB7XG5cdFx0XHRcdHJldHVybiByZWxzLnBhcmVudC5yZWZlcmVuY2U7XG5cdFx0XHR9IGVsc2UgaWYgKCB0aGlzLmNvbGxlY3Rpb24gJiYgdGhpcy5jb2xsZWN0aW9uLnBhcmVudCApIHtcblx0XHRcdFx0cmV0dXJuIHRoaXMuY29sbGVjdGlvbi5wYXJlbnQ7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogUmV0cmlldmUgYW4gYXJyYXkgb2YgcHJlcmVxdWlzaXRlIG9wdGlvbnMgYXZhaWxhYmxlIGZvciB0aGUgY3VycmVudCBsZXNzb25cblx0XHQgKiBAcmV0dXJuICAgb2JqXG5cdFx0ICogQHNpbmNlICAgIDMuMTcuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE3LjBcblx0XHQgKi9cblx0XHRnZXRfYXZhaWxhYmxlX3ByZXJlcV9vcHRpb25zOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0dmFyIHBhcmVudF9zZWN0aW9uX2luZGV4ID0gdGhpcy5nZXRfcGFyZW50KCkuY29sbGVjdGlvbi5pbmRleE9mKCB0aGlzLmdldF9wYXJlbnQoKSApLFxuXHRcdFx0XHRsZXNzb25faW5kZXhfaW5fc2VjdGlvbiA9IHRoaXMuY29sbGVjdGlvbi5pbmRleE9mKCB0aGlzICksXG5cdFx0XHRcdG9wdGlvbnMgPSBbXTtcblxuXHRcdFx0dGhpcy5nZXRfY291cnNlKCkuZ2V0KCAnc2VjdGlvbnMnICkuZWFjaCggZnVuY3Rpb24oIHNlY3Rpb24sIGN1cnJfc2VjX2luZGV4ICkge1xuXHRcdFx0XHRpZiAoIGN1cnJfc2VjX2luZGV4IDw9IHBhcmVudF9zZWN0aW9uX2luZGV4ICkge1xuXHRcdFx0XHRcdHZhciBncm91cCA9IHtcblx0XHRcdFx0XHRcdFx0LyogdHJhbnNsYXRvcnM6ICUxJGQgPSBzZWN0aW9uIG9yZGVyIG51bWJlciwgJTIkcyA9IHNlY3Rpb24gdGl0bGUgKi9cblx0XHRcdFx0XHRcdFx0bGFiZWw6IExMTVMubDEwbi5yZXBsYWNlKCAnU2VjdGlvbiAlMSRkOiAlMiRzJywge1xuXHRcdFx0XHRcdFx0XHRcdCclMSRkJzogc2VjdGlvbi5nZXQoICdvcmRlcicgKSxcblx0XHRcdFx0XHRcdFx0XHQnJTIkcyc6IHNlY3Rpb24uZ2V0KCAndGl0bGUnIClcblx0XHRcdFx0XHRcdFx0fSApLFxuXHRcdFx0XHRcdFx0XHRvcHRpb25zOiBbXSxcblx0XHRcdFx0XHRcdH07XG5cblx0XHRcdFx0XHRzZWN0aW9uLmdldCggJ2xlc3NvbnMnICkuZWFjaCggZnVuY3Rpb24oIGxlc3NvbiwgY3Vycl9sZXNfaW5kZXggKSB7XG5cdFx0XHRcdFx0XHRpZiAoIGN1cnJfc2VjX2luZGV4ICE9PSBwYXJlbnRfc2VjdGlvbl9pbmRleCB8fCBjdXJyX2xlc19pbmRleCA8IGxlc3Nvbl9pbmRleF9pbl9zZWN0aW9uICkge1xuXHRcdFx0XHRcdFx0XHQvKiB0cmFuc2xhdG9yczogJTEkZCA9IGxlc3NvbiBvcmRlciBudW1iZXIsICUyJHMgPSBsZXNzb24gdGl0bGUgKi9cblx0XHRcdFx0XHRcdFx0Z3JvdXAub3B0aW9ucy5wdXNoKCB7XG5cdFx0XHRcdFx0XHRcdFx0a2V5OiBsZXNzb24uZ2V0KCAnaWQnICksXG5cdFx0XHRcdFx0XHRcdFx0dmFsOiBMTE1TLmwxMG4ucmVwbGFjZSggJ0xlc3NvbiAlMSRkOiAlMiRzJywge1xuXHRcdFx0XHRcdFx0XHRcdFx0JyUxJGQnOiBsZXNzb24uZ2V0KCAnb3JkZXInICksXG5cdFx0XHRcdFx0XHRcdFx0XHQnJTIkcyc6IGxlc3Nvbi5nZXQoICd0aXRsZScgKVxuXHRcdFx0XHRcdFx0XHRcdH0gKSxcblx0XHRcdFx0XHRcdFx0fSApO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH0sIHRoaXMgKTtcblxuXHRcdFx0XHRcdG9wdGlvbnMucHVzaCggZ3JvdXAgKTtcblx0XHRcdFx0fVxuXHRcdFx0fSwgdGhpcyApO1xuXG5cdFx0XHRyZXR1cm4gb3B0aW9ucztcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBBZGQgYSBuZXcgcXVpeiB0byB0aGUgbGVzc29uXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIGRhdGEgICBvYmplY3Qgb2YgcXVpeiBkYXRhIHVzZWQgdG8gY29uc3RydWN0IGEgbmV3IHF1aXogbW9kZWxcblx0XHQgKiBAcmV0dXJuICAgb2JqICAgICAgICAgIG1vZGVsIGZvciB0aGUgY3JlYXRlZCBxdWl6XG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE5LjNcblx0XHQgKi9cblx0XHRhZGRfcXVpejogZnVuY3Rpb24oIGRhdGEgKSB7XG5cblx0XHRcdGRhdGEgPSBkYXRhIHx8IHt9O1xuXG5cdFx0XHRkYXRhLmxlc3Nvbl9pZCA9IHRoaXMuaWQ7XG5cdFx0XHRkYXRhLl9xdWVzdGlvbnNfbG9hZGVkID0gdHJ1ZTtcblxuXHRcdFx0aWYgKCAhIGRhdGEudGl0bGUgKSB7XG5cblx0XHRcdFx0ZGF0YS50aXRsZSA9IExMTVMubDEwbi5yZXBsYWNlKCAnJTEkcyBRdWl6Jywge1xuXHRcdFx0XHRcdCclMSRzJzogdGhpcy5nZXQoICd0aXRsZScgKSxcblx0XHRcdFx0fSApO1xuXG5cdFx0XHR9XG5cblx0XHRcdHRoaXMuc2V0KCAncXVpeicsIGRhdGEgKTtcblx0XHRcdHRoaXMuaW5pdF9yZWxhdGlvbnNoaXBzKCk7XG5cblx0XHRcdHZhciBxdWl6ID0gdGhpcy5nZXQoICdxdWl6JyApO1xuXHRcdFx0dGhpcy5zZXQoICdxdWl6X2VuYWJsZWQnLCAneWVzJyApO1xuXG5cdFx0XHRyZXR1cm4gcXVpejtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBEZXRlcm1pbmUgaWYgdGhpcyBpcyB0aGUgZmlyc3QgbGVzc29uXG5cdFx0ICogQHJldHVybiAgIHtCb29sZWFufVxuXHRcdCAqIEBzaW5jZSAgICAzLjE3LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNy4wXG5cdFx0ICovXG5cdFx0aXNfZmlyc3RfaW5fY291cnNlOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0Ly8gaWYgaXQncyBub3QgdGhlIGZpcnN0IGl0ZW0gaW4gdGhlIHNlY3Rpb24gaXQgY2FudCBiZSB0aGUgZmlyc3QgbGVzc29uXG5cdFx0XHRpZiAoIHRoaXMuY29sbGVjdGlvbi5pbmRleE9mKCB0aGlzICkgKSB7XG5cdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gaWYgaXQncyBub3QgdGhlIGZpcnN0IHNlY3Rpb24gaXQgY2FudCcgYmUgZmlyc3QgbGVzc29uXG5cdFx0XHR2YXIgc2VjdGlvbiA9IHRoaXMuZ2V0X3BhcmVudCgpO1xuXHRcdFx0aWYgKCBzZWN0aW9uLmNvbGxlY3Rpb24uaW5kZXhPZiggc2VjdGlvbiApICkge1xuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHR9XG5cblx0XHRcdC8vIGl0J3MgZmlyc3QgbGVzc29uIGluIGZpcnN0IHNlY3Rpb25cblx0XHRcdHJldHVybiB0cnVlO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIEluaXRpYWxpemUgbGVzc29uIGFzc2lnbm1lbnRzICppZiogdGhlIGFzc2lnbm1lbnRzIGFkZG9uIGlzIGF2YWlsYWxiZSBhbmQgZW5hYmxlZFxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTcuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE3LjBcblx0XHQgKi9cblx0XHRtYXliZV9pbml0X2Fzc2lnbm1lbnRzOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0aWYgKCAhIHdpbmRvdy5sbG1zX2J1aWxkZXIuYXNzaWdubWVudHMgKSB7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblxuXHRcdFx0dGhpcy5yZWxhdGlvbnNoaXBzLmNoaWxkcmVuLmFzc2lnbm1lbnQgPSB7XG5cdFx0XHRcdGNsYXNzOiAnQXNzaWdubWVudCcsXG5cdFx0XHRcdGNvbmRpdGlvbmFsOiBmdW5jdGlvbiggbW9kZWwgKSB7XG5cdFx0XHRcdFx0Ly8gaWYgYXNzaWdubWVudCBpcyBlbmFibGVkIE9SIG5vdCBlbmFibGVkIGJ1dCB3ZSBoYXZlIHNvbWUgYXNzaWdubWVudCBkYXRhIGFzIGFuIG9ialxuXHRcdFx0XHRcdHJldHVybiAoICd5ZXMnID09PSBtb2RlbC5nZXQoICdhc3NpZ25tZW50X2VuYWJsZWQnICkgfHwgISBfLmlzRW1wdHkoIG1vZGVsLmdldCggJ2Fzc2lnbm1lbnQnICkgKSApO1xuXHRcdFx0XHR9LFxuXHRcdFx0XHRtb2RlbDogJ2xsbXNfYXNzaWdubWVudCcsXG5cdFx0XHRcdHR5cGU6ICdtb2RlbCcsXG5cdFx0XHR9O1xuXG5cdFx0fSxcblxuXHR9LCBSZWxhdGlvbnNoaXBzLCBVdGlsaXRpZXMgKSApO1xuXG59ICk7XG5cbi8qKlxuICogTGVzc29ucyBDb2xsZWN0aW9uXG4gKiBAc2luY2UgICAgMy4xMy4wXG4gKiBAdmVyc2lvbiAgMy4xNy4wXG4gKi9cbmRlZmluZSggJ0NvbGxlY3Rpb25zL0xlc3NvbnMnLFsgJ01vZGVscy9MZXNzb24nIF0sIGZ1bmN0aW9uKCBtb2RlbCApIHtcblxuXHRyZXR1cm4gQmFja2JvbmUuQ29sbGVjdGlvbi5leHRlbmQoIHtcblxuXHRcdC8qKlxuXHRcdCAqIE1vZGVsIGZvciBjb2xsZWN0aW9uIGl0ZW1zXG5cdFx0ICogQHR5cGUgIG9ialxuXHRcdCAqL1xuXHRcdG1vZGVsOiBtb2RlbCxcblxuXHRcdC8qKlxuXHRcdCAqIEluaXRpYWxpemVyXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTcuMFxuXHRcdCAqL1xuXHRcdGluaXRpYWxpemU6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHQvLyByZW9yZGVyIGNhbGxlZCBieSBMZXNzb25MaXN0IHZpZXcgd2hlbiBzb3J0YWJsZSBkcm9wcyBvY2N1clxuXHRcdFx0dGhpcy5vbiggJ3Jlb3JkZXInLCB0aGlzLm9uX3Jlb3JkZXIgKTtcblxuXHRcdFx0Ly8gd2hlbiBhIGxlc3NvbiBpcyBhZGRlZCBvciByZW1vdmVkLCB1cGRhdGUgb3JkZXJcblx0XHRcdHRoaXMub24oICdhZGQnLCB0aGlzLm9uX3Jlb3JkZXIgKTtcblx0XHRcdHRoaXMub24oICdyZW1vdmUnLCB0aGlzLm9uX3Jlb3JkZXIgKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBPbiBsZXNzb24gcmVvcmRlciBjYWxsYmFja1xuXHRcdCAqXG5cdFx0ICogVXBkYXRlIHRoZSBvcmRlciBhdHRyIG9mIGVhY2ggbGVzc29uIHRvIHJlZmxlY3QgdGhlIG5ldyBsZXNzb24gb3JkZXJcblx0XHQgKiBWYWxpZGF0ZSBwcmVyZXF1aXNpdGUgKGlmIHNldCkgYW5kIHVuc2V0IGl0IGlmIGl0J3Mgbm8gbG9uZ2VyIGEgdmFsaWQgcHJlcmVxXG5cdFx0ICpcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE3LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNy4wXG5cdFx0ICovXG5cdFx0b25fcmVvcmRlcjogZnVuY3Rpb24oKSB7XG5cdFx0XHR0aGlzLnVwZGF0ZV9vcmRlcigpO1xuXHRcdFx0dGhpcy52YWxpZGF0ZV9wcmVyZXFzKCk7XG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFVwZGF0ZSBsZXNzb24gb3JkZXIgYXR0cmlidXRlIG9mIGFsbCBsZXNzb25zIHdoZW4gbGVzc29ucyBhcmUgcmVvcmRlcmVkXG5cdFx0ICogQHJldHVybiAgICAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gICAgIDMuMTcuMFxuXHRcdCAqL1xuXHRcdHVwZGF0ZV9vcmRlcjogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHRoaXMuZWFjaCggZnVuY3Rpb24oIGxlc3NvbiApIHtcblx0XHRcdFx0bGVzc29uLnNldCggJ29yZGVyJywgdGhpcy5pbmRleE9mKCBsZXNzb24gKSArIDEgKTtcblx0XHRcdH0sIHRoaXMgKTtcblxuXHRcdH0sXG5cblxuXHRcdC8qKlxuXHRcdCAqIFZhbGlkYXRlIHByZXJlcXVpc2l0ZSAoaWYgc2V0KSBhbmQgdW5zZXQgaXQgaWYgaXQncyBubyBsb25nZXIgYSB2YWxpZCBwcmVyZXFcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE3LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNy4wXG5cdFx0ICovXG5cdFx0dmFsaWRhdGVfcHJlcmVxczogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHRoaXMuZWFjaCggZnVuY3Rpb24oIGxlc3NvbiApIHtcblxuXHRcdFx0XHQvLyB2YWxpZGF0ZSBwcmVyZXFzXG5cdFx0XHRcdGlmICggJ3llcycgPT09IGxlc3Nvbi5nZXQoICdoYXNfcHJlcmVxdWlzaXRlJyApICkge1xuXHRcdFx0XHRcdHZhciB2YWxpZCA9IF8ucGx1Y2soIF8uZmxhdHRlbiggXy5wbHVjayggbGVzc29uLmdldF9hdmFpbGFibGVfcHJlcmVxX29wdGlvbnMoKSwgJ29wdGlvbnMnICkgKSwgJ2tleScgKTtcblx0XHRcdFx0XHRpZiAoIC0xID09PSB2YWxpZC5pbmRleE9mKCBsZXNzb24uZ2V0KCAncHJlcmVxdWlzaXRlJyApICogMSApICkge1xuXHRcdFx0XHRcdFx0bGVzc29uLnNldCgge1xuXHRcdFx0XHRcdFx0XHRwcmVyZXF1aXNpdGU6IDAsXG5cdFx0XHRcdFx0XHRcdGhhc19wcmVyZXF1aXNpdGU6ICdubycsXG5cdFx0XHRcdFx0XHR9ICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cblx0XHRcdH0sIHRoaXMgKTtcblxuXHRcdH0sXG5cblx0fSApO1xuXG59ICk7XG5cbi8qKlxuICogUXVpeiBRdWVzdGlvbiBUeXBlIENvbGxlY3Rpb25cbiAqIEBzaW5jZSAgICAzLjE2LjBcbiAqIEB2ZXJzaW9uICAzLjE2LjBcbiAqL1xuZGVmaW5lKCAnQ29sbGVjdGlvbnMvUXVlc3Rpb25UeXBlcycsWyAnTW9kZWxzL1F1ZXN0aW9uVHlwZScgXSwgZnVuY3Rpb24oIG1vZGVsICkge1xuXG5cdHJldHVybiBCYWNrYm9uZS5Db2xsZWN0aW9uLmV4dGVuZCgge1xuXG5cdFx0LyoqXG5cdFx0ICogTW9kZWwgZm9yIGNvbGxlY3Rpb24gaXRlbXNcblx0XHQgKiBAdHlwZSAgb2JqXG5cdFx0ICovXG5cdFx0bW9kZWw6IG1vZGVsLFxuXG5cdFx0LyoqXG5cdFx0ICogSW5pdGlhbGl6ZXJcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0aW5pdGlhbGl6ZTogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHRoaXMub24oICdhZGQnLCB0aGlzLmNvbXBhcmF0b3IgKTtcblx0XHRcdHRoaXMub24oICdyZW1vdmUnLCB0aGlzLmNvbXBhcmF0b3IgKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBDb21wYXJhdG9yIChzb3J0cyBjb2xsZWN0aW9uKVxuXHRcdCAqIEBwYXJhbSAgICBvYmogICBtb2RlbCAgUXVlc3Rpb25UeXBlIG1vZGVsXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGNvbXBhcmF0b3I6IGZ1bmN0aW9uKCBtb2RlbCApIHtcblxuXHRcdFx0cmV0dXJuIG1vZGVsLmdldCggJ2dyb3VwJyApLm9yZGVyO1xuXG5cdFx0fSxcblxuXHR9ICk7XG5cbn0gKTtcblxuLyoqXG4gKiBTZWN0aW9uIE1vZGVsXG4gKiBAc2luY2UgICAgMy4xNi4wXG4gKiBAdmVyc2lvbiAgMy4xNi4xMlxuICovXG5kZWZpbmUoICdNb2RlbHMvU2VjdGlvbicsWyAnQ29sbGVjdGlvbnMvTGVzc29ucycsICdNb2RlbHMvX1JlbGF0aW9uc2hpcHMnIF0sIGZ1bmN0aW9uKCBMZXNzb25zLCBSZWxhdGlvbnNoaXBzICkge1xuXG5cdHJldHVybiBCYWNrYm9uZS5Nb2RlbC5leHRlbmQoIF8uZGVmYXVsdHMoIHtcblxuXHRcdHJlbGF0aW9uc2hpcHM6IHtcblx0XHRcdHBhcmVudDoge1xuXHRcdFx0XHRtb2RlbDogJ2NvdXJzZScsXG5cdFx0XHRcdHR5cGU6ICdtb2RlbCcsXG5cdFx0XHR9LFxuXHRcdFx0Y2hpbGRyZW46IHtcblx0XHRcdFx0bGVzc29uczoge1xuXHRcdFx0XHRcdGNsYXNzOiAnTGVzc29ucycsXG5cdFx0XHRcdFx0bW9kZWw6ICdsZXNzb24nLFxuXHRcdFx0XHRcdHR5cGU6ICdjb2xsZWN0aW9uJyxcblx0XHRcdFx0fSxcblx0XHRcdH1cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogTmV3IHNlY3Rpb24gZGVmYXVsdHNcblx0XHQgKiBAcmV0dXJuICAgb2JqXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRkZWZhdWx0czogZnVuY3Rpb24oKSB7XG5cdFx0XHRyZXR1cm4ge1xuXHRcdFx0XHRpZDogXy51bmlxdWVJZCggJ3RlbXBfJyApLFxuXHRcdFx0XHRsZXNzb25zOiBbXSxcblx0XHRcdFx0b3JkZXI6IHRoaXMuY29sbGVjdGlvbiA/IHRoaXMuY29sbGVjdGlvbi5sZW5ndGggKyAxIDogMSxcblx0XHRcdFx0cGFyZW50X2NvdXJzZTogd2luZG93LmxsbXNfYnVpbGRlci5jb3Vyc2UuaWQsXG5cdFx0XHRcdHRpdGxlOiBMTE1TLmwxMG4udHJhbnNsYXRlKCAnTmV3IFNlY3Rpb24nICksXG5cdFx0XHRcdHR5cGU6ICdzZWN0aW9uJyxcblxuXHRcdFx0XHRfZXhwYW5kZWQ6IGZhbHNlLFxuXHRcdFx0XHRfc2VsZWN0ZWQ6IGZhbHNlLFxuXHRcdFx0fTtcblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogSW5pdGlhbGl6ZVxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRpbml0aWFsaXplOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0dGhpcy5zdGFydFRyYWNraW5nKCk7XG5cdFx0XHR0aGlzLmluaXRfcmVsYXRpb25zaGlwcygpO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIEFkZCBhIGxlc3NvbiB0byB0aGUgc2VjdGlvblxuXHRcdCAqIEBwYXJhbSAgICBvYmogICBkYXRhICAgICBoYXNoIG9mIGxlc3NvbiBkYXRhIChjcmVhdGVzIG5ldyBsZXNzb24pXG5cdFx0ICogICAgICAgICAgICAgICAgICAgICAgICAgIG9yIGV4aXN0aW5nIGxlc3NvbiBhcyBhIEJhY2tib25lLk1vZGVsXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIG9wdGlvbnMgIGhhcyBvZiBvcHRpb25zXG5cdFx0ICogQHJldHVybiAgIG9iaiAgICAgICAgICAgIEJhY2tib25lLk1vZGVsIG9mIHRoZSBuZXcvdXBkYXRlZCBsZXNzb25cblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMTFcblx0XHQgKi9cblx0XHRhZGRfbGVzc29uOiBmdW5jdGlvbiggZGF0YSwgb3B0aW9ucyApIHtcblxuXHRcdFx0ZGF0YSA9IGRhdGEgfHwge307XG5cdFx0XHRvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcblxuXHRcdFx0aWYgKCBkYXRhIGluc3RhbmNlb2YgQmFja2JvbmUuTW9kZWwgKSB7XG5cdFx0XHRcdGRhdGEuc2V0KCAncGFyZW50X3NlY3Rpb24nLCB0aGlzLmdldCggJ2lkJyApICk7XG5cdFx0XHRcdGRhdGEuc2V0X3BhcmVudCggdGhpcyApO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0ZGF0YS5wYXJlbnRfc2VjdGlvbiA9IHRoaXMuZ2V0KCAnaWQnICk7XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiB0aGlzLmdldCggJ2xlc3NvbnMnICkuYWRkKCBkYXRhLCBvcHRpb25zICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogUmV0cmlldmUgdGhlIHRyYW5zbGF0ZWQgcG9zdCB0eXBlIG5hbWUgZm9yIHRoZSBtb2RlbCdzIHR5cGVcblx0XHQgKiBAcGFyYW0gICAgYm9vbCAgICAgcGx1cmFsICBpZiB0cnVlLCByZXR1cm5zIHRoZSBwbHVyYWwsIG90aGVyd2lzZSByZXR1cm5zIHNpbmd1bGFyXG5cdFx0ICogQHJldHVybiAgIHN0cmluZ1xuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjEyXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMTJcblx0XHQgKi9cblx0XHRnZXRfbDEwbl90eXBlOiBmdW5jdGlvbiggcGx1cmFsICkge1xuXG5cdFx0XHRpZiAoIHBsdXJhbCApIHtcblx0XHRcdFx0cmV0dXJuIExMTVMubDEwbi50cmFuc2xhdGUoICdzZWN0aW9ucycgKTtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIExMTVMubDEwbi50cmFuc2xhdGUoICdzZWN0aW9uJyApO1xuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBHZXQgbmV4dCBzZWN0aW9uIGluIHRoZSBjb2xsZWN0aW9uXG5cdFx0ICogQHBhcmFtICAgIGJvb2wgICAgIGNpcmN1bGFyICAgaWYgdHJ1ZSBoYW5kbGVzIHRoZSBjb2xsZWN0aW9uIGluIGEgY2lyY2xlXG5cdFx0ICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXHRpZiBjdXJyZW50IGlzIHRoZSBsYXN0IHNlY3Rpb24sIHJldHVybnMgdGhlIGZpcnN0IHNlY3Rpb25cblx0XHQgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcdGlmIGN1cnJlbnQgaXMgdGhlIGZpcnN0IHNlY3Rpb24sIHJldHVybnMgdGhlIGxhc3Qgc2VjdGlvblxuXHRcdCAqIEByZXR1cm4gICBvYmp8ZmFsc2Vcblx0XHQgKiBAc2luY2UgICAgMy4xNi4xMVxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjExXG5cdFx0ICovXG5cdFx0Z2V0X25leHQ6IGZ1bmN0aW9uKCBjaXJjdWxhciApIHtcblx0XHRcdHJldHVybiB0aGlzLl9nZXRfc2libGluZyggJ25leHQnLCBjaXJjdWxhciApO1xuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBHZXQgcHJldiBzZWN0aW9uIGluIHRoZSBjb2xsZWN0aW9uXG5cdFx0ICogQHBhcmFtICAgIGJvb2wgICAgIGNpcmN1bGFyICAgaWYgdHJ1ZSBoYW5kbGVzIHRoZSBjb2xsZWN0aW9uIGluIGEgY2lyY2xlXG5cdFx0ICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXHRpZiBjdXJyZW50IGlzIHRoZSBsYXN0IHNlY3Rpb24sIHJldHVybnMgdGhlIGZpcnN0IHNlY3Rpb25cblx0XHQgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcdGlmIGN1cnJlbnQgaXMgdGhlIGZpcnN0IHNlY3Rpb24sIHJldHVybnMgdGhlIGxhc3Qgc2VjdGlvblxuXHRcdCAqIEByZXR1cm4gICBvYmp8ZmFsc2Vcblx0XHQgKiBAc2luY2UgICAgMy4xNi4xMVxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjExXG5cdFx0ICovXG5cdFx0Z2V0X3ByZXY6IGZ1bmN0aW9uKCBjaXJjdWxhciApIHtcblx0XHRcdHJldHVybiB0aGlzLl9nZXRfc2libGluZyggJ3ByZXYnLCBjaXJjdWxhciApO1xuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBHZXQgYSBzaWJsaW5nIHNlY3Rpb25cblx0XHQgKiBAcGFyYW0gICAgc3RyaW5nICAgZGlyZWN0aW9uICBzaWJsaW5ncyBkaXJlY3Rpb24gW25leHR8cHJldl1cblx0XHQgKiBAcGFyYW0gICAgYm9vbCAgICAgY2lyY3VsYXIgICBpZiB0cnVlIGhhbmRsZXMgdGhlIGNvbGxlY3Rpb24gaW4gYSBjaXJjbGVcblx0XHQgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcdGlmIGN1cnJlbnQgaXMgdGhlIGxhc3Qgc2VjdGlvbiwgcmV0dXJucyB0aGUgZmlyc3Qgc2VjdGlvblxuXHRcdCAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFx0aWYgY3VycmVudCBpcyB0aGUgZmlyc3Qgc2VjdGlvbiwgcmV0dXJucyB0aGUgbGFzdCBzZWN0aW9uXG5cdFx0ICogQHJldHVybiAgIG9ianxmYWxzZVxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjExXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMTFcblx0XHQgKi9cblx0XHRfZ2V0X3NpYmxpbmc6IGZ1bmN0aW9uKCBkaXJlY3Rpb24sIGNpcmN1bGFyICkge1xuXG5cdFx0XHRjaXJjdWxhciA9ICggJ3VuZGVmaW5lZCcgPT09IGNpcmN1bGFyICkgPyB0cnVlIDogY2lyY3VsYXI7XG5cblx0XHRcdHZhciBtYXggPSB0aGlzLmNvbGxlY3Rpb24uc2l6ZSgpIC0gMSxcblx0XHRcdFx0aW5kZXggPSB0aGlzLmNvbGxlY3Rpb24uaW5kZXhPZiggdGhpcyApLFxuXHRcdFx0XHRzaWJsaW5nX2luZGV4O1xuXG5cdFx0XHRpZiAoICduZXh0JyA9PT0gZGlyZWN0aW9uICkge1xuXHRcdFx0XHRzaWJsaW5nX2luZGV4ID0gaW5kZXggKyAxO1xuXHRcdFx0fSBlbHNlIGlmICggJ3ByZXYnID09PSBkaXJlY3Rpb24gKSB7XG5cdFx0XHRcdHNpYmxpbmdfaW5kZXggPSBpbmRleCAtIDE7XG5cdFx0XHR9XG5cblx0XHRcdC8vIGRvbnQgcmV0cmlldmUgZ3JlYXRlciB0aGFuIG1heCBvciBsZXNzIHRoYW4gbWluXG5cdFx0XHRpZiAoIHNpYmxpbmdfaW5kZXggPD0gbWF4IHx8IHNpYmxpbmdfaW5kZXggPD0gMCApIHtcblxuXHRcdFx0XHRyZXR1cm4gdGhpcy5jb2xsZWN0aW9uLmF0KCBzaWJsaW5nX2luZGV4ICk7XG5cblx0XHRcdH0gZWxzZSBpZiAoIGNpcmN1bGFyICkge1xuXG5cdFx0XHRcdGlmICggJ25leHQnID09PSBkaXJlY3Rpb24gKSB7XG5cdFx0XHRcdFx0cmV0dXJuIHRoaXMuY29sbGVjdGlvbi5maXJzdCgpO1xuXHRcdFx0XHR9IGVsc2UgaWYgKCAncHJldicgPT09IGRpcmVjdGlvbiApIHtcblx0XHRcdFx0XHRyZXR1cm4gdGhpcy5jb2xsZWN0aW9uLmxhc3QoKTtcblx0XHRcdFx0fVxuXG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBmYWxzZTtcblxuXHRcdH0sXG5cblx0fSwgUmVsYXRpb25zaGlwcyApICk7XG5cbn0gKTtcblxuLyoqXG4gKiBTZWN0aW9ucyBDb2xsZWN0aW9uXG4gKiBAc2luY2UgICAgMy4xNi4wXG4gKiBAdmVyc2lvbiAgMy4xNi4wXG4gKi9cbmRlZmluZSggJ0NvbGxlY3Rpb25zL1NlY3Rpb25zJyxbICdNb2RlbHMvU2VjdGlvbicgXSwgZnVuY3Rpb24oIG1vZGVsICkge1xuXG5cdHJldHVybiBCYWNrYm9uZS5Db2xsZWN0aW9uLmV4dGVuZCgge1xuXG5cdFx0LyoqXG5cdFx0ICogTW9kZWwgZm9yIGNvbGxlY3Rpb24gaXRlbXNcblx0XHQgKiBAdHlwZSAgb2JqXG5cdFx0ICovXG5cdFx0bW9kZWw6IG1vZGVsLFxuXG5cdFx0LyoqXG5cdFx0ICogSW5pdGlhbGl6ZVxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRpbml0aWFsaXplOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0dmFyIHNlbGYgPSB0aGlzO1xuXG5cdFx0XHQvLyByZW9yZGVyIGNhbGxlZCBieSBTZWN0aW9uTGlzdCB2aWV3IHdoZW4gc29ydGFibGUgZHJvcHMgb2NjdXJcblx0XHRcdHRoaXMub24oICdyZW9yZGVyJywgdGhpcy51cGRhdGVfb3JkZXIgKTtcblxuXHRcdFx0Ly8gd2hlbiBhIHNlY3Rpb24gaXMgYWRkZWQgb3IgcmVtb3ZlZCwgdXBkYXRlIG9yZGVyXG5cdFx0XHR0aGlzLm9uKCAnYWRkJywgdGhpcy51cGRhdGVfb3JkZXIgKTtcblx0XHRcdHRoaXMub24oICdyZW1vdmUnLCB0aGlzLnVwZGF0ZV9vcmRlciApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFVwZGF0ZSB0aGUgb3JkZXIgYXR0ciBvZiBlYWNoIHNlY3Rpb24gaW4gdGhlIGxpc3QgdG8gcmVmbGVjdCB0aGUgb3JkZXIgb2YgdGhlIGNvbGxlY3Rpb25cblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0dXBkYXRlX29yZGVyOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0dmFyIHNlbGYgPSB0aGlzO1xuXG5cdFx0XHR0aGlzLmVhY2goIGZ1bmN0aW9uKCBzZWN0aW9uICkge1xuXG5cdFx0XHRcdHNlY3Rpb24uc2V0KCAnb3JkZXInLCBzZWxmLmluZGV4T2YoIHNlY3Rpb24gKSArIDEgKTtcblxuXHRcdFx0fSApO1xuXG5cdFx0fSxcblxuXHR9ICk7XG5cbn0gKTtcblxuLyoqXG4gKiBMZXNzb25zIENvbGxlY3Rpb25cbiAqIEBzaW5jZSAgICAzLjEzLjBcbiAqIEB2ZXJzaW9uICAzLjE2LjBcbiAqL1xuZGVmaW5lKCAnQ29sbGVjdGlvbnMvbG9hZGVyJyxbXG5cdFx0J0NvbGxlY3Rpb25zL0xlc3NvbnMnLFxuXHRcdCdDb2xsZWN0aW9ucy9RdWVzdGlvbkNob2ljZXMnLFxuXHRcdCdDb2xsZWN0aW9ucy9RdWVzdGlvbnMnLFxuXHRcdCdDb2xsZWN0aW9ucy9RdWVzdGlvblR5cGVzJyxcblx0XHQnQ29sbGVjdGlvbnMvU2VjdGlvbnMnXG5cdF0sIGZ1bmN0aW9uKFxuXHRcdExlc3NvbnMsXG5cdFx0UXVlc3Rpb25DaG9pY2VzLFxuXHRcdFF1ZXN0aW9ucyxcblx0XHRRdWVzdGlvblR5cGVzLFxuXHRcdFNlY3Rpb25zXG5cdCkge1xuXG5cdHJldHVybiB7XG5cdFx0TGVzc29uczogTGVzc29ucyxcblx0XHRRdWVzdGlvbkNob2ljZXM6IFF1ZXN0aW9uQ2hvaWNlcyxcblx0XHRRdWVzdGlvbnM6IFF1ZXN0aW9ucyxcblx0XHRRdWVzdGlvblR5cGVzOiBRdWVzdGlvblR5cGVzLFxuXHRcdFNlY3Rpb25zOiBTZWN0aW9ucyxcblx0fTtcblxufSApO1xuXG4vKipcbiAqIEFic3RyYWN0IExpZnRlckxNUyBNb2RlbFxuICogQHNpbmNlICAgIDMuMTcuMFxuICogQHZlcnNpb24gIDMuMTcuMFxuICovXG5kZWZpbmUoICdNb2RlbHMvQWJzdHJhY3QnLFsgJ01vZGVscy9fUmVsYXRpb25zaGlwcycsICdNb2RlbHMvX1V0aWxpdGllcycgXSwgZnVuY3Rpb24oIFJlbGF0aW9uc2hpcHMsIFV0aWxpdGllcyApIHtcblxuXHRyZXR1cm4gQmFja2JvbmUuTW9kZWwuZXh0ZW5kKCBfLmRlZmF1bHRzKCB7fSwgUmVsYXRpb25zaGlwcywgVXRpbGl0aWVzICkgKTtcblxufSApO1xuXG4vKipcbiAqIENvdXJzZSBNb2RlbFxuICogQHNpbmNlICAgIDMuMTYuMFxuICogQHZlcnNpb24gIDMuMTYuMTFcbiAqL1xuZGVmaW5lKCAnTW9kZWxzL0NvdXJzZScsWyAnQ29sbGVjdGlvbnMvU2VjdGlvbnMnLCAnTW9kZWxzL19SZWxhdGlvbnNoaXBzJywgJ01vZGVscy9fVXRpbGl0aWVzJyBdLCBmdW5jdGlvbiggU2VjdGlvbnMsIFJlbGF0aW9uc2hpcHMsIFV0aWxpdGllcyApIHtcblxuXHRyZXR1cm4gQmFja2JvbmUuTW9kZWwuZXh0ZW5kKCBfLmRlZmF1bHRzKCB7XG5cblx0XHRyZWxhdGlvbnNoaXBzOiB7XG5cdFx0XHRjaGlsZHJlbjoge1xuXHRcdFx0XHRzZWN0aW9uczoge1xuXHRcdFx0XHRcdGNsYXNzOiAnU2VjdGlvbnMnLFxuXHRcdFx0XHRcdG1vZGVsOiAnc2VjdGlvbicsXG5cdFx0XHRcdFx0dHlwZTogJ2NvbGxlY3Rpb24nLFxuXHRcdFx0XHR9LFxuXHRcdFx0fVxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBOZXcgQ291cnNlIERlZmF1bHRzXG5cdFx0ICogQHJldHVybiAgIG9ialxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0ZGVmYXVsdHM6IGZ1bmN0aW9uKCkge1xuXHRcdFx0cmV0dXJuIHtcblx0XHRcdFx0ZWRpdF91cmw6ICcnLFxuXHRcdFx0XHRzZWN0aW9uczogW10sXG5cdFx0XHRcdHRpdGxlOiAnTmV3IENvdXJzZScsXG5cdFx0XHRcdHR5cGU6ICdjb3Vyc2UnLFxuXHRcdFx0XHR2aWV3X3VybDogJycsXG5cdFx0XHR9XG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIEluaXRcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0aW5pdGlhbGl6ZTogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHRoaXMuc3RhcnRUcmFja2luZygpO1xuXHRcdFx0dGhpcy5pbml0X3JlbGF0aW9uc2hpcHMoKTtcblxuXHRcdFx0Ly8gU2lkZWJhciBcIk5ldyBTZWN0aW9uXCIgYnV0dG9uIGJyb2FkY2FzdFxuXHRcdFx0QmFja2JvbmUucHViU3ViLm9uKCAnYWRkLW5ldy1zZWN0aW9uJywgdGhpcy5hZGRfc2VjdGlvbiwgdGhpcyApO1xuXG5cdFx0XHQvLyBTaWRlYmFyIFwiTmV3IExlc3NvblwiIGJ1dHRvbiBicm9hZGNhc3Rcblx0XHRcdEJhY2tib25lLnB1YlN1Yi5vbiggJ2FkZC1uZXctbGVzc29uJywgdGhpcy5hZGRfbGVzc29uLCB0aGlzICk7XG5cblx0XHRcdEJhY2tib25lLnB1YlN1Yi5vbiggJ2xlc3Nvbi1zZWFyY2gtc2VsZWN0JywgdGhpcy5hZGRfZXhpc3RpbmdfbGVzc29uLCB0aGlzICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogQWRkIGFuIGV4aXN0aW5nIGxlc3NvbiB0byB0aGUgY291cnNlXG5cdFx0ICogRHVwbGljYXRlIGEgbGVzc29uIGZyb20gdGhpcyBvciBhbm90aGVyIGNvdXJzZSBvciBhdHRhY2ggYW4gb3JwaGFuZWQgbGVzc29uXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIGxlc3NvbiAgbGVzc29uIGRhdGEgb2JqXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMTFcblx0XHQgKi9cblx0XHRhZGRfZXhpc3RpbmdfbGVzc29uOiBmdW5jdGlvbiggbGVzc29uICkge1xuXG5cdFx0XHR2YXIgZGF0YSA9IGxlc3Nvbi5kYXRhO1xuXG5cdFx0XHRpZiAoICdjbG9uZScgPT09IGxlc3Nvbi5hY3Rpb24gKSB7XG5cblx0XHRcdFx0ZGVsZXRlIGRhdGEuaWQ7XG5cdFx0XHRcdGlmICggZGF0YS5xdWl6ICkge1xuXHRcdFx0XHRcdGRlbGV0ZSBkYXRhLnF1aXo7XG5cdFx0XHRcdFx0ZGF0YS5xdWl6X2VuYWJsZWQgPSAnbm8nO1xuXHRcdFx0XHR9XG5cblx0XHRcdH0gZWxzZSB7XG5cblx0XHRcdFx0ZGF0YS5fZm9yY2VTeW5jID0gdHJ1ZTtcblxuXHRcdFx0fVxuXG5cdFx0XHRkZWxldGUgZGF0YS5vcmRlcjtcblx0XHRcdGRlbGV0ZSBkYXRhLnBhcmVudF9jb3Vyc2U7XG5cdFx0XHRkZWxldGUgZGF0YS5wYXJlbnRfc2VjdGlvbjtcblxuXHRcdFx0dGhpcy5hZGRfbGVzc29uKCBkYXRhICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogQWRkIGEgbmV3IGxlc3NvbiB0byB0aGUgY291cnNlXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIGRhdGEgICBsZXNzb24gZGF0YVxuXHRcdCAqIEByZXR1cm4gICBvYmogICAgICAgICAgQmFja2JvbmUuTW9kZWwgb2YgdGhlIGxlc3NvblxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0YWRkX2xlc3NvbjogZnVuY3Rpb24oIGRhdGEgKSB7XG5cblx0XHRcdGRhdGEgPSBkYXRhIHx8IHt9O1xuXHRcdFx0dmFyIG9wdGlvbnMgPSB7fSxcblx0XHRcdFx0c2VjdGlvbjtcblxuXHRcdFx0aWYgKCAhIGRhdGEucGFyZW50X3NlY3Rpb24gKSB7XG5cdFx0XHRcdHNlY3Rpb24gPSB0aGlzLmdldF9zZWxlY3RlZF9zZWN0aW9uKCk7XG5cdFx0XHRcdGlmICggISBzZWN0aW9uICkge1xuXHRcdFx0XHRcdHNlY3Rpb24gPSB0aGlzLmdldCggJ3NlY3Rpb25zJyApLmxhc3QoKTtcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0c2VjdGlvbiA9IHRoaXMuZ2V0KCAnc2VjdGlvbnMnICkuZ2V0KCBkYXRhLnBhcmVudF9zZWN0aW9uICk7XG5cdFx0XHR9XG5cblx0XHRcdGRhdGEuX3NlbGVjdGVkID0gdHJ1ZTtcblxuXHRcdFx0ZGF0YS5wYXJlbnRfY291cnNlID0gdGhpcy5nZXQoICdpZCcgKTtcblxuXHRcdFx0dmFyIGxlc3NvbiA9IHNlY3Rpb24uYWRkX2xlc3NvbiggZGF0YSwgb3B0aW9ucyApO1xuXHRcdFx0QmFja2JvbmUucHViU3ViLnRyaWdnZXIoICduZXctbGVzc29uLWFkZGVkJywgbGVzc29uICk7XG5cblx0XHRcdC8vIGV4cGFuZCB0aGUgc2VjdGlvblxuXHRcdFx0c2VjdGlvbi5zZXQoICdfZXhwYW5kZWQnLCB0cnVlICk7XG5cblx0XHRcdHJldHVybiBsZXNzb247XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogQWRkIGEgbmV3IHNlY3Rpb24gdG8gdGhlIGNvdXJzZVxuXHRcdCAqIEBwYXJhbSAgICBvYmogICBkYXRhICAgc2VjdGlvbiBkYXRhXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGFkZF9zZWN0aW9uOiBmdW5jdGlvbiggZGF0YSApIHtcblxuXHRcdFx0ZGF0YSA9IGRhdGEgfHwge307XG5cdFx0XHR2YXIgc2VjdGlvbnMgPSB0aGlzLmdldCggJ3NlY3Rpb25zJyApLFxuXHRcdFx0XHRvcHRpb25zID0ge30sXG5cdFx0XHRcdHNlbGVjdGVkID0gdGhpcy5nZXRfc2VsZWN0ZWRfc2VjdGlvbigpO1xuXG5cdFx0XHQvLyBpZiBhIHNlY3Rpb24gaXMgc2VsZWN0ZWQsIGFkZCB0aGUgbmV3IHNlY3Rpb24gYWZ0ZXIgdGhlIGN1cnJlbnRseSBzZWxlY3RlZCBvbmVcblx0XHRcdGlmICggc2VsZWN0ZWQgKSB7XG5cdFx0XHRcdG9wdGlvbnMuYXQgPSBzZWN0aW9ucy5pbmRleE9mKCBzZWxlY3RlZCApICsgMTtcblx0XHRcdH1cblxuXHRcdFx0c2VjdGlvbnMuYWRkKCBkYXRhLCBvcHRpb25zICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogUmV0cmlldmUgdGhlIGN1cnJlbnRseSBzZWxlY3RlZCBzZWN0aW9uIGluIHRoZSBjb3Vyc2Vcblx0XHQgKiBAcmV0dXJuICAgb2JqfHVuZGVmaW5lZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0Z2V0X3NlbGVjdGVkX3NlY3Rpb246IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHRyZXR1cm4gdGhpcy5nZXQoICdzZWN0aW9ucycgKS5maW5kKCBmdW5jdGlvbiggbW9kZWwgKSB7XG5cdFx0XHRcdHJldHVybiBtb2RlbC5nZXQoICdfc2VsZWN0ZWQnICk7XG5cdFx0XHR9ICk7XG5cblx0XHR9LFxuXG5cdH0sIFJlbGF0aW9uc2hpcHMsIFV0aWxpdGllcyApICk7XG5cbn0gKTtcblxuLyoqXG4gKiBMb2FkIGFsbCBtb2RlbHNcbiAqIEByZXR1cm4gICBvYmpcbiAqIEBzaW5jZSAgICAzLjE2LjBcbiAqIEB2ZXJzaW9uICAzLjE3LjBcbiAqL1xuZGVmaW5lKCAnTW9kZWxzL2xvYWRlcicsW1xuXHRcdCdNb2RlbHMvQWJzdHJhY3QnLFxuXHRcdCdNb2RlbHMvQ291cnNlJyxcblx0XHQnTW9kZWxzL0ltYWdlJyxcblx0XHQnTW9kZWxzL0xlc3NvbicsXG5cdFx0J01vZGVscy9RdWVzdGlvbicsXG5cdFx0J01vZGVscy9RdWVzdGlvbkNob2ljZScsXG5cdFx0J01vZGVscy9RdWVzdGlvblR5cGUnLFxuXHRcdCdNb2RlbHMvUXVpeicsXG5cdFx0J01vZGVscy9TZWN0aW9uJ1xuXHRdLFxuXHRmdW5jdGlvbihcblx0XHRBYnN0cmFjdCxcblx0XHRDb3Vyc2UsXG5cdFx0SW1hZ2UsXG5cdFx0TGVzc29uLFxuXHRcdFF1ZXN0aW9uLFxuXHRcdFF1ZXN0aW9uQ2hvaWNlLFxuXHRcdFF1ZXN0aW9uVHlwZSxcblx0XHRRdWl6LFxuXHRcdFNlY3Rpb25cblx0KSB7XG5cblx0cmV0dXJuIHtcblx0XHRBYnN0cmFjdDogQWJzdHJhY3QsXG5cdFx0Q291cnNlOiBDb3Vyc2UsXG5cdFx0SW1hZ2U6IEltYWdlLFxuXHRcdExlc3NvbjogTGVzc29uLFxuXHRcdFF1ZXN0aW9uOiBRdWVzdGlvbixcblx0XHRRdWVzdGlvbkNob2ljZTogUXVlc3Rpb25DaG9pY2UsXG5cdFx0UXVlc3Rpb25UeXBlOiBRdWVzdGlvblR5cGUsXG5cdFx0UXVpejogUXVpeixcblx0XHRTZWN0aW9uOiBTZWN0aW9uLFxuXHR9O1xuXG59ICk7XG5cbi8qKlxuICogRGV0YWNoYWJsZSBtb2RlbFxuICogQHR5cGUgICAgIHtPYmplY3R9XG4gKiBAc2luY2UgICAgMy4xNi4xMlxuICogQHZlcnNpb24gIDMuMTYuMTJcbiAqL1xuZGVmaW5lKCAnVmlld3MvX0RldGFjaGFibGUnLFtdLCBmdW5jdGlvbigpIHtcblxuXHRyZXR1cm4ge1xuXG5cdFx0LyoqXG5cdFx0ICogRE9NIEV2ZW50c1xuXHRcdCAqIEB0eXBlICB7T2JqZWN0fVxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjEyXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMTJcblx0XHQgKi9cblx0XHRldmVudHM6IHtcblx0XHRcdCdjbGljayBhW2hyZWY9XCIjbGxtcy1kZXRhY2gtbW9kZWxcIl0nOiAnZGV0YWNoX21vZGVsJyxcblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogRGV0YWNoZXMgYSBtb2RlbCBmcm9tIGl0J3MgcGFyZW50IChkb2Vzbid0IGRlbGV0ZSlcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgZXZlbnQgIGpzIGV2ZW50IG9iamVjdFxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMTJcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4xMlxuXHRcdCAqL1xuXHRcdGRldGFjaF9tb2RlbDogZnVuY3Rpb24oIGV2ZW50ICkge1xuXG5cdFx0XHRpZiAoIGV2ZW50ICkge1xuXHRcdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0XHRldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcblx0XHRcdH1cblxuXHRcdFx0dmFyIG1zZyA9IExMTVMubDEwbi5yZXBsYWNlKCAnQXJlIHlvdSBzdXJlIHlvdSB3YW50IHRvIGRldGFjaCB0aGlzICVzPycsIHtcblx0XHRcdFx0JyVzJzogdGhpcy5tb2RlbC5nZXRfbDEwbl90eXBlKCksXG5cdFx0XHR9ICk7XG5cblx0XHRcdGlmICggd2luZG93LmNvbmZpcm0oIG1zZyApICkge1xuXG5cdFx0XHRcdGlmICggdGhpcy5tb2RlbC5jb2xsZWN0aW9uICkge1xuXHRcdFx0XHRcdHRoaXMubW9kZWwuY29sbGVjdGlvbi5yZW1vdmUoIHRoaXMubW9kZWwgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIHB1Ymxpc2ggZ2xvYmFsIGV2ZW50XG5cdFx0XHRcdEJhY2tib25lLnB1YlN1Yi50cmlnZ2VyKCAnbW9kZWwtZGV0YWNoZWQnLCB0aGlzLm1vZGVsICk7XG5cblx0XHRcdFx0Ly8gdHJpZ2dlciBsb2NhbCBldmVudCBzbyBleHRlbmRpbmcgdmlld3MgY2FuIHJ1biBvdGhlciBhY3Rpb25zIHdoZXJlIG5lY2Vzc2FyeVxuXHRcdFx0XHR0aGlzLnRyaWdnZXIoICdtb2RlbC10cmFzaGVkJywgdGhpcy5tb2RlbCApO1xuXG5cdFx0XHR9XG5cblx0XHR9LFxuXG5cdH1cblxufSApO1xuXG4vKipcbiAqIEhhbmRsZXMgVVggYW5kIEV2ZW50cyBmb3IgaW5saW5lIGVkaXRpbmcgb2Ygdmlld3NcbiAqIFVzZSB3aXRoIGEgTW9kZWwncyBWaWV3XG4gKiBBbGxvd3MgZWRpdGluZyBtb2RlbC50aXRsZSBmaWVsZCB2aWEgLmxsbXMtZWRpdGFibGUtdGl0bGUgZWxlbWVudHNcbiAqIEB0eXBlICAgICB7T2JqZWN0fVxuICogQHNpbmNlICAgIDMuMTYuMFxuICogQHZlcnNpb24gIDMuMTcuOFxuICovXG5kZWZpbmUoICdWaWV3cy9fRWRpdGFibGUnLFtdLCBmdW5jdGlvbigpIHtcblxuXHRyZXR1cm4ge1xuXG5cdFx0bWVkaWFfbGliOiBudWxsLFxuXG5cdFx0LyoqXG5cdFx0ICogRE9NIEV2ZW50c1xuXHRcdCAqIEB0eXBlICB7T2JqZWN0fVxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNy44XG5cdFx0ICovXG5cdFx0ZXZlbnRzOiB7XG5cdFx0XHQnY2xpY2sgLmxsbXMtYWRkLWltYWdlJzogJ29wZW5fbWVkaWFfbGliJyxcblx0XHRcdCdjbGljayBhW2hyZWY9XCIjbGxtcy1lZGl0LXNsdWdcIl0nOiAnbWFrZV9zbHVnX2VkaXRhYmxlJyxcblx0XHRcdCdjbGljayBhW2hyZWY9XCIjbGxtcy1yZW1vdmUtaW1hZ2VcIl0nOiAncmVtb3ZlX2ltYWdlJyxcblx0XHRcdCdjaGFuZ2UgLmxsbXMtZWRpdGFibGUtc2VsZWN0IHNlbGVjdCc6ICdvbl9zZWxlY3QnLFxuXHRcdFx0J2NoYW5nZSAubGxtcy1zd2l0Y2ggaW5wdXRbdHlwZT1cImNoZWNrYm94XCJdJzogJ3RvZ2dsZV9zd2l0Y2gnLFxuXHRcdFx0J2NoYW5nZSAubGxtcy1lZGl0YWJsZS1yYWRpbyBpbnB1dCc6ICdvbl9yYWRpb19zZWxlY3QnLFxuXHRcdFx0J2ZvY3VzaW4gLmxsbXMtaW5wdXQnOiAnb25fZm9jdXMnLFxuXHRcdFx0J2ZvY3Vzb3V0IC5sbG1zLWlucHV0JzogJ29uX2JsdXInLFxuXHRcdFx0J2tleWRvd24gLmxsbXMtaW5wdXQnOiAnb25fa2V5ZG93bicsXG5cdFx0XHQnaW5wdXQgLmxsbXMtaW5wdXRbdHlwZT1cIm51bWJlclwiXSc6ICdvbl9ibHVyJyxcblx0XHRcdCdwYXN0ZSAubGxtcy1pbnB1dFtkYXRhLWZvcm1hdHRpbmddJzogJ29uX3Bhc3RlJyxcblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogUmV0cmlldmUgYSBsaXN0IG9mIGFsbG93ZWQgdGFncyBmb3IgYSBnaXZlbiBlbGVtZW50XG5cdFx0ICogQHBhcmFtICAgIG9iaiAgICRlbCAgalF1ZXJ5IHNlbGVjdG9yIGZvciB0aGUgZWxlbWVudFxuXHRcdCAqIEByZXR1cm4gICBhcnJheVxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNy44XG5cdFx0ICovXG5cdFx0Z2V0X2FsbG93ZWRfdGFnczogZnVuY3Rpb24oICRlbCApIHtcblxuXHRcdFx0aWYgKCAkZWwuYXR0ciggJ2RhdGEtZm9ybWF0dGluZycgKSApIHtcblx0XHRcdFx0cmV0dXJuIF8ubWFwKCAkZWwuYXR0ciggJ2RhdGEtZm9ybWF0dGluZycgKS5zcGxpdCggJywnICksIGZ1bmN0aW9uKCB0YWcgKSB7XG5cdFx0XHRcdFx0cmV0dXJuIHRhZy50cmltKCk7XG5cdFx0XHRcdH0gKTtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIFsgJ2InLCAnaScsICd1JywgJ3N0cm9uZycsICdlbScgXTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBSZXRyaWV2ZSB0aGUgY29udGVudCBvZiBhbiBlbGVtZW50XG5cdFx0ICogQHBhcmFtICAgIG9iaiAgICRlbCAgalF1ZXJ5IG9iamVjdCBvZiB0aGUgZWxlbWVudFxuXHRcdCAqIEByZXR1cm4gICBzdHJpbmdcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTcuOFxuXHRcdCAqL1xuXHRcdGdldF9jb250ZW50OiBmdW5jdGlvbiggJGVsICkge1xuXG5cdFx0XHRpZiAoICdJTlBVVCcgPT09ICRlbFswXS50YWdOYW1lICkge1xuXHRcdFx0XHRyZXR1cm4gJGVsLnZhbCgpO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoICEgJGVsLmF0dHIoICdkYXRhLWZvcm1hdHRpbmcnICkgJiYgISAkZWwuaGFzQ2xhc3MoICdxbC1lZGl0b3InICkgKSB7XG5cdFx0XHRcdHJldHVybiAkZWwudGV4dCgpO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gXy5zdHJpcEZvcm1hdHRpbmcoICRlbC5odG1sKCksIHRoaXMuZ2V0X2FsbG93ZWRfdGFncyggJGVsICkgKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBEZXRlcm1pbmUgaWYgY2hhbmdlcyBoYXZlIGJlZW4gbWFkZSB0byB0aGUgZWxlbWVudFxuXHRcdCAqIEBwYXJhbSAgICB7W29ial19ICAgZXZlbnQgIGpzIGV2ZW50IG9iamVjdFxuXHRcdCAqIEByZXR1cm4gICB7Qm9vbGVhbn0gICAgICAgIHRydWUgd2hlbiBjaGFuZ2VzIGhhdmUgYmVlbiBtYWRlLCBmYWxzZSBvdGhlcndpc2Vcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGhhc19jaGFuZ2VkOiBmdW5jdGlvbiggZXZlbnQgKSB7XG5cdFx0XHR2YXIgJGVsID0gJCggZXZlbnQudGFyZ2V0ICk7XG5cdFx0XHRyZXR1cm4gKCAkZWwuYXR0ciggJ2RhdGEtb3JpZ2luYWwtY29udGVudCcgKSAhPT0gdGhpcy5nZXRfY29udGVudCggJGVsICkgKTtcblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogRW5zdXJlIHRoYXQgbmV3IGNvbnRlbnQgaXMgYXQgbGVhc3QgMSBjaGFyYWN0ZXIgbG9uZ1xuXHRcdCAqIEBwYXJhbSAgICBvYmogICBldmVudCAganMgZXZlbnQgb2JqZWN0XG5cdFx0ICogQHJldHVybiAgIGJvb2xlYW5cblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTcuMlxuXHRcdCAqL1xuXHRcdGlzX3ZhbGlkOiBmdW5jdGlvbiggZXZlbnQgKSB7XG5cblx0XHRcdHZhciBzZWxmID0gdGhpcyxcblx0XHRcdFx0JGVsID0gJCggZXZlbnQudGFyZ2V0ICksXG5cdFx0XHRcdGNvbnRlbnQgPSB0aGlzLmdldF9jb250ZW50KCAkZWwgKSxcblx0XHRcdFx0dHlwZSA9ICRlbC5hdHRyKCAnZGF0YS10eXBlJyApO1xuXG5cdFx0XHRpZiAoICggJGVsLmF0dHIoICdyZXF1aXJlZCcgKSB8fCAkZWwuYXR0ciggJ2RhdGEtcmVxdWlyZWQnICkgKSAmJiBjb250ZW50Lmxlbmd0aCA8IDEgKSB7XG5cdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKCAndXJsJyA9PT0gdHlwZSB8fCAndmlkZW8nID09PSB0eXBlICkge1xuXHRcdFx0XHRpZiAoICEgdGhpcy5fdmFsaWRhdGVfdXJsKCB0aGlzLmdldF9jb250ZW50KCAkZWwgKSApICkge1xuXHRcdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdFx0fVxuXG5cdFx0XHR9IGVsc2UgaWYgKCAncGVybWFsaW5rJyA9PT0gdHlwZSApIHtcblxuXHRcdFx0XHRMTE1TLkFqYXguY2FsbCgge1xuXHRcdFx0XHRcdGRhdGE6IHtcblx0XHRcdFx0XHRcdGFjdGlvbjogJ2xsbXNfYnVpbGRlcicsXG5cdFx0XHRcdFx0XHRhY3Rpb25fdHlwZTogJ2dldF9wZXJtYWxpbmsnLFxuXHRcdFx0XHRcdFx0Y291cnNlX2lkOiB3aW5kb3cubGxtc19idWlsZGVyLkNvdXJzZU1vZGVsLmdldCggJ2lkJyApLFxuXHRcdFx0XHRcdFx0aWQ6IHNlbGYubW9kZWwuZ2V0KCAnaWQnICksXG5cdFx0XHRcdFx0XHR0aXRsZTogc2VsZi5tb2RlbC5nZXQoICd0aXRsZScgKSxcblx0XHRcdFx0XHRcdHNsdWc6IGNvbnRlbnQsXG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRiZWZvcmVTZW5kOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRcdExMTVMuU3Bpbm5lci5zdGFydCggJGVsLmNsb3Nlc3QoICcubGxtcy1lZGl0YWJsZS10b2dnbGUtZ3JvdXAnICksICdzbWFsbCcgKTtcblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdHN1Y2Nlc3M6IGZ1bmN0aW9uKCByICkge1xuXG5cdFx0XHRcdFx0XHRpZiAoIHIucGVybWFsaW5rICYmIHIuc2x1ZyApIHtcblx0XHRcdFx0XHRcdFx0c2VsZi5tb2RlbC5zZXQoICdwZXJtYWxpbmsnLCByLnBlcm1hbGluayApO1xuXHRcdFx0XHRcdFx0XHRzZWxmLm1vZGVsLnNldCggJ25hbWUnLCByLnNsdWcgKTtcblx0XHRcdFx0XHRcdFx0c2VsZi5yZW5kZXIoKTtcblx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSApO1xuXG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiB0cnVlO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIEluaXRpYWxpemUgZGF0ZXBpY2tlciBlbGVtZW50c1xuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTcuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE3LjBcblx0XHQgKi9cblx0XHRpbml0X2RhdGVwaWNrZXJzOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0dGhpcy4kZWwuZmluZCggJy5sbG1zLWVkaXRhYmxlLWRhdGUgaW5wdXQnICkuZWFjaCggZnVuY3Rpb24oKSB7XG5cblx0XHRcdFx0JCggdGhpcyApLmRhdGV0aW1lcGlja2VyKCB7XG5cdFx0XHRcdFx0Zm9ybWF0OiAkKCB0aGlzICkuYXR0ciggJ2RhdGEtZGF0ZS1mb3JtYXQnICkgfHwgJ1ktbS1kIGg6aSBBJyxcblx0XHRcdFx0XHRkYXRlcGlja2VyOiAoIHVuZGVmaW5lZCA9PT0gJCggdGhpcyApLmF0dHIoICdkYXRhLWRhdGUtZGF0ZXBpY2tlcicgKSApID8gdHJ1ZSA6ICggJ3RydWUnID09ICQoIHRoaXMgKS5hdHRyKCAnZGF0YS1kYXRlLWRhdGVwaWNrZXInICkgKSxcblx0XHRcdFx0XHR0aW1lcGlja2VyOiAoIHVuZGVmaW5lZCA9PT0gJCggdGhpcyApLmF0dHIoICdkYXRhLWRhdGUtdGltZXBpY2tlcicgKSApID8gdHJ1ZSA6ICggJ3RydWUnID09ICQoIHRoaXMgKS5hdHRyKCAnZGF0YS1kYXRlLXRpbWVwaWNrZXInICkgKSxcblx0XHRcdFx0XHRvbkNsb3NlOiBmdW5jdGlvbiggY3VycmVudF90aW1lLCAkaW5wdXQgKSB7XG5cdFx0XHRcdFx0XHQkaW5wdXQuYmx1cigpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSApO1xuXG5cdFx0XHR9ICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogSW5pdGlhbGl6ZSBlbGVtZW50cyB0aGF0IGFsbG93IGlubGluZSBmb3JtYXR0aW5nXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGluaXRfZm9ybWF0dGluZ19lbHM6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHR2YXIgc2VsZiA9IHRoaXM7XG5cblx0XHRcdHRoaXMuJGVsLmZpbmQoICcubGxtcy1pbnB1dC1mb3JtYXR0aW5nW2RhdGEtZm9ybWF0dGluZ10nICkuZWFjaCggZnVuY3Rpb24oKSB7XG5cblx0XHRcdFx0dmFyIGZvcm1hdHRpbmcgPSAkKCB0aGlzICkuYXR0ciggJ2RhdGEtZm9ybWF0dGluZycgKS5zcGxpdCggJywnICksXG5cdFx0XHRcdFx0YXR0ciA9ICQoIHRoaXMgKS5hdHRyKCAnZGF0YS1hdHRyaWJ1dGUnICk7XG5cblx0XHRcdFx0dmFyIGVkID0gbmV3IFF1aWxsKCB0aGlzLCB7XG5cdFx0XHRcdFx0bW9kdWxlczoge1xuXHRcdFx0XHRcdFx0dG9vbGJhcjogWyBmb3JtYXR0aW5nIF0sXG5cdFx0XHRcdFx0XHRrZXlib2FyZDoge1xuXHRcdFx0XHRcdFx0XHRiaW5kaW5nczoge1xuXHRcdFx0XHRcdFx0XHRcdHRhYjoge1xuXHRcdFx0XHRcdFx0XHRcdFx0a2V5OiA5LFxuXHRcdFx0XHRcdFx0XHRcdFx0aGFuZGxlcjogZnVuY3Rpb24oIHJhbmdlLCBjb250ZXh0ICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdFx0XHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRcdFx0XHQxMzoge1xuXHRcdFx0XHRcdFx0XHRcdFx0a2V5OiAxMyxcblx0XHRcdFx0XHRcdFx0XHRcdGhhbmRsZXI6IGZ1bmN0aW9uKCByYW5nZSwgY29udGV4dCApIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0ZWQucm9vdC5ibHVyKCk7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdFx0XHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRwbGFjZWhvbGRlcjogJCggdGhpcyApLmF0dHIoICdkYXRhLXBsYWNlaG9sZGVyJyApLFxuXHRcdFx0XHRcdHRoZW1lOiAnYnViYmxlJyxcblx0XHRcdFx0fSApO1xuXG5cdFx0XHRcdGVkLm9uKCAndGV4dC1jaGFuZ2UnLCBmdW5jdGlvbiggZGVsdGEsIG9sZERlbHRhLCBzb3VyY2UgKSB7XG5cdFx0XHRcdFx0c2VsZi5tb2RlbC5zZXQoIGF0dHIsIHNlbGYuZ2V0X2NvbnRlbnQoICQoIGVkLnJvb3QgKSApICk7XG5cdFx0XHRcdH0gKTtcblxuXHRcdFx0XHRCYWNrYm9uZS5wdWJTdWIudHJpZ2dlciggJ2Zvcm1hdHRpbmctZWQtaW5pdCcsIGVkLCAkKCB0aGlzICksIHNlbGYgKTtcblxuXHRcdFx0fSApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIEluaXRpYWxpemUgZWRpdGFibGUgc2VsZWN0IGVsZW1lbnRzXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGluaXRfc2VsZWN0czogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHRoaXMuJGVsLmZpbmQoICcubGxtcy1lZGl0YWJsZS1zZWxlY3Qgc2VsZWN0JyApLmxsbXNTZWxlY3QyKCB7XG5cdFx0XHRcdHdpZHRoOiAnMTAwJScsXG5cdFx0XHR9ICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogQmx1ci9mb2N1c291dCBmdW5jdGlvbiBmb3IgLmxsbXMtZWRpdGFibGUtdGl0bGUgZWxlbWVudHNcblx0XHQgKiBBdXRvbWF0aWNhbGx5IHNhdmVzIGNoYW5nZXMgaWYgY2hhbmdlcyBoYXZlIGJlZW4gbWFkZVxuXHRcdCAqIEBwYXJhbSAgICBvYmogICBldmVudCAganMgZXZlbnQgb2JqZWN0XG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuNlxuXHRcdCAqL1xuXHRcdG9uX2JsdXI6IGZ1bmN0aW9uKCBldmVudCApIHtcblxuXHRcdFx0ZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cblx0XHRcdHRoaXMubW9kZWwuc2V0KCAnX2hhc19mb2N1cycsIGZhbHNlLCB7IHNpbGVudDogdHJ1ZSB9ICk7XG5cblx0XHRcdHZhciBzZWxmID0gdGhpcyxcblx0XHRcdFx0JGVsID0gJCggZXZlbnQudGFyZ2V0ICksXG5cdFx0XHRcdGNoYW5nZWQgPSB0aGlzLmhhc19jaGFuZ2VkKCBldmVudCApO1xuXG5cdFx0XHRpZiAoIGNoYW5nZWQgKSB7XG5cblx0XHRcdFx0aWYgKCAhIHNlbGYuaXNfdmFsaWQoIGV2ZW50ICkgKSB7XG5cdFx0XHRcdFx0c2VsZi5yZXZlcnRfZWRpdHMoIGV2ZW50ICk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0dGhpcy5zYXZlX2VkaXRzKCBldmVudCApO1xuXHRcdFx0XHR9XG5cblx0XHRcdH1cblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBGb2N1cyBldmVudCBmb3IgZWRpdGFibGUgaW5wdXRzXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIGV2ZW50ICBqcyBldmVudCBvYmplY3Rcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjZcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi42XG5cdFx0ICovXG5cdFx0b25fZm9jdXM6IGZ1bmN0aW9uKCBldmVudCApIHtcblxuXHRcdFx0ZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cdFx0XHR0aGlzLm1vZGVsLnNldCggJ19oYXNfZm9jdXMnLCB0cnVlLCB7IHNpbGVudDogdHJ1ZSB9ICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogSGFuZGxlIGNvbnRlbnQgcGFzdGVkIGludG8gY29udGVudGVkaXRhYmxlIGZpZWxkc1xuXHRcdCAqIFRoaXMgd2lsbCBlbnN1cmUgdGhhdCBIVE1MIGZyb20gUlRGIGVkaXRvcnMgaXNuJ3QgcGFzdGVkIGludG8gdGhlIGRvbVxuXHRcdCAqIEBwYXJhbSAgICBvYmogICBldmVudCAganMgZXZlbnQgb2JqXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNy44XG5cdFx0ICogQHZlcnNpb24gIDMuMTcuOFxuXHRcdCAqL1xuXHRcdG9uX3Bhc3RlOiBmdW5jdGlvbiggZXZlbnQgKSB7XG5cblx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHRldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcblxuXHRcdFx0dmFyIHRleHQgPSAoIGV2ZW50Lm9yaWdpbmFsRXZlbnQgfHwgZXZlbnQgKS5jbGlwYm9hcmREYXRhLmdldERhdGEoICd0ZXh0L3BsYWluJyApO1xuXHRcdFx0d2luZG93LmRvY3VtZW50LmV4ZWNDb21tYW5kKCAnaW5zZXJ0VGV4dCcsIGZhbHNlLCB0ZXh0ICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogQ2hhbmdlIGV2ZW50IGZvciBzZWxlY3RhYmxlc1xuXHRcdCAqIEBwYXJhbSAgICBvYmogICBldmVudCAganMgZXZlbnQgb2JqZWN0XG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdG9uX3NlbGVjdDogZnVuY3Rpb24oIGV2ZW50ICkge1xuXG5cdFx0XHR2YXIgJGVsID0gJCggZXZlbnQudGFyZ2V0ICksXG5cdFx0XHRcdG11bHRpID0gKCAkZWwuYXR0ciggJ211bHRpcGxlJyApICksXG5cdFx0XHRcdGF0dHIgPSAkZWwuYXR0ciggJ25hbWUnICksXG5cdFx0XHRcdCRzZWxlY3RlZCA9ICRlbC5maW5kKCAnb3B0aW9uOnNlbGVjdGVkJyApLFxuXHRcdFx0XHR2YWw7XG5cblx0XHRcdGlmICggbXVsdGkgKSB7XG5cdFx0XHRcdHZhbCA9IFtdO1xuXHRcdFx0XHR2YWwgPSAkc2VsZWN0ZWQubWFwKCBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRyZXR1cm4gdGhpcy52YWx1ZTtcblx0XHRcdFx0fSApLmdldCgpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dmFsID0gJHNlbGVjdGVkWzBdLnZhbHVlO1xuXHRcdFx0fVxuXG5cdFx0XHR0aGlzLm1vZGVsLnNldCggYXR0ciwgdmFsICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogQ2hhbmdlIGV2ZW50IGZvciByYWRpbyBlbGVtZW50IGdyb3Vwc1xuXHRcdCAqIEBwYXJhbSAgICBvYmogICBldmVudCAganMgZXZlbnQgb2JqZWN0XG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNy42XG5cdFx0ICogQHZlcnNpb24gIDMuMTcuNlxuXHRcdCAqL1xuXHRcdG9uX3JhZGlvX3NlbGVjdDogZnVuY3Rpb24oIGV2ZW50ICkge1xuXG5cdFx0XHR2YXIgJGVsID0gJCggZXZlbnQudGFyZ2V0ICksXG5cdFx0XHRcdGF0dHIgPSAkZWwuYXR0ciggJ25hbWUnICksXG5cdFx0XHRcdHZhbCA9ICRlbC52YWwoKTtcblxuXHRcdFx0dGhpcy5tb2RlbC5zZXQoIGF0dHIsIHZhbCApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIEtleWRvd24gZnVuY3Rpb24gZm9yIC5sbG1zLWVkaXRhYmxlLXRpdGxlIGVsZW1lbnRzXG5cdFx0ICogQmx1cnNcblx0XHQgKiBAcGFyYW0gICAge29ian0gICBldmVudCAganMgZXZlbnQgb2JqZWN0XG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTcuOFxuXHRcdCAqL1xuXHRcdG9uX2tleWRvd246IGZ1bmN0aW9uKCBldmVudCApIHtcblxuXHRcdFx0ZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cblx0XHRcdHZhciBzZWxmID0gdGhpcyxcblx0XHRcdFx0a2V5ID0gZXZlbnQud2hpY2ggfHwgZXZlbnQua2V5Q29kZSxcblx0XHRcdFx0c2hpZnQgPSBldmVudC5zaGlmdEtleTtcblx0XHRcdFx0Ly8gY3RybCA9IGV2ZW50Lm1ldGFLZXkgfHwgZXZlbnQuY3RybEtleTtcblxuXHRcdFx0c3dpdGNoICgga2V5ICkge1xuXG5cdFx0XHRcdGNhc2UgMTM6IC8vIGVudGVyXG5cdFx0XHRcdFx0Ly8gc2hpZnQgKyBlbnRlciBzaG91bGQgYWRkIGEgcmV0dXJuXG5cdFx0XHRcdFx0aWYgKCAhIHNoaWZ0ICkge1xuXHRcdFx0XHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdFx0XHRcdGV2ZW50LnRhcmdldC5ibHVyKCk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRicmVhaztcblxuXHRcdFx0XHRjYXNlIDI3OiAvLyBlc2NhcGVcblx0XHRcdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0XHRcdHRoaXMucmV2ZXJ0X2VkaXRzKCBldmVudCApO1xuXHRcdFx0XHRcdGV2ZW50LnRhcmdldC5ibHVyKCk7XG5cdFx0XHRcdGJyZWFrO1xuXG5cdFx0XHR9XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogT3BlbiB0aGUgV1AgbWVkaWEgbGliXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIGV2ZW50ICBqcyBldmVudCBvYmplY3Rcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi42XG5cdFx0ICovXG5cdFx0b3Blbl9tZWRpYV9saWI6IGZ1bmN0aW9uKCBldmVudCApIHtcblxuXHRcdFx0ZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cblx0XHRcdHZhciBzZWxmID0gdGhpcyxcblx0XHRcdFx0JGVsID0gJCggZXZlbnQuY3VycmVudFRhcmdldCApO1xuXG5cdFx0XHRpZiAoIHNlbGYubWVkaWFfbGliICkge1xuXG5cdFx0XHRcdHNlbGYubWVkaWFfbGliLnVwbG9hZGVyLnVwbG9hZGVyLnBhcmFtKCAncG9zdF9pZCcgKTtcblxuXHRcdFx0fSBlbHNlIHtcblxuXHRcdFx0XHRzZWxmLm1lZGlhX2xpYiA9IHdwLm1lZGlhLmZyYW1lcy5maWxlX2ZyYW1lID0gd3AubWVkaWEoIHtcblx0XHRcdFx0XHR0aXRsZTogTExNUy5sMTBuLnRyYW5zbGF0ZSggJ1NlbGVjdCBhbiBpbWFnZScgKSxcblx0XHRcdFx0XHRidXR0b246IHtcblx0XHRcdFx0XHRcdHRleHQ6IExMTVMubDEwbi50cmFuc2xhdGUoICdVc2UgdGhpcyBpbWFnZScgKSxcblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdG11bHRpcGxlOiBmYWxzZVx0Ly8gU2V0IHRvIHRydWUgdG8gYWxsb3cgbXVsdGlwbGUgZmlsZXMgdG8gYmUgc2VsZWN0ZWRcblx0XHRcdFx0fSApO1xuXG5cdFx0XHRcdHNlbGYubWVkaWFfbGliLm9uKCAnc2VsZWN0JywgZnVuY3Rpb24oKSB7XG5cblx0XHRcdFx0XHR2YXIgc2l6ZSA9ICRlbC5hdHRyKCAnZGF0YS1pbWFnZS1zaXplJyApLFxuXHRcdFx0XHRcdFx0YXR0YWNobWVudCA9IHNlbGYubWVkaWFfbGliLnN0YXRlKCkuZ2V0KCAnc2VsZWN0aW9uJyApLmZpcnN0KCkudG9KU09OKCksXG5cdFx0XHRcdFx0XHRpbWFnZSA9IHNlbGYubW9kZWwuZ2V0KCAkZWwuYXR0ciggJ2RhdGEtYXR0cmlidXRlJyApICksXG5cdFx0XHRcdFx0XHR1cmw7XG5cblx0XHRcdFx0XHRpZiAoIHNpemUgJiYgYXR0YWNobWVudC5zaXplc1sgc2l6ZSBdICkge1xuXHRcdFx0XHRcdFx0dXJsID0gYXR0YWNobWVudC5zaXplc1sgc2l6ZSBdLnVybDtcblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0dXJsID0gYXR0YWNobWVudC51cmw7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0aW1hZ2Uuc2V0KCB7XG5cdFx0XHRcdFx0XHRpZDogYXR0YWNobWVudC5pZCxcblx0XHRcdFx0XHRcdHNyYzogdXJsLFxuXHRcdFx0XHRcdH0gKTtcblxuXHRcdFx0XHR9ICk7XG5cblx0XHRcdH1cblxuXHRcdFx0c2VsZi5tZWRpYV9saWIub3BlbigpO1xuXG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogQ2xpY2sgZXZlbnQgdG8gcmVtb3ZlIGFuIGltYWdlXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIGV2ZW50ICBqcyBldmVudCBvYmpcblx0XHQgKiBAcmV0dXJuICAgdm9pZHNcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdHJlbW92ZV9pbWFnZTogZnVuY3Rpb24oIGV2ZW50ICkge1xuXG5cdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG5cdFx0XHR0aGlzLm1vZGVsLmdldCggJCggZXZlbnQuY3VycmVudFRhcmdldCApLmF0dHIoICdkYXRhLWF0dHJpYnV0ZScgKSApLnNldCgge1xuXHRcdFx0XHRpZDogJycsXG5cdFx0XHRcdHNyYzogJycsXG5cdFx0XHR9ICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogSGVscGVyIHRvIHVuZG8gY2hhbmdlc1xuXHRcdCAqIEJvdW5kIHRvIFwiZXNjYXBlXCIga2V5IHZpYSBvbl9rZXlkd29uIGZ1bmN0aW9uXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIGV2ZW50ICBqcyBldmVudCBvYmplY3Rcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0cmV2ZXJ0X2VkaXRzOiBmdW5jdGlvbiggZXZlbnQgKSB7XG5cdFx0XHR2YXIgJGVsID0gJCggZXZlbnQudGFyZ2V0ICksXG5cdFx0XHRcdHZhbCA9ICRlbC5hdHRyKCAnZGF0YS1vcmlnaW5hbC1jb250ZW50JyApO1xuXHRcdFx0JGVsLmh0bWwoIHZhbCApO1xuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBTeW5jIGNoYWdlcyB0byB0aGUgbW9kZWwgYW5kIERCXG5cdFx0ICogQHBhcmFtICAgIHtvYmp9ICAgZXZlbnQgIGpzIGV2ZW50IG9iamVjdFxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRzYXZlX2VkaXRzOiBmdW5jdGlvbiggZXZlbnQgKSB7XG5cblx0XHRcdHZhciAkZWwgPSAkKCBldmVudC50YXJnZXQgKSxcblx0XHRcdFx0dmFsID0gdGhpcy5nZXRfY29udGVudCggJGVsICk7XG5cblx0XHRcdHRoaXMubW9kZWwuc2V0KCAkZWwuYXR0ciggJ2RhdGEtYXR0cmlidXRlJyApLCB2YWwgKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBDaGFuZ2UgZXZlbnQgZm9yIGEgc3dpdGNoIGVsZW1lbnRcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgZXZlbnQgIGpzIGV2ZW50IG9iamVjdFxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE3LjBcblx0XHQgKi9cblx0XHR0b2dnbGVfc3dpdGNoOiBmdW5jdGlvbiggZXZlbnQgKSB7XG5cblx0XHRcdGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuXHRcdFx0dmFyICRlbCA9ICQoIGV2ZW50LnRhcmdldCApLFxuXHRcdFx0XHRhdHRyID0gJGVsLmF0dHIoICduYW1lJyApLFxuXHRcdFx0XHRyZXJlbmRlciA9ICRlbC5hdHRyKCAnZGF0YS1yZXJlbmRlcicgKSxcblx0XHRcdFx0dmFsO1xuXG5cdFx0XHRpZiAoICRlbC5pcyggJzpjaGVja2VkJyApICkge1xuXHRcdFx0XHR2YWwgPSAkZWwuYXR0ciggJ2RhdGEtb24nICkgPyAkZWwuYXR0ciggJ2RhdGEtb24nICkgOiAneWVzJztcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHZhbCA9ICRlbC5hdHRyKCAnZGF0YS1vZmYnICkgPyAkZWwuYXR0ciggJ2RhdGEtb2ZmJyApIDogJ25vJztcblx0XHRcdH1cblxuXHRcdFx0aWYgKCAtMSAhPT0gYXR0ci5pbmRleE9mKCAnLicgKSApIHtcblxuXHRcdFx0XHR2YXIgc3BsaXQgPSBhdHRyLnNwbGl0KCAnLicgKTtcblxuXHRcdFx0XHRpZiAoICdwYXJlbnQnID09PSBzcGxpdFswXSApIHtcblx0XHRcdFx0XHR0aGlzLm1vZGVsLmdldF9wYXJlbnQoKS5zZXQoIHNwbGl0WzFdLCB2YWwgKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHR0aGlzLm1vZGVsLmdldCggc3BsaXRbMF0gKS5zZXQoIHNwbGl0WzFdLCB2YWwgKTtcblx0XHRcdFx0fVxuXG5cblx0XHRcdH0gZWxzZSB7XG5cblx0XHRcdFx0dGhpcy5tb2RlbC5zZXQoIGF0dHIsIHZhbCApO1xuXG5cdFx0XHR9XG5cblx0XHRcdHRoaXMudHJpZ2dlciggYXR0ci5yZXBsYWNlKCAnLicsICctJyApICsgJ190b2dnbGUnLCB2YWwgKTtcblxuXHRcdFx0aWYgKCAhIHJlcmVuZGVyIHx8ICd5ZXMnID09PSByZXJlbmRlciApIHtcblx0XHRcdFx0dmFyIHNlbGYgPSB0aGlzO1xuXHRcdFx0XHRzZXRUaW1lb3V0KCBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRzZWxmLnJlbmRlcigpO1xuXHRcdFx0XHR9LCAxMDAgKTtcblx0XHRcdH1cblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBJbml0aWFsaXplcyBhIFdQIEVkaXRvciBvbiBhIHRleHRhcmVhXG5cdFx0ICogQHBhcmFtICAgIHN0cmluZyAgIGlkICAgICAgICBDU1MgSUQgb2YgdGhlIGVkaXRvciAoZG9uJ3QgaW5jbHVkZSAjKVxuXHRcdCAqIEBwYXJhbSAgICBvYmogICAgICBzZXR0aW5ncyAgb3B0aW9uYWwgb2JqZWN0IG9mIHNldHRpbmdzIHRvIHBhc3MgdG8gd3AuZWRpdG9yLmluaXRpYWxpemUoKVxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRpbml0X2VkaXRvcjogZnVuY3Rpb24oIGlkLCBzZXR0aW5ncyApIHtcblxuXHRcdFx0c2V0dGluZ3MgPSBzZXR0aW5ncyB8fCB7fTtcblxuXHRcdFx0d3AuZWRpdG9yLnJlbW92ZSggaWQgKTtcblxuXHRcdFx0d3AuZWRpdG9yLmluaXRpYWxpemUoIGlkLCAkLmV4dGVuZCggdHJ1ZSwgd3AuZWRpdG9yLmdldERlZmF1bHRTZXR0aW5ncygpLCB7XG5cdFx0XHRcdG1lZGlhQnV0dG9uczogdHJ1ZSxcblx0XHRcdFx0dGlueW1jZToge1xuXHRcdFx0XHRcdHRvb2xiYXIxOiAnYm9sZCxpdGFsaWMsc3RyaWtldGhyb3VnaCxidWxsaXN0LG51bWxpc3QsYmxvY2txdW90ZSxocixhbGlnbmxlZnQsYWxpZ25jZW50ZXIsYWxpZ25yaWdodCxsaW5rLHVubGluayx3cF9hZHYnLFxuXHRcdFx0XHRcdHRvb2xiYXIyOiAnZm9ybWF0c2VsZWN0LHVuZGVybGluZSxhbGlnbmp1c3RpZnksZm9yZWNvbG9yLHBhc3RldGV4dCxyZW1vdmVmb3JtYXQsY2hhcm1hcCxvdXRkZW50LGluZGVudCx1bmRvLHJlZG8sd3BfaGVscCcsXG5cdFx0XHRcdFx0c2V0dXA6IF8uYmluZCggdGhpcy5vbl9lZGl0b3JfcmVhZHksIHRoaXMgKSxcblx0XHRcdFx0fVxuXHRcdFx0fSwgc2V0dGluZ3MgKSApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFNldHVwIGEgcGVybWFsaW5rIGVkaXRvciB0byBhbGxvdyBlZGl0aW5nIG9mIGEgcGVybWFsaW5rXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIGV2ZW50ICBqcyBldmVudCBvYmplY3Rcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjZcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi42XG5cdFx0ICovXG5cdFx0bWFrZV9zbHVnX2VkaXRhYmxlOiBmdW5jdGlvbiggZXZlbnQgKSB7XG5cblx0XHRcdHZhciBzZWxmID0gdGhpcyxcblx0XHRcdFx0JGJ0biA9ICQoIGV2ZW50LmN1cnJlbnRUYXJnZXQgKSxcblx0XHRcdFx0JGxpbmsgPSAkYnRuLnByZXZBbGwoICdhJyApLFxuXHRcdFx0XHQkaW5wdXQgPSAkYnRuLnByZXYoICdpbnB1dC5wZXJtYWxpbmsnICksXG5cdFx0XHRcdGZ1bGxfdXJsID0gJGxpbmsuYXR0ciggJ2hyZWYnICksXG5cdFx0XHRcdHNsdWcgPSAkaW5wdXQudmFsKCksXG5cdFx0XHRcdHNob3J0X3VybCA9IGZ1bGxfdXJsLnJlcGxhY2UoIHNsdWcsICcnICk7XG5cblx0XHRcdC8vIGhpZGUgdGhlIGJ1dHRvblxuXHRcdFx0JGJ0bi5oaWRlKCk7XG5cblx0XHRcdC8vIG1ha2UgdGhlIGxpbmsgbm90IGNsaWNrYWJsZVxuXHRcdFx0JGxpbmsuY3NzKCB7XG5cdFx0XHRcdGNvbG9yOiAnIzk5OScsXG5cdFx0XHRcdCdwb2ludGVyLWV2ZW50cyc6ICdub25lJyxcblx0XHRcdFx0J3RleHQtZGVjb3JhdGlvbic6ICdub25lJyxcblx0XHRcdH0gKTtcblxuXHRcdFx0Ly8gcmVtb3ZlIHRoZSBjdXJyZW50IHNsdWcgJiB0cmFpbGluZyBzbGFzaCBmcm9tIHRoZSBVUkxcblx0XHRcdCRsaW5rLnRleHQoIHNob3J0X3VybC5zdWJzdHJpbmcoIDAsIHNob3J0X3VybC5sZW5ndGggLSAxICkgKTtcblxuXHRcdFx0Ly8gZm9jdXMgaW4gb24gdGhlIGZpZWxkXG5cdFx0XHQkaW5wdXQuc2hvdygpLmZvY3VzKCk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogQ2FsbGJhY2sgZnVuY3Rpb24gY2FsbGVkIGFmdGVyIGluaXRpYWxpemF0aW9uIG9mIGFuIGVkaXRvclxuXHRcdCAqIFVwZGF0ZXMgVUkgaWYgYSBsYWJlbCBpcyBwcmVzZW50XG5cdFx0ICogQmluZHMgYSBjaGFuZ2UgZXZlbnQgdG8gZW5zdXJlIGVkaXRvciBjaGFuZ2VzIGFyZSBzYXZlZCB0byB0aGUgbW9kZWxcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgZWRpdG9yICB3cC5lZGl0b3IgaW5zdGFuY2Vcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNy4xXG5cdFx0ICovXG5cdFx0b25fZWRpdG9yX3JlYWR5OiBmdW5jdGlvbiggZWRpdG9yICkge1xuXG5cdFx0XHR2YXIgc2VsZiA9IHRoaXMsXG5cdFx0XHRcdCRlZCA9ICQoICcjJyArIGVkaXRvci5pZCApLFxuXHRcdFx0XHQkcGFyZW50ID0gJGVkLmNsb3Nlc3QoICcubGxtcy1lZGl0YWJsZS1lZGl0b3InICksXG5cdFx0XHRcdCRsYWJlbCA9ICRwYXJlbnQuZmluZCggJy5sbG1zLWxhYmVsJyApLFxuXHRcdFx0XHRwcm9wID0gJGVkLmF0dHIoICdkYXRhLWF0dHJpYnV0ZScgKVxuXG5cdFx0XHRpZiAoICRsYWJlbC5sZW5ndGggKSB7XG5cdFx0XHRcdCRsYWJlbC5wcmVwZW5kVG8oICRwYXJlbnQuZmluZCggJy53cC1lZGl0b3ItdG9vbHMnICkgKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gc2F2ZSBjaGFuZ2VzIHRvIHRoZSBtb2RlbCB2aWEgVmlzdWFsIGVkXG5cdFx0XHRlZGl0b3Iub24oICdjaGFuZ2UnLCBmdW5jdGlvbiggZXZlbnQgKSB7XG5cdFx0XHRcdHNlbGYubW9kZWwuc2V0KCBwcm9wLCB3cC5lZGl0b3IuZ2V0Q29udGVudCggZWRpdG9yLmlkICkgKTtcblx0XHRcdH0gKTtcblxuXHRcdFx0Ly8gc2F2ZSBjaGFuZ2VzIHZpYSBUZXh0IGVkXG5cdFx0XHQkZWQub24oICdpbnB1dCcsIGZ1bmN0aW9uKCBldmVudCApIHtcblx0XHRcdFx0c2VsZi5tb2RlbC5zZXQoIHByb3AsICRlZC52YWwoKSApO1xuXHRcdFx0fSApO1xuXG5cdFx0XHQvLyB0cmlnZ2VyIGFuIGlucHV0IG9uIHRoZSBUZXh0IGVkIHdoZW4gcXVpY2t0YWdzIGJ1dHRvbnMgYXJlIGNsaWNrZWRcblx0XHRcdCRwYXJlbnQub24oICdjbGljaycsICcucXVpY2t0YWdzLXRvb2xiYXIgLmVkX2J1dHRvbicsIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRzZXRUaW1lb3V0KCBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHQkZWQudHJpZ2dlciggJ2lucHV0JyApO1xuXHRcdFx0XHR9LCAxMCApO1xuXHRcdFx0fSApO1xuXG5cdFx0fSxcblxuXHRcdF92YWxpZGF0ZV91cmw6IGZ1bmN0aW9uKCBzdHIgKSB7XG5cblx0XHRcdHZhciBhID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCggJ2EnICk7XG5cdFx0XHRhLmhyZWYgPSBzdHI7XG5cdFx0XHRyZXR1cm4gKCBhLmhvc3QgJiYgYS5ob3N0ICE9PSB3aW5kb3cubG9jYXRpb24uaG9zdCApO1xuXG5cdFx0fVxuXG5cdH07XG5cbn0gKTtcblxuLyoqXG4gKiBfcmVjZWl2ZSBvdmVycmlkZSBmb3IgQmFja2JvbmUuQ29sbGVjdGlvblZpZXcgY29yZVxuICogZW5hYmxlcyBjb25uZWN0aW9uIHdpdGggalF1ZXJ5IFVJIGRyYWdnYWJsZSBidXR0b25zXG4gKiBAc2luY2UgICAgMy4xNi4wXG4gKiBAdmVyc2lvbiAgMy4xNi4wXG4gKi9cbmRlZmluZSggJ1ZpZXdzL19SZWNlaXZhYmxlJyxbXSwgZnVuY3Rpb24oKSB7XG5cblx0cmV0dXJuIHtcblxuXHRcdC8qKlxuXHRcdCAqIE92ZXJsb2FkcyB0aGUgZnVuY3Rpb24gZnJvbSBCYWNrYm9uZS5Db2xsZWN0aW9uVmlldyBjb3JlIGJlY2F1c2UgaXQgZG9lc24ndCBwcm9wZXJseSBoYW5kbGVcblx0XHQgKiByZWNlaWV2ZXMgZnJvbSBhIGpRdWVyeSBVSSBkcmFnZ2FibGUgb2JqZWN0XG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIGV2ZW50ICBqcyBldmVudCBvYmplY3Rcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgdWkgICAgIGpRdWVyeSBVSSBvYmplY3Rcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0X3JlY2VpdmUgOiBmdW5jdGlvbiggZXZlbnQsIHVpICkge1xuXG5cdFx0XHQvLyBjYW1lIGZyb20gc2lkZWJhciBkcmFnXG5cdFx0XHRpZiAoIHVpLnNlbmRlci5oYXNDbGFzcyggJ3VpLWRyYWdnYWJsZScgKSApIHtcblx0XHRcdFx0dmFyIGluZGV4ID0gdGhpcy5fZ2V0Q29udGFpbmVyRWwoKS5jaGlsZHJlbigpLmluZGV4KCB1aS5oZWxwZXIgKTtcblx0XHRcdFx0dWkuaGVscGVyLnJlbW92ZSgpOyAvLyByZW1vdmUgdGhlIGhlbHBlclxuXHRcdFx0XHR0aGlzLmNvbGxlY3Rpb24uYWRkKCB7fSwgeyBhdDogaW5kZXggfSApO1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cblx0XHRcdHZhciBzZW5kZXJMaXN0RWwgPSB1aS5zZW5kZXI7XG5cdFx0XHR2YXIgc2VuZGVyQ29sbGVjdGlvbkxpc3RWaWV3ID0gc2VuZGVyTGlzdEVsLmRhdGEoICd2aWV3JyApO1xuXHRcdFx0aWYoICEgc2VuZGVyQ29sbGVjdGlvbkxpc3RWaWV3IHx8ICEgc2VuZGVyQ29sbGVjdGlvbkxpc3RWaWV3LmNvbGxlY3Rpb24gKSByZXR1cm47XG5cblx0XHRcdHZhciBuZXdJbmRleCA9IHRoaXMuX2dldENvbnRhaW5lckVsKCkuY2hpbGRyZW4oKS5pbmRleCggdWkuaXRlbSApO1xuXHRcdFx0dmFyIG1vZGVsUmVjZWl2ZWQgPSBzZW5kZXJDb2xsZWN0aW9uTGlzdFZpZXcuY29sbGVjdGlvbi5nZXQoIHVpLml0ZW0uYXR0ciggJ2RhdGEtbW9kZWwtY2lkJyApICk7XG5cdFx0XHRzZW5kZXJDb2xsZWN0aW9uTGlzdFZpZXcuY29sbGVjdGlvbi5yZW1vdmUoIG1vZGVsUmVjZWl2ZWQgKTtcblx0XHRcdHRoaXMuY29sbGVjdGlvbi5hZGQoIG1vZGVsUmVjZWl2ZWQsIHsgYXQgOiBuZXdJbmRleCB9ICk7XG5cdFx0XHRtb2RlbFJlY2VpdmVkLmNvbGxlY3Rpb24gPSB0aGlzLmNvbGxlY3Rpb247IC8vIG90aGVyd2lzZSB3aWxsIG5vdCBnZXQgcHJvcGVybHkgc2V0LCBzaW5jZSBtb2RlbFJlY2VpdmVkLmNvbGxlY3Rpb24gbWlnaHQgYWxyZWFkeSBoYXZlIGEgdmFsdWUuXG5cdFx0XHR0aGlzLnNldFNlbGVjdGVkTW9kZWwoIG1vZGVsUmVjZWl2ZWQgKTtcblx0XHR9LFxuXG5cdH1cblxufSApO1xuXG5cbi8qKlxuICogU2hpZnRhYmxlIHZpZXcgbWl4aW4gZnVuY3Rpb25cbiAqIEBzaW5jZSAgICAzLjE2LjBcbiAqIEB2ZXJzaW9uICAzLjE2LjBcbiAqL1xuZGVmaW5lKCAnVmlld3MvX1NoaWZ0YWJsZScsW10sIGZ1bmN0aW9uKCkge1xuXG5cdHJldHVybiB7XG5cblx0XHQvKipcblx0XHQgKiBDb25kaXRpb25hbGx5IGhpZGUgYWN0aW9uIGJ1dHRvbnMgYmFzZWQgb24gc2VjdGlvbiBwb3NpdGlvbiBpbiBjb2xsZWN0aW9uXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdG1heWJlX2hpZGVfc2hpZnRhYmxlX2J1dHRvbnM6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHRpZiAoICEgdGhpcy5tb2RlbC5jb2xsZWN0aW9uICkge1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cblx0XHRcdHZhciB0eXBlID0gdGhpcy5tb2RlbC5nZXQoICd0eXBlJyApO1xuXG5cdFx0XHRpZiAoIHRoaXMubW9kZWwuY29sbGVjdGlvbi5maXJzdCgpID09PSB0aGlzLm1vZGVsICkge1xuXHRcdFx0XHR0aGlzLiRlbC5maW5kKCAnLnNoaWZ0LXVwLS0nICsgdHlwZSApLmhpZGUoKTtcblx0XHRcdH0gZWxzZSBpZiAoIHRoaXMubW9kZWwuY29sbGVjdGlvbi5sYXN0KCkgPT09IHRoaXMubW9kZWwgKSB7XG5cdFx0XHRcdHRoaXMuJGVsLmZpbmQoICcuc2hpZnQtZG93bi0tJyArIHR5cGUgKS5oaWRlKCk7XG5cdFx0XHR9XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogTW92ZSBhbiBpdGVtIGluIGEgY29sbGVjdGlvbiBmcm9tIG9uZSBwb3NpdGlvbiB0byBhbm90aGVyXG5cdFx0ICogQHBhcmFtICAgIGludCAgIG9sZF9pbmRleCAgY3VycmVudCAob2xkKSBpbmRleCB3aXRoaW4gdGhlIGNvbGxlY3Rpb25cblx0XHQgKiBAcGFyYW0gICAgaW50ICAgbmV3X2luZGV4ICBkZXNpcmVkIChuZXcpIGluZGV4IHdpdGhpbiB0aGUgY29sbGVjdGlvblxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRzaGlmdDogZnVuY3Rpb24oIG9sZF9pbmRleCwgbmV3X2luZGV4ICkge1xuXG5cdFx0XHR2YXIgY29sbGVjdGlvbiA9IHRoaXMubW9kZWwuY29sbGVjdGlvbjtcblxuXHRcdFx0Y29sbGVjdGlvbi5yZW1vdmUoIHRoaXMubW9kZWwgKTtcblx0XHRcdGNvbGxlY3Rpb24uYWRkKCB0aGlzLm1vZGVsLCB7IGF0OiBuZXdfaW5kZXggfSApO1xuXHRcdFx0Y29sbGVjdGlvbi50cmlnZ2VyKCAncmVvcmRlcicgKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBNb3ZlIGFuIGl0ZW0gZG93biB0aGUgdHJlZSBvbmUgcG9zaXRpb25cblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0c2hpZnRfZG93bjogZnVuY3Rpb24oIGUgKSB7XG5cblx0XHRcdGUucHJldmVudERlZmF1bHQoKTtcblx0XHRcdHZhciBpbmRleCA9IHRoaXMubW9kZWwuY29sbGVjdGlvbi5pbmRleE9mKCB0aGlzLm1vZGVsICk7XG5cdFx0XHR0aGlzLnNoaWZ0KCBpbmRleCwgaW5kZXggKyAxICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogTW92ZSBhbiBpdGVtIHVwIHRoZSB0cmVlIG9uZSBwb3NpdGlvblxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRzaGlmdF91cDogZnVuY3Rpb24oIGUgKSB7XG5cblx0XHRcdGUucHJldmVudERlZmF1bHQoKTtcblx0XHRcdHZhciBpbmRleCA9IHRoaXMubW9kZWwuY29sbGVjdGlvbi5pbmRleE9mKCB0aGlzLm1vZGVsICk7XG5cdFx0XHR0aGlzLnNoaWZ0KCBpbmRleCwgaW5kZXggLSAxICk7XG5cblx0XHR9LFxuXG5cdH07XG5cbn0gKTtcblxuLyoqXG4gKiBTdWJ2aWV3IHV0aWxpdHkgbWl4aW5cbiAqIEBzaW5jZSAgICAzLjE2LjBcbiAqIEB2ZXJzaW9uICAzLjE2LjBcbiAqL1xuZGVmaW5lKCAnVmlld3MvX1N1YnZpZXcnLFtdLCBmdW5jdGlvbigpIHtcblxuXHRyZXR1cm4ge1xuXG5cdFx0c3Vic2NyaXB0aW9uczoge30sXG5cblx0XHQvKipcblx0XHQgKiBOYW1lIG9mIHRoZSBjdXJyZW50IHN1YnZpZXdcblx0XHQgKiBAdHlwZSAge1N0cmluZ31cblx0XHQgKi9cblx0XHRzdGF0ZTogJycsXG5cblx0XHQvKipcblx0XHQgKiBPYmplY3Qgb2Ygc3VidmlldyBkYXRhXG5cdFx0ICogQHR5cGUgIHtPYmplY3R9XG5cdFx0ICovXG5cdFx0dmlld3M6IHt9LFxuXG5cdFx0LyoqXG5cdFx0ICogUmV0cmlldmUgYSBzdWJ2aWV3IGJ5IG5hbWUgZnJvbSB0aGlzLnZpZXdzXG5cdFx0ICogQHBhcmFtICAgIHN0cmluZyAgIG5hbWUgICBuYW1lIG9mIHRoZSBzdWJ2aWV3XG5cdFx0ICogQHJldHVybiAgIG9ibHxmYWxzZVxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0Z2V0X3N1YnZpZXc6IGZ1bmN0aW9uKCBuYW1lICkge1xuXG5cdFx0XHRpZiAoIHRoaXMudmlld3NbIG5hbWUgXSApIHtcblx0XHRcdFx0cmV0dXJuIHRoaXMudmlld3NbIG5hbWUgXTtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXG5cdFx0fSxcblxuXHRcdGV2ZW50c19zdWJzY3JpYmU6IGZ1bmN0aW9uKCBldmVudHMgKSB7XG5cblx0XHRcdF8uZWFjaCggZXZlbnRzLCBmdW5jdGlvbiggZnVuYywgZXZlbnQgKSB7XG5cblx0XHRcdFx0dGhpcy5zdWJzY3JpcHRpb25zWyBldmVudCBdID0gZnVuYztcblx0XHRcdFx0QmFja2JvbmUucHViU3ViLm9uKCBldmVudCwgZnVuYywgdGhpcyApO1xuXG5cdFx0XHR9LCB0aGlzICk7XG5cblx0XHR9LFxuXG5cdFx0ZXZlbnRzX3Vuc3Vic2NyaWJlOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0Xy5lYWNoKCB0aGlzLnN1YnNjcmlwdGlvbnMsIGZ1bmN0aW9uKCBmdW5jLCBldmVudCApIHtcblxuXHRcdFx0XHRCYWNrYm9uZS5wdWJTdWIub2ZmKCBldmVudCwgZnVuYywgdGhpcyApO1xuXHRcdFx0XHRkZWxldGUgdGhpcy5zdWJzY3JpcHRpb25zWyBldmVudCBdO1xuXG5cdFx0XHR9LCB0aGlzICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogUmVtb3ZlIGEgc2luZ2xlIHN1YnZpZXcgKGFuZCBhbGwgaXQncyBzdWJ2aWV3cykgYnkgbmFtZVxuXHRcdCAqIEBwYXJhbSAgICBzdHJpbmcgICBuYW1lICAgbmFtZSBvZiB0aGUgc3Vidmlld1xuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRyZW1vdmVfc3VidmlldzogZnVuY3Rpb24oIG5hbWUgKSB7XG5cblx0XHRcdHZhciB2aWV3ID0gdGhpcy5nZXRfc3VidmlldyggbmFtZSApO1xuXG5cdFx0XHRpZiAoICEgdmlldyApIHtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIHZpZXcuaW5zdGFuY2UgKSB7XG5cblx0XHRcdFx0Ly8gcmVtb3ZlIHRoZSBzdWJ2aWV3cyBpZiB0aGUgdmlldyBoYXMgc3Vidmlld3Ncblx0XHRcdFx0aWYgKCAhIF8uaXNFbXB0eSggdmlldy5pbnN0YW5jZS52aWV3cyApICkge1xuXHRcdFx0XHRcdHZpZXcuaW5zdGFuY2UuZXZlbnRzX3Vuc3Vic2NyaWJlKCk7XG5cdFx0XHRcdFx0dmlldy5pbnN0YW5jZS5yZW1vdmVfc3Vidmlld3MoKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHZpZXcuaW5zdGFuY2Uub2ZmKCk7XG5cdFx0XHRcdHZpZXcuaW5zdGFuY2Uub2ZmKCBudWxsLCBudWxsLCBudWxsICk7XG5cdFx0XHRcdHZpZXcuaW5zdGFuY2UucmVtb3ZlKCk7XG5cdFx0XHRcdHZpZXcuaW5zdGFuY2UudW5kZWxlZ2F0ZUV2ZW50cygpO1xuXG5cdFx0XHRcdC8vIF8uZWFjaCggdmlldy5pbnN0YW5jZSwgZnVuY3Rpb24oIHZhbCwga2V5ICkge1xuXHRcdFx0XHQvLyBcdGRlbGV0ZSB2aWV3Lmluc3RhbmNlWyBrZXkgXTtcblx0XHRcdFx0Ly8gfSApO1xuXG5cdFx0XHRcdHZpZXcuaW5zdGFuY2UgPSBudWxsO1xuXG5cdFx0XHR9XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogUmVtb3ZlIGFsbCBzdWJ2aWV3cyAoYW5kIGFsbCB0aGUgc3Vidmlld3Mgb2YgdGhvc2Ugc3Vidmlld3MpXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdHJlbW92ZV9zdWJ2aWV3czogZnVuY3Rpb24oKSB7XG5cblx0XHRcdF8uZWFjaCggdGhpcy52aWV3cywgZnVuY3Rpb24oIGRhdGEsIG5hbWUgKSB7XG5cblx0XHRcdFx0dGhpcy5yZW1vdmVfc3VidmlldyggbmFtZSApO1xuXG5cdFx0XHR9LCB0aGlzICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogUmVuZGVyIHN1YnZpZXdzIGJhc2VkIG9uIGN1cnJlbnQgc3RhdGVcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgdmlld19kYXRhICBhZGRpdGlvbmFsIGRhdGEgdG8gcGFzcyB0byB0aGUgc3Vidmlld3Ncblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0cmVuZGVyX3N1YnZpZXdzOiBmdW5jdGlvbiggdmlld19kYXRhICkge1xuXG5cdFx0XHR2aWV3X2RhdGEgPSB2aWV3X2RhdGEgfHwge307XG5cblx0XHRcdF8uZWFjaCggdGhpcy52aWV3cywgZnVuY3Rpb24oIGRhdGEsIG5hbWUgKSB7XG5cblx0XHRcdFx0aWYgKCB0aGlzLnN0YXRlID09PSBkYXRhLnN0YXRlICkge1xuXG5cdFx0XHRcdFx0dGhpcy5yZW5kZXJfc3VidmlldyggbmFtZSwgdmlld19kYXRhICk7XG5cblx0XHRcdFx0fSBlbHNlIHtcblxuXHRcdFx0XHRcdHRoaXMucmVtb3ZlX3N1YnZpZXcoIG5hbWUgKTtcblxuXHRcdFx0XHR9XG5cblx0XHRcdH0sIHRoaXMgKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBSZW5kZXIgYSBzaW5nbGUgc3VidmlldyBieSBuYW1lXG5cdFx0ICogQHBhcmFtICAgIHN0cmluZyAgIG5hbWUgICAgICAgbmFtZSBvZiB0aGUgc3Vidmlld1xuXHRcdCAqIEBwYXJhbSAgICBvYmogICAgICB2aWV3X2RhdGEgIGFkZGl0aW9uYWwgZGF0YSB0byBwYXNzIHRvIHRoZSBzdWJ2aWV3IGluaXRpYWxpemVyXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdHJlbmRlcl9zdWJ2aWV3OiBmdW5jdGlvbiggbmFtZSwgdmlld19kYXRhICkge1xuXG5cdFx0XHR2YXIgdmlldyA9IHRoaXMuZ2V0X3N1YnZpZXcoIG5hbWUgKTtcblxuXHRcdFx0aWYgKCAhIHZpZXcgKSB7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblxuXHRcdFx0dGhpcy5yZW1vdmVfc3VidmlldyggbmFtZSApO1xuXG5cdFx0XHRpZiAoICEgdmlldy5pbnN0YW5jZSApIHtcblx0XHRcdFx0dmlldy5pbnN0YW5jZSA9IG5ldyB2aWV3LmNsYXNzKCB2aWV3X2RhdGEgKTtcblx0XHRcdH1cblxuXHRcdFx0dmlldy5pbnN0YW5jZS5yZW5kZXIoKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBTZXQgdGhlIGN1cnJlbnQgc3Vidmlld1xuXHRcdCAqIE11c3QgY2FsbCByZW5kZXIgYWZ0ZXIhXG5cdFx0ICogQHBhcmFtICAgIHN0cmluZyAgIHN0YXRlICBuYW1lIG9mIHRoZSBzdGF0ZSBbYnVpbGRlcnxlZGl0b3JdXG5cdFx0ICogQHJldHVybiAgIG9iaiAgICAgICAgICAgICB0aGlzIGZvciBjaGFpbmluZ1xuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0c2V0X3N0YXRlOiBmdW5jdGlvbiAoIHN0YXRlICkge1xuXG5cdFx0XHR0aGlzLnN0YXRlID0gc3RhdGU7XG5cdFx0XHRyZXR1cm4gdGhpcztcblxuXHRcdH0sXG5cblx0fVxuXG59ICk7XG5cbi8qKlxuICogVHJhc2hhYmxlIG1vZGVsXG4gKiBAdHlwZSAgICAge09iamVjdH1cbiAqIEBzaW5jZSAgICAzLjE2LjEyXG4gKiBAdmVyc2lvbiAgMy4xNi4xMlxuICovXG5kZWZpbmUoICdWaWV3cy9fVHJhc2hhYmxlJyxbXSwgZnVuY3Rpb24oKSB7XG5cblx0cmV0dXJuIHtcblxuXHRcdC8qKlxuXHRcdCAqIERPTSBFdmVudHNcblx0XHQgKiBAdHlwZSAge09iamVjdH1cblx0XHQgKiBAc2luY2UgICAgMy4xNi4xMlxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjEyXG5cdFx0ICovXG5cdFx0ZXZlbnRzOiB7XG5cdFx0XHQnY2xpY2sgYVtocmVmPVwiI2xsbXMtdHJhc2gtbW9kZWxcIl0nOiAndHJhc2hfbW9kZWwnLFxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBSZW1vdmUgYSBtb2RlbCBmcm9tIGl0J3MgcGFyZW50IGFuZCBkZWxldGUgaXRcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgZXZlbnQgIGpzIGV2ZW50IG9iamVjdFxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMTJcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4xMlxuXHRcdCAqL1xuXHRcdHRyYXNoX21vZGVsOiBmdW5jdGlvbiggZXZlbnQgKSB7XG5cblx0XHRcdGlmICggZXZlbnQgKSB7XG5cdFx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHRcdGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuXHRcdFx0fVxuXG5cdFx0XHR2YXIgbXNnID0gTExNUy5sMTBuLnJlcGxhY2UoICdBcmUgeW91IHN1cmUgeW91IHdhbnQgdG8gbW92ZSB0aGlzICVzIHRvIHRoZSB0cmFzaD8nLCB7XG5cdFx0XHRcdCclcyc6IHRoaXMubW9kZWwuZ2V0X2wxMG5fdHlwZSgpLFxuXHRcdFx0fSApO1xuXG5cdFx0XHRpZiAoIHdpbmRvdy5jb25maXJtKCBtc2cgKSApIHtcblxuXHRcdFx0XHRpZiAoIHRoaXMubW9kZWwuY29sbGVjdGlvbiApIHtcblx0XHRcdFx0XHR0aGlzLm1vZGVsLmNvbGxlY3Rpb24ucmVtb3ZlKCB0aGlzLm1vZGVsICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBwdWJsaXNoIGV2ZW50XG5cdFx0XHRcdEJhY2tib25lLnB1YlN1Yi50cmlnZ2VyKCAnbW9kZWwtdHJhc2hlZCcsIHRoaXMubW9kZWwgKTtcblxuXHRcdFx0XHQvLyB0cmlnZ2VyIGxvY2FsIGV2ZW50IHNvIGV4dGVuZGluZyB2aWV3cyBjYW4gcnVuIG90aGVyIGFjdGlvbnMgd2hlcmUgbmVjZXNzYXJ5XG5cdFx0XHRcdHRoaXMudHJpZ2dlciggJ21vZGVsLXRyYXNoZWQnLCB0aGlzLm1vZGVsICk7XG5cblx0XHRcdH1cblxuXHRcdH0sXG5cblx0fVxuXG59ICk7XG5cbi8qKlxuICogTG9hZCB2aWV3IG1peGluc1xuICogQHJldHVybiAgIG9ialxuICogQHNpbmNlICAgIDMuMTcuMVxuICogQHZlcnNpb24gIDMuMTcuMVxuICovXG5kZWZpbmUoICdWaWV3cy9fbG9hZGVyJyxbXG5cdFx0J1ZpZXdzL19EZXRhY2hhYmxlJyxcblx0XHQnVmlld3MvX0VkaXRhYmxlJyxcblx0XHQnVmlld3MvX1JlY2VpdmFibGUnLFxuXHRcdCdWaWV3cy9fU2hpZnRhYmxlJyxcblx0XHQnVmlld3MvX1N1YnZpZXcnLFxuXHRcdCdWaWV3cy9fVHJhc2hhYmxlJ1xuXHRdLFxuXHRmdW5jdGlvbihcblx0XHREZXRhY2hhYmxlLFxuXHRcdEVkaXRhYmxlLFxuXHRcdFJlY2VpdmFibGUsXG5cdFx0U2hpZnRhYmxlLFxuXHRcdFN1YnZpZXcsXG5cdFx0VHJhc2hhYmxlXG5cdCkge1xuXG5cdHJldHVybiB7XG5cdFx0RGV0YWNoYWJsZTogRGV0YWNoYWJsZSxcblx0XHRFZGl0YWJsZTogRWRpdGFibGUsXG5cdFx0UmVjZWl2YWJsZTogUmVjZWl2YWJsZSxcblx0XHRTaGlmdGFibGU6IFNoaWZ0YWJsZSxcblx0XHRTdWJ2aWV3OiBTdWJ2aWV3LFxuXHRcdFRyYXNoYWJsZTogVHJhc2hhYmxlLFxuXHR9O1xuXG59ICk7XG5cbi8qKlxuICogQ29uc3RydWN0b3IgZnVuY3Rpb25zIGZvciBjb25zdHJ1Y3RpbmcgbW9kZWxzLCB2aWV3cywgYW5kIGNvbGxlY3Rpb25zXG4gKiBAc2luY2UgICAgMy4xNi4wXG4gKiBAdmVyc2lvbiAgMy4xNy4xXG4gKi9cbmRlZmluZSggJ0NvbnRyb2xsZXJzL0NvbnN0cnVjdCcsW1xuXHRcdCdDb2xsZWN0aW9ucy9sb2FkZXInLFxuXHRcdCdNb2RlbHMvbG9hZGVyJyxcblx0XHQnVmlld3MvX2xvYWRlcidcblx0XSwgZnVuY3Rpb24oXG5cdFx0Q29sbGVjdGlvbnMsXG5cdFx0TW9kZWxzLFxuXHRcdFZpZXdzXG5cdCkge1xuXG5cdHJldHVybiBmdW5jdGlvbigpIHtcblxuXHRcdC8qKlxuXHRcdCAqIEludGVybmFsIGdldHRlclxuXHRcdCAqIENvbnN0cnVjdHMgbmV3IENvbGxlY3Rpb25zLCBNb2RlbHMsIGFuZCBWaWV3c1xuXHRcdCAqIEBwYXJhbSAgICBvYmogICAgICB0eXBlICAgICB0eXBlIG9mIG9iamVjdCB0byBjb25zdHJ1Y3QgW0NvbGxlY3Rpb24sTW9kZWwsVmlld11cblx0XHQgKiBAcGFyYW0gICAgc3RyaW5nICAgbmFtZSAgICAgbmFtZSBvZiB0aGUgb2JqZWN0IHRvIGNvbnN0cnVjdFxuXHRcdCAqIEBwYXJhbSAgICBvYmogICAgICBkYXRhICAgICBvYmplY3QgZGF0YSB0byBwYXNzIGludG8gdGhlIG9iamVjdCdzIGNvbnN0cnVjdG9yXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgICAgIG9wdGlvbnMgIG9iamVjdCBvcHRpb25zIHRvIHBhc3MgaW50byB0aGUgY29uc3RydWN0b3Jcblx0XHQgKiBAcmV0dXJuICAgb2JqXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRmdW5jdGlvbiBnZXQoIHR5cGUsIG5hbWUsIGRhdGEsIG9wdGlvbnMgKSB7XG5cblx0XHRcdGlmICggISB0eXBlWyBuYW1lIF0gKSB7XG5cdFx0XHRcdGNvbnNvbGUubG9nKCAnXCInICsgbmFtZSArICdcIiBub3QgZm91bmQuJyApO1xuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBuZXcgdHlwZVsgbmFtZSBdKCBkYXRhLCBvcHRpb25zICk7XG5cblx0XHR9XG5cblx0XHQvKipcblx0XHQgKiBJbnN0YW50aWF0ZSBhIGNvbGxlY3Rpb25cblx0XHQgKiBAcGFyYW0gICAgc3RyaW5nICAgbmFtZSAgICAgQ29sbGVjdGlvbiBjbGFzcyBuYW1lIChFRzogXCJTZWN0aW9uc1wiKVxuXHRcdCAqIEBwYXJhbSAgICBhcnJheSAgICBkYXRhICAgICBBcnJheSBvZiBtb2RlbCBvYmplY3RzIHRvIHBhc3MgdG8gdGhlIGNvbnN0cnVjdG9yXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgICAgIG9wdGlvbnMgIE9iamVjdCBvZiBvcHRpb25zIHRvIHBhc3MgdG8gdGhlIGNvbnN0cnVjdG9yXG5cdFx0ICogQHJldHVybiAgIG9ialxuXHRcdCAqIEBzaW5jZSAgICAzLjE3LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNy4wXG5cdFx0ICovXG5cdFx0dGhpcy5nZXRfY29sbGVjdGlvbiA9IGZ1bmN0aW9uKCBuYW1lLCBkYXRhLCBvcHRpb25zICkge1xuXG5cdFx0XHRyZXR1cm4gZ2V0KCBDb2xsZWN0aW9ucywgbmFtZSwgZGF0YSwgb3B0aW9ucyApO1xuXG5cdFx0fTtcblxuXHRcdC8qKlxuXHRcdCAqIEluc3RhbnRpYXRlIGEgbW9kZWxcblx0XHQgKiBAcGFyYW0gICAgc3RyaW5nICAgbmFtZSAgICAgTW9kZWwgY2xhc3MgbmFtZSAoRUc6IFwiU2VjdGlvblwiKVxuXHRcdCAqIEBwYXJhbSAgICBvYmogICAgICBkYXRhICAgICBPYmplY3Qgb2YgbW9kZWwgYXR0cmlidXRlcyB0byBwYXNzIHRvIHRoZSBjb25zdHJ1Y3RvclxuXHRcdCAqIEBwYXJhbSAgICBvYmogICAgICBvcHRpb25zICBPYmplY3Qgb2Ygb3B0aW9ucyB0byBwYXNzIHRvIHRoZSBjb25zdHJ1Y3RvclxuXHRcdCAqIEByZXR1cm4gICBvYmpcblx0XHQgKiBAc2luY2UgICAgMy4xNy4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTcuMFxuXHRcdCAqL1xuXHRcdHRoaXMuZ2V0X21vZGVsID0gZnVuY3Rpb24oIG5hbWUsIGRhdGEsIG9wdGlvbnMgKSB7XG5cblx0XHRcdHJldHVybiBnZXQoIE1vZGVscywgbmFtZSwgZGF0YSwgb3B0aW9ucyApO1xuXG5cdFx0fTtcblxuXHRcdC8qKlxuXHRcdCAqIExldCAzcmQgcGFydGllcyBleHRlbmQgYSB2aWV3IHVzaW5nIGFueSBvZiB0aGUgbWl4aW4gKF8pIHZpZXdzXG5cdFx0ICogQHBhcmFtICAgIHtvYmp9ICAgICB2aWV3ICAgICBiYXNlIG9iamVjdCB1c2VkIGZvciB0aGUgdmlld1xuXHRcdCAqIEBwYXJhbS4uLiB7c3RyaW5nfSAgZXh0ZW5kcyAgYW55IG51bWJlciBvZiBzdHJpbmdzIHRoYXQgc2hvdWxkIGJlIG1peGVkIGludG8gdGhlIHZpZXdcblx0XHQgKiBAcmV0dXJuICAgb2JqXG5cdFx0ICogQHNpbmNlICAgIDMuMTcuMVxuXHRcdCAqIEB2ZXJzaW9uICAzLjE3LjFcblx0XHQgKi9cblx0XHR0aGlzLmV4dGVuZF92aWV3ID0gZnVuY3Rpb24oKSB7XG5cblx0XHRcdHZhciB2aWV3ID0gYXJndW1lbnRzWzBdLFxuXHRcdFx0XHRpID0gMTtcblxuXHRcdFx0d2hpbGUgKCBhcmd1bWVudHNbIGkgXSApIHtcblxuXHRcdFx0XHR2YXIgY2xhc3NuYW1lID0gYXJndW1lbnRzWyBpIF07XG5cdFx0XHRcdGlmICggVmlld3NbIGNsYXNzbmFtZSBdICkge1xuXG5cdFx0XHRcdFx0aWYgKCB2aWV3LmV2ZW50cyAmJiBWaWV3c1sgY2xhc3NuYW1lIF0uZXZlbnRzICkge1xuXHRcdFx0XHRcdFx0dmlldy5ldmVudHMgPSBfLmRlZmF1bHRzKCB2aWV3LmV2ZW50cywgVmlld3NbIGNsYXNzbmFtZSBdLmV2ZW50cyApO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdHZpZXcgPSBfLmRlZmF1bHRzKCB2aWV3LCBWaWV3c1sgY2xhc3NuYW1lIF0gKTtcblxuXHRcdFx0XHR9XG5cblx0XHRcdFx0aSsrO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gQmFja2JvbmUuVmlldy5leHRlbmQoIHZpZXcgKTtcblxuXHRcdH07XG5cblx0XHQvKipcblx0XHQgKiBBbGxvd3MgY3VzdG9tIGNvbGxlY3Rpb24gcmVnaXN0cmF0aW9uIGJ5IGV4dGVuZGluZyB0aGUgZGVmYXVsdCBCYWNrQm9uZSBjb2xsZWN0aW9uXG5cdFx0ICogQHBhcmFtICAgIHN0cmluZyAgIG5hbWUgICBtb2RlbCBuYW1lXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgICAgIHByb3BzICBwcm9wZXJ0aWVzIHRvIGV4dGVuZCB0aGUgY29sbGVjdGlvbiB3aXRoXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNy4xXG5cdFx0ICogQHZlcnNpb24gIDMuMTcuMVxuXHRcdCAqL1xuXHRcdHRoaXMucmVnaXN0ZXJfY29sbGVjdGlvbiA9IGZ1bmN0aW9uKCBuYW1lLCBwcm9wcyApIHtcblxuXHRcdFx0Q29sbGVjdGlvbnNbIG5hbWUgXSA9IEJhY2tib25lLkNvbGxlY3Rpb24uZXh0ZW5kKCBwcm9wcyApO1xuXG5cdFx0fTtcblxuXHRcdC8qKlxuXHRcdCAqIEFsbG93cyBjdXN0b20gbW9kZWwgcmVnaXN0cmF0aW9uIGJ5IGV4dGVuZGluZyB0aGUgZGVmYXVsdCBhYnN0cmFjdCBtb2RlbFxuXHRcdCAqIEBwYXJhbSAgICBzdHJpbmcgICBuYW1lICAgbW9kZWwgbmFtZVxuXHRcdCAqIEBwYXJhbSAgICBvYmogICAgICBwcm9wcyAgcHJvcGVydGllcyB0byBleHRlbmQgdGhlIGFic3RyYWN0IG1vZGVsIHdpdGhcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE3LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNy4wXG5cdFx0ICovXG5cdFx0dGhpcy5yZWdpc3Rlcl9tb2RlbCA9IGZ1bmN0aW9uKCBuYW1lLCBwcm9wcyApIHtcblxuXHRcdFx0TW9kZWxzWyBuYW1lIF0gPSBNb2RlbHNbJ0Fic3RyYWN0J10uZXh0ZW5kKCBwcm9wcyApO1xuXG5cdFx0fTtcblxuXHRcdHJldHVybiB0aGlzO1xuXG5cdH07XG5cbn0gKTtcblxuLyoqXG4gKiBMaWZ0ZXJMTVMgQnVpbGRlciBEZWJ1Z2dpbmcgc3VpdGVcbiAqIEBzaW5jZSAgICAzLjE2LjBcbiAqIEB2ZXJzaW9uICAzLjE2LjBcbiAqL1xuZGVmaW5lKCAnQ29udHJvbGxlcnMvRGVidWcnLFtdLCBmdW5jdGlvbigpIHtcblxuIFx0cmV0dXJuIGZ1bmN0aW9uKCBzZXR0aW5ncyApIHtcblxuIFx0XHR2YXIgc2VsZiA9IHRoaXMsXG4gXHRcdFx0ZW5hYmxlZCA9IHNldHRpbmdzLmVuYWJsZWQgfHwgZmFsc2U7XG5cblx0XHQvKipcblx0XHQgKiBEaXNhYmxlIGRlYnVnZ2luZ1xuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cbiBcdFx0dGhpcy5kaXNhYmxlID0gZnVuY3Rpb24oKSB7XG5cbiBcdFx0XHRzZWxmLmxvZyggJ0xpZnRlckxNUyBCdWlsZGVyIGRlYnVnZ2luZyBkaXNhYmxlZCcgKTtcbiBcdFx0XHRlbmFibGVkID0gZmFsc2U7XG5cbiBcdFx0fTtcblxuXHRcdC8qKlxuXHRcdCAqIEVuYWJsZSBkZWJ1Z2dpbmdcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG4gXHRcdHRoaXMuZW5hYmxlID0gZnVuY3Rpb24oKSB7XG5cbiBcdFx0XHRlbmFibGVkID0gdHJ1ZTtcbiBcdFx0XHRzZWxmLmxvZyggJ0xpZnRlckxNUyBCdWlsZGVyIGRlYnVnZ2luZyBlbmFibGVkJyApO1xuXG4gXHRcdH07XG5cbiBcdFx0LyoqXG4gXHRcdCAqIEdlbmVyYWwgbG9nZ2luZyBmdW5jdGlvblxuIFx0XHQgKiBMb2dzIHRvIHRoZSBqcyBjb25zb2xlIG9ubHkgaWYgbG9nZ2luZyBpcyBlbmFibGVkXG4gXHRcdCAqIEByZXR1cm4gICB2b2lkXG4gXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcbiBcdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuIFx0XHQgKi9cbiBcdFx0dGhpcy5sb2cgPSBmdW5jdGlvbigpIHtcblxuXHRcdFx0aWYgKCAhIGVuYWJsZWQgKSB7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblxuXHRcdFx0Xy5lYWNoKCBhcmd1bWVudHMsIGZ1bmN0aW9uKCBkYXRhICkge1xuXHRcdFx0XHRjb25zb2xlLmxvZyggZGF0YSApO1xuXHRcdFx0fSApO1xuXG4gXHRcdH07XG5cbiBcdFx0LyoqXG4gXHRcdCAqIFRvZ2dsZXMgY3VycmVudCBzdGF0ZSBvZiB0aGUgbG9nZ2VyIG9uIG9yIG9mZlxuIFx0XHQgKiBAcmV0dXJuICAgdm9pZFxuIFx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG4gXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcbiBcdFx0ICovXG4gXHRcdHRoaXMudG9nZ2xlID0gZnVuY3Rpb24oKSB7XG5cblx0XHRcdGlmICggZW5hYmxlZCApIHtcblx0XHRcdFx0c2VsZi5kaXNhYmxlKCk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRzZWxmLmVuYWJsZSgpO1xuXHRcdFx0fVxuXG4gXHRcdH07XG5cbiBcdFx0Ly8gb24gc3RhcnR1cCwgbG9nIGEgbWVzc2FnZSBpZiBsb2dnaW5nIGlzIGVuYWJsZWRcbiBcdFx0aWYgKCBlbmFibGVkICkge1xuIFx0XHRcdHNlbGYuZW5hYmxlKCk7XG4gXHRcdH1cblxuIFx0fVxuXG4gfSApO1xuXG4vKipcbiAqIE1vZGVsIHNjaGVtYSBmdW5jdGlvbnNcbiAqIEBzaW5jZSAgICAzLjE3LjBcbiAqIEB2ZXJzaW9uICAzLjE3LjBcbiAqL1xuZGVmaW5lKCAnQ29udHJvbGxlcnMvU2NoZW1hcycsW10sIGZ1bmN0aW9uKCkge1xuXG5cdC8qKlxuXHQgKiBNYWluIFNjaGVtYXMgY2xhc3Ncblx0ICogQHBhcmFtICAgIG9iaiAgIHNjaGVtYXMgIHNjaGVtYXMgZGVmaW5pdGlvbnMgaW5pdGlhbGl6ZWQgdmlhIFBIUCBmaWx0ZXJzXG5cdCAqIEByZXR1cm4gICBvYmpcblx0ICogQHNpbmNlICAgIDMuMTcuMFxuXHQgKiBAdmVyc2lvbiAgMy4xNy4wXG5cdCAqL1xuXHRyZXR1cm4gZnVuY3Rpb24oIHNjaGVtYXMgKSB7XG5cblx0XHQvLyBpbml0aWFsaXplIGFueSBjdXN0b20gc2NoZW1hcyBkZWZpbmVkIHZpYSBQSFBcblx0XHR2YXIgY3VzdG9tX3NjaGVtYXMgPSBzY2hlbWFzO1xuXHRcdF8uZWFjaCggY3VzdG9tX3NjaGVtYXMsIGZ1bmN0aW9uKCB0eXBlICkge1xuXHRcdFx0Xy5lYWNoKCB0eXBlLCBmdW5jdGlvbiggc2NoZW1hICkge1xuXHRcdFx0XHRzY2hlbWEuY3VzdG9tID0gdHJ1ZTtcblx0XHRcdH0gKTtcblx0XHR9ICk7XG5cblx0XHQvKipcblx0XHQgKiBSZXRyaWV2ZSBhIHNjaGVtYSBmb3IgYSBnaXZlbiBtb2RlbCBieSB0eXBlXG5cdFx0ICogRXh0ZW5kcyBkZWZhdWx0IHNjaGVtYXMgZGVmaW5pdGlvbnMgd2l0aCBjdXN0b20gM3JkIHBhcnR5IGRlZmluaXRpb25zXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgICAgIHNjaGVtYSAgICAgIGRlZmF1bHQgc2NoZW1hIGRlZmluaXRpb24gZnJvbSB0aGUgbW9kZWwgKG9yIGVtcHR5IG9iamVjdCBpZiBub25lIGRlZmluZWQpXG5cdFx0ICogQHBhcmFtICAgIHN0cmluZyAgIG1vZGVsX3R5cGUgIHRoZSBtb2RlbCB0eXBlICgnbGVzc29uJywgJ3F1aXonLCBldGMpXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgICAgIG1vZGVsICAgICAgIEluc3RhbmNlIG9mIHRoZSBCYWNrYm9uZS5Nb2RlbCBmb3IgdGhlIGdpdmVuIG1vZGVsXG5cdFx0ICogQHJldHVybiAgIG9ialxuXHRcdCAqIEBzaW5jZSAgICAzLjE3LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNy4wXG5cdFx0ICovXG5cdFx0dGhpcy5nZXQgPSBmdW5jdGlvbiggc2NoZW1hLCBtb2RlbF90eXBlLCBtb2RlbCApIHtcblxuXHRcdFx0Ly8gZXh0ZW5kIHRoZSBkZWZhdWx0IHNjaGVtYSB3aXRoIGN1c3RvbSBwaHAgc2NoZW1hcyBmb3IgdGhlIHR5cGUgaWYgdGhleSBleGlzdFxuXHRcdFx0aWYgKCBjdXN0b21fc2NoZW1hc1sgbW9kZWxfdHlwZSBdICkge1xuXHRcdFx0XHRzY2hlbWEgPSBfLmV4dGVuZCggc2NoZW1hLCBjdXN0b21fc2NoZW1hc1sgbW9kZWxfdHlwZSBdICk7XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBzY2hlbWE7XG5cblx0XHR9O1xuXG5cdFx0cmV0dXJuIHRoaXM7XG5cblx0fTtcblxufSApO1xuXG4vKipcbiAqIFN5bmMgYnVpbGRlciBkYXRhIHRvIHRoZSBzZXJ2ZXJcbiAqIEBzaW5jZSAgICAzLjE2LjBcbiAqIEB2ZXJzaW9uICAzLjE3LjFcbiAqL1xuZGVmaW5lKCAnQ29udHJvbGxlcnMvU3luYycsW10sIGZ1bmN0aW9uKCkge1xuXG4gXHRyZXR1cm4gZnVuY3Rpb24oIENvdXJzZSwgc2V0dGluZ3MgKSB7XG5cbiBcdFx0dGhpcy5zYXZpbmcgPSBmYWxzZTtcblxuIFx0XHR2YXIgc2VsZiA9IHRoaXMsXG4gXHRcdFx0YXV0b3NhdmUgPSB0cnVlLFxuIFx0XHRcdGNoZWNrX2ludGVydmFsID0gbnVsbCxcbiBcdFx0XHRjaGVja19pbnRlcnZhbF9tcyA9IHNldHRpbmdzLmNoZWNrX2ludGVydmFsX21zIHx8IDEwMDAwLFxuIFx0XHRcdGRldGFjaGVkID0gbmV3IEJhY2tib25lLkNvbGxlY3Rpb24oKSxcbiBcdFx0XHR0cmFzaGVkID0gbmV3IEJhY2tib25lLkNvbGxlY3Rpb24oKTtcblxuXHRcdC8qKlxuXHRcdCAqIGluaXRcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2Ljdcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi43XG5cdFx0ICovXG4gXHRcdGZ1bmN0aW9uIGluaXQoKSB7XG5cbiBcdFx0XHQvLyBkZXRlcm1pbmUgaWYgYXV0b3NhdmluZyBpcyBwb3NzaWJsZVxuIFx0XHRcdGlmICggJ3VuZGVmaW5lZCcgPT09IHR5cGVvZiB3cC5oZWFydGJlYXQgKSB7XG5cbiBcdFx0XHRcdHdpbmRvdy5sbG1zX2J1aWxkZXIuZGVidWcubG9nKCAnV29yZFByZXNzIEhlYXJ0YmVhdCBkaXNhYmxlZC4gQXV0b3NhdmluZyBpcyBkaXNhYmxlZCEnICk7XG4gXHRcdFx0XHRhdXRvc2F2ZSA9IGZhbHNlO1xuXG4gXHRcdFx0fVxuXG5cdFx0XHQvLyBzZXR1cCB0aGUgY2hlY2sgaW50ZXJ2YWxcblx0XHRcdGlmICggY2hlY2tfaW50ZXJ2YWxfbXMgKSB7XG5cdFx0XHRcdHNlbGYuc2V0X2NoZWNrX2ludGVydmFsKCBjaGVja19pbnRlcnZhbF9tcyApO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyB3YXJuIHdoZW4gdXNlcnMgYXR0ZW1wdCB0byBsZWF2ZSB0aGUgcGFnZVxuXHRcdFx0JCggd2luZG93ICkub24oICdiZWZvcmV1bmxvYWQnLCBmdW5jdGlvbigpIHtcblxuXHRcdFx0XHRpZiAoIHNlbGYuaGFzX3Vuc2F2ZWRfY2hhbmdlcygpICkge1xuXHRcdFx0XHRcdGNoZWNrX2Zvcl9jaGFuZ2VzKCk7XG5cdFx0XHRcdFx0cmV0dXJuICdBcmUgeW91IHN1cmUgeW91IHdhbnQgdG8gYWJhbmRvbiB5b3VyIGNoYW5nZXM/Jztcblx0XHRcdFx0fVxuXG5cdFx0XHR9ICk7XG5cbiBcdFx0fTtcblxuIFx0XHQvKlxuIFx0XHRcdCAvJCQgICAgICAgICAgICAgLyQkICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLyQkICAgICAgICAgICAgICAgICAgICAgICAgICAgLyQkXG4gXHRcdFx0fF9fLyAgICAgICAgICAgIHwgJCQgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgJCQgICAgICAgICAgICAgICAgICAgICAgICAgIHxfXy9cbiBcdFx0XHQgLyQkIC8kJCQkJCQkICAvJCQkJCQkICAgIC8kJCQkJCQgICAvJCQkJCQkICAvJCQkJCQkJCAgIC8kJCQkJCQgfCAkJCAgICAgICAgLyQkJCQkJCAgIC8kJCQkJCQgIC8kJFxuIFx0XHRcdHwgJCR8ICQkX18gICQkfF8gICQkXy8gICAvJCRfXyAgJCQgLyQkX18gICQkfCAkJF9fICAkJCB8X19fXyAgJCR8ICQkICAgICAgIHxfX19fICAkJCAvJCRfXyAgJCR8ICQkXG4gXHRcdFx0fCAkJHwgJCQgIFxcICQkICB8ICQkICAgIHwgJCQkJCQkJCR8ICQkICBcXF9fL3wgJCQgIFxcICQkICAvJCQkJCQkJHwgJCQgICAgICAgIC8kJCQkJCQkfCAkJCAgXFwgJCR8ICQkXG4gXHRcdFx0fCAkJHwgJCQgIHwgJCQgIHwgJCQgLyQkfCAkJF9fX19fL3wgJCQgICAgICB8ICQkICB8ICQkIC8kJF9fICAkJHwgJCQgICAgICAgLyQkX18gICQkfCAkJCAgfCAkJHwgJCRcbiBcdFx0XHR8ICQkfCAkJCAgfCAkJCAgfCAgJCQkJC98ICAkJCQkJCQkfCAkJCAgICAgIHwgJCQgIHwgJCR8ICAkJCQkJCQkfCAkJCAgICAgIHwgICQkJCQkJCR8ICQkJCQkJCQvfCAkJFxuIFx0XHRcdHxfXy98X18vICB8X18vICAgXFxfX18vICAgXFxfX19fX19fL3xfXy8gICAgICB8X18vICB8X18vIFxcX19fX19fXy98X18vICAgICAgIFxcX19fX19fXy98ICQkX19fXy8gfF9fL1xuIFx0XHRcdCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgJCRcbiBcdFx0XHQgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8ICQkXG4gXHRcdFx0ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfF9fL1xuIFx0XHQqL1xuXG4gXHRcdC8qKlxuIFx0XHQgKiBBZGRzIGVycm9yIG1lc3NhZ2UocykgdG8gdGhlIGRhdGEgb2JqZWN0IHJldHVybmVkIGJ5IGhlYXJ0YmVhdC10aWNrXG4gXHRcdCAqIEBwYXJhbSAgICBvYmogICAgICAgICAgICBkYXRhICBsbG1zX2J1aWxkZXIgZGF0YSBvYmplY3QgZnJvbSBoZWFydGJlYXQtdGlja1xuIFx0XHQgKiBAcGFyYW0gICAgc3RyaW5nfGFycmF5ICAgZXJyICAgZXJyb3IgbWVzc2FnZXMgYXJyYXkgb3Igc3RyaW5nXG4gXHRcdCAqIEByZXR1cm4gICBvYmpcbiBcdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuIFx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG4gXHRcdCAqL1xuXHRcdGZ1bmN0aW9uIGFkZF9lcnJvcl9tc2coIGRhdGEsIGVyciApIHtcblxuXHRcdFx0aWYgKCAnc3VjY2VzcycgPT09IGRhdGEuc3RhdHVzICkge1xuXHRcdFx0XHRkYXRhLm1lc3NhZ2UgPSBbXTtcblx0XHRcdH1cblxuXHRcdFx0ZGF0YS5zdGF0dXMgPSAnZXJyb3InO1xuXHRcdFx0aWYgKCAnc3RyaW5nJyA9PT0gdHlwZW9mIGVyciApIHtcblx0XHRcdFx0ZXJyID0gWyBlcnIgXTtcblx0XHRcdH1cblx0XHRcdGRhdGEubWVzc2FnZSA9IGRhdGEubWVzc2FnZS5jb25jYXQoIGVyciApO1xuXG5cdFx0XHRyZXR1cm4gZGF0YTtcblxuXHRcdH07XG5cblx0XHQvKipcblx0XHQgKiBQdWJsaXNoIHN5bmMgc3RhdHVzIHNvIG90aGVyIGFyZWFzIG9mIHRoZSBhcHBsaWNhdGlvbiBjYW4gc2VlIHdoYXQncyBoYXBwZW5pbmcgaGVyZVxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRmdW5jdGlvbiBjaGVja19mb3JfY2hhbmdlcygpIHtcblxuXHRcdFx0dmFyIGRhdGEgPSB7fTtcblx0XHRcdGRhdGEuY2hhbmdlcyA9IHNlbGYuZ2V0X3Vuc2F2ZWRfY2hhbmdlcygpO1xuXHRcdFx0ZGF0YS5oYXNfdW5zYXZlZF9jaGFuZ2VzID0gc2VsZi5oYXNfdW5zYXZlZF9jaGFuZ2VzKCBkYXRhLmNoYW5nZXMgKTtcblx0XHRcdGRhdGEuc2F2aW5nID0gc2VsZi5zYXZpbmc7XG5cblx0XHRcdHdpbmRvdy5sbG1zX2J1aWxkZXIuZGVidWcubG9nKCAnPT09PSBzdGFydCBjaGFuZ2VzIGNoZWNrID09PT0nLCBkYXRhLCAnPT09PSBmaW5pc2ggY2hhbmdlcyBjaGVjayA9PT09JyApO1xuXG5cdFx0XHRCYWNrYm9uZS5wdWJTdWIudHJpZ2dlciggJ2N1cnJlbnQtc2F2ZS1zdGF0dXMnLCBkYXRhICk7XG5cblx0XHR9O1xuXG5cdFx0LyoqXG5cdFx0ICogTWFudWFsbHkgU2F2ZSBkYXRhIHZpYSBBZG1pbiBBSkFYIHdoZW4gdGhlIGhlYXJ0YmVhdCBBUEkgaGFzIGJlZW4gZGlzYWJsZWRcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2Ljdcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi43XG5cdFx0ICovXG5cdFx0ZnVuY3Rpb24gZG9fYWpheF9zYXZlKCkge1xuXG5cdFx0XHQvLyBwcmV2ZW50IHNpbXVsdGFuZW91cyBzYXZlc1xuXHRcdFx0aWYgKCBzZWxmLnNhdmluZyApIHtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXG5cdFx0XHR2YXIgY2hhbmdlcyA9IHNlbGYuZ2V0X3Vuc2F2ZWRfY2hhbmdlcygpO1xuXG5cdFx0XHQvLyBvbmx5IHNlbmQgZGF0YSBpZiB3ZSBoYXZlIGRhdGEgdG8gc2VuZFxuXHRcdFx0aWYgKCBzZWxmLmhhc191bnNhdmVkX2NoYW5nZXMoIGNoYW5nZXMgKSApIHtcblxuXHRcdFx0XHRjaGFuZ2VzLmlkID0gQ291cnNlLmdldCggJ2lkJyApO1xuXG5cdFx0XHRcdExMTVMuQWpheC5jYWxsKCB7XG5cdFx0XHRcdFx0ZGF0YToge1xuXHRcdFx0XHRcdFx0YWN0aW9uOiAnbGxtc19idWlsZGVyJyxcblx0XHRcdFx0XHRcdGFjdGlvbl90eXBlOiAnYWpheF9zYXZlJyxcblx0XHRcdFx0XHRcdGNvdXJzZV9pZDogY2hhbmdlcy5pZCxcblx0XHRcdFx0XHRcdGxsbXNfYnVpbGRlcjogSlNPTi5zdHJpbmdpZnkoIGNoYW5nZXMgKSxcblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdGJlZm9yZVNlbmQ6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHRcdFx0XHR3aW5kb3cubGxtc19idWlsZGVyLmRlYnVnLmxvZyggJz09PT0gc3RhcnQgZG9fYWpheF9zYXZlIGJlZm9yZSA9PT09JywgY2hhbmdlcywgJz09PT0gZmluaXNoIGRvX2FqYXhfc2F2ZSBiZWZvcmUgPT09PScgKTtcblxuXHRcdFx0XHRcdFx0c2VsZi5zYXZpbmcgPSB0cnVlO1xuXG5cdFx0XHRcdFx0XHRCYWNrYm9uZS5wdWJTdWIudHJpZ2dlciggJ2hlYXJ0YmVhdC1zZW5kJywgc2VsZiApO1xuXG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRlcnJvcjogZnVuY3Rpb24oIHhociwgc3RhdHVzLCBlcnJvciApIHtcblxuXHRcdFx0XHRcdFx0d2luZG93LmxsbXNfYnVpbGRlci5kZWJ1Zy5sb2coICc9PT09IHN0YXJ0IGRvX2FqYXhfc2F2ZSBlcnJvciA9PT09JywgZGF0YSwgJz09PT0gZmluaXNoIGRvX2FqYXhfc2F2ZSBlcnJvciA9PT09JyApO1xuXG5cdFx0XHRcdFx0XHRzZWxmLnNhdmluZyA9IGZhbHNlO1xuXG5cdFx0XHRcdFx0XHRCYWNrYm9uZS5wdWJTdWIudHJpZ2dlciggJ2hlYXJ0YmVhdC10aWNrJywgc2VsZiwge1xuXHRcdFx0XHRcdFx0XHRzdGF0dXM6ICdlcnJvcicsXG5cdFx0XHRcdFx0XHRcdG1lc3NhZ2U6IHhoci5yZXNwb25zZVRleHQgKyAnICgnICsgZXJyb3IgKyAnICcgKyBzdGF0dXMgKycpJyxcblx0XHRcdFx0XHRcdH0gKTtcblxuXHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0c3VjY2VzczogZnVuY3Rpb24oIHJlcyApIHtcblxuXHRcdFx0XHRcdFx0aWYgKCAhIHJlcy5sbG1zX2J1aWxkZXIgKSB7XG5cdFx0XHRcdFx0XHRcdHJldHVybjtcblx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0d2luZG93LmxsbXNfYnVpbGRlci5kZWJ1Zy5sb2coICc9PT09IHN0YXJ0IGRvX2FqYXhfc2F2ZSBzdWNjZXNzID09PT0nLCByZXMsICc9PT09IGZpbmlzaCBkb19hamF4X3NhdmUgc3VjY2VzcyA9PT09JyApO1xuXG5cdFx0XHRcdFx0XHRyZXMubGxtc19idWlsZGVyID0gcHJvY2Vzc19yZW1vdmFscyggcmVzLmxsbXNfYnVpbGRlciApO1xuXHRcdFx0XHRcdFx0cmVzLmxsbXNfYnVpbGRlciA9IHByb2Nlc3NfdXBkYXRlcyggcmVzLmxsbXNfYnVpbGRlciApO1xuXG5cdFx0XHRcdFx0XHRzZWxmLnNhdmluZyA9IGZhbHNlO1xuXG5cdFx0XHRcdFx0XHRCYWNrYm9uZS5wdWJTdWIudHJpZ2dlciggJ2hlYXJ0YmVhdC10aWNrJywgc2VsZiwgcmVzLmxsbXNfYnVpbGRlciApO1xuXG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdH0gKTtcblxuXHRcdFx0fVxuXG5cblx0XHR9O1xuXG5cdFx0LyoqXG5cdFx0ICogUmV0cmlldmUgYWxsIHRoZSBhdHRyaWJ1dGVzIGNoYW5nZWQgb24gYSBtb2RlbCBzaW5jZSB0aGUgbGFzdCBzeW5jXG5cdFx0ICpcblx0XHQgKiBGb3IgYSBuZXcgbW9kZWwgKGEgbW9kZWwgd2l0aCBhIHRlbXAgSUQpIG9yIGEgbW9kZWwgd2hlcmUgX2ZvcmNlU3luYyBoYXMgYmVlbiBkZWZpbmVkIEFMTCBhdHRzIHdpbGwgYmUgcmV0dXJuZWRcblx0XHQgKiBGb3IgYW4gZXhpc3RpbmcgbW9kZWwgKHdpdGhvdXQgYSB0ZW1wIElEKSBvbmx5IHJldHJpZXZlcyBjaGFuZ2VkIGF0dHJpYnV0ZXMgYXMgdHJhY2tlZCBieSBCYWNrYm9uZS5UcmFja0l0XG5cdFx0ICpcblx0XHQgKiBUaGlzIGZ1bmN0aW9uIGV4Y2x1ZGVzIGFueSBhdHRyaWJ1dGVzIGRlZmluZWQgYXMgY2hpbGQgYXR0cmlidXRlcyB2aWEgdGhlIG1vZGVscyByZWxhdGlvbnNoaXAgc2V0dGluZ3Ncblx0XHQgKlxuXHRcdCAqIEBwYXJhbSAgICBvYmogICBtb2RlbCAgaW5zdGFuY2Ugb2YgYSBCYWNrYm9uZS5Nb2RlbFxuXHRcdCAqIEByZXR1cm4gICBvYmpcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuNlxuXHRcdCAqL1xuXHRcdGZ1bmN0aW9uIGdldF9jaGFuZ2VkX2F0dHJpYnV0ZXMoIG1vZGVsICkge1xuXG5cdFx0XHR2YXIgYXR0cyA9IHt9LFxuXHRcdFx0XHRzeW5jX3R5cGU7XG5cblx0XHRcdC8vIGRvbid0IHNhdmUgbWlkIGVkaXRpbmdcblx0XHRcdGlmICggbW9kZWwuZ2V0KCAnX2hhc19mb2N1cycgKSApIHtcblx0XHRcdFx0cmV0dXJuIGF0dHM7XG5cdFx0XHR9XG5cblx0XHRcdC8vIG1vZGVsIGhhc24ndCBiZWVuIHBlcnNpc3RlZCB0byB0aGUgZGF0YWJhc2UgdG8gZ2V0IGEgcmVhbCBJRCB5ZXRcblx0XHRcdC8vIHNlbmQgKmFsbCogb2YgaXQncyBhdHRzXG5cdFx0XHRpZiAoIGhhc190ZW1wX2lkKCBtb2RlbCApIHx8IHRydWUgPT09IG1vZGVsLmdldCggJ19mb3JjZVN5bmMnICkgKSB7XG5cblx0XHRcdFx0YXR0cyA9IF8uY2xvbmUoIG1vZGVsLmF0dHJpYnV0ZXMgKTtcblx0XHRcdFx0c3luY190eXBlID0gJ2Z1bGwnO1xuXG5cdFx0XHQvLyBvbmx5IHNlbmQgdGhlIGNoYW5nZWQgYXR0c1xuXHRcdFx0fSBlbHNlIHtcblxuXHRcdFx0XHRhdHRzID0gbW9kZWwudW5zYXZlZEF0dHJpYnV0ZXMoKTtcblx0XHRcdFx0c3luY190eXBlID0gJ3BhcnRpYWwnO1xuXG5cdFx0XHR9XG5cblx0XHRcdHZhciBleGNsdWRlID0gKCBtb2RlbC5nZXRfcmVsYXRpb25zaGlwcyApID8gbW9kZWwuZ2V0X2NoaWxkX3Byb3BzKCkgOiBbXTtcblx0XHRcdGF0dHMgPSBfLm9taXQoIGF0dHMsIGZ1bmN0aW9uKCB2YWwsIGtleSApIHtcblxuXHRcdFx0XHQvLyBleGNsdWRlIGtleXMgdGhhdCBzdGFydCB3aXRoIGFuIHVuZGVyc2NvcmUgd2hpY2ggYXJlIHVzZWQgYnkgdGhlXG5cdFx0XHRcdC8vIGFwcGxpY2F0aW9uIGJ1dCBkb24ndCBuZWVkIHRvIGJlIHN0b3JlZCBpbiB0aGUgZGF0YWJhc2Vcblx0XHRcdFx0aWYgKCAwID09PSBrZXkuaW5kZXhPZiggJ18nICkgKSB7XG5cdFx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHRcdH0gZWxzZSBpZiAoIC0xICE9PSBleGNsdWRlLmluZGV4T2YoIGtleSApICkge1xuXHRcdFx0XHRcdHJldHVybiB0cnVlO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHJldHVybiBmYWxzZTtcblxuXHRcdFx0fSApO1xuXG5cdFx0XHRpZiAoIG1vZGVsLmJlZm9yZV9zYXZlICkge1xuXHRcdFx0XHRhdHRzID0gbW9kZWwuYmVmb3JlX3NhdmUoIGF0dHMsIHN5bmNfdHlwZSApO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gYXR0cztcblxuXHRcdH07XG5cblx0XHQvKipcblx0XHQgKiBHZXQgYWxsIHRoZSBjaGFuZ2VzIHRvIGFuIG9iamVjdCAoZWl0aGVyIGEgTW9kZWwgb3IgYSBDb2xsZWN0aW9uIG9mIG1vZGVscylcblx0XHQgKiBSZXR1cm5zIG9ubHkgY2hhbmdlcyB0byBtb2RlbHMgYW5kIHRoZSBJRHMgb2YgdGhhdCBtb2RlbCAoc2hvdWxkIGNoYW5nZXMgZXhpc3QpXG5cdFx0ICogVXNlcyBnZXRfY2hhbmdlZF9hdHRyaWJ1dGVzKCkgdG8gZGV0ZXJtaW5lIGlmIGFsbCBhdHRzIG9yIG9ubHkgY2hhbmdlZCBhdHRzIGFyZSBuZWVkZWRcblx0XHQgKiBQcm9jZXNzZXMgY2hpbGRyZW4gaW50ZWxsaWdlbnRseSB0byBvbmx5IHJldHVybiBjaGFuZ2VkIGNoaWxkcmVuIHJhdGhlciB0aGFuIHRoZSBlbnRpcmUgY29sbGVjdGlvbiBvZiBjaGlsZHJlblxuXHRcdCAqXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgICAgICAgb2JqZWN0ICBpbnN0YW5jZSBvZiBhIEJhY2tib25lLk1vZGVsIG9yIEJhY2tib25lLkNvbGxlY3Rpb25cblx0XHQgKiBAcmV0dXJuICAgb2JqfGFycmF5XHQgIFx0XHRpZiBvYmplY3QgaXMgYSBtb2RlbCwgcmV0dXJucyBhbiBvYmplY3Rcblx0XHQgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcdGlmIG9iamVjdCBpcyBhIGNvbGxlY3Rpb24sIHJldHVybnMgYW4gYXJyYXkgb2Ygb2JqZWN0c1xuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4xMVxuXHRcdCAqL1xuXHRcdGZ1bmN0aW9uIGdldF9jaGFuZ2VzX3RvX29iamVjdCggb2JqZWN0ICkge1xuXG5cdFx0XHR2YXIgY2hhbmdlZF9hdHRzO1xuXG5cdFx0XHRpZiAoIG9iamVjdCBpbnN0YW5jZW9mIEJhY2tib25lLk1vZGVsICkge1xuXG5cdFx0XHRcdGNoYW5nZWRfYXR0cyA9IGdldF9jaGFuZ2VkX2F0dHJpYnV0ZXMoIG9iamVjdCApO1xuXG5cdFx0XHRcdGlmICggb2JqZWN0LmdldF9yZWxhdGlvbnNoaXBzICkge1xuXG5cdFx0XHRcdFx0Xy5lYWNoKCBvYmplY3QuZ2V0X2NoaWxkX3Byb3BzKCksIGZ1bmN0aW9uKCBwcm9wICkge1xuXG5cdFx0XHRcdFx0XHR2YXIgY2hpbGRyZW4gPSBnZXRfY2hhbmdlc190b19vYmplY3QoIG9iamVjdC5nZXQoIHByb3AgKSApO1xuXHRcdFx0XHRcdFx0aWYgKCAhIF8uaXNFbXB0eSggY2hpbGRyZW4gKSApIHtcblx0XHRcdFx0XHRcdFx0Y2hhbmdlZF9hdHRzWyBwcm9wIF0gPSBjaGlsZHJlbjtcblx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdH0gKTtcblxuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gaWYgd2UgaGF2ZSBhbnkgZGF0YSwgYWRkIHRoZSBpZCB0byB0aGUgbW9kZWxcblx0XHRcdFx0aWYgKCAhIF8uaXNFbXB0eSggY2hhbmdlZF9hdHRzICkgKSB7XG5cdFx0XHRcdFx0Y2hhbmdlZF9hdHRzLmlkID0gb2JqZWN0LmdldCggJ2lkJyApO1xuXHRcdFx0XHR9XG5cblx0XHRcdH0gZWxzZSBpZiAoIG9iamVjdCBpbnN0YW5jZW9mIEJhY2tib25lLkNvbGxlY3Rpb24gKSB7XG5cblx0XHRcdFx0Y2hhbmdlZF9hdHRzID0gW107XG5cdFx0XHRcdG9iamVjdC5lYWNoKCBmdW5jdGlvbiggbW9kZWwgKSB7XG5cdFx0XHRcdFx0dmFyIG1vZGVsX2NoYW5nZXMgPSBnZXRfY2hhbmdlc190b19vYmplY3QoIG1vZGVsICk7XG5cdFx0XHRcdFx0aWYgKCAhIF8uaXNFbXB0eSggbW9kZWxfY2hhbmdlcyApICkge1xuXHRcdFx0XHRcdFx0Y2hhbmdlZF9hdHRzLnB1c2goIG1vZGVsX2NoYW5nZXMgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0gKTtcblxuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gY2hhbmdlZF9hdHRzO1xuXG5cdFx0fTtcblxuXHRcdC8qKlxuXHRcdCAqIERldGVybWluZXMgaWYgYSBtb2RlbCBoYXMgYSB0ZW1wb3JhcnkgSUQgb3IgYSByZWFsIHBlcnNpc3RlZCBJRFxuXHRcdCAqIEBwYXJhbSAgICBvYmogICBtb2RlbCAgaW5zdGFuY2Ugb2YgYSBtb2RlbFxuXHRcdCAqIEByZXR1cm4gICBib29sZWFuXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRmdW5jdGlvbiBoYXNfdGVtcF9pZCggbW9kZWwgKSB7XG5cblx0XHRcdHJldHVybiAoICEgXy5pc051bWJlciggbW9kZWwuaWQgKSAmJiAwID09PSBtb2RlbC5pZC5pbmRleE9mKCAndGVtcF8nICkgKTtcblxuXHRcdH07XG5cblx0XHQvKipcblx0XHQgKiBDb21wYXJlcyBjaGFuZ2VzIHN5bmNlZCB0byB0aGUgc2VydmVyIGFnYWluc3QgY3VycmVudCBtb2RlbCBhbmQgcmVzdGFydHNcblx0XHQgKiB0cmFja2luZyBvbiBlbGVtZW50cyB0aGF0IGhhdmVuJ3QgY2hhbmdlZCBzaW5jZSB0aGUgbGFzdCBzeW5jXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIG1vZGVsICBpbnN0YW5jZSBvZiBhIEJhY2tib25lLk1vZGVsXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIGRhdGEgICBkYXRhIHNldCB0aGF0IHdhcyBwcm9jZXNzZWQgYnkgdGhlIHNlcnZlclxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMTFcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi42XG5cdFx0ICovXG5cdFx0ZnVuY3Rpb24gbWF5YmVfcmVzdGFydF90cmFja2luZyggbW9kZWwsIGRhdGEgKSB7XG5cblx0XHRcdEJhY2tib25lLnB1YlN1Yi50cmlnZ2VyKCBtb2RlbC5nZXQoICd0eXBlJyApICsgJy1tYXliZS1yZXN0YXJ0LXRyYWNraW5nJywgbW9kZWwsIGRhdGEgKTtcblxuXHRcdFx0dmFyIG9taXQgPSBbICdpZCcsICdvcmlnX2lkJyBdO1xuXG5cdFx0XHRpZiAoIG1vZGVsLmdldF9yZWxhdGlvbnNoaXBzICkge1xuXHRcdFx0XHRvbWl0LmNvbmNhdCggbW9kZWwuZ2V0X2NoaWxkX3Byb3BzKCkgKTtcblx0XHRcdH1cblxuXHRcdFx0Xy5lYWNoKCBfLm9taXQoIGRhdGEsIG9taXQgKSwgZnVuY3Rpb24oIHZhbCwgcHJvcCApIHtcblxuXHRcdFx0XHRpZiAoIF8uaXNFcXVhbCggbW9kZWwuZ2V0KCBwcm9wICksIHZhbCApICkge1xuXHRcdFx0XHRcdGRlbGV0ZSBtb2RlbC5fdW5zYXZlZENoYW5nZXNbIHByb3AgXTtcblx0XHRcdFx0XHRtb2RlbC5fb3JpZ2luYWxBdHRyc1sgcHJvcCBdID0gdmFsO1xuXHRcdFx0XHR9XG5cblx0XHRcdH0gKTtcblxuXHRcdFx0Ly8gaWYgc3luY2luZyB3YXMgZm9yY2VkLCBhbGxvdyB0cmFja2luZyB0byBtb3ZlIGZvcndhcmQgYXMgbm9ybWFsIG1vdmluZyBmb3J3YXJkXG5cdFx0XHRtb2RlbC51bnNldCggJ19mb3JjZVN5bmMnICk7XG5cblx0XHR9O1xuXG5cdFx0LyoqXG5cdFx0ICogUHJvY2Vzc2VzIHJlc3BvbnNlIGRhdGEgZnJvbSBoZWFydGJlYXQtdGljayByZWxhdGVkIHRvIHRyYXNoaW5nICYgZGV0YWNoaW5nIG1vZGVsc1xuXHRcdCAqIE9uIHN1Y2Nlc3MsIHJlbW92ZXMgZnJvbSBsb2NhbCByZW1vdmFsIGNvbGxlY3Rpb25cblx0XHQgKiBPbiBlcnJvciwgYXBwZW5kcyBlcnJvciBtZXNzYWdlcyB0byB0aGUgZGF0YSBvYmplY3QgcmV0dXJuZWQgdG8gVUkgZm9yIG9uLXNjcmVlbiBmZWVkYmFja1xuXHRcdCAqIEBwYXJhbSAgICBvYmogICBkYXRhICBkYXRhLmxsbXNfYnVpbGRlciBvYmplY3QgZnJvbSBoZWFydGJlYXQtdGljayByZXNwb25zZVxuXHRcdCAqIEByZXR1cm4gICBvYmpcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTcuMVxuXHRcdCAqL1xuXHRcdGZ1bmN0aW9uIHByb2Nlc3NfcmVtb3ZhbHMoIGRhdGEgKSB7XG5cblx0XHRcdC8vIGNoZWNrIHJlbW92YWxzIGZvciBlcnJvcnNcblx0XHRcdHZhciByZW1vdmFscyA9IHtcblx0XHRcdFx0ZGV0YWNoOiBkZXRhY2hlZCxcblx0XHRcdFx0dHJhc2g6IHRyYXNoZWQsXG5cdFx0XHR9O1xuXG5cdFx0XHRfLmVhY2goIHJlbW92YWxzLCBmdW5jdGlvbiggY29sbCwga2V5ICkge1xuXG5cdFx0XHRcdGlmICggZGF0YVsga2V5IF0gKSB7XG5cblx0XHRcdFx0XHR2YXIgZXJyb3JzID0gW107XG5cblx0XHRcdFx0XHRfLmVhY2goIGRhdGFbIGtleSBdICwgZnVuY3Rpb24oIGluZm8gKSB7XG5cblx0XHRcdFx0XHRcdC8vIHN1Y2Nlc2Z1bGx5IGRldGFjaGVkLCByZW1vdmUgaXQgZnJvbSB0aGUgZGV0YWNoZWQgY29sbGVjdGlvblxuXHRcdFx0XHRcdFx0aWYgKCAhIGluZm8uZXJyb3IgKSB7XG5cblx0XHRcdFx0XHRcdFx0Y29sbC5yZW1vdmUoIGluZm8uaWQgKTtcblxuXHRcdFx0XHRcdFx0fSBlbHNlIHtcblxuXHRcdFx0XHRcdFx0XHRlcnJvcnMucHVzaCggaW5mby5lcnJvciApO1xuXG5cdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHR9ICk7XG5cblx0XHRcdFx0XHRpZiAoIGVycm9ycy5sZW5ndGggKSB7XG5cdFx0XHRcdFx0XHRfLmV4dGVuZCggZGF0YSwgYWRkX2Vycm9yX21zZyggZGF0YSwgZXJyb3JzICkgKTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0fVxuXG5cdFx0XHR9ICk7XG5cblx0XHRcdHJldHVybiBkYXRhO1xuXHRcdH1cblxuXHRcdC8qKlxuXHRcdCAqIFByb2Nlc3NlcyByZXNwb25zZSBkYXRhIGZyb20gaGVhcnRiZWF0LXRpY2sgcmVsYXRlZCB0byBjcmVhdGluZyAvIHVwZGF0aW5nIGEgc2luZ2xlIG9iamVjdFxuXHRcdCAqIEhhbmRsZXMgYm90aCBjb2xsZWN0aW9ucyBhbmQgbW9kZWxzIGFzIGEgcmVjdXJzaXZlIGZ1bmN0aW9uXG5cdFx0ICogQHBhcmFtICAgIHtbdHlwZV19ICAgZGF0YSAgICAgICBbZGVzY3JpcHRpb25dXG5cdFx0ICogQHBhcmFtICAgIHtbdHlwZV19ICAgdHlwZSAgICAgICBbZGVzY3JpcHRpb25dXG5cdFx0ICogQHBhcmFtICAgIHtbdHlwZV19ICAgcGFyZW50ICAgICBbZGVzY3JpcHRpb25dXG5cdFx0ICogQHBhcmFtICAgIHtbdHlwZV19ICAgbWFpbl9kYXRhICBbZGVzY3JpcHRpb25dXG5cdFx0ICogQHJldHVybiAgIHtbdHlwZV19XG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjExXG5cdFx0ICovXG5cdFx0ZnVuY3Rpb24gcHJvY2Vzc19vYmplY3RfdXBkYXRlcyggZGF0YSwgdHlwZSwgcGFyZW50LCBtYWluX2RhdGEgKSB7XG5cblx0XHRcdGlmICggISBkYXRhWyB0eXBlIF0gKSB7XG5cdFx0XHRcdHJldHVybiBkYXRhO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIHBhcmVudC5nZXQoIHR5cGUgKSBpbnN0YW5jZW9mIEJhY2tib25lLk1vZGVsICkge1xuXG5cdFx0XHRcdHZhciBpbmZvID0gZGF0YVsgdHlwZSBdO1xuXG5cdFx0XHRcdGlmICggaW5mby5lcnJvciApIHtcblxuXHRcdFx0XHRcdF8uZXh0ZW5kKCBtYWluX2RhdGEsIGFkZF9lcnJvcl9tc2coIG1haW5fZGF0YSwgaW5mby5lcnJvciApICk7XG5cblx0XHRcdFx0fSBlbHNlIHtcblxuXHRcdFx0XHRcdHZhciBtb2RlbCA9IHBhcmVudC5nZXQoIHR5cGUgKTtcblxuXHRcdFx0XHRcdC8vIHVwZGF0ZSB0ZW1wIGlkcyB3aXRoIHRoZSByZWFsIGlkXG5cdFx0XHRcdFx0aWYgKCBpbmZvLmlkICE9IGluZm8ub3JpZ19pZCApIHtcblx0XHRcdFx0XHRcdG1vZGVsLnNldCggJ2lkJywgaW5mby5pZCApO1xuXHRcdFx0XHRcdFx0ZGVsZXRlIG1vZGVsLl91bnNhdmVkQ2hhbmdlcy5pZDtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0bWF5YmVfcmVzdGFydF90cmFja2luZyggbW9kZWwsIGluZm8gKTtcblxuXHRcdFx0XHRcdC8vIGNoZWNrIGNoaWxkcmVuXG5cdFx0XHRcdFx0aWYgKCBtb2RlbC5nZXRfcmVsYXRpb25zaGlwcyApIHtcblxuXHRcdFx0XHRcdFx0Xy5lYWNoKCBtb2RlbC5nZXRfY2hpbGRfcHJvcHMoKSwgZnVuY3Rpb24oIGNoaWxkX2tleSApIHtcblx0XHRcdFx0XHRcdFx0Xy5leHRlbmQoIGRhdGFbIHR5cGUgXSwgcHJvY2Vzc19vYmplY3RfdXBkYXRlcyggZGF0YVsgdHlwZSBdLCBjaGlsZF9rZXksIG1vZGVsLCBtYWluX2RhdGEgKSApO1xuXHRcdFx0XHRcdFx0fSApO1xuXG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdH1cblxuXHRcdFx0fSBlbHNlIGlmICggcGFyZW50LmdldCggdHlwZSApIGluc3RhbmNlb2YgQmFja2JvbmUuQ29sbGVjdGlvbiApIHtcblxuXHRcdFx0XHRfLmVhY2goIGRhdGFbIHR5cGUgXSwgZnVuY3Rpb24oIGluZm8sIGluZGV4ICkge1xuXG5cdFx0XHRcdFx0aWYgKCBpbmZvLmVycm9yICkge1xuXG5cdFx0XHRcdFx0XHRfLmV4dGVuZCggbWFpbl9kYXRhLCBhZGRfZXJyb3JfbXNnKCBtYWluX2RhdGEsIGluZm8uZXJyb3IgKSApO1xuXG5cdFx0XHRcdFx0fSBlbHNlIHtcblxuXHRcdFx0XHRcdFx0dmFyIG1vZGVsID0gcGFyZW50LmdldCggdHlwZSApLmdldCggaW5mby5vcmlnX2lkICk7XG5cblx0XHRcdFx0XHRcdC8vIHVwZGF0ZSB0ZW1wIGlkcyB3aXRoIHRoZSByZWFsIGlkXG5cdFx0XHRcdFx0XHRpZiAoIGluZm8uaWQgIT0gaW5mby5vcmlnX2lkICkge1xuXHRcdFx0XHRcdFx0XHRtb2RlbC5zZXQoICdpZCcsIGluZm8uaWQgKTtcblx0XHRcdFx0XHRcdFx0ZGVsZXRlIG1vZGVsLl91bnNhdmVkQ2hhbmdlcy5pZDtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdG1heWJlX3Jlc3RhcnRfdHJhY2tpbmcoIG1vZGVsLCBpbmZvICk7XG5cblx0XHRcdFx0XHRcdC8vIGNoZWNrIGNoaWxkcmVuXG5cdFx0XHRcdFx0XHRpZiAoIG1vZGVsLmdldF9yZWxhdGlvbnNoaXBzICkge1xuXG5cdFx0XHRcdFx0XHRcdF8uZWFjaCggbW9kZWwuZ2V0X2NoaWxkX3Byb3BzKCksIGZ1bmN0aW9uKCBjaGlsZF9rZXkgKSB7XG5cdFx0XHRcdFx0XHRcdFx0Xy5leHRlbmQoIGRhdGFbIHR5cGUgXSwgcHJvY2Vzc19vYmplY3RfdXBkYXRlcyggZGF0YVsgdHlwZSBdWyBpbmRleCBdLCBjaGlsZF9rZXksIG1vZGVsLCBtYWluX2RhdGEgKSApO1xuXHRcdFx0XHRcdFx0XHR9ICk7XG5cblx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHR9ICk7XG5cblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIG1haW5fZGF0YTtcblxuXHRcdH07XG5cblx0XHQvKipcblx0XHQgKiBQcm9jZXNzZXMgcmVzcG9uc2UgZGF0YSBmcm9tIGhlYXJ0YmVhdC10aWNrIHJlbGF0ZWQgdG8gdXBkYXRpbmcgJiBjcmVhdGluZyBuZXcgbW9kZWxzXG5cdFx0ICogT24gc3VjY2VzcywgcmVtb3ZlcyBmcm9tIGxvY2FsIHJlbW92YWwgY29sbGVjdGlvblxuXHRcdCAqIE9uIGVycm9yLCBhcHBlbmRzIGVycm9yIG1lc3NhZ2VzIHRvIHRoZSBkYXRhIG9iamVjdCByZXR1cm5lZCB0byBVSSBmb3Igb24tc2NyZWVuIGZlZWRiYWNrXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIGRhdGEgIGRhdGEubGxtc19idWlsZGVyIG9iamVjdCBmcm9tIGhlYXJ0YmVhdC10aWNrIHJlc3BvbnNlXG5cdFx0ICogQHJldHVybiAgIG9ialxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0ZnVuY3Rpb24gcHJvY2Vzc191cGRhdGVzKCBkYXRhICkge1xuXG5cdFx0XHQvLyBvbmx5IG1lc3Mgd2l0aCB1cGRhdGVzIGRhdGFcblx0XHRcdGlmICggISBkYXRhLnVwZGF0ZXMgKSB7XG5cdFx0XHRcdHJldHVybiBkYXRhO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIGRhdGEudXBkYXRlcyApIHtcblx0XHRcdFx0ZGF0YSA9IHByb2Nlc3Nfb2JqZWN0X3VwZGF0ZXMoIGRhdGEudXBkYXRlcywgJ3NlY3Rpb25zJywgQ291cnNlLCBkYXRhICk7XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBkYXRhO1xuXG5cdFx0fTtcblxuXHRcdC8qXG5cdFx0XHQgICAgICAgICAgICAgICAgICAgICAvJCQgICAgICAgLyQkIC8kJCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvJCRcblx0XHRcdCAgICAgICAgICAgICAgICAgICAgfCAkJCAgICAgIHwgJCR8X18vICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfF9fL1xuXHRcdFx0ICAvJCQkJCQkICAvJCQgICAvJCR8ICQkJCQkJCQgfCAkJCAvJCQgIC8kJCQkJCQkICAgICAgICAvJCQkJCQkICAgLyQkJCQkJCAgLyQkXG5cdFx0XHQgLyQkX18gICQkfCAkJCAgfCAkJHwgJCRfXyAgJCR8ICQkfCAkJCAvJCRfX19fXy8gICAgICAgfF9fX18gICQkIC8kJF9fICAkJHwgJCRcblx0XHRcdHwgJCQgIFxcICQkfCAkJCAgfCAkJHwgJCQgIFxcICQkfCAkJHwgJCR8ICQkICAgICAgICAgICAgICAvJCQkJCQkJHwgJCQgIFxcICQkfCAkJFxuXHRcdFx0fCAkJCAgfCAkJHwgJCQgIHwgJCR8ICQkICB8ICQkfCAkJHwgJCR8ICQkICAgICAgICAgICAgIC8kJF9fICAkJHwgJCQgIHwgJCR8ICQkXG5cdFx0XHR8ICQkJCQkJCQvfCAgJCQkJCQkL3wgJCQkJCQkJC98ICQkfCAkJHwgICQkJCQkJCQgICAgICB8ICAkJCQkJCQkfCAkJCQkJCQkL3wgJCRcblx0XHRcdHwgJCRfX19fLyAgXFxfX19fX18vIHxfX19fX19fLyB8X18vfF9fLyBcXF9fX19fX18vICAgICAgIFxcX19fX19fXy98ICQkX19fXy8gfF9fL1xuXHRcdFx0fCAkJCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgJCRcblx0XHRcdHwgJCQgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8ICQkXG5cdFx0XHR8X18vICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfF9fL1xuXHRcdCovXG5cblx0XHQvKipcblx0XHQgKiBSZXRyaWV2ZSBhbGwgdW5zYXZlZCBjaGFuZ2VzIGZvciB0aGUgYnVpbGRlciBpbnN0YW5jZVxuXHRcdCAqIEByZXR1cm4gICBvYmpcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTcuMVxuXHRcdCAqL1xuXHRcdHRoaXMuZ2V0X3Vuc2F2ZWRfY2hhbmdlcyA9IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHRyZXR1cm4ge1xuXHRcdFx0XHRkZXRhY2g6IGRldGFjaGVkLnBsdWNrKCAnaWQnICksXG5cdFx0XHRcdHRyYXNoOiB0cmFzaGVkLnBsdWNrKCAnaWQnICksXG5cdFx0XHRcdHVwZGF0ZXM6IGdldF9jaGFuZ2VzX3RvX29iamVjdCggQ291cnNlICksXG5cblx0XHRcdH1cblx0XHR9O1xuXG5cdFx0LyoqXG5cdFx0ICogQ2hlY2sgaWYgdGhlIGJ1aWxkZXIgaW5zdGFuY2UgaGFzIHVuc2F2ZWQgY2hhbmdlc1xuXHRcdCAqIEBwYXJhbSAgICBvYmogICAgICBjaGFuZ2VzICAgIG9wdGlvbmFsbHkgcGFzcyBpbiBhbiBvYmplY3QgZnJvbSB0aGUgcmV0dXJuIG9mIHRoaXMuZ2V0X3Vuc2F2ZWRfY2hhbmdlcygpXG5cdFx0ICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2F2ZSBzb21lIHJlc291cmNlcyBieSBub3QgcnVubmluZyB0aGUgY2hlY2sgdHdpY2UgZHVyaW5nIGhlYXJ0YmVhdHNcblx0XHQgKiBAcmV0dXJuICAgYm9vbGVhblxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0dGhpcy5oYXNfdW5zYXZlZF9jaGFuZ2VzID0gZnVuY3Rpb24oIGNoYW5nZXMgKSB7XG5cblx0XHRcdGlmICggJ3VuZGVmaW5lZCcgPT09IHR5cGVvZiBjaGFuZ2VzICkge1xuXHRcdFx0XHRjaGFuZ2VzID0gc2VsZi5nZXRfdW5zYXZlZF9jaGFuZ2VzKCk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIGNoZWNrIGFsbCBwb3NzaWJsZSBrZXlzLCBvbmNlIHdlIGZpbmQgb25lIHdpdGggY29udGVudCB3ZSBoYXZlIHNvbWUgY2hhbmdlcyB0byBwZXJzaXN0XG5cdFx0XHR2YXIgZm91bmQgPSBfLmZpbmQoIGNoYW5nZXMsIGZ1bmN0aW9uKCBkYXRhICkge1xuXG5cdFx0XHRcdHJldHVybiAoIGZhbHNlID09PSBfLmlzRW1wdHkoIGRhdGEgKSApO1xuXG5cdFx0XHR9ICk7XG5cblx0XHRcdHJldHVybiBmb3VuZCA/IHRydWUgOiBmYWxzZTtcblxuXHRcdH07XG5cblx0XHQvKipcblx0XHQgKiBTYXZlIGNoYW5nZXMgcmlnaHQgbm93LlxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2Ljdcblx0XHQgKi9cblx0XHR0aGlzLnNhdmVfbm93ID0gZnVuY3Rpb24oKSB7XG5cdFx0XHRpZiAoIGF1dG9zYXZlICkge1xuXHRcdFx0XHR3cC5oZWFydGJlYXQuY29ubmVjdE5vdygpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0ZG9fYWpheF9zYXZlKCk7XG5cdFx0XHR9XG5cdFx0fTtcblxuXHRcdC8qKlxuXHRcdCAqIFVwZGF0ZSB0aGUgaW50ZXJ2YWwgdGhhdCBjaGVja3MgZm9yIGNoYW5nZXMgdG8gdGhlIGJ1aWxkZXIgaW5zdGFuY2Vcblx0XHQgKiBAcGFyYW0gICAgaW50ICAgICAgICBtcyAgIHRpbWUgKGluIG1pbGxpc2Vjb25kcykgdG8gcnVuIHRoZSBjaGVjayBvblxuXHRcdCAqICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFzcyAwIHRvIGRpc2FibGUgdGhlIGNoZWNrXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdHRoaXMuc2V0X2NoZWNrX2ludGVydmFsID0gZnVuY3Rpb24oIG1zICkge1xuXHRcdFx0Y2hlY2tfaW50ZXJ2YWxfbXMgPSBtcztcblx0XHRcdGlmICggY2hlY2tfaW50ZXJ2YWwgKSB7XG5cdFx0XHRcdGNsZWFySW50ZXJ2YWwoIGNoZWNrX2ludGVydmFsICk7XG5cdFx0XHR9XG5cdFx0XHRpZiAoIGNoZWNrX2ludGVydmFsX21zICkge1xuXHRcdFx0XHRjaGVja19pbnRlcnZhbCA9IHNldEludGVydmFsKCBjaGVja19mb3JfY2hhbmdlcywgY2hlY2tfaW50ZXJ2YWxfbXMgKTtcblx0XHRcdH1cblx0XHR9O1xuXG5cdFx0Lypcblx0XHRcdCAvJCQgLyQkICAgICAgICAgICAgIC8kJFxuXHRcdFx0fCAkJHxfXy8gICAgICAgICAgICB8ICQkXG5cdFx0XHR8ICQkIC8kJCAgLyQkJCQkJCQgLyQkJCQkJCAgICAvJCQkJCQkICAvJCQkJCQkJCAgIC8kJCQkJCQgICAvJCQkJCQkICAgLyQkJCQkJCRcblx0XHRcdHwgJCR8ICQkIC8kJF9fX19fL3xfICAkJF8vICAgLyQkX18gICQkfCAkJF9fICAkJCAvJCRfXyAgJCQgLyQkX18gICQkIC8kJF9fX19fL1xuXHRcdFx0fCAkJHwgJCR8ICAkJCQkJCQgICB8ICQkICAgIHwgJCQkJCQkJCR8ICQkICBcXCAkJHwgJCQkJCQkJCR8ICQkICBcXF9fL3wgICQkJCQkJFxuXHRcdFx0fCAkJHwgJCQgXFxfX19fICAkJCAgfCAkJCAvJCR8ICQkX19fX18vfCAkJCAgfCAkJHwgJCRfX19fXy98ICQkICAgICAgIFxcX19fXyAgJCRcblx0XHRcdHwgJCR8ICQkIC8kJCQkJCQkLyAgfCAgJCQkJC98ICAkJCQkJCQkfCAkJCAgfCAkJHwgICQkJCQkJCR8ICQkICAgICAgIC8kJCQkJCQkL1xuXHRcdFx0fF9fL3xfXy98X19fX19fXy8gICAgXFxfX18vICAgXFxfX19fX19fL3xfXy8gIHxfXy8gXFxfX19fX19fL3xfXy8gICAgICB8X19fX19fXy9cblx0XHQqL1xuXG5cdFx0LyoqXG5cdFx0ICogTGlzdGVuIGZvciBkZXRhY2hlZCBtb2RlbHMgYW5kIHNlbmQgdGhlbSB0byB0aGUgc2VydmVyIGZvciBwZXJzaXN0ZW5jZVxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0QmFja2JvbmUucHViU3ViLm9uKCAnbW9kZWwtZGV0YWNoZWQnLCBmdW5jdGlvbiggbW9kZWwgKSB7XG5cblx0XHRcdC8vIGRldGFjaGVkIG1vZGVscyB3aXRoIHRlbXAgaWRzIGhhdmVuJ3QgYmVlbiBwZXJzaXN0ZWQgc28gd2UgZG9uJ3QgY2FyZVxuXHRcdFx0aWYgKCBoYXNfdGVtcF9pZCggbW9kZWwgKSApIHtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXG5cdFx0XHRkZXRhY2hlZC5hZGQoIF8uY2xvbmUoIG1vZGVsLmF0dHJpYnV0ZXMgKSApO1xuXG5cdFx0fSApO1xuXG5cdFx0LyoqXG5cdFx0ICogTGlzdGVuIGZvciB0cmFzaGVkIG1vZGVscyBhbmQgc2VuZCB0aGVtIHRvIHRoZSBzZXJ2ZXIgZm9yIGRlbGV0aW9uXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE3LjFcblx0XHQgKi9cblx0XHRCYWNrYm9uZS5wdWJTdWIub24oICdtb2RlbC10cmFzaGVkJywgZnVuY3Rpb24oIG1vZGVsICkge1xuXG5cdFx0XHQvLyBpZiB0aGUgbW9kZWwgaGFzIGEgdGVtcCBJRCB3ZSBkb24ndCBoYXZlIHRvIHBlcnNpc3QgdGhlIGRlbGV0aW9uXG5cdFx0XHRpZiAoIGhhc190ZW1wX2lkKCBtb2RlbCApICkge1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cblx0XHRcdHZhciBkYXRhID0gXy5jbG9uZSggbW9kZWwuYXR0cmlidXRlcyApO1xuXG5cdFx0XHRpZiAoIG1vZGVsLmdldF90cmFzaF9pZCApIHtcblx0XHRcdFx0ZGF0YS5pZCA9IG1vZGVsLmdldF90cmFzaF9pZCgpO1xuXHRcdFx0fVxuXG5cdFx0XHR0cmFzaGVkLmFkZCggZGF0YSApO1xuXG5cdFx0fSApO1xuXG5cdFx0Lypcblx0XHRcdCAvJCQgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvJCQgICAgIC8kJCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLyQkXG5cdFx0XHR8ICQkICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8ICQkICAgIHwgJCQgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCAkJFxuXHRcdFx0fCAkJCQkJCQkICAgLyQkJCQkJCAgIC8kJCQkJCQgICAvJCQkJCQkICAvJCQkJCQkICB8ICQkJCQkJCQgICAvJCQkJCQkICAgLyQkJCQkJCAgLyQkJCQkJFxuXHRcdFx0fCAkJF9fICAkJCAvJCRfXyAgJCQgfF9fX18gICQkIC8kJF9fICAkJHxfICAkJF8vICB8ICQkX18gICQkIC8kJF9fICAkJCB8X19fXyAgJCR8XyAgJCRfL1xuXHRcdFx0fCAkJCAgXFwgJCR8ICQkJCQkJCQkICAvJCQkJCQkJHwgJCQgIFxcX18vICB8ICQkICAgIHwgJCQgIFxcICQkfCAkJCQkJCQkJCAgLyQkJCQkJCQgIHwgJCRcblx0XHRcdHwgJCQgIHwgJCR8ICQkX19fX18vIC8kJF9fICAkJHwgJCQgICAgICAgIHwgJCQgLyQkfCAkJCAgfCAkJHwgJCRfX19fXy8gLyQkX18gICQkICB8ICQkIC8kJFxuXHRcdFx0fCAkJCAgfCAkJHwgICQkJCQkJCR8ICAkJCQkJCQkfCAkJCAgICAgICAgfCAgJCQkJC98ICQkJCQkJCQvfCAgJCQkJCQkJHwgICQkJCQkJCQgIHwgICQkJCQvXG5cdFx0XHR8X18vICB8X18vIFxcX19fX19fXy8gXFxfX19fX19fL3xfXy8gICAgICAgICBcXF9fXy8gIHxfX19fX19fLyAgXFxfX19fX19fLyBcXF9fX19fX18vICAgXFxfX18vXG5cdFx0Ki9cblxuXHRcdC8qKlxuXHRcdCAqIEFkZCBkYXRhIHRvIHRoZSBXUCBoZWFydGJlYXQgdG8gcGVyc2lzdCBuZXcgbW9kZWxzLCBjaGFuZ2VzLCBhbmQgZGVsZXRpb25zIHRvIHRoZSBEQlxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi43XG5cdFx0ICovXG5cdFx0JCggZG9jdW1lbnQgKS5vbiggJ2hlYXJ0YmVhdC1zZW5kJywgZnVuY3Rpb24oIGV2ZW50LCBkYXRhICkge1xuXG5cdFx0XHQvLyBwcmV2ZW50IHNpbXVsdGFuZW91cyBzYXZlc1xuXHRcdFx0aWYgKCBzZWxmLnNhdmluZyApIHtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXG5cdFx0XHR2YXIgY2hhbmdlcyA9IHNlbGYuZ2V0X3Vuc2F2ZWRfY2hhbmdlcygpO1xuXG5cdFx0XHQvLyBvbmx5IHNlbmQgZGF0YSBpZiB3ZSBoYXZlIGRhdGEgdG8gc2VuZFxuXHRcdFx0aWYgKCBzZWxmLmhhc191bnNhdmVkX2NoYW5nZXMoIGNoYW5nZXMgKSApIHtcblxuXHRcdFx0XHRjaGFuZ2VzLmlkID0gQ291cnNlLmdldCggJ2lkJyApO1xuXHRcdFx0XHRzZWxmLnNhdmluZyA9IHRydWU7XG5cdFx0XHRcdGRhdGEubGxtc19idWlsZGVyID0gSlNPTi5zdHJpbmdpZnkoIGNoYW5nZXMgKTtcblxuXHRcdFx0fVxuXG5cdFx0XHR3aW5kb3cubGxtc19idWlsZGVyLmRlYnVnLmxvZyggJz09PT0gc3RhcnQgaGVhcnRiZWF0LXNlbmQgPT09PScsIGRhdGEsICc9PT09IGZpbmlzaCBoZWFydGJlYXQtc2VuZCA9PT09JyApO1xuXG5cdFx0XHRCYWNrYm9uZS5wdWJTdWIudHJpZ2dlciggJ2hlYXJ0YmVhdC1zZW5kJywgc2VsZiApO1xuXG5cdFx0fSApO1xuXG5cdFx0LyoqXG5cdFx0ICogQ29uZmlybSBkZXRhY2htZW50cyAmIGRlbGV0aW9ucyBhbmQgcmVwbGFjZSB0ZW1wIElEcyB3aXRoIG5ldyBwZXJzaXN0ZWQgSURzXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHQkKCBkb2N1bWVudCApLm9uKCAnaGVhcnRiZWF0LXRpY2snLCBmdW5jdGlvbiggZXZlbnQsIGRhdGEgKSB7XG5cblx0XHRcdGlmICggISBkYXRhLmxsbXNfYnVpbGRlciApIHtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXG5cdFx0XHR3aW5kb3cubGxtc19idWlsZGVyLmRlYnVnLmxvZyggJz09PT0gc3RhcnQgaGVhcnRiZWF0LXRpY2sgPT09PScsIGRhdGEsICc9PT09IGZpbmlzaCBoZWFydGJlYXQtdGljayA9PT09JyApO1xuXG5cdFx0XHRkYXRhLmxsbXNfYnVpbGRlciA9IHByb2Nlc3NfcmVtb3ZhbHMoIGRhdGEubGxtc19idWlsZGVyICk7XG5cdFx0XHRkYXRhLmxsbXNfYnVpbGRlciA9IHByb2Nlc3NfdXBkYXRlcyggZGF0YS5sbG1zX2J1aWxkZXIgKTtcblxuXHRcdFx0c2VsZi5zYXZpbmcgPSBmYWxzZTtcblxuXHRcdFx0QmFja2JvbmUucHViU3ViLnRyaWdnZXIoICdoZWFydGJlYXQtdGljaycsIHNlbGYsIGRhdGEubGxtc19idWlsZGVyICk7XG5cblx0XHR9ICk7XG5cblx0XHQvKipcblx0XHQgKiBPbiBoZWFydGJlYXQgZXJyb3JzIHB1Ymxpc2ggYW4gZXJyb3IgdG8gdGhlIG1haW4gYnVpbGRlciBhcHBsaWNhdGlvblxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0JCggZG9jdW1lbnQgKS5vbiggJ2hlYXJ0YmVhdC1lcnJvcicsIGZ1bmN0aW9uKCBldmVudCwgZGF0YSApIHtcblxuXHRcdFx0d2luZG93LmxsbXNfYnVpbGRlci5kZWJ1Zy5sb2coICc9PT09IHN0YXJ0IGhlYXJ0YmVhdC1lcnJvciA9PT09JywgZGF0YSwgJz09PT0gZmluaXNoIGhlYXJ0YmVhdC1lcnJvciA9PT09JyApO1xuXG5cdFx0XHRzZWxmLnNhdmluZyA9IGZhbHNlO1xuXG5cdFx0XHRCYWNrYm9uZS5wdWJTdWIudHJpZ2dlciggJ2hlYXJ0YmVhdC10aWNrJywgc2VsZiwge1xuXHRcdFx0XHRzdGF0dXM6ICdlcnJvcicsXG5cdFx0XHRcdG1lc3NhZ2U6IGRhdGEucmVzcG9uc2VUZXh0ICsgJyAoJyArIGRhdGEuc3RhdHVzICsgJyAnICsgZGF0YS5zdGF0dXNUZXh0ICsnKScsXG5cdFx0XHR9ICk7XG5cblx0XHR9ICk7XG5cblx0XHQvKlxuXHRcdFx0IC8kJCAgICAgICAgICAgLyQkICAgLyQkXG5cdFx0XHR8X18vICAgICAgICAgIHxfXy8gIHwgJCRcblx0XHRcdCAvJCQgLyQkJCQkJCQgIC8kJCAvJCQkJCQkXG5cdFx0XHR8ICQkfCAkJF9fICAkJHwgJCR8XyAgJCRfL1xuXHRcdFx0fCAkJHwgJCQgIFxcICQkfCAkJCAgfCAkJFxuXHRcdFx0fCAkJHwgJCQgIHwgJCR8ICQkICB8ICQkIC8kJFxuXHRcdFx0fCAkJHwgJCQgIHwgJCR8ICQkICB8ICAkJCQkL1xuXHRcdFx0fF9fL3xfXy8gIHxfXy98X18vICAgXFxfX18vXG5cdFx0Ki9cblx0XHRpbml0KCk7XG5cblx0XHRyZXR1cm4gdGhpcztcblxuXHR9O1xuXG59ICk7XG5cbi8qKlxuICogU2luZ2xlIExlc3NvbiBWaWV3XG4gKiBAc2luY2UgICAgMy4xNi4wXG4gKiBAdmVyc2lvbiAgMy4xNy4wXG4gKi9cbmRlZmluZSggJ1ZpZXdzL0xlc3NvbicsW1xuXHRcdCdWaWV3cy9fRGV0YWNoYWJsZScsXG5cdFx0J1ZpZXdzL19FZGl0YWJsZScsXG5cdFx0J1ZpZXdzL19TaGlmdGFibGUnLFxuXHRcdCdWaWV3cy9fVHJhc2hhYmxlJ1xuXHRdLCBmdW5jdGlvbihcblx0XHREZXRhY2hhYmxlLFxuXHRcdEVkaXRhYmxlLFxuXHRcdFNoaWZ0YWJsZSxcblx0XHRUcmFzaGFibGVcblx0KSB7XG5cblx0cmV0dXJuIEJhY2tib25lLlZpZXcuZXh0ZW5kKCBfLmRlZmF1bHRzKCB7XG5cblx0XHQvKipcblx0XHQgKiBHZXQgZGVmYXVsdCBhdHRyaWJ1dGVzIGZvciB0aGUgaHRtbCB3cmFwcGVyIGVsZW1lbnRcblx0XHQgKiBAcmV0dXJuICAgb2JqXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRhdHRyaWJ1dGVzOiBmdW5jdGlvbigpIHtcblx0XHRcdHJldHVybiB7XG5cdFx0XHRcdCdkYXRhLWlkJzogdGhpcy5tb2RlbC5pZCxcblx0XHRcdFx0J2RhdGEtc2VjdGlvbi1pZCc6IHRoaXMubW9kZWwuZ2V0KCAncGFyZW50X3NlY3Rpb24nICksXG5cdFx0XHR9O1xuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBIVE1MIGNsYXNzIG5hbWVzXG5cdFx0ICogQHR5cGUgIHtTdHJpbmd9XG5cdFx0ICovXG5cdFx0Y2xhc3NOYW1lOiAnbGxtcy1idWlsZGVyLWl0ZW0gbGxtcy1sZXNzb24nLFxuXG5cdFx0LyoqXG5cdFx0ICogRXZlbnRzXG5cdFx0ICogQHR5cGUgIHtPYmplY3R9XG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjEyXG5cdFx0ICovXG5cdFx0ZXZlbnRzOiBfLmRlZmF1bHRzKCB7XG5cdFx0XHQnY2xpY2sgLmVkaXQtbGVzc29uJzogJ29wZW5fbGVzc29uX2VkaXRvcicsXG5cdFx0XHQnY2xpY2sgLmVkaXQtcXVpeic6ICdvcGVuX3F1aXpfZWRpdG9yJyxcblx0XHRcdCdjbGljayAuZWRpdC1hc3NpZ25tZW50JzogJ29wZW5fYXNzaWdubWVudF9lZGl0b3InLFxuXHRcdFx0J2NsaWNrIC5zZWN0aW9uLXByZXYnOiAnc2VjdGlvbl9wcmV2Jyxcblx0XHRcdCdjbGljayAuc2VjdGlvbi1uZXh0JzogJ3NlY3Rpb25fbmV4dCcsXG5cdFx0XHQnY2xpY2sgLnNoaWZ0LXVwLS1sZXNzb24nOiAnc2hpZnRfdXAnLFxuXHRcdFx0J2NsaWNrIC5zaGlmdC1kb3duLS1sZXNzb24nOiAnc2hpZnRfZG93bicsXG5cdFx0fSwgRGV0YWNoYWJsZS5ldmVudHMsIEVkaXRhYmxlLmV2ZW50cywgVHJhc2hhYmxlLmV2ZW50cyApLFxuXG5cdFx0LyoqXG5cdFx0ICogSFRNTCBlbGVtZW50IHdyYXBwZXIgSUQgYXR0cmlidXRlXG5cdFx0ICogQHJldHVybiAgIHN0cmluZ1xuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0aWQ6IGZ1bmN0aW9uKCkge1xuXHRcdFx0cmV0dXJuICdsbG1zLWxlc3Nvbi0nICsgdGhpcy5tb2RlbC5pZDtcblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogV3JhcHBlciBUYWcgbmFtZVxuXHRcdCAqIEB0eXBlICB7U3RyaW5nfVxuXHRcdCAqL1xuXHRcdHRhZ05hbWU6ICdsaScsXG5cblx0XHQvKipcblx0XHQgKiBHZXQgdGhlIHVuZGVyc2NvcmUgdGVtcGxhdGVcblx0XHQgKiBAdHlwZSAge1t0eXBlXX1cblx0XHQgKi9cblx0XHR0ZW1wbGF0ZTogd3AudGVtcGxhdGUoICdsbG1zLWxlc3Nvbi10ZW1wbGF0ZScgKSxcblxuXHRcdC8qKlxuXHRcdCAqIEluaXRpYWxpemF0aW9uIGNhbGxiYWNrIGZ1bmMgKHJlbmRlcnMgdGhlIGVsZW1lbnQgb24gc2NyZWVuKVxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTQuMVxuXHRcdCAqIEB2ZXJzaW9uICAzLjE0LjFcblx0XHQgKi9cblx0XHRpbml0aWFsaXplOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0dGhpcy5yZW5kZXIoKTtcblxuXHRcdFx0dGhpcy5saXN0ZW5UbyggdGhpcy5tb2RlbCwgJ2NoYW5nZScsIHRoaXMucmVuZGVyICk7XG5cblx0XHRcdEJhY2tib25lLnB1YlN1Yi5vbiggICdsZXNzb24tc2VsZWN0ZWQnLCB0aGlzLm9uX3NlbGVjdCwgdGhpcyApO1xuXHRcdFx0QmFja2JvbmUucHViU3ViLm9uKCAgJ25ldy1sZXNzb24tYWRkZWQnLCB0aGlzLm9uX3NlbGVjdCwgdGhpcyApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIENvbXBpbGVzIHRoZSB0ZW1wbGF0ZSBhbmQgcmVuZGVycyB0aGUgdmlld1xuXHRcdCAqIEByZXR1cm4gICBzZWxmIChmb3IgY2hhaW5pbmcpXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRyZW5kZXI6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHR0aGlzLiRlbC5odG1sKCB0aGlzLnRlbXBsYXRlKCB0aGlzLm1vZGVsICkgKTtcblx0XHRcdHRoaXMubWF5YmVfaGlkZV9zaGlmdGFibGVfYnV0dG9ucygpO1xuXHRcdFx0aWYgKCB0aGlzLm1vZGVsLmdldCggJ19zZWxlY3RlZCcgKSApIHtcblx0XHRcdFx0dGhpcy4kZWwuYWRkQ2xhc3MoICdzZWxlY3RlZCcgKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHRoaXMuJGVsLnJlbW92ZUNsYXNzKCAnc2VsZWN0ZWQnICk7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gdGhpcztcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBDbGljayBldmVudCBmb3IgdGhlIGFzc2lnbm1lbnQgZWRpdG9yIGFjdGlvbiBpY29uXG5cdFx0ICogT3BlbnMgc2lkZWJhciB0byB0aGUgYXNzaWdubWVudCBlZGl0b3IgdGFiXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNy4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTcuMFxuXHRcdCAqL1xuXHRcdG9wZW5fYXNzaWdubWVudF9lZGl0b3I6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHRCYWNrYm9uZS5wdWJTdWIudHJpZ2dlciggJ2xlc3Nvbi1zZWxlY3RlZCcsIHRoaXMubW9kZWwsICdhc3NpZ25tZW50JyApO1xuXHRcdFx0dGhpcy5tb2RlbC5zZXQoICdfc2VsZWN0ZWQnLCB0cnVlICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogQ2xpY2sgZXZlbnQgZm9yIGxlc3NvbiBzZXR0aW5ncyBhY3Rpb24gaWNvblxuXHRcdCAqIE9wZW5zIHNpZGViYXIgdG8gdGhlIGxlc3NvbiBlZGl0b3IgdGFiXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdG9wZW5fbGVzc29uX2VkaXRvcjogZnVuY3Rpb24oKSB7XG5cblx0XHRcdEJhY2tib25lLnB1YlN1Yi50cmlnZ2VyKCAnbGVzc29uLXNlbGVjdGVkJywgdGhpcy5tb2RlbCwgJ2xlc3NvbicgKTtcblx0XHRcdHRoaXMubW9kZWwuc2V0KCAnX3NlbGVjdGVkJywgdHJ1ZSApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIENsaWNrIGV2ZW50IGZvciB0aGUgcXVpeiBlZGl0b3IgYWN0aW9uIGljb25cblx0XHQgKiBPcGVucyBzaWRlYmFyIHRvIHRoZSBxdWl6IGVkaXRvciB0YWJcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0b3Blbl9xdWl6X2VkaXRvcjogZnVuY3Rpb24oKSB7XG5cblx0XHRcdEJhY2tib25lLnB1YlN1Yi50cmlnZ2VyKCAnbGVzc29uLXNlbGVjdGVkJywgdGhpcy5tb2RlbCwgJ3F1aXonICk7XG5cdFx0XHR0aGlzLm1vZGVsLnNldCggJ19zZWxlY3RlZCcsIHRydWUgKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBXaGVuIGEgbGVzc29uIGlzIHNlbGVjdGVkIG1hcmsgaXQgYXMgc2VsZWN0ZWQgaW4gdGhlIGhpZGRlbiBwcm9wXG5cdFx0ICogQWxsb3dzIHZpZXdzIHRvIHJlLXJlbmRlciBhbmQgcmVmbGVjdCBjdXJyZW50IHN0YXRlIHByb3Blcmx5XG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIG1vZGVsICBsZXNzb24gbW9kZWwgdGhhdCdzIGJlZW4gc2VsZWN0ZWRcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0b25fc2VsZWN0OiBmdW5jdGlvbiggbW9kZWwgKSB7XG5cblx0XHRcdGlmICggdGhpcy5tb2RlbC5pZCAhPT0gbW9kZWwuaWQgKSB7XG5cdFx0XHRcdHRoaXMubW9kZWwuc2V0KCAnX3NlbGVjdGVkJywgZmFsc2UgKTtcblx0XHRcdH1cblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBDbGljayBldmVudCBmb3IgdGhlIFwiTmV4dCBTZWN0aW9uXCIgYnV0dG9uXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIGV2ZW50ICAganMgZXZlbnQgb2JqXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4xMVxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjExXG5cdFx0ICovXG5cdFx0c2VjdGlvbl9uZXh0OiBmdW5jdGlvbiggZXZlbnQgKSB7XG5cdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0dGhpcy5fbW92ZV90b19zZWN0aW9uKCAnbmV4dCcgKTtcblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogQ2xpY2sgZXZlbnQgZm9yIHRoZSBcIlByZXZpb3VzIFNlY3Rpb25cIiBidXR0b25cblx0XHQgKiBAcGFyYW0gICAgb2JqICAgZXZlbnQgICBqcyBldmVudCBvYmpcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjExXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMTFcblx0XHQgKi9cblx0XHRzZWN0aW9uX3ByZXY6IGZ1bmN0aW9uKCBldmVudCApIHtcblx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHR0aGlzLl9tb3ZlX3RvX3NlY3Rpb24oICdwcmV2JyApO1xuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBNb3ZlIHRoZSBsZXNzb24gaW50byBhIG5ldyBzZWN0aW9uXG5cdFx0ICogQHBhcmFtICAgIHN0cmluZyAgIGRpcmVjdGlvbiAgZGlyZWN0aW9uIFtwcmV2fG5leHRdXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4xMVxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjExXG5cdFx0ICovXG5cdFx0X21vdmVfdG9fc2VjdGlvbjogZnVuY3Rpb24oIGRpcmVjdGlvbiApIHtcblxuXHRcdFx0dmFyIGZyb21fY29sbCA9IHRoaXMubW9kZWwuY29sbGVjdGlvbixcblx0XHRcdFx0dG9fc2VjdGlvbjtcblxuXHRcdFx0aWYgKCAnbmV4dCcgPT09IGRpcmVjdGlvbiApIHtcblx0XHRcdFx0dG9fc2VjdGlvbiA9IGZyb21fY29sbC5wYXJlbnQuZ2V0X25leHQoKTtcblx0XHRcdH0gZWxzZSBpZiAoICdwcmV2JyA9PT0gZGlyZWN0aW9uICkge1xuXHRcdFx0XHR0b19zZWN0aW9uID0gZnJvbV9jb2xsLnBhcmVudC5nZXRfcHJldigpO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIHRvX3NlY3Rpb24gKSB7XG5cblx0XHRcdFx0ZnJvbV9jb2xsLnJlbW92ZSggdGhpcy5tb2RlbCApO1xuXHRcdFx0XHR0b19zZWN0aW9uLmFkZF9sZXNzb24oIHRoaXMubW9kZWwgKTtcblx0XHRcdFx0dG9fc2VjdGlvbi5zZXQoICdfZXhwYW5kZWQnLCB0cnVlICk7XG5cblx0XHRcdH1cblxuXHRcdH0sXG5cblx0fSwgRGV0YWNoYWJsZSwgRWRpdGFibGUsIFNoaWZ0YWJsZSwgVHJhc2hhYmxlICkgKTtcblxufSApO1xuXG4vKipcbiAqIFNpbmdsZSBTZWN0aW9uIFZpZXdcbiAqIEBzaW5jZSAgICAzLjEzLjBcbiAqIEB2ZXJzaW9uICAzLjE2LjBcbiAqL1xuZGVmaW5lKCAnVmlld3MvTGVzc29uTGlzdCcsWyAnVmlld3MvTGVzc29uJywgJ1ZpZXdzL19SZWNlaXZhYmxlJyBdLCBmdW5jdGlvbiggTGVzc29uVmlldywgUmVjZWl2YWJsZSApIHtcblxuXHRyZXR1cm4gQmFja2JvbmUuQ29sbGVjdGlvblZpZXcuZXh0ZW5kKCBfLmRlZmF1bHRzKCB7XG5cblx0XHRjbGFzc05hbWU6ICdsbG1zLWxlc3NvbnMnLFxuXG5cdFx0LyoqXG5cdFx0ICogU2VjdGlvbiBtb2RlbFxuXHRcdCAqIEB0eXBlICB7W3R5cGVdfVxuXHRcdCAqL1xuXHRcdG1vZGVsVmlldzogTGVzc29uVmlldyxcblxuXHRcdC8qKlxuXHRcdCAqIEFyZSBzZWN0aW9ucyBzZWxlY3RhYmxlP1xuXHRcdCAqIEB0eXBlICB7Qm9vbH1cblx0XHQgKi9cblx0XHRzZWxlY3RhYmxlOiBmYWxzZSxcblxuXHRcdC8qKlxuXHRcdCAqIEFyZSBzZWN0aW9ucyBzb3J0YWJsZT9cblx0XHQgKiBAdHlwZSAge0Jvb2x9XG5cdFx0ICovXG5cdFx0c29ydGFibGU6IHRydWUsXG5cblx0XHRzb3J0YWJsZU9wdGlvbnM6IHtcblx0XHRcdGF4aXM6IGZhbHNlLFxuXHRcdFx0Y29ubmVjdFdpdGg6ICcubGxtcy1sZXNzb25zJyxcblx0XHRcdGN1cnNvcjogJ21vdmUnLFxuXHRcdFx0aGFuZGxlOiAnLmRyYWctbGVzc29uJyxcblx0XHRcdGl0ZW1zOiAnLmxsbXMtbGVzc29uJyxcblx0XHRcdHBsYWNlaG9sZGVyOiAnbGxtcy1sZXNzb24gbGxtcy1zb3J0YWJsZS1wbGFjZWhvbGRlcicsXG5cdFx0fSxcblxuXHRcdHNvcnRhYmxlX3N0YXJ0OiBmdW5jdGlvbiggY29sbGVjdGlvbiApIHtcblx0XHRcdCQoICcubGxtcy1sZXNzb25zJyApLmFkZENsYXNzKCAnZHJhZ2dpbmcnICk7XG5cdFx0fSxcblxuXHRcdHNvcnRhYmxlX3N0b3A6IGZ1bmN0aW9uKCBjb2xsZWN0aW9uICkge1xuXHRcdFx0JCggJy5sbG1zLWxlc3NvbnMnICkucmVtb3ZlQ2xhc3MoICdkcmFnZ2luZycgKTtcblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogT3ZlcmxvYWRzIHRoZSBmdW5jdGlvbiBmcm9tIEJhY2tib25lLkNvbGxlY3Rpb25WaWV3IGNvcmUgYmVjYXVzZSBpdCBkb2Vzbid0IHNlbmQgc3RvcCBldmVudHNcblx0XHQgKiBpZiBtb3ZpbmcgZnJvbSBvbmUgc29ydGFibGUgdG8gYW5vdGhlci4uLiA6LShcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgZXZlbnQgIGpzIGV2ZW50IG9iamVjdFxuXHRcdCAqIEBwYXJhbSAgICBvYmogICB1aSAgICAgalF1ZXJ5IFVJIG9iamVjdFxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRfc29ydFN0b3AgOiBmdW5jdGlvbiggZXZlbnQsIHVpICkge1xuXG5cdFx0XHR2YXIgbW9kZWxCZWluZ1NvcnRlZCA9IHRoaXMuY29sbGVjdGlvbi5nZXQoIHVpLml0ZW0uYXR0ciggJ2RhdGEtbW9kZWwtY2lkJyApICksXG5cdFx0XHRcdG1vZGVsVmlld0NvbnRhaW5lckVsID0gdGhpcy5fZ2V0Q29udGFpbmVyRWwoKSxcblx0XHRcdFx0bmV3SW5kZXggPSBtb2RlbFZpZXdDb250YWluZXJFbC5jaGlsZHJlbigpLmluZGV4KCB1aS5pdGVtICk7XG5cblx0XHRcdGlmICggbmV3SW5kZXggPT0gLTEgJiYgbW9kZWxCZWluZ1NvcnRlZCApIHtcblx0XHRcdFx0dGhpcy5jb2xsZWN0aW9uLnJlbW92ZSggbW9kZWxCZWluZ1NvcnRlZCApO1xuXHRcdFx0fVxuXG5cdFx0XHR0aGlzLl9yZW9yZGVyQ29sbGVjdGlvbkJhc2VkT25IVE1MKCk7XG5cdFx0XHR0aGlzLnVwZGF0ZURlcGVuZGVudENvbnRyb2xzKCk7XG5cblx0XHRcdGlmKCB0aGlzLl9pc0JhY2tib25lQ291cmllckF2YWlsYWJsZSgpICkge1xuXHRcdFx0XHR0aGlzLnNwYXduKCAnc29ydFN0b3AnLCB7IG1vZGVsQmVpbmdTb3J0ZWQgOiBtb2RlbEJlaW5nU29ydGVkLCBuZXdJbmRleCA6IG5ld0luZGV4IH0gKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHRoaXMudHJpZ2dlciggJ3NvcnRTdG9wJywgbW9kZWxCZWluZ1NvcnRlZCwgbmV3SW5kZXggKTtcblx0XHRcdH1cblxuXHRcdH0sXG5cblx0fSwgUmVjZWl2YWJsZSApICk7XG5cbn0gKTtcblxuLyoqXG4gKiBTaW5nbGUgU2VjdGlvbiBWaWV3XG4gKiBAc2luY2UgICAgMy4xMy4wXG4gKiBAdmVyc2lvbiAgMy4xNi4xMlxuICovXG5kZWZpbmUoICdWaWV3cy9TZWN0aW9uJyxbXG5cdFx0J1ZpZXdzL0xlc3Nvbkxpc3QnLFxuXHRcdCdWaWV3cy9fRWRpdGFibGUnLFxuXHRcdCdWaWV3cy9fU2hpZnRhYmxlJyxcblx0XHQnVmlld3MvX1RyYXNoYWJsZSdcblx0XSwgZnVuY3Rpb24oXG5cdFx0TGVzc29uTGlzdFZpZXcsXG5cdFx0RWRpdGFibGUsXG5cdFx0U2hpZnRhYmxlLFxuXHRcdFRyYXNoYWJsZVxuXHQpIHtcblxuXHRyZXR1cm4gQmFja2JvbmUuVmlldy5leHRlbmQoIF8uZGVmYXVsdHMoIHtcblxuXHRcdC8qKlxuXHRcdCAqIEdldCBkZWZhdWx0IGF0dHJpYnV0ZXMgZm9yIHRoZSBodG1sIHdyYXBwZXIgZWxlbWVudFxuXHRcdCAqIEByZXR1cm4gICBvYmpcblx0XHQgKiBAc2luY2UgICAgMy4xMy4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTMuMFxuXHRcdCAqL1xuXHRcdGF0dHJpYnV0ZXM6IGZ1bmN0aW9uKCkge1xuXHRcdFx0cmV0dXJuIHtcblx0XHRcdFx0J2RhdGEtaWQnOiB0aGlzLm1vZGVsLmlkLFxuXHRcdFx0fTtcblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogRWxlbWVudCBjbGFzc25hbWVzXG5cdFx0ICogQHR5cGUgIHtTdHJpbmd9XG5cdFx0ICovXG5cdFx0Y2xhc3NOYW1lOiAnbGxtcy1idWlsZGVyLWl0ZW0gbGxtcy1zZWN0aW9uJyxcblxuXHRcdC8qKlxuXHRcdCAqIEV2ZW50c1xuXHRcdCAqIEB0eXBlICAgICB7T2JqZWN0fVxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4xMlxuXHRcdCAqL1xuXHRcdGV2ZW50czogXy5kZWZhdWx0cygge1xuXG5cdFx0XHQnY2xpY2snOiAnc2VsZWN0Jyxcblx0XHRcdCdjbGljayAuZXhwYW5kJzogJ2V4cGFuZCcsXG5cdFx0XHQnY2xpY2sgLmNvbGxhcHNlJzogJ2NvbGxhcHNlJyxcblx0XHRcdCdjbGljayAuc2hpZnQtdXAtLXNlY3Rpb24nOiAnc2hpZnRfdXAnLFxuXHRcdFx0J2NsaWNrIC5zaGlmdC1kb3duLS1zZWN0aW9uJzogJ3NoaWZ0X2Rvd24nLFxuXG5cdFx0XHQnbW91c2VlbnRlciAubGxtcy1sZXNzb25zJzogJ29uX21vdXNlZW50ZXInLFxuXG5cdFx0fSwgRWRpdGFibGUuZXZlbnRzLCBUcmFzaGFibGUuZXZlbnRzICksXG5cblx0XHQvKipcblx0XHQgKiBIVE1MIGVsZW1lbnQgd3JhcHBlciBJRCBhdHRyaWJ1dGVcblx0XHQgKiBAcmV0dXJuICAgc3RyaW5nXG5cdFx0ICogQHNpbmNlICAgIDMuMTMuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjEzLjBcblx0XHQgKi9cblx0XHRpZDogZnVuY3Rpb24oKSB7XG5cdFx0XHRyZXR1cm4gJ2xsbXMtc2VjdGlvbi0nICsgdGhpcy5tb2RlbC5pZDtcblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogV3JhcHBlciBUYWcgbmFtZVxuXHRcdCAqIEB0eXBlICB7U3RyaW5nfVxuXHRcdCAqL1xuXHRcdHRhZ05hbWU6ICdsaScsXG5cblx0XHQvKipcblx0XHQgKiBHZXQgdGhlIHVuZGVyc2NvcmUgdGVtcGxhdGVcblx0XHQgKiBAdHlwZSAge1t0eXBlXX1cblx0XHQgKi9cblx0XHR0ZW1wbGF0ZTogd3AudGVtcGxhdGUoICdsbG1zLXNlY3Rpb24tdGVtcGxhdGUnICksXG5cblx0XHQvKipcblx0XHQgKiBJbml0aWFsaXphdGlvbiBjYWxsYmFjayBmdW5jIChyZW5kZXJzIHRoZSBlbGVtZW50IG9uIHNjcmVlbilcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjEzLjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0aW5pdGlhbGl6ZTogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHRoaXMucmVuZGVyKCk7XG5cdFx0XHR0aGlzLmxpc3RlblRvKCB0aGlzLm1vZGVsLCAnY2hhbmdlJywgdGhpcy5yZW5kZXIgKTtcblx0XHRcdHRoaXMubGlzdGVuVG8oIHRoaXMubW9kZWwsICdjaGFuZ2U6X2V4cGFuZGVkJywgdGhpcy50b2dnbGVfZXhwYW5kZWQgKTtcblx0XHRcdHRoaXMubGVzc29uTGlzdFZpZXcuY29sbGVjdGlvbi5vbiggJ2FkZCcsIHRoaXMub25fbGVzc29uX2FkZCwgdGhpcyApO1xuXG5cdFx0XHR0aGlzLmRyYWdUaW1lb3V0ID0gbnVsbDtcblxuXHRcdFx0QmFja2JvbmUucHViU3ViLm9uKCAnZXhwYW5kLWFsbCcsIHRoaXMuZXhwYW5kLCB0aGlzICk7XG5cdFx0XHRCYWNrYm9uZS5wdWJTdWIub24oICdjb2xsYXBzZS1hbGwnLCB0aGlzLmNvbGxhcHNlLCB0aGlzICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogUmVuZGVyIHRoZSBzZWN0aW9uXG5cdFx0ICogSW5pdGFsaXplcyBhIG5ldyBjb2xsZWN0aW9uIGFuZCB2aWV3cyBmb3IgYWxsIGxlc3NvbnMgaW4gdGhlIHNlY3Rpb25cblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjEzLjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0cmVuZGVyOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0dGhpcy4kZWwuaHRtbCggdGhpcy50ZW1wbGF0ZSggdGhpcy5tb2RlbC50b0pTT04oKSApICk7XG5cblx0XHRcdHRoaXMubWF5YmVfaGlkZV9zaGlmdGFibGVfYnV0dG9ucygpO1xuXG5cdFx0XHR0aGlzLmxlc3Nvbkxpc3RWaWV3ID0gbmV3IExlc3Nvbkxpc3RWaWV3KCB7XG5cdFx0XHRcdGVsOiB0aGlzLiRlbC5maW5kKCAnLmxsbXMtbGVzc29ucycgKSxcblx0XHRcdFx0Y29sbGVjdGlvbjogdGhpcy5tb2RlbC5nZXQoICdsZXNzb25zJyApLFxuXHRcdFx0fSApO1xuXHRcdFx0dGhpcy5sZXNzb25MaXN0Vmlldy5yZW5kZXIoKTtcblx0XHRcdHRoaXMubGVzc29uTGlzdFZpZXcub24oICdzb3J0U3RhcnQnLCB0aGlzLmxlc3Nvbkxpc3RWaWV3LnNvcnRhYmxlX3N0YXJ0ICk7XG5cdFx0XHR0aGlzLmxlc3Nvbkxpc3RWaWV3Lm9uKCAnc29ydFN0b3AnLCB0aGlzLmxlc3Nvbkxpc3RWaWV3LnNvcnRhYmxlX3N0b3AgKTtcblxuXHRcdFx0Ly8gc2VsZWN0aW9uIGNoYW5nZXNcblx0XHRcdHRoaXMubGVzc29uTGlzdFZpZXcub24oICdzZWxlY3Rpb25DaGFuZ2VkJywgdGhpcy5hY3RpdmVfbGVzc29uX2NoYW5nZSwgdGhpcyApO1xuXG5cdFx0XHR0aGlzLm1heWJlX2hpZGVfdHJhc2hfYnV0dG9uKCk7XG5cblx0XHRcdHJldHVybiB0aGlzO1xuXG5cdFx0fSxcblxuXHRcdGFjdGl2ZV9sZXNzb25fY2hhbmdlOiBmdW5jdGlvbiggY3VycmVudCwgcHJldmlvdXMgKSB7XG5cblx0XHRcdEJhY2tib25lLnB1YlN1Yi50cmlnZ2VyKCAnYWN0aXZlLWxlc3Nvbi1jaGFuZ2UnLCB7XG5cdFx0XHRcdGN1cnJlbnQ6IGN1cnJlbnQsXG5cdFx0XHRcdHByZXZpb3VzOiBwcmV2aW91cyxcblx0XHRcdH0gKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBDb2xsYXBzZSBsZXNzb25zIHdpdGhpbiB0aGUgc2VjdGlvblxuXHRcdCAqIEBwYXJhbSAgICBvYmogICBldmVudCAgICBqcyBldmVudCBvYmplY3Rcblx0XHQgKiBAcGFyYW0gICAgYm9vbCAgdXBkYXRlICAgaWYgdHJ1ZSwgdXBkYXRlcyB0aGUgbW9kZWwgdG8gcmVmbGVjdCB0aGUgbmV3IHN0YXRlXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGNvbGxhcHNlOiBmdW5jdGlvbiggZXZlbnQsIHVwZGF0ZSApIHtcblxuXHRcdFx0aWYgKCAndW5kZWZpbmVkJyA9PT0gdHlwZW9mIHVwZGF0ZSApIHtcblx0XHRcdFx0dXBkYXRlID0gdHJ1ZTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKCBldmVudCApIHtcblx0XHRcdFx0ZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cdFx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHR9XG5cblx0XHRcdHRoaXMuJGVsLnJlbW92ZUNsYXNzKCAnZXhwYW5kZWQnICkuZmluZCggJy5kcmFnLWV4cGFuZGVkJyApLnJlbW92ZUNsYXNzKCAnZHJhZy1leHBhbmRlZCcgKTtcblx0XHRcdGlmICggdXBkYXRlICkge1xuXHRcdFx0XHR0aGlzLm1vZGVsLnNldCggJ19leHBhbmRlZCcsIGZhbHNlICk7XG5cdFx0XHR9XG5cdFx0XHRCYWNrYm9uZS5wdWJTdWIudHJpZ2dlciggJ3NlY3Rpb24tdG9nZ2xlJywgdGhpcy5tb2RlbCApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIEV4cGFuZCBsZXNzb25zIHdpdGhpbiB0aGUgc2VjdGlvblxuXHRcdCAqIEBwYXJhbSAgICBvYmogICBldmVudCAgICBqcyBldmVudCBvYmplY3Rcblx0XHQgKiBAcGFyYW0gICAgYm9vbCAgdXBkYXRlICAgaWYgdHJ1ZSwgdXBkYXRlcyB0aGUgbW9kZWwgdG8gcmVmbGVjdCB0aGUgbmV3IHN0YXRlXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGV4cGFuZDogZnVuY3Rpb24oIGV2ZW50LCB1cGRhdGUgKSB7XG5cblx0XHRcdGlmICggJ3VuZGVmaW5lZCcgPT09IHR5cGVvZiB1cGRhdGUgKSB7XG5cdFx0XHRcdHVwZGF0ZSA9IHRydWU7XG5cdFx0XHR9XG5cblx0XHRcdGlmICggZXZlbnQgKSB7XG5cdFx0XHRcdGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuXHRcdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0fVxuXG5cdFx0XHR0aGlzLiRlbC5hZGRDbGFzcyggJ2V4cGFuZGVkJyApO1xuXHRcdFx0aWYgKCB1cGRhdGUgKSB7XG5cdFx0XHRcdHRoaXMubW9kZWwuc2V0KCAnX2V4cGFuZGVkJywgdHJ1ZSApO1xuXHRcdFx0fVxuXHRcdFx0QmFja2JvbmUucHViU3ViLnRyaWdnZXIoICdzZWN0aW9uLXRvZ2dsZScsIHRoaXMubW9kZWwgKTtcblxuXHRcdH0sXG5cblx0XHRtYXliZV9oaWRlX3RyYXNoX2J1dHRvbjogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHZhciAkYnRuID0gdGhpcy4kZWwuZmluZCggJy50cmFzaC0tc2VjdGlvbicgKTtcblxuXHRcdFx0aWYgKCB0aGlzLm1vZGVsLmdldCggJ2xlc3NvbnMnICkuaXNFbXB0eSgpICkge1xuXG5cdFx0XHRcdCRidG4uc2hvdygpO1xuXG5cdFx0XHR9IGVsc2Uge1xuXG5cdFx0XHRcdCRidG4uaGlkZSgpXG5cblx0XHRcdH1cblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBXaGVuIGEgbGVzc29uIGlzIGFkZGVkIHRvIHRoZSBzZWN0aW9uIHRyaWdnZXIgYSBjb2xsZWN0aW9uIHJlb3JkZXIgJiB1cGRhdGUgdGhlIGxlc3NvbidzIGlkXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIG1vZGVsICBMZXNzb24gbW9kZWxcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0b25fbGVzc29uX2FkZDogZnVuY3Rpb24oIG1vZGVsICkge1xuXG5cdFx0XHR0aGlzLmxlc3Nvbkxpc3RWaWV3LmNvbGxlY3Rpb24udHJpZ2dlciggJ3Jlb3JkZXInICk7XG5cdFx0XHRtb2RlbC5zZXQoICdwYXJlbnRfc2VjdGlvbicsIHRoaXMubW9kZWwuZ2V0KCAnaWQnICkgKTtcblx0XHRcdHRoaXMuZXhwYW5kKCk7XG5cblx0XHR9LFxuXG5cdFx0b25fbW91c2VlbnRlcjogZnVuY3Rpb24oIGV2ZW50ICkge1xuXG5cblx0XHRcdGlmICggJCggZXZlbnQudGFyZ2V0ICkuaGFzQ2xhc3MoICdkcmFnZ2luZycgKSApIHtcblxuXHRcdFx0XHQkKCAnLmRyYWctZXhwYW5kZWQnICkucmVtb3ZlQ2xhc3MoICdkcmFnLWV4cGFuZGVkJyApO1xuXHRcdFx0XHQkKCBldmVudC50YXJnZXQgKS5hZGRDbGFzcyggJ2RyYWctZXhwYW5kZWQnICk7XG5cblx0XHRcdH1cblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBFeHBhbmRcblx0XHQgKiBAcGFyYW0gICAge1t0eXBlXX0gICBtb2RlbCAgW2Rlc2NyaXB0aW9uXVxuXHRcdCAqIEBwYXJhbSAgICB7W3R5cGVdfSAgIHZhbHVlICBbZGVzY3JpcHRpb25dXG5cdFx0ICogQHJldHVybiAgIHtbdHlwZV19XG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHR0b2dnbGVfZXhwYW5kZWQ6IGZ1bmN0aW9uKCBtb2RlbCwgdmFsdWUgKSB7XG5cblx0XHRcdGlmICggdmFsdWUgKSB7XG5cdFx0XHRcdHRoaXMuZXhwYW5kKCBudWxsLCBmYWxzZSApO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dGhpcy5jb2xsYXBzZSggbnVsbCwgZmFsc2UgKTtcblx0XHRcdH1cblxuXHRcdH0sXG5cblx0fSwgRWRpdGFibGUsIFNoaWZ0YWJsZSwgVHJhc2hhYmxlICkgKTtcblxufSApO1xuXG4vKipcbiAqIFNpbmdsZSBTZWN0aW9uIFZpZXdcbiAqIEBzaW5jZSAgICAzLjEzLjBcbiAqIEB2ZXJzaW9uICAzLjE2LjBcbiAqL1xuZGVmaW5lKCAnVmlld3MvU2VjdGlvbkxpc3QnLFsgJ1ZpZXdzL1NlY3Rpb24nLCAnVmlld3MvX1JlY2VpdmFibGUnIF0sIGZ1bmN0aW9uKCBTZWN0aW9uVmlldywgUmVjZWl2YWJsZSApIHtcblxuXHRyZXR1cm4gQmFja2JvbmUuQ29sbGVjdGlvblZpZXcuZXh0ZW5kKCBfLmRlZmF1bHRzKCB7XG5cblx0XHQvKipcblx0XHQgKiBQYXJlbnQgZWxlbWVudFxuXHRcdCAqIEB0eXBlICB7U3RyaW5nfVxuXHRcdCAqL1xuXHRcdGVsOiAnI2xsbXMtc2VjdGlvbnMnLFxuXG5cdFx0ZXZlbnRzIDoge1xuXHRcdFx0J21vdXNlZG93biA+IGxpLmxsbXMtc2VjdGlvbiA+IC5sbG1zLWJ1aWxkZXItaGVhZGVyIC5sbG1zLWhlYWRsaW5lJyA6ICdfbGlzdEl0ZW1fb25Nb3VzZWRvd24nLFxuXHRcdFx0Ly8gJ2RibGNsaWNrID4gbGksIHRib2R5ID4gdHIgPiB0ZCcgOiAnX2xpc3RJdGVtX29uRG91YmxlQ2xpY2snLFxuXHRcdFx0J2NsaWNrJyA6ICdfbGlzdEJhY2tncm91bmRfb25DbGljaycsXG5cdFx0XHQnY2xpY2sgdWwuY29sbGVjdGlvbi12aWV3JyA6ICdfbGlzdEJhY2tncm91bmRfb25DbGljaycsXG5cdFx0XHQna2V5ZG93bicgOiAnX29uS2V5ZG93bidcblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogU2VjdGlvbiBtb2RlbFxuXHRcdCAqIEB0eXBlICB7W3R5cGVdfVxuXHRcdCAqL1xuXHRcdG1vZGVsVmlldzogU2VjdGlvblZpZXcsXG5cblx0XHQvKipcblx0XHQgKiBFbmFibGUga2V5Ym9hcmQgZXZlbnRzXG5cdFx0ICogQHR5cGUgIHtCb29sfVxuXHRcdCAqL1xuXHRcdHByb2Nlc3NLZXlFdmVudHM6IGZhbHNlLFxuXG5cdFx0LyoqXG5cdFx0ICogQXJlIHNlY3Rpb25zIHNlbGVjdGFibGU/XG5cdFx0ICogQHR5cGUgIHtCb29sfVxuXHRcdCAqL1xuXHRcdHNlbGVjdGFibGU6IHRydWUsXG5cblx0XHQvKipcblx0XHQgKiBBcmUgc2VjdGlvbnMgc29ydGFibGU/XG5cdFx0ICogQHR5cGUgIHtCb29sfVxuXHRcdCAqL1xuXHRcdHNvcnRhYmxlOiB0cnVlLFxuXG5cdFx0c29ydGFibGVPcHRpb25zOiB7XG5cdFx0XHRheGlzOiBmYWxzZSxcblx0XHRcdGN1cnNvcjogJ21vdmUnLFxuXHRcdFx0aGFuZGxlOiAnLmRyYWctc2VjdGlvbicsXG5cdFx0XHRpdGVtczogJy5sbG1zLXNlY3Rpb24nLFxuXHRcdFx0cGxhY2Vob2xkZXI6ICdsbG1zLXNlY3Rpb24gbGxtcy1zb3J0YWJsZS1wbGFjZWhvbGRlcicsXG5cdFx0fSxcblxuXHRcdHNvcnRhYmxlX3N0YXJ0OiBmdW5jdGlvbiggY29sbGVjdGlvbiApIHtcblx0XHRcdHRoaXMuJGVsLmFkZENsYXNzKCAnZHJhZ2dpbmcnICk7XG5cdFx0fSxcblxuXHRcdHNvcnRhYmxlX3N0b3A6IGZ1bmN0aW9uKCBjb2xsZWN0aW9uICkge1xuXHRcdFx0dGhpcy4kZWwucmVtb3ZlQ2xhc3MoICdkcmFnZ2luZycgKTtcblx0XHR9LFxuXG5cdH0sIFJlY2VpdmFibGUgKSApO1xuXG59ICk7XG5cbi8qKlxuICogU2luZ2xlIENvdXJzZSBWaWV3XG4gKiBAc2luY2UgICAgMy4xMy4wXG4gKiBAdmVyc2lvbiAgMy4xNi4wXG4gKi9cbmRlZmluZSggJ1ZpZXdzL0NvdXJzZScsWyAnVmlld3MvU2VjdGlvbkxpc3QnLCAnVmlld3MvX0VkaXRhYmxlJyBdLCBmdW5jdGlvbiggU2VjdGlvbkxpc3RWaWV3LCBFZGl0YWJsZSApIHtcblxuXHRyZXR1cm4gQmFja2JvbmUuVmlldy5leHRlbmQoIF8uZGVmYXVsdHMoIHtcblxuXHRcdC8qKlxuXHRcdCAqIEdldCBkZWZhdWx0IGF0dHJpYnV0ZXMgZm9yIHRoZSBodG1sIHdyYXBwZXIgZWxlbWVudFxuXHRcdCAqIEByZXR1cm4gICBvYmpcblx0XHQgKiBAc2luY2UgICAgMy4xMy4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTMuMFxuXHRcdCAqL1xuXHRcdGF0dHJpYnV0ZXM6IGZ1bmN0aW9uKCkge1xuXHRcdFx0cmV0dXJuIHtcblx0XHRcdFx0J2RhdGEtaWQnOiB0aGlzLm1vZGVsLmlkLFxuXHRcdFx0fTtcblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogSFRNTCBlbGVtZW50IHNlbGVjdG9yXG5cdFx0ICogQHR5cGUgIHtTdHJpbmd9XG5cdFx0ICovXG5cdFx0ZWw6ICcjbGxtcy1idWlsZGVyLW1haW4nLFxuXG5cdFx0LyoqXG5cdFx0ICogV3JhcHBlciBUYWcgbmFtZVxuXHRcdCAqIEB0eXBlICB7U3RyaW5nfVxuXHRcdCAqL1xuXHRcdHRhZ05hbWU6ICdkaXYnLFxuXG5cdFx0LyoqXG5cdFx0ICogR2V0IHRoZSB1bmRlcnNjb3JlIHRlbXBsYXRlXG5cdFx0ICogQHR5cGUgIHtbdHlwZV19XG5cdFx0ICovXG5cdFx0dGVtcGxhdGU6IHdwLnRlbXBsYXRlKCAnbGxtcy1jb3Vyc2UtdGVtcGxhdGUnICksXG5cblx0XHQvKipcblx0XHQgKiBJbml0aWFsaXphdGlvbiBjYWxsYmFjayBmdW5jIChyZW5kZXJzIHRoZSBlbGVtZW50IG9uIHNjcmVlbilcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjEzLjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xMy4wXG5cdFx0ICovXG5cdFx0aW5pdGlhbGl6ZTogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHZhciBzZWxmID0gdGhpcztcblxuXHRcdFx0Ly8gdGhpcy5saXN0ZW5UbyggdGhpcy5tb2RlbCwgJ3N5bmMnLCB0aGlzLnJlbmRlciApO1xuXHRcdFx0dGhpcy5yZW5kZXIoKTtcblxuXHRcdFx0dGhpcy5zZWN0aW9uTGlzdFZpZXcgPSBuZXcgU2VjdGlvbkxpc3RWaWV3KCB7XG5cdFx0XHRcdGNvbGxlY3Rpb246IHRoaXMubW9kZWwuZ2V0KCAnc2VjdGlvbnMnICksXG5cdFx0XHR9ICk7XG5cdFx0XHR0aGlzLnNlY3Rpb25MaXN0Vmlldy5yZW5kZXIoKTtcblx0XHRcdC8vIGRyYWcgYW5kIGRyb3Agc3RhcnRcblx0XHRcdHRoaXMuc2VjdGlvbkxpc3RWaWV3Lm9uKCAnc29ydFN0YXJ0JywgdGhpcy5zZWN0aW9uTGlzdFZpZXcuc29ydGFibGVfc3RhcnQgKTtcblx0XHRcdC8vIGRyYWcgYW5kIGRyb3Agc3RvcFxuXHRcdFx0dGhpcy5zZWN0aW9uTGlzdFZpZXcub24oICdzb3J0U3RvcCcsIHRoaXMuc2VjdGlvbkxpc3RWaWV3LnNvcnRhYmxlX3N0b3AgKTtcblx0XHRcdC8vIHNlbGVjdGlvbiBjaGFuZ2VzXG5cdFx0XHR0aGlzLnNlY3Rpb25MaXN0Vmlldy5vbiggJ3NlbGVjdGlvbkNoYW5nZWQnLCB0aGlzLmFjdGl2ZV9zZWN0aW9uX2NoYW5nZSApO1xuXHRcdFx0Ly8gXCJzZWxlY3RcIiBhIHNlY3Rpb24gd2hlbiBpdCdzIGFkZGVkIHRvIHRoZSBjb3Vyc2Vcblx0XHRcdHRoaXMubGlzdGVuVG8oIHRoaXMubW9kZWwuZ2V0KCAnc2VjdGlvbnMnKSwgJ2FkZCcsIHRoaXMub25fc2VjdGlvbl9hZGQgKTtcblxuXHRcdFx0QmFja2JvbmUucHViU3ViLm9uKCAnc2VjdGlvbi10b2dnbGUnLCB0aGlzLm9uX3NlY3Rpb25fdG9nZ2xlLCB0aGlzICk7XG5cblx0XHRcdEJhY2tib25lLnB1YlN1Yi5vbiggJ2V4cGFuZC1zZWN0aW9uJywgdGhpcy5leHBhbmRfc2VjdGlvbiwgdGhpcyApO1xuXG5cdFx0XHRCYWNrYm9uZS5wdWJTdWIub24oICdsZXNzb24tc2VsZWN0ZWQnLCB0aGlzLmFjdGl2ZV9sZXNzb25fY2hhbmdlLCB0aGlzICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogQ29tcGlsZXMgdGhlIHRlbXBsYXRlIGFuZCByZW5kZXJzIHRoZSB2aWV3XG5cdFx0ICogQHJldHVybiAgIHNlbGYgKGZvciBjaGFpbmluZylcblx0XHQgKiBAc2luY2UgICAgMy4xMy4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTMuMFxuXHRcdCAqL1xuXHRcdHJlbmRlcjogZnVuY3Rpb24oKSB7XG5cdFx0XHR0aGlzLiRlbC5odG1sKCB0aGlzLnRlbXBsYXRlKCB0aGlzLm1vZGVsICkgKTtcblx0XHRcdHJldHVybiB0aGlzO1xuXHRcdH0sXG5cblx0XHRhY3RpdmVfbGVzc29uX2NoYW5nZTogZnVuY3Rpb24oIG1vZGVsICkge1xuXG5cdFx0XHQvLyBzZXQgcGFyZW50IHNlY3Rpb24gdG8gYmUgYWN0aXZlXG5cdFx0XHR2YXIgc2VjdGlvbiA9IHRoaXMubW9kZWwuZ2V0KCAnc2VjdGlvbnMnICkuZ2V0KCBtb2RlbC5nZXQoICdwYXJlbnRfc2VjdGlvbicgKSApO1xuXHRcdFx0dGhpcy5zZWN0aW9uTGlzdFZpZXcuc2V0U2VsZWN0ZWRNb2RlbCggc2VjdGlvbiApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFdoZW4gYSBzZWN0aW9uIFwic2VsZWN0aW9uXCIgY2hhbmdlcyBpbiB0aGUgbGlzdFxuXHRcdCAqIFVwZGF0ZSBlYWNoIHNlY3Rpb24gbW9kZWwgc28gd2UgY2FuIGZpZ3VyZSBvdXQgd2hpY2ggb25lIGlzIHNlbGVjdGVkIGZyb20gb3RoZXIgdmlld3Ncblx0XHQgKiBAcGFyYW0gICAgYXJyYXkgICBjdXJyZW50ICAgYXJyYXkgb2Ygc2VsZWN0ZWQgbW9kZWxzXG5cdFx0ICogQHBhcmFtICAgIGFycmF5ICAgcHJldmlvdXMgIGFycmF5IG9mIHByZXZpb3VzbHkgc2VsZWN0ZWQgbW9kZWxzXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGFjdGl2ZV9zZWN0aW9uX2NoYW5nZTogZnVuY3Rpb24oIGN1cnJlbnQsIHByZXZpb3VzICkge1xuXG5cdFx0XHRfLmVhY2goIGN1cnJlbnQsIGZ1bmN0aW9uKCBtb2RlbCApIHtcblx0XHRcdFx0bW9kZWwuc2V0KCAnX3NlbGVjdGVkJywgdHJ1ZSApO1xuXHRcdFx0fSApO1xuXG5cdFx0XHRfLmVhY2goIHByZXZpb3VzLCBmdW5jdGlvbiggbW9kZWwgKSB7XG5cdFx0XHRcdG1vZGVsLnNldCggJ19zZWxlY3RlZCcsIGZhbHNlICk7XG5cdFx0XHR9ICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogXCJTZWxlY3RzXCIgdGhlIG5ldyBzZWN0aW9uIHdoZW4gaXQncyBhZGRlZCB0byB0aGUgY291cnNlXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIG1vZGVsICBTZWN0aW9uIG1vZGVsIHRoYXQncyBqdXN0IGJlZW4gYWRkZWRcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0b25fc2VjdGlvbl9hZGQ6IGZ1bmN0aW9uKCBtb2RlbCApIHtcblxuXHRcdFx0dGhpcy5zZWN0aW9uTGlzdFZpZXcuc2V0U2VsZWN0ZWRNb2RlbCggbW9kZWwgKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBXaGVuIGV4cGFuZGluZy9jb2xsYXBzaW5nIHNlY3Rpb25zXG5cdFx0ICogaWYgY29sbGFwc2luZywgdW5zZWxlY3QsIGlmIGV4cGFuZGluZywgc2VsZWN0XG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIG1vZGVsICB0b2dnbGVkIHNlY3Rpb25cblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0b25fc2VjdGlvbl90b2dnbGU6IGZ1bmN0aW9uKCBtb2RlbCApIHtcblxuXHRcdFx0dmFyIHNlbGVjdGVkID0gbW9kZWwuZ2V0KCAnX2V4cGFuZGVkJyApID8gWyBtb2RlbCBdIDogW107XG5cdFx0XHR0aGlzLnNlY3Rpb25MaXN0Vmlldy5zZXRTZWxlY3RlZE1vZGVscyggc2VsZWN0ZWQgKTtcblxuXHRcdH1cblxuXHR9LCBFZGl0YWJsZSApICk7XG5cbn0gKTtcblxuLyoqXG4gKiBNb2RlbCBzZXR0aW5ncyBmaWVsZHMgdmlld1xuICogQHNpbmNlICAgIDMuMTcuMFxuICogQHZlcnNpb24gIDMuMTcuN1xuICovXG5kZWZpbmUoICdWaWV3cy9TZXR0aW5nc0ZpZWxkcycsW10sIGZ1bmN0aW9uKCkge1xuXG5cdHJldHVybiBCYWNrYm9uZS5WaWV3LmV4dGVuZCggXy5kZWZhdWx0cygge1xuXG5cdFx0LyoqXG5cdFx0ICogRE9NIGV2ZW50c1xuXHRcdCAqIEB0eXBlICB7T2JqZWN0fVxuXHRcdCAqL1xuXHRcdGV2ZW50czoge1xuXHRcdFx0J2NsaWNrIC5sbG1zLXNldHRpbmdzLWdyb3VwLXRvZ2dsZSc6ICd0b2dnbGVfZ3JvdXAnLFxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBQcm9jZXNzZWQgZmllbGRzIGRhdGFcblx0XHQgKiBBbGxvd3MgYWNjZXNzIGJ5IElEIHdpdGhvdXQgdHJhdmVyc2luZyB0aGUgc2NoZW1hXG5cdFx0ICogQHR5cGUgIHtPYmplY3R9XG5cdFx0ICovXG5cdFx0ZmllbGRzOiB7fSxcblxuXHRcdC8qKlxuXHRcdCAqIFdyYXBwZXIgVGFnIG5hbWVcblx0XHQgKiBAdHlwZSAge1N0cmluZ31cblx0XHQgKi9cblx0XHR0YWdOYW1lOiAnZGl2JyxcblxuXHRcdC8qKlxuXHRcdCAqIEdldCB0aGUgdW5kZXJzY29yZSB0ZW1wbGF0ZVxuXHRcdCAqIEB0eXBlICB7W3R5cGVdfVxuXHRcdCAqL1xuXHRcdHRlbXBsYXRlOiB3cC50ZW1wbGF0ZSggJ2xsbXMtc2V0dGluZ3MtZmllbGRzLXRlbXBsYXRlJyApLFxuXG5cdFx0LyoqXG5cdFx0ICogSW5pdGlhbGl6YXRpb24gY2FsbGJhY2sgZnVuYyAocmVuZGVycyB0aGUgZWxlbWVudCBvbiBzY3JlZW4pXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNy4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTcuMFxuXHRcdCAqL1xuXHRcdC8vIGluaXRpYWxpemU6IGZ1bmN0aW9uKCkge30sXG5cblx0XHQvKipcblx0XHQgKiBSZXRyaWV2ZSBhbiBhcnJheSBvZiBhbGwgZWRpdG9yIGZpZWxkcyBpbiBhbGwgZ3JvdXBzXG5cdFx0ICogQHJldHVybiAgIGFycmF5XG5cdFx0ICogQHNpbmNlICAgIDMuMTcuMVxuXHRcdCAqIEB2ZXJzaW9uICAzLjE3LjFcblx0XHQgKi9cblx0XHRnZXRfZWRpdG9yX2ZpZWxkczogZnVuY3Rpb24oKSB7XG5cdFx0XHRyZXR1cm4gXy5maWx0ZXIoIHRoaXMuZmllbGRzLCBmdW5jdGlvbiggZmllbGQgKSB7XG5cdFx0XHRcdHJldHVybiB0aGlzLmlzX2VkaXRvcl9maWVsZCggZmllbGQudHlwZSApO1xuXHRcdFx0fSwgdGhpcyApO1xuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBHZXQgc2V0dGluZ3MgZ3JvdXAgZGF0YSBmcm9tIGEgbW9kZWxcblx0XHQgKiBAcmV0dXJuICAge1t0eXBlXX1cblx0XHQgKiBAc2luY2UgICAgMy4xNy4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTcuMFxuXHRcdCAqL1xuXHRcdGdldF9ncm91cHM6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHRyZXR1cm4gdGhpcy5tb2RlbC5nZXRfc2V0dGluZ3NfZmllbGRzKCk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogRGV0ZXJtaW5lIGlmIGEgc2V0dGluZ3MgZ3JvdXAgaXMgaGlkZGVuIGluIGxvY2FsU3RvcmFnZVxuXHRcdCAqIEBwYXJhbSAgICBzdHJpbmcgICBncm91cF9pZCAgaWQgb2YgdGhlIGdyb3VwXG5cdFx0ICogQHJldHVybiAgIHtCb29sZWFufVxuXHRcdCAqIEBzaW5jZSAgICAzLjE3LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNy4wXG5cdFx0ICovXG5cdFx0aXNfZ3JvdXBfaGlkZGVuOiBmdW5jdGlvbiggZ3JvdXBfaWQgKSB7XG5cblx0XHRcdHZhciBpZCA9ICdsbG1zLScgKyB0aGlzLm1vZGVsLmdldCggJ3R5cGUnICkgKyAnLXNldHRpbmdzLWdyb3VwLS0nICsgZ3JvdXBfaWQ7XG5cblx0XHRcdGlmICggJ3VuZGVmaW5lZCcgIT09IHdpbmRvdy5sb2NhbFN0b3JhZ2UgKSB7XG5cdFx0XHRcdHJldHVybiAoICdoaWRkZW4nID09PSB3aW5kb3cubG9jYWxTdG9yYWdlLmdldEl0ZW0oIGlkICkgKTtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIEdldCB0aGUgc3dpdGNoIGF0dHJpYnV0ZSBmb3IgYSBmaWVsZCB3aXRoIHN3aXRjaGVzXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIGZpZWxkICBmaWVsZCBkYXRhIG9ialxuXHRcdCAqIEByZXR1cm4gICBzdHJpbmdcblx0XHQgKiBAc2luY2UgICAgMy4xNy4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTcuMFxuXHRcdCAqL1xuXHRcdGdldF9zd2l0Y2hfYXR0cmlidXRlOiBmdW5jdGlvbiggZmllbGQgKSB7XG5cblx0XHRcdHJldHVybiBmaWVsZC5zd2l0Y2hfYXR0cmlidXRlID8gZmllbGQuc3dpdGNoX2F0dHJpYnV0ZSA6IGZpZWxkLmF0dHJpYnV0ZTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBEZXRlcm1pbmUgaWYgYSBmaWVsZCBoYXMgYSBzd2l0Y2hcblx0XHQgKiBAcGFyYW0gICAgc3RyaW5nICAgdHlwZSAgZmllbGQgdHlwZSBzdHJpbmdcblx0XHQgKiBAcmV0dXJuICAge0Jvb2xlYW59XG5cdFx0ICogQHNpbmNlICAgIDMuMTcuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE3LjBcblx0XHQgKi9cblx0XHRoYXNfc3dpdGNoOiBmdW5jdGlvbiggdHlwZSApIHtcblx0XHRcdHJldHVybiAoIC0xICE9PSB0eXBlLmluZGV4T2YoICdzd2l0Y2gnICkgKTtcblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogRGV0ZXJtaW5lIGlmIGEgZmllbGQgaXMgYSBkZWZhdWx0ICh0ZXh0KSBmaWVsZFxuXHRcdCAqIEBwYXJhbSAgICBzdHJpbmcgICB0eXBlICBmaWVsZCB0eXBlIHN0cmluZ1xuXHRcdCAqIEByZXR1cm4gICB7Qm9vbGVhbn1cblx0XHQgKiBAc2luY2UgICAgMy4xNy4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTcuMFxuXHRcdCAqL1xuXHRcdGlzX2RlZmF1bHRfZmllbGQ6IGZ1bmN0aW9uKCB0eXBlICkge1xuXG5cdFx0XHR2YXIgdHlwZXMgPSBbICdhdWRpb19lbWJlZCcsICdkYXRlcGlja2VyJywgJ251bWJlcicsICd0ZXh0JywgJ3ZpZGVvX2VtYmVkJyBdO1xuXHRcdFx0cmV0dXJuICggLTEgIT09IHR5cGVzLmluZGV4T2YoIHR5cGUucmVwbGFjZSggJ3N3aXRjaC0nLCAnJyApICkgKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBEZXRlcm1pbmUgaWYgYSBmaWVsZCBpcyBhIFdZU0lXWUcgZWRpdG9yIGZpZWxkXG5cdFx0ICogQHBhcmFtICAgIHN0cmluZyAgIHR5cGUgIGZpZWxkIHR5cGUgc3RyaW5nXG5cdFx0ICogQHJldHVybiAgIHtCb29sZWFufVxuXHRcdCAqIEBzaW5jZSAgICAzLjE3LjFcblx0XHQgKiBAdmVyc2lvbiAgMy4xNy4xXG5cdFx0ICovXG5cdFx0aXNfZWRpdG9yX2ZpZWxkOiBmdW5jdGlvbiggdHlwZSApIHtcblxuXHRcdFx0dmFyIHR5cGVzID0gWyAnZWRpdG9yJywgJ3N3aXRjaC1lZGl0b3InIF07XG5cdFx0XHRyZXR1cm4gKCAtMSAhPT0gdHlwZXMuaW5kZXhPZiggdHlwZS5yZXBsYWNlKCAnc3dpdGNoLScsICcnICkgKSApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIERldGVybWluZSBpZiBhIHN3aXRjaCBpcyBlbmFibGVkIGZvciBhIGZpZWxkXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIGZpZWxkICBmaWVsZCBkYXRhIG9iamVjdFxuXHRcdCAqIEByZXR1cm4gICB7Qm9vbGVhbn1cblx0XHQgKiBAc2luY2UgICAgMy4xNy4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTcuNlxuXHRcdCAqL1xuXHRcdGlzX3N3aXRjaF9jb25kaXRpb25fbWV0OiBmdW5jdGlvbiggZmllbGQgKSB7XG5cblx0XHRcdHJldHVybiAoIGZpZWxkLnN3aXRjaF9vbiA9PT0gdGhpcy5tb2RlbC5nZXQoIGZpZWxkLnN3aXRjaF9hdHRyaWJ1dGUgKSApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIENvbXBpbGVzIHRoZSB0ZW1wbGF0ZSBhbmQgcmVuZGVycyB0aGUgdmlld1xuXHRcdCAqIEByZXR1cm4gICBzZWxmIChmb3IgY2hhaW5pbmcpXG5cdFx0ICogQHNpbmNlICAgIDMuMTcuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE3LjFcblx0XHQgKi9cblx0XHRyZW5kZXI6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHR0aGlzLiRlbC5odG1sKCB0aGlzLnRlbXBsYXRlKCB0aGlzICkgKTtcblxuXHRcdFx0Ly8gaWYgZWRpdG9ycyBleGlzdCwgcmVuZGVyIHRoZW1cblx0XHRcdF8uZWFjaCggdGhpcy5nZXRfZWRpdG9yX2ZpZWxkcygpLCBmdW5jdGlvbiggZmllbGQgKSB7XG5cdFx0XHRcdHRoaXMucmVuZGVyX2VkaXRvciggZmllbGQgKTtcblx0XHRcdH0sIHRoaXMgKTtcblxuXHRcdFx0cmV0dXJuIHRoaXM7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogUmVuZGVycyBhbiBlZGl0b3IgZmllbGRcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgZmllbGQgIGZpZWxkIGRhdGEgb2JqZWN0XG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNy4xXG5cdFx0ICogQHZlcnNpb24gIDMuMTcuMVxuXHRcdCAqL1xuXHRcdHJlbmRlcl9lZGl0b3I6IGZ1bmN0aW9uKCBmaWVsZCApIHtcblxuXHRcdFx0dmFyIHNlbGYgPSB0aGlzO1xuXG5cdFx0XHR3cC5lZGl0b3IucmVtb3ZlKCBmaWVsZC5pZCApO1xuXHRcdFx0ZmllbGQuc2V0dGluZ3MudGlueW1jZS5zZXR1cCA9IGZ1bmN0aW9uKCBlZGl0b3IgKSB7XG5cblx0XHRcdFx0dmFyICRlZCA9ICQoICcjJyArIGVkaXRvci5pZCApLFxuXHRcdFx0XHRcdCRwYXJlbnQgPSAkZWQuY2xvc2VzdCggJy5sbG1zLWVkaXRhYmxlLWVkaXRvcicgKSxcblx0XHRcdFx0XHQkbGFiZWwgPSAkcGFyZW50LmZpbmQoICcubGxtcy1sYWJlbCcgKSxcblx0XHRcdFx0XHRwcm9wID0gJGVkLmF0dHIoICdkYXRhLWF0dHJpYnV0ZScgKVxuXG5cdFx0XHRcdGlmICggJGxhYmVsLmxlbmd0aCApIHtcblx0XHRcdFx0XHQkbGFiZWwucHJlcGVuZFRvKCAkcGFyZW50LmZpbmQoICcud3AtZWRpdG9yLXRvb2xzJyApICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBzYXZlIGNoYW5nZXMgdG8gdGhlIG1vZGVsIHZpYSBWaXN1YWwgZWRcblx0XHRcdFx0ZWRpdG9yLm9uKCAnY2hhbmdlJywgZnVuY3Rpb24oIGV2ZW50ICkge1xuXHRcdFx0XHRcdHNlbGYubW9kZWwuc2V0KCBwcm9wLCB3cC5lZGl0b3IuZ2V0Q29udGVudCggZWRpdG9yLmlkICkgKTtcblx0XHRcdFx0fSApO1xuXG5cdFx0XHRcdC8vIHNhdmUgY2hhbmdlcyB2aWEgVGV4dCBlZFxuXHRcdFx0XHQkZWQub24oICdpbnB1dCcsIGZ1bmN0aW9uKCBldmVudCApIHtcblx0XHRcdFx0XHRzZWxmLm1vZGVsLnNldCggcHJvcCwgJGVkLnZhbCgpICk7XG5cdFx0XHRcdH0gKTtcblxuXHRcdFx0XHQvLyB0cmlnZ2VyIGFuIGlucHV0IG9uIHRoZSBUZXh0IGVkIHdoZW4gcXVpY2t0YWdzIGJ1dHRvbnMgYXJlIGNsaWNrZWRcblx0XHRcdFx0JHBhcmVudC5vbiggJ2NsaWNrJywgJy5xdWlja3RhZ3MtdG9vbGJhciAuZWRfYnV0dG9uJywgZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0c2V0VGltZW91dCggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHQkZWQudHJpZ2dlciggJ2lucHV0JyApO1xuXHRcdFx0XHRcdH0sIDEwICk7XG5cdFx0XHRcdH0gKTtcblx0XHRcdH07XG5cblx0XHRcdHdwLmVkaXRvci5pbml0aWFsaXplKCBmaWVsZC5pZCwgZmllbGQuc2V0dGluZ3MgKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBHZXQgdGhlIEhUTUwgZm9yIGEgc2VsZWN0IGZpZWxkXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgICAgIG9wdGlvbnMgICAgZmxhdCBvciBtdWx0aS1kaW1lbnNpb25hbCBvcHRpb25zIG9iamVjdFxuXHRcdCAqIEBwYXJhbSAgICBzdHJpbmcgICBhdHRyaWJ1dGUgIG5hbWUgb2YgdGhlIHNlbGVjdCBmaWVsZCdzIGF0dHJpYnV0ZVxuXHRcdCAqIEByZXR1cm4gICBzdHJpbmdcblx0XHQgKiBAc2luY2UgICAgMy4xNy4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTcuMlxuXHRcdCAqL1xuXHRcdHJlbmRlcl9zZWxlY3Rfb3B0aW9uczogZnVuY3Rpb24oIG9wdGlvbnMsIGF0dHJpYnV0ZSApIHtcblxuXHRcdFx0dmFyIGh0bWwgPSAnJyxcblx0XHRcdFx0c2VsZWN0ZWQgPSB0aGlzLm1vZGVsLmdldCggYXR0cmlidXRlICk7XG5cblx0XHRcdGZ1bmN0aW9uIG9wdGlvbl9odG1sKCBsYWJlbCwgdmFsICkge1xuXG5cdFx0XHRcdHJldHVybiAnPG9wdGlvbiB2YWx1ZT1cIicgKyB2YWwgKyAnXCInICsgXy5zZWxlY3RlZCggdmFsLCBzZWxlY3RlZCApICsgJz4nICsgbGFiZWwgKyAnPC9vcHRpb24+JztcblxuXHRcdFx0fVxuXG5cdFx0XHRfLmVhY2goIG9wdGlvbnMsIGZ1bmN0aW9uKCBvcHRpb24sIGluZGV4ICkge1xuXG5cdFx0XHRcdC8vIHRoaXMgd2lsbCBiZSBhbiBrZXk6dmFsIG9iamVjdFxuXHRcdFx0XHRpZiAoICdzdHJpbmcnID09PSB0eXBlb2Ygb3B0aW9uICkge1xuXHRcdFx0XHRcdGh0bWwgKz0gb3B0aW9uX2h0bWwoIG9wdGlvbiwgaW5kZXggKTtcblx0XHRcdFx0Ly8gZWl0aGVyIG9wdGlvbiBncm91cCBvciBhcnJheSBvZiBrZXksdmFsIG9iamVjdHNcblx0XHRcdFx0fSBlbHNlIGlmICggJ29iamVjdCcgPT09IHR5cGVvZiBvcHRpb24gKSB7XG5cdFx0XHRcdFx0Ly8gb3B0aW9uIGdyb3VwXG5cdFx0XHRcdFx0aWYgKCBvcHRpb24ubGFiZWwgJiYgb3B0aW9uLm9wdGlvbnMgKSB7XG5cdFx0XHRcdFx0XHRodG1sICs9ICc8b3B0Z3JvdXAgbGFiZWw9XCInICsgb3B0aW9uLmxhYmVsICsgJ1wiPic7XG5cdFx0XHRcdFx0XHRodG1sICs9IHRoaXMucmVuZGVyX3NlbGVjdF9vcHRpb25zKCBvcHRpb24ub3B0aW9ucywgYXR0cmlidXRlICk7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdGh0bWwgKz0gb3B0aW9uX2h0bWwoIG9wdGlvbi52YWwsIG9wdGlvbi5rZXkgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblxuXHRcdFx0fSwgdGhpcyApO1xuXG5cdFx0XHRyZXR1cm4gaHRtbDtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBTZXR1cCBhbmQgZmlsbCBmaWVsZHMgd2l0aCBkZWZhdWx0IGRhdGEgYmFzZWQgb24gZmllbGQgdHlwZVxuXHRcdCAqIEBwYXJhbSAgICBvYmogICBvcmlnX2ZpZWxkICAgb3JpZ2luYWwgZmllbGQgYXMgZGVmaW5lZCBpbiB0aGUgc2V0dGluZ3Ncblx0XHQgKiBAcGFyYW0gICAgaW50ICAgZmllbGRfaW5kZXggIGluZGV4IG9mIHRoZSBmaWVsZCBpbiB0aGUgY3VycmVudCByb3dcblx0XHQgKiBAcmV0dXJuICAgb2JqXG5cdFx0ICogQHNpbmNlICAgIDMuMTcuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE3Ljdcblx0XHQgKi9cblx0XHRzZXR1cF9maWVsZDogZnVuY3Rpb24oIG9yaWdfZmllbGQsIGZpZWxkX2luZGV4ICkge1xuXG5cdFx0XHR2YXIgZGVmYXVsdHMgPSB7XG5cdFx0XHRcdGNsYXNzZXM6IFtdLFxuXHRcdFx0XHRpZDogXy51bmlxdWVJZCggb3JpZ19maWVsZC5hdHRyaWJ1dGUgKyAnXycgKSxcblx0XHRcdFx0aW5wdXRfdHlwZTogJ3RleHQnLFxuXHRcdFx0XHRsYWJlbDogJycsXG5cdFx0XHRcdG9wdGlvbnM6IHt9LFxuXHRcdFx0XHRwbGFjZWhvbGRlcjogJycsXG5cdFx0XHRcdHRpcDogJycsXG5cdFx0XHRcdHRpcF9wb3NpdGlvbjogJ3RvcC1yaWdodCcsXG5cdFx0XHRcdHNldHRpbmdzOiB7fSxcblx0XHRcdH07XG5cblx0XHRcdC8vIGNoZWNrIHRoZSBmaWVsZCBjb25kaXRpb24gaWYgc2V0XG5cdFx0XHRpZiAoIG9yaWdfZmllbGQuY29uZGl0aW9uICYmIGZhbHNlID09PSBfLmJpbmQoIG9yaWdfZmllbGQuY29uZGl0aW9uLCB0aGlzLm1vZGVsICkoKSApIHtcblx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0fVxuXG5cdFx0XHRzd2l0Y2ggKCBvcmlnX2ZpZWxkLnR5cGUgKSB7XG5cblx0XHRcdFx0Y2FzZSAnYXVkaW9fZW1iZWQnOlxuXHRcdFx0XHRcdGRlZmF1bHRzLmNsYXNzZXMucHVzaCggJ2xsbXMtZWRpdGFibGUtYXVkaW8nICk7XG5cdFx0XHRcdFx0ZGVmYXVsdHMucGxhY2Vob2xkZXIgPSAnaHR0cHM6Ly8nO1xuXHRcdFx0XHRcdGRlZmF1bHRzLnRpcCA9IExMTVMubDEwbi50cmFuc2xhdGUoICdVc2UgU291bmRDbG91ZCBvciBTcG90aWZ5IGF1ZGlvIFVSTFMuJyApO1xuXHRcdFx0XHRcdGRlZmF1bHRzLmlucHV0X3R5cGUgPSAndXJsJztcblx0XHRcdFx0YnJlYWs7XG5cblx0XHRcdFx0Y2FzZSAnZGF0ZXBpY2tlcic6XG5cdFx0XHRcdFx0ZGVmYXVsdHMuY2xhc3Nlcy5wdXNoKCAnbGxtcy1lZGl0YWJsZS1kYXRlJyApO1xuXHRcdFx0XHRicmVhaztcblxuXHRcdFx0XHRjYXNlICdlZGl0b3InOlxuXHRcdFx0XHRjYXNlICdzd2l0Y2gtZWRpdG9yJzpcblx0XHRcdFx0XHR2YXIgb3JpZ19zZXR0aW5ncyA9IG9yaWdfZmllbGQuc2V0dGluZ3MgfHwge307XG5cdFx0XHRcdFx0ZGVmYXVsdHMuc2V0dGluZ3MgPSAkLmV4dGVuZCggdHJ1ZSwgd3AuZWRpdG9yLmdldERlZmF1bHRTZXR0aW5ncygpLCB7XG5cdFx0XHRcdFx0XHRtZWRpYUJ1dHRvbnM6IHRydWUsXG5cdFx0XHRcdFx0XHR0aW55bWNlOiB7XG5cdFx0XHRcdFx0XHRcdHRvb2xiYXIxOiAnYm9sZCxpdGFsaWMsc3RyaWtldGhyb3VnaCxidWxsaXN0LG51bWxpc3QsYmxvY2txdW90ZSxocixhbGlnbmxlZnQsYWxpZ25jZW50ZXIsYWxpZ25yaWdodCxsaW5rLHVubGluayx3cF9hZHYnLFxuXHRcdFx0XHRcdFx0XHR0b29sYmFyMjogJ2Zvcm1hdHNlbGVjdCx1bmRlcmxpbmUsYWxpZ25qdXN0aWZ5LGZvcmVjb2xvcixwYXN0ZXRleHQscmVtb3ZlZm9ybWF0LGNoYXJtYXAsb3V0ZGVudCxpbmRlbnQsdW5kbyxyZWRvLHdwX2hlbHAnLFxuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH0sIG9yaWdfc2V0dGluZ3MgKTtcblx0XHRcdFx0YnJlYWs7XG5cblx0XHRcdFx0Y2FzZSAnbnVtYmVyJzpcblx0XHRcdFx0XHRkZWZhdWx0cy5pbnB1dF90eXBlID0gJ251bWJlcic7XG5cdFx0XHRcdGJyZWFrO1xuXG5cdFx0XHRcdGNhc2UgJ3Blcm1hbGluayc6XG5cdFx0XHRcdFx0ZGVmYXVsdHMubGFiZWwgPSBMTE1TLmwxMG4udHJhbnNsYXRlKCAnUGVybWFsaW5rJyApO1xuXHRcdFx0XHRicmVhaztcblxuXHRcdFx0XHRjYXNlICd2aWRlb19lbWJlZCc6XG5cdFx0XHRcdFx0ZGVmYXVsdHMuY2xhc3Nlcy5wdXNoKCAnbGxtcy1lZGl0YWJsZS12aWRlbycgKTtcblx0XHRcdFx0XHRkZWZhdWx0cy5wbGFjZWhvbGRlciA9ICdodHRwczovLyc7XG5cdFx0XHRcdFx0ZGVmYXVsdHMudGlwID0gTExNUy5sMTBuLnRyYW5zbGF0ZSggJ1VzZSBZb3VUdWJlLCBWaW1lbywgb3IgV2lzdGlhIHZpZGVvIFVSTFMuJyApO1xuXHRcdFx0XHRcdGRlZmF1bHRzLmlucHV0X3R5cGUgPSAndXJsJztcblx0XHRcdFx0YnJlYWs7XG5cblx0XHRcdH1cblxuXHRcdFx0aWYgKCB0aGlzLmhhc19zd2l0Y2goIG9yaWdfZmllbGQudHlwZSApICkge1xuXHRcdFx0XHRkZWZhdWx0cy5zd2l0Y2hfb24gPSAneWVzJztcblx0XHRcdFx0ZGVmYXVsdHMuc3dpdGNoX29mZiA9ICdubyc7XG5cdFx0XHR9XG5cblx0XHRcdHZhciBmaWVsZCA9IF8uZGVmYXVsdHMoIF8uZGVlcENsb25lKCBvcmlnX2ZpZWxkICksIGRlZmF1bHRzICk7XG5cblx0XHRcdC8vIGlmIG9wdGlvbnMgaXMgYSBmdW5jdGlvbiBydW4gaXRcblx0XHRcdGlmICggXy5pc0Z1bmN0aW9uKCBmaWVsZC5vcHRpb25zICkgKSB7XG5cdFx0XHRcdGZpZWxkLm9wdGlvbnMgPSBfLmJpbmQoIGZpZWxkLm9wdGlvbnMsIHRoaXMubW9kZWwgKSgpO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBpZiBpdCdzIGEgcmFkaW8gZmllbGQgb3B0aW9ucyB2YWx1ZXMgY2FuIGJlIHN1Ym1pdHRlZCBhcyBpbWFnZXNcblx0XHRcdC8vIHRoaXMgd2lsbCB0cmFuc2Zvcm0gdGhvc2UgaW1hZ2VzIGludG8gPGltZz4gaHRtbFxuXHRcdFx0aWYgKCAtMSAhPT0gWyAncmFkaW8nLCAnc3dpdGNoLXJhZGlvJyBdLmluZGV4T2YoIG9yaWdfZmllbGQudHlwZSApICkge1xuXG5cdFx0XHRcdHZhciBoYXNfaW1hZ2VzID0gZmFsc2U7XG5cdFx0XHRcdF8uZWFjaCggb3JpZ19maWVsZC5vcHRpb25zLCBmdW5jdGlvbiggdmFsLCBrZXkgKSB7XG5cdFx0XHRcdFx0aWYgKCAtMSAhPT0gdmFsLmluZGV4T2YoICcucG5nJyApIHx8IC0xICE9PSB2YWwuaW5kZXhPZiggJy5qcGcnICkgKSB7XG5cdFx0XHRcdFx0XHRmaWVsZC5vcHRpb25zW2tleV0gPSAnPHNwYW4+PGltZyBzcmM9XCInICsgdmFsICsgJ1wiPjwvc3Bhbj4nO1xuXHRcdFx0XHRcdFx0aGFzX2ltYWdlcyA9IHRydWU7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9ICk7XG5cdFx0XHRcdGlmICggaGFzX2ltYWdlcyApIHtcblx0XHRcdFx0XHRmaWVsZC5jbGFzc2VzLnB1c2goICdoYXMtaW1hZ2VzJyApO1xuXHRcdFx0XHR9XG5cblx0XHRcdH1cblxuXHRcdFx0Ly8gYWRkIHRvb2x0aXAgcG9zaXRpb24gY2xhc3Nlc1xuXHRcdFx0aWYgKCBmaWVsZC50aXAgKSB7XG5cdFx0XHRcdGZpZWxkLmNsYXNzZXMucHVzaCggJ3RpcC0tJyArIGZpZWxkLnRpcF9wb3NpdGlvbiApO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyB0cmFuc2Zvcm0gY2xhc3NlcyBhcnJheSB0byBhIGNzcyBjbGFzcyBzdHJpbmdcblx0XHRcdGlmICggZmllbGQuY2xhc3Nlcy5sZW5ndGggKSB7XG5cdFx0XHRcdGZpZWxkLmNsYXNzZXMgPSAnICcgKyBmaWVsZC5jbGFzc2VzLmpvaW4oICcgJyApO1xuXHRcdFx0fVxuXG5cdFx0XHR0aGlzLmZpZWxkc1sgZmllbGQuaWQgXSA9IGZpZWxkO1xuXG5cdFx0XHRyZXR1cm4gZmllbGQ7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogRGV0ZXJtaW5lIGlmIHRvZ2dsaW5nIGEgc3dpdGNoIHNlbGVjdCBzaG91bGQgcmVyZW5kZXIgdGhlIHZpZXdcblx0XHQgKiBAcGFyYW0gICAgc3RyaW5nICAgZmllbGRfdHlwZSAgZmllbGQgdHlwZSBzdHJpbmdcblx0XHQgKiBAcmV0dXJuICAgYm9vbGVhblxuXHRcdCAqIEBzaW5jZSAgICAzLjE3LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNy4wXG5cdFx0ICovXG5cdFx0c2hvdWxkX3JlcmVuZGVyX29uX3RvZ2dsZTogZnVuY3Rpb24oIGZpZWxkX3R5cGUgKSB7XG5cblx0XHRcdHJldHVybiAoIC0xICE9PSBmaWVsZF90eXBlLmluZGV4T2YoICdzd2l0Y2gtJyApICkgPyAneWVzJyA6ICdubyc7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogQ2xpY2sgZXZlbnQgZm9yIHRvZ2dsaW5nIHZpc2liaWxpdHkgb2Ygc2V0dGluZ3MgZ3JvdXBzXG5cdFx0ICogSWYgbG9jYWxTdG9yYWdlIGlzIGF2YWlsYWJsZSwgcGVyc2lzdCBzdGF0ZVxuXHRcdCAqIEBwYXJhbSAgICBvYmogICBldmVudCAganMgZXZlbnQgb2JqZWN0XG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNy4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTcuMFxuXHRcdCAqL1xuXHRcdHRvZ2dsZV9ncm91cDogZnVuY3Rpb24oIGV2ZW50ICkge1xuXG5cdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG5cdFx0XHR2YXIgJGVsID0gJCggZXZlbnQuY3VycmVudFRhcmdldCApLFxuXHRcdFx0XHQkZ3JvdXAgPSAkZWwuY2xvc2VzdCggJy5sbG1zLW1vZGVsLXNldHRpbmdzJyApO1xuXG5cdFx0XHQkZ3JvdXAudG9nZ2xlQ2xhc3MoICdoaWRkZW4nICk7XG5cblx0XHRcdGlmICggJ3VuZGVmaW5lZCcgIT09IHdpbmRvdy5sb2NhbFN0b3JhZ2UgKSB7XG5cblx0XHRcdFx0dmFyIGlkID0gJGdyb3VwLmF0dHIoICdpZCcgKTtcblx0XHRcdFx0aWYgKCAkZ3JvdXAuaGFzQ2xhc3MoICdoaWRkZW4nICkgKSB7XG5cdFx0XHRcdFx0d2luZG93LmxvY2FsU3RvcmFnZS5zZXRJdGVtKCBpZCwgJ2hpZGRlbicgKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHR3aW5kb3cubG9jYWxTdG9yYWdlLnJlbW92ZUl0ZW0oIGlkICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0fVxuXG5cdFx0fSxcblxuXHR9ICkgKTtcblxufSApO1xuXG4vKipcbiAqIExlc3NvbiBFZGl0b3IgKFNpZGViYXIpIFZpZXdcbiAqIEBzaW5jZSAgICAzLjE3LjBcbiAqIEB2ZXJzaW9uICAzLjE3LjBcbiAqL1xuZGVmaW5lKCAnVmlld3MvTGVzc29uRWRpdG9yJyxbXG5cdFx0J1ZpZXdzL19EZXRhY2hhYmxlJyxcblx0XHQnVmlld3MvX0VkaXRhYmxlJyxcblx0XHQnVmlld3MvX1RyYXNoYWJsZScsXG5cdFx0J1ZpZXdzL19TdWJ2aWV3Jyxcblx0XHQnVmlld3MvU2V0dGluZ3NGaWVsZHMnXG5cdF0sIGZ1bmN0aW9uKFxuXHRcdERldGFjaGFibGUsXG5cdFx0RWRpdGFibGUsXG5cdFx0VHJhc2hhYmxlLFxuXHRcdFN1YnZpZXcsXG5cdFx0U2V0dGluZ3NGaWVsZHNcblx0KSB7XG5cblx0cmV0dXJuIEJhY2tib25lLlZpZXcuZXh0ZW5kKCBfLmRlZmF1bHRzKCB7XG5cblx0XHQvKipcblx0XHQgKiBDdXJyZW50IHZpZXcgc3RhdGVcblx0XHQgKiBAdHlwZSAge1N0cmluZ31cblx0XHQgKi9cblx0XHRzdGF0ZTogJ2RlZmF1bHQnLFxuXG5cdFx0LyoqXG5cdFx0ICogQ3VycmVudCBTdWJ2aWV3c1xuXHRcdCAqIEB0eXBlICB7T2JqZWN0fVxuXHRcdCAqL1xuXHRcdHZpZXdzOiB7XG5cdFx0XHRzZXR0aW5nczoge1xuXHRcdFx0XHRjbGFzczogU2V0dGluZ3NGaWVsZHMsXG5cdFx0XHRcdGluc3RhbmNlOiBudWxsLFxuXHRcdFx0XHRzdGF0ZTogJ2RlZmF1bHQnLFxuXHRcdFx0fSxcblx0XHR9LFxuXG5cdFx0ZWw6ICcjbGxtcy1lZGl0b3ItbGVzc29uJyxcblxuXHRcdC8qKlxuXHRcdCAqIEV2ZW50c1xuXHRcdCAqIEB0eXBlICB7T2JqZWN0fVxuXHRcdCAqL1xuXHRcdGV2ZW50czogXy5kZWZhdWx0cygge30sIERldGFjaGFibGUuZXZlbnRzLCBFZGl0YWJsZS5ldmVudHMsIFRyYXNoYWJsZS5ldmVudHMgKSxcblxuXHRcdC8qKlxuXHRcdCAqIFRlbXBsYXRlIGZ1bmN0aW9uXG5cdFx0ICogQHR5cGUgIHtbdHlwZV19XG5cdFx0ICovXG5cdFx0dGVtcGxhdGU6IHdwLnRlbXBsYXRlKCAnbGxtcy1sZXNzb24tc2V0dGluZ3MtdGVtcGxhdGUnICksXG5cblx0XHQvKipcblx0XHQgKiBJbml0XG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIGRhdGEgIHBhcmVudCB0ZW1wbGF0ZSBkYXRhXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNy4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTcuMFxuXHRcdCAqL1xuXHRcdGluaXRpYWxpemU6IGZ1bmN0aW9uKCBkYXRhICkge1xuXG5cdFx0XHR0aGlzLm1vZGVsID0gZGF0YS5sZXNzb247XG5cblx0XHRcdHZhciBjaGFuZ2VfZXZlbnRzID0gW1xuXHRcdFx0XHQnY2hhbmdlOmRhdGVfYXZhaWxhYmxlJyxcblx0XHRcdFx0J2NoYW5nZTpkcmlwX21ldGhvZCcsXG5cdFx0XHRcdCdjaGFuZ2U6dGltZV9hdmFpbGFibGUnLFxuXHRcdFx0XTtcblx0XHRcdF8uZWFjaCggY2hhbmdlX2V2ZW50cywgZnVuY3Rpb24oIGV2ZW50ICkge1xuXHRcdFx0XHR0aGlzLmxpc3RlblRvKCB0aGlzLm1vZGVsLCBldmVudCwgdGhpcy5yZW5kZXIgKTtcblx0XHRcdH0sIHRoaXMgKTtcblxuXHRcdFx0Ly8gd2hlbiB0aGUgXCJoYXNfcHJlcmVxdWlzaXRlXCIgYXR0ciBpcyB0b2dnbGVkIE9OXG5cdFx0XHQvLyB0cmlnZ2VyIHRoZSBwcmVyZXEgc2VsZWN0IG9iamVjdCB0byBzZXQgdGhlIGRlZmF1bHQgKGZpcnN0IGF2YWlsYWJsZSkgcHJlcmVxIGZvciB0aGUgbGVzc29uXG5cdFx0XHR0aGlzLmxpc3RlblRvKCB0aGlzLm1vZGVsLCAnY2hhbmdlOmhhc19wcmVyZXF1aXNpdGUnLCBmdW5jdGlvbiggbGVzc29uLCB2YWwgKSB7XG5cdFx0XHRcdGlmICggJ3llcycgPT09IHZhbCApIHtcblx0XHRcdFx0XHR0aGlzLiRlbC5maW5kKCAnc2VsZWN0W25hbWU9XCJwcmVyZXF1aXNpdGVcIl0nICkudHJpZ2dlciggJ2NoYW5nZScgKTtcblx0XHRcdFx0fVxuXHRcdFx0fSApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFJlbmRlciB0aGUgdmlld1xuXHRcdCAqIEByZXR1cm4gICBvYmpcblx0XHQgKiBAc2luY2UgICAgMy4xNy4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTcuMFxuXHRcdCAqL1xuXHRcdHJlbmRlcjogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHRoaXMuJGVsLmh0bWwoIHRoaXMudGVtcGxhdGUoIHRoaXMubW9kZWwgKSApO1xuXG5cdFx0XHR0aGlzLnJlbW92ZV9zdWJ2aWV3KCAnc2V0dGluZ3MnICk7XG5cblx0XHRcdHRoaXMucmVuZGVyX3N1YnZpZXcoICdzZXR0aW5ncycsIHtcblx0XHRcdFx0ZWw6ICcjbGxtcy1sZXNzb24tc2V0dGluZ3MtZmllbGRzJyxcblx0XHRcdFx0bW9kZWw6IHRoaXMubW9kZWwsXG5cdFx0XHR9ICk7XG5cblx0XHRcdHRoaXMuaW5pdF9kYXRlcGlja2VycygpO1xuXHRcdFx0dGhpcy5pbml0X3NlbGVjdHMoKTtcblxuXHRcdFx0cmV0dXJuIHRoaXM7XG5cblx0XHR9LFxuXG5cdH0sIERldGFjaGFibGUsIEVkaXRhYmxlLCBUcmFzaGFibGUsIFN1YnZpZXcsIFNldHRpbmdzRmllbGRzICkgKTtcblxufSApO1xuXG4vKipcbiAqIFNpbmdsZSBRdWl6IFZpZXdcbiAqIEBzaW5jZSAgICAzLjE2LjBcbiAqIEB2ZXJzaW9uICAzLjE2LjBcbiAqL1xuZGVmaW5lKCAnVmlld3MvUG9wb3ZlcicsW10sIGZ1bmN0aW9uKCkge1xuXG5cdHJldHVybiBCYWNrYm9uZS5WaWV3LmV4dGVuZCgge1xuXG5cdFx0ZGVmYXVsdHM6IHtcblx0XHRcdHBsYWNlbWVudDogJ2F1dG8nLFxuXHRcdFx0Ly8gY29udGFpbmVyOiBkb2N1bWVudC5ib2R5LFxuXHRcdFx0d2lkdGg6ICdhdXRvJyxcblx0XHRcdHRyaWdnZXI6ICdtYW51YWwnLFxuXHRcdFx0c3R5bGU6ICdsaWdodCcsXG5cdFx0XHRhbmltYXRpb246ICdwb3AnLFxuXHRcdFx0dGl0bGU6ICcnLFxuXHRcdFx0Y29udGVudDogJycsXG5cdFx0XHRjbG9zZWFibGU6IGZhbHNlLFxuXHRcdFx0YmFja2Ryb3A6IGZhbHNlLFxuXHRcdFx0b25TaG93OiBmdW5jdGlvbiggJGVsICkge30sXG5cdFx0XHRvbkhpZGU6IGZ1bmN0aW9uKCAkZWwgKSB7fSxcblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogV3JhcHBlciBUYWcgbmFtZVxuXHRcdCAqIEB0eXBlICB7U3RyaW5nfVxuXHRcdCAqL1xuXHRcdHRhZ05hbWU6ICdkaXYnLFxuXG5cdFx0LyoqXG5cdFx0ICogSW5pdGlhbGl6YXRpb24gY2FsbGJhY2sgZnVuYyAocmVuZGVycyB0aGUgZWxlbWVudCBvbiBzY3JlZW4pXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNC4xXG5cdFx0ICogQHZlcnNpb24gIDMuMTQuMVxuXHRcdCAqL1xuXHRcdGluaXRpYWxpemU6IGZ1bmN0aW9uKCBkYXRhICkge1xuXG5cdFx0XHRpZiAoIHRoaXMuJGVsLmxlbmd0aCApIHtcblx0XHRcdFx0dGhpcy5kZWZhdWx0cy5jb250YWluZXIgPSB0aGlzLiRlbC5wYXJlbnQoKTtcblx0XHRcdH1cblxuXHRcdFx0dGhpcy5hcmdzID0gXy5kZWZhdWx0cyggZGF0YS5hcmdzLCB0aGlzLmRlZmF1bHRzICk7XG5cdFx0XHR0aGlzLnJlbmRlcigpO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIENvbXBpbGVzIHRoZSB0ZW1wbGF0ZSBhbmQgcmVuZGVycyB0aGUgdmlld1xuXHRcdCAqIEByZXR1cm4gICBzZWxmIChmb3IgY2hhaW5pbmcpXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRyZW5kZXI6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHR0aGlzLiRlbC53ZWJ1aVBvcG92ZXIoIHRoaXMuYXJncyApO1xuXHRcdFx0cmV0dXJuIHRoaXM7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogSGlkZSB0aGUgcG9wb3ZlclxuXHRcdCAqIEByZXR1cm4gICBzZWxmIChmb3IgY2hhaW5pbmcpXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjEyXG5cdFx0ICovXG5cdFx0aGlkZTogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHRoaXMuJGVsLndlYnVpUG9wb3ZlciggJ2hpZGUnICk7XG5cdFx0XHRyZXR1cm4gdGhpcztcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBTaG93IHRoZSBwb3BvdmVyXG5cdFx0ICogQHJldHVybiAgIHNlbGYgKGZvciBjaGFpbmluZylcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMTJcblx0XHQgKi9cblx0XHRzaG93OiBmdW5jdGlvbigpIHtcblxuXHRcdFx0dGhpcy4kZWwud2VidWlQb3BvdmVyKCAnc2hvdycgKTtcblx0XHRcdHJldHVybiB0aGlzO1xuXG5cdFx0fSxcblxuXHR9ICk7XG5cbn0gKTtcblxuLyoqXG4gKiBQb3N0IFBvcG92ZXIgU2VyYWNoIGNvbnRlbnQgVmlld1xuICogQHNpbmNlICAgIDMuMTYuMFxuICogQHZlcnNpb24gIDMuMTcuMFxuICovXG5kZWZpbmUoICdWaWV3cy9Qb3N0U2VhcmNoJyxbXSwgZnVuY3Rpb24oKSB7XG5cblx0cmV0dXJuIEJhY2tib25lLlZpZXcuZXh0ZW5kKCB7XG5cblx0XHQvKipcblx0XHQgKiBET00gRXZlbnRzXG5cdFx0ICogQHR5cGUgICAgIG9ialxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0ZXZlbnRzOiB7XG5cdFx0XHQnc2VsZWN0MjpzZWxlY3QnOiAnYWRkX3Bvc3QnLFxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBXcmFwcGVyIFRhZyBuYW1lXG5cdFx0ICogQHR5cGUgIHtTdHJpbmd9XG5cdFx0ICovXG5cdFx0dGFnTmFtZTogJ3NlbGVjdCcsXG5cblx0XHQvKipcblx0XHQgKiBJbml0aWFsaXplclxuXHRcdCAqIEBwYXJhbSAgICBvYmogICBkYXRhICBjdXN0b21pemUgdGhlIHNlYXJjaCBib3ggd2l0aCBkYXRhXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4xMlxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjEyXG5cdFx0ICovXG5cdFx0aW5pdGlhbGl6ZTogZnVuY3Rpb24oIGRhdGEgKSB7XG5cblx0XHRcdHRoaXMucG9zdF90eXBlID0gZGF0YS5wb3N0X3R5cGU7XG5cdFx0XHR0aGlzLnNlYXJjaGluZ19tZXNzYWdlID0gZGF0YS5zZWFyY2hpbmdfbWVzc2FnZSB8fCBMTE1TLmwxMG4udHJhbnNsYXRlKCAnU2VhcmNoaW5nLi4uJyApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFNlbGVjdCBldmVudCwgYWRkcyB0aGUgZXhpc3RpbmcgbGVzc29uIHRvIHRoZSBjb3Vyc2Vcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgZXZlbnQgIHNlbGVjdDI6c2VsZWN0IGV2ZW50IG9iamVjdFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNy4wXG5cdFx0ICovXG5cdFx0YWRkX3Bvc3Q6IGZ1bmN0aW9uKCBldmVudCApIHtcblxuXHRcdFx0dmFyIHR5cGUgPSB0aGlzLiRlbC5hdHRyKCAnZGF0YS1wb3N0LXR5cGUnICk7XG5cblx0XHRcdEJhY2tib25lLnB1YlN1Yi50cmlnZ2VyKCB0eXBlLnJlcGxhY2UoICdsbG1zXycsICcnICkgKyAnLXNlYXJjaC1zZWxlY3QnLCBldmVudC5wYXJhbXMuZGF0YSwgZXZlbnQgKTtcblx0XHRcdHRoaXMuJGVsLnZhbCggbnVsbCApLnRyaWdnZXIoICdjaGFuZ2UnICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogUmVuZGVyIHRoZSBzZWN0aW9uXG5cdFx0ICogSW5pdGFsaXplcyBhIG5ldyBjb2xsZWN0aW9uIGFuZCB2aWV3cyBmb3IgYWxsIGxlc3NvbnMgaW4gdGhlIHNlY3Rpb25cblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4xMlxuXHRcdCAqL1xuXHRcdHJlbmRlcjogZnVuY3Rpb24oKSB7XG5cdFx0XHR2YXIgc2VsZiA9IHRoaXM7XG5cdFx0XHRzZXRUaW1lb3V0KCBmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdHNlbGYuJGVsLmxsbXNTZWxlY3QyKCB7XG5cdFx0XHRcdFx0YWpheDoge1xuXHRcdFx0XHRcdFx0ZGF0YVR5cGU6ICdKU09OJyxcblx0XHRcdFx0XHRcdGRlbGF5OiAyNTAsXG5cdFx0XHRcdFx0XHRtZXRob2Q6ICdQT1NUJyxcblx0XHRcdFx0XHRcdHVybDogd2luZG93LmFqYXh1cmwsXG5cdFx0XHRcdFx0XHRkYXRhOiBmdW5jdGlvbiggcGFyYW1zICkge1xuXHRcdFx0XHRcdFx0XHRyZXR1cm4ge1xuXHRcdFx0XHRcdFx0XHRcdGFjdGlvbjogJ2xsbXNfYnVpbGRlcicsXG5cdFx0XHRcdFx0XHRcdFx0YWN0aW9uX3R5cGU6ICdzZWFyY2gnLFxuXHRcdFx0XHRcdFx0XHRcdGNvdXJzZV9pZDogd2luZG93LmxsbXNfYnVpbGRlci5jb3Vyc2UuaWQsXG5cdFx0XHRcdFx0XHRcdFx0cG9zdF90eXBlOiBzZWxmLnBvc3RfdHlwZSxcblx0XHRcdFx0XHRcdFx0XHR0ZXJtOiBwYXJhbXMudGVybSxcblx0XHRcdFx0XHRcdFx0XHRwYWdlOiBwYXJhbXMucGFnZSxcblx0XHRcdFx0XHRcdFx0XHRfYWpheF9ub25jZTogd3BfYWpheF9kYXRhLm5vbmNlLFxuXHRcdFx0XHRcdFx0XHR9O1xuXHRcdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRcdC8vIGVycm9yOiBmdW5jdGlvbiggeGhyLCBzdGF0dXMsIGVycm9yICkge1xuXHRcdFx0XHRcdFx0Ly8gXHRjb25zb2xlLmxvZyggc3RhdHVzLCBlcnJvciApO1xuXHRcdFx0XHRcdFx0Ly8gfSxcblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdGRyb3Bkb3duUGFyZW50OiAkKCAnLndyYXAubGlmdGVybG1zLmxsbXMtYnVpbGRlcicgKSxcblx0XHRcdFx0XHQvLyBkb24ndCBlc2NhcGUgaHRtbCBmcm9tIHJlbmRlcl9yZXN1bHRcblx0XHRcdFx0XHRlc2NhcGVNYXJrdXA6IGZ1bmN0aW9uKCBtYXJrdXAgKSB7XG5cdFx0XHRcdFx0XHRyZXR1cm4gbWFya3VwO1xuXHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0cGxhY2Vob2xkZXI6IHNlbGYuc2VhcmNoaW5nX21lc3NhZ2UsXG5cdFx0XHRcdFx0dGVtcGxhdGVSZXN1bHQ6IHNlbGYucmVuZGVyX3Jlc3VsdCxcblx0XHRcdFx0XHR3aWR0aDogJzEwMCUnLFxuXHRcdFx0XHR9ICk7XG5cdFx0XHRcdHNlbGYuJGVsLmF0dHIoICdkYXRhLXBvc3QtdHlwZScsIHNlbGYucG9zdF90eXBlICk7XG5cdFx0XHR9LCAwICk7XG5cdFx0XHRyZXR1cm4gdGhpcztcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBSZW5kZXIgYSBuaWNlciBVSSBmb3IgZWFjaCBzZWFyY2ggcmVzdWx0IGluIHRoZSBpbiB0aGUgU2VsZWN0MiBzZWFyY2ggcmVzdWx0c1xuXHRcdCAqIEBwYXJhbSAgICBvYmplY3QgICByZXMgIHJlc3VsdCBkYXRhXG5cdFx0ICogQHJldHVybiAgIHN0cmluZ1xuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4xMlxuXHRcdCAqL1xuXHRcdHJlbmRlcl9yZXN1bHQ6IGZ1bmN0aW9uKCByZXMgKSB7XG5cblx0XHRcdHZhciAkaHRtbCA9ICQoICc8ZGl2IGNsYXNzPVwibGxtcy1leGlzdGluZy1sZXNzb24tcmVzdWx0XCIgLz4nICk7XG5cblx0XHRcdGlmICggcmVzLmxvYWRpbmcgKSB7XG5cdFx0XHRcdHJldHVybiAkaHRtbC5hcHBlbmQoIHJlcy50ZXh0ICk7XG5cdFx0XHR9XG5cblx0XHRcdHZhciAkc2lkZSA9ICQoICc8YXNpZGUgY2xhc3M9XCJsbG1zLWV4aXN0aW5nLWFjdGlvblwiIC8+JyApLFxuXHRcdFx0XHQkbWFpbiA9ICQoICc8ZGl2IGNsYXNzPVwibGxtcy1leGlzdGluZy1pbmZvXCIgLz4nICk7XG5cdFx0XHRcdGljb24gPSAoICdhdHRhY2gnID09PSByZXMuYWN0aW9uICkgPyAncGFwZXJjbGlwJyA6ICdjbG9uZScsXG5cdFx0XHRcdHRleHQgPSAoICdhdHRhY2gnID09PSByZXMuYWN0aW9uICkgPyBMTE1TLmwxMG4udHJhbnNsYXRlKCAnQXR0YWNoJyApIDogTExNUy5sMTBuLnRyYW5zbGF0ZSggJ0Nsb25lJyApO1xuXG5cdFx0XHQkc2lkZS5hcHBlbmQoICc8aSBjbGFzcz1cImZhIGZhLScgKyBpY29uICsgJ1wiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjwvaT48c21hbGw+JyArIHRleHQgKyAnPC9zbWFsbD4nICk7XG5cblx0XHRcdCRtYWluLmFwcGVuZCggJzxoND4nICsgcmVzLmRhdGEudGl0bGUgKyAnPC9oND4nICk7XG5cdFx0XHQkbWFpbi5hcHBlbmQoICc8aDU+JyArIExMTVMubDEwbi50cmFuc2xhdGUoICdJRCcgKSArICc6IDxlbT4nICsgcmVzLmRhdGEuaWQgKyAnPC9lbT48L2g1PicgKTtcblxuXHRcdFx0Xy5lYWNoKCByZXMucGFyZW50cywgZnVuY3Rpb24oIHBhcmVudCApIHtcblx0XHRcdFx0JG1haW4uYXBwZW5kKCAnPGg1PicgKyBwYXJlbnQgKyAnPC9lbT48L2g1PicgKTtcblx0XHRcdH0gKTtcblxuXHRcdFx0cmV0dXJuICRodG1sLmFwcGVuZCggJHNpZGUgKS5hcHBlbmQoICRtYWluICk7XG5cblx0XHR9LFxuXG5cdH0gKTtcblxufSApO1xuXG4vKipcbiAqIFNpbmdsZSBMZXNzb24gVmlld1xuICogQHNpbmNlICAgIDMuMTYuMFxuICogQHZlcnNpb24gIDMuMTYuMFxuICovXG5kZWZpbmUoICdWaWV3cy9RdWVzdGlvblR5cGUnLFsgXSwgZnVuY3Rpb24oKSB7XG5cblx0cmV0dXJuIEJhY2tib25lLlZpZXcuZXh0ZW5kKCB7XG5cblx0XHQvKipcblx0XHQgKiBIVE1MIGNsYXNzIG5hbWVzXG5cdFx0ICogQHR5cGUgIHtTdHJpbmd9XG5cdFx0ICovXG5cdFx0Y2xhc3NOYW1lOiAnbGxtcy1xdWVzdGlvbi10eXBlJyxcblxuXHRcdGV2ZW50czoge1xuXHRcdFx0J2NsaWNrIC5sbG1zLWFkZC1xdWVzdGlvbic6ICdhZGRfcXVlc3Rpb24nLFxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBIVE1MIGVsZW1lbnQgd3JhcHBlciBJRCBhdHRyaWJ1dGVcblx0XHQgKiBAcmV0dXJuICAgc3RyaW5nXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRpZDogZnVuY3Rpb24oKSB7XG5cdFx0XHRyZXR1cm4gJ2xsbXMtcXVlc3Rpb24tdHlwZS0nICsgdGhpcy5tb2RlbC5pZDtcblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogV3JhcHBlciBUYWcgbmFtZVxuXHRcdCAqIEB0eXBlICB7U3RyaW5nfVxuXHRcdCAqL1xuXHRcdHRhZ05hbWU6ICdsaScsXG5cblx0XHQvKipcblx0XHQgKiBHZXQgdGhlIHVuZGVyc2NvcmUgdGVtcGxhdGVcblx0XHQgKiBAdHlwZSAge1t0eXBlXX1cblx0XHQgKi9cblx0XHR0ZW1wbGF0ZTogd3AudGVtcGxhdGUoICdsbG1zLXF1ZXN0aW9uLXR5cGUtdGVtcGxhdGUnICksXG5cblx0XHQvKipcblx0XHQgKiBJbml0aWFsaXphdGlvbiBjYWxsYmFjayBmdW5jIChyZW5kZXJzIHRoZSBlbGVtZW50IG9uIHNjcmVlbilcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0aW5pdGlhbGl6ZTogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHRoaXMucmVuZGVyKCk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogQ29tcGlsZXMgdGhlIHRlbXBsYXRlIGFuZCByZW5kZXJzIHRoZSB2aWV3XG5cdFx0ICogQHJldHVybiAgIHNlbGYgKGZvciBjaGFpbmluZylcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdHJlbmRlcjogZnVuY3Rpb24oKSB7XG5cdFx0XHR0aGlzLiRlbC5odG1sKCB0aGlzLnRlbXBsYXRlKCB0aGlzLm1vZGVsICkgKTtcblx0XHRcdHJldHVybiB0aGlzO1xuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBBZGQgYSBxdWVzdGlvbiBvZiB0aGUgc2VsZWN0ZWQgdHlwZSB0byB0aGUgY3VycmVudCBxdWl6XG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRhZGRfcXVlc3Rpb246IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHR0aGlzLnF1aXouYWRkX3F1ZXN0aW9uKCB7XG5cdFx0XHRcdF9leHBhbmRlZDogdHJ1ZSxcblx0XHRcdFx0Y2hvaWNlczogdGhpcy5tb2RlbC5nZXQoICdkZWZhdWx0X2Nob2ljZXMnICkgPyB0aGlzLm1vZGVsLmdldCggJ2RlZmF1bHRfY2hvaWNlcycgKSA6IG51bGwsXG5cdFx0XHRcdHF1ZXN0aW9uX3R5cGU6IHRoaXMubW9kZWwsXG5cdFx0XHR9ICk7XG5cblx0XHRcdHRoaXMucXVpei50cmlnZ2VyKCAnbmV3LXF1ZXN0aW9uLWFkZGVkJyApO1xuXG5cdFx0fSxcblxuXHRcdC8vIGZpbHRlcjogZnVuY3Rpb24oIHRlcm0gKSB7XG5cblx0XHQvLyBcdHZhciB3b3JkcyA9IHRoaXMubW9kZWwuZ2V0X2tleXdvcmRzKCkubWFwKCBmdW5jdGlvbiggd29yZCApIHtcblx0XHQvLyBcdFx0cmV0dXJuIHdvcmQudG9Mb3dlckNhc2UoKTtcblx0XHQvLyBcdH0gKTtcblxuXHRcdC8vIFx0dGVybSA9IHRlcm0udG9Mb3dlckNhc2UoKTtcblxuXHRcdC8vIFx0aWYgKCAtMSA9PT0gd29yZHMuaW5kZXhPZiggdGVybSApICkge1xuXHRcdC8vIFx0XHR0aGlzLiRlbC5hZGRDbGFzcyggJ2ZpbHRlcmVkJyApO1xuXHRcdC8vIFx0fSBlbHNlIHtcblx0XHQvLyBcdFx0dGhpcy4kZWwucmVtb3ZlQ2xhc3MoICdmaWx0ZXJlZCcgKTtcblx0XHQvLyBcdH1cblxuXHRcdC8vIH0sXG5cblx0XHQvLyBjbGVhcl9maWx0ZXI6IGZ1bmN0aW9uKCkge1xuXHRcdC8vIFx0dGhpcy4kZWwucmVtb3ZlQ2xhc3MoICdmaWx0ZXJlZCcgKTtcblx0XHQvLyB9XG5cblx0fSApO1xuXG59ICk7XG5cbi8qKlxuICogUXVpeiBxdWVzdGlvbiBiYW5rIHZpZXdcbiAqIEBzaW5jZSAgICAzLjE2LjBcbiAqIEB2ZXJzaW9uICAzLjE2LjBcbiAqL1xuZGVmaW5lKCAnVmlld3MvUXVlc3Rpb25CYW5rJyxbICdWaWV3cy9RdWVzdGlvblR5cGUnIF0sIGZ1bmN0aW9uKCBRdWVzdGlvblZpZXcgKSB7XG5cblx0cmV0dXJuIEJhY2tib25lLkNvbGxlY3Rpb25WaWV3LmV4dGVuZCgge1xuXG5cdFx0Y2xhc3NOYW1lOiAnbGxtcy1xdWVzdGlvbicsXG5cblx0XHQvKipcblx0XHQgKiBQYXJlbnQgZWxlbWVudFxuXHRcdCAqIEB0eXBlICB7U3RyaW5nfVxuXHRcdCAqL1xuXHRcdGVsOiAnI2xsbXMtcXVlc3Rpb24tYmFuaycsXG5cblx0XHQvKipcblx0XHQgKiBTZWN0aW9uIG1vZGVsXG5cdFx0ICogQHR5cGUgIHtbdHlwZV19XG5cdFx0ICovXG5cdFx0bW9kZWxWaWV3OiBRdWVzdGlvblZpZXcsXG5cblx0XHQvKipcblx0XHQgKiBBcmUgc2VjdGlvbnMgc2VsZWN0YWJsZT9cblx0XHQgKiBAdHlwZSAge0Jvb2x9XG5cdFx0ICovXG5cdFx0c2VsZWN0YWJsZTogZmFsc2UsXG5cblx0XHQvKipcblx0XHQgKiBBcmUgc2VjdGlvbnMgc29ydGFibGU/XG5cdFx0ICogQHR5cGUgIHtCb29sfVxuXHRcdCAqL1xuXHRcdHNvcnRhYmxlOiBmYWxzZSxcblxuXHR9ICk7XG5cbn0gKTtcblxuLyoqXG4gKiBTaW5nbGUgUXVlc3Rpb24gQ2hvaWNlIFZpZXdcbiAqIEBzaW5jZSAgICAzLjE2LjBcbiAqIEB2ZXJzaW9uICAzLjE2LjBcbiAqL1xuZGVmaW5lKCAnVmlld3MvUXVlc3Rpb25DaG9pY2UnLFsgJ1ZpZXdzL19FZGl0YWJsZScsIF0sIGZ1bmN0aW9uKCBFZGl0YWJsZSApIHtcblxuXHRyZXR1cm4gQmFja2JvbmUuVmlldy5leHRlbmQoIF8uZGVmYXVsdHMoIHtcblxuXHRcdC8qKlxuXHRcdCAqIEhUTUwgY2xhc3MgbmFtZXNcblx0XHQgKiBAdHlwZSAge1N0cmluZ31cblx0XHQgKi9cblx0XHRjbGFzc05hbWU6ICdsbG1zLXF1ZXN0aW9uLWNob2ljZScsXG5cblx0XHRldmVudHM6IF8uZGVmYXVsdHMoIHtcblx0XHRcdCdjaGFuZ2UgaW5wdXRbbmFtZT1cImNvcnJlY3RcIl0nOiAndG9nZ2xlX2NvcnJlY3QnLFxuXHRcdFx0J2NsaWNrIC5sbG1zLWFjdGlvbi1pY29uW2hyZWY9XCIjbGxtcy1hZGQtY2hvaWNlXCJdJzogJ2FkZF9jaG9pY2UnLFxuXHRcdFx0J2NsaWNrIC5sbG1zLWFjdGlvbi1pY29uW2hyZWY9XCIjbGxtcy1kZWwtY2hvaWNlXCJdJzogJ2RlbF9jaG9pY2UnLFxuXHRcdH0sIEVkaXRhYmxlLmV2ZW50cyApLFxuXG5cdFx0LyoqXG5cdFx0ICogSFRNTCBlbGVtZW50IHdyYXBwZXIgSUQgYXR0cmlidXRlXG5cdFx0ICogQHJldHVybiAgIHN0cmluZ1xuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0aWQ6IGZ1bmN0aW9uKCkge1xuXHRcdFx0cmV0dXJuICdsbG1zLXF1ZXN0aW9uLWNob2ljZS0nICsgdGhpcy5tb2RlbC5pZDtcblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogV3JhcHBlciBUYWcgbmFtZVxuXHRcdCAqIEB0eXBlICB7U3RyaW5nfVxuXHRcdCAqL1xuXHRcdHRhZ05hbWU6ICdsaScsXG5cblx0XHQvKipcblx0XHQgKiBHZXQgdGhlIHVuZGVyc2NvcmUgdGVtcGxhdGVcblx0XHQgKiBAdHlwZSAge1t0eXBlXX1cblx0XHQgKi9cblx0XHR0ZW1wbGF0ZTogd3AudGVtcGxhdGUoICdsbG1zLXF1ZXN0aW9uLWNob2ljZS10ZW1wbGF0ZScgKSxcblxuXHRcdC8qKlxuXHRcdCAqIEluaXRpYWxpemF0aW9uIGNhbGxiYWNrIGZ1bmMgKHJlbmRlcnMgdGhlIGVsZW1lbnQgb24gc2NyZWVuKVxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTQuMVxuXHRcdCAqIEB2ZXJzaW9uICAzLjE0LjFcblx0XHQgKi9cblx0XHRpbml0aWFsaXplOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0dGhpcy5yZW5kZXIoKTtcblxuXHRcdFx0dGhpcy5saXN0ZW5UbyggdGhpcy5tb2RlbC5jb2xsZWN0aW9uLCAnYWRkJywgdGhpcy5tYXliZV9kaXNhYmxlX2J1dHRvbnMgKTtcblx0XHRcdHRoaXMubGlzdGVuVG8oIHRoaXMubW9kZWwsICdjaGFuZ2UnLCB0aGlzLnJlbmRlciApO1xuXG5cdFx0XHRpZiAoICdpbWFnZScgPT09IHRoaXMubW9kZWwuZ2V0KCAnY2hvaWNlX3R5cGUnICkgKSB7XG5cdFx0XHRcdHRoaXMubGlzdGVuVG8oIHRoaXMubW9kZWwuZ2V0KCAnY2hvaWNlJyApLCAnY2hhbmdlJywgdGhpcy5yZW5kZXIgKTtcblx0XHRcdH1cblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBDb21waWxlcyB0aGUgdGVtcGxhdGUgYW5kIHJlbmRlcnMgdGhlIHZpZXdcblx0XHQgKiBAcmV0dXJuICAgc2VsZiAoZm9yIGNoYWluaW5nKVxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0cmVuZGVyOiBmdW5jdGlvbigpIHtcblx0XHRcdHRoaXMuJGVsLmh0bWwoIHRoaXMudGVtcGxhdGUoIHRoaXMubW9kZWwgKSApO1xuXHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIEFkZCBhIG5ldyBjaG9pY2UgdG8gdGhlIGN1cnJlbnQgY2hvaWNlIGxpc3Rcblx0XHQgKiBBZGRzICphZnRlciogdGhlIGNsaWNrZWQgY2hvaWNlXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIGV2ZW50ICBKUyBldmVudCBvYmplY3Rcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0YWRkX2Nob2ljZTogZnVuY3Rpb24oIGV2ZW50ICkge1xuXG5cdFx0XHRldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcblx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cblx0XHRcdHZhciBpbmRleCA9IHRoaXMubW9kZWwuY29sbGVjdGlvbi5pbmRleE9mKCB0aGlzLm1vZGVsICk7XG5cdFx0XHR0aGlzLm1vZGVsLmNvbGxlY3Rpb24ucGFyZW50LmFkZF9jaG9pY2UoIHt9LCB7XG5cdFx0XHRcdGF0OiBpbmRleCArIDEsXG5cdFx0XHR9ICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogRGVsZXRlIHRoZSBjaG9pY2UgZnJvbSB0aGUgY2hvaWNlIGxpc3QgJiBlbnN1cmUgdGhlcmUncyBhdCBsZWFzdCBvbmUgY29ycmVjdCBjaG9pY2Vcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgZXZlbnQgIGpzIGV2ZW50IG9ialxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRkZWxfY2hvaWNlOiBmdW5jdGlvbiggZXZlbnQgKSB7XG5cblx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHRCYWNrYm9uZS5wdWJTdWIudHJpZ2dlciggJ21vZGVsLXRyYXNoZWQnLCB0aGlzLm1vZGVsICk7XG5cdFx0XHR0aGlzLm1vZGVsLmNvbGxlY3Rpb24ucmVtb3ZlKCB0aGlzLm1vZGVsICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogV2hlbiB0aGUgY29ycmVjdCBhbnN3ZXIgaW5wdXQgY2hhbmdlcyBzeW5jIHN0YXR1cyB0byBtb2RlbFxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHR0b2dnbGVfY29ycmVjdDogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHZhciBjb3JyZWN0ID0gdGhpcy4kZWwuZmluZCggJ2lucHV0W25hbWU9XCJjb3JyZWN0XCJdJyApLmlzKCAnOmNoZWNrZWQnICk7XG5cdFx0XHR0aGlzLm1vZGVsLnNldCggJ2NvcnJlY3QnLCBjb3JyZWN0ICk7XG5cdFx0XHR0aGlzLm1vZGVsLmNvbGxlY3Rpb24udHJpZ2dlciggJ2NvcnJlY3QtdXBkYXRlJywgdGhpcy5tb2RlbCApO1xuXG5cdFx0fSxcblxuXHR9LCBFZGl0YWJsZSApICk7XG5cbn0gKTtcblxuLyoqXG4gKiBRdWl6IHF1ZXN0aW9uIGJhbmsgdmlld1xuICogQHNpbmNlICAgIDMuMTYuMFxuICogQHZlcnNpb24gIDMuMTYuMFxuICovXG5kZWZpbmUoICdWaWV3cy9RdWVzdGlvbkNob2ljZUxpc3QnLFsgJ1ZpZXdzL1F1ZXN0aW9uQ2hvaWNlJyBdLCBmdW5jdGlvbiggQ2hvaWNlVmlldyApIHtcblxuXHRyZXR1cm4gQmFja2JvbmUuQ29sbGVjdGlvblZpZXcuZXh0ZW5kKCB7XG5cblx0XHRjbGFzc05hbWU6ICdsbG1zLXF1aXotcXVlc3Rpb25zJyxcblxuXHRcdC8qKlxuXHRcdCAqIENob2ljZSBtb2RlbCB2aWV3XG5cdFx0ICogQHR5cGUgIHtbdHlwZV19XG5cdFx0ICovXG5cdFx0bW9kZWxWaWV3OiBDaG9pY2VWaWV3LFxuXG5cdFx0LyoqXG5cdFx0ICogRW5hYmxlIGtleWJvYXJkIGV2ZW50c1xuXHRcdCAqIEB0eXBlICB7Qm9vbH1cblx0XHQgKi9cblx0XHRwcm9jZXNzS2V5RXZlbnRzOiBmYWxzZSxcblxuXHRcdC8qKlxuXHRcdCAqIEFyZSBzZWN0aW9ucyBzZWxlY3RhYmxlP1xuXHRcdCAqIEB0eXBlICB7Qm9vbH1cblx0XHQgKi9cblx0XHRzZWxlY3RhYmxlOiBmYWxzZSxcblxuXHRcdC8qKlxuXHRcdCAqIEFyZSBzZWN0aW9ucyBzb3J0YWJsZT9cblx0XHQgKiBAdHlwZSAge0Jvb2x9XG5cdFx0ICovXG5cdFx0c29ydGFibGU6IHRydWUsXG5cblx0XHRzb3J0YWJsZU9wdGlvbnM6IHtcblx0XHRcdGF4aXM6IGZhbHNlLFxuXHRcdFx0Ly8gY29ubmVjdFdpdGg6ICcubGxtcy1sZXNzb25zJyxcblx0XHRcdGN1cnNvcjogJ21vdmUnLFxuXHRcdFx0aGFuZGxlOiAnLmxsbXMtY2hvaWNlLWlkJyxcblx0XHRcdGl0ZW1zOiAnLmxsbXMtcXVlc3Rpb24tY2hvaWNlJyxcblx0XHRcdHBsYWNlaG9sZGVyOiAnbGxtcy1xdWVzdGlvbi1jaG9pY2UgbGxtcy1zb3J0YWJsZS1wbGFjZWhvbGRlcicsXG5cdFx0fSxcblxuXHRcdHNvcnRhYmxlX3N0YXJ0OiBmdW5jdGlvbiggbW9kZWwgKSB7XG5cdFx0XHR0aGlzLiRlbC5hZGRDbGFzcyggJ2RyYWdnaW5nJyApO1xuXHRcdH0sXG5cblx0XHRzb3J0YWJsZV9zdG9wOiBmdW5jdGlvbiggbW9kZWwgKSB7XG5cdFx0XHR0aGlzLiRlbC5yZW1vdmVDbGFzcyggJ2RyYWdnaW5nJyApO1xuXHRcdH0sXG5cblx0fSApO1xuXG59ICk7XG5cbi8qKlxuICogU2luZ2xlIFF1ZXN0aW9uIFZpZXdcbiAqIEBzaW5jZSAgICAzLjE2LjBcbiAqIEB2ZXJzaW9uICAzLjE2LjBcbiAqL1xuZGVmaW5lKCAnVmlld3MvUXVlc3Rpb24nLFtcblx0XHQnVmlld3MvX0VkaXRhYmxlJyxcblx0XHQnVmlld3MvUXVlc3Rpb25DaG9pY2VMaXN0J1xuXHRdLCBmdW5jdGlvbihcblx0XHRFZGl0YWJsZSxcblx0XHRDaG9pY2VMaXN0Vmlld1xuXHQpIHtcblxuXHRyZXR1cm4gQmFja2JvbmUuVmlldy5leHRlbmQoIF8uZGVmYXVsdHMoIHtcblxuXHRcdC8qKlxuXHRcdCAqIEdlbmVyYXRlIENTUyBjbGFzc2VzIGZvciB0aGUgcXVlc3Rpb25cblx0XHQgKiBAcmV0dXJuICAgc3RyaW5nXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRjbGFzc05hbWU6IGZ1bmN0aW9uKCkge1xuXHRcdFx0cmV0dXJuICdsbG1zLXF1ZXN0aW9uIHF0eXBlLS0nICsgdGhpcy5tb2RlbC5nZXQoICdxdWVzdGlvbl90eXBlJyApLmdldCggJ2lkJyApO1xuXHRcdH0sXG5cblx0XHRldmVudHM6IF8uZGVmYXVsdHMoIHtcblx0XHRcdCdjbGljayAuY2xvbmUtLXF1ZXN0aW9uJzogJ2Nsb25lJyxcblx0XHRcdCdjbGljayAuZGVsZXRlLS1xdWVzdGlvbic6ICdkZWxldGUnLFxuXHRcdFx0J2NsaWNrIC5leHBhbmQtLXF1ZXN0aW9uJzogJ2V4cGFuZCcsXG5cdFx0XHQnY2xpY2sgLmNvbGxhcHNlLS1xdWVzdGlvbic6ICdjb2xsYXBzZScsXG5cdFx0XHQnY2hhbmdlIGlucHV0W25hbWU9XCJxdWVzdGlvbl9wb2ludHNcIl0nOiAndXBkYXRlX3BvaW50cycsXG5cdFx0fSwgRWRpdGFibGUuZXZlbnRzICksXG5cblx0XHQvKipcblx0XHQgKiBIVE1MIGVsZW1lbnQgd3JhcHBlciBJRCBhdHRyaWJ1dGVcblx0XHQgKiBAcmV0dXJuICAgc3RyaW5nXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRpZDogZnVuY3Rpb24oKSB7XG5cdFx0XHRyZXR1cm4gJ2xsbXMtcXVlc3Rpb24tJyArIHRoaXMubW9kZWwuaWQ7XG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFdyYXBwZXIgVGFnIG5hbWVcblx0XHQgKiBAdHlwZSAge1N0cmluZ31cblx0XHQgKi9cblx0XHR0YWdOYW1lOiAnbGknLFxuXG5cdFx0LyoqXG5cdFx0ICogR2V0IHRoZSB1bmRlcnNjb3JlIHRlbXBsYXRlXG5cdFx0ICogQHR5cGUgIHtbdHlwZV19XG5cdFx0ICovXG5cdFx0dGVtcGxhdGU6IHdwLnRlbXBsYXRlKCAnbGxtcy1xdWVzdGlvbi10ZW1wbGF0ZScgKSxcblxuXHRcdC8qKlxuXHRcdCAqIEluaXRpYWxpemF0aW9uIGNhbGxiYWNrIGZ1bmMgKHJlbmRlcnMgdGhlIGVsZW1lbnQgb24gc2NyZWVuKVxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRpbml0aWFsaXplOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0dmFyIGNoYW5nZV9ldmVudHMgPSBbXG5cdFx0XHRcdCdjaGFuZ2U6X2V4cGFuZGVkJyxcblx0XHRcdFx0J2NoYW5nZTptZW51X29yZGVyJyxcblx0XHRcdF07XG5cdFx0XHRfLmVhY2goIGNoYW5nZV9ldmVudHMsIGZ1bmN0aW9uKCBldmVudCApIHtcblx0XHRcdFx0dGhpcy5saXN0ZW5UbyggdGhpcy5tb2RlbCwgZXZlbnQsIHRoaXMucmVuZGVyICk7XG5cdFx0XHR9LCB0aGlzICk7XG5cblx0XHRcdHRoaXMubGlzdGVuVG8oIHRoaXMubW9kZWwuZ2V0KCAnaW1hZ2UnICksICdjaGFuZ2UnLCB0aGlzLnJlbmRlciApO1xuXG5cdFx0XHR0aGlzLmxpc3RlblRvKCB0aGlzLm1vZGVsLmdldF9wYXJlbnQoKSwgJ2NoYW5nZTpfcG9pbnRzJywgdGhpcy5yZW5kZXJfcG9pbnRzX3BlcmNlbnRhZ2UgKTtcblxuXHRcdFx0dGhpcy5vbiggJ211bHRpX2Nob2ljZXNfdG9nZ2xlJywgdGhpcy5tdWx0aV9jaG9pY2VzX3RvZ2dsZSwgdGhpcyApO1xuXG5cdFx0XHRCYWNrYm9uZS5wdWJTdWIub24oICdkZWwtcXVlc3Rpb24tY2hvaWNlJywgdGhpcy5kZWxfY2hvaWNlLCB0aGlzICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogQ29tcGlsZXMgdGhlIHRlbXBsYXRlIGFuZCByZW5kZXJzIHRoZSB2aWV3XG5cdFx0ICogQHJldHVybiAgIHNlbGYgKGZvciBjaGFpbmluZylcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdHJlbmRlcjogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHRoaXMuJGVsLmh0bWwoIHRoaXMudGVtcGxhdGUoIHRoaXMubW9kZWwgKSApO1xuXG5cdFx0XHRpZiAoIHRoaXMubW9kZWwuZ2V0KCAncXVlc3Rpb25fdHlwZScpLmdldCggJ2Nob2ljZXMnICkgKSB7XG5cblx0XHRcdFx0dGhpcy5jaG9pY2VMaXN0VmlldyA9IG5ldyBDaG9pY2VMaXN0Vmlldygge1xuXHRcdFx0XHRcdGVsOiB0aGlzLiRlbC5maW5kKCAnLmxsbXMtcXVlc3Rpb24tY2hvaWNlcycgKSxcblx0XHRcdFx0XHRjb2xsZWN0aW9uOiB0aGlzLm1vZGVsLmdldCggJ2Nob2ljZXMnICksXG5cdFx0XHRcdH0gKTtcblx0XHRcdFx0dGhpcy5jaG9pY2VMaXN0Vmlldy5yZW5kZXIoKTtcblx0XHRcdFx0dGhpcy5jaG9pY2VMaXN0Vmlldy5vbiggJ3NvcnRTdGFydCcsIHRoaXMuY2hvaWNlTGlzdFZpZXcuc29ydGFibGVfc3RhcnQgKTtcblx0XHRcdFx0dGhpcy5jaG9pY2VMaXN0Vmlldy5vbiggJ3NvcnRTdG9wJywgdGhpcy5jaG9pY2VMaXN0Vmlldy5zb3J0YWJsZV9zdG9wICk7XG5cblx0XHRcdH1cblxuXHRcdFx0aWYgKCAnZ3JvdXAnID09PSB0aGlzLm1vZGVsLmdldCggJ3F1ZXN0aW9uX3R5cGUnICkuZ2V0KCAnaWQnICkgKSB7XG5cblx0XHRcdFx0dmFyIHNlbGYgPSB0aGlzO1xuXHRcdFx0XHRzZXRUaW1lb3V0KCBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRzZWxmLnF1ZXN0aW9uTGlzdFZpZXcgPSBzZWxmLmNvbGxlY3Rpb25MaXN0Vmlldy5xdWl6LmdldF9xdWVzdGlvbl9saXN0KCB7XG5cdFx0XHRcdFx0XHRlbDogc2VsZi4kZWwuZmluZCggJy5sbG1zLXF1aXotcXVlc3Rpb25zJyApLFxuXHRcdFx0XHRcdFx0Y29sbGVjdGlvbjogc2VsZi5tb2RlbC5nZXQoICdxdWVzdGlvbnMnICksXG5cdFx0XHRcdFx0fSApO1xuXHRcdFx0XHRcdHNlbGYucXVlc3Rpb25MaXN0Vmlldy5yZW5kZXIoKTtcblx0XHRcdFx0XHRzZWxmLnF1ZXN0aW9uTGlzdFZpZXcub24oICdzb3J0U3RhcnQnLCBzZWxmLnF1ZXN0aW9uTGlzdFZpZXcuc29ydGFibGVfc3RhcnQgKTtcblx0XHRcdFx0XHRzZWxmLnF1ZXN0aW9uTGlzdFZpZXcub24oICdzb3J0U3RvcCcsIHNlbGYucXVlc3Rpb25MaXN0Vmlldy5zb3J0YWJsZV9zdG9wICk7XG5cdFx0XHRcdH0sIDEgKTtcblxuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIHRoaXMubW9kZWwuZ2V0KCAnZGVzY3JpcHRpb25fZW5hYmxlZCcgKSApIHtcblx0XHRcdFx0dGhpcy5pbml0X2VkaXRvciggJ3F1ZXN0aW9uLWRlc2MtLScgKyB0aGlzLm1vZGVsLmdldCggJ2lkJyApICk7XG5cdFx0XHR9XG5cblx0XHRcdGlmICggdGhpcy5tb2RlbC5nZXQoICdjbGFyaWZpY2F0aW9uc19lbmFibGVkJyApICkge1xuXHRcdFx0XHR0aGlzLmluaXRfZWRpdG9yKCAncXVlc3Rpb24tY2xhcmlmaWNhdGlvbnMtLScgKyB0aGlzLm1vZGVsLmdldCggJ2lkJyApLCB7XG5cdFx0XHRcdFx0bWVkaWFCdXR0b25zOiBmYWxzZSxcblx0XHRcdFx0XHR0aW55bWNlOiB7XG5cdFx0XHRcdFx0XHR0b29sYmFyMTogJ2JvbGQsaXRhbGljLHN0cmlrZXRocm91Z2gsYnVsbGlzdCxudW1saXN0LGFsaWdubGVmdCxhbGlnbmNlbnRlcixhbGlnbnJpZ2h0Jyxcblx0XHRcdFx0XHRcdHRvb2xiYXIyOiAnJyxcblx0XHRcdFx0XHRcdHNldHVwOiBfLmJpbmQoIHRoaXMub25fZWRpdG9yX3JlYWR5LCB0aGlzICksXG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9ICk7XG5cdFx0XHR9XG5cblx0XHRcdHRoaXMuaW5pdF9mb3JtYXR0aW5nX2VscygpO1xuXHRcdFx0dGhpcy5pbml0X3NlbGVjdHMoKTtcblxuXHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIHJlcmVuZGVyIHBvaW50cyBwZXJjZW50YWdlIHdoZW4gcXVlc3Rpb24gcG9pbnRzIGFyZSB1cGRhdGVkXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdHJlbmRlcl9wb2ludHNfcGVyY2VudGFnZTogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHRoaXMuJGVsLmZpbmQoICcubGxtcy1xdWVzdGlvbi1wb2ludHMnICkuYXR0ciggJ2RhdGEtdGlwJywgdGhpcy5tb2RlbC5nZXRfcG9pbnRzX3BlcmNlbnRhZ2UoKSApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIENsaWNrIGV2ZW50IHRvIGR1cGxpY2F0ZSBhIHF1ZXN0aW9uIHdpdGhpbiBhIHF1aXpcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgZXZlbnQgIGpzIGV2ZW50IG9iamVjdFxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRjbG9uZTogZnVuY3Rpb24oIGV2ZW50ICkge1xuXG5cdFx0XHRldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcblx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHR0aGlzLm1vZGVsLmNvbGxlY3Rpb24uYWRkKCB0aGlzLl9nZXRfcXVlc3Rpb25fY2xvbmUoIHRoaXMubW9kZWwgKSApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFJlY3Vyc2l2ZSBjbG9uZSBmdW5jdGlvbiB3aGljaCB3aWxsIGNvcnJlY3RseSBjbG9uZSBjaGlsZHJlbiBvZiBhIHF1ZXN0aW9uXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIHF1ZXN0aW9uICBxdWVzdG9uIG1vZGVsXG5cdFx0ICogQHJldHVybiAgIG9ialxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0X2dldF9xdWVzdGlvbl9jbG9uZTogZnVuY3Rpb24oIHF1ZXN0aW9uICkge1xuXG5cdFx0XHQvLyBjcmVhdGUgYSBkdXBsaWNhdGVcblx0XHRcdHZhciBjbG9uZSA9IF8uY2xvbmUoIHF1ZXN0aW9uLmF0dHJpYnV0ZXMgKTtcblxuXHRcdFx0Ly8gcmVtb3ZlIGlkICh3ZSB3YW50IHRoZSBkdXBsaWNhdGUgdG8gaGF2ZSBhIHRlbXAgaWQpXG5cdFx0XHRkZWxldGUgY2xvbmUuaWQ7XG5cblx0XHRcdGNsb25lLnBhcmVudF9pZCA9IHF1ZXN0aW9uLmdldCggJ2lkJyApO1xuXG5cdFx0XHQvLyBzZXQgdGhlIHF1ZXN0aW9uIHR5cGUgSURcblx0XHRcdGNsb25lLnF1ZXN0aW9uX3R5cGUgPSBxdWVzdGlvbi5nZXQoICdxdWVzdGlvbl90eXBlJyApLmdldCggJ2lkJyApO1xuXG5cdFx0XHQvLyBjbG9uZSB0aGUgaW1hZ2UgYXR0cmlidXRlcyBzZXBlcmF0ZWx5XG5cdFx0XHRjbG9uZS5pbWFnZSA9IF8uY2xvbmUoIHF1ZXN0aW9uLmdldCggJ2ltYWdlJyApLmF0dHJpYnV0ZXMgKTtcblxuXHRcdFx0Ly8gaWYgaXQgaGFzIGNob2ljZXMgY2xvbmUgYWxsIHRoZSBjaG9pY2VzXG5cdFx0XHRpZiAoIHF1ZXN0aW9uLmdldCggJ2Nob2ljZXMnICkgKSB7XG5cblx0XHRcdFx0Y2xvbmUuY2hvaWNlcyA9IFtdO1xuXG5cdFx0XHRcdHF1ZXN0aW9uLmdldCggJ2Nob2ljZXMnICkuZWFjaCggZnVuY3Rpb24gKCBjaG9pY2UgKSB7XG5cblx0XHRcdFx0XHR2YXIgY2hvaWNlX2Nsb25lID0gXy5jbG9uZSggY2hvaWNlLmF0dHJpYnV0ZXMgKTtcblx0XHRcdFx0XHRkZWxldGUgY2hvaWNlX2Nsb25lLmlkO1xuXHRcdFx0XHRcdGRlbGV0ZSBjaG9pY2VfY2xvbmUucXVlc3Rpb25faWQ7XG5cblx0XHRcdFx0XHRjbG9uZS5jaG9pY2VzLnB1c2goIGNob2ljZV9jbG9uZSApO1xuXG5cdFx0XHRcdH0gKTtcblxuXHRcdFx0fVxuXG5cdFx0XHRpZiAoICdncm91cCcgPT09IHF1ZXN0aW9uLmdldCggJ3F1ZXN0aW9uX3R5cGUnICkuZ2V0KCAnaWQnICkgKSB7XG5cblx0XHRcdFx0Y2xvbmUucXVlc3Rpb25zID0gW107XG5cdFx0XHRcdHF1ZXN0aW9uLmdldCggJ3F1ZXN0aW9ucycgKS5lYWNoKCBmdW5jdGlvbiggY2hpbGQgKSB7XG5cdFx0XHRcdFx0Y2xvbmUucXVlc3Rpb25zLnB1c2goIHRoaXMuX2dldF9xdWVzdGlvbl9jbG9uZSggY2hpbGQgKSApO1xuXHRcdFx0XHR9LCB0aGlzICk7XG5cblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIGNsb25lO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIENvbGxhcHNlIGEgcXVlc3Rpb24gYW5kIGhpZGUgaXQncyBzZXR0aW5nc1xuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRjb2xsYXBzZTogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHRoaXMubW9kZWwuc2V0KCAnX2V4cGFuZGVkJywgZmFsc2UgKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBEZWxldGUgdGhlIHF1ZXN0aW9uIGZyb20gYSBxdWl6IC8gcXVlc3Rpb24gZ3JvdXBcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgZXZlbnQgIGpzIGV2ZW50IG9iamVjdFxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRkZWxldGU6IGZ1bmN0aW9uKCBldmVudCApIHtcblxuXHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuXHRcdFx0aWYgKCB3aW5kb3cuY29uZmlybSggTExNUy5sMTBuLnRyYW5zbGF0ZSggJ0FyZSB5b3Ugc3VyZSB5b3Ugd2FudCB0byBkZWxldGUgdGhpcyBxdWVzdGlvbj8nICkgKSApIHtcblxuXHRcdFx0XHR0aGlzLm1vZGVsLmNvbGxlY3Rpb24ucmVtb3ZlKCB0aGlzLm1vZGVsICk7XG5cdFx0XHRcdEJhY2tib25lLnB1YlN1Yi50cmlnZ2VyKCAnbW9kZWwtdHJhc2hlZCcsIHRoaXMubW9kZWwgKTtcblxuXHRcdFx0fVxuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIENsaWNrIGV2ZW50IHRvIHJldmVhbCBhIHF1ZXN0aW9uJ3Mgc2V0dGluZ3MgJiBjaG9pY2VzXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGV4cGFuZDogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHRoaXMubW9kZWwuc2V0KCAnX2V4cGFuZGVkJywgdHJ1ZSApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFdoZW4gdG9nZ2xpbmcgbXVsdGlwbGUgY29ycmVjdCBhbnN3ZXJzICpvZmYqIHJlbW92ZSBhbGwgY29ycmVjdCBjaG9pY2VzIGV4Y2VwdCB0aGUgZmlyc3QgY29ycmVjdCBjaG9pY2UgaW4gdGhlIGxpc3Rcblx0XHQgKiBAcGFyYW0gICAgc3RyaW5nICAgdmFsICB2YWx1ZSBvZiB0aGUgcXVlc3Rpb24ncyBgbXVsdGlfY2hvaWNlYCBhdHRyIFt5ZXN8bm9dXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdG11bHRpX2Nob2ljZXNfdG9nZ2xlOiBmdW5jdGlvbiggdmFsICkge1xuXG5cdFx0XHRpZiAoICd5ZXMnID09PSB2YWwgKSB7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblxuXHRcdFx0dGhpcy5tb2RlbC5nZXQoICdjaG9pY2VzJyApLnVwZGF0ZV9jb3JyZWN0KCBfLmZpcnN0KCB0aGlzLm1vZGVsLmdldCggJ2Nob2ljZXMnICkuZ2V0X2NvcnJlY3QoKSApICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogVXBkYXRlIHRoZSBtb2RlbCdzIHBvaW50cyB3aGVuIHRoZSB2YWx1ZSBvZiB0aGUgcG9pbnRzIGlucHV0IGlzIHVwZGF0ZWRcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0dXBkYXRlX3BvaW50czogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHRoaXMubW9kZWwuc2V0KCAncG9pbnRzJywgdGhpcy4kZWwuZmluZCggJ2lucHV0W25hbWU9XCJxdWVzdGlvbl9wb2ludHNcIl0nICkudmFsKCkgKiAxICk7XG5cblx0XHR9XG5cblx0fSwgRWRpdGFibGUgKSApO1xuXG59ICk7XG5cbi8qKlxuICogUXVpeiBxdWVzdGlvbiBiYW5rIHZpZXdcbiAqIEBzaW5jZSAgICAzLjE2LjBcbiAqIEB2ZXJzaW9uICAzLjE2LjBcbiAqL1xuZGVmaW5lKCAnVmlld3MvUXVlc3Rpb25MaXN0JyxbICdWaWV3cy9RdWVzdGlvbicgXSwgZnVuY3Rpb24oIFF1ZXN0aW9uVmlldyApIHtcblxuXHRyZXR1cm4gQmFja2JvbmUuQ29sbGVjdGlvblZpZXcuZXh0ZW5kKCB7XG5cblx0XHRjbGFzc05hbWU6ICdsbG1zLXF1aXotcXVlc3Rpb25zJyxcblxuXHRcdC8qKlxuXHRcdCAqIFBhcmVudCBlbGVtZW50XG5cdFx0ICogQHR5cGUgIHtTdHJpbmd9XG5cdFx0ICovXG5cdFx0Ly8gZWw6ICcjbGxtcy1xdWl6LXF1ZXN0aW9ucycsXG5cblx0XHQvKipcblx0XHQgKiBTZWN0aW9uIG1vZGVsXG5cdFx0ICogQHR5cGUgIHtbdHlwZV19XG5cdFx0ICovXG5cdFx0bW9kZWxWaWV3OiBRdWVzdGlvblZpZXcsXG5cblx0XHQvKipcblx0XHQgKiBFbmFibGUga2V5Ym9hcmQgZXZlbnRzXG5cdFx0ICogQHR5cGUgIHtCb29sfVxuXHRcdCAqL1xuXHRcdHByb2Nlc3NLZXlFdmVudHM6IGZhbHNlLFxuXG5cdFx0LyoqXG5cdFx0ICogQXJlIHNlY3Rpb25zIHNlbGVjdGFibGU/XG5cdFx0ICogQHR5cGUgIHtCb29sfVxuXHRcdCAqL1xuXHRcdHNlbGVjdGFibGU6IGZhbHNlLFxuXG5cdFx0LyoqXG5cdFx0ICogQXJlIHNlY3Rpb25zIHNvcnRhYmxlP1xuXHRcdCAqIEB0eXBlICB7Qm9vbH1cblx0XHQgKi9cblx0XHRzb3J0YWJsZTogdHJ1ZSxcblxuXHRcdHNvcnRhYmxlT3B0aW9uczoge1xuXHRcdFx0YXhpczogZmFsc2UsXG5cdFx0XHRjb25uZWN0V2l0aDogJy5sbG1zLXF1aXotcXVlc3Rpb25zJyxcblx0XHRcdGN1cnNvcjogJ21vdmUnLFxuXHRcdFx0aGFuZGxlOiAnLmxsbXMtZGF0YS1zdGFtcCcsXG5cdFx0XHRpdGVtczogJy5sbG1zLXF1ZXN0aW9uJyxcblx0XHRcdHBsYWNlaG9sZGVyOiAnbGxtcy1xdWVzdGlvbiBsbG1zLXNvcnRhYmxlLXBsYWNlaG9sZGVyJyxcblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogSGlnaGxpZ2h0IGRyb3AgYXJlYXMgd2hlbiBkcmFnZ2luZyBzdGFydHNcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgbW9kZWwgIG1vZGVsIGJlaW5nIHNvcnRlZFxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRzb3J0YWJsZV9zdGFydDogZnVuY3Rpb24oIG1vZGVsICkge1xuXHRcdFx0dmFyIHNlbGVjdG9yID0gJ2dyb3VwJyA9PT0gbW9kZWwuZ2V0KCAncXVlc3Rpb25fdHlwZScgKS5nZXQoICdpZCcgKSA/ICcubGxtcy1lZGl0b3ItdGFiID4gLmxsbXMtcXVpei1xdWVzdGlvbnMnIDogJy5sbG1zLXF1aXotcXVlc3Rpb25zJztcblx0XHRcdCQoIHNlbGVjdG9yICkuYWRkQ2xhc3MoICdkcmFnZ2luZycgKTtcblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogUmVtb3ZlIGhpZ2hsaWdodHMgd2hlbiBkcmFnZ2luZyBzdG9wc1xuXHRcdCAqIEBwYXJhbSAgICBvYmogICBtb2RlbCAgbW9kZWwgYmVpbmcgc29ydGVkXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdHNvcnRhYmxlX3N0b3A6IGZ1bmN0aW9uKCkge1xuXHRcdFx0JCggJy5sbG1zLXF1aXotcXVlc3Rpb25zJyApLnJlbW92ZUNsYXNzKCAnZHJhZ2dpbmcnICk7XG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIE92ZXJyaWRlcyByZWNlaXZlIHRvIGVuc3VyZSB0aGF0IHF1ZXN0aW9uIGdyb3VwcyBjYW4ndCBiZSBtb3ZlZCBpbnRvIHF1ZXN0b24gZ3JvdXBzXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIGV2ZW50ICBqcyBldmVudCBvYmplY3Rcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgdWkgICAgIGpRdWVyeSBVSSBTb3J0YWJsZSB1aSBvYmplY3Rcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0X3JlY2VpdmUgOiBmdW5jdGlvbiggZXZlbnQsIHVpICkge1xuXG5cdFx0XHRldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcblxuXHRcdFx0Ly8gcHJldmVudCBtb3ZpbmcgYSBxdWVzdGlvbiBncm91cCBpbnRvIGEgcXVlc3Rpb24gZ3JvdXBcblx0XHRcdGlmICggdWkuaXRlbS5oYXNDbGFzcyggJ3F0eXBlLS1ncm91cCcgKSAmJiAkKCBldmVudC50YXJnZXQgKS5jbG9zZXN0KCAnLnF0eXBlLS1ncm91cCcgKS5sZW5ndGggKSB7O1xuXHRcdFx0XHR1aS5zZW5kZXIuc29ydGFibGUoICdjYW5jZWwnICk7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblxuXHRcdFx0dmFyIHNlbmRlckxpc3RFbCA9IHVpLnNlbmRlcjtcblx0XHRcdHZhciBzZW5kZXJDb2xsZWN0aW9uTGlzdFZpZXcgPSBzZW5kZXJMaXN0RWwuZGF0YSggXCJ2aWV3XCIgKTtcblx0XHRcdGlmKCAhIHNlbmRlckNvbGxlY3Rpb25MaXN0VmlldyB8fCAhIHNlbmRlckNvbGxlY3Rpb25MaXN0Vmlldy5jb2xsZWN0aW9uICkgcmV0dXJuO1xuXG5cdFx0XHR2YXIgbmV3SW5kZXggPSB0aGlzLl9nZXRDb250YWluZXJFbCgpLmNoaWxkcmVuKCkuaW5kZXgoIHVpLml0ZW0gKTtcblx0XHRcdHZhciBtb2RlbFJlY2VpdmVkID0gc2VuZGVyQ29sbGVjdGlvbkxpc3RWaWV3LmNvbGxlY3Rpb24uZ2V0KCB1aS5pdGVtLmF0dHIoIFwiZGF0YS1tb2RlbC1jaWRcIiApICk7XG5cdFx0XHRzZW5kZXJDb2xsZWN0aW9uTGlzdFZpZXcuY29sbGVjdGlvbi5yZW1vdmUoIG1vZGVsUmVjZWl2ZWQgKTtcblx0XHRcdHRoaXMuY29sbGVjdGlvbi5hZGQoIG1vZGVsUmVjZWl2ZWQsIHsgYXQgOiBuZXdJbmRleCB9ICk7XG5cdFx0XHRtb2RlbFJlY2VpdmVkLmNvbGxlY3Rpb24gPSB0aGlzLmNvbGxlY3Rpb247IC8vIG90aGVyd2lzZSB3aWxsIG5vdCBnZXQgcHJvcGVybHkgc2V0LCBzaW5jZSBtb2RlbFJlY2VpdmVkLmNvbGxlY3Rpb24gbWlnaHQgYWxyZWFkeSBoYXZlIGEgdmFsdWUuXG5cdFx0XHR0aGlzLnNldFNlbGVjdGVkTW9kZWwoIG1vZGVsUmVjZWl2ZWQgKTtcblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogT3ZlcnJpZGUgdG8gYWxsb3cgbWFuaXB1bGF0aW5vIG9mIHBsYWNlaG9sZGVyIGVsZW1lbnRcblx0XHQgKiBAcGFyYW0gICAge1t0eXBlXX0gICBldmVudCAgW2Rlc2NyaXB0aW9uXVxuXHRcdCAqIEBwYXJhbSAgICB7W3R5cGVdfSAgIHVpICAgICBbZGVzY3JpcHRpb25dXG5cdFx0ICogQHJldHVybiAgIHtbdHlwZV19XG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRfc29ydFN0YXJ0IDogZnVuY3Rpb24oIGV2ZW50LCB1aSApIHtcblxuXHRcdFx0dmFyIG1vZGVsQmVpbmdTb3J0ZWQgPSB0aGlzLmNvbGxlY3Rpb24uZ2V0KCB1aS5pdGVtLmF0dHIoIFwiZGF0YS1tb2RlbC1jaWRcIiApICk7XG5cblx0XHRcdHVpLnBsYWNlaG9sZGVyLmFkZENsYXNzKCAncXR5cGUtLScgKyBtb2RlbEJlaW5nU29ydGVkLmdldCggJ3F1ZXN0aW9uX3R5cGUnICkuZ2V0KCAnaWQnICkgKTtcblxuXHRcdFx0aWYoIHRoaXMuX2lzQmFja2JvbmVDb3VyaWVyQXZhaWxhYmxlKCkgKVxuXHRcdFx0XHR0aGlzLnNwYXduKCBcInNvcnRTdGFydFwiLCB7IG1vZGVsQmVpbmdTb3J0ZWQgOiBtb2RlbEJlaW5nU29ydGVkIH0gKTtcblx0XHRcdGVsc2UgdGhpcy50cmlnZ2VyKCBcInNvcnRTdGFydFwiLCBtb2RlbEJlaW5nU29ydGVkICk7XG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIE92ZXJsb2FkcyB0aGUgZnVuY3Rpb24gZnJvbSBCYWNrYm9uZS5Db2xsZWN0aW9uVmlldyBjb3JlIGJlY2F1c2UgaXQgZG9lc24ndCBzZW5kIHN0b3AgZXZlbnRzXG5cdFx0ICogaWYgbW92aW5nIGZyb20gb25lIHNvcnRhYmxlIHRvIGFub3RoZXIuLi4gOi0oXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIGV2ZW50ICBqcyBldmVudCBvYmplY3Rcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgdWkgICAgIGpRdWVyeSBVSSBvYmplY3Rcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0X3NvcnRTdG9wIDogZnVuY3Rpb24oIGV2ZW50LCB1aSApIHtcblxuXHRcdFx0ZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cblx0XHRcdHZhciBtb2RlbEJlaW5nU29ydGVkID0gdGhpcy5jb2xsZWN0aW9uLmdldCggdWkuaXRlbS5hdHRyKCAnZGF0YS1tb2RlbC1jaWQnICkgKSxcblx0XHRcdFx0bW9kZWxWaWV3Q29udGFpbmVyRWwgPSB0aGlzLl9nZXRDb250YWluZXJFbCgpLFxuXHRcdFx0XHRuZXdJbmRleCA9IG1vZGVsVmlld0NvbnRhaW5lckVsLmNoaWxkcmVuKCkuaW5kZXgoIHVpLml0ZW0gKTtcblxuXHRcdFx0aWYgKCBuZXdJbmRleCA9PSAtMSAmJiBtb2RlbEJlaW5nU29ydGVkICkge1xuXHRcdFx0XHR0aGlzLmNvbGxlY3Rpb24ucmVtb3ZlKCBtb2RlbEJlaW5nU29ydGVkICk7XG5cdFx0XHR9XG5cblx0XHRcdHRoaXMuX3Jlb3JkZXJDb2xsZWN0aW9uQmFzZWRPbkhUTUwoKTtcblx0XHRcdHRoaXMudXBkYXRlRGVwZW5kZW50Q29udHJvbHMoKTtcblxuXHRcdFx0aWYoIHRoaXMuX2lzQmFja2JvbmVDb3VyaWVyQXZhaWxhYmxlKCkgKSB7XG5cdFx0XHRcdHRoaXMuc3Bhd24oICdzb3J0U3RvcCcsIHsgbW9kZWxCZWluZ1NvcnRlZCA6IG1vZGVsQmVpbmdTb3J0ZWQsIG5ld0luZGV4IDogbmV3SW5kZXggfSApO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dGhpcy50cmlnZ2VyKCAnc29ydFN0b3AnLCBtb2RlbEJlaW5nU29ydGVkLCBuZXdJbmRleCApO1xuXHRcdFx0fVxuXG5cdFx0fSxcblxuXHR9ICk7XG5cbn0gKTtcblxuLyoqXG4gKiBTaW5nbGUgUXVpeiBWaWV3XG4gKiBAc2luY2UgICAgMy4xNi4wXG4gKiBAdmVyc2lvbiAgMy4xOS4yXG4gKi9cbmRlZmluZSggJ1ZpZXdzL1F1aXonLFtcblx0XHQnTW9kZWxzL1F1aXonLFxuXHRcdCdWaWV3cy9Qb3BvdmVyJyxcblx0XHQnVmlld3MvUG9zdFNlYXJjaCcsXG5cdFx0J1ZpZXdzL1F1ZXN0aW9uQmFuaycsXG5cdFx0J1ZpZXdzL1F1ZXN0aW9uTGlzdCcsXG5cdFx0J1ZpZXdzL1NldHRpbmdzRmllbGRzJyxcblx0XHQnVmlld3MvX0RldGFjaGFibGUnLFxuXHRcdCdWaWV3cy9fRWRpdGFibGUnLFxuXHRcdCdWaWV3cy9fU3VidmlldycsXG5cdFx0J1ZpZXdzL19UcmFzaGFibGUnXG5cdF0sIGZ1bmN0aW9uKFxuXHRcdFF1aXpNb2RlbCxcblx0XHRQb3BvdmVyLFxuXHRcdFBvc3RTZWFyY2gsXG5cdFx0UXVlc3Rpb25CYW5rLFxuXHRcdFF1ZXN0aW9uTGlzdCxcblx0XHRTZXR0aW5nc0ZpZWxkcyxcblx0XHREZXRhY2hhYmxlLFxuXHRcdEVkaXRhYmxlLFxuXHRcdFN1YnZpZXcsXG5cdFx0VHJhc2hhYmxlXG5cdCkge1xuXG5cdHJldHVybiBCYWNrYm9uZS5WaWV3LmV4dGVuZCggXy5kZWZhdWx0cygge1xuXG5cdFx0LyoqXG5cdFx0ICogQ3VycmVudCB2aWV3IHN0YXRlXG5cdFx0ICogQHR5cGUgIHtTdHJpbmd9XG5cdFx0ICovXG5cdFx0c3RhdGU6ICdkZWZhdWx0JyxcblxuXHRcdC8qKlxuXHRcdCAqIEN1cnJlbnQgU3Vidmlld3Ncblx0XHQgKiBAdHlwZSAge09iamVjdH1cblx0XHQgKi9cblx0XHR2aWV3czoge1xuXHRcdFx0c2V0dGluZ3M6IHtcblx0XHRcdFx0Y2xhc3M6IFNldHRpbmdzRmllbGRzLFxuXHRcdFx0XHRpbnN0YW5jZTogbnVsbCxcblx0XHRcdFx0c3RhdGU6ICdkZWZhdWx0Jyxcblx0XHRcdH0sXG5cdFx0XHRiYW5rOiB7XG5cdFx0XHRcdGNsYXNzOiBRdWVzdGlvbkJhbmssXG5cdFx0XHRcdGluc3RhbmNlOiBudWxsLFxuXHRcdFx0XHRzdGF0ZTogJ2RlZmF1bHQnLFxuXHRcdFx0fSxcblx0XHRcdGxpc3Q6IHtcblx0XHRcdFx0Y2xhc3M6IFF1ZXN0aW9uTGlzdCxcblx0XHRcdFx0aW5zdGFuY2U6IG51bGwsXG5cdFx0XHRcdHN0YXRlOiAnZGVmYXVsdCcsXG5cdFx0XHR9LFxuXHRcdH0sXG5cblx0XHRlbDogJyNsbG1zLWVkaXRvci1xdWl6JyxcblxuXHRcdC8qKlxuXHRcdCAqIEV2ZW50c1xuXHRcdCAqIEB0eXBlICB7T2JqZWN0fVxuXHRcdCAqL1xuXHRcdGV2ZW50czogXy5kZWZhdWx0cygge1xuXHRcdFx0J2NsaWNrICNsbG1zLWV4aXN0aW5nLXF1aXonOiAnYWRkX2V4aXN0aW5nX3F1aXpfY2xpY2snLFxuXHRcdFx0J2NsaWNrICNsbG1zLW5ldy1xdWl6JzogJ2FkZF9uZXdfcXVpeicsXG5cdFx0XHQnY2xpY2sgI2xsbXMtc2hvdy1xdWVzdGlvbi1iYW5rJzogJ3Nob3dfdG9vbHMnLFxuXHRcdFx0J2NsaWNrIC5idWxrLXRvZ2dsZSc6ICdidWxrX3RvZ2dsZScsXG5cdFx0XHQvLyAna2V5dXAgI2xsbXMtcXVlc3Rpb24tYmFuay1maWx0ZXInOiAnZmlsdGVyX3F1ZXN0aW9uX3R5cGVzJyxcblx0XHRcdC8vICdzZWFyY2ggI2xsbXMtcXVlc3Rpb24tYmFuay1maWx0ZXInOiAnZmlsdGVyX3F1ZXN0aW9uX3R5cGVzJyxcblx0XHR9LCBEZXRhY2hhYmxlLmV2ZW50cywgRWRpdGFibGUuZXZlbnRzLCBUcmFzaGFibGUuZXZlbnRzICksXG5cblx0XHQvKipcblx0XHQgKiBXcmFwcGVyIFRhZyBuYW1lXG5cdFx0ICogQHR5cGUgIHtTdHJpbmd9XG5cdFx0ICovXG5cdFx0dGFnTmFtZTogJ2RpdicsXG5cblx0XHQvKipcblx0XHQgKiBHZXQgdGhlIHVuZGVyc2NvcmUgdGVtcGxhdGVcblx0XHQgKiBAdHlwZSAge1t0eXBlXX1cblx0XHQgKi9cblx0XHR0ZW1wbGF0ZTogd3AudGVtcGxhdGUoICdsbG1zLXF1aXotdGVtcGxhdGUnICksXG5cblx0XHQvKipcblx0XHQgKiBJbml0aWFsaXphdGlvbiBjYWxsYmFjayBmdW5jIChyZW5kZXJzIHRoZSBlbGVtZW50IG9uIHNjcmVlbilcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xOS4yXG5cdFx0ICovXG5cdFx0aW5pdGlhbGl6ZTogZnVuY3Rpb24oIGRhdGEgKSB7XG5cblx0XHRcdHRoaXMubGVzc29uID0gZGF0YS5sZXNzb247XG5cblx0XHRcdC8vIGluaXRpYWxpemUgdGhlIG1vZGVsIGlmIHRoZSBxdWl6IGlzIGVuYWJsZWQgb3IgaXQncyBkaXNhYmxlZCBidXQgd2Ugc3RpbGwgaGF2ZSBkYXRhIGZvciBhIHF1aXpcblx0XHRcdGlmICggJ3llcycgPT09IHRoaXMubGVzc29uLmdldCggJ3F1aXpfZW5hYmxlZCcgKSB8fCAhIF8uaXNFbXB0eSggdGhpcy5sZXNzb24uZ2V0KCAncXVpeicgKSApICkge1xuXG5cdFx0XHRcdHRoaXMubW9kZWwgPSB0aGlzLmxlc3Nvbi5nZXQoICdxdWl6JyApO1xuXG5cdFx0XHRcdC8qKlxuXHRcdFx0XHQgKiBAdG9kbyAgdGhpcyBpcyBhIHRlcnJpbGJlIHRlcnJpYmxlIHBhdGNoXG5cdFx0XHRcdCAqICAgICAgICBJJ3ZlIHNwZW50IG5lYXJseSAzIGRheXMgdHJ5aW5nIHRvIGZpZ3VyZSBvdXQgaG93IHRvIG5vdCB1c2UgdGhpcyBsaW5lIG9mIGNvZGVcblx0XHRcdFx0ICogICAgICAgIElTU1VFIFJFUFJPRFVDVElPTjpcblx0XHRcdFx0ICogICAgICAgIE9wZW4gY291cnNlIGJ1aWxkZXJcblx0XHRcdFx0ICogICAgICAgIE9wZW4gYSBsZXNzb24gKEEpIGFuZCBhZGQgYSBxdWl6XG5cdFx0XHRcdCAqICAgICAgICBTd2l0Y2ggdG8gYSBuZXcgbGVzc29uIChCKVxuXHRcdFx0XHQgKiAgICAgICAgQWRkIGEgbmV3IHF1aXpcblx0XHRcdFx0ICogICAgICAgIFJldHVybiB0byBsZXNzb24gQSBhbmQgdGhlIHF1aXp6ZXMgcGFyZW50IHdpbGwgYmUgc2V0IHRvIExFU1NPTiBCXG5cdFx0XHRcdCAqICAgICAgICBUaGlzIHdpbGwgaGFwcGVuIGZvciAqZXZlcnkqIHF1aXogaW4gdGhlIGJ1aWxkZXIuLi5cblx0XHRcdFx0ICogICAgICAgIEFkZGluZyB0aGlzIHNldF9wYXJlbnQgb24gaW5pdCBndWFyYW50ZWVzIHRoYXQgdGhlIHF1aXp6ZXMgY29ycmVjdCBwYXJlbnQgaXMgc2V0XG5cdFx0XHRcdCAqICAgICAgICBhZnRlciBhZGRpbmcgbmV3IHF1aXp6ZXMgdG8gb3RoZXIgbGVzc29uc1xuXHRcdFx0XHQgKiAgICAgICAgaXQncyBhd2Z1bCBhbmQgaXQncyBncm9zcy4uLlxuXHRcdFx0XHQgKiAgICAgICAgSSdtIGNvbmZ1c2VkIGFuZCB0aXJlZCBhbmQgZ29pbmcgdG8gbWlzcyByZWxlYXNlIGRhdGVzIGFnYWluIGJlY2F1c2Ugb2YgaXRcblx0XHRcdFx0ICovXG5cdFx0XHRcdHRoaXMubW9kZWwuc2V0X3BhcmVudCggdGhpcy5sZXNzb24gKTtcblxuXHRcdFx0XHR0aGlzLmxpc3RlblRvKCB0aGlzLm1vZGVsLCAnY2hhbmdlOl9wb2ludHMnLCB0aGlzLnJlbmRlcl9wb2ludHMgKTtcblxuXHRcdFx0fVxuXG5cdFx0XHR0aGlzLm9uKCAnbW9kZWwtdHJhc2hlZCcsIHRoaXMub25fdHJhc2hlZCApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIENvbXBpbGVzIHRoZSB0ZW1wbGF0ZSBhbmQgcmVuZGVycyB0aGUgdmlld1xuXHRcdCAqIEByZXR1cm4gICBzZWxmIChmb3IgY2hhaW5pbmcpXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE5LjJcblx0XHQgKi9cblx0XHRyZW5kZXI6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHR0aGlzLiRlbC5odG1sKCB0aGlzLnRlbXBsYXRlKCB0aGlzLm1vZGVsICkgKTtcblxuXHRcdFx0Ly8gcmVuZGVyIHRoZSBxdWl6IGJ1aWxkZXJcblx0XHRcdGlmICggdGhpcy5tb2RlbCApIHtcblxuXHRcdFx0XHQvLyBkb24ndCBhbGxvdyBpbnRlcmFjdGlvbiB1bnRpbCBxdWVzdGlvbnMgYXJlIGxhenkgbG9hZGVkXG5cdFx0XHRcdExMTVMuU3Bpbm5lci5zdGFydCggdGhpcy4kZWwgKTtcblxuXHRcdFx0XHR0aGlzLnJlbmRlcl9zdWJ2aWV3KCAnc2V0dGluZ3MnLCB7XG5cdFx0XHRcdFx0ZWw6ICcjbGxtcy1xdWl6LXNldHRpbmdzLWZpZWxkcycsXG5cdFx0XHRcdFx0bW9kZWw6IHRoaXMubW9kZWwsXG5cdFx0XHRcdH0gKTtcblxuXHRcdFx0XHR0aGlzLmluaXRfZGF0ZXBpY2tlcnMoKTtcblx0XHRcdFx0dGhpcy5pbml0X3NlbGVjdHMoKTtcblxuXHRcdFx0XHR0aGlzLnJlbmRlcl9zdWJ2aWV3KCAnYmFuaycsIHtcblx0XHRcdFx0XHRjb2xsZWN0aW9uOiB3aW5kb3cubGxtc19idWlsZGVyLnF1ZXN0aW9ucyxcblx0XHRcdFx0fSApO1xuXG5cdFx0XHRcdHZhciBsYXN0X2dyb3VwID0gbnVsbCxcblx0XHRcdFx0XHRncm91cCA9IG51bGw7XG5cdFx0XHRcdC8vIGxldCBhbGwgdGhlIHF1ZXN0aW9uIHR5cGVzIHJlZmVyZW5jZSB0aGUgcXVpeiBmb3IgYWRkaW5nIHF1ZXN0aW9ucyBxdWlja2x5XG5cdFx0XHRcdHRoaXMuZ2V0X3N1YnZpZXcoICdiYW5rJyApLmluc3RhbmNlLnZpZXdNYW5hZ2VyLmVhY2goIGZ1bmN0aW9uKCB2aWV3ICkge1xuXG5cdFx0XHRcdFx0dmlldy5xdWl6ID0gdGhpcy5tb2RlbDtcblxuXHRcdFx0XHRcdGdyb3VwID0gdmlldy5tb2RlbC5nZXQoICdncm91cCcgKS5uYW1lO1xuXG5cdFx0XHRcdFx0aWYgKCBsYXN0X2dyb3VwICE9PSBncm91cCApIHtcblx0XHRcdFx0XHRcdGxhc3RfZ3JvdXAgPSBncm91cDtcblx0XHRcdFx0XHRcdHZpZXcuJGVsLmJlZm9yZSggJzxsaSBjbGFzcz1cImxsbXMtcXVlc3Rpb24tYmFuay1oZWFkZXJcIj48aDQ+JyArIGdyb3VwICsgJzwvaDQ+PC9saT4nICk7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdH0sIHRoaXMgKTtcblxuXHRcdFx0XHR0aGlzLm1vZGVsLmxvYWRfcXVlc3Rpb25zKCBfLmJpbmQoIGZ1bmN0aW9uKCBlcnIgKSB7XG5cblx0XHRcdFx0XHRpZiAoIGVyciApIHtcblx0XHRcdFx0XHRcdGFsZXJ0KCBMTE1TLmwxMG4udHJhbnNsYXRlKCAnQW4gZXJyb3Igb2NjdXJyZWQgd2hpbGUgdHJ5aW5nIHRvIGxvYWQgdGhlIHF1ZXN0aW9ucy4gUGxlYXNlIHJlZnJlc2ggdGhlIHBhZ2UgYW5kIHRyeSBhZ2Fpbi4nICkgKTtcblx0XHRcdFx0XHRcdHJldHVybiB0aGlzO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdExMTVMuU3Bpbm5lci5zdG9wKCB0aGlzLiRlbCApO1xuXHRcdFx0XHRcdHRoaXMucmVuZGVyX3N1YnZpZXcoICdsaXN0Jywge1xuXHRcdFx0XHRcdFx0ZWw6ICcjbGxtcy1xdWl6LXF1ZXN0aW9ucycsXG5cdFx0XHRcdFx0XHRjb2xsZWN0aW9uOiB0aGlzLm1vZGVsLmdldCggJ3F1ZXN0aW9ucycgKSxcblx0XHRcdFx0XHR9ICk7XG5cdFx0XHRcdFx0dmFyIGxpc3QgPSB0aGlzLmdldF9zdWJ2aWV3KCAnbGlzdCcgKS5pbnN0YW5jZTtcblx0XHRcdFx0XHRsaXN0LnF1aXogPSB0aGlzO1xuXHRcdFx0XHRcdGxpc3QuY29sbGVjdGlvbi5vbiggJ2FkZCcsIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdFx0bGlzdC5jb2xsZWN0aW9uLnRyaWdnZXIoICdyZW9yZGVyJyApO1xuXHRcdFx0XHRcdH0sIHRoaXMgKTtcblx0XHRcdFx0XHRsaXN0Lm9uKCAnc29ydFN0YXJ0JywgbGlzdC5zb3J0YWJsZV9zdGFydCApO1xuXHRcdFx0XHRcdGxpc3Qub24oICdzb3J0U3RvcCcsIGxpc3Quc29ydGFibGVfc3RvcCApO1xuXG5cdFx0XHRcdH0sIHRoaXMgKSApO1xuXG5cdFx0XHRcdHRoaXMubW9kZWwub24oICduZXctcXVlc3Rpb24tYWRkZWQnLCBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHR2YXIgJHF1ZXN0aW9ucyA9IHRoaXMuJGVsLmZpbmQoICcjbGxtcy1xdWl6LXF1ZXN0aW9ucycgKTtcblx0XHRcdFx0XHQkcXVlc3Rpb25zLmFuaW1hdGUoIHsgc2Nyb2xsVG9wOiAkcXVlc3Rpb25zLnByb3AoICdzY3JvbGxIZWlnaHQnICkgfSwgMjAwICk7XG5cdFx0XHRcdH0sIHRoaXMgKTtcblxuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gdGhpcztcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBPbiBxdWl6IHBvaW50cyB1cGRhdGUsIHVwZGF0ZSB0aGUgdmFsdWUgb2YgdGhlIFRvdGFsIFBvaW50cyBhcmVhIGluIHRoZSBoZWFkZXJcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgcXVpeiAgICBJbnN0YW5jZSBvZiB0aGUgcXVpeiBtb2RlbFxuXHRcdCAqIEBwYXJhbSAgICBpbnQgICBwb2ludHMgIFVwZGF0ZWQgbnVtYmVyIG9mIHBvaW50c1xuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTcuNlxuXHRcdCAqIEB2ZXJzaW9uICAzLjE3LjZcblx0XHQgKi9cblx0XHRyZW5kZXJfcG9pbnRzOiBmdW5jdGlvbiggcXVpeiwgcG9pbnRzICkge1xuXG5cdFx0XHR0aGlzLiRlbC5maW5kKCAnI2xsbXMtcXVpei10b3RhbC1wb2ludHMnICkudGV4dCggcG9pbnRzICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogQnVsayBleHBhbmQgLyBjb2xsYXBzZSBxdWVzdGlvbiBidXR0b25zXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIGV2ZW50ICBqcyBldmVudCBvYmplY3Rcblx0XHQgKiBAcmV0dXJuICAgb2JqXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRidWxrX3RvZ2dsZTogZnVuY3Rpb24oIGV2ZW50ICkge1xuXG5cdFx0XHR2YXIgZXhwYW5kZWQgPSAoICdleHBhbmQnID09PSAkKCBldmVudC50YXJnZXQgKS5hdHRyKCAnZGF0YS1hY3Rpb24nICkgKTtcblxuXHRcdFx0dGhpcy5tb2RlbC5nZXQoICdxdWVzdGlvbnMnICkuZWFjaCggZnVuY3Rpb24oIHF1ZXN0aW9uICkge1xuXHRcdFx0XHRxdWVzdGlvbi5zZXQoICdfZXhwYW5kZWQnLCBleHBhbmRlZCApO1xuXHRcdFx0fSApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIEFkZHMgYSBuZXcgcXVpeiB0byBhIGxlc3NvbiB3aGljaCBjdXJyZW50bHkgaGFzIG5vIHF1aXogYXNzb2NpYXRlZCB3bGl0aCBpdFxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRhZGRfbmV3X3F1aXo6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHR2YXIgcXVpeiA9IHRoaXMubGVzc29uLmdldCggJ3F1aXonICk7XG5cdFx0XHRpZiAoIF8uaXNFbXB0eSggcXVpeiApICkge1xuXHRcdFx0XHRxdWl6ID0gdGhpcy5sZXNzb24uYWRkX3F1aXooKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHRoaXMubGVzc29uLnNldCggJ3F1aXpfZW5hYmxlZCcsICd5ZXMnICk7XG5cdFx0XHR9XG5cblx0XHRcdHRoaXMubW9kZWwgPSBxdWl6O1xuXHRcdFx0dGhpcy5yZW5kZXIoKTtcblxuXHRcdH0sXG5cblx0XHQvLyBjb21lIGJhY2sgdG8gdGhpcyBhbmQgbWFrZSBzdXJlIGNsb25pbmcgcmVzZXRzIGFsbCB0aGUgSURzXG5cdFx0YWRkX2V4aXN0aW5nX3F1aXo6IGZ1bmN0aW9uKCBldmVudCApIHtcblxuXHRcdFx0dGhpcy5wb3N0X3NlYXJjaF9wb3BvdmVyLmhpZGUoKTtcblxuXHRcdFx0dmFyIHF1aXogPSBldmVudC5kYXRhO1xuXG5cdFx0XHRpZiAoICdjbG9uZScgPT09IGV2ZW50LmFjdGlvbiApIHtcblxuXHRcdFx0XHRkZWxldGUgcXVpei5pZDtcblxuXHRcdFx0XHRfLmVhY2goIHF1aXoucXVlc3Rpb25zLCBmdW5jdGlvbiggcXVlc3Rpb24gKSB7XG5cblx0XHRcdFx0XHRkZWxldGUgcXVlc3Rpb24ucGFyZW50X2lkO1xuXHRcdFx0XHRcdGRlbGV0ZSBxdWVzdGlvbi5pZDtcblxuXHRcdFx0XHRcdGlmICggcXVlc3Rpb24uY2hvaWNlcyApIHtcblxuXHRcdFx0XHRcdFx0Xy5lYWNoKCBxdWVzdGlvbi5jaG9pY2VzLCBmdW5jdGlvbiggY2hvaWNlICkge1xuXG5cdFx0XHRcdFx0XHRcdGRlbGV0ZSBjaG9pY2UucXVlc3Rpb25faWQ7XG5cdFx0XHRcdFx0XHRcdGRlbGV0ZSBjaG9pY2UuaWQ7XG5cblx0XHRcdFx0XHRcdH0gKTtcblxuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHR9ICk7XG5cblx0XHRcdH0gZWxzZSB7XG5cblx0XHRcdFx0cXVpei5fZm9yY2VTeW5jID0gdHJ1ZTtcblxuXHRcdFx0fVxuXG5cdFx0XHRkZWxldGUgcXVpei5sZXNzb25faWQ7XG5cblx0XHRcdHRoaXMubGVzc29uLmFkZF9xdWl6KCBxdWl6ICk7XG5cdFx0XHR0aGlzLm1vZGVsID0gdGhpcy5sZXNzb24uZ2V0KCAncXVpeicgKTtcblx0XHRcdHRoaXMucmVuZGVyKCk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogT3BlbiBhZGQgZXhpc3RpbmcgcXVpeiBwb3BvdmVyXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIGV2ZW50ICBKUyBldmVudCBvYmplY3Rcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjEyXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMTJcblx0XHQgKi9cblx0XHRhZGRfZXhpc3RpbmdfcXVpel9jbGljazogZnVuY3Rpb24oIGV2ZW50ICkge1xuXG5cdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG5cdFx0XHR0aGlzLnBvc3Rfc2VhcmNoX3BvcG92ZXIgPSBuZXcgUG9wb3Zlcigge1xuXHRcdFx0XHRlbDogJyNsbG1zLWV4aXN0aW5nLXF1aXonLFxuXHRcdFx0XHRhcmdzOiB7XG5cdFx0XHRcdFx0YmFja2Ryb3A6IHRydWUsXG5cdFx0XHRcdFx0Y2xvc2VhYmxlOiB0cnVlLFxuXHRcdFx0XHRcdGNvbnRhaW5lcjogJy53cmFwLmxpZnRlcmxtcy5sbG1zLWJ1aWxkZXInLFxuXHRcdFx0XHRcdGRpc21pc3NpYmxlOiB0cnVlLFxuXHRcdFx0XHRcdHBsYWNlbWVudDogJ2xlZnQnLFxuXHRcdFx0XHRcdHdpZHRoOiA0ODAsXG5cdFx0XHRcdFx0dGl0bGU6IExMTVMubDEwbi50cmFuc2xhdGUoICdBZGQgRXhpc3RpbmcgUXVpeicgKSxcblx0XHRcdFx0XHRjb250ZW50OiBuZXcgUG9zdFNlYXJjaCgge1xuXHRcdFx0XHRcdFx0cG9zdF90eXBlOiAnbGxtc19xdWl6Jyxcblx0XHRcdFx0XHRcdHNlYXJjaGluZ19tZXNzYWdlOiBMTE1TLmwxMG4udHJhbnNsYXRlKCAnU2VhcmNoIGZvciBleGlzdGluZyBxdWl6emVzLi4uJyApLFxuXHRcdFx0XHRcdH0gKS5yZW5kZXIoKS4kZWwsXG5cdFx0XHRcdFx0b25IaWRlOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRcdEJhY2tib25lLnB1YlN1Yi5vZmYoICdxdWl6LXNlYXJjaC1zZWxlY3QnICk7XG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0fVxuXHRcdFx0fSApO1xuXG5cdFx0XHR0aGlzLnBvc3Rfc2VhcmNoX3BvcG92ZXIuc2hvdygpO1xuXHRcdFx0QmFja2JvbmUucHViU3ViLm9uY2UoICdxdWl6LXNlYXJjaC1zZWxlY3QnLCB0aGlzLmFkZF9leGlzdGluZ19xdWl6LCB0aGlzICk7XG5cblx0XHR9LFxuXG5cdFx0Ly8gZmlsdGVyX3F1ZXN0aW9uX3R5cGVzOiBfLmRlYm91bmNlKCBmdW5jdGlvbiggZXZlbnQgKSB7XG5cblx0XHQvLyBcdHZhciB0ZXJtID0gJCggZXZlbnQudGFyZ2V0ICkudmFsKCk7XG5cblx0XHQvLyBcdHRoaXMuUXVlc3Rpb25CYW5rVmlldy52aWV3TWFuYWdlci5lYWNoKCBmdW5jdGlvbiggdmlldyApIHtcblx0XHQvLyBcdFx0aWYgKCAhIHRlcm0gKSB7XG5cdFx0Ly8gXHRcdFx0dmlldy5jbGVhcl9maWx0ZXIoKTtcblx0XHQvLyBcdFx0fSBlbHNlIHtcblx0XHQvLyBcdFx0XHR2aWV3LmZpbHRlciggdGVybSApO1xuXHRcdC8vIFx0XHR9XG5cdFx0Ly8gXHR9ICk7XG5cblxuXHRcdC8vIH0sIDMwMCApLFxuXG5cdFx0LyoqXG5cdFx0ICogQ2FsbGJhY2sgZnVuY3Rpb24gd2hlbiB0aGUgcXVpeiBoYXMgYmVlbiBkZWxldGVkXG5cdFx0ICogQHBhcmFtICAgIG9iamVjdCAgIHF1aXogIFF1aXogTW9kZWxcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjZcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi42XG5cdFx0ICovXG5cdFx0b25fdHJhc2hlZDogZnVuY3Rpb24oIHF1aXogKSB7XG5cblx0XHRcdHRoaXMubGVzc29uLnNldCggJ3F1aXpfZW5hYmxlZCcsICdubycgKTtcblx0XHRcdHRoaXMubGVzc29uLnNldCggJ3F1aXonLCAnJyApO1xuXG5cdFx0XHRkZWxldGUgdGhpcy5tb2RlbDtcblxuXHRcdFx0dGhpcy5yZW5kZXIoKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBcIkFkZCBRdWVzdGlvblwiIGJ1dHRvbiBjbGljayBldmVudFxuXHRcdCAqIENyZWF0ZXMgYSBwb3BvdmVyIHdpdGggcXVlc3Rpb24gdHlwZSBsaXN0IGludGVyZmFjZVxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRzaG93X3Rvb2xzOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0Ly8gY3JlYXRlIHBvcG92ZXJcblx0XHRcdHZhciBwb3AgPSBuZXcgUG9wb3Zlcigge1xuXHRcdFx0XHRlbDogJyNsbG1zLXNob3ctcXVlc3Rpb24tYmFuaycsXG5cdFx0XHRcdGFyZ3M6IHtcblx0XHRcdFx0XHRiYWNrZHJvcDogdHJ1ZSxcblx0XHRcdFx0XHRjbG9zZWFibGU6IHRydWUsXG5cdFx0XHRcdFx0Y29udGFpbmVyOiAnI2xsbXMtYnVpbGRlci1zaWRlYmFyJyxcblx0XHRcdFx0XHRkaXNtaXNzaWJsZTogdHJ1ZSxcblx0XHRcdFx0XHRwbGFjZW1lbnQ6ICd0b3AtbGVmdCcsXG5cdFx0XHRcdFx0d2lkdGg6ICdjYWxjKCAxMDAlIC0gNDBweCApJyxcblx0XHRcdFx0XHR0aXRsZTogTExNUy5sMTBuLnRyYW5zbGF0ZSggJ0FkZCBhIFF1ZXN0aW9uJyApLFxuXHRcdFx0XHRcdHVybDogJyNsbG1zLXF1aXotdG9vbHMnLFxuXHRcdFx0XHR9XG5cdFx0XHR9ICk7XG5cblx0XHRcdC8vIHNob3cgaXRcblx0XHRcdHBvcC5zaG93KCk7XG5cblx0XHRcdC8vIGlmIGEgcXVlc3Rpb24gaXMgYWRkZWQsIGhpZGUgdGhlIHBvcG92ZXJcblx0XHRcdHRoaXMubW9kZWwub24oICduZXctcXVlc3Rpb24tYWRkZWQnLCBmdW5jdGlvbigpIHtcblx0XHRcdFx0cG9wLmhpZGUoKTtcblx0XHRcdH0gKTtcblxuXHRcdH0sXG5cblx0XHRnZXRfcXVlc3Rpb25fbGlzdDogZnVuY3Rpb24oIG9wdGlvbnMgKSB7XG5cdFx0XHRyZXR1cm4gbmV3IFF1ZXN0aW9uTGlzdCggb3B0aW9ucyApO1xuXHRcdH1cblxuXHR9LCBEZXRhY2hhYmxlLCBFZGl0YWJsZSwgU3VidmlldywgVHJhc2hhYmxlLCBTZXR0aW5nc0ZpZWxkcyApICk7XG5cbn0gKTtcblxuLyoqXG4gKiBTaW5nbGUgQXNzaWdubWVudCBWaWV3XG4gKiBAc2luY2UgICAgMy4xNy4wXG4gKiBAdmVyc2lvbiAgMy4xNy43XG4gKi9cbmRlZmluZSggJ1ZpZXdzL0Fzc2lnbm1lbnQnLFtcblx0XHQnVmlld3MvUG9wb3ZlcicsXG5cdFx0J1ZpZXdzL1Bvc3RTZWFyY2gnLFxuXHRcdCdWaWV3cy9fRGV0YWNoYWJsZScsXG5cdFx0J1ZpZXdzL19FZGl0YWJsZScsXG5cdFx0J1ZpZXdzL19UcmFzaGFibGUnLFxuXHRcdCdWaWV3cy9fU3VidmlldycsXG5cdFx0J1ZpZXdzL1NldHRpbmdzRmllbGRzJ1xuXHRdLCBmdW5jdGlvbihcblx0XHRQb3BvdmVyLFxuXHRcdFBvc3RTZWFyY2gsXG5cdFx0RGV0YWNoYWJsZSxcblx0XHRFZGl0YWJsZSxcblx0XHRUcmFzaGFibGUsXG5cdFx0U3Vidmlldyxcblx0XHRTZXR0aW5nc0ZpZWxkc1xuXHQpIHtcblxuXHRyZXR1cm4gQmFja2JvbmUuVmlldy5leHRlbmQoIF8uZGVmYXVsdHMoIHtcblxuXHRcdC8qKlxuXHRcdCAqIEN1cnJlbnQgdmlldyBzdGF0ZVxuXHRcdCAqIEB0eXBlICB7U3RyaW5nfVxuXHRcdCAqL1xuXHRcdHN0YXRlOiAnZGVmYXVsdCcsXG5cblx0XHQvKipcblx0XHQgKiBDdXJyZW50IFN1YnZpZXdzXG5cdFx0ICogQHR5cGUgIHtPYmplY3R9XG5cdFx0ICovXG5cdFx0dmlld3M6IHtcblx0XHRcdHNldHRpbmdzOiB7XG5cdFx0XHRcdGNsYXNzOiBTZXR0aW5nc0ZpZWxkcyxcblx0XHRcdFx0aW5zdGFuY2U6IG51bGwsXG5cdFx0XHRcdHN0YXRlOiAnZGVmYXVsdCcsXG5cdFx0XHR9LFxuXHRcdH0sXG5cblx0XHRlbDogJyNsbG1zLWVkaXRvci1hc3NpZ25tZW50JyxcblxuXHRcdC8qKlxuXHRcdCAqIERPTSBFdmVudHNcblx0XHQgKiBAcmV0dXJuICAgb2JqXG5cdFx0ICogQHNpbmNlICAgIDMuMTcuMVxuXHRcdCAqIEB2ZXJzaW9uICAzLjE3LjFcblx0XHQgKi9cblx0XHRldmVudHM6IGZ1bmN0aW9uKCkge1xuXHRcdFx0dmFyIGFkZG9uX2V2ZW50cyA9IHRoaXMuaXNfYWRkb25fYXZhaWxhYmxlKCkgPyB3aW5kb3cubGxtc19idWlsZGVyLmFzc2lnbm1lbnRzLmdldF92aWV3X2V2ZW50cygpIDoge307XG5cdFx0XHRyZXR1cm4gXy5kZWZhdWx0cygge1xuXHRcdFx0XHQnY2xpY2sgI2xsbXMtZXhpc3RpbmctYXNzaWdubWVudCc6ICdhZGRfZXhpc3RpbmdfYXNzaWdubWVudF9jbGljaycsXG5cdFx0XHRcdCdjbGljayAjbGxtcy1uZXctYXNzaWdubWVudCc6ICdhZGRfbmV3X2Fzc2lnbm1lbnQnLFxuXHRcdFx0fSwgRGV0YWNoYWJsZS5ldmVudHMsIEVkaXRhYmxlLmV2ZW50cywgVHJhc2hhYmxlLmV2ZW50cywgYWRkb25fZXZlbnRzICk7XG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFdyYXBwZXIgVGFnIG5hbWVcblx0XHQgKiBAdHlwZSAge1N0cmluZ31cblx0XHQgKi9cblx0XHR0YWdOYW1lOiAnZGl2JyxcblxuXHRcdC8qKlxuXHRcdCAqIEdldCB0aGUgdW5kZXJzY29yZSB0ZW1wbGF0ZVxuXHRcdCAqIEB0eXBlICB7W3R5cGVdfVxuXHRcdCAqL1xuXHRcdHRlbXBsYXRlOiB3cC50ZW1wbGF0ZSggJ2xsbXMtYXNzaWdubWVudC10ZW1wbGF0ZScgKSxcblxuXHRcdC8qKlxuXHRcdCAqIEluaXRpYWxpemF0aW9uIGNhbGxiYWNrIGZ1bmMgKHJlbmRlcnMgdGhlIGVsZW1lbnQgb24gc2NyZWVuKVxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTcuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE3LjJcblx0XHQgKi9cblx0XHRpbml0aWFsaXplOiBmdW5jdGlvbiggZGF0YSApIHtcblxuXHRcdFx0dGhpcy5sZXNzb24gPSBkYXRhLmxlc3NvbjtcblxuXHRcdFx0Ly8gaW5pdGlhbGl6ZSB0aGUgbW9kZWwgaWYgdGhlIGFzc2lnbm1lbnQgaXMgZW5hYmxlZCBvciBpdCdzIGRpc2FibGVkIGJ1dCB3ZSBzdGlsbCBoYXZlIGRhdGEgZm9yIGEgYXNzaWdubWVudFxuXHRcdFx0aWYgKCAneWVzJyA9PT0gdGhpcy5sZXNzb24uZ2V0KCAnYXNzaWdubWVudF9lbmFibGVkJyApIHx8ICEgXy5pc0VtcHR5KCB0aGlzLmxlc3Nvbi5nZXQoICdhc3NpZ25tZW50JyApICkgKSB7XG5cblx0XHRcdFx0dGhpcy5tb2RlbCA9IHRoaXMubGVzc29uLmdldCggJ2Fzc2lnbm1lbnQnICk7XG5cblx0XHRcdFx0LyoqXG5cdFx0XHRcdCAqIEB0b2RvICB0aGlzIGlzIGEgdGVycmlsYmUgdGVycmlibGUgcGF0Y2hcblx0XHRcdFx0ICogICAgICAgIEkndmUgc3BlbnQgbmVhcmx5IDMgZGF5cyB0cnlpbmcgdG8gZmlndXJlIG91dCBob3cgdG8gbm90IHVzZSB0aGlzIGxpbmUgb2YgY29kZVxuXHRcdFx0XHQgKiAgICAgICAgSVNTVUUgUkVQUk9EVUNUSU9OOlxuXHRcdFx0XHQgKiAgICAgICAgT3BlbiBjb3Vyc2UgYnVpbGRlclxuXHRcdFx0XHQgKiAgICAgICAgT3BlbiBhIGxlc3NvbiAoQSkgYW5kIGFkZCBhIGFzc2lnbm1lbnRcblx0XHRcdFx0ICogICAgICAgIFN3aXRjaCB0byBhIG5ldyBsZXNzb24gKEIpXG5cdFx0XHRcdCAqICAgICAgICBBZGQgYSBuZXcgYXNzaWdubWVudFxuXHRcdFx0XHQgKiAgICAgICAgUmV0dXJuIHRvIGxlc3NvbiBBIGFuZCB0aGUgYXNzaWdubWVudCdzIHBhcmVudCB3aWxsIGJlIHNldCB0byBMRVNTT04gQlxuXHRcdFx0XHQgKiAgICAgICAgVGhpcyB3aWxsIGhhcHBlbiBmb3IgKmV2ZXJ5KiBhc3NpZ25tZW50IGluIHRoZSBidWlsZGVyLi4uXG5cdFx0XHRcdCAqICAgICAgICBBZGRpbmcgdGhpcyBzZXRfcGFyZW50IG9uIGluaXQgZ3VhcmFudGVlcyB0aGF0IHRoZSBhc3NpZ25tZW50J3MgY29ycmVjdCBwYXJlbnQgaXMgc2V0XG5cdFx0XHRcdCAqICAgICAgICBhZnRlciBhZGRpbmcgbmV3IGFzc2lnbm1lbnQncyB0byBvdGhlciBsZXNzb25zXG5cdFx0XHRcdCAqICAgICAgICBpdCdzIGF3ZnVsIGFuZCBpdCdzIGdyb3NzLi4uXG5cdFx0XHRcdCAqICAgICAgICBJJ20gY29uZnVzZWQgYW5kIHRpcmVkIGFuZCBnb2luZyB0byBtaXNzIHJlbGVhc2UgZGF0ZXMgYWdhaW4gYmVjYXVzZSBvZiBpdFxuXHRcdFx0XHQgKi9cblx0XHRcdFx0dGhpcy5tb2RlbC5zZXRfcGFyZW50KCB0aGlzLmxlc3NvbiApO1xuXG5cdFx0XHR9XG5cblx0XHRcdHRoaXMub24oICdtb2RlbC10cmFzaGVkJywgdGhpcy5vbl90cmFzaGVkICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogQ29tcGlsZXMgdGhlIHRlbXBsYXRlIGFuZCByZW5kZXJzIHRoZSB2aWV3XG5cdFx0ICogQHJldHVybiAgIHNlbGYgKGZvciBjaGFpbmluZylcblx0XHQgKiBAc2luY2UgICAgMy4xNy4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTcuN1xuXHRcdCAqL1xuXHRcdHJlbmRlcjogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHRoaXMuJGVsLmh0bWwoIHRoaXMudGVtcGxhdGUoIHRoaXMubW9kZWwgKSApO1xuXG5cdFx0XHRpZiAoIHRoaXMubW9kZWwgJiYgdGhpcy5pc19hZGRvbl9hdmFpbGFibGUoKSApIHtcblxuXHRcdFx0XHR0aGlzLnN0b3BMaXN0ZW5pbmcoIHRoaXMubW9kZWwsICdjaGFuZ2U6YXNzaWdubWVudF90eXBlJywgdGhpcy5yZW5kZXIgKTtcblxuXHRcdFx0XHR0aGlzLnJlbmRlcl9zdWJ2aWV3KCAnc2V0dGluZ3MnLCB7XG5cdFx0XHRcdFx0ZWw6ICcjbGxtcy1hc3NpZ25tZW50LXNldHRpbmdzLWZpZWxkcycsXG5cdFx0XHRcdFx0bW9kZWw6IHRoaXMubW9kZWwsXG5cdFx0XHRcdH0gKTtcblxuXHRcdFx0XHQvLyB0aGlzLmluaXRfZGF0ZXBpY2tlcnMoKTtcblx0XHRcdFx0dGhpcy5pbml0X3NlbGVjdHMoKTtcblxuXHRcdFx0XHR3aW5kb3cubGxtc19idWlsZGVyLmFzc2lnbm1lbnRzLnJlbmRlcl9lZGl0b3IoIHRoaXMgKTtcblxuXHRcdFx0XHR0aGlzLmxpc3RlblRvKCB0aGlzLm1vZGVsLCAnY2hhbmdlOmFzc2lnbm1lbnRfdHlwZScsIHRoaXMucmVuZGVyICk7XG5cblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIHRoaXM7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogQWRkcyBhIG5ldyBhc3NpZ25tZW50IHRvIGEgbGVzc29uIHdoaWNoIGN1cnJlbnRseSBoYXMgbm8gYXNzaWdubWVudCBhc3NvY2lhdGVkIHdsaXRoIGl0XG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNy4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTcuMFxuXHRcdCAqL1xuXHRcdGFkZF9uZXdfYXNzaWdubWVudDogZnVuY3Rpb24oKSB7XG5cblx0XHRcdGlmICggdGhpcy5pc19hZGRvbl9hdmFpbGFibGUoKSApIHtcblxuXHRcdFx0XHR0aGlzLm1vZGVsID0gd2luZG93LmxsbXNfYnVpbGRlci5hc3NpZ25tZW50cy5nZXRfYXNzaWdubWVudCgge1xuXHRcdFx0XHRcdC8qIHRyYW5zbGF0b3JzOiAlMSRzID0gYXNzb2NpYXRlZCBsZXNzb24gdGl0bGUgKi9cblx0XHRcdFx0XHR0aXRsZTogTExNUy5sMTBuLnJlcGxhY2UoICclMSRzIEFzc2lnbm1lbnQnLCB7XG5cdFx0XHRcdFx0XHQnJTEkcyc6IHRoaXMubGVzc29uLmdldCggJ3RpdGxlJyApLFxuXHRcdFx0XHRcdH0gKSxcblx0XHRcdFx0XHRsZXNzb25faWQ6IHRoaXMubGVzc29uLmdldCggJ2lkJyApLFxuXHRcdFx0XHR9ICk7XG5cblx0XHRcdFx0dGhpcy5sZXNzb24uc2V0KCAnYXNzaWdubWVudF9lbmFibGVkJywgJ3llcycgKTtcblx0XHRcdFx0dGhpcy5sZXNzb24uc2V0KCAnYXNzaWdubWVudCcsIHRoaXMubW9kZWwgKTtcblxuXHRcdFx0XHR0aGlzLnJlbmRlcigpO1xuXG5cdFx0XHR9IGVsc2Uge1xuXG5cdFx0XHRcdHRoaXMuc2hvd19hZF9wb3BvdmVyKCAnI2xsbXMtbmV3LWFzc2lnbm1lbnQnICk7XG5cblx0XHRcdH1cblxuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFdoZW4gYW4gYXNzaWdubWVudCBpcyBzZWxlY3RlZCBmcm9tIHRoZSBwb3N0IHNlbGVjdCBwb3BvdmVyXG5cdFx0ICogaW5zdGFudGlhdGUgaXQgYW5kIGFkZCBpdCB0byB0aGUgY3VycmVudCBsZXNzb25cblx0XHQgKiBAcGFyYW0gICAgb2JqZWN0ICAgZXZlbnQgIGRhdGEgZnJvbSB0aGUgc2VsZWN0MiBzZWxlY3QgZXZlbnRcblx0XHQgKiBAc2luY2UgICAgMy4xNy4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTcuMFxuXHRcdCAqL1xuXHRcdGFkZF9leGlzdGluZ19hc3NpZ25tZW50OiBmdW5jdGlvbiggZXZlbnQgKSB7XG5cblx0XHRcdHRoaXMucG9zdF9zZWFyY2hfcG9wb3Zlci5oaWRlKCk7XG5cblx0XHRcdHZhciBhc3NpZ25tZW50ID0gZXZlbnQuZGF0YTtcblxuXHRcdFx0aWYgKCAnY2xvbmUnID09PSBldmVudC5hY3Rpb24gKSB7XG5cblx0XHRcdFx0ZGVsZXRlIGFzc2lnbm1lbnQuaWQ7XG5cblx0XHRcdH0gZWxzZSB7XG5cblx0XHRcdFx0YXNzaWdubWVudC5fZm9yY2VTeW5jID0gdHJ1ZTtcblxuXHRcdFx0fVxuXG5cdFx0XHRhc3NpZ25tZW50Lmxlc3Nvbl9pZCA9IHRoaXMubGVzc29uLmdldCggJ2lkJyApXG5cblx0XHRcdGFzc2lnbm1lbnQgPSB3aW5kb3cubGxtc19idWlsZGVyLmNvbnN0cnVjdC5nZXRfbW9kZWwoICdBc3NpZ25tZW50JywgYXNzaWdubWVudCApO1xuXG5cdFx0XHR0aGlzLmxlc3Nvbi5zZXQoICdhc3NpZ25tZW50X2VuYWJsZWQnLCAneWVzJyApO1xuXHRcdFx0dGhpcy5sZXNzb24uc2V0KCAnYXNzaWdubWVudCcsIGFzc2lnbm1lbnQgKTtcblx0XHRcdHRoaXMubW9kZWwgPSBhc3NpZ25tZW50O1xuXG5cdFx0XHR0aGlzLnJlbmRlcigpO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIE9wZW4gYWRkIGV4aXN0aW5nIGFzc2lnbm1lbnQgcG9wb3ZlclxuXHRcdCAqIEBwYXJhbSAgICBvYmogICBldmVudCAgSlMgZXZlbnQgb2JqZWN0XG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNy4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTcuMFxuXHRcdCAqL1xuXHRcdGFkZF9leGlzdGluZ19hc3NpZ25tZW50X2NsaWNrOiBmdW5jdGlvbiggZXZlbnQgKSB7XG5cblx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cblx0XHRcdGlmICggdGhpcy5pc19hZGRvbl9hdmFpbGFibGUoKSApIHtcblxuXHRcdFx0XHR0aGlzLnBvc3Rfc2VhcmNoX3BvcG92ZXIgPSBuZXcgUG9wb3Zlcigge1xuXHRcdFx0XHRcdGVsOiAnI2xsbXMtZXhpc3RpbmctYXNzaWdubWVudCcsXG5cdFx0XHRcdFx0YXJnczoge1xuXHRcdFx0XHRcdFx0YmFja2Ryb3A6IHRydWUsXG5cdFx0XHRcdFx0XHRjbG9zZWFibGU6IHRydWUsXG5cdFx0XHRcdFx0XHRjb250YWluZXI6ICcud3JhcC5saWZ0ZXJsbXMubGxtcy1idWlsZGVyJyxcblx0XHRcdFx0XHRcdGRpc21pc3NpYmxlOiB0cnVlLFxuXHRcdFx0XHRcdFx0cGxhY2VtZW50OiAnbGVmdCcsXG5cdFx0XHRcdFx0XHR3aWR0aDogNDgwLFxuXHRcdFx0XHRcdFx0dGl0bGU6IExMTVMubDEwbi50cmFuc2xhdGUoICdBZGQgRXhpc3RpbmcgQXNzaWdubWVudCcgKSxcblx0XHRcdFx0XHRcdGNvbnRlbnQ6IG5ldyBQb3N0U2VhcmNoKCB7XG5cdFx0XHRcdFx0XHRcdHBvc3RfdHlwZTogJ2xsbXNfYXNzaWdubWVudCcsXG5cdFx0XHRcdFx0XHRcdHNlYXJjaGluZ19tZXNzYWdlOiBMTE1TLmwxMG4udHJhbnNsYXRlKCAnU2VhcmNoIGZvciBleGlzdGluZyBhc3NpZ25tZW50cy4uLicgKSxcblx0XHRcdFx0XHRcdH0gKS5yZW5kZXIoKS4kZWwsXG5cdFx0XHRcdFx0XHRvbkhpZGU6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdFx0XHRCYWNrYm9uZS5wdWJTdWIub2ZmKCAnYXNzaWdubWVudC1zZWFyY2gtc2VsZWN0JyApO1xuXHRcdFx0XHRcdFx0fSxcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0gKTtcblxuXHRcdFx0XHR0aGlzLnBvc3Rfc2VhcmNoX3BvcG92ZXIuc2hvdygpO1xuXHRcdFx0XHRCYWNrYm9uZS5wdWJTdWIub25jZSggJ2Fzc2lnbm1lbnQtc2VhcmNoLXNlbGVjdCcsIHRoaXMuYWRkX2V4aXN0aW5nX2Fzc2lnbm1lbnQsIHRoaXMgKTtcblxuXHRcdFx0fSBlbHNlIHtcblxuXHRcdFx0XHR0aGlzLnNob3dfYWRfcG9wb3ZlciggJyNsbG1zLWV4aXN0aW5nLWFzc2lnbm1lbnQnICk7XG5cblx0XHRcdH1cblxuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIERldGVybWluZSBpZiBBc3NpZ25tZW50cyBhZGRvbiBpcyBhdmFpbGFibGUgdG8gdXNlXG5cdFx0ICogQHJldHVybiAgIHtCb29sZWFufVxuXHRcdCAqIEBzaW5jZSAgICAzLjE3LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNy4wXG5cdFx0ICovXG5cdFx0aXNfYWRkb25fYXZhaWxhYmxlOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0cmV0dXJuICggd2luZG93LmxsbXNfYnVpbGRlci5hc3NpZ25tZW50cyApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIENhbGxlZCB3aGVuIGFzc2lnbm1lbnQgaXMgdHJhc2hlZFxuXHRcdCAqIEBwYXJhbSAgICBvYmogICBhc3NpZ25tZW50ICBBc3NpZ25tZW50IG1vZGVsXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNy4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTcuMFxuXHRcdCAqL1xuXHRcdG9uX3RyYXNoZWQ6IGZ1bmN0aW9uKCBhc3NpZ25tZW50ICkge1xuXG5cdFx0XHR0aGlzLmxlc3Nvbi5zZXQoICdhc3NpZ25tZW50X2VuYWJsZWQnLCAnbm8nICk7XG5cdFx0XHR0aGlzLmxlc3Nvbi5zZXQoICdhc3NpZ25tZW50JywgJycgKTtcblxuXHRcdFx0ZGVsZXRlIHRoaXMubW9kZWw7XG5cblx0XHRcdHRoaXMucmVuZGVyKCk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogU2hvd3MgYSBkaXJ0eSBkaXJ0eSBhZCBwb3BvZXZlciBmb3IgYWR2YW5jZWQgYXNzaWdubWVudHNcblx0XHQgKiBAcGFyYW0gICAgc3RyaW5nICAgZWwgIGpRdWVyeSBzZWxlY3RvciBzdHJpbmdcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE3LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNy4wXG5cdFx0ICovXG5cdFx0c2hvd19hZF9wb3BvdmVyOiBmdW5jdGlvbiggZWwgKSB7XG5cblx0XHRcdHZhciBoMyA9IExMTVMubDEwbi50cmFuc2xhdGUoICdHZXQgWW91ciBTdHVkZW50cyBUYWtpbmcgQWN0aW9uJyApLFxuXHRcdFx0XHRwID0gJ0dyZWF0IGxlYXJuaW5nIGNvbnRlbnQgaXMgb25seSBoYWxmIG9mIHRlYWNoaW5nIG9ubGluZS4gV2hlbiB5b3VyIGxlYXJuZXJzIGZ1bGx5IGVuZ2FnZSwgdGhleSB3aWxsIHRha2UgeW91ciBjb250ZW50IGFuZCBtb3ZlIGludG8gYWN0aW9uLiBSZW1vdmUgYmFycmllcnMgZm9yIHlvdXIgbGVhcm5lcnMgYnkgdGVsbGluZyB0aGVtIHdoYXQgdG8gZG8gdG8gYXBwbHkgd2hhdCB0aGV5IGp1c3QgbGVhcm5lZC4gQ3JlYXRlIGdyYWRlZCBhc3NpZ25tZW50cyBvciBzaW1wbHkgZ2l2ZSB0aGVtIGEgY2hlY2tsaXN0IG9mIGFjdGlvbiBpdGVtcyB0byBjb21wbGV0ZSBiZWZvcmUgbW92aW5nIG9uLicsXG5cdFx0XHRcdGJ0biA9IExMTVMubDEwbi50cmFuc2xhdGUoICdHZXQgQXNzaWdubWVudHMgTm93IScgKSxcblx0XHRcdFx0dXJsID0gJ2h0dHBzOi8vbGlmdGVybG1zLmNvbS9wcm9kdWN0L2xpZnRlcmxtcy1hc3NpZ25tZW50cz91dG1fc291cmNlPUxpZnRlckxNUyUyMFBsdWdpbiZ1dG1fbWVkaXVtPUFzc2lnbm1lbnQlMjBCdWlsZGVyJTIwQnV0dG9uJnV0bV9jYW1wYWlnbj1Bc3NpZ25tZW50JTIwQWRkb24lMjBVcHNlbGwmdXRtX2NvbnRlbnQ9My4xNy4wJztcblxuXHRcdFx0dGhpcy5hZF9wb3BvdmVyID0gbmV3IFBvcG92ZXIoIHtcblx0XHRcdFx0ZWw6IGVsLFxuXHRcdFx0XHRhcmdzOiB7XG5cdFx0XHRcdFx0YmFja2Ryb3A6IHRydWUsXG5cdFx0XHRcdFx0Y2xvc2VhYmxlOiB0cnVlLFxuXHRcdFx0XHRcdGNvbnRhaW5lcjogJy53cmFwLmxpZnRlcmxtcy5sbG1zLWJ1aWxkZXInLFxuXHRcdFx0XHRcdGRpc21pc3NpYmxlOiB0cnVlLFxuXHRcdFx0XHRcdC8vIHBsYWNlbWVudDogJ2xlZnQnLFxuXHRcdFx0XHRcdHdpZHRoOiAzODAsXG5cdFx0XHRcdFx0dGl0bGU6IExMTVMubDEwbi50cmFuc2xhdGUoICdVbmxvY2sgTGlmdGVyTE1TIEFzc2lnbm1lbnRzJyApLFxuXHRcdFx0XHRcdGNvbnRlbnQ6ICc8aDM+JyArIGgzICsgJzwvaDM+PHA+JyArIHAgKyAnPC9wPjxicj48cD48YSBjbGFzcz1cImxsbXMtYnV0dG9uLXByaW1hcnlcIiBocmVmPVwiJyArIHVybCArICdcIiB0YXJnZXQ9XCJfYmxhbmtcIj4nICsgYnRuICsgJzwvYT48L3A+J1xuXHRcdFx0XHR9XG5cdFx0XHR9ICk7XG5cblx0XHRcdHRoaXMuYWRfcG9wb3Zlci5zaG93KCk7XG5cblx0XHR9LFxuXG5cdH0sIERldGFjaGFibGUsIEVkaXRhYmxlLCBUcmFzaGFibGUsIFN1YnZpZXcsIFNldHRpbmdzRmllbGRzICkgKTtcblxufSApO1xuXG4vKipcbiAqIFNpZGViYXIgRWRpdG9yIFZpZXdcbiAqIEBzaW5jZSAgICAzLjE2LjBcbiAqIEB2ZXJzaW9uICAzLjE3LjBcbiAqL1xuZGVmaW5lKCAnVmlld3MvRWRpdG9yJyxbXG5cdFx0J1ZpZXdzL0xlc3NvbkVkaXRvcicsXG5cdFx0J1ZpZXdzL1F1aXonLFxuXHRcdCdWaWV3cy9Bc3NpZ25tZW50Jyxcblx0XHQnVmlld3MvX1N1YnZpZXcnXG5cdF0sIGZ1bmN0aW9uKFxuXHRcdExlc3NvbkVkaXRvcixcblx0XHRRdWl6LFxuXHRcdEFzc2lnbm1lbnQsXG5cdFx0U3Vidmlld1xuXHQpIHtcblxuXHRyZXR1cm4gQmFja2JvbmUuVmlldy5leHRlbmQoIF8uZGVmYXVsdHMoIHtcblxuXHRcdC8qKlxuXHRcdCAqIEN1cnJlbnQgdmlldyBzdGF0ZVxuXHRcdCAqIEB0eXBlICB7U3RyaW5nfVxuXHRcdCAqL1xuXHRcdHN0YXRlOiAnbGVzc29uJywgLy8gW2xlc3NvbnxxdWl6XVxuXG5cdFx0LyoqXG5cdFx0ICogQ3VycmVudCBTdWJ2aWV3c1xuXHRcdCAqIEB0eXBlICB7T2JqZWN0fVxuXHRcdCAqL1xuXHRcdHZpZXdzOiB7XG5cdFx0XHRsZXNzb246IHtcblx0XHRcdFx0Y2xhc3M6IExlc3NvbkVkaXRvcixcblx0XHRcdFx0aW5zdGFuY2U6IG51bGwsXG5cdFx0XHRcdHN0YXRlOiAnbGVzc29uJyxcblx0XHRcdH0sXG5cdFx0XHRhc3NpZ25tZW50OiB7XG5cdFx0XHRcdGNsYXNzOiBBc3NpZ25tZW50LFxuXHRcdFx0XHRpbnN0YW5jZTogbnVsbCxcblx0XHRcdFx0c3RhdGU6ICdhc3NpZ25tZW50Jyxcblx0XHRcdH0sXG5cdFx0XHRxdWl6OiB7XG5cdFx0XHRcdGNsYXNzOiBRdWl6LFxuXHRcdFx0XHRpbnN0YW5jZTogbnVsbCxcblx0XHRcdFx0c3RhdGU6ICdxdWl6Jyxcblx0XHRcdH0sXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIEhUTUwgZWxlbWVudCBzZWxlY3RvclxuXHRcdCAqIEB0eXBlICB7U3RyaW5nfVxuXHRcdCAqL1xuXHRcdGVsOiAnI2xsbXMtZWRpdG9yJyxcblxuXHRcdGV2ZW50czoge1xuXHRcdFx0J2NsaWNrIC5sbG1zLWVkaXRvci1uYXYgYVtocmVmPVwiI2xsbXMtZWRpdG9yLWNsb3NlXCJdJzogJ2Nsb3NlX2VkaXRvcicsXG5cdFx0XHQnY2xpY2sgLmxsbXMtZWRpdG9yLW5hdiBhOm5vdChbaHJlZj1cIiNsbG1zLWVkaXRvci1jbG9zZVwiXSknOiAnc3dpdGNoX3RhYicsXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFdyYXBwZXIgVGFnIG5hbWVcblx0XHQgKiBAdHlwZSAge1N0cmluZ31cblx0XHQgKi9cblx0XHR0YWdOYW1lOiAnZGl2JyxcblxuXHRcdC8qKlxuXHRcdCAqIEdldCB0aGUgdW5kZXJzY29yZSB0ZW1wbGF0ZVxuXHRcdCAqIEB0eXBlICB7W3R5cGVdfVxuXHRcdCAqL1xuXHRcdHRlbXBsYXRlOiB3cC50ZW1wbGF0ZSggJ2xsbXMtZWRpdG9yLXRlbXBsYXRlJyApLFxuXG5cdFx0LyoqXG5cdFx0ICogSW5pdGlhbGl6YXRpb24gY2FsbGJhY2sgZnVuYyAocmVuZGVycyB0aGUgZWxlbWVudCBvbiBzY3JlZW4pXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGluaXRpYWxpemU6IGZ1bmN0aW9uKCBkYXRhICkge1xuXG5cdFx0XHR0aGlzLlNpZGViYXJWaWV3ID0gZGF0YS5TaWRlYmFyVmlldztcblx0XHRcdGlmICggZGF0YS50YWIgKSB7XG5cdFx0XHRcdHRoaXMuc3RhdGUgPSBkYXRhLnRhYjtcblx0XHRcdH1cblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBDb21waWxlcyB0aGUgdGVtcGxhdGUgYW5kIHJlbmRlcnMgdGhlIHZpZXdcblx0XHQgKiBAcmV0dXJuICAgc2VsZiAoZm9yIGNoYWluaW5nKVxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0cmVuZGVyOiBmdW5jdGlvbiggdmlld19kYXRhICkge1xuXG5cdFx0XHR2aWV3X2RhdGEgPSB2aWV3X2RhdGEgfHwge307XG5cblx0XHRcdHRoaXMuJGVsLmh0bWwoIHRoaXMudGVtcGxhdGUoIHRoaXMgKSApO1xuXG5cdFx0XHR0aGlzLnJlbmRlcl9zdWJ2aWV3cyggXy5leHRlbmQoIHZpZXdfZGF0YSwge1xuXHRcdFx0XHRsZXNzb246IHRoaXMubW9kZWwsXG5cdFx0XHR9ICkgKTtcblxuXHRcdFx0cmV0dXJuIHRoaXM7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogQ2xpY2sgZXZlbnQgZm9yIGNsb3NlIHNpZGViYXIgZWRpdG9yIGJ1dHRvblxuXHRcdCAqIFNlbmRzIGV2ZW50IHRvIG1haW4gU2lkZWJhclZpZXcgdG8gdHJpZ2dlciBlZGl0b3IgY2xvc2luZyBldmVudHNcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgZXZlbnQgIGpzIGV2ZW50IG9ialxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRjbG9zZV9lZGl0b3I6IGZ1bmN0aW9uKCBldmVudCApIHtcblxuXHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdEJhY2tib25lLnB1YlN1Yi50cmlnZ2VyKCAnc2lkZWJhci1lZGl0b3ItY2xvc2UnICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogQ2xpY2sgZXZlbnQgZm9yIHN3aXRjaGluZyB0YWJzIGluIHRoZSBlZGl0b3IgbmF2aWdhdGlvblxuXHRcdCAqIEBwYXJhbSAgICBvYmplY3QgIGV2ZW50ICBqcyBldmVudCBvYmplY3Rcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0c3dpdGNoX3RhYjogZnVuY3Rpb24oIGV2ZW50ICkge1xuXG5cdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG5cdFx0XHR2YXIgJGJ0biA9ICQoIGV2ZW50LnRhcmdldCApLFxuXHRcdFx0XHR2aWV3ID0gJGJ0bi5hdHRyKCAnZGF0YS12aWV3JyApLFxuXHRcdFx0XHQkdGFiID0gdGhpcy4kZWwuZmluZCggJGJ0bi5hdHRyKCAnaHJlZicgKSApO1xuXG5cdFx0XHR0aGlzLnNldF9zdGF0ZSggdmlldyApLnJlbmRlcigpO1xuXG5cdFx0XHQvLyBCYWNrYm9uZS5wdWJTdWIudHJpZ2dlciggJ2VkaXRvci10YWItYWN0aXZhdGVkJywgJGJ0bi5hdHRyKCAnaHJlZicgKS5zdWJzdHJpbmcoIDEgKSApO1xuXG5cdFx0fSxcblxuXHR9LCBTdWJ2aWV3ICkgKTtcblxufSApO1xuXG4vKipcbiAqIFNpZGViYXIgRWxlbWVudHMgVmlld1xuICogQHNpbmNlICAgIDMuMTYuMFxuICogQHZlcnNpb24gIDMuMTYuMTJcbiAqL1xuZGVmaW5lKCAnVmlld3MvRWxlbWVudHMnLFsgJ01vZGVscy9TZWN0aW9uJywgJ1ZpZXdzL1NlY3Rpb24nLCAnTW9kZWxzL0xlc3NvbicsICdWaWV3cy9MZXNzb24nLCAnVmlld3MvUG9wb3ZlcicsICdWaWV3cy9Qb3N0U2VhcmNoJyBdLCBmdW5jdGlvbiggU2VjdGlvbiwgU2VjdGlvblZpZXcsIExlc3NvbiwgTGVzc29uVmlldywgUG9wb3ZlciwgTGVzc29uU2VhcmNoICkge1xuXG5cdHJldHVybiBCYWNrYm9uZS5WaWV3LmV4dGVuZCgge1xuXG5cdFx0LyoqXG5cdFx0ICogSFRNTCBlbGVtZW50IHNlbGVjdG9yXG5cdFx0ICogQHR5cGUgIHtTdHJpbmd9XG5cdFx0ICovXG5cdFx0ZWw6ICcjbGxtcy1lbGVtZW50cycsXG5cblx0XHRldmVudHM6IHtcblx0XHRcdCdjbGljayAjbGxtcy1uZXctc2VjdGlvbic6ICdhZGRfbmV3X3NlY3Rpb24nLFxuXHRcdFx0J2NsaWNrICNsbG1zLW5ldy1sZXNzb24nOiAnYWRkX25ld19sZXNzb24nLFxuXHRcdFx0J2NsaWNrICNsbG1zLWV4aXN0aW5nLWxlc3Nvbic6ICdhZGRfZXhpc3RpbmdfbGVzc29uJyxcblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogV3JhcHBlciBUYWcgbmFtZVxuXHRcdCAqIEB0eXBlICB7U3RyaW5nfVxuXHRcdCAqL1xuXHRcdHRhZ05hbWU6ICdkaXYnLFxuXG5cdFx0LyoqXG5cdFx0ICogR2V0IHRoZSB1bmRlcnNjb3JlIHRlbXBsYXRlXG5cdFx0ICogQHR5cGUgIHtbdHlwZV19XG5cdFx0ICovXG5cdFx0dGVtcGxhdGU6IHdwLnRlbXBsYXRlKCAnbGxtcy1lbGVtZW50cy10ZW1wbGF0ZScgKSxcblxuXHRcdC8qKlxuXHRcdCAqIEluaXRpYWxpemF0aW9uIGNhbGxiYWNrIGZ1bmMgKHJlbmRlcnMgdGhlIGVsZW1lbnQgb24gc2NyZWVuKVxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRpbml0aWFsaXplOiBmdW5jdGlvbiggZGF0YSApIHtcblxuXHRcdFx0Ly8gc2F2ZSBhIHJlZmVyZW5jZSB0byB0aGUgbWFpbiBDb3Vyc2Ugdmlld1xuXHRcdFx0dGhpcy5TaWRlYmFyVmlldyA9IGRhdGEuU2lkZWJhclZpZXc7XG5cblx0XHRcdC8vIHdhdGNoIGNvdXJzZSBzZWN0aW9ucyBhbmQgZW5hYmxlL2Rpc2FibGUgbGVzc29uIGJ1dHRvbnMgY29uZGl0aW9uYWxseVxuXHRcdFx0dGhpcy5saXN0ZW5UbyggdGhpcy5TaWRlYmFyVmlldy5Db3Vyc2VWaWV3Lm1vZGVsLmdldCggJ3NlY3Rpb25zJyApLCAnYWRkJywgdGhpcy5tYXliZV9kaXNhYmxlX2J1dHRvbnMgKTtcblx0XHRcdHRoaXMubGlzdGVuVG8oIHRoaXMuU2lkZWJhclZpZXcuQ291cnNlVmlldy5tb2RlbC5nZXQoICdzZWN0aW9ucycgKSwgJ3JlbW92ZScsIHRoaXMubWF5YmVfZGlzYWJsZV9idXR0b25zICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogQ29tcGlsZXMgdGhlIHRlbXBsYXRlIGFuZCByZW5kZXJzIHRoZSB2aWV3XG5cdFx0ICogQHJldHVybiAgIHNlbGYgKGZvciBjaGFpbmluZylcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdHJlbmRlcjogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHRoaXMuJGVsLmh0bWwoIHRoaXMudGVtcGxhdGUoKSApO1xuXHRcdFx0dGhpcy5kcmFnZ2FibGUoKTtcblx0XHRcdHRoaXMubWF5YmVfZGlzYWJsZV9idXR0b25zKCk7XG5cblx0XHRcdHJldHVybiB0aGlzO1xuXHRcdH0sXG5cblx0XHRkcmFnZ2FibGU6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHQkKCAnI2xsbXMtbmV3LXNlY3Rpb24nICkuZHJhZ2dhYmxlKCB7XG5cdFx0XHRcdGFwcGVuZFRvOiAnI2xsbXMtc2VjdGlvbnMnLFxuXHRcdFx0XHRjYW5jZWw6IGZhbHNlLFxuXHRcdFx0XHRjb25uZWN0VG9Tb3J0YWJsZTogJy5sbG1zLXNlY3Rpb25zJyxcblx0XHRcdFx0aGVscGVyOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRyZXR1cm4gbmV3IFNlY3Rpb25WaWV3KCB7IG1vZGVsOiBuZXcgU2VjdGlvbigpIH0gKS5yZW5kZXIoKS4kZWw7XG5cdFx0XHRcdH0sXG5cdFx0XHRcdHN0YXJ0OiBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHQkKCAnLmxsbXMtc2VjdGlvbnMnICkuYWRkQ2xhc3MoICdkcmFnZ2luZycgKTtcblx0XHRcdFx0fSxcblx0XHRcdFx0c3RvcDogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0JCggJy5sbG1zLXNlY3Rpb25zJyApLnJlbW92ZUNsYXNzKCAnZHJhZ2dpbmcnICk7XG5cdFx0XHRcdH0sXG5cdFx0XHR9ICk7XG5cblx0XHRcdCQoICcjbGxtcy1uZXctbGVzc29uJyApLmRyYWdnYWJsZSgge1xuXHRcdFx0XHQvLyBhcHBlbmRUbzogJyNsbG1zLXNlY3Rpb25zIC5sbG1zLXNlY3Rpb246Zmlyc3QtY2hpbGQgLmxsbXMtbGVzc29ucycsXG5cdFx0XHRcdGFwcGVuZFRvOiAnI2xsbXMtc2VjdGlvbnMnLFxuXHRcdFx0XHRjYW5jZWw6IGZhbHNlLFxuXHRcdFx0XHRjb25uZWN0VG9Tb3J0YWJsZTogJy5sbG1zLWxlc3NvbnMnLFxuXHRcdFx0XHRoZWxwZXI6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdHJldHVybiBuZXcgTGVzc29uVmlldyggeyBtb2RlbDogbmV3IExlc3NvbigpIH0gKS5yZW5kZXIoKS4kZWw7XG5cdFx0XHRcdH0sXG5cdFx0XHRcdHN0YXJ0OiBmdW5jdGlvbigpIHtcblxuXHRcdFx0XHRcdCQoICcubGxtcy1sZXNzb25zJyApLmFkZENsYXNzKCAnZHJhZ2dpbmcnICk7XG5cblx0XHRcdFx0fSxcblx0XHRcdFx0c3RvcDogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0JCggJy5sbG1zLWxlc3NvbnMnICkucmVtb3ZlQ2xhc3MoICdkcmFnZ2luZycgKTtcblx0XHRcdFx0XHQkKCAnLmRyYWctZXhwYW5kZWQnICkucmVtb3ZlQ2xhc3MoICcuZHJhZy1leHBhbmRlZCcgKTtcblx0XHRcdFx0fSxcblx0XHRcdH0gKTtcblxuXHRcdH0sXG5cblx0XHRhZGRfbmV3X3NlY3Rpb246IGZ1bmN0aW9uKCBldmVudCApIHtcblxuXHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdEJhY2tib25lLnB1YlN1Yi50cmlnZ2VyKCAnYWRkLW5ldy1zZWN0aW9uJyApO1xuXHRcdH0sXG5cblx0XHRhZGRfbmV3X2xlc3NvbjogZnVuY3Rpb24oIGV2ZW50ICkge1xuXHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdEJhY2tib25lLnB1YlN1Yi50cmlnZ2VyKCAnYWRkLW5ldy1sZXNzb24nICk7XG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFNob3cgdGhlIHBvcG92ZXIgdG8gYWRkIGFuIGV4aXN0aW5nIGxlc3NvbnNcblx0XHQgKiBAcGFyYW0gICAgb2JqZWN0ICAgZXZlbnQgIEpTIEV2ZW50IE9CamVjdFxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMTJcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4xMlxuXHRcdCAqL1xuXHRcdGFkZF9leGlzdGluZ19sZXNzb246IGZ1bmN0aW9uKCBldmVudCApIHtcblxuXHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuXHRcdFx0dmFyIHBvcCA9IG5ldyBQb3BvdmVyKCB7XG5cdFx0XHRcdGVsOiAnI2xsbXMtZXhpc3RpbmctbGVzc29uJyxcblx0XHRcdFx0YXJnczoge1xuXHRcdFx0XHRcdGJhY2tkcm9wOiB0cnVlLFxuXHRcdFx0XHRcdGNsb3NlYWJsZTogdHJ1ZSxcblx0XHRcdFx0XHRjb250YWluZXI6ICcud3JhcC5saWZ0ZXJsbXMubGxtcy1idWlsZGVyJyxcblx0XHRcdFx0XHRkaXNtaXNzaWJsZTogdHJ1ZSxcblx0XHRcdFx0XHRwbGFjZW1lbnQ6ICdsZWZ0Jyxcblx0XHRcdFx0XHR3aWR0aDogNDgwLFxuXHRcdFx0XHRcdHRpdGxlOiBMTE1TLmwxMG4udHJhbnNsYXRlKCAnQWRkIEV4aXN0aW5nIExlc3NvbicgKSxcblx0XHRcdFx0XHRjb250ZW50OiBuZXcgTGVzc29uU2VhcmNoKCB7XG5cdFx0XHRcdFx0XHRwb3N0X3R5cGU6ICdsZXNzb24nLFxuXHRcdFx0XHRcdFx0c2VhcmNoaW5nX21lc3NhZ2U6IExMTVMubDEwbi50cmFuc2xhdGUoICdTZWFyY2ggZm9yIGV4aXN0aW5nIGxlc3NvbnMuLi4nICksXG5cdFx0XHRcdFx0fSApLnJlbmRlcigpLiRlbCxcblx0XHRcdFx0fVxuXHRcdFx0fSApO1xuXG5cdFx0XHRwb3Auc2hvdygpO1xuXHRcdFx0QmFja2JvbmUucHViU3ViLm9uKCAnbGVzc29uLXNlYXJjaC1zZWxlY3QnLCBmdW5jdGlvbigpIHtcblx0XHRcdFx0cG9wLmhpZGUoKVxuXHRcdFx0fSApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIERpc2FibGVzIGxlc3NvbiBhZGQgYnV0dG9ucyBpZiBubyBzZWN0aW9ucyBhcmUgYXZhaWxhYmxlIHRvIGFkZCBhIGxlc3NvbiB0b1xuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRtYXliZV9kaXNhYmxlX2J1dHRvbnM6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHR2YXIgJGVscyA9ICQoICcjbGxtcy1uZXctbGVzc29uLCAjbGxtcy1leGlzdGluZy1sZXNzb24nICk7XG5cblx0XHRcdGlmICggISB0aGlzLlNpZGViYXJWaWV3LkNvdXJzZVZpZXcubW9kZWwuZ2V0KCAnc2VjdGlvbnMnICkubGVuZ3RoICkge1xuXHRcdFx0XHQkZWxzLmF0dHIoICdkaXNhYmxlZCcsICdkaXNhYmxlZCcgKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdCRlbHMucmVtb3ZlQXR0ciggJ2Rpc2FibGVkJyApO1xuXHRcdFx0fVxuXG5cdFx0fSxcblxuXHR9ICk7XG5cbn0gKTtcblxuLyoqXG4gKiBTaWRlYmFyIFV0aWxpdGllcyBWaWV3XG4gKiBAc2luY2UgICAgMy4xNi4wXG4gKiBAdmVyc2lvbiAgMy4xNi4wXG4gKi9cbmRlZmluZSggJ1ZpZXdzL1V0aWxpdGllcycsW10sIGZ1bmN0aW9uKCkge1xuXG5cdHJldHVybiBCYWNrYm9uZS5WaWV3LmV4dGVuZCgge1xuXG5cdFx0LyoqXG5cdFx0ICogSFRNTCBlbGVtZW50IHNlbGVjdG9yXG5cdFx0ICogQHR5cGUgIHtTdHJpbmd9XG5cdFx0ICovXG5cdFx0ZWw6ICcjbGxtcy11dGlsaXRpZXMnLFxuXG5cdFx0ZXZlbnRzOiB7XG5cdFx0XHQnY2xpY2sgI2xsbXMtY29sbGFwc2UtYWxsJzogJ2NvbGxhcHNlX2FsbCcsXG5cdFx0XHQnY2xpY2sgI2xsbXMtZXhwYW5kLWFsbCc6ICdleHBhbmRfYWxsJ1xuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBXcmFwcGVyIFRhZyBuYW1lXG5cdFx0ICogQHR5cGUgIHtTdHJpbmd9XG5cdFx0ICovXG5cdFx0dGFnTmFtZTogJ2RpdicsXG5cblx0XHQvKipcblx0XHQgKiBHZXQgdGhlIHVuZGVyc2NvcmUgdGVtcGxhdGVcblx0XHQgKiBAdHlwZSAge1t0eXBlXX1cblx0XHQgKi9cblx0XHR0ZW1wbGF0ZTogd3AudGVtcGxhdGUoICdsbG1zLXV0aWxpdGllcy10ZW1wbGF0ZScgKSxcblxuXHRcdC8qKlxuXHRcdCAqIEluaXRpYWxpemF0aW9uIGNhbGxiYWNrIGZ1bmMgKHJlbmRlcnMgdGhlIGVsZW1lbnQgb24gc2NyZWVuKVxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRpbml0aWFsaXplOiBmdW5jdGlvbigpIHtcblxuXHRcdFx0Ly8gdGhpcy5yZW5kZXIoKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBDb21waWxlcyB0aGUgdGVtcGxhdGUgYW5kIHJlbmRlcnMgdGhlIHZpZXdcblx0XHQgKiBAcmV0dXJuICAgc2VsZiAoZm9yIGNoYWluaW5nKVxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0cmVuZGVyOiBmdW5jdGlvbigpIHtcblx0XHRcdHRoaXMuJGVsLmh0bWwoIHRoaXMudGVtcGxhdGUoKSApO1xuXHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIENvbGxhcHNlIGFsbCBzZWN0aW9uc1xuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRjb2xsYXBzZV9hbGw6IGZ1bmN0aW9uKCBldmVudCApIHtcblx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHRCYWNrYm9uZS5wdWJTdWIudHJpZ2dlciggJ2NvbGxhcHNlLWFsbCcgKTtcblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogRXhwYW5kIGFsbCBzZWN0aW9uc1xuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRleHBhbmRfYWxsOiBmdW5jdGlvbiggZXZlbnQgKSB7XG5cdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0QmFja2JvbmUucHViU3ViLnRyaWdnZXIoICdleHBhbmQtYWxsJyApO1xuXHRcdH0sXG5cblx0fSApO1xuXG59ICk7XG5cbi8qKlxuICogTWFpbiBzaWRlYmFyIHZpZXdcbiAqIEBzaW5jZSAgICAzLjE2LjBcbiAqIEB2ZXJzaW9uICAzLjE2LjdcbiAqL1xuZGVmaW5lKCAnVmlld3MvU2lkZWJhcicsW1xuXHRcdCdWaWV3cy9FZGl0b3InLFxuXHRcdCdWaWV3cy9FbGVtZW50cycsXG5cdFx0J1ZpZXdzL1V0aWxpdGllcycsXG5cdFx0J1ZpZXdzL19TdWJ2aWV3J1xuXHRdLCBmdW5jdGlvbihcblx0XHRFZGl0b3IsXG5cdFx0RWxlbWVudHMsXG5cdFx0VXRpbGl0aWVzLFxuXHRcdFN1YnZpZXdcblx0KSB7XG5cblx0cmV0dXJuIEJhY2tib25lLlZpZXcuZXh0ZW5kKCBfLmRlZmF1bHRzKCB7XG5cblx0XHQvKipcblx0XHQgKiBDdXJyZW50IGJ1aWxkZXIgc3RhdGVcblx0XHQgKiBAdHlwZSAge1N0cmluZ31cblx0XHQgKi9cblx0XHRzdGF0ZTogJ2J1aWxkZXInLCAvLyBbYnVpbGRlcnxlZGl0b3JdXG5cblx0XHQvKipcblx0XHQgKiBDdXJyZW50IFN1YnZpZXdzXG5cdFx0ICogQHR5cGUgIHtPYmplY3R9XG5cdFx0ICovXG5cdFx0dmlld3M6IHtcblx0XHRcdGVsZW1lbnRzOiB7XG5cdFx0XHRcdGNsYXNzOiBFbGVtZW50cyxcblx0XHRcdFx0aW5zdGFuY2U6IG51bGwsXG5cdFx0XHRcdHN0YXRlOiAnYnVpbGRlcicsXG5cdFx0XHR9LFxuXHRcdFx0dXRpbGl0aWVzOiB7XG5cdFx0XHRcdGNsYXNzOiBVdGlsaXRpZXMsXG5cdFx0XHRcdGluc3RhbmNlOiBudWxsLFxuXHRcdFx0XHRzdGF0ZTogJ2J1aWxkZXInLFxuXHRcdFx0fSxcblx0XHRcdGVkaXRvcjoge1xuXHRcdFx0XHRjbGFzczogRWRpdG9yLFxuXHRcdFx0XHRpbnN0YW5jZTogbnVsbCxcblx0XHRcdFx0c3RhdGU6ICdlZGl0b3InLFxuXHRcdFx0fSxcblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogSFRNTCBlbGVtZW50IHNlbGVjdG9yXG5cdFx0ICogQHR5cGUgIHtTdHJpbmd9XG5cdFx0ICovXG5cdFx0ZWw6ICcjbGxtcy1idWlsZGVyLXNpZGViYXInLFxuXG5cdFx0LyoqXG5cdFx0ICogRE9NIGV2ZW50c1xuXHRcdCAqIEB0eXBlICB7T2JqZWN0fVxuXHRcdCAqL1xuXHRcdGV2ZW50czoge1xuXHRcdFx0J2NsaWNrICNsbG1zLXNhdmUtYnV0dG9uJzogJ3NhdmVfbm93Jyxcblx0XHRcdCdjbGljayAjbGxtcy1leGl0LWJ1dHRvbic6ICdleGl0X25vdycsXG5cdFx0XHQnY2xpY2sgLmxsbXMtYnVpbGRlci1lcnJvcic6ICdjbGVhcl9lcnJvcnMnLFxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBXcmFwcGVyIFRhZyBuYW1lXG5cdFx0ICogQHR5cGUgIHtTdHJpbmd9XG5cdFx0ICovXG5cdFx0dGFnTmFtZTogJ2FzaWRlJyxcblxuXHRcdC8qKlxuXHRcdCAqIEdldCB0aGUgdW5kZXJzY29yZSB0ZW1wbGF0ZVxuXHRcdCAqIEB0eXBlICB7W3R5cGVdfVxuXHRcdCAqL1xuXHRcdHRlbXBsYXRlOiB3cC50ZW1wbGF0ZSggJ2xsbXMtc2lkZWJhci10ZW1wbGF0ZScgKSxcblxuXHRcdC8qKlxuXHRcdCAqIEluaXRpYWxpemF0aW9uIGNhbGxiYWNrIGZ1bmMgKHJlbmRlcnMgdGhlIGVsZW1lbnQgb24gc2NyZWVuKVxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRpbml0aWFsaXplOiBmdW5jdGlvbiggZGF0YSApIHtcblxuXHRcdFx0Ly8gc2F2ZSBhIHJlZmVyZW5jZSB0byB0aGUgbWFpbiBDb3Vyc2Ugdmlld1xuXHRcdFx0dGhpcy5Db3Vyc2VWaWV3ID0gZGF0YS5Db3Vyc2VWaWV3O1xuXG5cdFx0XHR0aGlzLnJlbmRlcigpO1xuXG5cdFx0XHRCYWNrYm9uZS5wdWJTdWIub24oICdjdXJyZW50LXNhdmUtc3RhdHVzJywgdGhpcy5jaGFuZ2VzX21hZGUsIHRoaXMgKTtcblxuXHRcdFx0QmFja2JvbmUucHViU3ViLm9uKCAnaGVhcnRiZWF0LXNlbmQnLCB0aGlzLmhlYXJ0YmVhdF9zZW5kLCB0aGlzICk7XG5cdFx0XHRCYWNrYm9uZS5wdWJTdWIub24oICdoZWFydGJlYXQtdGljaycsIHRoaXMuaGVhcnRiZWF0X3RpY2ssIHRoaXMgKTtcblxuXHRcdFx0QmFja2JvbmUucHViU3ViLm9uKCAnbGVzc29uLXNlbGVjdGVkJywgdGhpcy5vbl9sZXNzb25fc2VsZWN0LCB0aGlzICk7XG5cdFx0XHRCYWNrYm9uZS5wdWJTdWIub24oICdzaWRlYmFyLWVkaXRvci1jbG9zZScsIHRoaXMub25fZWRpdG9yX2Nsb3NlLCB0aGlzICk7XG5cblx0XHRcdHRoaXMuJHNhdmVCdXR0b24gPSAkKCAnI2xsbXMtc2F2ZS1idXR0b24nICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogQ29tcGlsZXMgdGhlIHRlbXBsYXRlIGFuZCByZW5kZXJzIHRoZSB2aWV3XG5cdFx0ICogQHJldHVybiAgIHNlbGYgKGZvciBjaGFpbmluZylcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdHJlbmRlcjogZnVuY3Rpb24oIHZpZXdfZGF0YSApIHtcblxuXHRcdFx0dmlld19kYXRhID0gdmlld19kYXRhIHx8IHt9O1xuXG5cdFx0XHR0aGlzLiRlbC5odG1sKCB0aGlzLnRlbXBsYXRlKCkgKTtcblxuXHRcdFx0dGhpcy5yZW5kZXJfc3Vidmlld3MoIF8uZXh0ZW5kKCB2aWV3X2RhdGEsIHtcblx0XHRcdFx0U2lkZWJhclZpZXc6IHRoaXMsXG5cdFx0XHR9ICkgKTtcblxuXHRcdFx0dmFyICRlbCA9ICQoICcud3JhcC5saWZ0ZXJsbXMubGxtcy1idWlsZGVyJyApO1xuXHRcdFx0aWYgKCAnYnVpbGRlcicgPT09IHRoaXMuc3RhdGUgKSB7XG5cdFx0XHRcdCRlbC5yZW1vdmVDbGFzcyggJ2VkaXRvci1hY3RpdmUnICk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQkZWwuYWRkQ2xhc3MoICdlZGl0b3ItYWN0aXZlJyApO1xuXHRcdFx0fVxuXG5cdFx0XHR0aGlzLiRzYXZlQnV0dG9uID0gdGhpcy4kZWwuZmluZCggJyNsbG1zLXNhdmUtYnV0dG9uJyApO1xuXG5cdFx0XHRyZXR1cm4gdGhpcztcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBBZGRzIGVycm9yIG1lc3NhZ2UgZWxlbWVudFxuXHRcdCAqIEBwYXJhbSAgICB7W3R5cGVdfSAgICRlcnIgIFtkZXNjcmlwdGlvbl1cblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGFkZF9lcnJvcjogZnVuY3Rpb24oICRlcnIgKSB7XG5cblx0XHRcdHRoaXMuJGVsLmZpbmQoICcubGxtcy1idWlsZGVyLXNhdmUnICkucHJlcGVuZCggJGVyciApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIENsZWFyIGFueSBleGlzdGluZyBlcnJvciBtZXNzYWdlIGVsZW1lbnRzXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGNsZWFyX2Vycm9yczogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHRoaXMuJGVsLmZpbmQoICcubGxtcy1idWlsZGVyLXNhdmUgLmxsbXMtYnVpbGRlci1lcnJvcicgKS5yZW1vdmUoKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBVcGRhdGUgc2F2ZSBzdGF0dXMgYnV0dG9uIHdoZW4gY2hhbmdlcyBhcmUgZGV0ZWN0ZWRcblx0XHQgKiBydW5zIG9uIGFuIGludGVydmFsIHRvIGNoZWNrIHN0YXR1cyBvZiBjb3Vyc2UgcmVndWxhcmx5IGZvciB1bnNhdmVkIGNoYW5nZXNcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgc3luYyAgaW5zdGFuY2Ugb2YgdGhlIHN5bmMgY29udHJvbGxlclxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRjaGFuZ2VzX21hZGU6IGZ1bmN0aW9uKCBzeW5jICkge1xuXG5cdFx0XHQvLyBpZiBhIHNhdmUgaXMgY3VycmVudGx5IHJ1bm5pbmcsIGRvbid0IGRvIGFueXRoaW5nXG5cdFx0XHRpZiAoIHN5bmMuc2F2aW5nICkge1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cblx0XHRcdGlmICggc3luYy5oYXNfdW5zYXZlZF9jaGFuZ2VzICkge1xuXG5cdFx0XHRcdHRoaXMuJHNhdmVCdXR0b24uYXR0ciggJ2RhdGEtc3RhdHVzJywgJ3Vuc2F2ZWQnICk7XG5cdFx0XHRcdHRoaXMuJHNhdmVCdXR0b24ucmVtb3ZlQXR0ciggJ2Rpc2FibGVkJyApO1xuXG5cdFx0XHR9IGVsc2Uge1xuXG5cdFx0XHRcdHRoaXMuJHNhdmVCdXR0b24uYXR0ciggJ2RhdGEtc3RhdHVzJywgJ3NhdmVkJyApO1xuXHRcdFx0XHR0aGlzLiRzYXZlQnV0dG9uLmF0dHIoICdkaXNhYmxlZCcsICdkaXNhYmxlZCcgKTtcblxuXHRcdFx0fVxuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIEV4aXQgdGhlIGJ1aWxkZXIgYW5kIHJldHVybiB0byB0aGUgV1AgQ291cnNlIEVkaXRvclxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuN1xuXHRcdCAqIEB2ZXJzaW9uICAzLjE2Ljdcblx0XHQgKi9cblx0XHRleGl0X25vdzogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHdpbmRvdy5sb2NhdGlvbi5ocmVmID0gd2luZG93LmxsbXNfYnVpbGRlci5Db3Vyc2VNb2RlbC5nZXRfZWRpdF9wb3N0X2xpbmsoKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBUcmlnZ2VyZWQgd2hlbiBhIGhlYXJ0YmVhdCBzZW5kIGV2ZW50IHN0YXJ0cyBjb250YWluaW5nIGJ1aWxkZXIgaW5mb3JtYXRpb25cblx0XHQgKiBAcGFyYW0gICAgb2JqICAgc3luYyAgaW5zdGFuY2Ugb2YgdGhlIHN5bmMgY29udHJvbGxlclxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRoZWFydGJlYXRfc2VuZDogZnVuY3Rpb24oIHN5bmMgKSB7XG5cblx0XHRcdGlmICggc3luYy5zYXZpbmcgKSB7XG5cdFx0XHRcdExMTVMuU3Bpbm5lci5zdGFydCggdGhpcy4kc2F2ZUJ1dHRvbi5maW5kKCAnaScgKSwgJ3NtYWxsJyApO1xuXHRcdFx0XHR0aGlzLiRzYXZlQnV0dG9uLmF0dHIoIHtcblx0XHRcdFx0XHQnZGF0YS1zdGF0dXMnOiAnc2F2aW5nJyxcblx0XHRcdFx0XHRkaXNhYmxlZDogJ2Rpc2FibGVkJyxcblx0XHRcdFx0fSApO1xuXHRcdFx0fVxuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFRyaWdnZXJlZCB3aGVuIGEgaGVhcnRiZWF0IHRpY2sgY29tcGxldGVzIGFuZCB1cGRhdGVzIHNhdmUgc3RhdHVzIG9yIGFwcGVuZHMgZXJyb3JzXG5cdFx0ICogQHBhcmFtICAgIG9iaiAgIHN5bmMgIGluc3RhbmNlIG9mIHRoZSBzeW5jIGNvbnRyb2xsZXJcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgZGF0YSAgdXBkYXRlZCBkYXRhXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGhlYXJ0YmVhdF90aWNrOiBmdW5jdGlvbiggc3luYywgZGF0YSApIHtcblxuXHRcdFx0aWYgKCAhIHN5bmMuc2F2aW5nICkge1xuXG5cdFx0XHRcdHZhciBzdGF0dXMgPSAnc2F2ZWQnO1xuXG5cdFx0XHRcdHRoaXMuY2xlYXJfZXJyb3JzKCk7XG5cblx0XHRcdFx0aWYgKCAnZXJyb3InID09PSBkYXRhLnN0YXR1cyApIHtcblxuXHRcdFx0XHRcdHN0YXR1cyA9ICdlcnJvcic7XG5cblx0XHRcdFx0XHR2YXIgbXNnID0gZGF0YS5tZXNzYWdlLFxuXHRcdFx0XHRcdFx0JGVyciA9ICQoICc8b2wgY2xhc3M9XCJsbG1zLWJ1aWxkZXItZXJyb3JcIiAvPicgKTtcblxuXHRcdFx0XHRcdGlmICggJ29iamVjdCcgPT09IHR5cGVvZiBtc2cgKSB7XG5cdFx0XHRcdFx0XHRfLmVhY2goIG1zZywgZnVuY3Rpb24oIHR4dCApIHtcblx0XHRcdFx0XHRcdFx0JGVyci5hcHBlbmQoICc8bGk+JyArIHR4dCArICc8L2xpPicgKTtcblx0XHRcdFx0XHRcdH0gKTtcblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0JGVyciA9ICRlcnIuYXBwZW5kKCAnPGxpPicgKyBtc2cgKyAnPC9saT4nICk7O1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdHRoaXMuYWRkX2Vycm9yKCAkZXJyICk7XG5cblx0XHRcdFx0fVxuXG5cdFx0XHRcdHRoaXMuJHNhdmVCdXR0b24uZmluZCggJy5sbG1zLXNwaW5uaW5nJyApLnJlbW92ZSgpO1xuXHRcdFx0XHR0aGlzLiRzYXZlQnV0dG9uLmF0dHIoIHtcblx0XHRcdFx0XHQnZGF0YS1zdGF0dXMnOiBzdGF0dXMsXG5cdFx0XHRcdFx0ZGlzYWJsZWQ6ICdkaXNhYmxlZCcsXG5cdFx0XHRcdH0gKTtcblxuXHRcdFx0fVxuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIERldGVybWluZSBpZiB0aGUgZWRpdG9yIGlzIHRoZSBjdXJyZW50bHkgYWN0aXZlIHN0YXRlXG5cdFx0ICogQHJldHVybiAgIGJvb2xlYW5cblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdGlzX2VkaXRvcl9hY3RpdmU6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHRyZXR1cm4gKCAnZWRpdG9yJyA9PT0gdGhpcy5zdGF0ZSApO1xuXG5cdFx0fSxcblxuXHRcdC8qKlxuXHRcdCAqIFRyaWdnZXJlZCB3aGVuIHRoZSBlZGl0b3IgY2xvc2VzLCB1cGRhdGVzIHN0YXRlIHRvIGJlIHRoZSBjb3Vyc2UgYnVpbGRlciB2aWV3XG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNi4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTYuMFxuXHRcdCAqL1xuXHRcdG9uX2VkaXRvcl9jbG9zZTogZnVuY3Rpb24oKSB7XG5cblx0XHRcdHRoaXMuc2V0X3N0YXRlKCAnYnVpbGRlcicgKS5yZW5kZXIoKTtcblxuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBXaGVuIGEgbGVzc29uIGlzIHNlbGVjdGVkLCBvcGVucyB0aGUgc2lkZWJhciB0byB0aGUgZWRpdG9yIHZpZXdcblx0XHQgKiBAcGFyYW0gICAgb2JqICAgbGVzc29uX21vZGVsICBpbnN0YW5jZSBvZiB0aGUgbGVzc29uIG1vZGVsIHdoaWNoIHdhcyBzZWxlY3RlZFxuXHRcdCAqIEByZXR1cm4gICB2b2lkXG5cdFx0ICogQHNpbmNlICAgIDMuMTYuMFxuXHRcdCAqIEB2ZXJzaW9uICAzLjE2LjBcblx0XHQgKi9cblx0XHRvbl9sZXNzb25fc2VsZWN0OiBmdW5jdGlvbiggbGVzc29uX21vZGVsLCB0YWIgKSB7XG5cblx0XHRcdGlmICggJ2VkaXRvcicgIT09IHRoaXMuc3RhdGUgKSB7XG5cdFx0XHRcdHRoaXMuc2V0X3N0YXRlKCAnZWRpdG9yJyApO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dGhpcy5yZW1vdmVfc3VidmlldyggJ2VkaXRvcicgKTtcblx0XHRcdH1cblxuXHRcdFx0dGhpcy5yZW5kZXIoIHtcblx0XHRcdFx0bW9kZWw6IGxlc3Nvbl9tb2RlbCxcblx0XHRcdFx0dGFiOiB0YWIsXG5cdFx0XHR9ICk7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogU2F2ZSBidXR0b24gY2xpY2sgZXZlbnRcblx0XHQgKiBAcmV0dXJuICAgdm9pZFxuXHRcdCAqIEBzaW5jZSAgICAzLjE2LjBcblx0XHQgKiBAdmVyc2lvbiAgMy4xNi4wXG5cdFx0ICovXG5cdFx0c2F2ZV9ub3c6IGZ1bmN0aW9uKCkge1xuXG5cdFx0XHR3aW5kb3cubGxtc19idWlsZGVyLnN5bmMuc2F2ZV9ub3coKTtcblxuXHRcdH0sXG5cblx0fSwgU3VidmlldyApICk7XG5cbn0gKTtcblxuLyoqXG4gKiBMaWZ0ZXJMTVMgSlMgQnVpbGRlciBBcHAgQm9vdHN0cmFwXG4gKiBAc2luY2UgICAgMy4xNi4wXG4gKiBAdmVyc2lvbiAgMy4xNy44XG4gKi9cbnJlcXVpcmUoIFtcblx0J3ZlbmRvci9iYWNrYm9uZS5jb2xsZWN0aW9uVmlldycsXG5cdCd2ZW5kb3IvYmFja2JvbmUudHJhY2tpdCcsXG5cdCdDb250cm9sbGVycy9Db25zdHJ1Y3QnLFxuXHQnQ29udHJvbGxlcnMvRGVidWcnLFxuXHQnQ29udHJvbGxlcnMvU2NoZW1hcycsXG5cdCdDb250cm9sbGVycy9TeW5jJyxcblx0J01vZGVscy9sb2FkZXInLFxuXHQnVmlld3MvQ291cnNlJyxcblx0J1ZpZXdzL1NpZGViYXInXG5dLCBmdW5jdGlvbihcblx0Q1YsXG5cdFRyYWNrSXQsXG5cdENvbnN0cnVjdCxcblx0RGVidWcsXG5cdFNjaGVtYXMsXG5cdFN5bmMsXG5cdE1vZGVscyxcblx0Q291cnNlVmlldyxcblx0U2lkZWJhclZpZXdcbikge1xuXG5cdHdpbmRvdy5sbG1zX2J1aWxkZXIuZGVidWcgPSBuZXcgRGVidWcoIHdpbmRvdy5sbG1zX2J1aWxkZXIuZGVidWcgKTtcblx0d2luZG93LmxsbXNfYnVpbGRlci5jb25zdHJ1Y3QgPSBuZXcgQ29uc3RydWN0KCk7XG5cdHdpbmRvdy5sbG1zX2J1aWxkZXIuc2NoZW1hcyA9IG5ldyBTY2hlbWFzKCB3aW5kb3cubGxtc19idWlsZGVyLnNjaGVtYXMgKTtcblxuXHQvKipcblx0ICogQ29tcGFyZSB2YWx1ZXMsIHVzZWQgYnkgXy5jaGVja2VkICYgXy5zZWxlY3RlZCBtaXhpbnNcblx0ICogQHBhcmFtICAgIG1peGVkICAgZXhwZWN0ZWQgIGV4cGVjdGVkIHZhbHVlLCBwcm9iYWJseSBhIHN0cmluZyAodGhlIHZhbHVlIG9mIGEgc2VsZWN0IG9wdGlvbiBvciBjaGVja2JveCBlbGVtZW50KVxuXHQgKiBAcGFyYW0gICAgbWl4ZWQgICBhY3R1YWwgICAgYWN0dWFsIHZhbHVlLCBwcm9iYWJseSBhIHN0cmluZyAodGhlIHJldHVybiBvZiBtb2RlbC5nZXQoICdzb21ldGhpbmcnICkgKVxuXHQgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXHRcdFx0XHQgYnV0IGNvdWxkIGJlIGFuIGFycmF5IGxpa2UgYSBtdWx0aXNlbGVjdFxuXHQgKiBAcmV0dXJuICAgYm9vbGVhblxuXHQgKiBAc2luY2UgICAgMy4xNy4yXG5cdCAqIEB2ZXJzaW9uICAzLjE3LjJcblx0ICovXG5cdGZ1bmN0aW9uIHZhbHVlX2NvbXBhcmUoIGV4cGVjdGVkLCBhY3R1YWwgKSB7XG5cdFx0cmV0dXJuICggKCBfLmlzQXJyYXkoIGFjdHVhbCApICYmIC0xICE9PSBhY3R1YWwuaW5kZXhPZiggZXhwZWN0ZWQgKSApIHx8IGV4cGVjdGVkID09IGFjdHVhbCApO1xuXHR9O1xuXG5cdC8qKlxuXHQgKiBVbmRlcnNjb3JlcyB0ZW1wbGF0aW5nIHV0aWxpdGllc1xuXHQgKiBAc2luY2UgICAgMy4xNy4wXG5cdCAqIEB2ZXJzaW9uICAzLjE3Ljhcblx0ICovXG5cdF8ubWl4aW4oIHtcblxuXHRcdC8qKlxuXHRcdCAqIERldGVybWluZSBpZiB0d28gdmFsdWVzIGFyZSBlcXVhbCBhbmQgb3V0cHV0IGNoZWNrZWQgYXR0cmlidXRlIGlmIHRoZXkgYXJlXG5cdFx0ICogVXNlZnVsIGZvciB0ZW1wbGF0aW5nIGNoZWNrYm94ZXMgJiByYWRpbyBlbGVtZW50c1xuXHRcdCAqIExpa2UgV1AgQ29yZSBQSFAgY2hlY2tlZCgpIGJ1dCBpbiBKU1xuXHRcdCAqIEBwYXJhbSAgICBtaXhlZCAgIGV4cGVjdGVkICBleHBlY3RlZCBlbGVtZW50IHZhbHVlXG5cdFx0ICogQHBhcmFtICAgIG1peGVkICAgYWN0dWFsICAgIGFjdHVhbCBlbGVtZW50IHZhbHVlXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNy4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTcuMlxuXHRcdCAqL1xuXHRcdGNoZWNrZWQ6IGZ1bmN0aW9uKCBleHBlY3RlZCwgYWN0dWFsICkge1xuXHRcdFx0aWYgKCB2YWx1ZV9jb21wYXJlKCBleHBlY3RlZCwgYWN0dWFsICkgKSB7XG5cdFx0XHRcdHJldHVybiAnIGNoZWNrZWQ9XCJjaGVja2VkXCInO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuICcnO1xuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBSZWN1cnNpdmVseSBjbG9uZSBhbiBvYmplY3QgdmlhIF8uY2xvbmUoKVxuXHRcdCAqIEBwYXJhbSAgICBvYmogICBvYmogIG9iamVjdCB0byBjbG9uZVxuXHRcdCAqIEByZXR1cm4gICBvYmpcblx0XHQgKiBAc2luY2UgICAgMy4xNy43XG5cdFx0ICogQHZlcnNpb24gIDMuMTcuN1xuXHRcdCAqL1xuXHRcdGRlZXBDbG9uZTogZnVuY3Rpb24oIG9iaiApIHtcblxuXHRcdFx0dmFyIGNsb25lID0gXy5jbG9uZSggb2JqICk7XG5cblx0XHRcdF8uZWFjaCggY2xvbmUsIGZ1bmN0aW9uKCB2YWwsIGtleSApIHtcblx0XHRcdFx0aWYgKCAhIF8uaXNGdW5jdGlvbiggdmFsICkgJiYgXy5pc09iamVjdCggdmFsICkgKSB7XG5cdFx0XHRcdFx0Y2xvbmVbIGtleSBdID0gXy5kZWVwQ2xvbmUoIHZhbCApO1xuXHRcdFx0XHR9O1xuXHRcdFx0fSApO1xuXG5cdFx0XHRyZXR1cm4gY2xvbmU7XG5cblx0XHR9LFxuXG5cdFx0LyoqXG5cdFx0ICogRGV0ZXJtaW5lIGlmIHR3byB2YWx1ZXMgYXJlIGVxdWFsIGFuZCBvdXRwdXQgc2VsZXRlZCBhdHRyaWJ1dGUgaWYgdGhleSBhcmVcblx0XHQgKiBVc2VmdWwgZm9yIHRlbXBsYXRpbmcgc2VsZWN0IGVsZW1lbnRzXG5cdFx0ICogTGlrZSBXUCBDb3JlIFBIUCBzZWxlY3RlZCgpIGJ1dCBpbiBKU1xuXHRcdCAqIEBwYXJhbSAgICBtaXhlZCAgIGV4cGVjdGVkICBleHBlY3RlZCBlbGVtZW50IHZhbHVlXG5cdFx0ICogQHBhcmFtICAgIG1peGVkICAgYWN0dWFsICAgIGFjdHVhbCBlbGVtZW50IHZhbHVlXG5cdFx0ICogQHJldHVybiAgIHZvaWRcblx0XHQgKiBAc2luY2UgICAgMy4xNy4wXG5cdFx0ICogQHZlcnNpb24gIDMuMTcuMlxuXHRcdCAqL1xuXHRcdHNlbGVjdGVkOiBmdW5jdGlvbiggZXhwZWN0ZWQsIGFjdHVhbCApIHtcblx0XHRcdGlmICggdmFsdWVfY29tcGFyZSggZXhwZWN0ZWQsIGFjdHVhbCApICkge1xuXHRcdFx0XHRyZXR1cm4gJyBzZWxlY3RlZD1cInNlbGVjdGVkXCInO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuICcnO1xuXHRcdH0sXG5cblx0XHQvKipcblx0XHQgKiBHZW5lcmljIGZ1bmN0aW9uIGZvciBzdHJpcHBpbmcgSFRNTCB0YWdzIGZyb20gYSBzdHJpbmdcblx0XHQgKiBAcGFyYW0gICAgc3RyaW5nICAgY29udGVudCAgICAgICByYXcgc3RyaW5nXG5cdFx0ICogQHBhcmFtICAgIGFycmF5ICAgYWxsb3dlZF90YWdzICBhcnJheSBvZiBhbGxvd2VkIEhUTUwgdGFnc1xuXHRcdCAqIEByZXR1cm4gICBzdHJpbmdcblx0XHQgKiBAc2luY2UgICAgMy4xNy44XG5cdFx0ICogQHZlcnNpb24gIDMuMTcuOFxuXHRcdCAqL1xuXHRcdHN0cmlwRm9ybWF0dGluZzogZnVuY3Rpb24oIGNvbnRlbnQsIGFsbG93ZWRfdGFncyApIHtcblxuXHRcdFx0aWYgKCAhIGFsbG93ZWRfdGFncyApIHtcblx0XHRcdFx0YWxsb3dlZF90YWdzID0gWyAnYicsICdpJywgJ3UnLCAnc3Ryb25nJywgJ2VtJyBdO1xuXHRcdFx0fVxuXG5cdFx0XHR2YXIgJGh0bWwgPSAkKCAnPGRpdj4nICsgY29udGVudCArICc8L2Rpdj4nICk7XG5cblx0XHRcdCRodG1sLmZpbmQoICcqJyApLm5vdCggYWxsb3dlZF90YWdzLmpvaW4oICcsJyApICkuZWFjaCggZnVuY3Rpb24oICkge1xuXG5cdFx0XHRcdCQoIHRoaXMgKS5yZXBsYWNlV2l0aCggdGhpcy5pbm5lckhUTUwgKTtcblxuXHRcdFx0fSApO1xuXG5cdFx0XHRyZXR1cm4gJGh0bWwuaHRtbCgpO1xuXG5cdFx0fSxcblxuXHR9ICk7XG5cblx0QmFja2JvbmUucHViU3ViID0gXy5leHRlbmQoIHt9LCBCYWNrYm9uZS5FdmVudHMgKTtcblxuXHQkKCBkb2N1bWVudCApLnRyaWdnZXIoICdsbG1zLWJ1aWxkZXItcHJlLWluaXQnICk7XG5cblx0d2luZG93LmxsbXNfYnVpbGRlci5xdWVzdGlvbnMgPSB3aW5kb3cubGxtc19idWlsZGVyLmNvbnN0cnVjdC5nZXRfY29sbGVjdGlvbiggJ1F1ZXN0aW9uVHlwZXMnLCB3aW5kb3cubGxtc19idWlsZGVyLnF1ZXN0aW9ucyApO1xuXG5cdHZhciBDb3Vyc2VNb2RlbCA9IHdpbmRvdy5sbG1zX2J1aWxkZXIuY29uc3RydWN0LmdldF9tb2RlbCggJ0NvdXJzZScsIHdpbmRvdy5sbG1zX2J1aWxkZXIuY291cnNlICk7XG5cdHdpbmRvdy5sbG1zX2J1aWxkZXIuQ291cnNlTW9kZWwgPSBDb3Vyc2VNb2RlbDtcblxuXHR3aW5kb3cubGxtc19idWlsZGVyLnN5bmMgPSBuZXcgU3luYyggQ291cnNlTW9kZWwsIHdpbmRvdy5sbG1zX2J1aWxkZXIuc3luYyApO1xuXG5cdHZhciBDb3Vyc2UgPSBuZXcgQ291cnNlVmlldygge1xuXHRcdG1vZGVsOiBDb3Vyc2VNb2RlbCxcblx0fSApO1xuXG5cdHZhciBTaWRlYmFyID0gbmV3IFNpZGViYXJWaWV3KCB7XG5cdFx0Q291cnNlVmlldzogQ291cnNlXG5cdH0gKTtcblxuXHQkKCBkb2N1bWVudCApLnRyaWdnZXIoICdsbG1zLWJ1aWxkZXItaW5pdCcsIHtcblx0XHRjb3Vyc2U6IENvdXJzZSxcblx0XHRzaWRlYmFyOiBTaWRlYmFyLFxuXHR9ICk7XG5cbn0gKTtcblxuZGVmaW5lKFwibWFpblwiLCBmdW5jdGlvbigpe30pO1xuXG59KGpRdWVyeSkpO1xuXG4vLyMgc291cmNlTWFwcGluZ1VSTD1sbG1zLWJ1aWxkZXIuanMubWFwXG4iXX0=
diff --git a/assets/js/llms-builder.min.js.map b/assets/js/llms-builder.min.js.map
index 62a9ee05ee..45f5a237c3 100644
--- a/assets/js/llms-builder.min.js.map
+++ b/assets/js/llms-builder.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../../../config-wrap-start-default.js","vendor/almond.js","underscore.js","backbone.js","jquery.js","vendor/backbone.collectionView.js","vendor/backbone.trackit.js","Models/Image.js","Models/_Relationships.js","Models/QuestionChoice.js","Collections/QuestionChoices.js","Models/QuestionType.js","Models/Question.js","Collections/Questions.js","Models/_Utilities.js","Schemas/Quiz.js","Models/Quiz.js","Schemas/Lesson.js","Models/Lesson.js","Collections/Lessons.js","Collections/QuestionTypes.js","Models/Section.js","Collections/Sections.js","Collections/loader.js","Models/Abstract.js","Models/Course.js","Models/loader.js","Views/_Detachable.js","Views/_Editable.js","Views/_Receivable.js","Views/_Shiftable.js","Views/_Subview.js","Views/_Trashable.js","Views/_loader.js","Controllers/Construct.js","Controllers/Debug.js","Controllers/Schemas.js","Controllers/Sync.js","Views/Lesson.js","Views/LessonList.js","Views/Section.js","Views/SectionList.js","Views/Course.js","Views/SettingsFields.js","Views/LessonEditor.js","Views/Popover.js","Views/PostSearch.js","Views/QuestionType.js","Views/QuestionBank.js","Views/QuestionChoice.js","Views/QuestionChoiceList.js","Views/Question.js","Views/QuestionList.js","Views/Quiz.js","Views/Assignment.js","Views/Editor.js","Views/Elements.js","Views/Utilities.js","Views/Sidebar.js","main.js"],"names":["$","requirejs","require","define","undef","hasProp","obj","prop","hasOwn","call","normalize","name","baseName","nameParts","nameSegment","mapValue","foundMap","lastIndex","foundI","foundStarMap","starI","i","j","part","normalizedBaseParts","baseParts","split","map","config","starMap","length","nodeIdCompat","jsSuffixRegExp","test","replace","charAt","slice","concat","splice","join","makeRequire","relName","forceSync","args","aps","arguments","push","req","apply","makeNormalize","makeLoad","depName","value","defined","callDep","waiting","defining","main","Error","splitPrefix","prefix","index","indexOf","substring","makeRelParts","makeConfig","makeMap","handlers","Object","prototype","hasOwnProperty","relParts","plugin","parts","relResourceName","f","n","pr","p","exports","e","module","id","uri","deps","callback","cjsModule","ret","usingExports","callbackType","load","undefined","alt","setTimeout","cfg","_defined","amd","jQuery","_","Backbone","root","factory","Zepto","this","_normalizeOptionDeclarations","optionDeclarations","normalizedOptionDeclarations","isArray","each","thisOptionDeclaration","thisOptionName","thisOptionRequired","thisOptionDefaultValue","isString","isObject","first","keys","isFunction","clone","required","isUndefined","defaultValue","mDefaultModelViewConstructor","View","kOptionsRequiringRerendering","kStylesForEmptyListCaption","background","border","box-shadow","CollectionView","extend","tagName","events","mousedown > li, tbody > tr > td","dblclick > li, tbody > tr > td","click","click ul.collection-view, table.collection-view","keydown","spawnMessages","focus","passMessages","*","initializationOptions","collection","modelView","modelViewOptions","itemTemplate","itemTemplateFunction","selectable","clickToSelect","selectableModelsFilter","visibleModelsFilter","sortableModelsFilter","selectMultiple","clickToToggle","processKeyEvents","sortable","sortableOptions","reuseModelViews","detachedRendering","emptyListCaption","initialize","options","ViewOptions","add","setOptions","Collection","_hasBeenRendered","_isBackboneCourierAvailable","Courier","$el","data","addClass","attr","selectedItems","_updateItemTemplate","_registerCollectionEvents","viewManager","ChildViewContainer","_onOptionsChanged","changedOptions","originalOptions","_this","rerender","changedOptionKey","newVal","oldVal","stopListening","setSelectedModel","by","setSelectedModels","removeAttr","_setupSortable","reapplyFilter","view","remove","contains","render","setOption","optionName","optionValue","optionHash","getSelectedModel","getSelectedModels","referenceBy","items","item","get","curLineNumber","_getVisibleItemEls","is","findByModel","newSelectedItems","silent","newSelectedCids","thisModel","cid","pluck","model","thisItemEl","oldSelectedModels","oldSelectedCids","_convertStringsToInts","_validateSelection","newSelectedModels","_containSameElements","_addSelectedClassToSelectedItems","spawn","selectedModels","trigger","updateDependentControls","newSelectedItem","getView","reference","itemElements","_saveSelection","modelViewContainerEl","_getContainerEl","oldViewManager","thisModelView","detach","empty","fragmentContainer","document","createDocumentFragment","findByModelCid","_createNewModelView","_getModelViewOptions","_insertAndRenderModelView","append","_showEmptyListCaptionIfAppropriate","_restoreSelection","forceRerenderOnNextSortEvent","_removeEmptyListCaption","emptyListString","$emptyListCaptionEl","$varEl","_isRenderedAsList","wrapAll","parent","css","find","parentElOrDocumentFragment","atIndex","thisModelViewWrapped","_wrapModelView","nodeType","appendChild","numberOfModelViewsCurrentlyInDOM","children","eq","before","hide","hideThisModelView","toggle","toggleClass","whichFilter","notVisible","_modelViewHasWrapperLI","closest","notSortable","notSelectable","_removeModelView","_validateSelectionAndRender","listenTo","_isRenderedAsTable","tbody","_getClickedItemId","theEvent","clickedItemId","clickedItemEl","currentTarget","clickedItem","isNumeric","parseInt","itemTemplateHtml","html","template","modelReferenceIds","models","intersection","filter","thisItemId","savedSelection","offset","oldItemsIdsWithSelectedClass","itemsIdsFromWhichSelectedClassNeedsToBeRemoved","without","removeClass","itemsIdsFromWhichSelectedClassNeedsToBeAdded","_reorderCollectionBasedOnHTML","thisModelCid","sort","comparator","_getModelViewConstructor","modelViewConstructor","newModelView","collectionListView","collectionView","modelViewWrapperEl","theArray","thisEl","thisElAsNumber","arrayA","arrayB","toLowerCase","_charCodes","upArrow","downArrow","axis","distance","forcePlaceholderSize","start","bind","_sortStart","change","_sortChange","stop","_sortStop","receive","_receive","over","_over","result","event","ui","modelBeingSorted","newIndex","senderListEl","sender","senderCollectionListView","modelReceived","at","_onKeydown","trap","currentOffset","which","_listItem_onMousedown","clickedModel","metaKeyPressed","ctrlKey","metaKey","thisMethod","shiftKey","firstSelectedItemIndex","thisItemModel","clickedItemIndex","shiftKeyRootSelectedItemIndex","minSelectedItemIndex","Math","min","maxSelectedItemIndex","max","thisIndex","selection","window","getSelection","sel","removeAllRanges","union","_listItem_onDoubleClick","_listBackground_onClick","target","setDefaultModelViewConstructor","theConstructor","optionsDeclarationsProperty","optionsThatWereChanged","optionsThatWereChangedPreviousValues","thisOptionProperties","oldValue","newValue","onOptionsChanged","getOptions","optionsNames","pick","Container","views","_views","_indexByModel","_indexByCustom","_updateLength","customIndex","viewCid","modelCid","findByCid","findByCustom","findByIndex","values","findIndexByCid","any","key","method","tail","size","methods","toArray","unsavedModels","updateUnsavedModels","isEmpty","_unsavedChanges","m","findWhere","getPrompt","fnName","prompt","rest","evaluateModelFn","fn","isBoolean","_unsavedConfig","History","navigate","wrap","oldNav","fragment","confirm","onbeforeunload","Model","unsaved","_trackingChanges","_originalAttrs","startTracking","unloadRouterPrompt","unloadWindowPrompt","_resetTracking","_triggerUnsavedChanges","stopTracking","restartTracking","resetAttributes","attributes","unsavedAttributes","attrs","val","changed","old","isEqual","set","oldSet","sync","oldSync","success","oldSuccess","textStatus","jqXHR","defaults","enabled","src","relationship_defaults","relationships","init_relationships","rels","get_relationships","set_parent","child_data","child_key","conditional","child","child_val","lookup","type","llms_builder","construct","get_model","class","get_collection","_maybe_set_parent_reference","child_model","get_child_props","props","get_parent","Image","Relationships","choice","uniqueId","choice_type","correct","marker","question_id","get_trash_id","is_selectable","get_choice_selectable","on","update_order","update_correct","count_correct","get_correct","siblings","question","self","get_choice_markers","choices","clarifications","default_choices","description","icon","image","keywords","placeholder","points","video","get_keywords","_get_choice_option","get_choice_type","get_min_choices","get_max_choices","get_multi_choices","option","Questions","QuestionChoices","QuestionType","questions","question_type","content","description_enabled","multi_choices","menu_order","parent_id","title","video_enabled","video_src","_expanded","_ensure_min_choices","delay","update_points","add_choice","pubSub","before_save","atts","sync_type","get_type_index","curr_type","get_type_iterator","get_qid","get_parent_question","is_in_group","get_parent_quiz","get_points","get_points_percentage","total","toFixed","update_parent","fields","get_edit_post_link","has_temp_id","admin_url","get_settings_fields","schema","schemas","isNumber","init_custom_schema","groups","group","flatten","field","attribute","customs","switch_attribute","attribute_prefix","default","LLMS","l10n","translate","toggleable","label","tip","Lesson","Question","Utilities","QuizSchema","lesson_id","status","allowed_attempts","limit_attempts","limit_time","passing_percent","random_answers","time_limit","show_correct_answer","_points","permalink","_show_settings","_questions_loaded","get_total_points","add_question","get_l10n_type","plural","load_questions","cb","Ajax","action","action_type","course_id","CourseModel","load_id","error","xhr","console","log","debug","res","condition","assignments","is_first_in_course","get_available_prereq_options","get_course","date_format","timepicker","datepicker","Quiz","LessonSchema","parents","quiz","order","parent_course","course","parent_section","edit_url","view_url","audio_embed","has_prerequisite","require_passing_grade","require_assignment_passing_grade","video_embed","free_lesson","assignment","assignment_enabled","quiz_enabled","_forceSync","maybe_init_assignments","parent_section_index","lesson_index_in_section","section","curr_sec_index","%1$d","%2$s","lesson","curr_les_index","add_quiz","%1$s","on_reorder","validate_prereqs","prerequisite","Lessons","lessons","_selected","add_lesson","get_next","circular","_get_sibling","get_prev","direction","sibling_index","last","QuestionTypes","Sections","sections","add_section","add_existing_lesson","get_selected_section","selected","Abstract","Course","QuestionChoice","Section","click a[href=\"#llms-detach-model\"]","detach_model","preventDefault","stopPropagation","msg","%s","media_lib","click .llms-add-image","click a[href=\"#llms-edit-slug\"]","click a[href=\"#llms-remove-image\"]","change .llms-editable-select select","change .llms-switch input[type=\"checkbox\"]","change .llms-editable-radio input","focusin .llms-input","focusout .llms-input","keydown .llms-input","input .llms-input[type=\"number\"]","paste .llms-input[data-formatting]","get_allowed_tags","tag","trim","get_content","hasClass","stripFormatting","text","has_changed","is_valid","_validate_url","slug","beforeSend","Spinner","r","init_datepickers","datetimepicker","format","onClose","current_time","$input","blur","init_formatting_els","formatting","ed","Quill","modules","toolbar","keyboard","bindings","tab","handler","range","context","13","theme","delta","oldDelta","source","init_selects","llmsSelect2","width","on_blur","save_edits","revert_edits","on_focus","on_paste","originalEvent","clipboardData","getData","execCommand","on_select","multi","$selected","on_radio_select","on_keydown","keyCode","shift","open_media_lib","uploader","param","wp","media","frames","file_frame","button","multiple","url","attachment","state","toJSON","sizes","open","remove_image","toggle_switch","init_editor","settings","editor","getDefaultSettings","mediaButtons","tinymce","toolbar1","toolbar2","setup","on_editor_ready","make_slug_editable","$btn","$link","prevAll","prev","full_url","short_url","color","pointer-events","text-decoration","show","$ed","$parent","$label","prependTo","getContent","str","a","createElement","href","host","location","helper","maybe_hide_shiftable_buttons","old_index","new_index","shift_down","shift_up","subscriptions","get_subview","events_subscribe","func","events_unsubscribe","off","remove_subview","instance","remove_subviews","undelegateEvents","render_subviews","view_data","render_subview","set_state","click a[href=\"#llms-trash-model\"]","trash_model","Detachable","Editable","Receivable","Shiftable","Subview","Trashable","Collections","Models","Views","extend_view","classname","register_collection","register_model","disable","enable","custom_schemas","custom","model_type","add_error_msg","err","message","check_for_changes","changes","get_unsaved_changes","has_unsaved_changes","saving","do_ajax_save","JSON","stringify","responseText","process_removals","process_updates","get_changed_attributes","exclude","omit","get_changes_to_object","object","changed_atts","model_changes","maybe_restart_tracking","unset","removals","detached","trash","trashed","coll","errors","info","process_object_updates","main_data","orig_id","updates","autosave","check_interval","check_interval_ms","save_now","heartbeat","connectNow","set_check_interval","ms","clearInterval","setInterval","statusText","data-id","data-section-id","className","click .edit-lesson","click .edit-quiz","click .edit-assignment","click .section-prev","click .section-next","click .shift-up--lesson","click .shift-down--lesson","open_assignment_editor","open_lesson_editor","open_quiz_editor","section_next","_move_to_section","section_prev","to_section","from_coll","LessonView","connectWith","cursor","handle","sortable_start","sortable_stop","LessonListView","click .expand","click .collapse","click .shift-up--section","click .shift-down--section","mouseenter .llms-lessons","toggle_expanded","lessonListView","on_lesson_add","dragTimeout","expand","collapse","el","active_lesson_change","maybe_hide_trash_button","current","previous","update","on_mouseenter","SectionView","mousedown > li.llms-section > .llms-builder-header .llms-headline","click ul.collection-view","SectionListView","sectionListView","active_section_change","on_section_add","on_section_toggle","expand_section","click .llms-settings-group-toggle","get_editor_fields","is_editor_field","get_groups","is_group_hidden","group_id","localStorage","getItem","get_switch_attribute","has_switch","is_default_field","is_switch_condition_met","switch_on","render_editor","render_select_options","option_html","setup_field","orig_field","field_index","classes","input_type","tip_position","orig_settings","switch_off","deepClone","has_images","should_rerender_on_toggle","field_type","toggle_group","$group","setItem","removeItem","SettingsFields","change_events","placement","style","animation","closeable","backdrop","onShow","onHide","container","webuiPopover","select2:select","post_type","searching_message","add_post","params","ajax","dataType","ajaxurl","term","page","_ajax_nonce","wp_ajax_data","nonce","dropdownParent","escapeMarkup","markup","templateResult","render_result","$html","loading","$side","$main","click .llms-add-question","QuestionView","change input[name=\"correct\"]","click .llms-action-icon[href=\"#llms-add-choice\"]","click .llms-action-icon[href=\"#llms-del-choice\"]","maybe_disable_buttons","del_choice","toggle_correct","ChoiceView","ChoiceListView","click .clone--question","click .delete--question","click .expand--question","click .collapse--question","change input[name=\"question_points\"]","render_points_percentage","multi_choices_toggle","choiceListView","questionListView","get_question_list","_get_question_clone","choice_clone","delete","selector","QuizModel","Popover","PostSearch","QuestionBank","QuestionList","bank","list","click #llms-existing-quiz","click #llms-new-quiz","click #llms-show-question-bank","click .bulk-toggle","render_points","on_trashed","last_group","alert","$questions","animate","scrollTop","bulk_toggle","expanded","add_new_quiz","add_existing_quiz","post_search_popover","add_existing_quiz_click","dismissible","once","show_tools","pop","addon_events","is_addon_available","get_view_events","click #llms-existing-assignment","click #llms-new-assignment","add_new_assignment","get_assignment","show_ad_popover","add_existing_assignment","add_existing_assignment_click","h3","btn","ad_popover","LessonEditor","Assignment","click .llms-editor-nav a[href=\"#llms-editor-close\"]","click .llms-editor-nav a:not([href=\"#llms-editor-close\"])","SidebarView","close_editor","switch_tab","LessonSearch","click #llms-new-section","click #llms-new-lesson","click #llms-existing-lesson","CourseView","draggable","appendTo","cancel","connectToSortable","add_new_section","add_new_lesson","$els","click #llms-collapse-all","click #llms-expand-all","collapse_all","expand_all","Editor","Elements","elements","utilities","click #llms-save-button","click #llms-exit-button","click .llms-builder-error","changes_made","heartbeat_send","heartbeat_tick","on_lesson_select","on_editor_close","$saveButton","add_error","$err","prepend","clear_errors","exit_now","data-status","disabled","txt","is_editor_active","lesson_model","CV","TrackIt","Construct","Debug","Schemas","Sync","value_compare","expected","actual","mixin","checked","allowed_tags","not","replaceWith","innerHTML","Events","Sidebar","sidebar"],"mappings":"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","file":"llms-builder.min.js","sourcesContent":["(function($){\n","/**\n * @license almond 0.3.3 Copyright jQuery Foundation and other contributors.\n * Released under MIT license, http://github.com/requirejs/almond/LICENSE\n */\n//Going sloppy to avoid 'use strict' string cost, but strict practices should\n//be followed.\n/*global setTimeout: false */\n\nvar requirejs, require, define;\n(function (undef) {\n\tvar main, req, makeMap, handlers,\n\t\tdefined = {},\n\t\twaiting = {},\n\t\tconfig = {},\n\t\tdefining = {},\n\t\thasOwn = Object.prototype.hasOwnProperty,\n\t\taps = [].slice,\n\t\tjsSuffixRegExp = /\\.js$/;\n\n\tfunction hasProp(obj, prop) {\n\t\treturn hasOwn.call(obj, prop);\n\t}\n\n\t/**\n\t * Given a relative module name, like ./something, normalize it to\n\t * a real name that can be mapped to a path.\n\t * @param {String} name the relative name\n\t * @param {String} baseName a real name that the name arg is relative\n\t * to.\n\t * @returns {String} normalized name\n\t */\n\tfunction normalize(name, baseName) {\n\t\tvar nameParts, nameSegment, mapValue, foundMap, lastIndex,\n\t\t\tfoundI, foundStarMap, starI, i, j, part, normalizedBaseParts,\n\t\t\tbaseParts = baseName && baseName.split(\"/\"),\n\t\t\tmap = config.map,\n\t\t\tstarMap = (map && map['*']) || {};\n\n\t\t//Adjust any relative paths.\n\t\tif (name) {\n\t\t\tname = name.split('/');\n\t\t\tlastIndex = name.length - 1;\n\n\t\t\t// If wanting node ID compatibility, strip .js from end\n\t\t\t// of IDs. Have to do this here, and not in nameToUrl\n\t\t\t// because node allows either .js or non .js to map\n\t\t\t// to same file.\n\t\t\tif (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) {\n\t\t\t\tname[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, '');\n\t\t\t}\n\n\t\t\t// Starts with a '.' so need the baseName\n\t\t\tif (name[0].charAt(0) === '.' && baseParts) {\n\t\t\t\t//Convert baseName to array, and lop off the last part,\n\t\t\t\t//so that . matches that 'directory' and not name of the baseName's\n\t\t\t\t//module. For instance, baseName of 'one/two/three', maps to\n\t\t\t\t//'one/two/three.js', but we want the directory, 'one/two' for\n\t\t\t\t//this normalization.\n\t\t\t\tnormalizedBaseParts = baseParts.slice(0, baseParts.length - 1);\n\t\t\t\tname = normalizedBaseParts.concat(name);\n\t\t\t}\n\n\t\t\t//start trimDots\n\t\t\tfor (i = 0; i < name.length; i++) {\n\t\t\t\tpart = name[i];\n\t\t\t\tif (part === '.') {\n\t\t\t\t\tname.splice(i, 1);\n\t\t\t\t\ti -= 1;\n\t\t\t\t} else if (part === '..') {\n\t\t\t\t\t// If at the start, or previous value is still ..,\n\t\t\t\t\t// keep them so that when converted to a path it may\n\t\t\t\t\t// still work when converted to a path, even though\n\t\t\t\t\t// as an ID it is less than ideal. In larger point\n\t\t\t\t\t// releases, may be better to just kick out an error.\n\t\t\t\t\tif (i === 0 || (i === 1 && name[2] === '..') || name[i - 1] === '..') {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t} else if (i > 0) {\n\t\t\t\t\t\tname.splice(i - 1, 2);\n\t\t\t\t\t\ti -= 2;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t//end trimDots\n\n\t\t\tname = name.join('/');\n\t\t}\n\n\t\t//Apply map config if available.\n\t\tif ((baseParts || starMap) && map) {\n\t\t\tnameParts = name.split('/');\n\n\t\t\tfor (i = nameParts.length; i > 0; i -= 1) {\n\t\t\t\tnameSegment = nameParts.slice(0, i).join(\"/\");\n\n\t\t\t\tif (baseParts) {\n\t\t\t\t\t//Find the longest baseName segment match in the config.\n\t\t\t\t\t//So, do joins on the biggest to smallest lengths of baseParts.\n\t\t\t\t\tfor (j = baseParts.length; j > 0; j -= 1) {\n\t\t\t\t\t\tmapValue = map[baseParts.slice(0, j).join('/')];\n\n\t\t\t\t\t\t//baseName segment has config, find if it has one for\n\t\t\t\t\t\t//this name.\n\t\t\t\t\t\tif (mapValue) {\n\t\t\t\t\t\t\tmapValue = mapValue[nameSegment];\n\t\t\t\t\t\t\tif (mapValue) {\n\t\t\t\t\t\t\t\t//Match, update name to the new value.\n\t\t\t\t\t\t\t\tfoundMap = mapValue;\n\t\t\t\t\t\t\t\tfoundI = i;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (foundMap) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t//Check for a star map match, but just hold on to it,\n\t\t\t\t//if there is a shorter segment match later in a matching\n\t\t\t\t//config, then favor over this star map.\n\t\t\t\tif (!foundStarMap && starMap && starMap[nameSegment]) {\n\t\t\t\t\tfoundStarMap = starMap[nameSegment];\n\t\t\t\t\tstarI = i;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!foundMap && foundStarMap) {\n\t\t\t\tfoundMap = foundStarMap;\n\t\t\t\tfoundI = starI;\n\t\t\t}\n\n\t\t\tif (foundMap) {\n\t\t\t\tnameParts.splice(0, foundI, foundMap);\n\t\t\t\tname = nameParts.join('/');\n\t\t\t}\n\t\t}\n\n\t\treturn name;\n\t}\n\n\tfunction makeRequire(relName, forceSync) {\n\t\treturn function () {\n\t\t\t//A version of a require function that passes a moduleName\n\t\t\t//value for items that may need to\n\t\t\t//look up paths relative to the moduleName\n\t\t\tvar args = aps.call(arguments, 0);\n\n\t\t\t//If first arg is not require('string'), and there is only\n\t\t\t//one arg, it is the array form without a callback. Insert\n\t\t\t//a null so that the following concat is correct.\n\t\t\tif (typeof args[0] !== 'string' && args.length === 1) {\n\t\t\t\targs.push(null);\n\t\t\t}\n\t\t\treturn req.apply(undef, args.concat([relName, forceSync]));\n\t\t};\n\t}\n\n\tfunction makeNormalize(relName) {\n\t\treturn function (name) {\n\t\t\treturn normalize(name, relName);\n\t\t};\n\t}\n\n\tfunction makeLoad(depName) {\n\t\treturn function (value) {\n\t\t\tdefined[depName] = value;\n\t\t};\n\t}\n\n\tfunction callDep(name) {\n\t\tif (hasProp(waiting, name)) {\n\t\t\tvar args = waiting[name];\n\t\t\tdelete waiting[name];\n\t\t\tdefining[name] = true;\n\t\t\tmain.apply(undef, args);\n\t\t}\n\n\t\tif (!hasProp(defined, name) && !hasProp(defining, name)) {\n\t\t\tthrow new Error('No ' + name);\n\t\t}\n\t\treturn defined[name];\n\t}\n\n\t//Turns a plugin!resource to [plugin, resource]\n\t//with the plugin being undefined if the name\n\t//did not have a plugin prefix.\n\tfunction splitPrefix(name) {\n\t\tvar prefix,\n\t\t\tindex = name ? name.indexOf('!') : -1;\n\t\tif (index > -1) {\n\t\t\tprefix = name.substring(0, index);\n\t\t\tname = name.substring(index + 1, name.length);\n\t\t}\n\t\treturn [prefix, name];\n\t}\n\n\t//Creates a parts array for a relName where first part is plugin ID,\n\t//second part is resource ID. Assumes relName has already been normalized.\n\tfunction makeRelParts(relName) {\n\t\treturn relName ? splitPrefix(relName) : [];\n\t}\n\n\t/**\n\t * Makes a name map, normalizing the name, and using a plugin\n\t * for normalization if necessary. Grabs a ref to plugin\n\t * too, as an optimization.\n\t */\n\tmakeMap = function (name, relParts) {\n\t\tvar plugin,\n\t\t\tparts = splitPrefix(name),\n\t\t\tprefix = parts[0],\n\t\t\trelResourceName = relParts[1];\n\n\t\tname = parts[1];\n\n\t\tif (prefix) {\n\t\t\tprefix = normalize(prefix, relResourceName);\n\t\t\tplugin = callDep(prefix);\n\t\t}\n\n\t\t//Normalize according\n\t\tif (prefix) {\n\t\t\tif (plugin && plugin.normalize) {\n\t\t\t\tname = plugin.normalize(name, makeNormalize(relResourceName));\n\t\t\t} else {\n\t\t\t\tname = normalize(name, relResourceName);\n\t\t\t}\n\t\t} else {\n\t\t\tname = normalize(name, relResourceName);\n\t\t\tparts = splitPrefix(name);\n\t\t\tprefix = parts[0];\n\t\t\tname = parts[1];\n\t\t\tif (prefix) {\n\t\t\t\tplugin = callDep(prefix);\n\t\t\t}\n\t\t}\n\n\t\t//Using ridiculous property names for space reasons\n\t\treturn {\n\t\t\tf: prefix ? prefix + '!' + name : name, //fullName\n\t\t\tn: name,\n\t\t\tpr: prefix,\n\t\t\tp: plugin\n\t\t};\n\t};\n\n\tfunction makeConfig(name) {\n\t\treturn function () {\n\t\t\treturn (config && config.config && config.config[name]) || {};\n\t\t};\n\t}\n\n\thandlers = {\n\t\trequire: function (name) {\n\t\t\treturn makeRequire(name);\n\t\t},\n\t\texports: function (name) {\n\t\t\tvar e = defined[name];\n\t\t\tif (typeof e !== 'undefined') {\n\t\t\t\treturn e;\n\t\t\t} else {\n\t\t\t\treturn (defined[name] = {});\n\t\t\t}\n\t\t},\n\t\tmodule: function (name) {\n\t\t\treturn {\n\t\t\t\tid: name,\n\t\t\t\turi: '',\n\t\t\t\texports: defined[name],\n\t\t\t\tconfig: makeConfig(name)\n\t\t\t};\n\t\t}\n\t};\n\n\tmain = function (name, deps, callback, relName) {\n\t\tvar cjsModule, depName, ret, map, i, relParts,\n\t\t\targs = [],\n\t\t\tcallbackType = typeof callback,\n\t\t\tusingExports;\n\n\t\t//Use name if no relName\n\t\trelName = relName || name;\n\t\trelParts = makeRelParts(relName);\n\n\t\t//Call the callback to define the module, if necessary.\n\t\tif (callbackType === 'undefined' || callbackType === 'function') {\n\t\t\t//Pull out the defined dependencies and pass the ordered\n\t\t\t//values to the callback.\n\t\t\t//Default to [require, exports, module] if no deps\n\t\t\tdeps = !deps.length && callback.length ? ['require', 'exports', 'module'] : deps;\n\t\t\tfor (i = 0; i < deps.length; i += 1) {\n\t\t\t\tmap = makeMap(deps[i], relParts);\n\t\t\t\tdepName = map.f;\n\n\t\t\t\t//Fast path CommonJS standard dependencies.\n\t\t\t\tif (depName === \"require\") {\n\t\t\t\t\targs[i] = handlers.require(name);\n\t\t\t\t} else if (depName === \"exports\") {\n\t\t\t\t\t//CommonJS module spec 1.1\n\t\t\t\t\targs[i] = handlers.exports(name);\n\t\t\t\t\tusingExports = true;\n\t\t\t\t} else if (depName === \"module\") {\n\t\t\t\t\t//CommonJS module spec 1.1\n\t\t\t\t\tcjsModule = args[i] = handlers.module(name);\n\t\t\t\t} else if (hasProp(defined, depName) ||\n\t\t\t\t\t\t hasProp(waiting, depName) ||\n\t\t\t\t\t\t hasProp(defining, depName)) {\n\t\t\t\t\targs[i] = callDep(depName);\n\t\t\t\t} else if (map.p) {\n\t\t\t\t\tmap.p.load(map.n, makeRequire(relName, true), makeLoad(depName), {});\n\t\t\t\t\targs[i] = defined[depName];\n\t\t\t\t} else {\n\t\t\t\t\tthrow new Error(name + ' missing ' + depName);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tret = callback ? callback.apply(defined[name], args) : undefined;\n\n\t\t\tif (name) {\n\t\t\t\t//If setting exports via \"module\" is in play,\n\t\t\t\t//favor that over return value and exports. After that,\n\t\t\t\t//favor a non-undefined return value over exports use.\n\t\t\t\tif (cjsModule && cjsModule.exports !== undef &&\n\t\t\t\t\t\tcjsModule.exports !== defined[name]) {\n\t\t\t\t\tdefined[name] = cjsModule.exports;\n\t\t\t\t} else if (ret !== undef || !usingExports) {\n\t\t\t\t\t//Use the return value from the function.\n\t\t\t\t\tdefined[name] = ret;\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (name) {\n\t\t\t//May just be an object definition for the module. Only\n\t\t\t//worry about defining if have a module name.\n\t\t\tdefined[name] = callback;\n\t\t}\n\t};\n\n\trequirejs = require = req = function (deps, callback, relName, forceSync, alt) {\n\t\tif (typeof deps === \"string\") {\n\t\t\tif (handlers[deps]) {\n\t\t\t\t//callback in this case is really relName\n\t\t\t\treturn handlers[deps](callback);\n\t\t\t}\n\t\t\t//Just return the module wanted. In this scenario, the\n\t\t\t//deps arg is the module name, and second arg (if passed)\n\t\t\t//is just the relName.\n\t\t\t//Normalize module name, if it contains . or ..\n\t\t\treturn callDep(makeMap(deps, makeRelParts(callback)).f);\n\t\t} else if (!deps.splice) {\n\t\t\t//deps is a config object, not an array.\n\t\t\tconfig = deps;\n\t\t\tif (config.deps) {\n\t\t\t\treq(config.deps, config.callback);\n\t\t\t}\n\t\t\tif (!callback) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (callback.splice) {\n\t\t\t\t//callback is an array, which means it is a dependency list.\n\t\t\t\t//Adjust args if there are dependencies\n\t\t\t\tdeps = callback;\n\t\t\t\tcallback = relName;\n\t\t\t\trelName = null;\n\t\t\t} else {\n\t\t\t\tdeps = undef;\n\t\t\t}\n\t\t}\n\n\t\t//Support require(['a'])\n\t\tcallback = callback || function () {};\n\n\t\t//If relName is a function, it is an errback handler,\n\t\t//so remove it.\n\t\tif (typeof relName === 'function') {\n\t\t\trelName = forceSync;\n\t\t\tforceSync = alt;\n\t\t}\n\n\t\t//Simulate async callback;\n\t\tif (forceSync) {\n\t\t\tmain(undef, deps, callback, relName);\n\t\t} else {\n\t\t\t//Using a non-zero value because of concern for what old browsers\n\t\t\t//do, and latest browsers \"upgrade\" to 4 if lower value is used:\n\t\t\t//http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#dom-windowtimers-settimeout:\n\t\t\t//If want a value immediately, use require('id') instead -- something\n\t\t\t//that works in almond on the global level, but not guaranteed and\n\t\t\t//unlikely to work in other AMD implementations.\n\t\t\tsetTimeout(function () {\n\t\t\t\tmain(undef, deps, callback, relName);\n\t\t\t}, 4);\n\t\t}\n\n\t\treturn req;\n\t};\n\n\t/**\n\t * Just drops the config on the floor, but returns req in case\n\t * the config return value is used.\n\t */\n\treq.config = function (cfg) {\n\t\treturn req(cfg);\n\t};\n\n\t/**\n\t * Expose module registry for debugging and tooling\n\t */\n\trequirejs._defined = defined;\n\n\tdefine = function (name, deps, callback) {\n\t\tif (typeof name !== 'string') {\n\t\t\tthrow new Error('See almond README: incorrect module build, no module name');\n\t\t}\n\n\t\t//This module may not have dependencies\n\t\tif (!deps.splice) {\n\t\t\t//deps is not an array, so probably means\n\t\t\t//an object literal or factory function for\n\t\t\t//the value. Adjust args.\n\t\t\tcallback = deps;\n\t\t\tdeps = [];\n\t\t}\n\n\t\tif (!hasProp(defined, name) && !hasProp(waiting, name)) {\n\t\t\twaiting[name] = [name, deps, callback];\n\t\t}\n\t};\n\n\tdefine.amd = {\n\t\tjQuery: true\n\t};\n}());\n\ndefine(\"vendor/almond\", function(){});\n\n","/**\n * Returns the WordPress-loaded version of Underscore for use with things that need it and use Require.\n * @return obj\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'underscore',[],function() {\n\treturn _;\n} );\n\n","/**\n * Returns the WordPress-loaded version of Backbone for use with things that need it and use Require.\n * @return obj\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'backbone',[],function() {\n\treturn Backbone;\n} );\n\n","/**\n * Returns the WordPress-loaded version of Underscore for use with things that need it and use Require.\n * @return obj\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'jquery',[],function() {\n\treturn jQuery;\n} );\n\n","/*!\n* Backbone.CollectionView, v1.3.4\n* Copyright (c)2013 Rotunda Software, LLC.\n* Distributed under MIT license\n* http://github.com/rotundasoftware/backbone-collection-view\n*/\n\n( function( root, factory ) {\n\t// UMD wrapper\n\tif ( typeof define === 'function' && define.amd ) {\n\t\t// AMD\n\t\tdefine( 'vendor/backbone.collectionView',[ 'underscore', 'backbone', 'jquery' ], factory );\n\t} else if ( typeof exports !== 'undefined' ) {\n\t\t// Node/CommonJS\n\t\tmodule.exports = factory( require('underscore' ), require( 'backbone' ), require( 'backbone' ).$ );\n\t} else {\n\t\t// Browser globals\n\t\tfactory( root._, root.Backbone, ( root.jQuery || root.Zepto || root.$ ) );\n\t}\n}( this, function( _, Backbone, $ ) {\n\tvar mDefaultModelViewConstructor = Backbone.View;\n\n\tvar kDefaultReferenceBy = \"model\";\n\n\tvar kOptionsRequiringRerendering = [ \"collection\", \"modelView\", \"modelViewOptions\", \"itemTemplate\", \"itemTemplateFunction\", \"detachedRendering\" ];\n\n\tvar kStylesForEmptyListCaption = {\n\t\t\"background\" : \"transparent\",\n\t\t\"border\" : \"none\",\n\t\t\"box-shadow\" : \"none\"\n\t};\n\n\tBackbone.CollectionView = Backbone.View.extend( {\n\n\t\ttagName : \"ul\",\n\n\t\tevents : {\n\t\t\t\"mousedown > li, tbody > tr > td\" : \"_listItem_onMousedown\",\n\t\t\t\"dblclick > li, tbody > tr > td\" : \"_listItem_onDoubleClick\",\n\t\t\t\"click\" : \"_listBackground_onClick\",\n\t\t\t\"click ul.collection-view, table.collection-view\" : \"_listBackground_onClick\",\n\t\t\t\"keydown\" : \"_onKeydown\"\n\t\t},\n\n\t\t// only used if Backbone.Courier is available\n\t\tspawnMessages : {\n\t\t\t\"focus\" : \"focus\"\n\t\t},\n\n\t\t//only used if Backbone.Courier is available\n\t\tpassMessages : { \"*\" : \".\" },\n\n\t\t// viewOption definitions with default values.\n\t\tinitializationOptions : [\n\t\t\t{ \"collection\" : null },\n\t\t\t{ \"modelView\" : null },\n\t\t\t{ \"modelViewOptions\" : {} },\n\t\t\t{ \"itemTemplate\" : null },\n\t\t\t{ \"itemTemplateFunction\" : null },\n\t\t\t{ \"selectable\" : true },\n\t\t\t{ \"clickToSelect\" : true },\n\t\t\t{ \"selectableModelsFilter\" : null },\n\t\t\t{ \"visibleModelsFilter\" : null },\n\t\t\t{ \"sortableModelsFilter\" : null },\n\t\t\t{ \"selectMultiple\" : false },\n\t\t\t{ \"clickToToggle\" : false },\n\t\t\t{ \"processKeyEvents\" : true },\n\t\t\t{ \"sortable\" : false },\n\t\t\t{ \"sortableOptions\" : null },\n\t\t\t{ \"reuseModelViews\" : true },\n\t\t\t{ \"detachedRendering\" : false },\n\t\t\t{ \"emptyListCaption\" : null }\n\t\t],\n\n\t\tinitialize : function( options ) {\n\t\t\tBackbone.ViewOptions.add( this, \"initializationOptions\" ); // setup the ViewOptions functionality.\n\t\t\tthis.setOptions( options ); // and make use of any provided options\n\n\t\t\tif( ! this.collection ) this.collection = new Backbone.Collection();\n\n\t\t\tthis._hasBeenRendered = false;\n\n\t\t\tif( this._isBackboneCourierAvailable() ) {\n\t\t\t\tBackbone.Courier.add( this );\n\t\t\t}\n\n\t\t\tthis.$el.data( \"view\", this ); // needed for connected sortable lists\n\t\t\tthis.$el.addClass( \"collection-view collection-list\" ); // collection-list is in there for legacy purposes\n\t\t\tif( this.selectable ) this.$el.addClass( \"selectable\" );\n\n\t\t\tif( this.selectable && this.processKeyEvents )\n\t\t\t\tthis.$el.attr( \"tabindex\", 0 ); // so we get keyboard events\n\n\t\t\tthis.selectedItems = [];\n\n\t\t\tthis._updateItemTemplate();\n\n\t\t\tif( this.collection )\n\t\t\t\tthis._registerCollectionEvents();\n\n\t\t\tthis.viewManager = new ChildViewContainer();\n\t\t},\n\n\t\t_onOptionsChanged : function( changedOptions, originalOptions ) {\n\t\t\tvar _this = this;\n\t\t\tvar rerender = false;\n\n\t\t\t_.each( _.keys( changedOptions ), function( changedOptionKey ) {\n\t\t\t\tvar newVal = changedOptions[ changedOptionKey ];\n\t\t\t\tvar oldVal = originalOptions[ changedOptionKey ];\n\t\t\t\tswitch( changedOptionKey ) {\n\t\t\t\t\tcase \"collection\" :\n\t\t\t\t\t\tif ( newVal !== oldVal ) {\n\t\t\t\t\t\t\t_this.stopListening( oldVal );\n\t\t\t\t\t\t\t_this._registerCollectionEvents();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"selectMultiple\" :\n\t\t\t\t\t\tif( ! newVal && _this.selectedItems.length > 1 )\n\t\t\t\t\t\t\t_this.setSelectedModel( _.first( _this.selectedItems ), { by : \"cid\" } );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"selectable\" :\n\t\t\t\t\t\tif( ! newVal && _this.selectedItems.length > 0 )\n\t\t\t\t\t\t\t_this.setSelectedModels( [] );\n\n\t\t\t\t\t\tif( newVal && this.processKeyEvents ) _this.$el.attr( \"tabindex\", 0 ); // so we get keyboard events\n\t\t\t\t\t\telse _this.$el.removeAttr( \"tabindex\", 0 );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"sortable\" :\n\t\t\t\t\t\tchangedOptions.sortable ? _this._setupSortable() : _this.$el.sortable( \"destroy\" );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"selectableModelsFilter\" :\n\t\t\t\t\t\t_this.reapplyFilter( 'selectableModels' );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"sortableOptions\" :\n\t\t\t\t\t\t_this.$el.sortable( \"destroy\" );\n\t\t\t\t\t\t_this._setupSortable();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"sortableModelsFilter\" :\n\t\t\t\t\t\t_this.reapplyFilter( 'sortableModels' );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"visibleModelsFilter\" :\n\t\t\t\t\t\t_this.reapplyFilter( 'visibleModels' );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"itemTemplate\" :\n\t\t\t\t\t\t_this._updateItemTemplate();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"processKeyEvents\" :\n\t\t\t\t\t\tif( newVal && this.selectable ) _this.$el.attr( \"tabindex\", 0 ); // so we get keyboard events\n\t\t\t\t\t\telse _this.$el.removeAttr( \"tabindex\", 0 );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"modelView\" :\n\t\t\t\t\t\t//need to remove all old view instances\n\t\t\t\t\t\t_this.viewManager.each( function( view ) {\n\t\t\t\t\t\t\t_this.viewManager.remove( view );\n\t\t\t\t\t\t\t// destroy the View itself\n\t\t\t\t\t\t\tview.remove();\n\t\t\t\t\t\t} );\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif( _.contains( kOptionsRequiringRerendering, changedOptionKey ) ) rerender = true;\n\t\t\t} );\n\n\t\t\tif( this._hasBeenRendered && rerender ) {\n\t\t\t\tthis.render();\n\t\t\t}\n\t\t},\n\n\t\tsetOption : function( optionName, optionValue ) { // now is mearly a wrapper around backbone.viewOptions' setOptions()\n\t\t\tvar optionHash = {};\n\t\t\toptionHash[ optionName ] = optionValue;\n\t\t\tthis.setOptions( optionHash );\n\t\t},\n\n\t\tgetSelectedModel : function( options ) {\n\t\t\treturn this.selectedItems.length ? _.first( this.getSelectedModels( options ) ) : null;\n\t\t},\n\n\t\tgetSelectedModels : function ( options ) {\n\t\t\tvar _this = this;\n\n\t\t\toptions = _.extend( {}, {\n\t\t\t\tby : kDefaultReferenceBy\n\t\t\t}, options );\n\n\t\t\tvar referenceBy = options.by;\n\t\t\tvar items = [];\n\n\t\t\tswitch( referenceBy ) {\n\t\t\t\tcase \"id\" :\n\t\t\t\t\t_.each( this.selectedItems, function ( item ) {\n\t\t\t\t\t\titems.push( _this.collection.get( item ).id );\n\t\t\t\t\t} );\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"cid\" :\n\t\t\t\t\titems = items.concat( this.selectedItems );\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"offset\" :\n\t\t\t\t\tvar curLineNumber = 0;\n\n\t\t\t\t\tvar itemElements = this._getVisibleItemEls();\n\n\t\t\t\t\titemElements.each( function() {\n\t\t\t\t\t\tvar thisItemEl = $( this );\n\t\t\t\t\t\tif( thisItemEl.is( \".selected\" ) )\n\t\t\t\t\t\t\titems.push( curLineNumber );\n\t\t\t\t\t\tcurLineNumber++;\n\t\t\t\t\t} );\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"model\" :\n\t\t\t\t\t_.each( this.selectedItems, function ( item ) {\n\t\t\t\t\t\titems.push( _this.collection.get( item ) );\n\t\t\t\t\t} );\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"view\" :\n\t\t\t\t\t_.each( this.selectedItems, function ( item ) {\n\t\t\t\t\t\titems.push( _this.viewManager.findByModel( _this.collection.get( item ) ) );\n\t\t\t\t\t} );\n\t\t\t\t\tbreak;\n\t\t\t\tdefault :\n\t\t\t\t\tthrow new Error( \"Invalid referenceBy option: \" + referenceBy );\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\treturn items;\n\n\t\t},\n\n\t\tsetSelectedModels : function( newSelectedItems, options ) {\n\t\t\tif( ! _.isArray( newSelectedItems ) ) throw \"Invalid parameter value\";\n\t\t\tif( ! this.selectable && newSelectedItems.length > 0 ) return; // used to throw error, but there are some circumstances in which a list can be selectable at times and not at others, don't want to have to worry about catching errors\n\n\t\t\toptions = _.extend( {}, {\n\t\t\t\tsilent : false,\n\t\t\t\tby : kDefaultReferenceBy\n\t\t\t}, options );\n\n\t\t\tvar referenceBy = options.by;\n\t\t\tvar newSelectedCids = [];\n\n\t\t\tswitch( referenceBy ) {\n\t\t\t\tcase \"cid\" :\n\t\t\t\t\tnewSelectedCids = newSelectedItems;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"id\" :\n\t\t\t\t\tthis.collection.each( function( thisModel ) {\n\t\t\t\t\t\tif( _.contains( newSelectedItems, thisModel.id ) ) newSelectedCids.push( thisModel.cid );\n\t\t\t\t\t} );\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"model\" :\n\t\t\t\t\tnewSelectedCids = _.pluck( newSelectedItems, \"cid\" );\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"view\" :\n\t\t\t\t\t_.each( newSelectedItems, function( item ) {\n\t\t\t\t\t\tnewSelectedCids.push( item.model.cid );\n\t\t\t\t\t} );\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"offset\" :\n\t\t\t\t\tvar curLineNumber = 0;\n\t\t\t\t\tvar selectedItems = [];\n\n\t\t\t\t\tvar itemElements = this._getVisibleItemEls();\n\t\t\t\t\titemElements.each( function() {\n\t\t\t\t\t\tvar thisItemEl = $( this );\n\t\t\t\t\t\tif( _.contains( newSelectedItems, curLineNumber ) )\n\t\t\t\t\t\t\tnewSelectedCids.push( thisItemEl.attr( \"data-model-cid\" ) );\n\t\t\t\t\t\tcurLineNumber++;\n\t\t\t\t\t} );\n\t\t\t\t\tbreak;\n\t\t\t\tdefault :\n\t\t\t\t\tthrow new Error( \"Invalid referenceBy option: \" + referenceBy );\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tvar oldSelectedModels = this.getSelectedModels();\n\t\t\tvar oldSelectedCids = _.clone( this.selectedItems );\n\n\t\t\tthis.selectedItems = this._convertStringsToInts( newSelectedCids );\n\t\t\tthis._validateSelection();\n\n\t\t\tvar newSelectedModels = this.getSelectedModels();\n\n\t\t\tif( ! this._containSameElements( oldSelectedCids, this.selectedItems ) )\n\t\t\t{\n\t\t\t\tthis._addSelectedClassToSelectedItems( oldSelectedCids );\n\n\t\t\t\tif( ! options.silent )\n\t\t\t\t{\n\t\t\t\t\tif( this._isBackboneCourierAvailable() ) {\n\t\t\t\t\t\tthis.spawn( \"selectionChanged\", {\n\t\t\t\t\t\t\tselectedModels : newSelectedModels,\n\t\t\t\t\t\t\toldSelectedModels : oldSelectedModels\n\t\t\t\t\t\t} );\n\t\t\t\t\t} else this.trigger( \"selectionChanged\", newSelectedModels, oldSelectedModels );\n\t\t\t\t}\n\n\t\t\t\tthis.updateDependentControls();\n\t\t\t}\n\t\t},\n\n\t\tsetSelectedModel : function( newSelectedItem, options ) {\n\t\t\tif( ! newSelectedItem && newSelectedItem !== 0 )\n\t\t\t\tthis.setSelectedModels( [], options );\n\t\t\telse\n\t\t\t\tthis.setSelectedModels( [ newSelectedItem ], options );\n\t\t},\n\n\t\tgetView : function( reference, options ) {\n\t\t\toptions = _.extend( {}, {\n\t\t\t\tby : kDefaultReferenceBy\n\t\t\t}, options );\n\n\t\t\tswitch( options.by ) {\n\t\t\t\tcase \"id\" :\n\t\t\t\tcase \"cid\" :\n\t\t\t\t\tvar model = this.collection.get( reference ) || null;\n\t\t\t\t\treturn model && this.viewManager.findByModel( model );\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"offset\" :\n\t\t\t\t\tvar itemElements = this._getVisibleItemEls();\n\t\t\t\t\treturn $( itemElements.get( reference ) );\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"model\" :\n\t\t\t\t\treturn this.viewManager.findByModel( reference );\n\t\t\t\t\tbreak;\n\t\t\t\tdefault :\n\t\t\t\t\tthrow new Error( \"Invalid referenceBy option: \" + referenceBy );\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t},\n\n\t\trender : function() {\n\t\t\tvar _this = this;\n\n\t\t\tthis._hasBeenRendered = true;\n\n\t\t\tif( this.selectable ) this._saveSelection();\n\n\t\t\tvar modelViewContainerEl;\n\n\t\t\t// If collection view element is a table and it has a tbody\n\t\t\t// within it, render the model views inside of the tbody\n\t\t\tmodelViewContainerEl = this._getContainerEl();\n\n\t\t\tvar oldViewManager = this.viewManager;\n\t\t\tthis.viewManager = new ChildViewContainer();\n\n\t\t\t// detach each of our subviews that we have already created to represent models\n\t\t\t// in the collection. We are going to re-use the ones that represent models that\n\t\t\t// are still here, instead of creating new ones, so that we don't loose state\n\t\t\t// information in the views.\n\t\t\toldViewManager.each( function( thisModelView ) {\n\t\t\t\t// to boost performance, only detach those views that will be sticking around.\n\t\t\t\t// we won't need the other ones later, so no need to detach them individually.\n\t\t\t\tif( this.reuseModelViews && this.collection.get( thisModelView.model.cid ) ) {\n\t\t\t\t\tthisModelView.$el.detach();\n\t\t\t\t} else thisModelView.remove();\n\t\t\t}, this );\n\n\t\t\tmodelViewContainerEl.empty();\n\t\t\tvar fragmentContainer;\n\n\t\t\tif( this.detachedRendering )\n\t\t\t\tfragmentContainer = document.createDocumentFragment();\n\n\t\t\tthis.collection.each( function( thisModel ) {\n\t\t\t\tvar thisModelView = oldViewManager.findByModelCid( thisModel.cid );\n\t\t\t\tif( ! this.reuseModelViews || _.isUndefined( thisModelView ) ) {\n\t\t\t\t\t// if the model view has not already been created on a\n\t\t\t\t\t// previous render then create and initialize it now.\n\t\t\t\t\tthisModelView = this._createNewModelView( thisModel, this._getModelViewOptions( thisModel ) );\n\t\t\t\t}\n\n\t\t\t\tthis._insertAndRenderModelView( thisModelView, fragmentContainer || modelViewContainerEl );\n\t\t\t}, this );\n\n\t\t\tif( this.detachedRendering )\n\t\t\t\tmodelViewContainerEl.append( fragmentContainer );\n\n\t\t\tif( this.sortable ) this._setupSortable();\n\n\t\t\tthis._showEmptyListCaptionIfAppropriate();\n\n\t\t\tif( this._isBackboneCourierAvailable() )\n\t\t\t\tthis.spawn( \"render\" );\n\t\t\telse this.trigger( \"render\" );\n\n\t\t\tif( this.selectable ) {\n\t\t\t\tthis._restoreSelection();\n\t\t\t\tthis.updateDependentControls();\n\t\t\t}\n\n\t\t\tthis.forceRerenderOnNextSortEvent = false;\n\t\t},\n\n\t\t_showEmptyListCaptionIfAppropriate : function ( ) {\n\t\t\tthis._removeEmptyListCaption();\n\n\t\t\tif( this.emptyListCaption ) {\n\t\t\t\tvar visibleEls = this._getVisibleItemEls();\n\n\t\t\t\tif( visibleEls.length === 0 ) {\n\t\t\t\t\tvar emptyListString;\n\n\t\t\t\t\tif( _.isFunction( this.emptyListCaption ) )\n\t\t\t\t\t\temptyListString = this.emptyListCaption();\n\t\t\t\t\telse\n\t\t\t\t\t\temptyListString = this.emptyListCaption;\n\n\t\t\t\t\tvar $emptyListCaptionEl;\n\t\t\t\t\tvar $varEl = $( \"\" + emptyListString + \" \" );\n\n\t\t\t\t\t// need to wrap the empty caption to make it fit the rendered list structure (either with an li or a tr td)\n\t\t\t\t\tif( this._isRenderedAsList() )\n\t\t\t\t\t\t$emptyListCaptionEl = $varEl.wrapAll( \" \" ).parent().css( kStylesForEmptyListCaption );\n\t\t\t\t\telse\n\t\t\t\t\t\t$emptyListCaptionEl = $varEl.wrapAll( \" \" ).parent().parent().css( kStylesForEmptyListCaption );\n\n\t\t\t\t\tthis._getContainerEl().append( $emptyListCaptionEl );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t_removeEmptyListCaption : function( ) {\n\t\t\tif( this._isRenderedAsList() )\n\t\t\t\tthis._getContainerEl().find( \"> li > var.empty-list-caption\" ).parent().remove();\n\t\t\telse\n\t\t\t\tthis._getContainerEl().find( \"> tr > td > var.empty-list-caption\" ).parent().parent().remove();\n\t\t},\n\n\t\t// Render a single model view in container object \"parentElOrDocumentFragment\", which is either\n\t\t// a documentFragment or a jquery object. optional arg atIndex is not support for document fragments.\n\t\t_insertAndRenderModelView : function( modelView, parentElOrDocumentFragment, atIndex ) {\n\t\t\tvar thisModelViewWrapped = this._wrapModelView( modelView );\n\n\t\t\tif( parentElOrDocumentFragment.nodeType === 11 ) // if we are inserting into a document fragment, we need to use the DOM appendChild method\n\t\t\t\tparentElOrDocumentFragment.appendChild( thisModelViewWrapped.get( 0 ) );\n\t\t\telse {\n\t\t\t\tvar numberOfModelViewsCurrentlyInDOM = parentElOrDocumentFragment.children().length;\n\t\t\t\tif( ! _.isUndefined( atIndex ) && atIndex >= 0 && atIndex < numberOfModelViewsCurrentlyInDOM )\n\t\t\t\t\t// note this.collection.length might be greater than parentElOrDocumentFragment.children().length here\n\t\t\t\t\tparentElOrDocumentFragment.children().eq( atIndex ).before( thisModelViewWrapped );\n\t\t\t\telse {\n\t\t\t\t\t// if we are attempting to insert a modelView in an position that is beyond what is currently in the\n\t\t\t\t\t// DOM, then make a note that we need to re-render the collection view on the next sort event. If we dont\n\t\t\t\t\t// force this re-render, we can end up with modelViews in the wrong order when the collection defines\n\t\t\t\t\t// a comparator and multiple models are added at once. See https://github.com/rotundasoftware/backbone.collectionView/issues/69\n\t\t\t\t\tif( ! _.isUndefined( atIndex ) && atIndex > numberOfModelViewsCurrentlyInDOM ) this.forceRerenderOnNextSortEvent = true;\n\n\t\t\t\t\tparentElOrDocumentFragment.append( thisModelViewWrapped );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.viewManager.add( modelView );\n\n\t\t\t// we have to render the modelView after it has been put in context, as opposed to in the\n\t\t\t// initialize function of the modelView, because some rendering might be dependent on\n\t\t\t// the modelView's context in the DOM tree. For example, if the modelView stretch()'s itself,\n\t\t\t// it must be in full context in the DOM tree or else the stretch will not behave as intended.\n\t\t\tvar renderResult = modelView.render();\n\n\t\t\t// return false from the view's render function to hide this item\n\t\t\tif( renderResult === false ) {\n\t\t\t\tthisModelViewWrapped.hide();\n\t\t\t\tthisModelViewWrapped.addClass( \"not-visible\" );\n\t\t\t}\n\n\t\t\tvar hideThisModelView = false;\n\t\t\tif( _.isFunction( this.visibleModelsFilter ) )\n\t\t\t\thideThisModelView = ! this.visibleModelsFilter( modelView.model );\n\n\t\t\tif( thisModelViewWrapped.children().length === 1 )\n\t\t\t\tthisModelViewWrapped.toggle( ! hideThisModelView );\n\t\t\telse modelView.$el.toggle( ! hideThisModelView );\n\n\t\t\tthisModelViewWrapped.toggleClass( \"not-visible\", hideThisModelView );\n\n\t\t\tif( ! hideThisModelView && this.emptyListCaption ) this._removeEmptyListCaption();\n\t\t},\n\n\t\tupdateDependentControls : function() {\n\t\t\tif( this._isBackboneCourierAvailable() ) {\n\t\t\t\tthis.spawn( \"updateDependentControls\", {\n\t\t\t\t\tselectedModels : this.getSelectedModels()\n\t\t\t\t} );\n\t\t\t} else this.trigger( \"updateDependentControls\", this.getSelectedModels() );\n\t\t},\n\n\t\t// Override `Backbone.View.remove` to also destroy all Views in `viewManager`\n\t\tremove : function() {\n\t\t\tthis.viewManager.each( function( view ) {\n\t\t\t\tview.remove();\n\t\t\t} );\n\n\t\t\tBackbone.View.prototype.remove.apply( this, arguments );\n\t\t},\n\n\t\treapplyFilter : function( whichFilter ) {\n\t\t\tvar _this = this;\n\n\t\t\tif( ! _.contains( [ \"selectableModels\", \"sortableModels\", \"visibleModels\" ], whichFilter ) ) {\n\t\t\t\tthrow new Error( \"Invalid filter identifier supplied to reapplyFilter: \" + whichFilter );\n\t\t\t}\n\n\t\t\tswitch( whichFilter ) {\n\t\t\t\tcase \"visibleModels\":\n\t\t\t\t\t_this.viewManager.each( function( thisModelView ) {\n\t\t\t\t\t\tvar notVisible = _this.visibleModelsFilter && ! _this.visibleModelsFilter.call( _this, thisModelView.model );\n\n\t\t\t\t\t\tthisModelView.$el.toggleClass( \"not-visible\", notVisible );\n\t\t\t\t\t\tif( _this._modelViewHasWrapperLI( thisModelView ) ) {\n\t\t\t\t\t\t\tthisModelView.$el.closest( \"li\" ).toggleClass( \"not-visible\", notVisible ).toggle( ! notVisible );\n\t\t\t\t\t\t} else thisModelView.$el.toggle( ! notVisible );\n\t\t\t\t\t} );\n\n\t\t\t\t\tthis._showEmptyListCaptionIfAppropriate();\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"sortableModels\":\n\t\t\t\t\t_this.$el.sortable( \"destroy\" );\n\n\t\t\t\t\t_this.viewManager.each( function( thisModelView ) {\n\t\t\t\t\t\tvar notSortable = _this.sortableModelsFilter && ! _this.sortableModelsFilter.call( _this, thisModelView.model );\n\n\t\t\t\t\t\tthisModelView.$el.toggleClass( \"not-sortable\", notSortable );\n\t\t\t\t\t\tif( _this._modelViewHasWrapperLI( thisModelView ) ) {\n\t\t\t\t\t\t\tthisModelView.$el.closest( \"li\" ).toggleClass( \"not-sortable\", notSortable );\n\t\t\t\t\t\t}\n\t\t\t\t\t} );\n\n\t\t\t\t\t_this._setupSortable();\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"selectableModels\":\n\t\t\t\t\t_this.viewManager.each( function( thisModelView ) {\n\t\t\t\t\t\tvar notSelectable = _this.selectableModelsFilter && ! _this.selectableModelsFilter.call( _this, thisModelView.model );\n\n\t\t\t\t\t\tthisModelView.$el.toggleClass( \"not-selectable\", notSelectable );\n\t\t\t\t\t\tif( _this._modelViewHasWrapperLI( thisModelView ) ) {\n\t\t\t\t\t\t\tthisModelView.$el.closest( \"li\" ).toggleClass( \"not-selectable\", notSelectable );\n\t\t\t\t\t\t}\n\t\t\t\t\t} );\n\n\t\t\t\t\t_this._validateSelection();\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t},\n\n\t\t// A method to remove the view relating to model.\n\t\t_removeModelView : function( modelView ) {\n\t\t\tif( this.selectable ) this._saveSelection();\n\n\t\t\tthis.viewManager.remove( modelView ); // Remove the view from the viewManager\n\t\t\tif( this._modelViewHasWrapperLI( modelView ) ) modelView.$el.parent().remove(); // Remove the li wrapper from the DOM\n\t\t\tmodelView.remove(); // Remove the view from the DOM and stop listening to events\n\n\t\t\tif( this.selectable ) this._restoreSelection();\n\n\t\t\tthis._showEmptyListCaptionIfAppropriate();\n\t\t},\n\n\t\t_validateSelectionAndRender : function() {\n\t\t\tthis._validateSelection();\n\t\t\tthis.render();\n\t\t},\n\n\t\t_registerCollectionEvents : function() {\n\n\t\t\tthis.listenTo( this.collection, \"add\", function( model ) {\n\t\t\t\tvar modelView;\n\t\t\t\tif( this._hasBeenRendered ) {\n\t\t\t\t\tmodelView = this._createNewModelView( model, this._getModelViewOptions( model ) );\n\t\t\t\t\tthis._insertAndRenderModelView( modelView, this._getContainerEl(), this.collection.indexOf( model ) );\n\t\t\t\t}\n\n\t\t\t\tif( this._isBackboneCourierAvailable() )\n\t\t\t\t\tthis.spawn( \"add\", modelView );\n\t\t\t\telse this.trigger( \"add\", modelView );\n\t\t\t} );\n\n\t\t\tthis.listenTo( this.collection, \"remove\", function( model ) {\n\t\t\t\tvar modelView;\n\n\t\t\t\tif( this._hasBeenRendered ) {\n\t\t\t\t\tmodelView = this.viewManager.findByModelCid( model.cid );\n\t\t\t\t\tthis._removeModelView( modelView );\n\t\t\t\t}\n\n\t\t\t\tif( this._isBackboneCourierAvailable() )\n\t\t\t\t\tthis.spawn( \"remove\" );\n\t\t\t\telse this.trigger( \"remove\" );\n\t\t\t} );\n\n\t\t\tthis.listenTo( this.collection, \"reset\", function() {\n\t\t\t\tif( this._hasBeenRendered ) this.render();\n\t\t\t\tif( this._isBackboneCourierAvailable() )\n\t\t\t\t\tthis.spawn( \"reset\" );\n\t\t\t\telse this.trigger( \"reset\" );\n\t\t\t} );\n\n\t\t\t// we should not be listening to change events on the model as a default behavior. the models\n\t\t\t// should be responsible for re-rendering themselves if necessary, and if the collection does\n\t\t\t// also need to re-render as a result of a model change, this should be handled by overriding\n\t\t\t// this method. by default the collection view should not re-render in response to model changes\n\t\t\t// this.listenTo( this.collection, \"change\", function( model ) {\n\t\t\t// \tif( this._hasBeenRendered ) this.viewManager.findByModel( model ).render();\n\t\t\t// \tif( this._isBackboneCourierAvailable() )\n\t\t\t// \t\tthis.spawn( \"change\", { model : model } );\n\t\t\t// } );\n\n\t\t\tthis.listenTo( this.collection, \"sort\", function( collection, options ) {\n\t\t\t\tif( this._hasBeenRendered && ( options.add !== true || this.forceRerenderOnNextSortEvent ) ) this.render();\n\t\t\t\tif( this._isBackboneCourierAvailable() )\n\t\t\t\t\tthis.spawn( \"sort\" );\n\t\t\t\telse this.trigger( \"sort\" );\n\t\t\t} );\n\t\t},\n\n\t\t_getContainerEl : function() {\n\t\t\tif ( this._isRenderedAsTable() ) {\n\t\t\t\t// not all tables have a tbody, so we test\n\t\t\t\tvar tbody = this.$el.find( \"> tbody\" );\n\t\t\t\tif ( tbody.length > 0 )\n\t\t\t\t\treturn tbody;\n\t\t\t}\n\t\t\treturn this.$el;\n\t\t},\n\n\t\t_getClickedItemId : function( theEvent ) {\n\t\t\tvar clickedItemId = null;\n\n\t\t\t// important to use currentTarget as opposed to target, since we could be bubbling\n\t\t\t// an event that took place within another collectionList\n\t\t\tvar clickedItemEl = $( theEvent.currentTarget );\n\t\t\tif( clickedItemEl.closest( \".collection-view\" ).get(0) !== this.$el.get(0) ) return;\n\n\t\t\t// determine which list item was clicked. If we clicked in the blank area\n\t\t\t// underneath all the elements, we want to know that too, since in this\n\t\t\t// case we will want to deselect all elements. so check to see if the clicked\n\t\t\t// DOM element is the list itself to find that out.\n\t\t\tvar clickedItem = clickedItemEl.closest( \"[data-model-cid]\" );\n\t\t\tif( clickedItem.length > 0 )\n\t\t\t{\n\t\t\t\tclickedItemId = clickedItem.attr( \"data-model-cid\" );\n\t\t\t\tif( $.isNumeric( clickedItemId ) ) clickedItemId = parseInt( clickedItemId, 10 );\n\t\t\t}\n\n\t\t\treturn clickedItemId;\n\t\t},\n\n\t\t_updateItemTemplate : function() {\n\t\t\tvar itemTemplateHtml;\n\t\t\tif( this.itemTemplate )\n\t\t\t{\n\t\t\t\tif( $( this.itemTemplate ).length === 0 )\n\t\t\t\t\tthrow \"Could not find item template from selector: \" + this.itemTemplate;\n\n\t\t\t\titemTemplateHtml = $( this.itemTemplate ).html();\n\t\t\t}\n\t\t\telse\n\t\t\t\titemTemplateHtml = this.$( \".item-template\" ).html();\n\n\t\t\tif( itemTemplateHtml ) this.itemTemplateFunction = _.template( itemTemplateHtml );\n\n\t\t},\n\n\t\t_validateSelection : function() {\n\t\t\t// note can't use the collection's proxy to underscore because \"cid\" is not an attribute,\n\t\t\t// but an element of the model object itself.\n\t\t\tvar modelReferenceIds = _.pluck( this.collection.models, \"cid\" );\n\t\t\tthis.selectedItems = _.intersection( modelReferenceIds, this.selectedItems );\n\n\t\t\tif( _.isFunction( this.selectableModelsFilter ) )\n\t\t\t{\n\t\t\t\tthis.selectedItems = _.filter( this.selectedItems, function( thisItemId ) {\n\t\t\t\t\treturn this.selectableModelsFilter.call( this, this.collection.get( thisItemId ) );\n\t\t\t\t}, this );\n\t\t\t}\n\t\t},\n\n\t\t_saveSelection : function() {\n\t\t\t// save the current selection. use restoreSelection() to restore the selection to the state it was in the last time saveSelection() was called.\n\t\t\tif( ! this.selectable ) throw \"Attempt to save selection on non-selectable list\";\n\t\t\tthis.savedSelection = {\n\t\t\t\titems : _.clone( this.selectedItems ),\n\t\t\t\toffset : this.getSelectedModel( { by : \"offset\" } )\n\t\t\t};\n\t\t},\n\n\t\t_restoreSelection : function() {\n\t\t\tif( ! this.savedSelection ) throw \"Attempt to restore selection but no selection has been saved!\";\n\n\t\t\t// reset selectedItems to empty so that we \"redraw\" all \"selected\" classes\n\t\t\t// when we set our new selection. We do this because it is likely that our\n\t\t\t// contents have been refreshed, and we have thus lost all old \"selected\" classes.\n\t\t\tthis.setSelectedModels( [], { silent : true } );\n\n\t\t\tif( this.savedSelection.items.length > 0 )\n\t\t\t{\n\t\t\t\t// first try to restore the old selected items using their reference ids.\n\t\t\t\tthis.setSelectedModels( this.savedSelection.items, { by : \"cid\", silent : true } );\n\n\t\t\t\t// all the items with the saved reference ids have been removed from the list.\n\t\t\t\t// ok. try to restore the selection based on the offset that used to be selected.\n\t\t\t\t// this is the expected behavior after a item is deleted from a list (i.e. select\n\t\t\t\t// the line that immediately follows the deleted line).\n\t\t\t\tif( this.selectedItems.length === 0 )\n\t\t\t\t\tthis.setSelectedModel( this.savedSelection.offset, { by : \"offset\" } );\n\n\t\t\t\t// Trigger a selection changed if the previously selected items were not all found\n\t\t\t\tif (this.selectedItems.length !== this.savedSelection.items.length)\n\t\t\t\t{\n\t\t\t\t\tif( this._isBackboneCourierAvailable() ) {\n\t\t\t\t\t\tthis.spawn( \"selectionChanged\", {\n\t\t\t\t\t\t\tselectedModels : this.getSelectedModels(),\n\t\t\t\t\t\t\toldSelectedModels : []\n\t\t\t\t\t\t} );\n\t\t\t\t\t} else this.trigger( \"selectionChanged\", this.getSelectedModels(), [] );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t_addSelectedClassToSelectedItems : function( oldItemsIdsWithSelectedClass ) {\n\t\t\tif( _.isUndefined( oldItemsIdsWithSelectedClass ) ) oldItemsIdsWithSelectedClass = [];\n\n\t\t\t// oldItemsIdsWithSelectedClass is used for optimization purposes only. If this info is supplied then we\n\t\t\t// only have to add / remove the \"selected\" class from those items that \"selected\" state has changed.\n\n\t\t\tvar itemsIdsFromWhichSelectedClassNeedsToBeRemoved = oldItemsIdsWithSelectedClass;\n\t\t\titemsIdsFromWhichSelectedClassNeedsToBeRemoved = _.without( itemsIdsFromWhichSelectedClassNeedsToBeRemoved, this.selectedItems );\n\n\t\t\t_.each( itemsIdsFromWhichSelectedClassNeedsToBeRemoved, function( thisItemId ) {\n\t\t\t\tthis._getContainerEl().find( \"[data-model-cid=\" + thisItemId + \"]\" ).removeClass( \"selected\" );\n\n\t\t\t\tif( this._isRenderedAsList() ) {\n\t\t\t\t\tthis._getContainerEl().find( \"li[data-model-cid=\" + thisItemId + \"] > *\" ).removeClass( \"selected\" );\n\t\t\t\t}\n\t\t\t}, this );\n\n\t\t\tvar itemsIdsFromWhichSelectedClassNeedsToBeAdded = this.selectedItems;\n\t\t\titemsIdsFromWhichSelectedClassNeedsToBeAdded = _.without( itemsIdsFromWhichSelectedClassNeedsToBeAdded, oldItemsIdsWithSelectedClass );\n\n\t\t\t_.each( itemsIdsFromWhichSelectedClassNeedsToBeAdded, function( thisItemId ) {\n\t\t\t\tthis._getContainerEl().find( \"[data-model-cid=\" + thisItemId + \"]\" ).addClass( \"selected\" );\n\n\t\t\t\tif( this._isRenderedAsList() ) {\n\t\t\t\t\tthis._getContainerEl().find( \"li[data-model-cid=\" + thisItemId + \"] > *\" ).addClass( \"selected\" );\n\t\t\t\t}\n\t\t\t}, this );\n\t\t},\n\n\t\t_reorderCollectionBasedOnHTML : function() {\n\n\t\t\tvar _this = this;\n\n\t\t\tthis._getContainerEl().children().each( function() {\n\t\t\t\tvar thisModelCid = $( this ).attr( \"data-model-cid\" );\n\n\t\t\t\tif( thisModelCid )\n\t\t\t\t{\n\t\t\t\t\t// remove the current model and then add it back (at the end of the collection).\n\t\t\t\t\t// When we are done looping through all models, they will be in the correct order.\n\t\t\t\t\tvar thisModel = _this.collection.get( thisModelCid );\n\t\t\t\t\tif( thisModel )\n\t\t\t\t\t{\n\t\t\t\t\t\t_this.collection.remove( thisModel, { silent : true } );\n\t\t\t\t\t\t_this.collection.add( thisModel, { silent : true, sort : ! _this.collection.comparator } );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\tif( this._isBackboneCourierAvailable() ) this.spawn( \"reorder\" );\n\t\t\telse this.collection.trigger( \"reorder\" );\n\n\t\t\tif( this.collection.comparator ) this.collection.sort();\n\n\t\t},\n\n\t\t_getModelViewConstructor : function( thisModel ) {\n\t\t\treturn this.modelView || mDefaultModelViewConstructor;\n\t\t},\n\n\t\t_getModelViewOptions : function( thisModel ) {\n\t\t\tvar modelViewOptions = this.modelViewOptions;\n\t\t\tif( _.isFunction( modelViewOptions ) ) modelViewOptions = modelViewOptions( thisModel );\n\n\t\t\treturn _.extend( { model : thisModel }, modelViewOptions );\n\t\t},\n\n\t\t_createNewModelView : function( model, modelViewOptions ) {\n\t\t\tvar modelViewConstructor = this._getModelViewConstructor( model );\n\t\t\tif( _.isUndefined( modelViewConstructor ) ) throw \"Could not find modelView constructor for model\";\n\n\t\t\tvar newModelView = new( modelViewConstructor )( modelViewOptions );\n\t\t\tnewModelView.collectionListView = newModelView.collectionView = this; // collectionListView for legacy\n\n\t\t\treturn newModelView;\n\t\t},\n\n\t\t_wrapModelView : function( modelView ) {\n\t\t\tvar _this = this;\n\n\t\t\t// we use items client ids as opposed to real ids, since we may not have a representation\n\t\t\t// of these models on the server\n\t\t\tvar modelViewWrapperEl;\n\n\t\t\tif( this._isRenderedAsTable() ) {\n\t\t\t\t// if we are rendering the collection in a table, the template $el is a tr so we just need to set the data-model-cid\n\t\t\t\tmodelViewWrapperEl = modelView.$el;\n\t\t\t\tmodelView.$el.attr( \"data-model-cid\", modelView.model.cid );\n\t\t\t}\n\t\t\telse if( this._isRenderedAsList() ) {\n\t\t\t\t// if we are rendering the collection in a list, we need wrap each item in an (if its not already an )\n\t\t\t\t// and set the data-model-cid\n\t\t\t\tif( modelView.$el.is( \"li\" ) ) {\n\t\t\t\t\tmodelViewWrapperEl = modelView.$el;\n\t\t\t\t\tmodelView.$el.attr( \"data-model-cid\", modelView.model.cid );\n\t\t\t\t} else {\n\t\t\t\t\tmodelViewWrapperEl = modelView.$el.wrapAll( \" \" ).parent();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif( _.isFunction( this.sortableModelsFilter ) )\n\t\t\t\tif( ! this.sortableModelsFilter.call( _this, modelView.model ) ) {\n\t\t\t\t\tmodelViewWrapperEl.addClass( \"not-sortable\" );\n\t\t\t\t\tmodelView.$el.addClass( \"not-selectable\" );\n\t\t\t\t}\n\n\t\t\tif( _.isFunction( this.selectableModelsFilter ) )\n\t\t\t\tif( ! this.selectableModelsFilter.call( _this, modelView.model ) ) {\n\t\t\t\t\tmodelViewWrapperEl.addClass( \"not-selectable\" );\n\t\t\t\t\tmodelView.$el.addClass( \"not-selectable\" );\n\t\t\t\t}\n\n\t\t\treturn modelViewWrapperEl;\n\t\t},\n\n\t\t_convertStringsToInts : function( theArray ) {\n\t\t\treturn _.map( theArray, function( thisEl ) {\n\t\t\t\tif( ! _.isString( thisEl ) ) return thisEl;\n\t\t\t\tvar thisElAsNumber = parseInt( thisEl, 10 );\n\t\t\t\treturn( thisElAsNumber == thisEl ? thisElAsNumber : thisEl );\n\t\t\t} );\n\t\t},\n\n\t\t_containSameElements : function( arrayA, arrayB ) {\n\t\t\tif( arrayA.length != arrayB.length ) return false;\n\t\t\tvar intersectionSize = _.intersection( arrayA, arrayB ).length;\n\t\t\treturn intersectionSize == arrayA.length; // and must also equal arrayB.length, since arrayA.length == arrayB.length\n\t\t},\n\n\t\t_isRenderedAsTable : function() {\n\t\t\treturn this.$el.prop( \"tagName\" ).toLowerCase() === \"table\";\n\t\t},\n\n\t\t_isRenderedAsList : function() {\n\t\t\treturn ! this._isRenderedAsTable();\n\t\t},\n\n\t\t_modelViewHasWrapperLI : function( modelView ) {\n\t\t\treturn this._isRenderedAsList() && ! modelView.$el.is( \"li\" );\n\t\t},\n\n\t\t// Returns the wrapper HTML element for each visible modelView.\n\t\t// When rendering in a table context, the returned elements are the $el of each modelView.\n\t\t// When rendering in a list context,\n\t\t// If the $el of the modelView is an , the returned elements are the $el of each modelView.\n\t\t// Otherwise, the returned elements are the 's the collectionView wrapped around each modelView $el.\n\t\t_getVisibleItemEls : function() {\n\t\t\tvar itemElements = [];\n\t\t\titemElements = this._getContainerEl().find( \"> [data-model-cid]:not(.not-visible)\" );\n\n\t\t\treturn itemElements;\n\t\t},\n\n\t\t_charCodes : {\n\t\t\tupArrow : 38,\n\t\t\tdownArrow : 40\n\t\t},\n\n\t\t_isBackboneCourierAvailable : function() {\n\t\t\treturn !_.isUndefined( Backbone.Courier );\n\t\t},\n\n\t\t_setupSortable : function() {\n\t\t\tvar sortableOptions = _.extend( {\n\t\t\t\taxis : \"y\",\n\t\t\t\tdistance : 10,\n\t\t\t\tforcePlaceholderSize : true,\n\t\t\t\titems : this._isRenderedAsTable() ? \"> tbody > tr:not(.not-sortable)\" : \"> li:not(.not-sortable)\",\n\t\t\t\tstart : _.bind( this._sortStart, this ),\n\t\t\t\tchange : _.bind( this._sortChange, this ),\n\t\t\t\tstop : _.bind( this._sortStop, this ),\n\t\t\t\treceive : _.bind( this._receive, this ),\n\t\t\t\tover : _.bind( this._over, this )\n\t\t\t}, _.result( this, \"sortableOptions\" ) );\n\n\t\t\tthis.$el = this.$el.sortable( sortableOptions );\n\t\t\t//this.$el.sortable( \"enable\" ); // in case it was disabled previously\n\t\t},\n\n\t\t_sortStart : function( event, ui ) {\n\t\t\tvar modelBeingSorted = this.collection.get( ui.item.attr( \"data-model-cid\" ) );\n\t\t\tif( this._isBackboneCourierAvailable() )\n\t\t\t\tthis.spawn( \"sortStart\", { modelBeingSorted : modelBeingSorted } );\n\t\t\telse this.trigger( \"sortStart\", modelBeingSorted );\n\t\t},\n\n\t\t_sortChange : function( event, ui ) {\n\t\t\tvar modelBeingSorted = this.collection.get( ui.item.attr( \"data-model-cid\" ) );\n\n\t\t\tif( this._isBackboneCourierAvailable() )\n\t\t\t\tthis.spawn( \"sortChange\", { modelBeingSorted : modelBeingSorted } );\n\t\t\telse this.trigger( \"sortChange\", modelBeingSorted );\n\t\t},\n\n\t\t_sortStop : function( event, ui ) {\n\t\t\tvar modelBeingSorted = this.collection.get( ui.item.attr( \"data-model-cid\" ) );\n\t\t\tvar modelViewContainerEl = this._getContainerEl();\n\t\t\tvar newIndex = modelViewContainerEl.children().index( ui.item );\n\n\t\t\tif( newIndex == -1 && modelBeingSorted ) {\n\t\t\t\t// the element was removed from this list. can happen if this sortable is connected\n\t\t\t\t// to another sortable, and the item was dropped into the other sortable.\n\t\t\t\tthis.collection.remove( modelBeingSorted );\n\t\t\t}\n\n\t\t\tif( ! modelBeingSorted ) return; // something is wacky. we don't mess with this case, preferring to guarantee that we can always provide a reference to the model\n\n\t\t\tthis._reorderCollectionBasedOnHTML();\n\t\t\tthis.updateDependentControls();\n\n\t\t\tif( this._isBackboneCourierAvailable() )\n\t\t\t\tthis.spawn( \"sortStop\", { modelBeingSorted : modelBeingSorted, newIndex : newIndex } );\n\t\t\telse this.trigger( \"sortStop\", modelBeingSorted, newIndex );\n\t\t},\n\n\t\t_receive : function( event, ui ) {\n\n\t\t\tvar senderListEl = ui.sender;\n\t\t\tvar senderCollectionListView = senderListEl.data( \"view\" );\n\t\t\tif( ! senderCollectionListView || ! senderCollectionListView.collection ) return;\n\n\t\t\tvar newIndex = this._getContainerEl().children().index( ui.item );\n\t\t\tvar modelReceived = senderCollectionListView.collection.get( ui.item.attr( \"data-model-cid\" ) );\n\t\t\tsenderCollectionListView.collection.remove( modelReceived );\n\t\t\tthis.collection.add( modelReceived, { at : newIndex } );\n\t\t\tmodelReceived.collection = this.collection; // otherwise will not get properly set, since modelReceived.collection might already have a value.\n\t\t\tthis.setSelectedModel( modelReceived );\n\t\t},\n\n\t\t_over : function( event, ui ) {\n\t\t\t// when an item is being dragged into the sortable,\n\t\t\t// hide the empty list caption if it exists\n\t\t\tthis._getContainerEl().find( \"> var.empty-list-caption\" ).hide();\n\t\t},\n\n\t\t_onKeydown : function( event ) {\n\t\t\tif( ! this.processKeyEvents ) return true;\n\n\t\t\tvar trap = false;\n\n\t\t\tif( this.getSelectedModels( { by : \"offset\" } ).length == 1 )\n\t\t\t{\n\t\t\t\t// need to trap down and up arrows or else the browser\n\t\t\t\t// will end up scrolling a autoscroll div.\n\n\t\t\t\tvar currentOffset = this.getSelectedModel( { by : \"offset\" } );\n\t\t\t\tif( event.which === this._charCodes.upArrow && currentOffset !== 0 )\n\t\t\t\t{\n\t\t\t\t\tthis.setSelectedModel( currentOffset - 1, { by : \"offset\" } );\n\t\t\t\t\ttrap = true;\n\t\t\t\t}\n\t\t\t\telse if( event.which === this._charCodes.downArrow && currentOffset !== this.collection.length - 1 )\n\t\t\t\t{\n\t\t\t\t\tthis.setSelectedModel( currentOffset + 1, { by : \"offset\" } );\n\t\t\t\t\ttrap = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn ! trap;\n\t\t},\n\n\t\t_listItem_onMousedown : function( theEvent ) {\n\t\t\tvar clickedItemId = this._getClickedItemId( theEvent );\n\n\t\t\tif( clickedItemId ) {\n\t\t\t\tvar clickedModel = this.collection.get( clickedItemId );\n\t\t\t\tif( this._isBackboneCourierAvailable() ) {\n\t\t\t\t\tvar data = {\n\t\t\t\t\t\tclickedModel : clickedModel,\n\t\t\t\t\t\tmetaKeyPressed : theEvent.ctrlKey || theEvent.metaKey\n\t\t\t\t\t};\n\n\t\t\t\t\t_.each( [ 'preventDefault', 'stopPropagation', 'stopImmediatePropagation' ], function( thisMethod ) {\n\t\t\t\t\t\tdata[ thisMethod ] = function() {\n\t\t\t\t\t\t\ttheEvent[ thisMethod ]();\n\t\t\t\t\t\t};\n\t\t\t\t\t} );\n\n\t\t\t\t\tthis.spawn( \"click\", data );\n\t\t\t\t}\n\t\t\t\telse this.trigger( \"click\", clickedModel );\n\t\t\t}\n\n\t\t\tif( ! this.selectable || ! this.clickToSelect ) return;\n\n\t\t\tif( clickedItemId )\n\t\t\t{\n\t\t\t\t// Exit if an unselectable item was clicked\n\t\t\t\tif( _.isFunction( this.selectableModelsFilter ) &&\n\t\t\t\t\t! this.selectableModelsFilter.call( this, this.collection.get( clickedItemId ) ) )\n\t\t\t\t{\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// a selectable list item was clicked\n\t\t\t\tif( this.selectMultiple && theEvent.shiftKey )\n\t\t\t\t{\n\t\t\t\t\tvar firstSelectedItemIndex = -1;\n\n\t\t\t\t\tif( this.selectedItems.length > 0 )\n\t\t\t\t\t{\n\t\t\t\t\t\tthis.collection.find( function( thisItemModel ) {\n\t\t\t\t\t\t\tfirstSelectedItemIndex++;\n\n\t\t\t\t\t\t\t// exit when we find our first selected element\n\t\t\t\t\t\t\treturn _.contains( this.selectedItems, thisItemModel.cid );\n\t\t\t\t\t\t}, this );\n\t\t\t\t\t}\n\n\t\t\t\t\tvar clickedItemIndex = -1;\n\t\t\t\t\tthis.collection.find( function( thisItemModel ) {\n\t\t\t\t\t\tclickedItemIndex++;\n\n\t\t\t\t\t\t// exit when we find the clicked element\n\t\t\t\t\t\treturn thisItemModel.cid == clickedItemId;\n\t\t\t\t\t}, this );\n\n\t\t\t\t\tvar shiftKeyRootSelectedItemIndex = firstSelectedItemIndex == -1 ? clickedItemIndex : firstSelectedItemIndex;\n\t\t\t\t\tvar minSelectedItemIndex = Math.min( clickedItemIndex, shiftKeyRootSelectedItemIndex );\n\t\t\t\t\tvar maxSelectedItemIndex = Math.max( clickedItemIndex, shiftKeyRootSelectedItemIndex );\n\n\t\t\t\t\tvar newSelectedItems = [];\n\t\t\t\t\tfor( var thisIndex = minSelectedItemIndex; thisIndex <= maxSelectedItemIndex; thisIndex ++ )\n\t\t\t\t\t\tnewSelectedItems.push( this.collection.at( thisIndex ).cid );\n\t\t\t\t\tthis.setSelectedModels( newSelectedItems, { by : \"cid\" } );\n\n\t\t\t\t\t// shift clicking will usually highlight selectable text, which we do not want.\n\t\t\t\t\t// this is a cross browser (hopefully) snippet that deselects all text selection.\n\t\t\t\t\tif( document.selection && document.selection.empty )\n\t\t\t\t\t\tdocument.selection.empty();\n\t\t\t\t\telse if(window.getSelection) {\n\t\t\t\t\t\tvar sel = window.getSelection();\n\t\t\t\t\t\tif( sel && sel.removeAllRanges )\n\t\t\t\t\t\t\tsel.removeAllRanges();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if( ( this.selectMultiple || _.contains( this.selectedItems, clickedItemId ) ) && ( this.clickToToggle || theEvent.metaKey || theEvent.ctrlKey ) )\n\t\t\t\t{\n\t\t\t\t\tif( _.contains( this.selectedItems, clickedItemId ) )\n\t\t\t\t\t\tthis.setSelectedModels( _.without( this.selectedItems, clickedItemId ), { by : \"cid\" } );\n\t\t\t\t\telse this.setSelectedModels( _.union( this.selectedItems, [clickedItemId] ), { by : \"cid\" } );\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tthis.setSelectedModels( [ clickedItemId ], { by : \"cid\" } );\n\t\t\t}\n\t\t\telse\n\t\t\t\t// the blank area of the list was clicked\n\t\t\t\tthis.setSelectedModels( [] );\n\n\t\t},\n\n\t\t_listItem_onDoubleClick : function( theEvent ) {\n\n\t\t\tvar clickedItemId = this._getClickedItemId( theEvent );\n\n\t\t\tif( clickedItemId )\n\t\t\t{\n\t\t\t\tvar clickedModel = this.collection.get( clickedItemId );\n\n\t\t\t\tif( this._isBackboneCourierAvailable() )\n\t\t\t\t\tthis.spawn( \"doubleClick\", { clickedModel : clickedModel, metaKeyPressed : theEvent.ctrlKey || theEvent.metaKey } );\n\t\t\t\telse this.trigger( \"doubleClick\", clickedModel );\n\t\t\t}\n\t\t},\n\n\t\t_listBackground_onClick : function( theEvent ) {\n\t\t\tif( ! this.selectable || ! this.clickToSelect ) return;\n\t\t\tif( ! $( theEvent.target ).is( \".collection-view\" ) ) return;\n\n\t\t\tthis.setSelectedModels( [] );\n\t\t}\n\n\t}, {\n\t\tsetDefaultModelViewConstructor : function( theConstructor ) {\n\t\t\tmDefaultModelViewConstructor = theConstructor;\n\t\t}\n\t});\n\n\t/*\n\t* Backbone.ViewOptions, v0.2.4\n\t* Copyright (c)2014 Rotunda Software, LLC.\n\t* Distributed under MIT license\n\t* http://github.com/rotundasoftware/backbone.viewOptions\n\t*/\n\n\tBackbone.ViewOptions = {};\n\n\tBackbone.ViewOptions.add = function( view, optionsDeclarationsProperty ) {\n\t\tif( _.isUndefined( optionsDeclarationsProperty ) ) optionsDeclarationsProperty = \"options\";\n\n\t\t// ****************** Public methods added to view ******************\n\n\t\tview.setOptions = function( options ) {\n\t\t\tvar _this = this;\n\t\t\tvar optionsThatWereChanged = {};\n\t\t\tvar optionsThatWereChangedPreviousValues = {};\n\n\t\t\tvar optionDeclarations = _.result( this, optionsDeclarationsProperty );\n\n\t\t\tif( ! _.isUndefined( optionDeclarations ) ) {\n\t\t\t\tvar normalizedOptionDeclarations = _normalizeOptionDeclarations( optionDeclarations );\n\n\t\t\t\t_.each( normalizedOptionDeclarations, function( thisOptionProperties, thisOptionName ) {\n\t\t\t\t\tvar thisOptionRequired = thisOptionProperties.required;\n\t\t\t\t\tvar thisOptionDefaultValue = thisOptionProperties.defaultValue;\n\n\t\t\t\t\tif( thisOptionRequired ) {\n\t\t\t\t\t\t// note we do not throw an error if a required option is not supplied, but it is\n\t\t\t\t\t\t// found on the object itself (due to a prior call of view.setOptions, most likely)\n\n\t\t\t\t\t\tif( ( ! options || ! _.contains( _.keys( options ), thisOptionName ) ) && _.isUndefined( _this[ thisOptionName ] ) )\n\t\t\t\t\t\t\tthrow new Error( \"Required option \\\"\" + thisOptionName + \"\\\" was not supplied.\" );\n\n\t\t\t\t\t\tif( options && _.contains( _.keys( options ), thisOptionName ) && _.isUndefined( options[ thisOptionName ] ) )\n\t\t\t\t\t\t\tthrow new Error( \"Required option \\\"\" + thisOptionName + \"\\\" can not be set to undefined.\" );\n\t\t\t\t\t}\n\n\t\t\t\t\t// attach the supplied value of this option, or the appropriate default value, to the view object\n\t\t\t\t\tif( options && thisOptionName in options && ! _.isUndefined( options[ thisOptionName ] ) ) {\n\t\t\t\t\t\tvar oldValue = _this[ thisOptionName ];\n\t\t\t\t\t\tvar newValue = options[ thisOptionName ];\n\t\t\t\t\t\t// if this option already exists on the view, and the new value is different,\n\t\t\t\t\t\t// make a note that we will be changing it\n\t\t\t\t\t\tif( ! _.isUndefined( oldValue ) && oldValue !== newValue ) {\n\t\t\t\t\t\t\toptionsThatWereChangedPreviousValues[ thisOptionName ] = oldValue;\n\t\t\t\t\t\t\toptionsThatWereChanged[ thisOptionName ] = newValue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t_this[ thisOptionName ] = newValue;\n\t\t\t\t\t\t// note we do NOT delete the option off the options object here so that\n\t\t\t\t\t\t// multiple views can be passed the same options object without issue.\n\t\t\t\t\t}\n\t\t\t\t\telse if( _.isUndefined( _this[ thisOptionName ] ) ) {\n\t\t\t\t\t\t// note defaults do not write over any existing properties on the view itself.\n\t\t\t\t\t\t_this[ thisOptionName ] = thisOptionDefaultValue;\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\tif( _.keys( optionsThatWereChanged ).length > 0 ) {\n\t\t\t\tif( _.isFunction( _this.onOptionsChanged ) )\n\t\t\t\t\t_this.onOptionsChanged( optionsThatWereChanged, optionsThatWereChangedPreviousValues );\n\t\t\t\telse if( _.isFunction( _this._onOptionsChanged ) )\n\t\t\t\t\t_this._onOptionsChanged( optionsThatWereChanged, optionsThatWereChangedPreviousValues );\n\t\t\t}\n\t\t};\n\n\t\tview.getOptions = function() {\n\t\t\tvar optionDeclarations = _.result( this, optionsDeclarationsProperty );\n\t\t\tif( _.isUndefined( optionDeclarations ) ) return {};\n\n\t\t\tvar normalizedOptionDeclarations = _normalizeOptionDeclarations( optionDeclarations );\n\t\t\tvar optionsNames = _.keys( normalizedOptionDeclarations );\n\n\t\t\treturn _.pick( this, optionsNames );\n\t\t};\n\t};\n\n\t// ****************** Private Utility Functions ******************\n\n\tfunction _normalizeOptionDeclarations( optionDeclarations ) {\n\t\t// convert our short-hand option syntax (with exclamation marks, etc.)\n\t\t// to a simple array of standard option declaration objects.\n\n\t\tvar normalizedOptionDeclarations = {};\n\n\t\tif( ! _.isArray( optionDeclarations ) ) throw new Error( \"Option declarations must be an array.\" );\n\n\t\t_.each( optionDeclarations, function( thisOptionDeclaration ) {\n\t\t\tvar thisOptionName, thisOptionRequired, thisOptionDefaultValue;\n\n\t\t\tthisOptionRequired = false;\n\t\t\tthisOptionDefaultValue = undefined;\n\n\t\t\tif( _.isString( thisOptionDeclaration ) )\n\t\t\t\tthisOptionName = thisOptionDeclaration;\n\t\t\telse if( _.isObject( thisOptionDeclaration ) ) {\n\t\t\t\tthisOptionName = _.first( _.keys( thisOptionDeclaration ) );\n\t\t\t\tif( _.isFunction( thisOptionDeclaration[ thisOptionName ] ) )\n\t\t\t\t\tthisOptionDefaultValue = thisOptionDeclaration[ thisOptionName ];\n\t\t\t\telse\n\t\t\t\t\tthisOptionDefaultValue = _.clone( thisOptionDeclaration[ thisOptionName ] );\n\t\t\t}\n\t\t\telse throw new Error( \"Each element in the option declarations array must be either a string or an object.\" );\n\n\t\t\tif( thisOptionName[ thisOptionName.length - 1 ] === \"!\" ) {\n\t\t\t\tthisOptionRequired = true;\n\t\t\t\tthisOptionName = thisOptionName.slice( 0, thisOptionName.length - 1 );\n\t\t\t}\n\n\t\t\tnormalizedOptionDeclarations[ thisOptionName ] = normalizedOptionDeclarations[ thisOptionName ] || {};\n\t\t\tnormalizedOptionDeclarations[ thisOptionName ].required = thisOptionRequired;\n\t\t\tif( ! _.isUndefined( thisOptionDefaultValue ) ) normalizedOptionDeclarations[ thisOptionName ].defaultValue = thisOptionDefaultValue;\n\t\t} );\n\n\t\treturn normalizedOptionDeclarations;\n\t}\n\n\n\t// Backbone.BabySitter\n\t// -------------------\n\t// v0.0.6\n\t//\n\t// Copyright (c)2013 Derick Bailey, Muted Solutions, LLC.\n\t// Distributed under MIT license\n\t//\n\t// http://github.com/babysitterjs/backbone.babysitter\n\n\t// Backbone.ChildViewContainer\n\t// ---------------------------\n\t//\n\t// Provide a container to store, retrieve and\n\t// shut down child views.\n\n\tChildViewContainer = (function(Backbone, _){\n\n\t\t// Container Constructor\n\t\t// ---------------------\n\n\t\tvar Container = function(views){\n\t\t\tthis._views = {};\n\t\t\tthis._indexByModel = {};\n\t\t\tthis._indexByCustom = {};\n\t\t\tthis._updateLength();\n\n\t\t\t_.each(views, this.add, this);\n\t\t};\n\n\t\t// Container Methods\n\t\t// -----------------\n\n\t\t_.extend(Container.prototype, {\n\n\t\t\t// Add a view to this container. Stores the view\n\t\t\t// by `cid` and makes it searchable by the model\n\t\t\t// cid (and model itself). Optionally specify\n\t\t\t// a custom key to store an retrieve the view.\n\t\t\tadd: function(view, customIndex){\n\t\t\t\tvar viewCid = view.cid;\n\n\t\t\t\t// store the view\n\t\t\t\tthis._views[viewCid] = view;\n\n\t\t\t\t// index it by model\n\t\t\t\tif (view.model){\n\t\t\t\t\tthis._indexByModel[view.model.cid] = viewCid;\n\t\t\t\t}\n\n\t\t\t\t// index by custom\n\t\t\t\tif (customIndex){\n\t\t\t\t\tthis._indexByCustom[customIndex] = viewCid;\n\t\t\t\t}\n\n\t\t\t\tthis._updateLength();\n\t\t\t},\n\n\t\t\t// Find a view by the model that was attached to\n\t\t\t// it. Uses the model's `cid` to find it.\n\t\t\tfindByModel: function(model){\n\t\t\t\treturn this.findByModelCid(model.cid);\n\t\t\t},\n\n\t\t\t// Find a view by the `cid` of the model that was attached to\n\t\t\t// it. Uses the model's `cid` to find the view `cid` and\n\t\t\t// retrieve the view using it.\n\t\t\tfindByModelCid: function(modelCid){\n\t\t\t\tvar viewCid = this._indexByModel[modelCid];\n\t\t\t\treturn this.findByCid(viewCid);\n\t\t\t},\n\n\t\t\t// Find a view by a custom indexer.\n\t\t\tfindByCustom: function(index){\n\t\t\t\tvar viewCid = this._indexByCustom[index];\n\t\t\t\treturn this.findByCid(viewCid);\n\t\t\t},\n\n\t\t\t// Find by index. This is not guaranteed to be a\n\t\t\t// stable index.\n\t\t\tfindByIndex: function(index){\n\t\t\t\treturn _.values(this._views)[index];\n\t\t\t},\n\n\t\t\t// retrieve a view by it's `cid` directly\n\t\t\tfindByCid: function(cid){\n\t\t\t\treturn this._views[cid];\n\t\t\t},\n\n\t\t\tfindIndexByCid : function( cid ) {\n\t\t\t\tvar index = -1;\n\t\t\t\tvar view = _.find( this._views, function ( view ) {\n\t\t\t\t\tindex++;\n\t\t\t\t\tif( view.model.cid == cid )\n\t\t\t\t\t\treturn view;\n\t\t\t\t} );\n\t\t\t\treturn ( view ) ? index : -1;\n\t\t\t},\n\n\t\t\t// Remove a view\n\t\t\tremove: function(view){\n\t\t\t\tvar viewCid = view.cid;\n\n\t\t\t\t// delete model index\n\t\t\t\tif (view.model){\n\t\t\t\t\tdelete this._indexByModel[view.model.cid];\n\t\t\t\t}\n\n\t\t\t\t// delete custom index\n\t\t\t\t_.any(this._indexByCustom, function(cid, key) {\n\t\t\t\t\tif (cid === viewCid) {\n\t\t\t\t\t\tdelete this._indexByCustom[key];\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}, this);\n\n\t\t\t\t// remove the view from the container\n\t\t\t\tdelete this._views[viewCid];\n\n\t\t\t\t// update the length\n\t\t\t\tthis._updateLength();\n\t\t\t},\n\n\t\t\t// Call a method on every view in the container,\n\t\t\t// passing parameters to the call method one at a\n\t\t\t// time, like `function.call`.\n\t\t\tcall: function(method){\n\t\t\t\tthis.apply(method, _.tail(arguments));\n\t\t\t},\n\n\t\t\t// Apply a method on every view in the container,\n\t\t\t// passing parameters to the call method one at a\n\t\t\t// time, like `function.apply`.\n\t\t\tapply: function(method, args){\n\t\t\t\t_.each(this._views, function(view){\n\t\t\t\t\tif (_.isFunction(view[method])){\n\t\t\t\t\t\tview[method].apply(view, args || []);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t},\n\n\t\t\t// Update the `.length` attribute on this container\n\t\t\t_updateLength: function(){\n\t\t\t\tthis.length = _.size(this._views);\n\t\t\t}\n\t\t});\n\n\t\t// Borrowing this code from Backbone.Collection:\n\t\t// http://backbonejs.org/docs/backbone.html#section-106\n\t\t//\n\t\t// Mix in methods from Underscore, for iteration, and other\n\t\t// collection related features.\n\t\tvar methods = ['forEach', 'each', 'map', 'find', 'detect', 'filter',\n\t\t\t 'select', 'reject', 'every', 'all', 'some', 'any', 'include',\n\t\t\t 'contains', 'invoke', 'toArray', 'first', 'initial', 'rest',\n\t\t\t 'last', 'without', 'isEmpty', 'pluck'];\n\n\t\t_.each(methods, function(method) {\n\t\t\tContainer.prototype[method] = function() {\n\t\t\t\tvar views = _.values(this._views);\n\t\t\t\tvar args = [views].concat(_.toArray(arguments));\n\t\t\t\treturn _[method].apply(_, args);\n\t\t\t};\n\t\t});\n\n\t\t// return the public API\n\t\treturn Container;\n\t})(Backbone, _);\n\n\treturn Backbone.CollectionView;\n} ) );\n\n","//\n// backbone.trackit - 0.1.0\n// The MIT License\n// Copyright (c) 2013 The New York Times, CMS Group, Matthew DeLambo \n//\n(function() {\n\n\t// Unsaved Record Keeping\n\t// ----------------------\n\n\t// Collection of all models in an app that have unsaved changes.\n\tvar unsavedModels = [];\n\n\t// If the given model has unsaved changes then add it to\n\t// the `unsavedModels` collection, otherwise remove it.\n\tvar updateUnsavedModels = function(model) {\n\t\tif (!_.isEmpty(model._unsavedChanges)) {\n\t\t\tif (!_.findWhere(unsavedModels, {cid:model.cid})) unsavedModels.push(model);\n\t\t} else {\n\t\t\tunsavedModels = _.filter(unsavedModels, function(m) { return model.cid != m.cid; });\n\t\t}\n\t};\n\n\t// Unload Handlers\n\t// ---------------\n\n\t// Helper which returns a prompt message for an unload handler.\n\t// Uses the given function name (one of the callback names\n\t// from the `model.unsaved` configuration hash) to evaluate\n\t// whether a prompt is needed/returned.\n\tvar getPrompt = function(fnName) {\n\t\tvar prompt, args = _.rest(arguments);\n\t\t// Evaluate and return a boolean result. The given `fn` may be a\n\t\t// boolean value, a function, or the name of a function on the model.\n\t\tvar evaluateModelFn = function(model, fn) {\n\t\t\tif (_.isBoolean(fn)) return fn;\n\t\t\treturn (_.isString(fn) ? model[fn] : fn).apply(model, args);\n\t\t};\n\t\t_.each(unsavedModels, function(model) {\n\t\t\tif (!prompt && evaluateModelFn(model, model._unsavedConfig[fnName]))\n\t\t\t\tprompt = model._unsavedConfig.prompt;\n\t\t});\n\t\treturn prompt;\n\t};\n\n\t// Wrap Backbone.History.navigate so that in-app routing\n\t// (`router.navigate('/path')`) can be intercepted with a\n\t// confirmation if there are any unsaved models.\n\tBackbone.History.prototype.navigate = _.wrap(Backbone.History.prototype.navigate, function(oldNav, fragment, options) {\n\t\tvar prompt = getPrompt('unloadRouterPrompt', fragment, options);\n\t\tif (prompt) {\n\t\t\tif (confirm(prompt + ' \\n\\nAre you sure you want to leave this page?')) {\n\t\t\t\toldNav.call(this, fragment, options);\n\t\t\t}\n\t\t} else {\n\t\t\toldNav.call(this, fragment, options);\n\t\t}\n\t});\n\n\t// Create a browser unload handler which is triggered\n\t// on the refresh, back, or forward button.\n\twindow.onbeforeunload = function(e) {\n\t\treturn getPrompt('unloadWindowPrompt', e);\n\t};\n\n\t// Backbone.Model API\n\t// ------------------\n\n\t_.extend(Backbone.Model.prototype, {\n\n\t\tunsaved: {},\n\t\t_trackingChanges: false,\n\t\t_originalAttrs: {},\n\t\t_unsavedChanges: {},\n\n\t\t// Opt in to tracking attribute changes\n\t\t// between saves.\n\t\tstartTracking: function() {\n\t\t\tthis._unsavedConfig = _.extend({}, {\n\t\t\t\tprompt: 'You have unsaved changes!',\n\t\t\t\tunloadRouterPrompt: false,\n\t\t\t\tunloadWindowPrompt: false\n\t\t\t}, this.unsaved || {});\n\t\t\tthis._trackingChanges = true;\n\t\t\tthis._resetTracking();\n\t\t\tthis._triggerUnsavedChanges();\n\t\t\treturn this;\n\t\t},\n\n\t\t// Resets the default tracking values\n\t\t// and stops tracking attribute changes.\n\t\tstopTracking: function() {\n\t\t\tthis._trackingChanges = false;\n\t\t\tthis._originalAttrs = {};\n\t\t\tthis._unsavedChanges = {};\n\t\t\tthis._triggerUnsavedChanges();\n\t\t\treturn this;\n\t\t},\n\n\t\t// Gets rid of accrued changes and\n\t\t// resets state.\n\t\trestartTracking: function() {\n\t\t\tthis._resetTracking();\n\t\t\tthis._triggerUnsavedChanges();\n\t\t\treturn this;\n\t\t},\n\n\t\t// Restores this model's attributes to\n\t\t// their original values since tracking\n\t\t// started, the last save, or last restart.\n\t\tresetAttributes: function() {\n\t\t\tif (!this._trackingChanges) return;\n\t\t\tthis.attributes = this._originalAttrs;\n\t\t\tthis._resetTracking();\n\t\t\tthis._triggerUnsavedChanges();\n\t\t\treturn this;\n\t\t},\n\n\t\t// Symmetric to Backbone's `model.changedAttributes()`,\n\t\t// except that this returns a hash of the model's attributes that\n\t\t// have changed since the last save, or `false` if there are none.\n\t\t// Like `changedAttributes`, an external attributes hash can be\n\t\t// passed in, returning the attributes in that hash which differ\n\t\t// from the model.\n\t\tunsavedAttributes: function(attrs) {\n\t\t\tif (!attrs) return _.isEmpty(this._unsavedChanges) ? false : _.clone(this._unsavedChanges);\n\t\t\tvar val, changed = false, old = this._unsavedChanges;\n\t\t\tfor (var attr in attrs) {\n\t\t\t\tif (_.isEqual(old[attr], (val = attrs[attr]))) continue;\n\t\t\t\t(changed || (changed = {}))[attr] = val;\n\t\t\t}\n\t\t\treturn changed;\n\t\t},\n\n\t\t_resetTracking: function() {\n\t\t\tthis._originalAttrs = _.clone(this.attributes);\n\t\t\tthis._unsavedChanges = {};\n\t\t},\n\n\t\t// Trigger an `unsavedChanges` event on this model,\n\t\t// supplying the result of whether there are unsaved\n\t\t// changes and a changed attributes hash.\n\t\t_triggerUnsavedChanges: function() {\n\t\t\tthis.trigger('unsavedChanges', !_.isEmpty(this._unsavedChanges), _.clone(this._unsavedChanges));\n\t\t\tif (this.unsaved) updateUnsavedModels(this);\n\t\t}\n\t});\n\n\t// Wrap `model.set()` and update the internal\n\t// unsaved changes record keeping.\n\tBackbone.Model.prototype.set = _.wrap(Backbone.Model.prototype.set, function(oldSet, key, val, options) {\n\t\tvar attrs, ret;\n\t\tif (key == null) return this;\n\t\t// Handle both `\"key\", value` and `{key: value}` -style arguments.\n\t\tif (typeof key === 'object') {\n\t\t\tattrs = key;\n\t\t\toptions = val;\n\t\t} else {\n\t\t\t(attrs = {})[key] = val;\n\t\t}\n\t\toptions || (options = {});\n\n\t\t// Delegate to Backbone's set.\n\t\tret = oldSet.call(this, attrs, options);\n\n\t\tif (this._trackingChanges && !options.silent) {\n\t\t\t_.each(attrs, _.bind(function(val, key) {\n\t\t\t\tif (_.isEqual(this._originalAttrs[key], val))\n\t\t\t\t\tdelete this._unsavedChanges[key];\n\t\t\t\telse\n\t\t\t\t\tthis._unsavedChanges[key] = val;\n\t\t\t}, this));\n\t\t\tthis._triggerUnsavedChanges();\n\t\t}\n\t\treturn ret;\n\t});\n\n\t// Intercept `model.save()` and reset tracking/unsaved\n\t// changes if it was successful.\n\tBackbone.sync = _.wrap(Backbone.sync, function(oldSync, method, model, options) {\n\t\toptions || (options = {});\n\n\t\tif (method == 'update') {\n\t\t\toptions.success = _.wrap(options.success, _.bind(function(oldSuccess, data, textStatus, jqXHR) {\n\t\t\t\tvar ret;\n\t\t\t\tif (oldSuccess) ret = oldSuccess.call(this, data, textStatus, jqXHR);\n\t\t\t\tif (model._trackingChanges) {\n\t\t\t\t\tmodel._resetTracking();\n\t\t\t\t\tmodel._triggerUnsavedChanges();\n\t\t\t\t}\n\t\t\t\treturn ret;\n\t\t\t}, this));\n\t\t}\n\t\treturn oldSync(method, model, options);\n\t});\n\n})();\ndefine(\"vendor/backbone.trackit\", function(){});\n\n","/**\n * Image object model for use in various models for the 'image' attribute\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Models/Image',[], function() {\n\n\treturn Backbone.Model.extend( {\n\n\t\tdefaults: {\n\t\t\tenabled: 'no',\n\t\t\tid: '',\n\t\t\tsize: 'full',\n\t\t\tsrc: '',\n\t\t},\n\n\t\tinitialize: function() {\n\t\t\tthis.startTracking();\n\t\t},\n\n\t} );\n} );\n\n","/**\n * Model relationships mixin\n * @since 3.16.0\n * @version 3.16.11\n */\ndefine( 'Models/_Relationships',[], function() {\n\n\treturn {\n\n\t\t/**\n\t\t * Default relationship settings object\n\t\t * @type {Object}\n\t\t */\n\t\trelationship_defaults: {\n\t\t\tparent: {},\n\t\t\tchildren: {},\n\t\t},\n\n\t\t/**\n\t\t * Relationship settings object\n\t\t * Should be overriden in the model\n\t\t * @type {Object}\n\t\t */\n\t\trelationships: {},\n\n\t\t/**\n\t\t * Initialize all parent and child relationships\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinit_relationships: function( options ) {\n\n\t\t\tvar rels = this.get_relationships();\n\n\t\t\t// initialize parent relaxtionships\n\t\t\t// useful when adding a model to ensure parent is initialized\n\t\t\tif ( rels.parent && options && options.parent ) {\n\t\t\t\tthis.set_parent( options.parent );\n\t\t\t}\n\n\t\t\t// initialize all children relationships\n\t\t\t_.each( rels.children, function( child_data, child_key ) {\n\n\t\t\t\tif ( ! child_data.conditional || true === child_data.conditional( this ) ) {\n\n\t\t\t\t\tvar child_val = this.get( child_key ),\n\t\t\t\t\t\tchild;\n\n\t\t\t\t\tif ( child_data.lookup ) {\n\t\t\t\t\t\tchild = child_data.lookup( child_val );\n\t\t\t\t\t} else if ( 'model' === child_data.type ) {\n\t\t\t\t\t\tchild = window.llms_builder.construct.get_model( child_data.class, child_val );\n\t\t\t\t\t} else if ( 'collection' === child_data.type ) {\n\t\t\t\t\t\tchild = window.llms_builder.construct.get_collection( child_data.class, child_val );\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.set( child_key, child );\n\n\t\t\t\t\t// if the child defines a parent, save a reference to the parent on the child\n\t\t\t\t\tif ( 'model' === child_data.type ) {\n\t\t\t\t\t\tthis._maybe_set_parent_reference( child );\n\n\t\t\t\t\t// save directly to each model in the collection\n\t\t\t\t\t} else if ( 'collection' === child_data.type ) {\n\n\t\t\t\t\t\tchild.parent = this;\n\t\t\t\t\t\tchild.each( function( child_model ) {\n\n\t\t\t\t\t\t\tthis._maybe_set_parent_reference( child_model );\n\n\t\t\t\t\t\t}, this );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t}, this );\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the property names for all children of the model\n\t\t * @return array\n\t\t * @since 3.16.11\n\t\t * @version 3.16.11\n\t\t */\n\t\tget_child_props: function() {\n\n\t\t\tvar props = [];\n\n\t\t\t_.each( this.get_relationships().children, function( data, key ) {\n\n\t\t\t\tif ( ! data.conditional || true === data.conditional( this ) ) {\n\t\t\t\t\tprops.push( key );\n\t\t\t\t}\n\n\t\t\t}, this );\n\n\t\t\treturn props;\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the model's parent (if set)\n\t\t * @return obj|false\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_parent: function() {\n\n\t\t\tvar rels = this.get_relationships();\n\n\t\t\tif ( rels.parent ) {\n\t\t\t\treturn rels.parent.reference;\n\t\t\t}\n\n\t\t\treturn false;\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve relationships for the model\n\t\t * Extends with defaults\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_relationships: function() {\n\n\t\t\treturn $.extend( true, this.relationships, this.relationship_defaults );\n\n\t\t},\n\n\t\t/**\n\t\t * Set the parent reference for the given model\n\t\t * @param obj obj parent model obj\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tset_parent: function( obj ) {\n\t\t\tthis.relationships.parent.reference = obj;\n\t\t},\n\n\t\t/**\n\t\t * Set up the parent relationships for qualifying children during relationship initialization\n\t\t * @param obj model child model\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\t_maybe_set_parent_reference: function( model ) {\n\n\t\t\tif ( ! model || ! model.get_relationships ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar rels = model.get_relationships();\n\t\t\tif ( rels.parent && rels.parent.model === this.get( 'type' ) ) {\n\t\t\t\tmodel.set_parent( this );\n\t\t\t}\n\n\t\t},\n\n\t};\n\n} );\n\n","/**\n * Quiz Question Choice\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Models/QuestionChoice',[ 'Models/Image', 'Models/_Relationships' ], function( Image, Relationships ) {\n\n\treturn Backbone.Model.extend( _.defaults( {\n\n\t\t/**\n\t\t * Model relationships\n\t\t * @type {Object}\n\t\t */\n\t\trelationships: {\n\t\t\tparent: {\n\t\t\t\tmodel: 'llms_question',\n\t\t\t\ttype: 'model',\n\t\t\t},\n\t\t\tchildren: {\n\t\t\t\tchoice: {\n\t\t\t\t\tconditional: function( model ) {\n\t\t\t\t\t\treturn ( 'image' === model.get( 'choice_type' ) );\n\t\t\t\t\t},\n\t\t\t\t\tclass: 'Image',\n\t\t\t\t\tmodel: 'image',\n\t\t\t\t\ttype: 'model',\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\n\t\t/**\n\t\t * Model defaults\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tdefaults: function() {\n\t\t\treturn {\n\t\t\t\tid: _.uniqueId( 'temp_' ),\n\t\t\t\tchoice: '',\n\t\t\t\tchoice_type: 'text',\n\t\t\t\tcorrect: false,\n\t\t\t\tmarker: 'A',\n\t\t\t\tquestion_id: '',\n\t\t\t\ttype: 'choice',\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Initializer\n\t\t * @param obj data object of model attributes\n\t\t * @param obj options additional options\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function( data, options ) {\n\n\t\t\tthis.startTracking();\n\t\t\tthis.init_relationships( options );\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the choice's parent question\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_parent: function() {\n\t\t\treturn this.collection.parent;\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the ID used when trashing the model\n\t\t * @return string\n\t\t * @since 3.17.1\n\t\t * @version 3.17.1\n\t\t */\n\t\tget_trash_id: function() {\n\t\t\treturn this.get( 'question_id' ) + ':' + this.get( 'id' );\n\t\t},\n\n\t\t/**\n\t\t * Determine if \"selection\" is enabled for the question type\n\t\t * Choice type questions are selectable by reorder type questions are not but still use choices\n\t\t * @return {Boolean}\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tis_selectable: function() {\n\t\t\treturn this.get_parent().get( 'question_type' ).get_choice_selectable();\n\t\t},\n\n\t}, Relationships ) );\n\n} );\n\n","/**\n * Question Choice Collection\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Collections/QuestionChoices',[ 'Models/QuestionChoice' ], function( model ) {\n\n\treturn Backbone.Collection.extend( {\n\n\t\t/**\n\t\t * Model for collection items\n\t\t * @type obj\n\t\t */\n\t\tmodel: model,\n\n\t\tinitialize: function() {\n\n\t\t\t// reorder called by QuestionList view when sortable drops occur\n\t\t\tthis.on( 'reorder', this.update_order );\n\n\t\t\t// when a choice is added or removed, update order\n\t\t\tthis.on( 'add', this.update_order );\n\t\t\tthis.on( 'remove', this.update_order );\n\n\t\t\t// when a choice is added or remove, ensure min/max correct answers exist\n\t\t\tthis.on( 'add', this.update_correct );\n\t\t\tthis.on( 'remove', this.update_correct );\n\n\t\t\t// when a choice is toggled, ensure min/max correct exist\n\t\t\tthis.on( 'correct-update', this.update_correct );\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the number of correct choices in the collection\n\t\t * @return int\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tcount_correct: function() {\n\n\t\t\treturn _.size( this.get_correct() );\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the collection reduced to only correct choices\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_correct: function() {\n\t\t\treturn this.filter( function( choice ) {\n\t\t\t\treturn choice.get( 'correct' );\n\t\t\t} );\n\t\t},\n\n\t\t/**\n\t\t * Ensure min/max correct choices exist in the collection based on the question's settings\n\t\t * @param obj choice model of the choice that was toggled\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tupdate_correct: function( choice ) {\n\n\t\t\tif ( ! this.parent.get( 'question_type' ).get_choice_selectable() ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar siblings = this.without( choice ), // exclude the toggled choice from loops\n\t\t\t\tquestion = this.parent;\n\n\t\t\t// if multiple choices aren't enabled turn all other choices to incorrect\n\t\t\tif ( 'no' === question.get( 'multi_choices' ) ) {\n\t\t\t\t_.each( siblings, function( model ) {\n\t\t\t\t\tmodel.set( 'correct', false );\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\t// if we don't have a single corret answer & the question has points, set one\n\t\t\t// allows users to create quizzes / questions with no points and therefore no correct answers are allowed\n\t\t\tif ( 0 === this.count_correct() && question.get( 'points' ) > 0 ) {\n\t\t\t\tvar models = 1 === this.size() ? this.models : siblings;\n\t\t\t\t_.first( models ).set( 'correct', true );\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Update the marker attr of each choice in the list to reflect the order of the collection\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tupdate_order: function() {\n\n\t\t\tvar self = this,\n\t\t\t\tquestion = this.parent;\n\n\t\t\tthis.each( function( choice ) {\n\t\t\t\tchoice.set( 'marker', question.get( 'question_type' ).get_choice_markers()[ self.indexOf( choice ) ] );\n\t\t\t} );\n\n\t\t},\n\n\t} );\n\n} );\n\n","/**\n * Quiz Question Type\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Models/QuestionType',[], function() {\n\n\treturn Backbone.Model.extend( {\n\n\t\t/**\n\t\t * Get model default attributes\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tdefaults: function() {\n\t\t\treturn {\n\t\t\t\tchoices: false,\n\t\t\t\tclarifications: true,\n\t\t\t\tdefault_choices: [],\n\t\t\t\tdescription: true,\n\t\t\t\ticon: 'question',\n\t\t\t\tid: 'generic',\n\t\t\t\timage: true,\n\t\t\t\tkeywords: [],\n\t\t\t\tname: 'Generic',\n\t\t\t\tplaceholder: '',\n\t\t\t\tpoints: true,\n\t\t\t\tvideo: true,\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Retrieve an array of keywords for the question type\n\t\t * Used for filtering questions by search term in the quiz builder\n\t\t * @return array\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_keywords: function() {\n\n\t\t\tvar name = this.get( 'name' ),\n\t\t\t\twords = [ name ];\n\n\t\t\treturn words.concat( this.get( 'keywords' ) ).concat( name.split( ' ' ) );\n\n\t\t},\n\n\t\t/**\n\t\t * Get marker array for the question choices\n\t\t * @return array\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_choice_markers: function() {\n\n\t\t\treturn this._get_choice_option( 'markers' );\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if the question's choices are selectable\n\t\t * @return bool\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_choice_selectable: function() {\n\n\t\t\treturn this._get_choice_option( 'selectable' );\n\n\t\t},\n\n\t\t/**\n\t\t * Get the choice type (text,image)\n\t\t * @return string\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_choice_type: function() {\n\n\t\t\treturn this._get_choice_option( 'type' );\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve defined min. choices\n\t\t * @return int\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_min_choices: function() {\n\n\t\t\treturn this._get_choice_option( 'min' );\n\n\t\t},\n\n\t\t/**\n\t\t * Get type-defined max choices\n\t\t * @return string\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_max_choices: function() {\n\n\t\t\treturn this._get_choice_option( 'max' );\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if multi-choice selection is enabled\n\t\t * @return bool\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_multi_choices: function() {\n\n\t\t\tvar choices = this.get( 'choices' );\n\n\t\t\tif ( ! choices ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\treturn this._get_choice_option( 'multi' );\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve data from the type's \"choices\" attribute\n\t\t * Allows quick handling of types with no choice definitions w/o additional checks\n\t\t * @param string option name of the choice option to retrieve\n\t\t * @return mixed\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\t_get_choice_option: function( option ) {\n\n\t\t\tvar choices = this.get( 'choices' );\n\n\t\t\tif ( ! choices || ! choices[ option ] ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\treturn choices[ option ];\n\n\t\t},\n\n\t} );\n\n} );\n\n","/**\n * Quiz Question\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Models/Question',[\n\t\t'Models/Image',\n\t\t'Collections/Questions',\n\t\t'Collections/QuestionChoices',\n\t\t'Models/QuestionType',\n\t\t'Models/_Relationships'\n\t], function(\n\t\tImage,\n\t\tQuestions,\n\t\tQuestionChoices,\n\t\tQuestionType,\n\t\tRelationships\n\t) {\n\n\treturn Backbone.Model.extend( _.defaults( {\n\n\t\t/**\n\t\t * Model relationships\n\t\t * @type {Object}\n\t\t */\n\t\trelationships: {\n\t\t\tparent: {\n\t\t\t\tmodel: 'llms_quiz',\n\t\t\t\ttype: 'model',\n\t\t\t},\n\t\t\tchildren: {\n\t\t\t\tchoices: {\n\t\t\t\t\tclass: 'QuestionChoices',\n\t\t\t\t\tmodel: 'choice',\n\t\t\t\t\ttype: 'collection',\n\t\t\t\t},\n\t\t\t\timage: {\n\t\t\t\t\tclass: 'Image',\n\t\t\t\t\tmodel: 'image',\n\t\t\t\t\ttype: 'model',\n\t\t\t\t},\n\t\t\t\tquestions: {\n\t\t\t\t\tclass: 'Questions',\n\t\t\t\t\tconditional: function( model ) {\n\t\t\t\t\t\tvar type = model.get( 'question_type' ),\n\t\t\t\t\t\t\ttype_id = _.isString( type ) ? type : type.get( 'id' );\n\t\t\t\t\t\treturn ( 'group' === type_id );\n\t\t\t\t\t},\n\t\t\t\t\tmodel: 'llms_question',\n\t\t\t\t\ttype: 'collection',\n\t\t\t\t},\n\t\t\t\tquestion_type: {\n\t\t\t\t\tclass: 'QuestionType',\n\t\t\t\t\tlookup: function( val ) {\n\t\t\t\t\t\tif ( _.isString( val ) ) {\n\t\t\t\t\t\t\treturn window.llms_builder.questions.get( val );\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn val;\n\t\t\t\t\t},\n\t\t\t\t\tmodel: 'question_type',\n\t\t\t\t\ttype: 'model',\n\t\t\t\t},\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Model defaults\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tdefaults: function() {\n\t\t\treturn {\n\t\t\t\tid: _.uniqueId( 'temp_' ),\n\t\t\t\tchoices: [],\n\t\t\t\tcontent: '',\n\t\t\t\tdescription_enabled: 'no',\n\t\t\t\timage: {},\n\t\t\t\tmulti_choices: 'no',\n\t\t\t\tmenu_order: 1,\n\t\t\t\tpoints: 1,\n\t\t\t\tquestion_type: 'generic',\n\t\t\t\tquestions: [], // for question groups\n\t\t\t\tparent_id: '',\n\t\t\t\ttitle: '',\n\t\t\t\ttype: 'llms_question',\n\t\t\t\tvideo_enabled: 'no',\n\t\t\t\tvideo_src: '',\n\n\t\t\t\t_expanded: false,\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Initializer\n\t\t * @param obj data object of data for the model\n\t\t * @param obj options additional options\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function( data, options ) {\n\n\t\t\tvar self = this;\n\n\t\t\tthis.startTracking();\n\t\t\tthis.init_relationships( options );\n\n\t\t\tif ( false !== this.get( 'question_type' ).choices ) {\n\n\t\t\t\tthis._ensure_min_choices();\n\n\t\t\t\t// when a choice is removed, maybe add back some defaults so we always have the minimum\n\t\t\t\tthis.listenTo( this.get( 'choices' ), 'remove', function() {\n\t\t\t\t\t// new itmes are added at index 0 when there's only 1 item in the collection, not sure why exactly...\n\t\t\t\t\tsetTimeout( function() {\n\t\t\t\t\t\tself._ensure_min_choices();\n\t\t\t\t\t}, 0 );\n\t\t\t\t} );\n\n\t\t\t}\n\n\t\t\t// ensure question types that don't support points don't record default 1 point in database\n\t\t\tif ( ! this.get( 'question_type' ).get( 'points' ) ) {\n\t\t\t\tthis.set( 'points', 0 );\n\t\t\t}\n\n\t\t\t_.delay( function( self ) {\n\t\t\t\tself.on( 'change:points', self.get_parent().update_points, self.get_parent() );\n\t\t\t}, 1, this );\n\n\t\t},\n\n\t\t/**\n\t\t * Add a new question choice\n\t\t * @param obj data object of choice data\n\t\t * @param obj options additional options\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tadd_choice: function( data, options ) {\n\n\t\t\tvar max = this.get( 'question_type' ).get_max_choices();\n\t\t\tif ( this.get( 'choices' ).size() >= max ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tdata = data || {};\n\t\t\toptions = options || {};\n\n\t\t\tdata.choice_type = this.get( 'question_type' ).get_choice_type();\n\t\t\tdata.question_id = this.get( 'id' );\n\t\t\toptions.parent = this;\n\n\t\t\tvar choice = this.get( 'choices' ).add( data, options );\n\n\t\t\tBackbone.pubSub.trigger( 'question-add-choice', choice, this );\n\n\t\t},\n\n\t\t/**\n\t\t * Collapse question_type attribute during full syncs to save to database\n\t\t * Not needed because question types cannot be adjusted after question creation\n\t\t * Called from sync controller\n\t\t * @param obj atts flat object of attributes to be saved to db\n\t\t * @param string sync_type full or partial\n\t\t * full indicates a force resync or that the model isn't persisted yet\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tbefore_save: function( atts, sync_type ) {\n\t\t\tif ( 'full' === sync_type ) {\n\t\t\t\tatts.question_type = this.get( 'question_type' ).get( 'id' );\n\t\t\t}\n\t\t\treturn atts;\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the model's parent (if set)\n\t\t * @return obj|false\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_parent: function() {\n\n\t\t\tvar rels = this.get_relationships();\n\n\t\t\tif ( rels.parent ) {\n\t\t\t\tif ( this.collection && this.collection.parent ) {\n\t\t\t\t\treturn this.collection.parent;\n\t\t\t\t} else if ( rels.parent.reference ) {\n\t\t\t\t\treturn rels.parent.reference;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false;\n\n\t\t},\n\n\t\t/**\n\t\t * Gets the index of the question within it's parent\n\t\t * Question numbers skip content elements\n\t\t * & content elements skip questions\n\t\t * @return int\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_type_index: function() {\n\n\t\t\t// current models type, used to check the predicate in the filter function below\n\t\t\tvar curr_type = this.get( 'question_type' ).get( 'id' ),\n\t\t\t\tquestions;\n\n\t\t\tquestions = this.collection.filter( function( question ) {\n\n\t\t\t\tvar type = question.get( 'question_type' ).get( 'id' );\n\n\t\t\t\t// if current model is not content, return all non-content questions\n\t\t\t\tif ( curr_type !== 'content' ) {\n\t\t\t\t\treturn ( 'content' !== type );\n\t\t\t\t}\n\n\t\t\t\t// current model is content, return only content questions\n\t\t\t\treturn 'content' === type;\n\n\t\t\t} );\n\n\t\t\treturn questions.indexOf( this );\n\n\t\t},\n\n\t\t/**\n\t\t * Gets iterator for the given type\n\t\t * Questions use numbers and content uses alphabet\n\t\t * @return mixed\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_type_iterator: function() {\n\n\t\t\tvar index = this.get_type_index();\n\n\t\t\tif ( -1 === index ) {\n\t\t\t\treturn '';\n\t\t\t}\n\n\t\t\tif ( 'content' === this.get( 'question_type' ).get( 'id' ) ) {\n\t\t\t\tvar alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split( '' );\n\t\t\t\treturn alphabet[ index ];\n\t\t\t}\n\n\t\t\treturn index + 1;\n\n\t\t},\n\n\n\t\tget_qid: function() {\n\n\t\t\tvar parent = this.get_parent_question(),\n\t\t\t\tprefix = '';\n\n\t\t\tif ( parent ) {\n\n\t\t\t\tprefix = parent.get_qid() + '.';\n\n\t\t\t}\n\n\t\t\t// return short_id + this.get_type_iterator();\n\t\t\treturn prefix + this.get_type_iterator();\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the parent question (if the question is in a question group)\n\t\t * @return obj|false\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_parent_question: function() {\n\n\t\t\tif ( this.is_in_group() ) {\n\n\t\t\t\treturn this.collection.parent;\n\n\t\t\t}\n\n\t\t\treturn false;\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the parent quiz\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_parent_quiz: function() {\n\t\t\treturn this.get_parent();\n\t\t},\n\n\t\t/**\n\t\t * Points getter\n\t\t * ensures that 0 is always returned if the question type doesn't support points\n\t\t * @return int\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_points: function() {\n\n\t\t\tif ( ! this.get( 'question_type' ).get( 'points' ) ) {\n\t\t\t\treturn 0;\n\t\t\t}\n\n\t\t\treturn this.get( 'points' );\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the questions percentage value within the quiz\n\t\t * @return string\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_points_percentage: function() {\n\n\t\t\tvar total = this.get_parent().get( '_points' ),\n\t\t\t\tpoints = this.get( 'points' );\n\n\t\t\tif ( 0 === total ) {\n\t\t\t\treturn '0%';\n\t\t\t}\n\n\t\t\treturn ( ( points / total ) * 100 ).toFixed( 2 ) + '%';\n\n\t\t},\n\n\t\t/**\n\t\t * Deterine if the question belongs to a question group\n\t\t * @return {Boolean}\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tis_in_group: function() {\n\n\t\t\treturn ( 'question' === this.collection.parent.get( 'type' ) );\n\n\t\t},\n\n\t\t_ensure_min_choices: function() {\n\n\t\t\tvar choices = this.get( 'choices' );\n\t\t\twhile ( choices.size() < this.get( 'question_type' ).get_min_choices() ) {\n\t\t\t\tthis.add_choice();\n\t\t\t}\n\n\t\t},\n\n\t}, Relationships ) );\n\n} );\n\n","/**\n * Questions Collection\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Collections/Questions',[ 'Models/Question' ], function( model ) {\n\n\treturn Backbone.Collection.extend( {\n\n\t\t/**\n\t\t * Model for collection items\n\t\t * @type obj\n\t\t */\n\t\tmodel: model,\n\n\t\t/**\n\t\t * Initialize\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\t// reorder called by QuestionList view when sortable drops occur\n\t\t\tthis.on( 'reorder', this.update_order );\n\n\t\t\t// when a question is added or removed, update order\n\t\t\tthis.on( 'add', this.update_order );\n\t\t\tthis.on( 'remove', this.update_order );\n\n\t\t\tthis.on( 'add', this.update_parent );\n\n\t\t},\n\n\t\t/**\n\t\t * Update the order attr of each question in the list to reflect the order of the collection\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tupdate_order: function() {\n\n\t\t\tvar self = this;\n\n\t\t\tthis.each( function( question ) {\n\n\t\t\t\tquestion.set( 'menu_order', self.indexOf( question ) + 1 );\n\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * When adding a question to a question list, update the question's parent\n\t\t * Will ensure that questions moved into and out of groups always have the corerct parent_id\n\t\t * @param obj model instance of the question model\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tupdate_parent: function( model ) {\n\n\t\t\tmodel.set( 'parent_id', this.parent.get( 'id' ) );\n\n\t\t},\n\n\t} );\n\n} );\n\n","/**\n * Utility functions for Models\n * @since 3.16.0\n * @version 3.17.1\n */\ndefine( 'Models/_Utilities',[], function() {\n\n\treturn {\n\n\t\tfields: [],\n\n\t\t/**\n\t\t * Retrieve the edit post link for the current model\n\t\t * @return string\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_edit_post_link: function() {\n\n\t\t\tif ( this.has_temp_id() ) {\n\t\t\t\treturn '';\n\t\t\t}\n\n\t\t\treturn window.llms_builder.admin_url + 'post.php?post=' + this.get( 'id' ) + '&action=edit';\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve schema fields defined for the model\n\t\t * @return object\n\t\t * @since 3.17.0\n\t\t * @version 3.17.1\n\t\t */\n\t\tget_settings_fields: function() {\n\n\t\t\tvar schema = this.schema || {};\n\t\t\treturn window.llms_builder.schemas.get( schema, this.get( 'type' ).replace( 'llms_', '' ), this );\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if the model has a temporary ID\n\t\t * @return {Boolean}\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\thas_temp_id: function() {\n\n\t\t\treturn ( ! _.isNumber( this.get( 'id' ) ) && 0 === this.get( 'id' ).indexOf( 'temp_' ) );\n\n\t\t},\n\n\t\t/**\n\t\t * Initializes 3rd party custom schema (field) data for a model\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tinit_custom_schema: function() {\n\n\t\t\tvar groups = _.filter( this.get_settings_fields(), function( group ) {\n\t\t\t\treturn ( group.custom );\n\t\t\t} );\n\n\t\t\t_.each( groups, function( group ) {\n\t\t\t\t_.each( _.flatten( group.fields ), function( field ) {\n\n\n\t\t\t\t\tvar keys = [ field.attribute ],\n\t\t\t\t\t\tcustoms = this.get( 'custom' );\n\n\t\t\t\t\tif ( field.switch_attribute ) {\n\t\t\t\t\t\tkeys.push( field.switch_attribute );\n\t\t\t\t\t}\n\n\t\t\t\t\t_.each( keys, function( key ) {\n\t\t\t\t\t\tvar attr = field.attribute_prefix ? field.attribute_prefix + key : key;\n\t\t\t\t\t\tif ( customs && customs[ attr ] ) {\n\t\t\t\t\t\t\tthis.set( key, customs[ attr ][0] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}, this );\n\n\t\t\t\t}, this );\n\t\t\t}, this );\n\n\t\t},\n\n\t};\n\n} );\n\n","/**\n * Quiz Schema\n * @since 3.17.6\n * @version 3.17.6\n */\ndefine( 'Schemas/Quiz',[], function() {\n\n\treturn {\n\n\t\tdefault: {\n\t\t\ttitle: LLMS.l10n.translate( 'General Settings' ),\n\t\t\ttoggleable: true,\n\t\t\tfields: [\n\t\t\t\t[\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'permalink',\n\t\t\t\t\t\tid: 'permalink',\n\t\t\t\t\t\ttype: 'permalink',\n\t\t\t\t\t},\n\t\t\t\t], [\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'content',\n\t\t\t\t\t\tid: 'description',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Description' ),\n\t\t\t\t\t\ttype: 'editor',\n\t\t\t\t\t},\n\t\t\t\t], [\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'passing_percent',\n\t\t\t\t\t\tid: 'passing-percent',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Passing Percentage' ),\n\t\t\t\t\t\tmin: 0,\n\t\t\t\t\t\tmax: 100,\n\t\t\t\t\t\ttip: LLMS.l10n.translate( 'Minimum percentage of total points required to pass the quiz' ),\n\t\t\t\t\t\ttype: 'number',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'allowed_attempts',\n\t\t\t\t\t\tid: 'allowed-attempts',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Limit Attempts' ),\n\t\t\t\t\t\tswitch_attribute: 'limit_attempts',\n\t\t\t\t\t\ttip: LLMS.l10n.translate( 'Limit the maximum number of times a student can take this quiz' ),\n\t\t\t\t\t\ttype: 'switch-number',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'time_limit',\n\t\t\t\t\t\tid: 'time-limit',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Time Limit' ),\n\t\t\t\t\t\tmin: 1,\n\t\t\t\t\t\tmax: 360,\n\t\t\t\t\t\tswitch_attribute: 'limit_time',\n\t\t\t\t\t\ttip: LLMS.l10n.translate( 'Enforce a maximum number of minutes a student can spend on each attempt' ),\n\t\t\t\t\t\ttype: 'switch-number',\n\t\t\t\t\t},\n\t\t\t\t], [\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'show_correct_answer',\n\t\t\t\t\t\tid: 'show-correct-answer',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Show Correct Answers' ),\n\t\t\t\t\t\ttip: LLMS.l10n.translate( 'When enabled, students will be shown the correct answer to any question they answered incorrectly.' ),\n\t\t\t\t\t\ttype: 'switch',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'random_questions',\n\t\t\t\t\t\tid: 'random-questions',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Randomize Question Order' ),\n\t\t\t\t\t\ttip: LLMS.l10n.translate( 'Display questions in a random order for each attempt. Content questions are locked into their defined positions.' ),\n\t\t\t\t\t\ttype: 'switch',\n\t\t\t\t\t},\n\t\t\t\t],\n\n\t\t\t],\n\t\t},\n\n\t};\n\n} );\n\n","/**\n * Quiz Model\n * @since 3.16.0\n * @version 3.19.2\n */\ndefine( 'Models/Quiz',[\n\t\t'Collections/Questions',\n\t\t'Models/Lesson',\n\t\t'Models/Question',\n\t\t'Models/_Relationships',\n\t\t'Models/_Utilities',\n\t\t'Schemas/Quiz',\n\t], function(\n\t\tQuestions,\n\t\tLesson,\n\t\tQuestion,\n\t\tRelationships,\n\t\tUtilities,\n\t\tQuizSchema\n\t) {\n\n\treturn Backbone.Model.extend( _.defaults( {\n\n\t\t/**\n\t\t * model relationships\n\t\t * @type {Object}\n\t\t */\n\t\trelationships: {\n\t\t\tparent: {\n\t\t\t\tmodel: 'lesson',\n\t\t\t\ttype: 'model',\n\t\t\t},\n\t\t\tchildren: {\n\t\t\t\tquestions: {\n\t\t\t\t\tclass: 'Questions',\n\t\t\t\t\tmodel: 'llms_question',\n\t\t\t\t\ttype: 'collection',\n\t\t\t\t},\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Lesson Settings Schema\n\t\t * @type {Object}\n\t\t */\n\t\tschema: QuizSchema,\n\n\t\t/**\n\t\t * New lesson defaults\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.6\n\t\t */\n\t\tdefaults: function() {\n\n\t\t\treturn {\n\t\t\t\tid: _.uniqueId( 'temp_' ),\n\t\t\t\ttitle: LLMS.l10n.translate( 'New Quiz' ),\n\t\t\t\ttype: 'llms_quiz',\n\t\t\t\tlesson_id: '',\n\n\t\t\t\tstatus: 'draft',\n\n\t\t\t\t// editable fields\n\t\t\t\tcontent: '',\n\t\t\t\tallowed_attempts: 5,\n\t\t\t\tlimit_attempts: 'no',\n\t\t\t\tlimit_time: 'no',\n\t\t\t\tpassing_percent: 65,\n\t\t\t\tname: '',\n\t\t\t\trandom_answers: 'no',\n\t\t\t\ttime_limit: 30,\n\t\t\t\tshow_correct_answer: 'no',\n\n\t\t\t\tquestions: [],\n\n\t\t\t\t// calculated\n\t\t\t\t_points: 0,\n\n\t\t\t\t// display\n\t\t\t\tpermalink: '',\n\t\t\t\t_show_settings: false,\n\t\t\t\t_questions_loaded: false,\n\t\t\t};\n\n\t\t},\n\n\t\t/**\n\t\t * Initializer\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.17.6\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\tthis.init_custom_schema();\n\t\t\tthis.startTracking();\n\t\t\tthis.init_relationships();\n\n\t\t\tthis.listenTo( this.get( 'questions' ), 'add', this.update_points );\n\t\t\tthis.listenTo( this.get( 'questions' ), 'remove', this.update_points );\n\n\t\t\tthis.set( '_points', this.get_total_points() );\n\n\t\t\t// when a quiz is published, ensure the parent lesson is marked as \"Enabled\" for quizzing\n\t\t\tthis.on( 'change:status', function() {\n\t\t\t\tif ( 'publish' === this.get( 'status' ) ) {\n\t\t\t\t\tthis.get_parent().set( 'quiz_enabled', 'yes' );\n\t\t\t\t}\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * Add a new question to the quiz\n\t\t * @param obj data question data\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tadd_question: function( data ) {\n\n\t\t\tdata.parent_id = this.get( 'id' );\n\t\t\tvar question = this.get( 'questions' ).add( data, {\n\t\t\t\tparent: this,\n\t\t\t} );\n\t\t\tBackbone.pubSub.trigger( 'quiz-add-question', question, this );\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the translated post type name for the model's type\n\t\t * @param bool plural if true, returns the plural, otherwise returns singular\n\t\t * @return string\n\t\t * @since 3.16.12\n\t\t * @version 3.16.12\n\t\t */\n\t\tget_l10n_type: function( plural ) {\n\n\t\t\tif ( plural ) {\n\t\t\t\treturn LLMS.l10n.translate( 'quizzes' );\n\t\t\t}\n\n\t\t\treturn LLMS.l10n.translate( 'quiz' );\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the quiz's total points\n\t\t * @return int\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_total_points: function() {\n\n\t\t\tvar points = 0;\n\n\t\t\tthis.get( 'questions' ).each( function( question ) {\n\t\t\t\tpoints += question.get_points();\n\t\t\t} );\n\n\t\t\treturn points;\n\n\t\t},\n\n\t\t/**\n\t\t * Lazy load questions via AJAX\n\t\t * @param {Function} cb callback function\n\t\t * @return void\n\t\t * @since 3.19.2\n\t\t * @version 3.19.2\n\t\t */\n\t\tload_questions: function( cb ) {\n\n\t\t\tif ( this.get( '_questions_loaded' ) ) {\n\n\t\t\t\tcb();\n\n\t\t\t} else {\n\n\t\t\t\tvar self = this;\n\n\t\t\t\tLLMS.Ajax.call( {\n\t\t\t\t\tdata: {\n\t\t\t\t\t\taction: 'llms_builder',\n\t\t\t\t\t\taction_type: 'lazy_load',\n\t\t\t\t\t\tcourse_id: window.llms_builder.CourseModel.get( 'id' ),\n\t\t\t\t\t\tload_id: this.get( 'id' ),\n\t\t\t\t\t},\n\t\t\t\t\terror: function( xhr, status, error ) {\n\n\t\t\t\t\t\tconsole.log( xhr, status, error );\n\t\t\t\t\t\twindow.llms_builder.debug.log( '==== start load_questions error ====', xhr, status, error, '==== finish load_questions error ====' );\n\t\t\t\t\t\tcb( true );\n\n\t\t\t\t\t},\n\t\t\t\t\tsuccess: function( res ) {\n\t\t\t\t\t\tif ( res && res.questions ) {\n\t\t\t\t\t\t\tself.set( '_questions_loaded', true );\n\t\t\t\t\t\t\tif ( res.questions ) {\n\t\t\t\t\t\t\t\t_.each( res.questions, self.add_question, self );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcb();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tcb( true );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t} );\n\n\t\t\t}\n\n\n\t\t},\n\n\t\t/**\n\t\t * Update total number of points calculated property\n\t\t * @return int\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tupdate_points: function() {\n\n\t\t\tthis.set( '_points', this.get_total_points() );\n\n\t\t},\n\n\t}, Relationships, Utilities ) );\n\n} );\n\n","/**\n * Lesson Schemas\n * @since 3.17.0\n * @version 3.17.1\n */\ndefine( 'Schemas/Lesson',[], function() {\n\n\treturn {\n\n\t\tdefault: {\n\t\t\ttitle: LLMS.l10n.translate( 'General Settings' ),\n\t\t\ttoggleable: true,\n\t\t\tfields: [\n\t\t\t\t[\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'permalink',\n\t\t\t\t\t\tid: 'permalink',\n\t\t\t\t\t\ttype: 'permalink',\n\t\t\t\t\t},\n\t\t\t\t], [\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'video_embed',\n\t\t\t\t\t\tid: 'video-embed',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Video Embed URL' ),\n\t\t\t\t\t\ttype: 'video_embed',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'audio_embed',\n\t\t\t\t\t\tid: 'audio-embed',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Audio Embed URL' ),\n\t\t\t\t\t\ttype: 'audio_embed',\n\t\t\t\t\t},\n\t\t\t\t], [\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'free_lesson',\n\t\t\t\t\t\tid: 'free-lesson',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Free Lesson' ),\n\t\t\t\t\t\ttip: LLMS.l10n.translate( \"Free lessons can be accessed without enrollment.\" ),\n\t\t\t\t\t\ttype: 'switch',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'require_passing_grade',\n\t\t\t\t\t\tid: 'require-passing-grade',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Require Passing Grade on Quiz' ),\n\t\t\t\t\t\ttip: LLMS.l10n.translate( \"When enabled, students must pass this lesson's quiz before the lesson can be completed.\" ),\n\t\t\t\t\t\ttype: 'switch',\n\t\t\t\t\t\tcondition: function() {\n\t\t\t\t\t\t\treturn ( 'yes' === this.get( 'quiz_enabled' ) );\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'require_assignment_passing_grade',\n\t\t\t\t\t\tid: 'require-assignment-passing-grade',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Require Passing Grade on Assignment' ),\n\t\t\t\t\t\ttip: LLMS.l10n.translate( \"When enabled, students must pass this lesson's assignment before the lesson can be completed.\" ),\n\t\t\t\t\t\ttype: 'switch',\n\t\t\t\t\t\tcondition: function() {\n\t\t\t\t\t\t\treturn ( 'undefined' !== window.llms_builder.assignments && 'yes' === this.get( 'assignment_enabled' ) );\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t], [\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'prerequisite',\n\t\t\t\t\t\tcondition: function() {\n\t\t\t\t\t\t\treturn ( false === this.is_first_in_course() );\n\t\t\t\t\t\t},\n\t\t\t\t\t\tid: 'prerequisite',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Prerequisite' ),\n\t\t\t\t\t\tswitch_attribute: 'has_prerequisite',\n\t\t\t\t\t\ttype: 'switch-select',\n\t\t\t\t\t\toptions: function() {\n\t\t\t\t\t\t\treturn this.get_available_prereq_options();\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t], [\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'drip_method',\n\t\t\t\t\t\tid: 'drip-method',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Drip Method' ),\n\t\t\t\t\t\tswitch_attribute: 'drip_method',\n\t\t\t\t\t\ttype: 'select',\n\t\t\t\t\t\toptions: function() {\n\n\t\t\t\t\t\t\tvar options = [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tkey: '',\n\t\t\t\t\t\t\t\t\tval: LLMS.l10n.translate( 'None' ),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tkey: 'date',\n\t\t\t\t\t\t\t\t\tval: LLMS.l10n.translate( 'On a specific date' ),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tkey: 'enrollment',\n\t\t\t\t\t\t\t\t\tval: LLMS.l10n.translate( '# of days after course enrollment' ),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t];\n\n\t\t\t\t\t\t\tif ( this.get_course().get( 'start_date' ) ) {\n\t\t\t\t\t\t\t\toptions.push( {\n\t\t\t\t\t\t\t\t\tkey: 'start',\n\t\t\t\t\t\t\t\t\tval: LLMS.l10n.translate( '# of days after course start date' ),\n\t\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif ( 'yes' === this.get( 'has_prerequisite' ) ) {\n\t\t\t\t\t\t\t\toptions.push( {\n\t\t\t\t\t\t\t\t\tkey: 'prerequisite',\n\t\t\t\t\t\t\t\t\tval: LLMS.l10n.translate( '# of days after prerequisite lesson completion' ),\n\t\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\treturn options;\n\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'days_before_available',\n\t\t\t\t\t\tcondition: function() {\n\t\t\t\t\t\t\treturn ( -1 !== [ 'enrollment', 'start', 'prerequisite' ].indexOf( this.get( 'drip_method' ) ) );\n\t\t\t\t\t\t},\n\t\t\t\t\t\tid: 'days-before-available',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( '# of days' ),\n\t\t\t\t\t\tmin: 0,\n\t\t\t\t\t\ttype: 'number',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'date_available',\n\t\t\t\t\t\tdate_format: 'Y-m-d',\n\t\t\t\t\t\tcondition: function() {\n\t\t\t\t\t\t\treturn ( 'date' === this.get( 'drip_method' ) );\n\t\t\t\t\t\t},\n\t\t\t\t\t\tid: 'date-available',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Date' ),\n\t\t\t\t\t\ttimepicker: 'false',\n\t\t\t\t\t\ttype: 'datepicker',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'time_available',\n\t\t\t\t\t\tcondition: function() {\n\t\t\t\t\t\t\treturn ( 'date' === this.get( 'drip_method' ) );\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdatepicker: 'false',\n\t\t\t\t\t\tdate_format: 'h:i A',\n\t\t\t\t\t\tid: 'time-available',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Time' ),\n\t\t\t\t\t\ttype: 'datepicker',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t],\n\t\t},\n\n\t};\n\n} );\n\n","/**\n * Lesson Model\n * @since 3.13.0\n * @version 3.19.3\n */\ndefine( 'Models/Lesson',[ 'Models/Quiz', 'Models/_Relationships', 'Models/_Utilities', 'Schemas/Lesson' ], function( Quiz, Relationships, Utilities, LessonSchema ) {\n\n\treturn Backbone.Model.extend( _.defaults( {\n\n\t\t/**\n\t\t * Model relationships\n\t\t * @type {Object}\n\t\t */\n\t\trelationships: {\n\t\t\tparents: {\n\t\t\t\tmodel: 'section',\n\t\t\t\ttype: 'model',\n\t\t\t},\n\t\t\tchildren: {\n\t\t\t\tquiz: {\n\t\t\t\t\tclass: 'Quiz',\n\t\t\t\t\tconditional: function( model ) {\n\t\t\t\t\t\t// if quiz is enabled OR not enabled but we have some quiz data as an obj\n\t\t\t\t\t\treturn ( 'yes' === model.get( 'quiz_enabled' ) || ! _.isEmpty( model.get( 'quiz' ) ) );\n\t\t\t\t\t},\n\t\t\t\t\tmodel: 'llms_quiz',\n\t\t\t\t\ttype: 'model',\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\n\t\t/**\n\t\t * Lesson Settings Schema\n\t\t * @type {Object}\n\t\t */\n\t\tschema: LessonSchema,\n\n\t\t/**\n\t\t * New lesson defaults\n\t\t * @return obj\n\t\t * @since 3.13.0\n\t\t * @version 3.17.1\n\t\t */\n\t\tdefaults: function() {\n\t\t\treturn {\n\t\t\t\tid: _.uniqueId( 'temp_' ),\n\t\t\t\ttitle: LLMS.l10n.translate( 'New Lesson' ),\n\t\t\t\ttype: 'lesson',\n\t\t\t\torder: this.collection ? this.collection.length + 1 : 1,\n\t\t\t\tparent_course: window.llms_builder.course.id,\n\t\t\t\tparent_section: '',\n\n\t\t\t\t// urls\n\t\t\t\tedit_url: '',\n\t\t\t\tview_url: '',\n\n\t\t\t\t// editable fields\n\t\t\t\tcontent: '',\n\t\t\t\taudio_embed: '',\n\t\t\t\thas_prerequisite: 'no',\n\t\t\t\trequire_passing_grade: 'yes',\n\t\t\t\trequire_assignment_passing_grade: 'yes',\n\t\t\t\tvideo_embed: '',\n\t\t\t\tfree_lesson: '',\n\n\t\t\t\t// other fields\n\t\t\t\tassignment: {}, // assignment model/data\n\t\t\t\tassignment_enabled: 'no',\n\n\t\t\t\tquiz: {}, // quiz model/data\n\t\t\t\tquiz_enabled: 'no',\n\n\t\t\t\t_forceSync: false,\n\n\t\t\t};\n\t\t},\n\n\t\t/**\n\t\t * Initializer\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\tthis.init_custom_schema();\n\t\t\tthis.startTracking();\n\t\t\tthis.maybe_init_assignments();\n\t\t\tthis.init_relationships();\n\n\t\t\t// if the lesson ID isn't set on a quiz, set it\n\t\t\tvar quiz = this.get( 'quiz' );\n\t\t\tif ( ! _.isEmpty( quiz ) && ! quiz.get( 'lesson_id' ) ) {\n\t\t\t\tquiz.set( 'lesson_id', this.get( 'id' ) );\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve a reference to the parent course of the lesson\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_course: function() {\n\t\t\treturn this.get_parent().get_parent();\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the translated post type name for the model's type\n\t\t * @param bool plural if true, returns the plural, otherwise returns singular\n\t\t * @return string\n\t\t * @since 3.16.12\n\t\t * @version 3.16.12\n\t\t */\n\t\tget_l10n_type: function( plural ) {\n\n\t\t\tif ( plural ) {\n\t\t\t\treturn LLMS.l10n.translate( 'lessons' );\n\t\t\t}\n\n\t\t\treturn LLMS.l10n.translate( 'lesson' );\n\t\t},\n\n\t\t/**\n\t\t * Override default get_parent to grab from collection if models parent isn't set\n\t\t * @return obj\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tget_parent: function() {\n\n\t\t\tvar rels = this.get_relationships();\n\t\t\tif ( rels.parent && rels.parent.reference ) {\n\t\t\t\treturn rels.parent.reference;\n\t\t\t} else if ( this.collection && this.collection.parent ) {\n\t\t\t\treturn this.collection.parent;\n\t\t\t}\n\t\t\treturn false;\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve an array of prerequisite options available for the current lesson\n\t\t * @return obj\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tget_available_prereq_options: function() {\n\n\t\t\tvar parent_section_index = this.get_parent().collection.indexOf( this.get_parent() ),\n\t\t\t\tlesson_index_in_section = this.collection.indexOf( this ),\n\t\t\t\toptions = [];\n\n\t\t\tthis.get_course().get( 'sections' ).each( function( section, curr_sec_index ) {\n\t\t\t\tif ( curr_sec_index <= parent_section_index ) {\n\t\t\t\t\tvar group = {\n\t\t\t\t\t\t\t/* translators: %1$d = section order number, %2$s = section title */\n\t\t\t\t\t\t\tlabel: LLMS.l10n.replace( 'Section %1$d: %2$s', {\n\t\t\t\t\t\t\t\t'%1$d': section.get( 'order' ),\n\t\t\t\t\t\t\t\t'%2$s': section.get( 'title' )\n\t\t\t\t\t\t\t} ),\n\t\t\t\t\t\t\toptions: [],\n\t\t\t\t\t\t};\n\n\t\t\t\t\tsection.get( 'lessons' ).each( function( lesson, curr_les_index ) {\n\t\t\t\t\t\tif ( curr_sec_index !== parent_section_index || curr_les_index < lesson_index_in_section ) {\n\t\t\t\t\t\t\t/* translators: %1$d = lesson order number, %2$s = lesson title */\n\t\t\t\t\t\t\tgroup.options.push( {\n\t\t\t\t\t\t\t\tkey: lesson.get( 'id' ),\n\t\t\t\t\t\t\t\tval: LLMS.l10n.replace( 'Lesson %1$d: %2$s', {\n\t\t\t\t\t\t\t\t\t'%1$d': lesson.get( 'order' ),\n\t\t\t\t\t\t\t\t\t'%2$s': lesson.get( 'title' )\n\t\t\t\t\t\t\t\t} ),\n\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t}\n\t\t\t\t\t}, this );\n\n\t\t\t\t\toptions.push( group );\n\t\t\t\t}\n\t\t\t}, this );\n\n\t\t\treturn options;\n\n\t\t},\n\n\t\t/**\n\t\t * Add a new quiz to the lesson\n\t\t * @param obj data object of quiz data used to construct a new quiz model\n\t\t * @return obj model for the created quiz\n\t\t * @since 3.16.0\n\t\t * @version 3.19.3\n\t\t */\n\t\tadd_quiz: function( data ) {\n\n\t\t\tdata = data || {};\n\n\t\t\tdata.lesson_id = this.id;\n\t\t\tdata._questions_loaded = true;\n\n\t\t\tif ( ! data.title ) {\n\n\t\t\t\tdata.title = LLMS.l10n.replace( '%1$s Quiz', {\n\t\t\t\t\t'%1$s': this.get( 'title' ),\n\t\t\t\t} );\n\n\t\t\t}\n\n\t\t\tthis.set( 'quiz', data );\n\t\t\tthis.init_relationships();\n\n\t\t\tvar quiz = this.get( 'quiz' );\n\t\t\tthis.set( 'quiz_enabled', 'yes' );\n\n\t\t\treturn quiz;\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if this is the first lesson\n\t\t * @return {Boolean}\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tis_first_in_course: function() {\n\n\t\t\t// if it's not the first item in the section it cant be the first lesson\n\t\t\tif ( this.collection.indexOf( this ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// if it's not the first section it cant' be first lesson\n\t\t\tvar section = this.get_parent();\n\t\t\tif ( section.collection.indexOf( section ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// it's first lesson in first section\n\t\t\treturn true;\n\n\t\t},\n\n\t\t/**\n\t\t * Initialize lesson assignments *if* the assignments addon is availalbe and enabled\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tmaybe_init_assignments: function() {\n\n\t\t\tif ( ! window.llms_builder.assignments ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis.relationships.children.assignment = {\n\t\t\t\tclass: 'Assignment',\n\t\t\t\tconditional: function( model ) {\n\t\t\t\t\t// if assignment is enabled OR not enabled but we have some assignment data as an obj\n\t\t\t\t\treturn ( 'yes' === model.get( 'assignment_enabled' ) || ! _.isEmpty( model.get( 'assignment' ) ) );\n\t\t\t\t},\n\t\t\t\tmodel: 'llms_assignment',\n\t\t\t\ttype: 'model',\n\t\t\t};\n\n\t\t},\n\n\t}, Relationships, Utilities ) );\n\n} );\n\n","/**\n * Lessons Collection\n * @since 3.13.0\n * @version 3.17.0\n */\ndefine( 'Collections/Lessons',[ 'Models/Lesson' ], function( model ) {\n\n\treturn Backbone.Collection.extend( {\n\n\t\t/**\n\t\t * Model for collection items\n\t\t * @type obj\n\t\t */\n\t\tmodel: model,\n\n\t\t/**\n\t\t * Initializer\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\t// reorder called by LessonList view when sortable drops occur\n\t\t\tthis.on( 'reorder', this.on_reorder );\n\n\t\t\t// when a lesson is added or removed, update order\n\t\t\tthis.on( 'add', this.on_reorder );\n\t\t\tthis.on( 'remove', this.on_reorder );\n\n\t\t},\n\n\t\t/**\n\t\t * On lesson reorder callback\n\t\t *\n\t\t * Update the order attr of each lesson to reflect the new lesson order\n\t\t * Validate prerequisite (if set) and unset it if it's no longer a valid prereq\n\t\t *\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\ton_reorder: function() {\n\t\t\tthis.update_order();\n\t\t\tthis.validate_prereqs();\n\t\t},\n\n\t\t/**\n\t\t * Update lesson order attribute of all lessons when lessons are reordered\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tupdate_order: function() {\n\n\t\t\tthis.each( function( lesson ) {\n\t\t\t\tlesson.set( 'order', this.indexOf( lesson ) + 1 );\n\t\t\t}, this );\n\n\t\t},\n\n\n\t\t/**\n\t\t * Validate prerequisite (if set) and unset it if it's no longer a valid prereq\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tvalidate_prereqs: function() {\n\n\t\t\tthis.each( function( lesson ) {\n\n\t\t\t\t// validate prereqs\n\t\t\t\tif ( 'yes' === lesson.get( 'has_prerequisite' ) ) {\n\t\t\t\t\tvar valid = _.pluck( _.flatten( _.pluck( lesson.get_available_prereq_options(), 'options' ) ), 'key' );\n\t\t\t\t\tif ( -1 === valid.indexOf( lesson.get( 'prerequisite' ) * 1 ) ) {\n\t\t\t\t\t\tlesson.set( {\n\t\t\t\t\t\t\tprerequisite: 0,\n\t\t\t\t\t\t\thas_prerequisite: 'no',\n\t\t\t\t\t\t} );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t}, this );\n\n\t\t},\n\n\t} );\n\n} );\n\n","/**\n * Quiz Question Type Collection\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Collections/QuestionTypes',[ 'Models/QuestionType' ], function( model ) {\n\n\treturn Backbone.Collection.extend( {\n\n\t\t/**\n\t\t * Model for collection items\n\t\t * @type obj\n\t\t */\n\t\tmodel: model,\n\n\t\t/**\n\t\t * Initializer\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\tthis.on( 'add', this.comparator );\n\t\t\tthis.on( 'remove', this.comparator );\n\n\t\t},\n\n\t\t/**\n\t\t * Comparator (sorts collection)\n\t\t * @param obj model QuestionType model\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tcomparator: function( model ) {\n\n\t\t\treturn model.get( 'group' ).order;\n\n\t\t},\n\n\t} );\n\n} );\n\n","/**\n * Section Model\n * @since 3.16.0\n * @version 3.16.12\n */\ndefine( 'Models/Section',[ 'Collections/Lessons', 'Models/_Relationships' ], function( Lessons, Relationships ) {\n\n\treturn Backbone.Model.extend( _.defaults( {\n\n\t\trelationships: {\n\t\t\tparent: {\n\t\t\t\tmodel: 'course',\n\t\t\t\ttype: 'model',\n\t\t\t},\n\t\t\tchildren: {\n\t\t\t\tlessons: {\n\t\t\t\t\tclass: 'Lessons',\n\t\t\t\t\tmodel: 'lesson',\n\t\t\t\t\ttype: 'collection',\n\t\t\t\t},\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * New section defaults\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tdefaults: function() {\n\t\t\treturn {\n\t\t\t\tid: _.uniqueId( 'temp_' ),\n\t\t\t\tlessons: [],\n\t\t\t\torder: this.collection ? this.collection.length + 1 : 1,\n\t\t\t\tparent_course: window.llms_builder.course.id,\n\t\t\t\ttitle: LLMS.l10n.translate( 'New Section' ),\n\t\t\t\ttype: 'section',\n\n\t\t\t\t_expanded: false,\n\t\t\t\t_selected: false,\n\t\t\t};\n\t\t},\n\n\t\t/**\n\t\t * Initialize\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\tthis.startTracking();\n\t\t\tthis.init_relationships();\n\n\t\t},\n\n\t\t/**\n\t\t * Add a lesson to the section\n\t\t * @param obj data hash of lesson data (creates new lesson)\n\t\t * or existing lesson as a Backbone.Model\n\t\t * @param obj options has of options\n\t\t * @return obj Backbone.Model of the new/updated lesson\n\t\t * @since 3.16.0\n\t\t * @version 3.16.11\n\t\t */\n\t\tadd_lesson: function( data, options ) {\n\n\t\t\tdata = data || {};\n\t\t\toptions = options || {};\n\n\t\t\tif ( data instanceof Backbone.Model ) {\n\t\t\t\tdata.set( 'parent_section', this.get( 'id' ) );\n\t\t\t\tdata.set_parent( this );\n\t\t\t} else {\n\t\t\t\tdata.parent_section = this.get( 'id' );\n\t\t\t}\n\n\t\t\treturn this.get( 'lessons' ).add( data, options );\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the translated post type name for the model's type\n\t\t * @param bool plural if true, returns the plural, otherwise returns singular\n\t\t * @return string\n\t\t * @since 3.16.12\n\t\t * @version 3.16.12\n\t\t */\n\t\tget_l10n_type: function( plural ) {\n\n\t\t\tif ( plural ) {\n\t\t\t\treturn LLMS.l10n.translate( 'sections' );\n\t\t\t}\n\n\t\t\treturn LLMS.l10n.translate( 'section' );\n\t\t},\n\n\t\t/**\n\t\t * Get next section in the collection\n\t\t * @param bool circular if true handles the collection in a circle\n\t\t * \tif current is the last section, returns the first section\n\t\t * \tif current is the first section, returns the last section\n\t\t * @return obj|false\n\t\t * @since 3.16.11\n\t\t * @version 3.16.11\n\t\t */\n\t\tget_next: function( circular ) {\n\t\t\treturn this._get_sibling( 'next', circular );\n\t\t},\n\n\t\t/**\n\t\t * Get prev section in the collection\n\t\t * @param bool circular if true handles the collection in a circle\n\t\t * \tif current is the last section, returns the first section\n\t\t * \tif current is the first section, returns the last section\n\t\t * @return obj|false\n\t\t * @since 3.16.11\n\t\t * @version 3.16.11\n\t\t */\n\t\tget_prev: function( circular ) {\n\t\t\treturn this._get_sibling( 'prev', circular );\n\t\t},\n\n\t\t/**\n\t\t * Get a sibling section\n\t\t * @param string direction siblings direction [next|prev]\n\t\t * @param bool circular if true handles the collection in a circle\n\t\t * \tif current is the last section, returns the first section\n\t\t * \tif current is the first section, returns the last section\n\t\t * @return obj|false\n\t\t * @since 3.16.11\n\t\t * @version 3.16.11\n\t\t */\n\t\t_get_sibling: function( direction, circular ) {\n\n\t\t\tcircular = ( 'undefined' === circular ) ? true : circular;\n\n\t\t\tvar max = this.collection.size() - 1,\n\t\t\t\tindex = this.collection.indexOf( this ),\n\t\t\t\tsibling_index;\n\n\t\t\tif ( 'next' === direction ) {\n\t\t\t\tsibling_index = index + 1;\n\t\t\t} else if ( 'prev' === direction ) {\n\t\t\t\tsibling_index = index - 1;\n\t\t\t}\n\n\t\t\t// dont retrieve greater than max or less than min\n\t\t\tif ( sibling_index <= max || sibling_index <= 0 ) {\n\n\t\t\t\treturn this.collection.at( sibling_index );\n\n\t\t\t} else if ( circular ) {\n\n\t\t\t\tif ( 'next' === direction ) {\n\t\t\t\t\treturn this.collection.first();\n\t\t\t\t} else if ( 'prev' === direction ) {\n\t\t\t\t\treturn this.collection.last();\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn false;\n\n\t\t},\n\n\t}, Relationships ) );\n\n} );\n\n","/**\n * Sections Collection\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Collections/Sections',[ 'Models/Section' ], function( model ) {\n\n\treturn Backbone.Collection.extend( {\n\n\t\t/**\n\t\t * Model for collection items\n\t\t * @type obj\n\t\t */\n\t\tmodel: model,\n\n\t\t/**\n\t\t * Initialize\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\tvar self = this;\n\n\t\t\t// reorder called by SectionList view when sortable drops occur\n\t\t\tthis.on( 'reorder', this.update_order );\n\n\t\t\t// when a section is added or removed, update order\n\t\t\tthis.on( 'add', this.update_order );\n\t\t\tthis.on( 'remove', this.update_order );\n\n\t\t},\n\n\t\t/**\n\t\t * Update the order attr of each section in the list to reflect the order of the collection\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tupdate_order: function() {\n\n\t\t\tvar self = this;\n\n\t\t\tthis.each( function( section ) {\n\n\t\t\t\tsection.set( 'order', self.indexOf( section ) + 1 );\n\n\t\t\t} );\n\n\t\t},\n\n\t} );\n\n} );\n\n","/**\n * Lessons Collection\n * @since 3.13.0\n * @version 3.16.0\n */\ndefine( 'Collections/loader',[\n\t\t'Collections/Lessons',\n\t\t'Collections/QuestionChoices',\n\t\t'Collections/Questions',\n\t\t'Collections/QuestionTypes',\n\t\t'Collections/Sections'\n\t], function(\n\t\tLessons,\n\t\tQuestionChoices,\n\t\tQuestions,\n\t\tQuestionTypes,\n\t\tSections\n\t) {\n\n\treturn {\n\t\tLessons: Lessons,\n\t\tQuestionChoices: QuestionChoices,\n\t\tQuestions: Questions,\n\t\tQuestionTypes: QuestionTypes,\n\t\tSections: Sections,\n\t};\n\n} );\n\n","/**\n * Abstract LifterLMS Model\n * @since 3.17.0\n * @version 3.17.0\n */\ndefine( 'Models/Abstract',[ 'Models/_Relationships', 'Models/_Utilities' ], function( Relationships, Utilities ) {\n\n\treturn Backbone.Model.extend( _.defaults( {}, Relationships, Utilities ) );\n\n} );\n\n","/**\n * Course Model\n * @since 3.16.0\n * @version 3.16.11\n */\ndefine( 'Models/Course',[ 'Collections/Sections', 'Models/_Relationships', 'Models/_Utilities' ], function( Sections, Relationships, Utilities ) {\n\n\treturn Backbone.Model.extend( _.defaults( {\n\n\t\trelationships: {\n\t\t\tchildren: {\n\t\t\t\tsections: {\n\t\t\t\t\tclass: 'Sections',\n\t\t\t\t\tmodel: 'section',\n\t\t\t\t\ttype: 'collection',\n\t\t\t\t},\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * New Course Defaults\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tdefaults: function() {\n\t\t\treturn {\n\t\t\t\tedit_url: '',\n\t\t\t\tsections: [],\n\t\t\t\ttitle: 'New Course',\n\t\t\t\ttype: 'course',\n\t\t\t\tview_url: '',\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Init\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\tthis.startTracking();\n\t\t\tthis.init_relationships();\n\n\t\t\t// Sidebar \"New Section\" button broadcast\n\t\t\tBackbone.pubSub.on( 'add-new-section', this.add_section, this );\n\n\t\t\t// Sidebar \"New Lesson\" button broadcast\n\t\t\tBackbone.pubSub.on( 'add-new-lesson', this.add_lesson, this );\n\n\t\t\tBackbone.pubSub.on( 'lesson-search-select', this.add_existing_lesson, this );\n\n\t\t},\n\n\t\t/**\n\t\t * Add an existing lesson to the course\n\t\t * Duplicate a lesson from this or another course or attach an orphaned lesson\n\t\t * @param obj lesson lesson data obj\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.11\n\t\t */\n\t\tadd_existing_lesson: function( lesson ) {\n\n\t\t\tvar data = lesson.data;\n\n\t\t\tif ( 'clone' === lesson.action ) {\n\n\t\t\t\tdelete data.id;\n\t\t\t\tif ( data.quiz ) {\n\t\t\t\t\tdelete data.quiz;\n\t\t\t\t\tdata.quiz_enabled = 'no';\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\tdata._forceSync = true;\n\n\t\t\t}\n\n\t\t\tdelete data.order;\n\t\t\tdelete data.parent_course;\n\t\t\tdelete data.parent_section;\n\n\t\t\tthis.add_lesson( data );\n\n\t\t},\n\n\t\t/**\n\t\t * Add a new lesson to the course\n\t\t * @param obj data lesson data\n\t\t * @return obj Backbone.Model of the lesson\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tadd_lesson: function( data ) {\n\n\t\t\tdata = data || {};\n\t\t\tvar options = {},\n\t\t\t\tsection;\n\n\t\t\tif ( ! data.parent_section ) {\n\t\t\t\tsection = this.get_selected_section();\n\t\t\t\tif ( ! section ) {\n\t\t\t\t\tsection = this.get( 'sections' ).last();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tsection = this.get( 'sections' ).get( data.parent_section );\n\t\t\t}\n\n\t\t\tdata._selected = true;\n\n\t\t\tdata.parent_course = this.get( 'id' );\n\n\t\t\tvar lesson = section.add_lesson( data, options );\n\t\t\tBackbone.pubSub.trigger( 'new-lesson-added', lesson );\n\n\t\t\t// expand the section\n\t\t\tsection.set( '_expanded', true );\n\n\t\t\treturn lesson;\n\n\t\t},\n\n\t\t/**\n\t\t * Add a new section to the course\n\t\t * @param obj data section data\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tadd_section: function( data ) {\n\n\t\t\tdata = data || {};\n\t\t\tvar sections = this.get( 'sections' ),\n\t\t\t\toptions = {},\n\t\t\t\tselected = this.get_selected_section();\n\n\t\t\t// if a section is selected, add the new section after the currently selected one\n\t\t\tif ( selected ) {\n\t\t\t\toptions.at = sections.indexOf( selected ) + 1;\n\t\t\t}\n\n\t\t\tsections.add( data, options );\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the currently selected section in the course\n\t\t * @return obj|undefined\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_selected_section: function() {\n\n\t\t\treturn this.get( 'sections' ).find( function( model ) {\n\t\t\t\treturn model.get( '_selected' );\n\t\t\t} );\n\n\t\t},\n\n\t}, Relationships, Utilities ) );\n\n} );\n\n","/**\n * Load all models\n * @return obj\n * @since 3.16.0\n * @version 3.17.0\n */\ndefine( 'Models/loader',[\n\t\t'Models/Abstract',\n\t\t'Models/Course',\n\t\t'Models/Image',\n\t\t'Models/Lesson',\n\t\t'Models/Question',\n\t\t'Models/QuestionChoice',\n\t\t'Models/QuestionType',\n\t\t'Models/Quiz',\n\t\t'Models/Section'\n\t],\n\tfunction(\n\t\tAbstract,\n\t\tCourse,\n\t\tImage,\n\t\tLesson,\n\t\tQuestion,\n\t\tQuestionChoice,\n\t\tQuestionType,\n\t\tQuiz,\n\t\tSection\n\t) {\n\n\treturn {\n\t\tAbstract: Abstract,\n\t\tCourse: Course,\n\t\tImage: Image,\n\t\tLesson: Lesson,\n\t\tQuestion: Question,\n\t\tQuestionChoice: QuestionChoice,\n\t\tQuestionType: QuestionType,\n\t\tQuiz: Quiz,\n\t\tSection: Section,\n\t};\n\n} );\n\n","/**\n * Detachable model\n * @type {Object}\n * @since 3.16.12\n * @version 3.16.12\n */\ndefine( 'Views/_Detachable',[], function() {\n\n\treturn {\n\n\t\t/**\n\t\t * DOM Events\n\t\t * @type {Object}\n\t\t * @since 3.16.12\n\t\t * @version 3.16.12\n\t\t */\n\t\tevents: {\n\t\t\t'click a[href=\"#llms-detach-model\"]': 'detach_model',\n\t\t},\n\n\t\t/**\n\t\t * Detaches a model from it's parent (doesn't delete)\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.16.12\n\t\t * @version 3.16.12\n\t\t */\n\t\tdetach_model: function( event ) {\n\n\t\t\tif ( event ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tevent.stopPropagation();\n\t\t\t}\n\n\t\t\tvar msg = LLMS.l10n.replace( 'Are you sure you want to detach this %s?', {\n\t\t\t\t'%s': this.model.get_l10n_type(),\n\t\t\t} );\n\n\t\t\tif ( window.confirm( msg ) ) {\n\n\t\t\t\tif ( this.model.collection ) {\n\t\t\t\t\tthis.model.collection.remove( this.model );\n\t\t\t\t}\n\n\t\t\t\t// publish global event\n\t\t\t\tBackbone.pubSub.trigger( 'model-detached', this.model );\n\n\t\t\t\t// trigger local event so extending views can run other actions where necessary\n\t\t\t\tthis.trigger( 'model-trashed', this.model );\n\n\t\t\t}\n\n\t\t},\n\n\t}\n\n} );\n\n","/**\n * Handles UX and Events for inline editing of views\n * Use with a Model's View\n * Allows editing model.title field via .llms-editable-title elements\n * @type {Object}\n * @since 3.16.0\n * @version 3.17.8\n */\ndefine( 'Views/_Editable',[], function() {\n\n\treturn {\n\n\t\tmedia_lib: null,\n\n\t\t/**\n\t\t * DOM Events\n\t\t * @type {Object}\n\t\t * @since 3.16.0\n\t\t * @version 3.17.8\n\t\t */\n\t\tevents: {\n\t\t\t'click .llms-add-image': 'open_media_lib',\n\t\t\t'click a[href=\"#llms-edit-slug\"]': 'make_slug_editable',\n\t\t\t'click a[href=\"#llms-remove-image\"]': 'remove_image',\n\t\t\t'change .llms-editable-select select': 'on_select',\n\t\t\t'change .llms-switch input[type=\"checkbox\"]': 'toggle_switch',\n\t\t\t'change .llms-editable-radio input': 'on_radio_select',\n\t\t\t'focusin .llms-input': 'on_focus',\n\t\t\t'focusout .llms-input': 'on_blur',\n\t\t\t'keydown .llms-input': 'on_keydown',\n\t\t\t'input .llms-input[type=\"number\"]': 'on_blur',\n\t\t\t'paste .llms-input[data-formatting]': 'on_paste',\n\t\t},\n\n\t\t/**\n\t\t * Retrieve a list of allowed tags for a given element\n\t\t * @param obj $el jQuery selector for the element\n\t\t * @return array\n\t\t * @since 3.16.0\n\t\t * @version 3.17.8\n\t\t */\n\t\tget_allowed_tags: function( $el ) {\n\n\t\t\tif ( $el.attr( 'data-formatting' ) ) {\n\t\t\t\treturn _.map( $el.attr( 'data-formatting' ).split( ',' ), function( tag ) {\n\t\t\t\t\treturn tag.trim();\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\treturn [ 'b', 'i', 'u', 'strong', 'em' ];\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the content of an element\n\t\t * @param obj $el jQuery object of the element\n\t\t * @return string\n\t\t * @since 3.16.0\n\t\t * @version 3.17.8\n\t\t */\n\t\tget_content: function( $el ) {\n\n\t\t\tif ( 'INPUT' === $el[0].tagName ) {\n\t\t\t\treturn $el.val();\n\t\t\t}\n\n\t\t\tif ( ! $el.attr( 'data-formatting' ) && ! $el.hasClass( 'ql-editor' ) ) {\n\t\t\t\treturn $el.text();\n\t\t\t}\n\n\t\t\treturn _.stripFormatting( $el.html(), this.get_allowed_tags( $el ) );\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if changes have been made to the element\n\t\t * @param {[obj]} event js event object\n\t\t * @return {Boolean} true when changes have been made, false otherwise\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\thas_changed: function( event ) {\n\t\t\tvar $el = $( event.target );\n\t\t\treturn ( $el.attr( 'data-original-content' ) !== this.get_content( $el ) );\n\t\t},\n\n\t\t/**\n\t\t * Ensure that new content is at least 1 character long\n\t\t * @param obj event js event object\n\t\t * @return boolean\n\t\t * @since 3.16.0\n\t\t * @version 3.17.2\n\t\t */\n\t\tis_valid: function( event ) {\n\n\t\t\tvar self = this,\n\t\t\t\t$el = $( event.target ),\n\t\t\t\tcontent = this.get_content( $el ),\n\t\t\t\ttype = $el.attr( 'data-type' );\n\n\t\t\tif ( ( $el.attr( 'required' ) || $el.attr( 'data-required' ) ) && content.length < 1 ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tif ( 'url' === type || 'video' === type ) {\n\t\t\t\tif ( ! this._validate_url( this.get_content( $el ) ) ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t} else if ( 'permalink' === type ) {\n\n\t\t\t\tLLMS.Ajax.call( {\n\t\t\t\t\tdata: {\n\t\t\t\t\t\taction: 'llms_builder',\n\t\t\t\t\t\taction_type: 'get_permalink',\n\t\t\t\t\t\tcourse_id: window.llms_builder.CourseModel.get( 'id' ),\n\t\t\t\t\t\tid: self.model.get( 'id' ),\n\t\t\t\t\t\ttitle: self.model.get( 'title' ),\n\t\t\t\t\t\tslug: content,\n\t\t\t\t\t},\n\t\t\t\t\tbeforeSend: function() {\n\t\t\t\t\t\tLLMS.Spinner.start( $el.closest( '.llms-editable-toggle-group' ), 'small' );\n\t\t\t\t\t},\n\t\t\t\t\tsuccess: function( r ) {\n\n\t\t\t\t\t\tif ( r.permalink && r.slug ) {\n\t\t\t\t\t\t\tself.model.set( 'permalink', r.permalink );\n\t\t\t\t\t\t\tself.model.set( 'name', r.slug );\n\t\t\t\t\t\t\tself.render();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\t\t\t\t} );\n\n\t\t\t}\n\n\t\t\treturn true;\n\n\t\t},\n\n\t\t/**\n\t\t * Initialize datepicker elements\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tinit_datepickers: function() {\n\n\t\t\tthis.$el.find( '.llms-editable-date input' ).each( function() {\n\n\t\t\t\t$( this ).datetimepicker( {\n\t\t\t\t\tformat: $( this ).attr( 'data-date-format' ) || 'Y-m-d h:i A',\n\t\t\t\t\tdatepicker: ( undefined === $( this ).attr( 'data-date-datepicker' ) ) ? true : ( 'true' == $( this ).attr( 'data-date-datepicker' ) ),\n\t\t\t\t\ttimepicker: ( undefined === $( this ).attr( 'data-date-timepicker' ) ) ? true : ( 'true' == $( this ).attr( 'data-date-timepicker' ) ),\n\t\t\t\t\tonClose: function( current_time, $input ) {\n\t\t\t\t\t\t$input.blur();\n\t\t\t\t\t}\n\t\t\t\t} );\n\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * Initialize elements that allow inline formatting\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinit_formatting_els: function() {\n\n\t\t\tvar self = this;\n\n\t\t\tthis.$el.find( '.llms-input-formatting[data-formatting]' ).each( function() {\n\n\t\t\t\tvar formatting = $( this ).attr( 'data-formatting' ).split( ',' ),\n\t\t\t\t\tattr = $( this ).attr( 'data-attribute' );\n\n\t\t\t\tvar ed = new Quill( this, {\n\t\t\t\t\tmodules: {\n\t\t\t\t\t\ttoolbar: [ formatting ],\n\t\t\t\t\t\tkeyboard: {\n\t\t\t\t\t\t\tbindings: {\n\t\t\t\t\t\t\t\ttab: {\n\t\t\t\t\t\t\t\t\tkey: 9,\n\t\t\t\t\t\t\t\t\thandler: function( range, context ) {\n\t\t\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t13: {\n\t\t\t\t\t\t\t\t\tkey: 13,\n\t\t\t\t\t\t\t\t\thandler: function( range, context ) {\n\t\t\t\t\t\t\t\t\t\ted.root.blur();\n\t\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tplaceholder: $( this ).attr( 'data-placeholder' ),\n\t\t\t\t\ttheme: 'bubble',\n\t\t\t\t} );\n\n\t\t\t\ted.on( 'text-change', function( delta, oldDelta, source ) {\n\t\t\t\t\tself.model.set( attr, self.get_content( $( ed.root ) ) );\n\t\t\t\t} );\n\n\t\t\t\tBackbone.pubSub.trigger( 'formatting-ed-init', ed, $( this ), self );\n\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * Initialize editable select elements\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinit_selects: function() {\n\n\t\t\tthis.$el.find( '.llms-editable-select select' ).llmsSelect2( {\n\t\t\t\twidth: '100%',\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * Blur/focusout function for .llms-editable-title elements\n\t\t * Automatically saves changes if changes have been made\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.6\n\t\t */\n\t\ton_blur: function( event ) {\n\n\t\t\tevent.stopPropagation();\n\n\t\t\tthis.model.set( '_has_focus', false, { silent: true } );\n\n\t\t\tvar self = this,\n\t\t\t\t$el = $( event.target ),\n\t\t\t\tchanged = this.has_changed( event );\n\n\t\t\tif ( changed ) {\n\n\t\t\t\tif ( ! self.is_valid( event ) ) {\n\t\t\t\t\tself.revert_edits( event );\n\t\t\t\t} else {\n\t\t\t\t\tthis.save_edits( event );\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Focus event for editable inputs\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.16.6\n\t\t * @version 3.16.6\n\t\t */\n\t\ton_focus: function( event ) {\n\n\t\t\tevent.stopPropagation();\n\t\t\tthis.model.set( '_has_focus', true, { silent: true } );\n\n\t\t},\n\n\t\t/**\n\t\t * Handle content pasted into contenteditable fields\n\t\t * This will ensure that HTML from RTF editors isn't pasted into the dom\n\t\t * @param obj event js event obj\n\t\t * @return void\n\t\t * @since 3.17.8\n\t\t * @version 3.17.8\n\t\t */\n\t\ton_paste: function( event ) {\n\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\n\t\t\tvar text = ( event.originalEvent || event ).clipboardData.getData( 'text/plain' );\n\t\t\twindow.document.execCommand( 'insertText', false, text );\n\n\t\t},\n\n\t\t/**\n\t\t * Change event for selectables\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\ton_select: function( event ) {\n\n\t\t\tvar $el = $( event.target ),\n\t\t\t\tmulti = ( $el.attr( 'multiple' ) ),\n\t\t\t\tattr = $el.attr( 'name' ),\n\t\t\t\t$selected = $el.find( 'option:selected' ),\n\t\t\t\tval;\n\n\t\t\tif ( multi ) {\n\t\t\t\tval = [];\n\t\t\t\tval = $selected.map( function() {\n\t\t\t\t\treturn this.value;\n\t\t\t\t} ).get();\n\t\t\t} else {\n\t\t\t\tval = $selected[0].value;\n\t\t\t}\n\n\t\t\tthis.model.set( attr, val );\n\n\t\t},\n\n\t\t/**\n\t\t * Change event for radio element groups\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.17.6\n\t\t * @version 3.17.6\n\t\t */\n\t\ton_radio_select: function( event ) {\n\n\t\t\tvar $el = $( event.target ),\n\t\t\t\tattr = $el.attr( 'name' ),\n\t\t\t\tval = $el.val();\n\n\t\t\tthis.model.set( attr, val );\n\n\t\t},\n\n\t\t/**\n\t\t * Keydown function for .llms-editable-title elements\n\t\t * Blurs\n\t\t * @param {obj} event js event object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.17.8\n\t\t */\n\t\ton_keydown: function( event ) {\n\n\t\t\tevent.stopPropagation();\n\n\t\t\tvar self = this,\n\t\t\t\tkey = event.which || event.keyCode,\n\t\t\t\tshift = event.shiftKey;\n\t\t\t\t// ctrl = event.metaKey || event.ctrlKey;\n\n\t\t\tswitch ( key ) {\n\n\t\t\t\tcase 13: // enter\n\t\t\t\t\t// shift + enter should add a return\n\t\t\t\t\tif ( ! shift ) {\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\tevent.target.blur();\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t\tcase 27: // escape\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tthis.revert_edits( event );\n\t\t\t\t\tevent.target.blur();\n\t\t\t\tbreak;\n\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Open the WP media lib\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.6\n\t\t */\n\t\topen_media_lib: function( event ) {\n\n\t\t\tevent.stopPropagation();\n\n\t\t\tvar self = this,\n\t\t\t\t$el = $( event.currentTarget );\n\n\t\t\tif ( self.media_lib ) {\n\n\t\t\t\tself.media_lib.uploader.uploader.param( 'post_id' );\n\n\t\t\t} else {\n\n\t\t\t\tself.media_lib = wp.media.frames.file_frame = wp.media( {\n\t\t\t\t\ttitle: LLMS.l10n.translate( 'Select an image' ),\n\t\t\t\t\tbutton: {\n\t\t\t\t\t\ttext: LLMS.l10n.translate( 'Use this image' ),\n\t\t\t\t\t},\n\t\t\t\t\tmultiple: false\t// Set to true to allow multiple files to be selected\n\t\t\t\t} );\n\n\t\t\t\tself.media_lib.on( 'select', function() {\n\n\t\t\t\t\tvar size = $el.attr( 'data-image-size' ),\n\t\t\t\t\t\tattachment = self.media_lib.state().get( 'selection' ).first().toJSON(),\n\t\t\t\t\t\timage = self.model.get( $el.attr( 'data-attribute' ) ),\n\t\t\t\t\t\turl;\n\n\t\t\t\t\tif ( size && attachment.sizes[ size ] ) {\n\t\t\t\t\t\turl = attachment.sizes[ size ].url;\n\t\t\t\t\t} else {\n\t\t\t\t\t\turl = attachment.url;\n\t\t\t\t\t}\n\n\t\t\t\t\timage.set( {\n\t\t\t\t\t\tid: attachment.id,\n\t\t\t\t\t\tsrc: url,\n\t\t\t\t\t} );\n\n\t\t\t\t} );\n\n\t\t\t}\n\n\t\t\tself.media_lib.open();\n\n\n\t\t},\n\n\t\t/**\n\t\t * Click event to remove an image\n\t\t * @param obj event js event obj\n\t\t * @return voids\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tremove_image: function( event ) {\n\n\t\t\tevent.preventDefault();\n\n\t\t\tthis.model.get( $( event.currentTarget ).attr( 'data-attribute' ) ).set( {\n\t\t\t\tid: '',\n\t\t\t\tsrc: '',\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * Helper to undo changes\n\t\t * Bound to \"escape\" key via on_keydwon function\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trevert_edits: function( event ) {\n\t\t\tvar $el = $( event.target ),\n\t\t\t\tval = $el.attr( 'data-original-content' );\n\t\t\t$el.html( val );\n\t\t},\n\n\t\t/**\n\t\t * Sync chages to the model and DB\n\t\t * @param {obj} event js event object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tsave_edits: function( event ) {\n\n\t\t\tvar $el = $( event.target ),\n\t\t\t\tval = this.get_content( $el );\n\n\t\t\tthis.model.set( $el.attr( 'data-attribute' ), val );\n\n\t\t},\n\n\t\t/**\n\t\t * Change event for a switch element\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.17.0\n\t\t */\n\t\ttoggle_switch: function( event ) {\n\n\t\t\tevent.stopPropagation();\n\t\t\tvar $el = $( event.target ),\n\t\t\t\tattr = $el.attr( 'name' ),\n\t\t\t\trerender = $el.attr( 'data-rerender' ),\n\t\t\t\tval;\n\n\t\t\tif ( $el.is( ':checked' ) ) {\n\t\t\t\tval = $el.attr( 'data-on' ) ? $el.attr( 'data-on' ) : 'yes';\n\t\t\t} else {\n\t\t\t\tval = $el.attr( 'data-off' ) ? $el.attr( 'data-off' ) : 'no';\n\t\t\t}\n\n\t\t\tif ( -1 !== attr.indexOf( '.' ) ) {\n\n\t\t\t\tvar split = attr.split( '.' );\n\n\t\t\t\tif ( 'parent' === split[0] ) {\n\t\t\t\t\tthis.model.get_parent().set( split[1], val );\n\t\t\t\t} else {\n\t\t\t\t\tthis.model.get( split[0] ).set( split[1], val );\n\t\t\t\t}\n\n\n\t\t\t} else {\n\n\t\t\t\tthis.model.set( attr, val );\n\n\t\t\t}\n\n\t\t\tthis.trigger( attr.replace( '.', '-' ) + '_toggle', val );\n\n\t\t\tif ( ! rerender || 'yes' === rerender ) {\n\t\t\t\tvar self = this;\n\t\t\t\tsetTimeout( function() {\n\t\t\t\t\tself.render();\n\t\t\t\t}, 100 );\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Initializes a WP Editor on a textarea\n\t\t * @param string id CSS ID of the editor (don't include #)\n\t\t * @param obj settings optional object of settings to pass to wp.editor.initialize()\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinit_editor: function( id, settings ) {\n\n\t\t\tsettings = settings || {};\n\n\t\t\twp.editor.remove( id );\n\n\t\t\twp.editor.initialize( id, $.extend( true, wp.editor.getDefaultSettings(), {\n\t\t\t\tmediaButtons: true,\n\t\t\t\ttinymce: {\n\t\t\t\t\ttoolbar1: 'bold,italic,strikethrough,bullist,numlist,blockquote,hr,alignleft,aligncenter,alignright,link,unlink,wp_adv',\n\t\t\t\t\ttoolbar2: 'formatselect,underline,alignjustify,forecolor,pastetext,removeformat,charmap,outdent,indent,undo,redo,wp_help',\n\t\t\t\t\tsetup: _.bind( this.on_editor_ready, this ),\n\t\t\t\t}\n\t\t\t}, settings ) );\n\n\t\t},\n\n\t\t/**\n\t\t * Setup a permalink editor to allow editing of a permalink\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.16.6\n\t\t * @version 3.16.6\n\t\t */\n\t\tmake_slug_editable: function( event ) {\n\n\t\t\tvar self = this,\n\t\t\t\t$btn = $( event.currentTarget ),\n\t\t\t\t$link = $btn.prevAll( 'a' ),\n\t\t\t\t$input = $btn.prev( 'input.permalink' ),\n\t\t\t\tfull_url = $link.attr( 'href' ),\n\t\t\t\tslug = $input.val(),\n\t\t\t\tshort_url = full_url.replace( slug, '' );\n\n\t\t\t// hide the button\n\t\t\t$btn.hide();\n\n\t\t\t// make the link not clickable\n\t\t\t$link.css( {\n\t\t\t\tcolor: '#999',\n\t\t\t\t'pointer-events': 'none',\n\t\t\t\t'text-decoration': 'none',\n\t\t\t} );\n\n\t\t\t// remove the current slug & trailing slash from the URL\n\t\t\t$link.text( short_url.substring( 0, short_url.length - 1 ) );\n\n\t\t\t// focus in on the field\n\t\t\t$input.show().focus();\n\n\t\t},\n\n\t\t/**\n\t\t * Callback function called after initialization of an editor\n\t\t * Updates UI if a label is present\n\t\t * Binds a change event to ensure editor changes are saved to the model\n\t\t * @param obj editor wp.editor instance\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.17.1\n\t\t */\n\t\ton_editor_ready: function( editor ) {\n\n\t\t\tvar self = this,\n\t\t\t\t$ed = $( '#' + editor.id ),\n\t\t\t\t$parent = $ed.closest( '.llms-editable-editor' ),\n\t\t\t\t$label = $parent.find( '.llms-label' ),\n\t\t\t\tprop = $ed.attr( 'data-attribute' )\n\n\t\t\tif ( $label.length ) {\n\t\t\t\t$label.prependTo( $parent.find( '.wp-editor-tools' ) );\n\t\t\t}\n\n\t\t\t// save changes to the model via Visual ed\n\t\t\teditor.on( 'change', function( event ) {\n\t\t\t\tself.model.set( prop, wp.editor.getContent( editor.id ) );\n\t\t\t} );\n\n\t\t\t// save changes via Text ed\n\t\t\t$ed.on( 'input', function( event ) {\n\t\t\t\tself.model.set( prop, $ed.val() );\n\t\t\t} );\n\n\t\t\t// trigger an input on the Text ed when quicktags buttons are clicked\n\t\t\t$parent.on( 'click', '.quicktags-toolbar .ed_button', function() {\n\t\t\t\tsetTimeout( function() {\n\t\t\t\t\t$ed.trigger( 'input' );\n\t\t\t\t}, 10 );\n\t\t\t} );\n\n\t\t},\n\n\t\t_validate_url: function( str ) {\n\n\t\t\tvar a = document.createElement( 'a' );\n\t\t\ta.href = str;\n\t\t\treturn ( a.host && a.host !== window.location.host );\n\n\t\t}\n\n\t};\n\n} );\n\n","/**\n * _receive override for Backbone.CollectionView core\n * enables connection with jQuery UI draggable buttons\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Views/_Receivable',[], function() {\n\n\treturn {\n\n\t\t/**\n\t\t * Overloads the function from Backbone.CollectionView core because it doesn't properly handle\n\t\t * receieves from a jQuery UI draggable object\n\t\t * @param obj event js event object\n\t\t * @param obj ui jQuery UI object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\t_receive : function( event, ui ) {\n\n\t\t\t// came from sidebar drag\n\t\t\tif ( ui.sender.hasClass( 'ui-draggable' ) ) {\n\t\t\t\tvar index = this._getContainerEl().children().index( ui.helper );\n\t\t\t\tui.helper.remove(); // remove the helper\n\t\t\t\tthis.collection.add( {}, { at: index } );\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar senderListEl = ui.sender;\n\t\t\tvar senderCollectionListView = senderListEl.data( 'view' );\n\t\t\tif( ! senderCollectionListView || ! senderCollectionListView.collection ) return;\n\n\t\t\tvar newIndex = this._getContainerEl().children().index( ui.item );\n\t\t\tvar modelReceived = senderCollectionListView.collection.get( ui.item.attr( 'data-model-cid' ) );\n\t\t\tsenderCollectionListView.collection.remove( modelReceived );\n\t\t\tthis.collection.add( modelReceived, { at : newIndex } );\n\t\t\tmodelReceived.collection = this.collection; // otherwise will not get properly set, since modelReceived.collection might already have a value.\n\t\t\tthis.setSelectedModel( modelReceived );\n\t\t},\n\n\t}\n\n} );\n\n\n","/**\n * Shiftable view mixin function\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Views/_Shiftable',[], function() {\n\n\treturn {\n\n\t\t/**\n\t\t * Conditionally hide action buttons based on section position in collection\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tmaybe_hide_shiftable_buttons: function() {\n\n\t\t\tif ( ! this.model.collection ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar type = this.model.get( 'type' );\n\n\t\t\tif ( this.model.collection.first() === this.model ) {\n\t\t\t\tthis.$el.find( '.shift-up--' + type ).hide();\n\t\t\t} else if ( this.model.collection.last() === this.model ) {\n\t\t\t\tthis.$el.find( '.shift-down--' + type ).hide();\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Move an item in a collection from one position to another\n\t\t * @param int old_index current (old) index within the collection\n\t\t * @param int new_index desired (new) index within the collection\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tshift: function( old_index, new_index ) {\n\n\t\t\tvar collection = this.model.collection;\n\n\t\t\tcollection.remove( this.model );\n\t\t\tcollection.add( this.model, { at: new_index } );\n\t\t\tcollection.trigger( 'reorder' );\n\n\t\t},\n\n\t\t/**\n\t\t * Move an item down the tree one position\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tshift_down: function( e ) {\n\n\t\t\te.preventDefault();\n\t\t\tvar index = this.model.collection.indexOf( this.model );\n\t\t\tthis.shift( index, index + 1 );\n\n\t\t},\n\n\t\t/**\n\t\t * Move an item up the tree one position\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tshift_up: function( e ) {\n\n\t\t\te.preventDefault();\n\t\t\tvar index = this.model.collection.indexOf( this.model );\n\t\t\tthis.shift( index, index - 1 );\n\n\t\t},\n\n\t};\n\n} );\n\n","/**\n * Subview utility mixin\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Views/_Subview',[], function() {\n\n\treturn {\n\n\t\tsubscriptions: {},\n\n\t\t/**\n\t\t * Name of the current subview\n\t\t * @type {String}\n\t\t */\n\t\tstate: '',\n\n\t\t/**\n\t\t * Object of subview data\n\t\t * @type {Object}\n\t\t */\n\t\tviews: {},\n\n\t\t/**\n\t\t * Retrieve a subview by name from this.views\n\t\t * @param string name name of the subview\n\t\t * @return obl|false\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_subview: function( name ) {\n\n\t\t\tif ( this.views[ name ] ) {\n\t\t\t\treturn this.views[ name ];\n\t\t\t}\n\n\t\t\treturn false;\n\n\t\t},\n\n\t\tevents_subscribe: function( events ) {\n\n\t\t\t_.each( events, function( func, event ) {\n\n\t\t\t\tthis.subscriptions[ event ] = func;\n\t\t\t\tBackbone.pubSub.on( event, func, this );\n\n\t\t\t}, this );\n\n\t\t},\n\n\t\tevents_unsubscribe: function() {\n\n\t\t\t_.each( this.subscriptions, function( func, event ) {\n\n\t\t\t\tBackbone.pubSub.off( event, func, this );\n\t\t\t\tdelete this.subscriptions[ event ];\n\n\t\t\t}, this );\n\n\t\t},\n\n\t\t/**\n\t\t * Remove a single subview (and all it's subviews) by name\n\t\t * @param string name name of the subview\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tremove_subview: function( name ) {\n\n\t\t\tvar view = this.get_subview( name );\n\n\t\t\tif ( ! view ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( view.instance ) {\n\n\t\t\t\t// remove the subviews if the view has subviews\n\t\t\t\tif ( ! _.isEmpty( view.instance.views ) ) {\n\t\t\t\t\tview.instance.events_unsubscribe();\n\t\t\t\t\tview.instance.remove_subviews();\n\t\t\t\t}\n\n\t\t\t\tview.instance.off();\n\t\t\t\tview.instance.off( null, null, null );\n\t\t\t\tview.instance.remove();\n\t\t\t\tview.instance.undelegateEvents();\n\n\t\t\t\t// _.each( view.instance, function( val, key ) {\n\t\t\t\t// \tdelete view.instance[ key ];\n\t\t\t\t// } );\n\n\t\t\t\tview.instance = null;\n\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Remove all subviews (and all the subviews of those subviews)\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tremove_subviews: function() {\n\n\t\t\t_.each( this.views, function( data, name ) {\n\n\t\t\t\tthis.remove_subview( name );\n\n\t\t\t}, this );\n\n\t\t},\n\n\t\t/**\n\t\t * Render subviews based on current state\n\t\t * @param obj view_data additional data to pass to the subviews\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender_subviews: function( view_data ) {\n\n\t\t\tview_data = view_data || {};\n\n\t\t\t_.each( this.views, function( data, name ) {\n\n\t\t\t\tif ( this.state === data.state ) {\n\n\t\t\t\t\tthis.render_subview( name, view_data );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tthis.remove_subview( name );\n\n\t\t\t\t}\n\n\t\t\t}, this );\n\n\t\t},\n\n\t\t/**\n\t\t * Render a single subview by name\n\t\t * @param string name name of the subview\n\t\t * @param obj view_data additional data to pass to the subview initializer\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender_subview: function( name, view_data ) {\n\n\t\t\tvar view = this.get_subview( name );\n\n\t\t\tif ( ! view ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis.remove_subview( name );\n\n\t\t\tif ( ! view.instance ) {\n\t\t\t\tview.instance = new view.class( view_data );\n\t\t\t}\n\n\t\t\tview.instance.render();\n\n\t\t},\n\n\t\t/**\n\t\t * Set the current subview\n\t\t * Must call render after!\n\t\t * @param string state name of the state [builder|editor]\n\t\t * @return obj this for chaining\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tset_state: function ( state ) {\n\n\t\t\tthis.state = state;\n\t\t\treturn this;\n\n\t\t},\n\n\t}\n\n} );\n\n","/**\n * Trashable model\n * @type {Object}\n * @since 3.16.12\n * @version 3.16.12\n */\ndefine( 'Views/_Trashable',[], function() {\n\n\treturn {\n\n\t\t/**\n\t\t * DOM Events\n\t\t * @type {Object}\n\t\t * @since 3.16.12\n\t\t * @version 3.16.12\n\t\t */\n\t\tevents: {\n\t\t\t'click a[href=\"#llms-trash-model\"]': 'trash_model',\n\t\t},\n\n\t\t/**\n\t\t * Remove a model from it's parent and delete it\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.16.12\n\t\t * @version 3.16.12\n\t\t */\n\t\ttrash_model: function( event ) {\n\n\t\t\tif ( event ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tevent.stopPropagation();\n\t\t\t}\n\n\t\t\tvar msg = LLMS.l10n.replace( 'Are you sure you want to move this %s to the trash?', {\n\t\t\t\t'%s': this.model.get_l10n_type(),\n\t\t\t} );\n\n\t\t\tif ( window.confirm( msg ) ) {\n\n\t\t\t\tif ( this.model.collection ) {\n\t\t\t\t\tthis.model.collection.remove( this.model );\n\t\t\t\t}\n\n\t\t\t\t// publish event\n\t\t\t\tBackbone.pubSub.trigger( 'model-trashed', this.model );\n\n\t\t\t\t// trigger local event so extending views can run other actions where necessary\n\t\t\t\tthis.trigger( 'model-trashed', this.model );\n\n\t\t\t}\n\n\t\t},\n\n\t}\n\n} );\n\n","/**\n * Load view mixins\n * @return obj\n * @since 3.17.1\n * @version 3.17.1\n */\ndefine( 'Views/_loader',[\n\t\t'Views/_Detachable',\n\t\t'Views/_Editable',\n\t\t'Views/_Receivable',\n\t\t'Views/_Shiftable',\n\t\t'Views/_Subview',\n\t\t'Views/_Trashable'\n\t],\n\tfunction(\n\t\tDetachable,\n\t\tEditable,\n\t\tReceivable,\n\t\tShiftable,\n\t\tSubview,\n\t\tTrashable\n\t) {\n\n\treturn {\n\t\tDetachable: Detachable,\n\t\tEditable: Editable,\n\t\tReceivable: Receivable,\n\t\tShiftable: Shiftable,\n\t\tSubview: Subview,\n\t\tTrashable: Trashable,\n\t};\n\n} );\n\n","/**\n * Constructor functions for constructing models, views, and collections\n * @since 3.16.0\n * @version 3.17.1\n */\ndefine( 'Controllers/Construct',[\n\t\t'Collections/loader',\n\t\t'Models/loader',\n\t\t'Views/_loader'\n\t], function(\n\t\tCollections,\n\t\tModels,\n\t\tViews\n\t) {\n\n\treturn function() {\n\n\t\t/**\n\t\t * Internal getter\n\t\t * Constructs new Collections, Models, and Views\n\t\t * @param obj type type of object to construct [Collection,Model,View]\n\t\t * @param string name name of the object to construct\n\t\t * @param obj data object data to pass into the object's constructor\n\t\t * @param obj options object options to pass into the constructor\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tfunction get( type, name, data, options ) {\n\n\t\t\tif ( ! type[ name ] ) {\n\t\t\t\tconsole.log( '\"' + name + '\" not found.' );\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\treturn new type[ name ]( data, options );\n\n\t\t}\n\n\t\t/**\n\t\t * Instantiate a collection\n\t\t * @param string name Collection class name (EG: \"Sections\")\n\t\t * @param array data Array of model objects to pass to the constructor\n\t\t * @param obj options Object of options to pass to the constructor\n\t\t * @return obj\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tthis.get_collection = function( name, data, options ) {\n\n\t\t\treturn get( Collections, name, data, options );\n\n\t\t};\n\n\t\t/**\n\t\t * Instantiate a model\n\t\t * @param string name Model class name (EG: \"Section\")\n\t\t * @param obj data Object of model attributes to pass to the constructor\n\t\t * @param obj options Object of options to pass to the constructor\n\t\t * @return obj\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tthis.get_model = function( name, data, options ) {\n\n\t\t\treturn get( Models, name, data, options );\n\n\t\t};\n\n\t\t/**\n\t\t * Let 3rd parties extend a view using any of the mixin (_) views\n\t\t * @param {obj} view base object used for the view\n\t\t * @param... {string} extends any number of strings that should be mixed into the view\n\t\t * @return obj\n\t\t * @since 3.17.1\n\t\t * @version 3.17.1\n\t\t */\n\t\tthis.extend_view = function() {\n\n\t\t\tvar view = arguments[0],\n\t\t\t\ti = 1;\n\n\t\t\twhile ( arguments[ i ] ) {\n\n\t\t\t\tvar classname = arguments[ i ];\n\t\t\t\tif ( Views[ classname ] ) {\n\n\t\t\t\t\tif ( view.events && Views[ classname ].events ) {\n\t\t\t\t\t\tview.events = _.defaults( view.events, Views[ classname ].events );\n\t\t\t\t\t}\n\n\t\t\t\t\tview = _.defaults( view, Views[ classname ] );\n\n\t\t\t\t}\n\n\t\t\t\ti++;\n\t\t\t}\n\n\t\t\treturn Backbone.View.extend( view );\n\n\t\t};\n\n\t\t/**\n\t\t * Allows custom collection registration by extending the default BackBone collection\n\t\t * @param string name model name\n\t\t * @param obj props properties to extend the collection with\n\t\t * @return void\n\t\t * @since 3.17.1\n\t\t * @version 3.17.1\n\t\t */\n\t\tthis.register_collection = function( name, props ) {\n\n\t\t\tCollections[ name ] = Backbone.Collection.extend( props );\n\n\t\t};\n\n\t\t/**\n\t\t * Allows custom model registration by extending the default abstract model\n\t\t * @param string name model name\n\t\t * @param obj props properties to extend the abstract model with\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tthis.register_model = function( name, props ) {\n\n\t\t\tModels[ name ] = Models['Abstract'].extend( props );\n\n\t\t};\n\n\t\treturn this;\n\n\t};\n\n} );\n\n","/**\n * LifterLMS Builder Debugging suite\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Controllers/Debug',[], function() {\n\n \treturn function( settings ) {\n\n \t\tvar self = this,\n \t\t\tenabled = settings.enabled || false;\n\n\t\t/**\n\t\t * Disable debugging\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n \t\tthis.disable = function() {\n\n \t\t\tself.log( 'LifterLMS Builder debugging disabled' );\n \t\t\tenabled = false;\n\n \t\t};\n\n\t\t/**\n\t\t * Enable debugging\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n \t\tthis.enable = function() {\n\n \t\t\tenabled = true;\n \t\t\tself.log( 'LifterLMS Builder debugging enabled' );\n\n \t\t};\n\n \t\t/**\n \t\t * General logging function\n \t\t * Logs to the js console only if logging is enabled\n \t\t * @return void\n \t\t * @since 3.16.0\n \t\t * @version 3.16.0\n \t\t */\n \t\tthis.log = function() {\n\n\t\t\tif ( ! enabled ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t_.each( arguments, function( data ) {\n\t\t\t\tconsole.log( data );\n\t\t\t} );\n\n \t\t};\n\n \t\t/**\n \t\t * Toggles current state of the logger on or off\n \t\t * @return void\n \t\t * @since 3.16.0\n \t\t * @version 3.16.0\n \t\t */\n \t\tthis.toggle = function() {\n\n\t\t\tif ( enabled ) {\n\t\t\t\tself.disable();\n\t\t\t} else {\n\t\t\t\tself.enable();\n\t\t\t}\n\n \t\t};\n\n \t\t// on startup, log a message if logging is enabled\n \t\tif ( enabled ) {\n \t\t\tself.enable();\n \t\t}\n\n \t}\n\n } );\n\n","/**\n * Model schema functions\n * @since 3.17.0\n * @version 3.17.0\n */\ndefine( 'Controllers/Schemas',[], function() {\n\n\t/**\n\t * Main Schemas class\n\t * @param obj schemas schemas definitions initialized via PHP filters\n\t * @return obj\n\t * @since 3.17.0\n\t * @version 3.17.0\n\t */\n\treturn function( schemas ) {\n\n\t\t// initialize any custom schemas defined via PHP\n\t\tvar custom_schemas = schemas;\n\t\t_.each( custom_schemas, function( type ) {\n\t\t\t_.each( type, function( schema ) {\n\t\t\t\tschema.custom = true;\n\t\t\t} );\n\t\t} );\n\n\t\t/**\n\t\t * Retrieve a schema for a given model by type\n\t\t * Extends default schemas definitions with custom 3rd party definitions\n\t\t * @param obj schema default schema definition from the model (or empty object if none defined)\n\t\t * @param string model_type the model type ('lesson', 'quiz', etc)\n\t\t * @param obj model Instance of the Backbone.Model for the given model\n\t\t * @return obj\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tthis.get = function( schema, model_type, model ) {\n\n\t\t\t// extend the default schema with custom php schemas for the type if they exist\n\t\t\tif ( custom_schemas[ model_type ] ) {\n\t\t\t\tschema = _.extend( schema, custom_schemas[ model_type ] );\n\t\t\t}\n\n\t\t\treturn schema;\n\n\t\t};\n\n\t\treturn this;\n\n\t};\n\n} );\n\n","/**\n * Sync builder data to the server\n * @since 3.16.0\n * @version 3.17.1\n */\ndefine( 'Controllers/Sync',[], function() {\n\n \treturn function( Course, settings ) {\n\n \t\tthis.saving = false;\n\n \t\tvar self = this,\n \t\t\tautosave = true,\n \t\t\tcheck_interval = null,\n \t\t\tcheck_interval_ms = settings.check_interval_ms || 10000,\n \t\t\tdetached = new Backbone.Collection(),\n \t\t\ttrashed = new Backbone.Collection();\n\n\t\t/**\n\t\t * init\n\t\t * @return void\n\t\t * @since 3.16.7\n\t\t * @version 3.16.7\n\t\t */\n \t\tfunction init() {\n\n \t\t\t// determine if autosaving is possible\n \t\t\tif ( 'undefined' === typeof wp.heartbeat ) {\n\n \t\t\t\twindow.llms_builder.debug.log( 'WordPress Heartbeat disabled. Autosaving is disabled!' );\n \t\t\t\tautosave = false;\n\n \t\t\t}\n\n\t\t\t// setup the check interval\n\t\t\tif ( check_interval_ms ) {\n\t\t\t\tself.set_check_interval( check_interval_ms );\n\t\t\t}\n\n\t\t\t// warn when users attempt to leave the page\n\t\t\t$( window ).on( 'beforeunload', function() {\n\n\t\t\t\tif ( self.has_unsaved_changes() ) {\n\t\t\t\t\tcheck_for_changes();\n\t\t\t\t\treturn 'Are you sure you want to abandon your changes?';\n\t\t\t\t}\n\n\t\t\t} );\n\n \t\t};\n\n \t\t/*\n \t\t\t /$$ /$$ /$$ /$$\n \t\t\t|__/ | $$ | $$ |__/\n \t\t\t /$$ /$$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$$ /$$$$$$ | $$ /$$$$$$ /$$$$$$ /$$\n \t\t\t| $$| $$__ $$|_ $$_/ /$$__ $$ /$$__ $$| $$__ $$ |____ $$| $$ |____ $$ /$$__ $$| $$\n \t\t\t| $$| $$ \\ $$ | $$ | $$$$$$$$| $$ \\__/| $$ \\ $$ /$$$$$$$| $$ /$$$$$$$| $$ \\ $$| $$\n \t\t\t| $$| $$ | $$ | $$ /$$| $$_____/| $$ | $$ | $$ /$$__ $$| $$ /$$__ $$| $$ | $$| $$\n \t\t\t| $$| $$ | $$ | $$$$/| $$$$$$$| $$ | $$ | $$| $$$$$$$| $$ | $$$$$$$| $$$$$$$/| $$\n \t\t\t|__/|__/ |__/ \\___/ \\_______/|__/ |__/ |__/ \\_______/|__/ \\_______/| $$____/ |__/\n \t\t\t | $$\n \t\t\t | $$\n \t\t\t |__/\n \t\t*/\n\n \t\t/**\n \t\t * Adds error message(s) to the data object returned by heartbeat-tick\n \t\t * @param obj data llms_builder data object from heartbeat-tick\n \t\t * @param string|array err error messages array or string\n \t\t * @return obj\n \t\t * @since 3.16.0\n \t\t * @version 3.16.0\n \t\t */\n\t\tfunction add_error_msg( data, err ) {\n\n\t\t\tif ( 'success' === data.status ) {\n\t\t\t\tdata.message = [];\n\t\t\t}\n\n\t\t\tdata.status = 'error';\n\t\t\tif ( 'string' === typeof err ) {\n\t\t\t\terr = [ err ];\n\t\t\t}\n\t\t\tdata.message = data.message.concat( err );\n\n\t\t\treturn data;\n\n\t\t};\n\n\t\t/**\n\t\t * Publish sync status so other areas of the application can see what's happening here\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tfunction check_for_changes() {\n\n\t\t\tvar data = {};\n\t\t\tdata.changes = self.get_unsaved_changes();\n\t\t\tdata.has_unsaved_changes = self.has_unsaved_changes( data.changes );\n\t\t\tdata.saving = self.saving;\n\n\t\t\twindow.llms_builder.debug.log( '==== start changes check ====', data, '==== finish changes check ====' );\n\n\t\t\tBackbone.pubSub.trigger( 'current-save-status', data );\n\n\t\t};\n\n\t\t/**\n\t\t * Manually Save data via Admin AJAX when the heartbeat API has been disabled\n\t\t * @return void\n\t\t * @since 3.16.7\n\t\t * @version 3.16.7\n\t\t */\n\t\tfunction do_ajax_save() {\n\n\t\t\t// prevent simultaneous saves\n\t\t\tif ( self.saving ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar changes = self.get_unsaved_changes();\n\n\t\t\t// only send data if we have data to send\n\t\t\tif ( self.has_unsaved_changes( changes ) ) {\n\n\t\t\t\tchanges.id = Course.get( 'id' );\n\n\t\t\t\tLLMS.Ajax.call( {\n\t\t\t\t\tdata: {\n\t\t\t\t\t\taction: 'llms_builder',\n\t\t\t\t\t\taction_type: 'ajax_save',\n\t\t\t\t\t\tcourse_id: changes.id,\n\t\t\t\t\t\tllms_builder: JSON.stringify( changes ),\n\t\t\t\t\t},\n\t\t\t\t\tbeforeSend: function() {\n\n\t\t\t\t\t\twindow.llms_builder.debug.log( '==== start do_ajax_save before ====', changes, '==== finish do_ajax_save before ====' );\n\n\t\t\t\t\t\tself.saving = true;\n\n\t\t\t\t\t\tBackbone.pubSub.trigger( 'heartbeat-send', self );\n\n\t\t\t\t\t},\n\t\t\t\t\terror: function( xhr, status, error ) {\n\n\t\t\t\t\t\twindow.llms_builder.debug.log( '==== start do_ajax_save error ====', data, '==== finish do_ajax_save error ====' );\n\n\t\t\t\t\t\tself.saving = false;\n\n\t\t\t\t\t\tBackbone.pubSub.trigger( 'heartbeat-tick', self, {\n\t\t\t\t\t\t\tstatus: 'error',\n\t\t\t\t\t\t\tmessage: xhr.responseText + ' (' + error + ' ' + status +')',\n\t\t\t\t\t\t} );\n\n\t\t\t\t\t},\n\t\t\t\t\tsuccess: function( res ) {\n\n\t\t\t\t\t\tif ( ! res.llms_builder ) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\twindow.llms_builder.debug.log( '==== start do_ajax_save success ====', res, '==== finish do_ajax_save success ====' );\n\n\t\t\t\t\t\tres.llms_builder = process_removals( res.llms_builder );\n\t\t\t\t\t\tres.llms_builder = process_updates( res.llms_builder );\n\n\t\t\t\t\t\tself.saving = false;\n\n\t\t\t\t\t\tBackbone.pubSub.trigger( 'heartbeat-tick', self, res.llms_builder );\n\n\t\t\t\t\t}\n\n\t\t\t\t} );\n\n\t\t\t}\n\n\n\t\t};\n\n\t\t/**\n\t\t * Retrieve all the attributes changed on a model since the last sync\n\t\t *\n\t\t * For a new model (a model with a temp ID) or a model where _forceSync has been defined ALL atts will be returned\n\t\t * For an existing model (without a temp ID) only retrieves changed attributes as tracked by Backbone.TrackIt\n\t\t *\n\t\t * This function excludes any attributes defined as child attributes via the models relationship settings\n\t\t *\n\t\t * @param obj model instance of a Backbone.Model\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.6\n\t\t */\n\t\tfunction get_changed_attributes( model ) {\n\n\t\t\tvar atts = {},\n\t\t\t\tsync_type;\n\n\t\t\t// don't save mid editing\n\t\t\tif ( model.get( '_has_focus' ) ) {\n\t\t\t\treturn atts;\n\t\t\t}\n\n\t\t\t// model hasn't been persisted to the database to get a real ID yet\n\t\t\t// send *all* of it's atts\n\t\t\tif ( has_temp_id( model ) || true === model.get( '_forceSync' ) ) {\n\n\t\t\t\tatts = _.clone( model.attributes );\n\t\t\t\tsync_type = 'full';\n\n\t\t\t// only send the changed atts\n\t\t\t} else {\n\n\t\t\t\tatts = model.unsavedAttributes();\n\t\t\t\tsync_type = 'partial';\n\n\t\t\t}\n\n\t\t\tvar exclude = ( model.get_relationships ) ? model.get_child_props() : [];\n\t\t\tatts = _.omit( atts, function( val, key ) {\n\n\t\t\t\t// exclude keys that start with an underscore which are used by the\n\t\t\t\t// application but don't need to be stored in the database\n\t\t\t\tif ( 0 === key.indexOf( '_' ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t} else if ( -1 !== exclude.indexOf( key ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\treturn false;\n\n\t\t\t} );\n\n\t\t\tif ( model.before_save ) {\n\t\t\t\tatts = model.before_save( atts, sync_type );\n\t\t\t}\n\n\t\t\treturn atts;\n\n\t\t};\n\n\t\t/**\n\t\t * Get all the changes to an object (either a Model or a Collection of models)\n\t\t * Returns only changes to models and the IDs of that model (should changes exist)\n\t\t * Uses get_changed_attributes() to determine if all atts or only changed atts are needed\n\t\t * Processes children intelligently to only return changed children rather than the entire collection of children\n\t\t *\n\t\t * @param obj object instance of a Backbone.Model or Backbone.Collection\n\t\t * @return obj|array\t \t\tif object is a model, returns an object\n\t\t * \tif object is a collection, returns an array of objects\n\t\t * @since 3.16.0\n\t\t * @version 3.16.11\n\t\t */\n\t\tfunction get_changes_to_object( object ) {\n\n\t\t\tvar changed_atts;\n\n\t\t\tif ( object instanceof Backbone.Model ) {\n\n\t\t\t\tchanged_atts = get_changed_attributes( object );\n\n\t\t\t\tif ( object.get_relationships ) {\n\n\t\t\t\t\t_.each( object.get_child_props(), function( prop ) {\n\n\t\t\t\t\t\tvar children = get_changes_to_object( object.get( prop ) );\n\t\t\t\t\t\tif ( ! _.isEmpty( children ) ) {\n\t\t\t\t\t\t\tchanged_atts[ prop ] = children;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} );\n\n\t\t\t\t}\n\n\t\t\t\t// if we have any data, add the id to the model\n\t\t\t\tif ( ! _.isEmpty( changed_atts ) ) {\n\t\t\t\t\tchanged_atts.id = object.get( 'id' );\n\t\t\t\t}\n\n\t\t\t} else if ( object instanceof Backbone.Collection ) {\n\n\t\t\t\tchanged_atts = [];\n\t\t\t\tobject.each( function( model ) {\n\t\t\t\t\tvar model_changes = get_changes_to_object( model );\n\t\t\t\t\tif ( ! _.isEmpty( model_changes ) ) {\n\t\t\t\t\t\tchanged_atts.push( model_changes );\n\t\t\t\t\t}\n\t\t\t\t} );\n\n\t\t\t}\n\n\t\t\treturn changed_atts;\n\n\t\t};\n\n\t\t/**\n\t\t * Determines if a model has a temporary ID or a real persisted ID\n\t\t * @param obj model instance of a model\n\t\t * @return boolean\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tfunction has_temp_id( model ) {\n\n\t\t\treturn ( ! _.isNumber( model.id ) && 0 === model.id.indexOf( 'temp_' ) );\n\n\t\t};\n\n\t\t/**\n\t\t * Compares changes synced to the server against current model and restarts\n\t\t * tracking on elements that haven't changed since the last sync\n\t\t * @param obj model instance of a Backbone.Model\n\t\t * @param obj data data set that was processed by the server\n\t\t * @return void\n\t\t * @since 3.16.11\n\t\t * @version 3.16.6\n\t\t */\n\t\tfunction maybe_restart_tracking( model, data ) {\n\n\t\t\tvar omit = [ 'id', 'orig_id' ];\n\n\t\t\tif ( model.get_relationships ) {\n\t\t\t\tomit.concat( model.get_child_props() );\n\t\t\t}\n\n\t\t\t_.each( _.omit( data, omit ), function( val, prop ) {\n\n\t\t\t\tif ( _.isEqual( model.get( prop ), val ) ) {\n\t\t\t\t\tdelete model._unsavedChanges[ prop ];\n\t\t\t\t\tmodel._originalAttrs[ prop ] = val;\n\t\t\t\t}\n\n\t\t\t} );\n\n\t\t\t// if syncing was forced, allow tracking to move forward as normal moving forward\n\t\t\tmodel.unset( '_forceSync' );\n\n\t\t};\n\n\t\t/**\n\t\t * Processes response data from heartbeat-tick related to trashing & detaching models\n\t\t * On success, removes from local removal collection\n\t\t * On error, appends error messages to the data object returned to UI for on-screen feedback\n\t\t * @param obj data data.llms_builder object from heartbeat-tick response\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.17.1\n\t\t */\n\t\tfunction process_removals( data ) {\n\n\t\t\t// check removals for errors\n\t\t\tvar removals = {\n\t\t\t\tdetach: detached,\n\t\t\t\ttrash: trashed,\n\t\t\t};\n\n\t\t\t_.each( removals, function( coll, key ) {\n\n\t\t\t\tif ( data[ key ] ) {\n\n\t\t\t\t\tvar errors = [];\n\n\t\t\t\t\t_.each( data[ key ] , function( info ) {\n\n\t\t\t\t\t\t// succesfully detached, remove it from the detached collection\n\t\t\t\t\t\tif ( ! info.error ) {\n\n\t\t\t\t\t\t\tcoll.remove( info.id );\n\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\terrors.push( info.error );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} );\n\n\t\t\t\t\tif ( errors.length ) {\n\t\t\t\t\t\t_.extend( data, add_error_msg( data, errors ) );\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t} );\n\n\t\t\treturn data;\n\t\t}\n\n\t\t/**\n\t\t * Processes response data from heartbeat-tick related to creating / updating a single object\n\t\t * Handles both collections and models as a recursive function\n\t\t * @param {[type]} data [description]\n\t\t * @param {[type]} type [description]\n\t\t * @param {[type]} parent [description]\n\t\t * @param {[type]} main_data [description]\n\t\t * @return {[type]}\n\t\t * @since 3.16.0\n\t\t * @version 3.16.11\n\t\t */\n\t\tfunction process_object_updates( data, type, parent, main_data ) {\n\n\t\t\tif ( ! data[ type ] ) {\n\t\t\t\treturn data;\n\t\t\t}\n\n\t\t\tif ( parent.get( type ) instanceof Backbone.Model ) {\n\n\t\t\t\tvar info = data[ type ];\n\n\t\t\t\tif ( info.error ) {\n\n\t\t\t\t\t_.extend( main_data, add_error_msg( main_data, info.error ) );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tvar model = parent.get( type );\n\n\t\t\t\t\t// update temp ids with the real id\n\t\t\t\t\tif ( info.id != info.orig_id ) {\n\t\t\t\t\t\tmodel.set( 'id', info.id );\n\t\t\t\t\t\tdelete model._unsavedChanges.id;\n\t\t\t\t\t}\n\t\t\t\t\tmaybe_restart_tracking( model, info );\n\n\t\t\t\t\t// check children\n\t\t\t\t\tif ( model.get_relationships ) {\n\n\t\t\t\t\t\t_.each( model.get_child_props(), function( child_key ) {\n\t\t\t\t\t\t\t_.extend( data[ type ], process_object_updates( data[ type ], child_key, model, main_data ) );\n\t\t\t\t\t\t} );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t} else if ( parent.get( type ) instanceof Backbone.Collection ) {\n\n\t\t\t\t_.each( data[ type ], function( info, index ) {\n\n\t\t\t\t\tif ( info.error ) {\n\n\t\t\t\t\t\t_.extend( main_data, add_error_msg( main_data, info.error ) );\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tvar model = parent.get( type ).get( info.orig_id );\n\n\t\t\t\t\t\t// update temp ids with the real id\n\t\t\t\t\t\tif ( info.id != info.orig_id ) {\n\t\t\t\t\t\t\tmodel.set( 'id', info.id );\n\t\t\t\t\t\t\tdelete model._unsavedChanges.id;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmaybe_restart_tracking( model, info );\n\n\t\t\t\t\t\t// check children\n\t\t\t\t\t\tif ( model.get_relationships ) {\n\n\t\t\t\t\t\t\t_.each( model.get_child_props(), function( child_key ) {\n\t\t\t\t\t\t\t\t_.extend( data[ type ], process_object_updates( data[ type ][ index ], child_key, model, main_data ) );\n\t\t\t\t\t\t\t} );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t} );\n\n\t\t\t}\n\n\t\t\treturn main_data;\n\n\t\t};\n\n\t\t/**\n\t\t * Processes response data from heartbeat-tick related to updating & creating new models\n\t\t * On success, removes from local removal collection\n\t\t * On error, appends error messages to the data object returned to UI for on-screen feedback\n\t\t * @param obj data data.llms_builder object from heartbeat-tick response\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tfunction process_updates( data ) {\n\n\t\t\t// only mess with updates data\n\t\t\tif ( ! data.updates ) {\n\t\t\t\treturn data;\n\t\t\t}\n\n\t\t\tif ( data.updates ) {\n\t\t\t\tdata = process_object_updates( data.updates, 'sections', Course, data );\n\t\t\t}\n\n\t\t\treturn data;\n\n\t\t};\n\n\t\t/*\n\t\t\t /$$ /$$ /$$ /$$\n\t\t\t | $$ | $$|__/ |__/\n\t\t\t /$$$$$$ /$$ /$$| $$$$$$$ | $$ /$$ /$$$$$$$ /$$$$$$ /$$$$$$ /$$\n\t\t\t /$$__ $$| $$ | $$| $$__ $$| $$| $$ /$$_____/ |____ $$ /$$__ $$| $$\n\t\t\t| $$ \\ $$| $$ | $$| $$ \\ $$| $$| $$| $$ /$$$$$$$| $$ \\ $$| $$\n\t\t\t| $$ | $$| $$ | $$| $$ | $$| $$| $$| $$ /$$__ $$| $$ | $$| $$\n\t\t\t| $$$$$$$/| $$$$$$/| $$$$$$$/| $$| $$| $$$$$$$ | $$$$$$$| $$$$$$$/| $$\n\t\t\t| $$____/ \\______/ |_______/ |__/|__/ \\_______/ \\_______/| $$____/ |__/\n\t\t\t| $$ | $$\n\t\t\t| $$ | $$\n\t\t\t|__/ |__/\n\t\t*/\n\n\t\t/**\n\t\t * Retrieve all unsaved changes for the builder instance\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.17.1\n\t\t */\n\t\tthis.get_unsaved_changes = function() {\n\n\t\t\treturn {\n\t\t\t\tdetach: detached.pluck( 'id' ),\n\t\t\t\ttrash: trashed.pluck( 'id' ),\n\t\t\t\tupdates: get_changes_to_object( Course ),\n\n\t\t\t}\n\t\t};\n\n\t\t/**\n\t\t * Check if the builder instance has unsaved changes\n\t\t * @param obj changes optionally pass in an object from the return of this.get_unsaved_changes()\n\t\t * save some resources by not running the check twice during heartbeats\n\t\t * @return boolean\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tthis.has_unsaved_changes = function( changes ) {\n\n\t\t\tif ( 'undefined' === typeof changes ) {\n\t\t\t\tchanges = self.get_unsaved_changes();\n\t\t\t}\n\n\t\t\t// check all possible keys, once we find one with content we have some changes to persist\n\t\t\tvar found = _.find( changes, function( data ) {\n\n\t\t\t\treturn ( false === _.isEmpty( data ) );\n\n\t\t\t} );\n\n\t\t\treturn found ? true : false;\n\n\t\t};\n\n\t\t/**\n\t\t * Save changes right now.\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.7\n\t\t */\n\t\tthis.save_now = function() {\n\t\t\tif ( autosave ) {\n\t\t\t\twp.heartbeat.connectNow();\n\t\t\t} else {\n\t\t\t\tdo_ajax_save();\n\t\t\t}\n\t\t};\n\n\t\t/**\n\t\t * Update the interval that checks for changes to the builder instance\n\t\t * @param int ms time (in milliseconds) to run the check on\n\t\t * pass 0 to disable the check\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tthis.set_check_interval = function( ms ) {\n\t\t\tcheck_interval_ms = ms;\n\t\t\tif ( check_interval ) {\n\t\t\t\tclearInterval( check_interval );\n\t\t\t}\n\t\t\tif ( check_interval_ms ) {\n\t\t\t\tcheck_interval = setInterval( check_for_changes, check_interval_ms );\n\t\t\t}\n\t\t};\n\n\t\t/*\n\t\t\t /$$ /$$ /$$\n\t\t\t| $$|__/ | $$\n\t\t\t| $$ /$$ /$$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$$\n\t\t\t| $$| $$ /$$_____/|_ $$_/ /$$__ $$| $$__ $$ /$$__ $$ /$$__ $$ /$$_____/\n\t\t\t| $$| $$| $$$$$$ | $$ | $$$$$$$$| $$ \\ $$| $$$$$$$$| $$ \\__/| $$$$$$\n\t\t\t| $$| $$ \\____ $$ | $$ /$$| $$_____/| $$ | $$| $$_____/| $$ \\____ $$\n\t\t\t| $$| $$ /$$$$$$$/ | $$$$/| $$$$$$$| $$ | $$| $$$$$$$| $$ /$$$$$$$/\n\t\t\t|__/|__/|_______/ \\___/ \\_______/|__/ |__/ \\_______/|__/ |_______/\n\t\t*/\n\n\t\t/**\n\t\t * Listen for detached models and send them to the server for persistence\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tBackbone.pubSub.on( 'model-detached', function( model ) {\n\n\t\t\t// detached models with temp ids haven't been persisted so we don't care\n\t\t\tif ( has_temp_id( model ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tdetached.add( _.clone( model.attributes ) );\n\n\t\t} );\n\n\t\t/**\n\t\t * Listen for trashed models and send them to the server for deletion\n\t\t * @since 3.16.0\n\t\t * @version 3.17.1\n\t\t */\n\t\tBackbone.pubSub.on( 'model-trashed', function( model ) {\n\n\t\t\t// if the model has a temp ID we don't have to persist the deletion\n\t\t\tif ( has_temp_id( model ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar data = _.clone( model.attributes );\n\n\t\t\tif ( model.get_trash_id ) {\n\t\t\t\tdata.id = model.get_trash_id();\n\t\t\t}\n\n\t\t\ttrashed.add( data );\n\n\t\t} );\n\n\t\t/*\n\t\t\t /$$ /$$ /$$ /$$\n\t\t\t| $$ | $$ | $$ | $$\n\t\t\t| $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ | $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$\n\t\t\t| $$__ $$ /$$__ $$ |____ $$ /$$__ $$|_ $$_/ | $$__ $$ /$$__ $$ |____ $$|_ $$_/\n\t\t\t| $$ \\ $$| $$$$$$$$ /$$$$$$$| $$ \\__/ | $$ | $$ \\ $$| $$$$$$$$ /$$$$$$$ | $$\n\t\t\t| $$ | $$| $$_____/ /$$__ $$| $$ | $$ /$$| $$ | $$| $$_____/ /$$__ $$ | $$ /$$\n\t\t\t| $$ | $$| $$$$$$$| $$$$$$$| $$ | $$$$/| $$$$$$$/| $$$$$$$| $$$$$$$ | $$$$/\n\t\t\t|__/ |__/ \\_______/ \\_______/|__/ \\___/ |_______/ \\_______/ \\_______/ \\___/\n\t\t*/\n\n\t\t/**\n\t\t * Add data to the WP heartbeat to persist new models, changes, and deletions to the DB\n\t\t * @since 3.16.0\n\t\t * @version 3.16.7\n\t\t */\n\t\t$( document ).on( 'heartbeat-send', function( event, data ) {\n\n\t\t\t// prevent simultaneous saves\n\t\t\tif ( self.saving ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar changes = self.get_unsaved_changes();\n\n\t\t\t// only send data if we have data to send\n\t\t\tif ( self.has_unsaved_changes( changes ) ) {\n\n\t\t\t\tchanges.id = Course.get( 'id' );\n\t\t\t\tself.saving = true;\n\t\t\t\tdata.llms_builder = JSON.stringify( changes );\n\n\t\t\t}\n\n\t\t\twindow.llms_builder.debug.log( '==== start heartbeat-send ====', data, '==== finish heartbeat-send ====' );\n\n\t\t\tBackbone.pubSub.trigger( 'heartbeat-send', self );\n\n\t\t} );\n\n\t\t/**\n\t\t * Confirm detachments & deletions and replace temp IDs with new persisted IDs\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\t$( document ).on( 'heartbeat-tick', function( event, data ) {\n\n\t\t\tif ( ! data.llms_builder ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\twindow.llms_builder.debug.log( '==== start heartbeat-tick ====', data, '==== finish heartbeat-tick ====' );\n\n\t\t\tdata.llms_builder = process_removals( data.llms_builder );\n\t\t\tdata.llms_builder = process_updates( data.llms_builder );\n\n\t\t\tself.saving = false;\n\n\t\t\tBackbone.pubSub.trigger( 'heartbeat-tick', self, data.llms_builder );\n\n\t\t} );\n\n\t\t/**\n\t\t * On heartbeat errors publish an error to the main builder application\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\t$( document ).on( 'heartbeat-error', function( event, data ) {\n\n\t\t\twindow.llms_builder.debug.log( '==== start heartbeat-error ====', data, '==== finish heartbeat-error ====' );\n\n\t\t\tself.saving = false;\n\n\t\t\tBackbone.pubSub.trigger( 'heartbeat-tick', self, {\n\t\t\t\tstatus: 'error',\n\t\t\t\tmessage: data.responseText + ' (' + data.status + ' ' + data.statusText +')',\n\t\t\t} );\n\n\t\t} );\n\n\t\t/*\n\t\t\t /$$ /$$ /$$\n\t\t\t|__/ |__/ | $$\n\t\t\t /$$ /$$$$$$$ /$$ /$$$$$$\n\t\t\t| $$| $$__ $$| $$|_ $$_/\n\t\t\t| $$| $$ \\ $$| $$ | $$\n\t\t\t| $$| $$ | $$| $$ | $$ /$$\n\t\t\t| $$| $$ | $$| $$ | $$$$/\n\t\t\t|__/|__/ |__/|__/ \\___/\n\t\t*/\n\t\tinit();\n\n\t\treturn this;\n\n\t};\n\n} );\n\n","/**\n * Single Lesson View\n * @since 3.16.0\n * @version 3.17.0\n */\ndefine( 'Views/Lesson',[\n\t\t'Views/_Detachable',\n\t\t'Views/_Editable',\n\t\t'Views/_Shiftable',\n\t\t'Views/_Trashable'\n\t], function(\n\t\tDetachable,\n\t\tEditable,\n\t\tShiftable,\n\t\tTrashable\n\t) {\n\n\treturn Backbone.View.extend( _.defaults( {\n\n\t\t/**\n\t\t * Get default attributes for the html wrapper element\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tattributes: function() {\n\t\t\treturn {\n\t\t\t\t'data-id': this.model.id,\n\t\t\t\t'data-section-id': this.model.get( 'parent_section' ),\n\t\t\t};\n\t\t},\n\n\t\t/**\n\t\t * HTML class names\n\t\t * @type {String}\n\t\t */\n\t\tclassName: 'llms-builder-item llms-lesson',\n\n\t\t/**\n\t\t * Events\n\t\t * @type {Object}\n\t\t * @since 3.16.0\n\t\t * @version 3.16.12\n\t\t */\n\t\tevents: _.defaults( {\n\t\t\t'click .edit-lesson': 'open_lesson_editor',\n\t\t\t'click .edit-quiz': 'open_quiz_editor',\n\t\t\t'click .edit-assignment': 'open_assignment_editor',\n\t\t\t'click .section-prev': 'section_prev',\n\t\t\t'click .section-next': 'section_next',\n\t\t\t'click .shift-up--lesson': 'shift_up',\n\t\t\t'click .shift-down--lesson': 'shift_down',\n\t\t}, Detachable.events, Editable.events, Trashable.events ),\n\n\t\t/**\n\t\t * HTML element wrapper ID attribute\n\t\t * @return string\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tid: function() {\n\t\t\treturn 'llms-lesson-' + this.model.id;\n\t\t},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'li',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-lesson-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.14.1\n\t\t * @version 3.14.1\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\tthis.render();\n\n\t\t\tthis.listenTo( this.model, 'change', this.render );\n\n\t\t\tBackbone.pubSub.on( 'lesson-selected', this.on_select, this );\n\t\t\tBackbone.pubSub.on( 'new-lesson-added', this.on_select, this );\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender: function() {\n\n\t\t\tthis.$el.html( this.template( this.model ) );\n\t\t\tthis.maybe_hide_shiftable_buttons();\n\t\t\tif ( this.model.get( '_selected' ) ) {\n\t\t\t\tthis.$el.addClass( 'selected' );\n\t\t\t} else {\n\t\t\t\tthis.$el.removeClass( 'selected' );\n\t\t\t}\n\t\t\treturn this;\n\n\t\t},\n\n\t\t/**\n\t\t * Click event for the assignment editor action icon\n\t\t * Opens sidebar to the assignment editor tab\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\topen_assignment_editor: function() {\n\n\t\t\tBackbone.pubSub.trigger( 'lesson-selected', this.model, 'assignment' );\n\t\t\tthis.model.set( '_selected', true );\n\n\t\t},\n\n\t\t/**\n\t\t * Click event for lesson settings action icon\n\t\t * Opens sidebar to the lesson editor tab\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\topen_lesson_editor: function() {\n\n\t\t\tBackbone.pubSub.trigger( 'lesson-selected', this.model, 'lesson' );\n\t\t\tthis.model.set( '_selected', true );\n\n\t\t},\n\n\t\t/**\n\t\t * Click event for the quiz editor action icon\n\t\t * Opens sidebar to the quiz editor tab\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\topen_quiz_editor: function() {\n\n\t\t\tBackbone.pubSub.trigger( 'lesson-selected', this.model, 'quiz' );\n\t\t\tthis.model.set( '_selected', true );\n\n\t\t},\n\n\t\t/**\n\t\t * When a lesson is selected mark it as selected in the hidden prop\n\t\t * Allows views to re-render and reflect current state properly\n\t\t * @param obj model lesson model that's been selected\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\ton_select: function( model ) {\n\n\t\t\tif ( this.model.id !== model.id ) {\n\t\t\t\tthis.model.set( '_selected', false );\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Click event for the \"Next Section\" button\n\t\t * @param obj event js event obj\n\t\t * @return void\n\t\t * @since 3.16.11\n\t\t * @version 3.16.11\n\t\t */\n\t\tsection_next: function( event ) {\n\t\t\tevent.preventDefault();\n\t\t\tthis._move_to_section( 'next' );\n\t\t},\n\n\t\t/**\n\t\t * Click event for the \"Previous Section\" button\n\t\t * @param obj event js event obj\n\t\t * @return void\n\t\t * @since 3.16.11\n\t\t * @version 3.16.11\n\t\t */\n\t\tsection_prev: function( event ) {\n\t\t\tevent.preventDefault();\n\t\t\tthis._move_to_section( 'prev' );\n\t\t},\n\n\t\t/**\n\t\t * Move the lesson into a new section\n\t\t * @param string direction direction [prev|next]\n\t\t * @return void\n\t\t * @since 3.16.11\n\t\t * @version 3.16.11\n\t\t */\n\t\t_move_to_section: function( direction ) {\n\n\t\t\tvar from_coll = this.model.collection,\n\t\t\t\tto_section;\n\n\t\t\tif ( 'next' === direction ) {\n\t\t\t\tto_section = from_coll.parent.get_next();\n\t\t\t} else if ( 'prev' === direction ) {\n\t\t\t\tto_section = from_coll.parent.get_prev();\n\t\t\t}\n\n\t\t\tif ( to_section ) {\n\n\t\t\t\tfrom_coll.remove( this.model );\n\t\t\t\tto_section.add_lesson( this.model );\n\t\t\t\tto_section.set( '_expanded', true );\n\n\t\t\t}\n\n\t\t},\n\n\t}, Detachable, Editable, Shiftable, Trashable ) );\n\n} );\n\n","/**\n * Single Section View\n * @since 3.13.0\n * @version 3.16.0\n */\ndefine( 'Views/LessonList',[ 'Views/Lesson', 'Views/_Receivable' ], function( LessonView, Receivable ) {\n\n\treturn Backbone.CollectionView.extend( _.defaults( {\n\n\t\tclassName: 'llms-lessons',\n\n\t\t/**\n\t\t * Section model\n\t\t * @type {[type]}\n\t\t */\n\t\tmodelView: LessonView,\n\n\t\t/**\n\t\t * Are sections selectable?\n\t\t * @type {Bool}\n\t\t */\n\t\tselectable: false,\n\n\t\t/**\n\t\t * Are sections sortable?\n\t\t * @type {Bool}\n\t\t */\n\t\tsortable: true,\n\n\t\tsortableOptions: {\n\t\t\taxis: false,\n\t\t\tconnectWith: '.llms-lessons',\n\t\t\tcursor: 'move',\n\t\t\thandle: '.drag-lesson',\n\t\t\titems: '.llms-lesson',\n\t\t\tplaceholder: 'llms-lesson llms-sortable-placeholder',\n\t\t},\n\n\t\tsortable_start: function( collection ) {\n\t\t\t$( '.llms-lessons' ).addClass( 'dragging' );\n\t\t},\n\n\t\tsortable_stop: function( collection ) {\n\t\t\t$( '.llms-lessons' ).removeClass( 'dragging' );\n\t\t},\n\n\t\t/**\n\t\t * Overloads the function from Backbone.CollectionView core because it doesn't send stop events\n\t\t * if moving from one sortable to another... :-(\n\t\t * @param obj event js event object\n\t\t * @param obj ui jQuery UI object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\t_sortStop : function( event, ui ) {\n\n\t\t\tvar modelBeingSorted = this.collection.get( ui.item.attr( 'data-model-cid' ) ),\n\t\t\t\tmodelViewContainerEl = this._getContainerEl(),\n\t\t\t\tnewIndex = modelViewContainerEl.children().index( ui.item );\n\n\t\t\tif ( newIndex == -1 && modelBeingSorted ) {\n\t\t\t\tthis.collection.remove( modelBeingSorted );\n\t\t\t}\n\n\t\t\tthis._reorderCollectionBasedOnHTML();\n\t\t\tthis.updateDependentControls();\n\n\t\t\tif( this._isBackboneCourierAvailable() ) {\n\t\t\t\tthis.spawn( 'sortStop', { modelBeingSorted : modelBeingSorted, newIndex : newIndex } );\n\t\t\t} else {\n\t\t\t\tthis.trigger( 'sortStop', modelBeingSorted, newIndex );\n\t\t\t}\n\n\t\t},\n\n\t}, Receivable ) );\n\n} );\n\n","/**\n * Single Section View\n * @since 3.13.0\n * @version 3.16.12\n */\ndefine( 'Views/Section',[\n\t\t'Views/LessonList',\n\t\t'Views/_Editable',\n\t\t'Views/_Shiftable',\n\t\t'Views/_Trashable'\n\t], function(\n\t\tLessonListView,\n\t\tEditable,\n\t\tShiftable,\n\t\tTrashable\n\t) {\n\n\treturn Backbone.View.extend( _.defaults( {\n\n\t\t/**\n\t\t * Get default attributes for the html wrapper element\n\t\t * @return obj\n\t\t * @since 3.13.0\n\t\t * @version 3.13.0\n\t\t */\n\t\tattributes: function() {\n\t\t\treturn {\n\t\t\t\t'data-id': this.model.id,\n\t\t\t};\n\t\t},\n\n\t\t/**\n\t\t * Element classnames\n\t\t * @type {String}\n\t\t */\n\t\tclassName: 'llms-builder-item llms-section',\n\n\t\t/**\n\t\t * Events\n\t\t * @type {Object}\n\t\t * @since 3.16.0\n\t\t * @version 3.16.12\n\t\t */\n\t\tevents: _.defaults( {\n\n\t\t\t'click': 'select',\n\t\t\t'click .expand': 'expand',\n\t\t\t'click .collapse': 'collapse',\n\t\t\t'click .shift-up--section': 'shift_up',\n\t\t\t'click .shift-down--section': 'shift_down',\n\n\t\t\t'mouseenter .llms-lessons': 'on_mouseenter',\n\n\t\t}, Editable.events, Trashable.events ),\n\n\t\t/**\n\t\t * HTML element wrapper ID attribute\n\t\t * @return string\n\t\t * @since 3.13.0\n\t\t * @version 3.13.0\n\t\t */\n\t\tid: function() {\n\t\t\treturn 'llms-section-' + this.model.id;\n\t\t},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'li',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-section-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.13.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\tthis.render();\n\t\t\tthis.listenTo( this.model, 'change', this.render );\n\t\t\tthis.listenTo( this.model, 'change:_expanded', this.toggle_expanded );\n\t\t\tthis.lessonListView.collection.on( 'add', this.on_lesson_add, this );\n\n\t\t\tthis.dragTimeout = null;\n\n\t\t\tBackbone.pubSub.on( 'expand-all', this.expand, this );\n\t\t\tBackbone.pubSub.on( 'collapse-all', this.collapse, this );\n\n\t\t},\n\n\t\t/**\n\t\t * Render the section\n\t\t * Initalizes a new collection and views for all lessons in the section\n\t\t * @return void\n\t\t * @since 3.13.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender: function() {\n\n\t\t\tthis.$el.html( this.template( this.model.toJSON() ) );\n\n\t\t\tthis.maybe_hide_shiftable_buttons();\n\n\t\t\tthis.lessonListView = new LessonListView( {\n\t\t\t\tel: this.$el.find( '.llms-lessons' ),\n\t\t\t\tcollection: this.model.get( 'lessons' ),\n\t\t\t} );\n\t\t\tthis.lessonListView.render();\n\t\t\tthis.lessonListView.on( 'sortStart', this.lessonListView.sortable_start );\n\t\t\tthis.lessonListView.on( 'sortStop', this.lessonListView.sortable_stop );\n\n\t\t\t// selection changes\n\t\t\tthis.lessonListView.on( 'selectionChanged', this.active_lesson_change, this );\n\n\t\t\tthis.maybe_hide_trash_button();\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\tactive_lesson_change: function( current, previous ) {\n\n\t\t\tBackbone.pubSub.trigger( 'active-lesson-change', {\n\t\t\t\tcurrent: current,\n\t\t\t\tprevious: previous,\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * Collapse lessons within the section\n\t\t * @param obj event js event object\n\t\t * @param bool update if true, updates the model to reflect the new state\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tcollapse: function( event, update ) {\n\n\t\t\tif ( 'undefined' === typeof update ) {\n\t\t\t\tupdate = true;\n\t\t\t}\n\n\t\t\tif ( event ) {\n\t\t\t\tevent.stopPropagation();\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\n\t\t\tthis.$el.removeClass( 'expanded' ).find( '.drag-expanded' ).removeClass( 'drag-expanded' );\n\t\t\tif ( update ) {\n\t\t\t\tthis.model.set( '_expanded', false );\n\t\t\t}\n\t\t\tBackbone.pubSub.trigger( 'section-toggle', this.model );\n\n\t\t},\n\n\t\t/**\n\t\t * Expand lessons within the section\n\t\t * @param obj event js event object\n\t\t * @param bool update if true, updates the model to reflect the new state\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\texpand: function( event, update ) {\n\n\t\t\tif ( 'undefined' === typeof update ) {\n\t\t\t\tupdate = true;\n\t\t\t}\n\n\t\t\tif ( event ) {\n\t\t\t\tevent.stopPropagation();\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\n\t\t\tthis.$el.addClass( 'expanded' );\n\t\t\tif ( update ) {\n\t\t\t\tthis.model.set( '_expanded', true );\n\t\t\t}\n\t\t\tBackbone.pubSub.trigger( 'section-toggle', this.model );\n\n\t\t},\n\n\t\tmaybe_hide_trash_button: function() {\n\n\t\t\tvar $btn = this.$el.find( '.trash--section' );\n\n\t\t\tif ( this.model.get( 'lessons' ).isEmpty() ) {\n\n\t\t\t\t$btn.show();\n\n\t\t\t} else {\n\n\t\t\t\t$btn.hide()\n\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * When a lesson is added to the section trigger a collection reorder & update the lesson's id\n\t\t * @param obj model Lesson model\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\ton_lesson_add: function( model ) {\n\n\t\t\tthis.lessonListView.collection.trigger( 'reorder' );\n\t\t\tmodel.set( 'parent_section', this.model.get( 'id' ) );\n\t\t\tthis.expand();\n\n\t\t},\n\n\t\ton_mouseenter: function( event ) {\n\n\n\t\t\tif ( $( event.target ).hasClass( 'dragging' ) ) {\n\n\t\t\t\t$( '.drag-expanded' ).removeClass( 'drag-expanded' );\n\t\t\t\t$( event.target ).addClass( 'drag-expanded' );\n\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Expand\n\t\t * @param {[type]} model [description]\n\t\t * @param {[type]} value [description]\n\t\t * @return {[type]}\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\ttoggle_expanded: function( model, value ) {\n\n\t\t\tif ( value ) {\n\t\t\t\tthis.expand( null, false );\n\t\t\t} else {\n\t\t\t\tthis.collapse( null, false );\n\t\t\t}\n\n\t\t},\n\n\t}, Editable, Shiftable, Trashable ) );\n\n} );\n\n","/**\n * Single Section View\n * @since 3.13.0\n * @version 3.16.0\n */\ndefine( 'Views/SectionList',[ 'Views/Section', 'Views/_Receivable' ], function( SectionView, Receivable ) {\n\n\treturn Backbone.CollectionView.extend( _.defaults( {\n\n\t\t/**\n\t\t * Parent element\n\t\t * @type {String}\n\t\t */\n\t\tel: '#llms-sections',\n\n\t\tevents : {\n\t\t\t'mousedown > li.llms-section > .llms-builder-header .llms-headline' : '_listItem_onMousedown',\n\t\t\t// 'dblclick > li, tbody > tr > td' : '_listItem_onDoubleClick',\n\t\t\t'click' : '_listBackground_onClick',\n\t\t\t'click ul.collection-view' : '_listBackground_onClick',\n\t\t\t'keydown' : '_onKeydown'\n\t\t},\n\n\t\t/**\n\t\t * Section model\n\t\t * @type {[type]}\n\t\t */\n\t\tmodelView: SectionView,\n\n\t\t/**\n\t\t * Enable keyboard events\n\t\t * @type {Bool}\n\t\t */\n\t\tprocessKeyEvents: false,\n\n\t\t/**\n\t\t * Are sections selectable?\n\t\t * @type {Bool}\n\t\t */\n\t\tselectable: true,\n\n\t\t/**\n\t\t * Are sections sortable?\n\t\t * @type {Bool}\n\t\t */\n\t\tsortable: true,\n\n\t\tsortableOptions: {\n\t\t\taxis: false,\n\t\t\tcursor: 'move',\n\t\t\thandle: '.drag-section',\n\t\t\titems: '.llms-section',\n\t\t\tplaceholder: 'llms-section llms-sortable-placeholder',\n\t\t},\n\n\t\tsortable_start: function( collection ) {\n\t\t\tthis.$el.addClass( 'dragging' );\n\t\t},\n\n\t\tsortable_stop: function( collection ) {\n\t\t\tthis.$el.removeClass( 'dragging' );\n\t\t},\n\n\t}, Receivable ) );\n\n} );\n\n","/**\n * Single Course View\n * @since 3.13.0\n * @version 3.16.0\n */\ndefine( 'Views/Course',[ 'Views/SectionList', 'Views/_Editable' ], function( SectionListView, Editable ) {\n\n\treturn Backbone.View.extend( _.defaults( {\n\n\t\t/**\n\t\t * Get default attributes for the html wrapper element\n\t\t * @return obj\n\t\t * @since 3.13.0\n\t\t * @version 3.13.0\n\t\t */\n\t\tattributes: function() {\n\t\t\treturn {\n\t\t\t\t'data-id': this.model.id,\n\t\t\t};\n\t\t},\n\n\t\t/**\n\t\t * HTML element selector\n\t\t * @type {String}\n\t\t */\n\t\tel: '#llms-builder-main',\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'div',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-course-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.13.0\n\t\t * @version 3.13.0\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\tvar self = this;\n\n\t\t\t// this.listenTo( this.model, 'sync', this.render );\n\t\t\tthis.render();\n\n\t\t\tthis.sectionListView = new SectionListView( {\n\t\t\t\tcollection: this.model.get( 'sections' ),\n\t\t\t} );\n\t\t\tthis.sectionListView.render();\n\t\t\t// drag and drop start\n\t\t\tthis.sectionListView.on( 'sortStart', this.sectionListView.sortable_start );\n\t\t\t// drag and drop stop\n\t\t\tthis.sectionListView.on( 'sortStop', this.sectionListView.sortable_stop );\n\t\t\t// selection changes\n\t\t\tthis.sectionListView.on( 'selectionChanged', this.active_section_change );\n\t\t\t// \"select\" a section when it's added to the course\n\t\t\tthis.listenTo( this.model.get( 'sections'), 'add', this.on_section_add );\n\n\t\t\tBackbone.pubSub.on( 'section-toggle', this.on_section_toggle, this );\n\n\t\t\tBackbone.pubSub.on( 'expand-section', this.expand_section, this );\n\n\t\t\tBackbone.pubSub.on( 'lesson-selected', this.active_lesson_change, this );\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.13.0\n\t\t * @version 3.13.0\n\t\t */\n\t\trender: function() {\n\t\t\tthis.$el.html( this.template( this.model ) );\n\t\t\treturn this;\n\t\t},\n\n\t\tactive_lesson_change: function( model ) {\n\n\t\t\t// set parent section to be active\n\t\t\tvar section = this.model.get( 'sections' ).get( model.get( 'parent_section' ) );\n\t\t\tthis.sectionListView.setSelectedModel( section );\n\n\t\t},\n\n\t\t/**\n\t\t * When a section \"selection\" changes in the list\n\t\t * Update each section model so we can figure out which one is selected from other views\n\t\t * @param array current array of selected models\n\t\t * @param array previous array of previously selected models\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tactive_section_change: function( current, previous ) {\n\n\t\t\t_.each( current, function( model ) {\n\t\t\t\tmodel.set( '_selected', true );\n\t\t\t} );\n\n\t\t\t_.each( previous, function( model ) {\n\t\t\t\tmodel.set( '_selected', false );\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * \"Selects\" the new section when it's added to the course\n\t\t * @param obj model Section model that's just been added\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\ton_section_add: function( model ) {\n\n\t\t\tthis.sectionListView.setSelectedModel( model );\n\n\t\t},\n\n\t\t/**\n\t\t * When expanding/collapsing sections\n\t\t * if collapsing, unselect, if expanding, select\n\t\t * @param obj model toggled section\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\ton_section_toggle: function( model ) {\n\n\t\t\tvar selected = model.get( '_expanded' ) ? [ model ] : [];\n\t\t\tthis.sectionListView.setSelectedModels( selected );\n\n\t\t}\n\n\t}, Editable ) );\n\n} );\n\n","/**\n * Model settings fields view\n * @since 3.17.0\n * @version 3.17.7\n */\ndefine( 'Views/SettingsFields',[], function() {\n\n\treturn Backbone.View.extend( _.defaults( {\n\n\t\t/**\n\t\t * DOM events\n\t\t * @type {Object}\n\t\t */\n\t\tevents: {\n\t\t\t'click .llms-settings-group-toggle': 'toggle_group',\n\t\t},\n\n\t\t/**\n\t\t * Processed fields data\n\t\t * Allows access by ID without traversing the schema\n\t\t * @type {Object}\n\t\t */\n\t\tfields: {},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'div',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-settings-fields-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\t// initialize: function() {},\n\n\t\t/**\n\t\t * Retrieve an array of all editor fields in all groups\n\t\t * @return array\n\t\t * @since 3.17.1\n\t\t * @version 3.17.1\n\t\t */\n\t\tget_editor_fields: function() {\n\t\t\treturn _.filter( this.fields, function( field ) {\n\t\t\t\treturn this.is_editor_field( field.type );\n\t\t\t}, this );\n\t\t},\n\n\t\t/**\n\t\t * Get settings group data from a model\n\t\t * @return {[type]}\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tget_groups: function() {\n\n\t\t\treturn this.model.get_settings_fields();\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if a settings group is hidden in localStorage\n\t\t * @param string group_id id of the group\n\t\t * @return {Boolean}\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tis_group_hidden: function( group_id ) {\n\n\t\t\tvar id = 'llms-' + this.model.get( 'type' ) + '-settings-group--' + group_id;\n\n\t\t\tif ( 'undefined' !== window.localStorage ) {\n\t\t\t\treturn ( 'hidden' === window.localStorage.getItem( id ) );\n\t\t\t}\n\n\t\t\treturn false;\n\n\t\t},\n\n\t\t/**\n\t\t * Get the switch attribute for a field with switches\n\t\t * @param obj field field data obj\n\t\t * @return string\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tget_switch_attribute: function( field ) {\n\n\t\t\treturn field.switch_attribute ? field.switch_attribute : field.attribute;\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if a field has a switch\n\t\t * @param string type field type string\n\t\t * @return {Boolean}\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\thas_switch: function( type ) {\n\t\t\treturn ( -1 !== type.indexOf( 'switch' ) );\n\t\t},\n\n\t\t/**\n\t\t * Determine if a field is a default (text) field\n\t\t * @param string type field type string\n\t\t * @return {Boolean}\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tis_default_field: function( type ) {\n\n\t\t\tvar types = [ 'audio_embed', 'datepicker', 'number', 'text', 'video_embed' ];\n\t\t\treturn ( -1 !== types.indexOf( type.replace( 'switch-', '' ) ) );\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if a field is a WYSIWYG editor field\n\t\t * @param string type field type string\n\t\t * @return {Boolean}\n\t\t * @since 3.17.1\n\t\t * @version 3.17.1\n\t\t */\n\t\tis_editor_field: function( type ) {\n\n\t\t\tvar types = [ 'editor', 'switch-editor' ];\n\t\t\treturn ( -1 !== types.indexOf( type.replace( 'switch-', '' ) ) );\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if a switch is enabled for a field\n\t\t * @param obj field field data object\n\t\t * @return {Boolean}\n\t\t * @since 3.17.0\n\t\t * @version 3.17.6\n\t\t */\n\t\tis_switch_condition_met: function( field ) {\n\n\t\t\treturn ( field.switch_on === this.model.get( field.switch_attribute ) );\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.17.0\n\t\t * @version 3.17.1\n\t\t */\n\t\trender: function() {\n\n\t\t\tthis.$el.html( this.template( this ) );\n\n\t\t\t// if editors exist, render them\n\t\t\t_.each( this.get_editor_fields(), function( field ) {\n\t\t\t\tthis.render_editor( field );\n\t\t\t}, this );\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\t/**\n\t\t * Renders an editor field\n\t\t * @param obj field field data object\n\t\t * @return void\n\t\t * @since 3.17.1\n\t\t * @version 3.17.1\n\t\t */\n\t\trender_editor: function( field ) {\n\n\t\t\tvar self = this;\n\n\t\t\twp.editor.remove( field.id );\n\t\t\tfield.settings.tinymce.setup = function( editor ) {\n\n\t\t\t\tvar $ed = $( '#' + editor.id ),\n\t\t\t\t\t$parent = $ed.closest( '.llms-editable-editor' ),\n\t\t\t\t\t$label = $parent.find( '.llms-label' ),\n\t\t\t\t\tprop = $ed.attr( 'data-attribute' )\n\n\t\t\t\tif ( $label.length ) {\n\t\t\t\t\t$label.prependTo( $parent.find( '.wp-editor-tools' ) );\n\t\t\t\t}\n\n\t\t\t\t// save changes to the model via Visual ed\n\t\t\t\teditor.on( 'change', function( event ) {\n\t\t\t\t\tself.model.set( prop, wp.editor.getContent( editor.id ) );\n\t\t\t\t} );\n\n\t\t\t\t// save changes via Text ed\n\t\t\t\t$ed.on( 'input', function( event ) {\n\t\t\t\t\tself.model.set( prop, $ed.val() );\n\t\t\t\t} );\n\n\t\t\t\t// trigger an input on the Text ed when quicktags buttons are clicked\n\t\t\t\t$parent.on( 'click', '.quicktags-toolbar .ed_button', function() {\n\t\t\t\t\tsetTimeout( function() {\n\t\t\t\t\t\t$ed.trigger( 'input' );\n\t\t\t\t\t}, 10 );\n\t\t\t\t} );\n\t\t\t};\n\n\t\t\twp.editor.initialize( field.id, field.settings );\n\n\t\t},\n\n\t\t/**\n\t\t * Get the HTML for a select field\n\t\t * @param obj options flat or multi-dimensional options object\n\t\t * @param string attribute name of the select field's attribute\n\t\t * @return string\n\t\t * @since 3.17.0\n\t\t * @version 3.17.2\n\t\t */\n\t\trender_select_options: function( options, attribute ) {\n\n\t\t\tvar html = '',\n\t\t\t\tselected = this.model.get( attribute );\n\n\t\t\tfunction option_html( label, val ) {\n\n\t\t\t\treturn '' + label + ' ';\n\n\t\t\t}\n\n\t\t\t_.each( options, function( option, index ) {\n\n\t\t\t\t// this will be an key:val object\n\t\t\t\tif ( 'string' === typeof option ) {\n\t\t\t\t\thtml += option_html( option, index );\n\t\t\t\t// either option group or array of key,val objects\n\t\t\t\t} else if ( 'object' === typeof option ) {\n\t\t\t\t\t// option group\n\t\t\t\t\tif ( option.label && option.options ) {\n\t\t\t\t\t\thtml += '';\n\t\t\t\t\t\thtml += this.render_select_options( option.options, attribute );\n\t\t\t\t\t} else {\n\t\t\t\t\t\thtml += option_html( option.val, option.key );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t}, this );\n\n\t\t\treturn html;\n\n\t\t},\n\n\t\t/**\n\t\t * Setup and fill fields with default data based on field type\n\t\t * @param obj orig_field original field as defined in the settings\n\t\t * @param int field_index index of the field in the current row\n\t\t * @return obj\n\t\t * @since 3.17.0\n\t\t * @version 3.17.7\n\t\t */\n\t\tsetup_field: function( orig_field, field_index ) {\n\n\t\t\tvar defaults = {\n\t\t\t\tclasses: [],\n\t\t\t\tid: _.uniqueId( orig_field.attribute + '_' ),\n\t\t\t\tinput_type: 'text',\n\t\t\t\tlabel: '',\n\t\t\t\toptions: {},\n\t\t\t\tplaceholder: '',\n\t\t\t\ttip: '',\n\t\t\t\ttip_position: 'top-right',\n\t\t\t\tsettings: {},\n\t\t\t};\n\n\t\t\t// check the field condition if set\n\t\t\tif ( orig_field.condition && false === _.bind( orig_field.condition, this.model )() ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tswitch ( orig_field.type ) {\n\n\t\t\t\tcase 'audio_embed':\n\t\t\t\t\tdefaults.classes.push( 'llms-editable-audio' );\n\t\t\t\t\tdefaults.placeholder = 'https://';\n\t\t\t\t\tdefaults.tip = LLMS.l10n.translate( 'Use SoundCloud or Spotify audio URLS.' );\n\t\t\t\t\tdefaults.input_type = 'url';\n\t\t\t\tbreak;\n\n\t\t\t\tcase 'datepicker':\n\t\t\t\t\tdefaults.classes.push( 'llms-editable-date' );\n\t\t\t\tbreak;\n\n\t\t\t\tcase 'editor':\n\t\t\t\tcase 'switch-editor':\n\t\t\t\t\tvar orig_settings = orig_field.settings || {};\n\t\t\t\t\tdefaults.settings = $.extend( true, wp.editor.getDefaultSettings(), {\n\t\t\t\t\t\tmediaButtons: true,\n\t\t\t\t\t\ttinymce: {\n\t\t\t\t\t\t\ttoolbar1: 'bold,italic,strikethrough,bullist,numlist,blockquote,hr,alignleft,aligncenter,alignright,link,unlink,wp_adv',\n\t\t\t\t\t\t\ttoolbar2: 'formatselect,underline,alignjustify,forecolor,pastetext,removeformat,charmap,outdent,indent,undo,redo,wp_help',\n\t\t\t\t\t\t}\n\t\t\t\t\t}, orig_settings );\n\t\t\t\tbreak;\n\n\t\t\t\tcase 'number':\n\t\t\t\t\tdefaults.input_type = 'number';\n\t\t\t\tbreak;\n\n\t\t\t\tcase 'permalink':\n\t\t\t\t\tdefaults.label = LLMS.l10n.translate( 'Permalink' );\n\t\t\t\tbreak;\n\n\t\t\t\tcase 'video_embed':\n\t\t\t\t\tdefaults.classes.push( 'llms-editable-video' );\n\t\t\t\t\tdefaults.placeholder = 'https://';\n\t\t\t\t\tdefaults.tip = LLMS.l10n.translate( 'Use YouTube, Vimeo, or Wistia video URLS.' );\n\t\t\t\t\tdefaults.input_type = 'url';\n\t\t\t\tbreak;\n\n\t\t\t}\n\n\t\t\tif ( this.has_switch( orig_field.type ) ) {\n\t\t\t\tdefaults.switch_on = 'yes';\n\t\t\t\tdefaults.switch_off = 'no';\n\t\t\t}\n\n\t\t\tvar field = _.defaults( _.deepClone( orig_field ), defaults );\n\n\t\t\t// if options is a function run it\n\t\t\tif ( _.isFunction( field.options ) ) {\n\t\t\t\tfield.options = _.bind( field.options, this.model )();\n\t\t\t}\n\n\t\t\t// if it's a radio field options values can be submitted as images\n\t\t\t// this will transform those images into html\n\t\t\tif ( -1 !== [ 'radio', 'switch-radio' ].indexOf( orig_field.type ) ) {\n\n\t\t\t\tvar has_images = false;\n\t\t\t\t_.each( orig_field.options, function( val, key ) {\n\t\t\t\t\tif ( -1 !== val.indexOf( '.png' ) || -1 !== val.indexOf( '.jpg' ) ) {\n\t\t\t\t\t\tfield.options[key] = ' ';\n\t\t\t\t\t\thas_images = true;\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t\tif ( has_images ) {\n\t\t\t\t\tfield.classes.push( 'has-images' );\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t// add tooltip position classes\n\t\t\tif ( field.tip ) {\n\t\t\t\tfield.classes.push( 'tip--' + field.tip_position );\n\t\t\t}\n\n\t\t\t// transform classes array to a css class string\n\t\t\tif ( field.classes.length ) {\n\t\t\t\tfield.classes = ' ' + field.classes.join( ' ' );\n\t\t\t}\n\n\t\t\tthis.fields[ field.id ] = field;\n\n\t\t\treturn field;\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if toggling a switch select should rerender the view\n\t\t * @param string field_type field type string\n\t\t * @return boolean\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tshould_rerender_on_toggle: function( field_type ) {\n\n\t\t\treturn ( -1 !== field_type.indexOf( 'switch-' ) ) ? 'yes' : 'no';\n\n\t\t},\n\n\t\t/**\n\t\t * Click event for toggling visibility of settings groups\n\t\t * If localStorage is available, persist state\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\ttoggle_group: function( event ) {\n\n\t\t\tevent.preventDefault();\n\n\t\t\tvar $el = $( event.currentTarget ),\n\t\t\t\t$group = $el.closest( '.llms-model-settings' );\n\n\t\t\t$group.toggleClass( 'hidden' );\n\n\t\t\tif ( 'undefined' !== window.localStorage ) {\n\n\t\t\t\tvar id = $group.attr( 'id' );\n\t\t\t\tif ( $group.hasClass( 'hidden' ) ) {\n\t\t\t\t\twindow.localStorage.setItem( id, 'hidden' );\n\t\t\t\t} else {\n\t\t\t\t\twindow.localStorage.removeItem( id );\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t},\n\n\t} ) );\n\n} );\n\n","/**\n * Lesson Editor (Sidebar) View\n * @since 3.17.0\n * @version 3.17.0\n */\ndefine( 'Views/LessonEditor',[\n\t\t'Views/_Detachable',\n\t\t'Views/_Editable',\n\t\t'Views/_Trashable',\n\t\t'Views/_Subview',\n\t\t'Views/SettingsFields'\n\t], function(\n\t\tDetachable,\n\t\tEditable,\n\t\tTrashable,\n\t\tSubview,\n\t\tSettingsFields\n\t) {\n\n\treturn Backbone.View.extend( _.defaults( {\n\n\t\t/**\n\t\t * Current view state\n\t\t * @type {String}\n\t\t */\n\t\tstate: 'default',\n\n\t\t/**\n\t\t * Current Subviews\n\t\t * @type {Object}\n\t\t */\n\t\tviews: {\n\t\t\tsettings: {\n\t\t\t\tclass: SettingsFields,\n\t\t\t\tinstance: null,\n\t\t\t\tstate: 'default',\n\t\t\t},\n\t\t},\n\n\t\tel: '#llms-editor-lesson',\n\n\t\t/**\n\t\t * Events\n\t\t * @type {Object}\n\t\t */\n\t\tevents: _.defaults( {}, Detachable.events, Editable.events, Trashable.events ),\n\n\t\t/**\n\t\t * Template function\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-lesson-settings-template' ),\n\n\t\t/**\n\t\t * Init\n\t\t * @param obj data parent template data\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tinitialize: function( data ) {\n\n\t\t\tthis.model = data.lesson;\n\n\t\t\tvar change_events = [\n\t\t\t\t'change:date_available',\n\t\t\t\t'change:drip_method',\n\t\t\t\t'change:time_available',\n\t\t\t];\n\t\t\t_.each( change_events, function( event ) {\n\t\t\t\tthis.listenTo( this.model, event, this.render );\n\t\t\t}, this );\n\n\t\t\t// when the \"has_prerequisite\" attr is toggled ON\n\t\t\t// trigger the prereq select object to set the default (first available) prereq for the lesson\n\t\t\tthis.listenTo( this.model, 'change:has_prerequisite', function( lesson, val ) {\n\t\t\t\tif ( 'yes' === val ) {\n\t\t\t\t\tthis.$el.find( 'select[name=\"prerequisite\"]' ).trigger( 'change' );\n\t\t\t\t}\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * Render the view\n\t\t * @return obj\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\trender: function() {\n\n\t\t\tthis.$el.html( this.template( this.model ) );\n\n\t\t\tthis.remove_subview( 'settings' );\n\n\t\t\tthis.render_subview( 'settings', {\n\t\t\t\tel: '#llms-lesson-settings-fields',\n\t\t\t\tmodel: this.model,\n\t\t\t} );\n\n\t\t\tthis.init_datepickers();\n\t\t\tthis.init_selects();\n\n\t\t\treturn this;\n\n\t\t},\n\n\t}, Detachable, Editable, Trashable, Subview, SettingsFields ) );\n\n} );\n\n","/**\n * Single Quiz View\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Views/Popover',[], function() {\n\n\treturn Backbone.View.extend( {\n\n\t\tdefaults: {\n\t\t\tplacement: 'auto',\n\t\t\t// container: document.body,\n\t\t\twidth: 'auto',\n\t\t\ttrigger: 'manual',\n\t\t\tstyle: 'light',\n\t\t\tanimation: 'pop',\n\t\t\ttitle: '',\n\t\t\tcontent: '',\n\t\t\tcloseable: false,\n\t\t\tbackdrop: false,\n\t\t\tonShow: function( $el ) {},\n\t\t\tonHide: function( $el ) {},\n\t\t},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'div',\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.14.1\n\t\t * @version 3.14.1\n\t\t */\n\t\tinitialize: function( data ) {\n\n\t\t\tif ( this.$el.length ) {\n\t\t\t\tthis.defaults.container = this.$el.parent();\n\t\t\t}\n\n\t\t\tthis.args = _.defaults( data.args, this.defaults );\n\t\t\tthis.render();\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender: function() {\n\n\t\t\tthis.$el.webuiPopover( this.args );\n\t\t\treturn this;\n\n\t\t},\n\n\t\t/**\n\t\t * Hide the popover\n\t\t * @return self (for chaining)\n\t\t * @since 3.16.0\n\t\t * @version 3.16.12\n\t\t */\n\t\thide: function() {\n\n\t\t\tthis.$el.webuiPopover( 'hide' );\n\t\t\treturn this;\n\n\t\t},\n\n\t\t/**\n\t\t * Show the popover\n\t\t * @return self (for chaining)\n\t\t * @since 3.16.0\n\t\t * @version 3.16.12\n\t\t */\n\t\tshow: function() {\n\n\t\t\tthis.$el.webuiPopover( 'show' );\n\t\t\treturn this;\n\n\t\t},\n\n\t} );\n\n} );\n\n","/**\n * Post Popover Serach content View\n * @since 3.16.0\n * @version 3.17.0\n */\ndefine( 'Views/PostSearch',[], function() {\n\n\treturn Backbone.View.extend( {\n\n\t\t/**\n\t\t * DOM Events\n\t\t * @type obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tevents: {\n\t\t\t'select2:select': 'add_post',\n\t\t},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'select',\n\n\t\t/**\n\t\t * Initializer\n\t\t * @param obj data customize the search box with data\n\t\t * @return void\n\t\t * @since 3.16.12\n\t\t * @version 3.16.12\n\t\t */\n\t\tinitialize: function( data ) {\n\n\t\t\tthis.post_type = data.post_type;\n\t\t\tthis.searching_message = data.searching_message || LLMS.l10n.translate( 'Searching...' );\n\n\t\t},\n\n\t\t/**\n\t\t * Select event, adds the existing lesson to the course\n\t\t * @param obj event select2:select event object\n\t\t * @since 3.16.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tadd_post: function( event ) {\n\n\t\t\tvar type = this.$el.attr( 'data-post-type' );\n\n\t\t\tBackbone.pubSub.trigger( type.replace( 'llms_', '' ) + '-search-select', event.params.data, event );\n\t\t\tthis.$el.val( null ).trigger( 'change' );\n\n\t\t},\n\n\t\t/**\n\t\t * Render the section\n\t\t * Initalizes a new collection and views for all lessons in the section\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.12\n\t\t */\n\t\trender: function() {\n\t\t\tvar self = this;\n\t\t\tsetTimeout( function () {\n\t\t\t\tself.$el.llmsSelect2( {\n\t\t\t\t\tajax: {\n\t\t\t\t\t\tdataType: 'JSON',\n\t\t\t\t\t\tdelay: 250,\n\t\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\t\turl: window.ajaxurl,\n\t\t\t\t\t\tdata: function( params ) {\n\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\taction: 'llms_builder',\n\t\t\t\t\t\t\t\taction_type: 'search',\n\t\t\t\t\t\t\t\tcourse_id: window.llms_builder.course.id,\n\t\t\t\t\t\t\t\tpost_type: self.post_type,\n\t\t\t\t\t\t\t\tterm: params.term,\n\t\t\t\t\t\t\t\tpage: params.page,\n\t\t\t\t\t\t\t\t_ajax_nonce: wp_ajax_data.nonce,\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t},\n\t\t\t\t\t\t// error: function( xhr, status, error ) {\n\t\t\t\t\t\t// \tconsole.log( status, error );\n\t\t\t\t\t\t// },\n\t\t\t\t\t},\n\t\t\t\t\tdropdownParent: $( '.wrap.lifterlms.llms-builder' ),\n\t\t\t\t\t// don't escape html from render_result\n\t\t\t\t\tescapeMarkup: function( markup ) {\n\t\t\t\t\t\treturn markup;\n\t\t\t\t\t},\n\t\t\t\t\tplaceholder: self.searching_message,\n\t\t\t\t\ttemplateResult: self.render_result,\n\t\t\t\t\twidth: '100%',\n\t\t\t\t} );\n\t\t\t\tself.$el.attr( 'data-post-type', self.post_type );\n\t\t\t}, 0 );\n\t\t\treturn this;\n\n\t\t},\n\n\t\t/**\n\t\t * Render a nicer UI for each search result in the in the Select2 search results\n\t\t * @param object res result data\n\t\t * @return string\n\t\t * @since 3.16.0\n\t\t * @version 3.16.12\n\t\t */\n\t\trender_result: function( res ) {\n\n\t\t\tvar $html = $( '
' );\n\n\t\t\tif ( res.loading ) {\n\t\t\t\treturn $html.append( res.text );\n\t\t\t}\n\n\t\t\tvar $side = $( '' ),\n\t\t\t\t$main = $( '
' );\n\t\t\t\ticon = ( 'attach' === res.action ) ? 'paperclip' : 'clone',\n\t\t\t\ttext = ( 'attach' === res.action ) ? LLMS.l10n.translate( 'Attach' ) : LLMS.l10n.translate( 'Clone' );\n\n\t\t\t$side.append( '' + text + ' ' );\n\n\t\t\t$main.append( '' + res.data.title + ' ' );\n\t\t\t$main.append( '' + LLMS.l10n.translate( 'ID' ) + ': ' + res.data.id + ' ' );\n\n\t\t\t_.each( res.parents, function( parent ) {\n\t\t\t\t$main.append( '' + parent + ' ' );\n\t\t\t} );\n\n\t\t\treturn $html.append( $side ).append( $main );\n\n\t\t},\n\n\t} );\n\n} );\n\n","/**\n * Single Lesson View\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Views/QuestionType',[ ], function() {\n\n\treturn Backbone.View.extend( {\n\n\t\t/**\n\t\t * HTML class names\n\t\t * @type {String}\n\t\t */\n\t\tclassName: 'llms-question-type',\n\n\t\tevents: {\n\t\t\t'click .llms-add-question': 'add_question',\n\t\t},\n\n\t\t/**\n\t\t * HTML element wrapper ID attribute\n\t\t * @return string\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tid: function() {\n\t\t\treturn 'llms-question-type-' + this.model.id;\n\t\t},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'li',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-question-type-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\tthis.render();\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender: function() {\n\t\t\tthis.$el.html( this.template( this.model ) );\n\t\t\treturn this;\n\t\t},\n\n\t\t/**\n\t\t * Add a question of the selected type to the current quiz\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tadd_question: function() {\n\n\t\t\tthis.quiz.add_question( {\n\t\t\t\t_expanded: true,\n\t\t\t\tchoices: this.model.get( 'default_choices' ) ? this.model.get( 'default_choices' ) : null,\n\t\t\t\tquestion_type: this.model,\n\t\t\t} );\n\n\t\t\tthis.quiz.trigger( 'new-question-added' );\n\n\t\t},\n\n\t\t// filter: function( term ) {\n\n\t\t// \tvar words = this.model.get_keywords().map( function( word ) {\n\t\t// \t\treturn word.toLowerCase();\n\t\t// \t} );\n\n\t\t// \tterm = term.toLowerCase();\n\n\t\t// \tif ( -1 === words.indexOf( term ) ) {\n\t\t// \t\tthis.$el.addClass( 'filtered' );\n\t\t// \t} else {\n\t\t// \t\tthis.$el.removeClass( 'filtered' );\n\t\t// \t}\n\n\t\t// },\n\n\t\t// clear_filter: function() {\n\t\t// \tthis.$el.removeClass( 'filtered' );\n\t\t// }\n\n\t} );\n\n} );\n\n","/**\n * Quiz question bank view\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Views/QuestionBank',[ 'Views/QuestionType' ], function( QuestionView ) {\n\n\treturn Backbone.CollectionView.extend( {\n\n\t\tclassName: 'llms-question',\n\n\t\t/**\n\t\t * Parent element\n\t\t * @type {String}\n\t\t */\n\t\tel: '#llms-question-bank',\n\n\t\t/**\n\t\t * Section model\n\t\t * @type {[type]}\n\t\t */\n\t\tmodelView: QuestionView,\n\n\t\t/**\n\t\t * Are sections selectable?\n\t\t * @type {Bool}\n\t\t */\n\t\tselectable: false,\n\n\t\t/**\n\t\t * Are sections sortable?\n\t\t * @type {Bool}\n\t\t */\n\t\tsortable: false,\n\n\t} );\n\n} );\n\n","/**\n * Single Question Choice View\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Views/QuestionChoice',[ 'Views/_Editable', ], function( Editable ) {\n\n\treturn Backbone.View.extend( _.defaults( {\n\n\t\t/**\n\t\t * HTML class names\n\t\t * @type {String}\n\t\t */\n\t\tclassName: 'llms-question-choice',\n\n\t\tevents: _.defaults( {\n\t\t\t'change input[name=\"correct\"]': 'toggle_correct',\n\t\t\t'click .llms-action-icon[href=\"#llms-add-choice\"]': 'add_choice',\n\t\t\t'click .llms-action-icon[href=\"#llms-del-choice\"]': 'del_choice',\n\t\t}, Editable.events ),\n\n\t\t/**\n\t\t * HTML element wrapper ID attribute\n\t\t * @return string\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tid: function() {\n\t\t\treturn 'llms-question-choice-' + this.model.id;\n\t\t},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'li',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-question-choice-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.14.1\n\t\t * @version 3.14.1\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\tthis.render();\n\n\t\t\tthis.listenTo( this.model.collection, 'add', this.maybe_disable_buttons );\n\t\t\tthis.listenTo( this.model, 'change', this.render );\n\n\t\t\tif ( 'image' === this.model.get( 'choice_type' ) ) {\n\t\t\t\tthis.listenTo( this.model.get( 'choice' ), 'change', this.render );\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender: function() {\n\t\t\tthis.$el.html( this.template( this.model ) );\n\t\t\treturn this;\n\t\t},\n\n\t\t/**\n\t\t * Add a new choice to the current choice list\n\t\t * Adds *after* the clicked choice\n\t\t * @param obj event JS event object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tadd_choice: function( event ) {\n\n\t\t\tevent.stopPropagation();\n\t\t\tevent.preventDefault();\n\n\t\t\tvar index = this.model.collection.indexOf( this.model );\n\t\t\tthis.model.collection.parent.add_choice( {}, {\n\t\t\t\tat: index + 1,\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * Delete the choice from the choice list & ensure there's at least one correct choice\n\t\t * @param obj event js event obj\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tdel_choice: function( event ) {\n\n\t\t\tevent.preventDefault();\n\t\t\tBackbone.pubSub.trigger( 'model-trashed', this.model );\n\t\t\tthis.model.collection.remove( this.model );\n\n\t\t},\n\n\t\t/**\n\t\t * When the correct answer input changes sync status to model\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\ttoggle_correct: function() {\n\n\t\t\tvar correct = this.$el.find( 'input[name=\"correct\"]' ).is( ':checked' );\n\t\t\tthis.model.set( 'correct', correct );\n\t\t\tthis.model.collection.trigger( 'correct-update', this.model );\n\n\t\t},\n\n\t}, Editable ) );\n\n} );\n\n","/**\n * Quiz question bank view\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Views/QuestionChoiceList',[ 'Views/QuestionChoice' ], function( ChoiceView ) {\n\n\treturn Backbone.CollectionView.extend( {\n\n\t\tclassName: 'llms-quiz-questions',\n\n\t\t/**\n\t\t * Choice model view\n\t\t * @type {[type]}\n\t\t */\n\t\tmodelView: ChoiceView,\n\n\t\t/**\n\t\t * Enable keyboard events\n\t\t * @type {Bool}\n\t\t */\n\t\tprocessKeyEvents: false,\n\n\t\t/**\n\t\t * Are sections selectable?\n\t\t * @type {Bool}\n\t\t */\n\t\tselectable: false,\n\n\t\t/**\n\t\t * Are sections sortable?\n\t\t * @type {Bool}\n\t\t */\n\t\tsortable: true,\n\n\t\tsortableOptions: {\n\t\t\taxis: false,\n\t\t\t// connectWith: '.llms-lessons',\n\t\t\tcursor: 'move',\n\t\t\thandle: '.llms-choice-id',\n\t\t\titems: '.llms-question-choice',\n\t\t\tplaceholder: 'llms-question-choice llms-sortable-placeholder',\n\t\t},\n\n\t\tsortable_start: function( model ) {\n\t\t\tthis.$el.addClass( 'dragging' );\n\t\t},\n\n\t\tsortable_stop: function( model ) {\n\t\t\tthis.$el.removeClass( 'dragging' );\n\t\t},\n\n\t} );\n\n} );\n\n","/**\n * Single Question View\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Views/Question',[\n\t\t'Views/_Editable',\n\t\t'Views/QuestionChoiceList'\n\t], function(\n\t\tEditable,\n\t\tChoiceListView\n\t) {\n\n\treturn Backbone.View.extend( _.defaults( {\n\n\t\t/**\n\t\t * Generate CSS classes for the question\n\t\t * @return string\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tclassName: function() {\n\t\t\treturn 'llms-question qtype--' + this.model.get( 'question_type' ).get( 'id' );\n\t\t},\n\n\t\tevents: _.defaults( {\n\t\t\t'click .clone--question': 'clone',\n\t\t\t'click .delete--question': 'delete',\n\t\t\t'click .expand--question': 'expand',\n\t\t\t'click .collapse--question': 'collapse',\n\t\t\t'change input[name=\"question_points\"]': 'update_points',\n\t\t}, Editable.events ),\n\n\t\t/**\n\t\t * HTML element wrapper ID attribute\n\t\t * @return string\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tid: function() {\n\t\t\treturn 'llms-question-' + this.model.id;\n\t\t},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'li',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-question-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\tvar change_events = [\n\t\t\t\t'change:_expanded',\n\t\t\t\t'change:menu_order',\n\t\t\t];\n\t\t\t_.each( change_events, function( event ) {\n\t\t\t\tthis.listenTo( this.model, event, this.render );\n\t\t\t}, this );\n\n\t\t\tthis.listenTo( this.model.get( 'image' ), 'change', this.render );\n\n\t\t\tthis.listenTo( this.model.get_parent(), 'change:_points', this.render_points_percentage );\n\n\t\t\tthis.on( 'multi_choices_toggle', this.multi_choices_toggle, this );\n\n\t\t\tBackbone.pubSub.on( 'del-question-choice', this.del_choice, this );\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender: function() {\n\n\t\t\tthis.$el.html( this.template( this.model ) );\n\n\t\t\tif ( this.model.get( 'question_type').get( 'choices' ) ) {\n\n\t\t\t\tthis.choiceListView = new ChoiceListView( {\n\t\t\t\t\tel: this.$el.find( '.llms-question-choices' ),\n\t\t\t\t\tcollection: this.model.get( 'choices' ),\n\t\t\t\t} );\n\t\t\t\tthis.choiceListView.render();\n\t\t\t\tthis.choiceListView.on( 'sortStart', this.choiceListView.sortable_start );\n\t\t\t\tthis.choiceListView.on( 'sortStop', this.choiceListView.sortable_stop );\n\n\t\t\t}\n\n\t\t\tif ( 'group' === this.model.get( 'question_type' ).get( 'id' ) ) {\n\n\t\t\t\tvar self = this;\n\t\t\t\tsetTimeout( function() {\n\t\t\t\t\tself.questionListView = self.collectionListView.quiz.get_question_list( {\n\t\t\t\t\t\tel: self.$el.find( '.llms-quiz-questions' ),\n\t\t\t\t\t\tcollection: self.model.get( 'questions' ),\n\t\t\t\t\t} );\n\t\t\t\t\tself.questionListView.render();\n\t\t\t\t\tself.questionListView.on( 'sortStart', self.questionListView.sortable_start );\n\t\t\t\t\tself.questionListView.on( 'sortStop', self.questionListView.sortable_stop );\n\t\t\t\t}, 1 );\n\n\t\t\t}\n\n\t\t\tif ( this.model.get( 'description_enabled' ) ) {\n\t\t\t\tthis.init_editor( 'question-desc--' + this.model.get( 'id' ) );\n\t\t\t}\n\n\t\t\tif ( this.model.get( 'clarifications_enabled' ) ) {\n\t\t\t\tthis.init_editor( 'question-clarifications--' + this.model.get( 'id' ), {\n\t\t\t\t\tmediaButtons: false,\n\t\t\t\t\ttinymce: {\n\t\t\t\t\t\ttoolbar1: 'bold,italic,strikethrough,bullist,numlist,alignleft,aligncenter,alignright',\n\t\t\t\t\t\ttoolbar2: '',\n\t\t\t\t\t\tsetup: _.bind( this.on_editor_ready, this ),\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\tthis.init_formatting_els();\n\t\t\tthis.init_selects();\n\n\t\t\treturn this;\n\t\t},\n\n\t\t/**\n\t\t * rerender points percentage when question points are updated\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender_points_percentage: function() {\n\n\t\t\tthis.$el.find( '.llms-question-points' ).attr( 'data-tip', this.model.get_points_percentage() );\n\n\t\t},\n\n\t\t/**\n\t\t * Click event to duplicate a question within a quiz\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tclone: function( event ) {\n\n\t\t\tevent.stopPropagation();\n\t\t\tevent.preventDefault();\n\t\t\tthis.model.collection.add( this._get_question_clone( this.model ) );\n\n\t\t},\n\n\t\t/**\n\t\t * Recursive clone function which will correctly clone children of a question\n\t\t * @param obj question queston model\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\t_get_question_clone: function( question ) {\n\n\t\t\t// create a duplicate\n\t\t\tvar clone = _.clone( question.attributes );\n\n\t\t\t// remove id (we want the duplicate to have a temp id)\n\t\t\tdelete clone.id;\n\n\t\t\tclone.parent_id = question.get( 'id' );\n\n\t\t\t// set the question type ID\n\t\t\tclone.question_type = question.get( 'question_type' ).get( 'id' );\n\n\t\t\t// clone the image attributes seperately\n\t\t\tclone.image = _.clone( question.get( 'image' ).attributes );\n\n\t\t\t// if it has choices clone all the choices\n\t\t\tif ( question.get( 'choices' ) ) {\n\n\t\t\t\tclone.choices = [];\n\n\t\t\t\tquestion.get( 'choices' ).each( function ( choice ) {\n\n\t\t\t\t\tvar choice_clone = _.clone( choice.attributes );\n\t\t\t\t\tdelete choice_clone.id;\n\t\t\t\t\tdelete choice_clone.question_id;\n\n\t\t\t\t\tclone.choices.push( choice_clone );\n\n\t\t\t\t} );\n\n\t\t\t}\n\n\t\t\tif ( 'group' === question.get( 'question_type' ).get( 'id' ) ) {\n\n\t\t\t\tclone.questions = [];\n\t\t\t\tquestion.get( 'questions' ).each( function( child ) {\n\t\t\t\t\tclone.questions.push( this._get_question_clone( child ) );\n\t\t\t\t}, this );\n\n\t\t\t}\n\n\t\t\treturn clone;\n\n\t\t},\n\n\t\t/**\n\t\t * Collapse a question and hide it's settings\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tcollapse: function() {\n\n\t\t\tthis.model.set( '_expanded', false );\n\n\t\t},\n\n\t\t/**\n\t\t * Delete the question from a quiz / question group\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tdelete: function( event ) {\n\n\t\t\tevent.preventDefault();\n\n\t\t\tif ( window.confirm( LLMS.l10n.translate( 'Are you sure you want to delete this question?' ) ) ) {\n\n\t\t\t\tthis.model.collection.remove( this.model );\n\t\t\t\tBackbone.pubSub.trigger( 'model-trashed', this.model );\n\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Click event to reveal a question's settings & choices\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\texpand: function() {\n\n\t\t\tthis.model.set( '_expanded', true );\n\n\t\t},\n\n\t\t/**\n\t\t * When toggling multiple correct answers *off* remove all correct choices except the first correct choice in the list\n\t\t * @param string val value of the question's `multi_choice` attr [yes|no]\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tmulti_choices_toggle: function( val ) {\n\n\t\t\tif ( 'yes' === val ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis.model.get( 'choices' ).update_correct( _.first( this.model.get( 'choices' ).get_correct() ) );\n\n\t\t},\n\n\t\t/**\n\t\t * Update the model's points when the value of the points input is updated\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tupdate_points: function() {\n\n\t\t\tthis.model.set( 'points', this.$el.find( 'input[name=\"question_points\"]' ).val() * 1 );\n\n\t\t}\n\n\t}, Editable ) );\n\n} );\n\n","/**\n * Quiz question bank view\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Views/QuestionList',[ 'Views/Question' ], function( QuestionView ) {\n\n\treturn Backbone.CollectionView.extend( {\n\n\t\tclassName: 'llms-quiz-questions',\n\n\t\t/**\n\t\t * Parent element\n\t\t * @type {String}\n\t\t */\n\t\t// el: '#llms-quiz-questions',\n\n\t\t/**\n\t\t * Section model\n\t\t * @type {[type]}\n\t\t */\n\t\tmodelView: QuestionView,\n\n\t\t/**\n\t\t * Enable keyboard events\n\t\t * @type {Bool}\n\t\t */\n\t\tprocessKeyEvents: false,\n\n\t\t/**\n\t\t * Are sections selectable?\n\t\t * @type {Bool}\n\t\t */\n\t\tselectable: false,\n\n\t\t/**\n\t\t * Are sections sortable?\n\t\t * @type {Bool}\n\t\t */\n\t\tsortable: true,\n\n\t\tsortableOptions: {\n\t\t\taxis: false,\n\t\t\tconnectWith: '.llms-quiz-questions',\n\t\t\tcursor: 'move',\n\t\t\thandle: '.llms-data-stamp',\n\t\t\titems: '.llms-question',\n\t\t\tplaceholder: 'llms-question llms-sortable-placeholder',\n\t\t},\n\n\t\t/**\n\t\t * Highlight drop areas when dragging starts\n\t\t * @param obj model model being sorted\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tsortable_start: function( model ) {\n\t\t\tvar selector = 'group' === model.get( 'question_type' ).get( 'id' ) ? '.llms-editor-tab > .llms-quiz-questions' : '.llms-quiz-questions';\n\t\t\t$( selector ).addClass( 'dragging' );\n\t\t},\n\n\t\t/**\n\t\t * Remove highlights when dragging stops\n\t\t * @param obj model model being sorted\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tsortable_stop: function() {\n\t\t\t$( '.llms-quiz-questions' ).removeClass( 'dragging' );\n\t\t},\n\n\t\t/**\n\t\t * Overrides receive to ensure that question groups can't be moved into queston groups\n\t\t * @param obj event js event object\n\t\t * @param obj ui jQuery UI Sortable ui object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\t_receive : function( event, ui ) {\n\n\t\t\tevent.stopPropagation();\n\n\t\t\t// prevent moving a question group into a question group\n\t\t\tif ( ui.item.hasClass( 'qtype--group' ) && $( event.target ).closest( '.qtype--group' ).length ) {;\n\t\t\t\tui.sender.sortable( 'cancel' );\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar senderListEl = ui.sender;\n\t\t\tvar senderCollectionListView = senderListEl.data( \"view\" );\n\t\t\tif( ! senderCollectionListView || ! senderCollectionListView.collection ) return;\n\n\t\t\tvar newIndex = this._getContainerEl().children().index( ui.item );\n\t\t\tvar modelReceived = senderCollectionListView.collection.get( ui.item.attr( \"data-model-cid\" ) );\n\t\t\tsenderCollectionListView.collection.remove( modelReceived );\n\t\t\tthis.collection.add( modelReceived, { at : newIndex } );\n\t\t\tmodelReceived.collection = this.collection; // otherwise will not get properly set, since modelReceived.collection might already have a value.\n\t\t\tthis.setSelectedModel( modelReceived );\n\t\t},\n\n\t\t/**\n\t\t * Override to allow manipulatino of placeholder element\n\t\t * @param {[type]} event [description]\n\t\t * @param {[type]} ui [description]\n\t\t * @return {[type]}\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\t_sortStart : function( event, ui ) {\n\n\t\t\tvar modelBeingSorted = this.collection.get( ui.item.attr( \"data-model-cid\" ) );\n\n\t\t\tui.placeholder.addClass( 'qtype--' + modelBeingSorted.get( 'question_type' ).get( 'id' ) );\n\n\t\t\tif( this._isBackboneCourierAvailable() )\n\t\t\t\tthis.spawn( \"sortStart\", { modelBeingSorted : modelBeingSorted } );\n\t\t\telse this.trigger( \"sortStart\", modelBeingSorted );\n\t\t},\n\n\t\t/**\n\t\t * Overloads the function from Backbone.CollectionView core because it doesn't send stop events\n\t\t * if moving from one sortable to another... :-(\n\t\t * @param obj event js event object\n\t\t * @param obj ui jQuery UI object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\t_sortStop : function( event, ui ) {\n\n\t\t\tevent.stopPropagation();\n\n\t\t\tvar modelBeingSorted = this.collection.get( ui.item.attr( 'data-model-cid' ) ),\n\t\t\t\tmodelViewContainerEl = this._getContainerEl(),\n\t\t\t\tnewIndex = modelViewContainerEl.children().index( ui.item );\n\n\t\t\tif ( newIndex == -1 && modelBeingSorted ) {\n\t\t\t\tthis.collection.remove( modelBeingSorted );\n\t\t\t}\n\n\t\t\tthis._reorderCollectionBasedOnHTML();\n\t\t\tthis.updateDependentControls();\n\n\t\t\tif( this._isBackboneCourierAvailable() ) {\n\t\t\t\tthis.spawn( 'sortStop', { modelBeingSorted : modelBeingSorted, newIndex : newIndex } );\n\t\t\t} else {\n\t\t\t\tthis.trigger( 'sortStop', modelBeingSorted, newIndex );\n\t\t\t}\n\n\t\t},\n\n\t} );\n\n} );\n\n","/**\n * Single Quiz View\n * @since 3.16.0\n * @version 3.19.2\n */\ndefine( 'Views/Quiz',[\n\t\t'Models/Quiz',\n\t\t'Views/Popover',\n\t\t'Views/PostSearch',\n\t\t'Views/QuestionBank',\n\t\t'Views/QuestionList',\n\t\t'Views/SettingsFields',\n\t\t'Views/_Detachable',\n\t\t'Views/_Editable',\n\t\t'Views/_Subview',\n\t\t'Views/_Trashable'\n\t], function(\n\t\tQuizModel,\n\t\tPopover,\n\t\tPostSearch,\n\t\tQuestionBank,\n\t\tQuestionList,\n\t\tSettingsFields,\n\t\tDetachable,\n\t\tEditable,\n\t\tSubview,\n\t\tTrashable\n\t) {\n\n\treturn Backbone.View.extend( _.defaults( {\n\n\t\t/**\n\t\t * Current view state\n\t\t * @type {String}\n\t\t */\n\t\tstate: 'default',\n\n\t\t/**\n\t\t * Current Subviews\n\t\t * @type {Object}\n\t\t */\n\t\tviews: {\n\t\t\tsettings: {\n\t\t\t\tclass: SettingsFields,\n\t\t\t\tinstance: null,\n\t\t\t\tstate: 'default',\n\t\t\t},\n\t\t\tbank: {\n\t\t\t\tclass: QuestionBank,\n\t\t\t\tinstance: null,\n\t\t\t\tstate: 'default',\n\t\t\t},\n\t\t\tlist: {\n\t\t\t\tclass: QuestionList,\n\t\t\t\tinstance: null,\n\t\t\t\tstate: 'default',\n\t\t\t},\n\t\t},\n\n\t\tel: '#llms-editor-quiz',\n\n\t\t/**\n\t\t * Events\n\t\t * @type {Object}\n\t\t */\n\t\tevents: _.defaults( {\n\t\t\t'click #llms-existing-quiz': 'add_existing_quiz_click',\n\t\t\t'click #llms-new-quiz': 'add_new_quiz',\n\t\t\t'click #llms-show-question-bank': 'show_tools',\n\t\t\t'click .bulk-toggle': 'bulk_toggle',\n\t\t\t// 'keyup #llms-question-bank-filter': 'filter_question_types',\n\t\t\t// 'search #llms-question-bank-filter': 'filter_question_types',\n\t\t}, Detachable.events, Editable.events, Trashable.events ),\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'div',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-quiz-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.19.2\n\t\t */\n\t\tinitialize: function( data ) {\n\n\t\t\tthis.lesson = data.lesson;\n\n\t\t\t// initialize the model if the quiz is enabled or it's disabled but we still have data for a quiz\n\t\t\tif ( 'yes' === this.lesson.get( 'quiz_enabled' ) || ! _.isEmpty( this.lesson.get( 'quiz' ) ) ) {\n\n\t\t\t\tthis.model = this.lesson.get( 'quiz' );\n\n\t\t\t\t/**\n\t\t\t\t * @todo this is a terrilbe terrible patch\n\t\t\t\t * I've spent nearly 3 days trying to figure out how to not use this line of code\n\t\t\t\t * ISSUE REPRODUCTION:\n\t\t\t\t * Open course builder\n\t\t\t\t * Open a lesson (A) and add a quiz\n\t\t\t\t * Switch to a new lesson (B)\n\t\t\t\t * Add a new quiz\n\t\t\t\t * Return to lesson A and the quizzes parent will be set to LESSON B\n\t\t\t\t * This will happen for *every* quiz in the builder...\n\t\t\t\t * Adding this set_parent on init guarantees that the quizzes correct parent is set\n\t\t\t\t * after adding new quizzes to other lessons\n\t\t\t\t * it's awful and it's gross...\n\t\t\t\t * I'm confused and tired and going to miss release dates again because of it\n\t\t\t\t */\n\t\t\t\tthis.model.set_parent( this.lesson );\n\n\t\t\t\tthis.listenTo( this.model, 'change:_points', this.render_points );\n\n\t\t\t}\n\n\t\t\tthis.on( 'model-trashed', this.on_trashed );\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.16.0\n\t\t * @version 3.19.2\n\t\t */\n\t\trender: function() {\n\n\t\t\tthis.$el.html( this.template( this.model ) );\n\n\t\t\t// render the quiz builder\n\t\t\tif ( this.model ) {\n\n\t\t\t\t// don't allow interaction until questions are lazy loaded\n\t\t\t\tLLMS.Spinner.start( this.$el );\n\n\t\t\t\tthis.render_subview( 'settings', {\n\t\t\t\t\tel: '#llms-quiz-settings-fields',\n\t\t\t\t\tmodel: this.model,\n\t\t\t\t} );\n\n\t\t\t\tthis.init_datepickers();\n\t\t\t\tthis.init_selects();\n\n\t\t\t\tthis.render_subview( 'bank', {\n\t\t\t\t\tcollection: window.llms_builder.questions,\n\t\t\t\t} );\n\n\t\t\t\tvar last_group = null,\n\t\t\t\t\tgroup = null;\n\t\t\t\t// let all the question types reference the quiz for adding questions quickly\n\t\t\t\tthis.get_subview( 'bank' ).instance.viewManager.each( function( view ) {\n\n\t\t\t\t\tview.quiz = this.model;\n\n\t\t\t\t\tgroup = view.model.get( 'group' ).name;\n\n\t\t\t\t\tif ( last_group !== group ) {\n\t\t\t\t\t\tlast_group = group;\n\t\t\t\t\t\tview.$el.before( '' );\n\t\t\t\t\t}\n\n\t\t\t\t}, this );\n\n\t\t\t\tthis.model.load_questions( _.bind( function( err ) {\n\n\t\t\t\t\tif ( err ) {\n\t\t\t\t\t\talert( LLMS.l10n.translate( 'An error occurred while trying to load the questions. Please refresh the page and try again.' ) );\n\t\t\t\t\t\treturn this;\n\t\t\t\t\t}\n\n\t\t\t\t\tLLMS.Spinner.stop( this.$el );\n\t\t\t\t\tthis.render_subview( 'list', {\n\t\t\t\t\t\tel: '#llms-quiz-questions',\n\t\t\t\t\t\tcollection: this.model.get( 'questions' ),\n\t\t\t\t\t} );\n\t\t\t\t\tvar list = this.get_subview( 'list' ).instance;\n\t\t\t\t\tlist.quiz = this;\n\t\t\t\t\tlist.collection.on( 'add', function() {\n\t\t\t\t\t\tlist.collection.trigger( 'reorder' );\n\t\t\t\t\t}, this );\n\t\t\t\t\tlist.on( 'sortStart', list.sortable_start );\n\t\t\t\t\tlist.on( 'sortStop', list.sortable_stop );\n\n\t\t\t\t}, this ) );\n\n\t\t\t\tthis.model.on( 'new-question-added', function() {\n\t\t\t\t\tvar $questions = this.$el.find( '#llms-quiz-questions' );\n\t\t\t\t\t$questions.animate( { scrollTop: $questions.prop( 'scrollHeight' ) }, 200 );\n\t\t\t\t}, this );\n\n\t\t\t}\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\t/**\n\t\t * On quiz points update, update the value of the Total Points area in the header\n\t\t * @param obj quiz Instance of the quiz model\n\t\t * @param int points Updated number of points\n\t\t * @return void\n\t\t * @since 3.17.6\n\t\t * @version 3.17.6\n\t\t */\n\t\trender_points: function( quiz, points ) {\n\n\t\t\tthis.$el.find( '#llms-quiz-total-points' ).text( points );\n\n\t\t},\n\n\t\t/**\n\t\t * Bulk expand / collapse question buttons\n\t\t * @param obj event js event object\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tbulk_toggle: function( event ) {\n\n\t\t\tvar expanded = ( 'expand' === $( event.target ).attr( 'data-action' ) );\n\n\t\t\tthis.model.get( 'questions' ).each( function( question ) {\n\t\t\t\tquestion.set( '_expanded', expanded );\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * Adds a new quiz to a lesson which currently has no quiz associated wlith it\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tadd_new_quiz: function() {\n\n\t\t\tvar quiz = this.lesson.get( 'quiz' );\n\t\t\tif ( _.isEmpty( quiz ) ) {\n\t\t\t\tquiz = this.lesson.add_quiz();\n\t\t\t} else {\n\t\t\t\tthis.lesson.set( 'quiz_enabled', 'yes' );\n\t\t\t}\n\n\t\t\tthis.model = quiz;\n\t\t\tthis.render();\n\n\t\t},\n\n\t\t// come back to this and make sure cloning resets all the IDs\n\t\tadd_existing_quiz: function( event ) {\n\n\t\t\tthis.post_search_popover.hide();\n\n\t\t\tvar quiz = event.data;\n\n\t\t\tif ( 'clone' === event.action ) {\n\n\t\t\t\tdelete quiz.id;\n\n\t\t\t\t_.each( quiz.questions, function( question ) {\n\n\t\t\t\t\tdelete question.parent_id;\n\t\t\t\t\tdelete question.id;\n\n\t\t\t\t\tif ( question.choices ) {\n\n\t\t\t\t\t\t_.each( question.choices, function( choice ) {\n\n\t\t\t\t\t\t\tdelete choice.question_id;\n\t\t\t\t\t\t\tdelete choice.id;\n\n\t\t\t\t\t\t} );\n\n\t\t\t\t\t}\n\n\t\t\t\t} );\n\n\t\t\t} else {\n\n\t\t\t\tquiz._forceSync = true;\n\n\t\t\t}\n\n\t\t\tdelete quiz.lesson_id;\n\n\t\t\tthis.lesson.add_quiz( quiz );\n\t\t\tthis.model = this.lesson.get( 'quiz' );\n\t\t\tthis.render();\n\n\t\t},\n\n\t\t/**\n\t\t * Open add existing quiz popover\n\t\t * @param obj event JS event object\n\t\t * @return void\n\t\t * @since 3.16.12\n\t\t * @version 3.16.12\n\t\t */\n\t\tadd_existing_quiz_click: function( event ) {\n\n\t\t\tevent.preventDefault();\n\n\t\t\tthis.post_search_popover = new Popover( {\n\t\t\t\tel: '#llms-existing-quiz',\n\t\t\t\targs: {\n\t\t\t\t\tbackdrop: true,\n\t\t\t\t\tcloseable: true,\n\t\t\t\t\tcontainer: '.wrap.lifterlms.llms-builder',\n\t\t\t\t\tdismissible: true,\n\t\t\t\t\tplacement: 'left',\n\t\t\t\t\twidth: 480,\n\t\t\t\t\ttitle: LLMS.l10n.translate( 'Add Existing Quiz' ),\n\t\t\t\t\tcontent: new PostSearch( {\n\t\t\t\t\t\tpost_type: 'llms_quiz',\n\t\t\t\t\t\tsearching_message: LLMS.l10n.translate( 'Search for existing quizzes...' ),\n\t\t\t\t\t} ).render().$el,\n\t\t\t\t\tonHide: function() {\n\t\t\t\t\t\tBackbone.pubSub.off( 'quiz-search-select' );\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\tthis.post_search_popover.show();\n\t\t\tBackbone.pubSub.once( 'quiz-search-select', this.add_existing_quiz, this );\n\n\t\t},\n\n\t\t// filter_question_types: _.debounce( function( event ) {\n\n\t\t// \tvar term = $( event.target ).val();\n\n\t\t// \tthis.QuestionBankView.viewManager.each( function( view ) {\n\t\t// \t\tif ( ! term ) {\n\t\t// \t\t\tview.clear_filter();\n\t\t// \t\t} else {\n\t\t// \t\t\tview.filter( term );\n\t\t// \t\t}\n\t\t// \t} );\n\n\n\t\t// }, 300 ),\n\n\t\t/**\n\t\t * Callback function when the quiz has been deleted\n\t\t * @param object quiz Quiz Model\n\t\t * @return void\n\t\t * @since 3.16.6\n\t\t * @version 3.16.6\n\t\t */\n\t\ton_trashed: function( quiz ) {\n\n\t\t\tthis.lesson.set( 'quiz_enabled', 'no' );\n\t\t\tthis.lesson.set( 'quiz', '' );\n\n\t\t\tdelete this.model;\n\n\t\t\tthis.render();\n\n\t\t},\n\n\t\t/**\n\t\t * \"Add Question\" button click event\n\t\t * Creates a popover with question type list interface\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tshow_tools: function() {\n\n\t\t\t// create popover\n\t\t\tvar pop = new Popover( {\n\t\t\t\tel: '#llms-show-question-bank',\n\t\t\t\targs: {\n\t\t\t\t\tbackdrop: true,\n\t\t\t\t\tcloseable: true,\n\t\t\t\t\tcontainer: '#llms-builder-sidebar',\n\t\t\t\t\tdismissible: true,\n\t\t\t\t\tplacement: 'top-left',\n\t\t\t\t\twidth: 'calc( 100% - 40px )',\n\t\t\t\t\ttitle: LLMS.l10n.translate( 'Add a Question' ),\n\t\t\t\t\turl: '#llms-quiz-tools',\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\t// show it\n\t\t\tpop.show();\n\n\t\t\t// if a question is added, hide the popover\n\t\t\tthis.model.on( 'new-question-added', function() {\n\t\t\t\tpop.hide();\n\t\t\t} );\n\n\t\t},\n\n\t\tget_question_list: function( options ) {\n\t\t\treturn new QuestionList( options );\n\t\t}\n\n\t}, Detachable, Editable, Subview, Trashable, SettingsFields ) );\n\n} );\n\n","/**\n * Single Assignment View\n * @since 3.17.0\n * @version 3.17.7\n */\ndefine( 'Views/Assignment',[\n\t\t'Views/Popover',\n\t\t'Views/PostSearch',\n\t\t'Views/_Detachable',\n\t\t'Views/_Editable',\n\t\t'Views/_Trashable',\n\t\t'Views/_Subview',\n\t\t'Views/SettingsFields'\n\t], function(\n\t\tPopover,\n\t\tPostSearch,\n\t\tDetachable,\n\t\tEditable,\n\t\tTrashable,\n\t\tSubview,\n\t\tSettingsFields\n\t) {\n\n\treturn Backbone.View.extend( _.defaults( {\n\n\t\t/**\n\t\t * Current view state\n\t\t * @type {String}\n\t\t */\n\t\tstate: 'default',\n\n\t\t/**\n\t\t * Current Subviews\n\t\t * @type {Object}\n\t\t */\n\t\tviews: {\n\t\t\tsettings: {\n\t\t\t\tclass: SettingsFields,\n\t\t\t\tinstance: null,\n\t\t\t\tstate: 'default',\n\t\t\t},\n\t\t},\n\n\t\tel: '#llms-editor-assignment',\n\n\t\t/**\n\t\t * DOM Events\n\t\t * @return obj\n\t\t * @since 3.17.1\n\t\t * @version 3.17.1\n\t\t */\n\t\tevents: function() {\n\t\t\tvar addon_events = this.is_addon_available() ? window.llms_builder.assignments.get_view_events() : {};\n\t\t\treturn _.defaults( {\n\t\t\t\t'click #llms-existing-assignment': 'add_existing_assignment_click',\n\t\t\t\t'click #llms-new-assignment': 'add_new_assignment',\n\t\t\t}, Detachable.events, Editable.events, Trashable.events, addon_events );\n\t\t},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'div',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-assignment-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.2\n\t\t */\n\t\tinitialize: function( data ) {\n\n\t\t\tthis.lesson = data.lesson;\n\n\t\t\t// initialize the model if the assignment is enabled or it's disabled but we still have data for a assignment\n\t\t\tif ( 'yes' === this.lesson.get( 'assignment_enabled' ) || ! _.isEmpty( this.lesson.get( 'assignment' ) ) ) {\n\n\t\t\t\tthis.model = this.lesson.get( 'assignment' );\n\n\t\t\t\t/**\n\t\t\t\t * @todo this is a terrilbe terrible patch\n\t\t\t\t * I've spent nearly 3 days trying to figure out how to not use this line of code\n\t\t\t\t * ISSUE REPRODUCTION:\n\t\t\t\t * Open course builder\n\t\t\t\t * Open a lesson (A) and add a assignment\n\t\t\t\t * Switch to a new lesson (B)\n\t\t\t\t * Add a new assignment\n\t\t\t\t * Return to lesson A and the assignment's parent will be set to LESSON B\n\t\t\t\t * This will happen for *every* assignment in the builder...\n\t\t\t\t * Adding this set_parent on init guarantees that the assignment's correct parent is set\n\t\t\t\t * after adding new assignment's to other lessons\n\t\t\t\t * it's awful and it's gross...\n\t\t\t\t * I'm confused and tired and going to miss release dates again because of it\n\t\t\t\t */\n\t\t\t\tthis.model.set_parent( this.lesson );\n\n\t\t\t}\n\n\t\t\tthis.on( 'model-trashed', this.on_trashed );\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.17.0\n\t\t * @version 3.17.7\n\t\t */\n\t\trender: function() {\n\n\t\t\tthis.$el.html( this.template( this.model ) );\n\n\t\t\tif ( this.model && this.is_addon_available() ) {\n\n\t\t\t\tthis.stopListening( this.model, 'change:assignment_type', this.render );\n\n\t\t\t\tthis.render_subview( 'settings', {\n\t\t\t\t\tel: '#llms-assignment-settings-fields',\n\t\t\t\t\tmodel: this.model,\n\t\t\t\t} );\n\n\t\t\t\t// this.init_datepickers();\n\t\t\t\tthis.init_selects();\n\n\t\t\t\twindow.llms_builder.assignments.render_editor( this );\n\n\t\t\t\tthis.listenTo( this.model, 'change:assignment_type', this.render );\n\n\t\t\t}\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\t/**\n\t\t * Adds a new assignment to a lesson which currently has no assignment associated wlith it\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tadd_new_assignment: function() {\n\n\t\t\tif ( this.is_addon_available() ) {\n\n\t\t\t\tthis.model = window.llms_builder.assignments.get_assignment( {\n\t\t\t\t\t/* translators: %1$s = associated lesson title */\n\t\t\t\t\ttitle: LLMS.l10n.replace( '%1$s Assignment', {\n\t\t\t\t\t\t'%1$s': this.lesson.get( 'title' ),\n\t\t\t\t\t} ),\n\t\t\t\t\tlesson_id: this.lesson.get( 'id' ),\n\t\t\t\t} );\n\n\t\t\t\tthis.lesson.set( 'assignment_enabled', 'yes' );\n\t\t\t\tthis.lesson.set( 'assignment', this.model );\n\n\t\t\t\tthis.render();\n\n\t\t\t} else {\n\n\t\t\t\tthis.show_ad_popover( '#llms-new-assignment' );\n\n\t\t\t}\n\n\n\t\t},\n\n\t\t/**\n\t\t * When an assignment is selected from the post select popover\n\t\t * instantiate it and add it to the current lesson\n\t\t * @param object event data from the select2 select event\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tadd_existing_assignment: function( event ) {\n\n\t\t\tthis.post_search_popover.hide();\n\n\t\t\tvar assignment = event.data;\n\n\t\t\tif ( 'clone' === event.action ) {\n\n\t\t\t\tdelete assignment.id;\n\n\t\t\t} else {\n\n\t\t\t\tassignment._forceSync = true;\n\n\t\t\t}\n\n\t\t\tassignment.lesson_id = this.lesson.get( 'id' )\n\n\t\t\tassignment = window.llms_builder.construct.get_model( 'Assignment', assignment );\n\n\t\t\tthis.lesson.set( 'assignment_enabled', 'yes' );\n\t\t\tthis.lesson.set( 'assignment', assignment );\n\t\t\tthis.model = assignment;\n\n\t\t\tthis.render();\n\n\t\t},\n\n\t\t/**\n\t\t * Open add existing assignment popover\n\t\t * @param obj event JS event object\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tadd_existing_assignment_click: function( event ) {\n\n\t\t\tevent.preventDefault();\n\n\t\t\tif ( this.is_addon_available() ) {\n\n\t\t\t\tthis.post_search_popover = new Popover( {\n\t\t\t\t\tel: '#llms-existing-assignment',\n\t\t\t\t\targs: {\n\t\t\t\t\t\tbackdrop: true,\n\t\t\t\t\t\tcloseable: true,\n\t\t\t\t\t\tcontainer: '.wrap.lifterlms.llms-builder',\n\t\t\t\t\t\tdismissible: true,\n\t\t\t\t\t\tplacement: 'left',\n\t\t\t\t\t\twidth: 480,\n\t\t\t\t\t\ttitle: LLMS.l10n.translate( 'Add Existing Assignment' ),\n\t\t\t\t\t\tcontent: new PostSearch( {\n\t\t\t\t\t\t\tpost_type: 'llms_assignment',\n\t\t\t\t\t\t\tsearching_message: LLMS.l10n.translate( 'Search for existing assignments...' ),\n\t\t\t\t\t\t} ).render().$el,\n\t\t\t\t\t\tonHide: function() {\n\t\t\t\t\t\t\tBackbone.pubSub.off( 'assignment-search-select' );\n\t\t\t\t\t\t},\n\t\t\t\t\t}\n\t\t\t\t} );\n\n\t\t\t\tthis.post_search_popover.show();\n\t\t\t\tBackbone.pubSub.once( 'assignment-search-select', this.add_existing_assignment, this );\n\n\t\t\t} else {\n\n\t\t\t\tthis.show_ad_popover( '#llms-existing-assignment' );\n\n\t\t\t}\n\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if Assignments addon is available to use\n\t\t * @return {Boolean}\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tis_addon_available: function() {\n\n\t\t\treturn ( window.llms_builder.assignments );\n\n\t\t},\n\n\t\t/**\n\t\t * Called when assignment is trashed\n\t\t * @param obj assignment Assignment model\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\ton_trashed: function( assignment ) {\n\n\t\t\tthis.lesson.set( 'assignment_enabled', 'no' );\n\t\t\tthis.lesson.set( 'assignment', '' );\n\n\t\t\tdelete this.model;\n\n\t\t\tthis.render();\n\n\t\t},\n\n\t\t/**\n\t\t * Shows a dirty dirty ad popoever for advanced assignments\n\t\t * @param string el jQuery selector string\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tshow_ad_popover: function( el ) {\n\n\t\t\tvar h3 = LLMS.l10n.translate( 'Get Your Students Taking Action' ),\n\t\t\t\tp = 'Great learning content is only half of teaching online. When your learners fully engage, they will take your content and move into action. Remove barriers for your learners by telling them what to do to apply what they just learned. Create graded assignments or simply give them a checklist of action items to complete before moving on.',\n\t\t\t\tbtn = LLMS.l10n.translate( 'Get Assignments Now!' ),\n\t\t\t\turl = 'https://lifterlms.com/product/lifterlms-assignments?utm_source=LifterLMS%20Plugin&utm_medium=Assignment%20Builder%20Button&utm_campaign=Assignment%20Addon%20Upsell&utm_content=3.17.0';\n\n\t\t\tthis.ad_popover = new Popover( {\n\t\t\t\tel: el,\n\t\t\t\targs: {\n\t\t\t\t\tbackdrop: true,\n\t\t\t\t\tcloseable: true,\n\t\t\t\t\tcontainer: '.wrap.lifterlms.llms-builder',\n\t\t\t\t\tdismissible: true,\n\t\t\t\t\t// placement: 'left',\n\t\t\t\t\twidth: 380,\n\t\t\t\t\ttitle: LLMS.l10n.translate( 'Unlock LifterLMS Assignments' ),\n\t\t\t\t\tcontent: '' + h3 + ' ' + p + '
' + btn + '
'\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\tthis.ad_popover.show();\n\n\t\t},\n\n\t}, Detachable, Editable, Trashable, Subview, SettingsFields ) );\n\n} );\n\n","/**\n * Sidebar Editor View\n * @since 3.16.0\n * @version 3.17.0\n */\ndefine( 'Views/Editor',[\n\t\t'Views/LessonEditor',\n\t\t'Views/Quiz',\n\t\t'Views/Assignment',\n\t\t'Views/_Subview'\n\t], function(\n\t\tLessonEditor,\n\t\tQuiz,\n\t\tAssignment,\n\t\tSubview\n\t) {\n\n\treturn Backbone.View.extend( _.defaults( {\n\n\t\t/**\n\t\t * Current view state\n\t\t * @type {String}\n\t\t */\n\t\tstate: 'lesson', // [lesson|quiz]\n\n\t\t/**\n\t\t * Current Subviews\n\t\t * @type {Object}\n\t\t */\n\t\tviews: {\n\t\t\tlesson: {\n\t\t\t\tclass: LessonEditor,\n\t\t\t\tinstance: null,\n\t\t\t\tstate: 'lesson',\n\t\t\t},\n\t\t\tassignment: {\n\t\t\t\tclass: Assignment,\n\t\t\t\tinstance: null,\n\t\t\t\tstate: 'assignment',\n\t\t\t},\n\t\t\tquiz: {\n\t\t\t\tclass: Quiz,\n\t\t\t\tinstance: null,\n\t\t\t\tstate: 'quiz',\n\t\t\t},\n\t\t},\n\n\t\t/**\n\t\t * HTML element selector\n\t\t * @type {String}\n\t\t */\n\t\tel: '#llms-editor',\n\n\t\tevents: {\n\t\t\t'click .llms-editor-nav a[href=\"#llms-editor-close\"]': 'close_editor',\n\t\t\t'click .llms-editor-nav a:not([href=\"#llms-editor-close\"])': 'switch_tab',\n\t\t},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'div',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-editor-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function( data ) {\n\n\t\t\tthis.SidebarView = data.SidebarView;\n\t\t\tif ( data.tab ) {\n\t\t\t\tthis.state = data.tab;\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender: function( view_data ) {\n\n\t\t\tview_data = view_data || {};\n\n\t\t\tthis.$el.html( this.template( this ) );\n\n\t\t\tthis.render_subviews( _.extend( view_data, {\n\t\t\t\tlesson: this.model,\n\t\t\t} ) );\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\t/**\n\t\t * Click event for close sidebar editor button\n\t\t * Sends event to main SidebarView to trigger editor closing events\n\t\t * @param obj event js event obj\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tclose_editor: function( event ) {\n\n\t\t\tevent.preventDefault();\n\t\t\tBackbone.pubSub.trigger( 'sidebar-editor-close' );\n\n\t\t},\n\n\t\t/**\n\t\t * Click event for switching tabs in the editor navigation\n\t\t * @param object event js event object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tswitch_tab: function( event ) {\n\n\t\t\tevent.preventDefault();\n\n\t\t\tvar $btn = $( event.target ),\n\t\t\t\tview = $btn.attr( 'data-view' ),\n\t\t\t\t$tab = this.$el.find( $btn.attr( 'href' ) );\n\n\t\t\tthis.set_state( view ).render();\n\n\t\t\t// Backbone.pubSub.trigger( 'editor-tab-activated', $btn.attr( 'href' ).substring( 1 ) );\n\n\t\t},\n\n\t}, Subview ) );\n\n} );\n\n","/**\n * Sidebar Elements View\n * @since 3.16.0\n * @version 3.16.12\n */\ndefine( 'Views/Elements',[ 'Models/Section', 'Views/Section', 'Models/Lesson', 'Views/Lesson', 'Views/Popover', 'Views/PostSearch' ], function( Section, SectionView, Lesson, LessonView, Popover, LessonSearch ) {\n\n\treturn Backbone.View.extend( {\n\n\t\t/**\n\t\t * HTML element selector\n\t\t * @type {String}\n\t\t */\n\t\tel: '#llms-elements',\n\n\t\tevents: {\n\t\t\t'click #llms-new-section': 'add_new_section',\n\t\t\t'click #llms-new-lesson': 'add_new_lesson',\n\t\t\t'click #llms-existing-lesson': 'add_existing_lesson',\n\t\t},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'div',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-elements-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function( data ) {\n\n\t\t\t// save a reference to the main Course view\n\t\t\tthis.SidebarView = data.SidebarView;\n\n\t\t\t// watch course sections and enable/disable lesson buttons conditionally\n\t\t\tthis.listenTo( this.SidebarView.CourseView.model.get( 'sections' ), 'add', this.maybe_disable_buttons );\n\t\t\tthis.listenTo( this.SidebarView.CourseView.model.get( 'sections' ), 'remove', this.maybe_disable_buttons );\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender: function() {\n\n\t\t\tthis.$el.html( this.template() );\n\t\t\tthis.draggable();\n\t\t\tthis.maybe_disable_buttons();\n\n\t\t\treturn this;\n\t\t},\n\n\t\tdraggable: function() {\n\n\t\t\t$( '#llms-new-section' ).draggable( {\n\t\t\t\tappendTo: '#llms-sections',\n\t\t\t\tcancel: false,\n\t\t\t\tconnectToSortable: '.llms-sections',\n\t\t\t\thelper: function() {\n\t\t\t\t\treturn new SectionView( { model: new Section() } ).render().$el;\n\t\t\t\t},\n\t\t\t\tstart: function() {\n\t\t\t\t\t$( '.llms-sections' ).addClass( 'dragging' );\n\t\t\t\t},\n\t\t\t\tstop: function() {\n\t\t\t\t\t$( '.llms-sections' ).removeClass( 'dragging' );\n\t\t\t\t},\n\t\t\t} );\n\n\t\t\t$( '#llms-new-lesson' ).draggable( {\n\t\t\t\t// appendTo: '#llms-sections .llms-section:first-child .llms-lessons',\n\t\t\t\tappendTo: '#llms-sections',\n\t\t\t\tcancel: false,\n\t\t\t\tconnectToSortable: '.llms-lessons',\n\t\t\t\thelper: function() {\n\t\t\t\t\treturn new LessonView( { model: new Lesson() } ).render().$el;\n\t\t\t\t},\n\t\t\t\tstart: function() {\n\n\t\t\t\t\t$( '.llms-lessons' ).addClass( 'dragging' );\n\n\t\t\t\t},\n\t\t\t\tstop: function() {\n\t\t\t\t\t$( '.llms-lessons' ).removeClass( 'dragging' );\n\t\t\t\t\t$( '.drag-expanded' ).removeClass( '.drag-expanded' );\n\t\t\t\t},\n\t\t\t} );\n\n\t\t},\n\n\t\tadd_new_section: function( event ) {\n\n\t\t\tevent.preventDefault();\n\t\t\tBackbone.pubSub.trigger( 'add-new-section' );\n\t\t},\n\n\t\tadd_new_lesson: function( event ) {\n\t\t\tevent.preventDefault();\n\t\t\tBackbone.pubSub.trigger( 'add-new-lesson' );\n\t\t},\n\n\t\t/**\n\t\t * Show the popover to add an existing lessons\n\t\t * @param object event JS Event OBject\n\t\t * @return void\n\t\t * @since 3.16.12\n\t\t * @version 3.16.12\n\t\t */\n\t\tadd_existing_lesson: function( event ) {\n\n\t\t\tevent.preventDefault();\n\n\t\t\tvar pop = new Popover( {\n\t\t\t\tel: '#llms-existing-lesson',\n\t\t\t\targs: {\n\t\t\t\t\tbackdrop: true,\n\t\t\t\t\tcloseable: true,\n\t\t\t\t\tcontainer: '.wrap.lifterlms.llms-builder',\n\t\t\t\t\tdismissible: true,\n\t\t\t\t\tplacement: 'left',\n\t\t\t\t\twidth: 480,\n\t\t\t\t\ttitle: LLMS.l10n.translate( 'Add Existing Lesson' ),\n\t\t\t\t\tcontent: new LessonSearch( {\n\t\t\t\t\t\tpost_type: 'lesson',\n\t\t\t\t\t\tsearching_message: LLMS.l10n.translate( 'Search for existing lessons...' ),\n\t\t\t\t\t} ).render().$el,\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\tpop.show();\n\t\t\tBackbone.pubSub.on( 'lesson-search-select', function() {\n\t\t\t\tpop.hide()\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * Disables lesson add buttons if no sections are available to add a lesson to\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tmaybe_disable_buttons: function() {\n\n\t\t\tvar $els = $( '#llms-new-lesson, #llms-existing-lesson' );\n\n\t\t\tif ( ! this.SidebarView.CourseView.model.get( 'sections' ).length ) {\n\t\t\t\t$els.attr( 'disabled', 'disabled' );\n\t\t\t} else {\n\t\t\t\t$els.removeAttr( 'disabled' );\n\t\t\t}\n\n\t\t},\n\n\t} );\n\n} );\n\n","/**\n * Sidebar Utilities View\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Views/Utilities',[], function() {\n\n\treturn Backbone.View.extend( {\n\n\t\t/**\n\t\t * HTML element selector\n\t\t * @type {String}\n\t\t */\n\t\tel: '#llms-utilities',\n\n\t\tevents: {\n\t\t\t'click #llms-collapse-all': 'collapse_all',\n\t\t\t'click #llms-expand-all': 'expand_all'\n\t\t},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'div',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-utilities-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\t// this.render();\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender: function() {\n\t\t\tthis.$el.html( this.template() );\n\t\t\treturn this;\n\t\t},\n\n\t\t/**\n\t\t * Collapse all sections\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tcollapse_all: function( event ) {\n\t\t\tevent.preventDefault();\n\t\t\tBackbone.pubSub.trigger( 'collapse-all' );\n\t\t},\n\n\t\t/**\n\t\t * Expand all sections\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\texpand_all: function( event ) {\n\t\t\tevent.preventDefault();\n\t\t\tBackbone.pubSub.trigger( 'expand-all' );\n\t\t},\n\n\t} );\n\n} );\n\n","/**\n * Main sidebar view\n * @since 3.16.0\n * @version 3.16.7\n */\ndefine( 'Views/Sidebar',[\n\t\t'Views/Editor',\n\t\t'Views/Elements',\n\t\t'Views/Utilities',\n\t\t'Views/_Subview'\n\t], function(\n\t\tEditor,\n\t\tElements,\n\t\tUtilities,\n\t\tSubview\n\t) {\n\n\treturn Backbone.View.extend( _.defaults( {\n\n\t\t/**\n\t\t * Current builder state\n\t\t * @type {String}\n\t\t */\n\t\tstate: 'builder', // [builder|editor]\n\n\t\t/**\n\t\t * Current Subviews\n\t\t * @type {Object}\n\t\t */\n\t\tviews: {\n\t\t\telements: {\n\t\t\t\tclass: Elements,\n\t\t\t\tinstance: null,\n\t\t\t\tstate: 'builder',\n\t\t\t},\n\t\t\tutilities: {\n\t\t\t\tclass: Utilities,\n\t\t\t\tinstance: null,\n\t\t\t\tstate: 'builder',\n\t\t\t},\n\t\t\teditor: {\n\t\t\t\tclass: Editor,\n\t\t\t\tinstance: null,\n\t\t\t\tstate: 'editor',\n\t\t\t},\n\t\t},\n\n\t\t/**\n\t\t * HTML element selector\n\t\t * @type {String}\n\t\t */\n\t\tel: '#llms-builder-sidebar',\n\n\t\t/**\n\t\t * DOM events\n\t\t * @type {Object}\n\t\t */\n\t\tevents: {\n\t\t\t'click #llms-save-button': 'save_now',\n\t\t\t'click #llms-exit-button': 'exit_now',\n\t\t\t'click .llms-builder-error': 'clear_errors',\n\t\t},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'aside',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-sidebar-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function( data ) {\n\n\t\t\t// save a reference to the main Course view\n\t\t\tthis.CourseView = data.CourseView;\n\n\t\t\tthis.render();\n\n\t\t\tBackbone.pubSub.on( 'current-save-status', this.changes_made, this );\n\n\t\t\tBackbone.pubSub.on( 'heartbeat-send', this.heartbeat_send, this );\n\t\t\tBackbone.pubSub.on( 'heartbeat-tick', this.heartbeat_tick, this );\n\n\t\t\tBackbone.pubSub.on( 'lesson-selected', this.on_lesson_select, this );\n\t\t\tBackbone.pubSub.on( 'sidebar-editor-close', this.on_editor_close, this );\n\n\t\t\tthis.$saveButton = $( '#llms-save-button' );\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender: function( view_data ) {\n\n\t\t\tview_data = view_data || {};\n\n\t\t\tthis.$el.html( this.template() );\n\n\t\t\tthis.render_subviews( _.extend( view_data, {\n\t\t\t\tSidebarView: this,\n\t\t\t} ) );\n\n\t\t\tvar $el = $( '.wrap.lifterlms.llms-builder' );\n\t\t\tif ( 'builder' === this.state ) {\n\t\t\t\t$el.removeClass( 'editor-active' );\n\t\t\t} else {\n\t\t\t\t$el.addClass( 'editor-active' );\n\t\t\t}\n\n\t\t\tthis.$saveButton = this.$el.find( '#llms-save-button' );\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\t/**\n\t\t * Adds error message element\n\t\t * @param {[type]} $err [description]\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tadd_error: function( $err ) {\n\n\t\t\tthis.$el.find( '.llms-builder-save' ).prepend( $err );\n\n\t\t},\n\n\t\t/**\n\t\t * Clear any existing error message elements\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tclear_errors: function() {\n\n\t\t\tthis.$el.find( '.llms-builder-save .llms-builder-error' ).remove();\n\n\t\t},\n\n\t\t/**\n\t\t * Update save status button when changes are detected\n\t\t * runs on an interval to check status of course regularly for unsaved changes\n\t\t * @param obj sync instance of the sync controller\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tchanges_made: function( sync ) {\n\n\t\t\t// if a save is currently running, don't do anything\n\t\t\tif ( sync.saving ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( sync.has_unsaved_changes ) {\n\n\t\t\t\tthis.$saveButton.attr( 'data-status', 'unsaved' );\n\t\t\t\tthis.$saveButton.removeAttr( 'disabled' );\n\n\t\t\t} else {\n\n\t\t\t\tthis.$saveButton.attr( 'data-status', 'saved' );\n\t\t\t\tthis.$saveButton.attr( 'disabled', 'disabled' );\n\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Exit the builder and return to the WP Course Editor\n\t\t * @return void\n\t\t * @since 3.16.7\n\t\t * @version 3.16.7\n\t\t */\n\t\texit_now: function() {\n\n\t\t\twindow.location.href = window.llms_builder.CourseModel.get_edit_post_link();\n\n\t\t},\n\n\t\t/**\n\t\t * Triggered when a heartbeat send event starts containing builder information\n\t\t * @param obj sync instance of the sync controller\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\theartbeat_send: function( sync ) {\n\n\t\t\tif ( sync.saving ) {\n\t\t\t\tLLMS.Spinner.start( this.$saveButton.find( 'i' ), 'small' );\n\t\t\t\tthis.$saveButton.attr( {\n\t\t\t\t\t'data-status': 'saving',\n\t\t\t\t\tdisabled: 'disabled',\n\t\t\t\t} );\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Triggered when a heartbeat tick completes and updates save status or appends errors\n\t\t * @param obj sync instance of the sync controller\n\t\t * @param obj data updated data\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\theartbeat_tick: function( sync, data ) {\n\n\t\t\tif ( ! sync.saving ) {\n\n\t\t\t\tvar status = 'saved';\n\n\t\t\t\tthis.clear_errors();\n\n\t\t\t\tif ( 'error' === data.status ) {\n\n\t\t\t\t\tstatus = 'error';\n\n\t\t\t\t\tvar msg = data.message,\n\t\t\t\t\t\t$err = $( ' ' );\n\n\t\t\t\t\tif ( 'object' === typeof msg ) {\n\t\t\t\t\t\t_.each( msg, function( txt ) {\n\t\t\t\t\t\t\t$err.append( '' + txt + ' ' );\n\t\t\t\t\t\t} );\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$err = $err.append( '' + msg + ' ' );;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.add_error( $err );\n\n\t\t\t\t}\n\n\t\t\t\tthis.$saveButton.find( '.llms-spinning' ).remove();\n\t\t\t\tthis.$saveButton.attr( {\n\t\t\t\t\t'data-status': status,\n\t\t\t\t\tdisabled: 'disabled',\n\t\t\t\t} );\n\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if the editor is the currently active state\n\t\t * @return boolean\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tis_editor_active: function() {\n\n\t\t\treturn ( 'editor' === this.state );\n\n\t\t},\n\n\t\t/**\n\t\t * Triggered when the editor closes, updates state to be the course builder view\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\ton_editor_close: function() {\n\n\t\t\tthis.set_state( 'builder' ).render();\n\n\t\t},\n\n\t\t/**\n\t\t * When a lesson is selected, opens the sidebar to the editor view\n\t\t * @param obj lesson_model instance of the lesson model which was selected\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\ton_lesson_select: function( lesson_model, tab ) {\n\n\t\t\tif ( 'editor' !== this.state ) {\n\t\t\t\tthis.set_state( 'editor' );\n\t\t\t} else {\n\t\t\t\tthis.remove_subview( 'editor' );\n\t\t\t}\n\n\t\t\tthis.render( {\n\t\t\t\tmodel: lesson_model,\n\t\t\t\ttab: tab,\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * Save button click event\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tsave_now: function() {\n\n\t\t\twindow.llms_builder.sync.save_now();\n\n\t\t},\n\n\t}, Subview ) );\n\n} );\n\n","/**\n * LifterLMS JS Builder App Bootstrap\n * @since 3.16.0\n * @version 3.17.8\n */\nrequire( [\n\t'vendor/backbone.collectionView',\n\t'vendor/backbone.trackit',\n\t'Controllers/Construct',\n\t'Controllers/Debug',\n\t'Controllers/Schemas',\n\t'Controllers/Sync',\n\t'Models/loader',\n\t'Views/Course',\n\t'Views/Sidebar'\n], function(\n\tCV,\n\tTrackIt,\n\tConstruct,\n\tDebug,\n\tSchemas,\n\tSync,\n\tModels,\n\tCourseView,\n\tSidebarView\n) {\n\n\twindow.llms_builder.debug = new Debug( window.llms_builder.debug );\n\twindow.llms_builder.construct = new Construct();\n\twindow.llms_builder.schemas = new Schemas( window.llms_builder.schemas );\n\n\t/**\n\t * Compare values, used by _.checked & _.selected mixins\n\t * @param mixed expected expected value, probably a string (the value of a select option or checkbox element)\n\t * @param mixed actual actual value, probably a string (the return of model.get( 'something' ) )\n\t * \t\t\t\t but could be an array like a multiselect\n\t * @return boolean\n\t * @since 3.17.2\n\t * @version 3.17.2\n\t */\n\tfunction value_compare( expected, actual ) {\n\t\treturn ( ( _.isArray( actual ) && -1 !== actual.indexOf( expected ) ) || expected == actual );\n\t};\n\n\t/**\n\t * Underscores templating utilities\n\t * @since 3.17.0\n\t * @version 3.17.8\n\t */\n\t_.mixin( {\n\n\t\t/**\n\t\t * Determine if two values are equal and output checked attribute if they are\n\t\t * Useful for templating checkboxes & radio elements\n\t\t * Like WP Core PHP checked() but in JS\n\t\t * @param mixed expected expected element value\n\t\t * @param mixed actual actual element value\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.2\n\t\t */\n\t\tchecked: function( expected, actual ) {\n\t\t\tif ( value_compare( expected, actual ) ) {\n\t\t\t\treturn ' checked=\"checked\"';\n\t\t\t}\n\t\t\treturn '';\n\t\t},\n\n\t\t/**\n\t\t * Recursively clone an object via _.clone()\n\t\t * @param obj obj object to clone\n\t\t * @return obj\n\t\t * @since 3.17.7\n\t\t * @version 3.17.7\n\t\t */\n\t\tdeepClone: function( obj ) {\n\n\t\t\tvar clone = _.clone( obj );\n\n\t\t\t_.each( clone, function( val, key ) {\n\t\t\t\tif ( ! _.isFunction( val ) && _.isObject( val ) ) {\n\t\t\t\t\tclone[ key ] = _.deepClone( val );\n\t\t\t\t};\n\t\t\t} );\n\n\t\t\treturn clone;\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if two values are equal and output seleted attribute if they are\n\t\t * Useful for templating select elements\n\t\t * Like WP Core PHP selected() but in JS\n\t\t * @param mixed expected expected element value\n\t\t * @param mixed actual actual element value\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.2\n\t\t */\n\t\tselected: function( expected, actual ) {\n\t\t\tif ( value_compare( expected, actual ) ) {\n\t\t\t\treturn ' selected=\"selected\"';\n\t\t\t}\n\t\t\treturn '';\n\t\t},\n\n\t\t/**\n\t\t * Generic function for stripping HTML tags from a string\n\t\t * @param string content raw string\n\t\t * @param array allowed_tags array of allowed HTML tags\n\t\t * @return string\n\t\t * @since 3.17.8\n\t\t * @version 3.17.8\n\t\t */\n\t\tstripFormatting: function( content, allowed_tags ) {\n\n\t\t\tif ( ! allowed_tags ) {\n\t\t\t\tallowed_tags = [ 'b', 'i', 'u', 'strong', 'em' ];\n\t\t\t}\n\n\t\t\tvar $html = $( '' + content + '
' );\n\n\t\t\t$html.find( '*' ).not( allowed_tags.join( ',' ) ).each( function( ) {\n\n\t\t\t\t$( this ).replaceWith( this.innerHTML );\n\n\t\t\t} );\n\n\t\t\treturn $html.html();\n\n\t\t},\n\n\t} );\n\n\tBackbone.pubSub = _.extend( {}, Backbone.Events );\n\n\t$( document ).trigger( 'llms-builder-pre-init' );\n\n\twindow.llms_builder.questions = window.llms_builder.construct.get_collection( 'QuestionTypes', window.llms_builder.questions );\n\n\tvar CourseModel = window.llms_builder.construct.get_model( 'Course', window.llms_builder.course );\n\twindow.llms_builder.CourseModel = CourseModel;\n\n\twindow.llms_builder.sync = new Sync( CourseModel, window.llms_builder.sync );\n\n\tvar Course = new CourseView( {\n\t\tmodel: CourseModel,\n\t} );\n\n\tvar Sidebar = new SidebarView( {\n\t\tCourseView: Course\n\t} );\n\n\t$( document ).trigger( 'llms-builder-init', {\n\t\tcourse: Course,\n\t\tsidebar: Sidebar,\n\t} );\n\n} );\n\ndefine(\"main\", function(){});\n\n"]}
\ No newline at end of file
+{"version":3,"sources":["../../../config-wrap-start-default.js","vendor/almond.js","underscore.js","backbone.js","jquery.js","vendor/backbone.collectionView.js","vendor/backbone.trackit.js","Models/Image.js","Models/_Relationships.js","Models/QuestionChoice.js","Collections/QuestionChoices.js","Models/QuestionType.js","Models/Question.js","Collections/Questions.js","Models/_Utilities.js","Schemas/Quiz.js","Models/Quiz.js","Schemas/Lesson.js","Models/Lesson.js","Collections/Lessons.js","Collections/QuestionTypes.js","Models/Section.js","Collections/Sections.js","Collections/loader.js","Models/Abstract.js","Models/Course.js","Models/loader.js","Views/_Detachable.js","Views/_Editable.js","Views/_Receivable.js","Views/_Shiftable.js","Views/_Subview.js","Views/_Trashable.js","Views/_loader.js","Controllers/Construct.js","Controllers/Debug.js","Controllers/Schemas.js","Controllers/Sync.js","Views/Lesson.js","Views/LessonList.js","Views/Section.js","Views/SectionList.js","Views/Course.js","Views/SettingsFields.js","Views/LessonEditor.js","Views/Popover.js","Views/PostSearch.js","Views/QuestionType.js","Views/QuestionBank.js","Views/QuestionChoice.js","Views/QuestionChoiceList.js","Views/Question.js","Views/QuestionList.js","Views/Quiz.js","Views/Assignment.js","Views/Editor.js","Views/Elements.js","Views/Utilities.js","Views/Sidebar.js","main.js"],"names":["$","requirejs","require","define","undef","hasProp","obj","prop","hasOwn","call","normalize","name","baseName","nameParts","nameSegment","mapValue","foundMap","lastIndex","foundI","foundStarMap","starI","i","j","part","normalizedBaseParts","baseParts","split","map","config","starMap","length","nodeIdCompat","jsSuffixRegExp","test","replace","charAt","slice","concat","splice","join","makeRequire","relName","forceSync","args","aps","arguments","push","req","apply","makeNormalize","makeLoad","depName","value","defined","callDep","waiting","defining","main","Error","splitPrefix","prefix","index","indexOf","substring","makeRelParts","makeConfig","makeMap","handlers","Object","prototype","hasOwnProperty","relParts","plugin","parts","relResourceName","f","n","pr","p","exports","e","module","id","uri","deps","callback","cjsModule","ret","usingExports","callbackType","load","undefined","alt","setTimeout","cfg","_defined","amd","jQuery","_","Backbone","root","factory","Zepto","this","_normalizeOptionDeclarations","optionDeclarations","normalizedOptionDeclarations","isArray","each","thisOptionDeclaration","thisOptionName","thisOptionRequired","thisOptionDefaultValue","isString","isObject","first","keys","isFunction","clone","required","isUndefined","defaultValue","mDefaultModelViewConstructor","View","kOptionsRequiringRerendering","kStylesForEmptyListCaption","background","border","box-shadow","CollectionView","extend","tagName","events","mousedown > li, tbody > tr > td","dblclick > li, tbody > tr > td","click","click ul.collection-view, table.collection-view","keydown","spawnMessages","focus","passMessages","*","initializationOptions","collection","modelView","modelViewOptions","itemTemplate","itemTemplateFunction","selectable","clickToSelect","selectableModelsFilter","visibleModelsFilter","sortableModelsFilter","selectMultiple","clickToToggle","processKeyEvents","sortable","sortableOptions","reuseModelViews","detachedRendering","emptyListCaption","initialize","options","ViewOptions","add","setOptions","Collection","_hasBeenRendered","_isBackboneCourierAvailable","Courier","$el","data","addClass","attr","selectedItems","_updateItemTemplate","_registerCollectionEvents","viewManager","ChildViewContainer","_onOptionsChanged","changedOptions","originalOptions","_this","rerender","changedOptionKey","newVal","oldVal","stopListening","setSelectedModel","by","setSelectedModels","removeAttr","_setupSortable","reapplyFilter","view","remove","contains","render","setOption","optionName","optionValue","optionHash","getSelectedModel","getSelectedModels","referenceBy","items","item","get","curLineNumber","_getVisibleItemEls","is","findByModel","newSelectedItems","silent","newSelectedCids","thisModel","cid","pluck","model","thisItemEl","oldSelectedModels","oldSelectedCids","_convertStringsToInts","_validateSelection","newSelectedModels","_containSameElements","_addSelectedClassToSelectedItems","spawn","selectedModels","trigger","updateDependentControls","newSelectedItem","getView","reference","itemElements","_saveSelection","modelViewContainerEl","_getContainerEl","oldViewManager","thisModelView","detach","empty","fragmentContainer","document","createDocumentFragment","findByModelCid","_createNewModelView","_getModelViewOptions","_insertAndRenderModelView","append","_showEmptyListCaptionIfAppropriate","_restoreSelection","forceRerenderOnNextSortEvent","_removeEmptyListCaption","emptyListString","$emptyListCaptionEl","$varEl","_isRenderedAsList","wrapAll","parent","css","find","parentElOrDocumentFragment","atIndex","thisModelViewWrapped","_wrapModelView","nodeType","appendChild","numberOfModelViewsCurrentlyInDOM","children","eq","before","hide","hideThisModelView","toggle","toggleClass","whichFilter","notVisible","_modelViewHasWrapperLI","closest","notSortable","notSelectable","_removeModelView","_validateSelectionAndRender","listenTo","_isRenderedAsTable","tbody","_getClickedItemId","theEvent","clickedItemId","clickedItemEl","currentTarget","clickedItem","isNumeric","parseInt","itemTemplateHtml","html","template","modelReferenceIds","models","intersection","filter","thisItemId","savedSelection","offset","oldItemsIdsWithSelectedClass","itemsIdsFromWhichSelectedClassNeedsToBeRemoved","without","removeClass","itemsIdsFromWhichSelectedClassNeedsToBeAdded","_reorderCollectionBasedOnHTML","thisModelCid","sort","comparator","_getModelViewConstructor","modelViewConstructor","newModelView","collectionListView","collectionView","modelViewWrapperEl","theArray","thisEl","thisElAsNumber","arrayA","arrayB","toLowerCase","_charCodes","upArrow","downArrow","axis","distance","forcePlaceholderSize","start","bind","_sortStart","change","_sortChange","stop","_sortStop","receive","_receive","over","_over","result","event","ui","modelBeingSorted","newIndex","senderListEl","sender","senderCollectionListView","modelReceived","at","_onKeydown","trap","currentOffset","which","_listItem_onMousedown","clickedModel","metaKeyPressed","ctrlKey","metaKey","thisMethod","shiftKey","firstSelectedItemIndex","thisItemModel","clickedItemIndex","shiftKeyRootSelectedItemIndex","minSelectedItemIndex","Math","min","maxSelectedItemIndex","max","thisIndex","selection","window","getSelection","sel","removeAllRanges","union","_listItem_onDoubleClick","_listBackground_onClick","target","setDefaultModelViewConstructor","theConstructor","optionsDeclarationsProperty","optionsThatWereChanged","optionsThatWereChangedPreviousValues","thisOptionProperties","oldValue","newValue","onOptionsChanged","getOptions","optionsNames","pick","Container","views","_views","_indexByModel","_indexByCustom","_updateLength","customIndex","viewCid","modelCid","findByCid","findByCustom","findByIndex","values","findIndexByCid","any","key","method","tail","size","methods","toArray","unsavedModels","updateUnsavedModels","isEmpty","_unsavedChanges","m","findWhere","getPrompt","fnName","prompt","rest","evaluateModelFn","fn","isBoolean","_unsavedConfig","History","navigate","wrap","oldNav","fragment","confirm","onbeforeunload","Model","unsaved","_trackingChanges","_originalAttrs","startTracking","unloadRouterPrompt","unloadWindowPrompt","_resetTracking","_triggerUnsavedChanges","stopTracking","restartTracking","resetAttributes","attributes","unsavedAttributes","attrs","val","changed","old","isEqual","set","oldSet","sync","oldSync","success","oldSuccess","textStatus","jqXHR","defaults","enabled","src","relationship_defaults","relationships","init_relationships","rels","get_relationships","set_parent","child_data","child_key","conditional","child","child_val","lookup","type","llms_builder","construct","get_model","class","get_collection","_maybe_set_parent_reference","child_model","get_child_props","props","get_parent","Image","Relationships","choice","uniqueId","choice_type","correct","marker","question_id","get_trash_id","is_selectable","get_choice_selectable","on","update_order","update_correct","count_correct","get_correct","siblings","question","self","get_choice_markers","choices","clarifications","default_choices","description","icon","image","keywords","placeholder","points","video","get_keywords","_get_choice_option","get_choice_type","get_min_choices","get_max_choices","get_multi_choices","option","Questions","QuestionChoices","QuestionType","questions","question_type","content","description_enabled","multi_choices","menu_order","parent_id","title","video_enabled","video_src","_expanded","_ensure_min_choices","delay","update_points","add_choice","pubSub","before_save","atts","sync_type","get_type_index","curr_type","get_type_iterator","get_qid","get_parent_question","is_in_group","get_parent_quiz","get_points","get_points_percentage","total","toFixed","update_parent","fields","get_edit_post_link","has_temp_id","admin_url","get_settings_fields","schema","schemas","isNumber","init_custom_schema","groups","group","flatten","field","attribute","customs","switch_attribute","attribute_prefix","default","LLMS","l10n","translate","toggleable","label","tip","Lesson","Question","Utilities","QuizSchema","lesson_id","status","allowed_attempts","limit_attempts","limit_time","passing_percent","random_answers","time_limit","show_correct_answer","_points","permalink","_show_settings","_questions_loaded","get_total_points","add_question","get_l10n_type","plural","load_questions","cb","Ajax","action","action_type","course_id","CourseModel","load_id","error","xhr","console","log","debug","res","condition","assignments","is_first_in_course","get_available_prereq_options","get_course","date_format","timepicker","datepicker","Quiz","LessonSchema","parents","quiz","order","parent_course","course","parent_section","edit_url","view_url","audio_embed","has_prerequisite","require_passing_grade","require_assignment_passing_grade","video_embed","free_lesson","assignment","assignment_enabled","quiz_enabled","_forceSync","maybe_init_assignments","parent_section_index","lesson_index_in_section","section","curr_sec_index","%1$d","%2$s","lesson","curr_les_index","add_quiz","%1$s","on_reorder","validate_prereqs","prerequisite","Lessons","lessons","_selected","add_lesson","get_next","circular","_get_sibling","get_prev","direction","sibling_index","last","QuestionTypes","Sections","sections","add_section","add_existing_lesson","get_selected_section","selected","Abstract","Course","QuestionChoice","Section","click a[href=\"#llms-detach-model\"]","detach_model","preventDefault","stopPropagation","msg","%s","media_lib","click .llms-add-image","click a[href=\"#llms-edit-slug\"]","click a[href=\"#llms-remove-image\"]","change .llms-editable-select select","change .llms-switch input[type=\"checkbox\"]","change .llms-editable-radio input","focusin .llms-input","focusout .llms-input","keydown .llms-input","input .llms-input[type=\"number\"]","paste .llms-input[data-formatting]","get_allowed_tags","tag","trim","get_content","hasClass","stripFormatting","text","has_changed","is_valid","_validate_url","slug","beforeSend","Spinner","r","init_datepickers","datetimepicker","format","onClose","current_time","$input","blur","init_formatting_els","formatting","ed","Quill","modules","toolbar","keyboard","bindings","tab","handler","range","context","13","theme","delta","oldDelta","source","init_selects","llmsSelect2","width","on_blur","save_edits","revert_edits","on_focus","on_paste","originalEvent","clipboardData","getData","execCommand","on_select","multi","$selected","on_radio_select","on_keydown","keyCode","shift","open_media_lib","uploader","param","wp","media","frames","file_frame","button","multiple","url","attachment","state","toJSON","sizes","open","remove_image","toggle_switch","init_editor","settings","editor","getDefaultSettings","mediaButtons","tinymce","toolbar1","toolbar2","setup","on_editor_ready","make_slug_editable","$btn","$link","prevAll","prev","full_url","short_url","color","pointer-events","text-decoration","show","$ed","$parent","$label","prependTo","getContent","str","a","createElement","href","host","location","helper","maybe_hide_shiftable_buttons","old_index","new_index","shift_down","shift_up","subscriptions","get_subview","events_subscribe","func","events_unsubscribe","off","remove_subview","instance","remove_subviews","undelegateEvents","render_subviews","view_data","render_subview","set_state","click a[href=\"#llms-trash-model\"]","trash_model","Detachable","Editable","Receivable","Shiftable","Subview","Trashable","Collections","Models","Views","extend_view","classname","register_collection","register_model","disable","enable","custom_schemas","custom","model_type","add_error_msg","err","message","check_for_changes","changes","get_unsaved_changes","has_unsaved_changes","saving","do_ajax_save","JSON","stringify","responseText","process_removals","process_updates","get_changed_attributes","exclude","omit","get_changes_to_object","object","changed_atts","model_changes","maybe_restart_tracking","unset","removals","detached","trash","trashed","coll","errors","info","process_object_updates","main_data","orig_id","updates","autosave","check_interval","check_interval_ms","save_now","heartbeat","connectNow","set_check_interval","ms","clearInterval","setInterval","statusText","data-id","data-section-id","className","click .edit-lesson","click .edit-quiz","click .edit-assignment","click .section-prev","click .section-next","click .shift-up--lesson","click .shift-down--lesson","open_assignment_editor","open_lesson_editor","open_quiz_editor","section_next","_move_to_section","section_prev","to_section","from_coll","LessonView","connectWith","cursor","handle","sortable_start","sortable_stop","LessonListView","click .expand","click .collapse","click .shift-up--section","click .shift-down--section","mouseenter .llms-lessons","toggle_expanded","lessonListView","on_lesson_add","dragTimeout","expand","collapse","el","active_lesson_change","maybe_hide_trash_button","current","previous","update","on_mouseenter","SectionView","mousedown > li.llms-section > .llms-builder-header .llms-headline","click ul.collection-view","SectionListView","sectionListView","active_section_change","on_section_add","on_section_toggle","expand_section","click .llms-settings-group-toggle","get_editor_fields","is_editor_field","get_groups","is_group_hidden","group_id","localStorage","getItem","get_switch_attribute","has_switch","is_default_field","is_switch_condition_met","switch_on","render_editor","render_select_options","option_html","setup_field","orig_field","field_index","classes","input_type","tip_position","orig_settings","switch_off","deepClone","has_images","should_rerender_on_toggle","field_type","toggle_group","$group","setItem","removeItem","SettingsFields","change_events","placement","style","animation","closeable","backdrop","onShow","onHide","container","webuiPopover","select2:select","post_type","searching_message","add_post","params","ajax","dataType","ajaxurl","term","page","_ajax_nonce","wp_ajax_data","nonce","dropdownParent","escapeMarkup","markup","templateResult","render_result","$html","loading","$side","$main","click .llms-add-question","QuestionView","change input[name=\"correct\"]","click .llms-action-icon[href=\"#llms-add-choice\"]","click .llms-action-icon[href=\"#llms-del-choice\"]","maybe_disable_buttons","del_choice","toggle_correct","ChoiceView","ChoiceListView","click .clone--question","click .delete--question","click .expand--question","click .collapse--question","change input[name=\"question_points\"]","render_points_percentage","multi_choices_toggle","choiceListView","questionListView","get_question_list","_get_question_clone","choice_clone","delete","selector","QuizModel","Popover","PostSearch","QuestionBank","QuestionList","bank","list","click #llms-existing-quiz","click #llms-new-quiz","click #llms-show-question-bank","click .bulk-toggle","render_points","on_trashed","last_group","alert","$questions","animate","scrollTop","bulk_toggle","expanded","add_new_quiz","add_existing_quiz","post_search_popover","add_existing_quiz_click","dismissible","once","show_tools","pop","addon_events","is_addon_available","get_view_events","click #llms-existing-assignment","click #llms-new-assignment","add_new_assignment","get_assignment","show_ad_popover","add_existing_assignment","add_existing_assignment_click","h3","btn","ad_popover","LessonEditor","Assignment","click .llms-editor-nav a[href=\"#llms-editor-close\"]","click .llms-editor-nav a:not([href=\"#llms-editor-close\"])","SidebarView","close_editor","switch_tab","LessonSearch","click #llms-new-section","click #llms-new-lesson","click #llms-existing-lesson","CourseView","draggable","appendTo","cancel","connectToSortable","add_new_section","add_new_lesson","$els","click #llms-collapse-all","click #llms-expand-all","collapse_all","expand_all","Editor","Elements","elements","utilities","click #llms-save-button","click #llms-exit-button","click .llms-builder-error","changes_made","heartbeat_send","heartbeat_tick","on_lesson_select","on_editor_close","$saveButton","add_error","$err","prepend","clear_errors","exit_now","data-status","disabled","txt","is_editor_active","lesson_model","CV","TrackIt","Construct","Debug","Schemas","Sync","value_compare","expected","actual","mixin","checked","allowed_tags","not","replaceWith","innerHTML","Events","Sidebar","sidebar"],"mappings":"CAAA,SAAAA,GCQA,GAAAC,GAAAC,EAAAC,GACA,SAAAC,GAUA,QAAAC,GAAAC,EAAAC,GACA,MAAAC,GAAAC,KAAAH,EAAAC,GAWA,QAAAG,GAAAC,EAAAC,GACA,GAAAC,GAAAC,EAAAC,EAAAC,EAAAC,EACAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EACAC,EAAAb,GAAAA,EAAAc,MAAA,KACAC,EAAAC,EAAAD,IACAE,EAAAF,GAAAA,EAAA,QAGA,IAAAhB,EAAA,CAwBA,IAvBAA,EAAAA,EAAAe,MAAA,KACAT,EAAAN,EAAAmB,OAAA,EAMAF,EAAAG,cAAAC,EAAAC,KAAAtB,EAAAM,MACAN,EAAAM,GAAAN,EAAAM,GAAAiB,QAAAF,EAAA,KAIA,MAAArB,EAAA,GAAAwB,OAAA,IAAAV,IAMAD,EAAAC,EAAAW,MAAA,EAAAX,EAAAK,OAAA,GACAnB,EAAAa,EAAAa,OAAA1B,IAIAU,EAAA,EAAAA,EAAAV,EAAAmB,OAAAT,IAEA,GAAA,OADAE,EAAAZ,EAAAU,IAEAV,EAAA2B,OAAAjB,EAAA,GACAA,GAAA,MACA,IAAA,OAAAE,EAAA,CAMA,GAAA,IAAAF,GAAA,IAAAA,GAAA,OAAAV,EAAA,IAAA,OAAAA,EAAAU,EAAA,GACA,QACAA,GAAA,IACAV,EAAA2B,OAAAjB,EAAA,EAAA,GACAA,GAAA,GAMAV,EAAAA,EAAA4B,KAAA,KAIA,IAAAd,GAAAI,IAAAF,EAAA,CAGA,IAFAd,EAAAF,EAAAe,MAAA,KAEAL,EAAAR,EAAAiB,OAAAT,EAAA,EAAAA,GAAA,EAAA,CAGA,GAFAP,EAAAD,EAAAuB,MAAA,EAAAf,GAAAkB,KAAA,KAEAd,EAGA,IAAAH,EAAAG,EAAAK,OAAAR,EAAA,EAAAA,GAAA,EAKA,IAJAP,EAAAY,EAAAF,EAAAW,MAAA,EAAAd,GAAAiB,KAAA,SAKAxB,EAAAA,EAAAD,IACA,CAEAE,EAAAD,EACAG,EAAAG,CACA,OAMA,GAAAL,EACA,OAMAG,GAAAU,GAAAA,EAAAf,KACAK,EAAAU,EAAAf,GACAM,EAAAC,IAIAL,GAAAG,IACAH,EAAAG,EACAD,EAAAE,GAGAJ,IACAH,EAAAyB,OAAA,EAAApB,EAAAF,GACAL,EAAAE,EAAA0B,KAAA,MAIA,MAAA5B,GAGA,QAAA6B,GAAAC,EAAAC,GACA,MAAA,YAIA,GAAAC,GAAAC,EAAAnC,KAAAoC,UAAA,EAQA,OAHA,gBAAAF,GAAA,IAAA,IAAAA,EAAAb,QACAa,EAAAG,KAAA,MAEAC,EAAAC,MAAA5C,EAAAuC,EAAAN,QAAAI,EAAAC,MAIA,QAAAO,GAAAR,GACA,MAAA,UAAA9B,GACA,MAAAD,GAAAC,EAAA8B,IAIA,QAAAS,GAAAC,GACA,MAAA,UAAAC,GACAC,EAAAF,GAAAC,GAIA,QAAAE,GAAA3C,GACA,GAAAN,EAAAkD,EAAA5C,GAAA,CACA,GAAAgC,GAAAY,EAAA5C,SACA4C,GAAA5C,GACA6C,EAAA7C,IAAA,EACA8C,EAAAT,MAAA5C,EAAAuC,GAGA,IAAAtC,EAAAgD,EAAA1C,KAAAN,EAAAmD,EAAA7C,GACA,KAAA,IAAA+C,OAAA,MAAA/C,EAEA,OAAA0C,GAAA1C,GAMA,QAAAgD,GAAAhD,GACA,GAAAiD,GACAC,EAAAlD,EAAAA,EAAAmD,QAAA,MAAA,CAKA,OAJAD,IAAA,IACAD,EAAAjD,EAAAoD,UAAA,EAAAF,GACAlD,EAAAA,EAAAoD,UAAAF,EAAA,EAAAlD,EAAAmB,UAEA8B,EAAAjD,GAKA,QAAAqD,GAAAvB,GACA,MAAAA,GAAAkB,EAAAlB,MA+CA,QAAAwB,GAAAtD,GACA,MAAA,YACA,MAAAiB,IAAAA,EAAAA,QAAAA,EAAAA,OAAAjB,QA/OA,GAAA8C,GAAAV,EAAAmB,EAAAC,EACAd,KACAE,KACA3B,KACA4B,KACAhD,EAAA4D,OAAAC,UAAAC,eACA1B,KAAAR,MACAJ,EAAA,OA+LAkC,GAAA,SAAAvD,EAAA4D,GACA,GAAAC,GACAC,EAAAd,EAAAhD,GACAiD,EAAAa,EAAA,GACAC,EAAAH,EAAA,EA2BA,OAzBA5D,GAAA8D,EAAA,GAEAb,IACAA,EAAAlD,EAAAkD,EAAAc,GACAF,EAAAlB,EAAAM,IAIAA,EAEAjD,EADA6D,GAAAA,EAAA9D,UACA8D,EAAA9D,UAAAC,EAAAsC,EAAAyB,IAEAhE,EAAAC,EAAA+D,IAGA/D,EAAAD,EAAAC,EAAA+D,GACAD,EAAAd,EAAAhD,GACAiD,EAAAa,EAAA,GACA9D,EAAA8D,EAAA,GACAb,IACAY,EAAAlB,EAAAM,MAMAe,EAAAf,EAAAA,EAAA,IAAAjD,EAAAA,EACAiE,EAAAjE,EACAkE,GAAAjB,EACAkB,EAAAN,IAUAL,GACAjE,QAAA,SAAAS,GACA,MAAA6B,GAAA7B,IAEAoE,QAAA,SAAApE,GACA,GAAAqE,GAAA3B,EAAA1C,EACA,YAAA,KAAAqE,EACAA,EAEA3B,EAAA1C,OAGAsE,OAAA,SAAAtE,GACA,OACAuE,GAAAvE,EACAwE,IAAA,GACAJ,QAAA1B,EAAA1C,GACAiB,OAAAqC,EAAAtD,MAKA8C,EAAA,SAAA9C,EAAAyE,EAAAC,EAAA5C,GACA,GAAA6C,GAAAnC,EAAAoC,EAAA5D,EAAAN,EAAAkD,EAGAiB,EAFA7C,KACA8C,QAAAJ,EAQA,IAJA5C,EAAAA,GAAA9B,EACA4D,EAAAP,EAAAvB,GAGA,cAAAgD,GAAA,aAAAA,EAAA,CAKA,IADAL,GAAAA,EAAAtD,QAAAuD,EAAAvD,QAAA,UAAA,UAAA,UAAAsD,EACA/D,EAAA,EAAAA,EAAA+D,EAAAtD,OAAAT,GAAA,EAKA,GAJAM,EAAAuC,EAAAkB,EAAA/D,GAAAkD,GAIA,aAHApB,EAAAxB,EAAAgD,GAIAhC,EAAAtB,GAAA8C,EAAAjE,QAAAS,OACA,IAAA,YAAAwC,EAEAR,EAAAtB,GAAA8C,EAAAY,QAAApE,GACA6E,GAAA,MACA,IAAA,WAAArC,EAEAmC,EAAA3C,EAAAtB,GAAA8C,EAAAc,OAAAtE,OACA,IAAAN,EAAAgD,EAAAF,IACA9C,EAAAkD,EAAAJ,IACA9C,EAAAmD,EAAAL,GACAR,EAAAtB,GAAAiC,EAAAH,OACA,CAAA,IAAAxB,EAAAmD,EAIA,KAAA,IAAApB,OAAA/C,EAAA,YAAAwC,EAHAxB,GAAAmD,EAAAY,KAAA/D,EAAAiD,EAAApC,EAAAC,GAAA,GAAAS,EAAAC,OACAR,EAAAtB,GAAAgC,EAAAF,GAMAoC,EAAAF,EAAAA,EAAArC,MAAAK,EAAA1C,GAAAgC,OAAAgD,GAEAhF,IAIA2E,GAAAA,EAAAP,UAAA3E,GACAkF,EAAAP,UAAA1B,EAAA1C,GACA0C,EAAA1C,GAAA2E,EAAAP,QACAQ,IAAAnF,GAAAoF,IAEAnC,EAAA1C,GAAA4E,QAGA5E,KAGA0C,EAAA1C,GAAA0E,IAIApF,EAAAC,EAAA6C,EAAA,SAAAqC,EAAAC,EAAA5C,EAAAC,EAAAkD,GACA,GAAA,gBAAAR,GACA,MAAAjB,GAAAiB,GAEAjB,EAAAiB,GAAAC,GAMA/B,EAAAY,EAAAkB,EAAApB,EAAAqB,IAAAV,EACA,KAAAS,EAAA9C,OAAA,CAMA,GAJAV,EAAAwD,EACAxD,EAAAwD,MACArC,EAAAnB,EAAAwD,KAAAxD,EAAAyD,WAEAA,EACA,MAGAA,GAAA/C,QAGA8C,EAAAC,EACAA,EAAA5C,EACAA,EAAA,MAEA2C,EAAAhF,EA6BA,MAxBAiF,GAAAA,GAAA,aAIA,kBAAA5C,KACAA,EAAAC,EACAA,EAAAkD,GAIAlD,EACAe,EAAArD,EAAAgF,EAAAC,EAAA5C,GAQAoD,WAAA,WACApC,EAAArD,EAAAgF,EAAAC,EAAA5C,IACA,GAGAM,GAOAA,EAAAnB,OAAA,SAAAkE,GACA,MAAA/C,GAAA+C,IAMA7F,EAAA8F,SAAA1C,EAEAlD,EAAA,SAAAQ,EAAAyE,EAAAC,GACA,GAAA,gBAAA1E,GACA,KAAA,IAAA+C,OAAA,4DAIA0B,GAAA9C,SAIA+C,EAAAD,EACAA,MAGA/E,EAAAgD,EAAA1C,IAAAN,EAAAkD,EAAA5C,KACA4C,EAAA5C,IAAAA,EAAAyE,EAAAC,KAIAlF,EAAA6F,KACAC,QAAA,MAIA9F,EAAA,gBAAA,cC7aAA,EAAA,gBAAA,WACA,MAAA+F,KCDA/F,EAAA,cAAA,WACA,MAAAgG,YCDAhG,EAAA,YAAA,WACA,MAAA8F,UCAA,SAAAG,EAAAC,GAEA,kBAAAlG,IAAAA,EAAA6F,IAEA7F,EAAA,kCAAA,aAAA,WAAA,UAAAkG,GACA,mBAAAtB,SAEAE,OAAAF,QAAAsB,EAAAnG,EAAA,cAAAA,EAAA,YAAAA,EAAA,YAAAF,GAGAqG,EAAAD,EAAAF,EAAAE,EAAAD,SAAAC,EAAAH,QAAAG,EAAAE,OAAAF,EAAApG,IAEAuG,KAAA,SAAAL,EAAAC,EAAAnG,GAwoCA,QAAAwG,GAAAC,GAIA,GAAAC,KAEA,KAAAR,EAAAS,QAAAF,GAAA,KAAA,IAAA/C,OAAA,wCA6BA,OA3BAwC,GAAAU,KAAAH,EAAA,SAAAI,GACA,GAAAC,GAAAC,EAAAC,CAKA,IAHAD,GAAA,EACAC,MAAArB,GAEAO,EAAAe,SAAAJ,GACAC,EAAAD,MACA,CAAA,IAAAX,EAAAgB,SAAAL,GAOA,KAAA,IAAAnD,OAAA,sFANAoD,GAAAZ,EAAAiB,MAAAjB,EAAAkB,KAAAP,IAEAG,EADAd,EAAAmB,WAAAR,EAAAC,IACAD,EAAAC,GAEAZ,EAAAoB,MAAAT,EAAAC,IAIA,MAAAA,EAAAA,EAAAhF,OAAA,KACAiF,GAAA,EACAD,EAAAA,EAAA1E,MAAA,EAAA0E,EAAAhF,OAAA,IAGA4E,EAAAI,GAAAJ,EAAAI,OACAJ,EAAAI,GAAAS,SAAAR,EACAb,EAAAsB,YAAAR,KAAAN,EAAAI,GAAAW,aAAAT,KAGAN,EA1qCA,GAAAgB,GAAAvB,EAAAwB,KAIAC,GAAA,aAAA,YAAA,mBAAA,eAAA,uBAAA,qBAEAC,GACAC,WAAA,cACAC,OAAA,OACAC,aAAA,OA60CA,OA10CA7B,GAAA8B,eAAA9B,EAAAwB,KAAAO,QAEAC,QAAA,KAEAC,QACAC,kCAAA,wBACAC,iCAAA,0BACAC,MAAA,0BACAC,kDAAA,0BACAC,QAAA,cAIAC,eACAC,MAAA,SAIAC,cAAAC,IAAA,KAGAC,wBACAC,WAAA,OACAC,UAAA,OACAC,sBACAC,aAAA,OACAC,qBAAA,OACAC,YAAA,IACAC,eAAA,IACAC,uBAAA,OACAC,oBAAA,OACAC,qBAAA,OACAC,gBAAA,IACAC,eAAA,IACAC,kBAAA,IACAC,UAAA,IACAC,gBAAA,OACAC,iBAAA,IACAC,mBAAA,IACAC,iBAAA,OAGAC,WAAA,SAAAC,GACA/D,EAAAgE,YAAAC,IAAA7D,KAAA,yBACAA,KAAA8D,WAAAH,GAEA3D,KAAAwC,aAAAxC,KAAAwC,WAAA,GAAA5C,GAAAmE,YAEA/D,KAAAgE,kBAAA,EAEAhE,KAAAiE,+BACArE,EAAAsE,QAAAL,IAAA7D,MAGAA,KAAAmE,IAAAC,KAAA,OAAApE,MACAA,KAAAmE,IAAAE,SAAA,mCACArE,KAAA6C,YAAA7C,KAAAmE,IAAAE,SAAA,cAEArE,KAAA6C,YAAA7C,KAAAoD,kBACApD,KAAAmE,IAAAG,KAAA,WAAA,GAEAtE,KAAAuE,iBAEAvE,KAAAwE,sBAEAxE,KAAAwC,YACAxC,KAAAyE,4BAEAzE,KAAA0E,YAAA,GAAAC,qBAGAC,kBAAA,SAAAC,EAAAC,GACA,GAAAC,GAAA/E,KACAgF,GAAA,CAEArF,GAAAU,KAAAV,EAAAkB,KAAAgE,GAAA,SAAAI,GACA,GAAAC,GAAAL,EAAAI,GACAE,EAAAL,EAAAG,EACA,QAAAA,GACA,IAAA,aACAC,IAAAC,IACAJ,EAAAK,cAAAD,GACAJ,EAAAN,4BAEA,MACA,KAAA,kBACAS,GAAAH,EAAAR,cAAAhJ,OAAA,GACAwJ,EAAAM,iBAAA1F,EAAAiB,MAAAmE,EAAAR,gBAAAe,GAAA,OACA,MACA,KAAA,cACAJ,GAAAH,EAAAR,cAAAhJ,OAAA,GACAwJ,EAAAQ,sBAEAL,GAAAlF,KAAAoD,iBAAA2B,EAAAZ,IAAAG,KAAA,WAAA,GACAS,EAAAZ,IAAAqB,WAAA,WAAA,EACA,MACA,KAAA,WACAX,EAAAxB,SAAA0B,EAAAU,iBAAAV,EAAAZ,IAAAd,SAAA,UACA,MACA,KAAA,yBACA0B,EAAAW,cAAA,mBACA,MACA,KAAA,kBACAX,EAAAZ,IAAAd,SAAA,WACA0B,EAAAU,gBACA,MACA,KAAA,uBACAV,EAAAW,cAAA,iBACA,MACA,KAAA,sBACAX,EAAAW,cAAA,gBACA,MACA,KAAA,eACAX,EAAAP,qBACA,MACA,KAAA,mBACAU,GAAAlF,KAAA6C,WAAAkC,EAAAZ,IAAAG,KAAA,WAAA,GACAS,EAAAZ,IAAAqB,WAAA,WAAA,EACA,MACA,KAAA,YAEAT,EAAAL,YAAArE,KAAA,SAAAsF,GACAZ,EAAAL,YAAAkB,OAAAD,GAEAA,EAAAC,WAIAjG,EAAAkG,SAAAxE,EAAA4D,KAAAD,GAAA,KAGAhF,KAAAgE,kBAAAgB,GACAhF,KAAA8F,UAIAC,UAAA,SAAAC,EAAAC,GACA,GAAAC,KACAA,GAAAF,GAAAC,EACAjG,KAAA8D,WAAAoC,IAGAC,iBAAA,SAAAxC,GACA,MAAA3D,MAAAuE,cAAAhJ,OAAAoE,EAAAiB,MAAAZ,KAAAoG,kBAAAzC,IAAA,MAGAyC,kBAAA,SAAAzC,GACA,GAAAoB,GAAA/E,IAEA2D,GAAAhE,EAAAgC,WACA2D,GAhKA,SAiKA3B,EAEA,IAAA0C,GAAA1C,EAAA2B,GACAgB,IAEA,QAAAD,GACA,IAAA,KACA1G,EAAAU,KAAAL,KAAAuE,cAAA,SAAAgC,GACAD,EAAA/J,KAAAwI,EAAAvC,WAAAgE,IAAAD,GAAA5H,KAEA,MACA,KAAA,MACA2H,EAAAA,EAAAxK,OAAAkE,KAAAuE,cACA,MACA,KAAA,SACA,GAAAkC,GAAA,CAEAzG,MAAA0G,qBAEArG,KAAA,WACA5G,EAAAuG,MACA2G,GAAA,cACAL,EAAA/J,KAAAkK,GACAA,KAEA,MACA,KAAA,QACA9G,EAAAU,KAAAL,KAAAuE,cAAA,SAAAgC,GACAD,EAAA/J,KAAAwI,EAAAvC,WAAAgE,IAAAD,KAEA,MACA,KAAA,OACA5G,EAAAU,KAAAL,KAAAuE,cAAA,SAAAgC,GACAD,EAAA/J,KAAAwI,EAAAL,YAAAkC,YAAA7B,EAAAvC,WAAAgE,IAAAD,MAEA,MACA,SACA,KAAA,IAAApJ,OAAA,+BAAAkJ,GAIA,MAAAC,IAIAf,kBAAA,SAAAsB,EAAAlD,GACA,IAAAhE,EAAAS,QAAAyG,GAAA,KAAA,yBACA,IAAA7G,KAAA6C,cAAAgE,EAAAtL,OAAA,GAAA,CAEAoI,EAAAhE,EAAAgC,WACAmF,QAAA,EACAxB,GApNA,SAqNA3B,EAEA,IAAA0C,GAAA1C,EAAA2B,GACAyB,IAEA,QAAAV,GACA,IAAA,MACAU,EAAAF,CACA,MACA,KAAA,KACA7G,KAAAwC,WAAAnC,KAAA,SAAA2G,GACArH,EAAAkG,SAAAgB,EAAAG,EAAArI,KAAAoI,EAAAxK,KAAAyK,EAAAC,MAEA,MACA,KAAA,QACAF,EAAApH,EAAAuH,MAAAL,EAAA,MACA,MACA,KAAA,OACAlH,EAAAU,KAAAwG,EAAA,SAAAN,GACAQ,EAAAxK,KAAAgK,EAAAY,MAAAF,MAEA,MACA,KAAA,SACA,GAAAR,GAAA,CAGAzG,MAAA0G,qBACArG,KAAA,WACA,GAAA+G,GAAA3N,EAAAuG,KACAL,GAAAkG,SAAAgB,EAAAJ,IACAM,EAAAxK,KAAA6K,EAAA9C,KAAA,mBACAmC,KAEA,MACA,SACA,KAAA,IAAAtJ,OAAA,+BAAAkJ,GAIA,GAAAgB,GAAArH,KAAAoG,oBACAkB,EAAA3H,EAAAoB,MAAAf,KAAAuE,cAEAvE,MAAAuE,cAAAvE,KAAAuH,sBAAAR,GACA/G,KAAAwH,oBAEA,IAAAC,GAAAzH,KAAAoG,mBAEApG,MAAA0H,qBAAAJ,EAAAtH,KAAAuE,iBAEAvE,KAAA2H,iCAAAL,GAEA3D,EAAAmD,SAEA9G,KAAAiE,8BACAjE,KAAA4H,MAAA,oBACAC,eAAAJ,EACAJ,kBAAAA,IAEArH,KAAA8H,QAAA,mBAAAL,EAAAJ,IAGArH,KAAA+H,6BAIA1C,iBAAA,SAAA2C,EAAArE,GACAqE,GAAA,IAAAA,EAGAhI,KAAAuF,mBAAAyC,GAAArE,GAFA3D,KAAAuF,qBAAA5B,IAKAsE,QAAA,SAAAC,EAAAvE,GAKA,OAJAA,EAAAhE,EAAAgC,WACA2D,GA/RA,SAgSA3B,GAEAA,EAAA2B,IACA,IAAA,KACA,IAAA,MACA,GAAA6B,GAAAnH,KAAAwC,WAAAgE,IAAA0B,IAAA,IACA,OAAAf,IAAAnH,KAAA0E,YAAAkC,YAAAO,EAEA,KAAA,SACA,GAAAgB,GAAAnI,KAAA0G,oBACA,OAAAjN,GAAA0O,EAAA3B,IAAA0B,GAEA,KAAA,QACA,MAAAlI,MAAA0E,YAAAkC,YAAAsB,EAEA,SACA,KAAA,IAAA/K,OAAA,+BAAAkJ,eAKAP,OAAA,WAGA9F,KAAAgE,kBAAA,EAEAhE,KAAA6C,YAAA7C,KAAAoI,gBAEA,IAAAC,EAIAA,GAAArI,KAAAsI,iBAEA,IAAAC,GAAAvI,KAAA0E,WACA1E,MAAA0E,YAAA,GAAAC,oBAMA4D,EAAAlI,KAAA,SAAAmI,GAGAxI,KAAAuD,iBAAAvD,KAAAwC,WAAAgE,IAAAgC,EAAArB,MAAAF,KACAuB,EAAArE,IAAAsE,SACAD,EAAA5C,UACA5F,MAEAqI,EAAAK,OACA,IAAAC,EAEA3I,MAAAwD,oBACAmF,EAAAC,SAAAC,0BAEA7I,KAAAwC,WAAAnC,KAAA,SAAA2G,GACA,GAAAwB,GAAAD,EAAAO,eAAA9B,EAAAC,IACAjH,MAAAuD,kBAAA5D,EAAAsB,YAAAuH,KAGAA,EAAAxI,KAAA+I,oBAAA/B,EAAAhH,KAAAgJ,qBAAAhC,KAGAhH,KAAAiJ,0BAAAT,EAAAG,GAAAN,IACArI,MAEAA,KAAAwD,mBACA6E,EAAAa,OAAAP,GAEA3I,KAAAqD,UAAArD,KAAAyF,iBAEAzF,KAAAmJ,qCAEAnJ,KAAAiE,8BACAjE,KAAA4H,MAAA,UACA5H,KAAA8H,QAAA,UAEA9H,KAAA6C,aACA7C,KAAAoJ,oBACApJ,KAAA+H,2BAGA/H,KAAAqJ,8BAAA,GAGAF,mCAAA,WAGA,GAFAnJ,KAAAsJ,0BAEAtJ,KAAAyD,iBAAA,CAGA,GAAA,IAFAzD,KAAA0G,qBAEAnL,OAAA,CACA,GAAAgO,EAGAA,GADA5J,EAAAmB,WAAAd,KAAAyD,kBACAzD,KAAAyD,mBAEAzD,KAAAyD,gBAEA,IAAA+F,GACAC,EAAAhQ,EAAA,mCAAA8P,EAAA,SAIAC,GADAxJ,KAAA0J,oBACAD,EAAAE,QAAA,kCAAAC,SAAAC,IAAAvI,GAEAmI,EAAAE,QAAA,0DAAAC,SAAAA,SAAAC,IAAAvI,GAEAtB,KAAAsI,kBAAAY,OAAAM,MAKAF,wBAAA,WACAtJ,KAAA0J,oBACA1J,KAAAsI,kBAAAwB,KAAA,iCAAAF,SAAAhE,SAEA5F,KAAAsI,kBAAAwB,KAAA,sCAAAF,SAAAA,SAAAhE,UAKAqD,0BAAA,SAAAxG,EAAAsH,EAAAC,GACA,GAAAC,GAAAjK,KAAAkK,eAAAzH,EAEA,IAAA,KAAAsH,EAAAI,SACAJ,EAAAK,YAAAH,EAAAzD,IAAA,QACA,CACA,GAAA6D,GAAAN,EAAAO,WAAA/O,QACAoE,EAAAsB,YAAA+I,IAAAA,GAAA,GAAAA,EAAAK,EAEAN,EAAAO,WAAAC,GAAAP,GAAAQ,OAAAP,KAMAtK,EAAAsB,YAAA+I,IAAAA,EAAAK,IAAArK,KAAAqJ,8BAAA,GAEAU,EAAAb,OAAAe,IAIAjK,KAAA0E,YAAAb,IAAApB,IASA,IAHAA,EAAAqD,WAIAmE,EAAAQ,OACAR,EAAA5F,SAAA,eAGA,IAAAqG,IAAA,CACA/K,GAAAmB,WAAAd,KAAAgD,uBACA0H,GAAA1K,KAAAgD,oBAAAP,EAAA0E,QAEA,IAAA8C,EAAAK,WAAA/O,OACA0O,EAAAU,QAAAD,GACAjI,EAAA0B,IAAAwG,QAAAD,GAEAT,EAAAW,YAAA,cAAAF,IAEAA,GAAA1K,KAAAyD,kBAAAzD,KAAAsJ,2BAGAvB,wBAAA,WACA/H,KAAAiE,8BACAjE,KAAA4H,MAAA,2BACAC,eAAA7H,KAAAoG,sBAEApG,KAAA8H,QAAA,0BAAA9H,KAAAoG,sBAIAR,OAAA,WACA5F,KAAA0E,YAAArE,KAAA,SAAAsF,GACAA,EAAAC,WAGAhG,EAAAwB,KAAAtD,UAAA8H,OAAAnJ,MAAAuD,KAAA1D,YAGAoJ,cAAA,SAAAmF,GACA,GAAA9F,GAAA/E,IAEA,KAAAL,EAAAkG,UAAA,mBAAA,iBAAA,iBAAAgF,GACA,KAAA,IAAA1N,OAAA,wDAAA0N,EAGA,QAAAA,GACA,IAAA,gBACA9F,EAAAL,YAAArE,KAAA,SAAAmI,GACA,GAAAsC,GAAA/F,EAAA/B,sBAAA+B,EAAA/B,oBAAA9I,KAAA6K,EAAAyD,EAAArB,MAEAqB,GAAArE,IAAAyG,YAAA,cAAAE,GACA/F,EAAAgG,uBAAAvC,GACAA,EAAArE,IAAA6G,QAAA,MAAAJ,YAAA,cAAAE,GAAAH,QAAAG,GACAtC,EAAArE,IAAAwG,QAAAG,KAGA9K,KAAAmJ,oCACA,MACA,KAAA,iBACApE,EAAAZ,IAAAd,SAAA,WAEA0B,EAAAL,YAAArE,KAAA,SAAAmI,GACA,GAAAyC,GAAAlG,EAAA9B,uBAAA8B,EAAA9B,qBAAA/I,KAAA6K,EAAAyD,EAAArB,MAEAqB,GAAArE,IAAAyG,YAAA,eAAAK,GACAlG,EAAAgG,uBAAAvC,IACAA,EAAArE,IAAA6G,QAAA,MAAAJ,YAAA,eAAAK,KAIAlG,EAAAU,gBACA,MACA,KAAA,mBACAV,EAAAL,YAAArE,KAAA,SAAAmI,GACA,GAAA0C,GAAAnG,EAAAhC,yBAAAgC,EAAAhC,uBAAA7I,KAAA6K,EAAAyD,EAAArB,MAEAqB,GAAArE,IAAAyG,YAAA,iBAAAM,GACAnG,EAAAgG,uBAAAvC,IACAA,EAAArE,IAAA6G,QAAA,MAAAJ,YAAA,iBAAAM,KAIAnG,EAAAyC,uBAMA2D,iBAAA,SAAA1I,GACAzC,KAAA6C,YAAA7C,KAAAoI,iBAEApI,KAAA0E,YAAAkB,OAAAnD,GACAzC,KAAA+K,uBAAAtI,IAAAA,EAAA0B,IAAAyF,SAAAhE,SACAnD,EAAAmD,SAEA5F,KAAA6C,YAAA7C,KAAAoJ,oBAEApJ,KAAAmJ,sCAGAiC,4BAAA,WACApL,KAAAwH,qBACAxH,KAAA8F,UAGArB,0BAAA,WAEAzE,KAAAqL,SAAArL,KAAAwC,WAAA,MAAA,SAAA2E,GACA,GAAA1E,EACAzC,MAAAgE,mBACAvB,EAAAzC,KAAA+I,oBAAA5B,EAAAnH,KAAAgJ,qBAAA7B,IACAnH,KAAAiJ,0BAAAxG,EAAAzC,KAAAsI,kBAAAtI,KAAAwC,WAAAjF,QAAA4J,KAGAnH,KAAAiE,8BACAjE,KAAA4H,MAAA,MAAAnF,GACAzC,KAAA8H,QAAA,MAAArF,KAGAzC,KAAAqL,SAAArL,KAAAwC,WAAA,SAAA,SAAA2E,GACA,GAAA1E,EAEAzC,MAAAgE,mBACAvB,EAAAzC,KAAA0E,YAAAoE,eAAA3B,EAAAF,KACAjH,KAAAmL,iBAAA1I,IAGAzC,KAAAiE,8BACAjE,KAAA4H,MAAA,UACA5H,KAAA8H,QAAA,YAGA9H,KAAAqL,SAAArL,KAAAwC,WAAA,QAAA,WACAxC,KAAAgE,kBAAAhE,KAAA8F,SACA9F,KAAAiE,8BACAjE,KAAA4H,MAAA,SACA5H,KAAA8H,QAAA,WAaA9H,KAAAqL,SAAArL,KAAAwC,WAAA,OAAA,SAAAA,EAAAmB,GACA3D,KAAAgE,oBAAA,IAAAL,EAAAE,KAAA7D,KAAAqJ,+BAAArJ,KAAA8F,SACA9F,KAAAiE,8BACAjE,KAAA4H,MAAA,QACA5H,KAAA8H,QAAA,WAIAQ,gBAAA,WACA,GAAAtI,KAAAsL,qBAAA,CAEA,GAAAC,GAAAvL,KAAAmE,IAAA2F,KAAA,UACA,IAAAyB,EAAAhQ,OAAA,EACA,MAAAgQ,GAEA,MAAAvL,MAAAmE,KAGAqH,kBAAA,SAAAC,GACA,GAAAC,GAAA,KAIAC,EAAAlS,EAAAgS,EAAAG,cACA,IAAAD,EAAAX,QAAA,oBAAAxE,IAAA,KAAAxG,KAAAmE,IAAAqC,IAAA,GAAA,CAMA,GAAAqF,GAAAF,EAAAX,QAAA,mBAOA,OANAa,GAAAtQ,OAAA,IAEAmQ,EAAAG,EAAAvH,KAAA,kBACA7K,EAAAqS,UAAAJ,KAAAA,EAAAK,SAAAL,EAAA,MAGAA,IAGAlH,oBAAA,WACA,GAAAwH,EACA,IAAAhM,KAAA2C,aACA,CACA,GAAA,IAAAlJ,EAAAuG,KAAA2C,cAAApH,OACA,KAAA,+CAAAyE,KAAA2C,YAEAqJ,GAAAvS,EAAAuG,KAAA2C,cAAAsJ,WAGAD,GAAAhM,KAAAvG,EAAA,kBAAAwS,MAEAD,KAAAhM,KAAA4C,qBAAAjD,EAAAuM,SAAAF,KAIAxE,mBAAA,WAGA,GAAA2E,GAAAxM,EAAAuH,MAAAlH,KAAAwC,WAAA4J,OAAA,MACApM,MAAAuE,cAAA5E,EAAA0M,aAAAF,EAAAnM,KAAAuE,eAEA5E,EAAAmB,WAAAd,KAAA+C,0BAEA/C,KAAAuE,cAAA5E,EAAA2M,OAAAtM,KAAAuE,cAAA,SAAAgI,GACA,MAAAvM,MAAA+C,uBAAA7I,KAAA8F,KAAAA,KAAAwC,WAAAgE,IAAA+F,KACAvM,QAIAoI,eAAA,WAEA,IAAApI,KAAA6C,WAAA,KAAA,kDACA7C,MAAAwM,gBACAlG,MAAA3G,EAAAoB,MAAAf,KAAAuE,eACAkI,OAAAzM,KAAAmG,kBAAAb,GAAA,aAIA8D,kBAAA,WACA,IAAApJ,KAAAwM,eAAA,KAAA,+DAKAxM,MAAAuF,sBAAAuB,QAAA,IAEA9G,KAAAwM,eAAAlG,MAAA/K,OAAA,IAGAyE,KAAAuF,kBAAAvF,KAAAwM,eAAAlG,OAAAhB,GAAA,MAAAwB,QAAA,IAMA,IAAA9G,KAAAuE,cAAAhJ,QACAyE,KAAAqF,iBAAArF,KAAAwM,eAAAC,QAAAnH,GAAA,WAGAtF,KAAAuE,cAAAhJ,SAAAyE,KAAAwM,eAAAlG,MAAA/K,SAEAyE,KAAAiE,8BACAjE,KAAA4H,MAAA,oBACAC,eAAA7H,KAAAoG,oBACAiB,uBAEArH,KAAA8H,QAAA,mBAAA9H,KAAAoG,2BAKAuB,iCAAA,SAAA+E,GACA/M,EAAAsB,YAAAyL,KAAAA,KAKA,IAAAC,GAAAD,CACAC,GAAAhN,EAAAiN,QAAAD,EAAA3M,KAAAuE,eAEA5E,EAAAU,KAAAsM,EAAA,SAAAJ,GACAvM,KAAAsI,kBAAAwB,KAAA,mBAAAyC,EAAA,KAAAM,YAAA,YAEA7M,KAAA0J,qBACA1J,KAAAsI,kBAAAwB,KAAA,qBAAAyC,EAAA,SAAAM,YAAA,aAEA7M,KAEA,IAAA8M,GAAA9M,KAAAuE,aACAuI,GAAAnN,EAAAiN,QAAAE,EAAAJ,GAEA/M,EAAAU,KAAAyM,EAAA,SAAAP,GACAvM,KAAAsI,kBAAAwB,KAAA,mBAAAyC,EAAA,KAAAlI,SAAA,YAEArE,KAAA0J,qBACA1J,KAAAsI,kBAAAwB,KAAA,qBAAAyC,EAAA,SAAAlI,SAAA,aAEArE,OAGA+M,8BAAA,WAEA,GAAAhI,GAAA/E,IAEAA,MAAAsI,kBAAAgC,WAAAjK,KAAA,WACA,GAAA2M,GAAAvT,EAAAuG,MAAAsE,KAAA,iBAEA,IAAA0I,EACA,CAGA,GAAAhG,GAAAjC,EAAAvC,WAAAgE,IAAAwG,EACAhG,KAEAjC,EAAAvC,WAAAoD,OAAAoB,GAAAF,QAAA,IACA/B,EAAAvC,WAAAqB,IAAAmD,GAAAF,QAAA,EAAAmG,MAAAlI,EAAAvC,WAAA0K,iBAKAlN,KAAAiE,8BAAAjE,KAAA4H,MAAA,WACA5H,KAAAwC,WAAAsF,QAAA,WAEA9H,KAAAwC,WAAA0K,YAAAlN,KAAAwC,WAAAyK,QAIAE,yBAAA,SAAAnG,GACA,MAAAhH,MAAAyC,WAAAtB,GAGA6H,qBAAA,SAAAhC,GACA,GAAAtE,GAAA1C,KAAA0C,gBAGA,OAFA/C,GAAAmB,WAAA4B,KAAAA,EAAAA,EAAAsE,IAEArH,EAAAgC,QAAAwF,MAAAH,GAAAtE,IAGAqG,oBAAA,SAAA5B,EAAAzE,GACA,GAAA0K,GAAApN,KAAAmN,yBAAAhG,EACA,IAAAxH,EAAAsB,YAAAmM,GAAA,KAAA,gDAEA,IAAAC,GAAA,GAAA,GAAA3K,EAGA,OAFA2K,GAAAC,mBAAAD,EAAAE,eAAAvN,KAEAqN,GAGAnD,eAAA,SAAAzH,GACA,GAIA+K,GAJAzI,EAAA/E,IAkCA,OA5BAA,MAAAsL,sBAEAkC,EAAA/K,EAAA0B,IACA1B,EAAA0B,IAAAG,KAAA,iBAAA7B,EAAA0E,MAAAF,MAEAjH,KAAA0J,sBAGAjH,EAAA0B,IAAAwC,GAAA,OACA6G,EAAA/K,EAAA0B,IACA1B,EAAA0B,IAAAG,KAAA,iBAAA7B,EAAA0E,MAAAF,MAEAuG,EAAA/K,EAAA0B,IAAAwF,QAAA,uBAAAlH,EAAA0E,MAAAF,IAAA,WAAA2C,UAIAjK,EAAAmB,WAAAd,KAAAiD,wBACAjD,KAAAiD,qBAAA/I,KAAA6K,EAAAtC,EAAA0E,SACAqG,EAAAnJ,SAAA,gBACA5B,EAAA0B,IAAAE,SAAA,oBAGA1E,EAAAmB,WAAAd,KAAA+C,0BACA/C,KAAA+C,uBAAA7I,KAAA6K,EAAAtC,EAAA0E,SACAqG,EAAAnJ,SAAA,kBACA5B,EAAA0B,IAAAE,SAAA,oBAGAmJ,GAGAjG,sBAAA,SAAAkG,GACA,MAAA9N,GAAAvE,IAAAqS,EAAA,SAAAC,GACA,IAAA/N,EAAAe,SAAAgN,GAAA,MAAAA,EACA,IAAAC,GAAA5B,SAAA2B,EAAA,GACA,OAAAC,IAAAD,EAAAC,EAAAD,KAIAhG,qBAAA,SAAAkG,EAAAC,GACA,MAAAD,GAAArS,QAAAsS,EAAAtS,QACAoE,EAAA0M,aAAAuB,EAAAC,GAAAtS,QACAqS,EAAArS,QAGA+P,mBAAA,WACA,MAAA,UAAAtL,KAAAmE,IAAAnK,KAAA,WAAA8T,eAGApE,kBAAA,WACA,OAAA1J,KAAAsL,sBAGAP,uBAAA,SAAAtI,GACA,MAAAzC,MAAA0J,sBAAAjH,EAAA0B,IAAAwC,GAAA,OAQAD,mBAAA,WAIA,MAFA1G,MAAAsI,kBAAAwB,KAAA,yCAKAiE,YACAC,QAAA,GACAC,UAAA,IAGAhK,4BAAA,WACA,OAAAtE,EAAAsB,YAAArB,EAAAsE,UAGAuB,eAAA,WACA,GAAAnC,GAAA3D,EAAAgC,QACAuM,KAAA,IACAC,SAAA,GACAC,sBAAA,EACA9H,MAAAtG,KAAAsL,qBAAA,kCAAA,0BACA+C,MAAA1O,EAAA2O,KAAAtO,KAAAuO,WAAAvO,MACAwO,OAAA7O,EAAA2O,KAAAtO,KAAAyO,YAAAzO,MACA0O,KAAA/O,EAAA2O,KAAAtO,KAAA2O,UAAA3O,MACA4O,QAAAjP,EAAA2O,KAAAtO,KAAA6O,SAAA7O,MACA8O,KAAAnP,EAAA2O,KAAAtO,KAAA+O,MAAA/O,OACAL,EAAAqP,OAAAhP,KAAA,mBAEAA,MAAAmE,IAAAnE,KAAAmE,IAAAd,SAAAC,IAIAiL,WAAA,SAAAU,EAAAC,GACA,GAAAC,GAAAnP,KAAAwC,WAAAgE,IAAA0I,EAAA3I,KAAAjC,KAAA,kBACAtE,MAAAiE,8BACAjE,KAAA4H,MAAA,aAAAuH,iBAAAA,IACAnP,KAAA8H,QAAA,YAAAqH,IAGAV,YAAA,SAAAQ,EAAAC,GACA,GAAAC,GAAAnP,KAAAwC,WAAAgE,IAAA0I,EAAA3I,KAAAjC,KAAA,kBAEAtE,MAAAiE,8BACAjE,KAAA4H,MAAA,cAAAuH,iBAAAA,IACAnP,KAAA8H,QAAA,aAAAqH,IAGAR,UAAA,SAAAM,EAAAC,GACA,GAAAC,GAAAnP,KAAAwC,WAAAgE,IAAA0I,EAAA3I,KAAAjC,KAAA,mBACA+D,EAAArI,KAAAsI,kBACA8G,EAAA/G,EAAAiC,WAAAhN,MAAA4R,EAAA3I,OAEA,GAAA6I,GAAAD,GAGAnP,KAAAwC,WAAAoD,OAAAuJ,GAGAA,IAEAnP,KAAA+M,gCACA/M,KAAA+H,0BAEA/H,KAAAiE,8BACAjE,KAAA4H,MAAA,YAAAuH,iBAAAA,EAAAC,SAAAA,IACApP,KAAA8H,QAAA,WAAAqH,EAAAC,KAGAP,SAAA,SAAAI,EAAAC,GAEA,GAAAG,GAAAH,EAAAI,OACAC,EAAAF,EAAAjL,KAAA,OACA,IAAAmL,GAAAA,EAAA/M,WAAA,CAEA,GAAA4M,GAAApP,KAAAsI,kBAAAgC,WAAAhN,MAAA4R,EAAA3I,MACAiJ,EAAAD,EAAA/M,WAAAgE,IAAA0I,EAAA3I,KAAAjC,KAAA,kBACAiL,GAAA/M,WAAAoD,OAAA4J,GACAxP,KAAAwC,WAAAqB,IAAA2L,GAAAC,GAAAL,IACAI,EAAAhN,WAAAxC,KAAAwC,WACAxC,KAAAqF,iBAAAmK,KAGAT,MAAA,SAAAE,EAAAC,GAGAlP,KAAAsI,kBAAAwB,KAAA,4BAAAW,QAGAiF,WAAA,SAAAT,GACA,IAAAjP,KAAAoD,iBAAA,OAAA,CAEA,IAAAuM,IAAA,CAEA,IAAA,GAAA3P,KAAAoG,mBAAAd,GAAA,WAAA/J,OACA,CAIA,GAAAqU,GAAA5P,KAAAmG,kBAAAb,GAAA,UACA2J,GAAAY,QAAA7P,KAAA+N,WAAAC,SAAA,IAAA4B,GAEA5P,KAAAqF,iBAAAuK,EAAA,GAAAtK,GAAA,WACAqK,GAAA,GAEAV,EAAAY,QAAA7P,KAAA+N,WAAAE,WAAA2B,IAAA5P,KAAAwC,WAAAjH,OAAA,IAEAyE,KAAAqF,iBAAAuK,EAAA,GAAAtK,GAAA,WACAqK,GAAA,GAIA,OAAAA,GAGAG,sBAAA,SAAArE,GACA,GAAAC,GAAA1L,KAAAwL,kBAAAC,EAEA,IAAAC,EAAA,CACA,GAAAqE,GAAA/P,KAAAwC,WAAAgE,IAAAkF,EACA,IAAA1L,KAAAiE,8BAAA,CACA,GAAAG,IACA2L,aAAAA,EACAC,eAAAvE,EAAAwE,SAAAxE,EAAAyE,QAGAvQ,GAAAU,MAAA,iBAAA,kBAAA,4BAAA,SAAA8P,GACA/L,EAAA+L,GAAA,WACA1E,EAAA0E,QAIAnQ,KAAA4H,MAAA,QAAAxD,OAEApE,MAAA8H,QAAA,QAAAiI,GAGA,GAAA/P,KAAA6C,YAAA7C,KAAA8C,cAEA,GAAA4I,EACA,CAEA,GAAA/L,EAAAmB,WAAAd,KAAA+C,0BACA/C,KAAA+C,uBAAA7I,KAAA8F,KAAAA,KAAAwC,WAAAgE,IAAAkF,IAEA,MAIA,IAAA1L,KAAAkD,gBAAAuI,EAAA2E,SACA,CACA,GAAAC,IAAA,CAEArQ,MAAAuE,cAAAhJ,OAAA,GAEAyE,KAAAwC,WAAAsH,KAAA,SAAAwG,GAIA,MAHAD,KAGA1Q,EAAAkG,SAAA7F,KAAAuE,cAAA+L,EAAArJ,MACAjH,KAGA,IAAAuQ,IAAA,CACAvQ,MAAAwC,WAAAsH,KAAA,SAAAwG,GAIA,MAHAC,KAGAD,EAAArJ,KAAAyE,GACA1L,KAOA,KAAA,GALAwQ,IAAA,GAAAH,EAAAE,EAAAF,EACAI,EAAAC,KAAAC,IAAAJ,EAAAC,GACAI,EAAAF,KAAAG,IAAAN,EAAAC,GAEA3J,KACAiK,EAAAL,EAAAK,GAAAF,EAAAE,IACAjK,EAAAtK,KAAAyD,KAAAwC,WAAAiN,GAAAqB,GAAA7J,IAKA,IAJAjH,KAAAuF,kBAAAsB,GAAAvB,GAAA,QAIAsD,SAAAmI,WAAAnI,SAAAmI,UAAArI,MACAE,SAAAmI,UAAArI,YACA,IAAAsI,OAAAC,aAAA,CACA,GAAAC,GAAAF,OAAAC,cACAC,IAAAA,EAAAC,iBACAD,EAAAC,wBAGAnR,KAAAkD,gBAAAvD,EAAAkG,SAAA7F,KAAAuE,cAAAmH,MAAA1L,KAAAmD,eAAAsI,EAAAyE,SAAAzE,EAAAwE,SAEAtQ,EAAAkG,SAAA7F,KAAAuE,cAAAmH,GACA1L,KAAAuF,kBAAA5F,EAAAiN,QAAA5M,KAAAuE,cAAAmH,IAAApG,GAAA,QACAtF,KAAAuF,kBAAA5F,EAAAyR,MAAApR,KAAAuE,eAAAmH,KAAApG,GAAA,QAGAtF,KAAAuF,mBAAAmG,IAAApG,GAAA,YAIAtF,MAAAuF,uBAIA8L,wBAAA,SAAA5F,GAEA,GAAAC,GAAA1L,KAAAwL,kBAAAC,EAEA,IAAAC,EACA,CACA,GAAAqE,GAAA/P,KAAAwC,WAAAgE,IAAAkF,EAEA1L,MAAAiE,8BACAjE,KAAA4H,MAAA,eAAAmI,aAAAA,EAAAC,eAAAvE,EAAAwE,SAAAxE,EAAAyE,UACAlQ,KAAA8H,QAAA,cAAAiI,KAIAuB,wBAAA,SAAA7F,GACAzL,KAAA6C,YAAA7C,KAAA8C,eACArJ,EAAAgS,EAAA8F,QAAA5K,GAAA,qBAEA3G,KAAAuF,yBAIAiM,+BAAA,SAAAC,GACAtQ,EAAAsQ,KAWA7R,EAAAgE,eAEAhE,EAAAgE,YAAAC,IAAA,SAAA8B,EAAA+L,GACA/R,EAAAsB,YAAAyQ,KAAAA,EAAA,WAIA/L,EAAA7B,WAAA,SAAAH,GACA,GAAAoB,GAAA/E,KACA2R,KACAC,KAEA1R,EAAAP,EAAAqP,OAAAhP,KAAA0R,EAEA,KAAA/R,EAAAsB,YAAAf,GAAA,CACA,GAAAC,GAAAF,EAAAC,EAEAP,GAAAU,KAAAF,EAAA,SAAA0R,EAAAtR,GACA,GAAAC,GAAAqR,EAAA7Q,SACAP,EAAAoR,EAAA3Q,YAEA,IAAAV,EAAA,CAIA,KAAAmD,IAAAhE,EAAAkG,SAAAlG,EAAAkB,KAAA8C,GAAApD,KAAAZ,EAAAsB,YAAA8D,EAAAxE,IACA,KAAA,IAAApD,OAAA,oBAAAoD,EAAA,sBAEA,IAAAoD,GAAAhE,EAAAkG,SAAAlG,EAAAkB,KAAA8C,GAAApD,IAAAZ,EAAAsB,YAAA0C,EAAApD,IACA,KAAA,IAAApD,OAAA,oBAAAoD,EAAA,kCAIA,GAAAoD,GAAApD,IAAAoD,KAAAhE,EAAAsB,YAAA0C,EAAApD,IAAA,CACA,GAAAuR,GAAA/M,EAAAxE,GACAwR,EAAApO,EAAApD,EAGAZ,GAAAsB,YAAA6Q,IAAAA,IAAAC,IACAH,EAAArR,GAAAuR,EACAH,EAAApR,GAAAwR,GAEAhN,EAAAxE,GAAAwR,MAIApS,GAAAsB,YAAA8D,EAAAxE,MAEAwE,EAAAxE,GAAAE,KAKAd,EAAAkB,KAAA8Q,GAAApW,OAAA,IACAoE,EAAAmB,WAAAiE,EAAAiN,kBACAjN,EAAAiN,iBAAAL,EAAAC,GACAjS,EAAAmB,WAAAiE,EAAAH,oBACAG,EAAAH,kBAAA+M,EAAAC,KAIAjM,EAAAsM,WAAA,WACA,GAAA/R,GAAAP,EAAAqP,OAAAhP,KAAA0R,EACA,IAAA/R,EAAAsB,YAAAf,GAAA,QAEA,IAAAC,GAAAF,EAAAC,GACAgS,EAAAvS,EAAAkB,KAAAV,EAEA,OAAAR,GAAAwS,KAAAnS,KAAAkS,KA4DAvN,mBAAA,SAAA/E,EAAAD,GAKA,GAAAyS,GAAA,SAAAC,GACArS,KAAAsS,UACAtS,KAAAuS,iBACAvS,KAAAwS,kBACAxS,KAAAyS,gBAEA9S,EAAAU,KAAAgS,EAAArS,KAAA6D,IAAA7D,MAMAL,GAAAgC,OAAAyQ,EAAAtU,WAMA+F,IAAA,SAAA8B,EAAA+M,GACA,GAAAC,GAAAhN,EAAAsB,GAGAjH,MAAAsS,OAAAK,GAAAhN,EAGAA,EAAAwB,QACAnH,KAAAuS,cAAA5M,EAAAwB,MAAAF,KAAA0L,GAIAD,IACA1S,KAAAwS,eAAAE,GAAAC,GAGA3S,KAAAyS,iBAKA7L,YAAA,SAAAO,GACA,MAAAnH,MAAA8I,eAAA3B,EAAAF,MAMA6B,eAAA,SAAA8J,GACA,GAAAD,GAAA3S,KAAAuS,cAAAK,EACA,OAAA5S,MAAA6S,UAAAF,IAIAG,aAAA,SAAAxV,GACA,GAAAqV,GAAA3S,KAAAwS,eAAAlV,EACA,OAAA0C,MAAA6S,UAAAF,IAKAI,YAAA,SAAAzV,GACA,MAAAqC,GAAAqT,OAAAhT,KAAAsS,QAAAhV,IAIAuV,UAAA,SAAA5L,GACA,MAAAjH,MAAAsS,OAAArL,IAGAgM,eAAA,SAAAhM,GACA,GAAA3J,IAAA,CAMA,OALAqC,GAAAmK,KAAA9J,KAAAsS,OAAA,SAAA3M,GAEA,GADArI,IACAqI,EAAAwB,MAAAF,KAAAA,EACA,MAAAtB,KAEArI,GAAA,GAIAsI,OAAA,SAAAD,GACA,GAAAgN,GAAAhN,EAAAsB,GAGAtB,GAAAwB,aACAnH,MAAAuS,cAAA5M,EAAAwB,MAAAF,KAIAtH,EAAAuT,IAAAlT,KAAAwS,eAAA,SAAAvL,EAAAkM,GACA,GAAAlM,IAAA0L,EAEA,aADA3S,MAAAwS,eAAAW,IACA,GAEAnT,YAGAA,MAAAsS,OAAAK,GAGA3S,KAAAyS,iBAMAvY,KAAA,SAAAkZ,GACApT,KAAAvD,MAAA2W,EAAAzT,EAAA0T,KAAA/W,aAMAG,MAAA,SAAA2W,EAAAhX,GACAuD,EAAAU,KAAAL,KAAAsS,OAAA,SAAA3M,GACAhG,EAAAmB,WAAA6E,EAAAyN,KACAzN,EAAAyN,GAAA3W,MAAAkJ,EAAAvJ,UAMAqW,cAAA,WACAzS,KAAAzE,OAAAoE,EAAA2T,KAAAtT,KAAAsS,UASA,IAAAiB,IAAA,UAAA,OAAA,MAAA,OAAA,SAAA,SACA,SAAA,SAAA,QAAA,MAAA,OAAA,MAAA,UACA,WAAA,SAAA,UAAA,QAAA,UAAA,OACA,OAAA,UAAA,UAAA,QAWA,OATA5T,GAAAU,KAAAkT,EAAA,SAAAH,GACAhB,EAAAtU,UAAAsV,GAAA,WACA,GAAAf,GAAA1S,EAAAqT,OAAAhT,KAAAsS,QACAlW,GAAAiW,GAAAvW,OAAA6D,EAAA6T,QAAAlX,WACA,OAAAqD,GAAAyT,GAAA3W,MAAAkD,EAAAvD,MAKAgW,GACAxS,EAAAD,GAEAC,EAAA8B,iBCr2CA,WAMA,GAAA+R,MAIAC,EAAA,SAAAvM,GACAxH,EAAAgU,QAAAxM,EAAAyM,iBAGAH,EAAA9T,EAAA2M,OAAAmH,EAAA,SAAAI,GAAA,MAAA1M,GAAAF,KAAA4M,EAAA5M,MAFAtH,EAAAmU,UAAAL,GAAAxM,IAAAE,EAAAF,OAAAwM,EAAAlX,KAAA4K,IAaA4M,EAAA,SAAAC,GACA,GAAAC,GAAA7X,EAAAuD,EAAAuU,KAAA5X,WAGA6X,EAAA,SAAAhN,EAAAiN,GACA,MAAAzU,GAAA0U,UAAAD,GAAAA,GACAzU,EAAAe,SAAA0T,GAAAjN,EAAAiN,GAAAA,GAAA3X,MAAA0K,EAAA/K,GAMA,OAJAuD,GAAAU,KAAAoT,EAAA,SAAAtM,IACA8M,GAAAE,EAAAhN,EAAAA,EAAAmN,eAAAN,MACAC,EAAA9M,EAAAmN,eAAAL,UAEAA,EAMArU,UAAA2U,QAAAzW,UAAA0W,SAAA7U,EAAA8U,KAAA7U,SAAA2U,QAAAzW,UAAA0W,SAAA,SAAAE,EAAAC,EAAAhR,GACA,GAAAsQ,GAAAF,EAAA,qBAAAY,EAAAhR,EACAsQ,GACAW,QAAAX,EAAA,mDACAS,EAAAxa,KAAA8F,KAAA2U,EAAAhR,GAGA+Q,EAAAxa,KAAA8F,KAAA2U,EAAAhR,KAMAqN,OAAA6D,eAAA,SAAApW,GACA,MAAAsV,GAAA,qBAAAtV,IAMAkB,EAAAgC,OAAA/B,SAAAkV,MAAAhX,WAEAiX,WACAC,kBAAA,EACAC,kBACArB,mBAIAsB,cAAA,WASA,MARAlV,MAAAsU,eAAA3U,EAAAgC,WACAsS,OAAA,4BACAkB,oBAAA,EACAC,oBAAA,GACApV,KAAA+U,aACA/U,KAAAgV,kBAAA,EACAhV,KAAAqV,iBACArV,KAAAsV,yBACAtV,MAKAuV,aAAA,WAKA,MAJAvV,MAAAgV,kBAAA,EACAhV,KAAAiV,kBACAjV,KAAA4T,mBACA5T,KAAAsV,yBACAtV,MAKAwV,gBAAA,WAGA,MAFAxV,MAAAqV,iBACArV,KAAAsV,yBACAtV,MAMAyV,gBAAA,WACA,GAAAzV,KAAAgV,iBAIA,MAHAhV,MAAA0V,WAAA1V,KAAAiV,eACAjV,KAAAqV,iBACArV,KAAAsV,yBACAtV,MASA2V,kBAAA,SAAAC,GACA,IAAAA,EAAA,OAAAjW,EAAAgU,QAAA3T,KAAA4T,kBAAAjU,EAAAoB,MAAAf,KAAA4T,gBACA,IAAAiC,GAAAC,GAAA,EAAAC,EAAA/V,KAAA4T,eACA,KAAA,GAAAtP,KAAAsR,GACAjW,EAAAqW,QAAAD,EAAAzR,GAAAuR,EAAAD,EAAAtR,OACAwR,IAAAA,OAAAxR,GAAAuR,EAEA,OAAAC,IAGAT,eAAA,WACArV,KAAAiV,eAAAtV,EAAAoB,MAAAf,KAAA0V,YACA1V,KAAA4T,oBAMA0B,uBAAA,WACAtV,KAAA8H,QAAA,kBAAAnI,EAAAgU,QAAA3T,KAAA4T,iBAAAjU,EAAAoB,MAAAf,KAAA4T,kBACA5T,KAAA+U,SAAArB,EAAA1T,SAMAJ,SAAAkV,MAAAhX,UAAAmY,IAAAtW,EAAA8U,KAAA7U,SAAAkV,MAAAhX,UAAAmY,IAAA,SAAAC,EAAA/C,EAAA0C,EAAAlS,GACA,GAAAiS,GAAA5W,CACA,OAAA,OAAAmU,EAAAnT,MAEA,gBAAAmT,IACAyC,EAAAzC,EACAxP,EAAAkS,IAEAD,MAAAzC,GAAA0C,EAEAlS,IAAAA,MAGA3E,EAAAkX,EAAAhc,KAAA8F,KAAA4V,EAAAjS,GAEA3D,KAAAgV,mBAAArR,EAAAmD,SACAnH,EAAAU,KAAAuV,EAAAjW,EAAA2O,KAAA,SAAAuH,EAAA1C,GACAxT,EAAAqW,QAAAhW,KAAAiV,eAAA9B,GAAA0C,SACA7V,MAAA4T,gBAAAT,GAEAnT,KAAA4T,gBAAAT,GAAA0C,GACA7V,OACAA,KAAAsV,0BAEAtW,KAKAY,SAAAuW,KAAAxW,EAAA8U,KAAA7U,SAAAuW,KAAA,SAAAC,EAAAhD,EAAAjM,EAAAxD,GAcA,MAbAA,KAAAA,MAEA,UAAAyP,IACAzP,EAAA0S,QAAA1W,EAAA8U,KAAA9Q,EAAA0S,QAAA1W,EAAA2O,KAAA,SAAAgI,EAAAlS,EAAAmS,EAAAC,GACA,GAAAxX,EAMA,OALAsX,KAAAtX,EAAAsX,EAAApc,KAAA8F,KAAAoE,EAAAmS,EAAAC,IACArP,EAAA6N,mBACA7N,EAAAkO,iBACAlO,EAAAmO,0BAEAtW,GACAgB,QAEAoW,EAAAhD,EAAAjM,EAAAxD,QAIA/J,EAAA,0BAAA,cChMAA,EAAA,kBAAA,WAEA,MAAAgG,UAAAkV,MAAAnT,QAEA8U,UACAC,QAAA,KACA/X,GAAA,GACA2U,KAAA,OACAqD,IAAA,IAGAjT,WAAA,WACA1D,KAAAkV,qBCZAtb,EAAA,2BAAA,WAEA,OAMAgd,uBACAhN,UACAU,aAQAuM,iBAQAC,mBAAA,SAAAnT,GAEA,GAAAoT,GAAA/W,KAAAgX,mBAIAD,GAAAnN,QAAAjG,GAAAA,EAAAiG,QACA5J,KAAAiX,WAAAtT,EAAAiG,QAIAjK,EAAAU,KAAA0W,EAAAzM,SAAA,SAAA4M,EAAAC,GAEA,IAAAD,EAAAE,cAAA,IAAAF,EAAAE,YAAApX,MAAA,CAEA,GACAqX,GADAC,EAAAtX,KAAAwG,IAAA2Q,EAGAD,GAAAK,OACAF,EAAAH,EAAAK,OAAAD,GACA,UAAAJ,EAAAM,KACAH,EAAArG,OAAAyG,aAAAC,UAAAC,UAAAT,EAAAU,MAAAN,GACA,eAAAJ,EAAAM,OACAH,EAAArG,OAAAyG,aAAAC,UAAAG,eAAAX,EAAAU,MAAAN,IAGAtX,KAAAiW,IAAAkB,EAAAE,GAGA,UAAAH,EAAAM,KACAxX,KAAA8X,4BAAAT,GAGA,eAAAH,EAAAM,OAEAH,EAAAzN,OAAA5J,KACAqX,EAAAhX,KAAA,SAAA0X,GAEA/X,KAAA8X,4BAAAC,IAEA/X,SAMAA,OAUAgY,gBAAA,WAEA,GAAAC,KAUA,OARAtY,GAAAU,KAAAL,KAAAgX,oBAAA1M,SAAA,SAAAlG,EAAA+O,GAEA/O,EAAAgT,cAAA,IAAAhT,EAAAgT,YAAApX,OACAiY,EAAA1b,KAAA4W,IAGAnT,MAEAiY,GAUAC,WAAA,WAEA,GAAAnB,GAAA/W,KAAAgX,mBAEA,SAAAD,EAAAnN,QACAmN,EAAAnN,OAAA1B,WAcA8O,kBAAA,WAEA,MAAAvd,GAAAkI,QAAA,EAAA3B,KAAA6W,cAAA7W,KAAA4W,wBAWAK,WAAA,SAAAld,GACAiG,KAAA6W,cAAAjN,OAAA1B,UAAAnO,GAUA+d,4BAAA,SAAA3Q,GAEA,GAAAA,GAAAA,EAAA6P,kBAAA,CAGA,GAAAD,GAAA5P,EAAA6P,mBACAD,GAAAnN,QAAAmN,EAAAnN,OAAAzC,QAAAnH,KAAAwG,IAAA,SACAW,EAAA8P,WAAAjX,WC1JApG,EAAA,yBAAA,eAAA,yBAAA,SAAAue,EAAAC,GAEA,MAAAxY,UAAAkV,MAAAnT,OAAAhC,EAAA8W,UAMAI,eACAjN,QACAzC,MAAA,gBACAqQ,KAAA,SAEAlN,UACA+N,QACAjB,YAAA,SAAAjQ,GACA,MAAA,UAAAA,EAAAX,IAAA,gBAEAoR,MAAA,QACAzQ,MAAA,QACAqQ,KAAA,WAWAf,SAAA,WACA,OACA9X,GAAAgB,EAAA2Y,SAAA,SACAD,OAAA,GACAE,YAAA,OACAC,SAAA,EACAC,OAAA,IACAC,YAAA,GACAlB,KAAA,WAYA9T,WAAA,SAAAU,EAAAT,GAEA3D,KAAAkV,gBACAlV,KAAA8W,mBAAAnT,IAUAuU,WAAA,WACA,MAAAlY,MAAAwC,WAAAoH,QASA+O,aAAA,WACA,MAAA3Y,MAAAwG,IAAA,eAAA,IAAAxG,KAAAwG,IAAA,OAUAoS,cAAA,WACA,MAAA5Y,MAAAkY,aAAA1R,IAAA,iBAAAqS,0BAGAT,MCzFAxe,EAAA,+BAAA,yBAAA,SAAAuN,GAEA,MAAAvH,UAAAmE,WAAApC,QAMAwF,MAAAA,EAEAzD,WAAA,WAGA1D,KAAA8Y,GAAA,UAAA9Y,KAAA+Y,cAGA/Y,KAAA8Y,GAAA,MAAA9Y,KAAA+Y,cACA/Y,KAAA8Y,GAAA,SAAA9Y,KAAA+Y,cAGA/Y,KAAA8Y,GAAA,MAAA9Y,KAAAgZ,gBACAhZ,KAAA8Y,GAAA,SAAA9Y,KAAAgZ,gBAGAhZ,KAAA8Y,GAAA,iBAAA9Y,KAAAgZ,iBAUAC,cAAA,WAEA,MAAAtZ,GAAA2T,KAAAtT,KAAAkZ,gBAUAA,YAAA,WACA,MAAAlZ,MAAAsM,OAAA,SAAA+L,GACA,MAAAA,GAAA7R,IAAA,cAWAwS,eAAA,SAAAX,GAEA,GAAArY,KAAA4J,OAAApD,IAAA,iBAAAqS,wBAAA,CAIA,GAAAM,GAAAnZ,KAAA4M,QAAAyL,GACAe,EAAApZ,KAAA4J,MAWA,IARA,OAAAwP,EAAA5S,IAAA,kBACA7G,EAAAU,KAAA8Y,EAAA,SAAAhS,GACAA,EAAA8O,IAAA,WAAA,KAMA,IAAAjW,KAAAiZ,iBAAAG,EAAA5S,IAAA,UAAA,EAAA,CACA,GAAA4F,GAAA,IAAApM,KAAAsT,OAAAtT,KAAAoM,OAAA+M,CACAxZ,GAAAiB,MAAAwL,GAAA6J,IAAA,WAAA,MAWA8C,aAAA,WAEA,GAAAM,GAAArZ,KACAoZ,EAAApZ,KAAA4J,MAEA5J,MAAAK,KAAA,SAAAgY,GACAA,EAAApC,IAAA,SAAAmD,EAAA5S,IAAA,iBAAA8S,qBAAAD,EAAA9b,QAAA8a,YChGAze,EAAA,yBAAA,WAEA,MAAAgG,UAAAkV,MAAAnT,QAQA8U,SAAA,WACA,OACA8C,SAAA,EACAC,gBAAA,EACAC,mBACAC,aAAA,EACAC,KAAA,WACAhb,GAAA,UACAib,OAAA,EACAC,YACAzf,KAAA,UACA0f,YAAA,GACAC,QAAA,EACAC,OAAA,IAWAC,aAAA,WAEA,GAAA7f,GAAA4F,KAAAwG,IAAA,OAGA,QAFApM,GAEA0B,OAAAkE,KAAAwG,IAAA,aAAA1K,OAAA1B,EAAAe,MAAA,OAUAme,mBAAA,WAEA,MAAAtZ,MAAAka,mBAAA,YAUArB,sBAAA,WAEA,MAAA7Y,MAAAka,mBAAA,eAUAC,gBAAA,WAEA,MAAAna,MAAAka,mBAAA,SAUAE,gBAAA,WAEA,MAAApa,MAAAka,mBAAA,QAUAG,gBAAA,WAEA,MAAAra,MAAAka,mBAAA,QAUAI,kBAAA,WAIA,QAFAta,KAAAwG,IAAA,YAMAxG,KAAAka,mBAAA,UAYAA,mBAAA,SAAAK,GAEA,GAAAhB,GAAAvZ,KAAAwG,IAAA,UAEA,UAAA+S,IAAAA,EAAAgB,KAIAhB,EAAAgB,QCzIA3gB,EAAA,mBACA,eACA,wBACA,8BACA,sBACA,yBACA,SACAue,EACAqC,EACAC,EACAC,EACAtC,GAGA,MAAAxY,UAAAkV,MAAAnT,OAAAhC,EAAA8W,UAMAI,eACAjN,QACAzC,MAAA,YACAqQ,KAAA,SAEAlN,UACAiP,SACA3B,MAAA,kBACAzQ,MAAA,SACAqQ,KAAA,cAEAoC,OACAhC,MAAA,QACAzQ,MAAA,QACAqQ,KAAA,SAEAmD,WACA/C,MAAA,YACAR,YAAA,SAAAjQ,GACA,GAAAqQ,GAAArQ,EAAAX,IAAA,gBAEA,OAAA,WADA7G,EAAAe,SAAA8W,GAAAA,EAAAA,EAAAhR,IAAA,QAGAW,MAAA,gBACAqQ,KAAA,cAEAoD,eACAhD,MAAA,eACAL,OAAA,SAAA1B,GACA,MAAAlW,GAAAe,SAAAmV,GACA7E,OAAAyG,aAAAkD,UAAAnU,IAAAqP,GAEAA,GAEA1O,MAAA,gBACAqQ,KAAA,WAWAf,SAAA,WACA,OACA9X,GAAAgB,EAAA2Y,SAAA,SACAiB,WACAsB,QAAA,GACAC,oBAAA,KACAlB,SACAmB,cAAA,KACAC,WAAA,EACAjB,OAAA,EACAa,cAAA,UACAD,aACAM,UAAA,GACAC,MAAA,GACA1D,KAAA,gBACA2D,cAAA,KACAC,UAAA,GAEAC,WAAA,IAYA3X,WAAA,SAAAU,EAAAT,GAEA,GAAA0V,GAAArZ,IAEAA,MAAAkV,gBACAlV,KAAA8W,mBAAAnT,IAEA,IAAA3D,KAAAwG,IAAA,iBAAA+S,UAEAvZ,KAAAsb,sBAGAtb,KAAAqL,SAAArL,KAAAwG,IAAA,WAAA,SAAA,WAEAlH,WAAA,WACA+Z,EAAAiC,uBACA,MAMAtb,KAAAwG,IAAA,iBAAAA,IAAA,WACAxG,KAAAiW,IAAA,SAAA,GAGAtW,EAAA4b,MAAA,SAAAlC;oBACAA,EAAAP,GAAA,gBAAAO,EAAAnB,aAAAsD,cAAAnC,EAAAnB,eACA,EAAAlY,OAWAyb,WAAA,SAAArX,EAAAT,GAEA,GAAAkN,GAAA7Q,KAAAwG,IAAA,iBAAA6T,iBACA,MAAAra,KAAAwG,IAAA,WAAA8M,QAAAzC,GAAA,CAIAzM,EAAAA,MACAT,EAAAA,MAEAS,EAAAmU,YAAAvY,KAAAwG,IAAA,iBAAA2T,kBACA/V,EAAAsU,YAAA1Y,KAAAwG,IAAA,MACA7C,EAAAiG,OAAA5J,IAEA,IAAAqY,GAAArY,KAAAwG,IAAA,WAAA3C,IAAAO,EAAAT,EAEA/D,UAAA8b,OAAA5T,QAAA,sBAAAuQ,EAAArY,QAeA2b,YAAA,SAAAC,EAAAC,GAIA,MAHA,SAAAA,IACAD,EAAAhB,cAAA5a,KAAAwG,IAAA,iBAAAA,IAAA,OAEAoV,GASA1D,WAAA,WAEA,GAAAnB,GAAA/W,KAAAgX,mBAEA,IAAAD,EAAAnN,OAAA,CACA,GAAA5J,KAAAwC,YAAAxC,KAAAwC,WAAAoH,OACA,MAAA5J,MAAAwC,WAAAoH,MACA,IAAAmN,EAAAnN,OAAA1B,UACA,MAAA6O,GAAAnN,OAAA1B,UAIA,OAAA,GAYA4T,eAAA,WAGA,GACAnB,GADAoB,EAAA/b,KAAAwG,IAAA,iBAAAA,IAAA,KAiBA,OAdAmU,GAAA3a,KAAAwC,WAAA8J,OAAA,SAAA8M,GAEA,GAAA5B,GAAA4B,EAAA5S,IAAA,iBAAAA,IAAA,KAGA,OAAA,YAAAuV,EACA,YAAAvE,EAIA,YAAAA,IAIAmD,EAAApd,QAAAyC,OAWAgc,kBAAA,WAEA,GAAA1e,GAAA0C,KAAA8b,gBAEA,KAAA,IAAAxe,EACA,MAAA,EAGA,IAAA,YAAA0C,KAAAwG,IAAA,iBAAAA,IAAA,MAAA,CAEA,MADA,6BAAArL,MAAA,IACAmC,GAGA,MAAAA,GAAA,GAKA2e,QAAA,WAEA,GAAArS,GAAA5J,KAAAkc,sBACA7e,EAAA,EASA,OAPAuM,KAEAvM,EAAAuM,EAAAqS,UAAA,KAKA5e,EAAA2C,KAAAgc,qBAUAE,oBAAA,WAEA,QAAAlc,KAAAmc,eAEAnc,KAAAwC,WAAAoH,QAcAwS,gBAAA,WACA,MAAApc,MAAAkY,cAUAmE,WAAA,WAEA,MAAArc,MAAAwG,IAAA,iBAAAA,IAAA,UAIAxG,KAAAwG,IAAA,UAHA,GAaA8V,sBAAA,WAEA,GAAAC,GAAAvc,KAAAkY,aAAA1R,IAAA,WACAuT,EAAA/Z,KAAAwG,IAAA,SAEA,OAAA,KAAA+V,EACA,MAGAxC,EAAAwC,EAAA,KAAAC,QAAA,GAAA,KAUAL,YAAA,WAEA,MAAA,aAAAnc,KAAAwC,WAAAoH,OAAApD,IAAA,SAIA8U,oBAAA,WAGA,IADA,GAAA/B,GAAAvZ,KAAAwG,IAAA,WACA+S,EAAAjG,OAAAtT,KAAAwG,IAAA,iBAAA4T,mBACApa,KAAAyb,eAKArD,MCjWAxe,EAAA,yBAAA,mBAAA,SAAAuN,GAEA,MAAAvH,UAAAmE,WAAApC,QAMAwF,MAAAA,EAQAzD,WAAA,WAGA1D,KAAA8Y,GAAA,UAAA9Y,KAAA+Y,cAGA/Y,KAAA8Y,GAAA,MAAA9Y,KAAA+Y,cACA/Y,KAAA8Y,GAAA,SAAA9Y,KAAA+Y,cAEA/Y,KAAA8Y,GAAA,MAAA9Y,KAAAyc,gBAUA1D,aAAA,WAEA,GAAAM,GAAArZ,IAEAA,MAAAK,KAAA,SAAA+Y,GAEAA,EAAAnD,IAAA,aAAAoD,EAAA9b,QAAA6b,GAAA,MAcAqD,cAAA,SAAAtV,GAEAA,EAAA8O,IAAA,YAAAjW,KAAA4J,OAAApD,IAAA,YCzDA5M,EAAA,uBAAA,WAEA,OAEA8iB,UAQAC,mBAAA,WAEA,MAAA3c,MAAA4c,cACA,GAGA5L,OAAAyG,aAAAoF,UAAA,iBAAA7c,KAAAwG,IAAA,MAAA,gBAUAsW,oBAAA,WAEA,GAAAC,GAAA/c,KAAA+c,UACA,OAAA/L,QAAAyG,aAAAuF,QAAAxW,IAAAuW,EAAA/c,KAAAwG,IAAA,QAAA7K,QAAA,QAAA,IAAAqE,OAUA4c,YAAA,WAEA,OAAAjd,EAAAsd,SAAAjd,KAAAwG,IAAA,QAAA,IAAAxG,KAAAwG,IAAA,MAAAjJ,QAAA,UAUA2f,mBAAA,WAEA,GAAAC,GAAAxd,EAAA2M,OAAAtM,KAAA8c,sBAAA,SAAAM,GACA,MAAAA,GAAA,QAGAzd,GAAAU,KAAA8c,EAAA,SAAAC,GACAzd,EAAAU,KAAAV,EAAA0d,QAAAD,EAAAV,QAAA,SAAAY,GAGA,GAAAzc,IAAAyc,EAAAC,WACAC,EAAAxd,KAAAwG,IAAA,SAEA8W,GAAAG,kBACA5c,EAAAtE,KAAA+gB,EAAAG,kBAGA9d,EAAAU,KAAAQ,EAAA,SAAAsS,GACA,GAAA7O,GAAAgZ,EAAAI,iBAAAJ,EAAAI,iBAAAvK,EAAAA,CACAqK,IAAAA,EAAAlZ,IACAtE,KAAAiW,IAAA9C,EAAAqK,EAAAlZ,GAAA,KAEAtE,OAEAA,OACAA,UC9EApG,EAAA,kBAAA,WAEA,OAEA+jB,SACAzC,MAAA0C,KAAAC,KAAAC,UAAA,oBACAC,YAAA,EACArB,UAGAa,UAAA,YACA5e,GAAA,YACA6Y,KAAA,gBAIA+F,UAAA,UACA5e,GAAA,cACAqf,MAAAJ,KAAAC,KAAAC,UAAA,eACAtG,KAAA,aAIA+F,UAAA,kBACA5e,GAAA,kBACAqf,MAAAJ,KAAAC,KAAAC,UAAA,sBACAnN,IAAA,EACAE,IAAA,IACAoN,IAAAL,KAAAC,KAAAC,UAAA,gEACAtG,KAAA,WAGA+F,UAAA,mBACA5e,GAAA,mBACAqf,MAAAJ,KAAAC,KAAAC,UAAA,kBACAL,iBAAA,iBACAQ,IAAAL,KAAAC,KAAAC,UAAA,kEACAtG,KAAA,kBAGA+F,UAAA,aACA5e,GAAA,aACAqf,MAAAJ,KAAAC,KAAAC,UAAA,cACAnN,IAAA,EACAE,IAAA,IACA4M,iBAAA,aACAQ,IAAAL,KAAAC,KAAAC,UAAA,2EACAtG,KAAA,oBAIA+F,UAAA,sBACA5e,GAAA,sBACAqf,MAAAJ,KAAAC,KAAAC,UAAA,wBACAG,IAAAL,KAAAC,KAAAC,UAAA,sGACAtG,KAAA,WAGA+F,UAAA,mBACA5e,GAAA,mBACAqf,MAAAJ,KAAAC,KAAAC,UAAA,4BACAG,IAAAL,KAAAC,KAAAC,UAAA,oHACAtG,KAAA,gBC9DA5d,EAAA,eACA,wBACA,gBACA,kBACA,wBACA,oBACA,gBACA,SACA4gB,EACA0D,EACAC,EACA/F,EACAgG,EACAC,GAGA,MAAAze,UAAAkV,MAAAnT,OAAAhC,EAAA8W,UAMAI,eACAjN,QACAzC,MAAA,SACAqQ,KAAA,SAEAlN,UACAqQ,WACA/C,MAAA,YACAzQ,MAAA,gBACAqQ,KAAA,gBASAuF,OAAAsB,EAQA5H,SAAA,WAEA,OACA9X,GAAAgB,EAAA2Y,SAAA,SACA4C,MAAA0C,KAAAC,KAAAC,UAAA,YACAtG,KAAA,YACA8G,UAAA,GAEAC,OAAA,QAGA1D,QAAA,GACA2D,iBAAA,EACAC,eAAA,KACAC,WAAA,KACAC,gBAAA,GACAvkB,KAAA,GACAwkB,eAAA,KACAC,WAAA,GACAC,oBAAA,KAEAnE,aAGAoE,QAAA,EAGAC,UAAA,GACAC,gBAAA,EACAC,mBAAA,IAWAxb,WAAA,WAEA1D,KAAAkd,qBACAld,KAAAkV,gBACAlV,KAAA8W,qBAEA9W,KAAAqL,SAAArL,KAAAwG,IAAA,aAAA,MAAAxG,KAAAwb,eACAxb,KAAAqL,SAAArL,KAAAwG,IAAA,aAAA,SAAAxG,KAAAwb,eAEAxb,KAAAiW,IAAA,UAAAjW,KAAAmf,oBAGAnf,KAAA8Y,GAAA,gBAAA,WACA,YAAA9Y,KAAAwG,IAAA,WACAxG,KAAAkY,aAAAjC,IAAA,eAAA,UAaAmJ,aAAA,SAAAhb,GAEAA,EAAA6W,UAAAjb,KAAAwG,IAAA,KACA,IAAA4S,GAAApZ,KAAAwG,IAAA,aAAA3C,IAAAO,GACAwF,OAAA5J,MAEAJ,UAAA8b,OAAA5T,QAAA,oBAAAsR,EAAApZ,OAWAqf,cAAA,SAAAC,GAEA,MAAAA,GACA1B,KAAAC,KAAAC,UAAA,WAGAF,KAAAC,KAAAC,UAAA,SASAqB,iBAAA,WAEA,GAAApF,GAAA,CAMA,OAJA/Z,MAAAwG,IAAA,aAAAnG,KAAA,SAAA+Y,GACAW,GAAAX,EAAAiD,eAGAtC,GAWAwF,eAAA,SAAAC,GAEA,GAAAxf,KAAAwG,IAAA,qBAEAgZ,QAEA,CAEA,GAAAnG,GAAArZ,IAEA4d,MAAA6B,KAAAvlB,MACAkK,MACAsb,OAAA,eACAC,YAAA,YACAC,UAAA5O,OAAAyG,aAAAoI,YAAArZ,IAAA,MACAsZ,QAAA9f,KAAAwG,IAAA,OAEAuZ,MAAA,SAAAC,EAAAzB,EAAAwB,GAEAE,QAAAC,IAAAF,EAAAzB,EAAAwB,GACA/O,OAAAyG,aAAA0I,MAAAD,IAAA,uCAAAF,EAAAzB,EAAAwB,EAAA,yCACAP,GAAA,IAGAnJ,QAAA,SAAA+J,GACAA,GAAAA,EAAAzF,WACAtB,EAAApD,IAAA,qBAAA,GACAmK,EAAAzF,WACAhb,EAAAU,KAAA+f,EAAAzF,UAAAtB,EAAA+F,aAAA/F,GAEAmG,KAEAA,GAAA,QAiBAhE,cAAA,WAEAxb,KAAAiW,IAAA,UAAAjW,KAAAmf,sBAIA/G,EAAAgG,MC7NAxkB,EAAA,oBAAA,WAEA,OAEA+jB,SACAzC,MAAA0C,KAAAC,KAAAC,UAAA,oBACAC,YAAA,EACArB,UAGAa,UAAA,YACA5e,GAAA,YACA6Y,KAAA,gBAIA+F,UAAA,cACA5e,GAAA,cACAqf,MAAAJ,KAAAC,KAAAC,UAAA,mBACAtG,KAAA,gBAGA+F,UAAA,cACA5e,GAAA,cACAqf,MAAAJ,KAAAC,KAAAC,UAAA,mBACAtG,KAAA,kBAIA+F,UAAA,cACA5e,GAAA,cACAqf,MAAAJ,KAAAC,KAAAC,UAAA,eACAG,IAAAL,KAAAC,KAAAC,UAAA,oDACAtG,KAAA,WAGA+F,UAAA,wBACA5e,GAAA,wBACAqf,MAAAJ,KAAAC,KAAAC,UAAA,iCACAG,IAAAL,KAAAC,KAAAC,UAAA,2FACAtG,KAAA,SACA6I,UAAA,WACA,MAAA,QAAArgB,KAAAwG,IAAA,mBAIA+W,UAAA,mCACA5e,GAAA,mCACAqf,MAAAJ,KAAAC,KAAAC,UAAA,uCACAG,IAAAL,KAAAC,KAAAC,UAAA,iGACAtG,KAAA,SACA6I,UAAA,WACA,MAAA,cAAArP,OAAAyG,aAAA6I,aAAA,QAAAtgB,KAAAwG,IAAA,2BAKA+W,UAAA,eACA8C,UAAA,WACA,OAAA,IAAArgB,KAAAugB,sBAEA5hB,GAAA,eACAqf,MAAAJ,KAAAC,KAAAC,UAAA,gBACAL,iBAAA,mBACAjG,KAAA,gBACA7T,QAAA,WACA,MAAA3D,MAAAwgB,oCAKAjD,UAAA,cACA5e,GAAA,cACAqf,MAAAJ,KAAAC,KAAAC,UAAA,eACAL,iBAAA,cACAjG,KAAA,SACA7T,QAAA,WAEA,GAAAA,KAEAwP,IAAA,GACA0C,IAAA+H,KAAAC,KAAAC,UAAA,UAGA3K,IAAA,OACA0C,IAAA+H,KAAAC,KAAAC,UAAA,wBAGA3K,IAAA,aACA0C,IAAA+H,KAAAC,KAAAC,UAAA,sCAkBA,OAdA9d,MAAAygB,aAAAja,IAAA,eACA7C,EAAApH,MACA4W,IAAA,QACA0C,IAAA+H,KAAAC,KAAAC,UAAA,uCAIA,QAAA9d,KAAAwG,IAAA,qBACA7C,EAAApH,MACA4W,IAAA,eACA0C,IAAA+H,KAAAC,KAAAC,UAAA,oDAIAna,KAKA4Z,UAAA,wBACA8C,UAAA,WACA,OAAA,KAAA,aAAA,QAAA,gBAAA9iB,QAAAyC,KAAAwG,IAAA,iBAEA7H,GAAA,wBACAqf,MAAAJ,KAAAC,KAAAC,UAAA,aACAnN,IAAA,EACA6G,KAAA,WAGA+F,UAAA,iBACAmD,YAAA,QACAL,UAAA,WACA,MAAA,SAAArgB,KAAAwG,IAAA,gBAEA7H,GAAA,iBACAqf,MAAAJ,KAAAC,KAAAC,UAAA,QACA6C,WAAA,QACAnJ,KAAA,eAGA+F,UAAA,iBACA8C,UAAA,WACA,MAAA,SAAArgB,KAAAwG,IAAA,gBAEAoa,WAAA,QACAF,YAAA,QACA/hB,GAAA,iBACAqf,MAAAJ,KAAAC,KAAAC,UAAA,QACAtG,KAAA,oBC7IA5d,EAAA,iBAAA,cAAA,wBAAA,oBAAA,kBAAA,SAAAinB,EAAAzI,EAAAgG,EAAA0C,GAEA,MAAAlhB,UAAAkV,MAAAnT,OAAAhC,EAAA8W,UAMAI,eACAkK,SACA5Z,MAAA,UACAqQ,KAAA,SAEAlN,UACA0W,MACApJ,MAAA,OACAR,YAAA,SAAAjQ,GAEA,MAAA,QAAAA,EAAAX,IAAA,kBAAA7G,EAAAgU,QAAAxM,EAAAX,IAAA,UAEAW,MAAA,YACAqQ,KAAA,WASAuF,OAAA+D,EAQArK,SAAA,WACA,OACA9X,GAAAgB,EAAA2Y,SAAA,SACA4C,MAAA0C,KAAAC,KAAAC,UAAA,cACAtG,KAAA,SACAyJ,MAAAjhB,KAAAwC,WAAAxC,KAAAwC,WAAAjH,OAAA,EAAA,EACA2lB,cAAAlQ,OAAAyG,aAAA0J,OAAAxiB,GACAyiB,eAAA,GAGAC,SAAA,GACAC,SAAA,GAGAzG,QAAA,GACA0G,YAAA,GACAC,iBAAA,KACAC,sBAAA,MACAC,iCAAA,MACAC,YAAA,GACAC,YAAA,GAGAC,cACAC,mBAAA,KAEAd,QACAe,aAAA,KAEAC,YAAA,IAWAte,WAAA,WAEA1D,KAAAkd,qBACAld,KAAAkV,gBACAlV,KAAAiiB,yBACAjiB,KAAA8W,oBAGA,IAAAkK,GAAAhhB,KAAAwG,IAAA,OACA7G,GAAAgU,QAAAqN,IAAAA,EAAAxa,IAAA,cACAwa,EAAA/K,IAAA,YAAAjW,KAAAwG,IAAA,QAWAia,WAAA,WACA,MAAAzgB,MAAAkY,aAAAA,cAUAmH,cAAA,SAAAC,GAEA,MAAAA,GACA1B,KAAAC,KAAAC,UAAA,WAGAF,KAAAC,KAAAC,UAAA,WASA5F,WAAA,WAEA,GAAAnB,GAAA/W,KAAAgX,mBACA,OAAAD,GAAAnN,QAAAmN,EAAAnN,OAAA1B,UACA6O,EAAAnN,OAAA1B,aACAlI,KAAAwC,aAAAxC,KAAAwC,WAAAoH,SACA5J,KAAAwC,WAAAoH,QAYA4W,6BAAA,WAEA,GAAA0B,GAAAliB,KAAAkY,aAAA1V,WAAAjF,QAAAyC,KAAAkY,cACAiK,EAAAniB,KAAAwC,WAAAjF,QAAAyC,MACA2D,IA8BA,OA5BA3D,MAAAygB,aAAAja,IAAA,YAAAnG,KAAA,SAAA+hB,EAAAC,GACA,GAAAA,GAAAH,EAAA,CACA,GAAA9E,IAEAY,MAAAJ,KAAAC,KAAAliB,QAAA,sBACA2mB,OAAAF,EAAA5b,IAAA,SACA+b,OAAAH,EAAA5b,IAAA,WAEA7C,WAGAye,GAAA5b,IAAA,WAAAnG,KAAA,SAAAmiB,EAAAC,IACAJ,IAAAH,GAAAO,EAAAN,IAEA/E,EAAAzZ,QAAApH,MACA4W,IAAAqP,EAAAhc,IAAA,MACAqP,IAAA+H,KAAAC,KAAAliB,QAAA,qBACA2mB,OAAAE,EAAAhc,IAAA,SACA+b,OAAAC,EAAAhc,IAAA,cAIAxG,MAEA2D,EAAApH,KAAA6gB,KAEApd,MAEA2D,GAWA+e,SAAA,SAAAte,GAEAA,EAAAA,MAEAA,EAAAka,UAAAte,KAAArB,GACAyF,EAAA8a,mBAAA,EAEA9a,EAAA8W,QAEA9W,EAAA8W,MAAA0C,KAAAC,KAAAliB,QAAA,aACAgnB,OAAA3iB,KAAAwG,IAAA,YAKAxG,KAAAiW,IAAA,OAAA7R,GACApE,KAAA8W,oBAEA,IAAAkK,GAAAhhB,KAAAwG,IAAA,OAGA,OAFAxG,MAAAiW,IAAA,eAAA,OAEA+K,GAUAT,mBAAA,WAGA,GAAAvgB,KAAAwC,WAAAjF,QAAAyC,MACA,OAAA,CAIA,IAAAoiB,GAAApiB,KAAAkY,YACA,QAAAkK,EAAA5f,WAAAjF,QAAA6kB,IAeAH,uBAAA,WAEAjR,OAAAyG,aAAA6I,cAIAtgB,KAAA6W,cAAAvM,SAAAuX,YACAjK,MAAA,aACAR,YAAA,SAAAjQ,GAEA,MAAA,QAAAA,EAAAX,IAAA,wBAAA7G,EAAAgU,QAAAxM,EAAAX,IAAA,gBAEAW,MAAA,kBACAqQ,KAAA,YAKAY,EAAAgG,MCrQAxkB,EAAA,uBAAA,iBAAA,SAAAuN,GAEA,MAAAvH,UAAAmE,WAAApC,QAMAwF,MAAAA,EAQAzD,WAAA,WAGA1D,KAAA8Y,GAAA,UAAA9Y,KAAA4iB,YAGA5iB,KAAA8Y,GAAA,MAAA9Y,KAAA4iB,YACA5iB,KAAA8Y,GAAA,SAAA9Y,KAAA4iB,aAcAA,WAAA,WACA5iB,KAAA+Y,eACA/Y,KAAA6iB,oBASA9J,aAAA,WAEA/Y,KAAAK,KAAA,SAAAmiB,GACAA,EAAAvM,IAAA,QAAAjW,KAAAzC,QAAAilB,GAAA,IACAxiB,OAWA6iB,iBAAA,WAEA7iB,KAAAK,KAAA,SAAAmiB,GAGA,GAAA,QAAAA,EAAAhc,IAAA,oBAAA,EAEA,IADA7G,EAAAuH,MAAAvH,EAAA0d,QAAA1d,EAAAuH,MAAAsb,EAAAhC,+BAAA,YAAA,OACAjjB,QAAA,EAAAilB,EAAAhc,IAAA,kBACAgc,EAAAvM,KACA6M,aAAA,EACAtB,iBAAA,SAKAxhB,WC9EApG,EAAA,6BAAA,uBAAA,SAAAuN,GAEA,MAAAvH,UAAAmE,WAAApC,QAMAwF,MAAAA,EAQAzD,WAAA,WAEA1D,KAAA8Y,GAAA,MAAA9Y,KAAAkN,YACAlN,KAAA8Y,GAAA,SAAA9Y,KAAAkN,aAWAA,WAAA,SAAA/F,GAEA,MAAAA,GAAAX,IAAA,SAAAya,WChCArnB,EAAA,kBAAA,sBAAA,yBAAA,SAAAmpB,EAAA3K,GAEA,MAAAxY,UAAAkV,MAAAnT,OAAAhC,EAAA8W,UAEAI,eACAjN,QACAzC,MAAA,SACAqQ,KAAA,SAEAlN,UACA0Y,SACApL,MAAA,UACAzQ,MAAA,SACAqQ,KAAA,gBAWAf,SAAA,WACA,OACA9X,GAAAgB,EAAA2Y,SAAA,SACA0K,WACA/B,MAAAjhB,KAAAwC,WAAAxC,KAAAwC,WAAAjH,OAAA,EAAA,EACA2lB,cAAAlQ,OAAAyG,aAAA0J,OAAAxiB,GACAuc,MAAA0C,KAAAC,KAAAC,UAAA,eACAtG,KAAA,UAEA6D,WAAA,EACA4H,WAAA,IAUAvf,WAAA,WAEA1D,KAAAkV,gBACAlV,KAAA8W,sBAaAoM,WAAA,SAAA9e,EAAAT,GAYA,MAVAS,GAAAA,MACAT,EAAAA,MAEAS,YAAAxE,UAAAkV,OACA1Q,EAAA6R,IAAA,iBAAAjW,KAAAwG,IAAA,OACApC,EAAA6S,WAAAjX,OAEAoE,EAAAgd,eAAAphB,KAAAwG,IAAA,MAGAxG,KAAAwG,IAAA,WAAA3C,IAAAO,EAAAT,IAWA0b,cAAA,SAAAC,GAEA,MAAAA,GACA1B,KAAAC,KAAAC,UAAA,YAGAF,KAAAC,KAAAC,UAAA,YAYAqF,SAAA,SAAAC,GACA,MAAApjB,MAAAqjB,aAAA,OAAAD,IAYAE,SAAA,SAAAF,GACA,MAAApjB,MAAAqjB,aAAA,OAAAD,IAaAC,aAAA,SAAAE,EAAAH,GAEAA,EAAA,cAAAA,GAAAA,CAEA,IAEAI,GAFA3S,EAAA7Q,KAAAwC,WAAA8Q,OAAA,EACAhW,EAAA0C,KAAAwC,WAAAjF,QAAAyC,KAUA,IAPA,SAAAujB,EACAC,EAAAlmB,EAAA,EACA,SAAAimB,IACAC,EAAAlmB,EAAA,GAIAkmB,GAAA3S,GAAA2S,GAAA,EAEA,MAAAxjB,MAAAwC,WAAAiN,GAAA+T,EAEA,IAAAJ,EAAA,CAEA,GAAA,SAAAG,EACA,MAAAvjB,MAAAwC,WAAA5B,OACA,IAAA,SAAA2iB,EACA,MAAAvjB,MAAAwC,WAAAihB,OAKA,OAAA,IAIArL,MCjKAxe,EAAA,wBAAA,kBAAA,SAAAuN,GAEA,MAAAvH,UAAAmE,WAAApC,QAMAwF,MAAAA,EAQAzD,WAAA,WAKA1D,KAAA8Y,GAAA,UAAA9Y,KAAA+Y,cAGA/Y,KAAA8Y,GAAA,MAAA9Y,KAAA+Y,cACA/Y,KAAA8Y,GAAA,SAAA9Y,KAAA+Y,eAUAA,aAAA,WAEA,GAAAM,GAAArZ,IAEAA,MAAAK,KAAA,SAAA+hB,GAEAA,EAAAnM,IAAA,QAAAoD,EAAA9b,QAAA6kB,GAAA,UCzCAxoB,EAAA,sBACA,sBACA,8BACA,wBACA,4BACA,wBACA,SACAmpB,EACAtI,EACAD,EACAkJ,EACAC,GAGA,OACAZ,QAAAA,EACAtI,gBAAAA,EACAD,UAAAA,EACAkJ,cAAAA,EACAC,SAAAA,KCnBA/pB,EAAA,mBAAA,wBAAA,qBAAA,SAAAwe,EAAAgG,GAEA,MAAAxe,UAAAkV,MAAAnT,OAAAhC,EAAA8W,YAAA2B,EAAAgG,MCFAxkB,EAAA,iBAAA,uBAAA,wBAAA,qBAAA,SAAA+pB,EAAAvL,EAAAgG,GAEA,MAAAxe,UAAAkV,MAAAnT,OAAAhC,EAAA8W,UAEAI,eACAvM,UACAsZ,UACAhM,MAAA,WACAzQ,MAAA,UACAqQ,KAAA,gBAWAf,SAAA,WACA,OACA4K,SAAA,GACAuC,YACA1I,MAAA,aACA1D,KAAA,SACA8J,SAAA,KAUA5d,WAAA,WAEA1D,KAAAkV,gBACAlV,KAAA8W,qBAGAlX,SAAA8b,OAAA5C,GAAA,kBAAA9Y,KAAA6jB,YAAA7jB,MAGAJ,SAAA8b,OAAA5C,GAAA,iBAAA9Y,KAAAkjB,WAAAljB,MAEAJ,SAAA8b,OAAA5C,GAAA,uBAAA9Y,KAAA8jB,oBAAA9jB,OAYA8jB,oBAAA,SAAAtB,GAEA,GAAApe,GAAAoe,EAAApe,IAEA,WAAAoe,EAAA9C,cAEAtb,GAAAzF,GACAyF,EAAA4c,aACA5c,GAAA4c,KACA5c,EAAA2d,aAAA,OAKA3d,EAAA4d,YAAA,QAIA5d,GAAA6c,YACA7c,GAAA8c,oBACA9c,GAAAgd,eAEAphB,KAAAkjB,WAAA9e,IAWA8e,WAAA,SAAA9e,GAEAA,EAAAA,KACA,IACAge,GADAze,IAGAS,GAAAgd,eAMAgB,EAAApiB,KAAAwG,IAAA,YAAAA,IAAApC,EAAAgd,iBALAgB,EAAApiB,KAAA+jB,0BAEA3B,EAAApiB,KAAAwG,IAAA,YAAAid,QAMArf,EAAA6e,WAAA,EAEA7e,EAAA8c,cAAAlhB,KAAAwG,IAAA,KAEA,IAAAgc,GAAAJ,EAAAc,WAAA9e,EAAAT,EAMA,OALA/D,UAAA8b,OAAA5T,QAAA,mBAAA0a,GAGAJ,EAAAnM,IAAA,aAAA,GAEAuM,GAWAqB,YAAA,SAAAzf,GAEAA,EAAAA,KACA,IAAAwf,GAAA5jB,KAAAwG,IAAA,YACA7C,KACAqgB,EAAAhkB,KAAA+jB,sBAGAC,KACArgB,EAAA8L,GAAAmU,EAAArmB,QAAAymB,GAAA,GAGAJ,EAAA/f,IAAAO,EAAAT,IAUAogB,qBAAA,WAEA,MAAA/jB,MAAAwG,IAAA,YAAAsD,KAAA,SAAA3C,GACA,MAAAA,GAAAX,IAAA,iBAKA4R,EAAAgG,MC7JAxkB,EAAA,iBACA,kBACA,gBACA,eACA,gBACA,kBACA,wBACA,sBACA,cACA,kBAEA,SACAqqB,EACAC,EACA/L,EACA+F,EACAC,EACAgG,EACAzJ,EACAmG,EACAuD,GAGA,OACAH,SAAAA,EACAC,OAAAA,EACA/L,MAAAA,EACA+F,OAAAA,EACAC,SAAAA,EACAgG,eAAAA,EACAzJ,aAAAA,EACAmG,KAAAA,EACAuD,QAAAA,KChCAxqB,EAAA,uBAAA,WAEA,OAQAiI,QACAwiB,qCAAA,gBAUAC,aAAA,SAAArV,GAEAA,IACAA,EAAAsV,iBACAtV,EAAAuV,kBAGA,IAAAC,GAAA7G,KAAAC,KAAAliB,QAAA,4CACA+oB,KAAA1kB,KAAAmH,MAAAkY,iBAGArO,QAAA4D,QAAA6P,KAEAzkB,KAAAmH,MAAA3E,YACAxC,KAAAmH,MAAA3E,WAAAoD,OAAA5F,KAAAmH,OAIAvH,SAAA8b,OAAA5T,QAAA,iBAAA9H,KAAAmH,OAGAnH,KAAA8H,QAAA,gBAAA9H,KAAAmH,YCxCAvN,EAAA,qBAAA,WAEA,OAEA+qB,UAAA,KAQA9iB,QACA+iB,wBAAA,iBACAC,kCAAA,qBACAC,qCAAA,eACAC,sCAAA,YACAC,6CAAA,gBACAC,oCAAA,kBACAC,sBAAA,WACAC,uBAAA,UACAC,sBAAA,aACAC,mCAAA,UACAC,qCAAA,YAUAC,iBAAA,SAAAphB,GAEA,MAAAA,GAAAG,KAAA,mBACA3E,EAAAvE,IAAA+I,EAAAG,KAAA,mBAAAnJ,MAAA,KAAA,SAAAqqB,GACA,MAAAA,GAAAC,UAIA,IAAA,IAAA,IAAA,SAAA,OAWAC,YAAA,SAAAvhB,GAEA,MAAA,UAAAA,EAAA,GAAAvC,QACAuC,EAAA0R,MAGA1R,EAAAG,KAAA,oBAAAH,EAAAwhB,SAAA,aAIAhmB,EAAAimB,gBAAAzhB,EAAA8H,OAAAjM,KAAAulB,iBAAAphB,IAHAA,EAAA0hB,QAcAC,YAAA,SAAA7W,GACA,GAAA9K,GAAA1K,EAAAwV,EAAAsC,OACA,OAAApN,GAAAG,KAAA,2BAAAtE,KAAA0lB,YAAAvhB,IAUA4hB,SAAA,SAAA9W,GAEA,GAAAoK,GAAArZ,KACAmE,EAAA1K,EAAAwV,EAAAsC,QACAsJ,EAAA7a,KAAA0lB,YAAAvhB,GACAqT,EAAArT,EAAAG,KAAA,YAEA,KAAAH,EAAAG,KAAA,aAAAH,EAAAG,KAAA,mBAAAuW,EAAAtf,OAAA,EACA,OAAA,CAGA,IAAA,QAAAic,GAAA,UAAAA,GACA,IAAAxX,KAAAgmB,cAAAhmB,KAAA0lB,YAAAvhB,IACA,OAAA,MAGA,cAAAqT,GAEAoG,KAAA6B,KAAAvlB,MACAkK,MACAsb,OAAA,eACAC,YAAA,gBACAC,UAAA5O,OAAAyG,aAAAoI,YAAArZ,IAAA,MACA7H,GAAA0a,EAAAlS,MAAAX,IAAA,MACA0U,MAAA7B,EAAAlS,MAAAX,IAAA,SACAyf,KAAApL,GAEAqL,WAAA,WACAtI,KAAAuI,QAAA9X,MAAAlK,EAAA6G,QAAA,+BAAA,UAEAqL,QAAA,SAAA+P,GAEAA,EAAApH,WAAAoH,EAAAH,OACA5M,EAAAlS,MAAA8O,IAAA,YAAAmQ,EAAApH,WACA3F,EAAAlS,MAAA8O,IAAA,OAAAmQ,EAAAH,MACA5M,EAAAvT,YAQA,QAAA,GAUAugB,iBAAA,WAEArmB,KAAAmE,IAAA2F,KAAA,6BAAAzJ,KAAA,WAEA5G,EAAAuG,MAAAsmB,gBACAC,OAAA9sB,EAAAuG,MAAAsE,KAAA,qBAAA,cACAsc,eAAAxhB,KAAA3F,EAAAuG,MAAAsE,KAAA,yBAAA,QAAA7K,EAAAuG,MAAAsE,KAAA,wBACAqc,eAAAvhB,KAAA3F,EAAAuG,MAAAsE,KAAA,yBAAA,QAAA7K,EAAAuG,MAAAsE,KAAA,wBACAkiB,QAAA,SAAAC,EAAAC,GACAA,EAAAC,aAcAC,oBAAA,WAEA,GAAAvN,GAAArZ,IAEAA,MAAAmE,IAAA2F,KAAA,2CAAAzJ,KAAA,WAEA,GAAAwmB,GAAAptB,EAAAuG,MAAAsE,KAAA,mBAAAnJ,MAAA,KACAmJ,EAAA7K,EAAAuG,MAAAsE,KAAA,kBAEAwiB,EAAA,GAAAC,OAAA/mB,MACAgnB,SACAC,SAAAJ,GACAK,UACAC,UACAC,KACAjU,IAAA,EACAkU,QAAA,SAAAC,EAAAC,GACA,OAAA,IAGAC,IACArU,IAAA,GACAkU,QAAA,SAAAC,EAAAC,GAEA,MADAT,GAAAjnB,KAAA8mB,QACA,OAMA7M,YAAArgB,EAAAuG,MAAAsE,KAAA,oBACAmjB,MAAA,UAGAX,GAAAhO,GAAA,cAAA,SAAA4O,EAAAC,EAAAC,GACAvO,EAAAlS,MAAA8O,IAAA3R,EAAA+U,EAAAqM,YAAAjsB,EAAAqtB,EAAAjnB,UAGAD,SAAA8b,OAAA5T,QAAA,qBAAAgf,EAAArtB,EAAAuG,MAAAqZ,MAYAwO,aAAA,WAEA7nB,KAAAmE,IAAA2F,KAAA,gCAAAge,aACAC,MAAA,UAaAC,QAAA,SAAA/Y,GAEAA,EAAAuV,kBAEAxkB,KAAAmH,MAAA8O,IAAA,cAAA,GAAAnP,QAAA,GAEA,IAAAuS,GAAArZ,IACAvG,GAAAwV,EAAAsC,OACAvR,MAAA8lB,YAAA7W,KAIAoK,EAAA0M,SAAA9W,GAGAjP,KAAAioB,WAAAhZ,GAFAoK,EAAA6O,aAAAjZ,KAgBAkZ,SAAA,SAAAlZ,GAEAA,EAAAuV,kBACAxkB,KAAAmH,MAAA8O,IAAA,cAAA,GAAAnP,QAAA,KAYAshB,SAAA,SAAAnZ,GAEAA,EAAAsV,iBACAtV,EAAAuV,iBAEA,IAAAqB,IAAA5W,EAAAoZ,eAAApZ,GAAAqZ,cAAAC,QAAA,aACAvX,QAAApI,SAAA4f,YAAA,cAAA,EAAA3C,IAWA4C,UAAA,SAAAxZ,GAEA,GAIA4G,GAJA1R,EAAA1K,EAAAwV,EAAAsC,QACAmX,EAAAvkB,EAAAG,KAAA,YACAA,EAAAH,EAAAG,KAAA,QACAqkB,EAAAxkB,EAAA2F,KAAA,kBAGA4e,IACA7S,KACAA,EAAA8S,EAAAvtB,IAAA,WACA,MAAA4E,MAAAnD,QACA2J,OAEAqP,EAAA8S,EAAA,GAAA9rB,MAGAmD,KAAAmH,MAAA8O,IAAA3R,EAAAuR,IAWA+S,gBAAA,SAAA3Z,GAEA,GAAA9K,GAAA1K,EAAAwV,EAAAsC,QACAjN,EAAAH,EAAAG,KAAA,QACAuR,EAAA1R,EAAA0R,KAEA7V,MAAAmH,MAAA8O,IAAA3R,EAAAuR,IAYAgT,WAAA,SAAA5Z,GAEAA,EAAAuV,iBAEA,IACArR,GAAAlE,EAAAY,OAAAZ,EAAA6Z,QACAC,EAAA9Z,EAAAmB,QAGA,QAAA+C,GAEA,IAAA,IAEA4V,IACA9Z,EAAAsV,iBACAtV,EAAAsC,OAAAoV,OAEA,MAEA,KAAA,IACA1X,EAAAsV,iBACAvkB,KAAAkoB,aAAAjZ,GACAA,EAAAsC,OAAAoV,SAcAqC,eAAA,SAAA/Z,GAEAA,EAAAuV,iBAEA,IAAAnL,GAAArZ,KACAmE,EAAA1K,EAAAwV,EAAArD,cAEAyN,GAAAsL,UAEAtL,EAAAsL,UAAAsE,SAAAA,SAAAC,MAAA,YAIA7P,EAAAsL,UAAAwE,GAAAC,MAAAC,OAAAC,WAAAH,GAAAC,OACAlO,MAAA0C,KAAAC,KAAAC,UAAA,mBACAyL,QACA1D,KAAAjI,KAAAC,KAAAC,UAAA,mBAEA0L,UAAA,IAGAnQ,EAAAsL,UAAA7L,GAAA,SAAA,WAEA,GAGA2Q,GAHAnW,EAAAnP,EAAAG,KAAA,mBACAolB,EAAArQ,EAAAsL,UAAAgF,QAAAnjB,IAAA,aAAA5F,QAAAgpB,SACAhQ,EAAAP,EAAAlS,MAAAX,IAAArC,EAAAG,KAAA,kBAIAmlB,GADAnW,GAAAoW,EAAAG,MAAAvW,GACAoW,EAAAG,MAAAvW,GAAAmW,IAEAC,EAAAD,IAGA7P,EAAA3D,KACAtX,GAAA+qB,EAAA/qB,GACAgY,IAAA8S,OAOApQ,EAAAsL,UAAAmF,QAYAC,aAAA,SAAA9a,GAEAA,EAAAsV,iBAEAvkB,KAAAmH,MAAAX,IAAA/M,EAAAwV,EAAArD,eAAAtH,KAAA,mBAAA2R,KACAtX,GAAA,GACAgY,IAAA,MAaAuR,aAAA,SAAAjZ,GACA,GAAA9K,GAAA1K,EAAAwV,EAAAsC,QACAsE,EAAA1R,EAAAG,KAAA,wBACAH,GAAA8H,KAAA4J,IAUAoS,WAAA,SAAAhZ,GAEA,GAAA9K,GAAA1K,EAAAwV,EAAAsC,QACAsE,EAAA7V,KAAA0lB,YAAAvhB,EAEAnE,MAAAmH,MAAA8O,IAAA9R,EAAAG,KAAA,kBAAAuR,IAWAmU,cAAA,SAAA/a,GAEAA,EAAAuV,iBACA,IAGA3O,GAHA1R,EAAA1K,EAAAwV,EAAAsC,QACAjN,EAAAH,EAAAG,KAAA,QACAU,EAAAb,EAAAG,KAAA,gBASA,IALAuR,EADA1R,EAAAwC,GAAA,YACAxC,EAAAG,KAAA,WAAAH,EAAAG,KAAA,WAAA,MAEAH,EAAAG,KAAA,YAAAH,EAAAG,KAAA,YAAA,MAGA,IAAAA,EAAA/G,QAAA,KAAA,CAEA,GAAApC,GAAAmJ,EAAAnJ,MAAA,IAEA,YAAAA,EAAA,GACA6E,KAAAmH,MAAA+Q,aAAAjC,IAAA9a,EAAA,GAAA0a,GAEA7V,KAAAmH,MAAAX,IAAArL,EAAA,IAAA8a,IAAA9a,EAAA,GAAA0a,OAMA7V,MAAAmH,MAAA8O,IAAA3R,EAAAuR,EAMA,IAFA7V,KAAA8H,QAAAxD,EAAA3I,QAAA,IAAA,KAAA,UAAAka,IAEA7Q,GAAA,QAAAA,EAAA,CACA,GAAAqU,GAAArZ,IACAV,YAAA,WACA+Z,EAAAvT,UACA,OAaAmkB,YAAA,SAAAtrB,EAAAurB,GAEAA,EAAAA,MAEAf,GAAAgB,OAAAvkB,OAAAjH,GAEAwqB,GAAAgB,OAAAzmB,WAAA/E,EAAAlF,EAAAkI,QAAA,EAAAwnB,GAAAgB,OAAAC,sBACAC,cAAA,EACAC,SACAC,SAAA,8GACAC,SAAA,gHACAC,MAAA9qB,EAAA2O,KAAAtO,KAAA0qB,gBAAA1qB,QAEAkqB,KAWAS,mBAAA,SAAA1b,GAEA,GACA2b,GAAAnxB,EAAAwV,EAAArD,eACAif,EAAAD,EAAAE,QAAA,KACApE,EAAAkE,EAAAG,KAAA,mBACAC,EAAAH,EAAAvmB,KAAA,QACA2hB,EAAAS,EAAA7Q,MACAoV,EAAAD,EAAArvB,QAAAsqB,EAAA,GAGA2E,GAAAngB,OAGAogB,EAAAhhB,KACAqhB,MAAA,OACAC,iBAAA,OACAC,kBAAA,SAIAP,EAAAhF,KAAAoF,EAAAztB,UAAA,EAAAytB,EAAA1vB,OAAA,IAGAmrB,EAAA2E,OAAAjpB,SAaAsoB,gBAAA,SAAAP,GAEA,GAAA9Q,GAAArZ,KACAsrB,EAAA7xB,EAAA,IAAA0wB,EAAAxrB,IACA4sB,EAAAD,EAAAtgB,QAAA,yBACAwgB,EAAAD,EAAAzhB,KAAA,eACA9P,EAAAsxB,EAAAhnB,KAAA,iBAEAknB,GAAAjwB,QACAiwB,EAAAC,UAAAF,EAAAzhB,KAAA,qBAIAqgB,EAAArR,GAAA,SAAA,SAAA7J,GACAoK,EAAAlS,MAAA8O,IAAAjc,EAAAmvB,GAAAgB,OAAAuB,WAAAvB,EAAAxrB,OAIA2sB,EAAAxS,GAAA,QAAA,SAAA7J,GACAoK,EAAAlS,MAAA8O,IAAAjc,EAAAsxB,EAAAzV,SAIA0V,EAAAzS,GAAA,QAAA,gCAAA,WACAxZ,WAAA,WACAgsB,EAAAxjB,QAAA,UACA,OAKAke,cAAA,SAAA2F,GAEA,GAAAC,GAAAhjB,SAAAijB,cAAA,IAEA,OADAD,GAAAE,KAAAH,EACAC,EAAAG,MAAAH,EAAAG,OAAA/a,OAAAgb,SAAAD,SC7mBAnyB,EAAA,uBAAA,WAEA,OAWAiV,SAAA,SAAAI,EAAAC,GAGA,GAAAA,EAAAI,OAAAqW,SAAA,gBAAA,CACA,GAAAroB,GAAA0C,KAAAsI,kBAAAgC,WAAAhN,MAAA4R,EAAA+c,OAGA,OAFA/c,GAAA+c,OAAArmB,aACA5F,MAAAwC,WAAAqB,QAAA4L,GAAAnS,IAIA,GAAA+R,GAAAH,EAAAI,OACAC,EAAAF,EAAAjL,KAAA,OACA,IAAAmL,GAAAA,EAAA/M,WAAA,CAEA,GAAA4M,GAAApP,KAAAsI,kBAAAgC,WAAAhN,MAAA4R,EAAA3I,MACAiJ,EAAAD,EAAA/M,WAAAgE,IAAA0I,EAAA3I,KAAAjC,KAAA,kBACAiL,GAAA/M,WAAAoD,OAAA4J,GACAxP,KAAAwC,WAAAqB,IAAA2L,GAAAC,GAAAL,IACAI,EAAAhN,WAAAxC,KAAAwC,WACAxC,KAAAqF,iBAAAmK,QCjCA5V,EAAA,sBAAA,WAEA,OAQAsyB,6BAAA,WAEA,GAAAlsB,KAAAmH,MAAA3E,WAAA,CAIA,GAAAgV,GAAAxX,KAAAmH,MAAAX,IAAA,OAEAxG,MAAAmH,MAAA3E,WAAA5B,UAAAZ,KAAAmH,MACAnH,KAAAmE,IAAA2F,KAAA,cAAA0N,GAAA/M,OACAzK,KAAAmH,MAAA3E,WAAAihB,SAAAzjB,KAAAmH,OACAnH,KAAAmE,IAAA2F,KAAA,gBAAA0N,GAAA/M,SAaAse,MAAA,SAAAoD,EAAAC,GAEA,GAAA5pB,GAAAxC,KAAAmH,MAAA3E,UAEAA,GAAAoD,OAAA5F,KAAAmH,OACA3E,EAAAqB,IAAA7D,KAAAmH,OAAAsI,GAAA2c,IACA5pB,EAAAsF,QAAA,YAUAukB,WAAA,SAAA5tB,GAEAA,EAAA8lB,gBACA,IAAAjnB,GAAA0C,KAAAmH,MAAA3E,WAAAjF,QAAAyC,KAAAmH,MACAnH,MAAA+oB,MAAAzrB,EAAAA,EAAA,IAUAgvB,SAAA,SAAA7tB,GAEAA,EAAA8lB,gBACA,IAAAjnB,GAAA0C,KAAAmH,MAAA3E,WAAAjF,QAAAyC,KAAAmH,MACAnH,MAAA+oB,MAAAzrB,EAAAA,EAAA,OCpEA1D,EAAA,oBAAA,WAEA,OAEA2yB,iBAMA5C,MAAA,GAMAtX,SASAma,YAAA,SAAApyB,GAEA,QAAA4F,KAAAqS,MAAAjY,IACA4F,KAAAqS,MAAAjY,IAOAqyB,iBAAA,SAAA5qB,GAEAlC,EAAAU,KAAAwB,EAAA,SAAA6qB,EAAAzd,GAEAjP,KAAAusB,cAAAtd,GAAAyd,EACA9sB,SAAA8b,OAAA5C,GAAA7J,EAAAyd,EAAA1sB,OAEAA,OAIA2sB,mBAAA,WAEAhtB,EAAAU,KAAAL,KAAAusB,cAAA,SAAAG,EAAAzd,GAEArP,SAAA8b,OAAAkR,IAAA3d,EAAAyd,EAAA1sB,YACAA,MAAAusB,cAAAtd,IAEAjP,OAWA6sB,eAAA,SAAAzyB,GAEA,GAAAuL,GAAA3F,KAAAwsB,YAAApyB,EAEAuL,IAIAA,EAAAmnB,WAGAntB,EAAAgU,QAAAhO,EAAAmnB,SAAAza,SACA1M,EAAAmnB,SAAAH,qBACAhnB,EAAAmnB,SAAAC,mBAGApnB,EAAAmnB,SAAAF,MACAjnB,EAAAmnB,SAAAF,IAAA,KAAA,KAAA,MACAjnB,EAAAmnB,SAAAlnB,SACAD,EAAAmnB,SAAAE,mBAMArnB,EAAAmnB,SAAA,OAYAC,gBAAA,WAEAptB,EAAAU,KAAAL,KAAAqS,MAAA,SAAAjO,EAAAhK,GAEA4F,KAAA6sB,eAAAzyB,IAEA4F,OAWAitB,gBAAA,SAAAC,GAEAA,EAAAA,MAEAvtB,EAAAU,KAAAL,KAAAqS,MAAA,SAAAjO,EAAAhK,GAEA4F,KAAA2pB,QAAAvlB,EAAAulB,MAEA3pB,KAAAmtB,eAAA/yB,EAAA8yB,GAIAltB,KAAA6sB,eAAAzyB,IAIA4F,OAYAmtB,eAAA,SAAA/yB,EAAA8yB,GAEA,GAAAvnB,GAAA3F,KAAAwsB,YAAApyB,EAEAuL,KAIA3F,KAAA6sB,eAAAzyB,GAEAuL,EAAAmnB,WACAnnB,EAAAmnB,SAAA,GAAAnnB,GAAAiS,MAAAsV,IAGAvnB,EAAAmnB,SAAAhnB,WAYAsnB,UAAA,SAAAzD,GAGA,MADA3pB,MAAA2pB,MAAAA,EACA3pB,SC9KApG,EAAA,sBAAA,WAEA,OAQAiI,QACAwrB,oCAAA,eAUAC,YAAA,SAAAre,GAEAA,IACAA,EAAAsV,iBACAtV,EAAAuV,kBAGA,IAAAC,GAAA7G,KAAAC,KAAAliB,QAAA,uDACA+oB,KAAA1kB,KAAAmH,MAAAkY,iBAGArO,QAAA4D,QAAA6P,KAEAzkB,KAAAmH,MAAA3E,YACAxC,KAAAmH,MAAA3E,WAAAoD,OAAA5F,KAAAmH,OAIAvH,SAAA8b,OAAA5T,QAAA,gBAAA9H,KAAAmH,OAGAnH,KAAA8H,QAAA,gBAAA9H,KAAAmH,YC1CAvN,EAAA,iBACA,oBACA,kBACA,oBACA,mBACA,iBACA,oBAEA,SACA2zB,EACAC,EACAC,EACAC,EACAC,EACAC,GAGA,OACAL,WAAAA,EACAC,SAAAA,EACAC,WAAAA,EACAC,UAAAA,EACAC,QAAAA,EACAC,UAAAA,KCxBAh0B,EAAA,yBACA,qBACA,gBACA,iBACA,SACAi0B,EACAC,EACAC,GAGA,MAAA,YAaA,QAAAvnB,GAAAgR,EAAApd,EAAAgK,EAAAT,GAEA,MAAA6T,GAAApd,GAKA,GAAAod,GAAApd,GAAAgK,EAAAT,IAJAsc,QAAAC,IAAA,IAAA9lB,EAAA,iBACA,GAkGA,MAlFA4F,MAAA6X,eAAA,SAAAzd,EAAAgK,EAAAT,GAEA,MAAA6C,GAAAqnB,EAAAzzB,EAAAgK,EAAAT,IAaA3D,KAAA2X,UAAA,SAAAvd,EAAAgK,EAAAT,GAEA,MAAA6C,GAAAsnB,EAAA1zB,EAAAgK,EAAAT,IAYA3D,KAAAguB,YAAA,WAKA,IAHA,GAAAroB,GAAArJ,UAAA,GACAxB,EAAA,EAEAwB,UAAAxB,IAAA,CAEA,GAAAmzB,GAAA3xB,UAAAxB,EACAizB,GAAAE,KAEAtoB,EAAA9D,QAAAksB,EAAAE,GAAApsB,SACA8D,EAAA9D,OAAAlC,EAAA8W,SAAA9Q,EAAA9D,OAAAksB,EAAAE,GAAApsB,SAGA8D,EAAAhG,EAAA8W,SAAA9Q,EAAAooB,EAAAE,KAIAnzB,IAGA,MAAA8E,UAAAwB,KAAAO,OAAAgE,IAYA3F,KAAAkuB,oBAAA,SAAA9zB,EAAA6d,GAEA4V,EAAAzzB,GAAAwF,SAAAmE,WAAApC,OAAAsW,IAYAjY,KAAAmuB,eAAA,SAAA/zB,EAAA6d,GAEA6V,EAAA1zB,GAAA0zB,EAAA,SAAAnsB,OAAAsW,IAIAjY,QC7HApG,EAAA,uBAAA,WAEA,MAAA,UAAAswB,GAEA,GAAA7Q,GAAArZ,KACA0W,EAAAwT,EAAAxT,UAAA,CAQA1W,MAAAouB,QAAA,WAEA/U,EAAA6G,IAAA,wCACAxJ,GAAA,GAUA1W,KAAAquB,OAAA,WAEA3X,GAAA,EACA2C,EAAA6G,IAAA,wCAWAlgB,KAAAkgB,IAAA,WAEAxJ,GAIA/W,EAAAU,KAAA/D,UAAA,SAAA8H,GACA6b,QAAAC,IAAA9b,MAWApE,KAAA2K,OAAA,WAEA+L,EACA2C,EAAA+U,UAEA/U,EAAAgV,UAMA3X,GACA2C,EAAAgV,YCtEAz0B,EAAA,yBAAA,WASA,MAAA,UAAAojB,GAGA,GAAAsR,GAAAtR,CA4BA,OA3BArd,GAAAU,KAAAiuB,EAAA,SAAA9W,GACA7X,EAAAU,KAAAmX,EAAA,SAAAuF,GACAA,EAAAwR,QAAA,MAcAvuB,KAAAwG,IAAA,SAAAuW,EAAAyR,EAAArnB,GAOA,MAJAmnB,GAAAE,KACAzR,EAAApd,EAAAgC,OAAAob,EAAAuR,EAAAE,KAGAzR,GAIA/c,QCxCApG,EAAA,sBAAA,WAEA,MAAA,UAAAsqB,EAAAgG,GAkEA,QAAAuE,GAAArqB,EAAAsqB,GAYA,MAVA,YAAAtqB,EAAAma,SACAna,EAAAuqB,YAGAvqB,EAAAma,OAAA,QACA,gBAAAmQ,KACAA,GAAAA,IAEAtqB,EAAAuqB,QAAAvqB,EAAAuqB,QAAA7yB,OAAA4yB,GAEAtqB,EAUA,QAAAwqB,KAEA,GAAAxqB,KACAA,GAAAyqB,QAAAxV,EAAAyV,sBACA1qB,EAAA2qB,oBAAA1V,EAAA0V,oBAAA3qB,EAAAyqB,SACAzqB,EAAA4qB,OAAA3V,EAAA2V,OAEAhe,OAAAyG,aAAA0I,MAAAD,IAAA,gCAAA9b,EAAA,kCAEAxE,SAAA8b,OAAA5T,QAAA,sBAAA1D,GAUA,QAAA6qB,KAGA,IAAA5V,EAAA2V,OAAA,CAIA,GAAAH,GAAAxV,EAAAyV,qBAGAzV,GAAA0V,oBAAAF,KAEAA,EAAAlwB,GAAAulB,EAAA1d,IAAA,MAEAoX,KAAA6B,KAAAvlB,MACAkK,MACAsb,OAAA,eACAC,YAAA,YACAC,UAAAiP,EAAAlwB,GACA8Y,aAAAyX,KAAAC,UAAAN,IAEA3I,WAAA,WAEAlV,OAAAyG,aAAA0I,MAAAD,IAAA,sCAAA2O,EAAA,wCAEAxV,EAAA2V,QAAA,EAEApvB,SAAA8b,OAAA5T,QAAA,iBAAAuR,IAGA0G,MAAA,SAAAC,EAAAzB,EAAAwB,GAEA/O,OAAAyG,aAAA0I,MAAAD,IAAA,qCAAA9b,KAAA,uCAEAiV,EAAA2V,QAAA,EAEApvB,SAAA8b,OAAA5T,QAAA,iBAAAuR,GACAkF,OAAA,QACAoQ,QAAA3O,EAAAoP,aAAA,KAAArP,EAAA,IAAAxB,EAAA,OAIAlI,QAAA,SAAA+J,GAEAA,EAAA3I,eAIAzG,OAAAyG,aAAA0I,MAAAD,IAAA,uCAAAE,EAAA,yCAEAA,EAAA3I,aAAA4X,EAAAjP,EAAA3I,cACA2I,EAAA3I,aAAA6X,EAAAlP,EAAA3I,cAEA4B,EAAA2V,QAAA,EAEApvB,SAAA8b,OAAA5T,QAAA,iBAAAuR,EAAA+G,EAAA3I,oBAwBA,QAAA8X,GAAApoB,GAEA,GACA0U,GADAD,IAIA,IAAAzU,EAAAX,IAAA,cACA,MAAAoV,EAKAgB,GAAAzV,KAAA,IAAAA,EAAAX,IAAA,eAEAoV,EAAAjc,EAAAoB,MAAAoG,EAAAuO,YACAmG,EAAA,SAKAD,EAAAzU,EAAAwO,oBACAkG,EAAA,UAIA,IAAA2T,GAAAroB,EAAA,kBAAAA,EAAA6Q,oBAkBA,OAjBA4D,GAAAjc,EAAA8vB,KAAA7T,EAAA,SAAA/F,EAAA1C,GAIA,MAAA,KAAAA,EAAA5V,QAAA,OAEA,IAAAiyB,EAAAjyB,QAAA4V,KAOAhM,EAAAwU,cACAC,EAAAzU,EAAAwU,YAAAC,EAAAC,IAGAD,EAgBA,QAAA8T,GAAAC,GAEA,GAAAC,EAoCA,OAlCAD,aAAA/vB,UAAAkV,OAEA8a,EAAAL,EAAAI,GAEAA,EAAA3Y,mBAEArX,EAAAU,KAAAsvB,EAAA3X,kBAAA,SAAAhe,GAEA,GAAAsQ,GAAAolB,EAAAC,EAAAnpB,IAAAxM,GACA2F,GAAAgU,QAAArJ,KACAslB,EAAA51B,GAAAsQ,KAQA3K,EAAAgU,QAAAic,KACAA,EAAAjxB,GAAAgxB,EAAAnpB,IAAA,QAGAmpB,YAAA/vB,UAAAmE,aAEA6rB,KACAD,EAAAtvB,KAAA,SAAA8G,GACA,GAAA0oB,GAAAH,EAAAvoB,EACAxH,GAAAgU,QAAAkc,IACAD,EAAArzB,KAAAszB,MAMAD,EAWA,QAAAhT,GAAAzV,GAEA,OAAAxH,EAAAsd,SAAA9V,EAAAxI,KAAA,IAAAwI,EAAAxI,GAAApB,QAAA,SAaA,QAAAuyB,GAAA3oB,EAAA/C,GAEAxE,SAAA8b,OAAA5T,QAAAX,EAAAX,IAAA,QAAA,0BAAAW,EAAA/C,EAEA,IAAAqrB,IAAA,KAAA,UAEAtoB,GAAA6P,mBACAyY,EAAA3zB,OAAAqL,EAAA6Q,mBAGArY,EAAAU,KAAAV,EAAA8vB,KAAArrB,EAAAqrB,GAAA,SAAA5Z,EAAA7b,GAEA2F,EAAAqW,QAAA7O,EAAAX,IAAAxM,GAAA6b,WACA1O,GAAAyM,gBAAA5Z,GACAmN,EAAA8N,eAAAjb,GAAA6b,KAMA1O,EAAA4oB,MAAA,cAaA,QAAAV,GAAAjrB,GAGA,GAAA4rB,IACAvnB,OAAAwnB,EACAC,MAAAC,EAgCA,OA7BAxwB,GAAAU,KAAA2vB,EAAA,SAAAI,EAAAjd,GAEA,GAAA/O,EAAA+O,GAAA,CAEA,GAAAkd,KAEA1wB,GAAAU,KAAA+D,EAAA+O,GAAA,SAAAmd,GAGAA,EAAAvQ,MAMAsQ,EAAA9zB,KAAA+zB,EAAAvQ,OAJAqQ,EAAAxqB,OAAA0qB,EAAA3xB,MAUA0xB,EAAA90B,QACAoE,EAAAgC,OAAAyC,EAAAqqB,EAAArqB,EAAAisB,OAOAjsB,EAcA,QAAAmsB,GAAAnsB,EAAAoT,EAAA5N,EAAA4mB,GAEA,IAAApsB,EAAAoT,GACA,MAAApT,EAGA,IAAAwF,EAAApD,IAAAgR,YAAA5X,UAAAkV,MAAA,CAEA,GAAAwb,GAAAlsB,EAAAoT,EAEA,IAAA8Y,EAAAvQ,MAEApgB,EAAAgC,OAAA6uB,EAAA/B,EAAA+B,EAAAF,EAAAvQ,YAEA,CAEA,GAAA5Y,GAAAyC,EAAApD,IAAAgR,EAGA8Y,GAAA3xB,IAAA2xB,EAAAG,UACAtpB,EAAA8O,IAAA,KAAAqa,EAAA3xB,UACAwI,GAAAyM,gBAAAjV,IAEAmxB,EAAA3oB,EAAAmpB,GAGAnpB,EAAA6P,mBAEArX,EAAAU,KAAA8G,EAAA6Q,kBAAA,SAAAb,GACAxX,EAAAgC,OAAAyC,EAAAoT,GAAA+Y,EAAAnsB,EAAAoT,GAAAL,EAAAhQ,EAAAqpB,WAOA5mB,GAAApD,IAAAgR,YAAA5X,UAAAmE,YAEApE,EAAAU,KAAA+D,EAAAoT,GAAA,SAAA8Y,EAAAhzB,GAEA,GAAAgzB,EAAAvQ,MAEApgB,EAAAgC,OAAA6uB,EAAA/B,EAAA+B,EAAAF,EAAAvQ,YAEA,CAEA,GAAA5Y,GAAAyC,EAAApD,IAAAgR,GAAAhR,IAAA8pB,EAAAG,QAGAH,GAAA3xB,IAAA2xB,EAAAG,UACAtpB,EAAA8O,IAAA,KAAAqa,EAAA3xB,UACAwI,GAAAyM,gBAAAjV,IAEAmxB,EAAA3oB,EAAAmpB,GAGAnpB,EAAA6P,mBAEArX,EAAAU,KAAA8G,EAAA6Q,kBAAA,SAAAb,GACAxX,EAAAgC,OAAAyC,EAAAoT,GAAA+Y,EAAAnsB,EAAAoT,GAAAla,GAAA6Z,EAAAhQ,EAAAqpB,QAWA,OAAAA,GAaA,QAAAlB,GAAAlrB,GAGA,MAAAA,GAAAssB,SAIAtsB,EAAAssB,UACAtsB,EAAAmsB,EAAAnsB,EAAAssB,QAAA,WAAAxM,EAAA9f,IAGAA,GAPAA,EA9dApE,KAAAgvB,QAAA,CAEA,IAAA3V,GAAArZ,KACA2wB,GAAA,EACAC,EAAA,KACAC,EAAA3G,EAAA2G,mBAAA,IACAZ,EAAA,GAAArwB,UAAAmE,WACAosB,EAAA,GAAAvwB,UAAAmE,UAssBA,OAhNA/D,MAAA8uB,oBAAA,WAEA,OACArmB,OAAAwnB,EAAA/oB,MAAA,MACAgpB,MAAAC,EAAAjpB,MAAA,MACAwpB,QAAAhB,EAAAxL,KAaAlkB,KAAA+uB,oBAAA,SAAAF,GAaA,WAXA,KAAAA,IACAA,EAAAxV,EAAAyV,yBAIAnvB,EAAAmK,KAAA+kB,EAAA,SAAAzqB,GAEA,OAAA,IAAAzE,EAAAgU,QAAAvP,MAcApE,KAAA8wB,SAAA,WACAH,EACAxH,GAAA4H,UAAAC,aAEA/B,KAYAjvB,KAAAixB,mBAAA,SAAAC,GACAL,EAAAK,EACAN,GACAO,cAAAP,GAEAC,IACAD,EAAAQ,YAAAxC,EAAAiC,KAoBAjxB,SAAA8b,OAAA5C,GAAA,iBAAA,SAAA3R,GAGAyV,EAAAzV,IAIA8oB,EAAApsB,IAAAlE,EAAAoB,MAAAoG,EAAAuO,eASA9V,SAAA8b,OAAA5C,GAAA,gBAAA,SAAA3R,GAGA,IAAAyV,EAAAzV,GAAA,CAIA,GAAA/C,GAAAzE,EAAAoB,MAAAoG,EAAAuO,WAEAvO,GAAAwR,eACAvU,EAAAzF,GAAAwI,EAAAwR,gBAGAwX,EAAAtsB,IAAAO,MAoBA3K,EAAAmP,UAAAkQ,GAAA,iBAAA,SAAA7J,EAAA7K,GAGA,IAAAiV,EAAA2V,OAAA,CAIA,GAAAH,GAAAxV,EAAAyV,qBAGAzV,GAAA0V,oBAAAF,KAEAA,EAAAlwB,GAAAulB,EAAA1d,IAAA,MACA6S,EAAA2V,QAAA,EACA5qB,EAAAqT,aAAAyX,KAAAC,UAAAN,IAIA7d,OAAAyG,aAAA0I,MAAAD,IAAA,iCAAA9b,EAAA,mCAEAxE,SAAA8b,OAAA5T,QAAA,iBAAAuR,MASA5f,EAAAmP,UAAAkQ,GAAA,iBAAA,SAAA7J,EAAA7K,GAEAA,EAAAqT,eAIAzG,OAAAyG,aAAA0I,MAAAD,IAAA,iCAAA9b,EAAA,mCAEAA,EAAAqT,aAAA4X,EAAAjrB,EAAAqT,cACArT,EAAAqT,aAAA6X,EAAAlrB,EAAAqT,cAEA4B,EAAA2V,QAAA,EAEApvB,SAAA8b,OAAA5T,QAAA,iBAAAuR,EAAAjV,EAAAqT;8DASAhe,EAAAmP,UAAAkQ,GAAA,kBAAA,SAAA7J,EAAA7K,GAEA4M,OAAAyG,aAAA0I,MAAAD,IAAA,kCAAA9b,EAAA,oCAEAiV,EAAA2V,QAAA,EAEApvB,SAAA8b,OAAA5T,QAAA,iBAAAuR,GACAkF,OAAA,QACAoQ,QAAAvqB,EAAAgrB,aAAA,KAAAhrB,EAAAma,OAAA,IAAAna,EAAAitB,WAAA,QA7qBA,eAGA,KAAAlI,GAAA4H,YAEA/f,OAAAyG,aAAA0I,MAAAD,IAAA,yDACAyQ,GAAA,GAKAE,GACAxX,EAAA4X,mBAAAJ,GAIAp3B,EAAAuX,QAAA8H,GAAA,eAAA,WAEA,GAAAO,EAAA0V,sBAEA,MADAH,KACA,sDA0qBA5uB,QCjtBApG,EAAA,gBACA,oBACA,kBACA,mBACA,oBACA,SACA2zB,EACAC,EACAE,EACAE,GAGA,MAAAhuB,UAAAwB,KAAAO,OAAAhC,EAAA8W,UAQAf,WAAA,WACA,OACA4b,UAAAtxB,KAAAmH,MAAAxI,GACA4yB,kBAAAvxB,KAAAmH,MAAAX,IAAA,oBAQAgrB,UAAA,gCAQA3vB,OAAAlC,EAAA8W,UACAgb,qBAAA,qBACAC,mBAAA,mBACAC,yBAAA,yBACAC,sBAAA,eACAC,sBAAA,eACAC,0BAAA,WACAC,4BAAA,cACAxE,EAAA1rB,OAAA2rB,EAAA3rB,OAAA+rB,EAAA/rB,QAQAlD,GAAA,WACA,MAAA,eAAAqB,KAAAmH,MAAAxI,IAOAiD,QAAA,KAMAsK,SAAAid,GAAAjd,SAAA,wBAQAxI,WAAA,WAEA1D,KAAA8F,SAEA9F,KAAAqL,SAAArL,KAAAmH,MAAA,SAAAnH,KAAA8F,QAEAlG,SAAA8b,OAAA5C,GAAA,kBAAA9Y,KAAAyoB,UAAAzoB,MACAJ,SAAA8b,OAAA5C,GAAA,mBAAA9Y,KAAAyoB,UAAAzoB,OAUA8F,OAAA,WASA,MAPA9F,MAAAmE,IAAA8H,KAAAjM,KAAAkM,SAAAlM,KAAAmH,QACAnH,KAAAksB,+BACAlsB,KAAAmH,MAAAX,IAAA,aACAxG,KAAAmE,IAAAE,SAAA,YAEArE,KAAAmE,IAAA0I,YAAA,YAEA7M,MAWAgyB,uBAAA,WAEApyB,SAAA8b,OAAA5T,QAAA,kBAAA9H,KAAAmH,MAAA,cACAnH,KAAAmH,MAAA8O,IAAA,aAAA,IAWAgc,mBAAA,WAEAryB,SAAA8b,OAAA5T,QAAA,kBAAA9H,KAAAmH,MAAA,UACAnH,KAAAmH,MAAA8O,IAAA,aAAA,IAWAic,iBAAA,WAEAtyB,SAAA8b,OAAA5T,QAAA,kBAAA9H,KAAAmH,MAAA,QACAnH,KAAAmH,MAAA8O,IAAA,aAAA,IAYAwS,UAAA,SAAAthB,GAEAnH,KAAAmH,MAAAxI,KAAAwI,EAAAxI,IACAqB,KAAAmH,MAAA8O,IAAA,aAAA,IAYAkc,aAAA,SAAAljB,GACAA,EAAAsV,iBACAvkB,KAAAoyB,iBAAA,SAUAC,aAAA,SAAApjB,GACAA,EAAAsV,iBACAvkB,KAAAoyB,iBAAA,SAUAA,iBAAA,SAAA7O,GAEA,GACA+O,GADAC,EAAAvyB,KAAAmH,MAAA3E,UAGA,UAAA+gB,EACA+O,EAAAC,EAAA3oB,OAAAuZ,WACA,SAAAI,IACA+O,EAAAC,EAAA3oB,OAAA0Z,YAGAgP,IAEAC,EAAA3sB,OAAA5F,KAAAmH,OACAmrB,EAAApP,WAAAljB,KAAAmH,OACAmrB,EAAArc,IAAA,aAAA,MAMAsX,EAAAC,EAAAE,EAAAE,MCzNAh0B,EAAA,oBAAA,eAAA,qBAAA,SAAA44B,EAAA/E,GAEA,MAAA7tB,UAAA8B,eAAAC,OAAAhC,EAAA8W,UAEA+a,UAAA,eAMA/uB,UAAA+vB,EAMA3vB,YAAA,EAMAQ,UAAA,EAEAC,iBACA4K,MAAA,EACAukB,YAAA,gBACAC,OAAA,OACAC,OAAA,eACArsB,MAAA,eACAwT,YAAA,yCAGA8Y,eAAA,SAAApwB,GACA/I,EAAA,iBAAA4K,SAAA,aAGAwuB,cAAA,SAAArwB,GACA/I,EAAA,iBAAAoT,YAAA,aAYA8B,UAAA,SAAAM,EAAAC,GAEA,GAAAC,GAAAnP,KAAAwC,WAAAgE,IAAA0I,EAAA3I,KAAAjC,KAAA,mBACA+D,EAAArI,KAAAsI,kBACA8G,EAAA/G,EAAAiC,WAAAhN,MAAA4R,EAAA3I,OAEA,GAAA6I,GAAAD,GACAnP,KAAAwC,WAAAoD,OAAAuJ,GAGAnP,KAAA+M,gCACA/M,KAAA+H,0BAEA/H,KAAAiE,8BACAjE,KAAA4H,MAAA,YAAAuH,iBAAAA,EAAAC,SAAAA,IAEApP,KAAA8H,QAAA,WAAAqH,EAAAC,KAKAqe,MCvEA7zB,EAAA,iBACA,mBACA,kBACA,mBACA,oBACA,SACAk5B,EACAtF,EACAE,EACAE,GAGA,MAAAhuB,UAAAwB,KAAAO,OAAAhC,EAAA8W,UAQAf,WAAA,WACA,OACA4b,UAAAtxB,KAAAmH,MAAAxI,KAQA6yB,UAAA,iCAQA3vB,OAAAlC,EAAA8W,UAEAzU,MAAA,SACA+wB,gBAAA,SACAC,kBAAA,WACAC,2BAAA,WACAC,6BAAA,aAEAC,2BAAA,iBAEA3F,EAAA3rB,OAAA+rB,EAAA/rB,QAQAlD,GAAA,WACA,MAAA,gBAAAqB,KAAAmH,MAAAxI,IAOAiD,QAAA,KAMAsK,SAAAid,GAAAjd,SAAA,yBAQAxI,WAAA,WAEA1D,KAAA8F,SACA9F,KAAAqL,SAAArL,KAAAmH,MAAA,SAAAnH,KAAA8F,QACA9F,KAAAqL,SAAArL,KAAAmH,MAAA,mBAAAnH,KAAAozB,iBACApzB,KAAAqzB,eAAA7wB,WAAAsW,GAAA,MAAA9Y,KAAAszB,cAAAtzB,MAEAA,KAAAuzB,YAAA,KAEA3zB,SAAA8b,OAAA5C,GAAA,aAAA9Y,KAAAwzB,OAAAxzB,MACAJ,SAAA8b,OAAA5C,GAAA,eAAA9Y,KAAAyzB,SAAAzzB,OAWA8F,OAAA,WAmBA,MAjBA9F,MAAAmE,IAAA8H,KAAAjM,KAAAkM,SAAAlM,KAAAmH,MAAAyiB,WAEA5pB,KAAAksB,+BAEAlsB,KAAAqzB,eAAA,GAAAP,IACAY,GAAA1zB,KAAAmE,IAAA2F,KAAA,iBACAtH,WAAAxC,KAAAmH,MAAAX,IAAA,aAEAxG,KAAAqzB,eAAAvtB,SACA9F,KAAAqzB,eAAAva,GAAA,YAAA9Y,KAAAqzB,eAAAT,gBACA5yB,KAAAqzB,eAAAva,GAAA,WAAA9Y,KAAAqzB,eAAAR,eAGA7yB,KAAAqzB,eAAAva,GAAA,mBAAA9Y,KAAA2zB,qBAAA3zB,MAEAA,KAAA4zB,0BAEA5zB,MAIA2zB,qBAAA,SAAAE,EAAAC,GAEAl0B,SAAA8b,OAAA5T,QAAA,wBACA+rB,QAAAA,EACAC,SAAAA,KAaAL,SAAA,SAAAxkB,EAAA8kB,OAEA,KAAAA,IACAA,GAAA,GAGA9kB,IACAA,EAAAuV,kBACAvV,EAAAsV,kBAGAvkB,KAAAmE,IAAA0I,YAAA,YAAA/C,KAAA,kBAAA+C,YAAA,iBACAknB,GACA/zB,KAAAmH,MAAA8O,IAAA,aAAA,GAEArW,SAAA8b,OAAA5T,QAAA,iBAAA9H,KAAAmH,QAYAqsB,OAAA,SAAAvkB,EAAA8kB,OAEA,KAAAA,IACAA,GAAA,GAGA9kB,IACAA,EAAAuV,kBACAvV,EAAAsV,kBAGAvkB,KAAAmE,IAAAE,SAAA,YACA0vB,GACA/zB,KAAAmH,MAAA8O,IAAA,aAAA,GAEArW,SAAA8b,OAAA5T,QAAA,iBAAA9H,KAAAmH,QAIAysB,wBAAA,WAEA,GAAAhJ,GAAA5qB,KAAAmE,IAAA2F,KAAA,kBAEA9J,MAAAmH,MAAAX,IAAA,WAAAmN,UAEAiX,EAAAS,OAIAT,EAAAngB,QAaA6oB,cAAA,SAAAnsB,GAEAnH,KAAAqzB,eAAA7wB,WAAAsF,QAAA,WACAX,EAAA8O,IAAA,iBAAAjW,KAAAmH,MAAAX,IAAA,OACAxG,KAAAwzB,UAIAQ,cAAA,SAAA/kB,GAGAxV,EAAAwV,EAAAsC,QAAAoU,SAAA,cAEAlsB,EAAA,kBAAAoT,YAAA,iBACApT,EAAAwV,EAAAsC,QAAAlN,SAAA,mBAcA+uB,gBAAA,SAAAjsB,EAAAtK,GAEAA,EACAmD,KAAAwzB,OAAA,MAAA,GAEAxzB,KAAAyzB,SAAA,MAAA,KAKAjG,EAAAE,EAAAE,MCtPAh0B,EAAA,qBAAA,gBAAA,qBAAA,SAAAq6B,EAAAxG,GAEA,MAAA7tB,UAAA8B,eAAAC,OAAAhC,EAAA8W,UAMAid,GAAA,iBAEA7xB,QACAqyB,oEAAA,wBAEAlyB,MAAA,0BACAmyB,2BAAA,0BACAjyB,QAAA,cAOAO,UAAAwxB,EAMA7wB,kBAAA,EAMAP,YAAA,EAMAQ,UAAA,EAEAC,iBACA4K,MAAA,EACAwkB,OAAA,OACAC,OAAA,gBACArsB,MAAA,gBACAwT,YAAA,0CAGA8Y,eAAA,SAAApwB,GACAxC,KAAAmE,IAAAE,SAAA,aAGAwuB,cAAA,SAAArwB,GACAxC,KAAAmE,IAAA0I,YAAA,cAGA4gB,MC1DA7zB,EAAA,gBAAA,oBAAA,mBAAA,SAAAw6B,EAAA5G,GAEA,MAAA5tB,UAAAwB,KAAAO,OAAAhC,EAAA8W,UAQAf,WAAA,WACA,OACA4b,UAAAtxB,KAAAmH,MAAAxI,KAQA+0B,GAAA,qBAMA9xB,QAAA,MAMAsK,SAAAid,GAAAjd,SAAA,wBAQAxI,WAAA,WAKA1D,KAAA8F,SAEA9F,KAAAq0B,gBAAA,GAAAD,IACA5xB,WAAAxC,KAAAmH,MAAAX,IAAA,cAEAxG,KAAAq0B,gBAAAvuB,SAEA9F,KAAAq0B,gBAAAvb,GAAA,YAAA9Y,KAAAq0B,gBAAAzB,gBAEA5yB,KAAAq0B,gBAAAvb,GAAA,WAAA9Y,KAAAq0B,gBAAAxB,eAEA7yB,KAAAq0B,gBAAAvb,GAAA,mBAAA9Y,KAAAs0B,uBAEAt0B,KAAAqL,SAAArL,KAAAmH,MAAAX,IAAA,YAAA,MAAAxG,KAAAu0B,gBAEA30B,SAAA8b,OAAA5C,GAAA,iBAAA9Y,KAAAw0B,kBAAAx0B,MAEAJ,SAAA8b,OAAA5C,GAAA,iBAAA9Y,KAAAy0B,eAAAz0B,MAEAJ,SAAA8b,OAAA5C,GAAA,kBAAA9Y,KAAA2zB,qBAAA3zB,OAUA8F,OAAA,WAEA,MADA9F,MAAAmE,IAAA8H,KAAAjM,KAAAkM,SAAAlM,KAAAmH,QACAnH,MAGA2zB,qBAAA,SAAAxsB,GAGA,GAAAib,GAAApiB,KAAAmH,MAAAX,IAAA,YAAAA,IAAAW,EAAAX,IAAA,kBACAxG,MAAAq0B,gBAAAhvB,iBAAA+c,IAaAkS,sBAAA,SAAAT,EAAAC,GAEAn0B,EAAAU,KAAAwzB,EAAA,SAAA1sB,GACAA,EAAA8O,IAAA,aAAA,KAGAtW,EAAAU,KAAAyzB,EAAA,SAAA3sB,GACAA,EAAA8O,IAAA,aAAA,MAYAse,eAAA,SAAAptB,GAEAnH,KAAAq0B,gBAAAhvB,iBAAA8B,IAYAqtB,kBAAA,SAAArtB,GAEA,GAAA6c,GAAA7c,EAAAX,IAAA,cAAAW,KACAnH,MAAAq0B,gBAAA9uB,kBAAAye,KAIAwJ,MCxIA5zB,EAAA,0BAAA,WAEA,MAAAgG,UAAAwB,KAAAO,OAAAhC,EAAA8W,UAMA5U,QACA6yB,oCAAA,gBAQAhY,UAMA9a,QAAA,MAMAsK,SAAAid,GAAAjd,SAAA,iCAgBAyoB,kBAAA,WACA,MAAAh1B,GAAA2M,OAAAtM,KAAA0c,OAAA,SAAAY,GACA,MAAAtd,MAAA40B,gBAAAtX,EAAA9F,OACAxX,OASA60B,WAAA,WAEA,MAAA70B,MAAAmH,MAAA2V,uBAWAgY,gBAAA,SAAAC,GAEA,GAAAp2B,GAAA,QAAAqB,KAAAmH,MAAAX,IAAA,QAAA,oBAAAuuB,CAEA,OAAA,cAAA/jB,OAAAgkB,cACA,WAAAhkB,OAAAgkB,aAAAC,QAAAt2B,IAcAu2B,qBAAA,SAAA5X,GAEA,MAAAA,GAAAG,iBAAAH,EAAAG,iBAAAH,EAAAC,WAWA4X,WAAA,SAAA3d,GACA,OAAA,IAAAA,EAAAja,QAAA,WAUA63B,iBAAA,SAAA5d,GAGA,OAAA,KADA,cAAA,aAAA,SAAA,OAAA,eACAja,QAAAia,EAAA7b,QAAA,UAAA,MAWAi5B,gBAAA,SAAApd,GAGA,OAAA,KADA,SAAA,iBACAja,QAAAia,EAAA7b,QAAA,UAAA,MAWA05B,wBAAA,SAAA/X,GAEA,MAAAA,GAAAgY,YAAAt1B,KAAAmH,MAAAX,IAAA8W,EAAAG,mBAUA3X,OAAA,WASA,MAPA9F,MAAAmE,IAAA8H,KAAAjM,KAAAkM,SAAAlM,OAGAL,EAAAU,KAAAL,KAAA20B,oBAAA,SAAArX,GACAtd,KAAAu1B,cAAAjY,IACAtd,MAEAA,MAWAu1B,cAAA,SAAAjY,GAEA,GAAAjE,GAAArZ,IAEAmpB,IAAAgB,OAAAvkB,OAAA0X,EAAA3e,IACA2e,EAAA4M,SAAAI,QAAAG,MAAA,SAAAN,GAEA,GAAAmB,GAAA7xB,EAAA,IAAA0wB,EAAAxrB,IACA4sB,EAAAD,EAAAtgB,QAAA,yBACAwgB,EAAAD,EAAAzhB,KAAA,eACA9P,EAAAsxB,EAAAhnB,KAAA,iBAEAknB,GAAAjwB,QACAiwB,EAAAC,UAAAF,EAAAzhB,KAAA,qBAIAqgB,EAAArR,GAAA,SAAA,SAAA7J,GACAoK,EAAAlS,MAAA8O,IAAAjc,EAAAmvB,GAAAgB,OAAAuB,WAAAvB,EAAAxrB,OAIA2sB,EAAAxS,GAAA,QAAA,SAAA7J,GACAoK,EAAAlS,MAAA8O,IAAAjc,EAAAsxB,EAAAzV,SAIA0V,EAAAzS,GAAA,QAAA,gCAAA,WACAxZ,WAAA,WACAgsB,EAAAxjB,QAAA,UACA,OAIAqhB,GAAAgB,OAAAzmB,WAAA4Z,EAAA3e,GAAA2e,EAAA4M,WAYAsL,sBAAA,SAAA7xB,EAAA4Z,GAKA,QAAAkY,GAAAzX,EAAAnI,GAEA,MAAA,kBAAAA,EAAA,IAAAlW,EAAAqkB,SAAAnO,EAAAmO,GAAA,IAAAhG,EAAA,YALA,GAAA/R,GAAA,GACA+X,EAAAhkB,KAAAmH,MAAAX,IAAA+W,EA0BA,OAlBA5d,GAAAU,KAAAsD,EAAA,SAAA4W,EAAAjd,GAGA,gBAAAid,GACAtO,GAAAwpB,EAAAlb,EAAAjd,GAEA,gBAAAid,KAEAA,EAAAyD,OAAAzD,EAAA5W,SACAsI,GAAA,oBAAAsO,EAAAyD,MAAA,KACA/R,GAAAjM,KAAAw1B,sBAAAjb,EAAA5W,QAAA4Z,IAEAtR,GAAAwpB,EAAAlb,EAAA1E,IAAA0E,EAAApH,OAIAnT,MAEAiM,GAYAypB,YAAA,SAAAC,EAAAC,GAEA,GAAAnf,IACAof,WACAl3B,GAAAgB,EAAA2Y,SAAAqd,EAAApY,UAAA,KACAuY,WAAA,OACA9X,MAAA,GACAra,WACAmW,YAAA,GACAmE,IAAA,GACA8X,aAAA,YACA7L,YAIA,IAAAyL,EAAAtV,YAAA,IAAA1gB,EAAA2O,KAAAqnB,EAAAtV,UAAArgB,KAAAmH,SACA,OAAA,CAGA,QAAAwuB,EAAAne,MAEA,IAAA,cACAf,EAAAof,QAAAt5B,KAAA,uBACAka,EAAAqD,YAAA,WACArD,EAAAwH,IAAAL,KAAAC,KAAAC,UAAA,yCACArH,EAAAqf,WAAA,KACA,MAEA,KAAA,aACArf,EAAAof,QAAAt5B,KAAA,qBACA,MAEA,KAAA,SACA,IAAA,gBACA,GAAAy5B,GAAAL,EAAAzL,YACAzT,GAAAyT,SAAAzwB,EAAAkI,QAAA,EAAAwnB,GAAAgB,OAAAC,sBACAC,cAAA,EACAC,SACAC,SAAA,8GACAC,SAAA,kHAEAwL,EACA,MAEA,KAAA,SACAvf,EAAAqf,WAAA,QACA,MAEA,KAAA,YACArf,EAAAuH,MAAAJ,KAAAC,KAAAC,UAAA,YACA,MAEA,KAAA,cACArH,EAAAof,QAAAt5B,KAAA,uBACAka,EAAAqD,YAAA,WACArD,EAAAwH,IAAAL,KAAAC,KAAAC,UAAA,6CACArH,EAAAqf,WAAA,MAKA91B,KAAAm1B,WAAAQ,EAAAne,QACAf,EAAA6e,UAAA,MACA7e,EAAAwf,WAAA,KAGA,IAAA3Y,GAAA3d,EAAA8W,SAAA9W,EAAAu2B,UAAAP,GAAAlf,EASA,IANA9W,EAAAmB,WAAAwc,EAAA3Z,WACA2Z,EAAA3Z,QAAAhE,EAAA2O,KAAAgP,EAAA3Z,QAAA3D,KAAAmH,WAKA,KAAA,QAAA,gBAAA5J,QAAAo4B,EAAAne,MAAA,CAEA,GAAA2e,IAAA,CACAx2B,GAAAU,KAAAs1B,EAAAhyB,QAAA,SAAAkS,EAAA1C,IACA,IAAA0C,EAAAtY,QAAA,UAAA,IAAAsY,EAAAtY,QAAA,UACA+f,EAAA3Z,QAAAwP,GAAA,mBAAA0C,EAAA,YACAsgB,GAAA,KAGAA,GACA7Y,EAAAuY,QAAAt5B,KAAA,cAiBA,MAXA+gB,GAAAW,KACAX,EAAAuY,QAAAt5B,KAAA,QAAA+gB,EAAAyY,cAIAzY,EAAAuY,QAAAt6B,SACA+hB,EAAAuY,QAAA,IAAAvY,EAAAuY,QAAA75B,KAAA,MAGAgE,KAAA0c,OAAAY,EAAA3e,IAAA2e,EAEAA,GAWA8Y,0BAAA,SAAAC,GAEA,OAAA,IAAAA,EAAA94B,QAAA,WAAA,MAAA,MAYA+4B,aAAA,SAAArnB,GAEAA,EAAAsV,gBAEA,IAAApgB,GAAA1K,EAAAwV,EAAArD,eACA2qB,EAAApyB,EAAA6G,QAAA,uBAIA,IAFAurB,EAAA3rB,YAAA,UAEA,cAAAoG,OAAAgkB,aAAA,CAEA,GAAAr2B,GAAA43B,EAAAjyB,KAAA,KACAiyB,GAAA5Q,SAAA,UACA3U,OAAAgkB,aAAAwB,QAAA73B,EAAA,UAEAqS,OAAAgkB,aAAAyB,WAAA93B,UClZA/E,EAAA,sBACA,oBACA,kBACA,mBACA,iBACA,wBACA,SACA2zB,EACAC,EACAI,EACAD,EACA+I,GAGA,MAAA92B,UAAAwB,KAAAO,OAAAhC,EAAA8W,UAMAkT,MAAA,UAMAtX,OACA6X,UACAtS,MAAA8e,EACA5J,SAAA,KACAnD,MAAA,YAIA+J,GAAA,sBAMA7xB,OAAAlC,EAAA8W,YAAA8W,EAAA1rB,OAAA2rB,EAAA3rB,OAAA+rB,EAAA/rB,QAMAqK,SAAAid,GAAAjd,SAAA,iCASAxI,WAAA,SAAAU,GAEApE,KAAAmH,MAAA/C,EAAAoe,MAEA,IAAAmU,IACA,wBACA,qBACA,wBAEAh3B,GAAAU,KAAAs2B,EAAA,SAAA1nB,GACAjP,KAAAqL,SAAArL,KAAAmH,MAAA8H,EAAAjP,KAAA8F,SACA9F,MAIAA,KAAAqL,SAAArL,KAAAmH,MAAA,0BAAA,SAAAqb,EAAA3M,GACA,QAAAA,GACA7V,KAAAmE,IAAA2F,KAAA,+BAAAhC,QAAA,aAYAhC,OAAA,WAcA,MAZA9F,MAAAmE,IAAA8H,KAAAjM,KAAAkM,SAAAlM,KAAAmH,QAEAnH,KAAA6sB,eAAA,YAEA7sB,KAAAmtB,eAAA,YACAuG,GAAA,+BACAvsB,MAAAnH,KAAAmH,QAGAnH,KAAAqmB,mBACArmB,KAAA6nB,eAEA7nB,OAIAutB,EAAAC,EAAAI,EAAAD,EAAA+I,MCtGA98B,EAAA,mBAAA,WAEA,MAAAgG,UAAAwB,KAAAO,QAEA8U,UACAmgB,UAAA,OAEA7O,MAAA,OACAjgB,QAAA,SACA+uB,MAAA,QACAC,UAAA,MACA5b,MAAA,GACAL,QAAA,GACAkc,WAAA,EACAC,UAAA,EACAC,OAAA,SAAA9yB,KACA+yB,OAAA,SAAA/yB,MAOAvC,QAAA,MAQA8B,WAAA,SAAAU,GAEApE,KAAAmE,IAAA5I,SACAyE,KAAAyW,SAAA0gB,UAAAn3B,KAAAmE,IAAAyF,UAGA5J,KAAA5D,KAAAuD,EAAA8W,SAAArS,EAAAhI,KAAA4D,KAAAyW,UACAzW,KAAA8F,UAUAA,OAAA,WAGA,MADA9F,MAAAmE,IAAAizB,aAAAp3B,KAAA5D,MACA4D,MAUAyK,KAAA,WAGA,MADAzK,MAAAmE,IAAAizB,aAAA,QACAp3B,MAUAqrB,KAAA,WAGA,MADArrB,MAAAmE,IAAAizB,aAAA,QACAp3B,UC7EApG,EAAA,sBAAA,WAEA,MAAAgG,UAAAwB,KAAAO,QAQAE,QACAw1B,iBAAA,YAOAz1B,QAAA,SASA8B,WAAA,SAAAU,GAEApE,KAAAs3B,UAAAlzB,EAAAkzB,UACAt3B,KAAAu3B,kBAAAnzB,EAAAmzB,mBAAA3Z,KAAAC,KAAAC,UAAA,iBAUA0Z,SAAA,SAAAvoB,GAEA,GAAAuI,GAAAxX,KAAAmE,IAAAG,KAAA,iBAEA1E,UAAA8b,OAAA5T,QAAA0P,EAAA7b,QAAA,QAAA,IAAA,iBAAAsT,EAAAwoB,OAAArzB,KAAA6K,GACAjP,KAAAmE,IAAA0R,IAAA,MAAA/N,QAAA,WAWAhC,OAAA,WACA,GAAAuT,GAAArZ,IAkCA,OAjCAV,YAAA,WACA+Z,EAAAlV,IAAA2jB,aACA4P,MACAC,SAAA,OACApc,MAAA,IACAnI,OAAA,OACAqW,IAAAzY,OAAA4mB,QACAxzB,KAAA,SAAAqzB,GACA,OACA/X,OAAA,eACAC,YAAA,SACAC,UAAA5O,OAAAyG,aAAA0J,OAAAxiB,GACA24B,UAAAje,EAAAie,UACAO,KAAAJ,EAAAI,KACAC,KAAAL,EAAAK,KACAC,YAAAC,aAAAC,SAOAC,eAAAz+B,EAAA,gCAEA0+B,aAAA,SAAAC,GACA,MAAAA,IAEAte,YAAAT,EAAAke,kBACAc,eAAAhf,EAAAif,cACAvQ,MAAA,SAEA1O,EAAAlV,IAAAG,KAAA,iBAAA+U,EAAAie,YACA,GACAt3B,MAWAs4B,cAAA,SAAAlY,GAEA,GAAAmY,GAAA9+B,EAAA,8CAEA,IAAA2mB,EAAAoY,QACA,MAAAD,GAAArvB,OAAAkX,EAAAyF,KAGA,IAAA4S,GAAAh/B,EAAA,0CACAi/B,EAAAj/B,EAAA,qCAaA,OAZAkgB,MAAA,WAAAyG,EAAAV,OAAA,YAAA,QACAmG,KAAA,WAAAzF,EAAAV,OAAA9B,KAAAC,KAAAC,UAAA,UAAAF,KAAAC,KAAAC,UAAA,SAEA2a,EAAAvvB,OAAA,mBAAAyQ,KAAA,mCAAAkM,KAAA,YAEA6S,EAAAxvB,OAAA,OAAAkX,EAAAhc,KAAA8W,MAAA,SACAwd,EAAAxvB,OAAA,OAAA0U,KAAAC,KAAAC,UAAA,MAAA,SAAAsC,EAAAhc,KAAAzF,GAAA,cAEAgB,EAAAU,KAAA+f,EAAAW,QAAA,SAAAnX,GACA8uB,EAAAxvB,OAAA,OAAAU,EAAA,gBAGA2uB,EAAArvB,OAAAuvB,GAAAvvB,OAAAwvB,QC5HA9+B,EAAA,wBAAA,WAEA,MAAAgG,UAAAwB,KAAAO,QAMA6vB,UAAA,qBAEA3vB,QACA82B,2BAAA,gBASAh6B,GAAA,WACA,MAAA,sBAAAqB,KAAAmH,MAAAxI,IAOAiD,QAAA,KAMAsK,SAAAid,GAAAjd,SAAA,+BAQAxI,WAAA,WAEA1D,KAAA8F,UAUAA,OAAA,WAEA,MADA9F,MAAAmE,IAAA8H,KAAAjM,KAAAkM,SAAAlM,KAAAmH,QACAnH,MAQAof,aAAA,WAEApf,KAAAghB,KAAA5B,cACA/D,WAAA,EACA9B,QAAAvZ,KAAAmH,MAAAX,IAAA,mBAAAxG,KAAAmH,MAAAX,IAAA,mBAAA,KACAoU,cAAA5a,KAAAmH,QAGAnH,KAAAghB,KAAAlZ,QAAA,2BCxEAlO,EAAA,sBAAA,sBAAA,SAAAg/B,GAEA,MAAAh5B,UAAA8B,eAAAC,QAEA6vB,UAAA,gBAMAkC,GAAA,sBAMAjxB,UAAAm2B,EAMA/1B,YAAA,EAMAQ,UAAA,MC5BAzJ,EAAA,wBAAA,mBAAA,SAAA4zB,GAEA,MAAA5tB,UAAAwB,KAAAO,OAAAhC,EAAA8W,UAMA+a,UAAA,uBAEA3vB,OAAAlC,EAAA8W,UACAoiB,+BAAA,iBACAC,mDAAA,aACAC,mDAAA,cACAvL,EAAA3rB,QAQAlD,GAAA,WACA,MAAA,wBAAAqB,KAAAmH,MAAAxI,IAOAiD,QAAA,KAMAsK,SAAAid,GAAAjd,SAAA,iCAQAxI,WAAA,WAEA1D,KAAA8F,SAEA9F,KAAAqL,SAAArL,KAAAmH,MAAA3E,WAAA,MAAAxC,KAAAg5B,uBACAh5B,KAAAqL,SAAArL,KAAAmH,MAAA,SAAAnH,KAAA8F,QAEA,UAAA9F,KAAAmH,MAAAX,IAAA,gBACAxG,KAAAqL,SAAArL,KAAAmH,MAAAX,IAAA,UAAA,SAAAxG,KAAA8F,SAWAA,OAAA,WAEA,MADA9F,MAAAmE,IAAA8H,KAAAjM,KAAAkM,SAAAlM,KAAAmH,QACAnH,MAWAyb,WAAA,SAAAxM,GAEAA,EAAAuV,kBACAvV,EAAAsV,gBAEA,IAAAjnB,GAAA0C,KAAAmH,MAAA3E,WAAAjF,QAAAyC,KAAAmH,MACAnH,MAAAmH,MAAA3E,WAAAoH,OAAA6R,eACAhM,GAAAnS,EAAA,KAYA27B,WAAA,SAAAhqB,GAEAA,EAAAsV,iBACA3kB,SAAA8b,OAAA5T,QAAA,gBAAA9H,KAAAmH,OACAnH,KAAAmH,MAAA3E,WAAAoD,OAAA5F,KAAAmH,QAUA+xB,eAAA,WAEA,GAAA1gB,GAAAxY,KAAAmE,IAAA2F,KAAA,yBAAAnD,GAAA,WACA3G,MAAAmH,MAAA8O,IAAA,UAAAuC,GACAxY,KAAAmH,MAAA3E,WAAAsF,QAAA,iBAAA9H,KAAAmH,SAIAqmB,MCrHA5zB,EAAA,4BAAA,wBAAA,SAAAu/B,GAEA,MAAAv5B,UAAA8B,eAAAC,QAEA6vB,UAAA,sBAMA/uB,UAAA02B,EAMA/1B,kBAAA,EAMAP,YAAA,EAMAQ,UAAA,EAEAC,iBACA4K,MAAA,EAEAwkB,OAAA,OACAC,OAAA,kBACArsB,MAAA,wBACAwT,YAAA,kDAGA8Y,eAAA,SAAAzrB,GACAnH,KAAAmE,IAAAE,SAAA,aAGAwuB,cAAA,SAAA1rB,GACAnH,KAAAmE,IAAA0I,YAAA,iBC5CAjT,EAAA,kBACA,kBACA,4BACA,SACA4zB,EACA4L,GAGA,MAAAx5B,UAAAwB,KAAAO,OAAAhC,EAAA8W,UAQA+a,UAAA,WACA,MAAA,wBAAAxxB,KAAAmH,MAAAX,IAAA,iBAAAA,IAAA,OAGA3E,OAAAlC,EAAA8W,UACA4iB,yBAAA,QACAC,0BAAA,SACAC,0BAAA,SACAC,4BAAA,WACAC,uCAAA,iBACAjM,EAAA3rB,QAQAlD,GAAA,WACA,MAAA,iBAAAqB,KAAAmH,MAAAxI,IAOAiD,QAAA,KAMAsK,SAAAid,GAAAjd,SAAA,0BAQAxI,WAAA,WAEA,GAAAizB,IACA,mBACA,oBAEAh3B,GAAAU,KAAAs2B,EAAA,SAAA1nB,GACAjP,KAAAqL,SAAArL,KAAAmH,MAAA8H,EAAAjP,KAAA8F,SACA9F,MAEAA,KAAAqL,SAAArL,KAAAmH,MAAAX,IAAA,SAAA,SAAAxG,KAAA8F,QAEA9F,KAAAqL,SAAArL,KAAAmH,MAAA+Q,aAAA,iBAAAlY,KAAA05B,0BAEA15B,KAAA8Y,GAAA,uBAAA9Y,KAAA25B,qBAAA35B,MAEAJ,SAAA8b,OAAA5C,GAAA,sBAAA9Y,KAAAi5B,WAAAj5B,OAUA8F,OAAA,WAgBA,GAdA9F,KAAAmE,IAAA8H,KAAAjM,KAAAkM,SAAAlM,KAAAmH,QAEAnH,KAAAmH,MAAAX,IAAA,iBAAAA,IAAA,aAEAxG,KAAA45B,eAAA,GAAAR,IACA1F,GAAA1zB,KAAAmE,IAAA2F,KAAA,0BACAtH,WAAAxC,KAAAmH,MAAAX,IAAA,aAEAxG,KAAA45B,eAAA9zB,SACA9F,KAAA45B,eAAA9gB,GAAA,YAAA9Y,KAAA45B,eAAAhH,gBACA5yB,KAAA45B,eAAA9gB,GAAA,WAAA9Y,KAAA45B,eAAA/G,gBAIA,UAAA7yB,KAAAmH,MAAAX,IAAA,iBAAAA,IAAA,MAAA,CAEA,GAAA6S,GAAArZ,IACAV,YAAA,WACA+Z,EAAAwgB,iBAAAxgB,EAAA/L,mBAAA0T,KAAA8Y,mBACApG,GAAAra,EAAAlV,IAAA2F,KAAA,wBACAtH,WAAA6W,EAAAlS,MAAAX,IAAA,eAEA6S,EAAAwgB,iBAAA/zB,SACAuT,EAAAwgB,iBAAA/gB,GAAA,YAAAO,EAAAwgB,iBAAAjH,gBACAvZ,EAAAwgB,iBAAA/gB,GAAA,WAAAO,EAAAwgB,iBAAAhH,gBACA,GAsBA,MAlBA7yB,MAAAmH,MAAAX,IAAA,wBACAxG,KAAAiqB,YAAA,kBAAAjqB,KAAAmH,MAAAX,IAAA,OAGAxG,KAAAmH,MAAAX,IAAA,2BACAxG,KAAAiqB,YAAA,4BAAAjqB,KAAAmH,MAAAX,IAAA,OACA6jB,cAAA,EACAC,SACAC,SAAA,6EACAC,SAAA,GACAC,MAAA9qB,EAAA2O,KAAAtO,KAAA0qB,gBAAA1qB,SAKAA,KAAA4mB,sBACA5mB,KAAA6nB,eAEA7nB,MASA05B,yBAAA,WAEA15B,KAAAmE,IAAA2F,KAAA,yBAAAxF,KAAA,WAAAtE,KAAAmH,MAAAmV,0BAWAvb,MAAA,SAAAkO,GAEAA,EAAAuV,kBACAvV,EAAAsV,iBACAvkB,KAAAmH,MAAA3E,WAAAqB,IAAA7D,KAAA+5B,oBAAA/5B,KAAAmH,SAWA4yB,oBAAA,SAAA3gB,GAGA,GAAArY,GAAApB,EAAAoB,MAAAqY,EAAA1D,WAuCA,cApCA3U,GAAApC,GAEAoC,EAAAka,UAAA7B,EAAA5S,IAAA,MAGAzF,EAAA6Z,cAAAxB,EAAA5S,IAAA,iBAAAA,IAAA,MAGAzF,EAAA6Y,MAAAja,EAAAoB,MAAAqY,EAAA5S,IAAA,SAAAkP,YAGA0D,EAAA5S,IAAA,aAEAzF,EAAAwY,WAEAH,EAAA5S,IAAA,WAAAnG,KAAA,SAAAgY,GAEA,GAAA2hB,GAAAr6B,EAAAoB,MAAAsX,EAAA3C,kBACAskB,GAAAr7B,SACAq7B,GAAAthB,YAEA3X,EAAAwY,QAAAhd,KAAAy9B,MAMA,UAAA5gB,EAAA5S,IAAA,iBAAAA,IAAA,QAEAzF,EAAA4Z,aACAvB,EAAA5S,IAAA,aAAAnG,KAAA,SAAAgX,GACAtW,EAAA4Z,UAAApe,KAAAyD,KAAA+5B,oBAAA1iB,KACArX,OAIAe,GAUA0yB,SAAA,WAEAzzB,KAAAmH,MAAA8O,IAAA,aAAA,IAWAgkB,OAAA,SAAAhrB,GAEAA,EAAAsV,iBAEAvT,OAAA4D,QAAAgJ,KAAAC,KAAAC,UAAA,qDAEA9d,KAAAmH,MAAA3E,WAAAoD,OAAA5F,KAAAmH,OACAvH,SAAA8b,OAAA5T,QAAA,gBAAA9H,KAAAmH,SAYAqsB,OAAA,WAEAxzB,KAAAmH,MAAA8O,IAAA,aAAA,IAWA0jB,qBAAA,SAAA9jB,GAEA,QAAAA,GAIA7V,KAAAmH,MAAAX,IAAA,WAAAwS,eAAArZ,EAAAiB,MAAAZ,KAAAmH,MAAAX,IAAA,WAAA0S,iBAUAsC,cAAA,WAEAxb,KAAAmH,MAAA8O,IAAA,SAAA,EAAAjW,KAAAmE,IAAA2F,KAAA,iCAAA+L,SAIA2X,MC/RA5zB,EAAA,sBAAA,kBAAA,SAAAg/B,GAEA,MAAAh5B,UAAA8B,eAAAC,QAEA6vB,UAAA,sBAYA/uB,UAAAm2B,EAMAx1B,kBAAA,EAMAP,YAAA,EAMAQ,UAAA,EAEAC,iBACA4K,MAAA,EACAukB,YAAA,uBACAC,OAAA,OACAC,OAAA,mBACArsB,MAAA,iBACAwT,YAAA,2CAUA8Y,eAAA,SAAAzrB,GACA,GAAA+yB,GAAA,UAAA/yB,EAAAX,IAAA,iBAAAA,IAAA,MAAA,0CAAA,sBACA/M,GAAAygC,GAAA71B,SAAA,aAUAwuB,cAAA,WACAp5B,EAAA,wBAAAoT,YAAA,aAWAgC,SAAA,SAAAI,EAAAC,GAKA,GAHAD,EAAAuV,kBAGAtV,EAAA3I,KAAAof,SAAA,iBAAAlsB,EAAAwV,EAAAsC,QAAAvG,QAAA,iBAAAzP,OAEA,WADA2T,GAAAI,OAAAjM,SAAA,SAIA,IAAAgM,GAAAH,EAAAI,OACAC,EAAAF,EAAAjL,KAAA,OACA,IAAAmL,GAAAA,EAAA/M,WAAA,CAEA,GAAA4M,GAAApP,KAAAsI,kBAAAgC,WAAAhN,MAAA4R,EAAA3I,MACAiJ,EAAAD,EAAA/M,WAAAgE,IAAA0I,EAAA3I,KAAAjC,KAAA,kBACAiL,GAAA/M,WAAAoD,OAAA4J,GACAxP,KAAAwC,WAAAqB,IAAA2L,GAAAC,GAAAL,IACAI,EAAAhN,WAAAxC,KAAAwC,WACAxC,KAAAqF,iBAAAmK,KAWAjB,WAAA,SAAAU,EAAAC,GAEA,GAAAC,GAAAnP,KAAAwC,WAAAgE,IAAA0I,EAAA3I,KAAAjC,KAAA,kBAEA4K,GAAA4K,YAAAzV,SAAA,UAAA8K,EAAA3I,IAAA,iBAAAA,IAAA,OAEAxG,KAAAiE,8BACAjE,KAAA4H,MAAA,aAAAuH,iBAAAA,IACAnP,KAAA8H,QAAA,YAAAqH,IAYAR,UAAA,SAAAM,EAAAC,GAEAD,EAAAuV,iBAEA,IAAArV,GAAAnP,KAAAwC,WAAAgE,IAAA0I,EAAA3I,KAAAjC,KAAA,mBACA+D,EAAArI,KAAAsI,kBACA8G,EAAA/G,EAAAiC,WAAAhN,MAAA4R,EAAA3I,OAEA,GAAA6I,GAAAD,GACAnP,KAAAwC,WAAAoD,OAAAuJ,GAGAnP,KAAA+M,gCACA/M,KAAA+H,0BAEA/H,KAAAiE,8BACAjE,KAAA4H,MAAA,YAAAuH,iBAAAA,EAAAC,SAAAA,IAEApP,KAAA8H,QAAA,WAAAqH,EAAAC,QChJAxV,EAAA,cACA,cACA,gBACA,mBACA,qBACA,qBACA,uBACA,oBACA,kBACA,iBACA,oBACA,SACAugC,EACAC,EACAC,EACAC,EACAC,EACA7D,EACAnJ,EACAC,EACAG,EACAC,GAGA,MAAAhuB,UAAAwB,KAAAO,OAAAhC,EAAA8W,UAMAkT,MAAA,UAMAtX,OACA6X,UACAtS,MAAA8e,EACA5J,SAAA,KACAnD,MAAA,WAEA6Q,MACA5iB,MAAA0iB,EACAxN,SAAA,KACAnD,MAAA,WAEA8Q,MACA7iB,MAAA2iB,EACAzN,SAAA,KACAnD,MAAA,YAIA+J,GAAA,oBAMA7xB,OAAAlC,EAAA8W,UACAikB,4BAAA,0BACAC,uBAAA,eACAC,iCAAA,aACAC,qBAAA,eAGAtN,EAAA1rB,OAAA2rB,EAAA3rB,OAAA+rB,EAAA/rB,QAMAD,QAAA,MAMAsK,SAAAid,GAAAjd,SAAA,sBAQAxI,WAAA,SAAAU,GAEApE,KAAAwiB,OAAApe,EAAAoe,OAGA,QAAAxiB,KAAAwiB,OAAAhc,IAAA,iBAAA7G,EAAAgU,QAAA3T,KAAAwiB,OAAAhc,IAAA,WAEAxG,KAAAmH,MAAAnH,KAAAwiB,OAAAhc,IAAA,QAiBAxG,KAAAmH,MAAA8P,WAAAjX,KAAAwiB,QAEAxiB,KAAAqL,SAAArL,KAAAmH,MAAA,iBAAAnH,KAAA86B,gBAIA96B,KAAA8Y,GAAA,gBAAA9Y,KAAA+6B,aAUAj1B,OAAA,WAKA,GAHA9F,KAAAmE,IAAA8H,KAAAjM,KAAAkM,SAAAlM,KAAAmH,QAGAnH,KAAAmH,MAAA,CAGAyW,KAAAuI,QAAA9X,MAAArO,KAAAmE,KAEAnE,KAAAmtB,eAAA,YACAuG,GAAA,6BACAvsB,MAAAnH,KAAAmH,QAGAnH,KAAAqmB,mBACArmB,KAAA6nB,eAEA7nB,KAAAmtB,eAAA,QACA3qB,WAAAwO,OAAAyG,aAAAkD,WAGA,IAAAqgB,GAAA,KACA5d,EAAA,IAEApd,MAAAwsB,YAAA,QAAAM,SAAApoB,YAAArE,KAAA,SAAAsF,GAEAA,EAAAqb,KAAAhhB,KAAAmH,MAEAiW,EAAAzX,EAAAwB,MAAAX,IAAA,SAAApM,KAEA4gC,IAAA5d,IACA4d,EAAA5d,EACAzX,EAAAxB,IAAAqG,OAAA,6CAAA4S,EAAA,gBAGApd,MAEAA,KAAAmH,MAAAoY,eAAA5f,EAAA2O,KAAA,SAAAogB,GAEA,GAAAA,EAEA,MADAuM,OAAArd,KAAAC,KAAAC,UAAA,iGACA9d,IAGA4d,MAAAuI,QAAAzX,KAAA1O,KAAAmE,KACAnE,KAAAmtB,eAAA,QACAuG,GAAA,uBACAlxB,WAAAxC,KAAAmH,MAAAX,IAAA,cAEA,IAAAi0B,GAAAz6B,KAAAwsB,YAAA,QAAAM,QACA2N,GAAAzZ,KAAAhhB,KACAy6B,EAAAj4B,WAAAsW,GAAA,MAAA,WACA2hB,EAAAj4B,WAAAsF,QAAA,YACA9H,MACAy6B,EAAA3hB,GAAA,YAAA2hB,EAAA7H,gBACA6H,EAAA3hB,GAAA,WAAA2hB,EAAA5H,gBAEA7yB,OAEAA,KAAAmH,MAAA2R,GAAA,qBAAA,WACA,GAAAoiB,GAAAl7B,KAAAmE,IAAA2F,KAAA,uBACAoxB,GAAAC,SAAAC,UAAAF,EAAAlhC,KAAA,iBAAA,MACAgG,MAIA,MAAAA,OAYA86B,cAAA,SAAA9Z,EAAAjH,GAEA/Z,KAAAmE,IAAA2F,KAAA,2BAAA+b,KAAA9L,IAWAshB,YAAA,SAAApsB,GAEA,GAAAqsB,GAAA,WAAA7hC,EAAAwV,EAAAsC,QAAAjN,KAAA,cAEAtE,MAAAmH,MAAAX,IAAA,aAAAnG,KAAA,SAAA+Y,GACAA,EAAAnD,IAAA,YAAAqlB,MAWAC,aAAA,WAEA,GAAAva,GAAAhhB,KAAAwiB,OAAAhc,IAAA,OACA7G,GAAAgU,QAAAqN,GACAA,EAAAhhB,KAAAwiB,OAAAE,WAEA1iB,KAAAwiB,OAAAvM,IAAA,eAAA,OAGAjW,KAAAmH,MAAA6Z,EACAhhB,KAAA8F,UAKA01B,kBAAA,SAAAvsB,GAEAjP,KAAAy7B,oBAAAhxB,MAEA,IAAAuW,GAAA/R,EAAA7K,IAEA,WAAA6K,EAAAyQ,cAEAsB,GAAAriB,GAEAgB,EAAAU,KAAA2gB,EAAArG,UAAA,SAAAvB,SAEAA,GAAA6B,gBACA7B,GAAAza,GAEAya,EAAAG,SAEA5Z,EAAAU,KAAA+Y,EAAAG,QAAA,SAAAlB,SAEAA,GAAAK,kBACAL,GAAA1Z,QAUAqiB,EAAAgB,YAAA,QAIAhB,GAAA1C,UAEAte,KAAAwiB,OAAAE,SAAA1B,GACAhhB,KAAAmH,MAAAnH,KAAAwiB,OAAAhc,IAAA,QACAxG,KAAA8F,UAWA41B,wBAAA,SAAAzsB,GAEAA,EAAAsV,iBAEAvkB,KAAAy7B,oBAAA,GAAArB,IACA1G,GAAA,sBACAt3B,MACA46B,UAAA,EACAD,WAAA,EACAI,UAAA,+BACAwE,aAAA,EACA/E,UAAA,OACA7O,MAAA,IACA7M,MAAA0C,KAAAC,KAAAC,UAAA,qBACAjD,QAAA,GAAAwf,IACA/C,UAAA,YACAC,kBAAA3Z,KAAAC,KAAAC,UAAA,oCACAhY,SAAA3B,IACA+yB,OAAA,WACAt3B,SAAA8b,OAAAkR,IAAA,0BAKA5sB,KAAAy7B,oBAAApQ,OACAzrB,SAAA8b,OAAAkgB,KAAA,qBAAA57B,KAAAw7B,kBAAAx7B,OA0BA+6B,WAAA,SAAA/Z,GAEAhhB,KAAAwiB,OAAAvM,IAAA,eAAA,MACAjW,KAAAwiB,OAAAvM,IAAA,OAAA,UAEAjW,MAAAmH,MAEAnH,KAAA8F,UAWA+1B,WAAA,WAGA,GAAAC,GAAA,GAAA1B,IACA1G,GAAA,2BACAt3B,MACA46B,UAAA,EACAD,WAAA,EACAI,UAAA,wBACAwE,aAAA,EACA/E,UAAA,WACA7O,MAAA,sBACA7M,MAAA0C,KAAAC,KAAAC,UAAA,kBACA2L,IAAA,qBAKAqS,GAAAzQ,OAGArrB,KAAAmH,MAAA2R,GAAA,qBAAA,WACAgjB,EAAArxB,UAKAqvB,kBAAA,SAAAn2B,GACA,MAAA,IAAA42B,GAAA52B,KAGA4pB,EAAAC,EAAAG,EAAAC,EAAA8I,MC/YA98B,EAAA,oBACA,gBACA,mBACA,oBACA,kBACA,mBACA,iBACA,wBACA,SACAwgC,EACAC,EACA9M,EACAC,EACAI,EACAD,EACA+I,GAGA,MAAA92B,UAAAwB,KAAAO,OAAAhC,EAAA8W,UAMAkT,MAAA,UAMAtX,OACA6X,UACAtS,MAAA8e,EACA5J,SAAA,KACAnD,MAAA,YAIA+J,GAAA,0BAQA7xB,OAAA,WACA,GAAAk6B,GAAA/7B,KAAAg8B,qBAAAhrB,OAAAyG,aAAA6I,YAAA2b,oBACA,OAAAt8B,GAAA8W,UACAylB,kCAAA,gCACAC,6BAAA,sBACA5O,EAAA1rB,OAAA2rB,EAAA3rB,OAAA+rB,EAAA/rB,OAAAk6B,IAOAn6B,QAAA,MAMAsK,SAAAid,GAAAjd,SAAA,4BAQAxI,WAAA,SAAAU,GAEApE,KAAAwiB,OAAApe,EAAAoe,OAGA,QAAAxiB,KAAAwiB,OAAAhc,IAAA,uBAAA7G,EAAAgU,QAAA3T,KAAAwiB,OAAAhc,IAAA,iBAEAxG,KAAAmH,MAAAnH,KAAAwiB,OAAAhc,IAAA,cAiBAxG,KAAAmH,MAAA8P,WAAAjX,KAAAwiB,SAIAxiB,KAAA8Y,GAAA,gBAAA9Y,KAAA+6B,aAUAj1B,OAAA,WAsBA,MApBA9F,MAAAmE,IAAA8H,KAAAjM,KAAAkM,SAAAlM,KAAAmH,QAEAnH,KAAAmH,OAAAnH,KAAAg8B,uBAEAh8B,KAAAoF,cAAApF,KAAAmH,MAAA,yBAAAnH,KAAA8F,QAEA9F,KAAAmtB,eAAA,YACAuG,GAAA,mCACAvsB,MAAAnH,KAAAmH,QAIAnH,KAAA6nB,eAEA7W,OAAAyG,aAAA6I,YAAAiV,cAAAv1B,MAEAA,KAAAqL,SAAArL,KAAAmH,MAAA,yBAAAnH,KAAA8F,SAIA9F,MAUAo8B,mBAAA,WAEAp8B,KAAAg8B,sBAEAh8B,KAAAmH,MAAA6J,OAAAyG,aAAA6I,YAAA+b,gBAEAnhB,MAAA0C,KAAAC,KAAAliB,QAAA,mBACAgnB,OAAA3iB,KAAAwiB,OAAAhc,IAAA,WAEA8X,UAAAte,KAAAwiB,OAAAhc,IAAA,QAGAxG,KAAAwiB,OAAAvM,IAAA,qBAAA,OACAjW,KAAAwiB,OAAAvM,IAAA,aAAAjW,KAAAmH,OAEAnH,KAAA8F,UAIA9F,KAAAs8B,gBAAA,yBAcAC,wBAAA,SAAAttB,GAEAjP,KAAAy7B,oBAAAhxB,MAEA,IAAAoX,GAAA5S,EAAA7K,IAEA,WAAA6K,EAAAyQ,aAEAmC,GAAAljB,GAIAkjB,EAAAG,YAAA,EAIAH,EAAAvD,UAAAte,KAAAwiB,OAAAhc,IAAA,MAEAqb,EAAA7Q,OAAAyG,aAAAC,UAAAC,UAAA,aAAAkK,GAEA7hB,KAAAwiB,OAAAvM,IAAA,qBAAA,OACAjW,KAAAwiB,OAAAvM,IAAA,aAAA4L,GACA7hB,KAAAmH,MAAA0a,EAEA7hB,KAAA8F,UAWA02B,8BAAA,SAAAvtB,GAEAA,EAAAsV,iBAEAvkB,KAAAg8B,sBAEAh8B,KAAAy7B,oBAAA,GAAArB,IACA1G,GAAA,4BACAt3B,MACA46B,UAAA,EACAD,WAAA,EACAI,UAAA,+BACAwE,aAAA,EACA/E,UAAA,OACA7O,MAAA,IACA7M,MAAA0C,KAAAC,KAAAC,UAAA,2BACAjD,QAAA,GAAAwf,IACA/C,UAAA,kBACAC,kBAAA3Z,KAAAC,KAAAC,UAAA,wCACAhY,SAAA3B,IACA+yB,OAAA,WACAt3B,SAAA8b,OAAAkR,IAAA,gCAKA5sB,KAAAy7B,oBAAApQ,OACAzrB,SAAA8b,OAAAkgB,KAAA,2BAAA57B,KAAAu8B,wBAAAv8B,OAIAA,KAAAs8B,gBAAA,8BAaAN,mBAAA,WAEA,MAAAhrB,QAAAyG,aAAA,aAWAsjB,WAAA,SAAAlZ,GAEA7hB,KAAAwiB,OAAAvM,IAAA,qBAAA,MACAjW,KAAAwiB,OAAAvM,IAAA,aAAA,UAEAjW,MAAAmH,MAEAnH,KAAA8F,UAWAw2B,gBAAA,SAAA5I,GAEA,GAAA+I,GAAA7e,KAAAC,KAAAC,UAAA,mCAEA4e,EAAA9e,KAAAC,KAAAC,UAAA,uBAGA9d,MAAA28B,WAAA,GAAAvC,IACA1G,GAAAA,EACAt3B,MACA46B,UAAA,EACAD,WAAA,EACAI,UAAA,+BACAwE,aAAA,EAEA5T,MAAA,IACA7M,MAAA0C,KAAAC,KAAAC,UAAA,gCACAjD,QAAA,OAAA4hB,EAAA,mlBAAAC,EAAA,cAIA18B,KAAA28B,WAAAtR,SAIAkC,EAAAC,EAAAI,EAAAD,EAAA+I,MCtTA98B,EAAA,gBACA,qBACA,aACA,mBACA,kBACA,SACAgjC,EACA/b,EACAgc,EACAlP,GAGA,MAAA/tB,UAAAwB,KAAAO,OAAAhC,EAAA8W,UAMAkT,MAAA,SAMAtX,OACAmQ,QACA5K,MAAAglB,EACA9P,SAAA,KACAnD,MAAA,UAEA9H,YACAjK,MAAAilB,EACA/P,SAAA,KACAnD,MAAA,cAEA3I,MACApJ,MAAAiJ,EACAiM,SAAA,KACAnD,MAAA,SAQA+J,GAAA,eAEA7xB,QACAi7B,sDAAA,eACAC,4DAAA,cAOAn7B,QAAA,MAMAsK,SAAAid,GAAAjd,SAAA,wBAQAxI,WAAA,SAAAU,GAEApE,KAAAg9B,YAAA54B,EAAA44B,YACA54B,EAAAgjB,MACApnB,KAAA2pB,MAAAvlB,EAAAgjB,MAWAthB,OAAA,SAAAonB,GAUA,MARAA,GAAAA,MAEAltB,KAAAmE,IAAA8H,KAAAjM,KAAAkM,SAAAlM,OAEAA,KAAAitB,gBAAAttB,EAAAgC,OAAAurB,GACA1K,OAAAxiB,KAAAmH,SAGAnH,MAYAi9B,aAAA,SAAAhuB,GAEAA,EAAAsV,iBACA3kB,SAAA8b,OAAA5T,QAAA,yBAWAo1B,WAAA,SAAAjuB,GAEAA,EAAAsV,gBAEA,IAAAqG,GAAAnxB,EAAAwV,EAAAsC,QACA5L,EAAAilB,EAAAtmB,KAAA,YACAtE,MAAAmE,IAAA2F,KAAA8gB,EAAAtmB,KAAA,QAEAtE,MAAAotB,UAAAznB,GAAAG,WAMA6nB,MCxIA/zB,EAAA,kBAAA,iBAAA,gBAAA,gBAAA,eAAA,gBAAA,oBAAA,SAAAwqB,EAAA6P,EAAA/V,EAAAsU,EAAA4H,EAAA+C,GAEA,MAAAv9B,UAAAwB,KAAAO,QAMA+xB,GAAA;oBAEA7xB,QACAu7B,0BAAA,kBACAC,yBAAA,iBACAC,8BAAA,uBAOA17B,QAAA,MAMAsK,SAAAid,GAAAjd,SAAA,0BAQAxI,WAAA,SAAAU,GAGApE,KAAAg9B,YAAA54B,EAAA44B,YAGAh9B,KAAAqL,SAAArL,KAAAg9B,YAAAO,WAAAp2B,MAAAX,IAAA,YAAA,MAAAxG,KAAAg5B,uBACAh5B,KAAAqL,SAAArL,KAAAg9B,YAAAO,WAAAp2B,MAAAX,IAAA,YAAA,SAAAxG,KAAAg5B,wBAUAlzB,OAAA,WAMA,MAJA9F,MAAAmE,IAAA8H,KAAAjM,KAAAkM,YACAlM,KAAAw9B,YACAx9B,KAAAg5B,wBAEAh5B,MAGAw9B,UAAA,WAEA/jC,EAAA,qBAAA+jC,WACAC,SAAA,iBACAC,QAAA,EACAC,kBAAA,iBACA1R,OAAA,WACA,MAAA,IAAAgI,IAAA9sB,MAAA,GAAAid,KAAAte,SAAA3B,KAEAkK,MAAA,WACA5U,EAAA,kBAAA4K,SAAA,aAEAqK,KAAA,WACAjV,EAAA,kBAAAoT,YAAA,eAIApT,EAAA,oBAAA+jC,WAEAC,SAAA,iBACAC,QAAA,EACAC,kBAAA,gBACA1R,OAAA,WACA,MAAA,IAAAuG,IAAArrB,MAAA,GAAA+W,KAAApY,SAAA3B,KAEAkK,MAAA,WAEA5U,EAAA,iBAAA4K,SAAA,aAGAqK,KAAA,WACAjV,EAAA,iBAAAoT,YAAA,YACApT,EAAA,kBAAAoT,YAAA,sBAMA+wB,gBAAA,SAAA3uB,GAEAA,EAAAsV,iBACA3kB,SAAA8b,OAAA5T,QAAA,oBAGA+1B,eAAA,SAAA5uB,GACAA,EAAAsV,iBACA3kB,SAAA8b,OAAA5T,QAAA,mBAUAgc,oBAAA,SAAA7U,GAEAA,EAAAsV,gBAEA,IAAAuX,GAAA,GAAA1B,IACA1G,GAAA,wBACAt3B,MACA46B,UAAA,EACAD,WAAA,EACAI,UAAA,+BACAwE,aAAA,EACA/E,UAAA,OACA7O,MAAA,IACA7M,MAAA0C,KAAAC,KAAAC,UAAA,uBACAjD,QAAA,GAAAsiB,IACA7F,UAAA,SACAC,kBAAA3Z,KAAAC,KAAAC,UAAA,oCACAhY,SAAA3B,MAIA23B,GAAAzQ,OACAzrB,SAAA8b,OAAA5C,GAAA,uBAAA,WACAgjB,EAAArxB,UAWAuuB,sBAAA,WAEA,GAAA8E,GAAArkC,EAAA,0CAEAuG,MAAAg9B,YAAAO,WAAAp2B,MAAAX,IAAA,YAAAjL,OAGAuiC,EAAAt4B,WAAA,YAFAs4B,EAAAx5B,KAAA,WAAA,iBC3JA1K,EAAA,qBAAA,WAEA,MAAAgG,UAAAwB,KAAAO,QAMA+xB,GAAA,kBAEA7xB,QACAk8B,2BAAA,eACAC,yBAAA,cAOAp8B,QAAA,MAMAsK,SAAAid,GAAAjd,SAAA,2BAQAxI,WAAA,aAYAoC,OAAA,WAEA,MADA9F,MAAAmE,IAAA8H,KAAAjM,KAAAkM,YACAlM,MASAi+B,aAAA,SAAAhvB,GACAA,EAAAsV,iBACA3kB,SAAA8b,OAAA5T,QAAA,iBASAo2B,WAAA,SAAAjvB,GACAA,EAAAsV,iBACA3kB,SAAA8b,OAAA5T,QAAA,mBCrEAlO,EAAA,iBACA,eACA,iBACA,kBACA,kBACA,SACAukC,EACAC,EACAhgB,EACAuP,GAGA,MAAA/tB,UAAAwB,KAAAO,OAAAhC,EAAA8W,UAMAkT,MAAA,UAMAtX,OACAgsB,UACAzmB,MAAAwmB,EACAtR,SAAA,KACAnD,MAAA,WAEA2U,WACA1mB,MAAAwG,EACA0O,SAAA,KACAnD,MAAA,WAEAQ,QACAvS,MAAAumB,EACArR,SAAA,KACAnD,MAAA,WAQA+J,GAAA,wBAMA7xB,QACA08B,0BAAA,WACAC,0BAAA,WACAC,4BAAA,gBAOA78B,QAAA,QAMAsK,SAAAid,GAAAjd,SAAA,yBAQAxI,WAAA,SAAAU,GAGApE,KAAAu9B,WAAAn5B,EAAAm5B,WAEAv9B,KAAA8F,SAEAlG,SAAA8b,OAAA5C,GAAA,sBAAA9Y,KAAA0+B,aAAA1+B,MAEAJ,SAAA8b,OAAA5C,GAAA,iBAAA9Y,KAAA2+B,eAAA3+B,MACAJ,SAAA8b,OAAA5C,GAAA,iBAAA9Y,KAAA4+B,eAAA5+B,MAEAJ,SAAA8b,OAAA5C,GAAA,kBAAA9Y,KAAA6+B,iBAAA7+B,MACAJ,SAAA8b,OAAA5C,GAAA,uBAAA9Y,KAAA8+B,gBAAA9+B,MAEAA,KAAA++B,YAAAtlC,EAAA,sBAUAqM,OAAA,SAAAonB,GAEAA,EAAAA,MAEAltB,KAAAmE,IAAA8H,KAAAjM,KAAAkM,YAEAlM,KAAAitB,gBAAAttB,EAAAgC,OAAAurB,GACA8P,YAAAh9B,OAGA,IAAAmE,GAAA1K,EAAA,+BASA,OARA,YAAAuG,KAAA2pB,MACAxlB,EAAA0I,YAAA,iBAEA1I,EAAAE,SAAA,iBAGArE,KAAA++B,YAAA/+B,KAAAmE,IAAA2F,KAAA,qBAEA9J,MAUAg/B,UAAA,SAAAC,GAEAj/B,KAAAmE,IAAA2F,KAAA,sBAAAo1B,QAAAD,IAUAE,aAAA,WAEAn/B,KAAAmE,IAAA2F,KAAA,0CAAAlE,UAYA84B,aAAA,SAAAvoB,GAGAA,EAAA6Y,SAIA7Y,EAAA4Y,qBAEA/uB,KAAA++B,YAAAz6B,KAAA,cAAA,WACAtE,KAAA++B,YAAAv5B,WAAA,cAIAxF,KAAA++B,YAAAz6B,KAAA,cAAA,SACAtE,KAAA++B,YAAAz6B,KAAA,WAAA,eAYA86B,SAAA,WAEApuB,OAAAgb,SAAAF,KAAA9a,OAAAyG,aAAAoI,YAAAlD,sBAWAgiB,eAAA,SAAAxoB,GAEAA,EAAA6Y,SACApR,KAAAuI,QAAA9X,MAAArO,KAAA++B,YAAAj1B,KAAA,KAAA,SACA9J,KAAA++B,YAAAz6B,MACA+6B,cAAA,SACAC,SAAA,eAcAV,eAAA,SAAAzoB,EAAA/R,GAEA,IAAA+R,EAAA6Y,OAAA,CAEA,GAAAzQ,GAAA,OAIA,IAFAve,KAAAm/B,eAEA,UAAA/6B,EAAAma,OAAA,CAEAA,EAAA,OAEA,IAAAkG,GAAArgB,EAAAuqB,QACAsQ,EAAAxlC,EAAA,oCAEA,iBAAAgrB,GACA9kB,EAAAU,KAAAokB,EAAA,SAAA8a,GACAN,EAAA/1B,OAAA,OAAAq2B,EAAA,WAGAN,EAAAA,EAAA/1B,OAAA,OAAAub,EAAA,SAGAzkB,KAAAg/B,UAAAC,GAIAj/B,KAAA++B,YAAAj1B,KAAA,kBAAAlE,SACA5F,KAAA++B,YAAAz6B,MACA+6B,cAAA9gB,EACA+gB,SAAA,eAaAE,iBAAA,WAEA,MAAA,WAAAx/B,KAAA2pB,OAUAmV,gBAAA,WAEA9+B,KAAAotB,UAAA,WAAAtnB,UAWA+4B,iBAAA,SAAAY,EAAArY,GAEA,WAAApnB,KAAA2pB,MACA3pB,KAAAotB,UAAA,UAEAptB,KAAA6sB,eAAA,UAGA7sB,KAAA8F,QACAqB,MAAAs4B,EACArY,IAAAA,KAWA0J,SAAA,WAEA9f,OAAAyG,aAAAtB,KAAA2a,aAIAnD,MCvTAh0B,GACA,iCACA,0BACA,wBACA,oBACA,sBACA,mBACA,gBACA,eACA,iBACA,SACA+lC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAjS,EACAyP,EACAP,GAgBA,QAAAgD,GAAAC,EAAAC,GACA,MAAAvgC,GAAAS,QAAA8/B,KAAA,IAAAA,EAAA3iC,QAAA0iC,IAAAA,GAAAC,EAdAlvB,OAAAyG,aAAA0I,MAAA,GAAA0f,GAAA7uB,OAAAyG,aAAA0I,OACAnP,OAAAyG,aAAAC,UAAA,GAAAkoB,GACA5uB,OAAAyG,aAAAuF,QAAA,GAAA8iB,GAAA9uB,OAAAyG,aAAAuF,SAoBArd,EAAAwgC,OAYAC,QAAA,SAAAH,EAAAC,GACA,MAAAF,GAAAC,EAAAC,GACA,qBAEA,IAUAhK,UAAA,SAAAn8B,GAEA,GAAAgH,GAAApB,EAAAoB,MAAAhH,EAQA,OANA4F,GAAAU,KAAAU,EAAA,SAAA8U,EAAA1C,IACAxT,EAAAmB,WAAA+U,IAAAlW,EAAAgB,SAAAkV,KACA9U,EAAAoS,GAAAxT,EAAAu2B,UAAArgB,MAIA9U,GAcAijB,SAAA,SAAAic,EAAAC,GACA,MAAAF,GAAAC,EAAAC,GACA,uBAEA,IAWAta,gBAAA,SAAA/K,EAAAwlB,GAEAA,IACAA,GAAA,IAAA,IAAA,IAAA,SAAA,MAGA,IAAA9H,GAAA9+B,EAAA,QAAAohB,EAAA,SAQA,OANA0d,GAAAzuB,KAAA,KAAAw2B,IAAAD,EAAArkC,KAAA,MAAAqE,KAAA,WAEA5G,EAAAuG,MAAAugC,YAAAvgC,KAAAwgC,aAIAjI,EAAAtsB,UAMArM,SAAA8b,OAAA/b,EAAAgC,UAAA/B,SAAA6gC,QAEAhnC,EAAAmP,UAAAd,QAAA,yBAEAkJ,OAAAyG,aAAAkD,UAAA3J,OAAAyG,aAAAC,UAAAG,eAAA,gBAAA7G,OAAAyG,aAAAkD,UAEA,IAAAkF,GAAA7O,OAAAyG,aAAAC,UAAAC,UAAA,SAAA3G,OAAAyG,aAAA0J,OACAnQ,QAAAyG,aAAAoI,YAAAA,EAEA7O,OAAAyG,aAAAtB,KAAA,GAAA4pB,GAAAlgB,EAAA7O,OAAAyG,aAAAtB,KAEA,IAAA+N,GAAA,GAAAqZ,IACAp2B,MAAA0Y,IAGA6gB,EAAA,GAAA1D,IACAO,WAAArZ,GAGAzqB,GAAAmP,UAAAd,QAAA,qBACAqZ,OAAA+C,EACAyc,QAAAD,MAKA9mC,EAAA,OAAA,eAEA8F","file":"llms-builder.min.js","sourcesContent":["(function($){\n","/**\n * @license almond 0.3.3 Copyright jQuery Foundation and other contributors.\n * Released under MIT license, http://github.com/requirejs/almond/LICENSE\n */\n//Going sloppy to avoid 'use strict' string cost, but strict practices should\n//be followed.\n/*global setTimeout: false */\n\nvar requirejs, require, define;\n(function (undef) {\n\tvar main, req, makeMap, handlers,\n\t\tdefined = {},\n\t\twaiting = {},\n\t\tconfig = {},\n\t\tdefining = {},\n\t\thasOwn = Object.prototype.hasOwnProperty,\n\t\taps = [].slice,\n\t\tjsSuffixRegExp = /\\.js$/;\n\n\tfunction hasProp(obj, prop) {\n\t\treturn hasOwn.call(obj, prop);\n\t}\n\n\t/**\n\t * Given a relative module name, like ./something, normalize it to\n\t * a real name that can be mapped to a path.\n\t * @param {String} name the relative name\n\t * @param {String} baseName a real name that the name arg is relative\n\t * to.\n\t * @returns {String} normalized name\n\t */\n\tfunction normalize(name, baseName) {\n\t\tvar nameParts, nameSegment, mapValue, foundMap, lastIndex,\n\t\t\tfoundI, foundStarMap, starI, i, j, part, normalizedBaseParts,\n\t\t\tbaseParts = baseName && baseName.split(\"/\"),\n\t\t\tmap = config.map,\n\t\t\tstarMap = (map && map['*']) || {};\n\n\t\t//Adjust any relative paths.\n\t\tif (name) {\n\t\t\tname = name.split('/');\n\t\t\tlastIndex = name.length - 1;\n\n\t\t\t// If wanting node ID compatibility, strip .js from end\n\t\t\t// of IDs. Have to do this here, and not in nameToUrl\n\t\t\t// because node allows either .js or non .js to map\n\t\t\t// to same file.\n\t\t\tif (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) {\n\t\t\t\tname[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, '');\n\t\t\t}\n\n\t\t\t// Starts with a '.' so need the baseName\n\t\t\tif (name[0].charAt(0) === '.' && baseParts) {\n\t\t\t\t//Convert baseName to array, and lop off the last part,\n\t\t\t\t//so that . matches that 'directory' and not name of the baseName's\n\t\t\t\t//module. For instance, baseName of 'one/two/three', maps to\n\t\t\t\t//'one/two/three.js', but we want the directory, 'one/two' for\n\t\t\t\t//this normalization.\n\t\t\t\tnormalizedBaseParts = baseParts.slice(0, baseParts.length - 1);\n\t\t\t\tname = normalizedBaseParts.concat(name);\n\t\t\t}\n\n\t\t\t//start trimDots\n\t\t\tfor (i = 0; i < name.length; i++) {\n\t\t\t\tpart = name[i];\n\t\t\t\tif (part === '.') {\n\t\t\t\t\tname.splice(i, 1);\n\t\t\t\t\ti -= 1;\n\t\t\t\t} else if (part === '..') {\n\t\t\t\t\t// If at the start, or previous value is still ..,\n\t\t\t\t\t// keep them so that when converted to a path it may\n\t\t\t\t\t// still work when converted to a path, even though\n\t\t\t\t\t// as an ID it is less than ideal. In larger point\n\t\t\t\t\t// releases, may be better to just kick out an error.\n\t\t\t\t\tif (i === 0 || (i === 1 && name[2] === '..') || name[i - 1] === '..') {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t} else if (i > 0) {\n\t\t\t\t\t\tname.splice(i - 1, 2);\n\t\t\t\t\t\ti -= 2;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t//end trimDots\n\n\t\t\tname = name.join('/');\n\t\t}\n\n\t\t//Apply map config if available.\n\t\tif ((baseParts || starMap) && map) {\n\t\t\tnameParts = name.split('/');\n\n\t\t\tfor (i = nameParts.length; i > 0; i -= 1) {\n\t\t\t\tnameSegment = nameParts.slice(0, i).join(\"/\");\n\n\t\t\t\tif (baseParts) {\n\t\t\t\t\t//Find the longest baseName segment match in the config.\n\t\t\t\t\t//So, do joins on the biggest to smallest lengths of baseParts.\n\t\t\t\t\tfor (j = baseParts.length; j > 0; j -= 1) {\n\t\t\t\t\t\tmapValue = map[baseParts.slice(0, j).join('/')];\n\n\t\t\t\t\t\t//baseName segment has config, find if it has one for\n\t\t\t\t\t\t//this name.\n\t\t\t\t\t\tif (mapValue) {\n\t\t\t\t\t\t\tmapValue = mapValue[nameSegment];\n\t\t\t\t\t\t\tif (mapValue) {\n\t\t\t\t\t\t\t\t//Match, update name to the new value.\n\t\t\t\t\t\t\t\tfoundMap = mapValue;\n\t\t\t\t\t\t\t\tfoundI = i;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (foundMap) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t//Check for a star map match, but just hold on to it,\n\t\t\t\t//if there is a shorter segment match later in a matching\n\t\t\t\t//config, then favor over this star map.\n\t\t\t\tif (!foundStarMap && starMap && starMap[nameSegment]) {\n\t\t\t\t\tfoundStarMap = starMap[nameSegment];\n\t\t\t\t\tstarI = i;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!foundMap && foundStarMap) {\n\t\t\t\tfoundMap = foundStarMap;\n\t\t\t\tfoundI = starI;\n\t\t\t}\n\n\t\t\tif (foundMap) {\n\t\t\t\tnameParts.splice(0, foundI, foundMap);\n\t\t\t\tname = nameParts.join('/');\n\t\t\t}\n\t\t}\n\n\t\treturn name;\n\t}\n\n\tfunction makeRequire(relName, forceSync) {\n\t\treturn function () {\n\t\t\t//A version of a require function that passes a moduleName\n\t\t\t//value for items that may need to\n\t\t\t//look up paths relative to the moduleName\n\t\t\tvar args = aps.call(arguments, 0);\n\n\t\t\t//If first arg is not require('string'), and there is only\n\t\t\t//one arg, it is the array form without a callback. Insert\n\t\t\t//a null so that the following concat is correct.\n\t\t\tif (typeof args[0] !== 'string' && args.length === 1) {\n\t\t\t\targs.push(null);\n\t\t\t}\n\t\t\treturn req.apply(undef, args.concat([relName, forceSync]));\n\t\t};\n\t}\n\n\tfunction makeNormalize(relName) {\n\t\treturn function (name) {\n\t\t\treturn normalize(name, relName);\n\t\t};\n\t}\n\n\tfunction makeLoad(depName) {\n\t\treturn function (value) {\n\t\t\tdefined[depName] = value;\n\t\t};\n\t}\n\n\tfunction callDep(name) {\n\t\tif (hasProp(waiting, name)) {\n\t\t\tvar args = waiting[name];\n\t\t\tdelete waiting[name];\n\t\t\tdefining[name] = true;\n\t\t\tmain.apply(undef, args);\n\t\t}\n\n\t\tif (!hasProp(defined, name) && !hasProp(defining, name)) {\n\t\t\tthrow new Error('No ' + name);\n\t\t}\n\t\treturn defined[name];\n\t}\n\n\t//Turns a plugin!resource to [plugin, resource]\n\t//with the plugin being undefined if the name\n\t//did not have a plugin prefix.\n\tfunction splitPrefix(name) {\n\t\tvar prefix,\n\t\t\tindex = name ? name.indexOf('!') : -1;\n\t\tif (index > -1) {\n\t\t\tprefix = name.substring(0, index);\n\t\t\tname = name.substring(index + 1, name.length);\n\t\t}\n\t\treturn [prefix, name];\n\t}\n\n\t//Creates a parts array for a relName where first part is plugin ID,\n\t//second part is resource ID. Assumes relName has already been normalized.\n\tfunction makeRelParts(relName) {\n\t\treturn relName ? splitPrefix(relName) : [];\n\t}\n\n\t/**\n\t * Makes a name map, normalizing the name, and using a plugin\n\t * for normalization if necessary. Grabs a ref to plugin\n\t * too, as an optimization.\n\t */\n\tmakeMap = function (name, relParts) {\n\t\tvar plugin,\n\t\t\tparts = splitPrefix(name),\n\t\t\tprefix = parts[0],\n\t\t\trelResourceName = relParts[1];\n\n\t\tname = parts[1];\n\n\t\tif (prefix) {\n\t\t\tprefix = normalize(prefix, relResourceName);\n\t\t\tplugin = callDep(prefix);\n\t\t}\n\n\t\t//Normalize according\n\t\tif (prefix) {\n\t\t\tif (plugin && plugin.normalize) {\n\t\t\t\tname = plugin.normalize(name, makeNormalize(relResourceName));\n\t\t\t} else {\n\t\t\t\tname = normalize(name, relResourceName);\n\t\t\t}\n\t\t} else {\n\t\t\tname = normalize(name, relResourceName);\n\t\t\tparts = splitPrefix(name);\n\t\t\tprefix = parts[0];\n\t\t\tname = parts[1];\n\t\t\tif (prefix) {\n\t\t\t\tplugin = callDep(prefix);\n\t\t\t}\n\t\t}\n\n\t\t//Using ridiculous property names for space reasons\n\t\treturn {\n\t\t\tf: prefix ? prefix + '!' + name : name, //fullName\n\t\t\tn: name,\n\t\t\tpr: prefix,\n\t\t\tp: plugin\n\t\t};\n\t};\n\n\tfunction makeConfig(name) {\n\t\treturn function () {\n\t\t\treturn (config && config.config && config.config[name]) || {};\n\t\t};\n\t}\n\n\thandlers = {\n\t\trequire: function (name) {\n\t\t\treturn makeRequire(name);\n\t\t},\n\t\texports: function (name) {\n\t\t\tvar e = defined[name];\n\t\t\tif (typeof e !== 'undefined') {\n\t\t\t\treturn e;\n\t\t\t} else {\n\t\t\t\treturn (defined[name] = {});\n\t\t\t}\n\t\t},\n\t\tmodule: function (name) {\n\t\t\treturn {\n\t\t\t\tid: name,\n\t\t\t\turi: '',\n\t\t\t\texports: defined[name],\n\t\t\t\tconfig: makeConfig(name)\n\t\t\t};\n\t\t}\n\t};\n\n\tmain = function (name, deps, callback, relName) {\n\t\tvar cjsModule, depName, ret, map, i, relParts,\n\t\t\targs = [],\n\t\t\tcallbackType = typeof callback,\n\t\t\tusingExports;\n\n\t\t//Use name if no relName\n\t\trelName = relName || name;\n\t\trelParts = makeRelParts(relName);\n\n\t\t//Call the callback to define the module, if necessary.\n\t\tif (callbackType === 'undefined' || callbackType === 'function') {\n\t\t\t//Pull out the defined dependencies and pass the ordered\n\t\t\t//values to the callback.\n\t\t\t//Default to [require, exports, module] if no deps\n\t\t\tdeps = !deps.length && callback.length ? ['require', 'exports', 'module'] : deps;\n\t\t\tfor (i = 0; i < deps.length; i += 1) {\n\t\t\t\tmap = makeMap(deps[i], relParts);\n\t\t\t\tdepName = map.f;\n\n\t\t\t\t//Fast path CommonJS standard dependencies.\n\t\t\t\tif (depName === \"require\") {\n\t\t\t\t\targs[i] = handlers.require(name);\n\t\t\t\t} else if (depName === \"exports\") {\n\t\t\t\t\t//CommonJS module spec 1.1\n\t\t\t\t\targs[i] = handlers.exports(name);\n\t\t\t\t\tusingExports = true;\n\t\t\t\t} else if (depName === \"module\") {\n\t\t\t\t\t//CommonJS module spec 1.1\n\t\t\t\t\tcjsModule = args[i] = handlers.module(name);\n\t\t\t\t} else if (hasProp(defined, depName) ||\n\t\t\t\t\t\t hasProp(waiting, depName) ||\n\t\t\t\t\t\t hasProp(defining, depName)) {\n\t\t\t\t\targs[i] = callDep(depName);\n\t\t\t\t} else if (map.p) {\n\t\t\t\t\tmap.p.load(map.n, makeRequire(relName, true), makeLoad(depName), {});\n\t\t\t\t\targs[i] = defined[depName];\n\t\t\t\t} else {\n\t\t\t\t\tthrow new Error(name + ' missing ' + depName);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tret = callback ? callback.apply(defined[name], args) : undefined;\n\n\t\t\tif (name) {\n\t\t\t\t//If setting exports via \"module\" is in play,\n\t\t\t\t//favor that over return value and exports. After that,\n\t\t\t\t//favor a non-undefined return value over exports use.\n\t\t\t\tif (cjsModule && cjsModule.exports !== undef &&\n\t\t\t\t\t\tcjsModule.exports !== defined[name]) {\n\t\t\t\t\tdefined[name] = cjsModule.exports;\n\t\t\t\t} else if (ret !== undef || !usingExports) {\n\t\t\t\t\t//Use the return value from the function.\n\t\t\t\t\tdefined[name] = ret;\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (name) {\n\t\t\t//May just be an object definition for the module. Only\n\t\t\t//worry about defining if have a module name.\n\t\t\tdefined[name] = callback;\n\t\t}\n\t};\n\n\trequirejs = require = req = function (deps, callback, relName, forceSync, alt) {\n\t\tif (typeof deps === \"string\") {\n\t\t\tif (handlers[deps]) {\n\t\t\t\t//callback in this case is really relName\n\t\t\t\treturn handlers[deps](callback);\n\t\t\t}\n\t\t\t//Just return the module wanted. In this scenario, the\n\t\t\t//deps arg is the module name, and second arg (if passed)\n\t\t\t//is just the relName.\n\t\t\t//Normalize module name, if it contains . or ..\n\t\t\treturn callDep(makeMap(deps, makeRelParts(callback)).f);\n\t\t} else if (!deps.splice) {\n\t\t\t//deps is a config object, not an array.\n\t\t\tconfig = deps;\n\t\t\tif (config.deps) {\n\t\t\t\treq(config.deps, config.callback);\n\t\t\t}\n\t\t\tif (!callback) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (callback.splice) {\n\t\t\t\t//callback is an array, which means it is a dependency list.\n\t\t\t\t//Adjust args if there are dependencies\n\t\t\t\tdeps = callback;\n\t\t\t\tcallback = relName;\n\t\t\t\trelName = null;\n\t\t\t} else {\n\t\t\t\tdeps = undef;\n\t\t\t}\n\t\t}\n\n\t\t//Support require(['a'])\n\t\tcallback = callback || function () {};\n\n\t\t//If relName is a function, it is an errback handler,\n\t\t//so remove it.\n\t\tif (typeof relName === 'function') {\n\t\t\trelName = forceSync;\n\t\t\tforceSync = alt;\n\t\t}\n\n\t\t//Simulate async callback;\n\t\tif (forceSync) {\n\t\t\tmain(undef, deps, callback, relName);\n\t\t} else {\n\t\t\t//Using a non-zero value because of concern for what old browsers\n\t\t\t//do, and latest browsers \"upgrade\" to 4 if lower value is used:\n\t\t\t//http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#dom-windowtimers-settimeout:\n\t\t\t//If want a value immediately, use require('id') instead -- something\n\t\t\t//that works in almond on the global level, but not guaranteed and\n\t\t\t//unlikely to work in other AMD implementations.\n\t\t\tsetTimeout(function () {\n\t\t\t\tmain(undef, deps, callback, relName);\n\t\t\t}, 4);\n\t\t}\n\n\t\treturn req;\n\t};\n\n\t/**\n\t * Just drops the config on the floor, but returns req in case\n\t * the config return value is used.\n\t */\n\treq.config = function (cfg) {\n\t\treturn req(cfg);\n\t};\n\n\t/**\n\t * Expose module registry for debugging and tooling\n\t */\n\trequirejs._defined = defined;\n\n\tdefine = function (name, deps, callback) {\n\t\tif (typeof name !== 'string') {\n\t\t\tthrow new Error('See almond README: incorrect module build, no module name');\n\t\t}\n\n\t\t//This module may not have dependencies\n\t\tif (!deps.splice) {\n\t\t\t//deps is not an array, so probably means\n\t\t\t//an object literal or factory function for\n\t\t\t//the value. Adjust args.\n\t\t\tcallback = deps;\n\t\t\tdeps = [];\n\t\t}\n\n\t\tif (!hasProp(defined, name) && !hasProp(waiting, name)) {\n\t\t\twaiting[name] = [name, deps, callback];\n\t\t}\n\t};\n\n\tdefine.amd = {\n\t\tjQuery: true\n\t};\n}());\n\ndefine(\"vendor/almond\", function(){});\n\n","/**\n * Returns the WordPress-loaded version of Underscore for use with things that need it and use Require.\n * @return obj\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'underscore',[],function() {\n\treturn _;\n} );\n\n","/**\n * Returns the WordPress-loaded version of Backbone for use with things that need it and use Require.\n * @return obj\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'backbone',[],function() {\n\treturn Backbone;\n} );\n\n","/**\n * Returns the WordPress-loaded version of Underscore for use with things that need it and use Require.\n * @return obj\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'jquery',[],function() {\n\treturn jQuery;\n} );\n\n","/*!\n* Backbone.CollectionView, v1.3.4\n* Copyright (c)2013 Rotunda Software, LLC.\n* Distributed under MIT license\n* http://github.com/rotundasoftware/backbone-collection-view\n*/\n\n( function( root, factory ) {\n\t// UMD wrapper\n\tif ( typeof define === 'function' && define.amd ) {\n\t\t// AMD\n\t\tdefine( 'vendor/backbone.collectionView',[ 'underscore', 'backbone', 'jquery' ], factory );\n\t} else if ( typeof exports !== 'undefined' ) {\n\t\t// Node/CommonJS\n\t\tmodule.exports = factory( require('underscore' ), require( 'backbone' ), require( 'backbone' ).$ );\n\t} else {\n\t\t// Browser globals\n\t\tfactory( root._, root.Backbone, ( root.jQuery || root.Zepto || root.$ ) );\n\t}\n}( this, function( _, Backbone, $ ) {\n\tvar mDefaultModelViewConstructor = Backbone.View;\n\n\tvar kDefaultReferenceBy = \"model\";\n\n\tvar kOptionsRequiringRerendering = [ \"collection\", \"modelView\", \"modelViewOptions\", \"itemTemplate\", \"itemTemplateFunction\", \"detachedRendering\" ];\n\n\tvar kStylesForEmptyListCaption = {\n\t\t\"background\" : \"transparent\",\n\t\t\"border\" : \"none\",\n\t\t\"box-shadow\" : \"none\"\n\t};\n\n\tBackbone.CollectionView = Backbone.View.extend( {\n\n\t\ttagName : \"ul\",\n\n\t\tevents : {\n\t\t\t\"mousedown > li, tbody > tr > td\" : \"_listItem_onMousedown\",\n\t\t\t\"dblclick > li, tbody > tr > td\" : \"_listItem_onDoubleClick\",\n\t\t\t\"click\" : \"_listBackground_onClick\",\n\t\t\t\"click ul.collection-view, table.collection-view\" : \"_listBackground_onClick\",\n\t\t\t\"keydown\" : \"_onKeydown\"\n\t\t},\n\n\t\t// only used if Backbone.Courier is available\n\t\tspawnMessages : {\n\t\t\t\"focus\" : \"focus\"\n\t\t},\n\n\t\t//only used if Backbone.Courier is available\n\t\tpassMessages : { \"*\" : \".\" },\n\n\t\t// viewOption definitions with default values.\n\t\tinitializationOptions : [\n\t\t\t{ \"collection\" : null },\n\t\t\t{ \"modelView\" : null },\n\t\t\t{ \"modelViewOptions\" : {} },\n\t\t\t{ \"itemTemplate\" : null },\n\t\t\t{ \"itemTemplateFunction\" : null },\n\t\t\t{ \"selectable\" : true },\n\t\t\t{ \"clickToSelect\" : true },\n\t\t\t{ \"selectableModelsFilter\" : null },\n\t\t\t{ \"visibleModelsFilter\" : null },\n\t\t\t{ \"sortableModelsFilter\" : null },\n\t\t\t{ \"selectMultiple\" : false },\n\t\t\t{ \"clickToToggle\" : false },\n\t\t\t{ \"processKeyEvents\" : true },\n\t\t\t{ \"sortable\" : false },\n\t\t\t{ \"sortableOptions\" : null },\n\t\t\t{ \"reuseModelViews\" : true },\n\t\t\t{ \"detachedRendering\" : false },\n\t\t\t{ \"emptyListCaption\" : null }\n\t\t],\n\n\t\tinitialize : function( options ) {\n\t\t\tBackbone.ViewOptions.add( this, \"initializationOptions\" ); // setup the ViewOptions functionality.\n\t\t\tthis.setOptions( options ); // and make use of any provided options\n\n\t\t\tif( ! this.collection ) this.collection = new Backbone.Collection();\n\n\t\t\tthis._hasBeenRendered = false;\n\n\t\t\tif( this._isBackboneCourierAvailable() ) {\n\t\t\t\tBackbone.Courier.add( this );\n\t\t\t}\n\n\t\t\tthis.$el.data( \"view\", this ); // needed for connected sortable lists\n\t\t\tthis.$el.addClass( \"collection-view collection-list\" ); // collection-list is in there for legacy purposes\n\t\t\tif( this.selectable ) this.$el.addClass( \"selectable\" );\n\n\t\t\tif( this.selectable && this.processKeyEvents )\n\t\t\t\tthis.$el.attr( \"tabindex\", 0 ); // so we get keyboard events\n\n\t\t\tthis.selectedItems = [];\n\n\t\t\tthis._updateItemTemplate();\n\n\t\t\tif( this.collection )\n\t\t\t\tthis._registerCollectionEvents();\n\n\t\t\tthis.viewManager = new ChildViewContainer();\n\t\t},\n\n\t\t_onOptionsChanged : function( changedOptions, originalOptions ) {\n\t\t\tvar _this = this;\n\t\t\tvar rerender = false;\n\n\t\t\t_.each( _.keys( changedOptions ), function( changedOptionKey ) {\n\t\t\t\tvar newVal = changedOptions[ changedOptionKey ];\n\t\t\t\tvar oldVal = originalOptions[ changedOptionKey ];\n\t\t\t\tswitch( changedOptionKey ) {\n\t\t\t\t\tcase \"collection\" :\n\t\t\t\t\t\tif ( newVal !== oldVal ) {\n\t\t\t\t\t\t\t_this.stopListening( oldVal );\n\t\t\t\t\t\t\t_this._registerCollectionEvents();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"selectMultiple\" :\n\t\t\t\t\t\tif( ! newVal && _this.selectedItems.length > 1 )\n\t\t\t\t\t\t\t_this.setSelectedModel( _.first( _this.selectedItems ), { by : \"cid\" } );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"selectable\" :\n\t\t\t\t\t\tif( ! newVal && _this.selectedItems.length > 0 )\n\t\t\t\t\t\t\t_this.setSelectedModels( [] );\n\n\t\t\t\t\t\tif( newVal && this.processKeyEvents ) _this.$el.attr( \"tabindex\", 0 ); // so we get keyboard events\n\t\t\t\t\t\telse _this.$el.removeAttr( \"tabindex\", 0 );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"sortable\" :\n\t\t\t\t\t\tchangedOptions.sortable ? _this._setupSortable() : _this.$el.sortable( \"destroy\" );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"selectableModelsFilter\" :\n\t\t\t\t\t\t_this.reapplyFilter( 'selectableModels' );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"sortableOptions\" :\n\t\t\t\t\t\t_this.$el.sortable( \"destroy\" );\n\t\t\t\t\t\t_this._setupSortable();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"sortableModelsFilter\" :\n\t\t\t\t\t\t_this.reapplyFilter( 'sortableModels' );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"visibleModelsFilter\" :\n\t\t\t\t\t\t_this.reapplyFilter( 'visibleModels' );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"itemTemplate\" :\n\t\t\t\t\t\t_this._updateItemTemplate();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"processKeyEvents\" :\n\t\t\t\t\t\tif( newVal && this.selectable ) _this.$el.attr( \"tabindex\", 0 ); // so we get keyboard events\n\t\t\t\t\t\telse _this.$el.removeAttr( \"tabindex\", 0 );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"modelView\" :\n\t\t\t\t\t\t//need to remove all old view instances\n\t\t\t\t\t\t_this.viewManager.each( function( view ) {\n\t\t\t\t\t\t\t_this.viewManager.remove( view );\n\t\t\t\t\t\t\t// destroy the View itself\n\t\t\t\t\t\t\tview.remove();\n\t\t\t\t\t\t} );\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif( _.contains( kOptionsRequiringRerendering, changedOptionKey ) ) rerender = true;\n\t\t\t} );\n\n\t\t\tif( this._hasBeenRendered && rerender ) {\n\t\t\t\tthis.render();\n\t\t\t}\n\t\t},\n\n\t\tsetOption : function( optionName, optionValue ) { // now is mearly a wrapper around backbone.viewOptions' setOptions()\n\t\t\tvar optionHash = {};\n\t\t\toptionHash[ optionName ] = optionValue;\n\t\t\tthis.setOptions( optionHash );\n\t\t},\n\n\t\tgetSelectedModel : function( options ) {\n\t\t\treturn this.selectedItems.length ? _.first( this.getSelectedModels( options ) ) : null;\n\t\t},\n\n\t\tgetSelectedModels : function ( options ) {\n\t\t\tvar _this = this;\n\n\t\t\toptions = _.extend( {}, {\n\t\t\t\tby : kDefaultReferenceBy\n\t\t\t}, options );\n\n\t\t\tvar referenceBy = options.by;\n\t\t\tvar items = [];\n\n\t\t\tswitch( referenceBy ) {\n\t\t\t\tcase \"id\" :\n\t\t\t\t\t_.each( this.selectedItems, function ( item ) {\n\t\t\t\t\t\titems.push( _this.collection.get( item ).id );\n\t\t\t\t\t} );\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"cid\" :\n\t\t\t\t\titems = items.concat( this.selectedItems );\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"offset\" :\n\t\t\t\t\tvar curLineNumber = 0;\n\n\t\t\t\t\tvar itemElements = this._getVisibleItemEls();\n\n\t\t\t\t\titemElements.each( function() {\n\t\t\t\t\t\tvar thisItemEl = $( this );\n\t\t\t\t\t\tif( thisItemEl.is( \".selected\" ) )\n\t\t\t\t\t\t\titems.push( curLineNumber );\n\t\t\t\t\t\tcurLineNumber++;\n\t\t\t\t\t} );\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"model\" :\n\t\t\t\t\t_.each( this.selectedItems, function ( item ) {\n\t\t\t\t\t\titems.push( _this.collection.get( item ) );\n\t\t\t\t\t} );\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"view\" :\n\t\t\t\t\t_.each( this.selectedItems, function ( item ) {\n\t\t\t\t\t\titems.push( _this.viewManager.findByModel( _this.collection.get( item ) ) );\n\t\t\t\t\t} );\n\t\t\t\t\tbreak;\n\t\t\t\tdefault :\n\t\t\t\t\tthrow new Error( \"Invalid referenceBy option: \" + referenceBy );\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\treturn items;\n\n\t\t},\n\n\t\tsetSelectedModels : function( newSelectedItems, options ) {\n\t\t\tif( ! _.isArray( newSelectedItems ) ) throw \"Invalid parameter value\";\n\t\t\tif( ! this.selectable && newSelectedItems.length > 0 ) return; // used to throw error, but there are some circumstances in which a list can be selectable at times and not at others, don't want to have to worry about catching errors\n\n\t\t\toptions = _.extend( {}, {\n\t\t\t\tsilent : false,\n\t\t\t\tby : kDefaultReferenceBy\n\t\t\t}, options );\n\n\t\t\tvar referenceBy = options.by;\n\t\t\tvar newSelectedCids = [];\n\n\t\t\tswitch( referenceBy ) {\n\t\t\t\tcase \"cid\" :\n\t\t\t\t\tnewSelectedCids = newSelectedItems;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"id\" :\n\t\t\t\t\tthis.collection.each( function( thisModel ) {\n\t\t\t\t\t\tif( _.contains( newSelectedItems, thisModel.id ) ) newSelectedCids.push( thisModel.cid );\n\t\t\t\t\t} );\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"model\" :\n\t\t\t\t\tnewSelectedCids = _.pluck( newSelectedItems, \"cid\" );\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"view\" :\n\t\t\t\t\t_.each( newSelectedItems, function( item ) {\n\t\t\t\t\t\tnewSelectedCids.push( item.model.cid );\n\t\t\t\t\t} );\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"offset\" :\n\t\t\t\t\tvar curLineNumber = 0;\n\t\t\t\t\tvar selectedItems = [];\n\n\t\t\t\t\tvar itemElements = this._getVisibleItemEls();\n\t\t\t\t\titemElements.each( function() {\n\t\t\t\t\t\tvar thisItemEl = $( this );\n\t\t\t\t\t\tif( _.contains( newSelectedItems, curLineNumber ) )\n\t\t\t\t\t\t\tnewSelectedCids.push( thisItemEl.attr( \"data-model-cid\" ) );\n\t\t\t\t\t\tcurLineNumber++;\n\t\t\t\t\t} );\n\t\t\t\t\tbreak;\n\t\t\t\tdefault :\n\t\t\t\t\tthrow new Error( \"Invalid referenceBy option: \" + referenceBy );\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tvar oldSelectedModels = this.getSelectedModels();\n\t\t\tvar oldSelectedCids = _.clone( this.selectedItems );\n\n\t\t\tthis.selectedItems = this._convertStringsToInts( newSelectedCids );\n\t\t\tthis._validateSelection();\n\n\t\t\tvar newSelectedModels = this.getSelectedModels();\n\n\t\t\tif( ! this._containSameElements( oldSelectedCids, this.selectedItems ) )\n\t\t\t{\n\t\t\t\tthis._addSelectedClassToSelectedItems( oldSelectedCids );\n\n\t\t\t\tif( ! options.silent )\n\t\t\t\t{\n\t\t\t\t\tif( this._isBackboneCourierAvailable() ) {\n\t\t\t\t\t\tthis.spawn( \"selectionChanged\", {\n\t\t\t\t\t\t\tselectedModels : newSelectedModels,\n\t\t\t\t\t\t\toldSelectedModels : oldSelectedModels\n\t\t\t\t\t\t} );\n\t\t\t\t\t} else this.trigger( \"selectionChanged\", newSelectedModels, oldSelectedModels );\n\t\t\t\t}\n\n\t\t\t\tthis.updateDependentControls();\n\t\t\t}\n\t\t},\n\n\t\tsetSelectedModel : function( newSelectedItem, options ) {\n\t\t\tif( ! newSelectedItem && newSelectedItem !== 0 )\n\t\t\t\tthis.setSelectedModels( [], options );\n\t\t\telse\n\t\t\t\tthis.setSelectedModels( [ newSelectedItem ], options );\n\t\t},\n\n\t\tgetView : function( reference, options ) {\n\t\t\toptions = _.extend( {}, {\n\t\t\t\tby : kDefaultReferenceBy\n\t\t\t}, options );\n\n\t\t\tswitch( options.by ) {\n\t\t\t\tcase \"id\" :\n\t\t\t\tcase \"cid\" :\n\t\t\t\t\tvar model = this.collection.get( reference ) || null;\n\t\t\t\t\treturn model && this.viewManager.findByModel( model );\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"offset\" :\n\t\t\t\t\tvar itemElements = this._getVisibleItemEls();\n\t\t\t\t\treturn $( itemElements.get( reference ) );\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"model\" :\n\t\t\t\t\treturn this.viewManager.findByModel( reference );\n\t\t\t\t\tbreak;\n\t\t\t\tdefault :\n\t\t\t\t\tthrow new Error( \"Invalid referenceBy option: \" + referenceBy );\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t},\n\n\t\trender : function() {\n\t\t\tvar _this = this;\n\n\t\t\tthis._hasBeenRendered = true;\n\n\t\t\tif( this.selectable ) this._saveSelection();\n\n\t\t\tvar modelViewContainerEl;\n\n\t\t\t// If collection view element is a table and it has a tbody\n\t\t\t// within it, render the model views inside of the tbody\n\t\t\tmodelViewContainerEl = this._getContainerEl();\n\n\t\t\tvar oldViewManager = this.viewManager;\n\t\t\tthis.viewManager = new ChildViewContainer();\n\n\t\t\t// detach each of our subviews that we have already created to represent models\n\t\t\t// in the collection. We are going to re-use the ones that represent models that\n\t\t\t// are still here, instead of creating new ones, so that we don't loose state\n\t\t\t// information in the views.\n\t\t\toldViewManager.each( function( thisModelView ) {\n\t\t\t\t// to boost performance, only detach those views that will be sticking around.\n\t\t\t\t// we won't need the other ones later, so no need to detach them individually.\n\t\t\t\tif( this.reuseModelViews && this.collection.get( thisModelView.model.cid ) ) {\n\t\t\t\t\tthisModelView.$el.detach();\n\t\t\t\t} else thisModelView.remove();\n\t\t\t}, this );\n\n\t\t\tmodelViewContainerEl.empty();\n\t\t\tvar fragmentContainer;\n\n\t\t\tif( this.detachedRendering )\n\t\t\t\tfragmentContainer = document.createDocumentFragment();\n\n\t\t\tthis.collection.each( function( thisModel ) {\n\t\t\t\tvar thisModelView = oldViewManager.findByModelCid( thisModel.cid );\n\t\t\t\tif( ! this.reuseModelViews || _.isUndefined( thisModelView ) ) {\n\t\t\t\t\t// if the model view has not already been created on a\n\t\t\t\t\t// previous render then create and initialize it now.\n\t\t\t\t\tthisModelView = this._createNewModelView( thisModel, this._getModelViewOptions( thisModel ) );\n\t\t\t\t}\n\n\t\t\t\tthis._insertAndRenderModelView( thisModelView, fragmentContainer || modelViewContainerEl );\n\t\t\t}, this );\n\n\t\t\tif( this.detachedRendering )\n\t\t\t\tmodelViewContainerEl.append( fragmentContainer );\n\n\t\t\tif( this.sortable ) this._setupSortable();\n\n\t\t\tthis._showEmptyListCaptionIfAppropriate();\n\n\t\t\tif( this._isBackboneCourierAvailable() )\n\t\t\t\tthis.spawn( \"render\" );\n\t\t\telse this.trigger( \"render\" );\n\n\t\t\tif( this.selectable ) {\n\t\t\t\tthis._restoreSelection();\n\t\t\t\tthis.updateDependentControls();\n\t\t\t}\n\n\t\t\tthis.forceRerenderOnNextSortEvent = false;\n\t\t},\n\n\t\t_showEmptyListCaptionIfAppropriate : function ( ) {\n\t\t\tthis._removeEmptyListCaption();\n\n\t\t\tif( this.emptyListCaption ) {\n\t\t\t\tvar visibleEls = this._getVisibleItemEls();\n\n\t\t\t\tif( visibleEls.length === 0 ) {\n\t\t\t\t\tvar emptyListString;\n\n\t\t\t\t\tif( _.isFunction( this.emptyListCaption ) )\n\t\t\t\t\t\temptyListString = this.emptyListCaption();\n\t\t\t\t\telse\n\t\t\t\t\t\temptyListString = this.emptyListCaption;\n\n\t\t\t\t\tvar $emptyListCaptionEl;\n\t\t\t\t\tvar $varEl = $( \"\" + emptyListString + \" \" );\n\n\t\t\t\t\t// need to wrap the empty caption to make it fit the rendered list structure (either with an li or a tr td)\n\t\t\t\t\tif( this._isRenderedAsList() )\n\t\t\t\t\t\t$emptyListCaptionEl = $varEl.wrapAll( \" \" ).parent().css( kStylesForEmptyListCaption );\n\t\t\t\t\telse\n\t\t\t\t\t\t$emptyListCaptionEl = $varEl.wrapAll( \" \" ).parent().parent().css( kStylesForEmptyListCaption );\n\n\t\t\t\t\tthis._getContainerEl().append( $emptyListCaptionEl );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t_removeEmptyListCaption : function( ) {\n\t\t\tif( this._isRenderedAsList() )\n\t\t\t\tthis._getContainerEl().find( \"> li > var.empty-list-caption\" ).parent().remove();\n\t\t\telse\n\t\t\t\tthis._getContainerEl().find( \"> tr > td > var.empty-list-caption\" ).parent().parent().remove();\n\t\t},\n\n\t\t// Render a single model view in container object \"parentElOrDocumentFragment\", which is either\n\t\t// a documentFragment or a jquery object. optional arg atIndex is not support for document fragments.\n\t\t_insertAndRenderModelView : function( modelView, parentElOrDocumentFragment, atIndex ) {\n\t\t\tvar thisModelViewWrapped = this._wrapModelView( modelView );\n\n\t\t\tif( parentElOrDocumentFragment.nodeType === 11 ) // if we are inserting into a document fragment, we need to use the DOM appendChild method\n\t\t\t\tparentElOrDocumentFragment.appendChild( thisModelViewWrapped.get( 0 ) );\n\t\t\telse {\n\t\t\t\tvar numberOfModelViewsCurrentlyInDOM = parentElOrDocumentFragment.children().length;\n\t\t\t\tif( ! _.isUndefined( atIndex ) && atIndex >= 0 && atIndex < numberOfModelViewsCurrentlyInDOM )\n\t\t\t\t\t// note this.collection.length might be greater than parentElOrDocumentFragment.children().length here\n\t\t\t\t\tparentElOrDocumentFragment.children().eq( atIndex ).before( thisModelViewWrapped );\n\t\t\t\telse {\n\t\t\t\t\t// if we are attempting to insert a modelView in an position that is beyond what is currently in the\n\t\t\t\t\t// DOM, then make a note that we need to re-render the collection view on the next sort event. If we dont\n\t\t\t\t\t// force this re-render, we can end up with modelViews in the wrong order when the collection defines\n\t\t\t\t\t// a comparator and multiple models are added at once. See https://github.com/rotundasoftware/backbone.collectionView/issues/69\n\t\t\t\t\tif( ! _.isUndefined( atIndex ) && atIndex > numberOfModelViewsCurrentlyInDOM ) this.forceRerenderOnNextSortEvent = true;\n\n\t\t\t\t\tparentElOrDocumentFragment.append( thisModelViewWrapped );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.viewManager.add( modelView );\n\n\t\t\t// we have to render the modelView after it has been put in context, as opposed to in the\n\t\t\t// initialize function of the modelView, because some rendering might be dependent on\n\t\t\t// the modelView's context in the DOM tree. For example, if the modelView stretch()'s itself,\n\t\t\t// it must be in full context in the DOM tree or else the stretch will not behave as intended.\n\t\t\tvar renderResult = modelView.render();\n\n\t\t\t// return false from the view's render function to hide this item\n\t\t\tif( renderResult === false ) {\n\t\t\t\tthisModelViewWrapped.hide();\n\t\t\t\tthisModelViewWrapped.addClass( \"not-visible\" );\n\t\t\t}\n\n\t\t\tvar hideThisModelView = false;\n\t\t\tif( _.isFunction( this.visibleModelsFilter ) )\n\t\t\t\thideThisModelView = ! this.visibleModelsFilter( modelView.model );\n\n\t\t\tif( thisModelViewWrapped.children().length === 1 )\n\t\t\t\tthisModelViewWrapped.toggle( ! hideThisModelView );\n\t\t\telse modelView.$el.toggle( ! hideThisModelView );\n\n\t\t\tthisModelViewWrapped.toggleClass( \"not-visible\", hideThisModelView );\n\n\t\t\tif( ! hideThisModelView && this.emptyListCaption ) this._removeEmptyListCaption();\n\t\t},\n\n\t\tupdateDependentControls : function() {\n\t\t\tif( this._isBackboneCourierAvailable() ) {\n\t\t\t\tthis.spawn( \"updateDependentControls\", {\n\t\t\t\t\tselectedModels : this.getSelectedModels()\n\t\t\t\t} );\n\t\t\t} else this.trigger( \"updateDependentControls\", this.getSelectedModels() );\n\t\t},\n\n\t\t// Override `Backbone.View.remove` to also destroy all Views in `viewManager`\n\t\tremove : function() {\n\t\t\tthis.viewManager.each( function( view ) {\n\t\t\t\tview.remove();\n\t\t\t} );\n\n\t\t\tBackbone.View.prototype.remove.apply( this, arguments );\n\t\t},\n\n\t\treapplyFilter : function( whichFilter ) {\n\t\t\tvar _this = this;\n\n\t\t\tif( ! _.contains( [ \"selectableModels\", \"sortableModels\", \"visibleModels\" ], whichFilter ) ) {\n\t\t\t\tthrow new Error( \"Invalid filter identifier supplied to reapplyFilter: \" + whichFilter );\n\t\t\t}\n\n\t\t\tswitch( whichFilter ) {\n\t\t\t\tcase \"visibleModels\":\n\t\t\t\t\t_this.viewManager.each( function( thisModelView ) {\n\t\t\t\t\t\tvar notVisible = _this.visibleModelsFilter && ! _this.visibleModelsFilter.call( _this, thisModelView.model );\n\n\t\t\t\t\t\tthisModelView.$el.toggleClass( \"not-visible\", notVisible );\n\t\t\t\t\t\tif( _this._modelViewHasWrapperLI( thisModelView ) ) {\n\t\t\t\t\t\t\tthisModelView.$el.closest( \"li\" ).toggleClass( \"not-visible\", notVisible ).toggle( ! notVisible );\n\t\t\t\t\t\t} else thisModelView.$el.toggle( ! notVisible );\n\t\t\t\t\t} );\n\n\t\t\t\t\tthis._showEmptyListCaptionIfAppropriate();\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"sortableModels\":\n\t\t\t\t\t_this.$el.sortable( \"destroy\" );\n\n\t\t\t\t\t_this.viewManager.each( function( thisModelView ) {\n\t\t\t\t\t\tvar notSortable = _this.sortableModelsFilter && ! _this.sortableModelsFilter.call( _this, thisModelView.model );\n\n\t\t\t\t\t\tthisModelView.$el.toggleClass( \"not-sortable\", notSortable );\n\t\t\t\t\t\tif( _this._modelViewHasWrapperLI( thisModelView ) ) {\n\t\t\t\t\t\t\tthisModelView.$el.closest( \"li\" ).toggleClass( \"not-sortable\", notSortable );\n\t\t\t\t\t\t}\n\t\t\t\t\t} );\n\n\t\t\t\t\t_this._setupSortable();\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"selectableModels\":\n\t\t\t\t\t_this.viewManager.each( function( thisModelView ) {\n\t\t\t\t\t\tvar notSelectable = _this.selectableModelsFilter && ! _this.selectableModelsFilter.call( _this, thisModelView.model );\n\n\t\t\t\t\t\tthisModelView.$el.toggleClass( \"not-selectable\", notSelectable );\n\t\t\t\t\t\tif( _this._modelViewHasWrapperLI( thisModelView ) ) {\n\t\t\t\t\t\t\tthisModelView.$el.closest( \"li\" ).toggleClass( \"not-selectable\", notSelectable );\n\t\t\t\t\t\t}\n\t\t\t\t\t} );\n\n\t\t\t\t\t_this._validateSelection();\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t},\n\n\t\t// A method to remove the view relating to model.\n\t\t_removeModelView : function( modelView ) {\n\t\t\tif( this.selectable ) this._saveSelection();\n\n\t\t\tthis.viewManager.remove( modelView ); // Remove the view from the viewManager\n\t\t\tif( this._modelViewHasWrapperLI( modelView ) ) modelView.$el.parent().remove(); // Remove the li wrapper from the DOM\n\t\t\tmodelView.remove(); // Remove the view from the DOM and stop listening to events\n\n\t\t\tif( this.selectable ) this._restoreSelection();\n\n\t\t\tthis._showEmptyListCaptionIfAppropriate();\n\t\t},\n\n\t\t_validateSelectionAndRender : function() {\n\t\t\tthis._validateSelection();\n\t\t\tthis.render();\n\t\t},\n\n\t\t_registerCollectionEvents : function() {\n\n\t\t\tthis.listenTo( this.collection, \"add\", function( model ) {\n\t\t\t\tvar modelView;\n\t\t\t\tif( this._hasBeenRendered ) {\n\t\t\t\t\tmodelView = this._createNewModelView( model, this._getModelViewOptions( model ) );\n\t\t\t\t\tthis._insertAndRenderModelView( modelView, this._getContainerEl(), this.collection.indexOf( model ) );\n\t\t\t\t}\n\n\t\t\t\tif( this._isBackboneCourierAvailable() )\n\t\t\t\t\tthis.spawn( \"add\", modelView );\n\t\t\t\telse this.trigger( \"add\", modelView );\n\t\t\t} );\n\n\t\t\tthis.listenTo( this.collection, \"remove\", function( model ) {\n\t\t\t\tvar modelView;\n\n\t\t\t\tif( this._hasBeenRendered ) {\n\t\t\t\t\tmodelView = this.viewManager.findByModelCid( model.cid );\n\t\t\t\t\tthis._removeModelView( modelView );\n\t\t\t\t}\n\n\t\t\t\tif( this._isBackboneCourierAvailable() )\n\t\t\t\t\tthis.spawn( \"remove\" );\n\t\t\t\telse this.trigger( \"remove\" );\n\t\t\t} );\n\n\t\t\tthis.listenTo( this.collection, \"reset\", function() {\n\t\t\t\tif( this._hasBeenRendered ) this.render();\n\t\t\t\tif( this._isBackboneCourierAvailable() )\n\t\t\t\t\tthis.spawn( \"reset\" );\n\t\t\t\telse this.trigger( \"reset\" );\n\t\t\t} );\n\n\t\t\t// we should not be listening to change events on the model as a default behavior. the models\n\t\t\t// should be responsible for re-rendering themselves if necessary, and if the collection does\n\t\t\t// also need to re-render as a result of a model change, this should be handled by overriding\n\t\t\t// this method. by default the collection view should not re-render in response to model changes\n\t\t\t// this.listenTo( this.collection, \"change\", function( model ) {\n\t\t\t// \tif( this._hasBeenRendered ) this.viewManager.findByModel( model ).render();\n\t\t\t// \tif( this._isBackboneCourierAvailable() )\n\t\t\t// \t\tthis.spawn( \"change\", { model : model } );\n\t\t\t// } );\n\n\t\t\tthis.listenTo( this.collection, \"sort\", function( collection, options ) {\n\t\t\t\tif( this._hasBeenRendered && ( options.add !== true || this.forceRerenderOnNextSortEvent ) ) this.render();\n\t\t\t\tif( this._isBackboneCourierAvailable() )\n\t\t\t\t\tthis.spawn( \"sort\" );\n\t\t\t\telse this.trigger( \"sort\" );\n\t\t\t} );\n\t\t},\n\n\t\t_getContainerEl : function() {\n\t\t\tif ( this._isRenderedAsTable() ) {\n\t\t\t\t// not all tables have a tbody, so we test\n\t\t\t\tvar tbody = this.$el.find( \"> tbody\" );\n\t\t\t\tif ( tbody.length > 0 )\n\t\t\t\t\treturn tbody;\n\t\t\t}\n\t\t\treturn this.$el;\n\t\t},\n\n\t\t_getClickedItemId : function( theEvent ) {\n\t\t\tvar clickedItemId = null;\n\n\t\t\t// important to use currentTarget as opposed to target, since we could be bubbling\n\t\t\t// an event that took place within another collectionList\n\t\t\tvar clickedItemEl = $( theEvent.currentTarget );\n\t\t\tif( clickedItemEl.closest( \".collection-view\" ).get(0) !== this.$el.get(0) ) return;\n\n\t\t\t// determine which list item was clicked. If we clicked in the blank area\n\t\t\t// underneath all the elements, we want to know that too, since in this\n\t\t\t// case we will want to deselect all elements. so check to see if the clicked\n\t\t\t// DOM element is the list itself to find that out.\n\t\t\tvar clickedItem = clickedItemEl.closest( \"[data-model-cid]\" );\n\t\t\tif( clickedItem.length > 0 )\n\t\t\t{\n\t\t\t\tclickedItemId = clickedItem.attr( \"data-model-cid\" );\n\t\t\t\tif( $.isNumeric( clickedItemId ) ) clickedItemId = parseInt( clickedItemId, 10 );\n\t\t\t}\n\n\t\t\treturn clickedItemId;\n\t\t},\n\n\t\t_updateItemTemplate : function() {\n\t\t\tvar itemTemplateHtml;\n\t\t\tif( this.itemTemplate )\n\t\t\t{\n\t\t\t\tif( $( this.itemTemplate ).length === 0 )\n\t\t\t\t\tthrow \"Could not find item template from selector: \" + this.itemTemplate;\n\n\t\t\t\titemTemplateHtml = $( this.itemTemplate ).html();\n\t\t\t}\n\t\t\telse\n\t\t\t\titemTemplateHtml = this.$( \".item-template\" ).html();\n\n\t\t\tif( itemTemplateHtml ) this.itemTemplateFunction = _.template( itemTemplateHtml );\n\n\t\t},\n\n\t\t_validateSelection : function() {\n\t\t\t// note can't use the collection's proxy to underscore because \"cid\" is not an attribute,\n\t\t\t// but an element of the model object itself.\n\t\t\tvar modelReferenceIds = _.pluck( this.collection.models, \"cid\" );\n\t\t\tthis.selectedItems = _.intersection( modelReferenceIds, this.selectedItems );\n\n\t\t\tif( _.isFunction( this.selectableModelsFilter ) )\n\t\t\t{\n\t\t\t\tthis.selectedItems = _.filter( this.selectedItems, function( thisItemId ) {\n\t\t\t\t\treturn this.selectableModelsFilter.call( this, this.collection.get( thisItemId ) );\n\t\t\t\t}, this );\n\t\t\t}\n\t\t},\n\n\t\t_saveSelection : function() {\n\t\t\t// save the current selection. use restoreSelection() to restore the selection to the state it was in the last time saveSelection() was called.\n\t\t\tif( ! this.selectable ) throw \"Attempt to save selection on non-selectable list\";\n\t\t\tthis.savedSelection = {\n\t\t\t\titems : _.clone( this.selectedItems ),\n\t\t\t\toffset : this.getSelectedModel( { by : \"offset\" } )\n\t\t\t};\n\t\t},\n\n\t\t_restoreSelection : function() {\n\t\t\tif( ! this.savedSelection ) throw \"Attempt to restore selection but no selection has been saved!\";\n\n\t\t\t// reset selectedItems to empty so that we \"redraw\" all \"selected\" classes\n\t\t\t// when we set our new selection. We do this because it is likely that our\n\t\t\t// contents have been refreshed, and we have thus lost all old \"selected\" classes.\n\t\t\tthis.setSelectedModels( [], { silent : true } );\n\n\t\t\tif( this.savedSelection.items.length > 0 )\n\t\t\t{\n\t\t\t\t// first try to restore the old selected items using their reference ids.\n\t\t\t\tthis.setSelectedModels( this.savedSelection.items, { by : \"cid\", silent : true } );\n\n\t\t\t\t// all the items with the saved reference ids have been removed from the list.\n\t\t\t\t// ok. try to restore the selection based on the offset that used to be selected.\n\t\t\t\t// this is the expected behavior after a item is deleted from a list (i.e. select\n\t\t\t\t// the line that immediately follows the deleted line).\n\t\t\t\tif( this.selectedItems.length === 0 )\n\t\t\t\t\tthis.setSelectedModel( this.savedSelection.offset, { by : \"offset\" } );\n\n\t\t\t\t// Trigger a selection changed if the previously selected items were not all found\n\t\t\t\tif (this.selectedItems.length !== this.savedSelection.items.length)\n\t\t\t\t{\n\t\t\t\t\tif( this._isBackboneCourierAvailable() ) {\n\t\t\t\t\t\tthis.spawn( \"selectionChanged\", {\n\t\t\t\t\t\t\tselectedModels : this.getSelectedModels(),\n\t\t\t\t\t\t\toldSelectedModels : []\n\t\t\t\t\t\t} );\n\t\t\t\t\t} else this.trigger( \"selectionChanged\", this.getSelectedModels(), [] );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t_addSelectedClassToSelectedItems : function( oldItemsIdsWithSelectedClass ) {\n\t\t\tif( _.isUndefined( oldItemsIdsWithSelectedClass ) ) oldItemsIdsWithSelectedClass = [];\n\n\t\t\t// oldItemsIdsWithSelectedClass is used for optimization purposes only. If this info is supplied then we\n\t\t\t// only have to add / remove the \"selected\" class from those items that \"selected\" state has changed.\n\n\t\t\tvar itemsIdsFromWhichSelectedClassNeedsToBeRemoved = oldItemsIdsWithSelectedClass;\n\t\t\titemsIdsFromWhichSelectedClassNeedsToBeRemoved = _.without( itemsIdsFromWhichSelectedClassNeedsToBeRemoved, this.selectedItems );\n\n\t\t\t_.each( itemsIdsFromWhichSelectedClassNeedsToBeRemoved, function( thisItemId ) {\n\t\t\t\tthis._getContainerEl().find( \"[data-model-cid=\" + thisItemId + \"]\" ).removeClass( \"selected\" );\n\n\t\t\t\tif( this._isRenderedAsList() ) {\n\t\t\t\t\tthis._getContainerEl().find( \"li[data-model-cid=\" + thisItemId + \"] > *\" ).removeClass( \"selected\" );\n\t\t\t\t}\n\t\t\t}, this );\n\n\t\t\tvar itemsIdsFromWhichSelectedClassNeedsToBeAdded = this.selectedItems;\n\t\t\titemsIdsFromWhichSelectedClassNeedsToBeAdded = _.without( itemsIdsFromWhichSelectedClassNeedsToBeAdded, oldItemsIdsWithSelectedClass );\n\n\t\t\t_.each( itemsIdsFromWhichSelectedClassNeedsToBeAdded, function( thisItemId ) {\n\t\t\t\tthis._getContainerEl().find( \"[data-model-cid=\" + thisItemId + \"]\" ).addClass( \"selected\" );\n\n\t\t\t\tif( this._isRenderedAsList() ) {\n\t\t\t\t\tthis._getContainerEl().find( \"li[data-model-cid=\" + thisItemId + \"] > *\" ).addClass( \"selected\" );\n\t\t\t\t}\n\t\t\t}, this );\n\t\t},\n\n\t\t_reorderCollectionBasedOnHTML : function() {\n\n\t\t\tvar _this = this;\n\n\t\t\tthis._getContainerEl().children().each( function() {\n\t\t\t\tvar thisModelCid = $( this ).attr( \"data-model-cid\" );\n\n\t\t\t\tif( thisModelCid )\n\t\t\t\t{\n\t\t\t\t\t// remove the current model and then add it back (at the end of the collection).\n\t\t\t\t\t// When we are done looping through all models, they will be in the correct order.\n\t\t\t\t\tvar thisModel = _this.collection.get( thisModelCid );\n\t\t\t\t\tif( thisModel )\n\t\t\t\t\t{\n\t\t\t\t\t\t_this.collection.remove( thisModel, { silent : true } );\n\t\t\t\t\t\t_this.collection.add( thisModel, { silent : true, sort : ! _this.collection.comparator } );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\tif( this._isBackboneCourierAvailable() ) this.spawn( \"reorder\" );\n\t\t\telse this.collection.trigger( \"reorder\" );\n\n\t\t\tif( this.collection.comparator ) this.collection.sort();\n\n\t\t},\n\n\t\t_getModelViewConstructor : function( thisModel ) {\n\t\t\treturn this.modelView || mDefaultModelViewConstructor;\n\t\t},\n\n\t\t_getModelViewOptions : function( thisModel ) {\n\t\t\tvar modelViewOptions = this.modelViewOptions;\n\t\t\tif( _.isFunction( modelViewOptions ) ) modelViewOptions = modelViewOptions( thisModel );\n\n\t\t\treturn _.extend( { model : thisModel }, modelViewOptions );\n\t\t},\n\n\t\t_createNewModelView : function( model, modelViewOptions ) {\n\t\t\tvar modelViewConstructor = this._getModelViewConstructor( model );\n\t\t\tif( _.isUndefined( modelViewConstructor ) ) throw \"Could not find modelView constructor for model\";\n\n\t\t\tvar newModelView = new( modelViewConstructor )( modelViewOptions );\n\t\t\tnewModelView.collectionListView = newModelView.collectionView = this; // collectionListView for legacy\n\n\t\t\treturn newModelView;\n\t\t},\n\n\t\t_wrapModelView : function( modelView ) {\n\t\t\tvar _this = this;\n\n\t\t\t// we use items client ids as opposed to real ids, since we may not have a representation\n\t\t\t// of these models on the server\n\t\t\tvar modelViewWrapperEl;\n\n\t\t\tif( this._isRenderedAsTable() ) {\n\t\t\t\t// if we are rendering the collection in a table, the template $el is a tr so we just need to set the data-model-cid\n\t\t\t\tmodelViewWrapperEl = modelView.$el;\n\t\t\t\tmodelView.$el.attr( \"data-model-cid\", modelView.model.cid );\n\t\t\t}\n\t\t\telse if( this._isRenderedAsList() ) {\n\t\t\t\t// if we are rendering the collection in a list, we need wrap each item in an (if its not already an )\n\t\t\t\t// and set the data-model-cid\n\t\t\t\tif( modelView.$el.is( \"li\" ) ) {\n\t\t\t\t\tmodelViewWrapperEl = modelView.$el;\n\t\t\t\t\tmodelView.$el.attr( \"data-model-cid\", modelView.model.cid );\n\t\t\t\t} else {\n\t\t\t\t\tmodelViewWrapperEl = modelView.$el.wrapAll( \" \" ).parent();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif( _.isFunction( this.sortableModelsFilter ) )\n\t\t\t\tif( ! this.sortableModelsFilter.call( _this, modelView.model ) ) {\n\t\t\t\t\tmodelViewWrapperEl.addClass( \"not-sortable\" );\n\t\t\t\t\tmodelView.$el.addClass( \"not-selectable\" );\n\t\t\t\t}\n\n\t\t\tif( _.isFunction( this.selectableModelsFilter ) )\n\t\t\t\tif( ! this.selectableModelsFilter.call( _this, modelView.model ) ) {\n\t\t\t\t\tmodelViewWrapperEl.addClass( \"not-selectable\" );\n\t\t\t\t\tmodelView.$el.addClass( \"not-selectable\" );\n\t\t\t\t}\n\n\t\t\treturn modelViewWrapperEl;\n\t\t},\n\n\t\t_convertStringsToInts : function( theArray ) {\n\t\t\treturn _.map( theArray, function( thisEl ) {\n\t\t\t\tif( ! _.isString( thisEl ) ) return thisEl;\n\t\t\t\tvar thisElAsNumber = parseInt( thisEl, 10 );\n\t\t\t\treturn( thisElAsNumber == thisEl ? thisElAsNumber : thisEl );\n\t\t\t} );\n\t\t},\n\n\t\t_containSameElements : function( arrayA, arrayB ) {\n\t\t\tif( arrayA.length != arrayB.length ) return false;\n\t\t\tvar intersectionSize = _.intersection( arrayA, arrayB ).length;\n\t\t\treturn intersectionSize == arrayA.length; // and must also equal arrayB.length, since arrayA.length == arrayB.length\n\t\t},\n\n\t\t_isRenderedAsTable : function() {\n\t\t\treturn this.$el.prop( \"tagName\" ).toLowerCase() === \"table\";\n\t\t},\n\n\t\t_isRenderedAsList : function() {\n\t\t\treturn ! this._isRenderedAsTable();\n\t\t},\n\n\t\t_modelViewHasWrapperLI : function( modelView ) {\n\t\t\treturn this._isRenderedAsList() && ! modelView.$el.is( \"li\" );\n\t\t},\n\n\t\t// Returns the wrapper HTML element for each visible modelView.\n\t\t// When rendering in a table context, the returned elements are the $el of each modelView.\n\t\t// When rendering in a list context,\n\t\t// If the $el of the modelView is an , the returned elements are the $el of each modelView.\n\t\t// Otherwise, the returned elements are the 's the collectionView wrapped around each modelView $el.\n\t\t_getVisibleItemEls : function() {\n\t\t\tvar itemElements = [];\n\t\t\titemElements = this._getContainerEl().find( \"> [data-model-cid]:not(.not-visible)\" );\n\n\t\t\treturn itemElements;\n\t\t},\n\n\t\t_charCodes : {\n\t\t\tupArrow : 38,\n\t\t\tdownArrow : 40\n\t\t},\n\n\t\t_isBackboneCourierAvailable : function() {\n\t\t\treturn !_.isUndefined( Backbone.Courier );\n\t\t},\n\n\t\t_setupSortable : function() {\n\t\t\tvar sortableOptions = _.extend( {\n\t\t\t\taxis : \"y\",\n\t\t\t\tdistance : 10,\n\t\t\t\tforcePlaceholderSize : true,\n\t\t\t\titems : this._isRenderedAsTable() ? \"> tbody > tr:not(.not-sortable)\" : \"> li:not(.not-sortable)\",\n\t\t\t\tstart : _.bind( this._sortStart, this ),\n\t\t\t\tchange : _.bind( this._sortChange, this ),\n\t\t\t\tstop : _.bind( this._sortStop, this ),\n\t\t\t\treceive : _.bind( this._receive, this ),\n\t\t\t\tover : _.bind( this._over, this )\n\t\t\t}, _.result( this, \"sortableOptions\" ) );\n\n\t\t\tthis.$el = this.$el.sortable( sortableOptions );\n\t\t\t//this.$el.sortable( \"enable\" ); // in case it was disabled previously\n\t\t},\n\n\t\t_sortStart : function( event, ui ) {\n\t\t\tvar modelBeingSorted = this.collection.get( ui.item.attr( \"data-model-cid\" ) );\n\t\t\tif( this._isBackboneCourierAvailable() )\n\t\t\t\tthis.spawn( \"sortStart\", { modelBeingSorted : modelBeingSorted } );\n\t\t\telse this.trigger( \"sortStart\", modelBeingSorted );\n\t\t},\n\n\t\t_sortChange : function( event, ui ) {\n\t\t\tvar modelBeingSorted = this.collection.get( ui.item.attr( \"data-model-cid\" ) );\n\n\t\t\tif( this._isBackboneCourierAvailable() )\n\t\t\t\tthis.spawn( \"sortChange\", { modelBeingSorted : modelBeingSorted } );\n\t\t\telse this.trigger( \"sortChange\", modelBeingSorted );\n\t\t},\n\n\t\t_sortStop : function( event, ui ) {\n\t\t\tvar modelBeingSorted = this.collection.get( ui.item.attr( \"data-model-cid\" ) );\n\t\t\tvar modelViewContainerEl = this._getContainerEl();\n\t\t\tvar newIndex = modelViewContainerEl.children().index( ui.item );\n\n\t\t\tif( newIndex == -1 && modelBeingSorted ) {\n\t\t\t\t// the element was removed from this list. can happen if this sortable is connected\n\t\t\t\t// to another sortable, and the item was dropped into the other sortable.\n\t\t\t\tthis.collection.remove( modelBeingSorted );\n\t\t\t}\n\n\t\t\tif( ! modelBeingSorted ) return; // something is wacky. we don't mess with this case, preferring to guarantee that we can always provide a reference to the model\n\n\t\t\tthis._reorderCollectionBasedOnHTML();\n\t\t\tthis.updateDependentControls();\n\n\t\t\tif( this._isBackboneCourierAvailable() )\n\t\t\t\tthis.spawn( \"sortStop\", { modelBeingSorted : modelBeingSorted, newIndex : newIndex } );\n\t\t\telse this.trigger( \"sortStop\", modelBeingSorted, newIndex );\n\t\t},\n\n\t\t_receive : function( event, ui ) {\n\n\t\t\tvar senderListEl = ui.sender;\n\t\t\tvar senderCollectionListView = senderListEl.data( \"view\" );\n\t\t\tif( ! senderCollectionListView || ! senderCollectionListView.collection ) return;\n\n\t\t\tvar newIndex = this._getContainerEl().children().index( ui.item );\n\t\t\tvar modelReceived = senderCollectionListView.collection.get( ui.item.attr( \"data-model-cid\" ) );\n\t\t\tsenderCollectionListView.collection.remove( modelReceived );\n\t\t\tthis.collection.add( modelReceived, { at : newIndex } );\n\t\t\tmodelReceived.collection = this.collection; // otherwise will not get properly set, since modelReceived.collection might already have a value.\n\t\t\tthis.setSelectedModel( modelReceived );\n\t\t},\n\n\t\t_over : function( event, ui ) {\n\t\t\t// when an item is being dragged into the sortable,\n\t\t\t// hide the empty list caption if it exists\n\t\t\tthis._getContainerEl().find( \"> var.empty-list-caption\" ).hide();\n\t\t},\n\n\t\t_onKeydown : function( event ) {\n\t\t\tif( ! this.processKeyEvents ) return true;\n\n\t\t\tvar trap = false;\n\n\t\t\tif( this.getSelectedModels( { by : \"offset\" } ).length == 1 )\n\t\t\t{\n\t\t\t\t// need to trap down and up arrows or else the browser\n\t\t\t\t// will end up scrolling a autoscroll div.\n\n\t\t\t\tvar currentOffset = this.getSelectedModel( { by : \"offset\" } );\n\t\t\t\tif( event.which === this._charCodes.upArrow && currentOffset !== 0 )\n\t\t\t\t{\n\t\t\t\t\tthis.setSelectedModel( currentOffset - 1, { by : \"offset\" } );\n\t\t\t\t\ttrap = true;\n\t\t\t\t}\n\t\t\t\telse if( event.which === this._charCodes.downArrow && currentOffset !== this.collection.length - 1 )\n\t\t\t\t{\n\t\t\t\t\tthis.setSelectedModel( currentOffset + 1, { by : \"offset\" } );\n\t\t\t\t\ttrap = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn ! trap;\n\t\t},\n\n\t\t_listItem_onMousedown : function( theEvent ) {\n\t\t\tvar clickedItemId = this._getClickedItemId( theEvent );\n\n\t\t\tif( clickedItemId ) {\n\t\t\t\tvar clickedModel = this.collection.get( clickedItemId );\n\t\t\t\tif( this._isBackboneCourierAvailable() ) {\n\t\t\t\t\tvar data = {\n\t\t\t\t\t\tclickedModel : clickedModel,\n\t\t\t\t\t\tmetaKeyPressed : theEvent.ctrlKey || theEvent.metaKey\n\t\t\t\t\t};\n\n\t\t\t\t\t_.each( [ 'preventDefault', 'stopPropagation', 'stopImmediatePropagation' ], function( thisMethod ) {\n\t\t\t\t\t\tdata[ thisMethod ] = function() {\n\t\t\t\t\t\t\ttheEvent[ thisMethod ]();\n\t\t\t\t\t\t};\n\t\t\t\t\t} );\n\n\t\t\t\t\tthis.spawn( \"click\", data );\n\t\t\t\t}\n\t\t\t\telse this.trigger( \"click\", clickedModel );\n\t\t\t}\n\n\t\t\tif( ! this.selectable || ! this.clickToSelect ) return;\n\n\t\t\tif( clickedItemId )\n\t\t\t{\n\t\t\t\t// Exit if an unselectable item was clicked\n\t\t\t\tif( _.isFunction( this.selectableModelsFilter ) &&\n\t\t\t\t\t! this.selectableModelsFilter.call( this, this.collection.get( clickedItemId ) ) )\n\t\t\t\t{\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// a selectable list item was clicked\n\t\t\t\tif( this.selectMultiple && theEvent.shiftKey )\n\t\t\t\t{\n\t\t\t\t\tvar firstSelectedItemIndex = -1;\n\n\t\t\t\t\tif( this.selectedItems.length > 0 )\n\t\t\t\t\t{\n\t\t\t\t\t\tthis.collection.find( function( thisItemModel ) {\n\t\t\t\t\t\t\tfirstSelectedItemIndex++;\n\n\t\t\t\t\t\t\t// exit when we find our first selected element\n\t\t\t\t\t\t\treturn _.contains( this.selectedItems, thisItemModel.cid );\n\t\t\t\t\t\t}, this );\n\t\t\t\t\t}\n\n\t\t\t\t\tvar clickedItemIndex = -1;\n\t\t\t\t\tthis.collection.find( function( thisItemModel ) {\n\t\t\t\t\t\tclickedItemIndex++;\n\n\t\t\t\t\t\t// exit when we find the clicked element\n\t\t\t\t\t\treturn thisItemModel.cid == clickedItemId;\n\t\t\t\t\t}, this );\n\n\t\t\t\t\tvar shiftKeyRootSelectedItemIndex = firstSelectedItemIndex == -1 ? clickedItemIndex : firstSelectedItemIndex;\n\t\t\t\t\tvar minSelectedItemIndex = Math.min( clickedItemIndex, shiftKeyRootSelectedItemIndex );\n\t\t\t\t\tvar maxSelectedItemIndex = Math.max( clickedItemIndex, shiftKeyRootSelectedItemIndex );\n\n\t\t\t\t\tvar newSelectedItems = [];\n\t\t\t\t\tfor( var thisIndex = minSelectedItemIndex; thisIndex <= maxSelectedItemIndex; thisIndex ++ )\n\t\t\t\t\t\tnewSelectedItems.push( this.collection.at( thisIndex ).cid );\n\t\t\t\t\tthis.setSelectedModels( newSelectedItems, { by : \"cid\" } );\n\n\t\t\t\t\t// shift clicking will usually highlight selectable text, which we do not want.\n\t\t\t\t\t// this is a cross browser (hopefully) snippet that deselects all text selection.\n\t\t\t\t\tif( document.selection && document.selection.empty )\n\t\t\t\t\t\tdocument.selection.empty();\n\t\t\t\t\telse if(window.getSelection) {\n\t\t\t\t\t\tvar sel = window.getSelection();\n\t\t\t\t\t\tif( sel && sel.removeAllRanges )\n\t\t\t\t\t\t\tsel.removeAllRanges();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if( ( this.selectMultiple || _.contains( this.selectedItems, clickedItemId ) ) && ( this.clickToToggle || theEvent.metaKey || theEvent.ctrlKey ) )\n\t\t\t\t{\n\t\t\t\t\tif( _.contains( this.selectedItems, clickedItemId ) )\n\t\t\t\t\t\tthis.setSelectedModels( _.without( this.selectedItems, clickedItemId ), { by : \"cid\" } );\n\t\t\t\t\telse this.setSelectedModels( _.union( this.selectedItems, [clickedItemId] ), { by : \"cid\" } );\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tthis.setSelectedModels( [ clickedItemId ], { by : \"cid\" } );\n\t\t\t}\n\t\t\telse\n\t\t\t\t// the blank area of the list was clicked\n\t\t\t\tthis.setSelectedModels( [] );\n\n\t\t},\n\n\t\t_listItem_onDoubleClick : function( theEvent ) {\n\n\t\t\tvar clickedItemId = this._getClickedItemId( theEvent );\n\n\t\t\tif( clickedItemId )\n\t\t\t{\n\t\t\t\tvar clickedModel = this.collection.get( clickedItemId );\n\n\t\t\t\tif( this._isBackboneCourierAvailable() )\n\t\t\t\t\tthis.spawn( \"doubleClick\", { clickedModel : clickedModel, metaKeyPressed : theEvent.ctrlKey || theEvent.metaKey } );\n\t\t\t\telse this.trigger( \"doubleClick\", clickedModel );\n\t\t\t}\n\t\t},\n\n\t\t_listBackground_onClick : function( theEvent ) {\n\t\t\tif( ! this.selectable || ! this.clickToSelect ) return;\n\t\t\tif( ! $( theEvent.target ).is( \".collection-view\" ) ) return;\n\n\t\t\tthis.setSelectedModels( [] );\n\t\t}\n\n\t}, {\n\t\tsetDefaultModelViewConstructor : function( theConstructor ) {\n\t\t\tmDefaultModelViewConstructor = theConstructor;\n\t\t}\n\t});\n\n\t/*\n\t* Backbone.ViewOptions, v0.2.4\n\t* Copyright (c)2014 Rotunda Software, LLC.\n\t* Distributed under MIT license\n\t* http://github.com/rotundasoftware/backbone.viewOptions\n\t*/\n\n\tBackbone.ViewOptions = {};\n\n\tBackbone.ViewOptions.add = function( view, optionsDeclarationsProperty ) {\n\t\tif( _.isUndefined( optionsDeclarationsProperty ) ) optionsDeclarationsProperty = \"options\";\n\n\t\t// ****************** Public methods added to view ******************\n\n\t\tview.setOptions = function( options ) {\n\t\t\tvar _this = this;\n\t\t\tvar optionsThatWereChanged = {};\n\t\t\tvar optionsThatWereChangedPreviousValues = {};\n\n\t\t\tvar optionDeclarations = _.result( this, optionsDeclarationsProperty );\n\n\t\t\tif( ! _.isUndefined( optionDeclarations ) ) {\n\t\t\t\tvar normalizedOptionDeclarations = _normalizeOptionDeclarations( optionDeclarations );\n\n\t\t\t\t_.each( normalizedOptionDeclarations, function( thisOptionProperties, thisOptionName ) {\n\t\t\t\t\tvar thisOptionRequired = thisOptionProperties.required;\n\t\t\t\t\tvar thisOptionDefaultValue = thisOptionProperties.defaultValue;\n\n\t\t\t\t\tif( thisOptionRequired ) {\n\t\t\t\t\t\t// note we do not throw an error if a required option is not supplied, but it is\n\t\t\t\t\t\t// found on the object itself (due to a prior call of view.setOptions, most likely)\n\n\t\t\t\t\t\tif( ( ! options || ! _.contains( _.keys( options ), thisOptionName ) ) && _.isUndefined( _this[ thisOptionName ] ) )\n\t\t\t\t\t\t\tthrow new Error( \"Required option \\\"\" + thisOptionName + \"\\\" was not supplied.\" );\n\n\t\t\t\t\t\tif( options && _.contains( _.keys( options ), thisOptionName ) && _.isUndefined( options[ thisOptionName ] ) )\n\t\t\t\t\t\t\tthrow new Error( \"Required option \\\"\" + thisOptionName + \"\\\" can not be set to undefined.\" );\n\t\t\t\t\t}\n\n\t\t\t\t\t// attach the supplied value of this option, or the appropriate default value, to the view object\n\t\t\t\t\tif( options && thisOptionName in options && ! _.isUndefined( options[ thisOptionName ] ) ) {\n\t\t\t\t\t\tvar oldValue = _this[ thisOptionName ];\n\t\t\t\t\t\tvar newValue = options[ thisOptionName ];\n\t\t\t\t\t\t// if this option already exists on the view, and the new value is different,\n\t\t\t\t\t\t// make a note that we will be changing it\n\t\t\t\t\t\tif( ! _.isUndefined( oldValue ) && oldValue !== newValue ) {\n\t\t\t\t\t\t\toptionsThatWereChangedPreviousValues[ thisOptionName ] = oldValue;\n\t\t\t\t\t\t\toptionsThatWereChanged[ thisOptionName ] = newValue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t_this[ thisOptionName ] = newValue;\n\t\t\t\t\t\t// note we do NOT delete the option off the options object here so that\n\t\t\t\t\t\t// multiple views can be passed the same options object without issue.\n\t\t\t\t\t}\n\t\t\t\t\telse if( _.isUndefined( _this[ thisOptionName ] ) ) {\n\t\t\t\t\t\t// note defaults do not write over any existing properties on the view itself.\n\t\t\t\t\t\t_this[ thisOptionName ] = thisOptionDefaultValue;\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\tif( _.keys( optionsThatWereChanged ).length > 0 ) {\n\t\t\t\tif( _.isFunction( _this.onOptionsChanged ) )\n\t\t\t\t\t_this.onOptionsChanged( optionsThatWereChanged, optionsThatWereChangedPreviousValues );\n\t\t\t\telse if( _.isFunction( _this._onOptionsChanged ) )\n\t\t\t\t\t_this._onOptionsChanged( optionsThatWereChanged, optionsThatWereChangedPreviousValues );\n\t\t\t}\n\t\t};\n\n\t\tview.getOptions = function() {\n\t\t\tvar optionDeclarations = _.result( this, optionsDeclarationsProperty );\n\t\t\tif( _.isUndefined( optionDeclarations ) ) return {};\n\n\t\t\tvar normalizedOptionDeclarations = _normalizeOptionDeclarations( optionDeclarations );\n\t\t\tvar optionsNames = _.keys( normalizedOptionDeclarations );\n\n\t\t\treturn _.pick( this, optionsNames );\n\t\t};\n\t};\n\n\t// ****************** Private Utility Functions ******************\n\n\tfunction _normalizeOptionDeclarations( optionDeclarations ) {\n\t\t// convert our short-hand option syntax (with exclamation marks, etc.)\n\t\t// to a simple array of standard option declaration objects.\n\n\t\tvar normalizedOptionDeclarations = {};\n\n\t\tif( ! _.isArray( optionDeclarations ) ) throw new Error( \"Option declarations must be an array.\" );\n\n\t\t_.each( optionDeclarations, function( thisOptionDeclaration ) {\n\t\t\tvar thisOptionName, thisOptionRequired, thisOptionDefaultValue;\n\n\t\t\tthisOptionRequired = false;\n\t\t\tthisOptionDefaultValue = undefined;\n\n\t\t\tif( _.isString( thisOptionDeclaration ) )\n\t\t\t\tthisOptionName = thisOptionDeclaration;\n\t\t\telse if( _.isObject( thisOptionDeclaration ) ) {\n\t\t\t\tthisOptionName = _.first( _.keys( thisOptionDeclaration ) );\n\t\t\t\tif( _.isFunction( thisOptionDeclaration[ thisOptionName ] ) )\n\t\t\t\t\tthisOptionDefaultValue = thisOptionDeclaration[ thisOptionName ];\n\t\t\t\telse\n\t\t\t\t\tthisOptionDefaultValue = _.clone( thisOptionDeclaration[ thisOptionName ] );\n\t\t\t}\n\t\t\telse throw new Error( \"Each element in the option declarations array must be either a string or an object.\" );\n\n\t\t\tif( thisOptionName[ thisOptionName.length - 1 ] === \"!\" ) {\n\t\t\t\tthisOptionRequired = true;\n\t\t\t\tthisOptionName = thisOptionName.slice( 0, thisOptionName.length - 1 );\n\t\t\t}\n\n\t\t\tnormalizedOptionDeclarations[ thisOptionName ] = normalizedOptionDeclarations[ thisOptionName ] || {};\n\t\t\tnormalizedOptionDeclarations[ thisOptionName ].required = thisOptionRequired;\n\t\t\tif( ! _.isUndefined( thisOptionDefaultValue ) ) normalizedOptionDeclarations[ thisOptionName ].defaultValue = thisOptionDefaultValue;\n\t\t} );\n\n\t\treturn normalizedOptionDeclarations;\n\t}\n\n\n\t// Backbone.BabySitter\n\t// -------------------\n\t// v0.0.6\n\t//\n\t// Copyright (c)2013 Derick Bailey, Muted Solutions, LLC.\n\t// Distributed under MIT license\n\t//\n\t// http://github.com/babysitterjs/backbone.babysitter\n\n\t// Backbone.ChildViewContainer\n\t// ---------------------------\n\t//\n\t// Provide a container to store, retrieve and\n\t// shut down child views.\n\n\tChildViewContainer = (function(Backbone, _){\n\n\t\t// Container Constructor\n\t\t// ---------------------\n\n\t\tvar Container = function(views){\n\t\t\tthis._views = {};\n\t\t\tthis._indexByModel = {};\n\t\t\tthis._indexByCustom = {};\n\t\t\tthis._updateLength();\n\n\t\t\t_.each(views, this.add, this);\n\t\t};\n\n\t\t// Container Methods\n\t\t// -----------------\n\n\t\t_.extend(Container.prototype, {\n\n\t\t\t// Add a view to this container. Stores the view\n\t\t\t// by `cid` and makes it searchable by the model\n\t\t\t// cid (and model itself). Optionally specify\n\t\t\t// a custom key to store an retrieve the view.\n\t\t\tadd: function(view, customIndex){\n\t\t\t\tvar viewCid = view.cid;\n\n\t\t\t\t// store the view\n\t\t\t\tthis._views[viewCid] = view;\n\n\t\t\t\t// index it by model\n\t\t\t\tif (view.model){\n\t\t\t\t\tthis._indexByModel[view.model.cid] = viewCid;\n\t\t\t\t}\n\n\t\t\t\t// index by custom\n\t\t\t\tif (customIndex){\n\t\t\t\t\tthis._indexByCustom[customIndex] = viewCid;\n\t\t\t\t}\n\n\t\t\t\tthis._updateLength();\n\t\t\t},\n\n\t\t\t// Find a view by the model that was attached to\n\t\t\t// it. Uses the model's `cid` to find it.\n\t\t\tfindByModel: function(model){\n\t\t\t\treturn this.findByModelCid(model.cid);\n\t\t\t},\n\n\t\t\t// Find a view by the `cid` of the model that was attached to\n\t\t\t// it. Uses the model's `cid` to find the view `cid` and\n\t\t\t// retrieve the view using it.\n\t\t\tfindByModelCid: function(modelCid){\n\t\t\t\tvar viewCid = this._indexByModel[modelCid];\n\t\t\t\treturn this.findByCid(viewCid);\n\t\t\t},\n\n\t\t\t// Find a view by a custom indexer.\n\t\t\tfindByCustom: function(index){\n\t\t\t\tvar viewCid = this._indexByCustom[index];\n\t\t\t\treturn this.findByCid(viewCid);\n\t\t\t},\n\n\t\t\t// Find by index. This is not guaranteed to be a\n\t\t\t// stable index.\n\t\t\tfindByIndex: function(index){\n\t\t\t\treturn _.values(this._views)[index];\n\t\t\t},\n\n\t\t\t// retrieve a view by it's `cid` directly\n\t\t\tfindByCid: function(cid){\n\t\t\t\treturn this._views[cid];\n\t\t\t},\n\n\t\t\tfindIndexByCid : function( cid ) {\n\t\t\t\tvar index = -1;\n\t\t\t\tvar view = _.find( this._views, function ( view ) {\n\t\t\t\t\tindex++;\n\t\t\t\t\tif( view.model.cid == cid )\n\t\t\t\t\t\treturn view;\n\t\t\t\t} );\n\t\t\t\treturn ( view ) ? index : -1;\n\t\t\t},\n\n\t\t\t// Remove a view\n\t\t\tremove: function(view){\n\t\t\t\tvar viewCid = view.cid;\n\n\t\t\t\t// delete model index\n\t\t\t\tif (view.model){\n\t\t\t\t\tdelete this._indexByModel[view.model.cid];\n\t\t\t\t}\n\n\t\t\t\t// delete custom index\n\t\t\t\t_.any(this._indexByCustom, function(cid, key) {\n\t\t\t\t\tif (cid === viewCid) {\n\t\t\t\t\t\tdelete this._indexByCustom[key];\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}, this);\n\n\t\t\t\t// remove the view from the container\n\t\t\t\tdelete this._views[viewCid];\n\n\t\t\t\t// update the length\n\t\t\t\tthis._updateLength();\n\t\t\t},\n\n\t\t\t// Call a method on every view in the container,\n\t\t\t// passing parameters to the call method one at a\n\t\t\t// time, like `function.call`.\n\t\t\tcall: function(method){\n\t\t\t\tthis.apply(method, _.tail(arguments));\n\t\t\t},\n\n\t\t\t// Apply a method on every view in the container,\n\t\t\t// passing parameters to the call method one at a\n\t\t\t// time, like `function.apply`.\n\t\t\tapply: function(method, args){\n\t\t\t\t_.each(this._views, function(view){\n\t\t\t\t\tif (_.isFunction(view[method])){\n\t\t\t\t\t\tview[method].apply(view, args || []);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t},\n\n\t\t\t// Update the `.length` attribute on this container\n\t\t\t_updateLength: function(){\n\t\t\t\tthis.length = _.size(this._views);\n\t\t\t}\n\t\t});\n\n\t\t// Borrowing this code from Backbone.Collection:\n\t\t// http://backbonejs.org/docs/backbone.html#section-106\n\t\t//\n\t\t// Mix in methods from Underscore, for iteration, and other\n\t\t// collection related features.\n\t\tvar methods = ['forEach', 'each', 'map', 'find', 'detect', 'filter',\n\t\t\t 'select', 'reject', 'every', 'all', 'some', 'any', 'include',\n\t\t\t 'contains', 'invoke', 'toArray', 'first', 'initial', 'rest',\n\t\t\t 'last', 'without', 'isEmpty', 'pluck'];\n\n\t\t_.each(methods, function(method) {\n\t\t\tContainer.prototype[method] = function() {\n\t\t\t\tvar views = _.values(this._views);\n\t\t\t\tvar args = [views].concat(_.toArray(arguments));\n\t\t\t\treturn _[method].apply(_, args);\n\t\t\t};\n\t\t});\n\n\t\t// return the public API\n\t\treturn Container;\n\t})(Backbone, _);\n\n\treturn Backbone.CollectionView;\n} ) );\n\n","//\n// backbone.trackit - 0.1.0\n// The MIT License\n// Copyright (c) 2013 The New York Times, CMS Group, Matthew DeLambo \n//\n(function() {\n\n\t// Unsaved Record Keeping\n\t// ----------------------\n\n\t// Collection of all models in an app that have unsaved changes.\n\tvar unsavedModels = [];\n\n\t// If the given model has unsaved changes then add it to\n\t// the `unsavedModels` collection, otherwise remove it.\n\tvar updateUnsavedModels = function(model) {\n\t\tif (!_.isEmpty(model._unsavedChanges)) {\n\t\t\tif (!_.findWhere(unsavedModels, {cid:model.cid})) unsavedModels.push(model);\n\t\t} else {\n\t\t\tunsavedModels = _.filter(unsavedModels, function(m) { return model.cid != m.cid; });\n\t\t}\n\t};\n\n\t// Unload Handlers\n\t// ---------------\n\n\t// Helper which returns a prompt message for an unload handler.\n\t// Uses the given function name (one of the callback names\n\t// from the `model.unsaved` configuration hash) to evaluate\n\t// whether a prompt is needed/returned.\n\tvar getPrompt = function(fnName) {\n\t\tvar prompt, args = _.rest(arguments);\n\t\t// Evaluate and return a boolean result. The given `fn` may be a\n\t\t// boolean value, a function, or the name of a function on the model.\n\t\tvar evaluateModelFn = function(model, fn) {\n\t\t\tif (_.isBoolean(fn)) return fn;\n\t\t\treturn (_.isString(fn) ? model[fn] : fn).apply(model, args);\n\t\t};\n\t\t_.each(unsavedModels, function(model) {\n\t\t\tif (!prompt && evaluateModelFn(model, model._unsavedConfig[fnName]))\n\t\t\t\tprompt = model._unsavedConfig.prompt;\n\t\t});\n\t\treturn prompt;\n\t};\n\n\t// Wrap Backbone.History.navigate so that in-app routing\n\t// (`router.navigate('/path')`) can be intercepted with a\n\t// confirmation if there are any unsaved models.\n\tBackbone.History.prototype.navigate = _.wrap(Backbone.History.prototype.navigate, function(oldNav, fragment, options) {\n\t\tvar prompt = getPrompt('unloadRouterPrompt', fragment, options);\n\t\tif (prompt) {\n\t\t\tif (confirm(prompt + ' \\n\\nAre you sure you want to leave this page?')) {\n\t\t\t\toldNav.call(this, fragment, options);\n\t\t\t}\n\t\t} else {\n\t\t\toldNav.call(this, fragment, options);\n\t\t}\n\t});\n\n\t// Create a browser unload handler which is triggered\n\t// on the refresh, back, or forward button.\n\twindow.onbeforeunload = function(e) {\n\t\treturn getPrompt('unloadWindowPrompt', e);\n\t};\n\n\t// Backbone.Model API\n\t// ------------------\n\n\t_.extend(Backbone.Model.prototype, {\n\n\t\tunsaved: {},\n\t\t_trackingChanges: false,\n\t\t_originalAttrs: {},\n\t\t_unsavedChanges: {},\n\n\t\t// Opt in to tracking attribute changes\n\t\t// between saves.\n\t\tstartTracking: function() {\n\t\t\tthis._unsavedConfig = _.extend({}, {\n\t\t\t\tprompt: 'You have unsaved changes!',\n\t\t\t\tunloadRouterPrompt: false,\n\t\t\t\tunloadWindowPrompt: false\n\t\t\t}, this.unsaved || {});\n\t\t\tthis._trackingChanges = true;\n\t\t\tthis._resetTracking();\n\t\t\tthis._triggerUnsavedChanges();\n\t\t\treturn this;\n\t\t},\n\n\t\t// Resets the default tracking values\n\t\t// and stops tracking attribute changes.\n\t\tstopTracking: function() {\n\t\t\tthis._trackingChanges = false;\n\t\t\tthis._originalAttrs = {};\n\t\t\tthis._unsavedChanges = {};\n\t\t\tthis._triggerUnsavedChanges();\n\t\t\treturn this;\n\t\t},\n\n\t\t// Gets rid of accrued changes and\n\t\t// resets state.\n\t\trestartTracking: function() {\n\t\t\tthis._resetTracking();\n\t\t\tthis._triggerUnsavedChanges();\n\t\t\treturn this;\n\t\t},\n\n\t\t// Restores this model's attributes to\n\t\t// their original values since tracking\n\t\t// started, the last save, or last restart.\n\t\tresetAttributes: function() {\n\t\t\tif (!this._trackingChanges) return;\n\t\t\tthis.attributes = this._originalAttrs;\n\t\t\tthis._resetTracking();\n\t\t\tthis._triggerUnsavedChanges();\n\t\t\treturn this;\n\t\t},\n\n\t\t// Symmetric to Backbone's `model.changedAttributes()`,\n\t\t// except that this returns a hash of the model's attributes that\n\t\t// have changed since the last save, or `false` if there are none.\n\t\t// Like `changedAttributes`, an external attributes hash can be\n\t\t// passed in, returning the attributes in that hash which differ\n\t\t// from the model.\n\t\tunsavedAttributes: function(attrs) {\n\t\t\tif (!attrs) return _.isEmpty(this._unsavedChanges) ? false : _.clone(this._unsavedChanges);\n\t\t\tvar val, changed = false, old = this._unsavedChanges;\n\t\t\tfor (var attr in attrs) {\n\t\t\t\tif (_.isEqual(old[attr], (val = attrs[attr]))) continue;\n\t\t\t\t(changed || (changed = {}))[attr] = val;\n\t\t\t}\n\t\t\treturn changed;\n\t\t},\n\n\t\t_resetTracking: function() {\n\t\t\tthis._originalAttrs = _.clone(this.attributes);\n\t\t\tthis._unsavedChanges = {};\n\t\t},\n\n\t\t// Trigger an `unsavedChanges` event on this model,\n\t\t// supplying the result of whether there are unsaved\n\t\t// changes and a changed attributes hash.\n\t\t_triggerUnsavedChanges: function() {\n\t\t\tthis.trigger('unsavedChanges', !_.isEmpty(this._unsavedChanges), _.clone(this._unsavedChanges));\n\t\t\tif (this.unsaved) updateUnsavedModels(this);\n\t\t}\n\t});\n\n\t// Wrap `model.set()` and update the internal\n\t// unsaved changes record keeping.\n\tBackbone.Model.prototype.set = _.wrap(Backbone.Model.prototype.set, function(oldSet, key, val, options) {\n\t\tvar attrs, ret;\n\t\tif (key == null) return this;\n\t\t// Handle both `\"key\", value` and `{key: value}` -style arguments.\n\t\tif (typeof key === 'object') {\n\t\t\tattrs = key;\n\t\t\toptions = val;\n\t\t} else {\n\t\t\t(attrs = {})[key] = val;\n\t\t}\n\t\toptions || (options = {});\n\n\t\t// Delegate to Backbone's set.\n\t\tret = oldSet.call(this, attrs, options);\n\n\t\tif (this._trackingChanges && !options.silent) {\n\t\t\t_.each(attrs, _.bind(function(val, key) {\n\t\t\t\tif (_.isEqual(this._originalAttrs[key], val))\n\t\t\t\t\tdelete this._unsavedChanges[key];\n\t\t\t\telse\n\t\t\t\t\tthis._unsavedChanges[key] = val;\n\t\t\t}, this));\n\t\t\tthis._triggerUnsavedChanges();\n\t\t}\n\t\treturn ret;\n\t});\n\n\t// Intercept `model.save()` and reset tracking/unsaved\n\t// changes if it was successful.\n\tBackbone.sync = _.wrap(Backbone.sync, function(oldSync, method, model, options) {\n\t\toptions || (options = {});\n\n\t\tif (method == 'update') {\n\t\t\toptions.success = _.wrap(options.success, _.bind(function(oldSuccess, data, textStatus, jqXHR) {\n\t\t\t\tvar ret;\n\t\t\t\tif (oldSuccess) ret = oldSuccess.call(this, data, textStatus, jqXHR);\n\t\t\t\tif (model._trackingChanges) {\n\t\t\t\t\tmodel._resetTracking();\n\t\t\t\t\tmodel._triggerUnsavedChanges();\n\t\t\t\t}\n\t\t\t\treturn ret;\n\t\t\t}, this));\n\t\t}\n\t\treturn oldSync(method, model, options);\n\t});\n\n})();\ndefine(\"vendor/backbone.trackit\", function(){});\n\n","/**\n * Image object model for use in various models for the 'image' attribute\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Models/Image',[], function() {\n\n\treturn Backbone.Model.extend( {\n\n\t\tdefaults: {\n\t\t\tenabled: 'no',\n\t\t\tid: '',\n\t\t\tsize: 'full',\n\t\t\tsrc: '',\n\t\t},\n\n\t\tinitialize: function() {\n\t\t\tthis.startTracking();\n\t\t},\n\n\t} );\n} );\n\n","/**\n * Model relationships mixin\n * @since 3.16.0\n * @version 3.16.11\n */\ndefine( 'Models/_Relationships',[], function() {\n\n\treturn {\n\n\t\t/**\n\t\t * Default relationship settings object\n\t\t * @type {Object}\n\t\t */\n\t\trelationship_defaults: {\n\t\t\tparent: {},\n\t\t\tchildren: {},\n\t\t},\n\n\t\t/**\n\t\t * Relationship settings object\n\t\t * Should be overriden in the model\n\t\t * @type {Object}\n\t\t */\n\t\trelationships: {},\n\n\t\t/**\n\t\t * Initialize all parent and child relationships\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinit_relationships: function( options ) {\n\n\t\t\tvar rels = this.get_relationships();\n\n\t\t\t// initialize parent relaxtionships\n\t\t\t// useful when adding a model to ensure parent is initialized\n\t\t\tif ( rels.parent && options && options.parent ) {\n\t\t\t\tthis.set_parent( options.parent );\n\t\t\t}\n\n\t\t\t// initialize all children relationships\n\t\t\t_.each( rels.children, function( child_data, child_key ) {\n\n\t\t\t\tif ( ! child_data.conditional || true === child_data.conditional( this ) ) {\n\n\t\t\t\t\tvar child_val = this.get( child_key ),\n\t\t\t\t\t\tchild;\n\n\t\t\t\t\tif ( child_data.lookup ) {\n\t\t\t\t\t\tchild = child_data.lookup( child_val );\n\t\t\t\t\t} else if ( 'model' === child_data.type ) {\n\t\t\t\t\t\tchild = window.llms_builder.construct.get_model( child_data.class, child_val );\n\t\t\t\t\t} else if ( 'collection' === child_data.type ) {\n\t\t\t\t\t\tchild = window.llms_builder.construct.get_collection( child_data.class, child_val );\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.set( child_key, child );\n\n\t\t\t\t\t// if the child defines a parent, save a reference to the parent on the child\n\t\t\t\t\tif ( 'model' === child_data.type ) {\n\t\t\t\t\t\tthis._maybe_set_parent_reference( child );\n\n\t\t\t\t\t// save directly to each model in the collection\n\t\t\t\t\t} else if ( 'collection' === child_data.type ) {\n\n\t\t\t\t\t\tchild.parent = this;\n\t\t\t\t\t\tchild.each( function( child_model ) {\n\n\t\t\t\t\t\t\tthis._maybe_set_parent_reference( child_model );\n\n\t\t\t\t\t\t}, this );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t}, this );\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the property names for all children of the model\n\t\t * @return array\n\t\t * @since 3.16.11\n\t\t * @version 3.16.11\n\t\t */\n\t\tget_child_props: function() {\n\n\t\t\tvar props = [];\n\n\t\t\t_.each( this.get_relationships().children, function( data, key ) {\n\n\t\t\t\tif ( ! data.conditional || true === data.conditional( this ) ) {\n\t\t\t\t\tprops.push( key );\n\t\t\t\t}\n\n\t\t\t}, this );\n\n\t\t\treturn props;\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the model's parent (if set)\n\t\t * @return obj|false\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_parent: function() {\n\n\t\t\tvar rels = this.get_relationships();\n\n\t\t\tif ( rels.parent ) {\n\t\t\t\treturn rels.parent.reference;\n\t\t\t}\n\n\t\t\treturn false;\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve relationships for the model\n\t\t * Extends with defaults\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_relationships: function() {\n\n\t\t\treturn $.extend( true, this.relationships, this.relationship_defaults );\n\n\t\t},\n\n\t\t/**\n\t\t * Set the parent reference for the given model\n\t\t * @param obj obj parent model obj\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tset_parent: function( obj ) {\n\t\t\tthis.relationships.parent.reference = obj;\n\t\t},\n\n\t\t/**\n\t\t * Set up the parent relationships for qualifying children during relationship initialization\n\t\t * @param obj model child model\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\t_maybe_set_parent_reference: function( model ) {\n\n\t\t\tif ( ! model || ! model.get_relationships ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar rels = model.get_relationships();\n\t\t\tif ( rels.parent && rels.parent.model === this.get( 'type' ) ) {\n\t\t\t\tmodel.set_parent( this );\n\t\t\t}\n\n\t\t},\n\n\t};\n\n} );\n\n","/**\n * Quiz Question Choice\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Models/QuestionChoice',[ 'Models/Image', 'Models/_Relationships' ], function( Image, Relationships ) {\n\n\treturn Backbone.Model.extend( _.defaults( {\n\n\t\t/**\n\t\t * Model relationships\n\t\t * @type {Object}\n\t\t */\n\t\trelationships: {\n\t\t\tparent: {\n\t\t\t\tmodel: 'llms_question',\n\t\t\t\ttype: 'model',\n\t\t\t},\n\t\t\tchildren: {\n\t\t\t\tchoice: {\n\t\t\t\t\tconditional: function( model ) {\n\t\t\t\t\t\treturn ( 'image' === model.get( 'choice_type' ) );\n\t\t\t\t\t},\n\t\t\t\t\tclass: 'Image',\n\t\t\t\t\tmodel: 'image',\n\t\t\t\t\ttype: 'model',\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\n\t\t/**\n\t\t * Model defaults\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tdefaults: function() {\n\t\t\treturn {\n\t\t\t\tid: _.uniqueId( 'temp_' ),\n\t\t\t\tchoice: '',\n\t\t\t\tchoice_type: 'text',\n\t\t\t\tcorrect: false,\n\t\t\t\tmarker: 'A',\n\t\t\t\tquestion_id: '',\n\t\t\t\ttype: 'choice',\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Initializer\n\t\t * @param obj data object of model attributes\n\t\t * @param obj options additional options\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function( data, options ) {\n\n\t\t\tthis.startTracking();\n\t\t\tthis.init_relationships( options );\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the choice's parent question\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_parent: function() {\n\t\t\treturn this.collection.parent;\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the ID used when trashing the model\n\t\t * @return string\n\t\t * @since 3.17.1\n\t\t * @version 3.17.1\n\t\t */\n\t\tget_trash_id: function() {\n\t\t\treturn this.get( 'question_id' ) + ':' + this.get( 'id' );\n\t\t},\n\n\t\t/**\n\t\t * Determine if \"selection\" is enabled for the question type\n\t\t * Choice type questions are selectable by reorder type questions are not but still use choices\n\t\t * @return {Boolean}\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tis_selectable: function() {\n\t\t\treturn this.get_parent().get( 'question_type' ).get_choice_selectable();\n\t\t},\n\n\t}, Relationships ) );\n\n} );\n\n","/**\n * Question Choice Collection\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Collections/QuestionChoices',[ 'Models/QuestionChoice' ], function( model ) {\n\n\treturn Backbone.Collection.extend( {\n\n\t\t/**\n\t\t * Model for collection items\n\t\t * @type obj\n\t\t */\n\t\tmodel: model,\n\n\t\tinitialize: function() {\n\n\t\t\t// reorder called by QuestionList view when sortable drops occur\n\t\t\tthis.on( 'reorder', this.update_order );\n\n\t\t\t// when a choice is added or removed, update order\n\t\t\tthis.on( 'add', this.update_order );\n\t\t\tthis.on( 'remove', this.update_order );\n\n\t\t\t// when a choice is added or remove, ensure min/max correct answers exist\n\t\t\tthis.on( 'add', this.update_correct );\n\t\t\tthis.on( 'remove', this.update_correct );\n\n\t\t\t// when a choice is toggled, ensure min/max correct exist\n\t\t\tthis.on( 'correct-update', this.update_correct );\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the number of correct choices in the collection\n\t\t * @return int\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tcount_correct: function() {\n\n\t\t\treturn _.size( this.get_correct() );\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the collection reduced to only correct choices\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_correct: function() {\n\t\t\treturn this.filter( function( choice ) {\n\t\t\t\treturn choice.get( 'correct' );\n\t\t\t} );\n\t\t},\n\n\t\t/**\n\t\t * Ensure min/max correct choices exist in the collection based on the question's settings\n\t\t * @param obj choice model of the choice that was toggled\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tupdate_correct: function( choice ) {\n\n\t\t\tif ( ! this.parent.get( 'question_type' ).get_choice_selectable() ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar siblings = this.without( choice ), // exclude the toggled choice from loops\n\t\t\t\tquestion = this.parent;\n\n\t\t\t// if multiple choices aren't enabled turn all other choices to incorrect\n\t\t\tif ( 'no' === question.get( 'multi_choices' ) ) {\n\t\t\t\t_.each( siblings, function( model ) {\n\t\t\t\t\tmodel.set( 'correct', false );\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\t// if we don't have a single corret answer & the question has points, set one\n\t\t\t// allows users to create quizzes / questions with no points and therefore no correct answers are allowed\n\t\t\tif ( 0 === this.count_correct() && question.get( 'points' ) > 0 ) {\n\t\t\t\tvar models = 1 === this.size() ? this.models : siblings;\n\t\t\t\t_.first( models ).set( 'correct', true );\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Update the marker attr of each choice in the list to reflect the order of the collection\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tupdate_order: function() {\n\n\t\t\tvar self = this,\n\t\t\t\tquestion = this.parent;\n\n\t\t\tthis.each( function( choice ) {\n\t\t\t\tchoice.set( 'marker', question.get( 'question_type' ).get_choice_markers()[ self.indexOf( choice ) ] );\n\t\t\t} );\n\n\t\t},\n\n\t} );\n\n} );\n\n","/**\n * Quiz Question Type\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Models/QuestionType',[], function() {\n\n\treturn Backbone.Model.extend( {\n\n\t\t/**\n\t\t * Get model default attributes\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tdefaults: function() {\n\t\t\treturn {\n\t\t\t\tchoices: false,\n\t\t\t\tclarifications: true,\n\t\t\t\tdefault_choices: [],\n\t\t\t\tdescription: true,\n\t\t\t\ticon: 'question',\n\t\t\t\tid: 'generic',\n\t\t\t\timage: true,\n\t\t\t\tkeywords: [],\n\t\t\t\tname: 'Generic',\n\t\t\t\tplaceholder: '',\n\t\t\t\tpoints: true,\n\t\t\t\tvideo: true,\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Retrieve an array of keywords for the question type\n\t\t * Used for filtering questions by search term in the quiz builder\n\t\t * @return array\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_keywords: function() {\n\n\t\t\tvar name = this.get( 'name' ),\n\t\t\t\twords = [ name ];\n\n\t\t\treturn words.concat( this.get( 'keywords' ) ).concat( name.split( ' ' ) );\n\n\t\t},\n\n\t\t/**\n\t\t * Get marker array for the question choices\n\t\t * @return array\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_choice_markers: function() {\n\n\t\t\treturn this._get_choice_option( 'markers' );\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if the question's choices are selectable\n\t\t * @return bool\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_choice_selectable: function() {\n\n\t\t\treturn this._get_choice_option( 'selectable' );\n\n\t\t},\n\n\t\t/**\n\t\t * Get the choice type (text,image)\n\t\t * @return string\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_choice_type: function() {\n\n\t\t\treturn this._get_choice_option( 'type' );\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve defined min. choices\n\t\t * @return int\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_min_choices: function() {\n\n\t\t\treturn this._get_choice_option( 'min' );\n\n\t\t},\n\n\t\t/**\n\t\t * Get type-defined max choices\n\t\t * @return string\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_max_choices: function() {\n\n\t\t\treturn this._get_choice_option( 'max' );\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if multi-choice selection is enabled\n\t\t * @return bool\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_multi_choices: function() {\n\n\t\t\tvar choices = this.get( 'choices' );\n\n\t\t\tif ( ! choices ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\treturn this._get_choice_option( 'multi' );\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve data from the type's \"choices\" attribute\n\t\t * Allows quick handling of types with no choice definitions w/o additional checks\n\t\t * @param string option name of the choice option to retrieve\n\t\t * @return mixed\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\t_get_choice_option: function( option ) {\n\n\t\t\tvar choices = this.get( 'choices' );\n\n\t\t\tif ( ! choices || ! choices[ option ] ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\treturn choices[ option ];\n\n\t\t},\n\n\t} );\n\n} );\n\n","/**\n * Quiz Question\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Models/Question',[\n\t\t'Models/Image',\n\t\t'Collections/Questions',\n\t\t'Collections/QuestionChoices',\n\t\t'Models/QuestionType',\n\t\t'Models/_Relationships'\n\t], function(\n\t\tImage,\n\t\tQuestions,\n\t\tQuestionChoices,\n\t\tQuestionType,\n\t\tRelationships\n\t) {\n\n\treturn Backbone.Model.extend( _.defaults( {\n\n\t\t/**\n\t\t * Model relationships\n\t\t * @type {Object}\n\t\t */\n\t\trelationships: {\n\t\t\tparent: {\n\t\t\t\tmodel: 'llms_quiz',\n\t\t\t\ttype: 'model',\n\t\t\t},\n\t\t\tchildren: {\n\t\t\t\tchoices: {\n\t\t\t\t\tclass: 'QuestionChoices',\n\t\t\t\t\tmodel: 'choice',\n\t\t\t\t\ttype: 'collection',\n\t\t\t\t},\n\t\t\t\timage: {\n\t\t\t\t\tclass: 'Image',\n\t\t\t\t\tmodel: 'image',\n\t\t\t\t\ttype: 'model',\n\t\t\t\t},\n\t\t\t\tquestions: {\n\t\t\t\t\tclass: 'Questions',\n\t\t\t\t\tconditional: function( model ) {\n\t\t\t\t\t\tvar type = model.get( 'question_type' ),\n\t\t\t\t\t\t\ttype_id = _.isString( type ) ? type : type.get( 'id' );\n\t\t\t\t\t\treturn ( 'group' === type_id );\n\t\t\t\t\t},\n\t\t\t\t\tmodel: 'llms_question',\n\t\t\t\t\ttype: 'collection',\n\t\t\t\t},\n\t\t\t\tquestion_type: {\n\t\t\t\t\tclass: 'QuestionType',\n\t\t\t\t\tlookup: function( val ) {\n\t\t\t\t\t\tif ( _.isString( val ) ) {\n\t\t\t\t\t\t\treturn window.llms_builder.questions.get( val );\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn val;\n\t\t\t\t\t},\n\t\t\t\t\tmodel: 'question_type',\n\t\t\t\t\ttype: 'model',\n\t\t\t\t},\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Model defaults\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tdefaults: function() {\n\t\t\treturn {\n\t\t\t\tid: _.uniqueId( 'temp_' ),\n\t\t\t\tchoices: [],\n\t\t\t\tcontent: '',\n\t\t\t\tdescription_enabled: 'no',\n\t\t\t\timage: {},\n\t\t\t\tmulti_choices: 'no',\n\t\t\t\tmenu_order: 1,\n\t\t\t\tpoints: 1,\n\t\t\t\tquestion_type: 'generic',\n\t\t\t\tquestions: [], // for question groups\n\t\t\t\tparent_id: '',\n\t\t\t\ttitle: '',\n\t\t\t\ttype: 'llms_question',\n\t\t\t\tvideo_enabled: 'no',\n\t\t\t\tvideo_src: '',\n\n\t\t\t\t_expanded: false,\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Initializer\n\t\t * @param obj data object of data for the model\n\t\t * @param obj options additional options\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function( data, options ) {\n\n\t\t\tvar self = this;\n\n\t\t\tthis.startTracking();\n\t\t\tthis.init_relationships( options );\n\n\t\t\tif ( false !== this.get( 'question_type' ).choices ) {\n\n\t\t\t\tthis._ensure_min_choices();\n\n\t\t\t\t// when a choice is removed, maybe add back some defaults so we always have the minimum\n\t\t\t\tthis.listenTo( this.get( 'choices' ), 'remove', function() {\n\t\t\t\t\t// new itmes are added at index 0 when there's only 1 item in the collection, not sure why exactly...\n\t\t\t\t\tsetTimeout( function() {\n\t\t\t\t\t\tself._ensure_min_choices();\n\t\t\t\t\t}, 0 );\n\t\t\t\t} );\n\n\t\t\t}\n\n\t\t\t// ensure question types that don't support points don't record default 1 point in database\n\t\t\tif ( ! this.get( 'question_type' ).get( 'points' ) ) {\n\t\t\t\tthis.set( 'points', 0 );\n\t\t\t}\n\n\t\t\t_.delay( function( self ) {\n\t\t\t\tself.on( 'change:points', self.get_parent().update_points, self.get_parent() );\n\t\t\t}, 1, this );\n\n\t\t},\n\n\t\t/**\n\t\t * Add a new question choice\n\t\t * @param obj data object of choice data\n\t\t * @param obj options additional options\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tadd_choice: function( data, options ) {\n\n\t\t\tvar max = this.get( 'question_type' ).get_max_choices();\n\t\t\tif ( this.get( 'choices' ).size() >= max ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tdata = data || {};\n\t\t\toptions = options || {};\n\n\t\t\tdata.choice_type = this.get( 'question_type' ).get_choice_type();\n\t\t\tdata.question_id = this.get( 'id' );\n\t\t\toptions.parent = this;\n\n\t\t\tvar choice = this.get( 'choices' ).add( data, options );\n\n\t\t\tBackbone.pubSub.trigger( 'question-add-choice', choice, this );\n\n\t\t},\n\n\t\t/**\n\t\t * Collapse question_type attribute during full syncs to save to database\n\t\t * Not needed because question types cannot be adjusted after question creation\n\t\t * Called from sync controller\n\t\t * @param obj atts flat object of attributes to be saved to db\n\t\t * @param string sync_type full or partial\n\t\t * full indicates a force resync or that the model isn't persisted yet\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tbefore_save: function( atts, sync_type ) {\n\t\t\tif ( 'full' === sync_type ) {\n\t\t\t\tatts.question_type = this.get( 'question_type' ).get( 'id' );\n\t\t\t}\n\t\t\treturn atts;\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the model's parent (if set)\n\t\t * @return obj|false\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_parent: function() {\n\n\t\t\tvar rels = this.get_relationships();\n\n\t\t\tif ( rels.parent ) {\n\t\t\t\tif ( this.collection && this.collection.parent ) {\n\t\t\t\t\treturn this.collection.parent;\n\t\t\t\t} else if ( rels.parent.reference ) {\n\t\t\t\t\treturn rels.parent.reference;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false;\n\n\t\t},\n\n\t\t/**\n\t\t * Gets the index of the question within it's parent\n\t\t * Question numbers skip content elements\n\t\t * & content elements skip questions\n\t\t * @return int\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_type_index: function() {\n\n\t\t\t// current models type, used to check the predicate in the filter function below\n\t\t\tvar curr_type = this.get( 'question_type' ).get( 'id' ),\n\t\t\t\tquestions;\n\n\t\t\tquestions = this.collection.filter( function( question ) {\n\n\t\t\t\tvar type = question.get( 'question_type' ).get( 'id' );\n\n\t\t\t\t// if current model is not content, return all non-content questions\n\t\t\t\tif ( curr_type !== 'content' ) {\n\t\t\t\t\treturn ( 'content' !== type );\n\t\t\t\t}\n\n\t\t\t\t// current model is content, return only content questions\n\t\t\t\treturn 'content' === type;\n\n\t\t\t} );\n\n\t\t\treturn questions.indexOf( this );\n\n\t\t},\n\n\t\t/**\n\t\t * Gets iterator for the given type\n\t\t * Questions use numbers and content uses alphabet\n\t\t * @return mixed\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_type_iterator: function() {\n\n\t\t\tvar index = this.get_type_index();\n\n\t\t\tif ( -1 === index ) {\n\t\t\t\treturn '';\n\t\t\t}\n\n\t\t\tif ( 'content' === this.get( 'question_type' ).get( 'id' ) ) {\n\t\t\t\tvar alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split( '' );\n\t\t\t\treturn alphabet[ index ];\n\t\t\t}\n\n\t\t\treturn index + 1;\n\n\t\t},\n\n\n\t\tget_qid: function() {\n\n\t\t\tvar parent = this.get_parent_question(),\n\t\t\t\tprefix = '';\n\n\t\t\tif ( parent ) {\n\n\t\t\t\tprefix = parent.get_qid() + '.';\n\n\t\t\t}\n\n\t\t\t// return short_id + this.get_type_iterator();\n\t\t\treturn prefix + this.get_type_iterator();\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the parent question (if the question is in a question group)\n\t\t * @return obj|false\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_parent_question: function() {\n\n\t\t\tif ( this.is_in_group() ) {\n\n\t\t\t\treturn this.collection.parent;\n\n\t\t\t}\n\n\t\t\treturn false;\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the parent quiz\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_parent_quiz: function() {\n\t\t\treturn this.get_parent();\n\t\t},\n\n\t\t/**\n\t\t * Points getter\n\t\t * ensures that 0 is always returned if the question type doesn't support points\n\t\t * @return int\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_points: function() {\n\n\t\t\tif ( ! this.get( 'question_type' ).get( 'points' ) ) {\n\t\t\t\treturn 0;\n\t\t\t}\n\n\t\t\treturn this.get( 'points' );\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the questions percentage value within the quiz\n\t\t * @return string\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_points_percentage: function() {\n\n\t\t\tvar total = this.get_parent().get( '_points' ),\n\t\t\t\tpoints = this.get( 'points' );\n\n\t\t\tif ( 0 === total ) {\n\t\t\t\treturn '0%';\n\t\t\t}\n\n\t\t\treturn ( ( points / total ) * 100 ).toFixed( 2 ) + '%';\n\n\t\t},\n\n\t\t/**\n\t\t * Deterine if the question belongs to a question group\n\t\t * @return {Boolean}\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tis_in_group: function() {\n\n\t\t\treturn ( 'question' === this.collection.parent.get( 'type' ) );\n\n\t\t},\n\n\t\t_ensure_min_choices: function() {\n\n\t\t\tvar choices = this.get( 'choices' );\n\t\t\twhile ( choices.size() < this.get( 'question_type' ).get_min_choices() ) {\n\t\t\t\tthis.add_choice();\n\t\t\t}\n\n\t\t},\n\n\t}, Relationships ) );\n\n} );\n\n","/**\n * Questions Collection\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Collections/Questions',[ 'Models/Question' ], function( model ) {\n\n\treturn Backbone.Collection.extend( {\n\n\t\t/**\n\t\t * Model for collection items\n\t\t * @type obj\n\t\t */\n\t\tmodel: model,\n\n\t\t/**\n\t\t * Initialize\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\t// reorder called by QuestionList view when sortable drops occur\n\t\t\tthis.on( 'reorder', this.update_order );\n\n\t\t\t// when a question is added or removed, update order\n\t\t\tthis.on( 'add', this.update_order );\n\t\t\tthis.on( 'remove', this.update_order );\n\n\t\t\tthis.on( 'add', this.update_parent );\n\n\t\t},\n\n\t\t/**\n\t\t * Update the order attr of each question in the list to reflect the order of the collection\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tupdate_order: function() {\n\n\t\t\tvar self = this;\n\n\t\t\tthis.each( function( question ) {\n\n\t\t\t\tquestion.set( 'menu_order', self.indexOf( question ) + 1 );\n\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * When adding a question to a question list, update the question's parent\n\t\t * Will ensure that questions moved into and out of groups always have the corerct parent_id\n\t\t * @param obj model instance of the question model\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tupdate_parent: function( model ) {\n\n\t\t\tmodel.set( 'parent_id', this.parent.get( 'id' ) );\n\n\t\t},\n\n\t} );\n\n} );\n\n","/**\n * Utility functions for Models\n * @since 3.16.0\n * @version 3.17.1\n */\ndefine( 'Models/_Utilities',[], function() {\n\n\treturn {\n\n\t\tfields: [],\n\n\t\t/**\n\t\t * Retrieve the edit post link for the current model\n\t\t * @return string\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_edit_post_link: function() {\n\n\t\t\tif ( this.has_temp_id() ) {\n\t\t\t\treturn '';\n\t\t\t}\n\n\t\t\treturn window.llms_builder.admin_url + 'post.php?post=' + this.get( 'id' ) + '&action=edit';\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve schema fields defined for the model\n\t\t * @return object\n\t\t * @since 3.17.0\n\t\t * @version 3.17.1\n\t\t */\n\t\tget_settings_fields: function() {\n\n\t\t\tvar schema = this.schema || {};\n\t\t\treturn window.llms_builder.schemas.get( schema, this.get( 'type' ).replace( 'llms_', '' ), this );\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if the model has a temporary ID\n\t\t * @return {Boolean}\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\thas_temp_id: function() {\n\n\t\t\treturn ( ! _.isNumber( this.get( 'id' ) ) && 0 === this.get( 'id' ).indexOf( 'temp_' ) );\n\n\t\t},\n\n\t\t/**\n\t\t * Initializes 3rd party custom schema (field) data for a model\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tinit_custom_schema: function() {\n\n\t\t\tvar groups = _.filter( this.get_settings_fields(), function( group ) {\n\t\t\t\treturn ( group.custom );\n\t\t\t} );\n\n\t\t\t_.each( groups, function( group ) {\n\t\t\t\t_.each( _.flatten( group.fields ), function( field ) {\n\n\n\t\t\t\t\tvar keys = [ field.attribute ],\n\t\t\t\t\t\tcustoms = this.get( 'custom' );\n\n\t\t\t\t\tif ( field.switch_attribute ) {\n\t\t\t\t\t\tkeys.push( field.switch_attribute );\n\t\t\t\t\t}\n\n\t\t\t\t\t_.each( keys, function( key ) {\n\t\t\t\t\t\tvar attr = field.attribute_prefix ? field.attribute_prefix + key : key;\n\t\t\t\t\t\tif ( customs && customs[ attr ] ) {\n\t\t\t\t\t\t\tthis.set( key, customs[ attr ][0] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}, this );\n\n\t\t\t\t}, this );\n\t\t\t}, this );\n\n\t\t},\n\n\t};\n\n} );\n\n","/**\n * Quiz Schema\n * @since 3.17.6\n * @version 3.17.6\n */\ndefine( 'Schemas/Quiz',[], function() {\n\n\treturn {\n\n\t\tdefault: {\n\t\t\ttitle: LLMS.l10n.translate( 'General Settings' ),\n\t\t\ttoggleable: true,\n\t\t\tfields: [\n\t\t\t\t[\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'permalink',\n\t\t\t\t\t\tid: 'permalink',\n\t\t\t\t\t\ttype: 'permalink',\n\t\t\t\t\t},\n\t\t\t\t], [\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'content',\n\t\t\t\t\t\tid: 'description',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Description' ),\n\t\t\t\t\t\ttype: 'editor',\n\t\t\t\t\t},\n\t\t\t\t], [\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'passing_percent',\n\t\t\t\t\t\tid: 'passing-percent',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Passing Percentage' ),\n\t\t\t\t\t\tmin: 0,\n\t\t\t\t\t\tmax: 100,\n\t\t\t\t\t\ttip: LLMS.l10n.translate( 'Minimum percentage of total points required to pass the quiz' ),\n\t\t\t\t\t\ttype: 'number',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'allowed_attempts',\n\t\t\t\t\t\tid: 'allowed-attempts',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Limit Attempts' ),\n\t\t\t\t\t\tswitch_attribute: 'limit_attempts',\n\t\t\t\t\t\ttip: LLMS.l10n.translate( 'Limit the maximum number of times a student can take this quiz' ),\n\t\t\t\t\t\ttype: 'switch-number',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'time_limit',\n\t\t\t\t\t\tid: 'time-limit',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Time Limit' ),\n\t\t\t\t\t\tmin: 1,\n\t\t\t\t\t\tmax: 360,\n\t\t\t\t\t\tswitch_attribute: 'limit_time',\n\t\t\t\t\t\ttip: LLMS.l10n.translate( 'Enforce a maximum number of minutes a student can spend on each attempt' ),\n\t\t\t\t\t\ttype: 'switch-number',\n\t\t\t\t\t},\n\t\t\t\t], [\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'show_correct_answer',\n\t\t\t\t\t\tid: 'show-correct-answer',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Show Correct Answers' ),\n\t\t\t\t\t\ttip: LLMS.l10n.translate( 'When enabled, students will be shown the correct answer to any question they answered incorrectly.' ),\n\t\t\t\t\t\ttype: 'switch',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'random_questions',\n\t\t\t\t\t\tid: 'random-questions',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Randomize Question Order' ),\n\t\t\t\t\t\ttip: LLMS.l10n.translate( 'Display questions in a random order for each attempt. Content questions are locked into their defined positions.' ),\n\t\t\t\t\t\ttype: 'switch',\n\t\t\t\t\t},\n\t\t\t\t],\n\n\t\t\t],\n\t\t},\n\n\t};\n\n} );\n\n","/**\n * Quiz Model\n * @since 3.16.0\n * @version 3.19.2\n */\ndefine( 'Models/Quiz',[\n\t\t'Collections/Questions',\n\t\t'Models/Lesson',\n\t\t'Models/Question',\n\t\t'Models/_Relationships',\n\t\t'Models/_Utilities',\n\t\t'Schemas/Quiz',\n\t], function(\n\t\tQuestions,\n\t\tLesson,\n\t\tQuestion,\n\t\tRelationships,\n\t\tUtilities,\n\t\tQuizSchema\n\t) {\n\n\treturn Backbone.Model.extend( _.defaults( {\n\n\t\t/**\n\t\t * model relationships\n\t\t * @type {Object}\n\t\t */\n\t\trelationships: {\n\t\t\tparent: {\n\t\t\t\tmodel: 'lesson',\n\t\t\t\ttype: 'model',\n\t\t\t},\n\t\t\tchildren: {\n\t\t\t\tquestions: {\n\t\t\t\t\tclass: 'Questions',\n\t\t\t\t\tmodel: 'llms_question',\n\t\t\t\t\ttype: 'collection',\n\t\t\t\t},\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Lesson Settings Schema\n\t\t * @type {Object}\n\t\t */\n\t\tschema: QuizSchema,\n\n\t\t/**\n\t\t * New lesson defaults\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.6\n\t\t */\n\t\tdefaults: function() {\n\n\t\t\treturn {\n\t\t\t\tid: _.uniqueId( 'temp_' ),\n\t\t\t\ttitle: LLMS.l10n.translate( 'New Quiz' ),\n\t\t\t\ttype: 'llms_quiz',\n\t\t\t\tlesson_id: '',\n\n\t\t\t\tstatus: 'draft',\n\n\t\t\t\t// editable fields\n\t\t\t\tcontent: '',\n\t\t\t\tallowed_attempts: 5,\n\t\t\t\tlimit_attempts: 'no',\n\t\t\t\tlimit_time: 'no',\n\t\t\t\tpassing_percent: 65,\n\t\t\t\tname: '',\n\t\t\t\trandom_answers: 'no',\n\t\t\t\ttime_limit: 30,\n\t\t\t\tshow_correct_answer: 'no',\n\n\t\t\t\tquestions: [],\n\n\t\t\t\t// calculated\n\t\t\t\t_points: 0,\n\n\t\t\t\t// display\n\t\t\t\tpermalink: '',\n\t\t\t\t_show_settings: false,\n\t\t\t\t_questions_loaded: false,\n\t\t\t};\n\n\t\t},\n\n\t\t/**\n\t\t * Initializer\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.17.6\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\tthis.init_custom_schema();\n\t\t\tthis.startTracking();\n\t\t\tthis.init_relationships();\n\n\t\t\tthis.listenTo( this.get( 'questions' ), 'add', this.update_points );\n\t\t\tthis.listenTo( this.get( 'questions' ), 'remove', this.update_points );\n\n\t\t\tthis.set( '_points', this.get_total_points() );\n\n\t\t\t// when a quiz is published, ensure the parent lesson is marked as \"Enabled\" for quizzing\n\t\t\tthis.on( 'change:status', function() {\n\t\t\t\tif ( 'publish' === this.get( 'status' ) ) {\n\t\t\t\t\tthis.get_parent().set( 'quiz_enabled', 'yes' );\n\t\t\t\t}\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * Add a new question to the quiz\n\t\t * @param obj data question data\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tadd_question: function( data ) {\n\n\t\t\tdata.parent_id = this.get( 'id' );\n\t\t\tvar question = this.get( 'questions' ).add( data, {\n\t\t\t\tparent: this,\n\t\t\t} );\n\t\t\tBackbone.pubSub.trigger( 'quiz-add-question', question, this );\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the translated post type name for the model's type\n\t\t * @param bool plural if true, returns the plural, otherwise returns singular\n\t\t * @return string\n\t\t * @since 3.16.12\n\t\t * @version 3.16.12\n\t\t */\n\t\tget_l10n_type: function( plural ) {\n\n\t\t\tif ( plural ) {\n\t\t\t\treturn LLMS.l10n.translate( 'quizzes' );\n\t\t\t}\n\n\t\t\treturn LLMS.l10n.translate( 'quiz' );\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the quiz's total points\n\t\t * @return int\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_total_points: function() {\n\n\t\t\tvar points = 0;\n\n\t\t\tthis.get( 'questions' ).each( function( question ) {\n\t\t\t\tpoints += question.get_points();\n\t\t\t} );\n\n\t\t\treturn points;\n\n\t\t},\n\n\t\t/**\n\t\t * Lazy load questions via AJAX\n\t\t * @param {Function} cb callback function\n\t\t * @return void\n\t\t * @since 3.19.2\n\t\t * @version 3.19.2\n\t\t */\n\t\tload_questions: function( cb ) {\n\n\t\t\tif ( this.get( '_questions_loaded' ) ) {\n\n\t\t\t\tcb();\n\n\t\t\t} else {\n\n\t\t\t\tvar self = this;\n\n\t\t\t\tLLMS.Ajax.call( {\n\t\t\t\t\tdata: {\n\t\t\t\t\t\taction: 'llms_builder',\n\t\t\t\t\t\taction_type: 'lazy_load',\n\t\t\t\t\t\tcourse_id: window.llms_builder.CourseModel.get( 'id' ),\n\t\t\t\t\t\tload_id: this.get( 'id' ),\n\t\t\t\t\t},\n\t\t\t\t\terror: function( xhr, status, error ) {\n\n\t\t\t\t\t\tconsole.log( xhr, status, error );\n\t\t\t\t\t\twindow.llms_builder.debug.log( '==== start load_questions error ====', xhr, status, error, '==== finish load_questions error ====' );\n\t\t\t\t\t\tcb( true );\n\n\t\t\t\t\t},\n\t\t\t\t\tsuccess: function( res ) {\n\t\t\t\t\t\tif ( res && res.questions ) {\n\t\t\t\t\t\t\tself.set( '_questions_loaded', true );\n\t\t\t\t\t\t\tif ( res.questions ) {\n\t\t\t\t\t\t\t\t_.each( res.questions, self.add_question, self );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcb();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tcb( true );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t} );\n\n\t\t\t}\n\n\n\t\t},\n\n\t\t/**\n\t\t * Update total number of points calculated property\n\t\t * @return int\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tupdate_points: function() {\n\n\t\t\tthis.set( '_points', this.get_total_points() );\n\n\t\t},\n\n\t}, Relationships, Utilities ) );\n\n} );\n\n","/**\n * Lesson Schemas\n * @since 3.17.0\n * @version 3.17.1\n */\ndefine( 'Schemas/Lesson',[], function() {\n\n\treturn {\n\n\t\tdefault: {\n\t\t\ttitle: LLMS.l10n.translate( 'General Settings' ),\n\t\t\ttoggleable: true,\n\t\t\tfields: [\n\t\t\t\t[\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'permalink',\n\t\t\t\t\t\tid: 'permalink',\n\t\t\t\t\t\ttype: 'permalink',\n\t\t\t\t\t},\n\t\t\t\t], [\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'video_embed',\n\t\t\t\t\t\tid: 'video-embed',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Video Embed URL' ),\n\t\t\t\t\t\ttype: 'video_embed',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'audio_embed',\n\t\t\t\t\t\tid: 'audio-embed',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Audio Embed URL' ),\n\t\t\t\t\t\ttype: 'audio_embed',\n\t\t\t\t\t},\n\t\t\t\t], [\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'free_lesson',\n\t\t\t\t\t\tid: 'free-lesson',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Free Lesson' ),\n\t\t\t\t\t\ttip: LLMS.l10n.translate( \"Free lessons can be accessed without enrollment.\" ),\n\t\t\t\t\t\ttype: 'switch',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'require_passing_grade',\n\t\t\t\t\t\tid: 'require-passing-grade',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Require Passing Grade on Quiz' ),\n\t\t\t\t\t\ttip: LLMS.l10n.translate( \"When enabled, students must pass this lesson's quiz before the lesson can be completed.\" ),\n\t\t\t\t\t\ttype: 'switch',\n\t\t\t\t\t\tcondition: function() {\n\t\t\t\t\t\t\treturn ( 'yes' === this.get( 'quiz_enabled' ) );\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'require_assignment_passing_grade',\n\t\t\t\t\t\tid: 'require-assignment-passing-grade',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Require Passing Grade on Assignment' ),\n\t\t\t\t\t\ttip: LLMS.l10n.translate( \"When enabled, students must pass this lesson's assignment before the lesson can be completed.\" ),\n\t\t\t\t\t\ttype: 'switch',\n\t\t\t\t\t\tcondition: function() {\n\t\t\t\t\t\t\treturn ( 'undefined' !== window.llms_builder.assignments && 'yes' === this.get( 'assignment_enabled' ) );\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t], [\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'prerequisite',\n\t\t\t\t\t\tcondition: function() {\n\t\t\t\t\t\t\treturn ( false === this.is_first_in_course() );\n\t\t\t\t\t\t},\n\t\t\t\t\t\tid: 'prerequisite',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Prerequisite' ),\n\t\t\t\t\t\tswitch_attribute: 'has_prerequisite',\n\t\t\t\t\t\ttype: 'switch-select',\n\t\t\t\t\t\toptions: function() {\n\t\t\t\t\t\t\treturn this.get_available_prereq_options();\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t], [\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'drip_method',\n\t\t\t\t\t\tid: 'drip-method',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Drip Method' ),\n\t\t\t\t\t\tswitch_attribute: 'drip_method',\n\t\t\t\t\t\ttype: 'select',\n\t\t\t\t\t\toptions: function() {\n\n\t\t\t\t\t\t\tvar options = [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tkey: '',\n\t\t\t\t\t\t\t\t\tval: LLMS.l10n.translate( 'None' ),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tkey: 'date',\n\t\t\t\t\t\t\t\t\tval: LLMS.l10n.translate( 'On a specific date' ),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tkey: 'enrollment',\n\t\t\t\t\t\t\t\t\tval: LLMS.l10n.translate( '# of days after course enrollment' ),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t];\n\n\t\t\t\t\t\t\tif ( this.get_course().get( 'start_date' ) ) {\n\t\t\t\t\t\t\t\toptions.push( {\n\t\t\t\t\t\t\t\t\tkey: 'start',\n\t\t\t\t\t\t\t\t\tval: LLMS.l10n.translate( '# of days after course start date' ),\n\t\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif ( 'yes' === this.get( 'has_prerequisite' ) ) {\n\t\t\t\t\t\t\t\toptions.push( {\n\t\t\t\t\t\t\t\t\tkey: 'prerequisite',\n\t\t\t\t\t\t\t\t\tval: LLMS.l10n.translate( '# of days after prerequisite lesson completion' ),\n\t\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\treturn options;\n\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'days_before_available',\n\t\t\t\t\t\tcondition: function() {\n\t\t\t\t\t\t\treturn ( -1 !== [ 'enrollment', 'start', 'prerequisite' ].indexOf( this.get( 'drip_method' ) ) );\n\t\t\t\t\t\t},\n\t\t\t\t\t\tid: 'days-before-available',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( '# of days' ),\n\t\t\t\t\t\tmin: 0,\n\t\t\t\t\t\ttype: 'number',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'date_available',\n\t\t\t\t\t\tdate_format: 'Y-m-d',\n\t\t\t\t\t\tcondition: function() {\n\t\t\t\t\t\t\treturn ( 'date' === this.get( 'drip_method' ) );\n\t\t\t\t\t\t},\n\t\t\t\t\t\tid: 'date-available',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Date' ),\n\t\t\t\t\t\ttimepicker: 'false',\n\t\t\t\t\t\ttype: 'datepicker',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tattribute: 'time_available',\n\t\t\t\t\t\tcondition: function() {\n\t\t\t\t\t\t\treturn ( 'date' === this.get( 'drip_method' ) );\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdatepicker: 'false',\n\t\t\t\t\t\tdate_format: 'h:i A',\n\t\t\t\t\t\tid: 'time-available',\n\t\t\t\t\t\tlabel: LLMS.l10n.translate( 'Time' ),\n\t\t\t\t\t\ttype: 'datepicker',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t],\n\t\t},\n\n\t};\n\n} );\n\n","/**\n * Lesson Model\n * @since 3.13.0\n * @version 3.19.3\n */\ndefine( 'Models/Lesson',[ 'Models/Quiz', 'Models/_Relationships', 'Models/_Utilities', 'Schemas/Lesson' ], function( Quiz, Relationships, Utilities, LessonSchema ) {\n\n\treturn Backbone.Model.extend( _.defaults( {\n\n\t\t/**\n\t\t * Model relationships\n\t\t * @type {Object}\n\t\t */\n\t\trelationships: {\n\t\t\tparents: {\n\t\t\t\tmodel: 'section',\n\t\t\t\ttype: 'model',\n\t\t\t},\n\t\t\tchildren: {\n\t\t\t\tquiz: {\n\t\t\t\t\tclass: 'Quiz',\n\t\t\t\t\tconditional: function( model ) {\n\t\t\t\t\t\t// if quiz is enabled OR not enabled but we have some quiz data as an obj\n\t\t\t\t\t\treturn ( 'yes' === model.get( 'quiz_enabled' ) || ! _.isEmpty( model.get( 'quiz' ) ) );\n\t\t\t\t\t},\n\t\t\t\t\tmodel: 'llms_quiz',\n\t\t\t\t\ttype: 'model',\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\n\t\t/**\n\t\t * Lesson Settings Schema\n\t\t * @type {Object}\n\t\t */\n\t\tschema: LessonSchema,\n\n\t\t/**\n\t\t * New lesson defaults\n\t\t * @return obj\n\t\t * @since 3.13.0\n\t\t * @version 3.17.1\n\t\t */\n\t\tdefaults: function() {\n\t\t\treturn {\n\t\t\t\tid: _.uniqueId( 'temp_' ),\n\t\t\t\ttitle: LLMS.l10n.translate( 'New Lesson' ),\n\t\t\t\ttype: 'lesson',\n\t\t\t\torder: this.collection ? this.collection.length + 1 : 1,\n\t\t\t\tparent_course: window.llms_builder.course.id,\n\t\t\t\tparent_section: '',\n\n\t\t\t\t// urls\n\t\t\t\tedit_url: '',\n\t\t\t\tview_url: '',\n\n\t\t\t\t// editable fields\n\t\t\t\tcontent: '',\n\t\t\t\taudio_embed: '',\n\t\t\t\thas_prerequisite: 'no',\n\t\t\t\trequire_passing_grade: 'yes',\n\t\t\t\trequire_assignment_passing_grade: 'yes',\n\t\t\t\tvideo_embed: '',\n\t\t\t\tfree_lesson: '',\n\n\t\t\t\t// other fields\n\t\t\t\tassignment: {}, // assignment model/data\n\t\t\t\tassignment_enabled: 'no',\n\n\t\t\t\tquiz: {}, // quiz model/data\n\t\t\t\tquiz_enabled: 'no',\n\n\t\t\t\t_forceSync: false,\n\n\t\t\t};\n\t\t},\n\n\t\t/**\n\t\t * Initializer\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\tthis.init_custom_schema();\n\t\t\tthis.startTracking();\n\t\t\tthis.maybe_init_assignments();\n\t\t\tthis.init_relationships();\n\n\t\t\t// if the lesson ID isn't set on a quiz, set it\n\t\t\tvar quiz = this.get( 'quiz' );\n\t\t\tif ( ! _.isEmpty( quiz ) && ! quiz.get( 'lesson_id' ) ) {\n\t\t\t\tquiz.set( 'lesson_id', this.get( 'id' ) );\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve a reference to the parent course of the lesson\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_course: function() {\n\t\t\treturn this.get_parent().get_parent();\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the translated post type name for the model's type\n\t\t * @param bool plural if true, returns the plural, otherwise returns singular\n\t\t * @return string\n\t\t * @since 3.16.12\n\t\t * @version 3.16.12\n\t\t */\n\t\tget_l10n_type: function( plural ) {\n\n\t\t\tif ( plural ) {\n\t\t\t\treturn LLMS.l10n.translate( 'lessons' );\n\t\t\t}\n\n\t\t\treturn LLMS.l10n.translate( 'lesson' );\n\t\t},\n\n\t\t/**\n\t\t * Override default get_parent to grab from collection if models parent isn't set\n\t\t * @return obj\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tget_parent: function() {\n\n\t\t\tvar rels = this.get_relationships();\n\t\t\tif ( rels.parent && rels.parent.reference ) {\n\t\t\t\treturn rels.parent.reference;\n\t\t\t} else if ( this.collection && this.collection.parent ) {\n\t\t\t\treturn this.collection.parent;\n\t\t\t}\n\t\t\treturn false;\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve an array of prerequisite options available for the current lesson\n\t\t * @return obj\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tget_available_prereq_options: function() {\n\n\t\t\tvar parent_section_index = this.get_parent().collection.indexOf( this.get_parent() ),\n\t\t\t\tlesson_index_in_section = this.collection.indexOf( this ),\n\t\t\t\toptions = [];\n\n\t\t\tthis.get_course().get( 'sections' ).each( function( section, curr_sec_index ) {\n\t\t\t\tif ( curr_sec_index <= parent_section_index ) {\n\t\t\t\t\tvar group = {\n\t\t\t\t\t\t\t/* translators: %1$d = section order number, %2$s = section title */\n\t\t\t\t\t\t\tlabel: LLMS.l10n.replace( 'Section %1$d: %2$s', {\n\t\t\t\t\t\t\t\t'%1$d': section.get( 'order' ),\n\t\t\t\t\t\t\t\t'%2$s': section.get( 'title' )\n\t\t\t\t\t\t\t} ),\n\t\t\t\t\t\t\toptions: [],\n\t\t\t\t\t\t};\n\n\t\t\t\t\tsection.get( 'lessons' ).each( function( lesson, curr_les_index ) {\n\t\t\t\t\t\tif ( curr_sec_index !== parent_section_index || curr_les_index < lesson_index_in_section ) {\n\t\t\t\t\t\t\t/* translators: %1$d = lesson order number, %2$s = lesson title */\n\t\t\t\t\t\t\tgroup.options.push( {\n\t\t\t\t\t\t\t\tkey: lesson.get( 'id' ),\n\t\t\t\t\t\t\t\tval: LLMS.l10n.replace( 'Lesson %1$d: %2$s', {\n\t\t\t\t\t\t\t\t\t'%1$d': lesson.get( 'order' ),\n\t\t\t\t\t\t\t\t\t'%2$s': lesson.get( 'title' )\n\t\t\t\t\t\t\t\t} ),\n\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t}\n\t\t\t\t\t}, this );\n\n\t\t\t\t\toptions.push( group );\n\t\t\t\t}\n\t\t\t}, this );\n\n\t\t\treturn options;\n\n\t\t},\n\n\t\t/**\n\t\t * Add a new quiz to the lesson\n\t\t * @param obj data object of quiz data used to construct a new quiz model\n\t\t * @return obj model for the created quiz\n\t\t * @since 3.16.0\n\t\t * @version 3.19.3\n\t\t */\n\t\tadd_quiz: function( data ) {\n\n\t\t\tdata = data || {};\n\n\t\t\tdata.lesson_id = this.id;\n\t\t\tdata._questions_loaded = true;\n\n\t\t\tif ( ! data.title ) {\n\n\t\t\t\tdata.title = LLMS.l10n.replace( '%1$s Quiz', {\n\t\t\t\t\t'%1$s': this.get( 'title' ),\n\t\t\t\t} );\n\n\t\t\t}\n\n\t\t\tthis.set( 'quiz', data );\n\t\t\tthis.init_relationships();\n\n\t\t\tvar quiz = this.get( 'quiz' );\n\t\t\tthis.set( 'quiz_enabled', 'yes' );\n\n\t\t\treturn quiz;\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if this is the first lesson\n\t\t * @return {Boolean}\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tis_first_in_course: function() {\n\n\t\t\t// if it's not the first item in the section it cant be the first lesson\n\t\t\tif ( this.collection.indexOf( this ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// if it's not the first section it cant' be first lesson\n\t\t\tvar section = this.get_parent();\n\t\t\tif ( section.collection.indexOf( section ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// it's first lesson in first section\n\t\t\treturn true;\n\n\t\t},\n\n\t\t/**\n\t\t * Initialize lesson assignments *if* the assignments addon is availalbe and enabled\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tmaybe_init_assignments: function() {\n\n\t\t\tif ( ! window.llms_builder.assignments ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis.relationships.children.assignment = {\n\t\t\t\tclass: 'Assignment',\n\t\t\t\tconditional: function( model ) {\n\t\t\t\t\t// if assignment is enabled OR not enabled but we have some assignment data as an obj\n\t\t\t\t\treturn ( 'yes' === model.get( 'assignment_enabled' ) || ! _.isEmpty( model.get( 'assignment' ) ) );\n\t\t\t\t},\n\t\t\t\tmodel: 'llms_assignment',\n\t\t\t\ttype: 'model',\n\t\t\t};\n\n\t\t},\n\n\t}, Relationships, Utilities ) );\n\n} );\n\n","/**\n * Lessons Collection\n * @since 3.13.0\n * @version 3.17.0\n */\ndefine( 'Collections/Lessons',[ 'Models/Lesson' ], function( model ) {\n\n\treturn Backbone.Collection.extend( {\n\n\t\t/**\n\t\t * Model for collection items\n\t\t * @type obj\n\t\t */\n\t\tmodel: model,\n\n\t\t/**\n\t\t * Initializer\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\t// reorder called by LessonList view when sortable drops occur\n\t\t\tthis.on( 'reorder', this.on_reorder );\n\n\t\t\t// when a lesson is added or removed, update order\n\t\t\tthis.on( 'add', this.on_reorder );\n\t\t\tthis.on( 'remove', this.on_reorder );\n\n\t\t},\n\n\t\t/**\n\t\t * On lesson reorder callback\n\t\t *\n\t\t * Update the order attr of each lesson to reflect the new lesson order\n\t\t * Validate prerequisite (if set) and unset it if it's no longer a valid prereq\n\t\t *\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\ton_reorder: function() {\n\t\t\tthis.update_order();\n\t\t\tthis.validate_prereqs();\n\t\t},\n\n\t\t/**\n\t\t * Update lesson order attribute of all lessons when lessons are reordered\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tupdate_order: function() {\n\n\t\t\tthis.each( function( lesson ) {\n\t\t\t\tlesson.set( 'order', this.indexOf( lesson ) + 1 );\n\t\t\t}, this );\n\n\t\t},\n\n\n\t\t/**\n\t\t * Validate prerequisite (if set) and unset it if it's no longer a valid prereq\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tvalidate_prereqs: function() {\n\n\t\t\tthis.each( function( lesson ) {\n\n\t\t\t\t// validate prereqs\n\t\t\t\tif ( 'yes' === lesson.get( 'has_prerequisite' ) ) {\n\t\t\t\t\tvar valid = _.pluck( _.flatten( _.pluck( lesson.get_available_prereq_options(), 'options' ) ), 'key' );\n\t\t\t\t\tif ( -1 === valid.indexOf( lesson.get( 'prerequisite' ) * 1 ) ) {\n\t\t\t\t\t\tlesson.set( {\n\t\t\t\t\t\t\tprerequisite: 0,\n\t\t\t\t\t\t\thas_prerequisite: 'no',\n\t\t\t\t\t\t} );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t}, this );\n\n\t\t},\n\n\t} );\n\n} );\n\n","/**\n * Quiz Question Type Collection\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Collections/QuestionTypes',[ 'Models/QuestionType' ], function( model ) {\n\n\treturn Backbone.Collection.extend( {\n\n\t\t/**\n\t\t * Model for collection items\n\t\t * @type obj\n\t\t */\n\t\tmodel: model,\n\n\t\t/**\n\t\t * Initializer\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\tthis.on( 'add', this.comparator );\n\t\t\tthis.on( 'remove', this.comparator );\n\n\t\t},\n\n\t\t/**\n\t\t * Comparator (sorts collection)\n\t\t * @param obj model QuestionType model\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tcomparator: function( model ) {\n\n\t\t\treturn model.get( 'group' ).order;\n\n\t\t},\n\n\t} );\n\n} );\n\n","/**\n * Section Model\n * @since 3.16.0\n * @version 3.16.12\n */\ndefine( 'Models/Section',[ 'Collections/Lessons', 'Models/_Relationships' ], function( Lessons, Relationships ) {\n\n\treturn Backbone.Model.extend( _.defaults( {\n\n\t\trelationships: {\n\t\t\tparent: {\n\t\t\t\tmodel: 'course',\n\t\t\t\ttype: 'model',\n\t\t\t},\n\t\t\tchildren: {\n\t\t\t\tlessons: {\n\t\t\t\t\tclass: 'Lessons',\n\t\t\t\t\tmodel: 'lesson',\n\t\t\t\t\ttype: 'collection',\n\t\t\t\t},\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * New section defaults\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tdefaults: function() {\n\t\t\treturn {\n\t\t\t\tid: _.uniqueId( 'temp_' ),\n\t\t\t\tlessons: [],\n\t\t\t\torder: this.collection ? this.collection.length + 1 : 1,\n\t\t\t\tparent_course: window.llms_builder.course.id,\n\t\t\t\ttitle: LLMS.l10n.translate( 'New Section' ),\n\t\t\t\ttype: 'section',\n\n\t\t\t\t_expanded: false,\n\t\t\t\t_selected: false,\n\t\t\t};\n\t\t},\n\n\t\t/**\n\t\t * Initialize\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\tthis.startTracking();\n\t\t\tthis.init_relationships();\n\n\t\t},\n\n\t\t/**\n\t\t * Add a lesson to the section\n\t\t * @param obj data hash of lesson data (creates new lesson)\n\t\t * or existing lesson as a Backbone.Model\n\t\t * @param obj options has of options\n\t\t * @return obj Backbone.Model of the new/updated lesson\n\t\t * @since 3.16.0\n\t\t * @version 3.16.11\n\t\t */\n\t\tadd_lesson: function( data, options ) {\n\n\t\t\tdata = data || {};\n\t\t\toptions = options || {};\n\n\t\t\tif ( data instanceof Backbone.Model ) {\n\t\t\t\tdata.set( 'parent_section', this.get( 'id' ) );\n\t\t\t\tdata.set_parent( this );\n\t\t\t} else {\n\t\t\t\tdata.parent_section = this.get( 'id' );\n\t\t\t}\n\n\t\t\treturn this.get( 'lessons' ).add( data, options );\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the translated post type name for the model's type\n\t\t * @param bool plural if true, returns the plural, otherwise returns singular\n\t\t * @return string\n\t\t * @since 3.16.12\n\t\t * @version 3.16.12\n\t\t */\n\t\tget_l10n_type: function( plural ) {\n\n\t\t\tif ( plural ) {\n\t\t\t\treturn LLMS.l10n.translate( 'sections' );\n\t\t\t}\n\n\t\t\treturn LLMS.l10n.translate( 'section' );\n\t\t},\n\n\t\t/**\n\t\t * Get next section in the collection\n\t\t * @param bool circular if true handles the collection in a circle\n\t\t * \tif current is the last section, returns the first section\n\t\t * \tif current is the first section, returns the last section\n\t\t * @return obj|false\n\t\t * @since 3.16.11\n\t\t * @version 3.16.11\n\t\t */\n\t\tget_next: function( circular ) {\n\t\t\treturn this._get_sibling( 'next', circular );\n\t\t},\n\n\t\t/**\n\t\t * Get prev section in the collection\n\t\t * @param bool circular if true handles the collection in a circle\n\t\t * \tif current is the last section, returns the first section\n\t\t * \tif current is the first section, returns the last section\n\t\t * @return obj|false\n\t\t * @since 3.16.11\n\t\t * @version 3.16.11\n\t\t */\n\t\tget_prev: function( circular ) {\n\t\t\treturn this._get_sibling( 'prev', circular );\n\t\t},\n\n\t\t/**\n\t\t * Get a sibling section\n\t\t * @param string direction siblings direction [next|prev]\n\t\t * @param bool circular if true handles the collection in a circle\n\t\t * \tif current is the last section, returns the first section\n\t\t * \tif current is the first section, returns the last section\n\t\t * @return obj|false\n\t\t * @since 3.16.11\n\t\t * @version 3.16.11\n\t\t */\n\t\t_get_sibling: function( direction, circular ) {\n\n\t\t\tcircular = ( 'undefined' === circular ) ? true : circular;\n\n\t\t\tvar max = this.collection.size() - 1,\n\t\t\t\tindex = this.collection.indexOf( this ),\n\t\t\t\tsibling_index;\n\n\t\t\tif ( 'next' === direction ) {\n\t\t\t\tsibling_index = index + 1;\n\t\t\t} else if ( 'prev' === direction ) {\n\t\t\t\tsibling_index = index - 1;\n\t\t\t}\n\n\t\t\t// dont retrieve greater than max or less than min\n\t\t\tif ( sibling_index <= max || sibling_index <= 0 ) {\n\n\t\t\t\treturn this.collection.at( sibling_index );\n\n\t\t\t} else if ( circular ) {\n\n\t\t\t\tif ( 'next' === direction ) {\n\t\t\t\t\treturn this.collection.first();\n\t\t\t\t} else if ( 'prev' === direction ) {\n\t\t\t\t\treturn this.collection.last();\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn false;\n\n\t\t},\n\n\t}, Relationships ) );\n\n} );\n\n","/**\n * Sections Collection\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Collections/Sections',[ 'Models/Section' ], function( model ) {\n\n\treturn Backbone.Collection.extend( {\n\n\t\t/**\n\t\t * Model for collection items\n\t\t * @type obj\n\t\t */\n\t\tmodel: model,\n\n\t\t/**\n\t\t * Initialize\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\tvar self = this;\n\n\t\t\t// reorder called by SectionList view when sortable drops occur\n\t\t\tthis.on( 'reorder', this.update_order );\n\n\t\t\t// when a section is added or removed, update order\n\t\t\tthis.on( 'add', this.update_order );\n\t\t\tthis.on( 'remove', this.update_order );\n\n\t\t},\n\n\t\t/**\n\t\t * Update the order attr of each section in the list to reflect the order of the collection\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tupdate_order: function() {\n\n\t\t\tvar self = this;\n\n\t\t\tthis.each( function( section ) {\n\n\t\t\t\tsection.set( 'order', self.indexOf( section ) + 1 );\n\n\t\t\t} );\n\n\t\t},\n\n\t} );\n\n} );\n\n","/**\n * Lessons Collection\n * @since 3.13.0\n * @version 3.16.0\n */\ndefine( 'Collections/loader',[\n\t\t'Collections/Lessons',\n\t\t'Collections/QuestionChoices',\n\t\t'Collections/Questions',\n\t\t'Collections/QuestionTypes',\n\t\t'Collections/Sections'\n\t], function(\n\t\tLessons,\n\t\tQuestionChoices,\n\t\tQuestions,\n\t\tQuestionTypes,\n\t\tSections\n\t) {\n\n\treturn {\n\t\tLessons: Lessons,\n\t\tQuestionChoices: QuestionChoices,\n\t\tQuestions: Questions,\n\t\tQuestionTypes: QuestionTypes,\n\t\tSections: Sections,\n\t};\n\n} );\n\n","/**\n * Abstract LifterLMS Model\n * @since 3.17.0\n * @version 3.17.0\n */\ndefine( 'Models/Abstract',[ 'Models/_Relationships', 'Models/_Utilities' ], function( Relationships, Utilities ) {\n\n\treturn Backbone.Model.extend( _.defaults( {}, Relationships, Utilities ) );\n\n} );\n\n","/**\n * Course Model\n * @since 3.16.0\n * @version 3.16.11\n */\ndefine( 'Models/Course',[ 'Collections/Sections', 'Models/_Relationships', 'Models/_Utilities' ], function( Sections, Relationships, Utilities ) {\n\n\treturn Backbone.Model.extend( _.defaults( {\n\n\t\trelationships: {\n\t\t\tchildren: {\n\t\t\t\tsections: {\n\t\t\t\t\tclass: 'Sections',\n\t\t\t\t\tmodel: 'section',\n\t\t\t\t\ttype: 'collection',\n\t\t\t\t},\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * New Course Defaults\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tdefaults: function() {\n\t\t\treturn {\n\t\t\t\tedit_url: '',\n\t\t\t\tsections: [],\n\t\t\t\ttitle: 'New Course',\n\t\t\t\ttype: 'course',\n\t\t\t\tview_url: '',\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Init\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\tthis.startTracking();\n\t\t\tthis.init_relationships();\n\n\t\t\t// Sidebar \"New Section\" button broadcast\n\t\t\tBackbone.pubSub.on( 'add-new-section', this.add_section, this );\n\n\t\t\t// Sidebar \"New Lesson\" button broadcast\n\t\t\tBackbone.pubSub.on( 'add-new-lesson', this.add_lesson, this );\n\n\t\t\tBackbone.pubSub.on( 'lesson-search-select', this.add_existing_lesson, this );\n\n\t\t},\n\n\t\t/**\n\t\t * Add an existing lesson to the course\n\t\t * Duplicate a lesson from this or another course or attach an orphaned lesson\n\t\t * @param obj lesson lesson data obj\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.11\n\t\t */\n\t\tadd_existing_lesson: function( lesson ) {\n\n\t\t\tvar data = lesson.data;\n\n\t\t\tif ( 'clone' === lesson.action ) {\n\n\t\t\t\tdelete data.id;\n\t\t\t\tif ( data.quiz ) {\n\t\t\t\t\tdelete data.quiz;\n\t\t\t\t\tdata.quiz_enabled = 'no';\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\tdata._forceSync = true;\n\n\t\t\t}\n\n\t\t\tdelete data.order;\n\t\t\tdelete data.parent_course;\n\t\t\tdelete data.parent_section;\n\n\t\t\tthis.add_lesson( data );\n\n\t\t},\n\n\t\t/**\n\t\t * Add a new lesson to the course\n\t\t * @param obj data lesson data\n\t\t * @return obj Backbone.Model of the lesson\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tadd_lesson: function( data ) {\n\n\t\t\tdata = data || {};\n\t\t\tvar options = {},\n\t\t\t\tsection;\n\n\t\t\tif ( ! data.parent_section ) {\n\t\t\t\tsection = this.get_selected_section();\n\t\t\t\tif ( ! section ) {\n\t\t\t\t\tsection = this.get( 'sections' ).last();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tsection = this.get( 'sections' ).get( data.parent_section );\n\t\t\t}\n\n\t\t\tdata._selected = true;\n\n\t\t\tdata.parent_course = this.get( 'id' );\n\n\t\t\tvar lesson = section.add_lesson( data, options );\n\t\t\tBackbone.pubSub.trigger( 'new-lesson-added', lesson );\n\n\t\t\t// expand the section\n\t\t\tsection.set( '_expanded', true );\n\n\t\t\treturn lesson;\n\n\t\t},\n\n\t\t/**\n\t\t * Add a new section to the course\n\t\t * @param obj data section data\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tadd_section: function( data ) {\n\n\t\t\tdata = data || {};\n\t\t\tvar sections = this.get( 'sections' ),\n\t\t\t\toptions = {},\n\t\t\t\tselected = this.get_selected_section();\n\n\t\t\t// if a section is selected, add the new section after the currently selected one\n\t\t\tif ( selected ) {\n\t\t\t\toptions.at = sections.indexOf( selected ) + 1;\n\t\t\t}\n\n\t\t\tsections.add( data, options );\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the currently selected section in the course\n\t\t * @return obj|undefined\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_selected_section: function() {\n\n\t\t\treturn this.get( 'sections' ).find( function( model ) {\n\t\t\t\treturn model.get( '_selected' );\n\t\t\t} );\n\n\t\t},\n\n\t}, Relationships, Utilities ) );\n\n} );\n\n","/**\n * Load all models\n * @return obj\n * @since 3.16.0\n * @version 3.17.0\n */\ndefine( 'Models/loader',[\n\t\t'Models/Abstract',\n\t\t'Models/Course',\n\t\t'Models/Image',\n\t\t'Models/Lesson',\n\t\t'Models/Question',\n\t\t'Models/QuestionChoice',\n\t\t'Models/QuestionType',\n\t\t'Models/Quiz',\n\t\t'Models/Section'\n\t],\n\tfunction(\n\t\tAbstract,\n\t\tCourse,\n\t\tImage,\n\t\tLesson,\n\t\tQuestion,\n\t\tQuestionChoice,\n\t\tQuestionType,\n\t\tQuiz,\n\t\tSection\n\t) {\n\n\treturn {\n\t\tAbstract: Abstract,\n\t\tCourse: Course,\n\t\tImage: Image,\n\t\tLesson: Lesson,\n\t\tQuestion: Question,\n\t\tQuestionChoice: QuestionChoice,\n\t\tQuestionType: QuestionType,\n\t\tQuiz: Quiz,\n\t\tSection: Section,\n\t};\n\n} );\n\n","/**\n * Detachable model\n * @type {Object}\n * @since 3.16.12\n * @version 3.16.12\n */\ndefine( 'Views/_Detachable',[], function() {\n\n\treturn {\n\n\t\t/**\n\t\t * DOM Events\n\t\t * @type {Object}\n\t\t * @since 3.16.12\n\t\t * @version 3.16.12\n\t\t */\n\t\tevents: {\n\t\t\t'click a[href=\"#llms-detach-model\"]': 'detach_model',\n\t\t},\n\n\t\t/**\n\t\t * Detaches a model from it's parent (doesn't delete)\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.16.12\n\t\t * @version 3.16.12\n\t\t */\n\t\tdetach_model: function( event ) {\n\n\t\t\tif ( event ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tevent.stopPropagation();\n\t\t\t}\n\n\t\t\tvar msg = LLMS.l10n.replace( 'Are you sure you want to detach this %s?', {\n\t\t\t\t'%s': this.model.get_l10n_type(),\n\t\t\t} );\n\n\t\t\tif ( window.confirm( msg ) ) {\n\n\t\t\t\tif ( this.model.collection ) {\n\t\t\t\t\tthis.model.collection.remove( this.model );\n\t\t\t\t}\n\n\t\t\t\t// publish global event\n\t\t\t\tBackbone.pubSub.trigger( 'model-detached', this.model );\n\n\t\t\t\t// trigger local event so extending views can run other actions where necessary\n\t\t\t\tthis.trigger( 'model-trashed', this.model );\n\n\t\t\t}\n\n\t\t},\n\n\t}\n\n} );\n\n","/**\n * Handles UX and Events for inline editing of views\n * Use with a Model's View\n * Allows editing model.title field via .llms-editable-title elements\n * @type {Object}\n * @since 3.16.0\n * @version 3.17.8\n */\ndefine( 'Views/_Editable',[], function() {\n\n\treturn {\n\n\t\tmedia_lib: null,\n\n\t\t/**\n\t\t * DOM Events\n\t\t * @type {Object}\n\t\t * @since 3.16.0\n\t\t * @version 3.17.8\n\t\t */\n\t\tevents: {\n\t\t\t'click .llms-add-image': 'open_media_lib',\n\t\t\t'click a[href=\"#llms-edit-slug\"]': 'make_slug_editable',\n\t\t\t'click a[href=\"#llms-remove-image\"]': 'remove_image',\n\t\t\t'change .llms-editable-select select': 'on_select',\n\t\t\t'change .llms-switch input[type=\"checkbox\"]': 'toggle_switch',\n\t\t\t'change .llms-editable-radio input': 'on_radio_select',\n\t\t\t'focusin .llms-input': 'on_focus',\n\t\t\t'focusout .llms-input': 'on_blur',\n\t\t\t'keydown .llms-input': 'on_keydown',\n\t\t\t'input .llms-input[type=\"number\"]': 'on_blur',\n\t\t\t'paste .llms-input[data-formatting]': 'on_paste',\n\t\t},\n\n\t\t/**\n\t\t * Retrieve a list of allowed tags for a given element\n\t\t * @param obj $el jQuery selector for the element\n\t\t * @return array\n\t\t * @since 3.16.0\n\t\t * @version 3.17.8\n\t\t */\n\t\tget_allowed_tags: function( $el ) {\n\n\t\t\tif ( $el.attr( 'data-formatting' ) ) {\n\t\t\t\treturn _.map( $el.attr( 'data-formatting' ).split( ',' ), function( tag ) {\n\t\t\t\t\treturn tag.trim();\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\treturn [ 'b', 'i', 'u', 'strong', 'em' ];\n\n\t\t},\n\n\t\t/**\n\t\t * Retrieve the content of an element\n\t\t * @param obj $el jQuery object of the element\n\t\t * @return string\n\t\t * @since 3.16.0\n\t\t * @version 3.17.8\n\t\t */\n\t\tget_content: function( $el ) {\n\n\t\t\tif ( 'INPUT' === $el[0].tagName ) {\n\t\t\t\treturn $el.val();\n\t\t\t}\n\n\t\t\tif ( ! $el.attr( 'data-formatting' ) && ! $el.hasClass( 'ql-editor' ) ) {\n\t\t\t\treturn $el.text();\n\t\t\t}\n\n\t\t\treturn _.stripFormatting( $el.html(), this.get_allowed_tags( $el ) );\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if changes have been made to the element\n\t\t * @param {[obj]} event js event object\n\t\t * @return {Boolean} true when changes have been made, false otherwise\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\thas_changed: function( event ) {\n\t\t\tvar $el = $( event.target );\n\t\t\treturn ( $el.attr( 'data-original-content' ) !== this.get_content( $el ) );\n\t\t},\n\n\t\t/**\n\t\t * Ensure that new content is at least 1 character long\n\t\t * @param obj event js event object\n\t\t * @return boolean\n\t\t * @since 3.16.0\n\t\t * @version 3.17.2\n\t\t */\n\t\tis_valid: function( event ) {\n\n\t\t\tvar self = this,\n\t\t\t\t$el = $( event.target ),\n\t\t\t\tcontent = this.get_content( $el ),\n\t\t\t\ttype = $el.attr( 'data-type' );\n\n\t\t\tif ( ( $el.attr( 'required' ) || $el.attr( 'data-required' ) ) && content.length < 1 ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tif ( 'url' === type || 'video' === type ) {\n\t\t\t\tif ( ! this._validate_url( this.get_content( $el ) ) ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t} else if ( 'permalink' === type ) {\n\n\t\t\t\tLLMS.Ajax.call( {\n\t\t\t\t\tdata: {\n\t\t\t\t\t\taction: 'llms_builder',\n\t\t\t\t\t\taction_type: 'get_permalink',\n\t\t\t\t\t\tcourse_id: window.llms_builder.CourseModel.get( 'id' ),\n\t\t\t\t\t\tid: self.model.get( 'id' ),\n\t\t\t\t\t\ttitle: self.model.get( 'title' ),\n\t\t\t\t\t\tslug: content,\n\t\t\t\t\t},\n\t\t\t\t\tbeforeSend: function() {\n\t\t\t\t\t\tLLMS.Spinner.start( $el.closest( '.llms-editable-toggle-group' ), 'small' );\n\t\t\t\t\t},\n\t\t\t\t\tsuccess: function( r ) {\n\n\t\t\t\t\t\tif ( r.permalink && r.slug ) {\n\t\t\t\t\t\t\tself.model.set( 'permalink', r.permalink );\n\t\t\t\t\t\t\tself.model.set( 'name', r.slug );\n\t\t\t\t\t\t\tself.render();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\t\t\t\t} );\n\n\t\t\t}\n\n\t\t\treturn true;\n\n\t\t},\n\n\t\t/**\n\t\t * Initialize datepicker elements\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tinit_datepickers: function() {\n\n\t\t\tthis.$el.find( '.llms-editable-date input' ).each( function() {\n\n\t\t\t\t$( this ).datetimepicker( {\n\t\t\t\t\tformat: $( this ).attr( 'data-date-format' ) || 'Y-m-d h:i A',\n\t\t\t\t\tdatepicker: ( undefined === $( this ).attr( 'data-date-datepicker' ) ) ? true : ( 'true' == $( this ).attr( 'data-date-datepicker' ) ),\n\t\t\t\t\ttimepicker: ( undefined === $( this ).attr( 'data-date-timepicker' ) ) ? true : ( 'true' == $( this ).attr( 'data-date-timepicker' ) ),\n\t\t\t\t\tonClose: function( current_time, $input ) {\n\t\t\t\t\t\t$input.blur();\n\t\t\t\t\t}\n\t\t\t\t} );\n\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * Initialize elements that allow inline formatting\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinit_formatting_els: function() {\n\n\t\t\tvar self = this;\n\n\t\t\tthis.$el.find( '.llms-input-formatting[data-formatting]' ).each( function() {\n\n\t\t\t\tvar formatting = $( this ).attr( 'data-formatting' ).split( ',' ),\n\t\t\t\t\tattr = $( this ).attr( 'data-attribute' );\n\n\t\t\t\tvar ed = new Quill( this, {\n\t\t\t\t\tmodules: {\n\t\t\t\t\t\ttoolbar: [ formatting ],\n\t\t\t\t\t\tkeyboard: {\n\t\t\t\t\t\t\tbindings: {\n\t\t\t\t\t\t\t\ttab: {\n\t\t\t\t\t\t\t\t\tkey: 9,\n\t\t\t\t\t\t\t\t\thandler: function( range, context ) {\n\t\t\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t13: {\n\t\t\t\t\t\t\t\t\tkey: 13,\n\t\t\t\t\t\t\t\t\thandler: function( range, context ) {\n\t\t\t\t\t\t\t\t\t\ted.root.blur();\n\t\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tplaceholder: $( this ).attr( 'data-placeholder' ),\n\t\t\t\t\ttheme: 'bubble',\n\t\t\t\t} );\n\n\t\t\t\ted.on( 'text-change', function( delta, oldDelta, source ) {\n\t\t\t\t\tself.model.set( attr, self.get_content( $( ed.root ) ) );\n\t\t\t\t} );\n\n\t\t\t\tBackbone.pubSub.trigger( 'formatting-ed-init', ed, $( this ), self );\n\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * Initialize editable select elements\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinit_selects: function() {\n\n\t\t\tthis.$el.find( '.llms-editable-select select' ).llmsSelect2( {\n\t\t\t\twidth: '100%',\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * Blur/focusout function for .llms-editable-title elements\n\t\t * Automatically saves changes if changes have been made\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.6\n\t\t */\n\t\ton_blur: function( event ) {\n\n\t\t\tevent.stopPropagation();\n\n\t\t\tthis.model.set( '_has_focus', false, { silent: true } );\n\n\t\t\tvar self = this,\n\t\t\t\t$el = $( event.target ),\n\t\t\t\tchanged = this.has_changed( event );\n\n\t\t\tif ( changed ) {\n\n\t\t\t\tif ( ! self.is_valid( event ) ) {\n\t\t\t\t\tself.revert_edits( event );\n\t\t\t\t} else {\n\t\t\t\t\tthis.save_edits( event );\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Focus event for editable inputs\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.16.6\n\t\t * @version 3.16.6\n\t\t */\n\t\ton_focus: function( event ) {\n\n\t\t\tevent.stopPropagation();\n\t\t\tthis.model.set( '_has_focus', true, { silent: true } );\n\n\t\t},\n\n\t\t/**\n\t\t * Handle content pasted into contenteditable fields\n\t\t * This will ensure that HTML from RTF editors isn't pasted into the dom\n\t\t * @param obj event js event obj\n\t\t * @return void\n\t\t * @since 3.17.8\n\t\t * @version 3.17.8\n\t\t */\n\t\ton_paste: function( event ) {\n\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\n\t\t\tvar text = ( event.originalEvent || event ).clipboardData.getData( 'text/plain' );\n\t\t\twindow.document.execCommand( 'insertText', false, text );\n\n\t\t},\n\n\t\t/**\n\t\t * Change event for selectables\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\ton_select: function( event ) {\n\n\t\t\tvar $el = $( event.target ),\n\t\t\t\tmulti = ( $el.attr( 'multiple' ) ),\n\t\t\t\tattr = $el.attr( 'name' ),\n\t\t\t\t$selected = $el.find( 'option:selected' ),\n\t\t\t\tval;\n\n\t\t\tif ( multi ) {\n\t\t\t\tval = [];\n\t\t\t\tval = $selected.map( function() {\n\t\t\t\t\treturn this.value;\n\t\t\t\t} ).get();\n\t\t\t} else {\n\t\t\t\tval = $selected[0].value;\n\t\t\t}\n\n\t\t\tthis.model.set( attr, val );\n\n\t\t},\n\n\t\t/**\n\t\t * Change event for radio element groups\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.17.6\n\t\t * @version 3.17.6\n\t\t */\n\t\ton_radio_select: function( event ) {\n\n\t\t\tvar $el = $( event.target ),\n\t\t\t\tattr = $el.attr( 'name' ),\n\t\t\t\tval = $el.val();\n\n\t\t\tthis.model.set( attr, val );\n\n\t\t},\n\n\t\t/**\n\t\t * Keydown function for .llms-editable-title elements\n\t\t * Blurs\n\t\t * @param {obj} event js event object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.17.8\n\t\t */\n\t\ton_keydown: function( event ) {\n\n\t\t\tevent.stopPropagation();\n\n\t\t\tvar self = this,\n\t\t\t\tkey = event.which || event.keyCode,\n\t\t\t\tshift = event.shiftKey;\n\t\t\t\t// ctrl = event.metaKey || event.ctrlKey;\n\n\t\t\tswitch ( key ) {\n\n\t\t\t\tcase 13: // enter\n\t\t\t\t\t// shift + enter should add a return\n\t\t\t\t\tif ( ! shift ) {\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\tevent.target.blur();\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t\tcase 27: // escape\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tthis.revert_edits( event );\n\t\t\t\t\tevent.target.blur();\n\t\t\t\tbreak;\n\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Open the WP media lib\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.6\n\t\t */\n\t\topen_media_lib: function( event ) {\n\n\t\t\tevent.stopPropagation();\n\n\t\t\tvar self = this,\n\t\t\t\t$el = $( event.currentTarget );\n\n\t\t\tif ( self.media_lib ) {\n\n\t\t\t\tself.media_lib.uploader.uploader.param( 'post_id' );\n\n\t\t\t} else {\n\n\t\t\t\tself.media_lib = wp.media.frames.file_frame = wp.media( {\n\t\t\t\t\ttitle: LLMS.l10n.translate( 'Select an image' ),\n\t\t\t\t\tbutton: {\n\t\t\t\t\t\ttext: LLMS.l10n.translate( 'Use this image' ),\n\t\t\t\t\t},\n\t\t\t\t\tmultiple: false\t// Set to true to allow multiple files to be selected\n\t\t\t\t} );\n\n\t\t\t\tself.media_lib.on( 'select', function() {\n\n\t\t\t\t\tvar size = $el.attr( 'data-image-size' ),\n\t\t\t\t\t\tattachment = self.media_lib.state().get( 'selection' ).first().toJSON(),\n\t\t\t\t\t\timage = self.model.get( $el.attr( 'data-attribute' ) ),\n\t\t\t\t\t\turl;\n\n\t\t\t\t\tif ( size && attachment.sizes[ size ] ) {\n\t\t\t\t\t\turl = attachment.sizes[ size ].url;\n\t\t\t\t\t} else {\n\t\t\t\t\t\turl = attachment.url;\n\t\t\t\t\t}\n\n\t\t\t\t\timage.set( {\n\t\t\t\t\t\tid: attachment.id,\n\t\t\t\t\t\tsrc: url,\n\t\t\t\t\t} );\n\n\t\t\t\t} );\n\n\t\t\t}\n\n\t\t\tself.media_lib.open();\n\n\n\t\t},\n\n\t\t/**\n\t\t * Click event to remove an image\n\t\t * @param obj event js event obj\n\t\t * @return voids\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tremove_image: function( event ) {\n\n\t\t\tevent.preventDefault();\n\n\t\t\tthis.model.get( $( event.currentTarget ).attr( 'data-attribute' ) ).set( {\n\t\t\t\tid: '',\n\t\t\t\tsrc: '',\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * Helper to undo changes\n\t\t * Bound to \"escape\" key via on_keydwon function\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trevert_edits: function( event ) {\n\t\t\tvar $el = $( event.target ),\n\t\t\t\tval = $el.attr( 'data-original-content' );\n\t\t\t$el.html( val );\n\t\t},\n\n\t\t/**\n\t\t * Sync chages to the model and DB\n\t\t * @param {obj} event js event object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tsave_edits: function( event ) {\n\n\t\t\tvar $el = $( event.target ),\n\t\t\t\tval = this.get_content( $el );\n\n\t\t\tthis.model.set( $el.attr( 'data-attribute' ), val );\n\n\t\t},\n\n\t\t/**\n\t\t * Change event for a switch element\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.17.0\n\t\t */\n\t\ttoggle_switch: function( event ) {\n\n\t\t\tevent.stopPropagation();\n\t\t\tvar $el = $( event.target ),\n\t\t\t\tattr = $el.attr( 'name' ),\n\t\t\t\trerender = $el.attr( 'data-rerender' ),\n\t\t\t\tval;\n\n\t\t\tif ( $el.is( ':checked' ) ) {\n\t\t\t\tval = $el.attr( 'data-on' ) ? $el.attr( 'data-on' ) : 'yes';\n\t\t\t} else {\n\t\t\t\tval = $el.attr( 'data-off' ) ? $el.attr( 'data-off' ) : 'no';\n\t\t\t}\n\n\t\t\tif ( -1 !== attr.indexOf( '.' ) ) {\n\n\t\t\t\tvar split = attr.split( '.' );\n\n\t\t\t\tif ( 'parent' === split[0] ) {\n\t\t\t\t\tthis.model.get_parent().set( split[1], val );\n\t\t\t\t} else {\n\t\t\t\t\tthis.model.get( split[0] ).set( split[1], val );\n\t\t\t\t}\n\n\n\t\t\t} else {\n\n\t\t\t\tthis.model.set( attr, val );\n\n\t\t\t}\n\n\t\t\tthis.trigger( attr.replace( '.', '-' ) + '_toggle', val );\n\n\t\t\tif ( ! rerender || 'yes' === rerender ) {\n\t\t\t\tvar self = this;\n\t\t\t\tsetTimeout( function() {\n\t\t\t\t\tself.render();\n\t\t\t\t}, 100 );\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Initializes a WP Editor on a textarea\n\t\t * @param string id CSS ID of the editor (don't include #)\n\t\t * @param obj settings optional object of settings to pass to wp.editor.initialize()\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinit_editor: function( id, settings ) {\n\n\t\t\tsettings = settings || {};\n\n\t\t\twp.editor.remove( id );\n\n\t\t\twp.editor.initialize( id, $.extend( true, wp.editor.getDefaultSettings(), {\n\t\t\t\tmediaButtons: true,\n\t\t\t\ttinymce: {\n\t\t\t\t\ttoolbar1: 'bold,italic,strikethrough,bullist,numlist,blockquote,hr,alignleft,aligncenter,alignright,link,unlink,wp_adv',\n\t\t\t\t\ttoolbar2: 'formatselect,underline,alignjustify,forecolor,pastetext,removeformat,charmap,outdent,indent,undo,redo,wp_help',\n\t\t\t\t\tsetup: _.bind( this.on_editor_ready, this ),\n\t\t\t\t}\n\t\t\t}, settings ) );\n\n\t\t},\n\n\t\t/**\n\t\t * Setup a permalink editor to allow editing of a permalink\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.16.6\n\t\t * @version 3.16.6\n\t\t */\n\t\tmake_slug_editable: function( event ) {\n\n\t\t\tvar self = this,\n\t\t\t\t$btn = $( event.currentTarget ),\n\t\t\t\t$link = $btn.prevAll( 'a' ),\n\t\t\t\t$input = $btn.prev( 'input.permalink' ),\n\t\t\t\tfull_url = $link.attr( 'href' ),\n\t\t\t\tslug = $input.val(),\n\t\t\t\tshort_url = full_url.replace( slug, '' );\n\n\t\t\t// hide the button\n\t\t\t$btn.hide();\n\n\t\t\t// make the link not clickable\n\t\t\t$link.css( {\n\t\t\t\tcolor: '#999',\n\t\t\t\t'pointer-events': 'none',\n\t\t\t\t'text-decoration': 'none',\n\t\t\t} );\n\n\t\t\t// remove the current slug & trailing slash from the URL\n\t\t\t$link.text( short_url.substring( 0, short_url.length - 1 ) );\n\n\t\t\t// focus in on the field\n\t\t\t$input.show().focus();\n\n\t\t},\n\n\t\t/**\n\t\t * Callback function called after initialization of an editor\n\t\t * Updates UI if a label is present\n\t\t * Binds a change event to ensure editor changes are saved to the model\n\t\t * @param obj editor wp.editor instance\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.17.1\n\t\t */\n\t\ton_editor_ready: function( editor ) {\n\n\t\t\tvar self = this,\n\t\t\t\t$ed = $( '#' + editor.id ),\n\t\t\t\t$parent = $ed.closest( '.llms-editable-editor' ),\n\t\t\t\t$label = $parent.find( '.llms-label' ),\n\t\t\t\tprop = $ed.attr( 'data-attribute' )\n\n\t\t\tif ( $label.length ) {\n\t\t\t\t$label.prependTo( $parent.find( '.wp-editor-tools' ) );\n\t\t\t}\n\n\t\t\t// save changes to the model via Visual ed\n\t\t\teditor.on( 'change', function( event ) {\n\t\t\t\tself.model.set( prop, wp.editor.getContent( editor.id ) );\n\t\t\t} );\n\n\t\t\t// save changes via Text ed\n\t\t\t$ed.on( 'input', function( event ) {\n\t\t\t\tself.model.set( prop, $ed.val() );\n\t\t\t} );\n\n\t\t\t// trigger an input on the Text ed when quicktags buttons are clicked\n\t\t\t$parent.on( 'click', '.quicktags-toolbar .ed_button', function() {\n\t\t\t\tsetTimeout( function() {\n\t\t\t\t\t$ed.trigger( 'input' );\n\t\t\t\t}, 10 );\n\t\t\t} );\n\n\t\t},\n\n\t\t_validate_url: function( str ) {\n\n\t\t\tvar a = document.createElement( 'a' );\n\t\t\ta.href = str;\n\t\t\treturn ( a.host && a.host !== window.location.host );\n\n\t\t}\n\n\t};\n\n} );\n\n","/**\n * _receive override for Backbone.CollectionView core\n * enables connection with jQuery UI draggable buttons\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Views/_Receivable',[], function() {\n\n\treturn {\n\n\t\t/**\n\t\t * Overloads the function from Backbone.CollectionView core because it doesn't properly handle\n\t\t * receieves from a jQuery UI draggable object\n\t\t * @param obj event js event object\n\t\t * @param obj ui jQuery UI object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\t_receive : function( event, ui ) {\n\n\t\t\t// came from sidebar drag\n\t\t\tif ( ui.sender.hasClass( 'ui-draggable' ) ) {\n\t\t\t\tvar index = this._getContainerEl().children().index( ui.helper );\n\t\t\t\tui.helper.remove(); // remove the helper\n\t\t\t\tthis.collection.add( {}, { at: index } );\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar senderListEl = ui.sender;\n\t\t\tvar senderCollectionListView = senderListEl.data( 'view' );\n\t\t\tif( ! senderCollectionListView || ! senderCollectionListView.collection ) return;\n\n\t\t\tvar newIndex = this._getContainerEl().children().index( ui.item );\n\t\t\tvar modelReceived = senderCollectionListView.collection.get( ui.item.attr( 'data-model-cid' ) );\n\t\t\tsenderCollectionListView.collection.remove( modelReceived );\n\t\t\tthis.collection.add( modelReceived, { at : newIndex } );\n\t\t\tmodelReceived.collection = this.collection; // otherwise will not get properly set, since modelReceived.collection might already have a value.\n\t\t\tthis.setSelectedModel( modelReceived );\n\t\t},\n\n\t}\n\n} );\n\n\n","/**\n * Shiftable view mixin function\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Views/_Shiftable',[], function() {\n\n\treturn {\n\n\t\t/**\n\t\t * Conditionally hide action buttons based on section position in collection\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tmaybe_hide_shiftable_buttons: function() {\n\n\t\t\tif ( ! this.model.collection ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar type = this.model.get( 'type' );\n\n\t\t\tif ( this.model.collection.first() === this.model ) {\n\t\t\t\tthis.$el.find( '.shift-up--' + type ).hide();\n\t\t\t} else if ( this.model.collection.last() === this.model ) {\n\t\t\t\tthis.$el.find( '.shift-down--' + type ).hide();\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Move an item in a collection from one position to another\n\t\t * @param int old_index current (old) index within the collection\n\t\t * @param int new_index desired (new) index within the collection\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tshift: function( old_index, new_index ) {\n\n\t\t\tvar collection = this.model.collection;\n\n\t\t\tcollection.remove( this.model );\n\t\t\tcollection.add( this.model, { at: new_index } );\n\t\t\tcollection.trigger( 'reorder' );\n\n\t\t},\n\n\t\t/**\n\t\t * Move an item down the tree one position\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tshift_down: function( e ) {\n\n\t\t\te.preventDefault();\n\t\t\tvar index = this.model.collection.indexOf( this.model );\n\t\t\tthis.shift( index, index + 1 );\n\n\t\t},\n\n\t\t/**\n\t\t * Move an item up the tree one position\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tshift_up: function( e ) {\n\n\t\t\te.preventDefault();\n\t\t\tvar index = this.model.collection.indexOf( this.model );\n\t\t\tthis.shift( index, index - 1 );\n\n\t\t},\n\n\t};\n\n} );\n\n","/**\n * Subview utility mixin\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Views/_Subview',[], function() {\n\n\treturn {\n\n\t\tsubscriptions: {},\n\n\t\t/**\n\t\t * Name of the current subview\n\t\t * @type {String}\n\t\t */\n\t\tstate: '',\n\n\t\t/**\n\t\t * Object of subview data\n\t\t * @type {Object}\n\t\t */\n\t\tviews: {},\n\n\t\t/**\n\t\t * Retrieve a subview by name from this.views\n\t\t * @param string name name of the subview\n\t\t * @return obl|false\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tget_subview: function( name ) {\n\n\t\t\tif ( this.views[ name ] ) {\n\t\t\t\treturn this.views[ name ];\n\t\t\t}\n\n\t\t\treturn false;\n\n\t\t},\n\n\t\tevents_subscribe: function( events ) {\n\n\t\t\t_.each( events, function( func, event ) {\n\n\t\t\t\tthis.subscriptions[ event ] = func;\n\t\t\t\tBackbone.pubSub.on( event, func, this );\n\n\t\t\t}, this );\n\n\t\t},\n\n\t\tevents_unsubscribe: function() {\n\n\t\t\t_.each( this.subscriptions, function( func, event ) {\n\n\t\t\t\tBackbone.pubSub.off( event, func, this );\n\t\t\t\tdelete this.subscriptions[ event ];\n\n\t\t\t}, this );\n\n\t\t},\n\n\t\t/**\n\t\t * Remove a single subview (and all it's subviews) by name\n\t\t * @param string name name of the subview\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tremove_subview: function( name ) {\n\n\t\t\tvar view = this.get_subview( name );\n\n\t\t\tif ( ! view ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( view.instance ) {\n\n\t\t\t\t// remove the subviews if the view has subviews\n\t\t\t\tif ( ! _.isEmpty( view.instance.views ) ) {\n\t\t\t\t\tview.instance.events_unsubscribe();\n\t\t\t\t\tview.instance.remove_subviews();\n\t\t\t\t}\n\n\t\t\t\tview.instance.off();\n\t\t\t\tview.instance.off( null, null, null );\n\t\t\t\tview.instance.remove();\n\t\t\t\tview.instance.undelegateEvents();\n\n\t\t\t\t// _.each( view.instance, function( val, key ) {\n\t\t\t\t// \tdelete view.instance[ key ];\n\t\t\t\t// } );\n\n\t\t\t\tview.instance = null;\n\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Remove all subviews (and all the subviews of those subviews)\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tremove_subviews: function() {\n\n\t\t\t_.each( this.views, function( data, name ) {\n\n\t\t\t\tthis.remove_subview( name );\n\n\t\t\t}, this );\n\n\t\t},\n\n\t\t/**\n\t\t * Render subviews based on current state\n\t\t * @param obj view_data additional data to pass to the subviews\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender_subviews: function( view_data ) {\n\n\t\t\tview_data = view_data || {};\n\n\t\t\t_.each( this.views, function( data, name ) {\n\n\t\t\t\tif ( this.state === data.state ) {\n\n\t\t\t\t\tthis.render_subview( name, view_data );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tthis.remove_subview( name );\n\n\t\t\t\t}\n\n\t\t\t}, this );\n\n\t\t},\n\n\t\t/**\n\t\t * Render a single subview by name\n\t\t * @param string name name of the subview\n\t\t * @param obj view_data additional data to pass to the subview initializer\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender_subview: function( name, view_data ) {\n\n\t\t\tvar view = this.get_subview( name );\n\n\t\t\tif ( ! view ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis.remove_subview( name );\n\n\t\t\tif ( ! view.instance ) {\n\t\t\t\tview.instance = new view.class( view_data );\n\t\t\t}\n\n\t\t\tview.instance.render();\n\n\t\t},\n\n\t\t/**\n\t\t * Set the current subview\n\t\t * Must call render after!\n\t\t * @param string state name of the state [builder|editor]\n\t\t * @return obj this for chaining\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tset_state: function ( state ) {\n\n\t\t\tthis.state = state;\n\t\t\treturn this;\n\n\t\t},\n\n\t}\n\n} );\n\n","/**\n * Trashable model\n * @type {Object}\n * @since 3.16.12\n * @version 3.16.12\n */\ndefine( 'Views/_Trashable',[], function() {\n\n\treturn {\n\n\t\t/**\n\t\t * DOM Events\n\t\t * @type {Object}\n\t\t * @since 3.16.12\n\t\t * @version 3.16.12\n\t\t */\n\t\tevents: {\n\t\t\t'click a[href=\"#llms-trash-model\"]': 'trash_model',\n\t\t},\n\n\t\t/**\n\t\t * Remove a model from it's parent and delete it\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.16.12\n\t\t * @version 3.16.12\n\t\t */\n\t\ttrash_model: function( event ) {\n\n\t\t\tif ( event ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tevent.stopPropagation();\n\t\t\t}\n\n\t\t\tvar msg = LLMS.l10n.replace( 'Are you sure you want to move this %s to the trash?', {\n\t\t\t\t'%s': this.model.get_l10n_type(),\n\t\t\t} );\n\n\t\t\tif ( window.confirm( msg ) ) {\n\n\t\t\t\tif ( this.model.collection ) {\n\t\t\t\t\tthis.model.collection.remove( this.model );\n\t\t\t\t}\n\n\t\t\t\t// publish event\n\t\t\t\tBackbone.pubSub.trigger( 'model-trashed', this.model );\n\n\t\t\t\t// trigger local event so extending views can run other actions where necessary\n\t\t\t\tthis.trigger( 'model-trashed', this.model );\n\n\t\t\t}\n\n\t\t},\n\n\t}\n\n} );\n\n","/**\n * Load view mixins\n * @return obj\n * @since 3.17.1\n * @version 3.17.1\n */\ndefine( 'Views/_loader',[\n\t\t'Views/_Detachable',\n\t\t'Views/_Editable',\n\t\t'Views/_Receivable',\n\t\t'Views/_Shiftable',\n\t\t'Views/_Subview',\n\t\t'Views/_Trashable'\n\t],\n\tfunction(\n\t\tDetachable,\n\t\tEditable,\n\t\tReceivable,\n\t\tShiftable,\n\t\tSubview,\n\t\tTrashable\n\t) {\n\n\treturn {\n\t\tDetachable: Detachable,\n\t\tEditable: Editable,\n\t\tReceivable: Receivable,\n\t\tShiftable: Shiftable,\n\t\tSubview: Subview,\n\t\tTrashable: Trashable,\n\t};\n\n} );\n\n","/**\n * Constructor functions for constructing models, views, and collections\n * @since 3.16.0\n * @version 3.17.1\n */\ndefine( 'Controllers/Construct',[\n\t\t'Collections/loader',\n\t\t'Models/loader',\n\t\t'Views/_loader'\n\t], function(\n\t\tCollections,\n\t\tModels,\n\t\tViews\n\t) {\n\n\treturn function() {\n\n\t\t/**\n\t\t * Internal getter\n\t\t * Constructs new Collections, Models, and Views\n\t\t * @param obj type type of object to construct [Collection,Model,View]\n\t\t * @param string name name of the object to construct\n\t\t * @param obj data object data to pass into the object's constructor\n\t\t * @param obj options object options to pass into the constructor\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tfunction get( type, name, data, options ) {\n\n\t\t\tif ( ! type[ name ] ) {\n\t\t\t\tconsole.log( '\"' + name + '\" not found.' );\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\treturn new type[ name ]( data, options );\n\n\t\t}\n\n\t\t/**\n\t\t * Instantiate a collection\n\t\t * @param string name Collection class name (EG: \"Sections\")\n\t\t * @param array data Array of model objects to pass to the constructor\n\t\t * @param obj options Object of options to pass to the constructor\n\t\t * @return obj\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tthis.get_collection = function( name, data, options ) {\n\n\t\t\treturn get( Collections, name, data, options );\n\n\t\t};\n\n\t\t/**\n\t\t * Instantiate a model\n\t\t * @param string name Model class name (EG: \"Section\")\n\t\t * @param obj data Object of model attributes to pass to the constructor\n\t\t * @param obj options Object of options to pass to the constructor\n\t\t * @return obj\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tthis.get_model = function( name, data, options ) {\n\n\t\t\treturn get( Models, name, data, options );\n\n\t\t};\n\n\t\t/**\n\t\t * Let 3rd parties extend a view using any of the mixin (_) views\n\t\t * @param {obj} view base object used for the view\n\t\t * @param... {string} extends any number of strings that should be mixed into the view\n\t\t * @return obj\n\t\t * @since 3.17.1\n\t\t * @version 3.17.1\n\t\t */\n\t\tthis.extend_view = function() {\n\n\t\t\tvar view = arguments[0],\n\t\t\t\ti = 1;\n\n\t\t\twhile ( arguments[ i ] ) {\n\n\t\t\t\tvar classname = arguments[ i ];\n\t\t\t\tif ( Views[ classname ] ) {\n\n\t\t\t\t\tif ( view.events && Views[ classname ].events ) {\n\t\t\t\t\t\tview.events = _.defaults( view.events, Views[ classname ].events );\n\t\t\t\t\t}\n\n\t\t\t\t\tview = _.defaults( view, Views[ classname ] );\n\n\t\t\t\t}\n\n\t\t\t\ti++;\n\t\t\t}\n\n\t\t\treturn Backbone.View.extend( view );\n\n\t\t};\n\n\t\t/**\n\t\t * Allows custom collection registration by extending the default BackBone collection\n\t\t * @param string name model name\n\t\t * @param obj props properties to extend the collection with\n\t\t * @return void\n\t\t * @since 3.17.1\n\t\t * @version 3.17.1\n\t\t */\n\t\tthis.register_collection = function( name, props ) {\n\n\t\t\tCollections[ name ] = Backbone.Collection.extend( props );\n\n\t\t};\n\n\t\t/**\n\t\t * Allows custom model registration by extending the default abstract model\n\t\t * @param string name model name\n\t\t * @param obj props properties to extend the abstract model with\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tthis.register_model = function( name, props ) {\n\n\t\t\tModels[ name ] = Models['Abstract'].extend( props );\n\n\t\t};\n\n\t\treturn this;\n\n\t};\n\n} );\n\n","/**\n * LifterLMS Builder Debugging suite\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Controllers/Debug',[], function() {\n\n \treturn function( settings ) {\n\n \t\tvar self = this,\n \t\t\tenabled = settings.enabled || false;\n\n\t\t/**\n\t\t * Disable debugging\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n \t\tthis.disable = function() {\n\n \t\t\tself.log( 'LifterLMS Builder debugging disabled' );\n \t\t\tenabled = false;\n\n \t\t};\n\n\t\t/**\n\t\t * Enable debugging\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n \t\tthis.enable = function() {\n\n \t\t\tenabled = true;\n \t\t\tself.log( 'LifterLMS Builder debugging enabled' );\n\n \t\t};\n\n \t\t/**\n \t\t * General logging function\n \t\t * Logs to the js console only if logging is enabled\n \t\t * @return void\n \t\t * @since 3.16.0\n \t\t * @version 3.16.0\n \t\t */\n \t\tthis.log = function() {\n\n\t\t\tif ( ! enabled ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t_.each( arguments, function( data ) {\n\t\t\t\tconsole.log( data );\n\t\t\t} );\n\n \t\t};\n\n \t\t/**\n \t\t * Toggles current state of the logger on or off\n \t\t * @return void\n \t\t * @since 3.16.0\n \t\t * @version 3.16.0\n \t\t */\n \t\tthis.toggle = function() {\n\n\t\t\tif ( enabled ) {\n\t\t\t\tself.disable();\n\t\t\t} else {\n\t\t\t\tself.enable();\n\t\t\t}\n\n \t\t};\n\n \t\t// on startup, log a message if logging is enabled\n \t\tif ( enabled ) {\n \t\t\tself.enable();\n \t\t}\n\n \t}\n\n } );\n\n","/**\n * Model schema functions\n * @since 3.17.0\n * @version 3.17.0\n */\ndefine( 'Controllers/Schemas',[], function() {\n\n\t/**\n\t * Main Schemas class\n\t * @param obj schemas schemas definitions initialized via PHP filters\n\t * @return obj\n\t * @since 3.17.0\n\t * @version 3.17.0\n\t */\n\treturn function( schemas ) {\n\n\t\t// initialize any custom schemas defined via PHP\n\t\tvar custom_schemas = schemas;\n\t\t_.each( custom_schemas, function( type ) {\n\t\t\t_.each( type, function( schema ) {\n\t\t\t\tschema.custom = true;\n\t\t\t} );\n\t\t} );\n\n\t\t/**\n\t\t * Retrieve a schema for a given model by type\n\t\t * Extends default schemas definitions with custom 3rd party definitions\n\t\t * @param obj schema default schema definition from the model (or empty object if none defined)\n\t\t * @param string model_type the model type ('lesson', 'quiz', etc)\n\t\t * @param obj model Instance of the Backbone.Model for the given model\n\t\t * @return obj\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tthis.get = function( schema, model_type, model ) {\n\n\t\t\t// extend the default schema with custom php schemas for the type if they exist\n\t\t\tif ( custom_schemas[ model_type ] ) {\n\t\t\t\tschema = _.extend( schema, custom_schemas[ model_type ] );\n\t\t\t}\n\n\t\t\treturn schema;\n\n\t\t};\n\n\t\treturn this;\n\n\t};\n\n} );\n\n","/**\n * Sync builder data to the server\n * @since 3.16.0\n * @version 3.17.1\n */\ndefine( 'Controllers/Sync',[], function() {\n\n \treturn function( Course, settings ) {\n\n \t\tthis.saving = false;\n\n \t\tvar self = this,\n \t\t\tautosave = true,\n \t\t\tcheck_interval = null,\n \t\t\tcheck_interval_ms = settings.check_interval_ms || 10000,\n \t\t\tdetached = new Backbone.Collection(),\n \t\t\ttrashed = new Backbone.Collection();\n\n\t\t/**\n\t\t * init\n\t\t * @return void\n\t\t * @since 3.16.7\n\t\t * @version 3.16.7\n\t\t */\n \t\tfunction init() {\n\n \t\t\t// determine if autosaving is possible\n \t\t\tif ( 'undefined' === typeof wp.heartbeat ) {\n\n \t\t\t\twindow.llms_builder.debug.log( 'WordPress Heartbeat disabled. Autosaving is disabled!' );\n \t\t\t\tautosave = false;\n\n \t\t\t}\n\n\t\t\t// setup the check interval\n\t\t\tif ( check_interval_ms ) {\n\t\t\t\tself.set_check_interval( check_interval_ms );\n\t\t\t}\n\n\t\t\t// warn when users attempt to leave the page\n\t\t\t$( window ).on( 'beforeunload', function() {\n\n\t\t\t\tif ( self.has_unsaved_changes() ) {\n\t\t\t\t\tcheck_for_changes();\n\t\t\t\t\treturn 'Are you sure you want to abandon your changes?';\n\t\t\t\t}\n\n\t\t\t} );\n\n \t\t};\n\n \t\t/*\n \t\t\t /$$ /$$ /$$ /$$\n \t\t\t|__/ | $$ | $$ |__/\n \t\t\t /$$ /$$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$$ /$$$$$$ | $$ /$$$$$$ /$$$$$$ /$$\n \t\t\t| $$| $$__ $$|_ $$_/ /$$__ $$ /$$__ $$| $$__ $$ |____ $$| $$ |____ $$ /$$__ $$| $$\n \t\t\t| $$| $$ \\ $$ | $$ | $$$$$$$$| $$ \\__/| $$ \\ $$ /$$$$$$$| $$ /$$$$$$$| $$ \\ $$| $$\n \t\t\t| $$| $$ | $$ | $$ /$$| $$_____/| $$ | $$ | $$ /$$__ $$| $$ /$$__ $$| $$ | $$| $$\n \t\t\t| $$| $$ | $$ | $$$$/| $$$$$$$| $$ | $$ | $$| $$$$$$$| $$ | $$$$$$$| $$$$$$$/| $$\n \t\t\t|__/|__/ |__/ \\___/ \\_______/|__/ |__/ |__/ \\_______/|__/ \\_______/| $$____/ |__/\n \t\t\t | $$\n \t\t\t | $$\n \t\t\t |__/\n \t\t*/\n\n \t\t/**\n \t\t * Adds error message(s) to the data object returned by heartbeat-tick\n \t\t * @param obj data llms_builder data object from heartbeat-tick\n \t\t * @param string|array err error messages array or string\n \t\t * @return obj\n \t\t * @since 3.16.0\n \t\t * @version 3.16.0\n \t\t */\n\t\tfunction add_error_msg( data, err ) {\n\n\t\t\tif ( 'success' === data.status ) {\n\t\t\t\tdata.message = [];\n\t\t\t}\n\n\t\t\tdata.status = 'error';\n\t\t\tif ( 'string' === typeof err ) {\n\t\t\t\terr = [ err ];\n\t\t\t}\n\t\t\tdata.message = data.message.concat( err );\n\n\t\t\treturn data;\n\n\t\t};\n\n\t\t/**\n\t\t * Publish sync status so other areas of the application can see what's happening here\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tfunction check_for_changes() {\n\n\t\t\tvar data = {};\n\t\t\tdata.changes = self.get_unsaved_changes();\n\t\t\tdata.has_unsaved_changes = self.has_unsaved_changes( data.changes );\n\t\t\tdata.saving = self.saving;\n\n\t\t\twindow.llms_builder.debug.log( '==== start changes check ====', data, '==== finish changes check ====' );\n\n\t\t\tBackbone.pubSub.trigger( 'current-save-status', data );\n\n\t\t};\n\n\t\t/**\n\t\t * Manually Save data via Admin AJAX when the heartbeat API has been disabled\n\t\t * @return void\n\t\t * @since 3.16.7\n\t\t * @version 3.16.7\n\t\t */\n\t\tfunction do_ajax_save() {\n\n\t\t\t// prevent simultaneous saves\n\t\t\tif ( self.saving ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar changes = self.get_unsaved_changes();\n\n\t\t\t// only send data if we have data to send\n\t\t\tif ( self.has_unsaved_changes( changes ) ) {\n\n\t\t\t\tchanges.id = Course.get( 'id' );\n\n\t\t\t\tLLMS.Ajax.call( {\n\t\t\t\t\tdata: {\n\t\t\t\t\t\taction: 'llms_builder',\n\t\t\t\t\t\taction_type: 'ajax_save',\n\t\t\t\t\t\tcourse_id: changes.id,\n\t\t\t\t\t\tllms_builder: JSON.stringify( changes ),\n\t\t\t\t\t},\n\t\t\t\t\tbeforeSend: function() {\n\n\t\t\t\t\t\twindow.llms_builder.debug.log( '==== start do_ajax_save before ====', changes, '==== finish do_ajax_save before ====' );\n\n\t\t\t\t\t\tself.saving = true;\n\n\t\t\t\t\t\tBackbone.pubSub.trigger( 'heartbeat-send', self );\n\n\t\t\t\t\t},\n\t\t\t\t\terror: function( xhr, status, error ) {\n\n\t\t\t\t\t\twindow.llms_builder.debug.log( '==== start do_ajax_save error ====', data, '==== finish do_ajax_save error ====' );\n\n\t\t\t\t\t\tself.saving = false;\n\n\t\t\t\t\t\tBackbone.pubSub.trigger( 'heartbeat-tick', self, {\n\t\t\t\t\t\t\tstatus: 'error',\n\t\t\t\t\t\t\tmessage: xhr.responseText + ' (' + error + ' ' + status +')',\n\t\t\t\t\t\t} );\n\n\t\t\t\t\t},\n\t\t\t\t\tsuccess: function( res ) {\n\n\t\t\t\t\t\tif ( ! res.llms_builder ) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\twindow.llms_builder.debug.log( '==== start do_ajax_save success ====', res, '==== finish do_ajax_save success ====' );\n\n\t\t\t\t\t\tres.llms_builder = process_removals( res.llms_builder );\n\t\t\t\t\t\tres.llms_builder = process_updates( res.llms_builder );\n\n\t\t\t\t\t\tself.saving = false;\n\n\t\t\t\t\t\tBackbone.pubSub.trigger( 'heartbeat-tick', self, res.llms_builder );\n\n\t\t\t\t\t}\n\n\t\t\t\t} );\n\n\t\t\t}\n\n\n\t\t};\n\n\t\t/**\n\t\t * Retrieve all the attributes changed on a model since the last sync\n\t\t *\n\t\t * For a new model (a model with a temp ID) or a model where _forceSync has been defined ALL atts will be returned\n\t\t * For an existing model (without a temp ID) only retrieves changed attributes as tracked by Backbone.TrackIt\n\t\t *\n\t\t * This function excludes any attributes defined as child attributes via the models relationship settings\n\t\t *\n\t\t * @param obj model instance of a Backbone.Model\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.6\n\t\t */\n\t\tfunction get_changed_attributes( model ) {\n\n\t\t\tvar atts = {},\n\t\t\t\tsync_type;\n\n\t\t\t// don't save mid editing\n\t\t\tif ( model.get( '_has_focus' ) ) {\n\t\t\t\treturn atts;\n\t\t\t}\n\n\t\t\t// model hasn't been persisted to the database to get a real ID yet\n\t\t\t// send *all* of it's atts\n\t\t\tif ( has_temp_id( model ) || true === model.get( '_forceSync' ) ) {\n\n\t\t\t\tatts = _.clone( model.attributes );\n\t\t\t\tsync_type = 'full';\n\n\t\t\t// only send the changed atts\n\t\t\t} else {\n\n\t\t\t\tatts = model.unsavedAttributes();\n\t\t\t\tsync_type = 'partial';\n\n\t\t\t}\n\n\t\t\tvar exclude = ( model.get_relationships ) ? model.get_child_props() : [];\n\t\t\tatts = _.omit( atts, function( val, key ) {\n\n\t\t\t\t// exclude keys that start with an underscore which are used by the\n\t\t\t\t// application but don't need to be stored in the database\n\t\t\t\tif ( 0 === key.indexOf( '_' ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t} else if ( -1 !== exclude.indexOf( key ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\treturn false;\n\n\t\t\t} );\n\n\t\t\tif ( model.before_save ) {\n\t\t\t\tatts = model.before_save( atts, sync_type );\n\t\t\t}\n\n\t\t\treturn atts;\n\n\t\t};\n\n\t\t/**\n\t\t * Get all the changes to an object (either a Model or a Collection of models)\n\t\t * Returns only changes to models and the IDs of that model (should changes exist)\n\t\t * Uses get_changed_attributes() to determine if all atts or only changed atts are needed\n\t\t * Processes children intelligently to only return changed children rather than the entire collection of children\n\t\t *\n\t\t * @param obj object instance of a Backbone.Model or Backbone.Collection\n\t\t * @return obj|array\t \t\tif object is a model, returns an object\n\t\t * \tif object is a collection, returns an array of objects\n\t\t * @since 3.16.0\n\t\t * @version 3.16.11\n\t\t */\n\t\tfunction get_changes_to_object( object ) {\n\n\t\t\tvar changed_atts;\n\n\t\t\tif ( object instanceof Backbone.Model ) {\n\n\t\t\t\tchanged_atts = get_changed_attributes( object );\n\n\t\t\t\tif ( object.get_relationships ) {\n\n\t\t\t\t\t_.each( object.get_child_props(), function( prop ) {\n\n\t\t\t\t\t\tvar children = get_changes_to_object( object.get( prop ) );\n\t\t\t\t\t\tif ( ! _.isEmpty( children ) ) {\n\t\t\t\t\t\t\tchanged_atts[ prop ] = children;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} );\n\n\t\t\t\t}\n\n\t\t\t\t// if we have any data, add the id to the model\n\t\t\t\tif ( ! _.isEmpty( changed_atts ) ) {\n\t\t\t\t\tchanged_atts.id = object.get( 'id' );\n\t\t\t\t}\n\n\t\t\t} else if ( object instanceof Backbone.Collection ) {\n\n\t\t\t\tchanged_atts = [];\n\t\t\t\tobject.each( function( model ) {\n\t\t\t\t\tvar model_changes = get_changes_to_object( model );\n\t\t\t\t\tif ( ! _.isEmpty( model_changes ) ) {\n\t\t\t\t\t\tchanged_atts.push( model_changes );\n\t\t\t\t\t}\n\t\t\t\t} );\n\n\t\t\t}\n\n\t\t\treturn changed_atts;\n\n\t\t};\n\n\t\t/**\n\t\t * Determines if a model has a temporary ID or a real persisted ID\n\t\t * @param obj model instance of a model\n\t\t * @return boolean\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tfunction has_temp_id( model ) {\n\n\t\t\treturn ( ! _.isNumber( model.id ) && 0 === model.id.indexOf( 'temp_' ) );\n\n\t\t};\n\n\t\t/**\n\t\t * Compares changes synced to the server against current model and restarts\n\t\t * tracking on elements that haven't changed since the last sync\n\t\t * @param obj model instance of a Backbone.Model\n\t\t * @param obj data data set that was processed by the server\n\t\t * @return void\n\t\t * @since 3.16.11\n\t\t * @version 3.16.6\n\t\t */\n\t\tfunction maybe_restart_tracking( model, data ) {\n\n\t\t\tBackbone.pubSub.trigger( model.get( 'type' ) + '-maybe-restart-tracking', model, data );\n\n\t\t\tvar omit = [ 'id', 'orig_id' ];\n\n\t\t\tif ( model.get_relationships ) {\n\t\t\t\tomit.concat( model.get_child_props() );\n\t\t\t}\n\n\t\t\t_.each( _.omit( data, omit ), function( val, prop ) {\n\n\t\t\t\tif ( _.isEqual( model.get( prop ), val ) ) {\n\t\t\t\t\tdelete model._unsavedChanges[ prop ];\n\t\t\t\t\tmodel._originalAttrs[ prop ] = val;\n\t\t\t\t}\n\n\t\t\t} );\n\n\t\t\t// if syncing was forced, allow tracking to move forward as normal moving forward\n\t\t\tmodel.unset( '_forceSync' );\n\n\t\t};\n\n\t\t/**\n\t\t * Processes response data from heartbeat-tick related to trashing & detaching models\n\t\t * On success, removes from local removal collection\n\t\t * On error, appends error messages to the data object returned to UI for on-screen feedback\n\t\t * @param obj data data.llms_builder object from heartbeat-tick response\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.17.1\n\t\t */\n\t\tfunction process_removals( data ) {\n\n\t\t\t// check removals for errors\n\t\t\tvar removals = {\n\t\t\t\tdetach: detached,\n\t\t\t\ttrash: trashed,\n\t\t\t};\n\n\t\t\t_.each( removals, function( coll, key ) {\n\n\t\t\t\tif ( data[ key ] ) {\n\n\t\t\t\t\tvar errors = [];\n\n\t\t\t\t\t_.each( data[ key ] , function( info ) {\n\n\t\t\t\t\t\t// succesfully detached, remove it from the detached collection\n\t\t\t\t\t\tif ( ! info.error ) {\n\n\t\t\t\t\t\t\tcoll.remove( info.id );\n\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\terrors.push( info.error );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} );\n\n\t\t\t\t\tif ( errors.length ) {\n\t\t\t\t\t\t_.extend( data, add_error_msg( data, errors ) );\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t} );\n\n\t\t\treturn data;\n\t\t}\n\n\t\t/**\n\t\t * Processes response data from heartbeat-tick related to creating / updating a single object\n\t\t * Handles both collections and models as a recursive function\n\t\t * @param {[type]} data [description]\n\t\t * @param {[type]} type [description]\n\t\t * @param {[type]} parent [description]\n\t\t * @param {[type]} main_data [description]\n\t\t * @return {[type]}\n\t\t * @since 3.16.0\n\t\t * @version 3.16.11\n\t\t */\n\t\tfunction process_object_updates( data, type, parent, main_data ) {\n\n\t\t\tif ( ! data[ type ] ) {\n\t\t\t\treturn data;\n\t\t\t}\n\n\t\t\tif ( parent.get( type ) instanceof Backbone.Model ) {\n\n\t\t\t\tvar info = data[ type ];\n\n\t\t\t\tif ( info.error ) {\n\n\t\t\t\t\t_.extend( main_data, add_error_msg( main_data, info.error ) );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tvar model = parent.get( type );\n\n\t\t\t\t\t// update temp ids with the real id\n\t\t\t\t\tif ( info.id != info.orig_id ) {\n\t\t\t\t\t\tmodel.set( 'id', info.id );\n\t\t\t\t\t\tdelete model._unsavedChanges.id;\n\t\t\t\t\t}\n\t\t\t\t\tmaybe_restart_tracking( model, info );\n\n\t\t\t\t\t// check children\n\t\t\t\t\tif ( model.get_relationships ) {\n\n\t\t\t\t\t\t_.each( model.get_child_props(), function( child_key ) {\n\t\t\t\t\t\t\t_.extend( data[ type ], process_object_updates( data[ type ], child_key, model, main_data ) );\n\t\t\t\t\t\t} );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t} else if ( parent.get( type ) instanceof Backbone.Collection ) {\n\n\t\t\t\t_.each( data[ type ], function( info, index ) {\n\n\t\t\t\t\tif ( info.error ) {\n\n\t\t\t\t\t\t_.extend( main_data, add_error_msg( main_data, info.error ) );\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tvar model = parent.get( type ).get( info.orig_id );\n\n\t\t\t\t\t\t// update temp ids with the real id\n\t\t\t\t\t\tif ( info.id != info.orig_id ) {\n\t\t\t\t\t\t\tmodel.set( 'id', info.id );\n\t\t\t\t\t\t\tdelete model._unsavedChanges.id;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmaybe_restart_tracking( model, info );\n\n\t\t\t\t\t\t// check children\n\t\t\t\t\t\tif ( model.get_relationships ) {\n\n\t\t\t\t\t\t\t_.each( model.get_child_props(), function( child_key ) {\n\t\t\t\t\t\t\t\t_.extend( data[ type ], process_object_updates( data[ type ][ index ], child_key, model, main_data ) );\n\t\t\t\t\t\t\t} );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t} );\n\n\t\t\t}\n\n\t\t\treturn main_data;\n\n\t\t};\n\n\t\t/**\n\t\t * Processes response data from heartbeat-tick related to updating & creating new models\n\t\t * On success, removes from local removal collection\n\t\t * On error, appends error messages to the data object returned to UI for on-screen feedback\n\t\t * @param obj data data.llms_builder object from heartbeat-tick response\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tfunction process_updates( data ) {\n\n\t\t\t// only mess with updates data\n\t\t\tif ( ! data.updates ) {\n\t\t\t\treturn data;\n\t\t\t}\n\n\t\t\tif ( data.updates ) {\n\t\t\t\tdata = process_object_updates( data.updates, 'sections', Course, data );\n\t\t\t}\n\n\t\t\treturn data;\n\n\t\t};\n\n\t\t/*\n\t\t\t /$$ /$$ /$$ /$$\n\t\t\t | $$ | $$|__/ |__/\n\t\t\t /$$$$$$ /$$ /$$| $$$$$$$ | $$ /$$ /$$$$$$$ /$$$$$$ /$$$$$$ /$$\n\t\t\t /$$__ $$| $$ | $$| $$__ $$| $$| $$ /$$_____/ |____ $$ /$$__ $$| $$\n\t\t\t| $$ \\ $$| $$ | $$| $$ \\ $$| $$| $$| $$ /$$$$$$$| $$ \\ $$| $$\n\t\t\t| $$ | $$| $$ | $$| $$ | $$| $$| $$| $$ /$$__ $$| $$ | $$| $$\n\t\t\t| $$$$$$$/| $$$$$$/| $$$$$$$/| $$| $$| $$$$$$$ | $$$$$$$| $$$$$$$/| $$\n\t\t\t| $$____/ \\______/ |_______/ |__/|__/ \\_______/ \\_______/| $$____/ |__/\n\t\t\t| $$ | $$\n\t\t\t| $$ | $$\n\t\t\t|__/ |__/\n\t\t*/\n\n\t\t/**\n\t\t * Retrieve all unsaved changes for the builder instance\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.17.1\n\t\t */\n\t\tthis.get_unsaved_changes = function() {\n\n\t\t\treturn {\n\t\t\t\tdetach: detached.pluck( 'id' ),\n\t\t\t\ttrash: trashed.pluck( 'id' ),\n\t\t\t\tupdates: get_changes_to_object( Course ),\n\n\t\t\t}\n\t\t};\n\n\t\t/**\n\t\t * Check if the builder instance has unsaved changes\n\t\t * @param obj changes optionally pass in an object from the return of this.get_unsaved_changes()\n\t\t * save some resources by not running the check twice during heartbeats\n\t\t * @return boolean\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tthis.has_unsaved_changes = function( changes ) {\n\n\t\t\tif ( 'undefined' === typeof changes ) {\n\t\t\t\tchanges = self.get_unsaved_changes();\n\t\t\t}\n\n\t\t\t// check all possible keys, once we find one with content we have some changes to persist\n\t\t\tvar found = _.find( changes, function( data ) {\n\n\t\t\t\treturn ( false === _.isEmpty( data ) );\n\n\t\t\t} );\n\n\t\t\treturn found ? true : false;\n\n\t\t};\n\n\t\t/**\n\t\t * Save changes right now.\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.7\n\t\t */\n\t\tthis.save_now = function() {\n\t\t\tif ( autosave ) {\n\t\t\t\twp.heartbeat.connectNow();\n\t\t\t} else {\n\t\t\t\tdo_ajax_save();\n\t\t\t}\n\t\t};\n\n\t\t/**\n\t\t * Update the interval that checks for changes to the builder instance\n\t\t * @param int ms time (in milliseconds) to run the check on\n\t\t * pass 0 to disable the check\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tthis.set_check_interval = function( ms ) {\n\t\t\tcheck_interval_ms = ms;\n\t\t\tif ( check_interval ) {\n\t\t\t\tclearInterval( check_interval );\n\t\t\t}\n\t\t\tif ( check_interval_ms ) {\n\t\t\t\tcheck_interval = setInterval( check_for_changes, check_interval_ms );\n\t\t\t}\n\t\t};\n\n\t\t/*\n\t\t\t /$$ /$$ /$$\n\t\t\t| $$|__/ | $$\n\t\t\t| $$ /$$ /$$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$$\n\t\t\t| $$| $$ /$$_____/|_ $$_/ /$$__ $$| $$__ $$ /$$__ $$ /$$__ $$ /$$_____/\n\t\t\t| $$| $$| $$$$$$ | $$ | $$$$$$$$| $$ \\ $$| $$$$$$$$| $$ \\__/| $$$$$$\n\t\t\t| $$| $$ \\____ $$ | $$ /$$| $$_____/| $$ | $$| $$_____/| $$ \\____ $$\n\t\t\t| $$| $$ /$$$$$$$/ | $$$$/| $$$$$$$| $$ | $$| $$$$$$$| $$ /$$$$$$$/\n\t\t\t|__/|__/|_______/ \\___/ \\_______/|__/ |__/ \\_______/|__/ |_______/\n\t\t*/\n\n\t\t/**\n\t\t * Listen for detached models and send them to the server for persistence\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tBackbone.pubSub.on( 'model-detached', function( model ) {\n\n\t\t\t// detached models with temp ids haven't been persisted so we don't care\n\t\t\tif ( has_temp_id( model ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tdetached.add( _.clone( model.attributes ) );\n\n\t\t} );\n\n\t\t/**\n\t\t * Listen for trashed models and send them to the server for deletion\n\t\t * @since 3.16.0\n\t\t * @version 3.17.1\n\t\t */\n\t\tBackbone.pubSub.on( 'model-trashed', function( model ) {\n\n\t\t\t// if the model has a temp ID we don't have to persist the deletion\n\t\t\tif ( has_temp_id( model ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar data = _.clone( model.attributes );\n\n\t\t\tif ( model.get_trash_id ) {\n\t\t\t\tdata.id = model.get_trash_id();\n\t\t\t}\n\n\t\t\ttrashed.add( data );\n\n\t\t} );\n\n\t\t/*\n\t\t\t /$$ /$$ /$$ /$$\n\t\t\t| $$ | $$ | $$ | $$\n\t\t\t| $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ | $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$\n\t\t\t| $$__ $$ /$$__ $$ |____ $$ /$$__ $$|_ $$_/ | $$__ $$ /$$__ $$ |____ $$|_ $$_/\n\t\t\t| $$ \\ $$| $$$$$$$$ /$$$$$$$| $$ \\__/ | $$ | $$ \\ $$| $$$$$$$$ /$$$$$$$ | $$\n\t\t\t| $$ | $$| $$_____/ /$$__ $$| $$ | $$ /$$| $$ | $$| $$_____/ /$$__ $$ | $$ /$$\n\t\t\t| $$ | $$| $$$$$$$| $$$$$$$| $$ | $$$$/| $$$$$$$/| $$$$$$$| $$$$$$$ | $$$$/\n\t\t\t|__/ |__/ \\_______/ \\_______/|__/ \\___/ |_______/ \\_______/ \\_______/ \\___/\n\t\t*/\n\n\t\t/**\n\t\t * Add data to the WP heartbeat to persist new models, changes, and deletions to the DB\n\t\t * @since 3.16.0\n\t\t * @version 3.16.7\n\t\t */\n\t\t$( document ).on( 'heartbeat-send', function( event, data ) {\n\n\t\t\t// prevent simultaneous saves\n\t\t\tif ( self.saving ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar changes = self.get_unsaved_changes();\n\n\t\t\t// only send data if we have data to send\n\t\t\tif ( self.has_unsaved_changes( changes ) ) {\n\n\t\t\t\tchanges.id = Course.get( 'id' );\n\t\t\t\tself.saving = true;\n\t\t\t\tdata.llms_builder = JSON.stringify( changes );\n\n\t\t\t}\n\n\t\t\twindow.llms_builder.debug.log( '==== start heartbeat-send ====', data, '==== finish heartbeat-send ====' );\n\n\t\t\tBackbone.pubSub.trigger( 'heartbeat-send', self );\n\n\t\t} );\n\n\t\t/**\n\t\t * Confirm detachments & deletions and replace temp IDs with new persisted IDs\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\t$( document ).on( 'heartbeat-tick', function( event, data ) {\n\n\t\t\tif ( ! data.llms_builder ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\twindow.llms_builder.debug.log( '==== start heartbeat-tick ====', data, '==== finish heartbeat-tick ====' );\n\n\t\t\tdata.llms_builder = process_removals( data.llms_builder );\n\t\t\tdata.llms_builder = process_updates( data.llms_builder );\n\n\t\t\tself.saving = false;\n\n\t\t\tBackbone.pubSub.trigger( 'heartbeat-tick', self, data.llms_builder );\n\n\t\t} );\n\n\t\t/**\n\t\t * On heartbeat errors publish an error to the main builder application\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\t$( document ).on( 'heartbeat-error', function( event, data ) {\n\n\t\t\twindow.llms_builder.debug.log( '==== start heartbeat-error ====', data, '==== finish heartbeat-error ====' );\n\n\t\t\tself.saving = false;\n\n\t\t\tBackbone.pubSub.trigger( 'heartbeat-tick', self, {\n\t\t\t\tstatus: 'error',\n\t\t\t\tmessage: data.responseText + ' (' + data.status + ' ' + data.statusText +')',\n\t\t\t} );\n\n\t\t} );\n\n\t\t/*\n\t\t\t /$$ /$$ /$$\n\t\t\t|__/ |__/ | $$\n\t\t\t /$$ /$$$$$$$ /$$ /$$$$$$\n\t\t\t| $$| $$__ $$| $$|_ $$_/\n\t\t\t| $$| $$ \\ $$| $$ | $$\n\t\t\t| $$| $$ | $$| $$ | $$ /$$\n\t\t\t| $$| $$ | $$| $$ | $$$$/\n\t\t\t|__/|__/ |__/|__/ \\___/\n\t\t*/\n\t\tinit();\n\n\t\treturn this;\n\n\t};\n\n} );\n\n","/**\n * Single Lesson View\n * @since 3.16.0\n * @version 3.17.0\n */\ndefine( 'Views/Lesson',[\n\t\t'Views/_Detachable',\n\t\t'Views/_Editable',\n\t\t'Views/_Shiftable',\n\t\t'Views/_Trashable'\n\t], function(\n\t\tDetachable,\n\t\tEditable,\n\t\tShiftable,\n\t\tTrashable\n\t) {\n\n\treturn Backbone.View.extend( _.defaults( {\n\n\t\t/**\n\t\t * Get default attributes for the html wrapper element\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tattributes: function() {\n\t\t\treturn {\n\t\t\t\t'data-id': this.model.id,\n\t\t\t\t'data-section-id': this.model.get( 'parent_section' ),\n\t\t\t};\n\t\t},\n\n\t\t/**\n\t\t * HTML class names\n\t\t * @type {String}\n\t\t */\n\t\tclassName: 'llms-builder-item llms-lesson',\n\n\t\t/**\n\t\t * Events\n\t\t * @type {Object}\n\t\t * @since 3.16.0\n\t\t * @version 3.16.12\n\t\t */\n\t\tevents: _.defaults( {\n\t\t\t'click .edit-lesson': 'open_lesson_editor',\n\t\t\t'click .edit-quiz': 'open_quiz_editor',\n\t\t\t'click .edit-assignment': 'open_assignment_editor',\n\t\t\t'click .section-prev': 'section_prev',\n\t\t\t'click .section-next': 'section_next',\n\t\t\t'click .shift-up--lesson': 'shift_up',\n\t\t\t'click .shift-down--lesson': 'shift_down',\n\t\t}, Detachable.events, Editable.events, Trashable.events ),\n\n\t\t/**\n\t\t * HTML element wrapper ID attribute\n\t\t * @return string\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tid: function() {\n\t\t\treturn 'llms-lesson-' + this.model.id;\n\t\t},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'li',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-lesson-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.14.1\n\t\t * @version 3.14.1\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\tthis.render();\n\n\t\t\tthis.listenTo( this.model, 'change', this.render );\n\n\t\t\tBackbone.pubSub.on( 'lesson-selected', this.on_select, this );\n\t\t\tBackbone.pubSub.on( 'new-lesson-added', this.on_select, this );\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender: function() {\n\n\t\t\tthis.$el.html( this.template( this.model ) );\n\t\t\tthis.maybe_hide_shiftable_buttons();\n\t\t\tif ( this.model.get( '_selected' ) ) {\n\t\t\t\tthis.$el.addClass( 'selected' );\n\t\t\t} else {\n\t\t\t\tthis.$el.removeClass( 'selected' );\n\t\t\t}\n\t\t\treturn this;\n\n\t\t},\n\n\t\t/**\n\t\t * Click event for the assignment editor action icon\n\t\t * Opens sidebar to the assignment editor tab\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\topen_assignment_editor: function() {\n\n\t\t\tBackbone.pubSub.trigger( 'lesson-selected', this.model, 'assignment' );\n\t\t\tthis.model.set( '_selected', true );\n\n\t\t},\n\n\t\t/**\n\t\t * Click event for lesson settings action icon\n\t\t * Opens sidebar to the lesson editor tab\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\topen_lesson_editor: function() {\n\n\t\t\tBackbone.pubSub.trigger( 'lesson-selected', this.model, 'lesson' );\n\t\t\tthis.model.set( '_selected', true );\n\n\t\t},\n\n\t\t/**\n\t\t * Click event for the quiz editor action icon\n\t\t * Opens sidebar to the quiz editor tab\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\topen_quiz_editor: function() {\n\n\t\t\tBackbone.pubSub.trigger( 'lesson-selected', this.model, 'quiz' );\n\t\t\tthis.model.set( '_selected', true );\n\n\t\t},\n\n\t\t/**\n\t\t * When a lesson is selected mark it as selected in the hidden prop\n\t\t * Allows views to re-render and reflect current state properly\n\t\t * @param obj model lesson model that's been selected\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\ton_select: function( model ) {\n\n\t\t\tif ( this.model.id !== model.id ) {\n\t\t\t\tthis.model.set( '_selected', false );\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Click event for the \"Next Section\" button\n\t\t * @param obj event js event obj\n\t\t * @return void\n\t\t * @since 3.16.11\n\t\t * @version 3.16.11\n\t\t */\n\t\tsection_next: function( event ) {\n\t\t\tevent.preventDefault();\n\t\t\tthis._move_to_section( 'next' );\n\t\t},\n\n\t\t/**\n\t\t * Click event for the \"Previous Section\" button\n\t\t * @param obj event js event obj\n\t\t * @return void\n\t\t * @since 3.16.11\n\t\t * @version 3.16.11\n\t\t */\n\t\tsection_prev: function( event ) {\n\t\t\tevent.preventDefault();\n\t\t\tthis._move_to_section( 'prev' );\n\t\t},\n\n\t\t/**\n\t\t * Move the lesson into a new section\n\t\t * @param string direction direction [prev|next]\n\t\t * @return void\n\t\t * @since 3.16.11\n\t\t * @version 3.16.11\n\t\t */\n\t\t_move_to_section: function( direction ) {\n\n\t\t\tvar from_coll = this.model.collection,\n\t\t\t\tto_section;\n\n\t\t\tif ( 'next' === direction ) {\n\t\t\t\tto_section = from_coll.parent.get_next();\n\t\t\t} else if ( 'prev' === direction ) {\n\t\t\t\tto_section = from_coll.parent.get_prev();\n\t\t\t}\n\n\t\t\tif ( to_section ) {\n\n\t\t\t\tfrom_coll.remove( this.model );\n\t\t\t\tto_section.add_lesson( this.model );\n\t\t\t\tto_section.set( '_expanded', true );\n\n\t\t\t}\n\n\t\t},\n\n\t}, Detachable, Editable, Shiftable, Trashable ) );\n\n} );\n\n","/**\n * Single Section View\n * @since 3.13.0\n * @version 3.16.0\n */\ndefine( 'Views/LessonList',[ 'Views/Lesson', 'Views/_Receivable' ], function( LessonView, Receivable ) {\n\n\treturn Backbone.CollectionView.extend( _.defaults( {\n\n\t\tclassName: 'llms-lessons',\n\n\t\t/**\n\t\t * Section model\n\t\t * @type {[type]}\n\t\t */\n\t\tmodelView: LessonView,\n\n\t\t/**\n\t\t * Are sections selectable?\n\t\t * @type {Bool}\n\t\t */\n\t\tselectable: false,\n\n\t\t/**\n\t\t * Are sections sortable?\n\t\t * @type {Bool}\n\t\t */\n\t\tsortable: true,\n\n\t\tsortableOptions: {\n\t\t\taxis: false,\n\t\t\tconnectWith: '.llms-lessons',\n\t\t\tcursor: 'move',\n\t\t\thandle: '.drag-lesson',\n\t\t\titems: '.llms-lesson',\n\t\t\tplaceholder: 'llms-lesson llms-sortable-placeholder',\n\t\t},\n\n\t\tsortable_start: function( collection ) {\n\t\t\t$( '.llms-lessons' ).addClass( 'dragging' );\n\t\t},\n\n\t\tsortable_stop: function( collection ) {\n\t\t\t$( '.llms-lessons' ).removeClass( 'dragging' );\n\t\t},\n\n\t\t/**\n\t\t * Overloads the function from Backbone.CollectionView core because it doesn't send stop events\n\t\t * if moving from one sortable to another... :-(\n\t\t * @param obj event js event object\n\t\t * @param obj ui jQuery UI object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\t_sortStop : function( event, ui ) {\n\n\t\t\tvar modelBeingSorted = this.collection.get( ui.item.attr( 'data-model-cid' ) ),\n\t\t\t\tmodelViewContainerEl = this._getContainerEl(),\n\t\t\t\tnewIndex = modelViewContainerEl.children().index( ui.item );\n\n\t\t\tif ( newIndex == -1 && modelBeingSorted ) {\n\t\t\t\tthis.collection.remove( modelBeingSorted );\n\t\t\t}\n\n\t\t\tthis._reorderCollectionBasedOnHTML();\n\t\t\tthis.updateDependentControls();\n\n\t\t\tif( this._isBackboneCourierAvailable() ) {\n\t\t\t\tthis.spawn( 'sortStop', { modelBeingSorted : modelBeingSorted, newIndex : newIndex } );\n\t\t\t} else {\n\t\t\t\tthis.trigger( 'sortStop', modelBeingSorted, newIndex );\n\t\t\t}\n\n\t\t},\n\n\t}, Receivable ) );\n\n} );\n\n","/**\n * Single Section View\n * @since 3.13.0\n * @version 3.16.12\n */\ndefine( 'Views/Section',[\n\t\t'Views/LessonList',\n\t\t'Views/_Editable',\n\t\t'Views/_Shiftable',\n\t\t'Views/_Trashable'\n\t], function(\n\t\tLessonListView,\n\t\tEditable,\n\t\tShiftable,\n\t\tTrashable\n\t) {\n\n\treturn Backbone.View.extend( _.defaults( {\n\n\t\t/**\n\t\t * Get default attributes for the html wrapper element\n\t\t * @return obj\n\t\t * @since 3.13.0\n\t\t * @version 3.13.0\n\t\t */\n\t\tattributes: function() {\n\t\t\treturn {\n\t\t\t\t'data-id': this.model.id,\n\t\t\t};\n\t\t},\n\n\t\t/**\n\t\t * Element classnames\n\t\t * @type {String}\n\t\t */\n\t\tclassName: 'llms-builder-item llms-section',\n\n\t\t/**\n\t\t * Events\n\t\t * @type {Object}\n\t\t * @since 3.16.0\n\t\t * @version 3.16.12\n\t\t */\n\t\tevents: _.defaults( {\n\n\t\t\t'click': 'select',\n\t\t\t'click .expand': 'expand',\n\t\t\t'click .collapse': 'collapse',\n\t\t\t'click .shift-up--section': 'shift_up',\n\t\t\t'click .shift-down--section': 'shift_down',\n\n\t\t\t'mouseenter .llms-lessons': 'on_mouseenter',\n\n\t\t}, Editable.events, Trashable.events ),\n\n\t\t/**\n\t\t * HTML element wrapper ID attribute\n\t\t * @return string\n\t\t * @since 3.13.0\n\t\t * @version 3.13.0\n\t\t */\n\t\tid: function() {\n\t\t\treturn 'llms-section-' + this.model.id;\n\t\t},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'li',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-section-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.13.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\tthis.render();\n\t\t\tthis.listenTo( this.model, 'change', this.render );\n\t\t\tthis.listenTo( this.model, 'change:_expanded', this.toggle_expanded );\n\t\t\tthis.lessonListView.collection.on( 'add', this.on_lesson_add, this );\n\n\t\t\tthis.dragTimeout = null;\n\n\t\t\tBackbone.pubSub.on( 'expand-all', this.expand, this );\n\t\t\tBackbone.pubSub.on( 'collapse-all', this.collapse, this );\n\n\t\t},\n\n\t\t/**\n\t\t * Render the section\n\t\t * Initalizes a new collection and views for all lessons in the section\n\t\t * @return void\n\t\t * @since 3.13.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender: function() {\n\n\t\t\tthis.$el.html( this.template( this.model.toJSON() ) );\n\n\t\t\tthis.maybe_hide_shiftable_buttons();\n\n\t\t\tthis.lessonListView = new LessonListView( {\n\t\t\t\tel: this.$el.find( '.llms-lessons' ),\n\t\t\t\tcollection: this.model.get( 'lessons' ),\n\t\t\t} );\n\t\t\tthis.lessonListView.render();\n\t\t\tthis.lessonListView.on( 'sortStart', this.lessonListView.sortable_start );\n\t\t\tthis.lessonListView.on( 'sortStop', this.lessonListView.sortable_stop );\n\n\t\t\t// selection changes\n\t\t\tthis.lessonListView.on( 'selectionChanged', this.active_lesson_change, this );\n\n\t\t\tthis.maybe_hide_trash_button();\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\tactive_lesson_change: function( current, previous ) {\n\n\t\t\tBackbone.pubSub.trigger( 'active-lesson-change', {\n\t\t\t\tcurrent: current,\n\t\t\t\tprevious: previous,\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * Collapse lessons within the section\n\t\t * @param obj event js event object\n\t\t * @param bool update if true, updates the model to reflect the new state\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tcollapse: function( event, update ) {\n\n\t\t\tif ( 'undefined' === typeof update ) {\n\t\t\t\tupdate = true;\n\t\t\t}\n\n\t\t\tif ( event ) {\n\t\t\t\tevent.stopPropagation();\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\n\t\t\tthis.$el.removeClass( 'expanded' ).find( '.drag-expanded' ).removeClass( 'drag-expanded' );\n\t\t\tif ( update ) {\n\t\t\t\tthis.model.set( '_expanded', false );\n\t\t\t}\n\t\t\tBackbone.pubSub.trigger( 'section-toggle', this.model );\n\n\t\t},\n\n\t\t/**\n\t\t * Expand lessons within the section\n\t\t * @param obj event js event object\n\t\t * @param bool update if true, updates the model to reflect the new state\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\texpand: function( event, update ) {\n\n\t\t\tif ( 'undefined' === typeof update ) {\n\t\t\t\tupdate = true;\n\t\t\t}\n\n\t\t\tif ( event ) {\n\t\t\t\tevent.stopPropagation();\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\n\t\t\tthis.$el.addClass( 'expanded' );\n\t\t\tif ( update ) {\n\t\t\t\tthis.model.set( '_expanded', true );\n\t\t\t}\n\t\t\tBackbone.pubSub.trigger( 'section-toggle', this.model );\n\n\t\t},\n\n\t\tmaybe_hide_trash_button: function() {\n\n\t\t\tvar $btn = this.$el.find( '.trash--section' );\n\n\t\t\tif ( this.model.get( 'lessons' ).isEmpty() ) {\n\n\t\t\t\t$btn.show();\n\n\t\t\t} else {\n\n\t\t\t\t$btn.hide()\n\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * When a lesson is added to the section trigger a collection reorder & update the lesson's id\n\t\t * @param obj model Lesson model\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\ton_lesson_add: function( model ) {\n\n\t\t\tthis.lessonListView.collection.trigger( 'reorder' );\n\t\t\tmodel.set( 'parent_section', this.model.get( 'id' ) );\n\t\t\tthis.expand();\n\n\t\t},\n\n\t\ton_mouseenter: function( event ) {\n\n\n\t\t\tif ( $( event.target ).hasClass( 'dragging' ) ) {\n\n\t\t\t\t$( '.drag-expanded' ).removeClass( 'drag-expanded' );\n\t\t\t\t$( event.target ).addClass( 'drag-expanded' );\n\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Expand\n\t\t * @param {[type]} model [description]\n\t\t * @param {[type]} value [description]\n\t\t * @return {[type]}\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\ttoggle_expanded: function( model, value ) {\n\n\t\t\tif ( value ) {\n\t\t\t\tthis.expand( null, false );\n\t\t\t} else {\n\t\t\t\tthis.collapse( null, false );\n\t\t\t}\n\n\t\t},\n\n\t}, Editable, Shiftable, Trashable ) );\n\n} );\n\n","/**\n * Single Section View\n * @since 3.13.0\n * @version 3.16.0\n */\ndefine( 'Views/SectionList',[ 'Views/Section', 'Views/_Receivable' ], function( SectionView, Receivable ) {\n\n\treturn Backbone.CollectionView.extend( _.defaults( {\n\n\t\t/**\n\t\t * Parent element\n\t\t * @type {String}\n\t\t */\n\t\tel: '#llms-sections',\n\n\t\tevents : {\n\t\t\t'mousedown > li.llms-section > .llms-builder-header .llms-headline' : '_listItem_onMousedown',\n\t\t\t// 'dblclick > li, tbody > tr > td' : '_listItem_onDoubleClick',\n\t\t\t'click' : '_listBackground_onClick',\n\t\t\t'click ul.collection-view' : '_listBackground_onClick',\n\t\t\t'keydown' : '_onKeydown'\n\t\t},\n\n\t\t/**\n\t\t * Section model\n\t\t * @type {[type]}\n\t\t */\n\t\tmodelView: SectionView,\n\n\t\t/**\n\t\t * Enable keyboard events\n\t\t * @type {Bool}\n\t\t */\n\t\tprocessKeyEvents: false,\n\n\t\t/**\n\t\t * Are sections selectable?\n\t\t * @type {Bool}\n\t\t */\n\t\tselectable: true,\n\n\t\t/**\n\t\t * Are sections sortable?\n\t\t * @type {Bool}\n\t\t */\n\t\tsortable: true,\n\n\t\tsortableOptions: {\n\t\t\taxis: false,\n\t\t\tcursor: 'move',\n\t\t\thandle: '.drag-section',\n\t\t\titems: '.llms-section',\n\t\t\tplaceholder: 'llms-section llms-sortable-placeholder',\n\t\t},\n\n\t\tsortable_start: function( collection ) {\n\t\t\tthis.$el.addClass( 'dragging' );\n\t\t},\n\n\t\tsortable_stop: function( collection ) {\n\t\t\tthis.$el.removeClass( 'dragging' );\n\t\t},\n\n\t}, Receivable ) );\n\n} );\n\n","/**\n * Single Course View\n * @since 3.13.0\n * @version 3.16.0\n */\ndefine( 'Views/Course',[ 'Views/SectionList', 'Views/_Editable' ], function( SectionListView, Editable ) {\n\n\treturn Backbone.View.extend( _.defaults( {\n\n\t\t/**\n\t\t * Get default attributes for the html wrapper element\n\t\t * @return obj\n\t\t * @since 3.13.0\n\t\t * @version 3.13.0\n\t\t */\n\t\tattributes: function() {\n\t\t\treturn {\n\t\t\t\t'data-id': this.model.id,\n\t\t\t};\n\t\t},\n\n\t\t/**\n\t\t * HTML element selector\n\t\t * @type {String}\n\t\t */\n\t\tel: '#llms-builder-main',\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'div',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-course-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.13.0\n\t\t * @version 3.13.0\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\tvar self = this;\n\n\t\t\t// this.listenTo( this.model, 'sync', this.render );\n\t\t\tthis.render();\n\n\t\t\tthis.sectionListView = new SectionListView( {\n\t\t\t\tcollection: this.model.get( 'sections' ),\n\t\t\t} );\n\t\t\tthis.sectionListView.render();\n\t\t\t// drag and drop start\n\t\t\tthis.sectionListView.on( 'sortStart', this.sectionListView.sortable_start );\n\t\t\t// drag and drop stop\n\t\t\tthis.sectionListView.on( 'sortStop', this.sectionListView.sortable_stop );\n\t\t\t// selection changes\n\t\t\tthis.sectionListView.on( 'selectionChanged', this.active_section_change );\n\t\t\t// \"select\" a section when it's added to the course\n\t\t\tthis.listenTo( this.model.get( 'sections'), 'add', this.on_section_add );\n\n\t\t\tBackbone.pubSub.on( 'section-toggle', this.on_section_toggle, this );\n\n\t\t\tBackbone.pubSub.on( 'expand-section', this.expand_section, this );\n\n\t\t\tBackbone.pubSub.on( 'lesson-selected', this.active_lesson_change, this );\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.13.0\n\t\t * @version 3.13.0\n\t\t */\n\t\trender: function() {\n\t\t\tthis.$el.html( this.template( this.model ) );\n\t\t\treturn this;\n\t\t},\n\n\t\tactive_lesson_change: function( model ) {\n\n\t\t\t// set parent section to be active\n\t\t\tvar section = this.model.get( 'sections' ).get( model.get( 'parent_section' ) );\n\t\t\tthis.sectionListView.setSelectedModel( section );\n\n\t\t},\n\n\t\t/**\n\t\t * When a section \"selection\" changes in the list\n\t\t * Update each section model so we can figure out which one is selected from other views\n\t\t * @param array current array of selected models\n\t\t * @param array previous array of previously selected models\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tactive_section_change: function( current, previous ) {\n\n\t\t\t_.each( current, function( model ) {\n\t\t\t\tmodel.set( '_selected', true );\n\t\t\t} );\n\n\t\t\t_.each( previous, function( model ) {\n\t\t\t\tmodel.set( '_selected', false );\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * \"Selects\" the new section when it's added to the course\n\t\t * @param obj model Section model that's just been added\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\ton_section_add: function( model ) {\n\n\t\t\tthis.sectionListView.setSelectedModel( model );\n\n\t\t},\n\n\t\t/**\n\t\t * When expanding/collapsing sections\n\t\t * if collapsing, unselect, if expanding, select\n\t\t * @param obj model toggled section\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\ton_section_toggle: function( model ) {\n\n\t\t\tvar selected = model.get( '_expanded' ) ? [ model ] : [];\n\t\t\tthis.sectionListView.setSelectedModels( selected );\n\n\t\t}\n\n\t}, Editable ) );\n\n} );\n\n","/**\n * Model settings fields view\n * @since 3.17.0\n * @version 3.17.7\n */\ndefine( 'Views/SettingsFields',[], function() {\n\n\treturn Backbone.View.extend( _.defaults( {\n\n\t\t/**\n\t\t * DOM events\n\t\t * @type {Object}\n\t\t */\n\t\tevents: {\n\t\t\t'click .llms-settings-group-toggle': 'toggle_group',\n\t\t},\n\n\t\t/**\n\t\t * Processed fields data\n\t\t * Allows access by ID without traversing the schema\n\t\t * @type {Object}\n\t\t */\n\t\tfields: {},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'div',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-settings-fields-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\t// initialize: function() {},\n\n\t\t/**\n\t\t * Retrieve an array of all editor fields in all groups\n\t\t * @return array\n\t\t * @since 3.17.1\n\t\t * @version 3.17.1\n\t\t */\n\t\tget_editor_fields: function() {\n\t\t\treturn _.filter( this.fields, function( field ) {\n\t\t\t\treturn this.is_editor_field( field.type );\n\t\t\t}, this );\n\t\t},\n\n\t\t/**\n\t\t * Get settings group data from a model\n\t\t * @return {[type]}\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tget_groups: function() {\n\n\t\t\treturn this.model.get_settings_fields();\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if a settings group is hidden in localStorage\n\t\t * @param string group_id id of the group\n\t\t * @return {Boolean}\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tis_group_hidden: function( group_id ) {\n\n\t\t\tvar id = 'llms-' + this.model.get( 'type' ) + '-settings-group--' + group_id;\n\n\t\t\tif ( 'undefined' !== window.localStorage ) {\n\t\t\t\treturn ( 'hidden' === window.localStorage.getItem( id ) );\n\t\t\t}\n\n\t\t\treturn false;\n\n\t\t},\n\n\t\t/**\n\t\t * Get the switch attribute for a field with switches\n\t\t * @param obj field field data obj\n\t\t * @return string\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tget_switch_attribute: function( field ) {\n\n\t\t\treturn field.switch_attribute ? field.switch_attribute : field.attribute;\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if a field has a switch\n\t\t * @param string type field type string\n\t\t * @return {Boolean}\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\thas_switch: function( type ) {\n\t\t\treturn ( -1 !== type.indexOf( 'switch' ) );\n\t\t},\n\n\t\t/**\n\t\t * Determine if a field is a default (text) field\n\t\t * @param string type field type string\n\t\t * @return {Boolean}\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tis_default_field: function( type ) {\n\n\t\t\tvar types = [ 'audio_embed', 'datepicker', 'number', 'text', 'video_embed' ];\n\t\t\treturn ( -1 !== types.indexOf( type.replace( 'switch-', '' ) ) );\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if a field is a WYSIWYG editor field\n\t\t * @param string type field type string\n\t\t * @return {Boolean}\n\t\t * @since 3.17.1\n\t\t * @version 3.17.1\n\t\t */\n\t\tis_editor_field: function( type ) {\n\n\t\t\tvar types = [ 'editor', 'switch-editor' ];\n\t\t\treturn ( -1 !== types.indexOf( type.replace( 'switch-', '' ) ) );\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if a switch is enabled for a field\n\t\t * @param obj field field data object\n\t\t * @return {Boolean}\n\t\t * @since 3.17.0\n\t\t * @version 3.17.6\n\t\t */\n\t\tis_switch_condition_met: function( field ) {\n\n\t\t\treturn ( field.switch_on === this.model.get( field.switch_attribute ) );\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.17.0\n\t\t * @version 3.17.1\n\t\t */\n\t\trender: function() {\n\n\t\t\tthis.$el.html( this.template( this ) );\n\n\t\t\t// if editors exist, render them\n\t\t\t_.each( this.get_editor_fields(), function( field ) {\n\t\t\t\tthis.render_editor( field );\n\t\t\t}, this );\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\t/**\n\t\t * Renders an editor field\n\t\t * @param obj field field data object\n\t\t * @return void\n\t\t * @since 3.17.1\n\t\t * @version 3.17.1\n\t\t */\n\t\trender_editor: function( field ) {\n\n\t\t\tvar self = this;\n\n\t\t\twp.editor.remove( field.id );\n\t\t\tfield.settings.tinymce.setup = function( editor ) {\n\n\t\t\t\tvar $ed = $( '#' + editor.id ),\n\t\t\t\t\t$parent = $ed.closest( '.llms-editable-editor' ),\n\t\t\t\t\t$label = $parent.find( '.llms-label' ),\n\t\t\t\t\tprop = $ed.attr( 'data-attribute' )\n\n\t\t\t\tif ( $label.length ) {\n\t\t\t\t\t$label.prependTo( $parent.find( '.wp-editor-tools' ) );\n\t\t\t\t}\n\n\t\t\t\t// save changes to the model via Visual ed\n\t\t\t\teditor.on( 'change', function( event ) {\n\t\t\t\t\tself.model.set( prop, wp.editor.getContent( editor.id ) );\n\t\t\t\t} );\n\n\t\t\t\t// save changes via Text ed\n\t\t\t\t$ed.on( 'input', function( event ) {\n\t\t\t\t\tself.model.set( prop, $ed.val() );\n\t\t\t\t} );\n\n\t\t\t\t// trigger an input on the Text ed when quicktags buttons are clicked\n\t\t\t\t$parent.on( 'click', '.quicktags-toolbar .ed_button', function() {\n\t\t\t\t\tsetTimeout( function() {\n\t\t\t\t\t\t$ed.trigger( 'input' );\n\t\t\t\t\t}, 10 );\n\t\t\t\t} );\n\t\t\t};\n\n\t\t\twp.editor.initialize( field.id, field.settings );\n\n\t\t},\n\n\t\t/**\n\t\t * Get the HTML for a select field\n\t\t * @param obj options flat or multi-dimensional options object\n\t\t * @param string attribute name of the select field's attribute\n\t\t * @return string\n\t\t * @since 3.17.0\n\t\t * @version 3.17.2\n\t\t */\n\t\trender_select_options: function( options, attribute ) {\n\n\t\t\tvar html = '',\n\t\t\t\tselected = this.model.get( attribute );\n\n\t\t\tfunction option_html( label, val ) {\n\n\t\t\t\treturn '' + label + ' ';\n\n\t\t\t}\n\n\t\t\t_.each( options, function( option, index ) {\n\n\t\t\t\t// this will be an key:val object\n\t\t\t\tif ( 'string' === typeof option ) {\n\t\t\t\t\thtml += option_html( option, index );\n\t\t\t\t// either option group or array of key,val objects\n\t\t\t\t} else if ( 'object' === typeof option ) {\n\t\t\t\t\t// option group\n\t\t\t\t\tif ( option.label && option.options ) {\n\t\t\t\t\t\thtml += '';\n\t\t\t\t\t\thtml += this.render_select_options( option.options, attribute );\n\t\t\t\t\t} else {\n\t\t\t\t\t\thtml += option_html( option.val, option.key );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t}, this );\n\n\t\t\treturn html;\n\n\t\t},\n\n\t\t/**\n\t\t * Setup and fill fields with default data based on field type\n\t\t * @param obj orig_field original field as defined in the settings\n\t\t * @param int field_index index of the field in the current row\n\t\t * @return obj\n\t\t * @since 3.17.0\n\t\t * @version 3.17.7\n\t\t */\n\t\tsetup_field: function( orig_field, field_index ) {\n\n\t\t\tvar defaults = {\n\t\t\t\tclasses: [],\n\t\t\t\tid: _.uniqueId( orig_field.attribute + '_' ),\n\t\t\t\tinput_type: 'text',\n\t\t\t\tlabel: '',\n\t\t\t\toptions: {},\n\t\t\t\tplaceholder: '',\n\t\t\t\ttip: '',\n\t\t\t\ttip_position: 'top-right',\n\t\t\t\tsettings: {},\n\t\t\t};\n\n\t\t\t// check the field condition if set\n\t\t\tif ( orig_field.condition && false === _.bind( orig_field.condition, this.model )() ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tswitch ( orig_field.type ) {\n\n\t\t\t\tcase 'audio_embed':\n\t\t\t\t\tdefaults.classes.push( 'llms-editable-audio' );\n\t\t\t\t\tdefaults.placeholder = 'https://';\n\t\t\t\t\tdefaults.tip = LLMS.l10n.translate( 'Use SoundCloud or Spotify audio URLS.' );\n\t\t\t\t\tdefaults.input_type = 'url';\n\t\t\t\tbreak;\n\n\t\t\t\tcase 'datepicker':\n\t\t\t\t\tdefaults.classes.push( 'llms-editable-date' );\n\t\t\t\tbreak;\n\n\t\t\t\tcase 'editor':\n\t\t\t\tcase 'switch-editor':\n\t\t\t\t\tvar orig_settings = orig_field.settings || {};\n\t\t\t\t\tdefaults.settings = $.extend( true, wp.editor.getDefaultSettings(), {\n\t\t\t\t\t\tmediaButtons: true,\n\t\t\t\t\t\ttinymce: {\n\t\t\t\t\t\t\ttoolbar1: 'bold,italic,strikethrough,bullist,numlist,blockquote,hr,alignleft,aligncenter,alignright,link,unlink,wp_adv',\n\t\t\t\t\t\t\ttoolbar2: 'formatselect,underline,alignjustify,forecolor,pastetext,removeformat,charmap,outdent,indent,undo,redo,wp_help',\n\t\t\t\t\t\t}\n\t\t\t\t\t}, orig_settings );\n\t\t\t\tbreak;\n\n\t\t\t\tcase 'number':\n\t\t\t\t\tdefaults.input_type = 'number';\n\t\t\t\tbreak;\n\n\t\t\t\tcase 'permalink':\n\t\t\t\t\tdefaults.label = LLMS.l10n.translate( 'Permalink' );\n\t\t\t\tbreak;\n\n\t\t\t\tcase 'video_embed':\n\t\t\t\t\tdefaults.classes.push( 'llms-editable-video' );\n\t\t\t\t\tdefaults.placeholder = 'https://';\n\t\t\t\t\tdefaults.tip = LLMS.l10n.translate( 'Use YouTube, Vimeo, or Wistia video URLS.' );\n\t\t\t\t\tdefaults.input_type = 'url';\n\t\t\t\tbreak;\n\n\t\t\t}\n\n\t\t\tif ( this.has_switch( orig_field.type ) ) {\n\t\t\t\tdefaults.switch_on = 'yes';\n\t\t\t\tdefaults.switch_off = 'no';\n\t\t\t}\n\n\t\t\tvar field = _.defaults( _.deepClone( orig_field ), defaults );\n\n\t\t\t// if options is a function run it\n\t\t\tif ( _.isFunction( field.options ) ) {\n\t\t\t\tfield.options = _.bind( field.options, this.model )();\n\t\t\t}\n\n\t\t\t// if it's a radio field options values can be submitted as images\n\t\t\t// this will transform those images into html\n\t\t\tif ( -1 !== [ 'radio', 'switch-radio' ].indexOf( orig_field.type ) ) {\n\n\t\t\t\tvar has_images = false;\n\t\t\t\t_.each( orig_field.options, function( val, key ) {\n\t\t\t\t\tif ( -1 !== val.indexOf( '.png' ) || -1 !== val.indexOf( '.jpg' ) ) {\n\t\t\t\t\t\tfield.options[key] = ' ';\n\t\t\t\t\t\thas_images = true;\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t\tif ( has_images ) {\n\t\t\t\t\tfield.classes.push( 'has-images' );\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t// add tooltip position classes\n\t\t\tif ( field.tip ) {\n\t\t\t\tfield.classes.push( 'tip--' + field.tip_position );\n\t\t\t}\n\n\t\t\t// transform classes array to a css class string\n\t\t\tif ( field.classes.length ) {\n\t\t\t\tfield.classes = ' ' + field.classes.join( ' ' );\n\t\t\t}\n\n\t\t\tthis.fields[ field.id ] = field;\n\n\t\t\treturn field;\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if toggling a switch select should rerender the view\n\t\t * @param string field_type field type string\n\t\t * @return boolean\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tshould_rerender_on_toggle: function( field_type ) {\n\n\t\t\treturn ( -1 !== field_type.indexOf( 'switch-' ) ) ? 'yes' : 'no';\n\n\t\t},\n\n\t\t/**\n\t\t * Click event for toggling visibility of settings groups\n\t\t * If localStorage is available, persist state\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\ttoggle_group: function( event ) {\n\n\t\t\tevent.preventDefault();\n\n\t\t\tvar $el = $( event.currentTarget ),\n\t\t\t\t$group = $el.closest( '.llms-model-settings' );\n\n\t\t\t$group.toggleClass( 'hidden' );\n\n\t\t\tif ( 'undefined' !== window.localStorage ) {\n\n\t\t\t\tvar id = $group.attr( 'id' );\n\t\t\t\tif ( $group.hasClass( 'hidden' ) ) {\n\t\t\t\t\twindow.localStorage.setItem( id, 'hidden' );\n\t\t\t\t} else {\n\t\t\t\t\twindow.localStorage.removeItem( id );\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t},\n\n\t} ) );\n\n} );\n\n","/**\n * Lesson Editor (Sidebar) View\n * @since 3.17.0\n * @version 3.17.0\n */\ndefine( 'Views/LessonEditor',[\n\t\t'Views/_Detachable',\n\t\t'Views/_Editable',\n\t\t'Views/_Trashable',\n\t\t'Views/_Subview',\n\t\t'Views/SettingsFields'\n\t], function(\n\t\tDetachable,\n\t\tEditable,\n\t\tTrashable,\n\t\tSubview,\n\t\tSettingsFields\n\t) {\n\n\treturn Backbone.View.extend( _.defaults( {\n\n\t\t/**\n\t\t * Current view state\n\t\t * @type {String}\n\t\t */\n\t\tstate: 'default',\n\n\t\t/**\n\t\t * Current Subviews\n\t\t * @type {Object}\n\t\t */\n\t\tviews: {\n\t\t\tsettings: {\n\t\t\t\tclass: SettingsFields,\n\t\t\t\tinstance: null,\n\t\t\t\tstate: 'default',\n\t\t\t},\n\t\t},\n\n\t\tel: '#llms-editor-lesson',\n\n\t\t/**\n\t\t * Events\n\t\t * @type {Object}\n\t\t */\n\t\tevents: _.defaults( {}, Detachable.events, Editable.events, Trashable.events ),\n\n\t\t/**\n\t\t * Template function\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-lesson-settings-template' ),\n\n\t\t/**\n\t\t * Init\n\t\t * @param obj data parent template data\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tinitialize: function( data ) {\n\n\t\t\tthis.model = data.lesson;\n\n\t\t\tvar change_events = [\n\t\t\t\t'change:date_available',\n\t\t\t\t'change:drip_method',\n\t\t\t\t'change:time_available',\n\t\t\t];\n\t\t\t_.each( change_events, function( event ) {\n\t\t\t\tthis.listenTo( this.model, event, this.render );\n\t\t\t}, this );\n\n\t\t\t// when the \"has_prerequisite\" attr is toggled ON\n\t\t\t// trigger the prereq select object to set the default (first available) prereq for the lesson\n\t\t\tthis.listenTo( this.model, 'change:has_prerequisite', function( lesson, val ) {\n\t\t\t\tif ( 'yes' === val ) {\n\t\t\t\t\tthis.$el.find( 'select[name=\"prerequisite\"]' ).trigger( 'change' );\n\t\t\t\t}\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * Render the view\n\t\t * @return obj\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\trender: function() {\n\n\t\t\tthis.$el.html( this.template( this.model ) );\n\n\t\t\tthis.remove_subview( 'settings' );\n\n\t\t\tthis.render_subview( 'settings', {\n\t\t\t\tel: '#llms-lesson-settings-fields',\n\t\t\t\tmodel: this.model,\n\t\t\t} );\n\n\t\t\tthis.init_datepickers();\n\t\t\tthis.init_selects();\n\n\t\t\treturn this;\n\n\t\t},\n\n\t}, Detachable, Editable, Trashable, Subview, SettingsFields ) );\n\n} );\n\n","/**\n * Single Quiz View\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Views/Popover',[], function() {\n\n\treturn Backbone.View.extend( {\n\n\t\tdefaults: {\n\t\t\tplacement: 'auto',\n\t\t\t// container: document.body,\n\t\t\twidth: 'auto',\n\t\t\ttrigger: 'manual',\n\t\t\tstyle: 'light',\n\t\t\tanimation: 'pop',\n\t\t\ttitle: '',\n\t\t\tcontent: '',\n\t\t\tcloseable: false,\n\t\t\tbackdrop: false,\n\t\t\tonShow: function( $el ) {},\n\t\t\tonHide: function( $el ) {},\n\t\t},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'div',\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.14.1\n\t\t * @version 3.14.1\n\t\t */\n\t\tinitialize: function( data ) {\n\n\t\t\tif ( this.$el.length ) {\n\t\t\t\tthis.defaults.container = this.$el.parent();\n\t\t\t}\n\n\t\t\tthis.args = _.defaults( data.args, this.defaults );\n\t\t\tthis.render();\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender: function() {\n\n\t\t\tthis.$el.webuiPopover( this.args );\n\t\t\treturn this;\n\n\t\t},\n\n\t\t/**\n\t\t * Hide the popover\n\t\t * @return self (for chaining)\n\t\t * @since 3.16.0\n\t\t * @version 3.16.12\n\t\t */\n\t\thide: function() {\n\n\t\t\tthis.$el.webuiPopover( 'hide' );\n\t\t\treturn this;\n\n\t\t},\n\n\t\t/**\n\t\t * Show the popover\n\t\t * @return self (for chaining)\n\t\t * @since 3.16.0\n\t\t * @version 3.16.12\n\t\t */\n\t\tshow: function() {\n\n\t\t\tthis.$el.webuiPopover( 'show' );\n\t\t\treturn this;\n\n\t\t},\n\n\t} );\n\n} );\n\n","/**\n * Post Popover Serach content View\n * @since 3.16.0\n * @version 3.17.0\n */\ndefine( 'Views/PostSearch',[], function() {\n\n\treturn Backbone.View.extend( {\n\n\t\t/**\n\t\t * DOM Events\n\t\t * @type obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tevents: {\n\t\t\t'select2:select': 'add_post',\n\t\t},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'select',\n\n\t\t/**\n\t\t * Initializer\n\t\t * @param obj data customize the search box with data\n\t\t * @return void\n\t\t * @since 3.16.12\n\t\t * @version 3.16.12\n\t\t */\n\t\tinitialize: function( data ) {\n\n\t\t\tthis.post_type = data.post_type;\n\t\t\tthis.searching_message = data.searching_message || LLMS.l10n.translate( 'Searching...' );\n\n\t\t},\n\n\t\t/**\n\t\t * Select event, adds the existing lesson to the course\n\t\t * @param obj event select2:select event object\n\t\t * @since 3.16.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tadd_post: function( event ) {\n\n\t\t\tvar type = this.$el.attr( 'data-post-type' );\n\n\t\t\tBackbone.pubSub.trigger( type.replace( 'llms_', '' ) + '-search-select', event.params.data, event );\n\t\t\tthis.$el.val( null ).trigger( 'change' );\n\n\t\t},\n\n\t\t/**\n\t\t * Render the section\n\t\t * Initalizes a new collection and views for all lessons in the section\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.12\n\t\t */\n\t\trender: function() {\n\t\t\tvar self = this;\n\t\t\tsetTimeout( function () {\n\t\t\t\tself.$el.llmsSelect2( {\n\t\t\t\t\tajax: {\n\t\t\t\t\t\tdataType: 'JSON',\n\t\t\t\t\t\tdelay: 250,\n\t\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\t\turl: window.ajaxurl,\n\t\t\t\t\t\tdata: function( params ) {\n\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\taction: 'llms_builder',\n\t\t\t\t\t\t\t\taction_type: 'search',\n\t\t\t\t\t\t\t\tcourse_id: window.llms_builder.course.id,\n\t\t\t\t\t\t\t\tpost_type: self.post_type,\n\t\t\t\t\t\t\t\tterm: params.term,\n\t\t\t\t\t\t\t\tpage: params.page,\n\t\t\t\t\t\t\t\t_ajax_nonce: wp_ajax_data.nonce,\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t},\n\t\t\t\t\t\t// error: function( xhr, status, error ) {\n\t\t\t\t\t\t// \tconsole.log( status, error );\n\t\t\t\t\t\t// },\n\t\t\t\t\t},\n\t\t\t\t\tdropdownParent: $( '.wrap.lifterlms.llms-builder' ),\n\t\t\t\t\t// don't escape html from render_result\n\t\t\t\t\tescapeMarkup: function( markup ) {\n\t\t\t\t\t\treturn markup;\n\t\t\t\t\t},\n\t\t\t\t\tplaceholder: self.searching_message,\n\t\t\t\t\ttemplateResult: self.render_result,\n\t\t\t\t\twidth: '100%',\n\t\t\t\t} );\n\t\t\t\tself.$el.attr( 'data-post-type', self.post_type );\n\t\t\t}, 0 );\n\t\t\treturn this;\n\n\t\t},\n\n\t\t/**\n\t\t * Render a nicer UI for each search result in the in the Select2 search results\n\t\t * @param object res result data\n\t\t * @return string\n\t\t * @since 3.16.0\n\t\t * @version 3.16.12\n\t\t */\n\t\trender_result: function( res ) {\n\n\t\t\tvar $html = $( '
' );\n\n\t\t\tif ( res.loading ) {\n\t\t\t\treturn $html.append( res.text );\n\t\t\t}\n\n\t\t\tvar $side = $( '' ),\n\t\t\t\t$main = $( '
' );\n\t\t\t\ticon = ( 'attach' === res.action ) ? 'paperclip' : 'clone',\n\t\t\t\ttext = ( 'attach' === res.action ) ? LLMS.l10n.translate( 'Attach' ) : LLMS.l10n.translate( 'Clone' );\n\n\t\t\t$side.append( '' + text + ' ' );\n\n\t\t\t$main.append( '' + res.data.title + ' ' );\n\t\t\t$main.append( '' + LLMS.l10n.translate( 'ID' ) + ': ' + res.data.id + ' ' );\n\n\t\t\t_.each( res.parents, function( parent ) {\n\t\t\t\t$main.append( '' + parent + ' ' );\n\t\t\t} );\n\n\t\t\treturn $html.append( $side ).append( $main );\n\n\t\t},\n\n\t} );\n\n} );\n\n","/**\n * Single Lesson View\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Views/QuestionType',[ ], function() {\n\n\treturn Backbone.View.extend( {\n\n\t\t/**\n\t\t * HTML class names\n\t\t * @type {String}\n\t\t */\n\t\tclassName: 'llms-question-type',\n\n\t\tevents: {\n\t\t\t'click .llms-add-question': 'add_question',\n\t\t},\n\n\t\t/**\n\t\t * HTML element wrapper ID attribute\n\t\t * @return string\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tid: function() {\n\t\t\treturn 'llms-question-type-' + this.model.id;\n\t\t},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'li',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-question-type-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\tthis.render();\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender: function() {\n\t\t\tthis.$el.html( this.template( this.model ) );\n\t\t\treturn this;\n\t\t},\n\n\t\t/**\n\t\t * Add a question of the selected type to the current quiz\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tadd_question: function() {\n\n\t\t\tthis.quiz.add_question( {\n\t\t\t\t_expanded: true,\n\t\t\t\tchoices: this.model.get( 'default_choices' ) ? this.model.get( 'default_choices' ) : null,\n\t\t\t\tquestion_type: this.model,\n\t\t\t} );\n\n\t\t\tthis.quiz.trigger( 'new-question-added' );\n\n\t\t},\n\n\t\t// filter: function( term ) {\n\n\t\t// \tvar words = this.model.get_keywords().map( function( word ) {\n\t\t// \t\treturn word.toLowerCase();\n\t\t// \t} );\n\n\t\t// \tterm = term.toLowerCase();\n\n\t\t// \tif ( -1 === words.indexOf( term ) ) {\n\t\t// \t\tthis.$el.addClass( 'filtered' );\n\t\t// \t} else {\n\t\t// \t\tthis.$el.removeClass( 'filtered' );\n\t\t// \t}\n\n\t\t// },\n\n\t\t// clear_filter: function() {\n\t\t// \tthis.$el.removeClass( 'filtered' );\n\t\t// }\n\n\t} );\n\n} );\n\n","/**\n * Quiz question bank view\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Views/QuestionBank',[ 'Views/QuestionType' ], function( QuestionView ) {\n\n\treturn Backbone.CollectionView.extend( {\n\n\t\tclassName: 'llms-question',\n\n\t\t/**\n\t\t * Parent element\n\t\t * @type {String}\n\t\t */\n\t\tel: '#llms-question-bank',\n\n\t\t/**\n\t\t * Section model\n\t\t * @type {[type]}\n\t\t */\n\t\tmodelView: QuestionView,\n\n\t\t/**\n\t\t * Are sections selectable?\n\t\t * @type {Bool}\n\t\t */\n\t\tselectable: false,\n\n\t\t/**\n\t\t * Are sections sortable?\n\t\t * @type {Bool}\n\t\t */\n\t\tsortable: false,\n\n\t} );\n\n} );\n\n","/**\n * Single Question Choice View\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Views/QuestionChoice',[ 'Views/_Editable', ], function( Editable ) {\n\n\treturn Backbone.View.extend( _.defaults( {\n\n\t\t/**\n\t\t * HTML class names\n\t\t * @type {String}\n\t\t */\n\t\tclassName: 'llms-question-choice',\n\n\t\tevents: _.defaults( {\n\t\t\t'change input[name=\"correct\"]': 'toggle_correct',\n\t\t\t'click .llms-action-icon[href=\"#llms-add-choice\"]': 'add_choice',\n\t\t\t'click .llms-action-icon[href=\"#llms-del-choice\"]': 'del_choice',\n\t\t}, Editable.events ),\n\n\t\t/**\n\t\t * HTML element wrapper ID attribute\n\t\t * @return string\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tid: function() {\n\t\t\treturn 'llms-question-choice-' + this.model.id;\n\t\t},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'li',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-question-choice-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.14.1\n\t\t * @version 3.14.1\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\tthis.render();\n\n\t\t\tthis.listenTo( this.model.collection, 'add', this.maybe_disable_buttons );\n\t\t\tthis.listenTo( this.model, 'change', this.render );\n\n\t\t\tif ( 'image' === this.model.get( 'choice_type' ) ) {\n\t\t\t\tthis.listenTo( this.model.get( 'choice' ), 'change', this.render );\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender: function() {\n\t\t\tthis.$el.html( this.template( this.model ) );\n\t\t\treturn this;\n\t\t},\n\n\t\t/**\n\t\t * Add a new choice to the current choice list\n\t\t * Adds *after* the clicked choice\n\t\t * @param obj event JS event object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tadd_choice: function( event ) {\n\n\t\t\tevent.stopPropagation();\n\t\t\tevent.preventDefault();\n\n\t\t\tvar index = this.model.collection.indexOf( this.model );\n\t\t\tthis.model.collection.parent.add_choice( {}, {\n\t\t\t\tat: index + 1,\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * Delete the choice from the choice list & ensure there's at least one correct choice\n\t\t * @param obj event js event obj\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tdel_choice: function( event ) {\n\n\t\t\tevent.preventDefault();\n\t\t\tBackbone.pubSub.trigger( 'model-trashed', this.model );\n\t\t\tthis.model.collection.remove( this.model );\n\n\t\t},\n\n\t\t/**\n\t\t * When the correct answer input changes sync status to model\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\ttoggle_correct: function() {\n\n\t\t\tvar correct = this.$el.find( 'input[name=\"correct\"]' ).is( ':checked' );\n\t\t\tthis.model.set( 'correct', correct );\n\t\t\tthis.model.collection.trigger( 'correct-update', this.model );\n\n\t\t},\n\n\t}, Editable ) );\n\n} );\n\n","/**\n * Quiz question bank view\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Views/QuestionChoiceList',[ 'Views/QuestionChoice' ], function( ChoiceView ) {\n\n\treturn Backbone.CollectionView.extend( {\n\n\t\tclassName: 'llms-quiz-questions',\n\n\t\t/**\n\t\t * Choice model view\n\t\t * @type {[type]}\n\t\t */\n\t\tmodelView: ChoiceView,\n\n\t\t/**\n\t\t * Enable keyboard events\n\t\t * @type {Bool}\n\t\t */\n\t\tprocessKeyEvents: false,\n\n\t\t/**\n\t\t * Are sections selectable?\n\t\t * @type {Bool}\n\t\t */\n\t\tselectable: false,\n\n\t\t/**\n\t\t * Are sections sortable?\n\t\t * @type {Bool}\n\t\t */\n\t\tsortable: true,\n\n\t\tsortableOptions: {\n\t\t\taxis: false,\n\t\t\t// connectWith: '.llms-lessons',\n\t\t\tcursor: 'move',\n\t\t\thandle: '.llms-choice-id',\n\t\t\titems: '.llms-question-choice',\n\t\t\tplaceholder: 'llms-question-choice llms-sortable-placeholder',\n\t\t},\n\n\t\tsortable_start: function( model ) {\n\t\t\tthis.$el.addClass( 'dragging' );\n\t\t},\n\n\t\tsortable_stop: function( model ) {\n\t\t\tthis.$el.removeClass( 'dragging' );\n\t\t},\n\n\t} );\n\n} );\n\n","/**\n * Single Question View\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Views/Question',[\n\t\t'Views/_Editable',\n\t\t'Views/QuestionChoiceList'\n\t], function(\n\t\tEditable,\n\t\tChoiceListView\n\t) {\n\n\treturn Backbone.View.extend( _.defaults( {\n\n\t\t/**\n\t\t * Generate CSS classes for the question\n\t\t * @return string\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tclassName: function() {\n\t\t\treturn 'llms-question qtype--' + this.model.get( 'question_type' ).get( 'id' );\n\t\t},\n\n\t\tevents: _.defaults( {\n\t\t\t'click .clone--question': 'clone',\n\t\t\t'click .delete--question': 'delete',\n\t\t\t'click .expand--question': 'expand',\n\t\t\t'click .collapse--question': 'collapse',\n\t\t\t'change input[name=\"question_points\"]': 'update_points',\n\t\t}, Editable.events ),\n\n\t\t/**\n\t\t * HTML element wrapper ID attribute\n\t\t * @return string\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tid: function() {\n\t\t\treturn 'llms-question-' + this.model.id;\n\t\t},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'li',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-question-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\tvar change_events = [\n\t\t\t\t'change:_expanded',\n\t\t\t\t'change:menu_order',\n\t\t\t];\n\t\t\t_.each( change_events, function( event ) {\n\t\t\t\tthis.listenTo( this.model, event, this.render );\n\t\t\t}, this );\n\n\t\t\tthis.listenTo( this.model.get( 'image' ), 'change', this.render );\n\n\t\t\tthis.listenTo( this.model.get_parent(), 'change:_points', this.render_points_percentage );\n\n\t\t\tthis.on( 'multi_choices_toggle', this.multi_choices_toggle, this );\n\n\t\t\tBackbone.pubSub.on( 'del-question-choice', this.del_choice, this );\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender: function() {\n\n\t\t\tthis.$el.html( this.template( this.model ) );\n\n\t\t\tif ( this.model.get( 'question_type').get( 'choices' ) ) {\n\n\t\t\t\tthis.choiceListView = new ChoiceListView( {\n\t\t\t\t\tel: this.$el.find( '.llms-question-choices' ),\n\t\t\t\t\tcollection: this.model.get( 'choices' ),\n\t\t\t\t} );\n\t\t\t\tthis.choiceListView.render();\n\t\t\t\tthis.choiceListView.on( 'sortStart', this.choiceListView.sortable_start );\n\t\t\t\tthis.choiceListView.on( 'sortStop', this.choiceListView.sortable_stop );\n\n\t\t\t}\n\n\t\t\tif ( 'group' === this.model.get( 'question_type' ).get( 'id' ) ) {\n\n\t\t\t\tvar self = this;\n\t\t\t\tsetTimeout( function() {\n\t\t\t\t\tself.questionListView = self.collectionListView.quiz.get_question_list( {\n\t\t\t\t\t\tel: self.$el.find( '.llms-quiz-questions' ),\n\t\t\t\t\t\tcollection: self.model.get( 'questions' ),\n\t\t\t\t\t} );\n\t\t\t\t\tself.questionListView.render();\n\t\t\t\t\tself.questionListView.on( 'sortStart', self.questionListView.sortable_start );\n\t\t\t\t\tself.questionListView.on( 'sortStop', self.questionListView.sortable_stop );\n\t\t\t\t}, 1 );\n\n\t\t\t}\n\n\t\t\tif ( this.model.get( 'description_enabled' ) ) {\n\t\t\t\tthis.init_editor( 'question-desc--' + this.model.get( 'id' ) );\n\t\t\t}\n\n\t\t\tif ( this.model.get( 'clarifications_enabled' ) ) {\n\t\t\t\tthis.init_editor( 'question-clarifications--' + this.model.get( 'id' ), {\n\t\t\t\t\tmediaButtons: false,\n\t\t\t\t\ttinymce: {\n\t\t\t\t\t\ttoolbar1: 'bold,italic,strikethrough,bullist,numlist,alignleft,aligncenter,alignright',\n\t\t\t\t\t\ttoolbar2: '',\n\t\t\t\t\t\tsetup: _.bind( this.on_editor_ready, this ),\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\tthis.init_formatting_els();\n\t\t\tthis.init_selects();\n\n\t\t\treturn this;\n\t\t},\n\n\t\t/**\n\t\t * rerender points percentage when question points are updated\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender_points_percentage: function() {\n\n\t\t\tthis.$el.find( '.llms-question-points' ).attr( 'data-tip', this.model.get_points_percentage() );\n\n\t\t},\n\n\t\t/**\n\t\t * Click event to duplicate a question within a quiz\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tclone: function( event ) {\n\n\t\t\tevent.stopPropagation();\n\t\t\tevent.preventDefault();\n\t\t\tthis.model.collection.add( this._get_question_clone( this.model ) );\n\n\t\t},\n\n\t\t/**\n\t\t * Recursive clone function which will correctly clone children of a question\n\t\t * @param obj question queston model\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\t_get_question_clone: function( question ) {\n\n\t\t\t// create a duplicate\n\t\t\tvar clone = _.clone( question.attributes );\n\n\t\t\t// remove id (we want the duplicate to have a temp id)\n\t\t\tdelete clone.id;\n\n\t\t\tclone.parent_id = question.get( 'id' );\n\n\t\t\t// set the question type ID\n\t\t\tclone.question_type = question.get( 'question_type' ).get( 'id' );\n\n\t\t\t// clone the image attributes seperately\n\t\t\tclone.image = _.clone( question.get( 'image' ).attributes );\n\n\t\t\t// if it has choices clone all the choices\n\t\t\tif ( question.get( 'choices' ) ) {\n\n\t\t\t\tclone.choices = [];\n\n\t\t\t\tquestion.get( 'choices' ).each( function ( choice ) {\n\n\t\t\t\t\tvar choice_clone = _.clone( choice.attributes );\n\t\t\t\t\tdelete choice_clone.id;\n\t\t\t\t\tdelete choice_clone.question_id;\n\n\t\t\t\t\tclone.choices.push( choice_clone );\n\n\t\t\t\t} );\n\n\t\t\t}\n\n\t\t\tif ( 'group' === question.get( 'question_type' ).get( 'id' ) ) {\n\n\t\t\t\tclone.questions = [];\n\t\t\t\tquestion.get( 'questions' ).each( function( child ) {\n\t\t\t\t\tclone.questions.push( this._get_question_clone( child ) );\n\t\t\t\t}, this );\n\n\t\t\t}\n\n\t\t\treturn clone;\n\n\t\t},\n\n\t\t/**\n\t\t * Collapse a question and hide it's settings\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tcollapse: function() {\n\n\t\t\tthis.model.set( '_expanded', false );\n\n\t\t},\n\n\t\t/**\n\t\t * Delete the question from a quiz / question group\n\t\t * @param obj event js event object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tdelete: function( event ) {\n\n\t\t\tevent.preventDefault();\n\n\t\t\tif ( window.confirm( LLMS.l10n.translate( 'Are you sure you want to delete this question?' ) ) ) {\n\n\t\t\t\tthis.model.collection.remove( this.model );\n\t\t\t\tBackbone.pubSub.trigger( 'model-trashed', this.model );\n\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Click event to reveal a question's settings & choices\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\texpand: function() {\n\n\t\t\tthis.model.set( '_expanded', true );\n\n\t\t},\n\n\t\t/**\n\t\t * When toggling multiple correct answers *off* remove all correct choices except the first correct choice in the list\n\t\t * @param string val value of the question's `multi_choice` attr [yes|no]\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tmulti_choices_toggle: function( val ) {\n\n\t\t\tif ( 'yes' === val ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis.model.get( 'choices' ).update_correct( _.first( this.model.get( 'choices' ).get_correct() ) );\n\n\t\t},\n\n\t\t/**\n\t\t * Update the model's points when the value of the points input is updated\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tupdate_points: function() {\n\n\t\t\tthis.model.set( 'points', this.$el.find( 'input[name=\"question_points\"]' ).val() * 1 );\n\n\t\t}\n\n\t}, Editable ) );\n\n} );\n\n","/**\n * Quiz question bank view\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Views/QuestionList',[ 'Views/Question' ], function( QuestionView ) {\n\n\treturn Backbone.CollectionView.extend( {\n\n\t\tclassName: 'llms-quiz-questions',\n\n\t\t/**\n\t\t * Parent element\n\t\t * @type {String}\n\t\t */\n\t\t// el: '#llms-quiz-questions',\n\n\t\t/**\n\t\t * Section model\n\t\t * @type {[type]}\n\t\t */\n\t\tmodelView: QuestionView,\n\n\t\t/**\n\t\t * Enable keyboard events\n\t\t * @type {Bool}\n\t\t */\n\t\tprocessKeyEvents: false,\n\n\t\t/**\n\t\t * Are sections selectable?\n\t\t * @type {Bool}\n\t\t */\n\t\tselectable: false,\n\n\t\t/**\n\t\t * Are sections sortable?\n\t\t * @type {Bool}\n\t\t */\n\t\tsortable: true,\n\n\t\tsortableOptions: {\n\t\t\taxis: false,\n\t\t\tconnectWith: '.llms-quiz-questions',\n\t\t\tcursor: 'move',\n\t\t\thandle: '.llms-data-stamp',\n\t\t\titems: '.llms-question',\n\t\t\tplaceholder: 'llms-question llms-sortable-placeholder',\n\t\t},\n\n\t\t/**\n\t\t * Highlight drop areas when dragging starts\n\t\t * @param obj model model being sorted\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tsortable_start: function( model ) {\n\t\t\tvar selector = 'group' === model.get( 'question_type' ).get( 'id' ) ? '.llms-editor-tab > .llms-quiz-questions' : '.llms-quiz-questions';\n\t\t\t$( selector ).addClass( 'dragging' );\n\t\t},\n\n\t\t/**\n\t\t * Remove highlights when dragging stops\n\t\t * @param obj model model being sorted\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tsortable_stop: function() {\n\t\t\t$( '.llms-quiz-questions' ).removeClass( 'dragging' );\n\t\t},\n\n\t\t/**\n\t\t * Overrides receive to ensure that question groups can't be moved into queston groups\n\t\t * @param obj event js event object\n\t\t * @param obj ui jQuery UI Sortable ui object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\t_receive : function( event, ui ) {\n\n\t\t\tevent.stopPropagation();\n\n\t\t\t// prevent moving a question group into a question group\n\t\t\tif ( ui.item.hasClass( 'qtype--group' ) && $( event.target ).closest( '.qtype--group' ).length ) {;\n\t\t\t\tui.sender.sortable( 'cancel' );\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar senderListEl = ui.sender;\n\t\t\tvar senderCollectionListView = senderListEl.data( \"view\" );\n\t\t\tif( ! senderCollectionListView || ! senderCollectionListView.collection ) return;\n\n\t\t\tvar newIndex = this._getContainerEl().children().index( ui.item );\n\t\t\tvar modelReceived = senderCollectionListView.collection.get( ui.item.attr( \"data-model-cid\" ) );\n\t\t\tsenderCollectionListView.collection.remove( modelReceived );\n\t\t\tthis.collection.add( modelReceived, { at : newIndex } );\n\t\t\tmodelReceived.collection = this.collection; // otherwise will not get properly set, since modelReceived.collection might already have a value.\n\t\t\tthis.setSelectedModel( modelReceived );\n\t\t},\n\n\t\t/**\n\t\t * Override to allow manipulatino of placeholder element\n\t\t * @param {[type]} event [description]\n\t\t * @param {[type]} ui [description]\n\t\t * @return {[type]}\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\t_sortStart : function( event, ui ) {\n\n\t\t\tvar modelBeingSorted = this.collection.get( ui.item.attr( \"data-model-cid\" ) );\n\n\t\t\tui.placeholder.addClass( 'qtype--' + modelBeingSorted.get( 'question_type' ).get( 'id' ) );\n\n\t\t\tif( this._isBackboneCourierAvailable() )\n\t\t\t\tthis.spawn( \"sortStart\", { modelBeingSorted : modelBeingSorted } );\n\t\t\telse this.trigger( \"sortStart\", modelBeingSorted );\n\t\t},\n\n\t\t/**\n\t\t * Overloads the function from Backbone.CollectionView core because it doesn't send stop events\n\t\t * if moving from one sortable to another... :-(\n\t\t * @param obj event js event object\n\t\t * @param obj ui jQuery UI object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\t_sortStop : function( event, ui ) {\n\n\t\t\tevent.stopPropagation();\n\n\t\t\tvar modelBeingSorted = this.collection.get( ui.item.attr( 'data-model-cid' ) ),\n\t\t\t\tmodelViewContainerEl = this._getContainerEl(),\n\t\t\t\tnewIndex = modelViewContainerEl.children().index( ui.item );\n\n\t\t\tif ( newIndex == -1 && modelBeingSorted ) {\n\t\t\t\tthis.collection.remove( modelBeingSorted );\n\t\t\t}\n\n\t\t\tthis._reorderCollectionBasedOnHTML();\n\t\t\tthis.updateDependentControls();\n\n\t\t\tif( this._isBackboneCourierAvailable() ) {\n\t\t\t\tthis.spawn( 'sortStop', { modelBeingSorted : modelBeingSorted, newIndex : newIndex } );\n\t\t\t} else {\n\t\t\t\tthis.trigger( 'sortStop', modelBeingSorted, newIndex );\n\t\t\t}\n\n\t\t},\n\n\t} );\n\n} );\n\n","/**\n * Single Quiz View\n * @since 3.16.0\n * @version 3.19.2\n */\ndefine( 'Views/Quiz',[\n\t\t'Models/Quiz',\n\t\t'Views/Popover',\n\t\t'Views/PostSearch',\n\t\t'Views/QuestionBank',\n\t\t'Views/QuestionList',\n\t\t'Views/SettingsFields',\n\t\t'Views/_Detachable',\n\t\t'Views/_Editable',\n\t\t'Views/_Subview',\n\t\t'Views/_Trashable'\n\t], function(\n\t\tQuizModel,\n\t\tPopover,\n\t\tPostSearch,\n\t\tQuestionBank,\n\t\tQuestionList,\n\t\tSettingsFields,\n\t\tDetachable,\n\t\tEditable,\n\t\tSubview,\n\t\tTrashable\n\t) {\n\n\treturn Backbone.View.extend( _.defaults( {\n\n\t\t/**\n\t\t * Current view state\n\t\t * @type {String}\n\t\t */\n\t\tstate: 'default',\n\n\t\t/**\n\t\t * Current Subviews\n\t\t * @type {Object}\n\t\t */\n\t\tviews: {\n\t\t\tsettings: {\n\t\t\t\tclass: SettingsFields,\n\t\t\t\tinstance: null,\n\t\t\t\tstate: 'default',\n\t\t\t},\n\t\t\tbank: {\n\t\t\t\tclass: QuestionBank,\n\t\t\t\tinstance: null,\n\t\t\t\tstate: 'default',\n\t\t\t},\n\t\t\tlist: {\n\t\t\t\tclass: QuestionList,\n\t\t\t\tinstance: null,\n\t\t\t\tstate: 'default',\n\t\t\t},\n\t\t},\n\n\t\tel: '#llms-editor-quiz',\n\n\t\t/**\n\t\t * Events\n\t\t * @type {Object}\n\t\t */\n\t\tevents: _.defaults( {\n\t\t\t'click #llms-existing-quiz': 'add_existing_quiz_click',\n\t\t\t'click #llms-new-quiz': 'add_new_quiz',\n\t\t\t'click #llms-show-question-bank': 'show_tools',\n\t\t\t'click .bulk-toggle': 'bulk_toggle',\n\t\t\t// 'keyup #llms-question-bank-filter': 'filter_question_types',\n\t\t\t// 'search #llms-question-bank-filter': 'filter_question_types',\n\t\t}, Detachable.events, Editable.events, Trashable.events ),\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'div',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-quiz-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.19.2\n\t\t */\n\t\tinitialize: function( data ) {\n\n\t\t\tthis.lesson = data.lesson;\n\n\t\t\t// initialize the model if the quiz is enabled or it's disabled but we still have data for a quiz\n\t\t\tif ( 'yes' === this.lesson.get( 'quiz_enabled' ) || ! _.isEmpty( this.lesson.get( 'quiz' ) ) ) {\n\n\t\t\t\tthis.model = this.lesson.get( 'quiz' );\n\n\t\t\t\t/**\n\t\t\t\t * @todo this is a terrilbe terrible patch\n\t\t\t\t * I've spent nearly 3 days trying to figure out how to not use this line of code\n\t\t\t\t * ISSUE REPRODUCTION:\n\t\t\t\t * Open course builder\n\t\t\t\t * Open a lesson (A) and add a quiz\n\t\t\t\t * Switch to a new lesson (B)\n\t\t\t\t * Add a new quiz\n\t\t\t\t * Return to lesson A and the quizzes parent will be set to LESSON B\n\t\t\t\t * This will happen for *every* quiz in the builder...\n\t\t\t\t * Adding this set_parent on init guarantees that the quizzes correct parent is set\n\t\t\t\t * after adding new quizzes to other lessons\n\t\t\t\t * it's awful and it's gross...\n\t\t\t\t * I'm confused and tired and going to miss release dates again because of it\n\t\t\t\t */\n\t\t\t\tthis.model.set_parent( this.lesson );\n\n\t\t\t\tthis.listenTo( this.model, 'change:_points', this.render_points );\n\n\t\t\t}\n\n\t\t\tthis.on( 'model-trashed', this.on_trashed );\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.16.0\n\t\t * @version 3.19.2\n\t\t */\n\t\trender: function() {\n\n\t\t\tthis.$el.html( this.template( this.model ) );\n\n\t\t\t// render the quiz builder\n\t\t\tif ( this.model ) {\n\n\t\t\t\t// don't allow interaction until questions are lazy loaded\n\t\t\t\tLLMS.Spinner.start( this.$el );\n\n\t\t\t\tthis.render_subview( 'settings', {\n\t\t\t\t\tel: '#llms-quiz-settings-fields',\n\t\t\t\t\tmodel: this.model,\n\t\t\t\t} );\n\n\t\t\t\tthis.init_datepickers();\n\t\t\t\tthis.init_selects();\n\n\t\t\t\tthis.render_subview( 'bank', {\n\t\t\t\t\tcollection: window.llms_builder.questions,\n\t\t\t\t} );\n\n\t\t\t\tvar last_group = null,\n\t\t\t\t\tgroup = null;\n\t\t\t\t// let all the question types reference the quiz for adding questions quickly\n\t\t\t\tthis.get_subview( 'bank' ).instance.viewManager.each( function( view ) {\n\n\t\t\t\t\tview.quiz = this.model;\n\n\t\t\t\t\tgroup = view.model.get( 'group' ).name;\n\n\t\t\t\t\tif ( last_group !== group ) {\n\t\t\t\t\t\tlast_group = group;\n\t\t\t\t\t\tview.$el.before( '' );\n\t\t\t\t\t}\n\n\t\t\t\t}, this );\n\n\t\t\t\tthis.model.load_questions( _.bind( function( err ) {\n\n\t\t\t\t\tif ( err ) {\n\t\t\t\t\t\talert( LLMS.l10n.translate( 'An error occurred while trying to load the questions. Please refresh the page and try again.' ) );\n\t\t\t\t\t\treturn this;\n\t\t\t\t\t}\n\n\t\t\t\t\tLLMS.Spinner.stop( this.$el );\n\t\t\t\t\tthis.render_subview( 'list', {\n\t\t\t\t\t\tel: '#llms-quiz-questions',\n\t\t\t\t\t\tcollection: this.model.get( 'questions' ),\n\t\t\t\t\t} );\n\t\t\t\t\tvar list = this.get_subview( 'list' ).instance;\n\t\t\t\t\tlist.quiz = this;\n\t\t\t\t\tlist.collection.on( 'add', function() {\n\t\t\t\t\t\tlist.collection.trigger( 'reorder' );\n\t\t\t\t\t}, this );\n\t\t\t\t\tlist.on( 'sortStart', list.sortable_start );\n\t\t\t\t\tlist.on( 'sortStop', list.sortable_stop );\n\n\t\t\t\t}, this ) );\n\n\t\t\t\tthis.model.on( 'new-question-added', function() {\n\t\t\t\t\tvar $questions = this.$el.find( '#llms-quiz-questions' );\n\t\t\t\t\t$questions.animate( { scrollTop: $questions.prop( 'scrollHeight' ) }, 200 );\n\t\t\t\t}, this );\n\n\t\t\t}\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\t/**\n\t\t * On quiz points update, update the value of the Total Points area in the header\n\t\t * @param obj quiz Instance of the quiz model\n\t\t * @param int points Updated number of points\n\t\t * @return void\n\t\t * @since 3.17.6\n\t\t * @version 3.17.6\n\t\t */\n\t\trender_points: function( quiz, points ) {\n\n\t\t\tthis.$el.find( '#llms-quiz-total-points' ).text( points );\n\n\t\t},\n\n\t\t/**\n\t\t * Bulk expand / collapse question buttons\n\t\t * @param obj event js event object\n\t\t * @return obj\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tbulk_toggle: function( event ) {\n\n\t\t\tvar expanded = ( 'expand' === $( event.target ).attr( 'data-action' ) );\n\n\t\t\tthis.model.get( 'questions' ).each( function( question ) {\n\t\t\t\tquestion.set( '_expanded', expanded );\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * Adds a new quiz to a lesson which currently has no quiz associated wlith it\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tadd_new_quiz: function() {\n\n\t\t\tvar quiz = this.lesson.get( 'quiz' );\n\t\t\tif ( _.isEmpty( quiz ) ) {\n\t\t\t\tquiz = this.lesson.add_quiz();\n\t\t\t} else {\n\t\t\t\tthis.lesson.set( 'quiz_enabled', 'yes' );\n\t\t\t}\n\n\t\t\tthis.model = quiz;\n\t\t\tthis.render();\n\n\t\t},\n\n\t\t// come back to this and make sure cloning resets all the IDs\n\t\tadd_existing_quiz: function( event ) {\n\n\t\t\tthis.post_search_popover.hide();\n\n\t\t\tvar quiz = event.data;\n\n\t\t\tif ( 'clone' === event.action ) {\n\n\t\t\t\tdelete quiz.id;\n\n\t\t\t\t_.each( quiz.questions, function( question ) {\n\n\t\t\t\t\tdelete question.parent_id;\n\t\t\t\t\tdelete question.id;\n\n\t\t\t\t\tif ( question.choices ) {\n\n\t\t\t\t\t\t_.each( question.choices, function( choice ) {\n\n\t\t\t\t\t\t\tdelete choice.question_id;\n\t\t\t\t\t\t\tdelete choice.id;\n\n\t\t\t\t\t\t} );\n\n\t\t\t\t\t}\n\n\t\t\t\t} );\n\n\t\t\t} else {\n\n\t\t\t\tquiz._forceSync = true;\n\n\t\t\t}\n\n\t\t\tdelete quiz.lesson_id;\n\n\t\t\tthis.lesson.add_quiz( quiz );\n\t\t\tthis.model = this.lesson.get( 'quiz' );\n\t\t\tthis.render();\n\n\t\t},\n\n\t\t/**\n\t\t * Open add existing quiz popover\n\t\t * @param obj event JS event object\n\t\t * @return void\n\t\t * @since 3.16.12\n\t\t * @version 3.16.12\n\t\t */\n\t\tadd_existing_quiz_click: function( event ) {\n\n\t\t\tevent.preventDefault();\n\n\t\t\tthis.post_search_popover = new Popover( {\n\t\t\t\tel: '#llms-existing-quiz',\n\t\t\t\targs: {\n\t\t\t\t\tbackdrop: true,\n\t\t\t\t\tcloseable: true,\n\t\t\t\t\tcontainer: '.wrap.lifterlms.llms-builder',\n\t\t\t\t\tdismissible: true,\n\t\t\t\t\tplacement: 'left',\n\t\t\t\t\twidth: 480,\n\t\t\t\t\ttitle: LLMS.l10n.translate( 'Add Existing Quiz' ),\n\t\t\t\t\tcontent: new PostSearch( {\n\t\t\t\t\t\tpost_type: 'llms_quiz',\n\t\t\t\t\t\tsearching_message: LLMS.l10n.translate( 'Search for existing quizzes...' ),\n\t\t\t\t\t} ).render().$el,\n\t\t\t\t\tonHide: function() {\n\t\t\t\t\t\tBackbone.pubSub.off( 'quiz-search-select' );\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\tthis.post_search_popover.show();\n\t\t\tBackbone.pubSub.once( 'quiz-search-select', this.add_existing_quiz, this );\n\n\t\t},\n\n\t\t// filter_question_types: _.debounce( function( event ) {\n\n\t\t// \tvar term = $( event.target ).val();\n\n\t\t// \tthis.QuestionBankView.viewManager.each( function( view ) {\n\t\t// \t\tif ( ! term ) {\n\t\t// \t\t\tview.clear_filter();\n\t\t// \t\t} else {\n\t\t// \t\t\tview.filter( term );\n\t\t// \t\t}\n\t\t// \t} );\n\n\n\t\t// }, 300 ),\n\n\t\t/**\n\t\t * Callback function when the quiz has been deleted\n\t\t * @param object quiz Quiz Model\n\t\t * @return void\n\t\t * @since 3.16.6\n\t\t * @version 3.16.6\n\t\t */\n\t\ton_trashed: function( quiz ) {\n\n\t\t\tthis.lesson.set( 'quiz_enabled', 'no' );\n\t\t\tthis.lesson.set( 'quiz', '' );\n\n\t\t\tdelete this.model;\n\n\t\t\tthis.render();\n\n\t\t},\n\n\t\t/**\n\t\t * \"Add Question\" button click event\n\t\t * Creates a popover with question type list interface\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tshow_tools: function() {\n\n\t\t\t// create popover\n\t\t\tvar pop = new Popover( {\n\t\t\t\tel: '#llms-show-question-bank',\n\t\t\t\targs: {\n\t\t\t\t\tbackdrop: true,\n\t\t\t\t\tcloseable: true,\n\t\t\t\t\tcontainer: '#llms-builder-sidebar',\n\t\t\t\t\tdismissible: true,\n\t\t\t\t\tplacement: 'top-left',\n\t\t\t\t\twidth: 'calc( 100% - 40px )',\n\t\t\t\t\ttitle: LLMS.l10n.translate( 'Add a Question' ),\n\t\t\t\t\turl: '#llms-quiz-tools',\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\t// show it\n\t\t\tpop.show();\n\n\t\t\t// if a question is added, hide the popover\n\t\t\tthis.model.on( 'new-question-added', function() {\n\t\t\t\tpop.hide();\n\t\t\t} );\n\n\t\t},\n\n\t\tget_question_list: function( options ) {\n\t\t\treturn new QuestionList( options );\n\t\t}\n\n\t}, Detachable, Editable, Subview, Trashable, SettingsFields ) );\n\n} );\n\n","/**\n * Single Assignment View\n * @since 3.17.0\n * @version 3.17.7\n */\ndefine( 'Views/Assignment',[\n\t\t'Views/Popover',\n\t\t'Views/PostSearch',\n\t\t'Views/_Detachable',\n\t\t'Views/_Editable',\n\t\t'Views/_Trashable',\n\t\t'Views/_Subview',\n\t\t'Views/SettingsFields'\n\t], function(\n\t\tPopover,\n\t\tPostSearch,\n\t\tDetachable,\n\t\tEditable,\n\t\tTrashable,\n\t\tSubview,\n\t\tSettingsFields\n\t) {\n\n\treturn Backbone.View.extend( _.defaults( {\n\n\t\t/**\n\t\t * Current view state\n\t\t * @type {String}\n\t\t */\n\t\tstate: 'default',\n\n\t\t/**\n\t\t * Current Subviews\n\t\t * @type {Object}\n\t\t */\n\t\tviews: {\n\t\t\tsettings: {\n\t\t\t\tclass: SettingsFields,\n\t\t\t\tinstance: null,\n\t\t\t\tstate: 'default',\n\t\t\t},\n\t\t},\n\n\t\tel: '#llms-editor-assignment',\n\n\t\t/**\n\t\t * DOM Events\n\t\t * @return obj\n\t\t * @since 3.17.1\n\t\t * @version 3.17.1\n\t\t */\n\t\tevents: function() {\n\t\t\tvar addon_events = this.is_addon_available() ? window.llms_builder.assignments.get_view_events() : {};\n\t\t\treturn _.defaults( {\n\t\t\t\t'click #llms-existing-assignment': 'add_existing_assignment_click',\n\t\t\t\t'click #llms-new-assignment': 'add_new_assignment',\n\t\t\t}, Detachable.events, Editable.events, Trashable.events, addon_events );\n\t\t},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'div',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-assignment-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.2\n\t\t */\n\t\tinitialize: function( data ) {\n\n\t\t\tthis.lesson = data.lesson;\n\n\t\t\t// initialize the model if the assignment is enabled or it's disabled but we still have data for a assignment\n\t\t\tif ( 'yes' === this.lesson.get( 'assignment_enabled' ) || ! _.isEmpty( this.lesson.get( 'assignment' ) ) ) {\n\n\t\t\t\tthis.model = this.lesson.get( 'assignment' );\n\n\t\t\t\t/**\n\t\t\t\t * @todo this is a terrilbe terrible patch\n\t\t\t\t * I've spent nearly 3 days trying to figure out how to not use this line of code\n\t\t\t\t * ISSUE REPRODUCTION:\n\t\t\t\t * Open course builder\n\t\t\t\t * Open a lesson (A) and add a assignment\n\t\t\t\t * Switch to a new lesson (B)\n\t\t\t\t * Add a new assignment\n\t\t\t\t * Return to lesson A and the assignment's parent will be set to LESSON B\n\t\t\t\t * This will happen for *every* assignment in the builder...\n\t\t\t\t * Adding this set_parent on init guarantees that the assignment's correct parent is set\n\t\t\t\t * after adding new assignment's to other lessons\n\t\t\t\t * it's awful and it's gross...\n\t\t\t\t * I'm confused and tired and going to miss release dates again because of it\n\t\t\t\t */\n\t\t\t\tthis.model.set_parent( this.lesson );\n\n\t\t\t}\n\n\t\t\tthis.on( 'model-trashed', this.on_trashed );\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.17.0\n\t\t * @version 3.17.7\n\t\t */\n\t\trender: function() {\n\n\t\t\tthis.$el.html( this.template( this.model ) );\n\n\t\t\tif ( this.model && this.is_addon_available() ) {\n\n\t\t\t\tthis.stopListening( this.model, 'change:assignment_type', this.render );\n\n\t\t\t\tthis.render_subview( 'settings', {\n\t\t\t\t\tel: '#llms-assignment-settings-fields',\n\t\t\t\t\tmodel: this.model,\n\t\t\t\t} );\n\n\t\t\t\t// this.init_datepickers();\n\t\t\t\tthis.init_selects();\n\n\t\t\t\twindow.llms_builder.assignments.render_editor( this );\n\n\t\t\t\tthis.listenTo( this.model, 'change:assignment_type', this.render );\n\n\t\t\t}\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\t/**\n\t\t * Adds a new assignment to a lesson which currently has no assignment associated wlith it\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tadd_new_assignment: function() {\n\n\t\t\tif ( this.is_addon_available() ) {\n\n\t\t\t\tthis.model = window.llms_builder.assignments.get_assignment( {\n\t\t\t\t\t/* translators: %1$s = associated lesson title */\n\t\t\t\t\ttitle: LLMS.l10n.replace( '%1$s Assignment', {\n\t\t\t\t\t\t'%1$s': this.lesson.get( 'title' ),\n\t\t\t\t\t} ),\n\t\t\t\t\tlesson_id: this.lesson.get( 'id' ),\n\t\t\t\t} );\n\n\t\t\t\tthis.lesson.set( 'assignment_enabled', 'yes' );\n\t\t\t\tthis.lesson.set( 'assignment', this.model );\n\n\t\t\t\tthis.render();\n\n\t\t\t} else {\n\n\t\t\t\tthis.show_ad_popover( '#llms-new-assignment' );\n\n\t\t\t}\n\n\n\t\t},\n\n\t\t/**\n\t\t * When an assignment is selected from the post select popover\n\t\t * instantiate it and add it to the current lesson\n\t\t * @param object event data from the select2 select event\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tadd_existing_assignment: function( event ) {\n\n\t\t\tthis.post_search_popover.hide();\n\n\t\t\tvar assignment = event.data;\n\n\t\t\tif ( 'clone' === event.action ) {\n\n\t\t\t\tdelete assignment.id;\n\n\t\t\t} else {\n\n\t\t\t\tassignment._forceSync = true;\n\n\t\t\t}\n\n\t\t\tassignment.lesson_id = this.lesson.get( 'id' )\n\n\t\t\tassignment = window.llms_builder.construct.get_model( 'Assignment', assignment );\n\n\t\t\tthis.lesson.set( 'assignment_enabled', 'yes' );\n\t\t\tthis.lesson.set( 'assignment', assignment );\n\t\t\tthis.model = assignment;\n\n\t\t\tthis.render();\n\n\t\t},\n\n\t\t/**\n\t\t * Open add existing assignment popover\n\t\t * @param obj event JS event object\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tadd_existing_assignment_click: function( event ) {\n\n\t\t\tevent.preventDefault();\n\n\t\t\tif ( this.is_addon_available() ) {\n\n\t\t\t\tthis.post_search_popover = new Popover( {\n\t\t\t\t\tel: '#llms-existing-assignment',\n\t\t\t\t\targs: {\n\t\t\t\t\t\tbackdrop: true,\n\t\t\t\t\t\tcloseable: true,\n\t\t\t\t\t\tcontainer: '.wrap.lifterlms.llms-builder',\n\t\t\t\t\t\tdismissible: true,\n\t\t\t\t\t\tplacement: 'left',\n\t\t\t\t\t\twidth: 480,\n\t\t\t\t\t\ttitle: LLMS.l10n.translate( 'Add Existing Assignment' ),\n\t\t\t\t\t\tcontent: new PostSearch( {\n\t\t\t\t\t\t\tpost_type: 'llms_assignment',\n\t\t\t\t\t\t\tsearching_message: LLMS.l10n.translate( 'Search for existing assignments...' ),\n\t\t\t\t\t\t} ).render().$el,\n\t\t\t\t\t\tonHide: function() {\n\t\t\t\t\t\t\tBackbone.pubSub.off( 'assignment-search-select' );\n\t\t\t\t\t\t},\n\t\t\t\t\t}\n\t\t\t\t} );\n\n\t\t\t\tthis.post_search_popover.show();\n\t\t\t\tBackbone.pubSub.once( 'assignment-search-select', this.add_existing_assignment, this );\n\n\t\t\t} else {\n\n\t\t\t\tthis.show_ad_popover( '#llms-existing-assignment' );\n\n\t\t\t}\n\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if Assignments addon is available to use\n\t\t * @return {Boolean}\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tis_addon_available: function() {\n\n\t\t\treturn ( window.llms_builder.assignments );\n\n\t\t},\n\n\t\t/**\n\t\t * Called when assignment is trashed\n\t\t * @param obj assignment Assignment model\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\ton_trashed: function( assignment ) {\n\n\t\t\tthis.lesson.set( 'assignment_enabled', 'no' );\n\t\t\tthis.lesson.set( 'assignment', '' );\n\n\t\t\tdelete this.model;\n\n\t\t\tthis.render();\n\n\t\t},\n\n\t\t/**\n\t\t * Shows a dirty dirty ad popoever for advanced assignments\n\t\t * @param string el jQuery selector string\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.0\n\t\t */\n\t\tshow_ad_popover: function( el ) {\n\n\t\t\tvar h3 = LLMS.l10n.translate( 'Get Your Students Taking Action' ),\n\t\t\t\tp = 'Great learning content is only half of teaching online. When your learners fully engage, they will take your content and move into action. Remove barriers for your learners by telling them what to do to apply what they just learned. Create graded assignments or simply give them a checklist of action items to complete before moving on.',\n\t\t\t\tbtn = LLMS.l10n.translate( 'Get Assignments Now!' ),\n\t\t\t\turl = 'https://lifterlms.com/product/lifterlms-assignments?utm_source=LifterLMS%20Plugin&utm_medium=Assignment%20Builder%20Button&utm_campaign=Assignment%20Addon%20Upsell&utm_content=3.17.0';\n\n\t\t\tthis.ad_popover = new Popover( {\n\t\t\t\tel: el,\n\t\t\t\targs: {\n\t\t\t\t\tbackdrop: true,\n\t\t\t\t\tcloseable: true,\n\t\t\t\t\tcontainer: '.wrap.lifterlms.llms-builder',\n\t\t\t\t\tdismissible: true,\n\t\t\t\t\t// placement: 'left',\n\t\t\t\t\twidth: 380,\n\t\t\t\t\ttitle: LLMS.l10n.translate( 'Unlock LifterLMS Assignments' ),\n\t\t\t\t\tcontent: '' + h3 + ' ' + p + '
' + btn + '
'\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\tthis.ad_popover.show();\n\n\t\t},\n\n\t}, Detachable, Editable, Trashable, Subview, SettingsFields ) );\n\n} );\n\n","/**\n * Sidebar Editor View\n * @since 3.16.0\n * @version 3.17.0\n */\ndefine( 'Views/Editor',[\n\t\t'Views/LessonEditor',\n\t\t'Views/Quiz',\n\t\t'Views/Assignment',\n\t\t'Views/_Subview'\n\t], function(\n\t\tLessonEditor,\n\t\tQuiz,\n\t\tAssignment,\n\t\tSubview\n\t) {\n\n\treturn Backbone.View.extend( _.defaults( {\n\n\t\t/**\n\t\t * Current view state\n\t\t * @type {String}\n\t\t */\n\t\tstate: 'lesson', // [lesson|quiz]\n\n\t\t/**\n\t\t * Current Subviews\n\t\t * @type {Object}\n\t\t */\n\t\tviews: {\n\t\t\tlesson: {\n\t\t\t\tclass: LessonEditor,\n\t\t\t\tinstance: null,\n\t\t\t\tstate: 'lesson',\n\t\t\t},\n\t\t\tassignment: {\n\t\t\t\tclass: Assignment,\n\t\t\t\tinstance: null,\n\t\t\t\tstate: 'assignment',\n\t\t\t},\n\t\t\tquiz: {\n\t\t\t\tclass: Quiz,\n\t\t\t\tinstance: null,\n\t\t\t\tstate: 'quiz',\n\t\t\t},\n\t\t},\n\n\t\t/**\n\t\t * HTML element selector\n\t\t * @type {String}\n\t\t */\n\t\tel: '#llms-editor',\n\n\t\tevents: {\n\t\t\t'click .llms-editor-nav a[href=\"#llms-editor-close\"]': 'close_editor',\n\t\t\t'click .llms-editor-nav a:not([href=\"#llms-editor-close\"])': 'switch_tab',\n\t\t},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'div',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-editor-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function( data ) {\n\n\t\t\tthis.SidebarView = data.SidebarView;\n\t\t\tif ( data.tab ) {\n\t\t\t\tthis.state = data.tab;\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender: function( view_data ) {\n\n\t\t\tview_data = view_data || {};\n\n\t\t\tthis.$el.html( this.template( this ) );\n\n\t\t\tthis.render_subviews( _.extend( view_data, {\n\t\t\t\tlesson: this.model,\n\t\t\t} ) );\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\t/**\n\t\t * Click event for close sidebar editor button\n\t\t * Sends event to main SidebarView to trigger editor closing events\n\t\t * @param obj event js event obj\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tclose_editor: function( event ) {\n\n\t\t\tevent.preventDefault();\n\t\t\tBackbone.pubSub.trigger( 'sidebar-editor-close' );\n\n\t\t},\n\n\t\t/**\n\t\t * Click event for switching tabs in the editor navigation\n\t\t * @param object event js event object\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tswitch_tab: function( event ) {\n\n\t\t\tevent.preventDefault();\n\n\t\t\tvar $btn = $( event.target ),\n\t\t\t\tview = $btn.attr( 'data-view' ),\n\t\t\t\t$tab = this.$el.find( $btn.attr( 'href' ) );\n\n\t\t\tthis.set_state( view ).render();\n\n\t\t\t// Backbone.pubSub.trigger( 'editor-tab-activated', $btn.attr( 'href' ).substring( 1 ) );\n\n\t\t},\n\n\t}, Subview ) );\n\n} );\n\n","/**\n * Sidebar Elements View\n * @since 3.16.0\n * @version 3.16.12\n */\ndefine( 'Views/Elements',[ 'Models/Section', 'Views/Section', 'Models/Lesson', 'Views/Lesson', 'Views/Popover', 'Views/PostSearch' ], function( Section, SectionView, Lesson, LessonView, Popover, LessonSearch ) {\n\n\treturn Backbone.View.extend( {\n\n\t\t/**\n\t\t * HTML element selector\n\t\t * @type {String}\n\t\t */\n\t\tel: '#llms-elements',\n\n\t\tevents: {\n\t\t\t'click #llms-new-section': 'add_new_section',\n\t\t\t'click #llms-new-lesson': 'add_new_lesson',\n\t\t\t'click #llms-existing-lesson': 'add_existing_lesson',\n\t\t},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'div',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-elements-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function( data ) {\n\n\t\t\t// save a reference to the main Course view\n\t\t\tthis.SidebarView = data.SidebarView;\n\n\t\t\t// watch course sections and enable/disable lesson buttons conditionally\n\t\t\tthis.listenTo( this.SidebarView.CourseView.model.get( 'sections' ), 'add', this.maybe_disable_buttons );\n\t\t\tthis.listenTo( this.SidebarView.CourseView.model.get( 'sections' ), 'remove', this.maybe_disable_buttons );\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender: function() {\n\n\t\t\tthis.$el.html( this.template() );\n\t\t\tthis.draggable();\n\t\t\tthis.maybe_disable_buttons();\n\n\t\t\treturn this;\n\t\t},\n\n\t\tdraggable: function() {\n\n\t\t\t$( '#llms-new-section' ).draggable( {\n\t\t\t\tappendTo: '#llms-sections',\n\t\t\t\tcancel: false,\n\t\t\t\tconnectToSortable: '.llms-sections',\n\t\t\t\thelper: function() {\n\t\t\t\t\treturn new SectionView( { model: new Section() } ).render().$el;\n\t\t\t\t},\n\t\t\t\tstart: function() {\n\t\t\t\t\t$( '.llms-sections' ).addClass( 'dragging' );\n\t\t\t\t},\n\t\t\t\tstop: function() {\n\t\t\t\t\t$( '.llms-sections' ).removeClass( 'dragging' );\n\t\t\t\t},\n\t\t\t} );\n\n\t\t\t$( '#llms-new-lesson' ).draggable( {\n\t\t\t\t// appendTo: '#llms-sections .llms-section:first-child .llms-lessons',\n\t\t\t\tappendTo: '#llms-sections',\n\t\t\t\tcancel: false,\n\t\t\t\tconnectToSortable: '.llms-lessons',\n\t\t\t\thelper: function() {\n\t\t\t\t\treturn new LessonView( { model: new Lesson() } ).render().$el;\n\t\t\t\t},\n\t\t\t\tstart: function() {\n\n\t\t\t\t\t$( '.llms-lessons' ).addClass( 'dragging' );\n\n\t\t\t\t},\n\t\t\t\tstop: function() {\n\t\t\t\t\t$( '.llms-lessons' ).removeClass( 'dragging' );\n\t\t\t\t\t$( '.drag-expanded' ).removeClass( '.drag-expanded' );\n\t\t\t\t},\n\t\t\t} );\n\n\t\t},\n\n\t\tadd_new_section: function( event ) {\n\n\t\t\tevent.preventDefault();\n\t\t\tBackbone.pubSub.trigger( 'add-new-section' );\n\t\t},\n\n\t\tadd_new_lesson: function( event ) {\n\t\t\tevent.preventDefault();\n\t\t\tBackbone.pubSub.trigger( 'add-new-lesson' );\n\t\t},\n\n\t\t/**\n\t\t * Show the popover to add an existing lessons\n\t\t * @param object event JS Event OBject\n\t\t * @return void\n\t\t * @since 3.16.12\n\t\t * @version 3.16.12\n\t\t */\n\t\tadd_existing_lesson: function( event ) {\n\n\t\t\tevent.preventDefault();\n\n\t\t\tvar pop = new Popover( {\n\t\t\t\tel: '#llms-existing-lesson',\n\t\t\t\targs: {\n\t\t\t\t\tbackdrop: true,\n\t\t\t\t\tcloseable: true,\n\t\t\t\t\tcontainer: '.wrap.lifterlms.llms-builder',\n\t\t\t\t\tdismissible: true,\n\t\t\t\t\tplacement: 'left',\n\t\t\t\t\twidth: 480,\n\t\t\t\t\ttitle: LLMS.l10n.translate( 'Add Existing Lesson' ),\n\t\t\t\t\tcontent: new LessonSearch( {\n\t\t\t\t\t\tpost_type: 'lesson',\n\t\t\t\t\t\tsearching_message: LLMS.l10n.translate( 'Search for existing lessons...' ),\n\t\t\t\t\t} ).render().$el,\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\tpop.show();\n\t\t\tBackbone.pubSub.on( 'lesson-search-select', function() {\n\t\t\t\tpop.hide()\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * Disables lesson add buttons if no sections are available to add a lesson to\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tmaybe_disable_buttons: function() {\n\n\t\t\tvar $els = $( '#llms-new-lesson, #llms-existing-lesson' );\n\n\t\t\tif ( ! this.SidebarView.CourseView.model.get( 'sections' ).length ) {\n\t\t\t\t$els.attr( 'disabled', 'disabled' );\n\t\t\t} else {\n\t\t\t\t$els.removeAttr( 'disabled' );\n\t\t\t}\n\n\t\t},\n\n\t} );\n\n} );\n\n","/**\n * Sidebar Utilities View\n * @since 3.16.0\n * @version 3.16.0\n */\ndefine( 'Views/Utilities',[], function() {\n\n\treturn Backbone.View.extend( {\n\n\t\t/**\n\t\t * HTML element selector\n\t\t * @type {String}\n\t\t */\n\t\tel: '#llms-utilities',\n\n\t\tevents: {\n\t\t\t'click #llms-collapse-all': 'collapse_all',\n\t\t\t'click #llms-expand-all': 'expand_all'\n\t\t},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'div',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-utilities-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function() {\n\n\t\t\t// this.render();\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender: function() {\n\t\t\tthis.$el.html( this.template() );\n\t\t\treturn this;\n\t\t},\n\n\t\t/**\n\t\t * Collapse all sections\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tcollapse_all: function( event ) {\n\t\t\tevent.preventDefault();\n\t\t\tBackbone.pubSub.trigger( 'collapse-all' );\n\t\t},\n\n\t\t/**\n\t\t * Expand all sections\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\texpand_all: function( event ) {\n\t\t\tevent.preventDefault();\n\t\t\tBackbone.pubSub.trigger( 'expand-all' );\n\t\t},\n\n\t} );\n\n} );\n\n","/**\n * Main sidebar view\n * @since 3.16.0\n * @version 3.16.7\n */\ndefine( 'Views/Sidebar',[\n\t\t'Views/Editor',\n\t\t'Views/Elements',\n\t\t'Views/Utilities',\n\t\t'Views/_Subview'\n\t], function(\n\t\tEditor,\n\t\tElements,\n\t\tUtilities,\n\t\tSubview\n\t) {\n\n\treturn Backbone.View.extend( _.defaults( {\n\n\t\t/**\n\t\t * Current builder state\n\t\t * @type {String}\n\t\t */\n\t\tstate: 'builder', // [builder|editor]\n\n\t\t/**\n\t\t * Current Subviews\n\t\t * @type {Object}\n\t\t */\n\t\tviews: {\n\t\t\telements: {\n\t\t\t\tclass: Elements,\n\t\t\t\tinstance: null,\n\t\t\t\tstate: 'builder',\n\t\t\t},\n\t\t\tutilities: {\n\t\t\t\tclass: Utilities,\n\t\t\t\tinstance: null,\n\t\t\t\tstate: 'builder',\n\t\t\t},\n\t\t\teditor: {\n\t\t\t\tclass: Editor,\n\t\t\t\tinstance: null,\n\t\t\t\tstate: 'editor',\n\t\t\t},\n\t\t},\n\n\t\t/**\n\t\t * HTML element selector\n\t\t * @type {String}\n\t\t */\n\t\tel: '#llms-builder-sidebar',\n\n\t\t/**\n\t\t * DOM events\n\t\t * @type {Object}\n\t\t */\n\t\tevents: {\n\t\t\t'click #llms-save-button': 'save_now',\n\t\t\t'click #llms-exit-button': 'exit_now',\n\t\t\t'click .llms-builder-error': 'clear_errors',\n\t\t},\n\n\t\t/**\n\t\t * Wrapper Tag name\n\t\t * @type {String}\n\t\t */\n\t\ttagName: 'aside',\n\n\t\t/**\n\t\t * Get the underscore template\n\t\t * @type {[type]}\n\t\t */\n\t\ttemplate: wp.template( 'llms-sidebar-template' ),\n\n\t\t/**\n\t\t * Initialization callback func (renders the element on screen)\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tinitialize: function( data ) {\n\n\t\t\t// save a reference to the main Course view\n\t\t\tthis.CourseView = data.CourseView;\n\n\t\t\tthis.render();\n\n\t\t\tBackbone.pubSub.on( 'current-save-status', this.changes_made, this );\n\n\t\t\tBackbone.pubSub.on( 'heartbeat-send', this.heartbeat_send, this );\n\t\t\tBackbone.pubSub.on( 'heartbeat-tick', this.heartbeat_tick, this );\n\n\t\t\tBackbone.pubSub.on( 'lesson-selected', this.on_lesson_select, this );\n\t\t\tBackbone.pubSub.on( 'sidebar-editor-close', this.on_editor_close, this );\n\n\t\t\tthis.$saveButton = $( '#llms-save-button' );\n\n\t\t},\n\n\t\t/**\n\t\t * Compiles the template and renders the view\n\t\t * @return self (for chaining)\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\trender: function( view_data ) {\n\n\t\t\tview_data = view_data || {};\n\n\t\t\tthis.$el.html( this.template() );\n\n\t\t\tthis.render_subviews( _.extend( view_data, {\n\t\t\t\tSidebarView: this,\n\t\t\t} ) );\n\n\t\t\tvar $el = $( '.wrap.lifterlms.llms-builder' );\n\t\t\tif ( 'builder' === this.state ) {\n\t\t\t\t$el.removeClass( 'editor-active' );\n\t\t\t} else {\n\t\t\t\t$el.addClass( 'editor-active' );\n\t\t\t}\n\n\t\t\tthis.$saveButton = this.$el.find( '#llms-save-button' );\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\t/**\n\t\t * Adds error message element\n\t\t * @param {[type]} $err [description]\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tadd_error: function( $err ) {\n\n\t\t\tthis.$el.find( '.llms-builder-save' ).prepend( $err );\n\n\t\t},\n\n\t\t/**\n\t\t * Clear any existing error message elements\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tclear_errors: function() {\n\n\t\t\tthis.$el.find( '.llms-builder-save .llms-builder-error' ).remove();\n\n\t\t},\n\n\t\t/**\n\t\t * Update save status button when changes are detected\n\t\t * runs on an interval to check status of course regularly for unsaved changes\n\t\t * @param obj sync instance of the sync controller\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tchanges_made: function( sync ) {\n\n\t\t\t// if a save is currently running, don't do anything\n\t\t\tif ( sync.saving ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( sync.has_unsaved_changes ) {\n\n\t\t\t\tthis.$saveButton.attr( 'data-status', 'unsaved' );\n\t\t\t\tthis.$saveButton.removeAttr( 'disabled' );\n\n\t\t\t} else {\n\n\t\t\t\tthis.$saveButton.attr( 'data-status', 'saved' );\n\t\t\t\tthis.$saveButton.attr( 'disabled', 'disabled' );\n\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Exit the builder and return to the WP Course Editor\n\t\t * @return void\n\t\t * @since 3.16.7\n\t\t * @version 3.16.7\n\t\t */\n\t\texit_now: function() {\n\n\t\t\twindow.location.href = window.llms_builder.CourseModel.get_edit_post_link();\n\n\t\t},\n\n\t\t/**\n\t\t * Triggered when a heartbeat send event starts containing builder information\n\t\t * @param obj sync instance of the sync controller\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\theartbeat_send: function( sync ) {\n\n\t\t\tif ( sync.saving ) {\n\t\t\t\tLLMS.Spinner.start( this.$saveButton.find( 'i' ), 'small' );\n\t\t\t\tthis.$saveButton.attr( {\n\t\t\t\t\t'data-status': 'saving',\n\t\t\t\t\tdisabled: 'disabled',\n\t\t\t\t} );\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Triggered when a heartbeat tick completes and updates save status or appends errors\n\t\t * @param obj sync instance of the sync controller\n\t\t * @param obj data updated data\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\theartbeat_tick: function( sync, data ) {\n\n\t\t\tif ( ! sync.saving ) {\n\n\t\t\t\tvar status = 'saved';\n\n\t\t\t\tthis.clear_errors();\n\n\t\t\t\tif ( 'error' === data.status ) {\n\n\t\t\t\t\tstatus = 'error';\n\n\t\t\t\t\tvar msg = data.message,\n\t\t\t\t\t\t$err = $( ' ' );\n\n\t\t\t\t\tif ( 'object' === typeof msg ) {\n\t\t\t\t\t\t_.each( msg, function( txt ) {\n\t\t\t\t\t\t\t$err.append( '' + txt + ' ' );\n\t\t\t\t\t\t} );\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$err = $err.append( '' + msg + ' ' );;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.add_error( $err );\n\n\t\t\t\t}\n\n\t\t\t\tthis.$saveButton.find( '.llms-spinning' ).remove();\n\t\t\t\tthis.$saveButton.attr( {\n\t\t\t\t\t'data-status': status,\n\t\t\t\t\tdisabled: 'disabled',\n\t\t\t\t} );\n\n\t\t\t}\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if the editor is the currently active state\n\t\t * @return boolean\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tis_editor_active: function() {\n\n\t\t\treturn ( 'editor' === this.state );\n\n\t\t},\n\n\t\t/**\n\t\t * Triggered when the editor closes, updates state to be the course builder view\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\ton_editor_close: function() {\n\n\t\t\tthis.set_state( 'builder' ).render();\n\n\t\t},\n\n\t\t/**\n\t\t * When a lesson is selected, opens the sidebar to the editor view\n\t\t * @param obj lesson_model instance of the lesson model which was selected\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\ton_lesson_select: function( lesson_model, tab ) {\n\n\t\t\tif ( 'editor' !== this.state ) {\n\t\t\t\tthis.set_state( 'editor' );\n\t\t\t} else {\n\t\t\t\tthis.remove_subview( 'editor' );\n\t\t\t}\n\n\t\t\tthis.render( {\n\t\t\t\tmodel: lesson_model,\n\t\t\t\ttab: tab,\n\t\t\t} );\n\n\t\t},\n\n\t\t/**\n\t\t * Save button click event\n\t\t * @return void\n\t\t * @since 3.16.0\n\t\t * @version 3.16.0\n\t\t */\n\t\tsave_now: function() {\n\n\t\t\twindow.llms_builder.sync.save_now();\n\n\t\t},\n\n\t}, Subview ) );\n\n} );\n\n","/**\n * LifterLMS JS Builder App Bootstrap\n * @since 3.16.0\n * @version 3.17.8\n */\nrequire( [\n\t'vendor/backbone.collectionView',\n\t'vendor/backbone.trackit',\n\t'Controllers/Construct',\n\t'Controllers/Debug',\n\t'Controllers/Schemas',\n\t'Controllers/Sync',\n\t'Models/loader',\n\t'Views/Course',\n\t'Views/Sidebar'\n], function(\n\tCV,\n\tTrackIt,\n\tConstruct,\n\tDebug,\n\tSchemas,\n\tSync,\n\tModels,\n\tCourseView,\n\tSidebarView\n) {\n\n\twindow.llms_builder.debug = new Debug( window.llms_builder.debug );\n\twindow.llms_builder.construct = new Construct();\n\twindow.llms_builder.schemas = new Schemas( window.llms_builder.schemas );\n\n\t/**\n\t * Compare values, used by _.checked & _.selected mixins\n\t * @param mixed expected expected value, probably a string (the value of a select option or checkbox element)\n\t * @param mixed actual actual value, probably a string (the return of model.get( 'something' ) )\n\t * \t\t\t\t but could be an array like a multiselect\n\t * @return boolean\n\t * @since 3.17.2\n\t * @version 3.17.2\n\t */\n\tfunction value_compare( expected, actual ) {\n\t\treturn ( ( _.isArray( actual ) && -1 !== actual.indexOf( expected ) ) || expected == actual );\n\t};\n\n\t/**\n\t * Underscores templating utilities\n\t * @since 3.17.0\n\t * @version 3.17.8\n\t */\n\t_.mixin( {\n\n\t\t/**\n\t\t * Determine if two values are equal and output checked attribute if they are\n\t\t * Useful for templating checkboxes & radio elements\n\t\t * Like WP Core PHP checked() but in JS\n\t\t * @param mixed expected expected element value\n\t\t * @param mixed actual actual element value\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.2\n\t\t */\n\t\tchecked: function( expected, actual ) {\n\t\t\tif ( value_compare( expected, actual ) ) {\n\t\t\t\treturn ' checked=\"checked\"';\n\t\t\t}\n\t\t\treturn '';\n\t\t},\n\n\t\t/**\n\t\t * Recursively clone an object via _.clone()\n\t\t * @param obj obj object to clone\n\t\t * @return obj\n\t\t * @since 3.17.7\n\t\t * @version 3.17.7\n\t\t */\n\t\tdeepClone: function( obj ) {\n\n\t\t\tvar clone = _.clone( obj );\n\n\t\t\t_.each( clone, function( val, key ) {\n\t\t\t\tif ( ! _.isFunction( val ) && _.isObject( val ) ) {\n\t\t\t\t\tclone[ key ] = _.deepClone( val );\n\t\t\t\t};\n\t\t\t} );\n\n\t\t\treturn clone;\n\n\t\t},\n\n\t\t/**\n\t\t * Determine if two values are equal and output seleted attribute if they are\n\t\t * Useful for templating select elements\n\t\t * Like WP Core PHP selected() but in JS\n\t\t * @param mixed expected expected element value\n\t\t * @param mixed actual actual element value\n\t\t * @return void\n\t\t * @since 3.17.0\n\t\t * @version 3.17.2\n\t\t */\n\t\tselected: function( expected, actual ) {\n\t\t\tif ( value_compare( expected, actual ) ) {\n\t\t\t\treturn ' selected=\"selected\"';\n\t\t\t}\n\t\t\treturn '';\n\t\t},\n\n\t\t/**\n\t\t * Generic function for stripping HTML tags from a string\n\t\t * @param string content raw string\n\t\t * @param array allowed_tags array of allowed HTML tags\n\t\t * @return string\n\t\t * @since 3.17.8\n\t\t * @version 3.17.8\n\t\t */\n\t\tstripFormatting: function( content, allowed_tags ) {\n\n\t\t\tif ( ! allowed_tags ) {\n\t\t\t\tallowed_tags = [ 'b', 'i', 'u', 'strong', 'em' ];\n\t\t\t}\n\n\t\t\tvar $html = $( '' + content + '
' );\n\n\t\t\t$html.find( '*' ).not( allowed_tags.join( ',' ) ).each( function( ) {\n\n\t\t\t\t$( this ).replaceWith( this.innerHTML );\n\n\t\t\t} );\n\n\t\t\treturn $html.html();\n\n\t\t},\n\n\t} );\n\n\tBackbone.pubSub = _.extend( {}, Backbone.Events );\n\n\t$( document ).trigger( 'llms-builder-pre-init' );\n\n\twindow.llms_builder.questions = window.llms_builder.construct.get_collection( 'QuestionTypes', window.llms_builder.questions );\n\n\tvar CourseModel = window.llms_builder.construct.get_model( 'Course', window.llms_builder.course );\n\twindow.llms_builder.CourseModel = CourseModel;\n\n\twindow.llms_builder.sync = new Sync( CourseModel, window.llms_builder.sync );\n\n\tvar Course = new CourseView( {\n\t\tmodel: CourseModel,\n\t} );\n\n\tvar Sidebar = new SidebarView( {\n\t\tCourseView: Course\n\t} );\n\n\t$( document ).trigger( 'llms-builder-init', {\n\t\tcourse: Course,\n\t\tsidebar: Sidebar,\n\t} );\n\n} );\n\ndefine(\"main\", function(){});\n\n"]}
\ No newline at end of file