Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Problem Statement:

  • The creator should be able to add a sub-question against the options of a question.

  • Users should be able to see the relevant question based on the response of the previous question/s.

Rules/Behaviour:

  • A Question can have more than one dependent(child) question for its different option combinations.

  • Questions with a pre-condition (i.e. pre-condition is not null or empty) will not be part of the primary sequence of the question set.

  • Source question and its targets should be members of the same question set.

Current Implementation:

  • The dependent Question feature should be enabled only for observation & survey.

  • A question can't depend upon more than one question. It means multiple questions can't point to the same question as a dependent one.

  • The dependent question will not have further dependent questions.

Example:

Q1, Q2, Q3

Q4 - pre-condition:

  • if Q1. response = x or Q1.response = y

  • if Q1.response = x and Q2.response = y

    • delete Q1: delete Q1 from hierarchy and branching logic. return “Q4 is dependent on Q1” in the response.

      • hierarchy: Q2, Q3, Q4

      • branchingLogic:

        • Q2 - target = Q4

        • Q4 - source = Q1, Q2 & pre-condition: {Q1.response = x and Q2.response = y}

  • if Q1.response = x or Q2.response = y

Solution: Dependent Question Behaviour will be achieved using metadata (branchingLogic) with Immediate Parent ( A Section or Observation/Survey) who has a dependent question

  • The Feature will be enabled/disabled for a particular category using the flag “allowBranching“ with the value “Yes/No

  • The flag allowBranching will be stored at object level schema with default to “No“ and same can be overridden for specific category at category definition level.

  • A dependent question can be added only for questions available within the immediate parent. It means we can't target question available with other parents within observation/survey hierarchy.

  • The rule (branchingLogic) will be available with the immediate parent (section or root node)

  • The branchingLogic will be stored 

    • in the hierarchy itself, if available at section/unit level. 

    • in the hierarchy & graph, if available at root level (Observation/Survey)

  • “branchingLogic“ will be added to QuestionSet object level schema as an optional property.

  • Sample value of branchingLogic is as below:

Code Block
languagenone
 {
  "branchingLogic": { // Renamed from render config
      "questionId_do_1": { // Only parent or child questions will be stored here.
        "target": [
          "questionId_do_2"
        ],
        "preCondition": {}
      },
      "questionId_do_2": {
        "target": [],
        "source/parent": ["questionId_do_1"],
        "preCondition": {
          "and": [ // Use of JSON Logic library
            {
              "eq": [ // eq, ne, lt, gt, exists, not_exists, and, or
              {
                  "var": "do_1.response1.value",
                  "type": "responseDeclaration"
              },
              "0"
              ]
            }
          ]
        }
      }
  }
}
  • target : all target question id's will be stored here. 

  • preCondition: rule or set of rules for question response assertion

  • “branchingLogic” will have entries for only those objects which have a dependent question and a dependent one.

  • Dependent Question should be added only through update hierarchy api as we need to pass additional metadata branchingLogic as well. The metadata should be passed as part of nodesModified.

    • Question with visibility Parent/Default can be added as a dependent question.

  • ES Syncing will be disabled for the field “branchingLogic” through an existing config in search-indxer job.

  • Platform will always support the replace operation for “branchingLogic”. So any partial update shouldn’t happen.

  • compatibilityLevel for observation & survey categories will be set as current + 1 . i.e: 6. So that user will be forced to update the app, when observation/survey consumption will go live.

  • When The player starts playing a survey/observation, It should start rendering using hierarchy index as well as branchingLogic.

    • Question Index needs to be handled explicitly at player end as hierarchy index may be different for question which becomes visible first. the same will be applicable for dependent question as well.

  • Solution of Progress tracking/score computation for dependent question will be designed and taken up later before consumption start.

API Enhancement:

updateHierarchy:

The api will simply store the metadata after a basic validation. The validation includes below:

  1. the do_id should exist as children within the node the metadata is getting inserted.

  2. If it has targets, those id’s entry should be present in branchingLogic as well as children array.

  3. Platform won’t validate the preCondition data.

  4. UpdateHierarchyManager.validateRequest() function will be modified and branchingLogic will be validated there.

