@khanacademy/perseus-score 4.0.2 → 5.0.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/es/index.js +4 -2
- package/dist/es/index.js.map +1 -1
- package/dist/has-empty-diner-widgets.d.ts +15 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/score.d.ts +1 -2
- package/dist/util/score-noop.d.ts +1 -1
- package/dist/validate.d.ts +1 -1
- package/dist/widgets/categorizer/score-categorizer.d.ts +1 -1
- package/dist/widgets/categorizer/validate-categorizer.d.ts +1 -1
- package/dist/widgets/cs-program/score-cs-program.d.ts +1 -1
- package/dist/widgets/dropdown/score-dropdown.d.ts +1 -1
- package/dist/widgets/dropdown/validate-dropdown.d.ts +1 -1
- package/dist/widgets/expression/score-expression.d.ts +1 -1
- package/dist/widgets/expression/validate-expression.d.ts +1 -1
- package/dist/widgets/grapher/score-grapher.d.ts +1 -1
- package/dist/widgets/group/score-group.d.ts +1 -1
- package/dist/widgets/group/validate-group.d.ts +1 -1
- package/dist/widgets/iframe/score-iframe.d.ts +1 -1
- package/dist/widgets/input-number/score-input-number.d.ts +1 -1
- package/dist/widgets/interactive-graph/score-interactive-graph.d.ts +1 -1
- package/dist/widgets/label-image/score-label-image.d.ts +1 -1
- package/dist/widgets/label-image/validate-label-image.d.ts +1 -1
- package/dist/widgets/matcher/score-matcher.d.ts +1 -1
- package/dist/widgets/matrix/score-matrix.d.ts +1 -1
- package/dist/widgets/matrix/validate-matrix.d.ts +1 -1
- package/dist/widgets/mock-widget/score-mock-widget.d.ts +1 -1
- package/dist/widgets/mock-widget/validate-mock-widget.d.ts +1 -1
- package/dist/widgets/number-line/score-number-line.d.ts +1 -1
- package/dist/widgets/number-line/validate-number-line.d.ts +1 -1
- package/dist/widgets/numeric-input/score-numeric-input.d.ts +1 -1
- package/dist/widgets/orderer/score-orderer.d.ts +1 -1
- package/dist/widgets/orderer/validate-orderer.d.ts +1 -1
- package/dist/widgets/plotter/score-plotter.d.ts +1 -1
- package/dist/widgets/plotter/validate-plotter.d.ts +1 -1
- package/dist/widgets/radio/score-radio.d.ts +1 -1
- package/dist/widgets/radio/validate-radio.d.ts +1 -1
- package/dist/widgets/sorter/score-sorter.d.ts +1 -1
- package/dist/widgets/sorter/validate-sorter.d.ts +1 -1
- package/dist/widgets/table/score-table.d.ts +1 -1
- package/dist/widgets/table/validate-table.d.ts +1 -1
- package/dist/widgets/widget-registry.d.ts +1 -1
- package/package.json +3 -3
- package/dist/validation.types.d.ts +0 -281
- package/dist/validation.typetest.d.ts +0 -1
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { PerseusItem, UserInputMap } from "@khanacademy/perseus-core";
|
|
2
|
+
/**
|
|
3
|
+
* Check the emptiness of DINER widgets (for the AX team):
|
|
4
|
+
* - Dropdown
|
|
5
|
+
* - InteractiveGraph
|
|
6
|
+
* - NumericInput
|
|
7
|
+
* - Expression
|
|
8
|
+
* - Radio
|
|
9
|
+
*
|
|
10
|
+
* @param {PerseusItem} itemData
|
|
11
|
+
* @param {UserInputMap} userInputMap
|
|
12
|
+
* @returns {boolean} true if there's an empty widget, otherwise false
|
|
13
|
+
*/
|
|
14
|
+
declare function hasEmptyDINERWidgets(itemData: PerseusItem, userInputMap: UserInputMap): boolean;
|
|
15
|
+
export default hasEmptyDINERWidgets;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
export { default as KhanAnswerTypes } from "./util/answer-types";
|
|
2
2
|
export type { Score } from "./util/answer-types";
|
|
3
3
|
export { default as ErrorCodes } from "./error-codes";
|
|
4
|
-
export type * from "./validation.types";
|
|
5
4
|
export { default as scoreCategorizer } from "./widgets/categorizer/score-categorizer";
|
|
6
5
|
export { default as validateCategorizer } from "./widgets/categorizer/validate-categorizer";
|
|
7
6
|
export { default as scoreCSProgram } from "./widgets/cs-program/score-cs-program";
|
|
@@ -32,5 +31,6 @@ export { default as validateTable } from "./widgets/table/validate-table";
|
|
|
32
31
|
export { default as scoreInputNumber, inputNumberAnswerTypes, } from "./widgets/input-number/score-input-number";
|
|
33
32
|
export { scorePerseusItem, scoreWidgetsFunctional, flattenScores } from "./score";
|
|
34
33
|
export { emptyWidgetsFunctional } from "./validate";
|
|
34
|
+
export { default as hasEmptyDINERWidgets } from "./has-empty-diner-widgets";
|
|
35
35
|
export type { PerseusMockWidgetRubric, PerseusMockWidgetUserInput, } from "./widgets/mock-widget/mock-widget-validation.types";
|
|
36
36
|
export * from "./widgets/widget-registry";
|
package/dist/index.js
CHANGED
|
@@ -80,7 +80,7 @@ function validatePlotter(userInput,validationData){if(perseusCore.approximateDee
|
|
|
80
80
|
|
|
81
81
|
function scoreRadio(userInput,rubric){const numSelected=userInput.choicesSelected.reduce((sum,selected)=>{return sum+(selected?1:0)},0);const numCorrect=rubric.choices.reduce((sum,currentChoice)=>{return currentChoice.correct?sum+1:sum},0);if(numCorrect>1&&numSelected!==numCorrect){return {type:"invalid",message:ErrorCodes.CHOOSE_CORRECT_NUM_ERROR}}const noneOfTheAboveSelected=rubric.choices.some((choice,index)=>choice.isNoneOfTheAbove&&userInput.choicesSelected[index]);if(noneOfTheAboveSelected&&numSelected>1){return {type:"invalid",message:ErrorCodes.NOT_NONE_ABOVE_ERROR}}const correct=userInput.choicesSelected.every((selected,i)=>{let isCorrect;if(rubric.choices[i].isNoneOfTheAbove){isCorrect=rubric.choices.every((choice,j)=>{return i===j||!choice.correct});}else {isCorrect=!!rubric.choices[i].correct;}return isCorrect===selected});return {type:"points",earned:correct?1:0,total:1,message:null}}
|
|
82
82
|
|
|
83
|
-
function validateRadio(userInput){
|
|
83
|
+
function validateRadio(userInput){if(!userInput.choicesSelected.includes(true)){return {type:"invalid",message:null}}return null}
|
|
84
84
|
|
|
85
85
|
function scoreSorter(userInput,rubric){const correct=perseusCore.approximateDeepEqual(userInput.options,rubric.correct);return {type:"points",earned:correct?1:0,total:1,message:null}}
|
|
86
86
|
|
|
@@ -112,12 +112,15 @@ const widgets={};function registerWidget(type,scorer,validator){widgets[type]={s
|
|
|
112
112
|
|
|
113
113
|
const noScore={type:"points",earned:0,total:0,message:null};function scoreIsEmpty(score){return score.type==="invalid"&&(!score.message||score.message.length===0)}function combineScores(scoreA,scoreB){let message;if(scoreA.type==="points"&&scoreB.type==="points"){if(scoreA.message&&scoreB.message&&scoreA.message!==scoreB.message){message=null;}else {message=scoreA.message||scoreB.message;}return {type:"points",earned:scoreA.earned+scoreB.earned,total:scoreA.total+scoreB.total,message:message}}if(scoreA.type==="points"&&scoreB.type==="invalid"){return scoreB}if(scoreA.type==="invalid"&&scoreB.type==="points"){return scoreA}if(scoreA.type==="invalid"&&scoreB.type==="invalid"){if(scoreA.message&&scoreB.message&&scoreA.message!==scoreB.message){message=null;}else {message=scoreA.message||scoreB.message;}return {type:"invalid",message:message}}throw new perseusCore.PerseusError("PerseusScore with unknown type encountered",perseusCore.Errors.InvalidInput,{metadata:{scoreA:JSON.stringify(scoreA),scoreB:JSON.stringify(scoreB)}})}function flattenScores(widgetScoreMap){return Object.values(widgetScoreMap).reduce(combineScores,noScore)}function scorePerseusItem(perseusRenderData,userInputMap,locale){const usedWidgetIds=perseusCore.getWidgetIdsFromContent(perseusRenderData.content);const scores=scoreWidgetsFunctional(perseusRenderData.widgets,usedWidgetIds,userInputMap,locale);return flattenScores(scores)}function scoreWidgetsFunctional(widgets,widgetIds,userInputMap,locale){const upgradedWidgets=perseusCore.getUpgradedWidgetOptions(widgets);const gradedWidgetIds=widgetIds.filter(id=>{const props=upgradedWidgets[id];const widgetIsGraded=props?.graded==null||props.graded;const widgetIsStatic=!!props?.static;return widgetIsGraded&&!widgetIsStatic});const widgetScores={};gradedWidgetIds.forEach(id=>{const widget=upgradedWidgets[id];if(!widget){return}const userInput=userInputMap[id];const validator=getWidgetValidator(widget.type);const scorer=getWidgetScorer(widget.type);const score=validator?.(userInput,widget.options,locale)??scorer?.(userInput,widget.options,locale);if(score!=null){widgetScores[id]=score;}});return widgetScores}
|
|
114
114
|
|
|
115
|
+
function hasEmptyDINERWidgets(itemData,userInputMap){const usedWidgetIds=perseusCore.getWidgetIdsFromContent(itemData.question.content);const widgets=itemData.question.widgets;for(const widgetId of usedWidgetIds){const widget=widgets[widgetId];const input=userInputMap[widgetId];switch(widget.type){case "dropdown":{if(input.value===0){return true}break}case "interactive-graph":{break}case "numeric-input":{if(!input.currentValue&&!widget.options.coefficient){return true}break}case "expression":{if(!input){return true}break}case "radio":{if(!input.choicesSelected.includes(true)){return true}break}}}return false}
|
|
116
|
+
|
|
115
117
|
exports.ErrorCodes = ErrorCodes;
|
|
116
118
|
exports.KhanAnswerTypes = KhanAnswerTypes;
|
|
117
119
|
exports.emptyWidgetsFunctional = emptyWidgetsFunctional;
|
|
118
120
|
exports.flattenScores = flattenScores;
|
|
119
121
|
exports.getWidgetScorer = getWidgetScorer;
|
|
120
122
|
exports.getWidgetValidator = getWidgetValidator;
|
|
123
|
+
exports.hasEmptyDINERWidgets = hasEmptyDINERWidgets;
|
|
121
124
|
exports.inputNumberAnswerTypes = inputNumberAnswerTypes;
|
|
122
125
|
exports.registerWidget = registerWidget;
|
|
123
126
|
exports.scoreCSProgram = scoreCSProgram;
|