diff --git a/NEWS.md b/NEWS.md
index 4a68803f8..d23b8ce78 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -8,6 +8,8 @@
- Added a new quick restore option that restores both the last submitted exercise code and the output of that submission, if the output is available to be restored. This option is enabled by setting the global option `tutorial.quick_restore = 2` or the environment variable `TUTORIAL_QUICK_RESTORE=2`. This option augments the quick restore value when `TRUE` or `1`, wherein only the last submitted **code** is restored, such that users will need to click the "Submit" button to evaluate and see the output. (#794)
+- A new `exercise.pipe` tutorial or exercise chunk option can now be used to determine which pipe operator is used for interactive exercises. The default is `"|>"` (the native R pipe) when the tutorial is rendered with R >= 4.1.0, or `"%>%"` otherwise (the magrittr pipe). You can set the pipe used for the tutorial using `tutorial_options()`, or you can use `exercise.pipe` as a knitr chunk option on an individual exercise chunk. (#804)
+
# learnr 0.11.4
- Moved curl from Imports to Suggests. curl is only required when using an external evaluator (#776).
diff --git a/R/knitr-hooks.R b/R/knitr-hooks.R
index 27af9c1a0..94a0f121d 100644
--- a/R/knitr-hooks.R
+++ b/R/knitr-hooks.R
@@ -374,12 +374,16 @@ tutorial_knitr_options <- function() {
completion <- as.numeric(options$exercise.completion %||% 1 > 0)
diagnostics <- as.numeric(options$exercise.diagnostics %||% 1 > 0)
startover <- as.numeric(options$exercise.startover %||% 1 > 0)
- paste0('
');var p=e.children(".tutorial-exercise-output-frame"),f=$('
');f.attr("id",u("input"));var h=$('
');f.append(h);var y=$('
'),d=$('
');h.append(y),h.append(d),y.html(a);var g=$('
');f.append(g);function m(_,O,j,sr,K){var C=$(' ');C.append($(' ')),C.append(' '+j+" ");var Nt=navigator.platform.toUpperCase().indexOf("MAC")>=0,xr=j,ee=(Nt?"Cmd":"Ctrl")+"+Shift+Enter";return sr||(xr=xr+" ("+ee+")",C.attr("data-i18n-opts",'{"kbd": "'+ee+'"}')),C.attr("title",xr),C.attr("data-i18n",""),C.attr("data-i18n-attr-title","button."+K+"title"),sr&&C.attr("data-check","1"),C.attr("data-icon",_),C.on("click",function(){r.$removeSolution(e),r.$showExerciseProgress(n,C,!0)}),d.append(C),C}var S=m("fa-play","btn-success","Run Code",!1,"runcode");i.has_checker&&m("fa-check-square-o","btn-primary","Submit Answer",!0,"submitanswer");var E=$('
'),P=u("code-editor");E.attr("id",P),g.append(E),g.append(t),e.prepend(f);var T=$('
');T.attr("id",u("output")),p.append(T);var x=r.$attachAceEditor(P,o,i),M=null,V=e.attr("data-completion")==="1",H=e.attr("data-diagnostics")==="1",ur=e.attr("data-startover")==="1"?o:null,k=i.engine;k.toLowerCase()!=="r"&&(H=null),x.tutorial={label:n,engine:k,setup_code:M,completion:V,diagnostics:H,startover_code:ur};function B(_,O){var j=O.replace("Ctrl+","Command+");x.commands.addCommand({name:_,bindKey:{win:O,mac:j},exec:function(K){S.trigger("click")}})}B("execute1","Ctrl+Enter"),B("execute2","Ctrl+Shift+Enter");function R(_,O,j){typeof O=="string"&&(O={win:O,mac:O.replace("Ctrl+","Command+")}),typeof j=="string"&&(j={r:j,fallback:j}),x.commands.addCommand({name:_,bindKey:O,exec:function(K){j[K.tutorial.engine]?K.insert(j[K.tutorial.engine]):j.fallback&&K.insert(j.fallback)}})}var F=e.attr("data-pipe")||"%>%";R("insertPipe","Ctrl+Shift+M",{r:" "+F}),R("insertArrow","Alt+-",{r:" <- ",fallback:" = "}),S.on("click",function(){x.focus()});function Y(_){var O={indent:{win:"Tab",mac:"Tab"},outdent:{win:"Shift+Tab",mac:"Shift+Tab"}};["indent","outdent"].forEach(function(j){var sr=x.commands.byName[j];sr.bindKey=_?O[j]:null,x.commands.addCommand(sr)}),$(x.container).toggleClass("ace_indent_off",!_)}x.on("focus",function(){Y(!0)}),x.commands.addCommand({name:"escape",bindKey:{win:"Esc",mac:"Esc"},exec:function(){Y(!1)}});var Q=function(){var O=e.attr("data-lines");O&&O>0?x.setOptions({minLines:O,maxLines:O}):x.setOptions({minLines:r.kMinLines,maxLines:Math.max(Math.min(x.session.getLength(),15),r.kMinLines)})};Q(),x.getSession().on("change",Q),r.$addSolution(e,y,x),e.parents(".section").on("shown",function(){x.resize(!0)})})};b.prototype.$initializeExerciseSolutions=function(){var r=this;$(document).on("mouseup",function(e){var t=r.$exerciseContainer(e.target);t.length===0&&r.$forEachExercise(r.$removeSolution)})};b.prototype.$addSolution=function(r,e,t){var i=this,n=r.attr("data-label"),a=i.$exerciseSolutionCode(n),u=i.$exerciseHintsCode(n);u!==null&&a!==null&&(u.push(a),a=null);var o=i.$exerciseHintDiv(n);function s(S,E,P,T){var x=$(' ');if(x.attr("title",E),x.attr("data-i18n",""),x.addClass(P),x.append($(' ')),T){typeof T=="string"&&(T={key:T}),x.attr("data-i18n-attr-title",T.key+"title");var M=$(''.concat(E," "));M.attr("data-i18n",T.key),T.opts&&M.attr("data-i18n-opts",JSON.stringify(T.opts)),x.append(document.createTextNode(" ")),x.append(M),T.opts&&x.attr("data-i18n-opts",JSON.stringify(T.opts))}else x.append(" "+E);return e.append(x),x}function c(S,E){return E=E||"button.hint",s("fa-lightbulb-o",S,"btn-tutorial-hint",E)}function l(S){i.$recordEvent(n,"exercise_hint",{type:a!==null?"solution":"hint",index:S})}if(t.tutorial.startover_code!==null){var p=s("fa-refresh","Start Over","btn-tutorial-start-over","button.startover");p.on("click",function(){t.setValue(t.tutorial.startover_code,-1),i.$clearExerciseOutput(r)})}if(o!=null){o.addClass("tutorial-hint"),o.css("display","none");var f=c("Hint",{key:"button.hint",count:1});f.on("click",function(){l(0);var S=r.children(".tutorial-exercise-output-frame");if(S.find(".tutorial-hint").length===0){var E=$('
')),P=$('
')),T=o.clone().attr("id","").css("display","inherit");P.append(T),E.append(P),S.prepend(E)}else S.find(".tutorial-hint-panel").remove()})}else if(a||u){var h=a!==null,y=i.kMinLines;if(a)y=Math.max(i.$countLines(a),y);else for(var d=0;d1?"Hints":"Hint",h?{key:"button.solution",count:1}:{key:"button.hint",opts:{count:u.length}});m.on("click",function(S){l(g);var E=a!==null?a:u[g],P=m.parent().find("div.popover:visible").length>0;if(P){console.log("Removing hint popover",S),i.$removeSolution(r),t.focus();return}console.log("Revealing hint popover",S);var T=m.popover({placement:"top",template:'',content:E,container:m.parent(),boundary:$(".topics").get(0),viewport:$(".topics").get(0)}),x=!1;T.on("inserted.bs.popover",function(M){var V=this;if(!x){console.log("Instantiating hint popover",M);var H=i.isBS3?T.data("bs.popover").tip():$(window.bootstrap.Popover.getInstance(T).tip),ur=H.find(".popover-content"),k=i.$attachAceEditor(ur.get(0),E);k.setReadOnly(!0),k.setOption("minLines",Math.min(y,10)),k.setOption("maxLines",10),setTimeout(function(){HT(this,V),ur.parent().css("top","-".concat(ur.parent().height(),"px"))}.bind(this));var B=H.find(".popover-title");if(a===null&&u.length>1){var R=$(' '));R.append($('Next Hint ')),R.append(" "),R.append($(' ')),R.on("click",function(){g=g+1,k.setValue(u[g],-1),g===u.length-1&&(R.addClass("disabled"),R.prop("disabled",!0)),l(g)}),g===u.length-1&&(R.addClass("disabled"),R.prop("disabled",!0)),B.append(R)}var F=$(' '));F.append($(' ')),F.append(" "),F.append($('Copy to Clipboard ')),B.append(F);var Y=new ClipboardJS(F[0],{text:function(O){return k.getValue()}});Y.on("success",function(_){i.$removeSolution(r),t.focus()}),F.data("clipboard",Y),H.css("left","0");var Q=H.find(".arrow");Q.css("left",m.position().left+m.outerWidth()/2+"px"),H.trigger("i18n"),x=!0}}),m.on("shown.bs.popover",function(){var M=$(".tutorial-solution-popover");i.scrollIntoView(M),i.isBS3||window.bootstrap.Popover.getInstance(T).update()}),m.popover("show"),t.focus()})}};b.prototype.$removeSolution=function(r){var e=r.find(".btn-tutorial-copy-solution");if(e.length>0&&e.data("clipboard").destroy(),window.bootstrap){var t=r.find(".tutorial-solution-popover");if(!t.length)return;window.bootstrap.Popover.getInstance(t.get(0)).dispose()}else r.find(".tutorial-solution-popover").popover("destroy")};b.prototype.$initializeExerciseEvaluation=function(){var r=this;function e(a){return r.$exerciseContainer(a).attr("data-label")}function t(a){var u=r.$exerciseContainer(a)[0];r.scrollIntoView(u)}var i=new Shiny.InputBinding;$.extend(i,{find:function(u){return $(u).find(".tutorial-exercise-code-editor")},getValue:function(u){if(!this.clicked&&!this.restore)return null;var o={};o.label=e(u),o.should_check=this.should_check;var s=ace.edit($(u).attr("id"));return o.code=o.should_check?s.getSession().getValue():s.getSelectedText()||s.getSession().getValue(),o.restore=this.restore,o.timestamp=new Date().getTime(),o},setValue:function(u,o){var s=ace.edit($(u).attr("id"));s.getSession().setValue(o.code),this.runButtons(u).trigger("click"),window.shinytest&&setTimeout(function(){s.blur()},0)},getType:function(u){return"learnr.exercise"},subscribe:function(u,o){var s=this;this.runButtons(u).on("click.exerciseInputBinding",function(c){s.restore=!1,s.clicked=!0,s.should_check=c.delegateTarget.hasAttribute("data-check"),o(!0)}),$(u).on("restore.exerciseInputBinding",function(c,l){s.restore=!0,s.clicked=!1,s.should_check=l.should_check,o(!0)})},unsubscribe:function(u){this.runButtons(u).off(".exerciseInputBinding")},runButtons:function(u){var o=r.$exerciseContainer(u);return o.find(".btn-tutorial-run")},restore:!1,clicked:!1,check:!1}),Shiny.inputBindings.register(i,"tutorial.exerciseInput");var n=new Shiny.OutputBinding;$.extend(n,{find:function(u){return $(u).find(".tutorial-exercise-output")},onValueError:function(u,o){Shiny.unbindAll(u),this.renderError(u,o)},renderValue:function(u,o){r.$showExerciseProgress(e(u),null,!1),this.outputFrame(u).children().not($(u)).remove(),Shiny.renderContent(u,o),window.bootstrapStylePandocTables&&window.bootstrapStylePandocTables(),window.PagedTableDoc&&window.PagedTableDoc.initAll();var s=r.$exerciseContainer(u).data("restoring");s?r.$logTiming("restored-exercise-"+e(u)):(t(u),r.$exerciseContainer(u).data("restoring",!1))},showProgress:function(u,o){o&&r.$showExerciseProgress(e(u),null,o)},outputFrame:function(u){return $(u).closest(".tutorial-exercise-output-frame")}}),Shiny.outputBindings.register(n,"tutorial.exerciseOutput")};b.prototype.$clearExerciseOutput=function(r){var e=$(r).find(".tutorial-exercise-output-frame"),t=$(e).children(".tutorial-exercise-output");e.children().not(t).remove(),t.empty()};b.prototype.$initializeStorage=function(r,e){var t=this;if(!(typeof window.Promise!="undefined"&&typeof window.indexedDB!="undefined")){e({});return}var i="LearnrTutorialProgress",n="Store_"+window.btoa(r.tutorial_id+r.tutorial_version),a=function(l){l._dbp.then(function(p){p.close()})},u;try{var o=new window.idbKeyval.Store(i,n);a(o),u=!0}catch(c){u=!1}if(u===!1){e({});return}Shiny.addCustomMessageHandler("tutorial.store_object",function(c){var l=new window.idbKeyval.Store(i,n);window.idbKeyval.set(c.id,c.data,l).catch(function(p){console.error(p)}).finally(function(){a(l)})}),t.$removeState=function(c){var l=new window.idbKeyval.Store(i,n);window.idbKeyval.clear(l).then(c).catch(function(p){console.error(p),c()}).finally(function(){a(l)})};var s=new window.idbKeyval.Store(i,n);window.idbKeyval.keys(s).then(function(c){var l=c.map(function(p){return window.idbKeyval.get(p,s)});return Promise.all(l).then(function(p){var f={},h;for(h=0;h0&&function(){var l=ace.edit(c.attr("id"));l.setValue(o,-1),window.shinytest&&setTimeout(function(){l.blur()},0),e.$exerciseForLabel(u).data("restoring",!0),e.$showExerciseProgress(u,"run",!0),c.trigger("restore",{should_check:s})}()}}};b.prototype.$removeState=function(r){r()};b.prototype.$initializeClientState=function(r){var e=this,t={scroll_position:0,hash:""},i=this.$debounce(function(){var n={scroll_position:$(window).scrollTop(),hash:window.location.hash};(n.scroll_position!==t.scroll_position||n.hash!==t.hash)&&(e.$serverRequest("set_client_state",n,null),t=n)},1e3);$(window).scroll(i),window.addEventListener("popstate",i),!window.location.hash&&r.hash&&(window.location.hash=r.hash)};Shiny.addCustomMessageHandler("tutorial_isServerAvailable",function(r){na=!0});b.prototype.$initializeServer=function(){var r=this;r.$logTiming("wait-server-available");function e(){function t(i){setTimeout(function(){e()},i)}na?(r.$logTiming("server-available"),r.$serverRequest("initialize",{location:window.location},function(i){r.$logTiming("server-initialized"),r.$initializeStorage(i.identifiers,function(n){r.$logTiming("storage-initialized"),r.$restoreState(n)})})):t(250)}e()};window.Tutorial=b;})();
//# sourceMappingURL=tutorial.js.map
diff --git a/inst/lib/tutorial/tutorial.js.map b/inst/lib/tutorial/tutorial.js.map
index f34d553e1..69e19a5b2 100644
--- a/inst/lib/tutorial/tutorial.js.map
+++ b/inst/lib/tutorial/tutorial.js.map
@@ -1,7 +1,7 @@
{
"version": 3,
"sources": ["../../../learnr-js/tutorial/tutorial.js", "../../../learnr-js/tutorial/tutorial-diagnostics.mjs", "../../../learnr-js/tutorial/tutorial-autocompletion.mjs"],
- "sourcesContent": ["function _newArrowCheck(innerThis, boundThis) { if (innerThis !== boundThis) { throw new TypeError(\"Cannot instantiate an arrow function\"); } }\n\nimport \"core-js/modules/es.regexp.exec.js\";\nimport \"core-js/modules/es.string.replace.js\";\nimport \"core-js/modules/es.string.search.js\";\nimport \"core-js/modules/es.regexp.constructor.js\";\nimport \"core-js/modules/es.regexp.dot-all.js\";\nimport \"core-js/modules/es.regexp.sticky.js\";\nimport \"core-js/modules/es.regexp.to-string.js\";\nimport \"core-js/modules/es.array.find.js\";\nimport \"core-js/modules/es.object.to-string.js\";\nimport \"core-js/modules/es.array.splice.js\";\nimport \"core-js/modules/es.array.concat.js\";\nimport \"core-js/modules/es.json.stringify.js\";\nimport \"core-js/modules/es.string.split.js\";\nimport \"core-js/modules/es.string.match.js\";\nimport \"core-js/modules/es.array.slice.js\";\nimport \"core-js/modules/es.parse-float.js\";\nimport \"core-js/modules/es.regexp.test.js\";\nimport \"core-js/modules/es.object.assign.js\";\nimport \"core-js/modules/es.array.index-of.js\";\nimport \"core-js/modules/es.array.for-each.js\";\nimport \"core-js/modules/es.promise.js\";\nimport \"core-js/modules/es.promise.finally.js\";\nimport \"core-js/modules/es.array.iterator.js\";\nimport \"core-js/modules/web.dom-collections.iterator.js\";\nimport \"core-js/modules/es.array.map.js\";\nimport \"core-js/modules/es.string.iterator.js\";\nimport \"core-js/modules/es.error.cause.js\";\nimport \"core-js/modules/es.error.to-string.js\";\nimport { TutorialDiagnostics } from './tutorial-diagnostics.mjs';\nimport { TutorialCompleter } from './tutorial-autocompletion.mjs';\n$(document).ready(function () {\n var tutorial = new Tutorial();\n\n if (typeof TutorialCompleter !== 'undefined') {\n tutorial.$completer = new TutorialCompleter(tutorial);\n }\n\n if (typeof TutorialDiagnostics !== 'undefined') {\n tutorial.$diagnostics = new TutorialDiagnostics(tutorial);\n }\n\n window.tutorial = tutorial;\n});\nvar TUTORIAL_IS_SERVER_AVAILABLE = false;\n\nfunction Tutorial() {\n var thiz = this;\n this.$initTimingLog();\n this.isBS3 = !window.bootstrap;\n\n if (this.isBS3) {\n document.body.classList.add('tutorial-is-bs3');\n }\n\n this.onInit = function (handler) {\n this.$initCallbacks.add(handler);\n };\n\n this.onProgress = function (handler) {\n this.$progressCallbacks.add(handler);\n };\n\n this.startOver = function () {\n thiz.$removeState(function () {\n thiz.$serverRequest('remove_state', null, function () {\n window.location.replace(window.location.origin + window.location.pathname);\n });\n });\n };\n\n this.skipSection = function (sectionId) {\n if (TUTORIAL_IS_SERVER_AVAILABLE) {\n thiz.$serverRequest('section_skipped', {\n sectionId: sectionId\n }, null);\n }\n };\n\n this.scrollIntoView = function (element) {\n element = $(element);\n var rect = element[0].getBoundingClientRect();\n\n if (rect.top < 0 || rect.bottom > $(window).height()) {\n if (element[0].scrollIntoView) {\n element[0].scrollIntoView(false);\n document.body.scrollTop += 20;\n }\n }\n };\n\n thiz.$initializeVideos();\n thiz.$initializeExercises();\n thiz.$initializeServer();\n}\n\nTutorial.prototype.$initTimingLog = function () {\n try {\n if (performance.mark !== undefined) {\n performance.mark('tutorial-start-mark');\n }\n } catch (e) {\n console.log('Error initializing log timing: ' + e.message);\n }\n};\n\nTutorial.prototype.$logTiming = function (name) {\n try {\n if (performance.mark !== undefined && performance.measure !== undefined && performance.getEntriesByName !== undefined && this.queryVar('log-timings') === '1') {\n performance.mark(name + '-mark');\n performance.measure(name, 'tutorial-start-mark', name + '-mark');\n var entries = performance.getEntriesByName(name);\n console.log('(Timing) ' + name + ': ' + Math.round(entries[0].duration) + 'ms');\n }\n } catch (e) {\n console.log('Error logging timing: ' + e.message);\n }\n};\n\nTutorial.prototype.queryVar = function (name) {\n return decodeURI(window.location.search.replace(new RegExp('^(?:.*[&\\\\?]' + encodeURI(name).replace(/[.+*]/g, '\\\\$&') + '(?:\\\\=([^&]*))?)?.*$', 'i'), '$1'));\n};\n\nTutorial.prototype.$idSelector = function (id) {\n return '#' + id.replace(/(:|\\.|\\[|\\]|,|=|@)/g, '\\\\$1');\n};\n\nTutorial.triggerMathJax = function () {\n if (window.MathJax) {\n MathJax.Hub.Queue(['Typeset', MathJax.Hub]);\n }\n};\n\nTutorial.prototype.$initCallbacks = $.Callbacks();\n\nTutorial.prototype.$fireInit = function () {\n var thiz = this;\n\n try {\n thiz.$initCallbacks.fire();\n } catch (e) {\n console.log(e);\n }\n};\n\nTutorial.prototype.$progressCallbacks = $.Callbacks();\nTutorial.prototype.$progressEvents = [];\n\nTutorial.prototype.$hasCompletedProgressEvent = function (element) {\n var thiz = this;\n\n for (var e = 0; e < thiz.$progressEvents.length; e++) {\n var event = thiz.$progressEvents[e];\n\n if ($(event.element).is($(element))) {\n if (event.completed) {\n return true;\n }\n }\n }\n\n return false;\n};\n\nTutorial.prototype.$fireProgress = function (event) {\n this.$progressEvents.push(event);\n\n try {\n this.$progressCallbacks.fire(event);\n } catch (e) {\n console.log(e);\n }\n};\n\nTutorial.prototype.$fireSectionCompleted = function (element) {\n var thiz = this;\n\n function fireCompleted(el) {\n var event = {\n element: el,\n event: 'section_completed'\n };\n thiz.$fireProgress(event);\n }\n\n var section = $(element).parent().closest('.section');\n\n if (section.length === 0) {\n return;\n }\n\n var components = section.find('.tutorial-exercise, .tutorial-question, .tutorial-video');\n var allCompleted = true;\n\n for (var c = 0; c < components.length; c++) {\n var component = components.get(c);\n\n if (!thiz.$hasCompletedProgressEvent(component)) {\n allCompleted = false;\n break;\n }\n }\n\n if (allCompleted) {\n fireCompleted($(section).get(0));\n var previousSections = section.prevAll('.section');\n previousSections.each(function () {\n var components = $(this).find('.tutorial-exercise, .tutorial-question');\n\n if (components.length === 0) {\n fireCompleted(this);\n }\n });\n var parentSection = section.parent().closest('.section');\n\n if (parentSection.length > 0) {\n this.$fireSectionCompleted(section);\n }\n }\n};\n\nTutorial.prototype.$removeConflictingProgressEvents = function (progressEvent) {\n var thiz = this;\n var event;\n\n for (var i = thiz.$progressEvents.length - 1; i >= 0; i--) {\n event = thiz.$progressEvents[i];\n\n if (event.event === 'question_submission') {\n if (event.data.label === progressEvent.data.label & progressEvent.data.label !== undefined) {\n thiz.$progressEvents.splice(i, 1);\n return;\n }\n }\n }\n};\n\nTutorial.prototype.$fireProgressEvent = function (event, data) {\n var thiz = this;\n var progressEvent = {\n event: event,\n data: data\n };\n\n if (event === 'exercise_submission' || event === 'question_submission') {\n var element = $('.tutorial-exercise[data-label=\"' + data.label + '\"]').add('.tutorial-question[data-label=\"' + data.label + '\"]');\n\n if (element.length > 0) {\n progressEvent.element = element;\n\n if (event === 'exercise_submission') {\n progressEvent.completed = typeof data.completed !== 'undefined' ? data.completed : true;\n } else {\n progressEvent.completed = data.answer !== null;\n }\n }\n } else if (event === 'section_skipped') {\n var exerciseElement = $(thiz.$idSelector(data.sectionId));\n progressEvent.element = exerciseElement;\n progressEvent.completed = false;\n } else if (event === 'video_progress') {\n var videoElement = $('iframe[src=\"' + data.video_url + '\"]');\n\n if (videoElement.length > 0) {\n progressEvent.element = videoElement;\n progressEvent.completed = 2 * data.time > data.total_time;\n }\n }\n\n this.$removeConflictingProgressEvents(progressEvent);\n\n if (progressEvent.element) {\n this.$fireProgress(progressEvent);\n thiz.$fireSectionCompleted(progressEvent.element);\n }\n};\n\nTutorial.prototype.$initializeProgress = function (progressEvents) {\n var thiz = this;\n\n for (var i = 0; i < progressEvents.length; i++) {\n var progress = progressEvents[i];\n var progressEvent = progress.event;\n var progressEventData = {};\n\n if (progressEvent === 'exercise_submission') {\n progressEventData.label = progress.data.label;\n progressEventData.correct = progress.data.correct;\n } else if (progressEvent === 'question_submission') {\n progressEventData.label = progress.data.label;\n progressEventData.answer = progress.data.answer;\n } else if (progressEvent === 'section_skipped') {\n progressEventData.sectionId = progress.data.sectionId;\n } else if (progressEvent === 'video_progress') {\n progressEventData.video_url = progress.data.video_url;\n progressEventData.time = progress.data.time;\n progressEventData.total_time = progress.data.total_time;\n }\n\n thiz.$fireProgressEvent(progressEvent, progressEventData);\n }\n\n Shiny.addCustomMessageHandler('tutorial.progress_event', function (progress) {\n thiz.$fireProgressEvent(progress.event, progress.data);\n });\n};\n\nTutorial.prototype.$serverRequest = function (type, data, success, error) {\n var _Shiny$shinyapp$confi = Shiny.shinyapp.config,\n sessionId = _Shiny$shinyapp$confi.sessionId,\n workerId = _Shiny$shinyapp$confi.workerId;\n return $.ajax({\n type: 'POST',\n url: \"session/\".concat(sessionId, \"/dataobj/\").concat(type, \"?w=\").concat(workerId),\n contentType: 'application/json',\n data: JSON.stringify(data),\n dataType: 'json',\n success: success,\n error: error\n });\n};\n\nTutorial.prototype.$recordEvent = function (label, event, data) {\n var params = {\n label: label,\n event: event,\n data: data\n };\n this.$serverRequest('record_event', params, null);\n};\n\nTutorial.prototype.$countLines = function (str) {\n return str.split(/\\r\\n|\\r|\\n/).length;\n};\n\nTutorial.prototype.$injectScript = function (src, onload) {\n var script = document.createElement('script');\n script.src = src;\n var firstScriptTag = document.getElementsByTagName('script')[0];\n firstScriptTag.parentNode.insertBefore(script, firstScriptTag);\n $(script).on('load', onload);\n};\n\nTutorial.prototype.$debounce = function (func, wait, immediate) {\n var timeout;\n return function () {\n var context = this;\n var args = arguments;\n\n var later = function later() {\n timeout = null;\n if (!immediate) func.apply(context, args);\n };\n\n var callNow = immediate && !timeout;\n clearTimeout(timeout);\n timeout = setTimeout(later, wait);\n if (callNow) func.apply(context, args);\n };\n};\n\nTutorial.prototype.$initializeVideos = function () {\n var youtubeRegex = /^.*(youtu.be\\/|v\\/|u\\/\\w\\/|embed\\/|watch\\?v=|&v=)([^#&?]*).*/;\n var vimeoRegex = /(?:vimeo)\\.com.*(?:videos|video|channels|)\\/([\\d]+)/i;\n\n function isYouTubeVideo(src) {\n return src.match(youtubeRegex);\n }\n\n function isVimeoVideo(src) {\n return src.match(vimeoRegex);\n }\n\n function isVideo(src) {\n return isYouTubeVideo(src) || isVimeoVideo(src);\n }\n\n function normalizeVideoSrc(src) {\n var youtubeMatch = src.match(youtubeRegex);\n\n if (youtubeMatch) {\n return \"https://www.youtube.com/embed/\".concat(youtubeMatch[2], \"?enablejsapi=1\");\n }\n\n var vimeoMatch = src.match(vimeoRegex);\n\n if (vimeoMatch) {\n return \"https://player.vimeo.com/video/\".concat(vimeoMatch[1]);\n }\n\n return src;\n }\n\n function setContainerSize(container, width, height) {\n var aspectRatio = 9 / 16;\n\n if (!width) {\n width = '100%';\n }\n\n if (width.slice(-1) === '%') {\n container.css('width', width);\n\n if (!height) {\n height = 0;\n var paddingBottom = parseFloat(width) * aspectRatio + '%';\n container.css('padding-bottom', paddingBottom);\n }\n\n container.css('height', height);\n } else {\n if ($.isNumeric(width)) {\n width = width + 'px';\n }\n\n container.css('width', width);\n\n if (!height) {\n height = parseFloat(width) * aspectRatio + 'px';\n }\n\n container.css('height', height);\n }\n }\n\n $('img').each(function () {\n var videoSrc = $(this).attr('src');\n\n if (!isVideo(videoSrc)) {\n return;\n }\n\n $(this).css('display', 'none');\n var width = $(this).get(0).style.width;\n var height = $(this).get(0).style.height;\n $(this).css('width', '').css('height', '');\n var attrs = {};\n $.each(this.attributes, function (idex, attr) {\n switch (attr.nodeName) {\n case 'width':\n {\n width = String(attr.nodeValue);\n break;\n }\n\n case 'height':\n {\n height = String(attr.nodeValue);\n break;\n }\n\n case 'src':\n {\n attrs.src = normalizeVideoSrc(attr.nodeValue);\n break;\n }\n\n default:\n {\n attrs[attr.nodeName] = attr.nodeValue;\n }\n }\n });\n $(this).replaceWith(function () {\n var iframe = $('', attrs);\n iframe.addClass('tutorial-video');\n\n if (isYouTubeVideo(videoSrc)) {\n iframe.addClass('tutorial-video-youtube');\n } else if (isVimeoVideo(videoSrc)) {\n iframe.addClass('tutorial-video-vimeo');\n }\n\n iframe.attr('allowfullscreen', '');\n iframe.css('display', '');\n var container = $('
');\n setContainerSize(container, width, height);\n container.append(iframe);\n return container;\n });\n });\n this.$logTiming('initialized-videos');\n};\n\nTutorial.prototype.$initializeVideoPlayers = function (videoProgress) {\n if (/\\bQt\\//.test(window.navigator.userAgent)) {\n return;\n }\n\n this.$initializeYouTubePlayers(videoProgress);\n this.$initializeVimeoPlayers(videoProgress);\n};\n\nTutorial.prototype.$videoPlayerRestoreTime = function (src, videoProgress) {\n for (var v = 0; v < videoProgress.length; v++) {\n var id = videoProgress[v].id;\n\n if (src === id) {\n var time = videoProgress[v].data.time;\n var totalTime = videoProgress[v].data.total_time;\n\n if (time > 10 && totalTime - time > 10) {\n return time;\n }\n }\n }\n\n return 0;\n};\n\nTutorial.prototype.$initializeYouTubePlayers = function (videoProgress) {\n var thiz = this;\n var videos = $('iframe.tutorial-video-youtube');\n\n if (videos.length > 0) {\n this.$injectScript('https://www.youtube.com/iframe_api', function () {\n YT.ready(function () {\n videos.each(function () {\n var video = $(this);\n var videoUrl = video.attr('src');\n var player = null;\n var lastState = -1;\n\n function reportProgress() {\n thiz.$reportVideoProgress(videoUrl, player.getCurrentTime(), player.getDuration());\n }\n\n function restoreTime() {\n var restoreTime = thiz.$videoPlayerRestoreTime(videoUrl, videoProgress);\n\n if (restoreTime > 0) {\n player.mute();\n player.playVideo();\n setTimeout(function () {\n player.pauseVideo();\n player.seekTo(restoreTime, true);\n player.unMute();\n }, 2000);\n }\n }\n\n function onReady() {\n restoreTime();\n }\n\n function onStateChange() {\n var state = player.getPlayerState();\n var isNotStarted = state === -1;\n var isCued = state === YT.PlayerState.CUED;\n var isPlaying = state === YT.PlayerState.PLAYING;\n var isDuplicate = state === lastState;\n\n if (!(isNotStarted || isCued) && (isPlaying || isDuplicate)) {\n reportProgress();\n }\n\n lastState = state;\n }\n\n player = new YT.Player(this, {\n events: {\n onReady: onReady,\n onStateChange: onStateChange\n }\n });\n window.setInterval(onStateChange, 5000);\n });\n });\n });\n }\n};\n\nTutorial.prototype.$initializeVimeoPlayers = function (videoProgress) {\n var thiz = this;\n var videos = $('iframe.tutorial-video-vimeo');\n\n if (videos.length > 0) {\n this.$injectScript('https://player.vimeo.com/api/player.js', function () {\n videos.each(function () {\n var video = $(this);\n var videoUrl = video.attr('src');\n var player = new Vimeo.Player(this);\n var lastReportedTime = null;\n player.ready().then(function () {\n var restoreTime = thiz.$videoPlayerRestoreTime(videoUrl, videoProgress);\n\n if (restoreTime > 0) {\n player.getVolume().then(function (volume) {\n player.setCurrentTime(restoreTime).then(function () {\n player.pause().then(function () {\n player.setVolume(volume);\n });\n });\n });\n }\n });\n\n function reportProgress(data, throttle) {\n if (throttle === undefined) {\n throttle = false;\n }\n\n if (throttle && lastReportedTime != null && data.seconds - lastReportedTime < 5) {\n return;\n }\n\n thiz.$reportVideoProgress(videoUrl, data.seconds, data.duration);\n lastReportedTime = data.seconds;\n }\n\n player.on('play', reportProgress);\n player.on('pause', reportProgress);\n player.on('ended', reportProgress);\n player.on('timeupdate', function (data) {\n reportProgress(data, true);\n });\n });\n });\n }\n};\n\nTutorial.prototype.$reportVideoProgress = function (videoUrl, time, totalTime) {\n this.$serverRequest('video_progress', {\n video_url: videoUrl,\n time: time,\n total_time: totalTime\n });\n};\n\nTutorial.prototype.$initializeExercises = function () {\n this.$initializeExerciseEditors();\n this.$initializeExerciseSolutions();\n this.$initializeExerciseEvaluation();\n this.$logTiming('initialized-exercises');\n};\n\nTutorial.prototype.$exerciseForLabel = function (label) {\n return $('.tutorial-exercise[data-label=\"' + label + '\"]');\n};\n\nTutorial.prototype.$forEachExercise = function (operation) {\n return $('.tutorial-exercise').each(function () {\n var exercise = $(this);\n operation(exercise);\n });\n};\n\nTutorial.prototype.$exerciseSupportCode = function (label) {\n var selector = '.tutorial-exercise-support[data-label=\"' + label + '\"]';\n var code = $(selector).children('pre').children('code');\n\n if (code.length > 0) {\n return code.text();\n } else {\n return null;\n }\n};\n\nTutorial.prototype.$exerciseSolutionCode = function (label) {\n return this.$exerciseSupportCode(label + '-solution');\n};\n\nTutorial.prototype.$exerciseHintDiv = function (label) {\n var id = 'section-' + label + '-hint';\n var hintDiv = $('div#' + id);\n\n if (hintDiv.length > 0 && !hintDiv.hasClass('section')) {\n return hintDiv;\n } else {\n return null;\n }\n};\n\nTutorial.prototype.$exerciseHintsCode = function (label) {\n var hint = this.$exerciseSupportCode(label + '-hint');\n\n if (hint !== null) {\n return [hint];\n }\n\n var hints = [];\n var index = 1;\n\n while (true) {\n var hintLabel = label + '-hint-' + index++;\n hint = this.$exerciseSupportCode(hintLabel);\n\n if (hint !== null) {\n hints.push(hint);\n } else {\n break;\n }\n }\n\n if (hints.length > 0) {\n return hints;\n } else {\n return null;\n }\n};\n\nTutorial.prototype.$exerciseContainer = function (el) {\n return $(el).closest('.tutorial-exercise');\n};\n\nTutorial.prototype.$showExerciseProgress = function (label, button, show) {\n var exercise = this.$exerciseForLabel(label);\n var outputFrame = exercise.children('.tutorial-exercise-output-frame');\n var runButtons = exercise.find('.btn-tutorial-run');\n\n if (button === 'run') {\n button = exercise.find('.btn-tutorial-run').last();\n }\n\n var spinner = 'fa-spinner fa-spin fa-fw';\n\n if (show) {\n outputFrame.addClass('recalculating');\n runButtons.addClass('disabled');\n\n if (button !== null) {\n var runIcon = button.children('i');\n runIcon.removeClass(button.attr('data-icon'));\n runIcon.addClass(spinner);\n }\n } else {\n outputFrame.removeClass('recalculating');\n runButtons.removeClass('disabled');\n runButtons.each(function () {\n var button = $(this);\n var runIcon = button.children('i');\n runIcon.addClass(button.attr('data-icon'));\n runIcon.removeClass(spinner);\n });\n }\n};\n\nTutorial.prototype.kMinLines = 3;\n\nTutorial.prototype.$attachAceEditor = function (target, code, options) {\n var engineModes = {\n js: 'javascript'\n };\n var optsDefaults = {\n engine: 'r'\n };\n options = Object.assign({}, optsDefaults, options);\n options.engine = engineModes[options.engine] || options.engine;\n var editor = ace.edit(target);\n editor.setHighlightActiveLine(false);\n editor.setShowPrintMargin(false);\n editor.setShowFoldWidgets(false);\n editor.setBehavioursEnabled(true);\n editor.renderer.setDisplayIndentGuides(false);\n editor.setTheme('ace/theme/textmate');\n editor.$blockScrolling = Infinity;\n editor.session.setMode(\"ace/mode/\".concat(options.engine));\n editor.session.getSelection().clearSelection();\n editor.session.setNewLineMode('unix');\n editor.session.setTabSize(2);\n editor.setValue(code, -1);\n editor.setOptions({\n enableBasicAutocompletion: true\n });\n return editor;\n};\n\nTutorial.prototype.$exerciseEditor = function (label) {\n return this.$exerciseForLabel(label).find('.tutorial-exercise-code-editor');\n};\n\nTutorial.prototype.$initializeExerciseEditors = function () {\n var thiz = this;\n this.$forEachExercise(function (exercise) {\n var optsScript = exercise.children('script[data-ui-opts=\"1\"]').detach();\n var optsChunk = optsScript.length === 1 ? JSON.parse(optsScript.text()) : {};\n var label = exercise.attr('data-label');\n var caption = optsChunk.caption;\n\n function createId(suffix) {\n return 'tutorial-exercise-' + label + '-' + suffix;\n }\n\n exercise.on('focusin', function () {\n $('.btn-tutorial-solution').each(function () {\n if (exercise.has($(this)).length === 0) {\n thiz.$removeSolution(thiz.$exerciseContainer($(this)));\n }\n });\n });\n var code = '';\n var codeBlocks = exercise.children('pre.text, pre.lang-text');\n codeBlocks.each(function () {\n var codeElement = $(this).children('code');\n\n if (codeElement.length > 0) {\n code = code + codeElement.text();\n } else {\n code = code + $(this).text();\n }\n });\n codeBlocks.remove();\n var lines = code.split(/\\r\\n|\\r|\\n/).length;\n\n for (var i = lines; i < thiz.kMinLines; i++) {\n code = code + '\\n';\n }\n\n exercise.wrapInner('
');\n var outputFrame = exercise.children('.tutorial-exercise-output-frame');\n var inputDiv = $('
');\n inputDiv.attr('id', createId('input'));\n var panelHeading = $('
');\n inputDiv.append(panelHeading);\n var panelHeadingLeft = $('
');\n var panelHeadingRight = $('
');\n panelHeading.append(panelHeadingLeft);\n panelHeading.append(panelHeadingRight);\n panelHeadingLeft.html(caption);\n var panelBody = $('
');\n inputDiv.append(panelBody);\n\n function addSubmitButton(icon, style, text, check, datai18n) {\n var button = $(' ');\n button.append($(' '));\n button.append(' ' + '' + text + ' ');\n var isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0;\n var title = text;\n var kbdText = (isMac ? 'Cmd' : 'Ctrl') + '+Shift+Enter';\n\n if (!check) {\n title = title + ' (' + kbdText + ')';\n button.attr('data-i18n-opts', '{\"kbd\": \"' + kbdText + '\"}');\n }\n\n button.attr('title', title);\n button.attr('data-i18n', '');\n button.attr('data-i18n-attr-title', 'button.' + datai18n + 'title');\n\n if (check) {\n button.attr('data-check', '1');\n }\n\n button.attr('data-icon', icon);\n button.on('click', function () {\n thiz.$removeSolution(exercise);\n thiz.$showExerciseProgress(label, button, true);\n });\n panelHeadingRight.append(button);\n return button;\n }\n\n var runButton = addSubmitButton('fa-play', 'btn-success', 'Run Code', false, 'runcode');\n\n if (optsChunk.has_checker) {\n addSubmitButton('fa-check-square-o', 'btn-primary', 'Submit Answer', true, 'submitanswer');\n }\n\n var codeDiv = $('
');\n var codeDivId = createId('code-editor');\n codeDiv.attr('id', codeDivId);\n panelBody.append(codeDiv);\n panelBody.append(optsScript);\n exercise.prepend(inputDiv);\n var outputDiv = $('
');\n outputDiv.attr('id', createId('output'));\n outputFrame.append(outputDiv);\n var editor = thiz.$attachAceEditor(codeDivId, code, optsChunk);\n var setupCode = null;\n var completion = exercise.attr('data-completion') === '1';\n var diagnostics = exercise.attr('data-diagnostics') === '1';\n var startoverCode = exercise.attr('data-startover') === '1' ? code : null;\n var engine = optsChunk.engine;\n\n if (engine.toLowerCase() !== 'r') {\n diagnostics = null;\n }\n\n editor.tutorial = {\n label: label,\n engine: engine,\n setup_code: setupCode,\n completion: completion,\n diagnostics: diagnostics,\n startover_code: startoverCode\n };\n\n function bindExecutionKey(name, key) {\n var macKey = key.replace('Ctrl+', 'Command+');\n editor.commands.addCommand({\n name: name,\n bindKey: {\n win: key,\n mac: macKey\n },\n exec: function exec(editor) {\n runButton.trigger('click');\n }\n });\n }\n\n bindExecutionKey('execute1', 'Ctrl+Enter');\n bindExecutionKey('execute2', 'Ctrl+Shift+Enter');\n\n function bindInsertKey(name, keys, text) {\n if (typeof keys === 'string') {\n keys = {\n win: keys,\n mac: keys.replace('Ctrl+', 'Command+')\n };\n }\n\n if (typeof text === 'string') {\n text = {\n r: text,\n fallback: text\n };\n }\n\n editor.commands.addCommand({\n name: name,\n bindKey: keys,\n exec: function exec(editor) {\n if (text[editor.tutorial.engine]) {\n editor.insert(text[editor.tutorial.engine]);\n } else if (text.fallback) {\n editor.insert(text.fallback);\n }\n }\n });\n }\n\n bindInsertKey('insertPipe', 'Ctrl+Shift+M', {\n r: ' %>% '\n });\n bindInsertKey('insertArrow', 'Alt+-', {\n r: ' <- ',\n fallback: ' = '\n });\n runButton.on('click', function () {\n editor.focus();\n });\n\n function toggleTabCommands(enable) {\n var tabCommandKeys = {\n indent: {\n win: 'Tab',\n mac: 'Tab'\n },\n outdent: {\n win: 'Shift+Tab',\n mac: 'Shift+Tab'\n }\n };\n ['indent', 'outdent'].forEach(function (name) {\n var command = editor.commands.byName[name];\n command.bindKey = enable ? tabCommandKeys[name] : null;\n editor.commands.addCommand(command);\n });\n $(editor.container).toggleClass('ace_indent_off', !enable);\n }\n\n editor.on('focus', function () {\n toggleTabCommands(true);\n });\n editor.commands.addCommand({\n name: 'escape',\n bindKey: {\n win: 'Esc',\n mac: 'Esc'\n },\n exec: function exec() {\n toggleTabCommands(false);\n }\n });\n\n var updateAceHeight = function updateAceHeight() {\n var lines = exercise.attr('data-lines');\n\n if (lines && lines > 0) {\n editor.setOptions({\n minLines: lines,\n maxLines: lines\n });\n } else {\n editor.setOptions({\n minLines: thiz.kMinLines,\n maxLines: Math.max(Math.min(editor.session.getLength(), 15), thiz.kMinLines)\n });\n }\n };\n\n updateAceHeight();\n editor.getSession().on('change', updateAceHeight);\n thiz.$addSolution(exercise, panelHeadingLeft, editor);\n exercise.parents('.section').on('shown', function () {\n editor.resize(true);\n });\n });\n};\n\nTutorial.prototype.$initializeExerciseSolutions = function () {\n var thiz = this;\n $(document).on('mouseup', function (ev) {\n var exercise = thiz.$exerciseContainer(ev.target);\n\n if (exercise.length === 0) {\n thiz.$forEachExercise(thiz.$removeSolution);\n }\n });\n};\n\nTutorial.prototype.$addSolution = function (exercise, panelHeading, editor) {\n var thiz = this;\n var label = exercise.attr('data-label');\n var solution = thiz.$exerciseSolutionCode(label);\n var hints = thiz.$exerciseHintsCode(label);\n\n if (hints !== null && solution !== null) {\n hints.push(solution);\n solution = null;\n }\n\n var hintDiv = thiz.$exerciseHintDiv(label);\n\n function addHelperButton(icon, caption, classBtn, datai18n) {\n var button = $(' ');\n button.attr('title', caption);\n button.attr('data-i18n', '');\n button.addClass(classBtn);\n button.append($(' '));\n\n if (datai18n) {\n if (typeof datai18n === 'string') {\n datai18n = {\n key: datai18n\n };\n }\n\n button.attr('data-i18n-attr-title', datai18n.key + 'title');\n var buttonText = $(\"\".concat(caption, \" \"));\n buttonText.attr('data-i18n', datai18n.key);\n\n if (datai18n.opts) {\n buttonText.attr('data-i18n-opts', JSON.stringify(datai18n.opts));\n }\n\n button.append(document.createTextNode(' '));\n button.append(buttonText);\n\n if (datai18n.opts) {\n button.attr('data-i18n-opts', JSON.stringify(datai18n.opts));\n }\n } else {\n button.append(' ' + caption);\n }\n\n panelHeading.append(button);\n return button;\n }\n\n function addHintButton(caption, datai18n) {\n datai18n = datai18n || 'button.hint';\n return addHelperButton('fa-lightbulb-o', caption, 'btn-tutorial-hint', datai18n);\n }\n\n function recordHintRequest(index) {\n thiz.$recordEvent(label, 'exercise_hint', {\n type: solution !== null ? 'solution' : 'hint',\n index: index\n });\n }\n\n if (editor.tutorial.startover_code !== null) {\n var startOverButton = addHelperButton('fa-refresh', 'Start Over', 'btn-tutorial-start-over', 'button.startover');\n startOverButton.on('click', function () {\n editor.setValue(editor.tutorial.startover_code, -1);\n thiz.$clearExerciseOutput(exercise);\n });\n }\n\n if (hintDiv != null) {\n hintDiv.addClass('tutorial-hint');\n hintDiv.css('display', 'none');\n var button = addHintButton('Hint', {\n key: 'button.hint',\n count: 1\n });\n button.on('click', function () {\n recordHintRequest(0);\n var outputFrame = exercise.children('.tutorial-exercise-output-frame');\n\n if (outputFrame.find('.tutorial-hint').length === 0) {\n var panel = $(\"
\"));\n var panelBody = $(\"
\"));\n var hintDivClone = hintDiv.clone().attr('id', '').css('display', 'inherit');\n panelBody.append(hintDivClone);\n panel.append(panelBody);\n outputFrame.prepend(panel);\n } else {\n outputFrame.find('.tutorial-hint-panel').remove();\n }\n });\n } else if (solution || hints) {\n var isSolution = solution !== null;\n var editorLines = thiz.kMinLines;\n\n if (solution) {\n editorLines = Math.max(thiz.$countLines(solution), editorLines);\n } else {\n for (var i = 0; i < hints.length; i++) {\n editorLines = Math.max(thiz.$countLines(hints[i]), editorLines);\n }\n }\n\n var hintIndex = 0;\n\n var _button = addHintButton(isSolution ? 'Solution' : hints.length > 1 ? 'Hints' : 'Hint', isSolution ? {\n key: 'button.solution',\n count: 1\n } : {\n key: 'button.hint',\n opts: {\n count: hints.length\n }\n });\n\n _button.on('click', function (ev) {\n recordHintRequest(hintIndex);\n var solutionText = solution !== null ? solution : hints[hintIndex];\n var visible = _button.parent().find('div.popover:visible').length > 0;\n\n if (visible) {\n console.log('Removing hint popover', ev);\n thiz.$removeSolution(exercise);\n editor.focus();\n return;\n }\n\n console.log('Revealing hint popover', ev);\n\n var popover = _button.popover({\n placement: 'top',\n template: '',\n content: solutionText,\n container: _button.parent(),\n boundary: $('.topics').get(0),\n viewport: $('.topics').get(0)\n });\n\n var popoverIsInserted = false;\n popover.on('inserted.bs.popover', function (ev) {\n var _this = this;\n\n if (popoverIsInserted) return;\n console.log('Instantiating hint popover', ev);\n var popoverTip = thiz.isBS3 ? popover.data('bs.popover').tip() : $(window.bootstrap.Popover.getInstance(popover).tip);\n var content = popoverTip.find('.popover-content');\n var solutionEditor = thiz.$attachAceEditor(content.get(0), solutionText);\n solutionEditor.setReadOnly(true);\n solutionEditor.setOption('minLines', Math.min(editorLines, 10));\n solutionEditor.setOption('maxLines', 10);\n setTimeout(function () {\n _newArrowCheck(this, _this);\n\n content.parent().css('top', \"-\".concat(content.parent().height(), \"px\"));\n }.bind(this));\n var popoverTitle = popoverTip.find('.popover-title');\n\n if (solution === null && hints.length > 1) {\n var nextHintButton = $(\" \"));\n nextHintButton.append($('Next Hint '));\n nextHintButton.append(' ');\n nextHintButton.append($(' '));\n nextHintButton.on('click', function () {\n hintIndex = hintIndex + 1;\n solutionEditor.setValue(hints[hintIndex], -1);\n\n if (hintIndex === hints.length - 1) {\n nextHintButton.addClass('disabled');\n nextHintButton.prop('disabled', true);\n }\n\n recordHintRequest(hintIndex);\n });\n\n if (hintIndex === hints.length - 1) {\n nextHintButton.addClass('disabled');\n nextHintButton.prop('disabled', true);\n }\n\n popoverTitle.append(nextHintButton);\n }\n\n var copyButton = $(\" \"));\n copyButton.append($(' '));\n copyButton.append(' ');\n copyButton.append($('Copy to Clipboard '));\n popoverTitle.append(copyButton);\n var clipboard = new ClipboardJS(copyButton[0], {\n text: function text(trigger) {\n return solutionEditor.getValue();\n }\n });\n clipboard.on('success', function (e) {\n thiz.$removeSolution(exercise);\n editor.focus();\n });\n copyButton.data('clipboard', clipboard);\n popoverTip.css('left', '0');\n var popoverArrow = popoverTip.find('.arrow');\n popoverArrow.css('left', _button.position().left + _button.outerWidth() / 2 + 'px');\n popoverTip.trigger('i18n');\n popoverIsInserted = true;\n });\n\n _button.on('shown.bs.popover', function () {\n var popoverElement = $('.tutorial-solution-popover');\n thiz.scrollIntoView(popoverElement);\n\n if (!thiz.isBS3) {\n window.bootstrap.Popover.getInstance(popover).update();\n }\n });\n\n _button.popover('show');\n\n editor.focus();\n });\n }\n};\n\nTutorial.prototype.$removeSolution = function (exercise) {\n var solutionButton = exercise.find('.btn-tutorial-copy-solution');\n\n if (solutionButton.length > 0) {\n solutionButton.data('clipboard').destroy();\n }\n\n if (window.bootstrap) {\n var popover = exercise.find('.tutorial-solution-popover');\n if (!popover.length) return;\n window.bootstrap.Popover.getInstance(popover.get(0)).dispose();\n } else {\n exercise.find('.tutorial-solution-popover').popover('destroy');\n }\n};\n\nTutorial.prototype.$initializeExerciseEvaluation = function () {\n var thiz = this;\n\n function exerciseLabel(el) {\n return thiz.$exerciseContainer(el).attr('data-label');\n }\n\n function ensureExerciseVisible(el) {\n var exerciseEl = thiz.$exerciseContainer(el)[0];\n thiz.scrollIntoView(exerciseEl);\n }\n\n var exerciseInputBinding = new Shiny.InputBinding();\n $.extend(exerciseInputBinding, {\n find: function find(scope) {\n return $(scope).find('.tutorial-exercise-code-editor');\n },\n getValue: function getValue(el) {\n if (!this.clicked && !this.restore) {\n return null;\n }\n\n var value = {};\n value.label = exerciseLabel(el);\n value.should_check = this.should_check;\n var editor = ace.edit($(el).attr('id'));\n value.code = value.should_check ? editor.getSession().getValue() : editor.getSelectedText() || editor.getSession().getValue();\n value.restore = this.restore;\n value.timestamp = new Date().getTime();\n return value;\n },\n setValue: function setValue(el, value) {\n var editor = ace.edit($(el).attr('id'));\n editor.getSession().setValue(value.code);\n this.runButtons(el).trigger('click');\n\n if (window.shinytest) {\n setTimeout(function () {\n editor.blur();\n }, 0);\n }\n },\n getType: function getType(el) {\n return 'learnr.exercise';\n },\n subscribe: function subscribe(el, callBack) {\n var binding = this;\n this.runButtons(el).on('click.exerciseInputBinding', function (ev) {\n binding.restore = false;\n binding.clicked = true;\n binding.should_check = ev.delegateTarget.hasAttribute('data-check');\n callBack(true);\n });\n $(el).on('restore.exerciseInputBinding', function (ev, options) {\n binding.restore = true;\n binding.clicked = false;\n binding.should_check = options.should_check;\n callBack(true);\n });\n },\n unsubscribe: function unsubscribe(el) {\n this.runButtons(el).off('.exerciseInputBinding');\n },\n runButtons: function runButtons(el) {\n var exercise = thiz.$exerciseContainer(el);\n return exercise.find('.btn-tutorial-run');\n },\n restore: false,\n clicked: false,\n check: false\n });\n Shiny.inputBindings.register(exerciseInputBinding, 'tutorial.exerciseInput');\n var exerciseOutputBinding = new Shiny.OutputBinding();\n $.extend(exerciseOutputBinding, {\n find: function find(scope) {\n return $(scope).find('.tutorial-exercise-output');\n },\n onValueError: function onValueError(el, err) {\n Shiny.unbindAll(el);\n this.renderError(el, err);\n },\n renderValue: function renderValue(el, data) {\n thiz.$showExerciseProgress(exerciseLabel(el), null, false);\n this.outputFrame(el).children().not($(el)).remove();\n Shiny.renderContent(el, data);\n\n if (window.bootstrapStylePandocTables) {\n window.bootstrapStylePandocTables();\n }\n\n if (window.PagedTableDoc) {\n window.PagedTableDoc.initAll();\n }\n\n var restoring = thiz.$exerciseContainer(el).data('restoring');\n\n if (!restoring) {\n ensureExerciseVisible(el);\n thiz.$exerciseContainer(el).data('restoring', false);\n } else {\n thiz.$logTiming('restored-exercise-' + exerciseLabel(el));\n }\n },\n showProgress: function showProgress(el, show) {\n if (show) {\n thiz.$showExerciseProgress(exerciseLabel(el), null, show);\n } else {}\n },\n outputFrame: function outputFrame(el) {\n return $(el).closest('.tutorial-exercise-output-frame');\n }\n });\n Shiny.outputBindings.register(exerciseOutputBinding, 'tutorial.exerciseOutput');\n};\n\nTutorial.prototype.$clearExerciseOutput = function (exercise) {\n var outputFrame = $(exercise).find('.tutorial-exercise-output-frame');\n var outputDiv = $(outputFrame).children('.tutorial-exercise-output');\n outputFrame.children().not(outputDiv).remove();\n outputDiv.empty();\n};\n\nTutorial.prototype.$initializeStorage = function (identifiers, success) {\n var thiz = this;\n\n if (!(typeof window.Promise !== 'undefined' && typeof window.indexedDB !== 'undefined')) {\n success({});\n return;\n }\n\n var dbName = 'LearnrTutorialProgress';\n var storeName = 'Store_' + window.btoa(identifiers.tutorial_id + identifiers.tutorial_version);\n\n var closeStore = function closeStore(store) {\n store._dbp.then(function (db) {\n db.close();\n });\n };\n\n var storeCreated;\n\n try {\n var testStore = new window.idbKeyval.Store(dbName, storeName);\n closeStore(testStore);\n storeCreated = true;\n } catch (error) {\n storeCreated = false;\n }\n\n if (storeCreated === false) {\n success({});\n return;\n }\n\n Shiny.addCustomMessageHandler('tutorial.store_object', function (message) {\n var idbStoreSet = new window.idbKeyval.Store(dbName, storeName);\n window.idbKeyval.set(message.id, message.data, idbStoreSet)[\"catch\"](function (err) {\n console.error(err);\n })[\"finally\"](function () {\n closeStore(idbStoreSet);\n });\n });\n\n thiz.$removeState = function (completed) {\n var idbStoreClear = new window.idbKeyval.Store(dbName, storeName);\n window.idbKeyval.clear(idbStoreClear).then(completed)[\"catch\"](function (err) {\n console.error(err);\n completed();\n })[\"finally\"](function () {\n closeStore(idbStoreClear);\n });\n };\n\n var idbStoreGet = new window.idbKeyval.Store(dbName, storeName);\n window.idbKeyval.keys(idbStoreGet).then(function (keys) {\n var getPromises = keys.map(function (key) {\n return window.idbKeyval.get(key, idbStoreGet);\n });\n return Promise.all(getPromises).then(function (vals) {\n var ret = {};\n var i;\n\n for (i = 0; i < keys.length; i++) {\n ret[keys[i]] = vals[i];\n }\n\n return ret;\n });\n }).then(function (objs) {\n success(objs);\n })[\"catch\"](function (err) {\n console.error(err);\n success({});\n })[\"finally\"](function () {\n closeStore(idbStoreGet);\n });\n};\n\nTutorial.prototype.$restoreState = function (objects) {\n var thiz = this;\n thiz.$logTiming('restoring-state');\n this.$serverRequest('restore_state', objects, function (data) {\n thiz.$logTiming('state-received');\n thiz.$initializeClientState(data.client_state);\n thiz.$fireInit();\n thiz.$initializeProgress(data.progress_events);\n thiz.$restoreSubmissions(data.submissions);\n thiz.$initializeVideoPlayers(data.video_progress);\n });\n};\n\nTutorial.prototype.$restoreSubmissions = function (submissions) {\n var thiz = this;\n\n for (var i = 0; i < submissions.length; i++) {\n var submission = submissions[i];\n var type = submission.type;\n var id = submission.id;\n\n if (type === 'exercise_submission') {\n var label = id;\n var code = submission.data.code;\n var checked = submission.data.checked;\n thiz.$logTiming('restoring-exercise-' + label);\n var editorContainer = thiz.$exerciseEditor(label);\n\n if (editorContainer.length > 0) {\n (function () {\n var editor = ace.edit(editorContainer.attr('id'));\n editor.setValue(code, -1);\n\n if (window.shinytest) {\n setTimeout(function () {\n editor.blur();\n }, 0);\n }\n\n thiz.$exerciseForLabel(label).data('restoring', true);\n thiz.$showExerciseProgress(label, 'run', true);\n editorContainer.trigger('restore', {\n should_check: checked\n });\n })();\n }\n }\n }\n};\n\nTutorial.prototype.$removeState = function (completed) {\n completed();\n};\n\nTutorial.prototype.$initializeClientState = function (clientState) {\n var thiz = this;\n var clientStateLast = {\n scroll_position: 0,\n hash: ''\n };\n var maybePersistClientState = this.$debounce(function () {\n var clientStateCurrent = {\n scroll_position: $(window).scrollTop(),\n hash: window.location.hash\n };\n\n if (clientStateCurrent.scroll_position !== clientStateLast.scroll_position || clientStateCurrent.hash !== clientStateLast.hash) {\n thiz.$serverRequest('set_client_state', clientStateCurrent, null);\n clientStateLast = clientStateCurrent;\n }\n }, 1000);\n $(window).scroll(maybePersistClientState);\n window.addEventListener('popstate', maybePersistClientState);\n\n if (!window.location.hash && clientState.hash) {\n window.location.hash = clientState.hash;\n }\n};\n\nShiny.addCustomMessageHandler('tutorial_isServerAvailable', function (message) {\n TUTORIAL_IS_SERVER_AVAILABLE = true;\n});\n\nTutorial.prototype.$initializeServer = function () {\n var thiz = this;\n thiz.$logTiming('wait-server-available');\n\n function initializeServer() {\n function retry(delay) {\n setTimeout(function () {\n initializeServer();\n }, delay);\n }\n\n if (TUTORIAL_IS_SERVER_AVAILABLE) {\n thiz.$logTiming('server-available');\n thiz.$serverRequest('initialize', {\n location: window.location\n }, function (response) {\n thiz.$logTiming('server-initialized');\n thiz.$initializeStorage(response.identifiers, function (objects) {\n thiz.$logTiming('storage-initialized');\n thiz.$restoreState(objects);\n });\n });\n } else {\n retry(250);\n }\n }\n\n initializeServer();\n};\n\nwindow.Tutorial = Tutorial;", "import \"core-js/modules/es.array.filter.js\";\nimport \"core-js/modules/es.object.to-string.js\";\nimport \"core-js/modules/es.regexp.exec.js\";\nimport \"core-js/modules/es.regexp.test.js\";\nexport function TutorialDiagnostics(tutorial) {\n this.$tutorial = tutorial;\n var self = this;\n\n var unmatchedClosingBracket = function unmatchedClosingBracket(token) {\n return {\n row: token.position.row,\n column: token.position.column,\n type: 'error',\n text: \"unmatched closing bracket '\" + token.value + \"'\"\n };\n };\n\n var unmatchedOpeningBracket = function unmatchedOpeningBracket(token) {\n return {\n row: token.position.row,\n column: token.position.column,\n type: 'error',\n text: \"unmatched opening bracket '\" + token.value + \"'\"\n };\n };\n\n var unexpected = function unexpected(symbol, token, type) {\n return {\n row: token.position.row,\n column: token.position.column,\n type: type || 'error',\n text: 'unexpected ' + symbol + \" '\" + token.value + \"'\"\n };\n };\n\n var isSymbol = function isSymbol(token) {\n var value = token.value || '';\n\n if (value === 'in') {\n return false;\n }\n\n var type = token.type || '';\n return type === 'string' || type === 'constant.numeric' || type === 'constant.language.boolean' || type === 'identifier' || type === 'keyword' || type === 'variable.language';\n };\n\n var isOperator = function isOperator(token) {\n var type = token.type || '';\n return type === 'keyword.operator';\n };\n\n var isUnaryOperator = function isUnaryOperator(token) {\n var value = token.value || '';\n return value === '+' || value === '-' || value === '~' || value === '!' || value === '?';\n };\n\n var diagnose = function diagnose() {\n var editor = this;\n\n var Tokenizer = ace.require('ace/tokenizer').Tokenizer;\n\n var RHighlightRules = ace.require('ace/mode/r_highlight_rules').RHighlightRules;\n\n var rules = new RHighlightRules().getRules();\n\n for (var key in rules) {\n var rule = rules[key];\n\n for (var i = 0; i < rule.length; i++) {\n rule[i].merge = false;\n }\n }\n\n rules.start.unshift({\n token: 'string',\n regex: '\"(?:(?:\\\\\\\\.)|(?:[^\"\\\\\\\\]))*?\"',\n merge: false,\n next: 'start'\n });\n rules.start.unshift({\n token: 'string',\n regex: \"'(?:(?:\\\\\\\\.)|(?:[^'\\\\\\\\]))*?'\",\n merge: false,\n next: 'start'\n });\n rules.start.unshift({\n token: 'keyword.operator',\n regex: ':::|::|:=|%%|>=|<=|==|!=|\\\\|>|\\\\->|<\\\\-|<<\\\\-|\\\\|\\\\||&&|=|\\\\+|\\\\-|\\\\*\\\\*?|/|\\\\^|>|<|!|&|\\\\||~|\\\\$|:|@|\\\\?',\n merge: false,\n next: 'start'\n });\n rules.start.unshift({\n token: 'punctuation',\n regex: '[;,]',\n merge: false,\n next: 'start'\n });\n var tokenizer = new Tokenizer(rules);\n editor.session.clearAnnotations();\n var lines = editor.session.doc.$lines;\n var tokens = [];\n var state = 'start';\n\n for (var _i = 0; _i < lines.length; _i++) {\n var tokenized = tokenizer.getLineTokens(lines[_i], state);\n\n for (var j = 0; j < tokenized.tokens.length; j++) {\n tokens.push(tokenized.tokens[j]);\n }\n\n tokens.push({\n type: 'text',\n value: '\\n'\n });\n state = tokenized.state;\n }\n\n var doc = editor.session.doc;\n var docIndex = 0;\n\n for (var _i2 = 0; _i2 < tokens.length; _i2++) {\n tokens[_i2].position = doc.indexToPosition(docIndex);\n docIndex += tokens[_i2].value.length;\n }\n\n tokens = tokens.filter(function (token) {\n return token.type !== 'comment' && !/^\\s+$/.test(token.value);\n });\n var diagnostics = [];\n var bracketStack = [];\n\n for (var _i3 = 0; _i3 < tokens.length; _i3++) {\n var token = tokens[_i3];\n var type = token.type;\n var value = token.value;\n\n if (value === '(' || value === '{' || value === '[') {\n bracketStack.push(token);\n continue;\n }\n\n if (value === ')' || value === '}' || value === ']') {\n if (bracketStack.length === 0) {\n diagnostics.push(unmatchedClosingBracket(token));\n continue;\n }\n\n var openBracket = bracketStack.pop();\n var ok = value === ')' && openBracket.value === '(' || value === ']' && openBracket.value === '[' || value === '}' && openBracket.value === '{';\n\n if (!ok) {\n diagnostics.push(unmatchedClosingBracket(token));\n diagnostics.push(unmatchedOpeningBracket(openBracket));\n continue;\n }\n }\n\n if (_i3 > 0) {\n var lhs = tokens[_i3 - 1];\n var rhs = tokens[_i3];\n var bracket = bracketStack[bracketStack.length - 1] || {};\n\n if (lhs.position.row === rhs.position.row && isSymbol(lhs) && isSymbol(rhs)) {\n diagnostics.push(unexpected('symbol', rhs));\n continue;\n }\n\n if (lhs.position.row === rhs.position.row && isOperator(lhs) && isOperator(rhs) && !isUnaryOperator(rhs)) {\n diagnostics.push(unexpected('operator', rhs));\n continue;\n }\n\n if (lhs.value === ',' && rhs.value === ',' && bracket.value === '(') {\n diagnostics.push(unexpected('comma', rhs, 'warning'));\n continue;\n }\n\n if (lhs.value === ',' && (rhs.value === '}' || rhs.value === ')' || rhs.value === ']')) {\n diagnostics.push(unexpected('comma', lhs, 'warning'));\n continue;\n }\n }\n }\n\n for (var _i4 = 0; _i4 < bracketStack.length; _i4++) {\n diagnostics.push(unmatchedOpeningBracket(bracketStack[_i4]));\n }\n\n editor.session.setAnnotations(diagnostics);\n };\n\n var findActiveAceInstance = function findActiveAceInstance() {\n var el = document.activeElement;\n\n while (el != null) {\n if (el.env && el.env.editor) {\n return el.env.editor;\n }\n\n el = el.parentElement;\n }\n\n return null;\n };\n\n var ensureInitialized = function ensureInitialized(editor) {\n if (editor.$diagnosticsInitialized) {\n return;\n }\n\n if (!editor.tutorial.diagnostics) {\n return;\n }\n\n var handlers = {};\n handlers.change = self.$onChange.bind(editor);\n\n handlers.destroy = function (event) {\n for (var key in handlers) {\n this.off(key, handlers[key]);\n }\n }.bind(editor);\n\n for (var key in handlers) {\n editor.on(key, handlers[key]);\n }\n\n editor.$liveDiagnostics = diagnose.bind(editor);\n editor.$diagnosticsInitialized = 1;\n };\n\n this.$onChange = function (data) {\n if (!this.tutorial.diagnostics) {\n return;\n }\n\n clearTimeout(this.$diagnosticsTimerId);\n this.session.clearAnnotations();\n this.$diagnosticsTimerId = setTimeout(this.$liveDiagnostics, 1000);\n };\n\n this.$onKeyDown = function (event) {\n var editor = findActiveAceInstance();\n\n if (editor != null) {\n ensureInitialized(editor);\n document.removeEventListener('keydown', this.$onKeyDown);\n }\n };\n\n document.addEventListener('keydown', this.$onKeyDown);\n}", "import \"core-js/modules/es.regexp.exec.js\";\nimport \"core-js/modules/es.regexp.test.js\";\nimport \"core-js/modules/es.array.map.js\";\nimport \"core-js/modules/es.string.trim.js\";\nexport function TutorialCompleter(tutorial) {\n this.$tutorial = tutorial;\n var self = this;\n\n this.$onChange = function (data) {\n clearTimeout(this.$autocompletionTimerId);\n data = data || {};\n\n if (data.action !== 'insert') {\n return;\n }\n\n var lines = data.lines || [];\n\n if (lines.length !== 1) {\n return;\n }\n\n var pos = this.getCursorPosition();\n var line = this.session.getLine(pos.row);\n var popup = (this.completer || {}).popup;\n\n if (popup && popup.isOpen && !/::$/.test(line)) {\n return;\n }\n\n var delayMs = 300;\n\n if (/[$@]$|::$/.test(line)) {\n delayMs = 10;\n }\n\n this.$autocompletionTimerId = setTimeout(this.$liveAutocompleter, delayMs);\n };\n\n var MODIFIER_NONE = 0;\n var MODIFIER_CTRL = 1;\n var MODIFIER_ALT = 2;\n var MODIFIER_SHIFT = 4;\n var KEYCODE_TAB = 9;\n var KEYCODE_SPACE = 32;\n\n var KeyCombination = function KeyCombination(event) {\n this.keyCode = event.keyCode || event.which;\n this.modifier = MODIFIER_NONE;\n this.modifier |= event.ctrlKey ? MODIFIER_CTRL : 0;\n this.modifier |= event.altKey ? MODIFIER_ALT : 0;\n this.modifier |= event.shiftKey ? MODIFIER_SHIFT : 0;\n };\n\n function initializeAceEventListeners(editor) {\n var handlers = {};\n handlers.change = self.$onChange.bind(editor);\n\n handlers.destroy = function (event) {\n for (var key in handlers) {\n this.off(key, handlers[key]);\n }\n }.bind(editor);\n\n for (var key in handlers) {\n editor.on(key, handlers[key]);\n }\n }\n\n function initializeCompletionEngine(editor) {\n editor.completers = editor.completers || [];\n editor.completers.push({\n getCompletions: function getCompletions(editor, session, position, prefix, callback) {\n var contents = session.getTextRange({\n start: {\n row: 0,\n column: 0\n },\n end: position\n });\n var payload = {\n contents: contents,\n label: editor.tutorial.label\n };\n self.$tutorial.$serverRequest('completion', payload, function (data) {\n data = data || [];\n var completer = {\n insertMatch: function insertMatch(editor, data) {\n var ranges = editor.selection.getAllRanges();\n var completions = editor.completer.completions;\n var n = completions.filterText.length;\n\n for (var i = 0; i < ranges.length; i++) {\n ranges[i].start.column -= n;\n editor.session.remove(ranges[i]);\n }\n\n var term = data.value + (data.is_function ? '()' : '');\n editor.execCommand('insertstring', term);\n\n if (data.is_function) {\n editor.navigateLeft(1);\n }\n }\n };\n var completions = data.map(function (el) {\n return {\n caption: el[0] + (el[1] ? '()' : ''),\n value: el[0],\n score: 0,\n meta: 'R',\n is_function: el[1],\n completer: completer\n };\n });\n callback(null, completions);\n });\n }\n });\n editor.setOptions({\n enableBasicAutocompletion: true,\n enableLiveAutocompletion: false\n });\n }\n\n function initializeSetupChunk(editor) {\n var data = editor.tutorial;\n self.$tutorial.$serverRequest('initialize_chunk', data);\n }\n\n function ensureInitialized(editor) {\n if (!editor.tutorial.completion) {\n return;\n }\n\n if (editor.$autocompletionInitialized) {\n return;\n }\n\n initializeAceEventListeners(editor);\n initializeCompletionEngine(editor);\n initializeSetupChunk(editor);\n\n if (typeof editor.$liveAutocompleter === 'undefined') {\n editor.$liveAutocompleter = function () {\n this.execCommand('startAutocomplete');\n }.bind(editor);\n }\n\n editor.$autocompletionInitialized = 1;\n }\n\n function findActiveAceInstance() {\n var el = document.activeElement;\n\n while (el != null) {\n if (el.env && el.env.editor) {\n return el.env.editor;\n }\n\n el = el.parentElement;\n }\n\n return null;\n }\n\n function autocomplete(event) {\n var editor = findActiveAceInstance();\n\n if (editor == null) {\n return;\n }\n\n if (!editor.tutorial.completion) {\n return;\n }\n\n ensureInitialized(editor);\n clearTimeout(editor.$autocompletionTimerId);\n var keys = new KeyCombination(event);\n\n if (keys.keyCode === KEYCODE_TAB) {\n if (editor.container.matches('.ace_indent_off')) {\n return;\n }\n\n var pos = editor.getCursorPosition();\n var line = editor.session.getLine(pos.row);\n var isCursorAtStart = line.substr(0, pos.column).trim() === '';\n\n if (isCursorAtStart) {\n return;\n }\n }\n\n event.stopPropagation();\n event.preventDefault();\n editor.execCommand('startAutocomplete');\n }\n\n document.addEventListener('keydown', function (event) {\n var editor = findActiveAceInstance();\n\n if (editor !== null) {\n ensureInitialized(editor);\n }\n\n if (editor !== null && !editor.tutorial.completion) {\n return;\n }\n\n var keys = new KeyCombination(event);\n\n if (keys.keyCode === KEYCODE_TAB && keys.modifier === MODIFIER_NONE) {\n if (editor && editor.completer && editor.completer.activated) {\n return;\n }\n\n return autocomplete(event);\n }\n\n if (keys.keyCode === KEYCODE_SPACE && keys.modifier === MODIFIER_CTRL) {\n return autocomplete(event);\n }\n }, true);\n}"],
- "mappings": "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",
+ "sourcesContent": ["function _newArrowCheck(innerThis, boundThis) { if (innerThis !== boundThis) { throw new TypeError(\"Cannot instantiate an arrow function\"); } }\n\nimport \"core-js/modules/es.regexp.exec.js\";\nimport \"core-js/modules/es.string.replace.js\";\nimport \"core-js/modules/es.string.search.js\";\nimport \"core-js/modules/es.regexp.constructor.js\";\nimport \"core-js/modules/es.regexp.dot-all.js\";\nimport \"core-js/modules/es.regexp.sticky.js\";\nimport \"core-js/modules/es.regexp.to-string.js\";\nimport \"core-js/modules/es.array.find.js\";\nimport \"core-js/modules/es.object.to-string.js\";\nimport \"core-js/modules/es.array.splice.js\";\nimport \"core-js/modules/es.array.concat.js\";\nimport \"core-js/modules/es.json.stringify.js\";\nimport \"core-js/modules/es.string.split.js\";\nimport \"core-js/modules/es.string.match.js\";\nimport \"core-js/modules/es.array.slice.js\";\nimport \"core-js/modules/es.parse-float.js\";\nimport \"core-js/modules/es.regexp.test.js\";\nimport \"core-js/modules/es.object.assign.js\";\nimport \"core-js/modules/es.array.index-of.js\";\nimport \"core-js/modules/es.array.for-each.js\";\nimport \"core-js/modules/es.promise.js\";\nimport \"core-js/modules/es.promise.finally.js\";\nimport \"core-js/modules/es.array.iterator.js\";\nimport \"core-js/modules/web.dom-collections.iterator.js\";\nimport \"core-js/modules/es.array.map.js\";\nimport \"core-js/modules/es.string.iterator.js\";\nimport \"core-js/modules/es.error.cause.js\";\nimport \"core-js/modules/es.error.to-string.js\";\nimport { TutorialDiagnostics } from './tutorial-diagnostics.mjs';\nimport { TutorialCompleter } from './tutorial-autocompletion.mjs';\n$(document).ready(function () {\n var tutorial = new Tutorial();\n\n if (typeof TutorialCompleter !== 'undefined') {\n tutorial.$completer = new TutorialCompleter(tutorial);\n }\n\n if (typeof TutorialDiagnostics !== 'undefined') {\n tutorial.$diagnostics = new TutorialDiagnostics(tutorial);\n }\n\n window.tutorial = tutorial;\n});\nvar TUTORIAL_IS_SERVER_AVAILABLE = false;\n\nfunction Tutorial() {\n var thiz = this;\n this.$initTimingLog();\n this.isBS3 = !window.bootstrap;\n\n if (this.isBS3) {\n document.body.classList.add('tutorial-is-bs3');\n }\n\n this.onInit = function (handler) {\n this.$initCallbacks.add(handler);\n };\n\n this.onProgress = function (handler) {\n this.$progressCallbacks.add(handler);\n };\n\n this.startOver = function () {\n thiz.$removeState(function () {\n thiz.$serverRequest('remove_state', null, function () {\n window.location.replace(window.location.origin + window.location.pathname);\n });\n });\n };\n\n this.skipSection = function (sectionId) {\n if (TUTORIAL_IS_SERVER_AVAILABLE) {\n thiz.$serverRequest('section_skipped', {\n sectionId: sectionId\n }, null);\n }\n };\n\n this.scrollIntoView = function (element) {\n element = $(element);\n var rect = element[0].getBoundingClientRect();\n\n if (rect.top < 0 || rect.bottom > $(window).height()) {\n if (element[0].scrollIntoView) {\n element[0].scrollIntoView(false);\n document.body.scrollTop += 20;\n }\n }\n };\n\n thiz.$initializeVideos();\n thiz.$initializeExercises();\n thiz.$initializeServer();\n}\n\nTutorial.prototype.$initTimingLog = function () {\n try {\n if (performance.mark !== undefined) {\n performance.mark('tutorial-start-mark');\n }\n } catch (e) {\n console.log('Error initializing log timing: ' + e.message);\n }\n};\n\nTutorial.prototype.$logTiming = function (name) {\n try {\n if (performance.mark !== undefined && performance.measure !== undefined && performance.getEntriesByName !== undefined && this.queryVar('log-timings') === '1') {\n performance.mark(name + '-mark');\n performance.measure(name, 'tutorial-start-mark', name + '-mark');\n var entries = performance.getEntriesByName(name);\n console.log('(Timing) ' + name + ': ' + Math.round(entries[0].duration) + 'ms');\n }\n } catch (e) {\n console.log('Error logging timing: ' + e.message);\n }\n};\n\nTutorial.prototype.queryVar = function (name) {\n return decodeURI(window.location.search.replace(new RegExp('^(?:.*[&\\\\?]' + encodeURI(name).replace(/[.+*]/g, '\\\\$&') + '(?:\\\\=([^&]*))?)?.*$', 'i'), '$1'));\n};\n\nTutorial.prototype.$idSelector = function (id) {\n return '#' + id.replace(/(:|\\.|\\[|\\]|,|=|@)/g, '\\\\$1');\n};\n\nTutorial.triggerMathJax = function () {\n if (window.MathJax) {\n MathJax.Hub.Queue(['Typeset', MathJax.Hub]);\n }\n};\n\nTutorial.prototype.$initCallbacks = $.Callbacks();\n\nTutorial.prototype.$fireInit = function () {\n var thiz = this;\n\n try {\n thiz.$initCallbacks.fire();\n } catch (e) {\n console.log(e);\n }\n};\n\nTutorial.prototype.$progressCallbacks = $.Callbacks();\nTutorial.prototype.$progressEvents = [];\n\nTutorial.prototype.$hasCompletedProgressEvent = function (element) {\n var thiz = this;\n\n for (var e = 0; e < thiz.$progressEvents.length; e++) {\n var event = thiz.$progressEvents[e];\n\n if ($(event.element).is($(element))) {\n if (event.completed) {\n return true;\n }\n }\n }\n\n return false;\n};\n\nTutorial.prototype.$fireProgress = function (event) {\n this.$progressEvents.push(event);\n\n try {\n this.$progressCallbacks.fire(event);\n } catch (e) {\n console.log(e);\n }\n};\n\nTutorial.prototype.$fireSectionCompleted = function (element) {\n var thiz = this;\n\n function fireCompleted(el) {\n var event = {\n element: el,\n event: 'section_completed'\n };\n thiz.$fireProgress(event);\n }\n\n var section = $(element).parent().closest('.section');\n\n if (section.length === 0) {\n return;\n }\n\n var components = section.find('.tutorial-exercise, .tutorial-question, .tutorial-video');\n var allCompleted = true;\n\n for (var c = 0; c < components.length; c++) {\n var component = components.get(c);\n\n if (!thiz.$hasCompletedProgressEvent(component)) {\n allCompleted = false;\n break;\n }\n }\n\n if (allCompleted) {\n fireCompleted($(section).get(0));\n var previousSections = section.prevAll('.section');\n previousSections.each(function () {\n var components = $(this).find('.tutorial-exercise, .tutorial-question');\n\n if (components.length === 0) {\n fireCompleted(this);\n }\n });\n var parentSection = section.parent().closest('.section');\n\n if (parentSection.length > 0) {\n this.$fireSectionCompleted(section);\n }\n }\n};\n\nTutorial.prototype.$removeConflictingProgressEvents = function (progressEvent) {\n var thiz = this;\n var event;\n\n for (var i = thiz.$progressEvents.length - 1; i >= 0; i--) {\n event = thiz.$progressEvents[i];\n\n if (event.event === 'question_submission') {\n if (event.data.label === progressEvent.data.label & progressEvent.data.label !== undefined) {\n thiz.$progressEvents.splice(i, 1);\n return;\n }\n }\n }\n};\n\nTutorial.prototype.$fireProgressEvent = function (event, data) {\n var thiz = this;\n var progressEvent = {\n event: event,\n data: data\n };\n\n if (event === 'exercise_submission' || event === 'question_submission') {\n var element = $('.tutorial-exercise[data-label=\"' + data.label + '\"]').add('.tutorial-question[data-label=\"' + data.label + '\"]');\n\n if (element.length > 0) {\n progressEvent.element = element;\n\n if (event === 'exercise_submission') {\n progressEvent.completed = typeof data.completed !== 'undefined' ? data.completed : true;\n } else {\n progressEvent.completed = data.answer !== null;\n }\n }\n } else if (event === 'section_skipped') {\n var exerciseElement = $(thiz.$idSelector(data.sectionId));\n progressEvent.element = exerciseElement;\n progressEvent.completed = false;\n } else if (event === 'video_progress') {\n var videoElement = $('iframe[src=\"' + data.video_url + '\"]');\n\n if (videoElement.length > 0) {\n progressEvent.element = videoElement;\n progressEvent.completed = 2 * data.time > data.total_time;\n }\n }\n\n this.$removeConflictingProgressEvents(progressEvent);\n\n if (progressEvent.element) {\n this.$fireProgress(progressEvent);\n thiz.$fireSectionCompleted(progressEvent.element);\n }\n};\n\nTutorial.prototype.$initializeProgress = function (progressEvents) {\n var thiz = this;\n\n for (var i = 0; i < progressEvents.length; i++) {\n var progress = progressEvents[i];\n var progressEvent = progress.event;\n var progressEventData = {};\n\n if (progressEvent === 'exercise_submission') {\n progressEventData.label = progress.data.label;\n progressEventData.correct = progress.data.correct;\n } else if (progressEvent === 'question_submission') {\n progressEventData.label = progress.data.label;\n progressEventData.answer = progress.data.answer;\n } else if (progressEvent === 'section_skipped') {\n progressEventData.sectionId = progress.data.sectionId;\n } else if (progressEvent === 'video_progress') {\n progressEventData.video_url = progress.data.video_url;\n progressEventData.time = progress.data.time;\n progressEventData.total_time = progress.data.total_time;\n }\n\n thiz.$fireProgressEvent(progressEvent, progressEventData);\n }\n\n Shiny.addCustomMessageHandler('tutorial.progress_event', function (progress) {\n thiz.$fireProgressEvent(progress.event, progress.data);\n });\n};\n\nTutorial.prototype.$serverRequest = function (type, data, success, error) {\n var _Shiny$shinyapp$confi = Shiny.shinyapp.config,\n sessionId = _Shiny$shinyapp$confi.sessionId,\n workerId = _Shiny$shinyapp$confi.workerId;\n return $.ajax({\n type: 'POST',\n url: \"session/\".concat(sessionId, \"/dataobj/\").concat(type, \"?w=\").concat(workerId),\n contentType: 'application/json',\n data: JSON.stringify(data),\n dataType: 'json',\n success: success,\n error: error\n });\n};\n\nTutorial.prototype.$recordEvent = function (label, event, data) {\n var params = {\n label: label,\n event: event,\n data: data\n };\n this.$serverRequest('record_event', params, null);\n};\n\nTutorial.prototype.$countLines = function (str) {\n return str.split(/\\r\\n|\\r|\\n/).length;\n};\n\nTutorial.prototype.$injectScript = function (src, onload) {\n var script = document.createElement('script');\n script.src = src;\n var firstScriptTag = document.getElementsByTagName('script')[0];\n firstScriptTag.parentNode.insertBefore(script, firstScriptTag);\n $(script).on('load', onload);\n};\n\nTutorial.prototype.$debounce = function (func, wait, immediate) {\n var timeout;\n return function () {\n var context = this;\n var args = arguments;\n\n var later = function later() {\n timeout = null;\n if (!immediate) func.apply(context, args);\n };\n\n var callNow = immediate && !timeout;\n clearTimeout(timeout);\n timeout = setTimeout(later, wait);\n if (callNow) func.apply(context, args);\n };\n};\n\nTutorial.prototype.$initializeVideos = function () {\n var youtubeRegex = /^.*(youtu.be\\/|v\\/|u\\/\\w\\/|embed\\/|watch\\?v=|&v=)([^#&?]*).*/;\n var vimeoRegex = /(?:vimeo)\\.com.*(?:videos|video|channels|)\\/([\\d]+)/i;\n\n function isYouTubeVideo(src) {\n return src.match(youtubeRegex);\n }\n\n function isVimeoVideo(src) {\n return src.match(vimeoRegex);\n }\n\n function isVideo(src) {\n return isYouTubeVideo(src) || isVimeoVideo(src);\n }\n\n function normalizeVideoSrc(src) {\n var youtubeMatch = src.match(youtubeRegex);\n\n if (youtubeMatch) {\n return \"https://www.youtube.com/embed/\".concat(youtubeMatch[2], \"?enablejsapi=1\");\n }\n\n var vimeoMatch = src.match(vimeoRegex);\n\n if (vimeoMatch) {\n return \"https://player.vimeo.com/video/\".concat(vimeoMatch[1]);\n }\n\n return src;\n }\n\n function setContainerSize(container, width, height) {\n var aspectRatio = 9 / 16;\n\n if (!width) {\n width = '100%';\n }\n\n if (width.slice(-1) === '%') {\n container.css('width', width);\n\n if (!height) {\n height = 0;\n var paddingBottom = parseFloat(width) * aspectRatio + '%';\n container.css('padding-bottom', paddingBottom);\n }\n\n container.css('height', height);\n } else {\n if ($.isNumeric(width)) {\n width = width + 'px';\n }\n\n container.css('width', width);\n\n if (!height) {\n height = parseFloat(width) * aspectRatio + 'px';\n }\n\n container.css('height', height);\n }\n }\n\n $('img').each(function () {\n var videoSrc = $(this).attr('src');\n\n if (!isVideo(videoSrc)) {\n return;\n }\n\n $(this).css('display', 'none');\n var width = $(this).get(0).style.width;\n var height = $(this).get(0).style.height;\n $(this).css('width', '').css('height', '');\n var attrs = {};\n $.each(this.attributes, function (idex, attr) {\n switch (attr.nodeName) {\n case 'width':\n {\n width = String(attr.nodeValue);\n break;\n }\n\n case 'height':\n {\n height = String(attr.nodeValue);\n break;\n }\n\n case 'src':\n {\n attrs.src = normalizeVideoSrc(attr.nodeValue);\n break;\n }\n\n default:\n {\n attrs[attr.nodeName] = attr.nodeValue;\n }\n }\n });\n $(this).replaceWith(function () {\n var iframe = $('', attrs);\n iframe.addClass('tutorial-video');\n\n if (isYouTubeVideo(videoSrc)) {\n iframe.addClass('tutorial-video-youtube');\n } else if (isVimeoVideo(videoSrc)) {\n iframe.addClass('tutorial-video-vimeo');\n }\n\n iframe.attr('allowfullscreen', '');\n iframe.css('display', '');\n var container = $('
');\n setContainerSize(container, width, height);\n container.append(iframe);\n return container;\n });\n });\n this.$logTiming('initialized-videos');\n};\n\nTutorial.prototype.$initializeVideoPlayers = function (videoProgress) {\n if (/\\bQt\\//.test(window.navigator.userAgent)) {\n return;\n }\n\n this.$initializeYouTubePlayers(videoProgress);\n this.$initializeVimeoPlayers(videoProgress);\n};\n\nTutorial.prototype.$videoPlayerRestoreTime = function (src, videoProgress) {\n for (var v = 0; v < videoProgress.length; v++) {\n var id = videoProgress[v].id;\n\n if (src === id) {\n var time = videoProgress[v].data.time;\n var totalTime = videoProgress[v].data.total_time;\n\n if (time > 10 && totalTime - time > 10) {\n return time;\n }\n }\n }\n\n return 0;\n};\n\nTutorial.prototype.$initializeYouTubePlayers = function (videoProgress) {\n var thiz = this;\n var videos = $('iframe.tutorial-video-youtube');\n\n if (videos.length > 0) {\n this.$injectScript('https://www.youtube.com/iframe_api', function () {\n YT.ready(function () {\n videos.each(function () {\n var video = $(this);\n var videoUrl = video.attr('src');\n var player = null;\n var lastState = -1;\n\n function reportProgress() {\n thiz.$reportVideoProgress(videoUrl, player.getCurrentTime(), player.getDuration());\n }\n\n function restoreTime() {\n var restoreTime = thiz.$videoPlayerRestoreTime(videoUrl, videoProgress);\n\n if (restoreTime > 0) {\n player.mute();\n player.playVideo();\n setTimeout(function () {\n player.pauseVideo();\n player.seekTo(restoreTime, true);\n player.unMute();\n }, 2000);\n }\n }\n\n function onReady() {\n restoreTime();\n }\n\n function onStateChange() {\n var state = player.getPlayerState();\n var isNotStarted = state === -1;\n var isCued = state === YT.PlayerState.CUED;\n var isPlaying = state === YT.PlayerState.PLAYING;\n var isDuplicate = state === lastState;\n\n if (!(isNotStarted || isCued) && (isPlaying || isDuplicate)) {\n reportProgress();\n }\n\n lastState = state;\n }\n\n player = new YT.Player(this, {\n events: {\n onReady: onReady,\n onStateChange: onStateChange\n }\n });\n window.setInterval(onStateChange, 5000);\n });\n });\n });\n }\n};\n\nTutorial.prototype.$initializeVimeoPlayers = function (videoProgress) {\n var thiz = this;\n var videos = $('iframe.tutorial-video-vimeo');\n\n if (videos.length > 0) {\n this.$injectScript('https://player.vimeo.com/api/player.js', function () {\n videos.each(function () {\n var video = $(this);\n var videoUrl = video.attr('src');\n var player = new Vimeo.Player(this);\n var lastReportedTime = null;\n player.ready().then(function () {\n var restoreTime = thiz.$videoPlayerRestoreTime(videoUrl, videoProgress);\n\n if (restoreTime > 0) {\n player.getVolume().then(function (volume) {\n player.setCurrentTime(restoreTime).then(function () {\n player.pause().then(function () {\n player.setVolume(volume);\n });\n });\n });\n }\n });\n\n function reportProgress(data, throttle) {\n if (throttle === undefined) {\n throttle = false;\n }\n\n if (throttle && lastReportedTime != null && data.seconds - lastReportedTime < 5) {\n return;\n }\n\n thiz.$reportVideoProgress(videoUrl, data.seconds, data.duration);\n lastReportedTime = data.seconds;\n }\n\n player.on('play', reportProgress);\n player.on('pause', reportProgress);\n player.on('ended', reportProgress);\n player.on('timeupdate', function (data) {\n reportProgress(data, true);\n });\n });\n });\n }\n};\n\nTutorial.prototype.$reportVideoProgress = function (videoUrl, time, totalTime) {\n this.$serverRequest('video_progress', {\n video_url: videoUrl,\n time: time,\n total_time: totalTime\n });\n};\n\nTutorial.prototype.$initializeExercises = function () {\n this.$initializeExerciseEditors();\n this.$initializeExerciseSolutions();\n this.$initializeExerciseEvaluation();\n this.$logTiming('initialized-exercises');\n};\n\nTutorial.prototype.$exerciseForLabel = function (label) {\n return $('.tutorial-exercise[data-label=\"' + label + '\"]');\n};\n\nTutorial.prototype.$forEachExercise = function (operation) {\n return $('.tutorial-exercise').each(function () {\n var exercise = $(this);\n operation(exercise);\n });\n};\n\nTutorial.prototype.$exerciseSupportCode = function (label) {\n var selector = '.tutorial-exercise-support[data-label=\"' + label + '\"]';\n var code = $(selector).children('pre').children('code');\n\n if (code.length > 0) {\n return code.text();\n } else {\n return null;\n }\n};\n\nTutorial.prototype.$exerciseSolutionCode = function (label) {\n return this.$exerciseSupportCode(label + '-solution');\n};\n\nTutorial.prototype.$exerciseHintDiv = function (label) {\n var id = 'section-' + label + '-hint';\n var hintDiv = $('div#' + id);\n\n if (hintDiv.length > 0 && !hintDiv.hasClass('section')) {\n return hintDiv;\n } else {\n return null;\n }\n};\n\nTutorial.prototype.$exerciseHintsCode = function (label) {\n var hint = this.$exerciseSupportCode(label + '-hint');\n\n if (hint !== null) {\n return [hint];\n }\n\n var hints = [];\n var index = 1;\n\n while (true) {\n var hintLabel = label + '-hint-' + index++;\n hint = this.$exerciseSupportCode(hintLabel);\n\n if (hint !== null) {\n hints.push(hint);\n } else {\n break;\n }\n }\n\n if (hints.length > 0) {\n return hints;\n } else {\n return null;\n }\n};\n\nTutorial.prototype.$exerciseContainer = function (el) {\n return $(el).closest('.tutorial-exercise');\n};\n\nTutorial.prototype.$showExerciseProgress = function (label, button, show) {\n var exercise = this.$exerciseForLabel(label);\n var outputFrame = exercise.children('.tutorial-exercise-output-frame');\n var runButtons = exercise.find('.btn-tutorial-run');\n\n if (button === 'run') {\n button = exercise.find('.btn-tutorial-run').last();\n }\n\n var spinner = 'fa-spinner fa-spin fa-fw';\n\n if (show) {\n outputFrame.addClass('recalculating');\n runButtons.addClass('disabled');\n\n if (button !== null) {\n var runIcon = button.children('i');\n runIcon.removeClass(button.attr('data-icon'));\n runIcon.addClass(spinner);\n }\n } else {\n outputFrame.removeClass('recalculating');\n runButtons.removeClass('disabled');\n runButtons.each(function () {\n var button = $(this);\n var runIcon = button.children('i');\n runIcon.addClass(button.attr('data-icon'));\n runIcon.removeClass(spinner);\n });\n }\n};\n\nTutorial.prototype.kMinLines = 3;\n\nTutorial.prototype.$attachAceEditor = function (target, code, options) {\n var engineModes = {\n js: 'javascript'\n };\n var optsDefaults = {\n engine: 'r'\n };\n options = Object.assign({}, optsDefaults, options);\n options.engine = engineModes[options.engine] || options.engine;\n var editor = ace.edit(target);\n editor.setHighlightActiveLine(false);\n editor.setShowPrintMargin(false);\n editor.setShowFoldWidgets(false);\n editor.setBehavioursEnabled(true);\n editor.renderer.setDisplayIndentGuides(false);\n editor.setTheme('ace/theme/textmate');\n editor.$blockScrolling = Infinity;\n editor.session.setMode(\"ace/mode/\".concat(options.engine));\n editor.session.getSelection().clearSelection();\n editor.session.setNewLineMode('unix');\n editor.session.setTabSize(2);\n editor.setValue(code, -1);\n editor.setOptions({\n enableBasicAutocompletion: true\n });\n return editor;\n};\n\nTutorial.prototype.$exerciseEditor = function (label) {\n return this.$exerciseForLabel(label).find('.tutorial-exercise-code-editor');\n};\n\nTutorial.prototype.$initializeExerciseEditors = function () {\n var thiz = this;\n this.$forEachExercise(function (exercise) {\n var optsScript = exercise.children('script[data-ui-opts=\"1\"]').detach();\n var optsChunk = optsScript.length === 1 ? JSON.parse(optsScript.text()) : {};\n var label = exercise.attr('data-label');\n var caption = optsChunk.caption;\n\n function createId(suffix) {\n return 'tutorial-exercise-' + label + '-' + suffix;\n }\n\n exercise.on('focusin', function () {\n $('.btn-tutorial-solution').each(function () {\n if (exercise.has($(this)).length === 0) {\n thiz.$removeSolution(thiz.$exerciseContainer($(this)));\n }\n });\n });\n var code = '';\n var codeBlocks = exercise.children('pre.text, pre.lang-text');\n codeBlocks.each(function () {\n var codeElement = $(this).children('code');\n\n if (codeElement.length > 0) {\n code = code + codeElement.text();\n } else {\n code = code + $(this).text();\n }\n });\n codeBlocks.remove();\n var lines = code.split(/\\r\\n|\\r|\\n/).length;\n\n for (var i = lines; i < thiz.kMinLines; i++) {\n code = code + '\\n';\n }\n\n exercise.wrapInner('
');\n var outputFrame = exercise.children('.tutorial-exercise-output-frame');\n var inputDiv = $('
');\n inputDiv.attr('id', createId('input'));\n var panelHeading = $('
');\n inputDiv.append(panelHeading);\n var panelHeadingLeft = $('
');\n var panelHeadingRight = $('
');\n panelHeading.append(panelHeadingLeft);\n panelHeading.append(panelHeadingRight);\n panelHeadingLeft.html(caption);\n var panelBody = $('
');\n inputDiv.append(panelBody);\n\n function addSubmitButton(icon, style, text, check, datai18n) {\n var button = $(' ');\n button.append($(' '));\n button.append(' ' + '' + text + ' ');\n var isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0;\n var title = text;\n var kbdText = (isMac ? 'Cmd' : 'Ctrl') + '+Shift+Enter';\n\n if (!check) {\n title = title + ' (' + kbdText + ')';\n button.attr('data-i18n-opts', '{\"kbd\": \"' + kbdText + '\"}');\n }\n\n button.attr('title', title);\n button.attr('data-i18n', '');\n button.attr('data-i18n-attr-title', 'button.' + datai18n + 'title');\n\n if (check) {\n button.attr('data-check', '1');\n }\n\n button.attr('data-icon', icon);\n button.on('click', function () {\n thiz.$removeSolution(exercise);\n thiz.$showExerciseProgress(label, button, true);\n });\n panelHeadingRight.append(button);\n return button;\n }\n\n var runButton = addSubmitButton('fa-play', 'btn-success', 'Run Code', false, 'runcode');\n\n if (optsChunk.has_checker) {\n addSubmitButton('fa-check-square-o', 'btn-primary', 'Submit Answer', true, 'submitanswer');\n }\n\n var codeDiv = $('
');\n var codeDivId = createId('code-editor');\n codeDiv.attr('id', codeDivId);\n panelBody.append(codeDiv);\n panelBody.append(optsScript);\n exercise.prepend(inputDiv);\n var outputDiv = $('
');\n outputDiv.attr('id', createId('output'));\n outputFrame.append(outputDiv);\n var editor = thiz.$attachAceEditor(codeDivId, code, optsChunk);\n var setupCode = null;\n var completion = exercise.attr('data-completion') === '1';\n var diagnostics = exercise.attr('data-diagnostics') === '1';\n var startoverCode = exercise.attr('data-startover') === '1' ? code : null;\n var engine = optsChunk.engine;\n\n if (engine.toLowerCase() !== 'r') {\n diagnostics = null;\n }\n\n editor.tutorial = {\n label: label,\n engine: engine,\n setup_code: setupCode,\n completion: completion,\n diagnostics: diagnostics,\n startover_code: startoverCode\n };\n\n function bindExecutionKey(name, key) {\n var macKey = key.replace('Ctrl+', 'Command+');\n editor.commands.addCommand({\n name: name,\n bindKey: {\n win: key,\n mac: macKey\n },\n exec: function exec(editor) {\n runButton.trigger('click');\n }\n });\n }\n\n bindExecutionKey('execute1', 'Ctrl+Enter');\n bindExecutionKey('execute2', 'Ctrl+Shift+Enter');\n\n function bindInsertKey(name, keys, text) {\n if (typeof keys === 'string') {\n keys = {\n win: keys,\n mac: keys.replace('Ctrl+', 'Command+')\n };\n }\n\n if (typeof text === 'string') {\n text = {\n r: text,\n fallback: text\n };\n }\n\n editor.commands.addCommand({\n name: name,\n bindKey: keys,\n exec: function exec(editor) {\n if (text[editor.tutorial.engine]) {\n editor.insert(text[editor.tutorial.engine]);\n } else if (text.fallback) {\n editor.insert(text.fallback);\n }\n }\n });\n }\n\n var pipeCode = exercise.attr('data-pipe') || '%>%';\n bindInsertKey('insertPipe', 'Ctrl+Shift+M', {\n r: ' ' + pipeCode\n });\n bindInsertKey('insertArrow', 'Alt+-', {\n r: ' <- ',\n fallback: ' = '\n });\n runButton.on('click', function () {\n editor.focus();\n });\n\n function toggleTabCommands(enable) {\n var tabCommandKeys = {\n indent: {\n win: 'Tab',\n mac: 'Tab'\n },\n outdent: {\n win: 'Shift+Tab',\n mac: 'Shift+Tab'\n }\n };\n ['indent', 'outdent'].forEach(function (name) {\n var command = editor.commands.byName[name];\n command.bindKey = enable ? tabCommandKeys[name] : null;\n editor.commands.addCommand(command);\n });\n $(editor.container).toggleClass('ace_indent_off', !enable);\n }\n\n editor.on('focus', function () {\n toggleTabCommands(true);\n });\n editor.commands.addCommand({\n name: 'escape',\n bindKey: {\n win: 'Esc',\n mac: 'Esc'\n },\n exec: function exec() {\n toggleTabCommands(false);\n }\n });\n\n var updateAceHeight = function updateAceHeight() {\n var lines = exercise.attr('data-lines');\n\n if (lines && lines > 0) {\n editor.setOptions({\n minLines: lines,\n maxLines: lines\n });\n } else {\n editor.setOptions({\n minLines: thiz.kMinLines,\n maxLines: Math.max(Math.min(editor.session.getLength(), 15), thiz.kMinLines)\n });\n }\n };\n\n updateAceHeight();\n editor.getSession().on('change', updateAceHeight);\n thiz.$addSolution(exercise, panelHeadingLeft, editor);\n exercise.parents('.section').on('shown', function () {\n editor.resize(true);\n });\n });\n};\n\nTutorial.prototype.$initializeExerciseSolutions = function () {\n var thiz = this;\n $(document).on('mouseup', function (ev) {\n var exercise = thiz.$exerciseContainer(ev.target);\n\n if (exercise.length === 0) {\n thiz.$forEachExercise(thiz.$removeSolution);\n }\n });\n};\n\nTutorial.prototype.$addSolution = function (exercise, panelHeading, editor) {\n var thiz = this;\n var label = exercise.attr('data-label');\n var solution = thiz.$exerciseSolutionCode(label);\n var hints = thiz.$exerciseHintsCode(label);\n\n if (hints !== null && solution !== null) {\n hints.push(solution);\n solution = null;\n }\n\n var hintDiv = thiz.$exerciseHintDiv(label);\n\n function addHelperButton(icon, caption, classBtn, datai18n) {\n var button = $(' ');\n button.attr('title', caption);\n button.attr('data-i18n', '');\n button.addClass(classBtn);\n button.append($(' '));\n\n if (datai18n) {\n if (typeof datai18n === 'string') {\n datai18n = {\n key: datai18n\n };\n }\n\n button.attr('data-i18n-attr-title', datai18n.key + 'title');\n var buttonText = $(\"\".concat(caption, \" \"));\n buttonText.attr('data-i18n', datai18n.key);\n\n if (datai18n.opts) {\n buttonText.attr('data-i18n-opts', JSON.stringify(datai18n.opts));\n }\n\n button.append(document.createTextNode(' '));\n button.append(buttonText);\n\n if (datai18n.opts) {\n button.attr('data-i18n-opts', JSON.stringify(datai18n.opts));\n }\n } else {\n button.append(' ' + caption);\n }\n\n panelHeading.append(button);\n return button;\n }\n\n function addHintButton(caption, datai18n) {\n datai18n = datai18n || 'button.hint';\n return addHelperButton('fa-lightbulb-o', caption, 'btn-tutorial-hint', datai18n);\n }\n\n function recordHintRequest(index) {\n thiz.$recordEvent(label, 'exercise_hint', {\n type: solution !== null ? 'solution' : 'hint',\n index: index\n });\n }\n\n if (editor.tutorial.startover_code !== null) {\n var startOverButton = addHelperButton('fa-refresh', 'Start Over', 'btn-tutorial-start-over', 'button.startover');\n startOverButton.on('click', function () {\n editor.setValue(editor.tutorial.startover_code, -1);\n thiz.$clearExerciseOutput(exercise);\n });\n }\n\n if (hintDiv != null) {\n hintDiv.addClass('tutorial-hint');\n hintDiv.css('display', 'none');\n var button = addHintButton('Hint', {\n key: 'button.hint',\n count: 1\n });\n button.on('click', function () {\n recordHintRequest(0);\n var outputFrame = exercise.children('.tutorial-exercise-output-frame');\n\n if (outputFrame.find('.tutorial-hint').length === 0) {\n var panel = $(\"
\"));\n var panelBody = $(\"
\"));\n var hintDivClone = hintDiv.clone().attr('id', '').css('display', 'inherit');\n panelBody.append(hintDivClone);\n panel.append(panelBody);\n outputFrame.prepend(panel);\n } else {\n outputFrame.find('.tutorial-hint-panel').remove();\n }\n });\n } else if (solution || hints) {\n var isSolution = solution !== null;\n var editorLines = thiz.kMinLines;\n\n if (solution) {\n editorLines = Math.max(thiz.$countLines(solution), editorLines);\n } else {\n for (var i = 0; i < hints.length; i++) {\n editorLines = Math.max(thiz.$countLines(hints[i]), editorLines);\n }\n }\n\n var hintIndex = 0;\n\n var _button = addHintButton(isSolution ? 'Solution' : hints.length > 1 ? 'Hints' : 'Hint', isSolution ? {\n key: 'button.solution',\n count: 1\n } : {\n key: 'button.hint',\n opts: {\n count: hints.length\n }\n });\n\n _button.on('click', function (ev) {\n recordHintRequest(hintIndex);\n var solutionText = solution !== null ? solution : hints[hintIndex];\n var visible = _button.parent().find('div.popover:visible').length > 0;\n\n if (visible) {\n console.log('Removing hint popover', ev);\n thiz.$removeSolution(exercise);\n editor.focus();\n return;\n }\n\n console.log('Revealing hint popover', ev);\n\n var popover = _button.popover({\n placement: 'top',\n template: '',\n content: solutionText,\n container: _button.parent(),\n boundary: $('.topics').get(0),\n viewport: $('.topics').get(0)\n });\n\n var popoverIsInserted = false;\n popover.on('inserted.bs.popover', function (ev) {\n var _this = this;\n\n if (popoverIsInserted) return;\n console.log('Instantiating hint popover', ev);\n var popoverTip = thiz.isBS3 ? popover.data('bs.popover').tip() : $(window.bootstrap.Popover.getInstance(popover).tip);\n var content = popoverTip.find('.popover-content');\n var solutionEditor = thiz.$attachAceEditor(content.get(0), solutionText);\n solutionEditor.setReadOnly(true);\n solutionEditor.setOption('minLines', Math.min(editorLines, 10));\n solutionEditor.setOption('maxLines', 10);\n setTimeout(function () {\n _newArrowCheck(this, _this);\n\n content.parent().css('top', \"-\".concat(content.parent().height(), \"px\"));\n }.bind(this));\n var popoverTitle = popoverTip.find('.popover-title');\n\n if (solution === null && hints.length > 1) {\n var nextHintButton = $(\" \"));\n nextHintButton.append($('Next Hint '));\n nextHintButton.append(' ');\n nextHintButton.append($(' '));\n nextHintButton.on('click', function () {\n hintIndex = hintIndex + 1;\n solutionEditor.setValue(hints[hintIndex], -1);\n\n if (hintIndex === hints.length - 1) {\n nextHintButton.addClass('disabled');\n nextHintButton.prop('disabled', true);\n }\n\n recordHintRequest(hintIndex);\n });\n\n if (hintIndex === hints.length - 1) {\n nextHintButton.addClass('disabled');\n nextHintButton.prop('disabled', true);\n }\n\n popoverTitle.append(nextHintButton);\n }\n\n var copyButton = $(\" \"));\n copyButton.append($(' '));\n copyButton.append(' ');\n copyButton.append($('Copy to Clipboard '));\n popoverTitle.append(copyButton);\n var clipboard = new ClipboardJS(copyButton[0], {\n text: function text(trigger) {\n return solutionEditor.getValue();\n }\n });\n clipboard.on('success', function (e) {\n thiz.$removeSolution(exercise);\n editor.focus();\n });\n copyButton.data('clipboard', clipboard);\n popoverTip.css('left', '0');\n var popoverArrow = popoverTip.find('.arrow');\n popoverArrow.css('left', _button.position().left + _button.outerWidth() / 2 + 'px');\n popoverTip.trigger('i18n');\n popoverIsInserted = true;\n });\n\n _button.on('shown.bs.popover', function () {\n var popoverElement = $('.tutorial-solution-popover');\n thiz.scrollIntoView(popoverElement);\n\n if (!thiz.isBS3) {\n window.bootstrap.Popover.getInstance(popover).update();\n }\n });\n\n _button.popover('show');\n\n editor.focus();\n });\n }\n};\n\nTutorial.prototype.$removeSolution = function (exercise) {\n var solutionButton = exercise.find('.btn-tutorial-copy-solution');\n\n if (solutionButton.length > 0) {\n solutionButton.data('clipboard').destroy();\n }\n\n if (window.bootstrap) {\n var popover = exercise.find('.tutorial-solution-popover');\n if (!popover.length) return;\n window.bootstrap.Popover.getInstance(popover.get(0)).dispose();\n } else {\n exercise.find('.tutorial-solution-popover').popover('destroy');\n }\n};\n\nTutorial.prototype.$initializeExerciseEvaluation = function () {\n var thiz = this;\n\n function exerciseLabel(el) {\n return thiz.$exerciseContainer(el).attr('data-label');\n }\n\n function ensureExerciseVisible(el) {\n var exerciseEl = thiz.$exerciseContainer(el)[0];\n thiz.scrollIntoView(exerciseEl);\n }\n\n var exerciseInputBinding = new Shiny.InputBinding();\n $.extend(exerciseInputBinding, {\n find: function find(scope) {\n return $(scope).find('.tutorial-exercise-code-editor');\n },\n getValue: function getValue(el) {\n if (!this.clicked && !this.restore) {\n return null;\n }\n\n var value = {};\n value.label = exerciseLabel(el);\n value.should_check = this.should_check;\n var editor = ace.edit($(el).attr('id'));\n value.code = value.should_check ? editor.getSession().getValue() : editor.getSelectedText() || editor.getSession().getValue();\n value.restore = this.restore;\n value.timestamp = new Date().getTime();\n return value;\n },\n setValue: function setValue(el, value) {\n var editor = ace.edit($(el).attr('id'));\n editor.getSession().setValue(value.code);\n this.runButtons(el).trigger('click');\n\n if (window.shinytest) {\n setTimeout(function () {\n editor.blur();\n }, 0);\n }\n },\n getType: function getType(el) {\n return 'learnr.exercise';\n },\n subscribe: function subscribe(el, callBack) {\n var binding = this;\n this.runButtons(el).on('click.exerciseInputBinding', function (ev) {\n binding.restore = false;\n binding.clicked = true;\n binding.should_check = ev.delegateTarget.hasAttribute('data-check');\n callBack(true);\n });\n $(el).on('restore.exerciseInputBinding', function (ev, options) {\n binding.restore = true;\n binding.clicked = false;\n binding.should_check = options.should_check;\n callBack(true);\n });\n },\n unsubscribe: function unsubscribe(el) {\n this.runButtons(el).off('.exerciseInputBinding');\n },\n runButtons: function runButtons(el) {\n var exercise = thiz.$exerciseContainer(el);\n return exercise.find('.btn-tutorial-run');\n },\n restore: false,\n clicked: false,\n check: false\n });\n Shiny.inputBindings.register(exerciseInputBinding, 'tutorial.exerciseInput');\n var exerciseOutputBinding = new Shiny.OutputBinding();\n $.extend(exerciseOutputBinding, {\n find: function find(scope) {\n return $(scope).find('.tutorial-exercise-output');\n },\n onValueError: function onValueError(el, err) {\n Shiny.unbindAll(el);\n this.renderError(el, err);\n },\n renderValue: function renderValue(el, data) {\n thiz.$showExerciseProgress(exerciseLabel(el), null, false);\n this.outputFrame(el).children().not($(el)).remove();\n Shiny.renderContent(el, data);\n\n if (window.bootstrapStylePandocTables) {\n window.bootstrapStylePandocTables();\n }\n\n if (window.PagedTableDoc) {\n window.PagedTableDoc.initAll();\n }\n\n var restoring = thiz.$exerciseContainer(el).data('restoring');\n\n if (!restoring) {\n ensureExerciseVisible(el);\n thiz.$exerciseContainer(el).data('restoring', false);\n } else {\n thiz.$logTiming('restored-exercise-' + exerciseLabel(el));\n }\n },\n showProgress: function showProgress(el, show) {\n if (show) {\n thiz.$showExerciseProgress(exerciseLabel(el), null, show);\n } else {}\n },\n outputFrame: function outputFrame(el) {\n return $(el).closest('.tutorial-exercise-output-frame');\n }\n });\n Shiny.outputBindings.register(exerciseOutputBinding, 'tutorial.exerciseOutput');\n};\n\nTutorial.prototype.$clearExerciseOutput = function (exercise) {\n var outputFrame = $(exercise).find('.tutorial-exercise-output-frame');\n var outputDiv = $(outputFrame).children('.tutorial-exercise-output');\n outputFrame.children().not(outputDiv).remove();\n outputDiv.empty();\n};\n\nTutorial.prototype.$initializeStorage = function (identifiers, success) {\n var thiz = this;\n\n if (!(typeof window.Promise !== 'undefined' && typeof window.indexedDB !== 'undefined')) {\n success({});\n return;\n }\n\n var dbName = 'LearnrTutorialProgress';\n var storeName = 'Store_' + window.btoa(identifiers.tutorial_id + identifiers.tutorial_version);\n\n var closeStore = function closeStore(store) {\n store._dbp.then(function (db) {\n db.close();\n });\n };\n\n var storeCreated;\n\n try {\n var testStore = new window.idbKeyval.Store(dbName, storeName);\n closeStore(testStore);\n storeCreated = true;\n } catch (error) {\n storeCreated = false;\n }\n\n if (storeCreated === false) {\n success({});\n return;\n }\n\n Shiny.addCustomMessageHandler('tutorial.store_object', function (message) {\n var idbStoreSet = new window.idbKeyval.Store(dbName, storeName);\n window.idbKeyval.set(message.id, message.data, idbStoreSet)[\"catch\"](function (err) {\n console.error(err);\n })[\"finally\"](function () {\n closeStore(idbStoreSet);\n });\n });\n\n thiz.$removeState = function (completed) {\n var idbStoreClear = new window.idbKeyval.Store(dbName, storeName);\n window.idbKeyval.clear(idbStoreClear).then(completed)[\"catch\"](function (err) {\n console.error(err);\n completed();\n })[\"finally\"](function () {\n closeStore(idbStoreClear);\n });\n };\n\n var idbStoreGet = new window.idbKeyval.Store(dbName, storeName);\n window.idbKeyval.keys(idbStoreGet).then(function (keys) {\n var getPromises = keys.map(function (key) {\n return window.idbKeyval.get(key, idbStoreGet);\n });\n return Promise.all(getPromises).then(function (vals) {\n var ret = {};\n var i;\n\n for (i = 0; i < keys.length; i++) {\n ret[keys[i]] = vals[i];\n }\n\n return ret;\n });\n }).then(function (objs) {\n success(objs);\n })[\"catch\"](function (err) {\n console.error(err);\n success({});\n })[\"finally\"](function () {\n closeStore(idbStoreGet);\n });\n};\n\nTutorial.prototype.$restoreState = function (objects) {\n var thiz = this;\n thiz.$logTiming('restoring-state');\n this.$serverRequest('restore_state', objects, function (data) {\n thiz.$logTiming('state-received');\n thiz.$initializeClientState(data.client_state);\n thiz.$fireInit();\n thiz.$initializeProgress(data.progress_events);\n thiz.$restoreSubmissions(data.submissions);\n thiz.$initializeVideoPlayers(data.video_progress);\n });\n};\n\nTutorial.prototype.$restoreSubmissions = function (submissions) {\n var thiz = this;\n\n for (var i = 0; i < submissions.length; i++) {\n var submission = submissions[i];\n var type = submission.type;\n var id = submission.id;\n\n if (type === 'exercise_submission') {\n var label = id;\n var code = submission.data.code;\n var checked = submission.data.checked;\n thiz.$logTiming('restoring-exercise-' + label);\n var editorContainer = thiz.$exerciseEditor(label);\n\n if (editorContainer.length > 0) {\n (function () {\n var editor = ace.edit(editorContainer.attr('id'));\n editor.setValue(code, -1);\n\n if (window.shinytest) {\n setTimeout(function () {\n editor.blur();\n }, 0);\n }\n\n thiz.$exerciseForLabel(label).data('restoring', true);\n thiz.$showExerciseProgress(label, 'run', true);\n editorContainer.trigger('restore', {\n should_check: checked\n });\n })();\n }\n }\n }\n};\n\nTutorial.prototype.$removeState = function (completed) {\n completed();\n};\n\nTutorial.prototype.$initializeClientState = function (clientState) {\n var thiz = this;\n var clientStateLast = {\n scroll_position: 0,\n hash: ''\n };\n var maybePersistClientState = this.$debounce(function () {\n var clientStateCurrent = {\n scroll_position: $(window).scrollTop(),\n hash: window.location.hash\n };\n\n if (clientStateCurrent.scroll_position !== clientStateLast.scroll_position || clientStateCurrent.hash !== clientStateLast.hash) {\n thiz.$serverRequest('set_client_state', clientStateCurrent, null);\n clientStateLast = clientStateCurrent;\n }\n }, 1000);\n $(window).scroll(maybePersistClientState);\n window.addEventListener('popstate', maybePersistClientState);\n\n if (!window.location.hash && clientState.hash) {\n window.location.hash = clientState.hash;\n }\n};\n\nShiny.addCustomMessageHandler('tutorial_isServerAvailable', function (message) {\n TUTORIAL_IS_SERVER_AVAILABLE = true;\n});\n\nTutorial.prototype.$initializeServer = function () {\n var thiz = this;\n thiz.$logTiming('wait-server-available');\n\n function initializeServer() {\n function retry(delay) {\n setTimeout(function () {\n initializeServer();\n }, delay);\n }\n\n if (TUTORIAL_IS_SERVER_AVAILABLE) {\n thiz.$logTiming('server-available');\n thiz.$serverRequest('initialize', {\n location: window.location\n }, function (response) {\n thiz.$logTiming('server-initialized');\n thiz.$initializeStorage(response.identifiers, function (objects) {\n thiz.$logTiming('storage-initialized');\n thiz.$restoreState(objects);\n });\n });\n } else {\n retry(250);\n }\n }\n\n initializeServer();\n};\n\nwindow.Tutorial = Tutorial;", "import \"core-js/modules/es.array.filter.js\";\nimport \"core-js/modules/es.object.to-string.js\";\nimport \"core-js/modules/es.regexp.exec.js\";\nimport \"core-js/modules/es.regexp.test.js\";\nexport function TutorialDiagnostics(tutorial) {\n this.$tutorial = tutorial;\n var self = this;\n\n var unmatchedClosingBracket = function unmatchedClosingBracket(token) {\n return {\n row: token.position.row,\n column: token.position.column,\n type: 'error',\n text: \"unmatched closing bracket '\" + token.value + \"'\"\n };\n };\n\n var unmatchedOpeningBracket = function unmatchedOpeningBracket(token) {\n return {\n row: token.position.row,\n column: token.position.column,\n type: 'error',\n text: \"unmatched opening bracket '\" + token.value + \"'\"\n };\n };\n\n var unexpected = function unexpected(symbol, token, type) {\n return {\n row: token.position.row,\n column: token.position.column,\n type: type || 'error',\n text: 'unexpected ' + symbol + \" '\" + token.value + \"'\"\n };\n };\n\n var isSymbol = function isSymbol(token) {\n var value = token.value || '';\n\n if (value === 'in') {\n return false;\n }\n\n var type = token.type || '';\n return type === 'string' || type === 'constant.numeric' || type === 'constant.language.boolean' || type === 'identifier' || type === 'keyword' || type === 'variable.language';\n };\n\n var isOperator = function isOperator(token) {\n var type = token.type || '';\n return type === 'keyword.operator';\n };\n\n var isUnaryOperator = function isUnaryOperator(token) {\n var value = token.value || '';\n return value === '+' || value === '-' || value === '~' || value === '!' || value === '?';\n };\n\n var diagnose = function diagnose() {\n var editor = this;\n\n var Tokenizer = ace.require('ace/tokenizer').Tokenizer;\n\n var RHighlightRules = ace.require('ace/mode/r_highlight_rules').RHighlightRules;\n\n var rules = new RHighlightRules().getRules();\n\n for (var key in rules) {\n var rule = rules[key];\n\n for (var i = 0; i < rule.length; i++) {\n rule[i].merge = false;\n }\n }\n\n rules.start.unshift({\n token: 'string',\n regex: '\"(?:(?:\\\\\\\\.)|(?:[^\"\\\\\\\\]))*?\"',\n merge: false,\n next: 'start'\n });\n rules.start.unshift({\n token: 'string',\n regex: \"'(?:(?:\\\\\\\\.)|(?:[^'\\\\\\\\]))*?'\",\n merge: false,\n next: 'start'\n });\n rules.start.unshift({\n token: 'keyword.operator',\n regex: ':::|::|:=|%%|>=|<=|==|!=|\\\\|>|\\\\->|<\\\\-|<<\\\\-|\\\\|\\\\||&&|=|\\\\+|\\\\-|\\\\*\\\\*?|/|\\\\^|>|<|!|&|\\\\||~|\\\\$|:|@|\\\\?',\n merge: false,\n next: 'start'\n });\n rules.start.unshift({\n token: 'punctuation',\n regex: '[;,]',\n merge: false,\n next: 'start'\n });\n var tokenizer = new Tokenizer(rules);\n editor.session.clearAnnotations();\n var lines = editor.session.doc.$lines;\n var tokens = [];\n var state = 'start';\n\n for (var _i = 0; _i < lines.length; _i++) {\n var tokenized = tokenizer.getLineTokens(lines[_i], state);\n\n for (var j = 0; j < tokenized.tokens.length; j++) {\n tokens.push(tokenized.tokens[j]);\n }\n\n tokens.push({\n type: 'text',\n value: '\\n'\n });\n state = tokenized.state;\n }\n\n var doc = editor.session.doc;\n var docIndex = 0;\n\n for (var _i2 = 0; _i2 < tokens.length; _i2++) {\n tokens[_i2].position = doc.indexToPosition(docIndex);\n docIndex += tokens[_i2].value.length;\n }\n\n tokens = tokens.filter(function (token) {\n return token.type !== 'comment' && !/^\\s+$/.test(token.value);\n });\n var diagnostics = [];\n var bracketStack = [];\n\n for (var _i3 = 0; _i3 < tokens.length; _i3++) {\n var token = tokens[_i3];\n var type = token.type;\n var value = token.value;\n\n if (value === '(' || value === '{' || value === '[') {\n bracketStack.push(token);\n continue;\n }\n\n if (value === ')' || value === '}' || value === ']') {\n if (bracketStack.length === 0) {\n diagnostics.push(unmatchedClosingBracket(token));\n continue;\n }\n\n var openBracket = bracketStack.pop();\n var ok = value === ')' && openBracket.value === '(' || value === ']' && openBracket.value === '[' || value === '}' && openBracket.value === '{';\n\n if (!ok) {\n diagnostics.push(unmatchedClosingBracket(token));\n diagnostics.push(unmatchedOpeningBracket(openBracket));\n continue;\n }\n }\n\n if (_i3 > 0) {\n var lhs = tokens[_i3 - 1];\n var rhs = tokens[_i3];\n var bracket = bracketStack[bracketStack.length - 1] || {};\n\n if (lhs.position.row === rhs.position.row && isSymbol(lhs) && isSymbol(rhs)) {\n diagnostics.push(unexpected('symbol', rhs));\n continue;\n }\n\n if (lhs.position.row === rhs.position.row && isOperator(lhs) && isOperator(rhs) && !isUnaryOperator(rhs)) {\n diagnostics.push(unexpected('operator', rhs));\n continue;\n }\n\n if (lhs.value === ',' && rhs.value === ',' && bracket.value === '(') {\n diagnostics.push(unexpected('comma', rhs, 'warning'));\n continue;\n }\n\n if (lhs.value === ',' && (rhs.value === '}' || rhs.value === ')' || rhs.value === ']')) {\n diagnostics.push(unexpected('comma', lhs, 'warning'));\n continue;\n }\n }\n }\n\n for (var _i4 = 0; _i4 < bracketStack.length; _i4++) {\n diagnostics.push(unmatchedOpeningBracket(bracketStack[_i4]));\n }\n\n editor.session.setAnnotations(diagnostics);\n };\n\n var findActiveAceInstance = function findActiveAceInstance() {\n var el = document.activeElement;\n\n while (el != null) {\n if (el.env && el.env.editor) {\n return el.env.editor;\n }\n\n el = el.parentElement;\n }\n\n return null;\n };\n\n var ensureInitialized = function ensureInitialized(editor) {\n if (editor.$diagnosticsInitialized) {\n return;\n }\n\n if (!editor.tutorial.diagnostics) {\n return;\n }\n\n var handlers = {};\n handlers.change = self.$onChange.bind(editor);\n\n handlers.destroy = function (event) {\n for (var key in handlers) {\n this.off(key, handlers[key]);\n }\n }.bind(editor);\n\n for (var key in handlers) {\n editor.on(key, handlers[key]);\n }\n\n editor.$liveDiagnostics = diagnose.bind(editor);\n editor.$diagnosticsInitialized = 1;\n };\n\n this.$onChange = function (data) {\n if (!this.tutorial.diagnostics) {\n return;\n }\n\n clearTimeout(this.$diagnosticsTimerId);\n this.session.clearAnnotations();\n this.$diagnosticsTimerId = setTimeout(this.$liveDiagnostics, 1000);\n };\n\n this.$onKeyDown = function (event) {\n var editor = findActiveAceInstance();\n\n if (editor != null) {\n ensureInitialized(editor);\n document.removeEventListener('keydown', this.$onKeyDown);\n }\n };\n\n document.addEventListener('keydown', this.$onKeyDown);\n}", "import \"core-js/modules/es.regexp.exec.js\";\nimport \"core-js/modules/es.regexp.test.js\";\nimport \"core-js/modules/es.array.map.js\";\nimport \"core-js/modules/es.string.trim.js\";\nexport function TutorialCompleter(tutorial) {\n this.$tutorial = tutorial;\n var self = this;\n\n this.$onChange = function (data) {\n clearTimeout(this.$autocompletionTimerId);\n data = data || {};\n\n if (data.action !== 'insert') {\n return;\n }\n\n var lines = data.lines || [];\n\n if (lines.length !== 1) {\n return;\n }\n\n var pos = this.getCursorPosition();\n var line = this.session.getLine(pos.row);\n var popup = (this.completer || {}).popup;\n\n if (popup && popup.isOpen && !/::$/.test(line)) {\n return;\n }\n\n var delayMs = 300;\n\n if (/[$@]$|::$/.test(line)) {\n delayMs = 10;\n }\n\n this.$autocompletionTimerId = setTimeout(this.$liveAutocompleter, delayMs);\n };\n\n var MODIFIER_NONE = 0;\n var MODIFIER_CTRL = 1;\n var MODIFIER_ALT = 2;\n var MODIFIER_SHIFT = 4;\n var KEYCODE_TAB = 9;\n var KEYCODE_SPACE = 32;\n\n var KeyCombination = function KeyCombination(event) {\n this.keyCode = event.keyCode || event.which;\n this.modifier = MODIFIER_NONE;\n this.modifier |= event.ctrlKey ? MODIFIER_CTRL : 0;\n this.modifier |= event.altKey ? MODIFIER_ALT : 0;\n this.modifier |= event.shiftKey ? MODIFIER_SHIFT : 0;\n };\n\n function initializeAceEventListeners(editor) {\n var handlers = {};\n handlers.change = self.$onChange.bind(editor);\n\n handlers.destroy = function (event) {\n for (var key in handlers) {\n this.off(key, handlers[key]);\n }\n }.bind(editor);\n\n for (var key in handlers) {\n editor.on(key, handlers[key]);\n }\n }\n\n function initializeCompletionEngine(editor) {\n editor.completers = editor.completers || [];\n editor.completers.push({\n getCompletions: function getCompletions(editor, session, position, prefix, callback) {\n var contents = session.getTextRange({\n start: {\n row: 0,\n column: 0\n },\n end: position\n });\n var payload = {\n contents: contents,\n label: editor.tutorial.label\n };\n self.$tutorial.$serverRequest('completion', payload, function (data) {\n data = data || [];\n var completer = {\n insertMatch: function insertMatch(editor, data) {\n var ranges = editor.selection.getAllRanges();\n var completions = editor.completer.completions;\n var n = completions.filterText.length;\n\n for (var i = 0; i < ranges.length; i++) {\n ranges[i].start.column -= n;\n editor.session.remove(ranges[i]);\n }\n\n var term = data.value + (data.is_function ? '()' : '');\n editor.execCommand('insertstring', term);\n\n if (data.is_function) {\n editor.navigateLeft(1);\n }\n }\n };\n var completions = data.map(function (el) {\n return {\n caption: el[0] + (el[1] ? '()' : ''),\n value: el[0],\n score: 0,\n meta: 'R',\n is_function: el[1],\n completer: completer\n };\n });\n callback(null, completions);\n });\n }\n });\n editor.setOptions({\n enableBasicAutocompletion: true,\n enableLiveAutocompletion: false\n });\n }\n\n function initializeSetupChunk(editor) {\n var data = editor.tutorial;\n self.$tutorial.$serverRequest('initialize_chunk', data);\n }\n\n function ensureInitialized(editor) {\n if (!editor.tutorial.completion) {\n return;\n }\n\n if (editor.$autocompletionInitialized) {\n return;\n }\n\n initializeAceEventListeners(editor);\n initializeCompletionEngine(editor);\n initializeSetupChunk(editor);\n\n if (typeof editor.$liveAutocompleter === 'undefined') {\n editor.$liveAutocompleter = function () {\n this.execCommand('startAutocomplete');\n }.bind(editor);\n }\n\n editor.$autocompletionInitialized = 1;\n }\n\n function findActiveAceInstance() {\n var el = document.activeElement;\n\n while (el != null) {\n if (el.env && el.env.editor) {\n return el.env.editor;\n }\n\n el = el.parentElement;\n }\n\n return null;\n }\n\n function autocomplete(event) {\n var editor = findActiveAceInstance();\n\n if (editor == null) {\n return;\n }\n\n if (!editor.tutorial.completion) {\n return;\n }\n\n ensureInitialized(editor);\n clearTimeout(editor.$autocompletionTimerId);\n var keys = new KeyCombination(event);\n\n if (keys.keyCode === KEYCODE_TAB) {\n if (editor.container.matches('.ace_indent_off')) {\n return;\n }\n\n var pos = editor.getCursorPosition();\n var line = editor.session.getLine(pos.row);\n var isCursorAtStart = line.substr(0, pos.column).trim() === '';\n\n if (isCursorAtStart) {\n return;\n }\n }\n\n event.stopPropagation();\n event.preventDefault();\n editor.execCommand('startAutocomplete');\n }\n\n document.addEventListener('keydown', function (event) {\n var editor = findActiveAceInstance();\n\n if (editor !== null) {\n ensureInitialized(editor);\n }\n\n if (editor !== null && !editor.tutorial.completion) {\n return;\n }\n\n var keys = new KeyCombination(event);\n\n if (keys.keyCode === KEYCODE_TAB && keys.modifier === MODIFIER_NONE) {\n if (editor && editor.completer && editor.completer.activated) {\n return;\n }\n\n return autocomplete(event);\n }\n\n if (keys.keyCode === KEYCODE_SPACE && keys.modifier === MODIFIER_CTRL) {\n return autocomplete(event);\n }\n }, true);\n}"],
+ "mappings": "8lnCAEA,OAAO,4geAsBP,OAAO,ukECtBP,OAAO,WAEA,YAA6B,EAAU,CAC5C,KAAK,UAAY,EACjB,GAAI,GAAO,KAEP,EAA0B,SAAiC,EAAO,CACpE,MAAO,CACL,IAAK,EAAM,SAAS,IACpB,OAAQ,EAAM,SAAS,OACvB,KAAM,QACN,KAAM,8BAAgC,EAAM,MAAQ,MAIpD,EAA0B,SAAiC,EAAO,CACpE,MAAO,CACL,IAAK,EAAM,SAAS,IACpB,OAAQ,EAAM,SAAS,OACvB,KAAM,QACN,KAAM,8BAAgC,EAAM,MAAQ,MAIpD,EAAa,SAAoB,EAAQ,EAAO,EAAM,CACxD,MAAO,CACL,IAAK,EAAM,SAAS,IACpB,OAAQ,EAAM,SAAS,OACvB,KAAM,GAAQ,QACd,KAAM,cAAgB,EAAS,KAAO,EAAM,MAAQ,MAIpD,EAAW,SAAkB,EAAO,CACtC,GAAI,GAAQ,EAAM,OAAS,GAE3B,GAAI,IAAU,KACZ,MAAO,GAGT,GAAI,GAAO,EAAM,MAAQ,GACzB,MAAO,KAAS,UAAY,IAAS,oBAAsB,IAAS,6BAA+B,IAAS,cAAgB,IAAS,WAAa,IAAS,qBAGzJ,EAAa,SAAoB,EAAO,CAC1C,GAAI,GAAO,EAAM,MAAQ,GACzB,MAAO,KAAS,oBAGd,EAAkB,SAAyB,EAAO,CACpD,GAAI,GAAQ,EAAM,OAAS,GAC3B,MAAO,KAAU,KAAO,IAAU,KAAO,IAAU,KAAO,IAAU,KAAO,IAAU,KAGnF,EAAW,UAAoB,CACjC,GAAI,GAAS,KAET,EAAY,IAAI,QAAQ,iBAAiB,UAEzC,EAAkB,IAAI,QAAQ,8BAA8B,gBAE5D,EAAQ,GAAI,KAAkB,WAElC,OAAS,KAAO,GAGd,OAFI,GAAO,EAAM,GAER,EAAI,EAAG,EAAI,EAAK,OAAQ,IAC/B,EAAK,GAAG,MAAQ,GAIpB,EAAM,MAAM,QAAQ,CAClB,MAAO,SACP,MAAO,iCACP,MAAO,GACP,KAAM,UAER,EAAM,MAAM,QAAQ,CAClB,MAAO,SACP,MAAO,iCACP,MAAO,GACP,KAAM,UAER,EAAM,MAAM,QAAQ,CAClB,MAAO,mBACP,MAAO,4GACP,MAAO,GACP,KAAM,UAER,EAAM,MAAM,QAAQ,CAClB,MAAO,cACP,MAAO,OACP,MAAO,GACP,KAAM,UAER,GAAI,GAAY,GAAI,GAAU,GAC9B,EAAO,QAAQ,mBAKf,OAJI,GAAQ,EAAO,QAAQ,IAAI,OAC3B,EAAS,GACT,EAAQ,QAEH,EAAK,EAAG,EAAK,EAAM,OAAQ,IAAM,CAGxC,OAFI,GAAY,EAAU,cAAc,EAAM,GAAK,GAE1C,EAAI,EAAG,EAAI,EAAU,OAAO,OAAQ,IAC3C,EAAO,KAAK,EAAU,OAAO,IAG/B,EAAO,KAAK,CACV,KAAM,OACN,MAAO,OAET,EAAQ,EAAU,MAMpB,OAHI,IAAM,EAAO,QAAQ,IACrB,EAAW,EAEN,EAAM,EAAG,EAAM,EAAO,OAAQ,IACrC,EAAO,GAAK,SAAW,GAAI,gBAAgB,GAC3C,GAAY,EAAO,GAAK,MAAM,OAGhC,EAAS,EAAO,OAAO,SAAU,GAAO,CACtC,MAAO,IAAM,OAAS,WAAa,CAAC,QAAQ,KAAK,GAAM,SAKzD,OAHI,GAAc,GACd,EAAe,GAEV,EAAM,EAAG,EAAM,EAAO,OAAQ,IAAO,CAC5C,GAAI,GAAQ,EAAO,GACf,EAAO,EAAM,KACb,EAAQ,EAAM,MAElB,GAAI,IAAU,KAAO,IAAU,KAAO,IAAU,IAAK,CACnD,EAAa,KAAK,GAClB,SAGF,GAAI,IAAU,KAAO,IAAU,KAAO,IAAU,IAAK,CACnD,GAAI,EAAa,SAAW,EAAG,CAC7B,EAAY,KAAK,EAAwB,IACzC,SAGF,GAAI,GAAc,EAAa,MAC3B,GAAK,IAAU,KAAO,EAAY,QAAU,KAAO,IAAU,KAAO,EAAY,QAAU,KAAO,IAAU,KAAO,EAAY,QAAU,IAE5I,GAAI,CAAC,GAAI,CACP,EAAY,KAAK,EAAwB,IACzC,EAAY,KAAK,EAAwB,IACzC,UAIJ,GAAI,EAAM,EAAG,CACX,GAAI,GAAM,EAAO,EAAM,GACnB,EAAM,EAAO,GACb,GAAU,EAAa,EAAa,OAAS,IAAM,GAEvD,GAAI,EAAI,SAAS,MAAQ,EAAI,SAAS,KAAO,EAAS,IAAQ,EAAS,GAAM,CAC3E,EAAY,KAAK,EAAW,SAAU,IACtC,SAGF,GAAI,EAAI,SAAS,MAAQ,EAAI,SAAS,KAAO,EAAW,IAAQ,EAAW,IAAQ,CAAC,EAAgB,GAAM,CACxG,EAAY,KAAK,EAAW,WAAY,IACxC,SAGF,GAAI,EAAI,QAAU,KAAO,EAAI,QAAU,KAAO,GAAQ,QAAU,IAAK,CACnE,EAAY,KAAK,EAAW,QAAS,EAAK,YAC1C,SAGF,GAAI,EAAI,QAAU,KAAQ,GAAI,QAAU,KAAO,EAAI,QAAU,KAAO,EAAI,QAAU,KAAM,CACtF,EAAY,KAAK,EAAW,QAAS,EAAK,YAC1C,WAKN,OAAS,IAAM,EAAG,GAAM,EAAa,OAAQ,KAC3C,EAAY,KAAK,EAAwB,EAAa,MAGxD,EAAO,QAAQ,eAAe,IAG5B,EAAwB,UAAiC,CAG3D,OAFI,GAAK,SAAS,cAEX,GAAM,MAAM,CACjB,GAAI,EAAG,KAAO,EAAG,IAAI,OACnB,MAAO,GAAG,IAAI,OAGhB,EAAK,EAAG,cAGV,MAAO,OAGL,EAAoB,SAA2B,EAAQ,CACzD,GAAI,GAAO,yBAIP,EAAC,EAAO,SAAS,YAIrB,IAAI,GAAW,GACf,EAAS,OAAS,EAAK,UAAU,KAAK,GAEtC,EAAS,QAAU,SAAU,EAAO,CAClC,OAAS,KAAO,GACd,KAAK,IAAI,EAAK,EAAS,KAEzB,KAAK,GAEP,OAAS,KAAO,GACd,EAAO,GAAG,EAAK,EAAS,IAG1B,EAAO,iBAAmB,EAAS,KAAK,GACxC,EAAO,wBAA0B,IAGnC,KAAK,UAAY,SAAU,EAAM,CAC/B,AAAI,CAAC,KAAK,SAAS,aAInB,cAAa,KAAK,qBAClB,KAAK,QAAQ,mBACb,KAAK,oBAAsB,WAAW,KAAK,iBAAkB,OAG/D,KAAK,WAAa,SAAU,EAAO,CACjC,GAAI,GAAS,IAEb,AAAI,GAAU,MACZ,GAAkB,GAClB,SAAS,oBAAoB,UAAW,KAAK,cAIjD,SAAS,iBAAiB,UAAW,KAAK,YC1P5C,OAAO,+HAIA,YAA2B,EAAU,CAC1C,KAAK,UAAY,EACjB,GAAI,GAAO,KAEX,KAAK,UAAY,SAAU,EAAM,CAI/B,GAHA,aAAa,KAAK,wBAClB,EAAO,GAAQ,GAEX,EAAK,SAAW,SAIpB,IAAI,GAAQ,EAAK,OAAS,GAE1B,GAAI,EAAM,SAAW,EAIrB,IAAI,GAAM,KAAK,oBACX,EAAO,KAAK,QAAQ,QAAQ,EAAI,KAChC,EAAS,MAAK,WAAa,IAAI,MAEnC,GAAI,KAAS,EAAM,QAAU,CAAC,MAAM,KAAK,IAIzC,IAAI,GAAU,IAEd,AAAI,YAAY,KAAK,IACnB,GAAU,IAGZ,KAAK,uBAAyB,WAAW,KAAK,mBAAoB,OAGpE,GAAI,GAAgB,EAChB,EAAgB,EAChB,EAAe,EACf,EAAiB,EACjB,EAAc,EACd,EAAgB,GAEhB,EAAiB,SAAwB,EAAO,CAClD,KAAK,QAAU,EAAM,SAAW,EAAM,MACtC,KAAK,SAAW,EAChB,KAAK,UAAY,EAAM,QAAU,EAAgB,EACjD,KAAK,UAAY,EAAM,OAAS,EAAe,EAC/C,KAAK,UAAY,EAAM,SAAW,EAAiB,GAGrD,WAAqC,EAAQ,CAC3C,GAAI,GAAW,GACf,EAAS,OAAS,EAAK,UAAU,KAAK,GAEtC,EAAS,QAAU,SAAU,EAAO,CAClC,OAAS,KAAO,GACd,KAAK,IAAI,EAAK,EAAS,KAEzB,KAAK,GAEP,OAAS,KAAO,GACd,EAAO,GAAG,EAAK,EAAS,IAI5B,WAAoC,EAAQ,CAC1C,EAAO,WAAa,EAAO,YAAc,GACzC,EAAO,WAAW,KAAK,CACrB,eAAgB,SAAwB,EAAQ,EAAS,EAAU,EAAQ,EAAU,CACnF,GAAI,GAAW,EAAQ,aAAa,CAClC,MAAO,CACL,IAAK,EACL,OAAQ,GAEV,IAAK,IAEH,EAAU,CACZ,SAAU,EACV,MAAO,EAAO,SAAS,OAEzB,EAAK,UAAU,eAAe,aAAc,EAAS,SAAU,EAAM,CACnE,EAAO,GAAQ,GACf,GAAI,GAAY,CACd,YAAa,SAAqB,EAAQ,EAAM,CAK9C,OAJI,GAAS,EAAO,UAAU,eAC1B,EAAc,EAAO,UAAU,YAC/B,EAAI,EAAY,WAAW,OAEtB,EAAI,EAAG,EAAI,EAAO,OAAQ,IACjC,EAAO,GAAG,MAAM,QAAU,EAC1B,EAAO,QAAQ,OAAO,EAAO,IAG/B,GAAI,GAAO,EAAK,MAAS,GAAK,YAAc,KAAO,IACnD,EAAO,YAAY,eAAgB,GAE/B,EAAK,aACP,EAAO,aAAa,KAItB,GAAc,EAAK,IAAI,SAAU,EAAI,CACvC,MAAO,CACL,QAAS,EAAG,GAAM,GAAG,GAAK,KAAO,IACjC,MAAO,EAAG,GACV,MAAO,EACP,KAAM,IACN,YAAa,EAAG,GAChB,UAAW,KAGf,EAAS,KAAM,SAIrB,EAAO,WAAW,CAChB,0BAA2B,GAC3B,yBAA0B,KAI9B,WAA8B,EAAQ,CACpC,GAAI,GAAO,EAAO,SAClB,EAAK,UAAU,eAAe,mBAAoB,GAGpD,WAA2B,EAAQ,CACjC,AAAI,CAAC,EAAO,SAAS,YAIjB,EAAO,4BAIX,GAA4B,GAC5B,EAA2B,GAC3B,EAAqB,GAEjB,MAAO,GAAO,oBAAuB,aACvC,GAAO,mBAAqB,UAAY,CACtC,KAAK,YAAY,sBACjB,KAAK,IAGT,EAAO,2BAA6B,GAGtC,YAAiC,CAG/B,OAFI,GAAK,SAAS,cAEX,GAAM,MAAM,CACjB,GAAI,EAAG,KAAO,EAAG,IAAI,OACnB,MAAO,GAAG,IAAI,OAGhB,EAAK,EAAG,cAGV,MAAO,MAGT,WAAsB,EAAO,CAC3B,GAAI,GAAS,IAEb,GAAI,GAAU,MAIV,EAAC,EAAO,SAAS,WAIrB,GAAkB,GAClB,aAAa,EAAO,wBACpB,GAAI,GAAO,GAAI,GAAe,GAE9B,GAAI,EAAK,UAAY,EAAa,CAChC,GAAI,EAAO,UAAU,QAAQ,mBAC3B,OAGF,GAAI,GAAM,EAAO,oBACb,EAAO,EAAO,QAAQ,QAAQ,EAAI,KAClC,EAAkB,EAAK,OAAO,EAAG,EAAI,QAAQ,SAAW,GAE5D,GAAI,EACF,OAIJ,EAAM,kBACN,EAAM,iBACN,EAAO,YAAY,sBAGrB,SAAS,iBAAiB,UAAW,SAAU,EAAO,CACpD,GAAI,GAAS,IAMb,GAJI,IAAW,MACb,EAAkB,GAGhB,MAAW,MAAQ,CAAC,EAAO,SAAS,YAIxC,IAAI,GAAO,GAAI,GAAe,GAE9B,GAAI,EAAK,UAAY,GAAe,EAAK,WAAa,EACpD,MAAI,IAAU,EAAO,WAAa,EAAO,UAAU,UACjD,OAGK,EAAa,GAGtB,GAAI,EAAK,UAAY,GAAiB,EAAK,WAAa,EACtD,MAAO,GAAa,KAErB,IFhOL,YAAwB,EAAW,EAAW,CAAE,GAAI,IAAc,EAAa,KAAM,IAAI,WAAU,wCAgCnG,EAAE,UAAU,MAAM,UAAY,CAC5B,GAAI,GAAW,GAAI,GAEnB,AAAI,MAAO,KAAsB,aAC/B,GAAS,WAAa,GAAI,IAAkB,IAG1C,MAAO,KAAwB,aACjC,GAAS,aAAe,GAAI,IAAoB,IAGlD,OAAO,SAAW,IAEpB,GAAI,IAA+B,GAEnC,YAAoB,CAClB,GAAI,GAAO,KACX,KAAK,iBACL,KAAK,MAAQ,CAAC,OAAO,UAEjB,KAAK,OACP,SAAS,KAAK,UAAU,IAAI,mBAG9B,KAAK,OAAS,SAAU,EAAS,CAC/B,KAAK,eAAe,IAAI,IAG1B,KAAK,WAAa,SAAU,EAAS,CACnC,KAAK,mBAAmB,IAAI,IAG9B,KAAK,UAAY,UAAY,CAC3B,EAAK,aAAa,UAAY,CAC5B,EAAK,eAAe,eAAgB,KAAM,UAAY,CACpD,OAAO,SAAS,QAAQ,OAAO,SAAS,OAAS,OAAO,SAAS,eAKvE,KAAK,YAAc,SAAU,EAAW,CACtC,AAAI,IACF,EAAK,eAAe,kBAAmB,CACrC,UAAW,GACV,OAIP,KAAK,eAAiB,SAAU,EAAS,CACvC,EAAU,EAAE,GACZ,GAAI,GAAO,EAAQ,GAAG,wBAEtB,AAAI,GAAK,IAAM,GAAK,EAAK,OAAS,EAAE,QAAQ,WACtC,EAAQ,GAAG,gBACb,GAAQ,GAAG,eAAe,IAC1B,SAAS,KAAK,WAAa,KAKjC,EAAK,oBACL,EAAK,uBACL,EAAK,oBAGP,EAAS,UAAU,eAAiB,UAAY,CAC9C,GAAI,CACF,AAAI,YAAY,OAAS,QACvB,YAAY,KAAK,6BAEZ,EAAP,CACA,QAAQ,IAAI,kCAAoC,EAAE,WAItD,EAAS,UAAU,WAAa,SAAU,EAAM,CAC9C,GAAI,CACF,GAAI,YAAY,OAAS,QAAa,YAAY,UAAY,QAAa,YAAY,mBAAqB,QAAa,KAAK,SAAS,iBAAmB,IAAK,CAC7J,YAAY,KAAK,EAAO,SACxB,YAAY,QAAQ,EAAM,sBAAuB,EAAO,SACxD,GAAI,GAAU,YAAY,iBAAiB,GAC3C,QAAQ,IAAI,YAAc,EAAO,KAAO,KAAK,MAAM,EAAQ,GAAG,UAAY,aAErE,EAAP,CACA,QAAQ,IAAI,yBAA2B,EAAE,WAI7C,EAAS,UAAU,SAAW,SAAU,EAAM,CAC5C,MAAO,WAAU,OAAO,SAAS,OAAO,QAAQ,GAAI,QAAO,eAAiB,UAAU,GAAM,QAAQ,SAAU,QAAU,uBAAwB,KAAM,QAGxJ,EAAS,UAAU,YAAc,SAAU,EAAI,CAC7C,MAAO,IAAM,EAAG,QAAQ,sBAAuB,SAGjD,EAAS,eAAiB,UAAY,CACpC,AAAI,OAAO,SACT,QAAQ,IAAI,MAAM,CAAC,UAAW,QAAQ,OAI1C,EAAS,UAAU,eAAiB,EAAE,YAEtC,EAAS,UAAU,UAAY,UAAY,CACzC,GAAI,GAAO,KAEX,GAAI,CACF,EAAK,eAAe,aACb,EAAP,CACA,QAAQ,IAAI,KAIhB,EAAS,UAAU,mBAAqB,EAAE,YAC1C,EAAS,UAAU,gBAAkB,GAErC,EAAS,UAAU,2BAA6B,SAAU,EAAS,CAGjE,OAFI,GAAO,KAEF,EAAI,EAAG,EAAI,EAAK,gBAAgB,OAAQ,IAAK,CACpD,GAAI,GAAQ,EAAK,gBAAgB,GAEjC,GAAI,EAAE,EAAM,SAAS,GAAG,EAAE,KACpB,EAAM,UACR,MAAO,GAKb,MAAO,IAGT,EAAS,UAAU,cAAgB,SAAU,EAAO,CAClD,KAAK,gBAAgB,KAAK,GAE1B,GAAI,CACF,KAAK,mBAAmB,KAAK,SACtB,EAAP,CACA,QAAQ,IAAI,KAIhB,EAAS,UAAU,sBAAwB,SAAU,EAAS,CAC5D,GAAI,GAAO,KAEX,WAAuB,EAAI,CACzB,GAAI,GAAQ,CACV,QAAS,EACT,MAAO,qBAET,EAAK,cAAc,GAGrB,GAAI,GAAU,EAAE,GAAS,SAAS,QAAQ,YAE1C,GAAI,EAAQ,SAAW,EAOvB,QAHI,GAAa,EAAQ,KAAK,2DAC1B,EAAe,GAEV,EAAI,EAAG,EAAI,EAAW,OAAQ,IAAK,CAC1C,GAAI,GAAY,EAAW,IAAI,GAE/B,GAAI,CAAC,EAAK,2BAA2B,GAAY,CAC/C,EAAe,GACf,OAIJ,GAAI,EAAc,CAChB,EAAc,EAAE,GAAS,IAAI,IAC7B,GAAI,GAAmB,EAAQ,QAAQ,YACvC,EAAiB,KAAK,UAAY,CAChC,GAAI,GAAa,EAAE,MAAM,KAAK,0CAE9B,AAAI,EAAW,SAAW,GACxB,EAAc,QAGlB,GAAI,GAAgB,EAAQ,SAAS,QAAQ,YAE7C,AAAI,EAAc,OAAS,GACzB,KAAK,sBAAsB,MAKjC,EAAS,UAAU,iCAAmC,SAAU,EAAe,CAI7E,OAHI,GAAO,KACP,EAEK,EAAI,EAAK,gBAAgB,OAAS,EAAG,GAAK,EAAG,IAGpD,GAFA,EAAQ,EAAK,gBAAgB,GAEzB,EAAM,QAAU,uBACd,EAAM,KAAK,QAAU,EAAc,KAAK,MAAQ,EAAc,KAAK,QAAU,OAAW,CAC1F,EAAK,gBAAgB,OAAO,EAAG,GAC/B,SAMR,EAAS,UAAU,mBAAqB,SAAU,EAAO,EAAM,CAC7D,GAAI,GAAO,KACP,EAAgB,CAClB,MAAO,EACP,KAAM,GAGR,GAAI,IAAU,uBAAyB,IAAU,sBAAuB,CACtE,GAAI,GAAU,EAAE,kCAAoC,EAAK,MAAQ,MAAM,IAAI,kCAAoC,EAAK,MAAQ,MAE5H,AAAI,EAAQ,OAAS,GACnB,GAAc,QAAU,EAExB,AAAI,IAAU,sBACZ,EAAc,UAAY,MAAO,GAAK,WAAc,YAAc,EAAK,UAAY,GAEnF,EAAc,UAAY,EAAK,SAAW,cAGrC,IAAU,kBAAmB,CACtC,GAAI,GAAkB,EAAE,EAAK,YAAY,EAAK,YAC9C,EAAc,QAAU,EACxB,EAAc,UAAY,WACjB,IAAU,iBAAkB,CACrC,GAAI,GAAe,EAAE,eAAiB,EAAK,UAAY,MAEvD,AAAI,EAAa,OAAS,GACxB,GAAc,QAAU,EACxB,EAAc,UAAY,EAAI,EAAK,KAAO,EAAK,YAInD,KAAK,iCAAiC,GAElC,EAAc,SAChB,MAAK,cAAc,GACnB,EAAK,sBAAsB,EAAc,WAI7C,EAAS,UAAU,oBAAsB,SAAU,EAAgB,CAGjE,OAFI,GAAO,KAEF,EAAI,EAAG,EAAI,EAAe,OAAQ,IAAK,CAC9C,GAAI,GAAW,EAAe,GAC1B,EAAgB,EAAS,MACzB,EAAoB,GAExB,AAAI,IAAkB,sBACpB,GAAkB,MAAQ,EAAS,KAAK,MACxC,EAAkB,QAAU,EAAS,KAAK,SACrC,AAAI,IAAkB,sBAC3B,GAAkB,MAAQ,EAAS,KAAK,MACxC,EAAkB,OAAS,EAAS,KAAK,QACpC,AAAI,IAAkB,kBAC3B,EAAkB,UAAY,EAAS,KAAK,UACnC,IAAkB,kBAC3B,GAAkB,UAAY,EAAS,KAAK,UAC5C,EAAkB,KAAO,EAAS,KAAK,KACvC,EAAkB,WAAa,EAAS,KAAK,YAG/C,EAAK,mBAAmB,EAAe,GAGzC,MAAM,wBAAwB,0BAA2B,SAAU,EAAU,CAC3E,EAAK,mBAAmB,EAAS,MAAO,EAAS,SAIrD,EAAS,UAAU,eAAiB,SAAU,EAAM,EAAM,EAAS,EAAO,CACxE,GAAI,GAAwB,MAAM,SAAS,OACvC,EAAY,EAAsB,UAClC,EAAW,EAAsB,SACrC,MAAO,GAAE,KAAK,CACZ,KAAM,OACN,IAAK,WAAW,OAAO,EAAW,aAAa,OAAO,EAAM,OAAO,OAAO,GAC1E,YAAa,mBACb,KAAM,KAAK,UAAU,GACrB,SAAU,OACV,QAAS,EACT,MAAO,KAIX,EAAS,UAAU,aAAe,SAAU,EAAO,EAAO,EAAM,CAC9D,GAAI,GAAS,CACX,MAAO,EACP,MAAO,EACP,KAAM,GAER,KAAK,eAAe,eAAgB,EAAQ,OAG9C,EAAS,UAAU,YAAc,SAAU,EAAK,CAC9C,MAAO,GAAI,MAAM,cAAc,QAGjC,EAAS,UAAU,cAAgB,SAAU,EAAK,EAAQ,CACxD,GAAI,GAAS,SAAS,cAAc,UACpC,EAAO,IAAM,EACb,GAAI,GAAiB,SAAS,qBAAqB,UAAU,GAC7D,EAAe,WAAW,aAAa,EAAQ,GAC/C,EAAE,GAAQ,GAAG,OAAQ,IAGvB,EAAS,UAAU,UAAY,SAAU,EAAM,EAAM,EAAW,CAC9D,GAAI,GACJ,MAAO,WAAY,CACjB,GAAI,GAAU,KACV,EAAO,UAEP,EAAQ,UAAiB,CAC3B,EAAU,KACL,GAAW,EAAK,MAAM,EAAS,IAGlC,EAAU,GAAa,CAAC,EAC5B,aAAa,GACb,EAAU,WAAW,EAAO,GACxB,GAAS,EAAK,MAAM,EAAS,KAIrC,EAAS,UAAU,kBAAoB,UAAY,CACjD,GAAI,GAAe,+DACf,EAAa,uDAEjB,WAAwB,EAAK,CAC3B,MAAO,GAAI,MAAM,GAGnB,WAAsB,EAAK,CACzB,MAAO,GAAI,MAAM,GAGnB,WAAiB,EAAK,CACpB,MAAO,GAAe,IAAQ,EAAa,GAG7C,WAA2B,EAAK,CAC9B,GAAI,GAAe,EAAI,MAAM,GAE7B,GAAI,EACF,MAAO,iCAAiC,OAAO,EAAa,GAAI,kBAGlE,GAAI,GAAa,EAAI,MAAM,GAE3B,MAAI,GACK,kCAAkC,OAAO,EAAW,IAGtD,EAGT,WAA0B,EAAW,EAAO,EAAQ,CAClD,GAAI,GAAc,EAAI,GAMtB,GAJK,GACH,GAAQ,QAGN,EAAM,MAAM,MAAQ,IAAK,CAG3B,GAFA,EAAU,IAAI,QAAS,GAEnB,CAAC,EAAQ,CACX,EAAS,EACT,GAAI,GAAgB,WAAW,GAAS,EAAc,IACtD,EAAU,IAAI,iBAAkB,GAGlC,EAAU,IAAI,SAAU,OAExB,AAAI,GAAE,UAAU,IACd,GAAQ,EAAQ,MAGlB,EAAU,IAAI,QAAS,GAElB,GACH,GAAS,WAAW,GAAS,EAAc,MAG7C,EAAU,IAAI,SAAU,GAI5B,EAAE,OAAO,KAAK,UAAY,CACxB,GAAI,GAAW,EAAE,MAAM,KAAK,OAE5B,GAAI,EAAC,EAAQ,GAIb,GAAE,MAAM,IAAI,UAAW,QACvB,GAAI,GAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,MAC7B,EAAS,EAAE,MAAM,IAAI,GAAG,MAAM,OAClC,EAAE,MAAM,IAAI,QAAS,IAAI,IAAI,SAAU,IACvC,GAAI,GAAQ,GACZ,EAAE,KAAK,KAAK,WAAY,SAAU,EAAM,EAAM,CAC5C,OAAQ,EAAK,cACN,QACH,CACE,EAAQ,OAAO,EAAK,WACpB,UAGC,SACH,CACE,EAAS,OAAO,EAAK,WACrB,UAGC,MACH,CACE,EAAM,IAAM,EAAkB,EAAK,WACnC,cAKA,EAAM,EAAK,UAAY,EAAK,aAIpC,EAAE,MAAM,YAAY,UAAY,CAC9B,GAAI,GAAS,EAAE,YAAa,GAC5B,EAAO,SAAS,kBAEhB,AAAI,EAAe,GACjB,EAAO,SAAS,0BACP,EAAa,IACtB,EAAO,SAAS,wBAGlB,EAAO,KAAK,kBAAmB,IAC/B,EAAO,IAAI,UAAW,IACtB,GAAI,GAAY,EAAE,gDAClB,SAAiB,EAAW,EAAO,GACnC,EAAU,OAAO,GACV,OAGX,KAAK,WAAW,uBAGlB,EAAS,UAAU,wBAA0B,SAAU,EAAe,CACpE,AAAI,SAAS,KAAK,OAAO,UAAU,YAInC,MAAK,0BAA0B,GAC/B,KAAK,wBAAwB,KAG/B,EAAS,UAAU,wBAA0B,SAAU,EAAK,EAAe,CACzE,OAAS,GAAI,EAAG,EAAI,EAAc,OAAQ,IAAK,CAC7C,GAAI,GAAK,EAAc,GAAG,GAE1B,GAAI,IAAQ,EAAI,CACd,GAAI,GAAO,EAAc,GAAG,KAAK,KAC7B,EAAY,EAAc,GAAG,KAAK,WAEtC,GAAI,EAAO,IAAM,EAAY,EAAO,GAClC,MAAO,IAKb,MAAO,IAGT,EAAS,UAAU,0BAA4B,SAAU,EAAe,CACtE,GAAI,GAAO,KACP,EAAS,EAAE,iCAEf,AAAI,EAAO,OAAS,GAClB,KAAK,cAAc,qCAAsC,UAAY,CACnE,GAAG,MAAM,UAAY,CACnB,EAAO,KAAK,UAAY,CACtB,GAAI,GAAQ,EAAE,MACV,EAAW,EAAM,KAAK,OACtB,EAAS,KACT,EAAY,GAEhB,YAA0B,CACxB,EAAK,qBAAqB,EAAU,EAAO,iBAAkB,EAAO,eAGtE,YAAuB,CACrB,GAAI,GAAc,EAAK,wBAAwB,EAAU,GAEzD,AAAI,EAAc,GAChB,GAAO,OACP,EAAO,YACP,WAAW,UAAY,CACrB,EAAO,aACP,EAAO,OAAO,EAAa,IAC3B,EAAO,UACN,MAIP,YAAmB,CACjB,IAGF,YAAyB,CACvB,GAAI,GAAQ,EAAO,iBACf,EAAe,IAAU,GACzB,EAAS,IAAU,GAAG,YAAY,KAClC,EAAY,IAAU,GAAG,YAAY,QACrC,EAAc,IAAU,EAE5B,AAAI,CAAE,IAAgB,IAAY,IAAa,IAC7C,IAGF,EAAY,EAGd,EAAS,GAAI,IAAG,OAAO,KAAM,CAC3B,OAAQ,CACN,QAAS,EACT,cAAe,KAGnB,OAAO,YAAY,EAAe,YAO5C,EAAS,UAAU,wBAA0B,SAAU,EAAe,CACpE,GAAI,GAAO,KACP,EAAS,EAAE,+BAEf,AAAI,EAAO,OAAS,GAClB,KAAK,cAAc,yCAA0C,UAAY,CACvE,EAAO,KAAK,UAAY,CACtB,GAAI,GAAQ,EAAE,MACV,EAAW,EAAM,KAAK,OACtB,EAAS,GAAI,OAAM,OAAO,MAC1B,EAAmB,KACvB,EAAO,QAAQ,KAAK,UAAY,CAC9B,GAAI,GAAc,EAAK,wBAAwB,EAAU,GAEzD,AAAI,EAAc,GAChB,EAAO,YAAY,KAAK,SAAU,EAAQ,CACxC,EAAO,eAAe,GAAa,KAAK,UAAY,CAClD,EAAO,QAAQ,KAAK,UAAY,CAC9B,EAAO,UAAU,WAO3B,WAAwB,EAAM,EAAU,CAKtC,AAJI,IAAa,QACf,GAAW,IAGT,KAAY,GAAoB,MAAQ,EAAK,QAAU,EAAmB,IAI9E,GAAK,qBAAqB,EAAU,EAAK,QAAS,EAAK,UACvD,EAAmB,EAAK,SAG1B,EAAO,GAAG,OAAQ,GAClB,EAAO,GAAG,QAAS,GACnB,EAAO,GAAG,QAAS,GACnB,EAAO,GAAG,aAAc,SAAU,EAAM,CACtC,EAAe,EAAM,WAO/B,EAAS,UAAU,qBAAuB,SAAU,EAAU,EAAM,EAAW,CAC7E,KAAK,eAAe,iBAAkB,CACpC,UAAW,EACX,KAAM,EACN,WAAY,KAIhB,EAAS,UAAU,qBAAuB,UAAY,CACpD,KAAK,6BACL,KAAK,+BACL,KAAK,gCACL,KAAK,WAAW,0BAGlB,EAAS,UAAU,kBAAoB,SAAU,EAAO,CACtD,MAAO,GAAE,kCAAoC,EAAQ,OAGvD,EAAS,UAAU,iBAAmB,SAAU,EAAW,CACzD,MAAO,GAAE,sBAAsB,KAAK,UAAY,CAC9C,GAAI,GAAW,EAAE,MACjB,EAAU,MAId,EAAS,UAAU,qBAAuB,SAAU,EAAO,CACzD,GAAI,GAAW,0CAA4C,EAAQ,KAC/D,EAAO,EAAE,GAAU,SAAS,OAAO,SAAS,QAEhD,MAAI,GAAK,OAAS,EACT,EAAK,OAEL,MAIX,EAAS,UAAU,sBAAwB,SAAU,EAAO,CAC1D,MAAO,MAAK,qBAAqB,EAAQ,cAG3C,EAAS,UAAU,iBAAmB,SAAU,EAAO,CACrD,GAAI,GAAK,WAAa,EAAQ,QAC1B,EAAU,EAAE,OAAS,GAEzB,MAAI,GAAQ,OAAS,GAAK,CAAC,EAAQ,SAAS,WACnC,EAEA,MAIX,EAAS,UAAU,mBAAqB,SAAU,EAAO,CACvD,GAAI,GAAO,KAAK,qBAAqB,EAAQ,SAE7C,GAAI,IAAS,KACX,MAAO,CAAC,GAMV,OAHI,GAAQ,GACR,EAAQ,IAEC,CACX,GAAI,GAAY,EAAQ,SAAW,IAGnC,GAFA,EAAO,KAAK,qBAAqB,GAE7B,IAAS,KACX,EAAM,KAAK,OAEX,OAIJ,MAAI,GAAM,OAAS,EACV,EAEA,MAIX,EAAS,UAAU,mBAAqB,SAAU,EAAI,CACpD,MAAO,GAAE,GAAI,QAAQ,uBAGvB,EAAS,UAAU,sBAAwB,SAAU,EAAO,EAAQ,EAAM,CACxE,GAAI,GAAW,KAAK,kBAAkB,GAClC,EAAc,EAAS,SAAS,mCAChC,EAAa,EAAS,KAAK,qBAE/B,AAAI,IAAW,OACb,GAAS,EAAS,KAAK,qBAAqB,QAG9C,GAAI,GAAU,2BAEd,GAAI,GAIF,GAHA,EAAY,SAAS,iBACrB,EAAW,SAAS,YAEhB,IAAW,KAAM,CACnB,GAAI,GAAU,EAAO,SAAS,KAC9B,EAAQ,YAAY,EAAO,KAAK,cAChC,EAAQ,SAAS,QAGnB,GAAY,YAAY,iBACxB,EAAW,YAAY,YACvB,EAAW,KAAK,UAAY,CAC1B,GAAI,GAAS,EAAE,MACX,EAAU,EAAO,SAAS,KAC9B,EAAQ,SAAS,EAAO,KAAK,cAC7B,EAAQ,YAAY,MAK1B,EAAS,UAAU,UAAY,EAE/B,EAAS,UAAU,iBAAmB,SAAU,EAAQ,EAAM,EAAS,CACrE,GAAI,GAAc,CAChB,GAAI,cAEF,EAAe,CACjB,OAAQ,KAEV,EAAU,OAAO,OAAO,GAAI,EAAc,GAC1C,EAAQ,OAAS,EAAY,EAAQ,SAAW,EAAQ,OACxD,GAAI,GAAS,IAAI,KAAK,GACtB,SAAO,uBAAuB,IAC9B,EAAO,mBAAmB,IAC1B,EAAO,mBAAmB,IAC1B,EAAO,qBAAqB,IAC5B,EAAO,SAAS,uBAAuB,IACvC,EAAO,SAAS,sBAChB,EAAO,gBAAkB,IACzB,EAAO,QAAQ,QAAQ,YAAY,OAAO,EAAQ,SAClD,EAAO,QAAQ,eAAe,iBAC9B,EAAO,QAAQ,eAAe,QAC9B,EAAO,QAAQ,WAAW,GAC1B,EAAO,SAAS,EAAM,IACtB,EAAO,WAAW,CAChB,0BAA2B,KAEtB,GAGT,EAAS,UAAU,gBAAkB,SAAU,EAAO,CACpD,MAAO,MAAK,kBAAkB,GAAO,KAAK,mCAG5C,EAAS,UAAU,2BAA6B,UAAY,CAC1D,GAAI,GAAO,KACX,KAAK,iBAAiB,SAAU,EAAU,CACxC,GAAI,GAAa,EAAS,SAAS,4BAA4B,SAC3D,EAAY,EAAW,SAAW,EAAI,KAAK,MAAM,EAAW,QAAU,GACtE,EAAQ,EAAS,KAAK,cACtB,EAAU,EAAU,QAExB,WAAkB,EAAQ,CACxB,MAAO,qBAAuB,EAAQ,IAAM,EAG9C,EAAS,GAAG,UAAW,UAAY,CACjC,EAAE,0BAA0B,KAAK,UAAY,CAC3C,AAAI,EAAS,IAAI,EAAE,OAAO,SAAW,GACnC,EAAK,gBAAgB,EAAK,mBAAmB,EAAE,YAIrD,GAAI,GAAO,GACP,EAAa,EAAS,SAAS,2BACnC,EAAW,KAAK,UAAY,CAC1B,GAAI,GAAc,EAAE,MAAM,SAAS,QAEnC,AAAI,EAAY,OAAS,EACvB,EAAO,EAAO,EAAY,OAE1B,EAAO,EAAO,EAAE,MAAM,SAG1B,EAAW,SAGX,OAFI,GAAQ,EAAK,MAAM,cAAc,OAE5B,EAAI,EAAO,EAAI,EAAK,UAAW,IACtC,EAAO,EAAO,KAGhB,EAAS,UAAU,sDACnB,GAAI,GAAc,EAAS,SAAS,mCAChC,EAAW,EAAE,mEACjB,EAAS,KAAK,KAAM,EAAS,UAC7B,GAAI,GAAe,EAAE,4DACrB,EAAS,OAAO,GAChB,GAAI,GAAmB,EAAE,mDACrB,EAAoB,EAAE,oDAC1B,EAAa,OAAO,GACpB,EAAa,OAAO,GACpB,EAAiB,KAAK,GACtB,GAAI,GAAY,EAAE,kCAClB,EAAS,OAAO,GAEhB,WAAyB,EAAM,EAAO,EAAM,GAAO,EAAU,CAC3D,GAAI,GAAS,EAAE,sBAAwB,EAAQ,uCAC/C,EAAO,OAAO,EAAE,gBAAkB,EAAO,WACzC,EAAO,OAAO,4BAAmC,EAAW,KAAO,EAAO,WAC1E,GAAI,IAAQ,UAAU,SAAS,cAAc,QAAQ,QAAU,EAC3D,GAAQ,EACR,GAAW,IAAQ,MAAQ,QAAU,eAEzC,MAAK,KACH,IAAQ,GAAQ,KAAO,GAAU,IACjC,EAAO,KAAK,iBAAkB,YAAc,GAAU,OAGxD,EAAO,KAAK,QAAS,IACrB,EAAO,KAAK,YAAa,IACzB,EAAO,KAAK,uBAAwB,UAAY,EAAW,SAEvD,IACF,EAAO,KAAK,aAAc,KAG5B,EAAO,KAAK,YAAa,GACzB,EAAO,GAAG,QAAS,UAAY,CAC7B,EAAK,gBAAgB,GACrB,EAAK,sBAAsB,EAAO,EAAQ,MAE5C,EAAkB,OAAO,GAClB,EAGT,GAAI,GAAY,EAAgB,UAAW,cAAe,WAAY,GAAO,WAE7E,AAAI,EAAU,aACZ,EAAgB,oBAAqB,cAAe,gBAAiB,GAAM,gBAG7E,GAAI,GAAU,EAAE,qDACZ,EAAY,EAAS,eACzB,EAAQ,KAAK,KAAM,GACnB,EAAU,OAAO,GACjB,EAAU,OAAO,GACjB,EAAS,QAAQ,GACjB,GAAI,GAAY,EAAE,gDAClB,EAAU,KAAK,KAAM,EAAS,WAC9B,EAAY,OAAO,GACnB,GAAI,GAAS,EAAK,iBAAiB,EAAW,EAAM,GAChD,EAAY,KACZ,EAAa,EAAS,KAAK,qBAAuB,IAClD,EAAc,EAAS,KAAK,sBAAwB,IACpD,GAAgB,EAAS,KAAK,oBAAsB,IAAM,EAAO,KACjE,EAAS,EAAU,OAEvB,AAAI,EAAO,gBAAkB,KAC3B,GAAc,MAGhB,EAAO,SAAW,CAChB,MAAO,EACP,OAAQ,EACR,WAAY,EACZ,WAAY,EACZ,YAAa,EACb,eAAgB,IAGlB,WAA0B,EAAM,EAAK,CACnC,GAAI,GAAS,EAAI,QAAQ,QAAS,YAClC,EAAO,SAAS,WAAW,CACzB,KAAM,EACN,QAAS,CACP,IAAK,EACL,IAAK,GAEP,KAAM,SAAc,EAAQ,CAC1B,EAAU,QAAQ,YAKxB,EAAiB,WAAY,cAC7B,EAAiB,WAAY,oBAE7B,WAAuB,EAAM,EAAM,EAAM,CACvC,AAAI,MAAO,IAAS,UAClB,GAAO,CACL,IAAK,EACL,IAAK,EAAK,QAAQ,QAAS,cAI3B,MAAO,IAAS,UAClB,GAAO,CACL,EAAG,EACH,SAAU,IAId,EAAO,SAAS,WAAW,CACzB,KAAM,EACN,QAAS,EACT,KAAM,SAAc,EAAQ,CAC1B,AAAI,EAAK,EAAO,SAAS,QACvB,EAAO,OAAO,EAAK,EAAO,SAAS,SAC1B,EAAK,UACd,EAAO,OAAO,EAAK,aAM3B,GAAI,GAAW,EAAS,KAAK,cAAgB,MAC7C,EAAc,aAAc,eAAgB,CAC1C,EAAG,IAAM,IAEX,EAAc,cAAe,QAAS,CACpC,EAAG,OACH,SAAU,QAEZ,EAAU,GAAG,QAAS,UAAY,CAChC,EAAO,UAGT,WAA2B,EAAQ,CACjC,GAAI,GAAiB,CACnB,OAAQ,CACN,IAAK,MACL,IAAK,OAEP,QAAS,CACP,IAAK,YACL,IAAK,cAGT,CAAC,SAAU,WAAW,QAAQ,SAAU,EAAM,CAC5C,GAAI,IAAU,EAAO,SAAS,OAAO,GACrC,GAAQ,QAAU,EAAS,EAAe,GAAQ,KAClD,EAAO,SAAS,WAAW,MAE7B,EAAE,EAAO,WAAW,YAAY,iBAAkB,CAAC,GAGrD,EAAO,GAAG,QAAS,UAAY,CAC7B,EAAkB,MAEpB,EAAO,SAAS,WAAW,CACzB,KAAM,SACN,QAAS,CACP,IAAK,MACL,IAAK,OAEP,KAAM,UAAgB,CACpB,EAAkB,OAItB,GAAI,GAAkB,UAA2B,CAC/C,GAAI,GAAQ,EAAS,KAAK,cAE1B,AAAI,GAAS,EAAQ,EACnB,EAAO,WAAW,CAChB,SAAU,EACV,SAAU,IAGZ,EAAO,WAAW,CAChB,SAAU,EAAK,UACf,SAAU,KAAK,IAAI,KAAK,IAAI,EAAO,QAAQ,YAAa,IAAK,EAAK,cAKxE,IACA,EAAO,aAAa,GAAG,SAAU,GACjC,EAAK,aAAa,EAAU,EAAkB,GAC9C,EAAS,QAAQ,YAAY,GAAG,QAAS,UAAY,CACnD,EAAO,OAAO,SAKpB,EAAS,UAAU,6BAA+B,UAAY,CAC5D,GAAI,GAAO,KACX,EAAE,UAAU,GAAG,UAAW,SAAU,EAAI,CACtC,GAAI,GAAW,EAAK,mBAAmB,EAAG,QAE1C,AAAI,EAAS,SAAW,GACtB,EAAK,iBAAiB,EAAK,oBAKjC,EAAS,UAAU,aAAe,SAAU,EAAU,EAAc,EAAQ,CAC1E,GAAI,GAAO,KACP,EAAQ,EAAS,KAAK,cACtB,EAAW,EAAK,sBAAsB,GACtC,EAAQ,EAAK,mBAAmB,GAEpC,AAAI,IAAU,MAAQ,IAAa,MACjC,GAAM,KAAK,GACX,EAAW,MAGb,GAAI,GAAU,EAAK,iBAAiB,GAEpC,WAAyB,EAAM,EAAS,EAAU,EAAU,CAC1D,GAAI,GAAS,EAAE,wEAMf,GALA,EAAO,KAAK,QAAS,GACrB,EAAO,KAAK,YAAa,IACzB,EAAO,SAAS,GAChB,EAAO,OAAO,EAAE,gBAAkB,EAAO,WAErC,EAAU,CACZ,AAAI,MAAO,IAAa,UACtB,GAAW,CACT,IAAK,IAIT,EAAO,KAAK,uBAAwB,EAAS,IAAM,SACnD,GAAI,GAAa,EAAE,sEAAwE,OAAO,EAAS,YAC3G,EAAW,KAAK,YAAa,EAAS,KAElC,EAAS,MACX,EAAW,KAAK,iBAAkB,KAAK,UAAU,EAAS,OAG5D,EAAO,OAAO,SAAS,eAAe,MACtC,EAAO,OAAO,GAEV,EAAS,MACX,EAAO,KAAK,iBAAkB,KAAK,UAAU,EAAS,WAGxD,GAAO,OAAO,IAAM,GAGtB,SAAa,OAAO,GACb,EAGT,WAAuB,EAAS,EAAU,CACxC,SAAW,GAAY,cAChB,EAAgB,iBAAkB,EAAS,oBAAqB,GAGzE,WAA2B,EAAO,CAChC,EAAK,aAAa,EAAO,gBAAiB,CACxC,KAAM,IAAa,KAAO,WAAa,OACvC,MAAO,IAIX,GAAI,EAAO,SAAS,iBAAmB,KAAM,CAC3C,GAAI,GAAkB,EAAgB,aAAc,aAAc,0BAA2B,oBAC7F,EAAgB,GAAG,QAAS,UAAY,CACtC,EAAO,SAAS,EAAO,SAAS,eAAgB,IAChD,EAAK,qBAAqB,KAI9B,GAAI,GAAW,KAAM,CACnB,EAAQ,SAAS,iBACjB,EAAQ,IAAI,UAAW,QACvB,GAAI,GAAS,EAAc,OAAQ,CACjC,IAAK,cACL,MAAO,IAET,EAAO,GAAG,QAAS,UAAY,CAC7B,EAAkB,GAClB,GAAI,GAAc,EAAS,SAAS,mCAEpC,GAAI,EAAY,KAAK,kBAAkB,SAAW,EAAG,CACnD,GAAI,GAAQ,EAAE,eAAgB,OAAO,EAAK,MAAQ,sBAAwB,OAAQ,iCAC9E,EAAY,EAAE,eAAgB,OAAO,EAAK,MAAQ,aAAe,YAAa,aAC9E,EAAe,EAAQ,QAAQ,KAAK,KAAM,IAAI,IAAI,UAAW,WACjE,EAAU,OAAO,GACjB,EAAM,OAAO,GACb,EAAY,QAAQ,OAEpB,GAAY,KAAK,wBAAwB,mBAGpC,GAAY,EAAO,CAC5B,GAAI,GAAa,IAAa,KAC1B,EAAc,EAAK,UAEvB,GAAI,EACF,EAAc,KAAK,IAAI,EAAK,YAAY,GAAW,OAEnD,QAAS,GAAI,EAAG,EAAI,EAAM,OAAQ,IAChC,EAAc,KAAK,IAAI,EAAK,YAAY,EAAM,IAAK,GAIvD,GAAI,GAAY,EAEZ,EAAU,EAAc,EAAa,WAAa,EAAM,OAAS,EAAI,QAAU,OAAQ,EAAa,CACtG,IAAK,kBACL,MAAO,GACL,CACF,IAAK,cACL,KAAM,CACJ,MAAO,EAAM,UAIjB,EAAQ,GAAG,QAAS,SAAU,EAAI,CAChC,EAAkB,GAClB,GAAI,GAAe,IAAa,KAAO,EAAW,EAAM,GACpD,EAAU,EAAQ,SAAS,KAAK,uBAAuB,OAAS,EAEpE,GAAI,EAAS,CACX,QAAQ,IAAI,wBAAyB,GACrC,EAAK,gBAAgB,GACrB,EAAO,QACP,OAGF,QAAQ,IAAI,yBAA0B,GAEtC,GAAI,GAAU,EAAQ,QAAQ,CAC5B,UAAW,MACX,SAAU,2LACV,QAAS,EACT,UAAW,EAAQ,SACnB,SAAU,EAAE,WAAW,IAAI,GAC3B,SAAU,EAAE,WAAW,IAAI,KAGzB,EAAoB,GACxB,EAAQ,GAAG,sBAAuB,SAAU,EAAI,CAC9C,GAAI,GAAQ,KAEZ,GAAI,GACJ,SAAQ,IAAI,6BAA8B,GAC1C,GAAI,GAAa,EAAK,MAAQ,EAAQ,KAAK,cAAc,MAAQ,EAAE,OAAO,UAAU,QAAQ,YAAY,GAAS,KAC7G,GAAU,EAAW,KAAK,oBAC1B,EAAiB,EAAK,iBAAiB,GAAQ,IAAI,GAAI,GAC3D,EAAe,YAAY,IAC3B,EAAe,UAAU,WAAY,KAAK,IAAI,EAAa,KAC3D,EAAe,UAAU,WAAY,IACrC,WAAW,UAAY,CACrB,GAAe,KAAM,GAErB,GAAQ,SAAS,IAAI,MAAO,IAAI,OAAO,GAAQ,SAAS,SAAU,QAClE,KAAK,OACP,GAAI,GAAe,EAAW,KAAK,kBAEnC,GAAI,IAAa,MAAQ,EAAM,OAAS,EAAG,CACzC,GAAI,GAAiB,EAAE,gCAAiC,OAAO,EAAK,MAAQ,SAAW,SAAU,uCACjG,EAAe,OAAO,EAAE,uDACxB,EAAe,OAAO,KACtB,EAAe,OAAO,EAAE,6CACxB,EAAe,GAAG,QAAS,UAAY,CACrC,EAAY,EAAY,EACxB,EAAe,SAAS,EAAM,GAAY,IAEtC,IAAc,EAAM,OAAS,GAC/B,GAAe,SAAS,YACxB,EAAe,KAAK,WAAY,KAGlC,EAAkB,KAGhB,IAAc,EAAM,OAAS,GAC/B,GAAe,SAAS,YACxB,EAAe,KAAK,WAAY,KAGlC,EAAa,OAAO,GAGtB,GAAI,GAAa,EAAE,+BAAgC,OAAO,EAAK,MAAQ,SAAW,SAAU,sDAC5F,EAAW,OAAO,EAAE,+BACpB,EAAW,OAAO,KAClB,EAAW,OAAO,EAAE,oEACpB,EAAa,OAAO,GACpB,GAAI,GAAY,GAAI,aAAY,EAAW,GAAI,CAC7C,KAAM,SAAc,EAAS,CAC3B,MAAO,GAAe,cAG1B,EAAU,GAAG,UAAW,SAAU,EAAG,CACnC,EAAK,gBAAgB,GACrB,EAAO,UAET,EAAW,KAAK,YAAa,GAC7B,EAAW,IAAI,OAAQ,KACvB,GAAI,GAAe,EAAW,KAAK,UACnC,EAAa,IAAI,OAAQ,EAAQ,WAAW,KAAO,EAAQ,aAAe,EAAI,MAC9E,EAAW,QAAQ,QACnB,EAAoB,MAGtB,EAAQ,GAAG,mBAAoB,UAAY,CACzC,GAAI,GAAiB,EAAE,8BACvB,EAAK,eAAe,GAEf,EAAK,OACR,OAAO,UAAU,QAAQ,YAAY,GAAS,WAIlD,EAAQ,QAAQ,QAEhB,EAAO,YAKb,EAAS,UAAU,gBAAkB,SAAU,EAAU,CACvD,GAAI,GAAiB,EAAS,KAAK,+BAMnC,GAJI,EAAe,OAAS,GAC1B,EAAe,KAAK,aAAa,UAG/B,OAAO,UAAW,CACpB,GAAI,GAAU,EAAS,KAAK,8BAC5B,GAAI,CAAC,EAAQ,OAAQ,OACrB,OAAO,UAAU,QAAQ,YAAY,EAAQ,IAAI,IAAI,cAErD,GAAS,KAAK,8BAA8B,QAAQ,YAIxD,EAAS,UAAU,8BAAgC,UAAY,CAC7D,GAAI,GAAO,KAEX,WAAuB,EAAI,CACzB,MAAO,GAAK,mBAAmB,GAAI,KAAK,cAG1C,WAA+B,EAAI,CACjC,GAAI,GAAa,EAAK,mBAAmB,GAAI,GAC7C,EAAK,eAAe,GAGtB,GAAI,GAAuB,GAAI,OAAM,aACrC,EAAE,OAAO,EAAsB,CAC7B,KAAM,SAAc,EAAO,CACzB,MAAO,GAAE,GAAO,KAAK,mCAEvB,SAAU,SAAkB,EAAI,CAC9B,GAAI,CAAC,KAAK,SAAW,CAAC,KAAK,QACzB,MAAO,MAGT,GAAI,GAAQ,GACZ,EAAM,MAAQ,EAAc,GAC5B,EAAM,aAAe,KAAK,aAC1B,GAAI,GAAS,IAAI,KAAK,EAAE,GAAI,KAAK,OACjC,SAAM,KAAO,EAAM,aAAe,EAAO,aAAa,WAAa,EAAO,mBAAqB,EAAO,aAAa,WACnH,EAAM,QAAU,KAAK,QACrB,EAAM,UAAY,GAAI,QAAO,UACtB,GAET,SAAU,SAAkB,EAAI,EAAO,CACrC,GAAI,GAAS,IAAI,KAAK,EAAE,GAAI,KAAK,OACjC,EAAO,aAAa,SAAS,EAAM,MACnC,KAAK,WAAW,GAAI,QAAQ,SAExB,OAAO,WACT,WAAW,UAAY,CACrB,EAAO,QACN,IAGP,QAAS,SAAiB,EAAI,CAC5B,MAAO,mBAET,UAAW,SAAmB,EAAI,EAAU,CAC1C,GAAI,GAAU,KACd,KAAK,WAAW,GAAI,GAAG,6BAA8B,SAAU,EAAI,CACjE,EAAQ,QAAU,GAClB,EAAQ,QAAU,GAClB,EAAQ,aAAe,EAAG,eAAe,aAAa,cACtD,EAAS,MAEX,EAAE,GAAI,GAAG,+BAAgC,SAAU,EAAI,EAAS,CAC9D,EAAQ,QAAU,GAClB,EAAQ,QAAU,GAClB,EAAQ,aAAe,EAAQ,aAC/B,EAAS,OAGb,YAAa,SAAqB,EAAI,CACpC,KAAK,WAAW,GAAI,IAAI,0BAE1B,WAAY,SAAoB,EAAI,CAClC,GAAI,GAAW,EAAK,mBAAmB,GACvC,MAAO,GAAS,KAAK,sBAEvB,QAAS,GACT,QAAS,GACT,MAAO,KAET,MAAM,cAAc,SAAS,EAAsB,0BACnD,GAAI,GAAwB,GAAI,OAAM,cACtC,EAAE,OAAO,EAAuB,CAC9B,KAAM,SAAc,EAAO,CACzB,MAAO,GAAE,GAAO,KAAK,8BAEvB,aAAc,SAAsB,EAAI,EAAK,CAC3C,MAAM,UAAU,GAChB,KAAK,YAAY,EAAI,IAEvB,YAAa,SAAqB,EAAI,EAAM,CAC1C,EAAK,sBAAsB,EAAc,GAAK,KAAM,IACpD,KAAK,YAAY,GAAI,WAAW,IAAI,EAAE,IAAK,SAC3C,MAAM,cAAc,EAAI,GAEpB,OAAO,4BACT,OAAO,6BAGL,OAAO,eACT,OAAO,cAAc,UAGvB,GAAI,GAAY,EAAK,mBAAmB,GAAI,KAAK,aAEjD,AAAK,EAIH,EAAK,WAAW,qBAAuB,EAAc,IAHrD,GAAsB,GACtB,EAAK,mBAAmB,GAAI,KAAK,YAAa,MAKlD,aAAc,SAAsB,EAAI,EAAM,CAC5C,AAAI,GACF,EAAK,sBAAsB,EAAc,GAAK,KAAM,IAGxD,YAAa,SAAqB,EAAI,CACpC,MAAO,GAAE,GAAI,QAAQ,sCAGzB,MAAM,eAAe,SAAS,EAAuB,4BAGvD,EAAS,UAAU,qBAAuB,SAAU,EAAU,CAC5D,GAAI,GAAc,EAAE,GAAU,KAAK,mCAC/B,EAAY,EAAE,GAAa,SAAS,6BACxC,EAAY,WAAW,IAAI,GAAW,SACtC,EAAU,SAGZ,EAAS,UAAU,mBAAqB,SAAU,EAAa,EAAS,CACtE,GAAI,GAAO,KAEX,GAAI,CAAE,OAAO,QAAO,SAAY,aAAe,MAAO,QAAO,WAAc,aAAc,CACvF,EAAQ,IACR,OAGF,GAAI,GAAS,yBACT,EAAY,SAAW,OAAO,KAAK,EAAY,YAAc,EAAY,kBAEzE,EAAa,SAAoB,EAAO,CAC1C,EAAM,KAAK,KAAK,SAAU,EAAI,CAC5B,EAAG,WAIH,EAEJ,GAAI,CACF,GAAI,GAAY,GAAI,QAAO,UAAU,MAAM,EAAQ,GACnD,EAAW,GACX,EAAe,SACR,EAAP,CACA,EAAe,GAGjB,GAAI,IAAiB,GAAO,CAC1B,EAAQ,IACR,OAGF,MAAM,wBAAwB,wBAAyB,SAAU,EAAS,CACxE,GAAI,GAAc,GAAI,QAAO,UAAU,MAAM,EAAQ,GACrD,OAAO,UAAU,IAAI,EAAQ,GAAI,EAAQ,KAAM,GAAa,MAAS,SAAU,EAAK,CAClF,QAAQ,MAAM,KACb,QAAW,UAAY,CACxB,EAAW,OAIf,EAAK,aAAe,SAAU,EAAW,CACvC,GAAI,GAAgB,GAAI,QAAO,UAAU,MAAM,EAAQ,GACvD,OAAO,UAAU,MAAM,GAAe,KAAK,GAAW,MAAS,SAAU,EAAK,CAC5E,QAAQ,MAAM,GACd,MACC,QAAW,UAAY,CACxB,EAAW,MAIf,GAAI,GAAc,GAAI,QAAO,UAAU,MAAM,EAAQ,GACrD,OAAO,UAAU,KAAK,GAAa,KAAK,SAAU,EAAM,CACtD,GAAI,GAAc,EAAK,IAAI,SAAU,EAAK,CACxC,MAAO,QAAO,UAAU,IAAI,EAAK,KAEnC,MAAO,SAAQ,IAAI,GAAa,KAAK,SAAU,EAAM,CACnD,GAAI,GAAM,GACN,EAEJ,IAAK,EAAI,EAAG,EAAI,EAAK,OAAQ,IAC3B,EAAI,EAAK,IAAM,EAAK,GAGtB,MAAO,OAER,KAAK,SAAU,EAAM,CACtB,EAAQ,KACP,MAAS,SAAU,EAAK,CACzB,QAAQ,MAAM,GACd,EAAQ,MACP,QAAW,UAAY,CACxB,EAAW,MAIf,EAAS,UAAU,cAAgB,SAAU,EAAS,CACpD,GAAI,GAAO,KACX,EAAK,WAAW,mBAChB,KAAK,eAAe,gBAAiB,EAAS,SAAU,EAAM,CAC5D,EAAK,WAAW,kBAChB,EAAK,uBAAuB,EAAK,cACjC,EAAK,YACL,EAAK,oBAAoB,EAAK,iBAC9B,EAAK,oBAAoB,EAAK,aAC9B,EAAK,wBAAwB,EAAK,mBAItC,EAAS,UAAU,oBAAsB,SAAU,EAAa,CAG9D,OAFI,GAAO,KAEF,EAAI,EAAG,EAAI,EAAY,OAAQ,IAAK,CAC3C,GAAI,GAAa,EAAY,GACzB,EAAO,EAAW,KAClB,EAAK,EAAW,GAEpB,GAAI,IAAS,sBAAuB,CAClC,GAAI,GAAQ,EACR,EAAO,EAAW,KAAK,KACvB,EAAU,EAAW,KAAK,QAC9B,EAAK,WAAW,sBAAwB,GACxC,GAAI,GAAkB,EAAK,gBAAgB,GAE3C,AAAI,EAAgB,OAAS,GAC1B,UAAY,CACX,GAAI,GAAS,IAAI,KAAK,EAAgB,KAAK,OAC3C,EAAO,SAAS,EAAM,IAElB,OAAO,WACT,WAAW,UAAY,CACrB,EAAO,QACN,GAGL,EAAK,kBAAkB,GAAO,KAAK,YAAa,IAChD,EAAK,sBAAsB,EAAO,MAAO,IACzC,EAAgB,QAAQ,UAAW,CACjC,aAAc,UAQ1B,EAAS,UAAU,aAAe,SAAU,EAAW,CACrD,KAGF,EAAS,UAAU,uBAAyB,SAAU,EAAa,CACjE,GAAI,GAAO,KACP,EAAkB,CACpB,gBAAiB,EACjB,KAAM,IAEJ,EAA0B,KAAK,UAAU,UAAY,CACvD,GAAI,GAAqB,CACvB,gBAAiB,EAAE,QAAQ,YAC3B,KAAM,OAAO,SAAS,MAGxB,AAAI,GAAmB,kBAAoB,EAAgB,iBAAmB,EAAmB,OAAS,EAAgB,OACxH,GAAK,eAAe,mBAAoB,EAAoB,MAC5D,EAAkB,IAEnB,KACH,EAAE,QAAQ,OAAO,GACjB,OAAO,iBAAiB,WAAY,GAEhC,CAAC,OAAO,SAAS,MAAQ,EAAY,MACvC,QAAO,SAAS,KAAO,EAAY,OAIvC,MAAM,wBAAwB,6BAA8B,SAAU,EAAS,CAC7E,GAA+B,KAGjC,EAAS,UAAU,kBAAoB,UAAY,CACjD,GAAI,GAAO,KACX,EAAK,WAAW,yBAEhB,YAA4B,CAC1B,WAAe,EAAO,CACpB,WAAW,UAAY,CACrB,KACC,GAGL,AAAI,GACF,GAAK,WAAW,oBAChB,EAAK,eAAe,aAAc,CAChC,SAAU,OAAO,UAChB,SAAU,EAAU,CACrB,EAAK,WAAW,sBAChB,EAAK,mBAAmB,EAAS,YAAa,SAAU,EAAS,CAC/D,EAAK,WAAW,uBAChB,EAAK,cAAc,QAIvB,EAAM,KAIV,KAGF,OAAO,SAAW",
"names": []
}
diff --git a/learnr-js/tutorial/tutorial.js b/learnr-js/tutorial/tutorial.js
index 3ac19744b..59ebc6310 100644
--- a/learnr-js/tutorial/tutorial.js
+++ b/learnr-js/tutorial/tutorial.js
@@ -1087,7 +1087,9 @@ Tutorial.prototype.$initializeExerciseEditors = function () {
}
})
}
- bindInsertKey('insertPipe', 'Ctrl+Shift+M', { r: ' %>% ' })
+
+ const pipeCode = exercise.attr('data-pipe') || '%>%'
+ bindInsertKey('insertPipe', 'Ctrl+Shift+M', { r: ' ' + pipeCode })
bindInsertKey('insertArrow', 'Alt+-', { r: ' <- ', fallback: ' = ' })
// re-focus the editor on run button click
diff --git a/man/tutorial_options.Rd b/man/tutorial_options.Rd
index ca855136f..5d56f54f7 100644
--- a/man/tutorial_options.Rd
+++ b/man/tutorial_options.Rd
@@ -9,6 +9,7 @@ tutorial_options(
exercise.eval = FALSE,
exercise.timelimit = 30,
exercise.lines = NULL,
+ exercise.pipe = NULL,
exercise.blanks = NULL,
exercise.checker = NULL,
exercise.error.check.code = NULL,
@@ -30,6 +31,13 @@ see some default output (defaults to \code{FALSE}).}
\item{exercise.lines}{Lines of code for exercise editor (defaults to the
number of lines in the code chunk).}
+\item{exercise.pipe}{The characters to enter when the user presses the
+"Insert Pipe" keyboard shortcut in the exercise editor
+(\code{Ctrl/Cmd + Shift + M}). This can be set at the tutorial level or for an
+individual exercise. If \code{NULL} (default), the base R pipe (\verb{|>}) is used
+when the tutorial is rendered in R >= 4.1.0, otherwise the \pkg{magrittr}
+pipe (\verb{\%>\%}) is used.}
+
\item{exercise.blanks}{A regular expression to be used to identify blanks in
submitted code that the user should fill in. If \code{TRUE} (default), blanks
are three or more underscores in a row. If \code{FALSE}, blank checking is not
diff --git a/tests/manual/pipe-option/pipe-option.Rmd b/tests/manual/pipe-option/pipe-option.Rmd
new file mode 100644
index 000000000..d851ad577
--- /dev/null
+++ b/tests/manual/pipe-option/pipe-option.Rmd
@@ -0,0 +1,56 @@
+---
+title: "Exercise Pipe Option"
+output: learnr::tutorial
+runtime: shiny_prerendered
+---
+
+```{r setup, include=FALSE}
+library(learnr)
+library(dplyr)
+knitr::opts_chunk$set(echo = FALSE)
+```
+
+
+## Ceci n'est pas une pipe
+
+Qu'est-ce qu'une pipe, sinon l'idée d'une pipe?
+
+You can set the characters used for the pipe shortcut at the tutorial level with
+
+```r
+knitr::opts_chunk$set(exercise.pipe = "%>%")
+```
+
+Or you can set the pipe option at the individual level using the `exercise.pipe` chunk option.
+
+````{verbatim echo = TRUE}
+```{r base-pipe, exercise=TRUE, exercise.pipe="|>"}
+mtcars count(cyl)
+```
+````
+
+By default, if not set otherwise set, learnr will use the base R pipe (`|>`) when the tutorial is rendered in R >= 4.1.0.
+
+### Old school
+
+In this next chunk, pressing `Ctrl/Cmd + Shift + M` enters the magrittr pipe: `%>%`.
+
+```{r magrittr, exercise=TRUE, exercise.pipe="%>%"}
+mtcars count(cyl)
+```
+
+### New school
+
+In this next chunk, pressing `Ctrl/Cmd + Shift + M` enters the base R pipe: `|>`.
+
+```{r pipe, exercise=TRUE, exercise.pipe="|>"}
+mtcars count(cyl)
+```
+
+### Night school
+
+In this next chunk, pressing `Ctrl/Cmd + Shift + M` enters the pipe that matches your R version. It's the base R pipe for R >= 4.1.
+
+```{r auto, exercise=TRUE}
+mtcars count(cyl)
+```
diff --git a/vignettes/articles/exercises.Rmd b/vignettes/articles/exercises.Rmd
index eba38d27a..860247d4a 100644
--- a/vignettes/articles/exercises.Rmd
+++ b/vignettes/articles/exercises.Rmd
@@ -22,6 +22,8 @@ There are many options associated with tutorial exercises (all of which are desc
+-----------------------------+-------------------------------------------------------------------------------------------------------------------------------------+
| `exercise.lines` | Lines of code for exercise editor (default to size of code chunk). |
+-----------------------------+-------------------------------------------------------------------------------------------------------------------------------------+
+| `exercise.pipe` | The code to insert when the user presses `Ctrl/Cmd + Shift + M` (defaults to `|>` for R >= 4.1.0, otherwise `%>%`). |
++-----------------------------+-------------------------------------------------------------------------------------------------------------------------------------+
| `exercise.timelimit` | Number of seconds to limit execution time to (defaults to 30). |
+-----------------------------+-------------------------------------------------------------------------------------------------------------------------------------+
| `exercise.checker` | Function used to check exercise answers (e.g., `gradethis::grade_learnr()`). |