@khanacademy/perseus-core 34.0.0 → 34.0.2

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.js CHANGED
@@ -47,7 +47,7 @@ function addWidget(id){return `[[☃ ${id}]]`}function getWidgetRegex(){return /
47
47
 
48
48
  function deepClone(obj){return JSON.parse(JSON.stringify(obj))}
49
49
 
50
- const MOVABLES={PLOT:"PLOT",PARABOLA:"PARABOLA",SINUSOID:"SINUSOID"};function canonicalSineCoefficients(coeffs){let amplitude=coeffs[0];let angularFrequency=coeffs[1];let phase=coeffs[2];const verticalOffset=coeffs[3];if(amplitude<0){amplitude*=-1;angularFrequency*=-1;phase*=-1;}const period=2*Math.PI;if(angularFrequency<0){angularFrequency*=-1;phase*=-1;phase+=period/2;}while(phase>0){phase-=period;}while(phase<0){phase+=period;}return [amplitude,angularFrequency,phase,verticalOffset]}const PlotDefaults={areEqual:function(coeffs1,coeffs2){return approximateDeepEqual(coeffs1,coeffs2)},movable:MOVABLES.PLOT,getPropsForCoeffs:function(coeffs){return {fn:___default.default.partial(this.getFunctionForCoeffs,coeffs)}}};const Linear=___default.default.extend({},PlotDefaults,{url:"https://ka-perseus-graphie.s3.amazonaws.com/67aaf581e6d9ef9038c10558a1f70ac21c11c9f8.png",defaultCoords:[[.25,.75],[.75,.75]],getCoefficients:function(coords){const p1=coords[0];const p2=coords[1];const denom=p2[0]-p1[0];const num=p2[1]-p1[1];if(denom===0){return}const m=num/denom;const b=p2[1]-m*p2[0];return [m,b]},getFunctionForCoeffs:function(coeffs,x){const m=coeffs[0];const b=coeffs[1];return m*x+b},getEquationString:function(coords){const coeffs=this.getCoefficients(coords);const m=coeffs[0];const b=coeffs[1];return "y = "+m.toFixed(3)+"x + "+b.toFixed(3)}});const Quadratic=___default.default.extend({},PlotDefaults,{url:"https://ka-perseus-graphie.s3.amazonaws.com/e23d36e6fc29ee37174e92c9daba2a66677128ab.png",defaultCoords:[[.5,.5],[.75,.75]],movable:MOVABLES.PARABOLA,getCoefficients:function(coords){const p1=coords[0];const p2=coords[1];const h=p1[0];const k=p1[1];const a=(p2[1]-k)/((p2[0]-h)*(p2[0]-h));const b=-2*h*a;const c=a*h*h+k;return [a,b,c]},getFunctionForCoeffs:function(coeffs,x){const a=coeffs[0];const b=coeffs[1];const c=coeffs[2];return (a*x+b)*x+c},getPropsForCoeffs:function(coeffs){return {a:coeffs[0],b:coeffs[1],c:coeffs[2]}},getEquationString:function(coords){const coeffs=this.getCoefficients(coords);const a=coeffs[0];const b=coeffs[1];const c=coeffs[2];return "y = "+a.toFixed(3)+"x^2 + "+b.toFixed(3)+"x + "+c.toFixed(3)}});const Sinusoid=___default.default.extend({},PlotDefaults,{url:"https://ka-perseus-graphie.s3.amazonaws.com/3d68e7718498475f53b206c2ab285626baf8857e.png",defaultCoords:[[.5,.5],[.6,.6]],movable:MOVABLES.SINUSOID,getCoefficients:function(coords){const p1=coords[0];const p2=coords[1];const a=p2[1]-p1[1];const b=Math.PI/(2*(p2[0]-p1[0]));const c=p1[0]*b;const d=p1[1];return [a,b,c,d]},getFunctionForCoeffs:function(coeffs,x){const a=coeffs[0];const b=coeffs[1];const c=coeffs[2];const d=coeffs[3];return a*Math.sin(b*x-c)+d},getPropsForCoeffs:function(coeffs){return {a:coeffs[0],b:coeffs[1],c:coeffs[2],d:coeffs[3]}},getEquationString:function(coords){const coeffs=this.getCoefficients(coords);const a=coeffs[0];const b=coeffs[1];const c=coeffs[2];const d=coeffs[3];return "y = "+a.toFixed(3)+" sin("+b.toFixed(3)+"x - "+c.toFixed(3)+") + "+d.toFixed(3)},areEqual:function(coeffs1,coeffs2){return approximateDeepEqual(canonicalSineCoefficients(coeffs1),canonicalSineCoefficients(coeffs2))}});const Tangent=___default.default.extend({},PlotDefaults,{url:"https://ka-perseus-graphie.s3.amazonaws.com/7db80d23c35214f98659fe1cf0765811c1bbfbba.png",defaultCoords:[[.5,.5],[.75,.75]],getCoefficients:function(coords){const p1=coords[0];const p2=coords[1];const a=p2[1]-p1[1];const b=Math.PI/(4*(p2[0]-p1[0]));const c=p1[0]*b;const d=p1[1];return [a,b,c,d]},getFunctionForCoeffs:function(coeffs,x){const a=coeffs[0];const b=coeffs[1];const c=coeffs[2];const d=coeffs[3];return a*Math.tan(b*x-c)+d},getEquationString:function(coords){const coeffs=this.getCoefficients(coords);const a=coeffs[0];const b=coeffs[1];const c=coeffs[2];const d=coeffs[3];return "y = "+a.toFixed(3)+" tan("+b.toFixed(3)+"x - "+c.toFixed(3)+") + "+d.toFixed(3)}});const Exponential=___default.default.extend({},PlotDefaults,{url:"https://ka-perseus-graphie.s3.amazonaws.com/9cbfad55525e3ce755a31a631b074670a5dad611.png",defaultCoords:[[.5,.55],[.75,.75]],defaultAsymptote:[[0,.5],[1,.5]],extraCoordConstraint:function(newCoord,oldCoord,coords,asymptote,graph){const y=asymptote[0][1];return ___default.default.all(coords,coord=>coord[1]!==y)},extraAsymptoteConstraint:function(newCoord,oldCoord,coords,asymptote,graph){const y=newCoord[1];const isValid=___default.default.all(coords,coord=>coord[1]>y)||___default.default.all(coords,coord=>coord[1]<y);if(isValid){return [oldCoord[0],y]}const oldY=oldCoord[1];const wasBelow=___default.default.all(coords,coord=>coord[1]>oldY);if(wasBelow){const bottomMost=___default.default.min(___default.default.map(coords,coord=>coord[1]));return [oldCoord[0],bottomMost-graph.snapStep[1]]}const topMost=___default.default.max(___default.default.map(coords,coord=>coord[1]));return [oldCoord[0],topMost+graph.snapStep[1]]},allowReflectOverAsymptote:true,getCoefficients:function(coords,asymptote){const p1=coords[0];const p2=coords[1];const c=asymptote[0][1];const b=Math.log((p1[1]-c)/(p2[1]-c))/(p1[0]-p2[0]);const a=(p1[1]-c)/Math.exp(b*p1[0]);return [a,b,c]},getFunctionForCoeffs:function(coeffs,x){const a=coeffs[0];const b=coeffs[1];const c=coeffs[2];return a*Math.exp(b*x)+c},getEquationString:function(coords,asymptote){if(!asymptote){return null}const coeffs=this.getCoefficients(coords,asymptote);const a=coeffs[0];const b=coeffs[1];const c=coeffs[2];return "y = "+a.toFixed(3)+"e^("+b.toFixed(3)+"x) + "+c.toFixed(3)}});const Logarithm=___default.default.extend({},PlotDefaults,{url:"https://ka-perseus-graphie.s3.amazonaws.com/f6491e99d34af34d924bfe0231728ad912068dc3.png",defaultCoords:[[.55,.5],[.75,.75]],defaultAsymptote:[[.5,0],[.5,1]],extraCoordConstraint:function(newCoord,oldCoord,coords,asymptote,graph){const x=asymptote[0][0];return ___default.default.all(coords,coord=>coord[0]!==x)&&coords[0][1]!==coords[1][1]},extraAsymptoteConstraint:function(newCoord,oldCoord,coords,asymptote,graph){const x=newCoord[0];const isValid=___default.default.all(coords,coord=>coord[0]>x)||___default.default.all(coords,coord=>coord[0]<x);if(isValid){return [x,oldCoord[1]]}const oldX=oldCoord[0];const wasLeft=___default.default.all(coords,coord=>coord[0]>oldX);if(wasLeft){const leftMost=___default.default.min(___default.default.map(coords,coord=>coord[0]));return [leftMost-graph.snapStep[0],oldCoord[1]]}const rightMost=___default.default.max(___default.default.map(coords,coord=>coord[0]));return [rightMost+graph.snapStep[0],oldCoord[1]]},allowReflectOverAsymptote:true,getCoefficients:function(coords,asymptote){const flip=coord=>[coord[1],coord[0]];const inverseCoeffs=Exponential.getCoefficients(___default.default.map(coords,flip),___default.default.map(asymptote,flip));if(inverseCoeffs){const c=-inverseCoeffs[2]/inverseCoeffs[0];const b=1/inverseCoeffs[0];const a=1/inverseCoeffs[1];return [a,b,c]}},getFunctionForCoeffs:function(coeffs,x,asymptote){const a=coeffs[0];const b=coeffs[1];const c=coeffs[2];return a*Math.log(b*x+c)},getEquationString:function(coords,asymptote){if(!asymptote){return null}const coeffs=this.getCoefficients(coords,asymptote);const a=coeffs[0];const b=coeffs[1];const c=coeffs[2];return "y = ln("+a.toFixed(3)+"x + "+b.toFixed(3)+") + "+c.toFixed(3)}});const AbsoluteValue=___default.default.extend({},PlotDefaults,{url:"https://ka-perseus-graphie.s3.amazonaws.com/8256a630175a0cb1d11de223d6de0266daf98721.png",defaultCoords:[[.5,.5],[.75,.75]],getCoefficients:function(coords){const p1=coords[0];const p2=coords[1];const denom=p2[0]-p1[0];const num=p2[1]-p1[1];if(denom===0){return}let m=Math.abs(num/denom);if(p2[1]<p1[1]){m*=-1;}const horizontalOffset=p1[0];const verticalOffset=p1[1];return [m,horizontalOffset,verticalOffset]},getFunctionForCoeffs:function(coeffs,x){const m=coeffs[0];const horizontalOffset=coeffs[1];const verticalOffset=coeffs[2];return m*Math.abs(x-horizontalOffset)+verticalOffset},getEquationString:function(coords){const coeffs=this.getCoefficients(coords);const m=coeffs[0];const horizontalOffset=coeffs[1];const verticalOffset=coeffs[2];return "y = "+m.toFixed(3)+"| x - "+horizontalOffset.toFixed(3)+"| + "+verticalOffset.toFixed(3)}});const functionTypeMapping={linear:Linear,quadratic:Quadratic,sinusoid:Sinusoid,tangent:Tangent,exponential:Exponential,logarithm:Logarithm,absolute_value:AbsoluteValue};const allTypes=___default.default.keys(functionTypeMapping);function functionForType(type){return functionTypeMapping[type]}
50
+ const MOVABLES={PLOT:"PLOT",PARABOLA:"PARABOLA",SINUSOID:"SINUSOID"};function canonicalSineCoefficients(coeffs){let amplitude=coeffs[0];let angularFrequency=coeffs[1];let phase=coeffs[2];const verticalOffset=coeffs[3];if(amplitude<0){amplitude*=-1;angularFrequency*=-1;phase*=-1;}const period=2*Math.PI;if(angularFrequency<0){angularFrequency*=-1;phase*=-1;phase+=period/2;}while(phase>0){phase-=period;}while(phase<0){phase+=period;}return [amplitude,angularFrequency,phase,verticalOffset]}const PlotDefaults={areEqual:function(coeffs1,coeffs2){return approximateDeepEqual(coeffs1,coeffs2)},movable:MOVABLES.PLOT,getPropsForCoeffs:function(coeffs){return {fn:___default.default.partial(this.getFunctionForCoeffs,coeffs)}}};const Linear=___default.default.extend({},PlotDefaults,{url:"https://ka-perseus-graphie.s3.amazonaws.com/67aaf581e6d9ef9038c10558a1f70ac21c11c9f8.png",defaultCoords:[[.25,.75],[.75,.75]],getCoefficients:function(coords){const p1=coords[0];const p2=coords[1];const denom=p2[0]-p1[0];const num=p2[1]-p1[1];if(denom===0){return}const m=num/denom;const b=p2[1]-m*p2[0];return [m,b]},getFunctionForCoeffs:function(coeffs,x){const m=coeffs[0];const b=coeffs[1];return m*x+b},getEquationString:function(coords){const coeffs=this.getCoefficients(coords);const m=coeffs[0];const b=coeffs[1];return "y = "+m.toFixed(3)+"x + "+b.toFixed(3)}});const Quadratic=___default.default.extend({},PlotDefaults,{url:"https://ka-perseus-graphie.s3.amazonaws.com/e23d36e6fc29ee37174e92c9daba2a66677128ab.png",defaultCoords:[[.5,.5],[.75,.75]],movable:MOVABLES.PARABOLA,getCoefficients:function(coords){const p1=coords[0];const p2=coords[1];const h=p1[0];const k=p1[1];const a=(p2[1]-k)/((p2[0]-h)*(p2[0]-h));const b=-2*h*a;const c=a*h*h+k;return [a,b,c]},getFunctionForCoeffs:function(coeffs,x){const a=coeffs[0];const b=coeffs[1];const c=coeffs[2];return (a*x+b)*x+c},getPropsForCoeffs:function(coeffs){return {a:coeffs[0],b:coeffs[1],c:coeffs[2]}},getEquationString:function(coords){const coeffs=this.getCoefficients(coords);const a=coeffs[0];const b=coeffs[1];const c=coeffs[2];return "y = "+a.toFixed(3)+"x^2 + "+b.toFixed(3)+"x + "+c.toFixed(3)}});const Sinusoid=___default.default.extend({},PlotDefaults,{url:"https://ka-perseus-graphie.s3.amazonaws.com/3d68e7718498475f53b206c2ab285626baf8857e.png",defaultCoords:[[.5,.5],[.6,.6]],movable:MOVABLES.SINUSOID,getCoefficients:function(coords){const p1=coords[0];const p2=coords[1];const a=p2[1]-p1[1];const b=Math.PI/(2*(p2[0]-p1[0]));const c=p1[0]*b;const d=p1[1];return [a,b,c,d]},getFunctionForCoeffs:function(coeffs,x){const a=coeffs[0];const b=coeffs[1];const c=coeffs[2];const d=coeffs[3];return a*Math.sin(b*x-c)+d},getPropsForCoeffs:function(coeffs){return {a:coeffs[0],b:coeffs[1],c:coeffs[2],d:coeffs[3]}},getEquationString:function(coords){const coeffs=this.getCoefficients(coords);const a=coeffs[0];const b=coeffs[1];const c=coeffs[2];const d=coeffs[3];return "y = "+a.toFixed(3)+" sin("+b.toFixed(3)+"x - "+c.toFixed(3)+") + "+d.toFixed(3)},areEqual:function(coeffs1,coeffs2){return approximateDeepEqual(canonicalSineCoefficients(coeffs1),canonicalSineCoefficients(coeffs2))}});const Tangent=___default.default.extend({},PlotDefaults,{url:"https://ka-perseus-graphie.s3.amazonaws.com/7db80d23c35214f98659fe1cf0765811c1bbfbba.png",defaultCoords:[[.5,.5],[.75,.75]],getCoefficients:function(coords){const p1=coords[0];const p2=coords[1];const a=p2[1]-p1[1];const b=Math.PI/(4*(p2[0]-p1[0]));const c=p1[0]*b;const d=p1[1];return [a,b,c,d]},getFunctionForCoeffs:function(coeffs,x){const a=coeffs[0];const b=coeffs[1];const c=coeffs[2];const d=coeffs[3];return a*Math.tan(b*x-c)+d},getEquationString:function(coords){const coeffs=this.getCoefficients(coords);const a=coeffs[0];const b=coeffs[1];const c=coeffs[2];const d=coeffs[3];return "y = "+a.toFixed(3)+" tan("+b.toFixed(3)+"x - "+c.toFixed(3)+") + "+d.toFixed(3)}});const Exponential=___default.default.extend({},PlotDefaults,{url:"https://ka-perseus-graphie.s3.amazonaws.com/9cbfad55525e3ce755a31a631b074670a5dad611.png",defaultCoords:[[.5,.55],[.75,.75]],defaultAsymptote:[[0,.5],[1,.5]],extraCoordConstraint:function(newCoord,oldCoord,coords,asymptote,graph){const y=asymptote[0][1];return ___default.default.all(coords,coord=>coord[1]!==y)},extraAsymptoteConstraint:function(newCoord,oldCoord,coords,asymptote,graph){const y=newCoord[1];const isValid=___default.default.all(coords,coord=>coord[1]>y)||___default.default.all(coords,coord=>coord[1]<y);if(isValid){return [oldCoord[0],y]}const oldY=oldCoord[1];const wasBelow=___default.default.all(coords,coord=>coord[1]>oldY);if(wasBelow){const bottomMost=___default.default.min(coords.map(coord=>coord[1]));return [oldCoord[0],bottomMost-graph.snapStep[1]]}const topMost=___default.default.max(coords.map(coord=>coord[1]));return [oldCoord[0],topMost+graph.snapStep[1]]},allowReflectOverAsymptote:true,getCoefficients:function(coords,asymptote){const p1=coords[0];const p2=coords[1];const c=asymptote[0][1];const b=Math.log((p1[1]-c)/(p2[1]-c))/(p1[0]-p2[0]);const a=(p1[1]-c)/Math.exp(b*p1[0]);return [a,b,c]},getFunctionForCoeffs:function(coeffs,x){const a=coeffs[0];const b=coeffs[1];const c=coeffs[2];return a*Math.exp(b*x)+c},getEquationString:function(coords,asymptote){if(!asymptote){return null}const coeffs=this.getCoefficients(coords,asymptote);const a=coeffs[0];const b=coeffs[1];const c=coeffs[2];return "y = "+a.toFixed(3)+"e^("+b.toFixed(3)+"x) + "+c.toFixed(3)}});const Logarithm=___default.default.extend({},PlotDefaults,{url:"https://ka-perseus-graphie.s3.amazonaws.com/f6491e99d34af34d924bfe0231728ad912068dc3.png",defaultCoords:[[.55,.5],[.75,.75]],defaultAsymptote:[[.5,0],[.5,1]],extraCoordConstraint:function(newCoord,oldCoord,coords,asymptote,graph){const x=asymptote[0][0];return ___default.default.all(coords,coord=>coord[0]!==x)&&coords[0][1]!==coords[1][1]},extraAsymptoteConstraint:function(newCoord,oldCoord,coords,asymptote,graph){const x=newCoord[0];const isValid=___default.default.all(coords,coord=>coord[0]>x)||___default.default.all(coords,coord=>coord[0]<x);if(isValid){return [x,oldCoord[1]]}const oldX=oldCoord[0];const wasLeft=___default.default.all(coords,coord=>coord[0]>oldX);if(wasLeft){const leftMost=___default.default.min(coords.map(coord=>coord[0]));return [leftMost-graph.snapStep[0],oldCoord[1]]}const rightMost=___default.default.max(coords.map(coord=>coord[0]));return [rightMost+graph.snapStep[0],oldCoord[1]]},allowReflectOverAsymptote:true,getCoefficients:function(coords,asymptote){const flip=coord=>[coord[1],coord[0]];const inverseCoeffs=Exponential.getCoefficients(coords.map(flip),asymptote.map(flip));if(inverseCoeffs){const c=-inverseCoeffs[2]/inverseCoeffs[0];const b=1/inverseCoeffs[0];const a=1/inverseCoeffs[1];return [a,b,c]}},getFunctionForCoeffs:function(coeffs,x,asymptote){const a=coeffs[0];const b=coeffs[1];const c=coeffs[2];return a*Math.log(b*x+c)},getEquationString:function(coords,asymptote){if(!asymptote){return null}const coeffs=this.getCoefficients(coords,asymptote);const a=coeffs[0];const b=coeffs[1];const c=coeffs[2];return "y = ln("+a.toFixed(3)+"x + "+b.toFixed(3)+") + "+c.toFixed(3)}});const AbsoluteValue=___default.default.extend({},PlotDefaults,{url:"https://ka-perseus-graphie.s3.amazonaws.com/8256a630175a0cb1d11de223d6de0266daf98721.png",defaultCoords:[[.5,.5],[.75,.75]],getCoefficients:function(coords){const p1=coords[0];const p2=coords[1];const denom=p2[0]-p1[0];const num=p2[1]-p1[1];if(denom===0){return}let m=Math.abs(num/denom);if(p2[1]<p1[1]){m*=-1;}const horizontalOffset=p1[0];const verticalOffset=p1[1];return [m,horizontalOffset,verticalOffset]},getFunctionForCoeffs:function(coeffs,x){const m=coeffs[0];const horizontalOffset=coeffs[1];const verticalOffset=coeffs[2];return m*Math.abs(x-horizontalOffset)+verticalOffset},getEquationString:function(coords){const coeffs=this.getCoefficients(coords);const m=coeffs[0];const horizontalOffset=coeffs[1];const verticalOffset=coeffs[2];return "y = "+m.toFixed(3)+"| x - "+horizontalOffset.toFixed(3)+"| + "+verticalOffset.toFixed(3)}});const functionTypeMapping={linear:Linear,quadratic:Quadratic,sinusoid:Sinusoid,tangent:Tangent,exponential:Exponential,logarithm:Logarithm,absolute_value:AbsoluteValue};const allTypes=Object.keys(functionTypeMapping);function functionForType(type){return functionTypeMapping[type]}
51
51
 
52
52
  var grapherUtil = /*#__PURE__*/Object.freeze({
53
53
  __proto__: null,
@@ -86,7 +86,7 @@ function constant(acceptedValue){return (rawValue,ctx)=>{if(!Object.is(rawValue,
86
86
 
87
87
  function defaulted(parser,fallback){return (rawValue,ctx)=>{if(rawValue==null){return success(fallback(rawValue))}return parser(rawValue,ctx)}}function defaultedNonEmptyString(fallback){return (rawValue,ctx)=>{if(rawValue==null){return ctx.success(fallback())}if(typeof rawValue==="string"){if(rawValue.trim()===""){return ctx.success(fallback())}return ctx.success(rawValue)}return ctx.failure("string",rawValue)}}
88
88
 
89
- function enumeration(...acceptedValues){return (rawValue,ctx)=>{if(typeof rawValue==="string"){const index=acceptedValues.indexOf(rawValue);if(index>-1){return ctx.success(acceptedValues[index])}}const expected=acceptedValues.map(v=>JSON.stringify(v));return ctx.failure(expected,rawValue)}}
89
+ function enumeration(...acceptedValues){return (rawValue,ctx)=>{if(typeof rawValue==="string"||rawValue==null){const index=acceptedValues.indexOf(rawValue);if(index>-1){return ctx.success(acceptedValues[index])}}const expected=acceptedValues.map(v=>JSON.stringify(v));return ctx.failure(expected,rawValue)}}
90
90
 
91
91
  const objectConstructorString=Object.prototype.constructor.toString();const functionToString=Function.prototype.toString;function isPlainObject(x){if(x==null){return false}const prototype=Object.getPrototypeOf(x);if(prototype==null){return true}return typeof prototype.constructor==="function"&&functionToString.call(prototype.constructor)===objectConstructorString}
92
92
 
@@ -164,7 +164,7 @@ const booleanToZero=(rawValue,ctx)=>{if(typeof rawValue==="boolean"){return ctx.
164
164
 
165
165
  const pairOfNumbers$1=pair(number,number);const stringOrEmpty=defaulted(string,()=>"");const parseKey=pipeParsers(optional(string)).then(convert(String)).parser;const parseFunctionElement=object({type:constant("function"),key:parseKey,options:object({value:string,funcName:string,rangeMin:string,rangeMax:string,color:string,strokeDasharray:string,strokeWidth:number})});const parseLabelElement=object({type:constant("label"),key:parseKey,options:object({label:string,color:string,coordX:string,coordY:string})});const parseLineElement=object({type:constant("line"),key:parseKey,options:object({color:string,startX:string,startY:string,endX:string,endY:string,strokeDasharray:string,strokeWidth:number,arrows:string})});const parseMovableLineElement=object({type:constant("movable-line"),key:parseKey,options:object({startX:string,startY:string,startSubscript:number,endX:string,endY:string,endSubscript:number,constraint:string,snap:number,constraintFn:string,constraintXMin:string,constraintXMax:string,constraintYMin:string,constraintYMax:string})});const parseMovablePointElement=object({type:constant("movable-point"),key:parseKey,options:object({startX:string,startY:string,varSubscript:number,constraint:string,snap:number,constraintFn:string,constraintXMin:stringOrEmpty,constraintXMax:stringOrEmpty,constraintYMin:stringOrEmpty,constraintYMax:stringOrEmpty})});const parseParametricElement=object({type:constant("parametric"),key:parseKey,options:object({x:string,y:string,rangeMin:string,rangeMax:string,color:string,strokeDasharray:string,strokeWidth:number})});const parsePointElement=object({type:constant("point"),key:parseKey,options:object({color:string,coordX:string,coordY:string})});const parseRectangleElement=object({type:constant("rectangle"),key:parseKey,options:object({color:string,coordX:string,coordY:string,width:string,height:string})});const parseInteractionWidget=parseWidget(constant("interaction"),object({static:defaulted(boolean,()=>false),graph:object({editableSettings:optional(array(enumeration("canvas","graph"))),box:pairOfNumbers$1,labels:array(string),range:pair(pairOfNumbers$1,pairOfNumbers$1),gridStep:pairOfNumbers$1,markings:enumeration("graph","grid","none","axes"),snapStep:optional(pairOfNumbers$1),valid:optional(union(boolean).or(string).parser),backgroundImage:optional(parsePerseusImageBackground),showProtractor:optional(boolean),showRuler:optional(boolean),rulerLabel:optional(string),rulerTicks:optional(number),tickStep:pairOfNumbers$1}),elements:array(discriminatedUnionOn("type").withBranch("function",parseFunctionElement).withBranch("label",parseLabelElement).withBranch("line",parseLineElement).withBranch("movable-line",parseMovableLineElement).withBranch("movable-point",parseMovablePointElement).withBranch("parametric",parseParametricElement).withBranch("point",parsePointElement).withBranch("rectangle",parseRectangleElement).parser)}));
166
166
 
167
- const pairOfNumbers=pair(number,number);const parsePerseusGraphTypeAngle=object({type:constant("angle"),showAngles:optional(boolean),allowReflexAngles:optional(boolean),angleOffsetDeg:optional(nullable(number)),snapDegrees:optional(number),match:optional(constant("congruent")),coords:optional(trio(pairOfNumbers,pairOfNumbers,pairOfNumbers)),startCoords:optional(trio(pairOfNumbers,pairOfNumbers,pairOfNumbers)),pointLabels:optional(trio(string,string,string)),showPointLabels:optional(boolean)});const parsePerseusGraphTypeCircle=object({type:constant("circle"),center:optional(pairOfNumbers),radius:optional(number),startCoords:optional(object({center:pairOfNumbers,radius:number})),pointLabels:optional(array(string)),showPointLabels:optional(boolean)});const parsePerseusGraphTypeLinear=object({type:constant("linear"),coords:optional(nullable(pair(pairOfNumbers,pairOfNumbers))),startCoords:optional(pair(pairOfNumbers,pairOfNumbers)),pointLabels:optional(pair(string,string)),showPointLabels:optional(boolean)});const parsePerseusGraphTypeLinearSystem=object({type:constant("linear-system"),coords:optional(nullable(array(pair(pairOfNumbers,pairOfNumbers)))),startCoords:optional(array(pair(pairOfNumbers,pairOfNumbers))),pointLabels:optional(array(string)),showPointLabels:optional(boolean)});const parsePerseusGraphTypeNone=object({type:constant("none")});const parsePerseusGraphTypePoint=object({type:constant("point"),numPoints:optional(union(number).or(constant("unlimited")).parser),coords:optional(nullable(array(pairOfNumbers))),startCoords:optional(array(pairOfNumbers)),coord:optional(pairOfNumbers),pointLabels:optional(array(string)),showPointLabels:optional(boolean)});const parsePerseusGraphTypePolygon=object({type:constant("polygon"),numSides:optional(union(number).or(constant("unlimited")).parser),showAngles:optional(boolean),showSides:optional(boolean),snapTo:optional(enumeration("grid","angles","sides")),match:optional(enumeration("similar","congruent","approx","exact")),startCoords:optional(array(pairOfNumbers)),coords:optional(nullable(array(pairOfNumbers))),pointLabels:optional(array(string)),showPointLabels:optional(boolean)});const parsePerseusGraphTypeQuadratic=object({type:constant("quadratic"),coords:optional(nullable(trio(pairOfNumbers,pairOfNumbers,pairOfNumbers))),startCoords:optional(trio(pairOfNumbers,pairOfNumbers,pairOfNumbers)),pointLabels:optional(trio(string,string,string)),showPointLabels:optional(boolean)});const parsePerseusGraphTypeRay=object({type:constant("ray"),coords:optional(nullable(pair(pairOfNumbers,pairOfNumbers))),startCoords:optional(pair(pairOfNumbers,pairOfNumbers)),pointLabels:optional(pair(string,string)),showPointLabels:optional(boolean)});const parsePerseusGraphTypeSegment=object({type:constant("segment"),numSegments:optional(number),coords:optional(nullable(array(pair(pairOfNumbers,pairOfNumbers)))),startCoords:optional(array(pair(pairOfNumbers,pairOfNumbers))),pointLabels:optional(array(string)),showPointLabels:optional(boolean)});const parsePerseusGraphTypeSinusoid=object({type:constant("sinusoid"),coords:optional(nullable(pair(pairOfNumbers,pairOfNumbers))),startCoords:optional(pair(pairOfNumbers,pairOfNumbers)),pointLabels:optional(array(string)),showPointLabels:optional(boolean)});const parsePerseusGraphTypeExponential=object({type:constant("exponential"),coords:optional(nullable(pair(pairOfNumbers,pairOfNumbers))),asymptote:optional(nullable(number)),startCoords:optional(object({coords:pair(pairOfNumbers,pairOfNumbers),asymptote:number})),pointLabels:optional(array(string)),showPointLabels:optional(boolean)});const parsePerseusGraphTypeAbsoluteValue=object({type:constant("absolute-value"),coords:optional(nullable(pair(pairOfNumbers,pairOfNumbers))),startCoords:optional(pair(pairOfNumbers,pairOfNumbers)),pointLabels:optional(pair(string,string)),showPointLabels:optional(boolean)});const parsePerseusGraphTypeTangent=object({type:constant("tangent"),coords:optional(nullable(pair(pairOfNumbers,pairOfNumbers))),startCoords:optional(pair(pairOfNumbers,pairOfNumbers)),pointLabels:optional(array(string)),showPointLabels:optional(boolean)});const parsePerseusGraphTypeLogarithm=object({type:constant("logarithm"),coords:optional(nullable(pair(pairOfNumbers,pairOfNumbers))),asymptote:optional(nullable(number)),startCoords:optional(object({coords:pair(pairOfNumbers,pairOfNumbers),asymptote:number})),pointLabels:optional(array(string)),showPointLabels:optional(boolean)});const parsePerseusGraphTypeVector=object({type:constant("vector"),coords:optional(nullable(pair(pairOfNumbers,pairOfNumbers))),startCoords:optional(pair(pairOfNumbers,pairOfNumbers)),match:optional(enumeration("exact","congruent"))});const parsePerseusGraphType=discriminatedUnionOn("type").withBranch("absolute-value",parsePerseusGraphTypeAbsoluteValue).withBranch("angle",parsePerseusGraphTypeAngle).withBranch("circle",parsePerseusGraphTypeCircle).withBranch("exponential",parsePerseusGraphTypeExponential).withBranch("linear",parsePerseusGraphTypeLinear).withBranch("linear-system",parsePerseusGraphTypeLinearSystem).withBranch("none",parsePerseusGraphTypeNone).withBranch("point",parsePerseusGraphTypePoint).withBranch("polygon",parsePerseusGraphTypePolygon).withBranch("quadratic",parsePerseusGraphTypeQuadratic).withBranch("ray",parsePerseusGraphTypeRay).withBranch("segment",parsePerseusGraphTypeSegment).withBranch("sinusoid",parsePerseusGraphTypeSinusoid).withBranch("tangent",parsePerseusGraphTypeTangent).withBranch("logarithm",parsePerseusGraphTypeLogarithm).withBranch("vector",parsePerseusGraphTypeVector).parser;const parseLockedFigureColor=pipeParsers(enumeration("blue","gold","green","grayH","purple","pink","red","orange")).then(convert(color=>color==="orange"?"gold":color)).parser;const parseLockedFigureFillType=enumeration("none","white","translucent","solid");const parseLockedLineStyle=enumeration("solid","dashed");const parseStrokeWeight=defaulted(enumeration("medium","thin","thick"),()=>"medium");const parseLockedLabelType=object({type:constant("label"),coord:pairOfNumbers,text:defaulted(string,()=>""),color:defaulted(parseLockedFigureColor,()=>"grayH"),size:defaulted(enumeration("small","medium","large"),()=>"medium")});const parseLockedPointType=object({type:constant("point"),coord:pairOfNumbers,color:parseLockedFigureColor,filled:boolean,labels:defaulted(array(parseLockedLabelType),()=>[]),ariaLabel:optional(string)});const parseLockedLineType=object({type:constant("line"),kind:enumeration("line","ray","segment"),points:pair(parseLockedPointType,parseLockedPointType),color:parseLockedFigureColor,lineStyle:parseLockedLineStyle,showPoint1:defaulted(boolean,()=>false),showPoint2:defaulted(boolean,()=>false),weight:parseStrokeWeight,labels:defaulted(array(parseLockedLabelType),()=>[]),ariaLabel:optional(string)});const parseLockedVectorType=object({type:constant("vector"),points:pair(pairOfNumbers,pairOfNumbers),color:parseLockedFigureColor,weight:parseStrokeWeight,labels:defaulted(array(parseLockedLabelType),()=>[]),ariaLabel:optional(string)});const parseLockedEllipseType=object({type:constant("ellipse"),center:pairOfNumbers,radius:pairOfNumbers,angle:number,color:parseLockedFigureColor,fillStyle:parseLockedFigureFillType,strokeStyle:parseLockedLineStyle,weight:parseStrokeWeight,labels:defaulted(array(parseLockedLabelType),()=>[]),ariaLabel:optional(string)});const parseLockedPolygonType=object({type:constant("polygon"),points:array(pairOfNumbers),color:parseLockedFigureColor,showVertices:boolean,fillStyle:parseLockedFigureFillType,strokeStyle:parseLockedLineStyle,weight:parseStrokeWeight,labels:defaulted(array(parseLockedLabelType),()=>[]),ariaLabel:optional(string)});const numberOrNegativeInfinity=union(number).or(constant(-Infinity)).parser;const numberOrPositiveInfinity=union(number).or(constant(Infinity)).parser;const parseLockedFunctionDomain=defaulted(pair(defaulted(numberOrNegativeInfinity,()=>-Infinity),defaulted(numberOrPositiveInfinity,()=>Infinity)),()=>[-Infinity,Infinity]);const parseLockedFunctionType=object({type:constant("function"),color:parseLockedFigureColor,strokeStyle:parseLockedLineStyle,weight:parseStrokeWeight,equation:string,directionalAxis:enumeration("x","y"),domain:parseLockedFunctionDomain,labels:defaulted(array(parseLockedLabelType),()=>[]),ariaLabel:optional(string)});const parseLockedFigure=discriminatedUnionOn("type").withBranch("point",parseLockedPointType).withBranch("line",parseLockedLineType).withBranch("vector",parseLockedVectorType).withBranch("ellipse",parseLockedEllipseType).withBranch("polygon",parseLockedPolygonType).withBranch("function",parseLockedFunctionType).withBranch("label",parseLockedLabelType).parser;const parseLabelLocation=union(enumeration("onAxis","alongEdge")).or(pipeParsers(constant("")).then(convert(()=>"onAxis")).parser).parser;const parseInteractiveGraphWidget=parseWidget(constant("interactive-graph"),object({step:pairOfNumbers,gridStep:optional(pairOfNumbers),snapStep:optional(pairOfNumbers),backgroundImage:optional(parsePerseusImageBackground),markings:enumeration("graph","grid","none","axes"),labels:optional(array(string)),labelLocation:optional(parseLabelLocation),showProtractor:boolean,showRuler:optional(boolean),showTooltips:optional(boolean),rulerLabel:optional(string),rulerTicks:optional(number),range:pair(pairOfNumbers,pairOfNumbers),showAxisArrows:defaulted(object({xMin:boolean,xMax:boolean,yMin:boolean,yMax:boolean}),()=>({xMin:true,xMax:true,yMin:true,yMax:true})),showAxisTicks:defaulted(object({x:boolean,y:boolean}),()=>({x:true,y:true})),graph:defaulted(parsePerseusGraphType,()=>({type:"linear"})),correct:defaulted(parsePerseusGraphType,()=>({type:"linear"})),lockedFigures:defaulted(array(parseLockedFigure),()=>[]),fullGraphAriaLabel:optional(string),fullGraphAriaDescription:optional(string)}));
167
+ const pairOfNumbers=pair(number,number);const parsePerseusGraphTypeAngle=object({type:constant("angle"),showAngles:optional(boolean),allowReflexAngles:optional(boolean),angleOffsetDeg:optional(nullable(number)),snapDegrees:optional(number),match:optional(constant("congruent")),coords:optional(trio(pairOfNumbers,pairOfNumbers,pairOfNumbers)),startCoords:optional(trio(pairOfNumbers,pairOfNumbers,pairOfNumbers)),pointLabels:optional(trio(string,string,string)),showPointLabels:optional(boolean)});const parsePerseusGraphTypeCircle=object({type:constant("circle"),center:optional(pairOfNumbers),radius:optional(number),startCoords:optional(object({center:pairOfNumbers,radius:number})),pointLabels:optional(array(string)),showPointLabels:optional(boolean)});const parsePerseusGraphTypeLinear=object({type:constant("linear"),coords:optional(nullable(pair(pairOfNumbers,pairOfNumbers))),startCoords:optional(pair(pairOfNumbers,pairOfNumbers)),pointLabels:optional(pair(string,string)),showPointLabels:optional(boolean)});const parsePerseusGraphTypeLinearSystem=object({type:constant("linear-system"),coords:optional(nullable(array(pair(pairOfNumbers,pairOfNumbers)))),startCoords:optional(array(pair(pairOfNumbers,pairOfNumbers))),pointLabels:optional(array(string)),showPointLabels:optional(boolean)});const parsePerseusGraphTypeNone=object({type:constant("none")});const parsePerseusGraphTypePoint=object({type:constant("point"),numPoints:optional(union(number).or(constant("unlimited")).parser),coords:optional(nullable(array(pairOfNumbers))),startCoords:optional(array(pairOfNumbers)),coord:optional(pairOfNumbers),pointLabels:optional(array(string)),showPointLabels:optional(boolean)});const parsePerseusGraphTypePolygon=object({type:constant("polygon"),numSides:optional(union(number).or(constant("unlimited")).parser),showAngles:optional(boolean),showSides:optional(boolean),snapTo:optional(enumeration("grid","angles","sides")),match:optional(enumeration("similar","congruent","approx","exact")),startCoords:optional(array(pairOfNumbers)),coords:optional(nullable(array(pairOfNumbers))),pointLabels:optional(array(string)),showPointLabels:optional(boolean)});const parsePerseusGraphTypeQuadratic=object({type:constant("quadratic"),coords:optional(nullable(trio(pairOfNumbers,pairOfNumbers,pairOfNumbers))),startCoords:optional(trio(pairOfNumbers,pairOfNumbers,pairOfNumbers)),pointLabels:optional(trio(string,string,string)),showPointLabels:optional(boolean)});const parsePerseusGraphTypeRay=object({type:constant("ray"),coords:optional(nullable(pair(pairOfNumbers,pairOfNumbers))),startCoords:optional(pair(pairOfNumbers,pairOfNumbers)),pointLabels:optional(pair(string,string)),showPointLabels:optional(boolean)});const parsePerseusGraphTypeSegment=object({type:constant("segment"),numSegments:optional(number),coords:optional(nullable(array(pair(pairOfNumbers,pairOfNumbers)))),startCoords:optional(array(pair(pairOfNumbers,pairOfNumbers))),pointLabels:optional(array(string)),showPointLabels:optional(boolean)});const parsePerseusGraphTypeSinusoid=object({type:constant("sinusoid"),coords:optional(nullable(pair(pairOfNumbers,pairOfNumbers))),startCoords:optional(pair(pairOfNumbers,pairOfNumbers)),pointLabels:optional(array(string)),showPointLabels:optional(boolean)});const parsePerseusGraphTypeExponential=object({type:constant("exponential"),coords:optional(nullable(pair(pairOfNumbers,pairOfNumbers))),asymptote:optional(nullable(number)),startCoords:optional(object({coords:pair(pairOfNumbers,pairOfNumbers),asymptote:number})),pointLabels:optional(array(string)),showPointLabels:optional(boolean)});const parsePerseusGraphTypeAbsoluteValue=object({type:constant("absolute-value"),coords:optional(nullable(pair(pairOfNumbers,pairOfNumbers))),startCoords:optional(pair(pairOfNumbers,pairOfNumbers)),pointLabels:optional(pair(string,string)),showPointLabels:optional(boolean)});const parsePerseusGraphTypeTangent=object({type:constant("tangent"),coords:optional(nullable(pair(pairOfNumbers,pairOfNumbers))),startCoords:optional(pair(pairOfNumbers,pairOfNumbers)),pointLabels:optional(array(string)),showPointLabels:optional(boolean)});const parsePerseusGraphTypeLogarithm=object({type:constant("logarithm"),coords:optional(nullable(pair(pairOfNumbers,pairOfNumbers))),asymptote:optional(nullable(number)),startCoords:optional(object({coords:pair(pairOfNumbers,pairOfNumbers),asymptote:number})),pointLabels:optional(array(string)),showPointLabels:optional(boolean)});const parsePerseusGraphTypeVector=object({type:constant("vector"),coords:optional(nullable(pair(pairOfNumbers,pairOfNumbers))),startCoords:optional(pair(pairOfNumbers,pairOfNumbers)),match:optional(enumeration("exact","congruent"))});const parsePerseusGraphType=discriminatedUnionOn("type").withBranch("absolute-value",parsePerseusGraphTypeAbsoluteValue).withBranch("angle",parsePerseusGraphTypeAngle).withBranch("circle",parsePerseusGraphTypeCircle).withBranch("exponential",parsePerseusGraphTypeExponential).withBranch("linear",parsePerseusGraphTypeLinear).withBranch("linear-system",parsePerseusGraphTypeLinearSystem).withBranch("none",parsePerseusGraphTypeNone).withBranch("point",parsePerseusGraphTypePoint).withBranch("polygon",parsePerseusGraphTypePolygon).withBranch("quadratic",parsePerseusGraphTypeQuadratic).withBranch("ray",parsePerseusGraphTypeRay).withBranch("segment",parsePerseusGraphTypeSegment).withBranch("sinusoid",parsePerseusGraphTypeSinusoid).withBranch("tangent",parsePerseusGraphTypeTangent).withBranch("logarithm",parsePerseusGraphTypeLogarithm).withBranch("vector",parsePerseusGraphTypeVector).parser;const parseLockedFigureColor=pipeParsers(enumeration("blue","gold","green","grayH","purple","pink","red","orange")).then(convert(color=>color==="orange"?"gold":color)).parser;const parseLockedFigureFillType=enumeration("none","white","translucent","solid");const parseLockedLineStyle=enumeration("solid","dashed");const parseStrokeWeight=defaulted(enumeration("medium","thin","thick"),()=>"medium");const parseLockedLabelType=object({type:constant("label"),coord:pairOfNumbers,text:defaulted(string,()=>""),color:defaulted(parseLockedFigureColor,()=>"grayH"),size:defaulted(enumeration("small","medium","large"),()=>"medium")});const parseLockedPointType=object({type:constant("point"),coord:pairOfNumbers,color:parseLockedFigureColor,filled:boolean,labels:defaulted(array(parseLockedLabelType),()=>[]),ariaLabel:optional(string)});const parseLockedLineType=object({type:constant("line"),kind:enumeration("line","ray","segment"),points:pair(parseLockedPointType,parseLockedPointType),color:parseLockedFigureColor,lineStyle:parseLockedLineStyle,showPoint1:defaulted(boolean,()=>false),showPoint2:defaulted(boolean,()=>false),weight:parseStrokeWeight,labels:defaulted(array(parseLockedLabelType),()=>[]),ariaLabel:optional(string)});const parseLockedVectorType=object({type:constant("vector"),points:pair(pairOfNumbers,pairOfNumbers),color:parseLockedFigureColor,weight:parseStrokeWeight,labels:defaulted(array(parseLockedLabelType),()=>[]),ariaLabel:optional(string)});const parseLockedEllipseType=object({type:constant("ellipse"),center:pairOfNumbers,radius:pairOfNumbers,angle:number,color:parseLockedFigureColor,fillStyle:parseLockedFigureFillType,strokeStyle:parseLockedLineStyle,weight:parseStrokeWeight,labels:defaulted(array(parseLockedLabelType),()=>[]),ariaLabel:optional(string)});const parseLockedPolygonType=object({type:constant("polygon"),points:array(pairOfNumbers),color:parseLockedFigureColor,showVertices:boolean,fillStyle:parseLockedFigureFillType,strokeStyle:parseLockedLineStyle,weight:parseStrokeWeight,labels:defaulted(array(parseLockedLabelType),()=>[]),ariaLabel:optional(string)});const numberOrNegativeInfinity=union(number).or(constant(-Infinity)).parser;const numberOrPositiveInfinity=union(number).or(constant(Infinity)).parser;const parseLockedFunctionDomain=defaulted(pair(defaulted(numberOrNegativeInfinity,()=>-Infinity),defaulted(numberOrPositiveInfinity,()=>Infinity)),()=>[-Infinity,Infinity]);const parseLockedFunctionType=object({type:constant("function"),color:parseLockedFigureColor,strokeStyle:parseLockedLineStyle,weight:parseStrokeWeight,equation:string,directionalAxis:enumeration("x","y"),domain:parseLockedFunctionDomain,labels:defaulted(array(parseLockedLabelType),()=>[]),ariaLabel:optional(string)});const parseLockedFigure=discriminatedUnionOn("type").withBranch("point",parseLockedPointType).withBranch("line",parseLockedLineType).withBranch("vector",parseLockedVectorType).withBranch("ellipse",parseLockedEllipseType).withBranch("polygon",parseLockedPolygonType).withBranch("function",parseLockedFunctionType).withBranch("label",parseLockedLabelType).parser;const parseLabelLocation=pipeParsers(enumeration("onAxis","alongEdge","",null,undefined)).then(convert(value=>value||"onAxis")).parser;const parseInteractiveGraphWidget=parseWidget(constant("interactive-graph"),object({step:pairOfNumbers,gridStep:optional(pairOfNumbers),snapStep:optional(pairOfNumbers),backgroundImage:defaulted(parsePerseusImageBackground,()=>({url:null})),markings:enumeration("graph","grid","none","axes"),labels:defaulted(array(string),()=>["$x$","$y$"]),labelLocation:parseLabelLocation,showProtractor:boolean,showRuler:optional(boolean),showTooltips:defaulted(boolean,()=>false),rulerLabel:optional(string),rulerTicks:optional(number),range:pair(pairOfNumbers,pairOfNumbers),showAxisArrows:defaulted(object({xMin:boolean,xMax:boolean,yMin:boolean,yMax:boolean}),()=>({xMin:true,xMax:true,yMin:true,yMax:true})),showAxisTicks:defaulted(object({x:boolean,y:boolean}),()=>({x:true,y:true})),graph:defaulted(parsePerseusGraphType,()=>({type:"linear"})),correct:defaulted(parsePerseusGraphType,()=>({type:"linear"})),lockedFigures:defaulted(array(parseLockedFigure),()=>[]),fullGraphAriaLabel:optional(string),fullGraphAriaDescription:optional(string)}));
168
168
 
169
169
  const parseLabelImageWidget=parseWidget(constant("label-image"),object({choices:array(string),imageUrl:string,imageAlt:string,imageHeight:number,imageWidth:number,markers:array(object({answers:defaulted(array(string),()=>[]),label:string,x:number,y:number})),hideChoicesFromInstructions:boolean,multipleAnswers:boolean,static:defaulted(boolean,()=>false)}));
170
170
 
@@ -254,7 +254,7 @@ const parseUserInputMap=(rawValue,ctx)=>{if(!isPlainObject(rawValue)){return ctx
254
254
 
255
255
  function parseAndMigratePerseusItem(data){const object=typeof data==="string"?JSON.parse(data):data;const result=parse(object,parsePerseusItem);if(isFailure(result)){return failure({message:result.detail,invalidObject:object})}return result}function parseAndMigratePerseusArticle(data){const object=typeof data==="string"?JSON.parse(data):data;const result=parse(object,parsePerseusArticle);if(isFailure(result)){return failure({message:result.detail,invalidObject:object})}return result}function parseAndMigrateUserInputMap(data){const object=typeof data==="string"?JSON.parse(data):data;const result=parse(object,parseUserInputMap);if(isFailure(result)){return failure({message:result.detail,invalidObject:object})}return result}function parseAndMigratePerseusRenderer(data){const object=typeof data==="string"?JSON.parse(data):data;const result=parse(object,parsePerseusRenderer);if(isFailure(result)){return failure({message:result.detail,invalidObject:object})}return result}
256
256
 
257
- const libName="@khanacademy/perseus-core";const libVersion="34.0.0";perseusUtils.addLibraryVersionToPerseusDebug(libName,libVersion);
257
+ const libName="@khanacademy/perseus-core";const libVersion="34.0.2";perseusUtils.addLibraryVersionToPerseusDebug(libName,libVersion);
258
258
 
259
259
  const Errors=Object.freeze({Unknown:"Unknown",Internal:"Internal",InvalidInput:"InvalidInput",NotAllowed:"NotAllowed",TransientService:"TransientService",Service:"Service"});
260
260
 
@@ -395,7 +395,7 @@ function getGroupPublicWidgetOptions(options){return splitPerseusRenderer(option
395
395
 
396
396
  const defaultWidgetOptions={content:"",widgets:{},images:{}};const traverseChildWidgets=function(props,traverseRenderer){return {...props,...traverseRenderer(props)}};const groupWidgetLogic={name:"group",defaultWidgetOptions,accessible:false,traverseChildWidgets:traverseChildWidgets,getPublicWidgetOptions:getGroupPublicWidgetOptions};
397
397
 
398
- function convertGrapherOptionsToInteractiveGraph(grapherOptions){if(grapherOptions.availableTypes.length!==1){return null}const[type]=grapherOptions.availableTypes;if(type==="quadratic"){return null}const graph={type:grapherFunctionTypeToInteractiveGraphType(type)};return {step:grapherOptions.graph.step,gridStep:grapherOptions.graph.gridStep,snapStep:grapherOptions.graph.snapStep,backgroundImage:grapherOptions.graph.backgroundImage,markings:grapherOptions.graph.markings,labels:grapherOptions.graph.labels.map(wrapTexInDelimitersForMarkdown),labelLocation:"onAxis",showAxisArrows:{xMin:true,xMax:true,yMin:true,yMax:true},showAxisTicks:{x:true,y:true},showProtractor:grapherOptions.graph.showProtractor??false,showTooltips:grapherOptions.graph.showTooltips,range:grapherOptions.graph.range,graph,correct:grapherOptions.correct?grapherAnswerTypesToPerseusGraphType(grapherOptions.correct):graph,lockedFigures:[]}}function convertGrapherUserInputToInteractiveGraph(grapherUserInput){return grapherAnswerTypesToPerseusGraphType(grapherUserInput)}function convertInteractiveGraphUserInputToGrapher(interactiveGraphUserInput){switch(interactiveGraphUserInput.type){case "absolute-value":return {type:"absolute_value",coords:interactiveGraphUserInput.coords??null};case "exponential":{invariant__default.default(interactiveGraphUserInput.asymptote!=null,"exponential graph asymptote must not be nullish in user input");const asymptoteY=interactiveGraphUserInput.asymptote;return {type:"exponential",coords:interactiveGraphUserInput.coords??null,asymptote:[[0,asymptoteY],[1,asymptoteY]]}}case "linear":return {type:"linear",coords:interactiveGraphUserInput.coords??null};case "logarithm":{invariant__default.default(interactiveGraphUserInput.asymptote!=null,"logarithm graph asymptote must not be nullish in user input");const asymptoteX=interactiveGraphUserInput.asymptote;return {type:"logarithm",coords:interactiveGraphUserInput.coords??null,asymptote:[[asymptoteX,0],[asymptoteX,1]]}}case "sinusoid":return {type:"sinusoid",coords:interactiveGraphUserInput.coords??null};case "tangent":return {type:"tangent",coords:interactiveGraphUserInput.coords??null};case "angle":case "circle":case "linear-system":case "none":case "point":case "polygon":case "quadratic":case "ray":case "segment":case "vector":throw Error("Can't convert interactive-graph user input to grapher user input. Type: "+interactiveGraphUserInput.type);default:throw new wonderStuffCore.UnreachableCaseError(interactiveGraphUserInput)}}function grapherAnswerTypesToPerseusGraphType(grapherAnswerTypes){switch(grapherAnswerTypes.type){case "absolute_value":return {type:"absolute-value",coords:grapherAnswerTypes.coords};case "exponential":return {type:"exponential",coords:grapherAnswerTypes.coords,asymptote:grapherAnswerTypes.asymptote[0][1]};case "linear":return {type:"linear",coords:grapherAnswerTypes.coords};case "logarithm":return {type:"logarithm",coords:grapherAnswerTypes.coords,asymptote:grapherAnswerTypes.asymptote[0][0]};case "quadratic":throw Error("Can't convert GrapherAnswerTypes to interactive graph. Type: quadratic");case "sinusoid":return {type:"sinusoid",coords:grapherAnswerTypes.coords};case "tangent":return {type:"tangent",coords:grapherAnswerTypes.coords};default:throw new wonderStuffCore.UnreachableCaseError(grapherAnswerTypes)}}function grapherFunctionTypeToInteractiveGraphType(type){return type==="absolute_value"?"absolute-value":type}function wrapTexInDelimitersForMarkdown(tex){return `$${tex}$`}
398
+ function convertGrapherOptionsToInteractiveGraph(grapherOptions){if(grapherOptions.availableTypes.length!==1){return null}const[type]=grapherOptions.availableTypes;if(type==="quadratic"){return null}const graph={type:grapherFunctionTypeToInteractiveGraphType(type)};return {step:grapherOptions.graph.step,gridStep:grapherOptions.graph.gridStep,snapStep:grapherOptions.graph.snapStep,backgroundImage:grapherOptions.graph.backgroundImage,markings:grapherOptions.graph.markings,labels:grapherOptions.graph.labels.map(wrapTexInDelimitersForMarkdown),labelLocation:"onAxis",showAxisArrows:{xMin:true,xMax:true,yMin:true,yMax:true},showAxisTicks:{x:true,y:true},showProtractor:grapherOptions.graph.showProtractor??false,showTooltips:grapherOptions.graph.showTooltips??false,range:grapherOptions.graph.range,graph,correct:grapherOptions.correct?grapherAnswerTypesToPerseusGraphType(grapherOptions.correct):graph,lockedFigures:[]}}function convertGrapherUserInputToInteractiveGraph(grapherUserInput){return grapherAnswerTypesToPerseusGraphType(grapherUserInput)}function convertInteractiveGraphUserInputToGrapher(interactiveGraphUserInput){switch(interactiveGraphUserInput.type){case "absolute-value":return {type:"absolute_value",coords:interactiveGraphUserInput.coords??null};case "exponential":{invariant__default.default(interactiveGraphUserInput.asymptote!=null,"exponential graph asymptote must not be nullish in user input");const asymptoteY=interactiveGraphUserInput.asymptote;return {type:"exponential",coords:interactiveGraphUserInput.coords??null,asymptote:[[0,asymptoteY],[1,asymptoteY]]}}case "linear":return {type:"linear",coords:interactiveGraphUserInput.coords??null};case "logarithm":{invariant__default.default(interactiveGraphUserInput.asymptote!=null,"logarithm graph asymptote must not be nullish in user input");const asymptoteX=interactiveGraphUserInput.asymptote;return {type:"logarithm",coords:interactiveGraphUserInput.coords??null,asymptote:[[asymptoteX,0],[asymptoteX,1]]}}case "sinusoid":return {type:"sinusoid",coords:interactiveGraphUserInput.coords??null};case "tangent":return {type:"tangent",coords:interactiveGraphUserInput.coords??null};case "angle":case "circle":case "linear-system":case "none":case "point":case "polygon":case "quadratic":case "ray":case "segment":case "vector":throw Error("Can't convert interactive-graph user input to grapher user input. Type: "+interactiveGraphUserInput.type);default:throw new wonderStuffCore.UnreachableCaseError(interactiveGraphUserInput)}}function grapherAnswerTypesToPerseusGraphType(grapherAnswerTypes){switch(grapherAnswerTypes.type){case "absolute_value":return {type:"absolute-value",coords:grapherAnswerTypes.coords};case "exponential":return {type:"exponential",coords:grapherAnswerTypes.coords,asymptote:grapherAnswerTypes.asymptote[0][1]};case "linear":return {type:"linear",coords:grapherAnswerTypes.coords};case "logarithm":return {type:"logarithm",coords:grapherAnswerTypes.coords,asymptote:grapherAnswerTypes.asymptote[0][0]};case "quadratic":throw Error("Can't convert GrapherAnswerTypes to interactive graph. Type: quadratic");case "sinusoid":return {type:"sinusoid",coords:grapherAnswerTypes.coords};case "tangent":return {type:"tangent",coords:grapherAnswerTypes.coords};default:throw new wonderStuffCore.UnreachableCaseError(grapherAnswerTypes)}}function grapherFunctionTypeToInteractiveGraphType(type){return type==="absolute_value"?"absolute-value":type}function wrapTexInDelimitersForMarkdown(tex){return `$${tex}$`}
399
399
 
400
400
  function getDefaultAnswerArea(){return {...ItemExtras.reduce((acc,curr)=>({...acc,[curr]:false}),{}),calculatorVariant:undefined}}
401
401
 
@@ -433,6 +433,8 @@ function generateLabelImageOptions(options){return {...labelImageWidgetLogic.def
433
433
 
434
434
  function generateMatcherOptions(options){return {...matcherWidgetLogic.defaultWidgetOptions,...options}}function generateMatcherWidget(matcherWidgetProperties){return {type:"matcher",graded:true,version:{major:0,minor:0},static:false,alignment:"default",options:generateMatcherOptions(),...matcherWidgetProperties}}
435
435
 
436
+ function generateMeasurerOptions(options){return {...measurerWidgetLogic.defaultWidgetOptions,...options}}function generateMeasurerWidget(measurerWidgetProperties){return {type:"measurer",graded:true,version:{major:0,minor:0},static:false,alignment:"default",options:generateMeasurerOptions(),...measurerWidgetProperties}}
437
+
436
438
  function generateCategorizerOptions(options){return {...categorizerWidgetLogic.defaultWidgetOptions,...options}}function generateCategorizerWidget(categorizerWidgetProperties){return {type:"categorizer",graded:true,version:{major:0,minor:0},static:false,alignment:"default",...categorizerWidgetProperties,options:generateCategorizerOptions(categorizerWidgetProperties?.options)}}
437
439
 
438
440
  function generateInteractiveGraphWidget(interactiveGraphWidgetProperties){return {type:"interactive-graph",graded:true,version:{major:0,minor:0},static:false,alignment:"default",options:generateInteractiveGraphOptions(),...interactiveGraphWidgetProperties}}function generateInteractiveGraphOptions(options){return {...interactiveGraphWidgetLogic.defaultWidgetOptions,...options}}function generateIGAngleGraph(options){return {type:"angle",...options}}function generateIGCircleGraph(options){return {type:"circle",...options}}function generateIGLinearGraph(options){return {type:"linear",...options}}function generateIGLinearSystemGraph(options){return {type:"linear-system",...options}}function generateIGLogarithmGraph(options){return {type:"logarithm",...options}}function generateIGNoneGraph(){return {type:"none"}}function generateIGPointGraph(options){return {type:"point",...options}}function generateIGPolygonGraph(options){return {type:"polygon",...options}}function generateIGQuadraticGraph(options){return {type:"quadratic",...options}}function generateIGRayGraph(options){return {type:"ray",...options}}function generateIGSegmentGraph(options){return {type:"segment",...options}}function generateIGSinusoidGraph(options){return {type:"sinusoid",...options}}function generateIGTangentGraph(options){return {type:"tangent",...options}}function generateIGVectorGraph(options){return {type:"vector",...options}}function generateIGLockedPoint(options){return {...getDefaultFigureForType("point"),...options}}function generateIGLockedLine(options){return {...getDefaultFigureForType("line"),...options}}function generateIGLockedVector(options){return {...getDefaultFigureForType("vector"),...options}}function generateIGLockedEllipse(options){return {...getDefaultFigureForType("ellipse"),...options}}function generateIGLockedPolygon(options){return {...getDefaultFigureForType("polygon"),...options}}function generateIGLockedFunction(options){return {...getDefaultFigureForType("function"),...options}}function generateIGLockedLabel(options){return {...getDefaultFigureForType("label"),...options}}function generateIGExponentialGraph(options){return {type:"exponential",...options}}function generateIGAbsoluteValueGraph(options){return {type:"absolute-value",...options}}function generateInteractiveGraphQuestion(options){const{content="[[☃ interactive-graph 1]]",isStatic=false,graded=true,...widgetOptions}=options??{};if(widgetOptions.correct&&!widgetOptions.graph){const{coords,coord,center,radius,asymptote,match,...graphConfig}=widgetOptions.correct;widgetOptions.graph=graphConfig;}const optionsWithDefaults={gridStep:[1,1],snapStep:[.5,.5],...widgetOptions};return generateTestPerseusRenderer({content:content,widgets:{"interactive-graph 1":generateInteractiveGraphWidget({static:isStatic,graded,options:generateInteractiveGraphOptions(optionsWithDefaults)})}})}
@@ -441,6 +443,8 @@ function generateMatrixOptions(options){return {...matrixWidgetLogic.defaultWidg
441
443
 
442
444
  function generatePlotterOptions(options){return {...plotterWidgetLogic.defaultWidgetOptions,...options}}function generatePlotterWidget(plotterWidgetProperties){return {type:"plotter",graded:true,version:{major:0,minor:0},static:false,alignment:"default",options:generatePlotterOptions(),...plotterWidgetProperties}}
443
445
 
446
+ function generatePhetSimulationOptions(options){return {...phetSimulationWidgetLogic.defaultWidgetOptions,...options}}function generatePhetSimulationWidget(phetSimulationWidgetProperties){return {type:"phet-simulation",graded:false,version:{major:0,minor:0},static:false,alignment:"default",...phetSimulationWidgetProperties,options:generatePhetSimulationOptions(phetSimulationWidgetProperties?.options)}}
447
+
444
448
  function generateNumericInputOptions(options){return {...numericInputWidgetLogic.defaultWidgetOptions,static:false,...options}}function generateNumericInputAnswer(answerOptions){return {...numericInputWidgetLogic.defaultWidgetOptions.answers[0],...answerOptions}}function generateNumericInputWidget(numericInputWidgetProperties){return {type:"numeric-input",graded:true,version:{major:0,minor:0},static:false,alignment:"default",options:generateNumericInputOptions(),...numericInputWidgetProperties}}
445
449
 
446
450
  function generateRadioOptions(options){return {...radioWidgetLogic.defaultWidgetOptions,...options}}function generateRadioWidget(radioWidgetProperties){return {type:"radio",graded:true,version:{major:0,minor:0},static:false,alignment:"default",options:generateRadioOptions(),...radioWidgetProperties}}function generateRadioChoice(text,options){return {content:text,id:`radio-choice-${Math.random()}`,correct:false,...options}}function generateSimpleRadioQuestion(options){return generateTestPerseusRenderer({content:"[[☃ radio 1]]",widgets:{"radio 1":generateRadioWidget({options:generateRadioOptions(options)})}})}function generateSimpleRadioItem(options){return generateTestPerseusItem({question:generateSimpleRadioQuestion(options)})}
@@ -541,9 +545,13 @@ exports.generateMatcherOptions = generateMatcherOptions;
541
545
  exports.generateMatcherWidget = generateMatcherWidget;
542
546
  exports.generateMatrixOptions = generateMatrixOptions;
543
547
  exports.generateMatrixWidget = generateMatrixWidget;
548
+ exports.generateMeasurerOptions = generateMeasurerOptions;
549
+ exports.generateMeasurerWidget = generateMeasurerWidget;
544
550
  exports.generateNumericInputAnswer = generateNumericInputAnswer;
545
551
  exports.generateNumericInputOptions = generateNumericInputOptions;
546
552
  exports.generateNumericInputWidget = generateNumericInputWidget;
553
+ exports.generatePhetSimulationOptions = generatePhetSimulationOptions;
554
+ exports.generatePhetSimulationWidget = generatePhetSimulationWidget;
547
555
  exports.generatePlotterOptions = generatePlotterOptions;
548
556
  exports.generatePlotterWidget = generatePlotterWidget;
549
557
  exports.generateRadioChoice = generateRadioChoice;