@khanacademy/perseus-core 9.0.0 → 10.1.0
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/data-schema.d.ts +20 -22
- package/dist/es/index.js +66 -52
- package/dist/es/index.js.map +1 -1
- package/dist/index.d.ts +9 -1
- package/dist/index.js +70 -51
- package/dist/index.js.map +1 -1
- package/dist/parse-perseus-json/general-purpose-parsers/defaulted.d.ts +1 -1
- package/dist/parse-perseus-json/general-purpose-parsers/index.d.ts +1 -1
- package/dist/parse-perseus-json/general-purpose-parsers/is-plain-object.d.ts +8 -0
- package/dist/parse-perseus-json/general-purpose-parsers/test-helpers.d.ts +5 -0
- package/dist/parse-perseus-json/perseus-parsers/categorizer-widget.d.ts +13 -3
- package/dist/parse-perseus-json/perseus-parsers/categorizer-widget.typetest.d.ts +1 -0
- package/dist/parse-perseus-json/perseus-parsers/cs-program-widget.d.ts +12 -3
- package/dist/parse-perseus-json/perseus-parsers/cs-program-widget.typetest.d.ts +1 -0
- package/dist/parse-perseus-json/perseus-parsers/definition-widget.d.ts +5 -3
- package/dist/parse-perseus-json/perseus-parsers/definition-widget.typetest.d.ts +1 -0
- package/dist/parse-perseus-json/perseus-parsers/dropdown-widget.d.ts +10 -3
- package/dist/parse-perseus-json/perseus-parsers/dropdown-widget.typetest.d.ts +1 -0
- package/dist/parse-perseus-json/perseus-parsers/explanation-widget.d.ts +7 -3
- package/dist/parse-perseus-json/perseus-parsers/explanation-widget.typetest.d.ts +1 -0
- package/dist/parse-perseus-json/perseus-parsers/expression-widget.d.ts +16 -3
- package/dist/parse-perseus-json/perseus-parsers/expression-widget.typetest.d.ts +1 -0
- package/dist/parse-perseus-json/perseus-parsers/graded-group-set-widget.d.ts +15 -3
- package/dist/parse-perseus-json/perseus-parsers/graded-group-set-widget.typetest.d.ts +1 -0
- package/dist/parse-perseus-json/perseus-parsers/graded-group-widget.d.ts +14 -4
- package/dist/parse-perseus-json/perseus-parsers/graded-group-widget.typetest.d.ts +1 -0
- package/dist/parse-perseus-json/perseus-parsers/grapher-widget.d.ts +51 -3
- package/dist/parse-perseus-json/perseus-parsers/grapher-widget.typetest.d.ts +1 -0
- package/dist/parse-perseus-json/perseus-parsers/group-widget.d.ts +1 -3
- package/dist/parse-perseus-json/perseus-parsers/group-widget.typetest.d.ts +1 -0
- package/dist/parse-perseus-json/perseus-parsers/hint.d.ts +9 -3
- package/dist/parse-perseus-json/perseus-parsers/hint.typetest.d.ts +1 -0
- package/dist/parse-perseus-json/perseus-parsers/iframe-widget.d.ts +12 -3
- package/dist/parse-perseus-json/perseus-parsers/iframe-widget.typetest.d.ts +1 -0
- package/dist/parse-perseus-json/perseus-parsers/image-widget.d.ts +22 -3
- package/dist/parse-perseus-json/perseus-parsers/image-widget.typetest.d.ts +1 -0
- package/dist/parse-perseus-json/perseus-parsers/input-number-widget.d.ts +10 -2
- package/dist/parse-perseus-json/perseus-parsers/input-number-widget.typetest.d.ts +1 -0
- package/dist/parse-perseus-json/perseus-parsers/interaction-widget.d.ts +125 -3
- package/dist/parse-perseus-json/perseus-parsers/interaction-widget.typetest.d.ts +1 -0
- package/dist/parse-perseus-json/perseus-parsers/interactive-graph-user-input.d.ts +60 -1
- package/dist/parse-perseus-json/perseus-parsers/interactive-graph-widget.d.ts +326 -5
- package/dist/parse-perseus-json/perseus-parsers/interactive-graph-widget.typetest.d.ts +1 -0
- package/dist/parse-perseus-json/perseus-parsers/label-image-widget.d.ts +16 -3
- package/dist/parse-perseus-json/perseus-parsers/label-image-widget.typetest.d.ts +1 -0
- package/dist/parse-perseus-json/perseus-parsers/legacy-button-sets.d.ts +1 -3
- package/dist/parse-perseus-json/perseus-parsers/matcher-widget.d.ts +7 -3
- package/dist/parse-perseus-json/perseus-parsers/matcher-widget.typetest.d.ts +1 -0
- package/dist/parse-perseus-json/perseus-parsers/matrix-widget.d.ts +8 -3
- package/dist/parse-perseus-json/perseus-parsers/matrix-widget.typetest.d.ts +1 -0
- package/dist/parse-perseus-json/perseus-parsers/measurer-widget.d.ts +18 -3
- package/dist/parse-perseus-json/perseus-parsers/measurer-widget.typetest.d.ts +1 -0
- package/dist/parse-perseus-json/perseus-parsers/molecule-renderer-widget.d.ts +5 -3
- package/dist/parse-perseus-json/perseus-parsers/molecule-renderer-widget.typetest.d.ts +1 -0
- package/dist/parse-perseus-json/perseus-parsers/number-line-widget.d.ts +17 -3
- package/dist/parse-perseus-json/perseus-parsers/number-line-widget.typetest.d.ts +1 -0
- package/dist/parse-perseus-json/perseus-parsers/numeric-input-widget.d.ts +21 -4
- package/dist/parse-perseus-json/perseus-parsers/numeric-input-widget.typetest.d.ts +1 -0
- package/dist/parse-perseus-json/perseus-parsers/orderer-widget.d.ts +7 -3
- package/dist/parse-perseus-json/perseus-parsers/orderer-widget.typetest.d.ts +1 -0
- package/dist/parse-perseus-json/perseus-parsers/passage-ref-widget.d.ts +5 -3
- package/dist/parse-perseus-json/perseus-parsers/passage-ref-widget.typetest.d.ts +1 -0
- package/dist/parse-perseus-json/perseus-parsers/passage-widget.d.ts +7 -3
- package/dist/parse-perseus-json/perseus-parsers/passage-widget.typetest.d.ts +1 -0
- package/dist/parse-perseus-json/perseus-parsers/perseus-answer-area.d.ts +11 -2
- package/dist/parse-perseus-json/perseus-parsers/perseus-answer-area.typetest.d.ts +1 -0
- package/dist/parse-perseus-json/perseus-parsers/perseus-image-background.d.ts +9 -3
- package/dist/parse-perseus-json/perseus-parsers/perseus-image-background.typetest.d.ts +1 -0
- package/dist/parse-perseus-json/perseus-parsers/perseus-image-detail.d.ts +4 -0
- package/dist/parse-perseus-json/perseus-parsers/perseus-image-detail.typetest.d.ts +1 -0
- package/dist/parse-perseus-json/perseus-parsers/phet-simulation-widget.d.ts +4 -3
- package/dist/parse-perseus-json/perseus-parsers/phet-simulation-widget.typetest.d.ts +1 -0
- package/dist/parse-perseus-json/perseus-parsers/plotter-widget.d.ts +15 -3
- package/dist/parse-perseus-json/perseus-parsers/plotter-widget.typetest.d.ts +1 -0
- package/dist/parse-perseus-json/perseus-parsers/python-program-widget.d.ts +4 -3
- package/dist/parse-perseus-json/perseus-parsers/python-program-widget.typetest.d.ts +1 -0
- package/dist/parse-perseus-json/perseus-parsers/sorter-widget.d.ts +5 -3
- package/dist/parse-perseus-json/perseus-parsers/sorter-widget.typetest.d.ts +1 -0
- package/dist/parse-perseus-json/perseus-parsers/table-widget.d.ts +6 -3
- package/dist/parse-perseus-json/perseus-parsers/table-widget.typetest.d.ts +1 -0
- package/dist/parse-perseus-json/perseus-parsers/video-widget.d.ts +4 -3
- package/dist/parse-perseus-json/perseus-parsers/video-widget.typetest.d.ts +1 -0
- package/dist/types.d.ts +1 -1
- package/dist/utils/deep-clone.d.ts +1 -2
- package/dist/utils/item-has-hints.d.ts +5 -0
- package/dist/utils/item-has-rationales.d.ts +5 -0
- package/dist/utils/split-perseus-item.d.ts +3 -3
- package/dist/utils/split-perseus-renderer.d.ts +7 -0
- package/dist/utils/test-utils.d.ts +2 -1
- package/dist/widgets/core-widget-registry.d.ts +8 -0
- package/dist/widgets/grapher/grapher-util.d.ts +1 -2
- package/dist/widgets/group/group-util.d.ts +12 -0
- package/dist/widgets/input-number/input-number-util.d.ts +12 -0
- package/dist/widgets/logic-export.types.d.ts +3 -1
- package/dist/widgets/matrix/matrix-util.d.ts +1 -2
- package/dist/widgets/number-line/number-line-util.d.ts +1 -2
- package/dist/widgets/orderer/orderer-util.d.ts +2 -6
- package/dist/widgets/plotter/plotter-util.d.ts +1 -1
- package/package.json +4 -3
- package/dist/parse-perseus-json/general-purpose-parsers/is-object.d.ts +0 -1
package/dist/es/index.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import _ from 'underscore';
|
|
2
|
+
import 'tiny-invariant';
|
|
2
3
|
import * as KAS from '@khanacademy/kas';
|
|
3
4
|
import { addLibraryVersionToPerseusDebug } from '@khanacademy/perseus-utils';
|
|
4
5
|
|
|
5
|
-
function getMatrixSize(matrix){const matrixSize=[1,1];
|
|
6
|
+
function getMatrixSize(matrix){const matrixSize=[1,1];matrix.forEach((matrixRow,row)=>{let rowWidth=0;matrixRow.forEach((matrixCol,col)=>{if(matrixCol!=null&&matrixCol.toString().length){rowWidth=col+1;}});matrixSize[1]=Math.max(matrixSize[1],rowWidth);if(rowWidth>0){matrixSize[0]=Math.max(matrixSize[0],row+1);}});return matrixSize}
|
|
6
7
|
|
|
7
8
|
const getDecimalSeparator=locale=>{switch(locale){case "ka":return ",";default:const numberWithDecimalSeparator=1.1;const match=new Intl.NumberFormat(locale).format(numberWithDecimalSeparator).match(/[^\d\u0661\u06F1\u0967\u09e7]/);return match?.[0]??"."}};
|
|
8
9
|
|
|
@@ -10,7 +11,7 @@ function approximateEqual(x,y){if(typeof x==="number"&&typeof y==="number"){retu
|
|
|
10
11
|
|
|
11
12
|
function addWidget(id){return `[[☃ ${id}]]`}function getWidgetRegex(){return /\[\[☃ ([A-Za-z0-9- ]+)\]\]/g}function getWidgetIdsFromContent(content){const widgets=[];const localWidgetRegex=getWidgetRegex();let match=localWidgetRegex.exec(content);while(match!==null){widgets.push(match[1]);match=localWidgetRegex.exec(content);}return widgets}function getWidgetIdsFromContentByType(type,content,widgetMap){const rv=[];const widgetIdsInContent=getWidgetIdsFromContent(content);widgetIdsInContent.forEach(widgetId=>{const widget=widgetMap[widgetId];if(widget?.type===type){rv.push(widgetId);}});return rv}
|
|
12
13
|
|
|
13
|
-
function deepClone(obj){
|
|
14
|
+
function deepClone(obj){return JSON.parse(JSON.stringify(obj))}
|
|
14
15
|
|
|
15
16
|
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]}function canonicalTangentCoefficients(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=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:_.partial(this.getFunctionForCoeffs,coeffs)}}};const Linear=_.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=_.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=_.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=_.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)+" sin("+b.toFixed(3)+"x - "+c.toFixed(3)+") + "+d.toFixed(3)},areEqual:function(coeffs1,coeffs2){return approximateDeepEqual(canonicalTangentCoefficients(coeffs1),canonicalTangentCoefficients(coeffs2))}});const Exponential=_.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 _.all(coords,coord=>coord[1]!==y)},extraAsymptoteConstraint:function(newCoord,oldCoord,coords,asymptote,graph){const y=newCoord[1];const isValid=_.all(coords,coord=>coord[1]>y)||_.all(coords,coord=>coord[1]<y);if(isValid){return [oldCoord[0],y]}const oldY=oldCoord[1];const wasBelow=_.all(coords,coord=>coord[1]>oldY);if(wasBelow){const bottomMost=_.min(_.map(coords,coord=>coord[1]));return [oldCoord[0],bottomMost-graph.snapStep[1]]}const topMost=_.max(_.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=_.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 _.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=_.all(coords,coord=>coord[0]>x)||_.all(coords,coord=>coord[0]<x);if(isValid){return [x,oldCoord[1]]}const oldX=oldCoord[0];const wasLeft=_.all(coords,coord=>coord[0]>oldX);if(wasLeft){const leftMost=_.min(_.map(coords,coord=>coord[0]));return [leftMost-graph.snapStep[0],oldCoord[1]]}const rightMost=_.max(_.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(_.map(coords,flip),_.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=_.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=_.keys(functionTypeMapping);function functionForType(type){return functionTypeMapping[type]}
|
|
16
17
|
|
|
@@ -21,7 +22,11 @@ var grapherUtil = /*#__PURE__*/Object.freeze({
|
|
|
21
22
|
functionForType: functionForType
|
|
22
23
|
});
|
|
23
24
|
|
|
24
|
-
const
|
|
25
|
+
const blankPerseusRenderer={content:"",images:{},widgets:{}};function generateTestPerseusRenderer(customFields={}){return deepClone({...blankPerseusRenderer,...customFields})}const blankPerseusItemData={question:generateTestPerseusRenderer(),answerArea:{calculator:false,chi2Table:false,periodicTable:false,tTable:false,zTable:false,financialCalculatorMonthlyPayment:false,financialCalculatorTotalAmount:false,financialCalculatorTimeToPayOff:false,periodicTableWithKey:false},hints:[]};function generateTestPerseusItem(customFields={}){return deepClone({...blankPerseusItemData,...customFields})}
|
|
26
|
+
|
|
27
|
+
const itemHasRationales=item=>widgetsHaveRationales(item.question.widgets);const widgetsHaveRationales=widgets=>Object.values(widgets).some(widgetHasRationales);const widgetHasRationales=widget=>{switch(widget.type){case "radio":return radioWidgetHasRationales(widget);case "label-image":return labelImageWidgetHasRationales(widget);case "graded-group":case "group":return widgetsHaveRationales(widget.options.widgets);default:return false}};const radioWidgetHasRationales=widget=>{return widget.options.choices.some(choice=>!!choice.clue)};const labelImageWidgetHasRationales=widget=>{return widget.options.markers.some(marker=>marker.answers.length>0)};
|
|
28
|
+
|
|
29
|
+
const itemHasHints=item=>{return item.hints.length>0};
|
|
25
30
|
|
|
26
31
|
function isRealJSONParse(jsonParse){const randomPhrase=buildRandomPhrase();const randomHintPhrase=buildRandomPhrase();const randomString=buildRandomString();const testingObject=JSON.stringify({answerArea:{calculator:false,chi2Table:false,financialCalculatorMonthlyPayment:false,financialCalculatorTimeToPayOff:false,financialCalculatorTotalAmount:false,periodicTable:false,periodicTableWithKey:false,tTable:false,zTable:false},hints:[randomHintPhrase,`=${Math.floor(Math.random()*50)+1}`],question:{content:`${randomPhrase}`,images:{},widgets:{expression1:{alignment:"default",graded:false,options:{answerForms:[{considered:"wrong",form:false,key:0,simplify:false,value:`${randomString}`}],ariaLabel:"Answer",buttonSets:["basic"],functions:["f","g","h"],static:true,times:false,visibleLabel:"Answer"},static:true,type:"expression",version:{major:1,minor:0}}}}});const testJSON=buildTestData(testingObject.replace(/"/g,'\\"'));const parsedTestJSON=jsonParse(testJSON);const parsedTestItemData=parsedTestJSON.data.assessmentItem.item.itemData;return approximateDeepEqual(parsedTestItemData,testingObject)}function buildRandomString(capitalize=false){let randomString="";const randomLength=Math.floor(Math.random()*8)+3;for(let i=0;i<randomLength;i++){const randomLetter=String.fromCharCode(97+Math.floor(Math.random()*26));randomString+=capitalize&&i===0?randomLetter.toUpperCase():randomLetter;}return randomString}function buildRandomPhrase(){const phrases=[];const randomLength=Math.floor(Math.random()*10)+5;for(let i=0;i<randomLength;i++){phrases.push(buildRandomString(i===0));}const modifierStart=["**","$"];const modifierEnd=["**","$"];const modifierIndex=Math.floor(Math.random()*modifierStart.length);return `${modifierStart[modifierIndex]}${phrases.join(" ")}${modifierEnd[modifierIndex]}`}function buildTestData(testObject){return `{"data":{"assessmentItem":{"__typename":"AssessmentItemOrError","error":null,"item":{"__typename":"AssessmentItem","id":"x890b3c70f3e8f4a6","itemData":"${testObject}","problemType":"Type 1","sha":"c7284a3ad65214b4e62bccce236d92f7f5d35941"}}}}`}
|
|
27
32
|
|
|
@@ -45,13 +50,13 @@ function constant(acceptedValue){return (rawValue,ctx)=>{if(rawValue!==acceptedV
|
|
|
45
50
|
|
|
46
51
|
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)}}
|
|
47
52
|
|
|
48
|
-
function
|
|
53
|
+
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}
|
|
49
54
|
|
|
50
55
|
function nullable(parseValue){return (rawValue,ctx)=>{if(rawValue===null){return ctx.success(rawValue)}return parseValue(rawValue,ctx)}}
|
|
51
56
|
|
|
52
57
|
const number=(rawValue,ctx)=>{if(typeof rawValue==="number"){return ctx.success(rawValue)}return ctx.failure("number",rawValue)};
|
|
53
58
|
|
|
54
|
-
function objectWithAllPropertiesRequired(schema){return object(schema)}function object(schema){return (rawValue,ctx)=>{if(!
|
|
59
|
+
function objectWithAllPropertiesRequired(schema){return object(schema)}function object(schema){return (rawValue,ctx)=>{if(!isPlainObject(rawValue)){return ctx.failure("object",rawValue)}const ret={...rawValue};const mismatches=[];for(const[prop,propParser]of Object.entries(schema)){const result=propParser(rawValue[prop],ctx.forSubtree(prop));if(isSuccess(result)){if(result.value!==undefined||prop in rawValue){ret[prop]=result.value;}}else {mismatches.push(...result.detail);}}if(mismatches.length>0){return failure(mismatches)}return ctx.success(ret)}}
|
|
55
60
|
|
|
56
61
|
function optional(parseValue){return (rawValue,ctx)=>{if(rawValue===undefined){return ctx.success(rawValue)}return parseValue(rawValue,ctx)}}
|
|
57
62
|
|
|
@@ -59,7 +64,7 @@ function pair(parseA,parseB){return (rawValue,ctx)=>{if(!Array.isArray(rawValue)
|
|
|
59
64
|
|
|
60
65
|
function pipeParsers(p){return new ParserPipeline(p)}class ParserPipeline{then(nextParser){return new ParserPipeline(composeParsers(this.parser,nextParser))}constructor(parser){this.parser=parser;}}function composeParsers(parserA,parserB){return (rawValue,ctx)=>{const partialResult=parserA(rawValue,ctx);if(isFailure(partialResult)){return partialResult}return parserB(partialResult.value,ctx)}}
|
|
61
66
|
|
|
62
|
-
function record(parseKey,parseValue){return (rawValue,ctx)=>{if(!
|
|
67
|
+
function record(parseKey,parseValue){return (rawValue,ctx)=>{if(!isPlainObject(rawValue)){return ctx.failure("object",rawValue)}const result={};const mismatches=[];for(const[key,value]of Object.entries(rawValue)){const entryCtx=ctx.forSubtree(key);const keyResult=parseKey(key,entryCtx);if(isFailure(keyResult)){mismatches.push(...keyResult.detail);}const valueResult=parseValue(value,entryCtx);if(isFailure(valueResult)){mismatches.push(...valueResult.detail);}if(isSuccess(keyResult)&&isSuccess(valueResult)){result[keyResult.value]=valueResult.value;}}if(mismatches.length>0){return failure(mismatches)}return ctx.success(result)}}
|
|
63
68
|
|
|
64
69
|
const string=(rawValue,ctx)=>{if(typeof rawValue==="string"){return ctx.success(rawValue)}return ctx.failure("string",rawValue)};
|
|
65
70
|
|
|
@@ -69,7 +74,9 @@ function union(parseBranch){return new UnionBuilder(parseBranch)}class UnionBuil
|
|
|
69
74
|
|
|
70
75
|
function defaulted(parser,fallback){return (rawValue,ctx)=>{if(rawValue==null){return success(fallback(rawValue))}return parser(rawValue,ctx)}}
|
|
71
76
|
|
|
72
|
-
const
|
|
77
|
+
const parsePerseusImageDetail=object({width:number,height:number});
|
|
78
|
+
|
|
79
|
+
const parseImages=defaulted(record(string,parsePerseusImageDetail),()=>({}));
|
|
73
80
|
|
|
74
81
|
function parseWidget(parseType,parseOptions){return objectWithAllPropertiesRequired({type:parseType,static:optional(boolean),graded:optional(boolean),alignment:optional(string),options:parseOptions,key:optional(nullable(number)),version:optional(object({major:number,minor:number}))})}function parseWidgetWithVersion(parseVersion,parseType,parseOptions){return objectWithAllPropertiesRequired({type:parseType,static:optional(boolean),graded:optional(boolean),alignment:optional(string),options:parseOptions,key:optional(nullable(number)),version:parseVersion})}
|
|
75
82
|
|
|
@@ -91,17 +98,17 @@ function convert(f){return (rawValue,ctx)=>ctx.success(f(rawValue))}
|
|
|
91
98
|
|
|
92
99
|
const parseLegacyButtonSet=enumeration("basic","basic+div","trig","prealgebra","logarithms","basic relations","advanced relations","scientific");const parseLegacyButtonSets=defaulted(array(parseLegacyButtonSet),()=>["basic","trig","prealgebra","logarithms"]);
|
|
93
100
|
|
|
94
|
-
function versionedWidgetOptions(latestMajorVersion,parseLatest){return new VersionedWidgetOptionsParserBuilder(latestMajorVersion,parseLatest,latest=>latest,(raw,ctx)=>ctx.failure("widget options with a known version number",raw))}class VersionedWidgetOptionsParserBuilder{withMigrationFrom(majorVersion,parseOldVersion,migrateToNextVersion){const parseOtherVersions=this.parser;const migrateToLatest=old=>this.migrateToLatest(migrateToNextVersion(old));return new VersionedWidgetOptionsParserBuilder(majorVersion,parseOldVersion,migrateToLatest,parseOtherVersions)}constructor(majorVersion,parseThisVersion,migrateToLatest,parseOtherVersions){this.migrateToLatest=migrateToLatest;this.parseOtherVersions=parseOtherVersions;const parseThisVersionAndMigrateToLatest=pipeParsers(parseThisVersion).then(convert(this.migrateToLatest)).parser;this.parser=(raw,ctx)=>{if(!
|
|
101
|
+
function versionedWidgetOptions(latestMajorVersion,parseLatest){return new VersionedWidgetOptionsParserBuilder(latestMajorVersion,parseLatest,latest=>latest,(raw,ctx)=>ctx.failure("widget options with a known version number",raw))}class VersionedWidgetOptionsParserBuilder{withMigrationFrom(majorVersion,parseOldVersion,migrateToNextVersion){const parseOtherVersions=this.parser;const migrateToLatest=old=>this.migrateToLatest(migrateToNextVersion(old));return new VersionedWidgetOptionsParserBuilder(majorVersion,parseOldVersion,migrateToLatest,parseOtherVersions)}constructor(majorVersion,parseThisVersion,migrateToLatest,parseOtherVersions){this.migrateToLatest=migrateToLatest;this.parseOtherVersions=parseOtherVersions;const parseThisVersionAndMigrateToLatest=pipeParsers(parseThisVersion).then(convert(this.migrateToLatest)).parser;this.parser=(raw,ctx)=>{if(!isPlainObject(raw)){return ctx.failure("object",raw)}const versionParseResult=parseVersionedObject(raw,ctx);if(isFailure(versionParseResult)){return versionParseResult}if(versionParseResult.value.version.major!==majorVersion){return this.parseOtherVersions(raw,ctx)}return parseThisVersionAndMigrateToLatest(raw,ctx)};}}const parseVersionedObject=object({version:defaulted(object({major:number,minor:number}),()=>({major:0,minor:0}))});
|
|
95
102
|
|
|
96
|
-
const stringOrNumberOrNullOrUndefined=union(string).or(number).or(constant(null)).or(constant(undefined)).parser;const parsePossiblyInvalidAnswerForm=object({value:optional(string),form:defaulted(boolean,()=>false),simplify:defaulted(boolean,()=>false),considered:enumeration("correct","wrong","ungraded"),key:pipeParsers(stringOrNumberOrNullOrUndefined).then(convert(
|
|
103
|
+
const stringOrNumberOrNullOrUndefined=union(string).or(number).or(constant(null)).or(constant(undefined)).parser;function numberOrNullToString(v){return typeof v==="number"||v===null?String(v):v}const parsePossiblyInvalidAnswerForm=object({value:optional(string),form:defaulted(boolean,()=>false),simplify:defaulted(boolean,()=>false),considered:enumeration("correct","wrong","ungraded"),key:pipeParsers(stringOrNumberOrNullOrUndefined).then(convert(numberOrNullToString)).parser});function removeInvalidAnswerForms(possiblyInvalid){return possiblyInvalid.flatMap(answerForm=>{const{value}=answerForm;if(value!=null){return [{...answerForm,value}]}return []})}const version2$1=object({major:constant(2),minor:number});const parseExpressionWidgetV2=parseWidgetWithVersion(version2$1,constant("expression"),object({answerForms:pipeParsers(array(parsePossiblyInvalidAnswerForm)).then(convert(removeInvalidAnswerForms)).parser,functions:array(string),times:boolean,visibleLabel:optional(string),ariaLabel:optional(string),buttonSets:parseLegacyButtonSets,buttonsVisible:optional(enumeration("always","never","focused")),extraKeys:optional(array(enumeration(...KeypadKeys)))}));const version1$1=object({major:constant(1),minor:number});const parseExpressionWidgetV1=parseWidgetWithVersion(version1$1,constant("expression"),object({answerForms:pipeParsers(array(parsePossiblyInvalidAnswerForm)).then(convert(removeInvalidAnswerForms)).parser,functions:array(string),times:boolean,visibleLabel:optional(string),ariaLabel:optional(string),buttonSets:parseLegacyButtonSets,buttonsVisible:optional(enumeration("always","never","focused"))}));function migrateV1ToV2$1(widget){const{options}=widget;return {...widget,version:{major:2,minor:0},options:{times:options.times,buttonSets:options.buttonSets,functions:options.functions,buttonsVisible:options.buttonsVisible,visibleLabel:options.visibleLabel,ariaLabel:options.ariaLabel,answerForms:options.answerForms,extraKeys:deriveExtraKeys(options)??[]}}}const version0$1=optional(object({major:constant(0),minor:number}));const parseExpressionWidgetV0=parseWidgetWithVersion(version0$1,constant("expression"),object({functions:array(string),times:boolean,visibleLabel:optional(string),ariaLabel:optional(string),form:boolean,simplify:boolean,value:string,buttonSets:parseLegacyButtonSets,buttonsVisible:optional(enumeration("always","never","focused"))}));function migrateV0ToV1$1(widget){const{options}=widget;return {...widget,version:{major:1,minor:0},options:{times:options.times,buttonSets:options.buttonSets,functions:options.functions,buttonsVisible:options.buttonsVisible,visibleLabel:options.visibleLabel,ariaLabel:options.ariaLabel,answerForms:[{considered:"correct",form:options.form,simplify:options.simplify,value:options.value}]}}}const parseExpressionWidget=versionedWidgetOptions(2,parseExpressionWidgetV2).withMigrationFrom(1,parseExpressionWidgetV1,migrateV1ToV2$1).withMigrationFrom(0,parseExpressionWidgetV0,migrateV0ToV1$1).parser;
|
|
97
104
|
|
|
98
105
|
const falseToNull=pipeParsers(constant(false)).then(convert(()=>null)).parser;const parseGradedGroupWidgetOptions=object({title:defaulted(string,()=>""),hasHint:optional(nullable(boolean)),hint:union(falseToNull).or(constant(null)).or(constant(undefined)).or((rawVal,ctx)=>parsePerseusRenderer(rawVal,ctx)).parser,content:string,widgets:(rawVal,ctx)=>parseWidgetsMap(rawVal,ctx),widgetEnabled:optional(nullable(boolean)),immutableWidgets:optional(nullable(boolean)),images:record(string,object({width:number,height:number}))});const parseGradedGroupWidget=parseWidget(constant("graded-group"),parseGradedGroupWidgetOptions);
|
|
99
106
|
|
|
100
107
|
const parseGradedGroupSetWidget=parseWidget(constant("graded-group-set"),object({gradedGroups:array(parseGradedGroupWidgetOptions)}));
|
|
101
108
|
|
|
102
|
-
function discriminatedUnionOn(discriminantKey){const noMoreBranches=(raw,ctx)=>{if(!
|
|
109
|
+
function discriminatedUnionOn(discriminantKey){const noMoreBranches=(raw,ctx)=>{if(!isPlainObject(raw)){return ctx.failure("object",raw)}return ctx.forSubtree(discriminantKey).failure("a valid value",raw[discriminantKey])};return new DiscriminatedUnionBuilder(discriminantKey,noMoreBranches)}class DiscriminatedUnionBuilder{withBranch(discriminantValue,parseNewVariant){const parseNewBranch=discriminatedUnionBranch(this.discriminantKey,discriminantValue,parseNewVariant,this.parser);return new DiscriminatedUnionBuilder(this.discriminantKey,parseNewBranch)}constructor(discriminantKey,parser){this.discriminantKey=discriminantKey;this.parser=parser;}}function discriminatedUnionBranch(discriminantKey,discriminantValue,parseVariant,parseOtherBranches){return (raw,ctx)=>{if(!isPlainObject(raw)){return ctx.failure("object",raw)}if(raw[discriminantKey]===discriminantValue){return parseVariant(raw,ctx)}return parseOtherBranches(raw,ctx)}}
|
|
103
110
|
|
|
104
|
-
const pairOfNumbers$3=pair(number,number);const pairOfPoints=pair(pairOfNumbers$3,pairOfNumbers$3);const parseGrapherWidget=parseWidget(constant("grapher"),object({availableTypes:array(enumeration("absolute_value","exponential","linear","logarithm","quadratic","sinusoid","tangent")),correct:discriminatedUnionOn("type").withBranch("absolute_value",object({type:constant("absolute_value"),coords:nullable(pairOfPoints)})).withBranch("exponential",object({type:constant("exponential"),asymptote:pairOfPoints,coords:nullable(pairOfPoints)})).withBranch("linear",object({type:constant("linear"),coords:nullable(pairOfPoints)})).withBranch("logarithm",object({type:constant("logarithm"),asymptote:pairOfPoints,coords:nullable(pairOfPoints)})).withBranch("quadratic",object({type:constant("quadratic"),coords:nullable(pairOfPoints)})).withBranch("sinusoid",object({type:constant("sinusoid"),coords:nullable(pairOfPoints)})).withBranch("tangent",object({type:constant("tangent"),coords:nullable(pairOfPoints)})).parser,graph:object({backgroundImage:object({bottom:optional(number),height:optional(number),left:optional(number),scale:optional(number),url:optional(nullable(string)),width:optional(number)}),box:optional(pairOfNumbers$3),editableSettings:optional(array(enumeration("graph","snap","image","measure"))),gridStep:optional(pairOfNumbers$3),labels:pair(string,string),markings:enumeration("graph","none","grid"),range:pair(pairOfNumbers$3,pairOfNumbers$3),rulerLabel:constant(""),rulerTicks:number,showProtractor:optional(boolean),showRuler:optional(boolean),showTooltips:optional(boolean),snapStep:optional(pairOfNumbers$3),step:pairOfNumbers$3,valid:optional(union(boolean).or(string).parser)})}));
|
|
111
|
+
const pairOfNumbers$3=pair(number,number);const pairOfPoints=pair(pairOfNumbers$3,pairOfNumbers$3);const parseGrapherWidget=parseWidget(constant("grapher"),object({availableTypes:array(enumeration("absolute_value","exponential","linear","logarithm","quadratic","sinusoid","tangent")),correct:discriminatedUnionOn("type").withBranch("absolute_value",object({type:constant("absolute_value"),coords:nullable(pairOfPoints)})).withBranch("exponential",object({type:constant("exponential"),asymptote:pairOfPoints,coords:nullable(pairOfPoints)})).withBranch("linear",object({type:constant("linear"),coords:nullable(pairOfPoints)})).withBranch("logarithm",object({type:constant("logarithm"),asymptote:pairOfPoints,coords:nullable(pairOfPoints)})).withBranch("quadratic",object({type:constant("quadratic"),coords:nullable(pairOfPoints)})).withBranch("sinusoid",object({type:constant("sinusoid"),coords:nullable(pairOfPoints)})).withBranch("tangent",object({type:constant("tangent"),coords:nullable(pairOfPoints)})).parser,graph:object({backgroundImage:object({bottom:optional(number),height:optional(number),left:optional(number),scale:optional(number),url:optional(nullable(string)),width:optional(number)}),box:optional(pairOfNumbers$3),editableSettings:optional(array(enumeration("graph","snap","image","measure"))),gridStep:optional(pairOfNumbers$3),labels:pair(string,string),markings:enumeration("graph","none","grid","axes"),range:pair(pairOfNumbers$3,pairOfNumbers$3),rulerLabel:constant(""),rulerTicks:number,showProtractor:optional(boolean),showRuler:optional(boolean),showTooltips:optional(boolean),snapStep:optional(pairOfNumbers$3),step:pairOfNumbers$3,valid:optional(union(boolean).or(string).parser)})}));
|
|
105
112
|
|
|
106
113
|
const parseGroupWidget=parseWidget(constant("group"),(rawVal,ctx)=>parsePerseusRenderer(rawVal,ctx));
|
|
107
114
|
|
|
@@ -109,17 +116,17 @@ const parseIframeWidget=parseWidget(constant("iframe"),object({url:string,settin
|
|
|
109
116
|
|
|
110
117
|
const stringToNumber=(rawValue,ctx)=>{if(typeof rawValue==="number"){return ctx.success(rawValue)}const parsedNumber=+rawValue;if(rawValue===""||isNaN(parsedNumber)){return ctx.failure("a number or numeric string",rawValue)}return ctx.success(parsedNumber)};
|
|
111
118
|
|
|
112
|
-
function emptyToZero(x){return x===""?0:x}const imageDimensionToNumber=pipeParsers(union(number).or(string).parser).then(convert(emptyToZero)).then(stringToNumber).parser;const dimensionOrUndefined=defaulted(imageDimensionToNumber,()=>undefined);const parsePerseusImageBackground=object({url:optional(nullable(string)),width:dimensionOrUndefined,height:dimensionOrUndefined,top:dimensionOrUndefined,left:dimensionOrUndefined,bottom:dimensionOrUndefined,scale:dimensionOrUndefined});
|
|
119
|
+
function emptyToZero(x){return x===""?0:x}const imageDimensionToNumber=pipeParsers(union(number).or(string).parser).then(convert(emptyToZero)).then(stringToNumber).parser;const dimensionOrUndefined=defaulted(optional(imageDimensionToNumber),()=>undefined);const parsePerseusImageBackground=object({url:optional(nullable(string)),width:dimensionOrUndefined,height:dimensionOrUndefined,top:dimensionOrUndefined,left:dimensionOrUndefined,bottom:dimensionOrUndefined,scale:dimensionOrUndefined});
|
|
113
120
|
|
|
114
121
|
const pairOfNumbers$2=pair(number,number);const parseImageWidget=parseWidget(constant("image"),object({title:optional(string),caption:optional(string),alt:optional(string),backgroundImage:parsePerseusImageBackground,static:optional(boolean),labels:optional(array(object({content:string,alignment:string,coordinates:array(number)}))),range:optional(pair(pairOfNumbers$2,pairOfNumbers$2)),box:optional(pairOfNumbers$2)}));
|
|
115
122
|
|
|
116
123
|
const booleanToString=(rawValue,ctx)=>{if(typeof rawValue==="boolean"){return ctx.success(String(rawValue))}return ctx.failure("boolean",rawValue)};const parseInputNumberWidget=parseWidget(constant("input-number"),object({answerType:optional(enumeration("number","decimal","integer","rational","improper","mixed","percent","pi")),inexact:optional(boolean),maxError:optional(union(number).or(string).parser),rightAlign:optional(boolean),simplify:enumeration("required","optional","enforced"),size:enumeration("normal","small"),value:union(number).or(string).or(booleanToString).parser,customKeypad:optional(boolean)}));
|
|
117
124
|
|
|
118
|
-
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"),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)}));
|
|
125
|
+
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)}));
|
|
119
126
|
|
|
120
127
|
const ItemExtras=["calculator","chi2Table","financialCalculatorMonthlyPayment","financialCalculatorTotalAmount","financialCalculatorTimeToPayOff","periodicTable","periodicTableWithKey","tTable","zTable"];const PerseusExpressionAnswerFormConsidered=["correct","wrong","ungraded"];const lockedFigureColorNames=["blue","green","grayH","purple","pink","orange","red"];const lockedFigureColors={blue:"#3D7586",green:"#447A53",grayH:"#3B3D45",purple:"#594094",pink:"#B25071",red:"#D92916",orange:"#946700"};const lockedFigureFillStyles={none:0,white:1,translucent:.4,solid:1};const plotterPlotTypes=["bar","line","pic","histogram","dotplot"];
|
|
121
128
|
|
|
122
|
-
const pairOfNumbers=pair(number,number);const parsePerseusGraphTypeAngle=object({type:constant("angle"),showAngles:optional(boolean),allowReflexAngles:optional(boolean),angleOffsetDeg:optional(number),snapDegrees:optional(number),match:optional(constant("congruent")),coords:optional(trio(pairOfNumbers,pairOfNumbers,pairOfNumbers)),startCoords:optional(trio(pairOfNumbers,pairOfNumbers,pairOfNumbers))});const parsePerseusGraphTypeCircle=object({type:constant("circle"),center:optional(pairOfNumbers),radius:optional(number),startCoords:optional(object({center:pairOfNumbers,radius:number}))
|
|
129
|
+
const pairOfNumbers=pair(number,number);const parsePerseusGraphTypeAngle=object({type:constant("angle"),showAngles:optional(boolean),allowReflexAngles:optional(boolean),angleOffsetDeg:optional(number),snapDegrees:optional(number),match:optional(constant("congruent")),coords:optional(trio(pairOfNumbers,pairOfNumbers,pairOfNumbers)),startCoords:optional(trio(pairOfNumbers,pairOfNumbers,pairOfNumbers))});const parsePerseusGraphTypeCircle=object({type:constant("circle"),center:optional(pairOfNumbers),radius:optional(number),startCoords:optional(object({center:pairOfNumbers,radius:number}))});const parsePerseusGraphTypeLinear=object({type:constant("linear"),coords:optional(nullable(pair(pairOfNumbers,pairOfNumbers))),startCoords:optional(pair(pairOfNumbers,pairOfNumbers))});const parsePerseusGraphTypeLinearSystem=object({type:constant("linear-system"),coords:optional(nullable(array(pair(pairOfNumbers,pairOfNumbers)))),startCoords:optional(array(pair(pairOfNumbers,pairOfNumbers)))});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)});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)))});const parsePerseusGraphTypeQuadratic=object({type:constant("quadratic"),coords:optional(nullable(trio(pairOfNumbers,pairOfNumbers,pairOfNumbers))),startCoords:optional(trio(pairOfNumbers,pairOfNumbers,pairOfNumbers))});const parsePerseusGraphTypeRay=object({type:constant("ray"),coords:optional(nullable(pair(pairOfNumbers,pairOfNumbers))),startCoords:optional(pair(pairOfNumbers,pairOfNumbers))});const parsePerseusGraphTypeSegment=object({type:constant("segment"),numSegments:optional(number),coords:optional(nullable(array(pair(pairOfNumbers,pairOfNumbers)))),startCoords:optional(array(pair(pairOfNumbers,pairOfNumbers)))});const parsePerseusGraphTypeSinusoid=object({type:constant("sinusoid"),coords:optional(nullable(array(pairOfNumbers))),startCoords:optional(array(pairOfNumbers))});const parsePerseusGraphType=discriminatedUnionOn("type").withBranch("angle",parsePerseusGraphTypeAngle).withBranch("circle",parsePerseusGraphTypeCircle).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).parser;const parseLockedFigureColor=enumeration(...lockedFigureColorNames);const parseLockedFigureFillType=enumeration("none","white","translucent","solid");const parseLockedLineStyle=enumeration("solid","dashed");const parseLockedLabelType=object({type:constant("label"),coord:pairOfNumbers,text:string,color:parseLockedFigureColor,size:enumeration("small","medium","large")});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),labels:defaulted(array(parseLockedLabelType),()=>[]),ariaLabel:optional(string)});const parseLockedVectorType=object({type:constant("vector"),points:pair(pairOfNumbers,pairOfNumbers),color:parseLockedFigureColor,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,labels:defaulted(array(parseLockedLabelType),()=>[]),ariaLabel:optional(string)});const parseLockedPolygonType=object({type:constant("polygon"),points:array(pairOfNumbers),color:parseLockedFigureColor,showVertices:boolean,fillStyle:parseLockedFigureFillType,strokeStyle:parseLockedLineStyle,labels:defaulted(array(parseLockedLabelType),()=>[]),ariaLabel:optional(string)});const parseLockedFunctionDomain=defaulted(pair(defaulted(number,()=>-Infinity),defaulted(number,()=>Infinity)),()=>[-Infinity,Infinity]);const parseLockedFunctionType=object({type:constant("function"),color:parseLockedFigureColor,strokeStyle:parseLockedLineStyle,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 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(enumeration("onAxis","alongEdge")),showProtractor:boolean,showRuler:optional(boolean),showTooltips:optional(boolean),rulerLabel:optional(string),rulerTicks:optional(number),range:pair(pairOfNumbers,pairOfNumbers),graph:defaulted(parsePerseusGraphType,()=>({type:"linear"})),correct:parsePerseusGraphType,lockedFigures:defaulted(array(parseLockedFigure),()=>[]),fullGraphAriaLabel:optional(string),fullGraphAriaDescription:optional(string)}));
|
|
123
130
|
|
|
124
131
|
const parseLabelImageWidget=parseWidget(constant("label-image"),object({choices:array(string),imageUrl:string,imageAlt:string,imageHeight:number,imageWidth:number,markers:array(object({answers:array(string),label:string,x:number,y:number})),hideChoicesFromInstructions:boolean,multipleAnswers:boolean,static:defaulted(boolean,()=>false)}));
|
|
125
132
|
|
|
@@ -127,13 +134,13 @@ const parseMatcherWidget=parseWidget(constant("matcher"),object({labels:array(st
|
|
|
127
134
|
|
|
128
135
|
const numberOrString=union(number).or(string).parser;const numeric=pipeParsers(defaulted(numberOrString,()=>NaN)).then(stringToNumber).parser;const parseMatrixWidget=parseWidget(defaulted(constant("matrix"),()=>"matrix"),object({prefix:optional(string),suffix:optional(string),answers:array(array(numeric)),cursorPosition:optional(array(number)),matrixBoardSize:array(number),static:optional(boolean)}));
|
|
129
136
|
|
|
130
|
-
const parseMeasurerWidget=parseWidget(constant("measurer"),object({image:defaulted(parsePerseusImageBackground,()=>({url:null,top:0,left:0})),showProtractor:boolean,showRuler:boolean,rulerLabel:string,rulerTicks:number,rulerPixels:number,rulerLength:number,box:pair(number,number)
|
|
137
|
+
const parseMeasurerWidget=parseWidget(constant("measurer"),object({image:defaulted(parsePerseusImageBackground,()=>({url:null,top:0,left:0})),showProtractor:boolean,showRuler:boolean,rulerLabel:string,rulerTicks:number,rulerPixels:number,rulerLength:number,box:pair(number,number)}));
|
|
131
138
|
|
|
132
139
|
const parseMoleculeRendererWidget=parseWidget(constant("molecule-renderer"),object({widgetId:string,rotationAngle:optional(number),smiles:optional(string)}));
|
|
133
140
|
|
|
134
|
-
const emptyStringToNull=pipeParsers(constant("")).then(convert(()=>null)).parser;const parseNumberLineWidget=parseWidget(constant("number-line"),object({range:array(number),labelRange:array(nullable(union(number).or(emptyStringToNull).parser)),labelStyle:string,labelTicks:boolean,isTickCtrl:optional(nullable(boolean)),divisionRange:array(number),numDivisions:optional(nullable(number)),snapDivisions:defaulted(number,()=>2),tickStep:optional(nullable(number)),correctRel:optional(
|
|
141
|
+
const emptyStringToNull=pipeParsers(constant("")).then(convert(()=>null)).parser;const parseNumberLineWidget=parseWidget(constant("number-line"),object({range:array(number),labelRange:array(nullable(union(number).or(emptyStringToNull).parser)),labelStyle:string,labelTicks:boolean,isTickCtrl:optional(nullable(boolean)),isInequality:defaulted(boolean,()=>false),divisionRange:array(number),numDivisions:optional(nullable(number)),snapDivisions:defaulted(number,()=>2),tickStep:optional(nullable(number)),correctRel:defaulted(optional(enumeration("eq","lt","gt","le","ge")),()=>undefined),correctX:nullable(number),initialX:optional(nullable(number)),showTooltips:optional(boolean),static:defaulted(boolean,()=>false)}));
|
|
135
142
|
|
|
136
|
-
const parseMathFormat=enumeration("integer","mixed","improper","proper","decimal","percent","pi");const parseSimplify=pipeParsers(union(constant(null)).or(constant(undefined)).or(boolean).or(constant("required")).or(constant("correct")).or(constant("enforced")).or(constant("optional")).or(constant("accepted")).parser).then(convert(deprecatedSimplifyValuesToRequired)).parser;function deprecatedSimplifyValuesToRequired(simplify){switch(simplify){case "enforced":case "required":case "optional":return simplify;default:return "required"}}const parseNumericInputWidget=parseWidget(constant("numeric-input"),object({answers:array(object({message:string,value:optional(nullable(number)),status:string,answerForms:defaulted(array(parseMathFormat),()=>undefined),strict:boolean,maxError:optional(nullable(number)),simplify:parseSimplify})),labelText:optional(string),size:string,coefficient:defaulted(boolean,()=>false),rightAlign:optional(boolean),static:defaulted(boolean,()=>false),answerForms:optional(array(object({name:parseMathFormat,simplify:parseSimplify})))}));
|
|
143
|
+
const parseMathFormat=enumeration("integer","mixed","improper","proper","decimal","percent","pi");const parseSimplify=pipeParsers(union(constant(null)).or(constant(undefined)).or(boolean).or(constant("required")).or(constant("correct")).or(constant("enforced")).or(constant("optional")).or(constant("accepted")).parser).then(convert(deprecatedSimplifyValuesToRequired)).parser;function deprecatedSimplifyValuesToRequired(simplify){switch(simplify){case "enforced":case "required":case "optional":return simplify;default:return "required"}}const parseNumericInputWidget=parseWidget(constant("numeric-input"),object({answers:array(object({message:string,value:optional(nullable(number)),status:string,answerForms:defaulted(optional(array(parseMathFormat)),()=>undefined),strict:boolean,maxError:optional(nullable(number)),simplify:parseSimplify})),labelText:optional(string),size:string,coefficient:defaulted(boolean,()=>false),rightAlign:optional(boolean),static:defaulted(boolean,()=>false),answerForms:optional(array(object({name:parseMathFormat,simplify:parseSimplify})))}));
|
|
137
144
|
|
|
138
145
|
function parseRenderer(rawValue,ctx){return parsePerseusRenderer(rawValue,ctx)}const largeToAuto=(height,ctx)=>{if(height==="large"){return ctx.success("auto")}return ctx.success(height)};const parseOrdererWidget=parseWidget(constant("orderer"),object({options:defaulted(array(parseRenderer),()=>[]),correctOptions:array(parseRenderer),otherOptions:array(parseRenderer),height:pipeParsers(enumeration("normal","auto","large")).then(largeToAuto).parser,layout:defaulted(enumeration("horizontal","vertical"),()=>"horizontal")}));
|
|
139
146
|
|
|
@@ -149,7 +156,7 @@ const parsePythonProgramWidget=parseWidget(constant("python-program"),object({pr
|
|
|
149
156
|
|
|
150
157
|
const currentVersion$3={major:2,minor:0};function deriveNumCorrect(options){const{choices,numCorrect}=options;return numCorrect??choices.filter(c=>c.correct).length}const widgetOptionsUpgrades$2={"2":v1props=>{const upgraded={...v1props,numCorrect:deriveNumCorrect(v1props)};return upgraded},"1":v0props=>{const{noneOfTheAbove,...rest}=v0props;if(noneOfTheAbove){throw new Error("radio widget v0 no longer supports auto noneOfTheAbove")}return {...rest,hasNoneOfTheAbove:false}}};const defaultWidgetOptions$v={choices:[{},{},{},{}],displayCount:null,randomize:false,hasNoneOfTheAbove:false,multipleSelect:false,countChoices:false,deselectEnabled:false};
|
|
151
158
|
|
|
152
|
-
const parseWidgetsMapOrUndefined=defaulted((rawVal,ctx)=>parseWidgetsMap(rawVal,ctx),()=>undefined);const version2=optional(object({major:constant(2),minor:number}));const parseRadioWidgetV2=parseWidgetWithVersion(version2,constant("radio"),object({numCorrect:optional(number),choices:array(object({content:defaulted(string,()=>""),clue:optional(string),correct:optional(boolean),isNoneOfTheAbove:optional(boolean),widgets:parseWidgetsMapOrUndefined})),hasNoneOfTheAbove:optional(boolean),countChoices:optional(boolean),randomize:optional(boolean),multipleSelect:optional(boolean),deselectEnabled:optional(boolean),onePerLine:optional(boolean),displayCount:optional(any),noneOfTheAbove:optional(constant(false))}));const version1=optional(object({major:constant(1),minor:number}));const parseRadioWidgetV1=parseWidgetWithVersion(version1,constant("radio"),object({choices:array(object({content:defaulted(string,()=>""),clue:optional(string),correct:optional(boolean),isNoneOfTheAbove:optional(boolean),widgets:parseWidgetsMapOrUndefined})),hasNoneOfTheAbove:optional(boolean),countChoices:optional(boolean),randomize:optional(boolean),multipleSelect:optional(boolean),deselectEnabled:optional(boolean),onePerLine:optional(boolean),displayCount:optional(any),noneOfTheAbove:optional(constant(false))}));function migrateV1ToV2(widget){const{options}=widget;return {...widget,version:{major:2,minor:0},options:{...options,numCorrect:deriveNumCorrect(options)}}}const version0=optional(object({major:constant(0),minor:number}));const parseRadioWidgetV0=parseWidgetWithVersion(version0,constant("radio"),object({choices:array(object({content:defaulted(string,()=>""),clue:optional(string),correct:optional(boolean),isNoneOfTheAbove:optional(boolean),widgets:parseWidgetsMapOrUndefined})),hasNoneOfTheAbove:optional(boolean),countChoices:optional(boolean),randomize:optional(boolean),multipleSelect:optional(boolean),deselectEnabled:optional(boolean),onePerLine:optional(boolean),displayCount:optional(any),noneOfTheAbove:optional(constant(false))}));function migrateV0ToV1(widget){const{options}=widget;const{noneOfTheAbove:_,...rest}=options;return {...widget,version:{major:1,minor:0},options:{...rest,hasNoneOfTheAbove:false,noneOfTheAbove:undefined}}}const parseRadioWidget=versionedWidgetOptions(2,parseRadioWidgetV2).withMigrationFrom(1,parseRadioWidgetV1,migrateV1ToV2).withMigrationFrom(0,parseRadioWidgetV0,migrateV0ToV1).parser;
|
|
159
|
+
const parseWidgetsMapOrUndefined=defaulted(optional((rawVal,ctx)=>parseWidgetsMap(rawVal,ctx)),()=>undefined);const version2=optional(object({major:constant(2),minor:number}));const parseRadioWidgetV2=parseWidgetWithVersion(version2,constant("radio"),object({numCorrect:optional(number),choices:array(object({content:defaulted(string,()=>""),clue:optional(string),correct:optional(boolean),isNoneOfTheAbove:optional(boolean),widgets:parseWidgetsMapOrUndefined})),hasNoneOfTheAbove:optional(boolean),countChoices:optional(boolean),randomize:optional(boolean),multipleSelect:optional(boolean),deselectEnabled:optional(boolean),onePerLine:optional(boolean),displayCount:optional(any),noneOfTheAbove:optional(constant(false))}));const version1=optional(object({major:constant(1),minor:number}));const parseRadioWidgetV1=parseWidgetWithVersion(version1,constant("radio"),object({choices:array(object({content:defaulted(string,()=>""),clue:optional(string),correct:optional(boolean),isNoneOfTheAbove:optional(boolean),widgets:parseWidgetsMapOrUndefined})),hasNoneOfTheAbove:optional(boolean),countChoices:optional(boolean),randomize:optional(boolean),multipleSelect:optional(boolean),deselectEnabled:optional(boolean),onePerLine:optional(boolean),displayCount:optional(any),noneOfTheAbove:optional(constant(false))}));function migrateV1ToV2(widget){const{options}=widget;return {...widget,version:{major:2,minor:0},options:{...options,numCorrect:deriveNumCorrect(options)}}}const version0=optional(object({major:constant(0),minor:number}));const parseRadioWidgetV0=parseWidgetWithVersion(version0,constant("radio"),object({choices:array(object({content:defaulted(string,()=>""),clue:optional(string),correct:optional(boolean),isNoneOfTheAbove:optional(boolean),widgets:parseWidgetsMapOrUndefined})),hasNoneOfTheAbove:optional(boolean),countChoices:optional(boolean),randomize:optional(boolean),multipleSelect:optional(boolean),deselectEnabled:optional(boolean),onePerLine:optional(boolean),displayCount:optional(any),noneOfTheAbove:optional(constant(false))}));function migrateV0ToV1(widget){const{options}=widget;const{noneOfTheAbove:_,...rest}=options;return {...widget,version:{major:1,minor:0},options:{...rest,hasNoneOfTheAbove:false,noneOfTheAbove:undefined}}}const parseRadioWidget=versionedWidgetOptions(2,parseRadioWidgetV2).withMigrationFrom(1,parseRadioWidgetV1,migrateV1ToV2).withMigrationFrom(0,parseRadioWidgetV0,migrateV0ToV1).parser;
|
|
153
160
|
|
|
154
161
|
const parseSorterWidget=parseWidget(constant("sorter"),object({correct:array(string),padding:boolean,layout:enumeration("horizontal","vertical")}));
|
|
155
162
|
|
|
@@ -157,13 +164,13 @@ const parseTableWidget=parseWidget(constant("table"),object({headers:array(strin
|
|
|
157
164
|
|
|
158
165
|
const parseVideoWidget=parseWidget(constant("video"),object({location:string,static:optional(boolean)}));
|
|
159
166
|
|
|
160
|
-
const parseWidgetsMap=(rawValue,ctx)=>{if(!
|
|
167
|
+
const parseWidgetsMap=(rawValue,ctx)=>{if(!isPlainObject(rawValue)){return ctx.failure("PerseusWidgetsMap",rawValue)}const widgetsMap={};for(const key of Object.keys(rawValue)){const entryResult=parseWidgetsMapEntry([key,rawValue[key]],widgetsMap,ctx.forSubtree(key));if(isFailure(entryResult)){return entryResult}}return ctx.success(widgetsMap)};const parseWidgetsMapEntry=([id,widget],widgetMap,ctx)=>{const idComponentsResult=parseWidgetIdComponents(id.split(" "),ctx.forSubtree("(widget ID)"));if(isFailure(idComponentsResult)){return idComponentsResult}const[type,n]=idComponentsResult.value;function parseAndAssign(key,parse){const widgetResult=parse(widget,ctx);if(isFailure(widgetResult)){return widgetResult}widgetMap[key]=widgetResult.value;return ctx.success(undefined)}switch(type){case "categorizer":return parseAndAssign(`categorizer ${n}`,parseCategorizerWidget);case "cs-program":return parseAndAssign(`cs-program ${n}`,parseCSProgramWidget);case "definition":return parseAndAssign(`definition ${n}`,parseDefinitionWidget);case "dropdown":return parseAndAssign(`dropdown ${n}`,parseDropdownWidget);case "explanation":return parseAndAssign(`explanation ${n}`,parseExplanationWidget);case "expression":return parseAndAssign(`expression ${n}`,parseExpressionWidget);case "grapher":return parseAndAssign(`grapher ${n}`,parseGrapherWidget);case "group":return parseAndAssign(`group ${n}`,parseGroupWidget);case "graded-group":return parseAndAssign(`graded-group ${n}`,parseGradedGroupWidget);case "graded-group-set":return parseAndAssign(`graded-group-set ${n}`,parseGradedGroupSetWidget);case "iframe":return parseAndAssign(`iframe ${n}`,parseIframeWidget);case "image":return parseAndAssign(`image ${n}`,parseImageWidget);case "input-number":return parseAndAssign(`input-number ${n}`,parseInputNumberWidget);case "interaction":return parseAndAssign(`interaction ${n}`,parseInteractionWidget);case "interactive-graph":return parseAndAssign(`interactive-graph ${n}`,parseInteractiveGraphWidget);case "label-image":return parseAndAssign(`label-image ${n}`,parseLabelImageWidget);case "matcher":return parseAndAssign(`matcher ${n}`,parseMatcherWidget);case "matrix":return parseAndAssign(`matrix ${n}`,parseMatrixWidget);case "measurer":return parseAndAssign(`measurer ${n}`,parseMeasurerWidget);case "molecule-renderer":return parseAndAssign(`molecule-renderer ${n}`,parseMoleculeRendererWidget);case "number-line":return parseAndAssign(`number-line ${n}`,parseNumberLineWidget);case "numeric-input":return parseAndAssign(`numeric-input ${n}`,parseNumericInputWidget);case "orderer":return parseAndAssign(`orderer ${n}`,parseOrdererWidget);case "passage":return parseAndAssign(`passage ${n}`,parsePassageWidget);case "passage-ref":return parseAndAssign(`passage-ref ${n}`,parsePassageRefWidget);case "passage-ref-target":return parseAndAssign(`passage-ref-target ${n}`,any);case "phet-simulation":return parseAndAssign(`phet-simulation ${n}`,parsePhetSimulationWidget);case "plotter":return parseAndAssign(`plotter ${n}`,parsePlotterWidget);case "python-program":return parseAndAssign(`python-program ${n}`,parsePythonProgramWidget);case "radio":return parseAndAssign(`radio ${n}`,parseRadioWidget);case "sorter":return parseAndAssign(`sorter ${n}`,parseSorterWidget);case "table":return parseAndAssign(`table ${n}`,parseTableWidget);case "video":return parseAndAssign(`video ${n}`,parseVideoWidget);case "sequence":return parseAndAssign(`sequence ${n}`,parseDeprecatedWidget);case "lights-puzzle":return parseAndAssign(`lights-puzzle ${n}`,parseDeprecatedWidget);case "simulator":return parseAndAssign(`simulator ${n}`,parseDeprecatedWidget);case "transformer":return parseAndAssign(`transformer ${n}`,parseDeprecatedWidget);default:return parseAndAssign(`${type} ${n}`,parseWidget(constant(type),any))}};const parseDeprecatedWidget=parseWidget((_,ctx)=>ctx.success("deprecated-standin"),object({}));const parseStringToNonNegativeInt=(rawValue,ctx)=>{if(typeof rawValue!=="string"||!/^(0|[1-9][0-9]*)$/.test(rawValue)){return ctx.failure("a string representing a non-negative integer",rawValue)}return ctx.success(+rawValue)};const parseWidgetIdComponents=pair(string,parseStringToNonNegativeInt);
|
|
161
168
|
|
|
162
169
|
const parsePerseusRenderer=defaulted(object({content:defaulted(string,()=>""),widgets:defaulted((rawVal,ctx)=>parseWidgetsMap(rawVal,ctx),()=>({})),images:parseImages,metadata:any}),()=>({content:"",widgets:{},images:{}}));
|
|
163
170
|
|
|
164
171
|
const parsePerseusArticle=union(parsePerseusRenderer).or(array(parsePerseusRenderer)).parser;
|
|
165
172
|
|
|
166
|
-
const parseHint=object({replace:defaulted(boolean,()=>undefined),content:string,widgets:defaulted(parseWidgetsMap,()=>({})),images:parseImages,metadata:any});
|
|
173
|
+
const parseHint=object({replace:defaulted(optional(boolean),()=>undefined),content:string,widgets:defaulted(parseWidgetsMap,()=>({})),images:parseImages,metadata:any});
|
|
167
174
|
|
|
168
175
|
const parsePerseusAnswerArea=pipeParsers(defaulted(object({}),()=>({}))).then(convert(toAnswerArea)).parser;function toAnswerArea(raw){return {zTable:!!raw.zTable,calculator:!!raw.calculator,chi2Table:!!raw.chi2Table,financialCalculatorMonthlyPayment:!!raw.financialCalculatorMonthlyPayment,financialCalculatorTotalAmount:!!raw.financialCalculatorTotalAmount,financialCalculatorTimeToPayOff:!!raw.financialCalculatorTimeToPayOff,periodicTable:!!raw.periodicTable,periodicTableWithKey:!!raw.periodicTableWithKey,tTable:!!raw.tTable}}
|
|
169
176
|
|
|
@@ -171,7 +178,7 @@ const parsePerseusItem$1=object({question:parsePerseusRenderer,hints:defaulted(a
|
|
|
171
178
|
|
|
172
179
|
function parsePerseusItem(json){if(isRealJSONParse(JSON.parse)){return JSON.parse(json)}throw new Error("Something went wrong.")}function parseAndMigratePerseusItem(json){throwErrorIfCheatingDetected();const object=JSON.parse(json);const result=parse(object,parsePerseusItem$1);if(isFailure(result)){return failure({message:result.detail,invalidObject:object})}return result}function parseAndMigratePerseusArticle(json){throwErrorIfCheatingDetected();const object=JSON.parse(json);const result=parse(object,parsePerseusArticle);if(isFailure(result)){return failure({message:result.detail,invalidObject:object})}return result}function throwErrorIfCheatingDetected(){if(!isRealJSONParse(JSON.parse)){throw new Error("Something went wrong.")}}
|
|
173
180
|
|
|
174
|
-
const libName="@khanacademy/perseus-core";const libVersion="
|
|
181
|
+
const libName="@khanacademy/perseus-core";const libVersion="10.1.0";addLibraryVersionToPerseusDebug(libName,libVersion);
|
|
175
182
|
|
|
176
183
|
const Errors=Object.freeze({Unknown:"Unknown",Internal:"Internal",InvalidInput:"InvalidInput",NotAllowed:"NotAllowed",TransientService:"TransientService",Service:"Service"});
|
|
177
184
|
|
|
@@ -191,7 +198,7 @@ const defaultWidgetOptions$s={togglePrompt:"",definition:""};const definitionWid
|
|
|
191
198
|
|
|
192
199
|
function getDropdownPublicWidgetOptions(options){return {choices:options.choices.map(choice=>({content:choice.content})),placeholder:options.placeholder,static:options.static,visibleLabel:options.visibleLabel,ariaLabel:options.ariaLabel}}
|
|
193
200
|
|
|
194
|
-
const defaultWidgetOptions$r={placeholder:"",choices:[{content:"",correct:false}]};const dropdownWidgetLogic={name:"
|
|
201
|
+
const defaultWidgetOptions$r={placeholder:"",choices:[{content:"",correct:false}]};const dropdownWidgetLogic={name:"dropdown",defaultWidgetOptions: defaultWidgetOptions$r,defaultAlignment:"inline-block",getPublicWidgetOptions:getDropdownPublicWidgetOptions};
|
|
195
202
|
|
|
196
203
|
const defaultWidgetOptions$q={showPrompt:"Explain",hidePrompt:"Hide explanation",explanation:"explanation goes here\n\nmore explanation",widgets:{}};const explanationWidgetLogic={name:"explanation",defaultWidgetOptions: defaultWidgetOptions$q,defaultAlignment:"inline"};
|
|
197
204
|
|
|
@@ -209,67 +216,67 @@ function getGrapherPublicWidgetOptions(options){const{correct:_,...publicOptions
|
|
|
209
216
|
|
|
210
217
|
const defaultWidgetOptions$m={graph:{labels:["x","y"],range:[[-10,10],[-10,10]],step:[1,1],backgroundImage:{url:null},markings:"graph",rulerLabel:"",rulerTicks:10,valid:true,showTooltips:false},correct:{type:"linear",coords:null},availableTypes:["linear"]};const grapherWidgetLogic={name:"grapher",defaultWidgetOptions: defaultWidgetOptions$m,getPublicWidgetOptions:getGrapherPublicWidgetOptions};
|
|
211
218
|
|
|
212
|
-
const defaultWidgetOptions$l={content:"",widgets:{},images:{}};const groupWidgetLogic={name:"group",defaultWidgetOptions: defaultWidgetOptions$l};
|
|
213
|
-
|
|
214
219
|
function getIFramePublicWidgetOptions(options){return options}
|
|
215
220
|
|
|
216
|
-
const defaultWidgetOptions$
|
|
221
|
+
const defaultWidgetOptions$l={url:"",settings:[{name:"",value:""}],width:"400",height:"400",allowFullScreen:false,allowTopNavigation:false};const iframeWidgetLogic={name:"iframe",defaultWidgetOptions: defaultWidgetOptions$l,getPublicWidgetOptions:getIFramePublicWidgetOptions};
|
|
217
222
|
|
|
218
|
-
const defaultWidgetOptions$
|
|
223
|
+
const defaultWidgetOptions$k={title:"",range:[[0,10],[0,10]],box:[400,400],backgroundImage:{url:null,width:0,height:0},labels:[],alt:"",caption:""};const imageWidgetLogic={name:"image",defaultWidgetOptions: defaultWidgetOptions$k,supportedAlignments:["block","full-width"],defaultAlignment:"block"};
|
|
219
224
|
|
|
220
|
-
|
|
225
|
+
function getInputNumberPublicWidgetOptions(options){const{value:_,...publicWidgetOptions}=options;return publicWidgetOptions}
|
|
221
226
|
|
|
222
|
-
const defaultWidgetOptions$
|
|
227
|
+
const defaultWidgetOptions$j={value:0,simplify:"required",size:"normal",inexact:false,maxError:.1,answerType:"number",rightAlign:false};const inputNumberWidgetLogic={name:"input-number",defaultWidgetOptions: defaultWidgetOptions$j,defaultAlignment:"inline-block",getPublicWidgetOptions:getInputNumberPublicWidgetOptions};
|
|
228
|
+
|
|
229
|
+
const defaultWidgetOptions$i={graph:{box:[400,400],labels:["x","y"],range:[[-10,10],[-10,10]],tickStep:[1,1],gridStep:[1,1],markings:"graph"},elements:[]};const interactionWidgetLogic={name:"interaction",defaultWidgetOptions: defaultWidgetOptions$i};
|
|
223
230
|
|
|
224
231
|
function getInteractiveGraphPublicWidgetOptions(options){const{correct:_,...publicOptions}=options;return publicOptions}
|
|
225
232
|
|
|
226
|
-
const defaultWidgetOptions$
|
|
233
|
+
const defaultWidgetOptions$h={labels:["x","y"],range:[[-10,10],[-10,10]],step:[1,1],backgroundImage:{url:null},markings:"graph",showTooltips:false,showProtractor:false,graph:{type:"linear"},correct:{type:"linear",coords:null}};const interactiveGraphWidgetLogic={name:"interactive-graph",defaultWidgetOptions: defaultWidgetOptions$h,getPublicWidgetOptions:getInteractiveGraphPublicWidgetOptions};
|
|
227
234
|
|
|
228
235
|
function getLabelImagePublicWidgetOptions(options){return {...options,markers:options.markers.map(getLabelImageMarkerPublicData)}}function getLabelImageMarkerPublicData(marker){const{answers:_,...publicData}=marker;return publicData}
|
|
229
236
|
|
|
230
|
-
const defaultWidgetOptions$
|
|
237
|
+
const defaultWidgetOptions$g={choices:[],imageAlt:"",imageUrl:"",imageWidth:0,imageHeight:0,markers:[],multipleAnswers:false,hideChoicesFromInstructions:false};const labelImageWidgetLogic={name:"label-image",defaultWidgetOptions: defaultWidgetOptions$g,getPublicWidgetOptions:getLabelImagePublicWidgetOptions};
|
|
231
238
|
|
|
232
239
|
const seededRNG=function(seed){let randomSeed=seed;return function(){let seed=randomSeed;seed=seed+0x7ed55d16+(seed<<12)&0xffffffff;seed=(seed^0xc761c23c^seed>>>19)&0xffffffff;seed=seed+0x165667b1+(seed<<5)&0xffffffff;seed=(seed+0xd3a2646c^seed<<9)&0xffffffff;seed=seed+0xfd7046c5+(seed<<3)&0xffffffff;seed=(seed^0xb55a4f09^seed>>>16)&0xffffffff;return (randomSeed=seed&0xfffffff)/0x10000000}};function shuffle(array,randomSeed,ensurePermuted=false){const shuffled=[...array];if(!shuffled.length||_.all(shuffled,function(value){return _.isEqual(value,shuffled[0])})){return shuffled}let random;if(typeof randomSeed==="function"){random=randomSeed;}else {random=seededRNG(randomSeed);}do{for(let top=shuffled.length;top>0;top--){const newEnd=Math.floor(random()*top);const temp=shuffled[newEnd];shuffled[newEnd]=shuffled[top-1];shuffled[top-1]=temp;}}while(ensurePermuted&&_.isEqual(array,shuffled))return shuffled}const random=seededRNG(new Date().getTime()&0xffffffff);
|
|
233
240
|
|
|
234
241
|
const shuffleMatcher=props=>{const rng=seededRNG(props.problemNum);let left;if(!props.orderMatters){left=props.left;}else {left=shuffle(props.left,rng,true);}const right=shuffle(props.right,rng,true);return {left,right}};function shuffleMatcherWithRandom(data){let left;if(!data.orderMatters){left=data.left;}else {left=shuffle(data.left,Math.random,true);}const right=shuffle(data.right,Math.random,true);return {left,right}}function getMatcherPublicWidgetOptions(options){const{left,right}=shuffleMatcherWithRandom(options);return {...options,left:left,right:right}}
|
|
235
242
|
|
|
236
|
-
const defaultWidgetOptions$
|
|
243
|
+
const defaultWidgetOptions$f={left:["$x$","$y$","$z$"],right:["$1$","$2$","$3$"],labels:["test","label"],orderMatters:false,padding:true};const matcherWidgetLogic={name:"matcher",defaultWidgetOptions: defaultWidgetOptions$f,getPublicWidgetOptions:getMatcherPublicWidgetOptions};
|
|
237
244
|
|
|
238
245
|
function getMatrixPublicWidgetOptions(options){const{answers:_,...publicOptions}=options;return publicOptions}
|
|
239
246
|
|
|
240
|
-
const defaultWidgetOptions$
|
|
247
|
+
const defaultWidgetOptions$e={matrixBoardSize:[3,3],answers:[[]],prefix:"",suffix:"",cursorPosition:[0,0]};const matrixWidgetLogic={name:"matrix",defaultWidgetOptions: defaultWidgetOptions$e,getPublicWidgetOptions:getMatrixPublicWidgetOptions};
|
|
241
248
|
|
|
242
|
-
const currentVersion$1={major:1,minor:0};const widgetOptionsUpgrades={"1":v0options=>{const{imageUrl,imageTop,imageLeft,...rest}=v0options;return {...rest,image:{url:imageUrl,top:imageTop,left:imageLeft}}}};const defaultWidgetOptions$
|
|
249
|
+
const currentVersion$1={major:1,minor:0};const widgetOptionsUpgrades={"1":v0options=>{const{imageUrl,imageTop,imageLeft,...rest}=v0options;return {...rest,image:{url:imageUrl,top:imageTop,left:imageLeft}}}};const defaultWidgetOptions$d={box:[480,480],image:{},showProtractor:true,showRuler:false,rulerLabel:"",rulerTicks:10,rulerPixels:40,rulerLength:10};
|
|
243
250
|
|
|
244
|
-
const measurerWidgetLogic={name:"measurer",version:currentVersion$1,widgetOptionsUpgrades:widgetOptionsUpgrades,defaultWidgetOptions:defaultWidgetOptions$
|
|
251
|
+
const measurerWidgetLogic={name:"measurer",version:currentVersion$1,widgetOptionsUpgrades:widgetOptionsUpgrades,defaultWidgetOptions:defaultWidgetOptions$d};
|
|
245
252
|
|
|
246
253
|
function getNumberLinePublicWidgetOptions(options){const{correctX:_,correctRel:__,...publicOptions}=options;return publicOptions}
|
|
247
254
|
|
|
248
|
-
const defaultWidgetOptions$
|
|
255
|
+
const defaultWidgetOptions$c={range:[0,10],labelRange:[null,null],labelStyle:"decimal",labelTicks:true,divisionRange:[1,12],numDivisions:5,snapDivisions:2,tickStep:null,correctRel:"eq",correctX:null,initialX:null,showTooltips:false};const numberLineWidgetLogic={name:"number-line",defaultWidgetOptions: defaultWidgetOptions$c,getPublicWidgetOptions:getNumberLinePublicWidgetOptions};
|
|
249
256
|
|
|
250
257
|
function getNumericInputAnswerPublicData(answer){const{answerForms,simplify,status}=answer;return {answerForms,simplify,status}}function getNumericInputPublicWidgetOptions(options){const{answers,...publicWidgetOptions}=options;return {...publicWidgetOptions,answers:answers.map(getNumericInputAnswerPublicData)}}
|
|
251
258
|
|
|
252
|
-
const defaultWidgetOptions$
|
|
259
|
+
const defaultWidgetOptions$b={answers:[{value:null,status:"correct",message:"",simplify:"required",answerForms:[],strict:false,maxError:null}],size:"normal",coefficient:false,labelText:"",rightAlign:false};const numericInputWidgetLogic={name:"numeric-input",defaultWidgetOptions: defaultWidgetOptions$b,defaultAlignment:"inline-block",getPublicWidgetOptions:getNumericInputPublicWidgetOptions};
|
|
253
260
|
|
|
254
|
-
function getOrdererPublicWidgetOptions(
|
|
261
|
+
function getOrdererPublicWidgetOptions(fullOptions){const{options,height,layout}=fullOptions;return {options,height,layout}}
|
|
255
262
|
|
|
256
|
-
const defaultWidgetOptions$
|
|
263
|
+
const defaultWidgetOptions$a={correctOptions:[{content:"$x$"}],otherOptions:[{content:"$y$"}],height:"normal",layout:"horizontal"};const ordererWidgetLogic={name:"orderer",defaultWidgetOptions: defaultWidgetOptions$a,getPublicWidgetOptions:getOrdererPublicWidgetOptions};
|
|
257
264
|
|
|
258
|
-
const defaultWidgetOptions$
|
|
265
|
+
const defaultWidgetOptions$9={passageTitle:"",passageText:"",footnotes:"",showLineNumbers:true};const passageWidgetLogic={name:"passage",defaultWidgetOptions: defaultWidgetOptions$9};
|
|
259
266
|
|
|
260
|
-
const currentVersion={major:0,minor:1};const defaultWidgetOptions$
|
|
267
|
+
const currentVersion={major:0,minor:1};const defaultWidgetOptions$8={passageNumber:1,referenceNumber:1,summaryText:""};
|
|
261
268
|
|
|
262
|
-
const passageRefWidgetLogic={name:"
|
|
269
|
+
const passageRefWidgetLogic={name:"passage-ref",version:currentVersion,defaultWidgetOptions:defaultWidgetOptions$8,defaultAlignment:"inline"};
|
|
263
270
|
|
|
264
|
-
const defaultWidgetOptions$
|
|
271
|
+
const defaultWidgetOptions$7={content:""};const passageRefTargetWidgetLogic={name:"passage-ref-target",defaultWidgetOptions: defaultWidgetOptions$7,defaultAlignment:"inline"};
|
|
265
272
|
|
|
266
|
-
const defaultWidgetOptions$
|
|
273
|
+
const defaultWidgetOptions$6={url:"",description:""};const phetSimulationWidgetLogic={name:"phet-simulation",defaultWidgetOptions: defaultWidgetOptions$6};
|
|
267
274
|
|
|
268
275
|
function getPlotterPublicWidgetOptions(options){const{correct:_,...publicOptions}=options;return publicOptions}
|
|
269
276
|
|
|
270
|
-
const defaultWidgetOptions$
|
|
277
|
+
const defaultWidgetOptions$5={scaleY:1,maxY:10,snapsPerLine:2,correct:[1],starting:[1],type:"bar",labels:["",""],categories:[""],picSize:30,picBoxHeight:36,plotDimensions:[275,200],labelInterval:1,picUrl:null};const plotterWidgetLogic={name:"plotter",defaultWidgetOptions: defaultWidgetOptions$5,getPublicWidgetOptions:getPlotterPublicWidgetOptions};
|
|
271
278
|
|
|
272
|
-
const defaultWidgetOptions$
|
|
279
|
+
const defaultWidgetOptions$4={programID:"",height:400};const pythonProgramWidgetLogic={name:"python-program",defaultWidgetOptions: defaultWidgetOptions$4};
|
|
273
280
|
|
|
274
281
|
function getRadioChoicePublicData(choice){const{content,isNoneOfTheAbove,widgets}=choice;return {content,isNoneOfTheAbove,widgets}}function usesNumCorrect(multipleSelect,countChoices,numCorrect){return multipleSelect&&countChoices&&numCorrect}function getRadioPublicWidgetOptions(options){const{numCorrect,choices,multipleSelect,countChoices}=options;return {...options,numCorrect:usesNumCorrect(multipleSelect,countChoices,numCorrect)?numCorrect:undefined,choices:choices.map(getRadioChoicePublicData)}}
|
|
275
282
|
|
|
@@ -277,15 +284,15 @@ const radioWidgetLogic={name:"radio",version:currentVersion$3,widgetOptionsUpgra
|
|
|
277
284
|
|
|
278
285
|
function getSorterPublicWidgetOptions(options){const shuffledCorrect=shuffle(options.correct,Math.random,true);return {...options,correct:shuffledCorrect,isCorrectShuffled:true}}
|
|
279
286
|
|
|
280
|
-
const defaultWidgetOptions$
|
|
287
|
+
const defaultWidgetOptions$3={correct:["$x$","$y$","$z$"],layout:"horizontal",padding:true};const sorterWidgetLogic={name:"sorter",defaultWidgetOptions: defaultWidgetOptions$3,getPublicWidgetOptions:getSorterPublicWidgetOptions};
|
|
281
288
|
|
|
282
289
|
function getTablePublicWidgetOptions(options){const{answers:_,...publicOptions}=options;return publicOptions}
|
|
283
290
|
|
|
284
|
-
const defaultRows=4;const defaultColumns=1;const answers=new Array(defaultRows).fill(0).map(()=>new Array(defaultColumns).fill(""));const defaultWidgetOptions$
|
|
291
|
+
const defaultRows=4;const defaultColumns=1;const answers=new Array(defaultRows).fill(0).map(()=>new Array(defaultColumns).fill(""));const defaultWidgetOptions$2={headers:[""],rows:defaultRows,columns:defaultColumns,answers:answers};const tableWidgetLogic={name:"table",defaultWidgetOptions: defaultWidgetOptions$2,getPublicWidgetOptions:getTablePublicWidgetOptions};
|
|
285
292
|
|
|
286
|
-
const defaultWidgetOptions={location:""};const videoWidgetLogic={name:"video",defaultWidgetOptions,supportedAlignments:["block","float-left","float-right","full-width"],defaultAlignment:"block"};
|
|
293
|
+
const defaultWidgetOptions$1={location:""};const videoWidgetLogic={name:"video",defaultWidgetOptions: defaultWidgetOptions$1,supportedAlignments:["block","float-left","float-right","full-width"],defaultAlignment:"block"};
|
|
287
294
|
|
|
288
|
-
const widgets={};function registerWidget(type,logic){widgets[type]=logic;}function isWidgetRegistered(type){const widgetLogic=widgets[type];return !!widgetLogic}function getCurrentVersion(type){const widgetLogic=widgets[type];return widgetLogic?.version||{major:0,minor:0}}const getPublicWidgetOptionsFunction=name=>{return widgets[name]?.getPublicWidgetOptions??(i=>i)};function getWidgetOptionsUpgrades(type){const widgetLogic=widgets[type];return widgetLogic?.widgetOptionsUpgrades||{}}function getDefaultWidgetOptions(type){const widgetLogic=widgets[type];return widgetLogic?.defaultWidgetOptions||{}}const getSupportedAlignments=type=>{const widgetLogic=widgets[type];if(!widgetLogic?.supportedAlignments?.[0]){return ["default"]}return widgetLogic?.supportedAlignments};const getDefaultAlignment=type=>{const widgetLogic=widgets[type];if(!widgetLogic?.defaultAlignment){return "block"}return widgetLogic.defaultAlignment};
|
|
295
|
+
const widgets={};function registerWidget(type,logic){widgets[type]=logic;}function isWidgetRegistered(type){const widgetLogic=widgets[type];return !!widgetLogic}function getCurrentVersion(type){const widgetLogic=widgets[type];return widgetLogic?.version||{major:0,minor:0}}const getPublicWidgetOptionsFunction=name=>{return widgets[name]?.getPublicWidgetOptions??(i=>i)};function getWidgetOptionsUpgrades(type){const widgetLogic=widgets[type];return widgetLogic?.widgetOptionsUpgrades||{}}function getDefaultWidgetOptions(type){const widgetLogic=widgets[type];return widgetLogic?.defaultWidgetOptions||{}}const getSupportedAlignments=type=>{const widgetLogic=widgets[type];if(!widgetLogic?.supportedAlignments?.[0]){return ["default"]}return widgetLogic?.supportedAlignments};const getDefaultAlignment=type=>{const widgetLogic=widgets[type];if(!widgetLogic?.defaultAlignment){return "block"}return widgetLogic.defaultAlignment};function registerCoreWidgets(){const widgets=[categorizerWidgetLogic,csProgramWidgetLogic,definitionWidgetLogic,dropdownWidgetLogic,explanationWidgetLogic,expressionWidgetLogic,gradedGroupWidgetLogic,gradedGroupSetWidgetLogic,grapherWidgetLogic,groupWidgetLogic,iframeWidgetLogic,imageWidgetLogic,inputNumberWidgetLogic,interactionWidgetLogic,interactiveGraphWidgetLogic,labelImageWidgetLogic,matcherWidgetLogic,matrixWidgetLogic,measurerWidgetLogic,numberLineWidgetLogic,numericInputWidgetLogic,ordererWidgetLogic,passageWidgetLogic,passageRefWidgetLogic,passageRefTargetWidgetLogic,phetSimulationWidgetLogic,plotterWidgetLogic,pythonProgramWidgetLogic,radioWidgetLogic,sorterWidgetLogic,tableWidgetLogic,videoWidgetLogic];widgets.forEach(w=>{registerWidget(w.name,w);});}
|
|
289
296
|
|
|
290
297
|
var coreWidgetRegistry = /*#__PURE__*/Object.freeze({
|
|
291
298
|
__proto__: null,
|
|
@@ -295,14 +302,21 @@ var coreWidgetRegistry = /*#__PURE__*/Object.freeze({
|
|
|
295
302
|
getPublicWidgetOptionsFunction: getPublicWidgetOptionsFunction,
|
|
296
303
|
getSupportedAlignments: getSupportedAlignments,
|
|
297
304
|
getWidgetOptionsUpgrades: getWidgetOptionsUpgrades,
|
|
298
|
-
isWidgetRegistered: isWidgetRegistered
|
|
305
|
+
isWidgetRegistered: isWidgetRegistered,
|
|
306
|
+
registerCoreWidgets: registerCoreWidgets
|
|
299
307
|
});
|
|
300
308
|
|
|
301
309
|
const DEFAULT_STATIC=false;const upgradeWidgetInfoToLatestVersion=oldWidgetInfo=>{const type=oldWidgetInfo.type;if(!_.isString(type)){throw new PerseusError("widget type must be a string, but was: "+type,Errors.Internal)}if(!isWidgetRegistered(type)){return oldWidgetInfo}const initialVersion=oldWidgetInfo.version||{major:0,minor:0};const latestVersion=getCurrentVersion(type);if(initialVersion.major>latestVersion.major||initialVersion.major===latestVersion.major&&initialVersion.minor>latestVersion.minor){return oldWidgetInfo}let newEditorOptions=_.clone(oldWidgetInfo.options)||{};const upgradePropsMap=getWidgetOptionsUpgrades(type);if(_.keys(newEditorOptions).length!==0){for(let nextVersion=initialVersion.major+1;nextVersion<=latestVersion.major;nextVersion++){if(upgradePropsMap[String(nextVersion)]){newEditorOptions=upgradePropsMap[String(nextVersion)](newEditorOptions);}else {throw new PerseusError("No upgrade found for widget. Cannot render.",Errors.Internal,{metadata:{type,fromMajorVersion:nextVersion-1,toMajorVersion:nextVersion,oldWidgetInfo:JSON.stringify(oldWidgetInfo)}})}}}const defaultOptions=getDefaultWidgetOptions(type);newEditorOptions={...defaultOptions,...newEditorOptions};let alignment=oldWidgetInfo.alignment;if(alignment==null||alignment==="default"){alignment=getSupportedAlignments(type)?.[0];if(!alignment){throw new PerseusError("No default alignment found when upgrading widget",Errors.Internal,{metadata:{widgetType:type}})}}let widgetStatic=oldWidgetInfo.static;if(widgetStatic==null){widgetStatic=DEFAULT_STATIC;}return {...oldWidgetInfo,version:latestVersion,graded:oldWidgetInfo.graded!=null?oldWidgetInfo.graded:true,alignment:alignment,static:widgetStatic,options:newEditorOptions}};function getUpgradedWidgetOptions(oldWidgetOptions){return mapObject(oldWidgetOptions,(widgetInfo,widgetId)=>{if(!widgetInfo.type||!widgetInfo.alignment){const newValues={};if(!widgetInfo.type){newValues.type=widgetId.split(" ")[0];}if(!widgetInfo.alignment){newValues.alignment="default";}widgetInfo={...widgetInfo,...newValues};}return upgradeWidgetInfoToLatestVersion(widgetInfo)})}
|
|
302
310
|
|
|
303
|
-
function
|
|
311
|
+
function splitPerseusRenderer(original){const clone=deepClone(original);const originalWidgets=clone.widgets??{};const upgradedWidgets=getUpgradedWidgetOptions(originalWidgets);const splitWidgets={};for(const[id,widget]of Object.entries(upgradedWidgets)){const publicWidgetOptionsFun=getPublicWidgetOptionsFunction(widget.type);splitWidgets[id]={...widget,options:publicWidgetOptionsFun(widget.options)};}return {...original,widgets:splitWidgets}}
|
|
312
|
+
|
|
313
|
+
function getGroupPublicWidgetOptions(options){return splitPerseusRenderer(options)}
|
|
314
|
+
|
|
315
|
+
const defaultWidgetOptions={content:"",widgets:{},images:{}};const groupWidgetLogic={name:"group",defaultWidgetOptions,getPublicWidgetOptions:getGroupPublicWidgetOptions};
|
|
316
|
+
|
|
317
|
+
function splitPerseusItem(original){const item=deepClone(original);return {...item,question:splitPerseusRenderer(item.question),hints:[]}}
|
|
304
318
|
|
|
305
319
|
const PerseusFeatureFlags=["new-radio-widget"];
|
|
306
320
|
|
|
307
|
-
export { coreWidgetRegistry as CoreWidgetRegistry, Errors, grapherUtil as GrapherUtil, ItemExtras, PerseusError, PerseusExpressionAnswerFormConsidered, PerseusFeatureFlags, addWidget, approximateDeepEqual, approximateEqual, categorizerWidgetLogic as categorizerLogic, csProgramWidgetLogic as csProgramLogic, deepClone, definitionWidgetLogic as definitionLogic, deriveExtraKeys, deriveNumCorrect, dropdownWidgetLogic as dropdownLogic, explanationWidgetLogic as explanationLogic, expressionWidgetLogic as expressionLogic, generateTestPerseusItem, getCSProgramPublicWidgetOptions, getCategorizerPublicWidgetOptions, getDecimalSeparator, getDropdownPublicWidgetOptions, getExpressionPublicWidgetOptions, getGrapherPublicWidgetOptions, getIFramePublicWidgetOptions, getInteractiveGraphPublicWidgetOptions, getLabelImagePublicWidgetOptions, getMatcherPublicWidgetOptions, getMatrixPublicWidgetOptions, getMatrixSize, getNumberLinePublicWidgetOptions, getNumericInputPublicWidgetOptions, getOrdererPublicWidgetOptions, getPlotterPublicWidgetOptions, getRadioPublicWidgetOptions, getSorterPublicWidgetOptions, getTablePublicWidgetOptions, getUpgradedWidgetOptions, getWidgetIdsFromContent, getWidgetIdsFromContentByType, gradedGroupWidgetLogic as gradedGroupLogic, gradedGroupSetWidgetLogic as gradedGroupSetLogic, grapherWidgetLogic as grapherLogic, groupWidgetLogic as groupLogic, iframeWidgetLogic as iframeLogic, imageWidgetLogic as imageLogic, inputNumberWidgetLogic as inputNumberLogic, interactionWidgetLogic as interactionLogic, interactiveGraphWidgetLogic as interactiveGraphLogic, isFailure, isSuccess, labelImageWidgetLogic as labelImageLogic, libVersion, lockedFigureColorNames, lockedFigureColors, lockedFigureFillStyles, mapObject, matcherWidgetLogic as matcherLogic, matrixWidgetLogic as matrixLogic, measurerWidgetLogic as measurerLogic, numberLineWidgetLogic as numberLineLogic, numericInputWidgetLogic as numericInputLogic, ordererWidgetLogic as ordererLogic, parseAndMigratePerseusArticle, parseAndMigratePerseusItem, parsePerseusItem, passageWidgetLogic as passageLogic, passageRefWidgetLogic as passageRefLogic, passageRefTargetWidgetLogic as passageRefTargetLogic, phetSimulationWidgetLogic as phetSimulationLogic, plotterWidgetLogic as plotterLogic, plotterPlotTypes, pluck, pythonProgramWidgetLogic as pythonProgramLogic, radioWidgetLogic as radioLogic, random, seededRNG, shuffle, shuffleMatcher, sorterWidgetLogic as sorterLogic, splitPerseusItem, tableWidgetLogic as tableLogic, upgradeWidgetInfoToLatestVersion, usesNumCorrect, videoWidgetLogic as videoLogic };
|
|
321
|
+
export { coreWidgetRegistry as CoreWidgetRegistry, Errors, grapherUtil as GrapherUtil, ItemExtras, PerseusError, PerseusExpressionAnswerFormConsidered, PerseusFeatureFlags, addWidget, approximateDeepEqual, approximateEqual, categorizerWidgetLogic as categorizerLogic, csProgramWidgetLogic as csProgramLogic, deepClone, definitionWidgetLogic as definitionLogic, deriveExtraKeys, deriveNumCorrect, dropdownWidgetLogic as dropdownLogic, explanationWidgetLogic as explanationLogic, expressionWidgetLogic as expressionLogic, generateTestPerseusItem, generateTestPerseusRenderer, getCSProgramPublicWidgetOptions, getCategorizerPublicWidgetOptions, getDecimalSeparator, getDropdownPublicWidgetOptions, getExpressionPublicWidgetOptions, getGrapherPublicWidgetOptions, getGroupPublicWidgetOptions, getIFramePublicWidgetOptions, getInteractiveGraphPublicWidgetOptions, getLabelImagePublicWidgetOptions, getMatcherPublicWidgetOptions, getMatrixPublicWidgetOptions, getMatrixSize, getNumberLinePublicWidgetOptions, getNumericInputPublicWidgetOptions, getOrdererPublicWidgetOptions, getPlotterPublicWidgetOptions, getRadioPublicWidgetOptions, getSorterPublicWidgetOptions, getTablePublicWidgetOptions, getUpgradedWidgetOptions, getWidgetIdsFromContent, getWidgetIdsFromContentByType, gradedGroupWidgetLogic as gradedGroupLogic, gradedGroupSetWidgetLogic as gradedGroupSetLogic, grapherWidgetLogic as grapherLogic, groupWidgetLogic as groupLogic, iframeWidgetLogic as iframeLogic, imageWidgetLogic as imageLogic, inputNumberWidgetLogic as inputNumberLogic, interactionWidgetLogic as interactionLogic, interactiveGraphWidgetLogic as interactiveGraphLogic, isFailure, isSuccess, itemHasHints, itemHasRationales, labelImageWidgetLogic as labelImageLogic, libVersion, lockedFigureColorNames, lockedFigureColors, lockedFigureFillStyles, mapObject, matcherWidgetLogic as matcherLogic, matrixWidgetLogic as matrixLogic, measurerWidgetLogic as measurerLogic, numberLineWidgetLogic as numberLineLogic, numericInputWidgetLogic as numericInputLogic, ordererWidgetLogic as ordererLogic, parseAndMigratePerseusArticle, parseAndMigratePerseusItem, parsePerseusItem, passageWidgetLogic as passageLogic, passageRefWidgetLogic as passageRefLogic, passageRefTargetWidgetLogic as passageRefTargetLogic, phetSimulationWidgetLogic as phetSimulationLogic, plotterWidgetLogic as plotterLogic, plotterPlotTypes, pluck, pythonProgramWidgetLogic as pythonProgramLogic, radioWidgetLogic as radioLogic, random, registerCoreWidgets, seededRNG, shuffle, shuffleMatcher, sorterWidgetLogic as sorterLogic, splitPerseusItem, tableWidgetLogic as tableLogic, upgradeWidgetInfoToLatestVersion, usesNumCorrect, videoWidgetLogic as videoLogic };
|
|
308
322
|
//# sourceMappingURL=index.js.map
|