https://github.com/project-sunbird/knowledge-platform/blob/8f579b5ca4a25feca628832ce2706d0ad25ab25c/assessment-api/qs-hierarchy-manager/src/main/scala/org/sunbird/managers/UpdateHierarchyManager.scala#L73

  1. Sample Request for adding dependent question (q2 depends on q1):

...

Problem Statement:

  • The creator should be able to add a sub-question against the options of a question.

  • Users should be able to see the relevant question based on the response of the previous question/s.

Rules/Behaviour:

  • A Question can have more than one dependent(child) question for its different option combinations.

  • Questions with a pre-condition (i.e. pre-condition is not null or empty) will not be part of the primary sequence of the question set.

  • Source question and its targets should be members of the same question set.

Current Implementation:

  • The dependent Question feature should be enabled only for observation & survey.

  • A question can't depend upon more than one question. It means multiple questions can't point to the same question as a dependent one.

  • The dependent question will not have further dependent questions.

Example:

Q1, Q2, Q3

Q4 - pre-condition:

  • if Q1. response = x or Q1.response = y

  • if Q1.response = x and Q2.response = y

    • delete Q1: delete Q1 from hierarchy and branching logic. return “Q4 is dependent on Q1” in the response.

      • hierarchy: Q2, Q3, Q4

      • branchingLogic:

        • Q2 - target = Q4

        • Q4 - source = Q1, Q2 & pre-condition: {Q1.response = x and Q2.response = y}

  • if Q1.response = x or Q2.response = y

Solution: Dependent Question Behaviour will be achieved using metadata (branchingLogic) with Immediate Parent ( A Section or Observation/Survey) who has a dependent question

  • The Feature will be enabled/disabled for a particular category using the flag “allowBranching“ with the value “Yes/No

  • The flag allowBranching will be stored at object level schema with default to “No“ and same can be overridden for specific category at category definition level.

  • A dependent question can be added only for questions available within the immediate parent. It means we can't target question available with other parents within observation/survey hierarchy.

  • The rule (branchingLogic) will be available with the immediate parent (section or root node)

  • The branchingLogic will be stored 

    • in the hierarchy itself, if available at section/unit level. 

    • in the hierarchy & graph, if available at root level (Observation/Survey)

  • “branchingLogic“ will be added to QuestionSet object level schema as an optional property.

  • Sample value of branchingLogic is as below:

Code Block
languagenone
 {
  "branchingLogic": { // Renamed from render config
      "questionId_do_1": { // Only parent or child questions will be stored here.
        "target": [
          "questionId_do_2"
        ],
        "preCondition": {}
      },
      "questionId_do_2": {
        "target": [],
        "source/parent": ["questionId_do_1"],
        "preCondition": {
          "and": [ // Use of JSON Logic library
            {
              "eq": [ // eq, ne, lt, gt, exists, not_exists, and, or
              {
                  "var": "do_1.response1.value",
                  "type": "responseDeclaration"
              },
              "0"
              ]
            }
          ]
        }
      }
  }
}
  • target : all target question id's will be stored here. 

  • preCondition: rule or set of rules for question response assertion

  • “branchingLogic” will have entries for only those objects which have a dependent question and a dependent one.

  • Dependent Question should be added only through update hierarchy api as well as addNodeToHierachy api.

    • Question with visibility Parent/Default can be added as a dependent question.

  • ES Syncing will be disabled for the field “branchingLogic” through an existing config in search-indxer job.

  • Platform will support the merge operation for “branchingLogic”. So any partial update for branchingLogic will be supported.

  • compatibilityLevel for observation & survey categories will be set as current + 1 . i.e: 6. So that user will be forced to update the app, when observation/survey consumption will go live.

  • When The player starts playing a survey/observation, It should start rendering using hierarchy index as well as branchingLogic.

    • Question Index needs to be handled explicitly at player end as hierarchy index may be different for question which becomes visible first. the same will be applicable for dependent question as well.

  • Solution of Progress tracking/score computation for dependent question will be designed and taken up later before consumption start.

API Enhancement:

updateHierarchy:

The api will simply store the metadata after a basic validation. The validation includes below:

  1. the do_id should exist as children within the node the metadata is getting inserted.

  2. If it has targets, those id’s entry should be present in branchingLogic as well as children array.

  3. Platform won’t validate the preCondition data.

  4. UpdateHierarchyManager.validateRequest() function will be modified and branchingLogic will be validated there.

