moodle_local_treestudyplan/amd/build/report-viewer-components.min.js.map
2023-08-15 16:06:30 +02:00

1 line
121 KiB
Plaintext

{"version":3,"file":"report-viewer-components.min.js","sources":["../src/report-viewer-components.js"],"sourcesContent":["/*eslint no-var: \"error\"*/\n/*eslint no-console: \"off\"*/\n/*eslint no-unused-vars: warn */\n/*eslint max-len: [\"error\", { \"code\": 160 }] */\n/*eslint-disable no-trailing-spaces */\n/*eslint-env es6*/\n// Put this file in path/to/plugin/amd/src\n\nimport {SimpleLine} from './simpleline';\nimport {get_strings} from 'core/str';\nimport {load_strings, format_date} from './string-helper';\nimport {call} from 'core/ajax';\nimport notification from 'core/notification';\nimport {svgarcpath} from './svgarc';\nimport Debugger from './debugger';\nimport Config from \"core/config\";\n\n// Make π available as a constant\nconst π = Math.PI;\n// Gravity value for arrow lines - determines how much a line is pulled in the direction of the start/end before changing direction\nconst LINE_GRAVITY = 1.3;\n\nexport default {\n install(Vue/*,options*/){\n let debug = new Debugger(\"treestudyplan-viewer\");\n debug.enable();\n let lastCaller = null;\n /**\n * Scroll current period into view\n * @param {*} handle A key to pass so subsequent calls with the same key won't trigger (always triggers when null or undefined)\n */\n function scrollCurrentIntoView(handle){\n const elScrollContainer = document.querySelector(\".r-studyplan-scrollable\");\n const elCurrentHeader = elScrollContainer.querySelector(\".s-studyline-header-period.current\");\n\n if(elCurrentHeader && ((!handle) || (handle != lastCaller))){\n lastCaller = handle;\n elCurrentHeader.scrollIntoView({\n behavior: \"smooth\",\n block: \"start\",\n inline: \"center\",\n });\n }\n }\n\n let strings = load_strings({\n invalid: {\n error: 'error',\n },\n grading: {\n ungraded: \"ungraded\",\n graded: \"graded\",\n allgraded: \"allgraded\",\n unsubmitted: \"unsubmitted\",\n nogrades: \"nogrades\",\n unknown: \"unknown\",\n },\n completion: {\n completed: \"completion_completed\",\n incomplete: \"completion_incomplete\",\n completed_pass: \"completion_passed\",\n completed_fail: \"completion_failed\",\n ungraded: \"ungraded\",\n aggregation_all: \"aggregation_all\",\n aggregation_any: \"aggregation_any\",\n aggregation_overall_all: \"aggregation_overall_all\",\n aggregation_overall_any: \"aggregation_overall_any\",\n completion_not_configured: \"completion_not_configured\",\n configure_completion: \"configure_completion\",\n view_completion_report: \"view_completion_report\",\n\n },\n badge: {\n share_badge: \"share_badge\",\n dateissued: \"dateissued\",\n dateexpire: \"dateexpire\",\n badgeinfo: \"badgeinfo\",\n badgeissuedstats: \"badgeissuedstats\",\n },\n course: {\n completion_incomplete: \"completion_incomplete\",\n completion_failed: \"completion_failed\",\n completion_pending: \"completion_pending\",\n completion_progress: \"completion_progress\",\n completion_completed: \"completion_completed\",\n completion_good: \"completion_good\",\n completion_excellent: \"completion_excellent\",\n view_feedback: \"view_feedback\",\n coursetiming_past: \"coursetiming_past\",\n coursetiming_present: \"coursetiming_present\",\n coursetiming_future: \"coursetiming_future\",\n required_goal: \"required_goal\",\n },\n teachercourse: {\n select_conditions: \"select_conditions\",\n select_grades: \"select_grades\",\n coursetiming_past: \"coursetiming_past\",\n coursetiming_present: \"coursetiming_present\",\n coursetiming_future: \"coursetiming_future\", \n grade_include: \"grade_include\", \n grade_require: \"grade_require\", \n required_goal: \"required_goal\",\n }\n\n });\n\n /************************************\n * *\n * Treestudyplan Viewer components *\n * *\n ************************************/\n\n /**\n * Check if element is visible\n * @param {Object} elem The element to check\n * @returns {boolean} True if visible\n */\n function isVisible(elem){\n return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length );\n }\n\n // Create new eventbus for interaction between item components\n const ItemEventBus = new Vue();\n\n Vue.component('r-progress-circle',{\n props: {\n value: {\n type: Number,\n },\n max: {\n type: Number,\n default: 100,\n },\n min: {\n type: Number,\n default: 0,\n },\n stroke: {\n type: Number,\n default: 0.2,\n },\n bgopacity: {\n type: Number,\n default: 0.2,\n },\n title: {\n type: String,\n default: \"\",\n },\n icon: {\n type: String,\n }\n\n },\n data() {\n return {\n selectedstudyplan: null,\n };\n },\n computed: {\n range() {\n return this.max - this.min;\n },\n fraction(){\n if(this.max - this.min == 0){\n return 0;\n // 0 size is always empty :)\n } else {\n return (this.value - this.min)/(this.max - this.min);\n }\n },\n radius() {\n return 50 - (50*this.stroke);\n },\n arcpath() {\n let fraction = 0; \n const r = 50 - (50*this.stroke);\n if(this.max - this.min != 0){\n fraction = (this.value - this.min)/(this.max - this.min);\n }\n\n const Δ = fraction * 2*π;\n return svgarcpath([50,50],[r,r],[0,Δ], 1.5*π);\n },\n },\n methods: {\n },\n template: `\n <div style=\"display: inline-block; width: 1em; height: 1em; position:relative; padding: 0;\">\n <svg width=\"1em\" height=\"1em\" viewBox=\"0 0 100 100\"\n style=\"position: absolute;top: 0;left: 0;\">\n <title>{{title}}</title>\n <circle v-if=\"fraction >= 1.0\" cx=\"50\" cy=\"50\" :r=\"radius\" \n :style=\"'opacity: 1; stroke-width: '+ (stroke*100)+'; stroke: currentcolor; fill: none;'\"/>\n <g v-else>\n <circle cx=\"50\" cy=\"50\" :r=\"radius\" \n :style=\"'opacity: ' + bgopacity + ';stroke-width: '+ (stroke*100)+'; stroke: currentcolor; fill: none;'\"/>\n <path :d=\"arcpath\" \n :style=\"'stroke-width: ' + (stroke*100) +'; stroke: currentcolor; fill: none;'\"/>\n </g>\n </svg>\n <i v-if='icon' :class=\"'fa fa-'+icon\" \n style=\" position: absolute; top: 0.42em; left: 0.43em; text-align:center; display: inline-block; \n width:1em; font-size: 0.55em; \"\n ></i>\n </div>\n `,\n });\n\n\n Vue.component('r-report', {\n props: {\n value: {\n type: Array,\n },\n guestmode: {\n type: Boolean,\n default: false,\n },\n teachermode: {\n type: Boolean,\n default: false,\n }\n },\n data() {\n return {\n selectedstudyplan: null,\n };\n },\n computed: {\n displayedstudyplan(){\n if(this.selectedstudyplan){\n return this.selectedstudyplan;\n } else if(this.value && this.value.length > 0){\n return this.value[0];\n } else {\n return null;\n }\n }\n },\n methods: {\n },\n template: `\n <div class='t-studyplan-container'> \n <b-list-group horizontal\n class='r-report-tabs'>\n <b-list-group-item \n v-for=\"(studyplan,planindex) in value\"\n :key=\"studyplan.id\"\n :active=\"displayedstudyplan && studyplan.id == displayedstudyplan.id\"\n button\n @click=\"selectedstudyplan = studyplan\"\n >{{studyplan.name}}</b-list-group-item>\n </b-list-group>\n <r-studyplan v-if='displayedstudyplan' v-model='displayedstudyplan' :guestmode='guestmode' :teachermode='teachermode'></r-studyplan>\n </div>\n `,\n });\n\n Vue.component('r-studyplan', {\n props: {\n value: {\n type: Object,\n },\n guestmode: {\n type: Boolean,\n default: false,\n },\n teachermode: {\n type: Boolean,\n default: false,\n }\n },\n data() {\n return {\n };\n },\n computed: {\n columns() {\n return 1+ (this.page.periods * 2);\n },\n columns_stylerule() {\n // Uses css variables, so width for slots and filters can be configured in css\n let s = \"grid-template-columns: var(--studyplan-filter-width)\"; // use css variable here\n for(let i=0; i<this.page.periods;i++){\n s+= \" var(--studyplan-course-width) var(--studyplan-filter-width)\";\n }\n return s+\";\";\n },\n page() {\n //FIXME: Replace this when actual page management is implemented\n return this.value.pages[0];\n },\n },\n methods: {\n countLineLayers(line){\n let maxLayer = -1;\n for(let i = 0; i <= this.page.periods; i++){\n const slot = line.slots[i];\n // Determine the amount of used layers in a studyline slit\n for(const ix in line.slots[i].competencies){\n const item = line.slots[i].competencies[ix];\n if(item.layer > maxLayer){\n maxLayer = item.layer;\n }\n }\n for(const ix in line.slots[i].filters){\n const item = line.slots[i].filters[ix];\n if(item.layer > maxLayer){\n maxLayer = item.layer;\n }\n }\n }\n return (maxLayer >= 0)?(maxLayer+1):1;\n },\n showslot(line,index, layeridx, type){\n // check if the slot should be hidden because a previous slot has an item with a span\n // so big that it hides this slot\n const forGradable = (type == 'gradable')?true:false;\n const periods = this.page.periods;\n let show = true;\n for(let i = 0; i < periods; i++){\n if(line.slots[index-i] && line.slots[index-i].competencies){\n const list = line.slots[index-i].competencies;\n for(const ix in list){ // Really wish that 'for of' would work with the minifier moodle uses\n const item = list[ix];\n if(item.layer == layeridx){\n if(forGradable){\n if(i > 0 && (item.span - i) > 0){\n show = false;\n }\n } else {\n if((item.span - i) > 1){\n show = false;\n }\n }\n }\n }\n }\n }\n \n return show;\n }\n },\n mounted() {\n scrollCurrentIntoView(this.value.id);\n },\n updated() {\n scrollCurrentIntoView(this.value.id);\n },\n template: `\n <div class='r-studyplan-content'>\n <!-- First paint the headings-->\n <div class='r-studyplan-headings'\n ><s-studyline-header-heading></s-studyline-header-heading>\n <r-studyline-heading v-for=\"(line,lineindex) in page.studylines\"\n :key=\"line.id\"\n v-model=\"page.studylines[lineindex]\"\n :layers='countLineLayers(line)+1'\n :class=\" 't-studyline' + ((lineindex%2==0)?' odd ' :' even ' )\n + ((lineindex==0)?' first ':' ') \n + ((lineindex==page.studylines.length-1)?' last ':' ')\"\n ></r-studyline-heading\n ></div>\n <!-- Next, paint all the cells in the scrollable -->\n <div class=\"r-studyplan-scrollable\" >\n <div class=\"r-studyplan-timeline\" :style=\"columns_stylerule\">\n <!-- add period information -->\n <template v-for=\"(n,index) in (page.periods+1)\">\n <s-studyline-header-period \n v-if=\"index > 0\"\n v-model=\"page.perioddesc[index-1]\"\n ></s-studyline-header-period>\n <div class=\"s-studyline-header-filter\"></div>\n </template>\n \n <!-- Line by line add the items -->\n <!-- The grid layout handles putting it in rows and columns -->\n <template v-for=\"(line,lineindex) in page.studylines\"\n ><template v-for=\"(layernr,layeridx) in countLineLayers(line)\"\n ><template v-for=\"(n,index) in (page.periods+1)\"\n ><r-studyline-slot \n v-if=\"index > 0 && showslot(line, index, layeridx, 'gradable')\"\n type='gradable'\n v-model=\"line.slots[index].competencies\" \n :key=\"'c-'+lineindex+'-'+index+'-'+layernr\" \n :slotindex=\"index\" \n :line=\"line\"\n :plan=\"value\"\n :page=\"page\"\n :period=\"page.perioddesc[index-1]\"\n :guestmode='guestmode'\n :teachermode='teachermode'\n :layer=\"layeridx\"\n :class=\"'t-studyline ' + ((lineindex%2==0)?' odd ':' even ')\n + ((lineindex==0 && layernr==1)?' first ':' ')\n + ((lineindex==page.studylines.length-1)?' last ':' ')\"\n ></r-studyline-slot\n ><r-studyline-slot \n v-if=\"showslot(line, index, layeridx, 'gradable')\"\n type='filter'\n v-model=\"line.slots[index].filters\" \n :teachermode='teachermode'\n :key=\"'f-'+lineindex+'-'+index+'-'+layernr\" \n :slotindex=\"index\" \n :line=\"line\"\n :plan=\"value\"\n :page=\"page\"\n :layer=\"layeridx\"\n :class=\"'t-studyline ' + ((lineindex%2==0)?' odd ':' even ')\n + ((lineindex==0 && layernr==1)?' first ':'')\n + ((lineindex==page.studylines.length-1)?' last ':' ')\n + ((index==page.periods)?' rightmost':'')\"\n >\n </r-studyline-slot\n ></template\n ></template\n ></template\n ></div\n ></div\n ></div>\n `,\n });\n\n /*\n * R-STUDYLINE-HEADER\n */\n Vue.component('r-studyline-heading', {\n props: {\n value : {\n type: Object, // Studyline\n default: function(){ return {};},\n },\n layers: {\n type: Number,\n default: 1,\n },\n },\n data() {\n return {\n layerHeights: {}\n };\n },\n created() {\n // Listener for the signal that a new connection was made and needs to be drawn\n // Sent by the incoming item - By convention, outgoing items are responsible for drawing the lines\n ItemEventBus.$on('lineHeightChange', this.onLineHeightChange);\n },\n computed: {\n \n },\n methods: {\n onLineHeightChange(lineid,layerid,newheight){\n // All layers for this line have the first slot send an update message on layer height change.\n // When one of those updates is received, record the height and recalculate the total height of the \n // header\n if(this.$refs.mainEl && lineid == this.value.id){\n const items = document.querySelectorAll(\n `.r-studyline-slot-0[data-studyline='${this.value.id}']`);\n // determine the height of all the lines and add them up.\n let heightSum = 0;\n items.forEach((el) => {\n // getBoundingClientRect() Gets the actual fractional height instead of rounded to integer pixels\n const r = el.getBoundingClientRect();\n const height = r.height;\n heightSum += height;\n });\n\n const heightStyle=`${heightSum}px`;\n this.$refs.mainEl.style.height = heightStyle;\n }\n }\n },\n template: `\n <div class=\"r-studyline r-studyline-heading \" \n :data-studyline=\"value.id\" ref=\"mainEl\"\n ><div class=\"r-studyline-handle\" :style=\"'background-color: ' + value.color\"></div>\n <div class=\"r-studyline-title\">\n <abbr v-b-tooltip.hover :title=\"value.name\">{{ value.shortname }}</abbr>\n </div>\n </div>\n `,\n });\n\n Vue.component('r-studyline-slot', {\n props: {\n value: {\n type: Array, // item to display\n default(){ return [];},\n },\n type : {\n type: String,\n default: 'gradable',\n },\n slotindex : {\n type: Number,\n default: 0,\n },\n line : {\n type: Object,\n default(){ return null;},\n },\n layer : {\n type: Number,\n }, \n plan: {\n type: Object,\n default(){ return null;},\n },\n page: {\n type: Object,\n default(){ return null;},\n }, \n guestmode: {\n type: Boolean,\n default: false,\n },\n teachermode: {\n type: Boolean,\n default: false,\n },\n period: { \n type: Object,\n default(){ return null;},\n }\n },\n mounted() {\n const self=this;\n if(self.type == \"gradable\" && self.slotindex == 1){\n self.resizeListener = new ResizeObserver(() => {\n if(self.$refs.sizeElement){\n const height = self.$refs.sizeElement.getBoundingClientRect().height;\n ItemEventBus.$emit('lineHeightChange', self.line.id, self.layer, height);\n }\n }).observe(self.$refs.sizeElement);\n }\n },\n computed: {\n item(){\n for(const ix in this.value){\n const itm = this.value[ix];\n if(itm.layer == this.layer){\n return itm;\n }\n }\n return null;\n },\n current(){\n if( this.period && this.period.startdate && this.period.enddate){\n const now = new Date();\n const pstart = new Date(this.period.startdate);\n const pend = new Date(this.period.enddate);\n return (now >= pstart && now < pend);\n }\n else {\n return false;\n }\n },\n spanCss(){\n if(this.item && this.item.span > 1){\n const span = (2 * this.item.span) - 1;\n return `width: 100%; grid-column: span ${span};`;\n } else {\n return \"\";\n }\n }\n },\n data() {\n return {\n };\n },\n methods: {\n \n },\n template: `\n <div :class=\" 'r-studyline-slot ' + type + ' ' + (current?'current ':' ') \n + 'r-studyline-slot-' + slotindex + ' ' \n + ((slotindex==0)?'r-studyline-firstcolumn ':' ')\"\n :data-studyline=\"line.id\" ref=\"sizeElement\"\n :style='spanCss'\n ><div class=\"r-slot-item\" v-if=\"item\"\n ><r-item \n v-model=\"item\" \n :plan=\"plan\"\n :guestmode='guestmode'\n :teachermode='teachermode'></r-item\n ></div\n ></r-item\n ></div>\n `,\n });\n\n\n Vue.component('r-item', {\n props: {\n value :{\n type: Object,\n default: function(){ return null;},\n }, \n plan: {\n type: Object,\n default(){ return null;}\n },\n guestmode: {\n type: Boolean,\n default: false,\n },\n teachermode: {\n type: Boolean,\n default: false,\n }\n },\n data() {\n return {\n lines: [],\n };\n },\n methods: {\n lineColor(){\n if(this.teachermode){\n return \"var(--gray)\";\n }\n else{\n switch(this.value.completion){\n default: // \"incomplete\"\n return \"var(--gray)\";\n case \"failed\":\n return \"var(--danger)\";\n case \"progress\":\n return \"var(--warning)\";\n case \"completed\":\n return \"var(--success)\";\n case \"good\":\n return \"var(--info)\";\n case \"excellent\":\n return \"var(--blue)\";\n }\n }\n },\n redrawLine(conn){\n let lineColor = this.lineColor();\n\n // prepare lineinfo link or delete old line\n let lineinfo = this.lines[conn.to_id];\n if(lineinfo){\n if(lineinfo.line){\n if(lineinfo.lineElm ){\n lineinfo.lineElm.parentNode.removeChild(lineinfo.lineElm);\n lineinfo.lineElm = undefined;\n } else {\n lineinfo.line.remove();\n }\n lineinfo.line = undefined;\n }\n } else {\n lineinfo = {};\n this.lines[conn.to_id] = lineinfo;\n }\n\n // draw new line...\n let start = document.getElementById('studyitem-'+conn.from_id);\n let end= document.getElementById('studyitem-'+conn.to_id);\n if(start !== null && end !== null && isVisible(start) && isVisible(end)){\n lineinfo.line = new SimpleLine(start,end,{\n color: lineColor,\n gravity: {\n start: LINE_GRAVITY,\n end: LINE_GRAVITY,\n },\n });\n\n let elmWrapper = (this.plan.id >=0)?document.getElementById('studyplan-linewrapper-'+this.plan.id):null;\n if(elmWrapper !== null){\n let elmLine = document.querySelector('body > .leader-line:last-child');\n elmWrapper.appendChild(elmLine);\n lineinfo.lineElm = elmLine; // store line element so it can more easily be removed from the dom\n }\n }\n },\n redrawLines(){\n for(let i in this.value.connections.out){\n let conn = this.value.connections.out[i];\n this.redrawLine(conn);\n }\n },\n onWindowResize(){\n this.redrawLines();\n }\n },\n computed: {\n hasConnectionsOut() {\n return !([\"finish\",].includes(this.value.type));\n },\n hasConnectionsIn() {\n return !([\"start\",].includes(this.value.type));\n },\n hasContext() {\n return ['start','junction','finish'].includes(this.value.type);\n }\n },\n created(){\n \n },\n mounted(){\n // Initialize connection lines when mounting\n\n this.redrawLines();\n setTimeout(()=>{\n this.redrawLines();\n },50);\n\n // Add resize event listener\n window.addEventListener('resize',this.onWindowResize);\n },\n beforeDestroy(){\n for(let i in this.value.connections.out){\n let conn = this.value.connections.out[i];\n let lineinfo = this.lines[conn.to_id];\n if(lineinfo){\n if(lineinfo.line){\n if(lineinfo.lineElm ){\n lineinfo.lineElm.parentNode.removeChild(lineinfo.lineElm);\n lineinfo.lineElm = undefined;\n } else {\n lineinfo.line.remove();\n }\n lineinfo.line = undefined;\n }\n } \n }\n // Remove resize event listener\n window.removeEventListener('resize',this.onWindowResize);\n },\n beforeUpdate(){\n },\n updated(){\n if(!this.dummy) {\n this.redrawLines();\n }\n },\n template: `\n <div class=\"r-item-base\" :id=\"'studyitem-'+value.id\" :data-x='value.type'>\n <r-item-competency v-if=\"value.type == 'competency'\"\n v-model=\"value\" :guestmode=\"guestmode\" :teachermode=\"teachermode\" ></r-item-competency>\n <r-item-course v-if=\"value.type == 'course' && !teachermode\" :plan=\"plan\"\n v-model=\"value\" :guestmode=\"guestmode\" :teachermode=\"teachermode\" ></r-item-course>\n <r-item-teachercourse v-if=\"value.type == 'course' && teachermode\" :plan=\"plan\"\n v-model=\"value\" :guestmode=\"guestmode\" :teachermode=\"teachermode\" ></r-item-teachercourse>\n <r-item-junction v-if=\"value.type == 'junction'\"\n v-model=\"value\" :guestmode=\"guestmode\" :teachermode=\"teachermode\" ></r-item-junction>\n <r-item-start v-if=\"value.type == 'start'\"\n v-model=\"value\" :guestmode=\"guestmode\" :teachermode=\"teachermode\" ></r-item-start>\n <r-item-finish v-if=\"value.type == 'finish'\"\n v-model=\"value\" :guestmode=\"guestmode\" :teachermode=\"teachermode\" ></r-item-finish>\n <r-item-badge v-if=\"value.type == 'badge'\"\n v-model=\"value\" :guestmode=\"guestmode\" :teachermode=\"teachermode\" ></r-item-badge>\n <r-item-invalid v-if=\"value.type == 'invalid' && teachermode\" \n v-model=\"value\" ></r-item-invalid>\n </div>\n `,\n });\n\n Vue.component('r-item-invalid', {\n props: {\n 'value' :{\n type: Object,\n default: function(){ return null;},\n },\n },\n data() {\n return {\n text: strings.invalid,\n };\n },\n methods: {\n },\n template: `\n <b-card no-body class=\"r-item-invalid\">\n <b-row no-gutters>\n <b-col md=\"1\">\n <span class=\"r-timing-indicator timing-invalid\"></span>\n </b-col>\n <b-col md=\"11\">\n <b-card-body class=\"align-items-center\">\n <i class=\"fa fa-exclamation\"></i> {{ text.error }}\n </b-card-body>\n </b-col>\n </b-row>\n </b-card>\n `,\n });\n\n //TAG: Item Course\n Vue.component('r-item-course', {\n props: {\n value :{\n type: Object,\n default(){ return null;},\n },\n guestmode: {\n type: Boolean,\n default(){ return false;}\n },\n teachermode: {\n type: Boolean,\n default(){ return false;}\n }, \n plan: {\n type: Object,\n default(){ return null;}\n }\n },\n data() {\n return {\n text: strings.course,\n };\n },\n computed: {\n startdate(){\n return format_date(this.value.course.startdate);\n },\n enddate(){\n if(this.value.course.enddate){\n return format_date(this.value.course.enddate);\n } \n else {\n return this.text.noenddate;\n }\n }\n },\n created(){\n const self = this;\n // Get text strings for condition settings\n let stringkeys = [];\n for(const key in this.text){\n stringkeys.push({ key: key, component: 'local_treestudyplan'});\n }\n get_strings(stringkeys).then(function(strings){\n let i = 0;\n for(const key in self.text){\n self.text[key] = strings[i];\n i++;\n }\n });\n },\n methods: {\n completion_icon(completion) {\n switch(completion){\n default: // case \"incomplete\"\n return \"circle-o\";\n case \"pending\":\n return \"question-circle\";\n case \"failed\":\n return \"times-circle\"; \n case \"progress\":\n return \"exclamation-circle\";\n case \"completed\":\n return \"check-circle\";\n case \"good\":\n return \"check-circle\";\n case \"excellent\":\n return \"check-circle\";\n }\n },\n circle_icon(completion) {\n switch(completion){\n default: // case \"incomplete\"\n return null;\n case \"failed\":\n return \"times\"; \n case \"progress\":\n return \"exclamation\";\n case \"completed\":\n return \"check\";\n case \"good\":\n return \"check\";\n case \"excellent\":\n return \"check\";\n }\n },\n },\n template: `\n <b-card no-body :class=\"'r-item-competency completion-'+value.completion\">\n <b-row no-gutters>\n <b-col md=\"1\">\n <span \n :title=\"text['coursetiming_'+value.course.timing]\" \n v-b-popover.hover.top=\"startdate+' - '+enddate\" \n :class=\"'r-timing-indicator timing-'+value.course.timing\"></span>\n </b-col>\n <b-col md=\"11\">\n <b-card-body class=\"align-items-center\">\n <template v-if='value.course.completion'>\n <r-progress-circle v-if='[\"failed\", \"progress\",\"incomplete\"].includes(value.completion)'\n :value='value.course.completion.progress'\n :max='value.course.completion.count'\n :min='0'\n :class=\"'r-course-result r-completion-'+value.completion\"\n :icon='circle_icon(value.completion)'\n :title=\"text['completion_'+value.completion]\"\n ></r-progress-circle>\n <i v-else v-b-popover.top \n :class=\"'r-course-result fa fa-'+completion_icon(value.completion)+\n ' r-completion-'+value.completion\"\n :title=\"text['completion_'+value.completion]\"></i>\n </template>\n <template v-else>\n <i v-b-popover.top \n :class=\"'r-course-result fa fa-'+completion_icon(value.completion)+\n ' r-completion-'+value.completion\"\n :title=\"text['completion_'+value.completion]\"></i>\n </template>\n <a v-b-modal=\"'r-item-course-details-'+value.id\" \n :href=\"(!guestmode)?('/course/view.php?id='+value.course.id):'#'\"\n @click.prevent.stop=''\n >{{ value.course.displayname }}</i></a>\n </b-card-body>\n </b-col>\n </b-row>\n \n <b-modal\n :id=\"'r-item-course-details-'+value.id\" \n :title=\"value.course.displayname + ' - ' + value.course.fullname\" \n size=\"lg\"\n ok-only\n centered\n scrollable\n >\n <template #modal-header>\n <div>\n <h1><a :href=\"(!guestmode)?('/course/view.php?id='+value.course.id):undefined\" target=\"_blank\"\n ><i class=\"fa fa-graduation-cap\"></i> {{ value.course.fullname }}</a></h1>\n {{ value.course.context.path.join(\" / \")}}\n </div>\n <div class=\"r-course-detail-header-right\">\n <div class=\"r-completion-detail-header\">\n <template v-if='value.course.completion'>\n {{text['completion_'+value.completion]}}\n <r-progress-circle v-if='[\"failed\",\"progress\",\"incomplete\"].includes(value.completion)'\n :value='value.course.completion.progress'\n :max='value.course.completion.count'\n :min='0'\n :title=\"text['completion_'+value.completion]\"\n :class=\"'r-progress-circle-popup r-completion-'+value.completion\"\n :icon='circle_icon(value.completion)'\n ></r-progress-circle\n ><i v-else v-b-popover.top \n :class=\"'fa fa-'+completion_icon(value.completion)+\n ' r-progress-icon-popup r-completion-'+value.completion\"\n :title=\"text['completion_'+value.completion]\"></i>\n </template>\n <template v-else>\n {{text['completion_'+value.completion]}}\n <i :class=\"'fa fa-'+completion_icon(value.completion)+' r-completion-'+value.completion\"\n :title=\"text['completion_'+value.completion]\"></i>\n </template>\n </div>\n <div :class=\"'r-timing-'+value.course.timing\">\n {{text['coursetiming_'+value.course.timing]}}<br>\n {{ startdate }} - {{ enddate }}\n </div>\n </div>\n </template>\n <r-item-studentgrades \n v-if='!!value.course.grades && value.course.grades.length > 0' \n v-model='value'\n :guestmode='guestmode'></r-item-studentgrades>\n <r-item-studentcompletion\n v-if='!!value.course.completion' \n v-model='value.course.completion'\n :course='value.course'\n :guestmode='guestmode'></r-item-studentcompletion>\n </b-modal> \n </b-card>\n `,\n });\n\n //TAG: Selected activities dispaly\n Vue.component('r-item-studentgrades',{\n props: {\n value : {\n type: Object,\n default: function(){ return {};},\n },\n guestmode: {\n type: Boolean,\n default: false,\n },\n },\n data() {\n return {\n text: strings.course,\n };\n },\n computed: {\n pendingsubmission(){\n let result = false;\n for(const ix in this.value.course.grades){\n const g = this.value.course.grades[ix];\n if(g.pendingsubmission){\n result = true;\n break;\n }\n }\n return result;\n },\n useRequiredGrades() {\n if(this.plan && this.plan.aggregation_info && this.plan.aggregation_info.useRequiredGrades !== undefined){\n return this.plan.aggregation_info.useRequiredGrades;\n }\n else {\n return false;\n }\n }, \n },\n methods: {\n completion_icon(completion) {\n switch(completion){\n default: // case \"incomplete\"\n return \"circle-o\";\n case \"pending\":\n return \"question-circle\";\n case \"failed\":\n return \"times-circle\"; \n case \"progress\":\n return \"exclamation-circle\";\n case \"completed\":\n return \"check-circle\";\n case \"good\":\n return \"check-circle\";\n case \"excellent\":\n return \"check-circle\";\n }\n },\n },\n template: `\n <table class=\"r-item-course-grade-details\">\n <tr v-for=\"g in value.course.grades\">\n <td><span class=\"r-activity-icon\" :title=\"g.typename\" v-html=\"g.icon\"></span\n ><a\n :href=\"(!guestmode)?(g.link):undefined\" target=\"_blank\" :title=\"g.name\">{{g.name}}</a>\n <abbr v-if=\"useRequiredGrades && g.required\" :title=\"text.required_goal\"\n :class=\"'s-required ' + g.completion\"\n ><i class='fa fa-asterisk' ></i\n ></abbr>\n </td>\n <td><span :class=\"' r-completion-'+g.completion\">{{g.grade}}</span></td>\n <td><i :class=\"'fa fa-'+completion_icon(g.completion)+' r-completion-'+g.completion\"\n :title=\"text['completion_'+g.completion]\"></i>\n <i v-if='g.pendingsubmission' :title=\"text['completion_pending']\" \n class=\"r-pendingsubmission fa fa-clock-o\"></i></td>\n <td v-if=\"g.feedback\">\n <a v-b-modal=\"'r-grade-feedback-'+g.id\" \n href=\"#\" \n >{{ text[\"view_feedback\"]}}</a>\n <b-modal\n :id=\"'r-grade-feedback-'+g.id\" \n size=\"sm\"\n ok-only\n centered\n scrollable\n >\n <template #modal-header>\n <h2><i class=\"fa fa-graduation-cap\"></i>{{ value.course.fullname }}</h2><br>\n <span class=\"r-activity-icon\" :title=\"g.typename\" v-html=\"g.icon\"></span>{{g.name}}\n </template> \n <span v-html=\"g.feedback\"></span>\n </b-modal>\n </td>\n </tr>\n </table>\n `,\n });\n\n //TAG: Core completion version of student course info\n Vue.component('r-item-studentcompletion',{\n props: {\n value : {\n type: Object,\n default: function(){ return {};},\n },\n guestmode: {\n type: Boolean,\n default: false,\n },\n course: {\n type: Object,\n default: function(){ return {};},\n },\n },\n data() {\n return {\n text: {\n completion_incomplete: \"completion_incomplete\",\n completion_failed: \"completion_failed\",\n completion_pending: \"completion_pending\",\n completion_progress: \"completion_progress\",\n completion_completed: \"completion_completed\",\n completion_good: \"completion_good\",\n completion_excellent: \"completion_excellent\",\n view_feedback: \"view_feedback\",\n coursetiming_past: \"coursetiming_past\",\n coursetiming_present: \"coursetiming_present\",\n coursetiming_future: \"coursetiming_future\",\n required_goal: \"required_goal\",\n },\n };\n },\n created(){\n const self = this;\n // Get text strings for condition settings\n let stringkeys = [];\n for(const key in this.text){\n stringkeys.push({ key: key, component: 'local_treestudyplan'});\n }\n get_strings(stringkeys).then(function(strings){\n let i = 0;\n for(const key in self.text){\n self.text[key] = strings[i];\n i++;\n }\n });\n },\n computed: {\n },\n methods: {\n completion_icon(completion) {\n switch(completion){\n case \"progress\":\n return \"exclamation-circle\";\n case \"complete\":\n return \"check-circle\";\n case \"complete-pass\":\n return \"check-circle\";\n case \"complete-fail\":\n return \"times-circle\";\n default: // case \"incomplete\"\n return \"circle-o\";\n }\n },\n\n completion_tag(cgroup){\n return cgroup.completion?'completed':'incomplete';\n }\n },\n template: `\n <table class=\"r-item-course-grade-details\">\n <template v-for='cgroup in value.conditions'>\n <tr>\n <th colspan='2'>{{cgroup.title}}</th>\n <th><r-progress-circle v-if=\"cgroup.progress < cgroup.count\"\n :value='cgroup.progress'\n :max='cgroup.count'\n :class=\"'r-completion-'+cgroup.status\"\n :title=\"text['completion_'+cgroup.status]\"\n ></r-progress-circle>\n <i v-else :class=\"'fa fa-check-circle r-completion-'+cgroup.status\"></i>\n </th>\n </tr>\n <tr v-for='ci in cgroup.items'>\n <td><span v-if='guestmode'>{{ci.title}}</span>\n <span v-else v-html='ci.details.criteria'></span>\n <a href=\"#\" v-b-tooltip.click=\"{ customClass: 'r-tooltip ' + ci.status}\"\n :title=\"ci.details.requirement\"\n :class=\"'s-required ' + ci.status\"><i v-if=\"ci.details.requirement\" \n class='fa fa-question-circle' \n ></i></a>\n <td><span :class=\"' r-completion-'+ci.status\">{{ci.grade}}</span></td>\n <td><i :class=\"'fa fa-'+completion_icon(ci.status)+' r-completion-'+ci.status\"\n :title=\"text['completion_'+ci.status]\"></i>\n <i v-if='ci.pending' :title=\"text['completion_pending']\" \n class=\"r-pendingsubmission fa fa-clock-o\"></i>\n </td>\n <td v-if=\"ci.feedback\">\n <a v-b-modal=\"'r-grade-feedback-'+ci.id\" \n href=\"#\" \n >{{ text[\"view_feedback\"]}}</a>\n <b-modal\n :id=\"'r-grade-feedback-'+ci.id\" \n size=\"sm\"\n ok-only\n centered\n scrollable\n >\n <template #modal-header>\n <h2><i class=\"fa fa-graduation-cap\"></i>{{ course.fullname }}</h2><br>\n <span class=\"r-activity-icon\" :title=\"ci.typename\" v-html=\"ci.icon\"></span>{{ci.name}}\n </template>\n <span v-html=\"ci.feedback\"></span>\n </b-modal>\n </td>\n </tr>\n </template>\n </table>\n `,\n });\n\n //TAG: Teacher course\n Vue.component('r-item-teachercourse', {\n props: {\n value :{\n type: Object,\n default(){ return null;}\n },\n guestmode: {\n type: Boolean,\n default(){ return false;}\n },\n teachermode: {\n type: Boolean,\n default(){ return false;}\n },\n plan: {\n type: Object,\n default(){ return null;}\n }\n },\n data() {\n return {\n text: strings.teachercourse,\n txt: {\n grading: strings.grading,\n }\n };\n },\n computed: {\n course_grading_needed(){\n return this.course_grading_state();\n },\n course_grading_icon(){\n return this.determine_grading_icon(this.course_grading_state());\n },\n filtered_grades(){\n return this.value.course.grades.filter(g => g.selected);\n },\n useRequiredGrades() {\n if(this.plan && this.plan.aggregation_info && this.plan.aggregation_info.useRequiredGrades !== undefined){\n return this.plan.aggregation_info.useRequiredGrades;\n }\n else {\n return false;\n }\n },\n isCompletable() {\n let completable = false;\n if(this.value.course.completion){\n if(this.value.course.completion.conditions.length > 0){\n completable = true;\n }\n } else if (this.value.course.grades){\n if(this.value.course.grades.length > 0){\n completable = true;\n }\n }\n\n return completable;\n },\n progress_circle() { //INFO:\n const status = {\n students: 0,\n completed: 0,\n completed_pass: 0,\n completed_fail: 0,\n ungraded: 0,\n };\n\n if(this.value.course.completion){\n for(const cond of this.value.course.completion.conditions){\n for(const itm of cond.items){\n if(itm.progress){\n status.students += itm.progress.students;\n status.completed += itm.progress.completed;\n status.completed_pass += itm.progress.completed_pass;\n status.completed_fail += itm.progress.completed_fail;\n status.ungraded += itm.progress.completed;\n }\n }\n }\n\n } else if (this.value.course.grades){\n for( const g of this.value.course.grades){\n if(g.grading){\n status.students += g.grading.students;\n status.completed += g.grading.completed;\n status.completed_pass += g.grading.completed_pass;\n status.completed_fail += g.grading.completed_fail;\n status.ungraded += g.grading.ungraded;\n }\n }\n }\n\n return status;\n },\n startdate(){\n return format_date(this.value.course.startdate);\n },\n enddate(){\n if(this.value.course.enddate){\n return format_date(this.value.course.enddate);\n } \n else {\n return this.text.noenddate;\n }\n }\n },\n created(){\n const self = this;\n // Get text strings for condition settings\n let stringkeys = [];\n for(const key in this.text){\n stringkeys.push({ key: key, component: 'local_treestudyplan'});\n }\n get_strings(stringkeys).then(function(strings){\n let i = 0;\n for(const key in self.text){\n self.text[key] = strings[i];\n i++;\n }\n });\n },\n methods: {\n course_grading_state(){\n let ungraded = 0;\n let unknown = 0;\n let graded = 0;\n let allgraded = 0;\n const grades = this.filtered_grades;\n\n if(!Array.isArray(grades) || grades == 0){\n return 'nogrades';\n }\n\n for(const ix in grades){\n const grade = grades[ix];\n if(grade.grading){\n if(Number(grade.grading.ungraded) > 0){\n ungraded++;\n }\n else if(Number(grade.grading.graded) > 0) {\n if(Number(grade.grading.graded) == Number(grade.grading.students)){\n allgraded++; \n } else {\n graded++;\n }\n }\n } else {\n unknown = true;\n }\n }\n \n if(ungraded > 0){\n return 'ungraded';\n } else if(unknown) {\n return 'unknown';\n } else if(graded){\n return 'graded';\n } else if(allgraded){\n return 'allgraded';\n } else {\n return 'unsubmitted';\n }\n },\n determine_grading_icon(gradingstate){\n switch(gradingstate){\n default: // \"nogrades\":\n return \"circle-o\";\n case \"ungraded\":\n return \"exclamation-circle\";\n case \"unknown\":\n return \"question-circle-o\";\n case \"graded\":\n return \"check\";\n case \"allgraded\":\n return \"check\";\n case \"unsubmitted\":\n return \"dot-circle-o\";\n }\n },\n },\n template: `\n <b-card no-body :class=\"'r-item-competency '+ (value.course.amteacher?'r-course-am-teacher':'')\">\n <div class='d-flex flex-wrap mr-0 ml-0'>\n <div>\n <span \n :title=\"text['coursetiming_'+value.course.timing]\" \n v-b-popover.hover.top=\"startdate+' - '+enddate\" \n :class=\"'r-timing-indicator timing-'+value.course.timing\"></span>\n </div>\n <div class=\"flex-fill\">\n <b-card-body class=\"align-items-center\">\n <a v-b-modal=\"'r-item-course-details-'+value.id\" \n :href=\"(!guestmode)?('/course/view.php?id='+value.course.id):'#'\"\n @click.prevent.stop=''\n >{{ value.course.displayname }}</i></a>\n <r-completion-circle class=\"r-course-graded\" :disabled=\"!isCompletable\"\n v-model=\"progress_circle\"></r-completion-circle>\n </b-card-body>\n </div>\n </div>\n <b-modal\n v-if=\"true\"\n :id=\"'r-item-course-details-'+value.id\" \n :title=\"value.course.displayname + ' - ' + value.course.fullname\" \n size=\"lg\"\n ok-only\n centered\n scrollable\n >\n <template #modal-header>\n <div>\n <h1><a :href=\"(!guestmode)?('/course/view.php?id='+value.course.id):undefined\" target=\"_blank\"\n ><i class=\"fa fa-graduation-cap\"></i> {{ value.course.fullname }}</a>\n <r-item-teacher-gradepicker v-model=\"value.course\"\n v-if=\"value.course.grades && value.course.grades.length > 0\"\n :useRequiredGrades=\"useRequiredGrades\"\n :plan=\"plan\"\n ></r-item-teacher-gradepicker>\n <a v-if='!!value.course.completion && value.course.amteacher' \n :href=\"'/course/completion.php?id='+value.course.id\" target=\"_blank\"\n :title=\"text.configure_completion\"><i class=\"fa fa-gear\"></i></a>\n </h1>\n {{ value.course.context.path.join(\" / \")}}\n </div>\n <div class=\"r-course-detail-header-right\">\n <div class=\"r-completion-detail-header\">\n <r-completion-circle class=\"r-progress-circle-popup\" :disabled=\"!isCompletable\"\n v-model=\"progress_circle\"></r-completion-circle>\n </div>\n <div :class=\"'r-timing-'+value.course.timing\">\n {{ text['coursetiming_'+value.course.timing] }}<br>\n {{ startdate }} - {{ enddate }}\n </div>\n </div>\n </template>\n <r-item-teachergrades \n v-if='!!value.course.grades && value.course.grades.length > 0' \n v-model='value.course'\n :useRequiredGrades=\"useRequiredGrades\"\n ></r-item-teachergrades>\n <r-item-teachercompletion\n v-if='!!value.course.completion' \n v-model='value.course.completion'\n :course='value.course'\n ></r-item-teachercompletion>\n </b-modal>\n \n </b-card>\n `,\n });\n\n\n //TAG: Select activities to use in grade overview\n Vue.component('r-item-teacher-gradepicker', {\n props: {\n value : {\n type: Object,\n default: function(){ return {};},\n },\n useRequiredGrades: {\n type: Boolean,\n default(){ return null;}\n }\n },\n data() {\n return {\n };\n },\n computed: {\n },\n methods: {\n\n },\n template: `\n <a v-if=\"value.canselectgradables\" href='#' \n v-b-modal=\"'r-item-course-config-'+value.id\" \n @click.prevent.stop=''\n ><i class='fa fa-cog'></i>\n <b-modal v-if='value.canselectgradables'\n :id=\"'r-item-course-config-'+value.id\" \n :title=\"value.displayname + ' - ' + value.fullname\" \n ok-only\n scrollable\n >\n <template #modal-header>\n <div>\n <h1><a :href=\"'/course/view.php?id='+value.id\" target=\"_blank\"\n ><i class=\"fa fa-graduation-cap\"></i> {{ value.fullname }}</a></h1>\n {{ value.course.context.path.join(\" / \")}} / {{value.displayname}}\n </div>\n <div class=\"r-course-detail-header-right\">\n <div :class=\"'r-timing-'+value.timing\">\n {{text['coursetiming_'+value.timing]}}<br>\n {{ value.startdate }} - {{ value.enddate }}\n </div>\n </div>\n </template>\n <b-form-group\n :label=\"text.select_grades\"\n ><ul class=\"t-item-module-children\">\n <li class=\"t-item-course-gradeinfo\">\n <span class='t-item-course-chk-lbl'>{{text.grade_include}}</span\n ><span v-if=\"useRequiredGrades\" class='t-item-course-chk-lbl'>{{text.grade_require}}</span>\n </li>\n <li class=\"t-item-course-gradeinfo\" v-for=\"g in value.grades\">\n <b-form-checkbox inline\n @change=\"includeChanged($event,g)\" v-model=\"g.selected\"\n ></b-form-checkbox>\n <b-form-checkbox v-if=\"useRequiredGrades\" inline :disabled=\"!g.selected\"\n @change=\"requiredChanged($event,g)\" v-model=\"g.required\"\n ></b-form-checkbox>\n <span :title=\"g.typename\" v-html=\"g.icon\"></span><a \n :href=\"g.link\" target=\"_blank\">{{g.name}}</a>\n <s-edit-mod \n :title=\"value.fullname\"\n @saved=\"(fd) => g.name = fd.get('name')\"\n v-if=\"g.cmid > 0\" \n :cmid=\"g.cmid\" \n :coursectxid=\"value.ctxid\"\n genericonly></s-edit-mod>\n </li>\n </ul>\n </b-form-group>\n </b-modal></a>\n `,\n });\n\n\n\n //TAG: Selected activities dispaly\n Vue.component('r-item-teachergrades',{\n props: {\n value : {\n type: Object,\n default: function(){ return {};},\n },\n useRequiredGrades: {\n type: Boolean,\n default: false,\n },\n },\n data() {\n return {\n text: strings.teachercourse,\n txt: {\n grading: strings.grading,\n }\n };\n },\n computed: {\n pendingsubmission(){\n let result = false;\n for(const ix in this.value.grades){\n const g = this.value.grades[ix];\n if(g.pendingsubmission){\n result = true;\n break;\n }\n }\n return result;\n },\n filtered_grades(){\n return this.value.grades.filter(g => g.selected);\n },\n },\n methods: {\n determine_grading_icon(gradingstate){\n switch(gradingstate){\n default: // \"nogrades\":\n return \"circle-o\";\n case \"ungraded\":\n return \"exclamation-circle\";\n case \"unknown\":\n return \"question-circle-o\";\n case \"graded\":\n return \"check\";\n case \"allgraded\":\n return \"check\";\n case \"unsubmitted\":\n return \"dot-circle-o\";\n }\n },\n grading_icon(grade){\n return this.determine_grading_icon(this.is_grading_needed(grade));\n },\n is_grading_needed(grade){\n debug.info(\"Grade: \", grade.name);\n debug.info(grade.grading);\n if(grade.grading){\n debug.info(\"Ping\");\n if(grade.grading.ungraded){\n return 'ungraded';\n } \n else if(grade.grading.completed_pass || grade.grading.completed || grade.grading.completed_fail) {\n if(Number(grade.grading.completed) + Number(grade.grading.completed_pass)\n + Number(grade.grading.completed_fail)\n == Number(grade.grading.students)){\n return 'allgraded';\n }\n else {\n return 'graded';\n }\n }\n else {\n return 'unsubmitted';\n }\n } else {\n return 'unknown';\n }\n },\n includeChanged(newValue,g){\n call([{\n methodname: 'local_treestudyplan_include_grade',\n args: { 'grade_id': g.id,\n 'item_id': this.value.id, \n 'include': newValue,\n 'required': g.required,\n }\n }])[0].fail(notification.exception);\n },\n requiredChanged(newValue,g){\n call([{\n methodname: 'local_treestudyplan_include_grade',\n args: { 'grade_id': g.id,\n 'item_id': this.value.id, \n 'include': g.selected,\n 'required': newValue,\n }\n }])[0].fail(notification.exception);\n }, \n },\n template: `\n <div>\n <table class=\"r-item-course-grade-details\">\n <tr v-for=\"g in filtered_grades\">\n <td><span class=\"r-activity-icon\" :title=\"g.typename\" v-html=\"g.icon\"></span\n ><a\n :href=\"g.gradinglink\"\n target=\"_blank\" :title=\"g.name\">{{g.name}}</a>\n <s-edit-mod \n :title=\"value.fullname\"\n @saved=\"(fd) => g.name = fd.get('name')\"\n v-if=\"g.cmid > 0\" \n :cmid=\"g.cmid\" \n :coursectxid=\"value.ctxid\"\n genericonly></s-edit-mod>\n <abbr v-if=\"useRequiredGrades && g.required\" :title=\"text.required_goal\"\n :class=\"'s-required ' + is_grading_needed(g)\"\n ><i class='fa fa-asterisk' ></i\n ></abbr> \n </td>\n <td v-if='g.grading'\n ><i :class=\"'r-course-grading fa fa-'+grading_icon(g)+' r-graded-'+is_grading_needed(g)\"\n :title=\"txt.grading[is_grading_needed(g)]\"></i>\n </td>\n <td v-if='g.grading'>\n <r-completion-bar v-model=\"g.grading\" :width=\"150\" :height=\"15\"></r-completion-bar>\n </td>\n </tr>\n </table>\n </div>\n `,\n });\n\n //TAG: Core completion version of student course info\n Vue.component('r-item-teachercompletion',{\n props: {\n value : {\n type: Object,\n default: function(){ return {};},\n },\n guestmode: {\n type: Boolean,\n default: false,\n },\n course: {\n type: Object,\n default: function(){ return {};},\n },\n },\n data() {\n return {\n text: strings.completion,\n };\n },\n created(){\n const self = this;\n // Get text strings for condition settings\n let stringkeys = [];\n for(const key in this.text){\n stringkeys.push({ key: key, component: 'local_treestudyplan'});\n }\n get_strings(stringkeys).then(function(strings){\n let i = 0;\n for(const key in self.text){\n self.text[key] = strings[i];\n i++;\n }\n });\n },\n computed: {\n completionreport(){\n return `${Config.wwwroot}/report/completion/index.php?course=${this.course.id}`;\n }\n },\n methods: {\n hasCompletions() {\n if(this.value.conditions) {\n for(const cgroup of this.value.conditions){\n if(cgroup.items && cgroup.items.length > 0){\n return true;\n }\n }\n }\n return false;\n },\n },\n template: `\n <table class=\"r-item-course-grade-details\">\n <tr v-if=\"hasCompletions\">\n <td colspan='2'><span v-if=\"value.aggregation == 'all'\">{{ text.aggregation_overall_all}}</span\n ><span v-else>{{ text.aggregation_overall_any}}</span></td>\n </tr>\n <tr v-else>\n <td colspan='2'>{{text.completion_not_configured}}!\n <span v-if=\"course.amteacher\">\n <br><a :href=\"'/course/completion.php?id='+course.id\" target='_blank'>{{text.configure_completion}}</a>\n </span>\n </td>\n </tr>\n <template v-for='cgroup in value.conditions'>\n <tr>\n <th colspan='2'><span v-if=\"cgroup.items.length > 1\"\n ><span v-if=\"cgroup.aggregation == 'all'\">{{ text.aggregation_all}}</span\n ><span v-else>{{ text.aggregation_any}}</span></span>\n {{cgroup.title}}</th>\n </tr>\n <tr v-for='ci in cgroup.items'>\n <td><span v-html='ci.details.criteria'></span>\n <a href=\"#\" v-b-tooltip.click\n :title=\"ci.details.requirement\"\n class='text-info'><i v-if=\"ci.details.requirement\" \n class='fa fa-question-circle' \n ></i></a>\n </td>\n <td>\n <r-completion-bar v-model=\"ci.progress\" :width=\"150\" :height=\"15\"></r-completion-bar>\n </td>\n </tr>\n </template>\n <tr><td colspan='2' class='pt-2'>\n <a target=\"_blank\" :href='completionreport'>{{ text.view_completion_report}} \n <i class='fa fa-external-link'></i></a></td></tr>\n </table>\n `,\n });\n\n\n Vue.component('r-grading-bar',{\n props: {\n value : {\n type: Object,\n default: function(){ return {};},\n },\n width: {\n type: Number,\n default: 150,\n },\n height: {\n type: Number,\n default: 15,\n }\n },\n data() {\n return {\n text: strings.grading,\n };\n },\n computed: {\n width_unsubmitted() {\n return this.width * this.fraction_unsubmitted();\n },\n width_graded() {\n return this.width * this.fraction_graded();\n },\n width_ungraded() {\n return this.width * this.fraction_ungraded();\n },\n count_unsubmitted(){\n return (this.value.students - this.value.graded - this.value.ungraded);\n }\n },\n methods: {\n fraction_unsubmitted() {\n if(this.value.students > 0){\n return 1 - ((this.value.graded + this.value.ungraded) / this.value.students);\n } else {\n return 1;\n }\n },\n fraction_graded() {\n if(this.value.students > 0){\n return this.value.graded / this.value.students;\n } else {\n return 0;\n }\n },\n fraction_ungraded() {\n if(this.value.students > 0){\n return this.value.ungraded / this.value.students;\n } else {\n return 0;\n }\n },\n },\n template: `\n <span class=\"r-grading-bar\" :style=\"{height: height+'px'}\"\n ><span :style=\"{height: height+'px', width: width_ungraded+'px'}\"\n class='r-grading-bar-segment r-grading-bar-ungraded'\n :title=\"text.ungraded + ' (' + this.value.ungraded + ')'\" v-b-popover.hover.top\n ></span\n ><span :style=\"{height: height+'px', width: width_graded+'px'}\"\n class='r-grading-bar-segment r-grading-bar-graded'\n :title=\"text.graded+ ' (' + this.value.graded + ')'\" v-b-popover.hover.top\n ></span\n ><span :style=\"{height: height+'px', width: width_unsubmitted+'px'}\"\n class='r-grading-bar-segment r-grading-bar-unsubmitted'\n :title=\"text.unsubmitted + ' (' + count_unsubmitted + ')'\" v-b-popover.hover.top\n ></span\n ></span>\n `,\n });\n\n Vue.component('r-completion-bar',{\n props: {\n value : {\n type: Object,\n default: function(){ return {\n students: 0,\n completed: 0,\n completed_pass: 0,\n completed_fail: 0,\n ungraded: 0,\n };},\n },\n width: {\n type: Number,\n default: 150,\n },\n height: {\n type: Number,\n default: 15,\n }\n },\n data() {\n return {\n text: strings.completion,\n };\n },\n computed: {\n width_incomplete() {\n return this.width * this.fraction_incomplete();\n },\n width_completed() {\n return this.width * this.fraction_completed();\n },\n width_completed_pass() {\n return this.width * this.fraction_completed_pass();\n },\n width_completed_fail() {\n return this.width * this.fraction_completed_fail();\n },\n width_ungraded() {\n return this.width * this.fraction_ungraded();\n },\n count_incomplete(){\n return (this.value.students - this.value.completed - this.value.completed_pass\n - this.value.completed_fail - this.value.ungraded);\n }\n },\n methods: {\n fraction_incomplete() {\n if(this.value.students > 0){\n return 1 - (\n (this.value.completed + this.value.completed_pass +\n this.value.completed_fail + this.value.ungraded) / this.value.students);\n } else {\n return 1;\n }\n },\n fraction_completed() {\n if(this.value.students > 0){\n return this.value.completed / this.value.students;\n } else {\n return 0;\n }\n },\n fraction_completed_pass() {\n if(this.value.students > 0){\n return this.value.completed_pass / this.value.students;\n } else {\n return 0;\n }\n },\n fraction_completed_fail() {\n if(this.value.students > 0){\n return this.value.completed_fail / this.value.students;\n } else {\n return 0;\n }\n },\n fraction_ungraded() {\n if(this.value.students > 0){\n return this.value.ungraded / this.value.students;\n } else {\n return 0;\n }\n },\n },\n template: `\n <span class=\"r-grading-bar\" :style=\"{height: height+'px'}\"\n ><span :style=\"{height: height+'px', width: width_ungraded+'px'}\"\n class='r-grading-bar-segment r-completion-bar-ungraded'\n :title=\"text.ungraded + ' (' + this.value.ungraded + ')'\" v-b-popover.hover.top\n ></span\n ><span :style=\"{height: height+'px', width: width_completed+'px'}\"\n class='r-grading-bar-segment r-completion-bar-completed'\n :title=\"text.completed + ' (' + this.value.completed + ')'\" v-b-popover.hover.top\n ></span\n ><span :style=\"{height: height+'px', width: width_completed_pass+'px'}\"\n class='r-grading-bar-segment r-completion-bar-completed-pass'\n :title=\"text.completed_pass + ' (' + this.value.completed_pass + ')'\" v-b-popover.hover.top\n ></span\n ><span :style=\"{height: height+'px', width: width_completed_fail+'px'}\"\n class='r-grading-bar-segment r-completion-bar-completed-fail'\n :title=\"text.completed_fail + ' (' + this.value.completed_fail + ')'\" v-b-popover.hover.top\n ></span\n ><span :style=\"{height: height+'px', width: width_incomplete+'px'}\"\n class='r-grading-bar-segment r-completion-bar-incomplete'\n :title=\"text.incomplete + ' (' + count_incomplete + ')'\" v-b-popover.hover.top\n ></span\n ></span>\n `,\n });\n\n Vue.component('r-completion-circle',{\n props: {\n value : {\n type: Object,\n default: function(){ return {\n students: 10,\n completed: 2,\n completed_pass: 2,\n completed_fail: 2,\n ungraded: 2,\n };},\n },\n stroke: {\n type: Number,\n default: 0.2,\n },\n disabled: {\n type: Boolean,\n default: false,\n },\n title: {\n type: String,\n default: \"\",\n }\n },\n computed: {\n radius() {\n return 50 - (50*this.stroke);\n },\n\n arcpath_ungraded() {\n const begin = 0;\n return this.arcpath(begin,this.fraction_ungraded());\n },\n arcpath_completed() {\n const begin = this.fraction_ungraded();\n return this.arcpath(begin,this.fraction_completed());\n },\n arcpath_completed_pass() {\n const begin = this.fraction_ungraded()\n + this.fraction_completed();\n return this.arcpath(begin,this.fraction_completed_pass());\n },\n arcpath_completed_fail() {\n const begin = this.fraction_ungraded()\n + this.fraction_completed()\n + this.fraction_completed_pass();\n return this.arcpath(begin,this.fraction_completed_fail());\n },\n arcpath_incomplete() {\n const begin = this.fraction_ungraded() \n + this.fraction_completed()\n + this.fraction_completed_pass()\n + this.fraction_completed_fail();\n return this.arcpath(begin,this.fraction_incomplete());\n },\n\n },\n methods: {\n arcpath(start, end) {\n const r = 50 - (50*this.stroke);\n\n const t1 = start * 2*π;\n const Δ = end * 2*π;\n return svgarcpath([50,50],[r,r],[t1,Δ], 1.5*π);\n },\n fraction_incomplete() {\n if(this.value.students > 0){\n return 1 - (\n (this.value.completed + this.value.completed_pass +\n this.value.completed_fail + this.value.ungraded) / this.value.students);\n } else {\n return 1;\n }\n },\n fraction_completed() {\n if(this.value.students > 0){\n return this.value.completed / this.value.students;\n } else {\n return 0;\n }\n },\n fraction_completed_pass() {\n if(this.value.students > 0){\n return this.value.completed_pass / this.value.students;\n } else {\n return 0;\n }\n },\n fraction_completed_fail() {\n if(this.value.students > 0){\n return this.value.completed_fail / this.value.students;\n } else {\n return 0;\n }\n },\n fraction_ungraded() {\n if(this.value.students > 0){\n return this.value.ungraded / this.value.students;\n } else {\n return 0;\n }\n },\n },\n template: `\n <svg width=\"1em\" height=\"1em\" viewBox=\"0 0 100 100\">\n <title>{{title}}</title>\n <circle cx=\"50\" cy=\"50\" :r=\"radius\" \n :style=\"'stroke-width: ' + (stroke*100)+'; stroke: #ccc; fill: none;'\"/>\n <path :d=\"arcpath_ungraded\" \n :style=\"'stroke-width: ' + (stroke*100) +'; stroke: var(--warning); fill: none;'\"/>\n <path :d=\"arcpath_completed\" \n :style=\"'stroke-width: ' + (stroke*100) +'; stroke: var(--info); fill: none;'\"/>\n <path :d=\"arcpath_completed_pass\" \n :style=\"'stroke-width: ' + (stroke*100) +'; stroke: var(--success); fill: none;'\"/>\n <path :d=\"arcpath_completed_fail\" \n :style=\"'stroke-width: ' + (stroke*100) +'; stroke: var(--danger); fill: none;'\"/>\n \n <circle v-if=\"disabled\" cx=\"50\" cy=\"50\" :r=\"radius/2\" \n :style=\"'fill: var(--dark);'\"/>\n <circle v-else-if=\"value.ungraded > 0\" cx=\"50\" cy=\"50\" :r=\"radius/2\" \n :style=\"'fill: var(--warning);'\"/>\n </g>\n </svg>\n `,\n });\n\n Vue.component('r-item-junction',{\n props: {\n value : {\n type: Object,\n default: function(){ return {};},\n },\n guestmode: {\n type: Boolean,\n default: false,\n },\n teachermode: {\n type: Boolean,\n default: false,\n }\n },\n data() {\n return {\n };\n },\n computed: {\n completion(){\n if(this.value.completion){\n return this.value.completion;\n } else {\n return \"incomplete\";\n }\n }\n },\n methods: {\n\n },\n template: `\n <div :class=\"'r-item-junction r-item-filter completion-'+completion\"> \n <i v-if=\"value.completion=='incomplete'\" class=\"fa fa-circle-o\"></i>\n <i v-else-if=\"value.completion=='failed'\" class=\"fa fa-times-circle\"></i>\n <i v-else-if=\"value.completion=='progress'\" class=\"fa fa-exclamation-circle\"></i>\n <i v-else class=\"fa fa-check-circle\"></i>\n </div>\n `,\n });\n\n Vue.component('r-item-finish',{\n props: {\n value : {\n type: Object,\n default: function(){ return {};},\n },\n guestmode: {\n type: Boolean,\n default: false,\n },\n teachermode: {\n type: Boolean,\n default: false,\n }\n },\n data() {\n return {\n };\n },\n computed: {\n completion(){\n if(this.value.completion){\n return this.value.completion;\n } else {\n return \"incomplete\";\n }\n }\n },\n methods: {\n },\n template: `\n <div :class=\"'r-item-finish r-item-filter completion-'+completion\"> \n <i class=\"fa fa-stop-circle\"></i>\n </div> \n `,\n });\n\n Vue.component('r-item-start',{\n props: {\n value : {\n type: Object,\n default: function(){ return {};},\n },\n guestmode: {\n type: Boolean,\n default: false,\n },\n teachermode: {\n type: Boolean,\n default: false,\n }\n },\n data() {\n return {\n };\n },\n computed: {\n completion(){\n if(this.value.completion){\n return this.value.completion;\n } else {\n return \"incomplete\";\n }\n }\n }, \n created(){\n \n },\n methods: {\n },\n template: `\n <div :class=\"'r-item-start r-item-filter completion-'+completion\">\n <i class=\"fa fa-play-circle\"></i>\n </div>\n `,\n });\n\n Vue.component('r-item-badge',{\n props: {\n value : {\n type: Object,\n default: function(){ return {};},\n },\n guestmode: {\n type: Boolean,\n default: false,\n },\n teachermode: {\n type: Boolean,\n default: false,\n }\n },\n data() {\n return {\n txt: strings\n };\n },\n computed: {\n completion() {\n return this.value.badge.issued?\"completed\":\"incomplete\";\n },\n issued_icon(){\n switch(this.value.badge.issued){\n default: // \"nogrades\":\n return \"circle-o\";\n case true:\n return \"check\";\n }\n },\n issuestats(){\n // so the r-completion-bar can be used to show issuing stats\n return {\n students: (this.value.badge.studentcount)?this.value.badge.studentcount:0,\n completed: (this.value.badge.issuedcount)?this.value.badge.issuedcount:0,\n completed_pass: 0,\n completed_fail: 0,\n ungraded: 0,\n };\n },\n arcpath_issued(){\n if(this.value.badge.studentcount){\n const fraction = this.value.badge.issuedcount/this.value.badge.studentcount;\n return this.arcpath(0,fraction);\n } else {\n return \"\"; // no path\n }\n }\n\n },\n methods: {\n arcpath(start, end) {\n const r = 44;\n\n const t1 = start * 2*π;\n const Δ = end * 2*π;\n return svgarcpath([50,50],[r,r],[t1,Δ], 1.5*π);\n },\n },\n template: `\n <div :class=\"'r-item-badge r-item-filter r-completion-'+completion\" v-b-tooltip.hover :title=\"value.badge.name\"> \n <a v-b-modal=\"'r-item-badge-details-'+value.id\" \n ><svg class=\"r-badge-backdrop \" width='50px' height='50px' viewBox=\"0 0 100 100\">\n <title>{{value.badge.name}}</title>\n <template v-if=\"teachermode\">\n <circle cx=\"50\" cy=\"50\" r=\"44\" \n style=\"stroke: #ccc; stroke-width: 8; fill: #ddd; fill-opacity: 0.8;\"/>\n <path :d=\"arcpath_issued\" \n :style=\"'stroke-width: 8; stroke: var(--info); fill: none;'\"/>\n </template>\n <circle v-else-if=\"value.badge.issued\" cx=\"50\" cy=\"50\" r=\"46\" \n style=\"stroke: currentcolor; stroke-width: 4; fill: currentcolor; fill-opacity: 0.5;\"/>\n <circle v-else cx=\"50\" cy=\"50\" r=\"46\" \n stroke-dasharray=\"6 9\"\n style=\"stroke: #999; stroke-width: 6; fill: #ddd; fill-opacity: 0.8;\"/>\n <image class=\"badge-image\" clip-path=\"circle() fill-box\"\n :href=\"value.badge.imageurl\" x=\"12\" y=\"12\" width=\"76\" height=\"76\"\n :style=\"(value.badge.issued||teachermode)?'':'opacity: 0.4;'\" />\n </svg></a>\n\n <b-modal\n :id=\"'r-item-badge-details-'+value.id\" \n :title=\"value.badge.name\" \n size=\"lg\"\n ok-only\n centered\n scrollable\n >\n <template #modal-header>\n <div>\n <h1><i class=\"fa fa-certificate\"></i>\n <a :href=\"(!guestmode)?(value.badge.infolink):undefined\" target=\"_blank\"\n >{{ value.badge.name }}</a\n ></h1>\n </div>\n <div class=\"r-course-detail-header-right\" v-if=\"!teachermode\">\n <div class=\"r-completion-detail-header\">\n {{ txt.completion['completion_'+completion] }}\n <i v-b-popover.hover :class=\"'fa fa-'+issued_icon+' r-completion-'+completion\"\n :title=\"txt.completion['completion_'+completion]\"></i>\n </div>\n </div>\n </template>\n <b-container fluid>\n <b-row><b-col cols=\"3\">\n <img :src=\"value.badge.imageurl\"/>\n </b-col><b-col cols=\"9\">\n <p>{{value.badge.description}}</p>\n <ul v-if=\"value.badge.issued\" class=\"list-unstyled pt-1 mb-1 border-grey border-top\">\n <li><strong><i class=\"fa fa-calendar-check-o r-completion-complete-pass\"></i>\n {{txt.badge.dateissued}}:</strong> {{ value.badge.dateissued }}</li>\n <li v-if='value.badge.dateexpired'\n ><strong><i class=\"fa fa-calendar-times-o r-completion-complete\"></i>\n {{txt.badge.dateexpired}}:</strong> {{ value.badge.dateexpired }}</li>\n <li><strong><i class=\"fa fa-share-alt r-completion-complete-pass\"></i>\n <a :href=\"value.badge.issuedlink\">{{txt.badge.share_badge}}</a></strong> </li>\n </ul>\n <ul class=\"list-unstyled w-100 border-grey border-top border-bottom pt-1 pb-1 mb-1\"\n v-if=\"value.badge.criteria\"><li v-for=\"crit in value.badge.criteria\"\n ><span v-html='crit'></span></li></ul>\n <p v-if=\"(!guestmode)\"><strong><i class=\"fa fa-link\"></i>\n <a :href=\"value.badge.infolink\" target=\"_blank\"\n >{{ txt.badge.badgeinfo }}</a></strong></p>\n <p v-if=\"teachermode && !guestmode\"\n >{{txt.badge.badgeissuedstats}}:<br>\n <r-completion-bar v-model=\"issuestats\" :width=\"150\" :height=\"15\"></r-completion-bar>\n </p>\n </b-col></b-row>\n </b-container>\n </b-modal>\n </div> \n\n `,\n });\n },\n};"],"names":["π","Math","PI","install","Vue","debug","Debugger","enable","lastCaller","scrollCurrentIntoView","handle","elCurrentHeader","document","querySelector","scrollIntoView","behavior","block","inline","strings","invalid","error","grading","ungraded","graded","allgraded","unsubmitted","nogrades","unknown","completion","completed","incomplete","completed_pass","completed_fail","aggregation_all","aggregation_any","aggregation_overall_all","aggregation_overall_any","completion_not_configured","configure_completion","view_completion_report","badge","share_badge","dateissued","dateexpire","badgeinfo","badgeissuedstats","course","completion_incomplete","completion_failed","completion_pending","completion_progress","completion_completed","completion_good","completion_excellent","view_feedback","coursetiming_past","coursetiming_present","coursetiming_future","required_goal","teachercourse","select_conditions","select_grades","grade_include","grade_require","isVisible","elem","offsetWidth","offsetHeight","getClientRects","length","ItemEventBus","component","props","value","type","Number","max","default","min","stroke","bgopacity","title","String","icon","data","selectedstudyplan","computed","range","this","fraction","radius","arcpath","r","Δ","methods","template","Array","guestmode","Boolean","teachermode","displayedstudyplan","Object","columns","page","periods","columns_stylerule","s","i","pages","countLineLayers","line","maxLayer","slots","ix","competencies","item","layer","filters","showslot","index","layeridx","forGradable","show","list","span","mounted","id","updated","layers","layerHeights","created","$on","onLineHeightChange","lineid","layerid","newheight","$refs","mainEl","items","querySelectorAll","heightSum","forEach","el","height","getBoundingClientRect","heightStyle","style","slotindex","plan","period","self","resizeListener","ResizeObserver","sizeElement","$emit","observe","itm","current","startdate","enddate","now","Date","pstart","pend","spanCss","lines","lineColor","redrawLine","conn","lineinfo","to_id","lineElm","parentNode","removeChild","undefined","remove","start","getElementById","from_id","end","SimpleLine","color","gravity","elmWrapper","elmLine","appendChild","redrawLines","connections","out","onWindowResize","hasConnectionsOut","includes","hasConnectionsIn","hasContext","setTimeout","_this","window","addEventListener","beforeDestroy","removeEventListener","beforeUpdate","dummy","text","noenddate","stringkeys","key","push","then","completion_icon","circle_icon","pendingsubmission","result","grades","useRequiredGrades","aggregation_info","completion_tag","cgroup","txt","course_grading_needed","course_grading_state","course_grading_icon","determine_grading_icon","filtered_grades","filter","g","selected","isCompletable","completable","conditions","progress_circle","status","students","progress","isArray","grade","gradingstate","grading_icon","is_grading_needed","info","name","includeChanged","newValue","methodname","args","required","fail","notification","exception","requiredChanged","completionreport","Config","wwwroot","hasCompletions","width","width_unsubmitted","fraction_unsubmitted","width_graded","fraction_graded","width_ungraded","fraction_ungraded","count_unsubmitted","width_incomplete","fraction_incomplete","width_completed","fraction_completed","width_completed_pass","fraction_completed_pass","width_completed_fail","fraction_completed_fail","count_incomplete","disabled","arcpath_ungraded","arcpath_completed","begin","arcpath_completed_pass","arcpath_completed_fail","arcpath_incomplete","t1","issued","issued_icon","issuestats","studentcount","issuedcount","arcpath_issued"],"mappings":"i0DAkBMA,EAAIC,KAAKC,aAIA,CACXC,iBAAQC,SACAC,MAAQ,IAAIC,kBAAS,wBACzBD,MAAME,aACFC,WAAa,cAKRC,sBAAsBC,YAErBC,gBADoBC,SAASC,cAAc,2BACPA,cAAc,uCAErDF,iBAAsBD,QAAYA,QAAUF,aAC3CA,WAAaE,OACbC,gBAAgBG,eAAe,CAC3BC,SAAU,SACVC,MAAO,QACPC,OAAQ,gBAKhBC,SAAU,8BAAa,CACvBC,QAAS,CACLC,MAAO,SAEXC,QAAS,CACLC,SAAU,WACVC,OAAQ,SACRC,UAAW,YACXC,YAAa,cACbC,SAAU,WACVC,QAAS,WAEbC,WAAY,CACRC,UAAW,uBACXC,WAAY,wBACZC,eAAgB,oBAChBC,eAAgB,oBAChBV,SAAU,WACVW,gBAAiB,kBACjBC,gBAAiB,kBACjBC,wBAAyB,0BACzBC,wBAAyB,0BACzBC,0BAA2B,4BAC3BC,qBAAsB,uBACtBC,uBAAwB,0BAG5BC,MAAO,CACHC,YAAa,cACbC,WAAY,aACZC,WAAY,aACZC,UAAW,YACXC,iBAAkB,oBAEtBC,OAAQ,CACJC,sBAAuB,wBACvBC,kBAAmB,oBACnBC,mBAAoB,qBACpBC,oBAAqB,sBACrBC,qBAAsB,uBACtBC,gBAAiB,kBACjBC,qBAAsB,uBACtBC,cAAe,gBACfC,kBAAmB,oBACnBC,qBAAsB,uBACtBC,oBAAqB,sBACrBC,cAAe,iBAEnBC,cAAe,CACXC,kBAAmB,oBACnBC,cAAe,gBACfN,kBAAmB,oBACnBC,qBAAsB,uBACtBC,oBAAqB,sBACrBK,cAAe,gBACfC,cAAe,gBACfL,cAAe,4BAgBdM,UAAUC,eACJA,KAAKC,aAAeD,KAAKE,cAAgBF,KAAKG,iBAAiBC,YAIxEC,aAAe,IAAIlE,IAEzBA,IAAImE,UAAU,oBAAoB,CAC9BC,MAAO,CACHC,MAAO,CACHC,KAAMC,QAEVC,IAAK,CACDF,KAAMC,OACNE,QAAS,KAEbC,IAAK,CACDJ,KAAMC,OACNE,QAAS,GAEbE,OAAQ,CACJL,KAAMC,OACNE,QAAS,IAEbG,UAAW,CACPN,KAAMC,OACNE,QAAS,IAEbI,MAAO,CACHP,KAAMQ,OACNL,QAAS,IAEbM,KAAM,CACFT,KAAMQ,SAIdE,sBACW,CACHC,kBAAmB,OAG3BC,SAAU,CACNC,wBACWC,KAAKZ,IAAMY,KAAKV,KAE3BW,2BACOD,KAAKZ,IAAMY,KAAKV,KAAO,EACf,GAGCU,KAAKf,MAAQe,KAAKV,MAAMU,KAAKZ,IAAMY,KAAKV,MAGxDY,yBACW,GAAM,GAAGF,KAAKT,QAEzBY,uBACQF,SAAW,EACTG,EAAI,GAAM,GAAGJ,KAAKT,OACrBS,KAAKZ,IAAMY,KAAKV,KAAO,IACtBW,UAAYD,KAAKf,MAAQe,KAAKV,MAAMU,KAAKZ,IAAMY,KAAKV,UAGlDe,EAAe,EAAXJ,SAAazF,SAChB,sBAAW,CAAC,GAAG,IAAI,CAAC4F,EAAEA,GAAG,CAAC,EAAEC,GAAI,IAAI7F,KAGnD8F,QAAS,GAETC,8tCAuBJ3F,IAAImE,UAAU,WAAY,CACtBC,MAAO,CACHC,MAAO,CACHC,KAAMsB,OAEVC,UAAW,CACPvB,KAAMwB,QACNrB,SAAS,GAEbsB,YAAa,CACTzB,KAAMwB,QACNrB,SAAS,IAGjBO,sBACW,CACHC,kBAAmB,OAG3BC,SAAU,CACNc,qCACOZ,KAAKH,kBACGG,KAAKH,kBACNG,KAAKf,OAASe,KAAKf,MAAMJ,OAAS,EACjCmB,KAAKf,MAAM,GAEX,OAInBqB,QAAS,GAETC,6wBAiBJ3F,IAAImE,UAAU,cAAe,CACzBC,MAAO,CACHC,MAAO,CACHC,KAAM2B,QAEVJ,UAAW,CACPvB,KAAMwB,QACNrB,SAAS,GAEbsB,YAAa,CACTzB,KAAMwB,QACNrB,SAAS,IAGjBO,sBACW,IAGXE,SAAU,CACNgB,0BACW,EAAwB,EAApBd,KAAKe,KAAKC,SAEzBC,qCAEQC,EAAI,uDACAC,EAAE,EAAGA,EAAEnB,KAAKe,KAAKC,QAAQG,IAC7BD,GAAI,sEAEDA,EAAE,KAEbH,uBAEWf,KAAKf,MAAMmC,MAAM,KAGhCd,QAAS,CACLe,yBAAgBC,cACRC,UAAY,EACRJ,EAAI,EAAGA,GAAKnB,KAAKe,KAAKC,QAASG,IAAI,CAC1BG,KAAKE,MAAML,OAEpB,IAAMM,MAAMH,KAAKE,MAAML,GAAGO,aAAa,KACjCC,KAAOL,KAAKE,MAAML,GAAGO,aAAaD,IACrCE,KAAKC,MAAQL,WACZA,SAAWI,KAAKC,WAGpB,IAAMH,OAAMH,KAAKE,MAAML,GAAGU,QAAQ,KAC5BF,MAAOL,KAAKE,MAAML,GAAGU,QAAQJ,KAChCE,MAAKC,MAAQL,WACZA,SAAWI,MAAKC,eAIpBL,UAAY,EAAIA,SAAS,EAAG,GAExCO,kBAASR,KAAKS,MAAOC,SAAU9C,cAGrB+C,YAAuB,YAAR/C,KACf8B,QAAUhB,KAAKe,KAAKC,QACtBkB,MAAO,EACHf,EAAI,EAAGA,EAAIH,QAASG,OACrBG,KAAKE,MAAMO,MAAMZ,IAAMG,KAAKE,MAAMO,MAAMZ,GAAGO,aAAa,KACjDS,KAAOb,KAAKE,MAAMO,MAAMZ,GAAGO,iBAC7B,IAAMD,MAAMU,KAAK,KACXR,KAAOQ,KAAKV,IACfE,KAAKC,OAASI,WACVC,YACId,EAAI,GAAMQ,KAAKS,KAAOjB,EAAK,IAC1Be,MAAO,GAGPP,KAAKS,KAAOjB,EAAM,IAClBe,MAAO,YAQxBA,OAGfG,mBACIpH,sBAAsB+E,KAAKf,MAAMqD,KAErCC,mBACItH,sBAAsB+E,KAAKf,MAAMqD,KAErC/B,spJA6EJ3F,IAAImE,UAAU,sBAAuB,CACjCC,MAAO,CACHC,MAAQ,CACJC,KAAM2B,OACNxB,QAAS,iBAAmB,KAEhCmD,OAAQ,CACJtD,KAAMC,OACNE,QAAS,IAGjBO,sBACW,CACH6C,aAAc,KAGtBC,mBAGQ5D,aAAa6D,IAAI,mBAAoB3C,KAAK4C,qBAElD9C,SAAU,GAGVQ,QAAS,CACLsC,4BAAmBC,OAAOC,QAAQC,cAI3B/C,KAAKgD,MAAMC,QAAUJ,QAAU7C,KAAKf,MAAMqD,GAAG,KACtCY,MAAQ9H,SAAS+H,+DACoBnD,KAAKf,MAAMqD,UAElDc,UAAY,EAChBF,MAAMG,SAAQ,SAACC,QAGLC,OADID,GAAGE,wBACID,OACjBH,WAAaG,cAGXE,sBAAeL,qBAChBJ,MAAMC,OAAOS,MAAMH,OAASE,eAI7ClD,mbAWJ3F,IAAImE,UAAU,mBAAoB,CAC9BC,MAAO,CACHC,MAAO,CACHC,KAAMsB,MACNnB,yBAAkB,KAEtBH,KAAO,CACHA,KAAMQ,OACNL,QAAS,YAEbsE,UAAY,CACRzE,KAAMC,OACNE,QAAS,GAEbiC,KAAO,CACHpC,KAAM2B,OACNxB,0BAAkB,OAEtBuC,MAAQ,CACJ1C,KAAMC,QAEVyE,KAAM,CACF1E,KAAM2B,OACNxB,0BAAkB,OAEtB0B,KAAM,CACF7B,KAAM2B,OACNxB,0BAAkB,OAEtBoB,UAAW,CACPvB,KAAMwB,QACNrB,SAAS,GAEbsB,YAAa,CACTzB,KAAMwB,QACNrB,SAAS,GAEbwE,OAAQ,CACJ3E,KAAM2B,OACNxB,0BAAkB,QAG1BgD,uBACUyB,KAAK9D,KACK,YAAb8D,KAAK5E,MAAwC,GAAlB4E,KAAKH,YAC/BG,KAAKC,eAAiB,IAAIC,gBAAe,cAClCF,KAAKd,MAAMiB,YAAY,KAChBV,OAASO,KAAKd,MAAMiB,YAAYT,wBAAwBD,OAC9DzE,aAAaoF,MAAM,mBAAoBJ,KAAKxC,KAAKgB,GAAIwB,KAAKlC,MAAO2B,YAEtEY,QAAQL,KAAKd,MAAMiB,eAG9BnE,SAAU,CACN6B,oBACQ,IAAMF,MAAMzB,KAAKf,MAAM,KACjBmF,IAAMpE,KAAKf,MAAMwC,OACpB2C,IAAIxC,OAAS5B,KAAK4B,aACVwC,WAGR,MAEXC,sBACQrE,KAAK6D,QAAU7D,KAAK6D,OAAOS,WAAatE,KAAK6D,OAAOU,QAAQ,KACtDC,IAAM,IAAIC,KACVC,OAAS,IAAID,KAAKzE,KAAK6D,OAAOS,WAC9BK,KAAO,IAAIF,KAAKzE,KAAK6D,OAAOU,gBAC1BC,KAAOE,QAAUF,IAAMG,YAGxB,GAGfC,sBACO5E,KAAK2B,MAAQ3B,KAAK2B,KAAKS,KAAO,EAAE,KACzBA,KAAQ,EAAIpC,KAAK2B,KAAKS,KAAQ,iDACKA,gBAElC,KAInBxC,sBACW,IAGXU,QAAS,GAGTC,gtBAmBJ3F,IAAImE,UAAU,SAAU,CACpBC,MAAO,CACHC,MAAO,CACHC,KAAM2B,OACNxB,QAAS,kBAAmB,OAEhCuE,KAAM,CACF1E,KAAM2B,OACNxB,0BAAkB,OAEtBoB,UAAW,CACPvB,KAAMwB,QACNrB,SAAS,GAEbsB,YAAa,CACTzB,KAAMwB,QACNrB,SAAS,IAGjBO,sBACW,CACHiF,MAAO,KAGfvE,QAAS,CACLwE,wBACO9E,KAAKW,kBACG,qBAGAX,KAAKf,MAAM7C,0BAEH,kBACN,eACM,oBACN,iBACM,qBACN,kBACM,qBACN,aACM,kBACN,kBACM,gBAIvB2I,oBAAWC,UACHF,UAAY9E,KAAK8E,YAGjBG,SAAWjF,KAAK6E,MAAMG,KAAKE,OAC5BD,SACIA,SAAS3D,OACL2D,SAASE,SACRF,SAASE,QAAQC,WAAWC,YAAYJ,SAASE,SACjDF,SAASE,aAAUG,GAEnBL,SAAS3D,KAAKiE,SAElBN,SAAS3D,UAAOgE,IAGpBL,SAAW,QACNJ,MAAMG,KAAKE,OAASD,cAIzBO,MAAQpK,SAASqK,eAAe,aAAaT,KAAKU,SAClDC,IAAKvK,SAASqK,eAAe,aAAaT,KAAKE,UACtC,OAAVM,OAA0B,OAARG,KAAgBnH,UAAUgH,QAAUhH,UAAUmH,KAAK,CACpEV,SAAS3D,KAAO,IAAIsE,uBAAWJ,MAAMG,IAAI,CACrCE,MAAOf,UACPgB,QAAS,CACLN,MAtoBX,IAuoBWG,IAvoBX,WA2oBOI,WAAc/F,KAAK4D,KAAKtB,IAAK,EAAGlH,SAASqK,eAAe,yBAAyBzF,KAAK4D,KAAKtB,IAAI,QACjF,OAAfyD,WAAoB,KACfC,QAAU5K,SAASC,cAAc,kCACrC0K,WAAWE,YAAYD,SACvBf,SAASE,QAAUa,WAI/BE,2BACQ,IAAI/E,KAAKnB,KAAKf,MAAMkH,YAAYC,IAAI,KAChCpB,KAAOhF,KAAKf,MAAMkH,YAAYC,IAAIjF,QACjC4D,WAAWC,QAGxBqB,+BACSH,gBAGbpG,SAAU,CACNwG,oCACa,CAAC,UAAWC,SAASvG,KAAKf,MAAMC,OAE7CsH,mCACa,CAAC,SAAUD,SAASvG,KAAKf,MAAMC,OAE5CuH,4BACW,CAAC,QAAQ,WAAW,UAAUF,SAASvG,KAAKf,MAAMC,QAGjEwD,qBAGAL,uCAGS6D,cACLQ,YAAW,WACPC,MAAKT,gBACP,IAGFU,OAAOC,iBAAiB,SAAS7G,KAAKqG,iBAE1CS,6BACQ,IAAI3F,KAAKnB,KAAKf,MAAMkH,YAAYC,IAAI,KAChCpB,KAAOhF,KAAKf,MAAMkH,YAAYC,IAAIjF,GAClC8D,SAAWjF,KAAK6E,MAAMG,KAAKE,OAC5BD,UACIA,SAAS3D,OACL2D,SAASE,SACRF,SAASE,QAAQC,WAAWC,YAAYJ,SAASE,SACjDF,SAASE,aAAUG,GAEnBL,SAAS3D,KAAKiE,SAElBN,SAAS3D,UAAOgE,GAK5BsB,OAAOG,oBAAoB,SAAS/G,KAAKqG,iBAE7CW,0BAEAzE,mBACQvC,KAAKiH,YACAf,eAGb3F,ojDAsBJ3F,IAAImE,UAAU,iBAAkB,CAC5BC,MAAO,OACM,CACLE,KAAM2B,OACNxB,QAAS,kBAAmB,QAGpCO,sBACW,CACHsH,KAAMxL,QAAQC,UAGtB2E,QAAS,GAETC,sjBAiBJ3F,IAAImE,UAAU,gBAAiB,CAC3BC,MAAO,CACHC,MAAO,CACHC,KAAM2B,OACNxB,0BAAkB,OAEtBoB,UAAW,CACPvB,KAAMwB,QACNrB,0BAAkB,IAEtBsB,YAAa,CACTzB,KAAMwB,QACNrB,0BAAkB,IAEtBuE,KAAM,CACF1E,KAAM2B,OACNxB,0BAAkB,QAG1BO,sBACW,CACHsH,KAAMxL,QAAQ4B,SAGtBwC,SAAU,CACNwE,4BACW,6BAAYtE,KAAKf,MAAM3B,OAAOgH,YAEzCC,0BACOvE,KAAKf,MAAM3B,OAAOiH,SACV,6BAAYvE,KAAKf,MAAM3B,OAAOiH,SAG9BvE,KAAKkH,KAAKC,YAI7BzE,uBACUoB,KAAO9D,KAEToH,WAAa,OACb,IAAMC,OAAQrH,KAAKkH,KACnBE,WAAWE,KAAK,CAAED,IAAKA,IAAKtI,UAAW,6CAE/BqI,YAAYG,MAAK,SAAS7L,aAC9ByF,EAAI,MACJ,IAAMkG,QAAQvD,KAAKoD,KACnBpD,KAAKoD,KAAKG,MAAO3L,QAAQyF,GACzBA,QAIZb,QAAS,CACLkH,yBAAgBpL,mBACLA,0BAEQ,eACN,gBACM,sBACN,eACM,mBACN,iBACM,yBACN,gBAEA,WAEA,kBACM,iBAGnBqL,qBAAYrL,mBACDA,2BAEQ,SACN,eACM,YACN,iBACM,kBACN,gBAEA,WAEA,kBACM,WAIvBmE,03LAiGJ3F,IAAImE,UAAU,uBAAuB,CACjCC,MAAO,CACHC,MAAQ,CACJC,KAAM2B,OACNxB,QAAS,iBAAmB,KAEhCoB,UAAW,CACPvB,KAAMwB,QACNrB,SAAS,IAGjBO,sBACW,CACHsH,KAAMxL,QAAQ4B,SAGtBwC,SAAU,CACN4H,iCACQC,QAAS,MACT,IAAMlG,MAAMzB,KAAKf,MAAM3B,OAAOsK,OAAO,IAC3B5H,KAAKf,MAAM3B,OAAOsK,OAAOnG,IAC9BiG,kBAAkB,CACnBC,QAAS,gBAIVA,QAEXE,sCACO7H,KAAK4D,OAAQ5D,KAAK4D,KAAKkE,uBAAqExC,IAAjDtF,KAAK4D,KAAKkE,iBAAiBD,oBAC9D7H,KAAK4D,KAAKkE,iBAAiBD,oBAO9CvH,QAAS,CACLkH,yBAAgBpL,mBACLA,0BAEQ,eACN,gBACM,sBACN,eACM,mBACN,iBACM,yBACN,gBAEA,WAEA,kBACM,kBAIvBmE,mlEAwCJ3F,IAAImE,UAAU,2BAA2B,CACrCC,MAAO,CACHC,MAAQ,CACJC,KAAM2B,OACNxB,QAAS,iBAAmB,KAEhCoB,UAAW,CACPvB,KAAMwB,QACNrB,SAAS,GAEb/B,OAAQ,CACJ4B,KAAM2B,OACNxB,QAAS,iBAAmB,MAGpCO,sBACW,CACHsH,KAAM,CACF3J,sBAAuB,wBACvBC,kBAAmB,oBACnBC,mBAAoB,qBACpBC,oBAAqB,sBACrBC,qBAAsB,uBACtBC,gBAAiB,kBACjBC,qBAAsB,uBACtBC,cAAe,gBACfC,kBAAmB,oBACnBC,qBAAsB,uBACtBC,oBAAqB,sBACrBC,cAAe,mBAI3BwE,uBACUoB,KAAO9D,KAEToH,WAAa,OACb,IAAMC,OAAQrH,KAAKkH,KACnBE,WAAWE,KAAK,CAAED,IAAKA,IAAKtI,UAAW,6CAE/BqI,YAAYG,MAAK,SAAS7L,aAC9ByF,EAAI,MACJ,IAAMkG,SAAQvD,KAAKoD,KACnBpD,KAAKoD,KAAKG,OAAO3L,QAAQyF,GACzBA,QAIZrB,SAAU,GAEVQ,QAAS,CACLkH,yBAAgBpL,mBACLA,gBACE,iBACM,yBACN,eAEA,sBACM,mBACN,sBACM,6BAEA,aAInB2L,wBAAeC,eACJA,OAAO5L,WAAW,YAAY,eAG7CmE,85FAqDJ3F,IAAImE,UAAU,uBAAwB,CAClCC,MAAO,CACHC,MAAO,CACHC,KAAM2B,OACNxB,0BAAkB,OAEtBoB,UAAW,CACPvB,KAAMwB,QACNrB,0BAAkB,IAEtBsB,YAAa,CACTzB,KAAMwB,QACNrB,0BAAkB,IAEtBuE,KAAM,CACF1E,KAAM2B,OACNxB,0BAAkB,QAG1BO,sBACW,CACHsH,KAAMxL,QAAQyC,cACd8J,IAAK,CACDpM,QAASH,QAAQG,WAI7BiE,SAAU,CACNoI,wCACWlI,KAAKmI,wBAEhBC,sCACWpI,KAAKqI,uBAAuBrI,KAAKmI,yBAE5CG,kCACWtI,KAAKf,MAAM3B,OAAOsK,OAAOW,QAAO,SAAAC,UAAKA,EAAEC,aAElDZ,sCACO7H,KAAK4D,OAAQ5D,KAAK4D,KAAKkE,uBAAqExC,IAAjDtF,KAAK4D,KAAKkE,iBAAiBD,oBAC9D7H,KAAK4D,KAAKkE,iBAAiBD,mBAM1Ca,6BACQC,aAAc,SACf3I,KAAKf,MAAM3B,OAAOlB,WACd4D,KAAKf,MAAM3B,OAAOlB,WAAWwM,WAAW/J,OAAS,IAChD8J,aAAc,GAEX3I,KAAKf,MAAM3B,OAAOsK,QACtB5H,KAAKf,MAAM3B,OAAOsK,OAAO/I,OAAS,IACjC8J,aAAc,GAIfA,aAEXE,+BACUC,OAAS,CACXC,SAAU,EACV1M,UAAW,EACXE,eAAgB,EAChBC,eAAgB,EAChBV,SAAU,MAGXkE,KAAKf,MAAM3B,OAAOlB,WAAW,gDACV4D,KAAKf,MAAM3B,OAAOlB,WAAWwM,+DAAW,8DAChC1F,6DAAM,KAAlBkB,iBACHA,IAAI4E,WACHF,OAAOC,UAAY3E,IAAI4E,SAASD,SAChCD,OAAOzM,WAAa+H,IAAI4E,SAAS3M,UACjCyM,OAAOvM,gBAAkB6H,IAAI4E,SAASzM,eACtCuM,OAAOtM,gBAAkB4H,IAAI4E,SAASxM,eACtCsM,OAAOhN,UAAYsI,IAAI4E,SAAS3M,0HAKzC,GAAI2D,KAAKf,MAAM3B,OAAOsK,OAAO,kDAChB5H,KAAKf,MAAM3B,OAAOsK,8DAAO,KAA9BY,eACJA,EAAE3M,UACDiN,OAAOC,UAAYP,EAAE3M,QAAQkN,SAC7BD,OAAOzM,WAAamM,EAAE3M,QAAQQ,UAC9ByM,OAAOvM,gBAAkBiM,EAAE3M,QAAQU,eACnCuM,OAAOtM,gBAAkBgM,EAAE3M,QAAQW,eACnCsM,OAAOhN,UAAY0M,EAAE3M,QAAQC,uEAKlCgN,QAEXxE,4BACW,6BAAYtE,KAAKf,MAAM3B,OAAOgH,YAEzCC,0BACOvE,KAAKf,MAAM3B,OAAOiH,SACV,6BAAYvE,KAAKf,MAAM3B,OAAOiH,SAG9BvE,KAAKkH,KAAKC,YAI7BzE,uBACUoB,KAAO9D,KAEToH,WAAa,OACb,IAAMC,OAAQrH,KAAKkH,KACnBE,WAAWE,KAAK,CAAED,IAAKA,IAAKtI,UAAW,6CAE/BqI,YAAYG,MAAK,SAAS7L,aAC9ByF,EAAI,MACJ,IAAMkG,SAAQvD,KAAKoD,KACnBpD,KAAKoD,KAAKG,OAAO3L,QAAQyF,GACzBA,QAIZb,QAAS,CACL6H,oCACQrM,SAAW,EACXK,QAAU,EACVJ,OAAS,EACTC,UAAY,EACV4L,OAAS5H,KAAKsI,oBAEhB9H,MAAMyI,QAAQrB,SAAqB,GAAVA,aAClB,eAGP,IAAMnG,MAAMmG,OAAO,KACbsB,MAAQtB,OAAOnG,IAClByH,MAAMrN,QACFsD,OAAO+J,MAAMrN,QAAQC,UAAY,EAChCA,WAEIqD,OAAO+J,MAAMrN,QAAQE,QAAU,IAChCoD,OAAO+J,MAAMrN,QAAQE,SAAWoD,OAAO+J,MAAMrN,QAAQkN,UACpD/M,YAEAD,UAIRI,SAAU,SAIfL,SAAW,EACH,WACDK,QACC,UACDJ,OACC,SACDC,UACC,YAEA,eAGfqM,gCAAuBc,qBACZA,4BAEQ,eACN,iBACM,yBACN,gBACM,wBACN,aAEA,kBACM,YACN,oBACM,kBAIvB5I,s+HAyER3F,IAAImE,UAAU,6BAA8B,CACxCC,MAAO,CACHC,MAAQ,CACJC,KAAM2B,OACNxB,QAAS,iBAAmB,KAEhCwI,kBAAmB,CACf3I,KAAMwB,QACNrB,0BAAkB,QAG1BO,sBACW,IAGXE,SAAU,GAEVQ,QAAS,GAGTC,8kGAyDJ3F,IAAImE,UAAU,uBAAuB,CACjCC,MAAO,CACHC,MAAQ,CACJC,KAAM2B,OACNxB,QAAS,iBAAmB,KAEhCwI,kBAAmB,CACf3I,KAAMwB,QACNrB,SAAS,IAGjBO,sBACW,CACHsH,KAAMxL,QAAQyC,cACd8J,IAAK,CACDpM,QAASH,QAAQG,WAI7BiE,SAAU,CACN4H,iCACQC,QAAS,MACT,IAAMlG,MAAMzB,KAAKf,MAAM2I,OAAO,IACpB5H,KAAKf,MAAM2I,OAAOnG,IACvBiG,kBAAkB,CACnBC,QAAS,gBAIVA,QAEXW,kCACWtI,KAAKf,MAAM2I,OAAOW,QAAO,SAAAC,UAAKA,EAAEC,cAG/CnI,QAAS,CACL+H,gCAAuBc,qBACZA,4BAEQ,eACN,iBACM,yBACN,gBACM,wBACN,aAEA,kBACM,YACN,oBACM,iBAGnBC,sBAAaF,cACFlJ,KAAKqI,uBAAuBrI,KAAKqJ,kBAAkBH,SAE9DG,2BAAkBH,cACdrO,MAAMyO,KAAK,UAAWJ,MAAMK,MAC5B1O,MAAMyO,KAAKJ,MAAMrN,SACdqN,MAAMrN,SACLhB,MAAMyO,KAAK,QACRJ,MAAMrN,QAAQC,SACN,WAEHoN,MAAMrN,QAAQU,gBAAkB2M,MAAMrN,QAAQQ,WAAa6M,MAAMrN,QAAQW,eAC1E2C,OAAO+J,MAAMrN,QAAQQ,WAAa8C,OAAO+J,MAAMrN,QAAQU,gBACpD4C,OAAO+J,MAAMrN,QAAQW,iBACnB2C,OAAO+J,MAAMrN,QAAQkN,UAClB,YAGA,SAIJ,eAGJ,WAGfS,wBAAeC,SAASjB,kBACf,CAAC,CACFkB,WAAY,oCACZC,KAAM,UAAcnB,EAAElG,WACHtC,KAAKf,MAAMqD,WACXmH,kBACCjB,EAAEoB,aAEtB,GAAGC,KAAKC,sBAAaC,YAE7BC,yBAAgBP,SAASjB,kBAChB,CAAC,CACFkB,WAAY,oCACZC,KAAM,UAAcnB,EAAElG,WACHtC,KAAKf,MAAMqD,WACXkG,EAAEC,kBACDgB,aAEpB,GAAGI,KAAKC,sBAAaC,aAGjCxJ,2jDAkCJ3F,IAAImE,UAAU,2BAA2B,CACrCC,MAAO,CACHC,MAAQ,CACJC,KAAM2B,OACNxB,QAAS,iBAAmB,KAEhCoB,UAAW,CACPvB,KAAMwB,QACNrB,SAAS,GAEb/B,OAAQ,CACJ4B,KAAM2B,OACNxB,QAAS,iBAAmB,MAGpCO,sBACW,CACHsH,KAAMxL,QAAQU,aAGtBsG,uBACUoB,KAAO9D,KAEToH,WAAa,OACb,IAAMC,OAAQrH,KAAKkH,KACnBE,WAAWE,KAAK,CAAED,IAAKA,IAAKtI,UAAW,6CAE/BqI,YAAYG,MAAK,SAAS7L,aAC9ByF,EAAI,MACJ,IAAMkG,SAAQvD,KAAKoD,KACnBpD,KAAKoD,KAAKG,OAAO3L,QAAQyF,GACzBA,QAIZrB,SAAU,CACNmK,4CACcC,gBAAOC,uDAA8CnK,KAAK1C,OAAOgF,MAGnFhC,QAAS,CACL8J,6BACOpK,KAAKf,MAAM2J,WAAY,kDACF5I,KAAKf,MAAM2J,kEAAW,KAAhCZ,uBACHA,OAAO9E,OAAS8E,OAAO9E,MAAMrE,OAAS,SAC9B,+DAIZ,IAGf0B,w6DAyCA3F,IAAImE,UAAU,gBAAgB,CAC1BC,MAAO,CACHC,MAAQ,CACJC,KAAM2B,OACNxB,QAAS,iBAAmB,KAEhCgL,MAAO,CACHnL,KAAMC,OACNE,QAAS,KAEbkE,OAAQ,CACJrE,KAAMC,OACNE,QAAS,KAGjBO,sBACW,CACHsH,KAAMxL,QAAQG,UAGtBiE,SAAU,CACNwK,oCACWtK,KAAKqK,MAAQrK,KAAKuK,wBAE7BC,+BACWxK,KAAKqK,MAAQrK,KAAKyK,mBAE7BC,iCACW1K,KAAKqK,MAAQrK,KAAK2K,qBAE7BC,oCACY5K,KAAKf,MAAM8J,SAAW/I,KAAKf,MAAMlD,OAASiE,KAAKf,MAAMnD,WAGrEwE,QAAS,CACLiK,uCACOvK,KAAKf,MAAM8J,SAAW,EACd,GAAM/I,KAAKf,MAAMlD,OAASiE,KAAKf,MAAMnD,UAAYkE,KAAKf,MAAM8J,SAE5D,GAGf0B,kCACOzK,KAAKf,MAAM8J,SAAW,EACd/I,KAAKf,MAAMlD,OAASiE,KAAKf,MAAM8J,SAE/B,GAGf4B,oCACO3K,KAAKf,MAAM8J,SAAW,EACd/I,KAAKf,MAAMnD,SAAWkE,KAAKf,MAAM8J,SAEjC,IAInBxI,o/BAkBJ3F,IAAImE,UAAU,mBAAmB,CAC7BC,MAAO,CACHC,MAAQ,CACJC,KAAM2B,OACNxB,QAAS,iBAAmB,CACxB0J,SAAU,EACV1M,UAAW,EACXE,eAAgB,EAChBC,eAAgB,EAChBV,SAAU,KAGlBuO,MAAO,CACHnL,KAAMC,OACNE,QAAS,KAEbkE,OAAQ,CACJrE,KAAMC,OACNE,QAAS,KAGjBO,sBACW,CACHsH,KAAMxL,QAAQU,aAGtB0D,SAAU,CACN+K,mCACW7K,KAAKqK,MAAQrK,KAAK8K,uBAE7BC,kCACW/K,KAAKqK,MAAQrK,KAAKgL,sBAE7BC,uCACWjL,KAAKqK,MAAQrK,KAAKkL,2BAE7BC,uCACWnL,KAAKqK,MAAQrK,KAAKoL,2BAE7BV,iCACW1K,KAAKqK,MAAQrK,KAAK2K,qBAE7BU,mCACYrL,KAAKf,MAAM8J,SAAW/I,KAAKf,MAAM5C,UAAY2D,KAAKf,MAAM1C,eACrDyD,KAAKf,MAAMzC,eAAiBwD,KAAKf,MAAMnD,WAG1DwE,QAAS,CACLwK,sCACO9K,KAAKf,MAAM8J,SAAW,EACd,GACF/I,KAAKf,MAAM5C,UAAY2D,KAAKf,MAAM1C,eAClCyD,KAAKf,MAAMzC,eAAiBwD,KAAKf,MAAMnD,UAAYkE,KAAKf,MAAM8J,SAE5D,GAGfiC,qCACOhL,KAAKf,MAAM8J,SAAW,EACd/I,KAAKf,MAAM5C,UAAY2D,KAAKf,MAAM8J,SAElC,GAGfmC,0CACOlL,KAAKf,MAAM8J,SAAW,EACd/I,KAAKf,MAAM1C,eAAiByD,KAAKf,MAAM8J,SAEvC,GAGfqC,0CACOpL,KAAKf,MAAM8J,SAAW,EACd/I,KAAKf,MAAMzC,eAAiBwD,KAAKf,MAAM8J,SAEvC,GAGf4B,oCACO3K,KAAKf,MAAM8J,SAAW,EACd/I,KAAKf,MAAMnD,SAAWkE,KAAKf,MAAM8J,SAEjC,IAInBxI,4oDA0BJ3F,IAAImE,UAAU,sBAAsB,CAChCC,MAAO,CACHC,MAAQ,CACJC,KAAM2B,OACNxB,QAAS,iBAAmB,CACxB0J,SAAU,GACV1M,UAAW,EACXE,eAAgB,EAChBC,eAAgB,EAChBV,SAAU,KAGlByD,OAAQ,CACJL,KAAMC,OACNE,QAAS,IAEbiM,SAAU,CACNpM,KAAMwB,QACNrB,SAAS,GAEbI,MAAO,CACHP,KAAMQ,OACNL,QAAS,KAGjBS,SAAU,CACNI,yBACW,GAAM,GAAGF,KAAKT,QAGzBgM,mCAEWvL,KAAKG,QADE,EACYH,KAAK2K,sBAEnCa,iCACUC,MAAQzL,KAAK2K,2BACZ3K,KAAKG,QAAQsL,MAAMzL,KAAKgL,uBAEnCU,sCACUD,MAAQzL,KAAK2K,oBACL3K,KAAKgL,4BACZhL,KAAKG,QAAQsL,MAAMzL,KAAKkL,4BAEnCS,sCACUF,MAAQzL,KAAK2K,oBACL3K,KAAKgL,qBACLhL,KAAKkL,iCACZlL,KAAKG,QAAQsL,MAAMzL,KAAKoL,4BAEnCQ,kCACUH,MAAQzL,KAAK2K,oBACL3K,KAAKgL,qBACLhL,KAAKkL,0BACLlL,KAAKoL,iCACZpL,KAAKG,QAAQsL,MAAMzL,KAAK8K,yBAIvCxK,QAAS,CACLH,iBAAQqF,MAAOG,SACLvF,EAAI,GAAM,GAAGJ,KAAKT,OAElBsM,GAAc,EAARrG,MAAUhL,EAChB6F,EAAU,EAANsF,IAAQnL,SACX,sBAAW,CAAC,GAAG,IAAI,CAAC4F,EAAEA,GAAG,CAACyL,GAAGxL,GAAI,IAAI7F,IAEhDsQ,sCACO9K,KAAKf,MAAM8J,SAAW,EACd,GACF/I,KAAKf,MAAM5C,UAAY2D,KAAKf,MAAM1C,eAC/ByD,KAAKf,MAAMzC,eAAiBwD,KAAKf,MAAMnD,UAAYkE,KAAKf,MAAM8J,SAE/D,GAGfiC,qCACOhL,KAAKf,MAAM8J,SAAW,EACd/I,KAAKf,MAAM5C,UAAY2D,KAAKf,MAAM8J,SAElC,GAGfmC,0CACOlL,KAAKf,MAAM8J,SAAW,EACd/I,KAAKf,MAAM1C,eAAiByD,KAAKf,MAAM8J,SAEvC,GAGfqC,0CACOpL,KAAKf,MAAM8J,SAAW,EACd/I,KAAKf,MAAMzC,eAAiBwD,KAAKf,MAAM8J,SAEvC,GAGf4B,oCACO3K,KAAKf,MAAM8J,SAAW,EACd/I,KAAKf,MAAMnD,SAAWkE,KAAKf,MAAM8J,SAEjC,IAInBxI,6tCAuBJ3F,IAAImE,UAAU,kBAAkB,CAC5BC,MAAO,CACHC,MAAQ,CACJC,KAAM2B,OACNxB,QAAS,iBAAmB,KAEhCoB,UAAW,CACPvB,KAAMwB,QACNrB,SAAS,GAEbsB,YAAa,CACTzB,KAAMwB,QACNrB,SAAS,IAGjBO,sBACW,IAGXE,SAAU,CACN1D,6BACO4D,KAAKf,MAAM7C,WACH4D,KAAKf,MAAM7C,WAEX,eAInBkE,QAAS,GAGTC,2dAUJ3F,IAAImE,UAAU,gBAAgB,CAC1BC,MAAO,CACHC,MAAQ,CACJC,KAAM2B,OACNxB,QAAS,iBAAmB,KAEhCoB,UAAW,CACPvB,KAAMwB,QACNrB,SAAS,GAEbsB,YAAa,CACTzB,KAAMwB,QACNrB,SAAS,IAGjBO,sBACW,IAGXE,SAAU,CACN1D,6BACO4D,KAAKf,MAAM7C,WACH4D,KAAKf,MAAM7C,WAEX,eAInBkE,QAAS,GAETC,2LAOJ3F,IAAImE,UAAU,eAAe,CACzBC,MAAO,CACHC,MAAQ,CACJC,KAAM2B,OACNxB,QAAS,iBAAmB,KAEhCoB,UAAW,CACPvB,KAAMwB,QACNrB,SAAS,GAEbsB,YAAa,CACTzB,KAAMwB,QACNrB,SAAS,IAGjBO,sBACW,IAGXE,SAAU,CACN1D,6BACO4D,KAAKf,MAAM7C,WACH4D,KAAKf,MAAM7C,WAEX,eAInBsG,qBAGApC,QAAS,GAETC,qLAOJ3F,IAAImE,UAAU,eAAe,CACzBC,MAAO,CACHC,MAAQ,CACJC,KAAM2B,OACNxB,QAAS,iBAAmB,KAEhCoB,UAAW,CACPvB,KAAMwB,QACNrB,SAAS,GAEbsB,YAAa,CACTzB,KAAMwB,QACNrB,SAAS,IAGjBO,sBACW,CACHqI,IAAKvM,UAGboE,SAAU,CACN1D,6BACW4D,KAAKf,MAAMjC,MAAM8O,OAAO,YAAY,cAE/CC,8BAIa,IAHF/L,KAAKf,MAAMjC,MAAM8O,OAIT,QAFA,YAKnBE,4BAEW,CACHjD,SAAW/I,KAAKf,MAAMjC,MAAMiP,aAAcjM,KAAKf,MAAMjC,MAAMiP,aAAa,EACxE5P,UAAY2D,KAAKf,MAAMjC,MAAMkP,YAAalM,KAAKf,MAAMjC,MAAMkP,YAAY,EACvE3P,eAAgB,EAChBC,eAAgB,EAChBV,SAAU,IAGlBqQ,6BACOnM,KAAKf,MAAMjC,MAAMiP,aAAa,KACvBhM,SAAWD,KAAKf,MAAMjC,MAAMkP,YAAYlM,KAAKf,MAAMjC,MAAMiP,oBACxDjM,KAAKG,QAAQ,EAAEF,gBAEf,KAKnBK,QAAS,CACLH,iBAAQqF,MAAOG,SAGLkG,GAAc,EAARrG,MAAUhL,EAChB6F,EAAU,EAANsF,IAAQnL,SACX,sBAAW,CAAC,GAAG,IAAI,CAJhB,OAIsB,CAACqR,GAAGxL,GAAI,IAAI7F,KAGpD+F"}