Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 67 Next »

Definition

For OGHR, Platform needs to enable user to undertake exams. Platform should be capable of processing the user responses and evaluate these responses with relevant applicable scores. Outcome of this design should enable the platform users to take up examination with server side evaluation of results.


Background

In the present system, Question Set consist of following :

Assessment User : Active seeker of Assessment in the platform.

QuML Player : QuML Player has capability to play the questions in QuML format. It also has capability to locally validate the user input. Response Validation,Score Computing is completely handled in player. Once User Submits the overall response, client validated scores and response are updated using Content State Update API.

Flink Jobs : Flink Jobs aggregates the content state using Collection Activity Aggregator, Collection Assessment Aggregator, Cert Pre-processor, Cert Generator jobs.

Objective Types:

a) MCQ (Multiple Choice Questions)

b) MSQ (Multiple Select Questions)

c) MTF (Match The Following)

d) FTB (Fill in The Blanks)

Subjective Types

a) VSA - (Very Short Answer)

b) SA - (Short Answer)

c) LA - (Long Answer)

Building Blocks :

Building Blocks

API

Flink Jobs

Sunbird InQuiry

Question Set Hierarchy API

Question List Read API

QuestionSet Create API

Question Create API

Sunbird Lern

Content State Read

Collection Activity Aggregate

Content State Update

Collection Assessment Aggregate

Enrollment List API

Cert Pre Processer

Cert Generator

Sunbird RC

Cert Registry Download API


Design Problems :

  • Allow the response processing of question to be done on server rather than client as happening today.

  • Scalable Response Processing Solution for Question Sets.

  • Score Calculation Based on Content State Update need to be shifted to server side evaluation.

  • Solution to the question needs to be masqueraded or excluded from the Question Read API/ Question List API.

  • Response Processing can happen in two ways:

    • Entire Question Set Response Processing

    • Question by Question Response Processing


Current Workflow


Solution Proposed

Proposed System:

Technical Design Details:

Step 1 : “serverEvaluable“ attribute at question and questionSet Object

A new attribute in QuestionSet to be introduced to have evaluated response on server. (“serverEvaluable“).

//Question Set Object
"questionSet": {
  "serverEvaluable": true //#true for Server Side Valuation Default:#false for client side validation
}
//Question Object
"question" : {
  "serverEvaluable": true
}

Question Create API:
It is possible to permanently mark the question to be “serverEvaluable“ in nature. Any serverEvaluable question would automatically qualify for serverEvaluable question Set. These Questions can be part of Evaluable QuestionSet only.

KeySet (Futuristic):

Any Responses on Question Set can be persisted separately to ensure the keyset can be used for administrative purposes.

There are two modes of accessing questionSet as per design:
a) non-evaluable mode : Player invokes questionSetHierarchy GET API.

b) evaluable mode : Player would invoke questionSetHierarchy POST API (New API). This change would be used to manage requirements like Question Randomization, Question Token generation etc.

Step 2: Introduce new POST method for QuestionSet Hierarchy API.Enable QuestionSetToken in Question Set Hierarchy API (New API). Mark Question and QuestionSet Objects as “serverEvaluable“

QuestionSet Hierarchy API (POST) : A new API method to be introduced for QuestionSet Hierarchy of Exam Question Sets. This API will have payload as follows

"request": {
  "contentID": "",
  "collectionID": "", 
  "userID": "",
  "attemptID": "" 
  }

Every QuestionSet Hierarchy will attach “QuestionSetToken“ based on encrypted value of user-id, content-id, collection-id,attempt-id+selected_questionid_list recieved as part of hierarchy payload. This token will further be used to validate the request during response processing on server.

"questionSet": {
  "timeLimits": "{\"maxTime\":\"3600\"}",
  "questionSetToken": "", //#Question Set token to be generated at hierarchy read API with combination of "Question Set ID + userID"
  "serverEvaluable": true //#true for Server Side Valuation Default:#false for client side validation
}

QuestionSetToken : This key is almost equivalent of jwt token created as follows:

“questionSetToken“ = > {
"contentID": "",
"collectionID": "",
"userID": "",
"attemptID": "",
“questionList“: [“<do-id-1>“,”<do-id-2>”,…..”<do-id-n>”]
}

Step 2: Trim Off correctResponse from Question List API

Question Read API : Any Question Associated with serverEvaluable behaviour to trim off response declaration from Question Set.