https://github.com/project-sunbird/knowledge-platform/blob/8f579b5ca4a25feca628832ce2706d0ad25ab25c/assessment-api/qs-hierarchy-manager/src/main/scala/org/sunbird/managers/UpdateHierarchyManager.scala#L73

  1. Sample Request for adding dependent question (q2 depends on q1):

Code Block
{
				  "request": {
				    "data": {
				      "nodesModified": {
				                ],"section1": {
				                "preConditionisNew": {}	// this will be emptyfalse,
				              }"root": false,
				              "q2metadata": {
				            "branchingLogic": {
				  "target": [], // this will be empty 
				                 "q1": {
				           "preCondition": {}	// this will have required rule."target": [
				                  }"q2"
				                }],
				          }
				      "preCondition": {}	// this will be },empty
				        "q2": {}	// metadata for question q2      },
				       }, 				      "hierarchyq2": {
				                "survey-1target": { [], // this will be empty 
				                "namepreCondition": "survey 1",{}	// this will have required rule.
				             "primaryCategory": "Survey", }
				          "children": [  }
				          }
 "section1"
				          ]},
				          "rootq2": true {}	// metadata for question q2
				      },
				       },"hierarchy": {
				        "section1survey-1": {
				          "name": "Sectionsurvey 1",
				          "primaryCategory": "Survey",
				          "children": [
				            "q1",
				            "q2section1"
				          ],
				          "root": falsetrue
				        },
				         },"section1": {
				          "lastUpdatedByname": "5a587cc1-e018-4859-a0a8-e842650b9d64"Section 1",
				     } 				  } 				}

deleteFromHierarchy:

  • deleting a dependent question:

    • delete from hierarchy

    • delete the entry from branching logic

    • <update all the targets> - using the source

  • deleting an independent question:

    • if the question has targets, throw an error…

      • the dependent questions should be deleted first and then the delete should be triggered again

    • if there are no targets, delete the node from hierarchy

  • If a node gets deleted from hierarchy through this api, platform will first check if its parent has branchingLogic meta, if yes, further check the node entry in branchingLogic, if entry found, there are two possible behaviour:

  • 1st Behaviour:

    • if target of the requested node is not empty, delete all target ids from hierarchy as well as from branchingLogic first and then delete the requested node.

    • if target is empty, scan the identifier in other entries of branchingLogic and update the target, then delete the requested node from hierarchy and remove the entry from branchingLogic

  • 2nd Behaviour:

    • If the target is not empty, throw client error with target ids because it has a dependent question. So in this case, the user should remove the dependent question first and update the branchingLogic of the parent question and then delete the parent one.

    • If the target is empty but preCondition is not empty, it will delete the node from the hierarchy and remove the entry from branchingLogic.

...

 "primaryCategory": "Survey",
				          "children": [
				            "q1",
				            "q2"
				          ],
				          "root": false
				        }
				      },
				      "lastUpdatedBy": "5a587cc1-e018-4859-a0a8-e842650b9d64"
				    }
				  }
				}

deleteFromHierarchy:

  • deleting a dependent question:

    • delete from hierarchy

    • <update all the targets> - using the source property

    • delete the entry of the question from branching logic

  • deleting an independent question:

    • if the question has targets, throw an error…

      • the dependent questions should be deleted first and then the delete should be triggered again

    • if there are no targets, delete the node from hierarchy, remove the entry from branchingLogic

  • HierarchyManager.removeLeafNodesFromHierarchy() function will be modified.

https://github.com/project-sunbird/knowledge-platform/blob/8f579b5ca4a25feca628832ce2706d0ad25ab25c/assessment-api/qs-hierarchy-manager/src/main/scala/org/sunbird/managers/HierarchyManager.scala#L96


addNodeToHierachy:

  • The api won’t be used for will support dependent question feature. All children added through this api will be treated as independent object. So no code change is required.. “branchingLogic“ can be passed as an optional data.

  • The Request will be as below:

  • input:

    • identifier of the question

    • branching for this node

      • source & pre-condition: source must already exist within the question set

  • TODO: add Platform will support for atomic operations to add/remove dependent questions

  • The api version won’t be upgraded as branchingLogic is an optional input and backward compatibility won’t break.

questionset-publish flink job:

...