@m2c2kit/assessment-color-shapes 0.8.34 → 0.8.35

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.min.js CHANGED
@@ -1 +1 @@
1
- import{Game as Me,RandomDraws as L,Sprite as Fe,Scene as J,M2Error as ye,WebColors as I,Transition as ue,Shape as R,Label as Te,Action as x,Timer as pe,Easings as Be,TransitionDirection as ke}from"@m2c2kit/core";import{LocalePicker as xe,Instructions as de,CountdownScene as Ue,Grid as we,Button as _e}from"@m2c2kit/addons";class _ extends Error{constructor(...t){super(...t),this.name="M2Error",Object.setPrototypeOf(this,_.prototype),Error.captureStackTrace&&Error.captureStackTrace(this,_)}}const me=new Map;let Pe=0;function ie(u){return me.get(u)}function q(u){me.delete(u)}function ve(){const u=(r=>{if(!r)return;let n=r;for(const s of u.ops){const i=n[s.name];if(typeof i!="function")throw new _(`chain: method ${s.name} does not exist on DataCalc`);const e=i.apply(n,s.args);if(e instanceof b){n=e;continue}return e}});u.ops=[];const t=(r,n)=>(u.ops.push({name:r,args:n}),u);return u.arrange=(...r)=>t("arrange",r),u.slice=(r,n)=>t("slice",[r,n]),u.pull=r=>t("pull",[r]),u.filter=r=>t("filter",[r]),u.mutate=r=>t("mutate",[r]),u.select=(...r)=>t("select",r),u.groupBy=(...r)=>t("groupBy",r),u.ungroup=()=>t("ungroup",[]),u.rename=r=>t("rename",[r]),u.distinct=()=>t("distinct",[]),Object.defineProperty(u,"length",{configurable:!0,get:function(){try{const r=`c${++Pe}`;return me.set(r,(u.ops||[]).map(n=>({...n}))),`__CHAIN_EXPR__[${r}]`}catch{return}}}),u}function Se(...u){return ve().arrange(...u)}function h(u){return ve().filter(u)}class b{constructor(t,r){if(this._groups=new Array,this._warnings=!1,!Array.isArray(t))throw new _("DataCalc constructor expects an array of observations as first argument");for(let s=0;s<t.length;s++)if(t[s]===null||typeof t[s]!="object"||Array.isArray(t[s]))throw new _(`DataCalc constructor expects all elements to be objects (observations). Element at index ${s} is ${typeof t[s]}. Element: ${JSON.stringify(t[s])}`);this._observations=this.deepCopy(t);const n=new Set;for(const s of t)for(const i of Object.keys(s))n.add(i);for(const s of this._observations)for(const i of n)i in s||(s[i]=null);r?.groups&&(this._groups=Array.from(r.groups)),r?.warnings&&(this._warnings=!0)}get groups(){return this._groups}get observations(){return this._observations}get rows(){return this._observations}pull(t){if(this._observations.length===0)return this._warnings&&console.warn(`DataCalc.pull(): No observations available to pull variable "${t}" from. Returning null.`),null;this.verifyObservationsContainVariable(t);const r=this._observations.map(n=>n[t]);return r.length===1?r[0]:r}get length(){return this._observations.length}filter(t){if(this._groups.length>0)throw new _(`filter() cannot be used on grouped data. The data are currently grouped by ${this._groups.join(", ")}. Ungroup the data first using ungroup().`);return new b(this._observations.filter(t),{groups:this._groups,warnings:this._warnings})}groupBy(...t){return t.forEach(r=>{this.verifyObservationsContainVariable(r);for(let n=0;n<this._observations.length;n++){const s=this._observations[n][r];if(s===null)continue;const i=typeof s;if(i!=="number"&&i!=="string"&&i!=="boolean")throw new _(`groupBy(): variable "${r}" contains non-primitive value at index ${n} (type=${i}). Only number, string, boolean, or null are allowed for grouping.`)}}),new b(this._observations,{groups:t})}ungroup(){return new b(this._observations)}mutate(t){if(this._groups.length>0)throw new _(`mutate() cannot be used on grouped data. The data are currently grouped by ${this._groups.join(", ")}. Ungroup the data first using ungroup().`);const r=this._observations.map(n=>{let s={...n};for(const[i,e]of Object.entries(t))s={...s,[i]:e(n)};return s});return new b(r,{groups:this._groups,warnings:this._warnings})}summarize(t){if(this._groups.length===0){const r={};for(const[n,s]of Object.entries(t))if(typeof s=="object"&&s!==null&&"summarizeFunction"in s){const i=s;r[n]=i.summarizeFunction(this,i.parameters,i.options)}else if(typeof s=="function")try{const i=s(this);if(typeof i=="function")throw new _(`summarize(): lazy callback for ${n} returned a function; expected a value or array of values.`);if(i instanceof b)throw new _(`summarize(): lazy callback for ${n} returned a DataCalc; expected a value or array of values.`);r[n]=i}catch(i){throw new _(`summarize(): lazy callback for ${n} threw an error: ${i&&i.message?i.message:String(i)}`)}else{if(typeof s=="string"){const i=/__CHAIN_EXPR__\[(.*?)\]/g,e=Array.from(s.matchAll(i));if(e.length>0){let a=0;for(const l of e){const p=l[1];let d=ie(p);if(!d)try{d=JSON.parse(decodeURIComponent(p))}catch{throw new _(`summarize(): failed to parse chain payload for ${n}`)}let m=this,g;if(!d)throw new _(`summarize(): empty chain ops for ${n}`);for(const v of d){const C=m[v.name];if(typeof C!="function")throw new _(`summarize(): chain method ${v.name} does not exist on DataCalc`);const N=C.apply(m,v.args);if(N instanceof b){m=N;continue}if(Array.isArray(N)){g=N.length;break}if(typeof N=="boolean"){g=N?1:0;break}g=typeof N=="number"?N:Number(N);break}g===void 0&&(g=m instanceof b?m.length:0),a+=g}let o=s;for(const l of e)o=o.replace(l[0],"");const c=Number(o);Number.isNaN(c)||(a+=c),r[n]=a;for(const l of e)q(l[1]);continue}}r[n]=s}return new b([r],{groups:this._groups,warnings:this._warnings})}return this.summarizeByGroups(t)}summarizeByGroups(t){const r=new Map;this._observations.forEach(s=>{const i=this._groups.map(a=>String(s[a])).join("|");r.has(i)||r.set(i,[]);const e=r.get(i);e?e.push(s):r.set(i,[s])});const n=[];return r.forEach((s,i)=>{const e=i.split("|"),a=s[0],o={};this._groups.forEach((l,p)=>{const d=e[p];if(a[l]===null)o[l]=null;else{const m=typeof a[l];m==="number"?o[l]=Number(d):m==="boolean"?o[l]=d==="true":o[l]=d}});const c=new b(s);for(const[l,p]of Object.entries(t))if(typeof p=="object"&&p!==null&&"summarizeFunction"in p){const d=p;o[l]=d.summarizeFunction(c,d.parameters,d.options)}else if(typeof p=="function")try{const d=p(c);if(typeof d=="function")throw new _(`summarize(): lazy callback for ${l} returned a function; expected a value or array of values.`);if(d instanceof b)throw new _(`summarize(): lazy callback for ${l} returned a DataCalc; expected a value or array of values.`);o[l]=d}catch(d){throw new _(`summarize(): lazy callback for ${l} threw an error: ${d&&d.message?d.message:String(d)}`)}else{if(typeof p=="string"){const d=/__CHAIN_EXPR__\[(.*?)\]/g,m=Array.from(p.matchAll(d));if(m.length>0){let g=0;for(const N of m){const K=N[1];let V=ie(K);if(!V)try{V=JSON.parse(decodeURIComponent(K))}catch{throw new _(`summarize(): failed to parse chain payload for ${l}`)}let O=c,B;if(!V)throw new _(`summarize(): empty chain ops for ${l}`);for(const D of V){const k=O[D.name];if(typeof k!="function")throw new _(`summarize(): chain method ${D.name} does not exist on DataCalc`);const A=k.apply(O,D.args);if(A instanceof b){O=A;continue}if(Array.isArray(A)){B=A.length;break}if(typeof A=="boolean"){B=A?1:0;break}B=typeof A=="number"?A:Number(A);break}B===void 0&&(B=O instanceof b?O.length:0),g+=B}let v=p;for(const N of m)v=v.replace(N[0],"");const C=Number(v);Number.isNaN(C)||(g+=C),o[l]=g;for(const N of m)q(N[1]);continue}}o[l]=p}n.push(o)}),new b(n,{groups:this._groups,warnings:this._warnings})}select(...t){const r=[],n=[];t.forEach(a=>{a.startsWith("-")?n.push(a.substring(1)):r.push(a)}),[...r.length>0?r:Object.keys(this._observations[0]||{}),...n].forEach(a=>{this.verifyObservationsContainVariable(a)});const i=new Set(n),e=this._observations.map(a=>{const o={};return r.length>0?r.forEach(c=>{i.has(c)||(o[c]=a[c])}):Object.keys(a).forEach(c=>{i.has(c)||(o[c]=a[c])}),o});return new b(e,{groups:this._groups,warnings:this._warnings})}arrange(...t){if(this._groups.length>0)throw new _(`arrange() cannot be used on grouped data. The data are currently grouped by ${this._groups.join(", ")}. Ungroup the data first using ungroup().`);const r=[...this._observations].sort((n,s)=>{for(const i of t){let e=i,a=1;if(i.startsWith("-")&&(e=i.substring(1),a=-1),!(e in n)||!(e in s))throw new _(`arrange(): variable ${e} does not exist in all observations`);const o=n[e],c=s[e];if(typeof o!=typeof c)return a*(String(o)<String(c)?-1:1);if(o<c)return-1*a;if(o>c)return 1*a}return 0});return new b(r,{groups:this._groups,warnings:this._warnings})}distinct(){const t=new Set,r=this._observations.filter(n=>{const s=JSON.stringify(this.normalizeForComparison(n));return t.has(s)?!1:(t.add(s),!0)});return new b(r,{groups:this._groups,warnings:this._warnings})}rename(t){if(this._observations.length===0)throw new _("Cannot rename variables on an empty dataset");if(Object.values(t).forEach(n=>{this.verifyObservationsContainVariable(n)}),this._observations.length>0){const n=new Set(Object.keys(this._observations[0])),s=new Set(Object.values(t)),i=Object.keys(t).filter(e=>n.has(e)&&!s.has(e));i.length>0&&this._warnings&&console.warn(`DataCalc.rename(): renaming will overwrite existing variables: ${i.join(", ")}`)}const r=this._observations.map(n=>{const s={},i=new Set(Object.keys(t));for(const[e,a]of Object.entries(n)){const o=Object.entries(t).find(([,c])=>c===e)?.[0];o?s[o]=a:i.has(e)||(s[e]=a)}return s});return new b(r,{groups:this._groups,warnings:this._warnings})}innerJoin(t,r){if(this._groups.length>0||t._groups.length>0)throw new _("innerJoin() cannot be used on grouped data. Ungroup the data first using ungroup().");r.forEach(i=>{this.verifyObservationsContainVariable(i),t.verifyObservationsContainVariable(i)});const n=new Map;t.observations.forEach(i=>{if(this.hasNullJoinKeys(i,r))return;const e=r.map(o=>JSON.stringify(this.normalizeForComparison(i[o]))).join("|"),a=n.get(e)||[];a.push(i),n.set(e,a)});const s=[];return this._observations.forEach(i=>{if(this.hasNullJoinKeys(i,r))return;const e=r.map(o=>JSON.stringify(this.normalizeForComparison(i[o]))).join("|"),a=n.get(e)||[];a.length>0&&a.forEach(o=>{const c={...i};Object.entries(o).forEach(([l,p])=>{r.includes(l)||(c[l]=p)}),s.push(c)})}),new b(s)}leftJoin(t,r){if(this._groups.length>0||t._groups.length>0)throw new _("leftJoin() cannot be used on grouped data. Ungroup the data first using ungroup().");r.forEach(i=>{this.verifyObservationsContainVariable(i),t.verifyObservationsContainVariable(i)});const n=new Map;t.observations.forEach(i=>{if(this.hasNullJoinKeys(i,r))return;const e=r.map(o=>JSON.stringify(this.normalizeForComparison(i[o]))).join("|"),a=n.get(e)||[];a.push(i),n.set(e,a)});const s=[];return this._observations.forEach(i=>{if(this.hasNullJoinKeys(i,r)){s.push({...i});return}const e=r.map(o=>JSON.stringify(this.normalizeForComparison(i[o]))).join("|"),a=n.get(e)||[];a.length>0?a.forEach(o=>{const c={...i};Object.entries(o).forEach(([l,p])=>{r.includes(l)||(c[l]=p)}),s.push(c)}):s.push({...i})}),new b(s)}rightJoin(t,r){if(this._groups.length>0||t._groups.length>0)throw new _("rightJoin() cannot be used on grouped data. Ungroup the data first using ungroup().");r.forEach(e=>{this.verifyObservationsContainVariable(e),t.verifyObservationsContainVariable(e)});const n=new Map;t.observations.forEach(e=>{if(this.hasNullJoinKeys(e,r))return;const a=r.map(c=>JSON.stringify(this.normalizeForComparison(e[c]))).join("|"),o=n.get(a)||[];o.push(e),n.set(a,o)});const s=[],i=new Set;return this._observations.forEach(e=>{if(this.hasNullJoinKeys(e,r))return;const a=r.map(c=>JSON.stringify(this.normalizeForComparison(e[c]))).join("|"),o=n.get(a)||[];o.length>0&&(o.forEach(c=>{const l={...e};Object.entries(c).forEach(([p,d])=>{r.includes(p)||(l[p]=d)}),s.push(l)}),i.add(a))}),t.observations.forEach(e=>{if(this.hasNullJoinKeys(e,r)){s.push({...e});return}const a=r.map(o=>JSON.stringify(this.normalizeForComparison(e[o]))).join("|");i.has(a)||(s.push({...e}),i.add(a))}),new b(s)}fullJoin(t,r){if(this._groups.length>0||t._groups.length>0)throw new _("fullJoin() cannot be used on grouped data. Ungroup the data first using ungroup().");r.forEach(e=>{this.verifyObservationsContainVariable(e),t.verifyObservationsContainVariable(e)});const n=new Map;t.observations.forEach(e=>{if(this.hasNullJoinKeys(e,r))return;const a=r.map(c=>JSON.stringify(this.normalizeForComparison(e[c]))).join("|"),o=n.get(a)||[];o.push(e),n.set(a,o)});const s=[],i=new Set;return this._observations.forEach(e=>{if(this.hasNullJoinKeys(e,r)){s.push({...e});return}const a=r.map(c=>JSON.stringify(this.normalizeForComparison(e[c]))).join("|"),o=n.get(a)||[];o.length>0?(o.forEach(c=>{const l={...e};Object.entries(c).forEach(([p,d])=>{r.includes(p)||(l[p]=d)}),s.push(l)}),i.add(a)):s.push({...e})}),t.observations.forEach(e=>{if(this.hasNullJoinKeys(e,r)){s.push({...e});return}const a=r.map(o=>JSON.stringify(this.normalizeForComparison(e[o]))).join("|");i.has(a)||(s.push({...e}),i.add(a))}),new b(s)}slice(t,r){if(this._groups.length>0)throw new _("slice() cannot be used on grouped data. Ungroup the data first using ungroup().");let n;if(t>=this._observations.length)return new b([],{groups:this._groups,warnings:this._warnings});if(r===void 0){const s=t<0?this._observations.length+t:t;n=[this._observations[s]]}else n=this._observations.slice(t,r);return new b(n,{groups:this._groups,warnings:this._warnings})}bindRows(t){if(this._observations.length>0&&t.observations.length>0){const r=new Set(Object.keys(this._observations[0])),n=new Set(Object.keys(t.observations[0]));[...r].filter(i=>n.has(i)).forEach(i=>{const e=this.getVariableType(i),a=t.getVariableType(i);e!==a&&console.warn(`Warning: bindRows() is combining datasets with different data types for variable '${i}'. Left dataset has type '${e}' and right dataset has type '${a}'.`)})}return new b([...this._observations,...t.observations])}getVariableType(t){if(this._observations.length===0)return"unknown";const r={};this._observations.forEach(i=>{if(t in i){const e=i[t],a=e===null?"null":Array.isArray(e)?"array":typeof e;r[a]=(r[a]||0)+1}});let n=0,s="unknown";for(const[i,e]of Object.entries(r))e>n&&(n=e,s=i);return s}verifyObservationsContainVariable(t){if(!this._observations.every(r=>t in r))throw new _(`Variable ${t} does not exist for each item (row) in the data array.`)}variableExists(t){return this._observations.some(r=>t in r)}isNonMissingNumeric(t){return typeof t=="number"&&!isNaN(t)&&isFinite(t)}isMissingNumeric(t){return typeof t=="number"&&(isNaN(t)||!isFinite(t))||t===null||typeof t>"u"}normalizeForComparison(t){return t===null||typeof t!="object"?t:Array.isArray(t)?t.map(r=>this.normalizeForComparison(r)):Object.keys(t).sort().reduce((r,n)=>(r[n]=this.normalizeForComparison(t[n]),r),{})}deepCopy(t,r=new WeakMap){const n=globalThis.structuredClone;if(typeof n=="function")try{const e=t&&typeof t=="object"?Object.getPrototypeOf(t):null;if(Array.isArray(t)||e===Object.prototype||e===null){const o=Object.getOwnPropertyDescriptors(t);if(!Object.values(o).some(l=>typeof l.get=="function"||typeof l.set=="function"))return n(t)}}catch{}if(t===null||typeof t!="object")return t;if(r.has(t))return r.get(t);const s=Array.isArray(t)?[]:Object.create(Object.getPrototypeOf(t));r.set(t,s);const i=[...Object.getOwnPropertyNames(t),...Object.getOwnPropertySymbols(t)];for(const e of i){const a=Object.getOwnPropertyDescriptor(t,e);if(a){const{get:o,set:c,...l}=a;Object.defineProperty(s,e,{...l,value:this.deepCopy(t[e],r)})}}return s}hasNullJoinKeys(t,r){return r.some(n=>t[n]===null||t[n]===void 0)}}const Ne={"+":1,"-":1,"*":2,"/":2,"^":3};class X{constructor(t,r,n,s){this.leafFn=t,this.parameters=r,this.options=n,s&&s.length>0?this.tokens=s.slice():t?this.tokens=[{t:"operand",v:this}]:this.tokens=[],this.summarizeFunction=i=>this.evaluateAsValue(i)}static leaf(t,r,n){return new X(t,r,n)}cloneWithTokens(t){return new X(void 0,void 0,void 0,t)}appendOp(t,r){const n=this.tokens.slice();return n.push({t:"op",v:t}),n.push({t:"operand",v:r}),this.cloneWithTokens(n)}add(t){return this.appendOp("+",t)}sub(t){return this.appendOp("-",t)}mul(t){return this.appendOp("*",t)}div(t){return this.appendOp("/",t)}pow(t){return this.appendOp("^",t)}evaluateOperandToNumber(t,r){if(this._usedChainIds||(this._usedChainIds=new Set),typeof t=="number")return t;if(typeof t=="string"){const a=/^__CHAIN_EXPR__\[(.*?)\]$/.exec(t);if(a){const o=a[1];let c=ie(o);if(c&&this._usedChainIds?.add(o),!c)try{c=JSON.parse(decodeURIComponent(o))}catch{c=void 0}if(!c)return NaN;let l=r,p;for(const d of c){const m=l[d.name];if(typeof m!="function")return NaN;const g=m.apply(l,d.args);if(g instanceof b){l=g;continue}if(Array.isArray(g)){p=g.length;break}if(typeof g=="boolean")if(this.options&&typeof this.options.coerceBooleans=="boolean"?this.options.coerceBooleans:!0){p=g?1:0;break}else return NaN;p=typeof g=="number"?g:Number(g);break}return p===void 0&&(p=l instanceof b?l.length:NaN),typeof p=="number"&&!isNaN(p)?p:NaN}}const n=Array.isArray(t.parameters)?t.parameters:t.parameters===void 0?void 0:[t.parameters],s=t.leafFn?t.leafFn(r,n,t.options):t.evaluateAsValue(r);if(s==null)return NaN;const i=Number(s);return typeof i=="number"&&!isNaN(i)?i:NaN}evaluateFlatTokens(t,r){const n=[],s=[];for(const a of t)a.t==="operand"?n.push(a.v):s.push(a.v);if(n.length===0)return NaN;for(;s.length>0;){let a=0,o=Ne[s[0]]??0;for(let v=1;v<s.length;v++){const C=Ne[s[v]]??0;(C>o||C===o&&s[v]==="^")&&(o=C,a=v)}const c=s.splice(a,1)[0],l=n.splice(a,1)[0],p=n.splice(a,1)[0],d=this.evaluateOperandToNumber(l,r),m=this.evaluateOperandToNumber(p,r);let g=NaN;c==="+"?g=d+m:c==="-"?g=d-m:c==="*"?g=d*m:c==="/"?g=m===0?NaN:d/m:c==="^"&&(g=Math.pow(d,m)),n.splice(a,0,g)}const i=n[0];if(typeof i=="number"){if(this._usedChainIds){for(const a of this._usedChainIds)q(a);this._usedChainIds=void 0}return i}const e=this.evaluateOperandToNumber(i,r);if(this._usedChainIds){for(const a of this._usedChainIds)q(a);this._usedChainIds=void 0}return e}parens(){return Ee(this)}evaluateAsValue(t){if(this.leafFn){const n=Array.isArray(this.parameters)?this.parameters:this.parameters===void 0?void 0:[this.parameters],s=this.leafFn(t,n,this.options);return typeof s=="number"&&Number.isNaN(s)?null:s}if(!this.tokens||this.tokens.length===0)return NaN;const r=this.evaluateFlatTokens(this.tokens,t);return typeof r=="number"&&Number.isNaN(r)?null:r}}function Ee(u){const t=[{t:"operand",v:u}];return new X(void 0,void 0,void 0,t)}const ze={coerceBooleans:!0,skipMissing:!1};function se(u){return{...ze,...u}}function fe(u,t,r){if(typeof u!="function")return u;try{const n=u(t);if(typeof n=="function")throw new _(`${r||"summarize()"}: lazy callback returned a function; expected a value or array of values.`);if(n instanceof b)throw new _(`${r||"summarize()"}: lazy callback returned a DataCalc instance; expected a value or array of values.`);return n}catch(n){throw new _(`summarize(): lazy callback threw an error: ${n&&n.message?n.message:String(n)}`)}}function Ce(u,t,r,n,s,i){const e=se(r);u.verifyObservationsContainVariable(t);let a=0,o=i,c=!1;return u.observations.forEach(l=>{if(u.isNonMissingNumeric(l[t])){o=n(l[t],o),a++;return}if(typeof l[t]=="boolean"&&e.coerceBooleans){o=n(l[t]?1:0,o),a++;return}if(u.isMissingNumeric(l[t])){c=!0;return}throw new _(`${s}: variable ${t} has non-numeric value ${l[t]} in this observation: ${JSON.stringify(l)}`)}),{state:o,count:a,containsMissing:c}}function Ie(u,t,r){const n=se(t);if(typeof u=="number"&&!isNaN(u)&&isFinite(u))return{value:u,isMissing:!1};if(typeof u=="boolean"&&n.coerceBooleans)return{value:u?1:0,isMissing:!1};if(u==null||typeof u=="number"&&(isNaN(u)||!isFinite(u)))return{value:0,isMissing:!0};throw new _(`${r}: has non-numeric value ${u}`)}const Oe=(u,t,r)=>{let n=t?t[0]:void 0;n=fe(n,u);const s=se(r);if(typeof n=="string"){if(!u.variableExists(n))return null;const i=n,e=Ce(u,i,r,(c,l)=>l+c,"variance()",0);if(e.containsMissing&&!s.skipMissing||e.count<=1)return null;const a=e.state/e.count;return Ce(u,i,r,(c,l)=>{const p=typeof c=="boolean"&&s.coerceBooleans?c?1:0:c;return l+Math.pow(p-a,2)},"variance()",0).state/(e.count-1)}else if(Array.isArray(n)){const i=[];let e=!1;for(const l of n)if(typeof l=="number"&&!isNaN(l)&&isFinite(l))i.push(l);else if(typeof l=="boolean"&&s.coerceBooleans)i.push(l?1:0);else if(l==null||typeof l=="number"&&(isNaN(l)||!isFinite(l)))e=!0;else throw new _(`variance(): has non-numeric value ${l}`);if(e&&!s.skipMissing||i.length<=1)return null;const o=i.reduce((l,p)=>l+p,0)/i.length;return i.reduce((l,p)=>l+Math.pow(p-o,2),0)/(i.length-1)}else return null},je=(u,t,r)=>{let n=t?t[0]:void 0;n=fe(n,u);const s=se(r);if(typeof n=="string"){if(!u.variableExists(n))return null;const i=n;u.verifyObservationsContainVariable(i);const e=[];let a=!1;if(u.observations.forEach(c=>{if(u.isNonMissingNumeric(c[i]))e.push(c[i]);else if(typeof c[i]=="boolean"&&s.coerceBooleans)e.push(c[i]?1:0);else if(u.isMissingNumeric(c[i]))a=!0;else throw new _(`median(): variable ${i} has non-numeric value ${c[i]} in this observation: ${JSON.stringify(c)}`)}),a&&!s.skipMissing||e.length===0)return null;e.sort((c,l)=>c-l);const o=Math.floor(e.length/2);return e.length%2===0?(e[o-1]+e[o])/2:e[o]}else if(Array.isArray(n)){const i=[];let e=!1;for(const o of n)if(typeof o=="number"&&!isNaN(o)&&isFinite(o))i.push(o);else if(typeof o=="boolean"&&s.coerceBooleans)i.push(o?1:0);else if(o==null||typeof o=="number"&&(isNaN(o)||!isFinite(o)))e=!0;else throw new _(`median(): has non-numeric value ${o}`);if(e&&!s.skipMissing||i.length===0)return null;i.sort((o,c)=>o-c);const a=Math.floor(i.length/2);return i.length%2===0?(i[a-1]+i[a])/2:i[a]}else{const i=Ie(n,r,"median()");return i.isMissing&&!s.skipMissing||i.isMissing?null:i.value}};function M(u,t){return X.leaf(je,[u],t)}const Le=(u,t,r)=>{let n=t?t[0]:void 0;if(n=fe(n,u),typeof n=="string"){if(!u.variableExists(n))return null;const s=Oe(u,t,r);return s===null?null:Math.sqrt(s)}else if(Array.isArray(n)){const s=t?[...t]:[n],i=Oe(u,s,r);return i===null?null:Math.sqrt(i)}else return null};function F(u,t){return X.leaf(Le,[u],t)}const Xe=(u,t,r)=>{let n=t?t[0]:void 0;if(typeof n=="function"&&(n=n(u)),typeof n=="string"){const e=/^__CHAIN_EXPR__\[(.*?)\]$/.exec(n);if(e){const a=e[1];let o=ie(a);if(!o)try{o=JSON.parse(decodeURIComponent(a))}catch{o=void 0}if(o){let c=u,l;for(const p of o){const d=c[p.name];if(typeof d!="function"){l=NaN;break}const m=d.apply(c,p.args);if(m instanceof b){c=m;continue}if(Array.isArray(m)){l=m.length;break}if(typeof m=="boolean"){l=m;break}l=typeof m=="number"?m:Number(m);break}l===void 0&&(l=c instanceof b?c.length:NaN),Number.isNaN(l)?n=null:n=l;try{q(a)}catch{}}}}if(typeof n=="object"&&n!==null&&"summarizeFunction"in n)try{const i=n,e=Array.isArray(i.parameters)?i.parameters:i.parameters===void 0?void 0:[i.parameters];n=i.summarizeFunction(u,e,i.options)}catch{n=null}const s=Ie(n,r,"scalar()");return s.isMissing?null:s.value};function oe(u){return X.leaf(Xe,[u],void 0)}console.log("\u26AA @m2c2kit/data-calc version 0.8.7 (38a5862e)");class Ve extends Me{constructor(){const t={fixation_duration_ms:{default:500,description:"How long fixation scene is shown, milliseconds.",type:"number"},shape_colors:{type:"array",description:"Array of colors for shapes.",items:{type:"object",properties:{colorName:{type:"string",description:"Human-friendly name of color."},rgbaColor:{type:"array",description:"Color as array, [r,g,b,a].",items:{type:"number"}}}},default:[{colorName:"black",rgbaColor:[0,0,0,1]},{colorName:"green",rgbaColor:[0,158,115,1]},{colorName:"yellow",rgbaColor:[240,228,66,1]},{colorName:"blue",rgbaColor:[0,114,178,1]},{colorName:"orange",rgbaColor:[213,94,0,1]},{colorName:"pink",rgbaColor:[204,121,167,1]}]},number_of_shapes_shown:{default:3,description:"How many shapes to show on the grid at one time.",type:"integer"},number_of_shapes_changing_color:{default:2,description:"If a different color trial, how many shapes should change color (minimum is 2, because changes are swaps with other shapes).",type:"integer"},shapes_presented_duration_ms:{default:2e3,description:"How long the shapes are shown, milliseconds.",type:"number"},shapes_removed_duration_ms:{default:1e3,description:"How long to show a blank square after shapes are removed, milliseconds.",type:"number"},cells_per_side:{default:3,description:"How many cell positions for each side of the square grid (e.g., 3 is a 3x3 grid; 4 is a 4x4 grid).",type:"integer"},number_of_different_colors_trials:{default:6,type:"integer",description:"Number of trials where the shapes have different colors."},number_of_trials:{default:12,description:"How many trials to run.",type:"integer"},show_trials_complete_scene:{default:!0,type:"boolean",description:"After the final trial, should a completion scene be shown? Otherwise, the game will immediately end."},instruction_type:{default:"long",description:"Type of instructions to show, 'short' or 'long'.",type:"string",enum:["short","long"]},instructions:{default:null,type:["object","null"],description:"When non-null, an InstructionsOptions object that will completely override the built-in instructions."},show_quit_button:{type:"boolean",default:!1,description:"Should the activity quit button be shown?"},show_fps:{type:"boolean",default:!1,description:"Should the FPS be shown?"},show_locale_picker:{type:"boolean",default:!1,description:"Should the icon that allows the participant to switch the locale be shown?"},seed:{type:["string","null"],default:null,description:"Optional seed for the seeded pseudo-random number generator. When null, the default Math.random() is used."},scoring:{type:"boolean",default:!1,description:"Should scoring data be generated? Default is false."},scoring_filter_response_time_duration_ms:{type:"array",items:{type:"number"},default:[100,1e4],description:"When scoring, values of response_time_duration_ms less than the lower bound or greater than the upper bound are discarded. This array contains two numbers, the lower and upper bounds."}},r={activity_begin_iso8601_timestamp:{type:"string",format:"date-time",description:"ISO 8601 timestamp at the beginning of the game activity."},trial_begin_iso8601_timestamp:{type:["string","null"],format:"date-time",description:"ISO 8601 timestamp at the beginning of the trial. Null if trial was skipped."},trial_end_iso8601_timestamp:{type:["string","null"],format:"date-time",description:"ISO 8601 timestamp at the end of the trial (when user presses 'Same' or 'Different'). Null if trial was skipped."},trial_index:{type:["integer","null"],description:"Index of the trial within this assessment, 0-based."},present_shapes:{description:"Configuration of shapes shown to the user in the presentation phase. Null if trial was skipped.",type:["array","null"],items:{type:"object",properties:{shape_index:{type:"integer",description:"Index of the shape within the library of shapes, 0-based"},color_name:{type:"string",description:"Human-friendly name of color."},rgba_color:{type:"array",description:"Color as array, [r,g,b,a].",items:{type:"number"}},location:{type:"object",description:"Location of shape.",properties:{row:{type:"number",description:"Row of the shape, 0-based."},column:{type:"number",description:"Column of the shape, 0-based."}}}}}},response_shapes:{description:"Configuration of shapes shown to the user in the response phase. Null if trial was skipped.",type:["array","null"],items:{type:"object",properties:{shape_index:{type:"integer",description:"Index of the shape within the library of shapes, 0-based"},color_name:{type:"string",description:"Human-friendly name of color."},rgba_color:{type:"array",description:"Color as array, [r,g,b,a].",items:{type:"number"}},location:{type:"object",description:"Location of shape.",properties:{row:{type:"number",description:"Row of the shape, 0-based."},column:{type:"number",description:"Column of the shape, 0-based."}}}}}},response_time_duration_ms:{type:["number","null"],description:"Milliseconds from when the response configuration of shapes is shown until the user taps a response. Null if trial was skipped."},user_response:{type:["string","null"],enum:["same","different"],description:"User's response to whether the shapes are same colors or different."},user_response_correct:{type:["boolean","null"],description:"Was the user's response correct?"},quit_button_pressed:{type:"boolean",description:"Was the quit button pressed?"}},n={activity_begin_iso8601_timestamp:{type:"string",format:"date-time",description:"ISO 8601 timestamp at the beginning of the game activity."},first_trial_begin_iso8601_timestamp:{type:["string","null"],format:"date-time",description:"ISO 8601 timestamp at the beginning of the first trial. Null if no trials were completed."},last_trial_end_iso8601_timestamp:{type:["string","null"],format:"date-time",description:"ISO 8601 timestamp at the end of the last trial. Null if no trials were completed."},response_time_filter_lower_bound:{type:"number",description:"Response times less than this lower bound were discarded when calculating filtered response times."},response_time_filter_upper_bound:{type:"number",description:"Response times greater than this upper bound were discarded when calculating filtered response times."},n_trials:{type:"integer",description:"Number of trials completed."},flag_trials_match_expected:{type:"integer",description:"Does the number of completed and expected trials match? 1 = true, 0 = false."},n_trials_correct:{type:"integer",description:"Number of correct trials."},n_trials_incorrect:{type:"integer",description:"Number of incorrect trials."},participant_score:{type:["number","null"],description:"Participant-facing score, calculated as (number of correct trials / number of trials attempted) * 100. This is a simple metric to provide feedback to the participant. Null if no trials attempted."},flag_trials_lt_expected:{type:"number",description:"Is the number of completed trials fewer than expected? 1 = true, 0 = false."},flag_trials_gt_expected:{type:"number",description:"Is the number of completed trials greater than expected? 1 = true, 0 = false."},n_trials_HIT:{type:"number",description:"Number of HIT trials (correctly identified a 'different' trial)"},n_trials_MISS:{type:"number",description:"Number of MISS trials (failed to detect a 'different' trial, responded 'same')"},n_trials_FA:{type:"number",description:"Number of False Alarm trials (incorrectly responded 'different' on a 'same' trial)"},n_trials_CR:{type:"number",description:"Number of Correct Rejection trials (correctly responded 'same' on a 'same' trial)"},n_trials_type_same:{type:"number",description:"Number of trials where the true signal type was 'SAME' (presented and response shapes were identical)"},n_trials_type_different:{type:"number",description:"Number of trials where the true signal type was 'DIFFERENT' (response shapes differed from presented)"},HIT_rate:{type:["number","null"],description:"Proportion of 'different' trials correctly identified as different. Calculated as n_trials_HIT / n_trials_type_different"},MISS_rate:{type:["number","null"],description:"Proportion of 'different' trials incorrectly identified as same. Calculated as 1 - HIT_rate"},FA_rate:{type:["number","null"],description:"Proportion of 'same' trials incorrectly identified as different. Calculated as n_trials_FA / n_trials_type_same"},CR_rate:{type:["number","null"],description:"Proportion of 'same' trials correctly identified as same. Calculated as 1 - FA_rate"},n_trials_rt_invalid:{type:"number",description:"Number of trials with null or non-positive response times (excluded from RT calculations)"},median_rt_overall_valid:{type:["number","null"],description:"Median response time (ms) across all trials with valid (non-null, positive) response times. No outlier filtering applied"},sd_rt_overall_valid:{type:["number","null"],description:"Standard deviation of response time (ms) across all trials with valid response times. No outlier filtering applied"},median_rt_HIT_valid:{type:["number","null"],description:"Median response time (ms) for HIT trials with valid response times. No outlier filtering"},sd_rt_HIT_valid:{type:["number","null"],description:"Standard deviation of response time (ms) for HIT trials with valid response times. No outlier filtering"},median_rt_MISS_valid:{type:["number","null"],description:"Median response time (ms) for MISS trials with valid response times. No outlier filtering"},sd_rt_MISS_valid:{type:["number","null"],description:"Standard deviation of response time (ms) for MISS trials with valid response times. No outlier filtering"},median_rt_FA_valid:{type:["number","null"],description:"Median response time (ms) for False Alarm trials with valid response times. No outlier filtering"},sd_rt_FA_valid:{type:["number","null"],description:"Standard deviation of response time (ms) for False Alarm trials with valid response times. No outlier filtering"},median_rt_CR_valid:{type:["number","null"],description:"Median response time (ms) for Correct Rejection trials with valid response times. No outlier filtering"},sd_rt_CR_valid:{type:["number","null"],description:"Standard deviation of response time (ms) for Correct Rejection trials with valid response times. No outlier filtering"},median_rt_overall_valid_filtered:{type:["number","null"],description:"Median response time (ms) across all valid trials after removing outliers, as specified in response_time_filter_lower_bound and response_time_filter_upper_bound."},sd_rt_overall_valid_filtered:{type:["number","null"],description:"Standard deviation of response time (ms) across all valid trials after removing outliers, as specified in response_time_filter_lower_bound and response_time_filter_upper_bound."},n_outliers_rt_overall_valid:{type:"number",description:"Number of valid trials removed as RT outliers, as specified in response_time_filter_lower_bound and response_time_filter_upper_bound."},median_rt_HIT_valid_filtered:{type:["number","null"],description:"Median response time (ms) for HIT trials after removing outliers, as specified in response_time_filter_lower_bound and response_time_filter_upper_bound."},sd_rt_HIT_valid_filtered:{type:["number","null"],description:"Standard deviation of response time (ms) for HIT trials after removing outliers, as specified in response_time_filter_lower_bound and response_time_filter_upper_bound."},n_outliers_rt_HIT_valid:{type:"number",description:"Number of HIT trials removed as RT outliers, as specified in response_time_filter_lower_bound and response_time_filter_upper_bound."},median_rt_MISS_valid_filtered:{type:["number","null"],description:"Median response time (ms) for MISS trials after removing outliers, as specified in response_time_filter_lower_bound and response_time_filter_upper_bound."},sd_rt_MISS_valid_filtered:{type:["number","null"],description:"Standard deviation of response time (ms) for MISS trials after removing outliers, as specified in response_time_filter_lower_bound and response_time_filter_upper_bound."},n_outliers_rt_MISS_valid:{type:"number",description:"Number of MISS trials removed as RT outliers, as specified in response_time_filter_lower_bound and response_time_filter_upper_bound."},median_rt_FA_valid_filtered:{type:["number","null"],description:"Median response time (ms) for False Alarm trials after removing outliers, as specified in response_time_filter_lower_bound and response_time_filter_upper_bound."},sd_rt_FA_valid_filtered:{type:["number","null"],description:"Standard deviation of response time (ms) for False Alarm trials after removing outliers, as specified in response_time_filter_lower_bound and response_time_filter_upper_bound."},n_outliers_rt_FA_valid:{type:"number",description:"Number of False Alarm trials removed as RT outliers, as specified in response_time_filter_lower_bound and response_time_filter_upper_bound."},median_rt_CR_valid_filtered:{type:["number","null"],description:"Median response time (ms) for Correct Rejection trials after removing outliers, as specified in response_time_filter_lower_bound and response_time_filter_upper_bound."},sd_rt_CR_valid_filtered:{type:["number","null"],description:"Standard deviation of response time (ms) for Correct Rejection trials after removing outliers, as specified in response_time_filter_lower_bound and response_time_filter_upper_bound."},n_outliers_rt_CR_valid:{type:["number","null"],description:"Number of Correct Rejection trials removed as RT outliers, as specified in response_time_filter_lower_bound and response_time_filter_upper_bound."}},i={name:"Color Shapes",id:"color-shapes",publishUuid:"394cb010-2ccf-4a87-9d23-cda7fb07a960",version:"0.8.34 (38a5862e)",moduleMetadata:{name:"@m2c2kit/assessment-color-shapes",version:"0.8.34",dependencies:{"@m2c2kit/addons":"0.3.35","@m2c2kit/core":"0.3.36","@m2c2kit/data-calc":"0.8.7"}},translation:{configuration:{baseLocale:"en-US"},"en-US":{localeName:"English",INSTRUCTIONS_TITLE:"Color Shapes",SHORT_INSTRUCTIONS_TEXT_PAGE_1:"Try to remember the color of 3 shapes, because they will soon disappear. When the shapes reappear, answer whether they have the SAME or DIFFERENT colors as they had before",INSTRUCTIONS_TEXT_PAGE_1:"Try to remember the color of 3 shapes, because they will soon disappear.",INSTRUCTIONS_TEXT_PAGE_2:"Next you will see the same shapes reappear.",INSTRUCTIONS_TEXT_PAGE_3:"Answer whether the shapes have the SAME or DIFFERENT colors as they had before.",START_BUTTON_TEXT:"START",NEXT_BUTTON_TEXT:"Next",BACK_BUTTON_TEXT:"Back",GET_READY_COUNTDOWN_TEXT:"GET READY!",SAME_BUTTON_TEXT:"Same",DIFFERENT_BUTTON_TEXT:"Different",TRIALS_COMPLETE_SCENE_TEXT:"This activity is complete.",TRIALS_COMPLETE_SCENE_BUTTON_TEXT:"OK"},"es-MX":{localeName:"Espa\xF1ol",INSTRUCTIONS_TITLE:"Formas de Color",INSTRUCTIONS_TEXT_PAGE_1:"Intenta recordar el color de las 3 formas, porque pronto desaparecer\xE1n.",INSTRUCTIONS_TEXT_PAGE_2:"Luego ver\xE1s reaparecer las mismas formas.",INSTRUCTIONS_TEXT_PAGE_3:"Responde si las formas tienen el MISMO o DIFERENTE color que antes.",START_BUTTON_TEXT:"COMENZAR",NEXT_BUTTON_TEXT:"Siguiente",BACK_BUTTON_TEXT:"Atr\xE1s",GET_READY_COUNTDOWN_TEXT:"PREP\xC1RESE",SAME_BUTTON_TEXT:"Mismo",DIFFERENT_BUTTON_TEXT:"Diferente",TRIALS_COMPLETE_SCENE_TEXT:"Esta actividad est\xE1 completa.",TRIALS_COMPLETE_SCENE_BUTTON_TEXT:"OK"},"de-DE":{localeName:"Deutsch",INSTRUCTIONS_TITLE:"Farb-Formen",INSTRUCTIONS_TEXT_PAGE_1:"Oben und unten sehen Sie Symbolpaare.",INSTRUCTIONS_TEXT_PAGE_2:"Ihre Aufgabe wird es sein, auf dasjenige untere Paar zu tippen, welches mit einem der obigen Paare exakt \xFCbereinstimmt.",INSTRUCTIONS_TEXT_PAGE_3:"Versuchen Sie bitte, so schnell und korrekt wie m\xF6glich zu sein.",START_BUTTON_TEXT:"START",NEXT_BUTTON_TEXT:"Weiter",BACK_BUTTON_TEXT:"Vorherige",GET_READY_COUNTDOWN_TEXT:"BEREIT MACHEN",SAME_BUTTON_TEXT:"Gleich",DIFFERENT_BUTTON_TEXT:"Unterschiedlich",TRIALS_COMPLETE_SCENE_TEXT:"Die Aufgabe ist beendet.",TRIALS_COMPLETE_SCENE_BUTTON_TEXT:"OK"}},shortDescription:"Color Shapes is a visual array change detection task, measuring intra-item feature binding, where participants determine if shapes change color across two sequential presentations of shape stimuli.",longDescription:'Color Shapes is a change detection paradigm used to measure visual short-term memory binding (Parra et al., 2009). Participants are asked to memorize the shapes and colors of three different polygons for 3 seconds. The three polygons are then removed from the screen and re-displayed at different locations, either having the same or different colors. Participants are then asked to decide whether the combination of colors and shapes are the "Same" or "Different" between the study and test phases.',showFps:t.show_fps.default,width:400,height:800,trialSchema:r,scoringSchema:n,parameters:t,fonts:[{fontName:"roboto",url:"fonts/roboto/Roboto-Regular.ttf"}],images:[{imageName:"instructions-1",height:256,width:256,url:"images/cs-instructions-1.png"},{imageName:"instructions-2",height:256,width:256,url:"images/cs-instructions-2.png"},{imageName:"instructions-3",height:350,width:300,url:"images/cs-instructions-3.png",localize:!0},{imageName:"circle-x",height:32,width:32,url:"images/circle-x.svg"}]};super(i)}async initialize(){await super.initialize();const t=this,r=t.getParameter("seed");typeof r=="string"&&L.setSeed(r);const n=96,s=350,i=t.getParameter("number_of_shapes_shown"),e=this.makeShapes(n);if(t.getParameter("show_quit_button")){const T=new Fe({imageName:"circle-x",position:{x:380,y:20},isUserInteractionEnabled:!0});t.addFreeNode(T),T.onTapDown(w=>{t.removeAllFreeNodes(),w.handled=!0;const S=new J;if(t.addScene(S),t.presentScene(S),t.addTrialData("quit_button_pressed",!0),t.trialComplete(),t.getParameter("scoring")){const z=t.calculateScores([],{rtLowerBound:t.getParameter("scoring_filter_response_time_duration_ms")[0],rtUpperBound:t.getParameter("scoring_filter_response_time_duration_ms")[1],numberOfTrials:t.getParameter("number_of_trials")});t.addScoringData(z),t.scoringComplete()}t.cancel()})}let a;t.getParameter("show_locale_picker")&&(a=new xe,t.addFreeNode(a));let o;const c=t.getParameter("instructions");if(c)o=de.create(c);else switch(t.getParameter("instruction_type")){case"short":{o=de.create({instructionScenes:[{title:"INSTRUCTIONS_TITLE",text:"SHORT_INSTRUCTIONS_TEXT_PAGE_1",imageName:"instructions-1",imageAboveText:!1,imageMarginTop:32,textFontSize:24,titleFontSize:30,textVerticalBias:.2,nextButtonText:"START_BUTTON_TEXT",nextButtonBackgroundColor:I.Green,nextSceneTransition:ue.none()}]});break}case"long":{o=de.create({instructionScenes:[{title:"INSTRUCTIONS_TITLE",text:"INSTRUCTIONS_TEXT_PAGE_1",imageName:"instructions-1",imageAboveText:!1,imageMarginTop:32,textFontSize:24,titleFontSize:30,textVerticalBias:.2,nextButtonText:"NEXT_BUTTON_TEXT",backButtonText:"BACK_BUTTON_TEXT"},{title:"INSTRUCTIONS_TITLE",text:"INSTRUCTIONS_TEXT_PAGE_2",imageName:"instructions-2",imageAboveText:!1,imageMarginTop:32,textFontSize:24,titleFontSize:30,textVerticalBias:.2,nextButtonText:"NEXT_BUTTON_TEXT",backButtonText:"BACK_BUTTON_TEXT"},{title:"INSTRUCTIONS_TITLE",text:"INSTRUCTIONS_TEXT_PAGE_3",imageName:"instructions-3",imageAboveText:!1,imageMarginTop:32,textFontSize:24,titleFontSize:30,textVerticalBias:.2,nextButtonText:"START_BUTTON_TEXT",nextButtonBackgroundColor:I.Green,backButtonText:"BACK_BUTTON_TEXT"}]});break}default:throw new ye("invalid value for instruction_type")}o[0].onAppear(()=>{t.addTrialData("activity_begin_iso8601_timestamp",this.beginIso8601Timestamp)}),t.addScenes(o);const l=new Ue({milliseconds:3e3,text:"GET_READY_COUNTDOWN_TEXT",zeroDwellMilliseconds:1e3,transition:ue.none()});t.addScene(l);const p=t.getParameter("cells_per_side"),d=t.getParameter("cells_per_side"),m=t.getParameter("number_of_trials"),g=t.getParameter("shape_colors"),v=[],C=t.getParameter("cells_per_side"),N=C,K=t.getParameter("number_of_different_colors_trials"),V=L.fromRangeWithoutReplacement(K,0,m-1);for(let T=0;T<m;T++){const w=new Array,S=new Array,z=L.fromRangeWithoutReplacement(i,0,e.length-1),G=L.fromRangeWithoutReplacement(i,0,g.length-1),te=y=>!!(y.map(f=>f.row===0&&f.column===0).some(f=>f===!0)&&y.map(f=>f.row===1&&f.column===1).some(f=>f===!0)&&y.map(f=>f.row===2&&f.column===2).some(f=>f===!0)||y.map(f=>f.row===2&&f.column===0).some(f=>f===!0)&&y.map(f=>f.row===1&&f.column===1).some(f=>f===!0)&&y.map(f=>f.row===0&&f.column===2).some(f=>f===!0)),E=y=>{const f=new Set(y.map(W=>W.row)).size,H=new Set(y.map(W=>W.column)).size;return!(f!==1&&H!==1)};let le=!1,re;do re=L.fromGridWithoutReplacement(i,C,N),!E(re)&&!te(re)?le=!0:le=!1;while(!le);for(let y=0;y<i;y++){const f={shape:e[z[y]],shapeIndex:z[y],color:g[G[y]].rgbaColor,colorName:g[G[y]].colorName,location:re[y]};w.push(f)}let ce=!1,ne;do ne=L.fromGridWithoutReplacement(i,C,N),!E(ne)&&!te(ne)?ce=!0:ce=!1;while(!ce);for(let y=0;y<i;y++){const f={shape:w[y].shape,shapeIndex:z[y],color:w[y].color,colorName:g[G[y]].colorName,location:ne[y]};S.push(f)}let ge=0;if(V.includes(T)){const y=t.getParameter("number_of_shapes_changing_color");if(y>i)throw new ye(`number_of_shapes_changing_color is ${y}, but it must be less than or equal to number_of_shapes_shown (which is ${i}).`);const H=L.fromRangeWithoutReplacement(y,0,i-1).map(j=>S[j]);ge=H.length;const W=H[0].color;for(let j=0;j<y;j++){const be=H[j];j+1<y?be.color=H[j+1].color:be.color=W}}v.push({presentShapes:w,responseShapes:S,numberOfShapesWithDifferentColors:ge})}const O=new J;t.addScene(O);const B=new R({rect:{size:{width:s,height:s}},fillColor:I.Transparent,strokeColor:I.Gray,lineWidth:4,position:{x:200,y:300}});O.addChild(B);const D=new Te({text:"+",fontSize:32,fontColor:I.Black,localize:!1});B.addChild(D),O.onAppear(()=>{t.addTrialData("activity_begin_iso8601_timestamp",this.beginIso8601Timestamp),t.addTrialData("trial_begin_iso8601_timestamp",new Date().toISOString()),O.run(x.sequence([x.wait({duration:t.getParameter("fixation_duration_ms")}),x.custom({callback:()=>{t.presentScene(k)}})]))});const k=new J;t.addScene(k);const A=new R({rect:{size:{width:s,height:s}},fillColor:I.Transparent,strokeColor:I.Gray,lineWidth:4,position:{x:200,y:300}});k.addChild(A);const Z=new we({rows:p,columns:d,size:{width:s,height:s},position:{x:200,y:300},backgroundColor:I.Transparent,gridLineColor:I.Transparent});k.addChild(Z),k.onAppear(()=>{const T=v[t.trialIndex];for(let w=0;w<T.presentShapes.length;w++){const S=T.presentShapes[w].shape;S.fillColor=T.presentShapes[w].color,S.position={x:0,y:0},Z.addAtCell(S,T.presentShapes[w].location.row,T.presentShapes[w].location.column)}k.run(x.sequence([x.wait({duration:t.getParameter("shapes_presented_duration_ms")}),x.custom({callback:()=>{Z.removeAllGridChildren()}}),x.wait({duration:t.getParameter("shapes_removed_duration_ms")}),x.custom({callback:()=>{Z.removeAllGridChildren(),t.presentScene(P)}})]))});const P=new J;t.addScene(P);const Ae=new R({rect:{size:{width:s,height:s}},fillColor:I.Transparent,strokeColor:I.Gray,lineWidth:4,position:{x:200,y:300}});P.addChild(Ae);const ae=new we({rows:p,columns:d,size:{width:s,height:s},position:{x:200,y:300},backgroundColor:I.Transparent,gridLineColor:I.Transparent});P.addChild(ae),P.onAppear(()=>{const T=v[t.trialIndex];for(let w=0;w<T.responseShapes.length;w++){const S=T.responseShapes[w].shape;S.fillColor=T.responseShapes[w].color,S.position={x:0,y:0},ae.addAtCell(S,T.responseShapes[w].location.row,T.responseShapes[w].location.column)}Y.isUserInteractionEnabled=!0,Q.isUserInteractionEnabled=!0,pe.startNew("rt")});const Y=new _e({text:"SAME_BUTTON_TEXT",position:{x:100,y:700},size:{width:150,height:50}});P.addChild(Y),Y.onTapDown(()=>{Y.isUserInteractionEnabled=!1,he(!1)});const Q=new _e({text:"DIFFERENT_BUTTON_TEXT",position:{x:300,y:700},size:{width:150,height:50}});P.addChild(Q),Q.onTapDown(()=>{Q.isUserInteractionEnabled=!1,he(!0)});const he=T=>{const w=pe.elapsed("rt");pe.remove("rt"),ae.removeAllGridChildren(),t.addTrialData("trial_end_iso8601_timestamp",new Date().toISOString());const S=v[t.trialIndex];t.addTrialData("response_time_duration_ms",w),t.addTrialData("user_response",T?"different":"same");const z=S.numberOfShapesWithDifferentColors===0&&!T||S.numberOfShapesWithDifferentColors>0&&T;t.addTrialData("user_response_correct",z);const G=S.presentShapes.map(E=>({shape_index:E.shapeIndex,color_name:E.colorName,rgba_color:E.color,location:E.location}));t.addTrialData("present_shapes",G),t.addTrialData("quit_button_pressed",!1);const te=S.responseShapes.map(E=>({shape_index:E.shapeIndex,color_name:E.colorName,rgba_color:E.color,location:E.location}));if(t.addTrialData("response_shapes",te),t.addTrialData("trial_index",t.trialIndex),t.trialComplete(),t.trialIndex<m)t.presentScene(O);else{if(t.getParameter("scoring")){const E=t.calculateScores(t.data.trials,{rtLowerBound:t.getParameter("scoring_filter_response_time_duration_ms")[0],rtUpperBound:t.getParameter("scoring_filter_response_time_duration_ms")[1],numberOfTrials:t.getParameter("number_of_trials")});t.addScoringData(E),t.scoringComplete()}t.getParameter("show_trials_complete_scene")?t.presentScene($,ue.slide({direction:ke.Left,duration:500,easing:Be.sinusoidalInOut})):t.end()}},$=new J;t.addScene($);const Re=new Te({text:"TRIALS_COMPLETE_SCENE_TEXT",position:{x:200,y:400}});$.addChild(Re);const ee=new _e({text:"TRIALS_COMPLETE_SCENE_BUTTON_TEXT",position:{x:200,y:650}});ee.isUserInteractionEnabled=!0,ee.onTapDown(()=>{ee.isUserInteractionEnabled=!1,$.removeAllChildren(),t.end()}),$.addChild(ee),$.onSetup(()=>{t.removeAllFreeNodes()})}calculateScores(t,r){const n=new b(t),s=n.filter(e=>e.quit_button_pressed===!1).length;return n.mutate({metric_accuracy:e=>{const a=e.user_response,o=e.user_response_correct;return a==="same"&&o===!0?"CR":a==="same"&&o===!1?"MISS":a==="different"&&o===!0?"HIT":a==="different"&&o===!1?"FA":null},metric_trial_type:e=>{const a=e.user_response,o=e.user_response_correct;return a==="same"&&o===!0?"SAME":a==="same"&&o===!1||a==="different"&&o===!0?"DIFFERENT":a==="different"&&o===!1?"SAME":null},is_valid:e=>typeof e.response_time_duration_ms=="number"&&e.response_time_duration_ms>0}).summarize({activity_begin_iso8601_timestamp:this.beginIso8601Timestamp,first_trial_begin_iso8601_timestamp:Se("trial_begin_iso8601_timestamp").slice(0).pull("trial_begin_iso8601_timestamp"),last_trial_end_iso8601_timestamp:Se("-trial_end_iso8601_timestamp").slice(0).pull("trial_end_iso8601_timestamp"),n_trials:s,flag_trials_match_expected:s===r.numberOfTrials?1:0,flag_trials_lt_expected:s<r.numberOfTrials?1:0,flag_trials_gt_expected:s>r.numberOfTrials?1:0,n_trials_HIT:h(e=>e.metric_accuracy==="HIT").length,n_trials_MISS:h(e=>e.metric_accuracy==="MISS").length,n_trials_FA:h(e=>e.metric_accuracy==="FA").length,n_trials_CR:h(e=>e.metric_accuracy==="CR").length,n_trials_type_same:h(e=>e.metric_trial_type==="SAME").length,n_trials_type_different:h(e=>e.metric_trial_type==="DIFFERENT").length,HIT_rate:e=>{const a=e.filter(o=>o.metric_trial_type==="DIFFERENT").length;return a>0?e.filter(o=>o.metric_accuracy==="HIT").length/a:null},MISS_rate:e=>{const a=e.filter(o=>o.metric_trial_type==="DIFFERENT").length;return a>0?1-e.filter(o=>o.metric_accuracy==="HIT").length/a:null},FA_rate:e=>{const a=e.filter(o=>o.metric_trial_type==="SAME").length;return a>0?e.filter(o=>o.metric_accuracy==="FA").length/a:null},CR_rate:e=>{const a=e.filter(o=>o.metric_trial_type==="SAME").length;return a>0?1-e.filter(o=>o.metric_accuracy==="FA").length/a:null},median_rt_overall_valid:M(h(e=>e.is_valid).pull("response_time_duration_ms")),sd_rt_overall_valid:F(h(e=>e.is_valid).pull("response_time_duration_ms")),median_rt_overall_valid_filtered:M(h(e=>e.is_valid).filter(e=>e.response_time_duration_ms>=r.rtLowerBound&&e.response_time_duration_ms<=r.rtUpperBound).pull("response_time_duration_ms")),sd_rt_overall_valid_filtered:F(h(e=>e.is_valid).filter(e=>e.response_time_duration_ms>=r.rtLowerBound&&e.response_time_duration_ms<=r.rtUpperBound).pull("response_time_duration_ms")),n_trials_rt_invalid:h(e=>!e.is_valid).length,n_outliers_rt_overall_valid:h(e=>e.is_valid).filter(e=>e.response_time_duration_ms<r.rtLowerBound||e.response_time_duration_ms>r.rtUpperBound).length,response_time_filter_lower_bound:r.rtLowerBound,response_time_filter_upper_bound:r.rtUpperBound,median_rt_HIT_valid:M(h(e=>e.is_valid).filter(e=>e.metric_accuracy==="HIT").pull("response_time_duration_ms")),sd_rt_HIT_valid:F(h(e=>e.is_valid).filter(e=>e.metric_accuracy==="HIT").pull("response_time_duration_ms")),median_rt_HIT_valid_filtered:M(h(e=>e.is_valid).filter(e=>e.metric_accuracy==="HIT"&&e.response_time_duration_ms>=r.rtLowerBound&&e.response_time_duration_ms<=r.rtUpperBound).pull("response_time_duration_ms")),sd_rt_HIT_valid_filtered:F(h(e=>e.is_valid).filter(e=>e.metric_accuracy==="HIT"&&e.response_time_duration_ms>=r.rtLowerBound&&e.response_time_duration_ms<=r.rtUpperBound).pull("response_time_duration_ms")),n_outliers_rt_HIT_valid:h(e=>e.is_valid).filter(e=>e.metric_accuracy==="HIT").filter(e=>e.response_time_duration_ms<r.rtLowerBound||e.response_time_duration_ms>r.rtUpperBound).length,median_rt_MISS_valid:M(h(e=>e.is_valid).filter(e=>e.metric_accuracy==="MISS").pull("response_time_duration_ms")),sd_rt_MISS_valid:F(h(e=>e.is_valid).filter(e=>e.metric_accuracy==="MISS").pull("response_time_duration_ms")),median_rt_MISS_valid_filtered:M(h(e=>e.is_valid).filter(e=>e.metric_accuracy==="MISS"&&e.response_time_duration_ms>=r.rtLowerBound&&e.response_time_duration_ms<=r.rtUpperBound).pull("response_time_duration_ms")),sd_rt_MISS_valid_filtered:F(h(e=>e.is_valid).filter(e=>e.metric_accuracy==="MISS"&&e.response_time_duration_ms>=r.rtLowerBound&&e.response_time_duration_ms<=r.rtUpperBound).pull("response_time_duration_ms")),n_outliers_rt_MISS_valid:h(e=>e.is_valid).filter(e=>e.metric_accuracy==="MISS").filter(e=>e.response_time_duration_ms<r.rtLowerBound||e.response_time_duration_ms>r.rtUpperBound).length,median_rt_FA_valid:M(h(e=>e.is_valid).filter(e=>e.metric_accuracy==="FA").pull("response_time_duration_ms")),sd_rt_FA_valid:F(h(e=>e.is_valid).filter(e=>e.metric_accuracy==="FA").pull("response_time_duration_ms")),median_rt_FA_valid_filtered:M(h(e=>e.is_valid).filter(e=>e.metric_accuracy==="FA"&&e.response_time_duration_ms>=r.rtLowerBound&&e.response_time_duration_ms<=r.rtUpperBound).pull("response_time_duration_ms")),sd_rt_FA_valid_filtered:F(h(e=>e.is_valid).filter(e=>e.metric_accuracy==="FA"&&e.response_time_duration_ms>=r.rtLowerBound&&e.response_time_duration_ms<=r.rtUpperBound).pull("response_time_duration_ms")),n_outliers_rt_FA_valid:h(e=>e.is_valid).filter(e=>e.metric_accuracy==="FA").filter(e=>e.response_time_duration_ms<r.rtLowerBound||e.response_time_duration_ms>r.rtUpperBound).length,median_rt_CR_valid:M(h(e=>e.is_valid).filter(e=>e.metric_accuracy==="CR").pull("response_time_duration_ms")),sd_rt_CR_valid:F(h(e=>e.is_valid).filter(e=>e.metric_accuracy==="CR").pull("response_time_duration_ms")),median_rt_CR_valid_filtered:M(h(e=>e.is_valid).filter(e=>e.metric_accuracy==="CR"&&e.response_time_duration_ms>=r.rtLowerBound&&e.response_time_duration_ms<=r.rtUpperBound).pull("response_time_duration_ms")),sd_rt_CR_valid_filtered:F(h(e=>e.is_valid).filter(e=>e.metric_accuracy==="CR"&&e.response_time_duration_ms>=r.rtLowerBound&&e.response_time_duration_ms<=r.rtUpperBound).pull("response_time_duration_ms")),n_outliers_rt_CR_valid:h(e=>e.is_valid).filter(e=>e.metric_accuracy==="CR").filter(e=>e.response_time_duration_ms<r.rtLowerBound||e.response_time_duration_ms>r.rtUpperBound).length,n_trials_correct:h(e=>e.metric_accuracy==="HIT"||e.metric_accuracy==="CR").length,n_trials_incorrect:h(e=>e.metric_accuracy==="MISS"||e.metric_accuracy==="FA").length,participant_score:e=>{const a=e.length;return a===0?null:e.summarize({correct:Ee(oe(e.filter(o=>o.metric_accuracy==="HIT").length).add(oe(e.filter(o=>o.metric_accuracy==="CR").length))).div(oe(a)).mul(oe(100))}).pull("correct")}}).observations}makeShapes(t){const r=new R({path:{pathString:U[0],height:t},lineWidth:0}),n=new R({path:{pathString:U[1],height:t},lineWidth:0}),s=new R({path:{pathString:U[2],height:t*.8},lineWidth:0}),i=new R({path:{pathString:U[3],height:t},lineWidth:0}),e=new R({path:{pathString:U[4],height:t*.8},lineWidth:0}),a=new R({path:{pathString:U[5],height:t},lineWidth:0}),o=new R({path:{pathString:U[6],height:t},lineWidth:0}),c=new R({path:{pathString:U[7],height:t},lineWidth:0});return[r,n,s,i,e,a,o,c]}}const U=["M0 89.94v-2L131.95 0h2v88.7c2.34 1.6 4.47 3.11 6.65 4.55 42.77 28.22 85.54 56.42 128.3 84.63v2c-44.65 29.65-89.3 59.29-133.95 88.94h-1v-90.84C89.44 148.72 44.72 119.33 0 89.94Z","M162 188c-.33 27-.67 54-1 81-26.87-26.18-53.74-52.35-80-77.94V269H0C0 180.83 0 92.67.04 4.5.04 3 .67 1.5 1 0c24.64 29.1 49.15 58.31 73.96 87.26 28.88 33.7 58.01 67.17 87.04 100.74Z","M3 148.86V61.12C41.76 40.75 80.52 20.37 119.28 0h2.91c21.32 20.7 42.64 41.4 63.96 62.11v89.71c-38.44 20.04-76.88 40.09-115.31 60.13h-2.91L3.01 148.86Z","M134 0h2c7.26 22.31 14.38 44.67 21.86 66.9 3.91 11.61 5.47 29.91 13.25 33.27C203 113.94 236.86 123.13 270 134v1L136 269h-1c-11.04-33.58-22.08-67.16-33.21-101.03C67.87 156.98 33.93 145.99 0 135v-1L134 0Z","M107 0h1l108 108v1c-26.67 35.33-53.33 70.66-80 106h-1c-8.82-35.03-17.64-70.07-27-107.28C98.62 145.01 89.81 180 81.01 215h-1C53.33 179.66 26.67 144.33 0 109v-2L107 0Z","M0 1C2.17.67 4.33.05 6.5.04 58.33-.01 110.17 0 162 0v270H2c26.2-22.17 52.41-44.33 78.86-66.71V67.4c-3.85-3.22-7.35-6.2-10.9-9.11C46.64 39.18 23.32 20.09 0 1Z","M95 268.99h-1C62.66 238.66 31.33 208.33 0 178V88C26.67 58.67 53.33 29.33 80 0h1c0 29.45 0 58.89-.01 88.38 35.99 29.57 72 59.09 108.01 88.61v1l-94 91Z","M13 0h67l135 135v1L81 270c-27-.33-54-.67-81-1 11.73-12.51 23.61-24.87 35.16-37.54 33.14-36.35 66.14-72.82 100.23-110.38C94.4 80.52 53.7 40.26 13 0Z"];export{Ve as ColorShapes};
1
+ import{Action as e,Easings as t,Game as n,Label as r,M2Error as i,RandomDraws as a,Scene as o,Shape as s,Sprite as c,Timer as l,Transition as u,TransitionDirection as d,WebColors as f}from"@m2c2kit/core";import{Button as p,CountdownScene as m,Grid as h,Instructions as g,LocalePicker as _}from"@m2c2kit/addons";var v=class extends Error{constructor(e,t){super(e),t&&`cause`in t&&(this.cause=t.cause),this.name=`M2Error`,new.target&&Object.setPrototypeOf(this,new.target.prototype),`captureStackTrace`in Error&&typeof Error.captureStackTrace==`function`?Error.captureStackTrace(this,new.target):this.stack||(this.stack=Error(e).stack)}toJSON(){let e={name:this.name,message:this.message,stack:this.stack};if(this.cause!==void 0)if(this.cause instanceof Error){let t=this.cause;if(typeof t.toJSON==`function`)e.cause=t.toJSON();else{let t={name:this.cause.name,message:this.cause.message,stack:this.cause.stack},n=this.cause;for(let e of Object.keys(n))e in t||(t[e]=n[e]);e.cause=t}}else e.cause=this.cause;let t=this;for(let n of Object.keys(t))n in e||(e[n]=t[n]);return e}};function y(e){"@babel/helpers - typeof";return y=typeof Symbol==`function`&&typeof Symbol.iterator==`symbol`?function(e){return typeof e}:function(e){return e&&typeof Symbol==`function`&&e.constructor===Symbol&&e!==Symbol.prototype?`symbol`:typeof e},y(e)}function b(e,t){if(y(e)!=`object`||!e)return e;var n=e[Symbol.toPrimitive];if(n!==void 0){var r=n.call(e,t||`default`);if(y(r)!=`object`)return r;throw TypeError(`@@toPrimitive must return a primitive value.`)}return(t===`string`?String:Number)(e)}function x(e){var t=b(e,`string`);return y(t)==`symbol`?t:t+``}function S(e,t,n){return(t=x(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function C(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),n.push.apply(n,r)}return n}function w(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]==null?{}:arguments[t];t%2?C(Object(n),!0).forEach(function(t){S(e,t,n[t])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):C(Object(n)).forEach(function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))})}return e}const T=new Map;let E=0;function D(e){return T.get(e)}function O(){let e=(t=>{if(!t)return;let n=t;for(let t of e.ops){let e=n[t.name];if(typeof e!=`function`)throw new v(`chain: method ${t.name} does not exist on DataCalc`);let r=e.apply(n,t.args);if(r instanceof P){n=r;continue}return r}});e.ops=[];let t=(t,n)=>(e.ops.push({name:t,args:n}),e);return e.arrange=(...e)=>t(`arrange`,e),e.slice=(e,n)=>t(`slice`,[e,n]),e.pull=e=>t(`pull`,[e]),e.filter=e=>t(`filter`,[e]),e.mutate=e=>t(`mutate`,[e]),e.select=(...e)=>t(`select`,e),e.groupBy=(...e)=>t(`groupBy`,e),e.ungroup=()=>t(`ungroup`,[]),e.rename=e=>t(`rename`,[e]),e.distinct=()=>t(`distinct`,[]),Object.defineProperty(e,"length",{configurable:!0,get:function(){try{let t=`c${++E}`;if(T.set(t,(e.ops||[]).map(e=>w({},e))),T.size>1e4){let e=T.keys().next().value;e&&T.delete(e)}return`__CHAIN_EXPR__[${t}]`}catch(e){return}}}),e}function k(...e){return O().arrange(...e)}function A(e){return O().filter(e)}function j(e,t){if(e==null)return{};var n={};for(var r in e)if({}.hasOwnProperty.call(e,r)){if(t.includes(r))continue;n[r]=e[r]}return n}function M(e,t){if(e==null)return{};var n,r,i=j(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r<a.length;r++)n=a[r],t.includes(n)||{}.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}const N=[`get`,`set`];var P=class e{constructor(e,t){if(this._groups=[],this._warnings=!1,!Array.isArray(e))throw new v(`DataCalc constructor expects an array of observations as first argument`);for(let t=0;t<e.length;t++)if(e[t]===null||typeof e[t]!=`object`||Array.isArray(e[t]))throw new v(`DataCalc constructor expects all elements to be objects (observations). Element at index ${t} is ${typeof e[t]}. Element: ${JSON.stringify(e[t])}`);if(this._observations=this.deepCopy(e),!(t!=null&&t.skipNormalization)){let t=new Set;for(let n of e)for(let e of Object.keys(n))t.add(e);for(let e of this._observations)for(let n of t)n in e||(e[n]=null)}t!=null&&t.groups&&(this._groups=Array.from(t.groups)),t!=null&&t.warnings&&(this._warnings=!0)}get groups(){return this._groups}get observations(){return this._observations}get rows(){return this._observations}pull(e){if(this._observations.length===0)return this._warnings&&console.warn(`DataCalc.pull(): No observations available to pull variable "${e}" from. Returning null.`),null;this.verifyObservationsContainVariable(e);let t=this._observations.map(t=>t[e]);return t.length===1?t[0]:t}pullScalar(e){if(this._observations.length===0)return this._warnings&&console.warn(`DataCalc.pullScalar(): No observations available to pull variable "${e}" from. Returning null.`),null;if(this._observations.length>1)throw new v(`DataCalc.pullScalar(): Expected 1 observation, but found ${this._observations.length}. Use pull() or pullArray() instead.`);return this.verifyObservationsContainVariable(e),this._observations[0][e]}pullArray(e){return this._observations.length===0?(this._warnings&&console.warn(`DataCalc.pullArray(): No observations available to pull variable "${e}" from. Returning null.`),null):(this.verifyObservationsContainVariable(e),this._observations.map(t=>t[e]))}get length(){return this._observations.length}filter(t){if(this._groups.length>0)throw new v(`filter() cannot be used on grouped data. The data are currently grouped by ${this._groups.join(`, `)}. Ungroup the data first using ungroup().`);return new e(this._observations.filter(t),{groups:this._groups,warnings:this._warnings,skipNormalization:!0})}groupBy(...t){return t.forEach(e=>{this.verifyObservationsContainVariable(e);for(let t=0;t<this._observations.length;t++){let n=this._observations[t][e];if(n===null)continue;let r=typeof n;if(r!==`number`&&r!==`string`&&r!==`boolean`)throw new v(`groupBy(): variable "${e}" contains non-primitive value at index ${t} (type=${r}). Only number, string, boolean, or null are allowed for grouping.`)}}),new e(this._observations,{groups:t,skipNormalization:!0})}ungroup(){return new e(this._observations,{skipNormalization:!0})}mutate(t){if(this._groups.length>0)throw new v(`mutate() cannot be used on grouped data. The data are currently grouped by ${this._groups.join(`, `)}. Ungroup the data first using ungroup().`);return new e(this._observations.map(e=>{let n=w({},e);for(let[r,i]of Object.entries(t))n=w(w({},n),{},{[r]:i(e)});return n}),{groups:this._groups,warnings:this._warnings})}summarize(t){if(this._groups.length===0){let n={};for(let[r,i]of Object.entries(t))if(typeof i==`object`&&i&&`summarizeFunction`in i){let e=i;n[r]=e.summarizeFunction(this,e.parameters,e.options)}else if(typeof i==`function`)try{let t=i(this);if(typeof t==`function`)throw new v(`summarize(): lazy callback for ${r} returned a function; expected a value or array of values.`);if(t instanceof e)throw new v(`summarize(): lazy callback for ${r} returned a DataCalc; expected a value or array of values.`);n[r]=t}catch(e){throw new v(`summarize(): lazy callback for ${r} threw an error: ${e&&e.message?e.message:String(e)}`)}else{if(typeof i==`string`){let t=Array.from(F.matchAll(i,/__CHAIN_EXPR__\[(.*?)\]/g));if(t.length>0){let a=0;for(let n of t){let t=n[1],i=D(t);if(!i)try{i=JSON.parse(decodeURIComponent(t))}catch(e){throw new v(`summarize(): failed to parse chain payload for ${r}`)}let o=this,s;if(!i)throw new v(`summarize(): empty chain ops for ${r}`);for(let t of i){let n=o[t.name];if(typeof n!=`function`)throw new v(`summarize(): chain method ${t.name} does not exist on DataCalc`);let r=n.apply(o,t.args);if(r instanceof e){o=r;continue}if(Array.isArray(r)){s=r.length;break}if(typeof r==`boolean`){s=+!!r;break}s=typeof r==`number`?r:Number(r);break}s===void 0&&(s=o instanceof e?o.length:0),a+=s}let o=i;for(let e of t)o=o.replace(e[0],``);let s=Number(o);Number.isNaN(s)||(a+=s),n[r]=a;continue}}n[r]=i}return new e([n],{groups:this._groups,warnings:this._warnings})}return this.summarizeByGroups(t)}summarizeByGroups(t){let n=new Map;this._observations.forEach(e=>{let t=this._groups.map(t=>String(e[t])).join(`|`);n.has(t)||n.set(t,[]);let r=n.get(t);r?r.push(e):n.set(t,[e])});let r=[];return n.forEach((n,i)=>{let a=i.split(`|`),o=n[0],s={};this._groups.forEach((e,t)=>{let n=a[t];if(o[e]===null)s[e]=null;else{let t=typeof o[e];t===`number`?s[e]=Number(n):t===`boolean`?s[e]=n===`true`:s[e]=n}});let c=new e(n);for(let[n,r]of Object.entries(t))if(typeof r==`object`&&r&&`summarizeFunction`in r){let e=r;s[n]=e.summarizeFunction(c,e.parameters,e.options)}else if(typeof r==`function`)try{let t=r(c);if(typeof t==`function`)throw new v(`summarize(): lazy callback for ${n} returned a function; expected a value or array of values.`);if(t instanceof e)throw new v(`summarize(): lazy callback for ${n} returned a DataCalc; expected a value or array of values.`);s[n]=t}catch(e){throw new v(`summarize(): lazy callback for ${n} threw an error: ${e&&e.message?e.message:String(e)}`)}else{if(typeof r==`string`){let t=Array.from(F.matchAll(r,/__CHAIN_EXPR__\[(.*?)\]/g));if(t.length>0){let i=0;for(let r of t){let t=r[1],a=D(t);if(!a)try{a=JSON.parse(decodeURIComponent(t))}catch(e){throw new v(`summarize(): failed to parse chain payload for ${n}`)}let o=c,s;if(!a)throw new v(`summarize(): empty chain ops for ${n}`);for(let t of a){let n=o[t.name];if(typeof n!=`function`)throw new v(`summarize(): chain method ${t.name} does not exist on DataCalc`);let r=n.apply(o,t.args);if(r instanceof e){o=r;continue}if(Array.isArray(r)){s=r.length;break}if(typeof r==`boolean`){s=+!!r;break}s=typeof r==`number`?r:Number(r);break}s===void 0&&(s=o instanceof e?o.length:0),i+=s}let a=r;for(let e of t)a=a.replace(e[0],``);let o=Number(a);Number.isNaN(o)||(i+=o),s[n]=i;continue}}s[n]=r}r.push(s)}),new e(r,{groups:this._groups,warnings:this._warnings})}select(...t){let n=[],r=[];t.forEach(e=>{e.startsWith(`-`)?r.push(e.substring(1)):n.push(e)}),[...n.length>0?n:Object.keys(this._observations[0]||{}),...r].forEach(e=>{this.verifyObservationsContainVariable(e)});let i=new Set(r);return new e(this._observations.map(e=>{let t={};return n.length>0?n.forEach(n=>{i.has(n)||(t[n]=e[n])}):Object.keys(e).forEach(n=>{i.has(n)||(t[n]=e[n])}),t}),{groups:this._groups,warnings:this._warnings})}arrange(...t){if(this._groups.length>0)throw new v(`arrange() cannot be used on grouped data. The data are currently grouped by ${this._groups.join(`, `)}. Ungroup the data first using ungroup().`);return new e([...this._observations].sort((e,n)=>{for(let r of t){let t=r,i=1;if(r.startsWith(`-`)&&(t=r.substring(1),i=-1),!(t in e)||!(t in n))throw new v(`arrange(): variable ${t} does not exist in all observations`);let a=e[t],o=n[t];if(typeof a!=typeof o)return i*(String(a)<String(o)?-1:1);if(a<o)return-1*i;if(a>o)return 1*i}return 0}),{groups:this._groups,warnings:this._warnings,skipNormalization:!0})}distinct(){let t=new Set;return new e(this._observations.filter(e=>{let n=JSON.stringify(this.normalizeForComparison(e));return t.has(n)?!1:(t.add(n),!0)}),{groups:this._groups,warnings:this._warnings,skipNormalization:!0})}rename(t){if(this._observations.length===0)throw new v(`Cannot rename variables on an empty dataset`);if(Object.values(t).forEach(e=>{this.verifyObservationsContainVariable(e)}),this._observations.length>0){let e=new Set(Object.keys(this._observations[0])),n=new Set(Object.values(t)),r=Object.keys(t).filter(t=>e.has(t)&&!n.has(t));r.length>0&&this._warnings&&console.warn(`DataCalc.rename(): renaming will overwrite existing variables: ${r.join(`, `)}`)}return new e(this._observations.map(e=>{let n={},r=new Set(Object.keys(t));for(let[a,o]of Object.entries(e)){var i;let e=(i=Object.entries(t).find(([,e])=>e===a))==null?void 0:i[0];e?n[e]=o:r.has(a)||(n[a]=o)}return n}),{groups:this._groups,warnings:this._warnings})}innerJoin(t,n){if(this._groups.length>0||t._groups.length>0)throw new v(`innerJoin() cannot be used on grouped data. Ungroup the data first using ungroup().`);n.forEach(e=>{this.verifyObservationsContainVariable(e),t.verifyObservationsContainVariable(e)});let r=new Map;t.observations.forEach(e=>{if(this.hasNullJoinKeys(e,n))return;let t=n.map(t=>JSON.stringify(this.normalizeForComparison(e[t]))).join(`|`),i=r.get(t)||[];i.push(e),r.set(t,i)});let i=[];return this._observations.forEach(e=>{if(this.hasNullJoinKeys(e,n))return;let t=n.map(t=>JSON.stringify(this.normalizeForComparison(e[t]))).join(`|`),a=r.get(t)||[];a.length>0&&a.forEach(t=>{let r=w({},e);Object.entries(t).forEach(([e,t])=>{n.includes(e)||(r[e]=t)}),i.push(r)})}),new e(i)}leftJoin(t,n){if(this._groups.length>0||t._groups.length>0)throw new v(`leftJoin() cannot be used on grouped data. Ungroup the data first using ungroup().`);n.forEach(e=>{this.verifyObservationsContainVariable(e),t.verifyObservationsContainVariable(e)});let r=new Map;t.observations.forEach(e=>{if(this.hasNullJoinKeys(e,n))return;let t=n.map(t=>JSON.stringify(this.normalizeForComparison(e[t]))).join(`|`),i=r.get(t)||[];i.push(e),r.set(t,i)});let i=[];return this._observations.forEach(e=>{if(this.hasNullJoinKeys(e,n)){i.push(w({},e));return}let t=n.map(t=>JSON.stringify(this.normalizeForComparison(e[t]))).join(`|`),a=r.get(t)||[];a.length>0?a.forEach(t=>{let r=w({},e);Object.entries(t).forEach(([e,t])=>{n.includes(e)||(r[e]=t)}),i.push(r)}):i.push(w({},e))}),new e(i)}rightJoin(t,n){if(this._groups.length>0||t._groups.length>0)throw new v(`rightJoin() cannot be used on grouped data. Ungroup the data first using ungroup().`);n.forEach(e=>{this.verifyObservationsContainVariable(e),t.verifyObservationsContainVariable(e)});let r=new Map,i=[];t.observations.forEach(e=>{if(this.hasNullJoinKeys(e,n)){i.push(e);return}let t=n.map(t=>JSON.stringify(this.normalizeForComparison(e[t]))).join(`|`),a=r.get(t)||[];a.push(e),r.set(t,a)});let a=[],o=new Set;return this._observations.forEach(e=>{if(this.hasNullJoinKeys(e,n))return;let t=n.map(t=>JSON.stringify(this.normalizeForComparison(e[t]))).join(`|`),i=r.get(t)||[];i.length>0&&(i.forEach(t=>{let r=w({},e);Object.entries(t).forEach(([e,t])=>{n.includes(e)||(r[e]=t)}),a.push(r)}),o.add(t))}),t.observations.forEach(e=>{if(this.hasNullJoinKeys(e,n)){a.push(w({},e));return}let t=n.map(t=>JSON.stringify(this.normalizeForComparison(e[t]))).join(`|`);o.has(t)||(a.push(w({},e)),o.add(t))}),new e(a)}fullJoin(t,n){if(this._groups.length>0||t._groups.length>0)throw new v(`fullJoin() cannot be used on grouped data. Ungroup the data first using ungroup().`);n.forEach(e=>{this.verifyObservationsContainVariable(e),t.verifyObservationsContainVariable(e)});let r=new Map,i=[];t.observations.forEach(e=>{if(this.hasNullJoinKeys(e,n)){i.push(e);return}let t=n.map(t=>JSON.stringify(this.normalizeForComparison(e[t]))).join(`|`),a=r.get(t)||[];a.push(e),r.set(t,a)});let a=[],o=new Set;return this._observations.forEach(e=>{if(this.hasNullJoinKeys(e,n)){a.push(w({},e));return}let t=n.map(t=>JSON.stringify(this.normalizeForComparison(e[t]))).join(`|`),i=r.get(t)||[];i.length>0?(i.forEach(t=>{let r=w({},e);Object.entries(t).forEach(([e,t])=>{n.includes(e)||(r[e]=t)}),a.push(r)}),o.add(t)):a.push(w({},e))}),t.observations.forEach(e=>{if(this.hasNullJoinKeys(e,n)){a.push(w({},e));return}let t=n.map(t=>JSON.stringify(this.normalizeForComparison(e[t]))).join(`|`);o.has(t)||(a.push(w({},e)),o.add(t))}),new e(a)}slice(t,n){if(this._groups.length>0)throw new v(`slice() cannot be used on grouped data. Ungroup the data first using ungroup().`);let r;if(t>=this._observations.length)return new e([],{groups:this._groups,warnings:this._warnings,skipNormalization:!0});if(n===void 0){let e=t<0?this._observations.length+t:t;r=[this._observations[e]]}else r=this._observations.slice(t,n);return new e(r,{groups:this._groups,warnings:this._warnings,skipNormalization:!0})}bindRows(t){if(this._observations.length>0&&t.observations.length>0){let e=new Set(Object.keys(this._observations[0])),n=new Set(Object.keys(t.observations[0]));[...e].filter(e=>n.has(e)).forEach(e=>{let n=this.getVariableType(e),r=t.getVariableType(e);n!==r&&console.warn(`Warning: bindRows() is combining datasets with different data types for variable '${e}'. Left dataset has type '${n}' and right dataset has type '${r}'.`)})}return new e([...this._observations,...t.observations])}getVariableType(e){if(this._observations.length===0)return`unknown`;let t={};this._observations.forEach(n=>{if(e in n){let r=n[e],i=r===null?`null`:Array.isArray(r)?`array`:typeof r;t[i]=(t[i]||0)+1}});let n=0,r=`unknown`;for(let[e,i]of Object.entries(t))i>n&&(n=i,r=e);return r}verifyObservationsContainVariable(e){if(!this._observations.every(t=>e in t))throw new v(`Variable ${e} does not exist for each item (row) in the data array.`)}variableExists(e){return this._observations.some(t=>e in t)}isNonMissingNumeric(e){return typeof e==`number`&&!isNaN(e)&&isFinite(e)}isMissingNumeric(e){return typeof e==`number`&&(isNaN(e)||!isFinite(e))||e==null}normalizeForComparison(e){return typeof e!=`object`||!e?e:Array.isArray(e)?e.map(e=>this.normalizeForComparison(e)):Object.keys(e).sort().reduce((t,n)=>(t[n]=this.normalizeForComparison(e[n]),t),{})}deepCopy(e,t=new WeakMap){let n=globalThis.structuredClone;if(typeof n==`function`)try{let t=e&&typeof e==`object`?Object.getPrototypeOf(e):null;if((Array.isArray(e)||t===Object.prototype||t===null)&&!Object.values(Object.getOwnPropertyDescriptors(e)).some(e=>typeof e.get==`function`||typeof e.set==`function`))return n(e)}catch(e){}if(typeof e!=`object`||!e)return e;if(t.has(e))return t.get(e);let r=Array.isArray(e)?[]:Object.create(Object.getPrototypeOf(e));t.set(e,r);let i=[...Object.getOwnPropertyNames(e),...Object.getOwnPropertySymbols(e)];for(let n of i){let i=Object.getOwnPropertyDescriptor(e,n);if(i){let{get:a,set:o}=i,s=M(i,N);Object.defineProperty(r,n,w(w({},s),{},{value:this.deepCopy(e[n],t)}))}}return r}hasNullJoinKeys(e,t){return t.some(t=>e[t]===null||e[t]===void 0)}};const F={matchAll:function*(e,t){if(e==null)throw TypeError(`String is null or not defined`);let n=String(e),r;if(t instanceof RegExp){if(!t.global)throw TypeError(`matchAll called with a non-global RegExp argument`);r=new RegExp(t.source,t.flags)}else r=new RegExp(t,`g`);let i;for(;(i=r.exec(n))!==null;)if(yield i,i[0].length===0){if(r.unicode){let e=n.charCodeAt(r.lastIndex);e>=55296&&e<=56319&&r.lastIndex++}r.lastIndex++}}},I={"+":1,"-":1,"*":2,"/":2,"^":3};var L=class e{constructor(e,t,n,r){this.leafFn=e,this.parameters=t,this.options=n,r&&r.length>0?this.tokens=r.slice():e?this.tokens=[{t:`operand`,v:this}]:this.tokens=[],this.summarizeFunction=e=>this.evaluateAsValue(e)}static leaf(t,n,r){return new e(t,n,r)}cloneWithTokens(t){return new e(void 0,void 0,void 0,t)}appendOp(e,t){let n=this.tokens.slice();return n.push({t:`op`,v:e}),n.push({t:`operand`,v:t}),this.cloneWithTokens(n)}add(e){return this.appendOp(`+`,e)}sub(e){return this.appendOp(`-`,e)}mul(e){return this.appendOp(`*`,e)}div(e){return this.appendOp(`/`,e)}pow(e){return this.appendOp(`^`,e)}evaluateOperandToNumber(e,t){if(typeof e==`number`)return e;if(typeof e==`string`){let n=/^__CHAIN_EXPR__\[(.*?)\]$/.exec(e);if(n){let e=n[1],r=D(e);if(!r)try{r=JSON.parse(decodeURIComponent(e))}catch(e){r=void 0}if(!r)return NaN;let i=t,a;for(let e of r){let t=i[e.name];if(typeof t!=`function`)return NaN;let n=t.apply(i,e.args);if(n instanceof P){i=n;continue}if(Array.isArray(n)){a=n.length;break}if(typeof n==`boolean`)if(!(this.options&&typeof this.options.coerceBooleans==`boolean`)||this.options.coerceBooleans){a=+!!n;break}else return NaN;a=typeof n==`number`?n:Number(n);break}return a===void 0&&(a=i instanceof P?i.length:NaN),typeof a==`number`&&!isNaN(a)?a:NaN}}let n=Array.isArray(e.parameters)?e.parameters:e.parameters===void 0?void 0:[e.parameters],r=e.leafFn?e.leafFn(t,n,e.options):e.evaluateAsValue(t);if(r==null)return NaN;let i=Number(r);return typeof i==`number`&&!isNaN(i)?i:NaN}evaluateFlatTokens(e,t){let n=[],r=[];for(let t of e)t.t===`operand`?n.push(t.v):r.push(t.v);if(n.length===0)return NaN;for(;r.length>0;){var i;let e=0,o=(i=I[r[0]])==null?0:i;for(let t=1;t<r.length;t++){var a;let n=(a=I[r[t]])==null?0:a;(n>o||n===o&&r[t]===`^`)&&(o=n,e=t)}let s=r.splice(e,1)[0],c=n.splice(e,1)[0],l=n.splice(e,1)[0],u=this.evaluateOperandToNumber(c,t),d=this.evaluateOperandToNumber(l,t),f=NaN;s===`+`?f=u+d:s===`-`?f=u-d:s===`*`?f=u*d:s===`/`?f=d===0?NaN:u/d:s===`^`&&(f=u**+d),n.splice(e,0,f)}let o=n[0];return typeof o==`number`?o:this.evaluateOperandToNumber(o,t)}parens(){return R(this)}evaluateAsValue(e){if(this.leafFn){let t=Array.isArray(this.parameters)?this.parameters:this.parameters===void 0?void 0:[this.parameters],n=this.leafFn(e,t,this.options);return typeof n==`number`&&Number.isNaN(n)?null:n}if(!this.tokens||this.tokens.length===0)return NaN;let t=this.evaluateFlatTokens(this.tokens,e);return typeof t==`number`&&Number.isNaN(t)?null:t}};function R(e){return new L(void 0,void 0,void 0,[{t:`operand`,v:e}])}const z={coerceBooleans:!0,skipMissing:!1};function B(e){return w(w({},z),e)}function V(e,t,n){if(typeof e!=`function`)return e;try{let r=e(t);if(typeof r==`function`)throw new v(`${n||`summarize()`}: lazy callback returned a function; expected a value or array of values.`);if(r instanceof P)throw new v(`${n||`summarize()`}: lazy callback returned a DataCalc instance; expected a value or array of values.`);return r}catch(e){throw new v(`${n||`summarize()`}: lazy callback threw an error: ${e&&e.message?e.message:String(e)}`)}}function H(e,t,n,r,i,a){let o=B(n);e.verifyObservationsContainVariable(t);let s=0,c=a,l=!1;return e.observations.forEach(n=>{if(e.isNonMissingNumeric(n[t])){c=r(n[t],c),s++;return}if(typeof n[t]==`boolean`&&o.coerceBooleans){c=r(+!!n[t],c),s++;return}if(e.isMissingNumeric(n[t])){l=!0;return}throw new v(`${i}: variable ${t} has non-numeric value ${n[t]} in this observation: ${JSON.stringify(n)}`)}),{state:c,count:s,containsMissing:l}}function U(e,t,n){let r=B(t);if(typeof e==`number`&&!isNaN(e)&&isFinite(e))return{value:e,isMissing:!1};if(typeof e==`boolean`&&r.coerceBooleans)return{value:+!!e,isMissing:!1};if(e==null||typeof e==`number`&&(isNaN(e)||!isFinite(e)))return{value:0,isMissing:!0};throw new v(`${n}: has non-numeric value ${e}`)}const W=(e,t,n)=>{let r=t?t[0]:void 0;r=V(r,e);let i=B(n);if(typeof r==`string`){if(!e.variableExists(r))return null;let t=r,a=H(e,t,n,(e,t)=>t+e,`variance()`,0);if(a.containsMissing&&!i.skipMissing||a.count<=1)return null;let o=a.state/a.count;return H(e,t,n,(e,t)=>t+((typeof e==`boolean`&&i.coerceBooleans?+!!e:e)-o)**2,`variance()`,0).state/(a.count-1)}else if(Array.isArray(r)){let e=[],t=!1;for(let n of r)if(typeof n==`number`&&!isNaN(n)&&isFinite(n))e.push(n);else if(typeof n==`boolean`&&i.coerceBooleans)e.push(+!!n);else if(n==null||typeof n==`number`&&(isNaN(n)||!isFinite(n)))t=!0;else throw new v(`variance(): has non-numeric value ${n}`);if(t&&!i.skipMissing||e.length<=1)return null;let n=e.reduce((e,t)=>e+t,0)/e.length;return e.reduce((e,t)=>e+(t-n)**2,0)/(e.length-1)}else return null},G=(e,t,n)=>{let r=t?t[0]:void 0;r=V(r,e);let i=B(n);if(typeof r==`string`){if(!e.variableExists(r))return null;let t=r;e.verifyObservationsContainVariable(t);let n=[],a=!1;if(e.observations.forEach(r=>{if(e.isNonMissingNumeric(r[t]))n.push(r[t]);else if(typeof r[t]==`boolean`&&i.coerceBooleans)n.push(+!!r[t]);else if(e.isMissingNumeric(r[t]))a=!0;else throw new v(`median(): variable ${t} has non-numeric value ${r[t]} in this observation: ${JSON.stringify(r)}`)}),a&&!i.skipMissing||n.length===0)return null;n.sort((e,t)=>e-t);let o=Math.floor(n.length/2);return n.length%2==0?(n[o-1]+n[o])/2:n[o]}else if(Array.isArray(r)){let e=[],t=!1;for(let n of r)if(typeof n==`number`&&!isNaN(n)&&isFinite(n))e.push(n);else if(typeof n==`boolean`&&i.coerceBooleans)e.push(+!!n);else if(n==null||typeof n==`number`&&(isNaN(n)||!isFinite(n)))t=!0;else throw new v(`median(): has non-numeric value ${n}`);if(t&&!i.skipMissing||e.length===0)return null;e.sort((e,t)=>e-t);let n=Math.floor(e.length/2);return e.length%2==0?(e[n-1]+e[n])/2:e[n]}else{let e=U(r,n,`median()`);return e.isMissing&&!i.skipMissing||e.isMissing?null:e.value}};function K(e,t){return L.leaf(G,[e],t)}const q=(e,t,n)=>{let r=t?t[0]:void 0;if(r=V(r,e),typeof r==`string`){if(!e.variableExists(r))return null;let i=W(e,t,n);return i===null?null:Math.sqrt(i)}else if(Array.isArray(r)){let i=W(e,t?[...t]:[r],n);return i===null?null:Math.sqrt(i)}else return null};function J(e,t){return L.leaf(q,[e],t)}const Y=(e,t,n)=>{let r=t?t[0]:void 0;if(typeof r==`function`&&(r=r(e)),typeof r==`string`){let t=/^__CHAIN_EXPR__\[(.*?)\]$/.exec(r);if(t){let n=t[1],i=D(n);if(!i)try{i=JSON.parse(decodeURIComponent(n))}catch(e){i=void 0}if(i){let t=e,n;for(let e of i){let r=t[e.name];if(typeof r!=`function`){n=NaN;break}let i=r.apply(t,e.args);if(i instanceof P){t=i;continue}if(Array.isArray(i)){n=i.length;break}if(typeof i==`boolean`){n=i;break}n=typeof i==`number`?i:Number(i);break}n===void 0&&(n=t instanceof P?t.length:NaN),r=Number.isNaN(n)?null:n}}}if(typeof r==`object`&&r&&`summarizeFunction`in r)try{let t=r,n=Array.isArray(t.parameters)?t.parameters:t.parameters===void 0?void 0:[t.parameters];r=t.summarizeFunction(e,n,t.options)}catch(e){r=null}let i=U(r,n,`scalar()`);return i.isMissing?null:i.value};function X(e){return L.leaf(Y,[e],void 0)}console.log(`⚪ @m2c2kit/data-calc version 0.8.8 (35887002)`);var Z=class extends n{constructor(){let e={fixation_duration_ms:{default:500,description:`How long fixation scene is shown, milliseconds.`,type:`number`},shape_colors:{type:`array`,description:`Array of colors for shapes.`,items:{type:`object`,properties:{colorName:{type:`string`,description:`Human-friendly name of color.`},rgbaColor:{type:`array`,description:`Color as array, [r,g,b,a].`,items:{type:`number`}}}},default:[{colorName:`black`,rgbaColor:[0,0,0,1]},{colorName:`green`,rgbaColor:[0,158,115,1]},{colorName:`yellow`,rgbaColor:[240,228,66,1]},{colorName:`blue`,rgbaColor:[0,114,178,1]},{colorName:`orange`,rgbaColor:[213,94,0,1]},{colorName:`pink`,rgbaColor:[204,121,167,1]}]},number_of_shapes_shown:{default:3,description:`How many shapes to show on the grid at one time.`,type:`integer`},number_of_shapes_changing_color:{default:2,description:`If a different color trial, how many shapes should change color (minimum is 2, because changes are swaps with other shapes).`,type:`integer`},shapes_presented_duration_ms:{default:2e3,description:`How long the shapes are shown, milliseconds.`,type:`number`},shapes_removed_duration_ms:{default:1e3,description:`How long to show a blank square after shapes are removed, milliseconds.`,type:`number`},cells_per_side:{default:3,description:`How many cell positions for each side of the square grid (e.g., 3 is a 3x3 grid; 4 is a 4x4 grid).`,type:`integer`},number_of_different_colors_trials:{default:6,type:`integer`,description:`Number of trials where the shapes have different colors.`},number_of_trials:{default:12,description:`How many trials to run.`,type:`integer`},show_trials_complete_scene:{default:!0,type:`boolean`,description:`After the final trial, should a completion scene be shown? Otherwise, the game will immediately end.`},instruction_type:{default:`long`,description:`Type of instructions to show, 'short' or 'long'.`,type:`string`,enum:[`short`,`long`]},instructions:{default:null,type:[`object`,`null`],description:`When non-null, an InstructionsOptions object that will completely override the built-in instructions.`},show_quit_button:{type:`boolean`,default:!1,description:`Should the activity quit button be shown?`},show_fps:{type:`boolean`,default:!1,description:`Should the FPS be shown?`},show_locale_picker:{type:`boolean`,default:!1,description:`Should the icon that allows the participant to switch the locale be shown?`},seed:{type:[`string`,`null`],default:null,description:`Optional seed for the seeded pseudo-random number generator. When null, the default Math.random() is used.`},scoring:{type:`boolean`,default:!1,description:`Should scoring data be generated? Default is false.`},scoring_filter_response_time_duration_ms:{type:`array`,items:{type:`number`},default:[100,1e4],description:`When scoring, values of response_time_duration_ms less than the lower bound or greater than the upper bound are discarded. This array contains two numbers, the lower and upper bounds.`}},t={name:`Color Shapes`,id:`color-shapes`,publishUuid:`394cb010-2ccf-4a87-9d23-cda7fb07a960`,version:`0.8.35 (35887002)`,moduleMetadata:{name:`@m2c2kit/assessment-color-shapes`,version:`0.8.35`,dependencies:{"@m2c2kit/addons":`0.3.36`,"@m2c2kit/core":`0.3.37`,"@m2c2kit/data-calc":`0.8.8`}},translation:{configuration:{baseLocale:`en-US`},"en-US":{localeName:`English`,INSTRUCTIONS_TITLE:`Color Shapes`,SHORT_INSTRUCTIONS_TEXT_PAGE_1:`Try to remember the color of 3 shapes, because they will soon disappear. When the shapes reappear, answer whether they have the SAME or DIFFERENT colors as they had before`,INSTRUCTIONS_TEXT_PAGE_1:`Try to remember the color of 3 shapes, because they will soon disappear.`,INSTRUCTIONS_TEXT_PAGE_2:`Next you will see the same shapes reappear.`,INSTRUCTIONS_TEXT_PAGE_3:`Answer whether the shapes have the SAME or DIFFERENT colors as they had before.`,START_BUTTON_TEXT:`START`,NEXT_BUTTON_TEXT:`Next`,BACK_BUTTON_TEXT:`Back`,GET_READY_COUNTDOWN_TEXT:`GET READY!`,SAME_BUTTON_TEXT:`Same`,DIFFERENT_BUTTON_TEXT:`Different`,TRIALS_COMPLETE_SCENE_TEXT:`This activity is complete.`,TRIALS_COMPLETE_SCENE_BUTTON_TEXT:`OK`},"es-MX":{localeName:`Español`,INSTRUCTIONS_TITLE:`Formas de Color`,INSTRUCTIONS_TEXT_PAGE_1:`Intenta recordar el color de las 3 formas, porque pronto desaparecerán.`,INSTRUCTIONS_TEXT_PAGE_2:`Luego verás reaparecer las mismas formas.`,INSTRUCTIONS_TEXT_PAGE_3:`Responde si las formas tienen el MISMO o DIFERENTE color que antes.`,START_BUTTON_TEXT:`COMENZAR`,NEXT_BUTTON_TEXT:`Siguiente`,BACK_BUTTON_TEXT:`Atrás`,GET_READY_COUNTDOWN_TEXT:`PREPÁRESE`,SAME_BUTTON_TEXT:`Mismo`,DIFFERENT_BUTTON_TEXT:`Diferente`,TRIALS_COMPLETE_SCENE_TEXT:`Esta actividad está completa.`,TRIALS_COMPLETE_SCENE_BUTTON_TEXT:`OK`},"de-DE":{localeName:`Deutsch`,INSTRUCTIONS_TITLE:`Farb-Formen`,INSTRUCTIONS_TEXT_PAGE_1:`Oben und unten sehen Sie Symbolpaare.`,INSTRUCTIONS_TEXT_PAGE_2:`Ihre Aufgabe wird es sein, auf dasjenige untere Paar zu tippen, welches mit einem der obigen Paare exakt übereinstimmt.`,INSTRUCTIONS_TEXT_PAGE_3:`Versuchen Sie bitte, so schnell und korrekt wie möglich zu sein.`,START_BUTTON_TEXT:`START`,NEXT_BUTTON_TEXT:`Weiter`,BACK_BUTTON_TEXT:`Vorherige`,GET_READY_COUNTDOWN_TEXT:`BEREIT MACHEN`,SAME_BUTTON_TEXT:`Gleich`,DIFFERENT_BUTTON_TEXT:`Unterschiedlich`,TRIALS_COMPLETE_SCENE_TEXT:`Die Aufgabe ist beendet.`,TRIALS_COMPLETE_SCENE_BUTTON_TEXT:`OK`}},shortDescription:`Color Shapes is a visual array change detection task, measuring intra-item feature binding, where participants determine if shapes change color across two sequential presentations of shape stimuli.`,longDescription:`Color Shapes is a change detection paradigm used to measure visual short-term memory binding (Parra et al., 2009). Participants are asked to memorize the shapes and colors of three different polygons for 3 seconds. The three polygons are then removed from the screen and re-displayed at different locations, either having the same or different colors. Participants are then asked to decide whether the combination of colors and shapes are the "Same" or "Different" between the study and test phases.`,showFps:e.show_fps.default,width:400,height:800,trialSchema:{activity_begin_iso8601_timestamp:{type:`string`,format:`date-time`,description:`ISO 8601 timestamp at the beginning of the game activity.`},trial_begin_iso8601_timestamp:{type:[`string`,`null`],format:`date-time`,description:`ISO 8601 timestamp at the beginning of the trial. Null if trial was skipped.`},trial_end_iso8601_timestamp:{type:[`string`,`null`],format:`date-time`,description:`ISO 8601 timestamp at the end of the trial (when user presses 'Same' or 'Different'). Null if trial was skipped.`},trial_index:{type:[`integer`,`null`],description:`Index of the trial within this assessment, 0-based.`},present_shapes:{description:`Configuration of shapes shown to the user in the presentation phase. Null if trial was skipped.`,type:[`array`,`null`],items:{type:`object`,properties:{shape_index:{type:`integer`,description:`Index of the shape within the library of shapes, 0-based`},color_name:{type:`string`,description:`Human-friendly name of color.`},rgba_color:{type:`array`,description:`Color as array, [r,g,b,a].`,items:{type:`number`}},location:{type:`object`,description:`Location of shape.`,properties:{row:{type:`number`,description:`Row of the shape, 0-based.`},column:{type:`number`,description:`Column of the shape, 0-based.`}}}}}},response_shapes:{description:`Configuration of shapes shown to the user in the response phase. Null if trial was skipped.`,type:[`array`,`null`],items:{type:`object`,properties:{shape_index:{type:`integer`,description:`Index of the shape within the library of shapes, 0-based`},color_name:{type:`string`,description:`Human-friendly name of color.`},rgba_color:{type:`array`,description:`Color as array, [r,g,b,a].`,items:{type:`number`}},location:{type:`object`,description:`Location of shape.`,properties:{row:{type:`number`,description:`Row of the shape, 0-based.`},column:{type:`number`,description:`Column of the shape, 0-based.`}}}}}},response_time_duration_ms:{type:[`number`,`null`],description:`Milliseconds from when the response configuration of shapes is shown until the user taps a response. Null if trial was skipped.`},user_response:{type:[`string`,`null`],enum:[`same`,`different`],description:`User's response to whether the shapes are same colors or different.`},user_response_correct:{type:[`boolean`,`null`],description:`Was the user's response correct?`},quit_button_pressed:{type:`boolean`,description:`Was the quit button pressed?`}},scoringSchema:{activity_begin_iso8601_timestamp:{type:`string`,format:`date-time`,description:`ISO 8601 timestamp at the beginning of the game activity.`},first_trial_begin_iso8601_timestamp:{type:[`string`,`null`],format:`date-time`,description:`ISO 8601 timestamp at the beginning of the first trial. Null if no trials were completed.`},last_trial_end_iso8601_timestamp:{type:[`string`,`null`],format:`date-time`,description:`ISO 8601 timestamp at the end of the last trial. Null if no trials were completed.`},response_time_filter_lower_bound:{type:`number`,description:`Response times less than this lower bound were discarded when calculating filtered response times.`},response_time_filter_upper_bound:{type:`number`,description:`Response times greater than this upper bound were discarded when calculating filtered response times.`},n_trials:{type:`integer`,description:`Number of trials completed.`},flag_trials_match_expected:{type:`integer`,description:`Does the number of completed and expected trials match? 1 = true, 0 = false.`},n_trials_correct:{type:`integer`,description:`Number of correct trials.`},n_trials_incorrect:{type:`integer`,description:`Number of incorrect trials.`},participant_score:{type:[`number`,`null`],description:`Participant-facing score, calculated as (number of correct trials / number of trials attempted) * 100. This is a simple metric to provide feedback to the participant. Null if no trials attempted.`},flag_trials_lt_expected:{type:`number`,description:`Is the number of completed trials fewer than expected? 1 = true, 0 = false.`},flag_trials_gt_expected:{type:`number`,description:`Is the number of completed trials greater than expected? 1 = true, 0 = false.`},n_trials_HIT:{type:`number`,description:`Number of HIT trials (correctly identified a 'different' trial)`},n_trials_MISS:{type:`number`,description:`Number of MISS trials (failed to detect a 'different' trial, responded 'same')`},n_trials_FA:{type:`number`,description:`Number of False Alarm trials (incorrectly responded 'different' on a 'same' trial)`},n_trials_CR:{type:`number`,description:`Number of Correct Rejection trials (correctly responded 'same' on a 'same' trial)`},n_trials_type_same:{type:`number`,description:`Number of trials where the true signal type was 'SAME' (presented and response shapes were identical)`},n_trials_type_different:{type:`number`,description:`Number of trials where the true signal type was 'DIFFERENT' (response shapes differed from presented)`},HIT_rate:{type:[`number`,`null`],description:`Proportion of 'different' trials correctly identified as different. Calculated as n_trials_HIT / n_trials_type_different`},MISS_rate:{type:[`number`,`null`],description:`Proportion of 'different' trials incorrectly identified as same. Calculated as 1 - HIT_rate`},FA_rate:{type:[`number`,`null`],description:`Proportion of 'same' trials incorrectly identified as different. Calculated as n_trials_FA / n_trials_type_same`},CR_rate:{type:[`number`,`null`],description:`Proportion of 'same' trials correctly identified as same. Calculated as 1 - FA_rate`},n_trials_rt_invalid:{type:`number`,description:`Number of trials with null or non-positive response times (excluded from RT calculations)`},median_rt_overall_valid:{type:[`number`,`null`],description:`Median response time (ms) across all trials with valid (non-null, positive) response times. No outlier filtering applied`},sd_rt_overall_valid:{type:[`number`,`null`],description:`Standard deviation of response time (ms) across all trials with valid response times. No outlier filtering applied`},median_rt_HIT_valid:{type:[`number`,`null`],description:`Median response time (ms) for HIT trials with valid response times. No outlier filtering`},sd_rt_HIT_valid:{type:[`number`,`null`],description:`Standard deviation of response time (ms) for HIT trials with valid response times. No outlier filtering`},median_rt_MISS_valid:{type:[`number`,`null`],description:`Median response time (ms) for MISS trials with valid response times. No outlier filtering`},sd_rt_MISS_valid:{type:[`number`,`null`],description:`Standard deviation of response time (ms) for MISS trials with valid response times. No outlier filtering`},median_rt_FA_valid:{type:[`number`,`null`],description:`Median response time (ms) for False Alarm trials with valid response times. No outlier filtering`},sd_rt_FA_valid:{type:[`number`,`null`],description:`Standard deviation of response time (ms) for False Alarm trials with valid response times. No outlier filtering`},median_rt_CR_valid:{type:[`number`,`null`],description:`Median response time (ms) for Correct Rejection trials with valid response times. No outlier filtering`},sd_rt_CR_valid:{type:[`number`,`null`],description:`Standard deviation of response time (ms) for Correct Rejection trials with valid response times. No outlier filtering`},median_rt_overall_valid_filtered:{type:[`number`,`null`],description:`Median response time (ms) across all valid trials after removing outliers, as specified in response_time_filter_lower_bound and response_time_filter_upper_bound.`},sd_rt_overall_valid_filtered:{type:[`number`,`null`],description:`Standard deviation of response time (ms) across all valid trials after removing outliers, as specified in response_time_filter_lower_bound and response_time_filter_upper_bound.`},n_outliers_rt_overall_valid:{type:`number`,description:`Number of valid trials removed as RT outliers, as specified in response_time_filter_lower_bound and response_time_filter_upper_bound.`},median_rt_HIT_valid_filtered:{type:[`number`,`null`],description:`Median response time (ms) for HIT trials after removing outliers, as specified in response_time_filter_lower_bound and response_time_filter_upper_bound.`},sd_rt_HIT_valid_filtered:{type:[`number`,`null`],description:`Standard deviation of response time (ms) for HIT trials after removing outliers, as specified in response_time_filter_lower_bound and response_time_filter_upper_bound.`},n_outliers_rt_HIT_valid:{type:`number`,description:`Number of HIT trials removed as RT outliers, as specified in response_time_filter_lower_bound and response_time_filter_upper_bound.`},median_rt_MISS_valid_filtered:{type:[`number`,`null`],description:`Median response time (ms) for MISS trials after removing outliers, as specified in response_time_filter_lower_bound and response_time_filter_upper_bound.`},sd_rt_MISS_valid_filtered:{type:[`number`,`null`],description:`Standard deviation of response time (ms) for MISS trials after removing outliers, as specified in response_time_filter_lower_bound and response_time_filter_upper_bound.`},n_outliers_rt_MISS_valid:{type:`number`,description:`Number of MISS trials removed as RT outliers, as specified in response_time_filter_lower_bound and response_time_filter_upper_bound.`},median_rt_FA_valid_filtered:{type:[`number`,`null`],description:`Median response time (ms) for False Alarm trials after removing outliers, as specified in response_time_filter_lower_bound and response_time_filter_upper_bound.`},sd_rt_FA_valid_filtered:{type:[`number`,`null`],description:`Standard deviation of response time (ms) for False Alarm trials after removing outliers, as specified in response_time_filter_lower_bound and response_time_filter_upper_bound.`},n_outliers_rt_FA_valid:{type:`number`,description:`Number of False Alarm trials removed as RT outliers, as specified in response_time_filter_lower_bound and response_time_filter_upper_bound.`},median_rt_CR_valid_filtered:{type:[`number`,`null`],description:`Median response time (ms) for Correct Rejection trials after removing outliers, as specified in response_time_filter_lower_bound and response_time_filter_upper_bound.`},sd_rt_CR_valid_filtered:{type:[`number`,`null`],description:`Standard deviation of response time (ms) for Correct Rejection trials after removing outliers, as specified in response_time_filter_lower_bound and response_time_filter_upper_bound.`},n_outliers_rt_CR_valid:{type:[`number`,`null`],description:`Number of Correct Rejection trials removed as RT outliers, as specified in response_time_filter_lower_bound and response_time_filter_upper_bound.`}},parameters:e,fonts:[{fontName:`roboto`,url:`fonts/roboto/Roboto-Regular.ttf`}],images:[{imageName:`instructions-1`,height:256,width:256,url:`images/cs-instructions-1.png`},{imageName:`instructions-2`,height:256,width:256,url:`images/cs-instructions-2.png`},{imageName:`instructions-3`,height:350,width:300,url:`images/cs-instructions-3.png`,localize:!0},{imageName:`circle-x`,height:32,width:32,url:`images/circle-x.svg`}]};super(t)}async initialize(){var n=()=>super.initialize,v=this;await n().call(v);let y=v,b=y.getParameter(`seed`);typeof b==`string`&&a.setSeed(b);let x=y.getParameter(`number_of_shapes_shown`),S=v.makeShapes(96);if(y.getParameter(`show_quit_button`)){let e=new c({imageName:`circle-x`,position:{x:380,y:20},isUserInteractionEnabled:!0});y.addFreeNode(e),e.onTapDown(e=>{y.removeAllFreeNodes(),e.handled=!0;let t=new o;if(y.addScene(t),y.presentScene(t),y.addTrialData(`quit_button_pressed`,!0),y.trialComplete(),y.getParameter(`scoring`)){let e=y.calculateScores([],{rtLowerBound:y.getParameter(`scoring_filter_response_time_duration_ms`)[0],rtUpperBound:y.getParameter(`scoring_filter_response_time_duration_ms`)[1],numberOfTrials:y.getParameter(`number_of_trials`)});y.addScoringData(e),y.scoringComplete()}y.cancel()})}let C;y.getParameter(`show_locale_picker`)&&(C=new _,y.addFreeNode(C));let w,T=y.getParameter(`instructions`);if(T)w=g.create(T);else switch(y.getParameter(`instruction_type`)){case`short`:w=g.create({instructionScenes:[{title:`INSTRUCTIONS_TITLE`,text:`SHORT_INSTRUCTIONS_TEXT_PAGE_1`,imageName:`instructions-1`,imageAboveText:!1,imageMarginTop:32,textFontSize:24,titleFontSize:30,textVerticalBias:.2,nextButtonText:`START_BUTTON_TEXT`,nextButtonBackgroundColor:f.Green,nextSceneTransition:u.none()}]});break;case`long`:w=g.create({instructionScenes:[{title:`INSTRUCTIONS_TITLE`,text:`INSTRUCTIONS_TEXT_PAGE_1`,imageName:`instructions-1`,imageAboveText:!1,imageMarginTop:32,textFontSize:24,titleFontSize:30,textVerticalBias:.2,nextButtonText:`NEXT_BUTTON_TEXT`,backButtonText:`BACK_BUTTON_TEXT`},{title:`INSTRUCTIONS_TITLE`,text:`INSTRUCTIONS_TEXT_PAGE_2`,imageName:`instructions-2`,imageAboveText:!1,imageMarginTop:32,textFontSize:24,titleFontSize:30,textVerticalBias:.2,nextButtonText:`NEXT_BUTTON_TEXT`,backButtonText:`BACK_BUTTON_TEXT`},{title:`INSTRUCTIONS_TITLE`,text:`INSTRUCTIONS_TEXT_PAGE_3`,imageName:`instructions-3`,imageAboveText:!1,imageMarginTop:32,textFontSize:24,titleFontSize:30,textVerticalBias:.2,nextButtonText:`START_BUTTON_TEXT`,nextButtonBackgroundColor:f.Green,backButtonText:`BACK_BUTTON_TEXT`}]});break;default:throw new i(`invalid value for instruction_type`)}w[0].onAppear(()=>{y.addTrialData(`activity_begin_iso8601_timestamp`,v.beginIso8601Timestamp)}),y.addScenes(w);let E=new m({milliseconds:3e3,text:`GET_READY_COUNTDOWN_TEXT`,zeroDwellMilliseconds:1e3,transition:u.none()});y.addScene(E);let D=y.getParameter(`cells_per_side`),O=y.getParameter(`cells_per_side`),k=y.getParameter(`number_of_trials`),A=y.getParameter(`shape_colors`),j=[],M=y.getParameter(`cells_per_side`),N=M,P=y.getParameter(`number_of_different_colors_trials`),F=a.fromRangeWithoutReplacement(P,0,k-1);for(let e=0;e<k;e++){let t=[],n=[],r=a.fromRangeWithoutReplacement(x,0,S.length-1),o=a.fromRangeWithoutReplacement(x,0,A.length-1),s=e=>!!(e.map(e=>e.row===0&&e.column===0).some(e=>e===!0)&&e.map(e=>e.row===1&&e.column===1).some(e=>e===!0)&&e.map(e=>e.row===2&&e.column===2).some(e=>e===!0)||e.map(e=>e.row===2&&e.column===0).some(e=>e===!0)&&e.map(e=>e.row===1&&e.column===1).some(e=>e===!0)&&e.map(e=>e.row===0&&e.column===2).some(e=>e===!0)),c=e=>{let t=new Set(e.map(e=>e.row)).size,n=new Set(e.map(e=>e.column)).size;return!(t!==1&&n!==1)},l=!1,u;do u=a.fromGridWithoutReplacement(x,M,N),l=!c(u)&&!s(u);while(!l);for(let e=0;e<x;e++){let n={shape:S[r[e]],shapeIndex:r[e],color:A[o[e]].rgbaColor,colorName:A[o[e]].colorName,location:u[e]};t.push(n)}let d=!1,f;do f=a.fromGridWithoutReplacement(x,M,N),d=!c(f)&&!s(f);while(!d);for(let e=0;e<x;e++){let i={shape:t[e].shape,shapeIndex:r[e],color:t[e].color,colorName:A[o[e]].colorName,location:f[e]};n.push(i)}let p=0;if(F.includes(e)){let e=y.getParameter(`number_of_shapes_changing_color`);if(e>x)throw new i(`number_of_shapes_changing_color is ${e}, but it must be less than or equal to number_of_shapes_shown (which is ${x}).`);let t=a.fromRangeWithoutReplacement(e,0,x-1).map(e=>n[e]);p=t.length;let r=t[0].color;for(let n=0;n<e;n++){let i=t[n];n+1<e?i.color=t[n+1].color:i.color=r}}j.push({presentShapes:t,responseShapes:n,numberOfShapesWithDifferentColors:p})}let I=new o;y.addScene(I);let L=new s({rect:{size:{width:350,height:350}},fillColor:f.Transparent,strokeColor:f.Gray,lineWidth:4,position:{x:200,y:300}});I.addChild(L);let R=new r({text:`+`,fontSize:32,fontColor:f.Black,localize:!1});L.addChild(R),I.onAppear(()=>{y.addTrialData(`activity_begin_iso8601_timestamp`,v.beginIso8601Timestamp),y.addTrialData(`trial_begin_iso8601_timestamp`,new Date().toISOString()),I.run(e.sequence([e.wait({duration:y.getParameter(`fixation_duration_ms`)}),e.custom({callback:()=>{y.presentScene(z)}})]))});let z=new o;y.addScene(z);let B=new s({rect:{size:{width:350,height:350}},fillColor:f.Transparent,strokeColor:f.Gray,lineWidth:4,position:{x:200,y:300}});z.addChild(B);let V=new h({rows:D,columns:O,size:{width:350,height:350},position:{x:200,y:300},backgroundColor:f.Transparent,gridLineColor:f.Transparent});z.addChild(V),z.onAppear(()=>{let t=j[y.trialIndex];for(let e=0;e<t.presentShapes.length;e++){let n=t.presentShapes[e].shape;n.fillColor=t.presentShapes[e].color,n.position={x:0,y:0},V.addAtCell(n,t.presentShapes[e].location.row,t.presentShapes[e].location.column)}z.run(e.sequence([e.wait({duration:y.getParameter(`shapes_presented_duration_ms`)}),e.custom({callback:()=>{V.removeAllGridChildren()}}),e.wait({duration:y.getParameter(`shapes_removed_duration_ms`)}),e.custom({callback:()=>{V.removeAllGridChildren(),y.presentScene(H)}})]))});let H=new o;y.addScene(H);let U=new s({rect:{size:{width:350,height:350}},fillColor:f.Transparent,strokeColor:f.Gray,lineWidth:4,position:{x:200,y:300}});H.addChild(U);let W=new h({rows:D,columns:O,size:{width:350,height:350},position:{x:200,y:300},backgroundColor:f.Transparent,gridLineColor:f.Transparent});H.addChild(W),H.onAppear(()=>{let e=j[y.trialIndex];for(let t=0;t<e.responseShapes.length;t++){let n=e.responseShapes[t].shape;n.fillColor=e.responseShapes[t].color,n.position={x:0,y:0},W.addAtCell(n,e.responseShapes[t].location.row,e.responseShapes[t].location.column)}G.isUserInteractionEnabled=!0,K.isUserInteractionEnabled=!0,l.startNew(`rt`)});let G=new p({text:`SAME_BUTTON_TEXT`,position:{x:100,y:700},size:{width:150,height:50}});H.addChild(G),G.onTapDown(()=>{G.isUserInteractionEnabled=!1,q(!1)});let K=new p({text:`DIFFERENT_BUTTON_TEXT`,position:{x:300,y:700},size:{width:150,height:50}});H.addChild(K),K.onTapDown(()=>{K.isUserInteractionEnabled=!1,q(!0)});let q=e=>{let n=l.elapsed(`rt`);l.remove(`rt`),W.removeAllGridChildren(),y.addTrialData(`trial_end_iso8601_timestamp`,new Date().toISOString());let r=j[y.trialIndex];y.addTrialData(`response_time_duration_ms`,n),y.addTrialData(`user_response`,e?`different`:`same`);let i=r.numberOfShapesWithDifferentColors===0&&!e||r.numberOfShapesWithDifferentColors>0&&e;y.addTrialData(`user_response_correct`,i);let a=r.presentShapes.map(e=>({shape_index:e.shapeIndex,color_name:e.colorName,rgba_color:e.color,location:e.location}));y.addTrialData(`present_shapes`,a),y.addTrialData(`quit_button_pressed`,!1);let o=r.responseShapes.map(e=>({shape_index:e.shapeIndex,color_name:e.colorName,rgba_color:e.color,location:e.location}));if(y.addTrialData(`response_shapes`,o),y.addTrialData(`trial_index`,y.trialIndex),y.trialComplete(),y.trialIndex<k)y.presentScene(I);else{if(y.getParameter(`scoring`)){let e=y.calculateScores(y.data.trials,{rtLowerBound:y.getParameter(`scoring_filter_response_time_duration_ms`)[0],rtUpperBound:y.getParameter(`scoring_filter_response_time_duration_ms`)[1],numberOfTrials:y.getParameter(`number_of_trials`)});y.addScoringData(e),y.scoringComplete()}y.getParameter(`show_trials_complete_scene`)?y.presentScene(J,u.slide({direction:d.Left,duration:500,easing:t.sinusoidalInOut})):y.end()}},J=new o;y.addScene(J);let Y=new r({text:`TRIALS_COMPLETE_SCENE_TEXT`,position:{x:200,y:400}});J.addChild(Y);let X=new p({text:`TRIALS_COMPLETE_SCENE_BUTTON_TEXT`,position:{x:200,y:650}});X.isUserInteractionEnabled=!0,X.onTapDown(()=>{X.isUserInteractionEnabled=!1,J.removeAllChildren(),y.end()}),J.addChild(X),J.onSetup(()=>{y.removeAllFreeNodes()})}calculateScores(e,t){let n=new P(e),r=n.filter(e=>e.quit_button_pressed===!1).length;return n.mutate({metric_accuracy:e=>{let t=e.user_response,n=e.user_response_correct;return t===`same`&&n===!0?`CR`:t===`same`&&n===!1?`MISS`:t===`different`&&n===!0?`HIT`:t===`different`&&n===!1?`FA`:null},metric_trial_type:e=>{let t=e.user_response,n=e.user_response_correct;return t===`same`&&n===!0?`SAME`:t===`same`&&n===!1||t===`different`&&n===!0?`DIFFERENT`:t===`different`&&n===!1?`SAME`:null},is_valid:e=>typeof e.response_time_duration_ms==`number`&&e.response_time_duration_ms>0}).summarize({activity_begin_iso8601_timestamp:this.beginIso8601Timestamp,first_trial_begin_iso8601_timestamp:k(`trial_begin_iso8601_timestamp`).slice(0).pull(`trial_begin_iso8601_timestamp`),last_trial_end_iso8601_timestamp:k(`-trial_end_iso8601_timestamp`).slice(0).pull(`trial_end_iso8601_timestamp`),n_trials:r,flag_trials_match_expected:+(r===t.numberOfTrials),flag_trials_lt_expected:+(r<t.numberOfTrials),flag_trials_gt_expected:+(r>t.numberOfTrials),n_trials_HIT:A(e=>e.metric_accuracy===`HIT`).length,n_trials_MISS:A(e=>e.metric_accuracy===`MISS`).length,n_trials_FA:A(e=>e.metric_accuracy===`FA`).length,n_trials_CR:A(e=>e.metric_accuracy===`CR`).length,n_trials_type_same:A(e=>e.metric_trial_type===`SAME`).length,n_trials_type_different:A(e=>e.metric_trial_type===`DIFFERENT`).length,HIT_rate:e=>{let t=e.filter(e=>e.metric_trial_type===`DIFFERENT`).length;return t>0?e.filter(e=>e.metric_accuracy===`HIT`).length/t:null},MISS_rate:e=>{let t=e.filter(e=>e.metric_trial_type===`DIFFERENT`).length;return t>0?1-e.filter(e=>e.metric_accuracy===`HIT`).length/t:null},FA_rate:e=>{let t=e.filter(e=>e.metric_trial_type===`SAME`).length;return t>0?e.filter(e=>e.metric_accuracy===`FA`).length/t:null},CR_rate:e=>{let t=e.filter(e=>e.metric_trial_type===`SAME`).length;return t>0?1-e.filter(e=>e.metric_accuracy===`FA`).length/t:null},median_rt_overall_valid:K(A(e=>e.is_valid).pull(`response_time_duration_ms`)),sd_rt_overall_valid:J(A(e=>e.is_valid).pull(`response_time_duration_ms`)),median_rt_overall_valid_filtered:K(A(e=>e.is_valid).filter(e=>e.response_time_duration_ms>=t.rtLowerBound&&e.response_time_duration_ms<=t.rtUpperBound).pull(`response_time_duration_ms`)),sd_rt_overall_valid_filtered:J(A(e=>e.is_valid).filter(e=>e.response_time_duration_ms>=t.rtLowerBound&&e.response_time_duration_ms<=t.rtUpperBound).pull(`response_time_duration_ms`)),n_trials_rt_invalid:A(e=>!e.is_valid).length,n_outliers_rt_overall_valid:A(e=>e.is_valid).filter(e=>e.response_time_duration_ms<t.rtLowerBound||e.response_time_duration_ms>t.rtUpperBound).length,response_time_filter_lower_bound:t.rtLowerBound,response_time_filter_upper_bound:t.rtUpperBound,median_rt_HIT_valid:K(A(e=>e.is_valid).filter(e=>e.metric_accuracy===`HIT`).pull(`response_time_duration_ms`)),sd_rt_HIT_valid:J(A(e=>e.is_valid).filter(e=>e.metric_accuracy===`HIT`).pull(`response_time_duration_ms`)),median_rt_HIT_valid_filtered:K(A(e=>e.is_valid).filter(e=>e.metric_accuracy===`HIT`&&e.response_time_duration_ms>=t.rtLowerBound&&e.response_time_duration_ms<=t.rtUpperBound).pull(`response_time_duration_ms`)),sd_rt_HIT_valid_filtered:J(A(e=>e.is_valid).filter(e=>e.metric_accuracy===`HIT`&&e.response_time_duration_ms>=t.rtLowerBound&&e.response_time_duration_ms<=t.rtUpperBound).pull(`response_time_duration_ms`)),n_outliers_rt_HIT_valid:A(e=>e.is_valid).filter(e=>e.metric_accuracy===`HIT`).filter(e=>e.response_time_duration_ms<t.rtLowerBound||e.response_time_duration_ms>t.rtUpperBound).length,median_rt_MISS_valid:K(A(e=>e.is_valid).filter(e=>e.metric_accuracy===`MISS`).pull(`response_time_duration_ms`)),sd_rt_MISS_valid:J(A(e=>e.is_valid).filter(e=>e.metric_accuracy===`MISS`).pull(`response_time_duration_ms`)),median_rt_MISS_valid_filtered:K(A(e=>e.is_valid).filter(e=>e.metric_accuracy===`MISS`&&e.response_time_duration_ms>=t.rtLowerBound&&e.response_time_duration_ms<=t.rtUpperBound).pull(`response_time_duration_ms`)),sd_rt_MISS_valid_filtered:J(A(e=>e.is_valid).filter(e=>e.metric_accuracy===`MISS`&&e.response_time_duration_ms>=t.rtLowerBound&&e.response_time_duration_ms<=t.rtUpperBound).pull(`response_time_duration_ms`)),n_outliers_rt_MISS_valid:A(e=>e.is_valid).filter(e=>e.metric_accuracy===`MISS`).filter(e=>e.response_time_duration_ms<t.rtLowerBound||e.response_time_duration_ms>t.rtUpperBound).length,median_rt_FA_valid:K(A(e=>e.is_valid).filter(e=>e.metric_accuracy===`FA`).pull(`response_time_duration_ms`)),sd_rt_FA_valid:J(A(e=>e.is_valid).filter(e=>e.metric_accuracy===`FA`).pull(`response_time_duration_ms`)),median_rt_FA_valid_filtered:K(A(e=>e.is_valid).filter(e=>e.metric_accuracy===`FA`&&e.response_time_duration_ms>=t.rtLowerBound&&e.response_time_duration_ms<=t.rtUpperBound).pull(`response_time_duration_ms`)),sd_rt_FA_valid_filtered:J(A(e=>e.is_valid).filter(e=>e.metric_accuracy===`FA`&&e.response_time_duration_ms>=t.rtLowerBound&&e.response_time_duration_ms<=t.rtUpperBound).pull(`response_time_duration_ms`)),n_outliers_rt_FA_valid:A(e=>e.is_valid).filter(e=>e.metric_accuracy===`FA`).filter(e=>e.response_time_duration_ms<t.rtLowerBound||e.response_time_duration_ms>t.rtUpperBound).length,median_rt_CR_valid:K(A(e=>e.is_valid).filter(e=>e.metric_accuracy===`CR`).pull(`response_time_duration_ms`)),sd_rt_CR_valid:J(A(e=>e.is_valid).filter(e=>e.metric_accuracy===`CR`).pull(`response_time_duration_ms`)),median_rt_CR_valid_filtered:K(A(e=>e.is_valid).filter(e=>e.metric_accuracy===`CR`&&e.response_time_duration_ms>=t.rtLowerBound&&e.response_time_duration_ms<=t.rtUpperBound).pull(`response_time_duration_ms`)),sd_rt_CR_valid_filtered:J(A(e=>e.is_valid).filter(e=>e.metric_accuracy===`CR`&&e.response_time_duration_ms>=t.rtLowerBound&&e.response_time_duration_ms<=t.rtUpperBound).pull(`response_time_duration_ms`)),n_outliers_rt_CR_valid:A(e=>e.is_valid).filter(e=>e.metric_accuracy===`CR`).filter(e=>e.response_time_duration_ms<t.rtLowerBound||e.response_time_duration_ms>t.rtUpperBound).length,n_trials_correct:A(e=>e.metric_accuracy===`HIT`||e.metric_accuracy===`CR`).length,n_trials_incorrect:A(e=>e.metric_accuracy===`MISS`||e.metric_accuracy===`FA`).length,participant_score:e=>{let t=e.length;return t===0?null:e.summarize({correct:R(X(e.filter(e=>e.metric_accuracy===`HIT`).length).add(X(e.filter(e=>e.metric_accuracy===`CR`).length))).div(X(t)).mul(X(100))}).pull(`correct`)}}).observations}makeShapes(e){return[new s({path:{pathString:Q[0],height:e},lineWidth:0}),new s({path:{pathString:Q[1],height:e},lineWidth:0}),new s({path:{pathString:Q[2],height:e*.8},lineWidth:0}),new s({path:{pathString:Q[3],height:e},lineWidth:0}),new s({path:{pathString:Q[4],height:e*.8},lineWidth:0}),new s({path:{pathString:Q[5],height:e},lineWidth:0}),new s({path:{pathString:Q[6],height:e},lineWidth:0}),new s({path:{pathString:Q[7],height:e},lineWidth:0})]}};const Q=[`M0 89.94v-2L131.95 0h2v88.7c2.34 1.6 4.47 3.11 6.65 4.55 42.77 28.22 85.54 56.42 128.3 84.63v2c-44.65 29.65-89.3 59.29-133.95 88.94h-1v-90.84C89.44 148.72 44.72 119.33 0 89.94Z`,`M162 188c-.33 27-.67 54-1 81-26.87-26.18-53.74-52.35-80-77.94V269H0C0 180.83 0 92.67.04 4.5.04 3 .67 1.5 1 0c24.64 29.1 49.15 58.31 73.96 87.26 28.88 33.7 58.01 67.17 87.04 100.74Z`,`M3 148.86V61.12C41.76 40.75 80.52 20.37 119.28 0h2.91c21.32 20.7 42.64 41.4 63.96 62.11v89.71c-38.44 20.04-76.88 40.09-115.31 60.13h-2.91L3.01 148.86Z`,`M134 0h2c7.26 22.31 14.38 44.67 21.86 66.9 3.91 11.61 5.47 29.91 13.25 33.27C203 113.94 236.86 123.13 270 134v1L136 269h-1c-11.04-33.58-22.08-67.16-33.21-101.03C67.87 156.98 33.93 145.99 0 135v-1L134 0Z`,`M107 0h1l108 108v1c-26.67 35.33-53.33 70.66-80 106h-1c-8.82-35.03-17.64-70.07-27-107.28C98.62 145.01 89.81 180 81.01 215h-1C53.33 179.66 26.67 144.33 0 109v-2L107 0Z`,`M0 1C2.17.67 4.33.05 6.5.04 58.33-.01 110.17 0 162 0v270H2c26.2-22.17 52.41-44.33 78.86-66.71V67.4c-3.85-3.22-7.35-6.2-10.9-9.11C46.64 39.18 23.32 20.09 0 1Z`,`M95 268.99h-1C62.66 238.66 31.33 208.33 0 178V88C26.67 58.67 53.33 29.33 80 0h1c0 29.45 0 58.89-.01 88.38 35.99 29.57 72 59.09 108.01 88.61v1l-94 91Z`,`M13 0h67l135 135v1L81 270c-27-.33-54-.67-81-1 11.73-12.51 23.61-24.87 35.16-37.54 33.14-36.35 66.14-72.82 100.23-110.38C94.4 80.52 53.7 40.26 13 0Z`];export{Z as ColorShapes};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@m2c2kit/assessment-color-shapes",
3
- "version": "0.8.34",
3
+ "version": "0.8.35",
4
4
  "m2c2kit": {
5
5
  "assessmentId": "color-shapes",
6
6
  "locales": [
@@ -11,10 +11,10 @@
11
11
  },
12
12
  "description": "A visual array change detection task, measuring intra-item feature binding, where participants determine if shapes change color across two sequential presentations of shape stimuli",
13
13
  "scripts": {
14
- "build": "npm run clean && tsc && rollup -c && npm run schemas",
15
- "serve": "concurrently \"rollup -c rollup.config.runner.mjs --watch --configServe\" \"tsc --project tsconfig.runner.json --watch\" --names rollup,typescript --prefix-colors auto,red",
16
- "schemas": "node ../schema-util/build/index.js list --schema=all --files=src/index.ts --format=json-schema --title=\"Color Shapes version __VERSION__\" > schemas.json",
17
- "clean": "rimraf build dist .rollup.cache tsconfig.tsbuildinfo tsconfig.runner.tsbuildinfo",
14
+ "build": "npm run clean && tsc && rolldown -c && npm run schemas",
15
+ "serve": "concurrently \"rolldown -c rolldown.config.runner.mjs --watch\" \"tsc --project tsconfig.runner.json --watch\" --names rolldown,typescript --prefix-colors auto,red",
16
+ "schemas": "node ../schema-util/dist/index.js list --schema=all --files=src/index.ts --format=json-schema --title=\"Color Shapes version __VERSION__\" > schemas.json",
17
+ "clean": "rimraf build dist *.tsbuildinfo schemas.json --glob",
18
18
  "test": "cd ../.. && npx env-cmd -f .env.jest jest --selectProjects @m2c2kit/assessment-color-shapes"
19
19
  },
20
20
  "main": "./dist/index.js",
@@ -23,8 +23,9 @@
23
23
  "types": "./dist/index.d.ts",
24
24
  "exports": {
25
25
  ".": {
26
+ "types": "./dist/index.d.ts",
26
27
  "import": "./dist/index.js",
27
- "types": "./dist/index.d.ts"
28
+ "default": "./dist/index.js"
28
29
  }
29
30
  },
30
31
  "files": [
@@ -44,20 +45,17 @@
44
45
  },
45
46
  "homepage": "https://m2c2-project.github.io/m2c2kit",
46
47
  "dependencies": {
47
- "@m2c2kit/addons": "0.3.35",
48
- "@m2c2kit/core": "0.3.36",
49
- "@m2c2kit/data-calc": "0.8.7"
48
+ "@m2c2kit/addons": "0.3.36",
49
+ "@m2c2kit/core": "0.3.37",
50
+ "@m2c2kit/data-calc": "0.8.8"
50
51
  },
51
52
  "devDependencies": {
52
- "@m2c2kit/build-helpers": "0.3.32",
53
- "@m2c2kit/schema-util": "0.1.26",
54
- "@m2c2kit/session": "0.3.18",
55
- "@rollup/plugin-node-resolve": "16.0.3",
56
- "concurrently": "9.2.1",
53
+ "@m2c2kit/build-helpers": "0.3.33",
54
+ "@m2c2kit/schema-util": "0.1.27",
55
+ "@m2c2kit/session": "0.3.19",
56
+ "concurrently": "10.0.3",
57
57
  "rimraf": "6.1.3",
58
- "rollup": "4.59.0",
59
- "rollup-plugin-copy": "3.5.0",
60
- "rollup-plugin-esbuild": "6.2.1",
58
+ "rolldown": "1.1.0",
61
59
  "typescript": "5.9.3"
62
60
  },
63
61
  "engines": {
package/schemas.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "http://json-schema.org/draft-07/schema",
3
- "title": "Color Shapes version 0.8.34, 38a5862e",
3
+ "title": "Color Shapes version 0.8.35, 35887002",
4
4
  "type": "object",
5
5
  "description": "All game schemas",
6
6
  "properties": {
@@ -1,3 +0,0 @@
1
- import { ActivityKeyValueData } from "@m2c2kit/core";
2
- export declare const data: ActivityKeyValueData[][];
3
- //# sourceMappingURL=data.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"data.d.ts","sourceRoot":"","sources":["../../src/__tests__/data.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAErD,eAAO,MAAM,IAAI,EAAE,oBAAoB,EAAE,EA2/DxC,CAAC"}
@@ -1,2 +0,0 @@
1
- export declare const pythonCode = "\nimport numpy as np\nimport pandas as pd\nfrom typing import Dict, Any\n\ndef summarize_common_metadata(x: pd.DataFrame, trials_expected: int) -> Dict[str, Any]:\n \"\"\"\n Extract shared metadata and trial count checks from a grouped DataFrame.\n\n Args:\n x (pd.DataFrame): Grouped trial-level DataFrame.\n trials_expected (int): Expected number of trials.\n\n Returns:\n Dict[str, Any]: Summary metadata and quality flags.\n \"\"\"\n if \"trial_index\" in x.columns:\n n_trials = x[\"trial_index\"].nunique()\n else:\n # warnings.warn(\"No 'trial_index' column found; assuming single-trial task.\")\n # For single-trial tasks (like Trailmaking), treat as one trial\n n_trials = 1\n return {\n \"activity_begin_iso8601_timestamp\": x[\"activity_begin_iso8601_timestamp\"].iloc[\n 0\n ],\n \"n_trials\": n_trials,\n \"flag_trials_match_expected\": n_trials == trials_expected,\n \"flag_trials_lt_expected\": n_trials < trials_expected,\n \"flag_trials_gt_expected\": n_trials > trials_expected,\n }\n\ndef score_shapes(row: pd.Series, method=\"accuracy\"):\n \"\"\"Score a single row of a color shapes task dataframe based on the method given.\n\n Args:\n row (pd.Series):\n A single row of a color shapes task dataframe containing the columns \"user_response\" and \"user_response_correct\".\n method (str, optional):\n The scoring method to use. Defaults to \"accuracy\". Can be \"accuracy\" or \"signal\".\n\n Returns:\n (str | None):\n If method is \"accuracy\", returns \"CR\", \"MISS\", \"HIT\", or \"FA\".\n If method is \"signal\", returns \"SAME\" or \"DIFFERENT\".\n Otherwise, returns None.\n\n Raises:\n Exception:\n If an error occurs while processing the row.\n\n \"\"\"\n\n try:\n user_response_string = row[\"user_response\"]\n user_response_correct = row[\"user_response_correct\"]\n\n if user_response_string == \"same\" and user_response_correct:\n if method == \"accuracy\":\n return \"CR\" # Correct Rejection\n elif method == \"signal\":\n return \"SAME\"\n\n elif user_response_string == \"same\" and not user_response_correct:\n if method == \"accuracy\":\n return \"MISS\"\n elif method == \"signal\":\n return \"DIFFERENT\"\n\n elif user_response_string == \"different\" and user_response_correct:\n if method == \"accuracy\":\n return \"HIT\"\n elif method == \"signal\":\n return \"DIFFERENT\"\n\n elif user_response_string == \"different\" and not user_response_correct:\n if method == \"accuracy\":\n return \"FA\" # False Alarm\n elif method == \"signal\":\n return \"SAME\"\n\n else:\n # Return None on unexpected response combinations\n print(\n f\"Unexpected response combination: user_response='{user_response_string}', user_response_correct='{user_response_correct}'\"\n )\n return None\n\n except Exception as e:\n print(f\"Error processing row: {e}\")\n return None\n\n\ndef score_accuracy(row):\n \"\"\"\n Scores the accuracy of the response for a single trial in the Color Shapes task.\n\n Args:\n row (pd.Series): A single row of the trial-level Color Shapes task dataframe.\n\n Returns:\n (str | None):\n A string indicating the accuracy of the response, such as \"CR\" for Correct Rejection,\n \"MISS\", \"HIT\", or \"FA\" for False Alarm, based on the scoring criteria.\n None is returned if an error occurs while processing the row.\n \"\"\"\n\n return score_shapes(row, method=\"accuracy\")\n\n\ndef score_signal(row):\n \"\"\"\n Scores the signal type of the response for a single trial in the Color Shapes task.\n\n Args:\n row (pd.Series): A single row of the trial-level Color Shapes task dataframe.\n\n Returns:\n (str | None): A string indicating the signal type of the response, either \"SAME\" or \"DIFFERENT\",\n based on the scoring criteria.\n None is returned if an error occurs while processing the row.\n \"\"\"\n\n return score_shapes(row, method=\"signal\")\n\n\ndef summarize(x, trials_expected=10, rt_outlier_low=100, rt_outlier_high=10000):\n \"\"\"\n Summarizes the Color Shapes task data by calculating various statistics.\n\n This function calculates the number of hits, misses, false alarms, and correct rejections\n based on the accuracy of responses in the Color Shapes task. It computes signal detection\n rates and evaluates response times, filtering out null, invalid, and outlier values.\n\n Args:\n x (pd.DataFrame): The trial-level scored dataset for the Color Shapes task.\n trials_expected (int, optional): The expected number of trials. Defaults to 10.\n rt_outlier_low (int, optional): The lower bound for filtering outliers in response times. Defaults to 100.\n rt_outlier_high (int, optional): The upper bound for filtering outliers in response times. Defaults to 10000.\n\n Returns:\n (pd.Series): A Pandas Series containing the summary statistics for the Color Shapes task.\n \"\"\"\n\n d = summarize_common_metadata(x, trials_expected)\n \n # Number of accuracy hits, misses, false alarms, and correct rejections\n for metric in [\"HIT\", \"MISS\", \"FA\", \"CR\"]:\n d[f\"n_trials_{metric}\"] = (x[\"metric_accuracy\"] == metric).sum()\n\n # Number of each trial type\n d[\"n_trials_type_same\"] = (x[\"metric_trial_type\"] == \"SAME\").sum()\n d[\"n_trials_type_different\"] = (x[\"metric_trial_type\"] == \"DIFFERENT\").sum()\n\n # Signal Detection Rates - with safe division for zero trial types\n if d[\"n_trials_type_different\"] > 0:\n d[\"HIT_rate\"] = d[\"n_trials_HIT\"] / d[\"n_trials_type_different\"]\n d[\"MISS_rate\"] = 1 - d[\"HIT_rate\"]\n else:\n d[\"HIT_rate\"] = np.nan\n d[\"MISS_rate\"] = np.nan\n\n if d[\"n_trials_type_same\"] > 0:\n d[\"FA_rate\"] = d[\"n_trials_FA\"] / d[\"n_trials_type_same\"]\n d[\"CR_rate\"] = 1 - d[\"FA_rate\"]\n else:\n d[\"FA_rate\"] = np.nan\n d[\"CR_rate\"] = np.nan\n\n # Response Times - Handle null/invalid response times first\n valid_rt_mask = pd.notna(x[\"response_time_duration_ms\"]) & (\n x[\"response_time_duration_ms\"] > 0\n )\n valid_rt_data = x.loc[valid_rt_mask, \"response_time_duration_ms\"]\n\n # Number of trials that had null/invalid response times\n d[\"n_trials_rt_invalid\"] = (\n x[\"response_time_duration_ms\"].shape[0] - valid_rt_data.shape[0]\n )\n\n # Overall Response Times (nulls/invalid removed only)\n d[\"median_rt_overall_valid\"] = valid_rt_data.median()\n d[\"sd_rt_overall_valid\"] = valid_rt_data.std()\n\n # Response Times by accuracy type (nulls/invalid removed only)\n for metric in [\"HIT\", \"MISS\", \"FA\", \"CR\"]:\n metric_mask = (x[\"metric_accuracy\"] == metric) & valid_rt_mask\n rt_signal = x.loc[metric_mask, \"response_time_duration_ms\"]\n d[f\"median_rt_{metric}_valid\"] = rt_signal.median()\n d[f\"sd_rt_{metric}_valid\"] = rt_signal.std()\n\n # Filtered Overall Response Times (nulls/invalid and outliers removed)\n rt_filtered_overall = x.loc[\n valid_rt_mask\n & (x[\"response_time_duration_ms\"] >= rt_outlier_low)\n & (x[\"response_time_duration_ms\"] <= rt_outlier_high),\n \"response_time_duration_ms\",\n ]\n d[\"median_rt_overall_valid_filtered\"] = rt_filtered_overall.median()\n d[\"sd_rt_overall_valid_filtered\"] = rt_filtered_overall.std()\n\n # Count of outliers filtered out\n d[\"n_outliers_rt_overall_valid\"] = (\n valid_rt_data.shape[0] - rt_filtered_overall.shape[0]\n )\n\n # Filtered Response Times by accuracy type (nulls/invalid and outliers removed)\n for metric in [\"HIT\", \"MISS\", \"FA\", \"CR\"]:\n metric_mask = (x[\"metric_accuracy\"] == metric) & valid_rt_mask\n rt_filtered_signal = x.loc[\n metric_mask\n & (x[\"response_time_duration_ms\"] >= rt_outlier_low)\n & (x[\"response_time_duration_ms\"] <= rt_outlier_high),\n \"response_time_duration_ms\",\n ]\n d[f\"median_rt_{metric}_valid_filtered\"] = rt_filtered_signal.median()\n d[f\"sd_rt_{metric}_valid_filtered\"] = rt_filtered_signal.std()\n\n # Count of outliers filtered out per accuracy type\n metric_rt_data = x.loc[metric_mask, \"response_time_duration_ms\"]\n d[f\"n_outliers_rt_{metric}_valid\"] = (\n metric_rt_data.shape[0] - rt_filtered_signal.shape[0]\n )\n\n return pd.Series(d)\n";
2
- //# sourceMappingURL=python-code.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"python-code.d.ts","sourceRoot":"","sources":["../../src/__tests__/python-code.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU,m5RAiOtB,CAAC"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=scoring.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"scoring.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/scoring.test.ts"],"names":[],"mappings":""}