"serverEvaluable": true,
"responseDeclaration": {
          "response1": {
            "maxScore": 1,
            "cardinality": "single",
            "type": "integer",
            -- To be Trimmed off ----
            "correctResponse": {
              "value": "0",
              "outcomes": {
                "SCORE": 1
              }
            },
            -- To be Trimmed off --
           
          }
        },

There are multiple attributes which persists correct answer in QuML

a) responseDeclaration: (Shown above)

b) answer

c) editorState

Step 3: Introduce QuestionReponseValidate API to process user responses to QuestionSet.

QuestionResponseValidateAPI (Async API Behaviour):

QuestionSetToken generated in Hierarchy is sent as part of this request. This token will ensure the user’s attempt against questionSetID on a collection.

API accepts the request payload similar to content state update API.

{
  "request": {
    "userId": "843a9940-720f-43ed-a415-26bbfd3da9ef",
    "questionSetToken": "",
    "assessments":[
      {
        "assessmentTs": 1681284869464,
        "batchId": "0132677340746629120",
        "collectionId": "do_213267731619962880127",
        "userId": "843a9940-720f-43ed-a415-26bbfd3da9ef",
        "attemptId": "5486724f41afb4997118e6d97695684f",
        "contentId": "do_2129959063404544001107"
        },
        "events":[],
        responses:[{
          "identifier":"<question-id>",
          "questionType": "",
          "userResponse":[""]
        }]
      }],
    "contents": [
      {
        "contentId": "do_2132671468826214401203",
        "batchId": "0132677340746629120",
        "status": 2,
        "courseId": "do_213267731619962880127",
        "lastAccessTime": "2023-04-12 12:56:45:687+0530"
      },
      
    ]
  }
}

The Above payload mimics ContentStateUpdate API to mimic responses as above.

 Reference Call for Content State Update
