/*! otree-front v1.3.b microframework for interactive pages for oTree platform (C) qwiglydee@gmail.com https://github.com/qwiglydee/otree-front */ var ot=function(t){"use strict";function e(t){return Array.isArray(t)}function n(t){return null==t||Number.isNaN(t)}function a(t){return Object.prototype.toString.call(t).startsWith("[object HTML")}function i(t){var e=typeof t;return"string"===e||("number"===e||("boolean"===e||("symbol"===e||(null==t||(t instanceof Symbol||(t instanceof String||(t instanceof Number||t instanceof Boolean)))))))}function r(t){return"[object Object]"===Object.prototype.toString.call(t)}function o(t){var e,n;return!1!==r(t)&&(void 0===(e=t.constructor)||!1!==r(n=e.prototype)&&!1!==n.hasOwnProperty("isPrototypeOf"))}function s(t,n){return Array.from(t).every(((t,a)=>function(t,n){switch(n){case"data":return!0;case"array":return e(t);case"object":return r(t);default:return typeof t===n}}(t,n[a])))}function l(t,e){for(var n=arguments.length,a=new Array(n>2?n-2:0),i=2;it.length==e.length&&s(e,t))).length){const e=a.map((e=>"".concat(t,"(").concat(e.join(", "),")"))).join(" or ");throw new Error("Invalid arguments, expected: ".concat(e))}}function c(t){return 2==t.length?{match:t[0],handler:t[1]}:{match:void 0,handler:t[0]}}const u=/^[a-zA-Z]\w+(\.\w+)*$/;function m(t,e){return e.endsWith(".*")&&(e=e.slice(0,-2)),e.split(".").reduce(((t,e)=>t&&e in t?t[e]:void 0),t)}var d=Object.freeze({__proto__:null,extract:m,length:function(t){return t.split(".").length},update:function(t,e,n){const a=e.split("."),i=a.slice(0,-1),r=a.slice(-1)[0];let o=i.length?function(t,e){return e.reduce(((t,e)=>t&&e in t?t[e]:void 0),t)}(t,i):t;if(void 0===o)throw new Error("Unreachable keypath ".concat(e));o[r]=n},upsert:function(t,e,n){const a=e.split("."),i=a.slice(0,-1),r=a.slice(-1)[0];let o=i.length?function(t,e){return e.reduce(((t,e)=>t&&e in t?t[e]:void 0),t)}(t,i):t;if(void 0===o)throw new Error("Unreachable keypath ".concat(e));o[r]=n},validate:function(t){return t.match(u)}});const h={string:/^.*$/,number:/^-?\d*(\.\d+)?$/,boolean:/^(true|false)$/,name:/^[a-zA-Z]\w+$/,variable:/^vars.[a-zA-Z]\w+(\.\w+)*(\.\*)?$/};function p(t,e){if(!(t in h))throw new Error("Unknown parameter type: ".concat(t));return e.match(h[t])}function f(t,e,n){if(!p(e,n))throw new Error("Invalid parameter '".concat(t,"'; expected: ").concat(e));switch(e){case"number":return Number(n);case"boolean":return"true"===n;case"variable":return n.slice(5);default:return n}}function v(t,e,n){void 0===e.type||e.type in h||Error("Unrecognized parameter type '".concat(e.type,"'"));let a=e.attr?n[e.attr]:n[t];if("flag"==e.type){if(""!=a&&null!=a)throw new Error("Invalid parameter '".concat(t,"'; expected: flag with no value"));return{val:t in n,type:"flag"}}if(void 0===a){if(!e.optional)throw new Error("Missing parameter '".concat(t,"'"));return{val:e.default,type:e.type}}if(p("variable",a)){if(!1===e.variable)throw new Error("Invalid parameter '".concat(t,"'; expected: value"));return{var:a.slice(5),type:e.type,val:e.default}}if(!0===e.variable)throw new Error("Invalid parameter '".concat(t,"'; expected: variable"));return void 0!==e.type?{val:f(t,e.type,a),type:e.type}:{val:a,type:void 0}}function g(t,e,n,a){if(void 0===e.var||!n.affect(e.var))return;let i=m(a,e.var);if(void 0===i)return null;if(e.type&&typeof i!=e.type)throw new Error("Invalid value of 'vars.".concat(e.var,"' for parameter '").concat(t,"'; expected: ").concat(e.type));return i}function w(t){return i(t)||r(t)||e(t)||a(t)}function y(t){let a=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";return function*(){if(""!=a&&w(t)&&(yield[a,n(t)?null:t]),o(i=t)||e(i))for(let[e,n]of Object.entries(t))w(n)&&(yield*y(n,a?"".concat(a,".").concat(e):e));var i}()}class b extends Set{affect(t){return Array.from(this.keys()).some((e=>{return n=e,(a=t).endsWith(".*")?n.startsWith(a.slice(0,-2)):a==n||a.startsWith(n+".");var n,a}))}}function E(t){let e=t.split(".");return e.map(((t,n)=>e.slice(0,n+1).join(".")))}function I(t,e){let n=new b,a=new Set([].concat(Array.from(t.keys()),Array.from(e.keys())));for(let i of a)E(i).some((t=>n.has(t)))||t.get(i)!==e.get(i)&&n.add(i);return n}let T=new Map;function x(){let t=2;for(;t>0;){t--;let n=(e=window.vars,new Map(y(e))),a=I(T,n);if(0==a.size)break;T=n,document.body.dispatchEvent(new CustomEvent("ot.update",{detail:a}))}var e}function k(t,e){l("dispatchEvent",arguments,["string","data"],["string"]),document.body.dispatchEvent(new CustomEvent("ot.".concat(t),{detail:e}))}function P(t,e){l("emitEvent",arguments,["string","data"],["string"]),setTimeout((()=>document.body.dispatchEvent(new CustomEvent("ot.".concat(t),{detail:e}))))}function A(t,e){l("onEvent",arguments,["string","function"]),document.body.addEventListener("ot.".concat(t),(async t=>{await e(t.detail,t),x()}))}const S={startPage:function(){},completePage:function(){},nextIteration:null,completeIteration:null,startTrial:null,completeTrial:null};function C(t,e){let n=S[t];if(!n)throw new Error("Missing ".concat(t," handler"));setTimeout((async()=>{await n.apply(null,e),x()}))}function j(t){l("onStartPage",arguments,["function"]),S.startPage=t}function L(){C("startPage")}function O(t){l("onCompletePage",arguments,["function"]),S.completePage=t}function M(t){l("onNextIteration",arguments,["function"]),S.nextIteration=t}function _(t){l("onCompleteIteration",arguments,["function"]),S.completeIteration=t}function D(t){l("onStartTrial",arguments,["function"]),S.startTrial=t}function N(t){l("onCompleteTrial",arguments,["function"]),S.completeTrial=t}const U={};function z(t){l("cancelTimeout",arguments,["string"]),t in U&&(window.clearTimeout(U[t]),delete U[t])}const H={};function W(){l("cancelPhases",arguments,[]);for(let t in H)window.clearTimeout(H[t]),delete H[t]}const $={},F={};function R(t){l("cancelTimer",arguments,["string"]),t in $&&(window.clearInterval($[t]),delete $[t],delete F[t])}function q(t){return l("preloadImage",arguments,["string"]),new Promise(((e,n)=>{let a=new Image;a.loading="eager",a.src=t,a.onload=()=>e(a)}))}const Z={};function B(){void 0!==window.liveSocket&&(window.liveSocket.onmessage=function(t){let e=JSON.parse(t.data);Object.entries(e).forEach((t=>function(t,e){let n=Z[t];if(!n)throw new Error("Missing onLive('".concat(t,"') handler"));setTimeout((async()=>{await n.apply(null,[e]),x()}))}(t[0],t[1])))})}function K(t,e,n){n?t.setAttribute(e,""):t.removeAttribute(e)}class J{parameters(){return{}}constructor(t){this.elem=t,this.init(Object.fromEntries(Array.from(this.elem.attributes).map((t=>[t.name,t.value])))),this.render(),this.setup()}init(t){this.params=this.initParams(t);let e=Object.fromEntries(Object.entries(this.params).filter((t=>{let[e,n]=t;return void 0!==n.val})).map((t=>{let[e,n]=t;return[e,n.val]})));Object.assign(this,e)}get disabled(){return this.elem.disabled||this.elem.hidden}setup(){this.onPageEvent("ot.update",this.onUpdate)}render(){}update(t){Object.assign(this,t)}onUpdate(t){let e=this.evalParams(t);0!=Object.entries(e).length&&this.update(e)}initParams(t){let e=this.parameters(),n={};for(let a in e){let i=e[a];try{let e=v(a,i,t);n&&(n[a]=e)}catch(t){console.error(t.message),n=null}}if(null===n)throw new Error("Failed to initialize some params");return n}evalParams(t){let e={};for(let n in this.params)try{let a=g(n,this.params[n],t,window.vars);e&&void 0!==a&&(e[n]=a)}catch(t){console.error(t.message),e=null}if(null===e)throw new Error("Failed to evaluate some params");return e}_wrap(t){return function(e){try{t.call(this,e.detail,e)}catch(t){console.error(t),console.error("Failed to handle ".concat(e.type," for ").concat(this.constructor.name," at"),this.elem)}}.bind(this)}onElemEvent(t,e){this.elem.addEventListener(t,this._wrap(e))}onPageEvent(t,e){document.body.addEventListener(t,this._wrap(e))}emitElemEvent(t,e){setTimeout((()=>this.elem.dispatchEvent(new CustomEvent(t,{detail:e}))))}dispatchElemEvent(t,e){this.elem.dispatchEvent(new CustomEvent(t,{detail:e}))}}class V extends J{constructor(t){super(t),K(this.elem,"input",!0)}parameters(){return{name:{type:"name",variable:!1}}}setup(){super.setup(),this.onPageEvent("ot.switchInputs",this.onSwitch),this.onPageEvent("ot.resetInputs",this.onReset),this.onElemEvent("ot.resetInputs",this.onReset),this.onPageEvent("ot.commitInputs",this.onCommit),this.onElemEvent("ot.commitInputs",this.onCommit),this.onElemEvent("ot.refocusInput",this.onRefocus),this.switch(!1)}onReset(t){t&&t.name!=this.name||this.reset(t&&"value"in t?t.value:null)}reset(t){this.update({value:t})}onSwitch(t){(void 0===t.selected||t.selected.includes(this.name))&&this.switch(t.state)}switch(t){this.elem.disabled=!t,this.elem.hasAttribute("xmlns")&&K(this.elem,"disabled",!t),this.refocus()}onCommit(t){t&&t.name!=this.name||this.disabled||this.commit()}commit(){k("input",{name:this.name,value:this.value})}onRefocus(){this.refocus()}refocus(){this.disabled?this.elem.blur():this.elem.hasAttribute("autofocus")&&this.elem.focus()}}const X={};function Y(t,e){X[e]=t}function G(t,e){document.querySelectorAll(e).forEach((n=>{try{new t(n)}catch(a){console.error(a),console.error("Failed to create directive ".concat(t.name," for ").concat(e," at"),n)}}))}class Q extends J{get attr_name(){}parameters(){return{value:{attr:"ot-".concat(this.attr_name),variable:!0}}}render(){n(this.value)?this.elem.removeAttribute(this.attr_name):this.elem.setAttribute(this.attr_name,this.value)}update(t){super.update(t),this.render()}}Y(class extends Q{get attr_name(){return"min"}},"[ot-min]"),Y(class extends Q{get attr_name(){return"max"}},"[ot-max]"),Y(class extends Q{get attr_name(){return"height"}},"[ot-height]"),Y(class extends Q{get attr_name(){return"width"}},"[ot-width]"),Y(class extends Q{get attr_name(){return"src"}},"[ot-src]"),Y(class extends Q{get attr_name(){return"href"}},"[ot-href]");Y(class extends J{parameters(){return{value:{attr:"ot-text",variable:!0}}}render(){let t=n(this.value)?"":this.value;this.elem.innerText=t}update(t){super.update(t),this.render()}},"[ot-text]");Y(class extends J{parameters(){return{value:{attr:"ot-html",variable:!0}}}render(){let t=n(this.value)?"":this.value;this.elem.innerHTML=t}update(t){super.update(t),this.render()}},"[ot-html]");Y(class extends J{parameters(){return{value:{attr:"ot-class",variable:!0}}}init(t){super.init(t),this.initial=Array.from(this.elem.classList)}render(){this.elem.classList.remove(...this.elem.classList),this.initial&&this.elem.classList.add(...this.initial),!n(this.value)&&this.value&&(Array.isArray(this.value)?this.elem.classList.add(...this.value):this.elem.classList.add(this.value))}update(t){super.update(t),this.render()}},"[ot-class]");function tt(t,e){t.hidden=e,t.hasAttribute("xmlns")&&K(t,"hidden",e)}Y(class extends J{parameters(){return{image:{attr:"ot-img",variable:!0}}}render(){if(n(this.image))return;let t=this.image;for(let e of this.elem.attributes)"src"!=e.name&&t.setAttribute(e.name,e.value);this.elem.replaceWith(t),this.elem=t}update(t){if(n(t.image))t.image=new Image;else if(!(t.image instanceof HTMLImageElement))throw new Error("Invalid value of 'vars.".concat(this.params.image.var,"'; expected: preloaded HTMLImage"));super.update(t),this.render()}},"img[ot-img]");Y(class extends J{parameters(){return{name:{attr:"ot-display",type:"name",variable:!1}}}setup(){super.setup(),this.onPageEvent("ot.switchDisplays",this.onSwitch)}switch(t){tt(this.elem,!t),this.elem.querySelectorAll("[input]").forEach((t=>{t.removeAttribute("hidden"),tt(t,null!==t.closest("[hidden]")),t.dispatchEvent(new CustomEvent("ot.refocusInput"))}))}onSwitch(t){(void 0===t.selected||t.selected.includes(this.name))&&this.switch(t.state)}},"[ot-display]");Y(class extends J{parameters(){return{value:{attr:"ot-value",variable:!0}}}update(t){this.elem.hasAttribute("input")?this.dispatchElemEvent("ot.resetInputs",{name:this.elem.getAttribute("name"),value:t.value}):this.elem.value=t.value}},"[ot-value]");Y(class extends J{parameters(){return{style:{attr:"ot-style",variable:!0}}}update(t){let e=t.style;for(;void 0!==this.elem.style[0];)this.elem.style[this.elem.style[0]]=null;n(e)||Object.assign(this.elem.style,e)}},"[ot-style]");class et extends V{parameters(){return{"ot-input":{type:"flag"},name:{type:"name",variable:!1}}}setup(){super.setup(),this.onElemEvent("change",this.onCommit)}get value(){return this.elem.value}set value(t){this.elem.value=t}}Y(et,"input[ot-input]:not([type=radio], [type=checkbox])"),Y(class extends et{get value(){return this.elem.checked}set value(t){this.elem.checked=!!t}},"input[ot-input][type=checkbox]"),Y(class extends et{commit(){this.elem.checked&&super.commit()}get value(){return this.elem.value}set value(t){this.elem.checked=this.elem.value==t}},"input[ot-input][type=radio]"),Y(et,"select[ot-input]"),Y(et,"textarea[ot-input]"),Y(class extends V{parameters(){return{"ot-input":{type:"flag"},name:{type:"name",variable:!1},value:{optional:!0}}}get value(){return this.elem.value}set value(t){this.elem.value=t}reset(t){}},"[ot-input]:not(input, select, textarea)");Y(class extends V{parameters(){return{name:{attr:"ot-event",type:"name",variable:!1}}}commit(){k(this.name)}},"[ot-event]");class nt extends J{parameters(){return{"ot-click":{type:"flag"}}}setup(){this.onElemEvent("click",this.onClick)}onClick(){this.elem.disabled||this.dispatchElemEvent("ot.commitInputs")}}Y(nt,"[ot-click]:not(button)"),Y(nt,"button[type=button][ot-input]"),Y(nt,"button[type=button][ot-event]");Y(class extends J{init(t){if(this.key=t["ot-kbd"],1!=this.key.length&&!this.key.match(/[A-Z]\w+/))throw new Error('Invalid attribute value: "'.concat(this.key,'", expected a letter or a codename (see "Code values for keyboard" at developer.mozilla.org'))}setup(){this.elem instanceof HTMLInputElement?this.onElemEvent("keydown",this.onKey):this.onPageEvent("keydown",this.onKey)}onKey(t,e){this.disabled||this.key!=e.key&&this.key!=e.code||(e.preventDefault(),this.dispatchElemEvent("ot.commitInputs"))}},"[ot-kbd]");Y(class extends V{parameters(){return{"ot-point-input":{type:"flag"},name:{type:"name",variable:!1}}}setup(){super.setup(),this.onElemEvent("click",this.onClick)}onClick(t,e){this.disabled||(this.update({value:{x:e.offsetX,y:e.offsetY}}),this.commit())}},"[ot-point-input]");const at={onStartPage:j,onCompletePage:O,onNextIteration:M,onCompleteIteration:_,onStartTrial:D,onCompleteTrial:N};return window.addEventListener("DOMContentLoaded",(()=>{!function(){document.querySelectorAll("[ot-display]").forEach((t=>{t.setAttribute("hidden","")}));for(let t in X)G(X[t],t)}(),B(),window.vars={},function(t){for(let e in at)window[t][e]!==at[e]&&console.error("Invalid usage of ".concat(e,"; Expected: ").concat(t,".").concat(e,"(function() { ... })"))}("ot")})),window.addEventListener("load",(()=>{L()})),t.cancelPhases=W,t.cancelTimeout=z,t.cancelTimeouts=function(){l("cancelTimeouts",arguments,[]);for(let t in U)z(t)},t.cancelTimer=R,t.cancelTimers=function(){l("cancelTimers",arguments,[]);for(let t in $)R(t)},t.commitInput=function(t){l("commitInput",arguments,["string"]),k("commitInputs",{name:t})},t.completeIteration=function(){l("completeIteration",arguments,[]),C("completeIteration")},t.completePage=function(){l("completePage",arguments,[]),C("completePage"),setTimeout((()=>document.querySelector("form#form").submit()))},t.completeTrial=function(t){l("completeTrial",arguments,["object"]),C("completeTrial",arguments)},t.delay=async function(t,e){return l("delay",arguments,["number","function"],["number"]),new Promise(void 0===e?(e,n)=>{setTimeout((()=>e()),t)}:(n,a)=>{setTimeout((()=>{e(),x(),n()}),t)})},t.delayEvent=function(t,e,n){l("delayEvent",arguments,["number","string","data"],["number","string"]),setTimeout((()=>document.body.dispatchEvent(new CustomEvent("ot.".concat(e),{detail:n}))),t)},t.disableInputs=function(t){l("disableInputs",arguments,[],["string"],["array"]),"string"==typeof t&&(t=[t]),k("switchInputs",{state:!1,selected:t})},t.dispatchEvent=k,t.emitEvent=P,t.enableInputs=function(t){l("enableInputs",arguments,[],["string"],["array"]),"string"==typeof t&&(t=[t]),P("switchInputs",{state:!0,selected:t})},t.evalParam=g,t.getTimeMeasurement=function(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"response";return function(t){performance.mark("ot.".concat(t))}(t),function(t){return performance.measure("ot.".concat(t,".measure"),"ot.".concat(t,".start"),"ot.".concat(t))}(t).duration},t.hideDisplays=function(t){l("hideDisplays",arguments,[],["string"],["array"]),"string"==typeof t&&(t=[t]),k("switchDisplays",{state:!1,selected:t})},t.isArray=e,t.isFunction=function(t){return"function"==typeof t},t.isHTMLElement=a,t.isObject=r,t.isPlainObject=o,t.isScalar=i,t.isVoid=n,t.keypath=d,t.nextIteration=function(){l("nextIteration",arguments,[]),C("nextIteration")},t.onCompleteIteration=_,t.onCompletePage=O,t.onCompleteTrial=N,t.onDelete=function(t,e){let a;try{l("onDelete",arguments,["string","function"]),a=f("variable","variable",t)}catch(t){throw console.error(t),new Error("Invalid onDelete usage")}document.body.addEventListener("ot.update",(function(t){if(t.detail.affect(a)){n(m(window.vars,a))&&e()}}))},t.onEvent=A,t.onInput=function(){l("onInput",arguments,["string","function"],["function"]);let{handler:t,match:e}=c(arguments);A("input",void 0!==e?n=>{n.name==e&&t(n.value)}:e=>{t(e.name,e.value)})},t.onLive=function(t,e){if(void 0===window.liveSocket)throw new Error("The page doesn't seem live");l("onLive",arguments,["string","function"]),Z[t]=e},t.onNextIteration=M,t.onPhase=function(){l("onPhase",arguments,["string","function"],["function"]);let{handler:t,match:e}=c(arguments);A("phase",e?n=>{n.name==e&&n.start&&t()}:e=>{e.start&&t(e.name)})},t.onPhaseEnd=function(){l("onPhase",arguments,["string","function"]);let{handler:t,match:e}=c(arguments);A("phase",(n=>{n.name==e&&n.end&&t()}))},t.onStartPage=j,t.onStartTrial=D,t.onTimeout=function(){l("onTimeout",arguments,["string","function"]);let{handler:t,match:e}=c(arguments);A("timeout",(n=>{n.name==e&&t()}))},t.onTimer=function(){l("onTimer",arguments,["string","function"]);let{handler:t,match:e}=c(arguments);A("timer",(n=>{n.name==e&&t(n.time)}))},t.onUpdate=function(t,e){let a;try{l("onUpdate",arguments,["string","function"]),a=f("variable","variable",t)}catch(t){throw console.error(t),new Error("Invalid onUpdate usage")}document.body.addEventListener("ot.update",(function(t){if(t.detail.affect(a)){let t=m(window.vars,a);n(t)||e(t)}}))},t.otDirectiveBase=J,t.otInputBase=V,t.parseParam=v,t.parseValue=f,t.preloadImage=q,t.preloadImages=function(t){return l("preloadImage",arguments,["array"]),Promise.all(t.map((t=>q(t))))},t.registerDirective=Y,t.resetInput=function(t,e){l("resetInput",arguments,["string"],["string","data"]),k("resetInputs",{name:t,value:e})},t.resetInputs=function(){l("resetInputs",arguments,[]),k("resetInputs")},t.sendLive=function(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;if(void 0===window.liveSocket)throw new Error("Missing live socket, the page is not live");l("sendLive",arguments,["string","object"],["string"]),window.liveSocket.send(JSON.stringify({[t]:e}))},t.showDisplays=function(t){l("showDisplays",arguments,[],["string"],["array"]),"string"==typeof t&&(t=[t]),P("switchDisplays",{state:!0,selected:t})},t.startPage=L,t.startPhases=function(t){l("startPhases",arguments,["object"]),W();let e=0;for(let n in t){let a=t[n];H["".concat(n,".start")]=window.setTimeout((function(){P("phase",{name:n,start:!0})}),e),null!==a&&(e+=a,H["".concat(n,".end")]=window.setTimeout((function(){P("phase",{name:n,end:!0})}),e))}},t.startTimeMeasurement=function(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"response";!function(t){performance.clearMarks("ot.".concat(t,".start")),performance.clearMarks("ot.".concat(t)),performance.clearMeasures("ot.".concat(t,".measure"))}(t),function(t){performance.mark("ot.".concat(t,".start"))}(t)},t.startTimeout=function(t,e){l("startTimeout",arguments,["number","string"]),z(e),U[e]=window.setTimeout((function(){P("timeout",{name:e})}),t)},t.startTimer=function(t,e){l("startTimer",arguments,["number","string"]),R(e),F[e]=window.performance.now(),$[e]=window.setInterval((function(){P("timer",{name:e,time:window.performance.now()-F[e]})}),t),P("timer",{name:e,time:0})},t.startTrial=function(t){l("startTrial",arguments,["object"]),C("startTrial",arguments)},t.updatePage=x,t}({});