From c26c2b55223be9123247e66009414fe438ab95a2 Mon Sep 17 00:00:00 2001 From: Kumar Gauraw Date: Wed, 28 Jun 2023 20:26:08 +0530 Subject: [PATCH] Issue #9 feat: added quml 1.1 spec --- v1.1/question-schema.json | 535 ++++++++++++++++++++++++++++++++++ v1.1/question-set-schema.json | 370 +++++++++++++++++++++++ 2 files changed, 905 insertions(+) create mode 100644 v1.1/question-schema.json create mode 100644 v1.1/question-set-schema.json diff --git a/v1.1/question-schema.json b/v1.1/question-schema.json new file mode 100644 index 0000000..f89b6a1 --- /dev/null +++ b/v1.1/question-schema.json @@ -0,0 +1,535 @@ +{ + "$id": "https://github.com/sunbird-specs/inQuiry/blob/master/v1/question-schema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Question", + "type": "object", + "required": ["body"], + "properties": { + "body": { + "description": "Body contains the text, graphics, media objects and interactions that describe the question’s content.", + "oneOf": [ + { + "type": "string", + "description": "Question body as HTML string when the question is used in only one language." + }, + { "$ref": "#/definitions/i18nData" } + ] + }, + "answer": { + "description": "answer contains the text, graphics, media objects that describe the question’s content.", + "oneOf": [ + { + "type": "string", + "description": "Answer as HTML string when the answer is used in only one language." + }, + { + "$ref": "#/definitions/i18nData" + } + ] + }, + "instructions": { + "description": "Instructions on how to understand, attempt or how the question will be evaluated.", + "oneOf": [ + { + "type": "string", + "description": "Instructions as HTML string when the question is used in only one language." + }, + { "$ref": "#/definitions/i18nData" } + ] + }, + "feedback": { + "description": "Feedback shown to the students after response processing.", + "type": "object", + "additionalProperties": { + "oneOf": [ + { + "type": "string" + }, + { "$ref": "#/definitions/i18nData" } + ] + } + + }, + "hints": { + "description": "Hints are shown to the students after response processing or when the student requests for hints.", + "type": "object", + "additionalProperties": { + "oneOf": [ + { + "type": "string" + }, + { "$ref": "#/definitions/i18nData" } + ] + } + }, + "solutions": { + "description": "Solutions to the question.", + "type": "object", + "additionalProperties": { + "oneOf": [ + { + "type": "string" + }, + { "$ref": "#/definitions/i18nData" } + ] + } + }, + "media": { + "type": "array", + "items": { "$ref": "#/definitions/media" }, + "description": "List of media used in the question" + }, + "responseDeclaration": { + "description": "Information about answer to the question, when it is correct and optionally, how it is scored.", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/responseVariableDef" + } + }, + "outcomeDeclaration": { + "description": "Information about the outcome variables of the question, i.e the values that are output of a question session.", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/outcomeVariableDef" + } + }, + "templateDeclaration": { + "description": "Declaration of template variables that are to used for the purposes of cloning questions, i.e. auto-generating different sets of values for variables in the question.", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/templateVariableDef" + } + + }, + "templateProcessing": { + "description": "One or more template rules to assign values to the template variables.", + "type": "object", + "additionalProperties": { "$ref": "#/definitions/templateProcessingDef" } + }, + "responseProcessing": { + "description": "Rules to assign values to outcome variables based on the student's reponses.", + "type": "object", + "oneOf": [ + { + "required": ["eval"], + "properties": { + "eval": { + "type": "string", + "description": "Custom response processing logic using javascript." + } + }, + "$comment": "custom 'eval' data is mandatory if response processing templates are not used for the question." + }, + { + "required": ["template"], + "properties": { + "template": { + "enum": ["MATCH_CORRECT", "MAP_RESPONSE", "MATCH_TEMPLATE"] + }, + "mappingConfig": { + "type": "array", + "items": {"$ref": "#/definitions/mappingConfigDef"} + }, + "matchTemplateConfig": { + "type": "array", + "items": {"$ref": "#/definitions/matchTemplateConfigDef"} + } + }, + "allOf": [ + { + "if": { "properties": {"template": {"const": "MAP_RESPONSE"}} }, + "then": {"required": ["mappingConfig"]} + }, + { + "if": { "properties": {"template": {"const": "MATCH_TEMPLATE"}} }, + "then": {"required": ["matchTemplateConfig"]} + } + ] + } + ] + }, + "complexityLevel": { + "type": "array", + "enum": [""], + "description": "Cognitive processes involved to answer the question." + }, + "showHints": { + "type": "boolean", + "description": "Configuration to enable/disable hints for the student while using the question set." + }, + "showFeedback": { + "type": "boolean", + "description": "Configuration to enable/disable feedback for the student while using the question set." + }, + "showSolutions": { + "type": "boolean", + "description": "Configuration to enable/disable solutions for the student while using the question set." + }, + "qlevel": { + "type": "array", + "enum": ["EASY", "MEDIUM", "HARD"], + "description": "Difficulty level of the question." + }, + "purpose": { + "type": "string", + "enum": ["recall", "explore", "sense", "assess", "teach", "revise"], + "description": "Purpose served by the question." + }, + "expectedDuration": { + "type": "number", + "description": "Expected time for one attempt of the question." + }, + "maxScore": { + "type": "number", + "description": "Maximum score that can be awarded for the question." + }, + "type": { + "type": "string", + "description": "One of the standard question types - mcq, mtf, ftb, mmcq, essay, short answers, programming, other. this can be auto-derived based on the interactions used in the question." + }, + "visibility": { + "type": "string", + "enum": ["public", "private"], + "description": "If the question is visible for all or only for those who created it and/or for some specific systems or use cases." + }, + "isTemplate": { + "type": "boolean", + "description": "Set to true if question data has template variables and template processing, else it is set to false." + }, + "interactions": { + "type": "array", + "items": {"type": "string"}, + "description": "List of interactions present in the question." + }, + "solutionAvailable": { + "type": "boolean", + "description": "true, if question data has solutions, else, set to false" + }, + "scoringMode": { + "type": "string", + "enum": ["responseProcessing", "offline", "external"], + "description": "One of the values: responseProcessing (if question has inbuild response processing), offline (if scoring will be done offline and/or manually) or external (if an external system does the evaluation and submit the score)." + }, + "qumlVersion": { + "type": "number", + "const": 1.1, + "description": "Version of the QuML specification using which the question is created." + }, + "totalTimeSpent": { + "type": "number", + "description": "Total cumulative time spent, in milliseconds, on the question by all users." + }, + "avgTimeSpent": { + "type": "number", + "description": "Average time spent per attempt, in milliseconds." + }, + "numAttempts": { + "type": "number", + "description": "total number of attempts." + }, + "numCorrectAttempts": { + "type": "number", + "description": "Number of attempts where the user response is correct." + }, + "numInCorrectAttempts": { + "type": "number", + "description": "Number of attempts where the user response is in-correct." + }, + "numSkips": { + "type": "number", + "description": "Total number of attempts where the user did not give a response." + }, + "avgRating": { + "type": "number", + "description": "Average rating of the question." + }, + "totalRatings": { + "type": "number", + "description": "Total number of ratings given for the question." + } + }, + "additionalProperties": true, + "definitions": { + "cardinality": { + "enum": ["single", "multiple", "ordered"] + }, + "type": { + "enum": ["string", "integer", "float", "boolean", "map", "uri", "points", "coordinate"] + }, + "coordinate": { + "type": "object", + "required": ["x", "y"], + "properties": { + "x": {"type": "number"}, + "y": {"type": "number"} + }, + "additionalProperties": false + }, + "points": { + "type": "object", + "required": ["shape", "coordinates"], + "properties": { + "shape": {"enum": ["point", "circle", "ellipse", "poly", "rect"]}, + "coordinates": { + "type": "array", + "items": { "$ref": "#/definitions/coordinate" } + } + }, + "additionalProperties": false + }, + "media": { + "type": "object", + "required": ["id", "type", "src"], + "properties": { + "id": { + "type": "string" + }, + "mimeType": { + "type": "string" + }, + "type": { + "enum": ["application", "audio", "font", "example", "image", "message", "model", "multipart", "text", "video"] + }, + "src": { + "type": "string" + }, + "baseUrl": { + "type": "string" + } + }, + "additionalProperties": true + }, + "anyTypeDef": { + "oneOf": [ + {"type": ["string", "number", "integer", "boolean", "object", "array"]}, + {"$ref": "#/definitions/points"}, + {"$ref": "#/definitions/media"} + ] + }, + "i18nData": { + "type": "object", + "description": "i18n data in map format, where key is the ISO language code and value is string data in the the specified language.", + "additionalProperties": { + "type": "string" + } + }, + "responseVariableDef": { + "type": "object", + "required": ["cardinality", "type"], + "properties": { + "cardinality": {"$ref": "#/definitions/cardinality"}, + "type": {"$ref": "#/definitions/type"}, + "correctResponse": {"$ref": "#/definitions/correctResponseDef"}, + "mapping": { + "type": "array", + "items": {"$ref": "#/definitions/mappingDef"} + }, + "areaMapping": {"$ref": "#/definitions/areaMappingDef"} + }, + "additionalProperties": false + }, + "correctResponseDef": { + "type": "object", + "required": ["value"], + "properties": { + "value": { + "$ref": "#/definitions/anyTypeDef" + } + }, + "additionalProperties": false + }, + "mappingDef": { + "type": "object", + "required": ["value", "score"], + "properties": { + "value": {"$ref": "#/definitions/anyTypeDef"}, + "score": {"type": "number"}, + "caseSensitive": {"type": "boolean", "default": false} + }, + "additionalProperties": false + }, + "areaMappingDef": { + "type": "object", + "required": ["key", "value"], + "properties": { + "key": {"$ref": "#/definitions/points"}, + "value": {"type": "number"} + }, + "additionalProperties": false + }, + "outcomeVariableDef": { + "type": "object", + "required": ["cardinality", "type"], + "properties": { + "cardinality": {"$ref": "#/definitions/cardinality"}, + "type": {"$ref": "#/definitions/type"}, + "defaultValue": {"$ref": "#/definitions/anyTypeDef"}, + "range": { + "type": "array", + "items": {"$ref": "#/definitions/anyTypeDef"} + } + }, + "additionalProperties": false + }, + "templateVariableDef": { + "type": "object", + "required": ["cardinality", "type"], + "properties": { + "cardinality": {"$ref": "#/definitions/cardinality"}, + "type": {"$ref": "#/definitions/type"}, + "defaultValue": {"$ref": "#/definitions/anyTypeDef"} + }, + "additionalProperties": false + }, + "templateProcessingDef": { + "type": "array", + "items": { + "$ref": "#/definitions/templateProcessingRuleDef" + }, + "minItems": 1 + }, + "templateProcessingRuleDef": { + "type": "object", + "oneOf": [ + { + "properties": { + "random": {"$ref": "#/definitions/randomVariableDef"}, + "language": {"type": "string", "description": "ISO Language code"} + } + }, + { + "properties": { + "regex": {"type": "string"}, + "language": {"type": "string", "description": "ISO Language code"} + } + }, + { + "properties": { + "eval": {"type": "string"}, + "language": {"type": "string", "description": "ISO Language code"} + } + } + ], + "additionalProperties": false + }, + "randomVariableDef": { + "type": "object", + "oneOf": [ + { + "properties": { + "list": { + "type": "array", + "items": {"$ref": "#/definitions/anyTypeDef"} + } + } + }, + { + "properties": { + "number": {"$ref": "#/definitions/randomNumberDef"} + } + } + ], + "additionalProperties": false + }, + "randomNumberDef": { + "type": "object", + "required": ["type", "min", "max"], + "oneOf": [ + { + "properties": { + "type": {"enum": ["integer"]}, + "min": {"type": "integer"}, + "max": {"type": "integer"}, + "step": {"type": "integer"} + } + }, + { + "properties": { + "type": {"enum": ["float"]}, + "min": {"type": "number"}, + "max": {"type": "number"}, + "step": {"type": "number"} + } + } + ], + "additionalProperties": false + }, + "mappingConfigDef": { + "type": "object", + "properties": { + "SCORE": { + "type": "object", + "oneOf": [ + { + "patternProperties": { + "^[g,l]e$": { "type": "number"}, + "^[g,l]t$": { "type": "number"}, + "^eq$": { "type": "number"}, + "^in$": { "type": "array", "items": {"type": "number"}} + }, + "$comment": "Define the SCORE range using the operators: le (less than or equal to), lt (less than), eq (equals to), ge (greater than or equals to), gt (greater than) and in (in a list of values). e.g.: {“lt”: 1.0}." + }, + { + "required": ["regex"], + "properties": { + "regex": { "type": "string", "format": "regex" } + }, + "$comment": "Alternatively, a regex expression can also be used to define the SCORE range." + } + ], + "additionalProperties": false + }, + "outcomeVariables": { + "type": "object", + "description": "List of outcome variables, defined in outcomeDeclaration, and the values to be set for them when the computed SCORE falls in the defined range.", + "additionalProperties": { + "$ref": "#/definitions/anyTypeDef" + } + } + }, + "additionalProperties": false + }, + "matchTemplateConfigDef": { + "type": "object", + "required": ["mapping", "SCORE"], + "properties": { + "mapping": { + "type": "object", + "$comment": "A list of mapping conditions can be configured for reach response variable.", + "additionalProperties": { + "type": "array", + "items": { + "$ref": "#/definitions/responseMappingDef" + }, + "minItems": 1, + "$comment": "AND operation is applied between multiple conditions of a response variable." + } + }, + "SCORE": { + "type": "number", + "description": "SCORE value to be set when the specified mapping resolves to be true." + } + } + }, + "responseMappingDef": { + "type": "object", + "required": ["operator", "templateVariables"], + "properties": { + "operator": { + "type": "string", + "enum": ["lt", "le", "eq", "ge", "gt", "in"], + "description": "Operators: le (less than or equal to), lt (less than), eq (equals to), ge (greater than or equals to), gt (greater than) and in (in a list of values)." + }, + "templateVariables": { + "type": "array", + "items": { + "type": "string" + }, + "minItems": 1, + "description": "One or more template variables can be specified for each operator. If more than one template variable is provided, an OR condition will be applied." + } + } + } + } + } + \ No newline at end of file diff --git a/v1.1/question-set-schema.json b/v1.1/question-set-schema.json new file mode 100644 index 0000000..a2aff0d --- /dev/null +++ b/v1.1/question-set-schema.json @@ -0,0 +1,370 @@ +{ + "$id": "https://github.com/sunbird-specs/inQuiry/blob/master/v1/question-set-schema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "QuestionSet", + "type": "object", + "required": [], + "properties": { + "instructions": { + "description": "Instructions on how to understand, attempt or how the question set will be evaluated.", + "oneOf": [ + { + "type": "string", + "description": "Instructions as HTML string when the question set is used in only one language." + }, + { "$ref": "#/definitions/i18nData" } + ] + }, + "feedback": { + "description": "Feedback shown to the students after outcome processing.", + "type": "object", + "additionalProperties": { + "oneOf": [ + { + "type": "string" + }, + { "$ref": "#/definitions/i18nData" } + ] + } + }, + "hints": { + "description": "Hints are shown to the students after outcome processing or when the student requests for hints.", + "type": "object", + "additionalProperties": { + "oneOf": [ + { + "type": "string" + }, + { "$ref": "#/definitions/i18nData" } + ] + } + }, + "navigationMode": { + "type": "string", + "enum": ["linear", "non-linear"], + "description": "Determines the general paths that the student may take during the test session. Applicable only when questions data is present." + }, + "timeLimits": { + "type": "object", + "description": "Time limits for the complete set and/or for each question in the question set.", + "properties": { + "questionSet": { "$ref": "#/definitions/timeRange" }, + "question": { "$ref": "#/definitions/timeRange" } + } + }, + "showHints": { + "type": "boolean", + "description": "Configuration to enable/disable hints for the student while using the question set." + }, + "showFeedback": { + "type": "boolean", + "description": "Configuration to enable/disable feedback for the student while using the question set." + }, + "showSolutions": { + "type": "boolean", + "description": "Configuration to enable/disable solutions for the student while using the question set." + }, + "questions": { + "type": "object", + "description": "Questions associated with the question set. This property is mutually exclusive with questionSets property.", + "required": ["shuffle", "totalQuestions", "maxQuestions", "list"], + "properties": { + "shuffle": { + "type": "boolean", + "default": false + }, + "totalQuestions": { "type": "integer" }, + "maxQuestions": { "type": "integer" }, + "list": { + "type": "array", + "items": { "type": "string" }, + "description": "List of question identifiers that are added to the question set." + } + } + }, + "questionSets": { + "type": "array", + "description": "Question Sets associated with the current set.", + "items": { "$ref": "#/definitions/questionSetDef" } + }, + "outcomeDeclaration": { + "description": "Information about the outcome variables of the question set, i.e the values that are output of a question set session.", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/outcomeVariableDef" + } + }, + "outcomeProcessing": { + "description": "Rules to assign values to outcome variables based on the student's reponses.", + "type": "object", + "oneOf": [ + { + "required": ["eval"], + "properties": { + "eval": { + "type": "string", + "description": "Custom response processing logic using javascript." + } + }, + "$comment": "custom 'eval' data is mandatory if outcome processing templates are not used for the question set." + }, + { + "required": ["template"], + "properties": { + "template": { + "enum": ["SUM_OF_SCORES", "AVG_OF_SCORES", "WEIGHTED_AVG_OF_SCORES"] + }, + "ignoreNullValues": { + "type": "boolean", + "default": false + }, + "weightageConfig": { + "type": "object", + "additionalProperties": { "type": "number" }, + "description": "Weightages for questions or question sets when WEIGHTED_AVG_OF_SCORES template is used. If not provided, same weightage is given to all." + }, + "mappingConfig": { + "type": "array", + "items": {"$ref": "#/definitions/mappingConfigDef"}, + "description": "Configuration to set additional outcome variables (other than SCORE)." + } + } + } + ] + }, + "questionSetType": { + "type": "string", + "enum": ["materialized", "dynamic"], + "description": "A question set can be comprised of a materialized list of questions, or can also be dynamically built at runtime by using a criteria to select member questions." + }, + "criteria": { + "type": "object", + "additionalProperties": { "$ref": "#/definitions/anyTypeDef" }, + "description": "Criteria to be used when the set type is dynamic." + }, + "usedFor": { + "type": "string", + "enum": ["practice", "exam"] + }, + "purpose": { + "type": "string", + "enum": ["recall", "explore", "sense", "assess", "teach", "revise"], + "description": "Purpose served by the question." + }, + "visibility": { + "type": "string", + "enum": ["public", "private", "parent"], + "description": "Visibility of the question set." + }, + "qumlVersion": { + "type": "number", + "const": 1.1, + "description": "Version of the QuML specification using which the question set is created." + } + }, + "additionalProperties": true, + "oneOf": [ + { + "type": "object", + "required": [ "questions" ] + }, + { + "type": "object", + "required": [ "questionSets" ] + } + ], + "definitions": { + "cardinality": { + "enum": ["single", "multiple", "ordered"] + }, + "type": { + "enum": ["string", "integer", "float", "boolean", "map", "uri", "points", "coordinate"] + }, + "coordinate": { + "type": "object", + "required": ["x", "y"], + "properties": { + "x": {"type": "number"}, + "y": {"type": "number"} + }, + "additionalProperties": false + }, + "points": { + "type": "object", + "required": ["shape", "coordinates"], + "properties": { + "shape": {"enum": ["point", "circle", "ellipse", "poly", "rect"]}, + "coordinates": { + "type": "array", + "items": { "$ref": "#/definitions/coordinate" } + } + }, + "additionalProperties": false + }, + "anyTypeDef": { + "oneOf": [ + {"type": ["string", "number", "integer", "boolean", "object", "array"]}, + {"$ref": "#/definitions/points"}, + {"$ref": "#/definitions/media"} + ] + }, + "i18nData": { + "type": "object", + "description": "i18n data in map format, where key is the ISO language code and value is string data in the the specified language.", + "additionalProperties": { + "type": "string" + } + }, + "timeRange": { + "type": "object", + "required": ["min", "max"], + "properties": { + "min": { "type": "number" }, + "max": { "type": "number" } + }, + "additionalProperties": false + }, + "questionSetDef": { + "type": "object", + "required": ["questionSetId"], + "properties": { + "questionSetId": { + "type": "string", + "description": "Identifier of the member question set." + }, + "shuffle": { + "type": "boolean", + "default": false, + "description": "If questions in the member question set should be shuffled or not when presented to the student." + }, + "totalQuestions": { + "type": "integer", + "description": "Total number of questions in the member question set. applicable only if the member question set has questions." + }, + "maxQuestions": { + "type": "integer", + "description": "Number of questions in the member question set that should be used in one session. applicable only if the member question set has questions." + }, + "preConditions": { + "type": "array", + "description": "Conditions to be validated before rendering the question set. generally depends on the outcomes of question sets presented earlier in the session.", + "items": { "$ref": "#/definitions/preConditionDef" } + }, + "branchRules": { + "type": "array", + "description": "Evaluated after question set is complete and jumps forward to the specified target.", + "items": { "$ref": "#/definitions/branchRuleDef" } + } + }, + "additionalProperties": false + }, + "preConditionDef": { + "type": "object", + "required": ["questionSetId", "match"], + "properties": { + "questionSetId": { + "type": "string", + "description": "Identifier of the question set whose outcome will be used to do the precondition check." + }, + "match": { + "type": "array", + "items": { "$ref": "#/definitions/outcomeMatchDef" } + } + }, + "additionalProperties": false + }, + "outcomeMatchDef": { + "type": "object", + "required": ["outcomeVariable", "operator", "value"], + "properties": { + "outcomeVariable": { "type": "string" }, + "operator": { + "type": "string", + "enum": ["lt", "le", "eq", "ge", "gt", "in"] + }, + "value": { + "type": ["string", "number", "integer", "boolean", "array", "object"] + } + }, + "additionalProperties": false + }, + "branchRuleDef": { + "type": "object", + "required": ["match", "target"], + "properties": { + "match": { + "type": "array", + "items": { "$ref": "#/definitions/outcomeMatchDef" } + }, + "target": { + "type": "object", + "oneOf": [ + { + "required": ["questionSetId"], + "properties": { + "questionSetId": {"type": "string"} + } + }, + { + "required": ["exit"], + "properties": { + "exit": {"type": "boolean", "const": true} + } + } + ] + } + }, + "additionalProperties": false + }, + "outcomeVariableDef": { + "type": "object", + "required": ["cardinality", "type"], + "properties": { + "cardinality": {"$ref": "#/definitions/cardinality"}, + "type": {"$ref": "#/definitions/type"}, + "defaultValue": {"$ref": "#/definitions/anyTypeDef"}, + "range": { + "type": "array", + "items": {"$ref": "#/definitions/anyTypeDef"} + } + }, + "additionalProperties": false + }, + "mappingConfigDef": { + "type": "object", + "properties": { + "SCORE": { + "type": "object", + "oneOf": [ + { + "patternProperties": { + "^[g,l]e$": { "type": "number"}, + "^[g,l]t$": { "type": "number"}, + "^eq$": { "type": "number"}, + "^in$": { "type": "array", "items": {"type": "number"}} + }, + "$comment": "Define the SCORE range using the operators: le (less than or equal to), lt (less than), eq (equals to), ge (greater than or equals to), gt (greater than) and in (in a list of values). e.g.: {“lt”: 1.0}." + }, + { + "required": ["regex"], + "properties": { + "regex": { "type": "string", "format": "regex" } + }, + "$comment": "Alternatively, a regex expression can also be used to define the SCORE range." + } + ], + "additionalProperties": false + }, + "outcomeVariables": { + "type": "object", + "description": "List of outcome variables, defined in outcomeDeclaration, and the values to be set for them when the computed SCORE falls in the defined range.", + "additionalProperties": { + "$ref": "#/definitions/anyTypeDef" + } + } + }, + "additionalProperties": false + } + } + } + \ No newline at end of file