curl 'https://staging.sunbirded.org/content/course/v1/content/state/update' \
  -X 'PATCH' \
  -H 'Accept: application/json' \
  -H 'Accept-Language: en-GB,en-US;q=0.9,en;q=0.8' \
  -H 'Connection: keep-alive' \
  -H 'Content-Type: application/json' \
  -H 'Cookie: connect.sid=s%3Ahiv7abkP2ptQEspxLosgzBh_WeQAMcyt.Xx9l7ib6kHeMr131BvH4SHBzcXlcenr6BwIMAe1%2FVzo' \
  -H 'Origin: https://staging.sunbirded.org' \
  -H 'Referer: https://staging.sunbirded.org/learn/course/play/do_213267732169023488128?batchId=0132677340746629120&courseId=do_213267731619962880127&courseName=April%20course%203.9&selectedContent=do_2129959063404544001107' \
  -H 'Sec-Fetch-Dest: empty' \
  -H 'Sec-Fetch-Mode: cors' \
  -H 'Sec-Fetch-Site: same-origin' \
  -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36' \
  -H 'X-App-Id: staging.sunbird.portal' \
  -H 'X-App-Version: 5.2.0' \
  -H 'X-Channel-Id: 0126796199493140480' \
  -H 'X-Device-ID: dfab80b18d8ce5d4df8159ba05dde951' \
  -H 'X-Org-code: 0126796199493140480' \
  -H 'X-Request-ID: 0d460871-be9d-adf1-f7ab-aac64d1eaff7' \
  -H 'X-Session-ID: hiv7abkP2ptQEspxLosgzBh_WeQAMcyt' \
  -H 'X-Source: web' \
  -H 'X-User-ID: 843a9940-720f-43ed-a415-26bbfd3da9ef' \
  -H 'X-msgid: 0d460871-be9d-adf1-f7ab-aac64d1eaff7' \
  -H 'sec-ch-ua: "Chromium";v="112", "Google Chrome";v="112", "Not:A-Brand";v="99"' \
  -H 'sec-ch-ua-mobile: ?0' \
  -H 'sec-ch-ua-platform: "macOS"' \
  -H 'ts: 2023-04-12T13:05:05+05:30' \
  --data-raw '{"request":{"userId":"843a9940-720f-43ed-a415-26bbfd3da9ef","contents":[{"contentId":"do_2129959063404544001107","batchId":"0132677340746629120","status":2,"courseId":"do_213267731619962880127","lastAccessTime":"2023-04-12 13:05:05:524+0530"}],"assessments":[{"assessmentTs":1681284869464,"batchId":"0132677340746629120","courseId":"do_213267731619962880127","userId":"843a9940-720f-43ed-a415-26bbfd3da9ef","attemptId":"5486724f41afb4997118e6d97695684f","contentId":"do_2129959063404544001107","events":[{"eid":"ASSESS","ets":1681284888762,"ver":"3.1","mid":"ASSESS:67cf520cf4d9a29473844c19c3c3813d","actor":{"id":"843a9940-720f-43ed-a415-26bbfd3da9ef","type":"User"},"context":{"channel":"0126796199493140480","pdata":{"id":"staging.sunbird.portal","ver":"5.2.0","pid":"sunbird-portal.contentplayer"},"env":"contentplayer","sid":"hiv7abkP2ptQEspxLosgzBh_WeQAMcyt","did":"dfab80b18d8ce5d4df8159ba05dde951","cdata":[{"id":"do_213267732169023488128","type":"course"},{"type":"batch","id":"0132677340746629120"},{"id":"af588b6a747b6b3d28bea6d947dfbc49","type":"ContentSession"},{"id":"1a20fb335ff8dada7802d4473fe1a55e","type":"PlaySession"}],"rollup":{"l1":"0126796199493140480"}},"object":{"id":"do_2129959063404544001107","type":"Content","ver":"2","rollup":{"l1":"do_213267732169023488128","l2":"do_2129959063404544001107"}},"tags":["0126796199493140480"],"edata":{"item":{"id":"do_21299582901864857613016","maxscore":1,"type":"ftb","exlength":0,"params":[{"1":"{\"text\":\"\"}"},{"2":"{\"text\":\"\"}"},{"3":"{\"text\":\"\"}"},{"eval":"order"}],"uri":"","title":"Registration","mmc":[],"mc":[],"desc":""},"index":1,"pass":"No","score":0,"resvalues":[{"1":"{\"text\":\"Sharath\"}"},{"2":"{\"text\":\"10\"}"},{"3":"{\"text\":\"CSE\"}"}],"duration":16}},{"eid":"ASSESS","ets":1681284892463,"ver":"3.1","mid":"ASSESS:e57069e81c8e561915b20de23969e7ab","actor":{"id":"843a9940-720f-43ed-a415-26bbfd3da9ef","type":"User"},"context":{"channel":"0126796199493140480","pdata":{"id":"staging.sunbird.portal","ver":"5.2.0","pid":"sunbird-portal.contentplayer"},"env":"contentplayer","sid":"hiv7abkP2ptQEspxLosgzBh_WeQAMcyt","did":"dfab80b18d8ce5d4df8159ba05dde951","cdata":[{"id":"do_213267732169023488128","type":"course"},{"type":"batch","id":"0132677340746629120"},{"id":"af588b6a747b6b3d28bea6d947dfbc49","type":"ContentSession"},{"id":"1a20fb335ff8dada7802d4473fe1a55e","type":"PlaySession"}],"rollup":{"l1":"0126796199493140480"}},"object":{"id":"do_2129959063404544001107","type":"Content","ver":"2","rollup":{"l1":"do_213267732169023488128","l2":"do_2129959063404544001107"}},"tags":["0126796199493140480"],"edata":{"item":{"id":"do_21299582796158566413015","maxscore":1,"type":"ftb","exlength":0,"params":[{"1":"{\"text\":\"\"}"},{"eval":"order"}],"uri":"","title":"Edit test UT","mmc":[],"mc":[],"desc":""},"index":2,"pass":"No","score":0,"resvalues":[{"1":"{\"text\":\"1\"}"}],"duration":4}}]}]}}' \
  --compressed


Question Set Response Processing flow

QuestionList Validation

In order to check for validity of Question inside a QuestionSet. Design proposes the value to be encrypted based on QuestionID List in hierarchy and persist this information against QuestionSetToken.

console.time("dbsave");
var crypto = require('crypto');
var encryptList = [];
var string = "sdgxsoksgdaodjqwdhuwdh";
var count = 0;
var salt = "salty";
for(var i=0;i<1000000;i++) {
    var encrypt = crypto.pbkdf2('secret'+i, salt, 10, 64, 'sha512', (err, derivedKey) => {
        if (err) throw err;
       
     });
    encryptList.push(encrypt);
    if(string === encrypt) {
        count++;
    }
}
console.log(count);
console.log(encryptList.length);
console.timeEnd("dbsave");

Response Times for Benchmarking


1000000 encrypt generation
dbsave: 4011.281ms


100000 encrypt generation
dbsave: 377.208ms


10000 encrypt generation
dbsave: 57.326ms

  • No labels