Versions Compared

Key

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

...

As a State Admin, I would want to have access to scores of self-assessment/s of all users within a batch of a course, So that I can get some insights on the quality of the contents within a course.


Solution I:

As part of Every question units having evaluation logic and plugin knows the question attempted or not. This data we are not sending as part of Telemetry.

After evaluation, there is a callback to the question-set /assessment, we are generating the "ASSESS" telemetry event for all questions during the evaluation of the question. So each ASSESS event contains question params and resValues. 

So looking into telemetry Assess event resValues empty or contains data in an array based on this data will consider Question attempted or skipped.

...

Expand
titleSkipped question

"edata": {
"item": {
"id": "do_11286000975564800011904",
"maxscore": 1,
"type": "ftb",
"exlength": 0,
"params": [
{
"1": "{\"text\":\"1\"}"
},
{
"eval": "order"
}
],
"uri": "",
"title": "FTB: QuestionService fix____\n",
"mmc": [],
"mc": [],
"desc": ""
},
"index": 1,
"pass": "No",
"score": 0,
"resvalues": [],
"duration": 26
}

...

titleSkipped question

...

plugin. so while returning data from question unit plugins will send attempted: true/false and questionId:"do_id" as part of the result. This data will carry to question-set and dispatch event to org.ekstep.questionset:summary.

So it will help to know the score report of the assessment.

Example: 

Expand
titleMCQ state data


Code Block
languagejs
{
"attempted":true,
"eval": true,
"state": {
"val": 0,
"options": [
{
"text": "<p>True</p>\n",
"image": "",
"audio": "",
"audioName": "",
"hint": "",
"isCorrect": true,
"$$hashKey": "object:1456"
},
{
"text": "<p>False</p>\n",
"image": "",
"audio": "",
"audioName": "",
"hint": "",
"isCorrect": false,
"$$hashKey": "object:1457"
}
]
},
"score": 1,
"params": [
{
"1": "{\"text\":\"True\\n\"}"

...


},

...


{

...


"2": "{\"text\":\"False\\n\"}"

...


},

...


{

...


"answer": "{\"correct\":[\"1\"]}"

...


}

...


],

...


"

...

values": [
{
"

...

1": "{\"text\":

...

\"True\\n\"}"
}
],

...


"

...

type":

...

 "mcq",
"questionId":"do_11287200486896435214"

...


}

...

...


Solution II:

As part of the question-set/assessment, we are generating the "ASSESS" telemetry event for all questions during the evaluation of the question. So each ASSESS event contains question params and resValues. 

So looking into telemetry Assess event resValues empty or contains data in an array based on this data will consider Question attempted or skipped.



FTBMCQMTFSequenceReorder
ASSESS Event resvalues(tick)(tick)(error)(error)(tick)


Expand
titleSkipped question

"edata": {
"item": {
"id": "do_

11286000903443251211902

11286000975564800011904",
"maxscore": 1,
"type": "

mtf

ftb",
"exlength": 0,
"params": [
{

"lhs":

"

[{\"

1

\

":

\

"{

\\

\"text

\\

\":\

\\"A\\\\n\\\

"1\"}

\

"
},
{

\


"

2\

eval":

\

"

{\\\"text\\\":\\\"B\\\\n\\\"}\"},{\"3\":\"{\\\"text\\\":\\\"C\\\\n\\\"}\"}]"
},
{
"rhs": "[{\"1\":\"{\\\"text\\\":\\\"b\\\\n\\\"}\"},{\"2\":\"{\\\"text\\\":\\\"c\\\\n\\\"}\"},{\"3\":\"{\\\"text\\\":\\\"a\\\\n\\\"}\"}]"
},
{
"answer": "{\"lhs\":[\"1\",\"2\",\"3\"],\"rhs\":[\"3\",\"1\",\"2\"]}"
}
],
"uri": "",
"title": "MTF:QuestionService fix\n"

order"
}
],
"uri": "",
"title": "FTB: QuestionService fix____\n",
"mmc": [],
"mc": [],
"desc": ""
},
"index": 1,
"pass": "No",
"score": 0,
"resvalues": [],
"duration": 26
}




Expand
titleSkipped question

"edata": {
"item": {
"id": "do_11286000940202393611903",
"maxscore": 1,
"type": "mcq",
"exlength": 0,
"params": [
{
"1": "{\"text\":\"True\\n\"}"
},
{
"2": "{\"text\":\"False\\n\"}"
},
{
"answer": "{\"correct\":[\"1\"]}"
}
],
"uri": "",
"title": "MCQ: QuestionService fix\n",
"mmc": [],
"mc": [],
"desc": ""
},
"index":

3

2,
"pass": "No",
"score": 0,
"resvalues": [
{}
],
"

lhs": "[{\"

duration": 6
}



Expand
titleSkipped question

"edata": {
"item": {
"id": "do_11286000903443251211902",
"maxscore": 1,
"type": "mtf",
"exlength": 0,
"params": [
{
"lhs": "[{\"1\":\"{\\\"text\\\":\\\"A\\\\n\\\"}\"},{\"2\":\"{\\\"text\\\":\\\"B\\\\n\\\"}\"},{\"3\":\"{\\\"text\\\":\\\"C\\\\n\\\"}\"}]"
},
{
"rhs": "[{\"1\":\"{\\\"text\\\":\\\"b\\\\n\\\"}\"},{\"2\":\"{\\\"text\\\":\\\"c\\\\n\\\"}\"},{\"3\":\"{\\\"text\\\":\\\"a\\\\n\\\"}\"}]"
},

],

{
"

duration

answer":

3
} Expand
titleSkipped question

"

edata":

{


\"

item

lhs\":

{
"id": "do_11286001060099686411906",
"maxscore": 1,
"type": "sequence",
"exlength": 0,
"params": [
{
"1": "{\"text\":\"Two\"}"
},
{
"2": "{\"text\":\"One\"}"
},
{
"answer": "{\"seq\":[\"2\",\"1\"]}"
}
],
"uri": "",
"title": "Question service fix \n",
"mmc": [],
"mc": [],
"desc": ""
},
"index": 4,
"pass": "No",
"score": 0,
"resvalues": [
{
"1": "{\"text\":\"Two\"}

[\"1\",\"2\",\"3\"],\"rhs\":[\"3\",\"1\",\"2\"]}"
}
],
"uri": "",
"title": "MTF:QuestionService fix\n",
"mmc": [],
"mc": [],
"desc": ""
},
"index": 3,
"pass": "No",
"score": 0,
"resvalues": [
{
"lhs": "[{\"1\":\"{\\\"text\\\":\\\"A\\\\n\\\"}\"},{\"2\":\"{\\\"text\\\":\\\"B\\\\n\\\"}\"},{\"3\":\"{\\\"text\\\":\\\"C\\\\n\\\"}\"}]"
},
{
"

2

rhs": "[{\"1\":\"{\\\"text\\\":\\\"

One

b\\\\n\\\"}\"


}


]

,


{\"

duration

2\":

3
} Expand
titleSkipped question
"edata": {
"item": {
"id": "do_11286001026143846411905",
"maxscore": 1,
"type": "reorder",
"exlength": 0,
"params": [
{
"1": "{\"text\":\"4\"}"
},
{
"2": "{\"text\":\"8\"}"
},
{
"3

\"{\\\"text\\\":\\\"c\\\\n\\\"}\"},{\"3\":\"{\\\"text\\\":\\\"a\\\\n\\\"}\"}]"
}
],
"duration": 3
}



Expand
titleSkipped question

"edata": {
"item": {
"id": "do_11286001060099686411906",
"maxscore": 1,
"type": "sequence",
"exlength": 0,
"params": [
{
"1": "{\"text\":\"

6

Two\"}"
},
{
"

4

2": "{\"text\":\"

5

One\"}"
},
{
"

5

answer": "{\"

text

seq\":[\"2\",\"1\"]}"
}
],

{

"

6

uri": "

{\"text\

",
"title": "Question service fix \n"

7\

,
"

}"
}

mmc": [],

{

"

7

mc":

"{\"text\":\"1\"}

[],
"desc": ""
},

{

"

answer

index": 4,
"

{\

pass"

seq\"

:

[\

"

3\

No",

\


"

7\

score": 0,
"resvalues": [
{
"1": "{\"

5

text\"

,

:\"

4

Two\"

,\

}"
},
{
"2

\

": "

,

{\"

6

text\"

,

:\"

1

One\"

]

}"
}
],
"

uri

duration": 3
}



Expand
titleSkipped question

"edata"

,

: {
"

title

item":

"QuestionService fixArrange the given words in proper order to form a sentence.\n\n \n",
"mmc": [],
"mc": [],
"desc": ""
},
"index": 5,
"pass": "No",
"score": 0,
"resvalues": [],
"duration": 3
} Expand
titleAttempted question
"edata": {
"item": {
"id": "do_11286000975564800011904",
"maxscore": 1,
"type": "ftb",
"exlength": 0,
"params": [
{
"1

{
"id": "do_11286001026143846411905",
"maxscore": 1,
"type": "reorder",
"exlength": 0,
"params": [
{
"1": "{\"text\":\"4\"}"
},
{
"2": "{\"text\":\"8\"}"
},
{
"3": "{\"text\":\"6\"}"
},
{
"4": "{\"text\":\"

1

5\"}"
},
{
"

eval

5": "

order

{\"text\":\"2\"}"
},

],

{
"

uri

6": "

",
"title

{\"text\":

"FTB: QuestionService fix____\n",
"mmc": [],
"mc": [],
"desc": ""

\"7\"}"
},
{
"7": "{\"text\":\"1\"}"
},
{
"

index

answer":

1,
"pass

"{\"seq\":[\"

Yes

3\",


\"

score

7\"

: 1,
"resvalues": [
{
"1": "{\"text\":

,\"5\",\"4\",\"2\",\"6\",\"1\"]}"
}
],
"

duration

uri":

588
} Expand
titleAttempted question

"

edata

"

: {

,
"

item

title":

{
"id": "do_11286000940202393611903",
"maxscore": 1,
"type": "mcq",
"exlength": 0,
"params": [
{
"1": "{\"text\":\"True\\n\"}"
},
{
"2": "{\"text\":\"False\\n\"}"
},
{
"answer

"QuestionService fixArrange the given words in proper order to form a sentence.\n\n \n",
"mmc": [],
"mc": [],
"desc": ""
},
"index": 5,
"pass": "No",
"score": 0,
"resvalues": [],
"duration": 3
}




Expand
titleAttempted question

"edata": {
"item": {
"id": "do_11286000975564800011904",
"maxscore": 1,
"type": "ftb",
"exlength": 0,
"params": [
{
"1": "{\"

correct

text\":

[

\"1\"

]

}"
},
{
"eval": "order"
}
],
"uri": "",
"title": "

MCQ

FTB: QuestionService fix____\n",
"mmc": [],
"mc": [],
"desc": ""
},
"index":

2

1,
"pass": "Yes",
"score": 1,
"resvalues": [
{
"1": "{\"text\":\"

True

1\

\n\

"}"
}
],
"duration":

293

588
}



Expand
titleAttempted question

"edata": {
"item": {
"id": "do_

11286000903443251211902

11286000940202393611903",
"maxscore": 1,
"type": "

mtf

mcq",
"exlength": 0,
"params": [
{

"lhs": "[{\

"1

\

":

\

"{\

\\

"text

\\

\":

\

\

\

"

A

True\\

\\

n

\\

\"}

\

"
},
{

\


"2

\

":

\

"{

\\

\"text

\\

\":\

\\

"

B

False\\

\\

n

\

\

\

"}

\

"
},
{

\


"

3\

answer":

\

"{

\

\

\

"

text

correct\

\\

":

\\

[\"

C\\\\n\\

1\"]}

\

"
}
]

"
}

,


{


"

rhs

uri": "

[{\"1\":\"{\\\"text\\\":\\\"b\\\\n\\\"}\"},{\"2\":\"{\\\"text\\\":\\\"c\\\\n\\\"}\"},{\"3\":\"{\\\"text\\\":\\\"a\\\\n\\\"}\"}]"
},
{
"answer": "{\"lhs\":[\"1\",\"2\",\"3\"],\"rhs\":[\"3\",\"1\",\"2\"]}"
}
],
"uri": "",
"title": "MTF:QuestionService fix\n",
"mmc": [],
"mc": [],
"desc": ""
},
"index": 3,
"pass": "No",
"score": 0.33,
"resvalues": [
{
"lhs": "

",
"title": "MCQ: QuestionService fix\n",
"mmc": [],
"mc": [],
"desc": ""
},
"index": 2,
"pass": "Yes",
"score": 1,
"resvalues": [
{
"1": "{\"text\":\"True\\n\"}"
}
],
"duration": 293
}



Expand
titleAttempted question

"edata": {
"item": {
"id": "do_11286000903443251211902",
"maxscore": 1,
"type": "mtf",
"exlength": 0,
"params": [
{
"lhs": "[{\"1\":\"{\\\"text\\\":\\\"A\\\\n\\\"}\"},{\"2\":\"{\\\"text\\\":\\\"B\\\\n\\\"}\"},{\"3\":\"{\\\"text\\\":\\\"C\\\\n\\\"}\"}]"
},
{
"rhs": "[{\"1\":\"{\\\"text\\\":\\\"

A

b\\\\n\\\"}\"},{\"2\":\"{\\\"text\\\":\\\"

B

c\\\\n\\\"}\"},{\"3\":\"{\\\"text\\\":\\\"

C

a\\\\n\\\"}\"}]"
},
{
"

rhs

answer": "

[

{\"

1

lhs\":[\"

{\\

1\",\"2\",\"

text

3\"],\"rhs\":[\"3\",\"

c

1\",\"2\

\n\\\

"]}

\

"
}
],

{\


"

2\

uri":

\"{\\\"text\\\":\\\"b\\\\n\\\"}\"},{\"3\":\"{\\\"text\\\":\\\"a\\\\n\\\"}\"}]"
}
],
"duration": 63
} Expand
titleAttempted question
"edata": {
"item": {
"id": "do_11286001060099686411906",
"maxscore": 1,
"type": "sequence",
"exlength": 0,
"params

"",
"title": "MTF:QuestionService fix\n",
"mmc": [],
"mc": [],
"desc": ""
},
"index": 3,
"pass": "No",
"score": 0.33,
"resvalues": [
{
"lhs": "[{\"1\":\"{\\\"text\\\":\

"Two

\\"A\\\\n\\\"}\"


},


{


\"2\":\"{\\\"text\\\":\\\"

One

B\\\\n\\\"}\"


},


{


\"

answer

3\":\"{\\\"

seq

text\\\":

[

\\\"

2

C\

",

\

"1\"]}

\\n\\\"}\"}]"
},

],

{
"

uri

rhs": "

",
"title": "Question service fix \n",
"mmc": [],
"mc": [],
"desc": ""
},
"index": 4,
"pass": "Yes",
"score": 1,
"resvalues": [
{
"2": "{\"text\":\"One\"}"
},
{
"1": "{\"text\":\"Two\"}"

[{\"1\":\"{\\\"text\\\":\\\"c\\\\n\\\"}\"},{\"2\":\"{\\\"text\\\":\\\"b\\\\n\\\"}\"},{\"3\":\"{\\\"text\\\":\\\"a\\\\n\\\"}\"}]"
}
],
"duration":

62

63
}



Expand
titleAttempted question

"edata": {
"item": {
"id": "do_

11286001026143846411905

11286001060099686411906",
"maxscore": 1,
"type": "

reorder

sequence",
"exlength": 0,
"params": [
{
"1": "{\"text\":\"

4

Two\"}"
},
{
"2": "{\"text\":\"

8

One\"}"
},
{
"

3

answer": "{\"

text

seq\":[\"

6

2\",\"1\"]}"
}
],

{

"

4

uri": ""

{\"text\

,
"title":

\

"

5

Question service fix \n"

}"
}

,


{


"

5

mmc":

"{\"text\":\"2\"}"

[],
"mc": [],
"desc": ""
},

{

"index": 4,
"

6

pass": "Yes"

{\"text\

,
"score":

\"7\"}"
},

1,
"resvalues": [
{
"

7

2": "{\"text\":\"

1

One\"}"
},
{
"

answer

1": "{\"

seq

text\":

[

\"

3

Two\"

,\"7\",\"5\",\"4\",\"2\",\"6\",\"1\"]}"
}
],
"uri": "",
"title": "QuestionService fixArrange the given words in proper order to form a sentence.\n\n \n",
"mmc": [],
"mc": [],
"desc": ""
},
"index": 5,
"pass": "No",
"score": 0,
"resvalues": [

}"
}
],
"duration": 62
}



Expand
titleAttempted question

"edata": {
"item": {
"id": "do_11286001026143846411905",
"maxscore": 1,
"type": "reorder",
"exlength": 0,
"params": [
{
"1": "{\"text\":\"4\"}"
},
{
"2": "{\"text\":\"8\"}"
},
{
"3": "{\"text\":\"6\"}"
},

],
"duration": 55
}

Solution II:

Based on Telemetry Response event. Currently, MCQ type of questions only generating a Response event.

If the response event generates so it is considered as an attempted question.

MCQFTBMTFSequenceReorderResponse event

(tick)

Expand
titleAttempted question
{
"eid": "RESPONSE",
"ets": 1571385741820,
"ver": "3.0",
"mid": "RESPONSE:c35bb556e3920e6a5b287ac699d96448",
"actor": {
"id": "874ed8a5-782e-4f6c-8f36-e0288455901e",
"type": "User"
},
"context": {
"channel": "b00bc992ef25f1a9a8d63291e20efc8d",
"pdata": {
"id": "dev.sunbird.portal",
"ver": "2.4.0",
"pid": "sunbird-portal.contenteditor.contentplayer"
},
"env": "contentplayer",
"sid": "nm-dQSSXROxfJpbONAmdXSmY_2ttSA6C",
"did": "d1b3344d6b8d8b5441c3b47842b61abd",
"cdata": [
{
"id": "f799686c9c913589cf270153edf8dbf6",
"type": "ContentSession

{
"4": "{\"text\":\"5\"}"
},
{
"5": "{\"text\":\"2\"}"
},
{
"6": "{\"text\":\"7\"}"
},
{
"7": "{\"text\":\"1\"}"
},
{
"answer": "{\"seq\":[\"3\",\"7\",\"5\",\"4\",\"2\",\"6\",\"1\"]}"
}
],
"uri": "",
"title": "QuestionService fixArrange the given words in proper order to form a sentence.\n\n \n",
"mmc": [],
"mc": [],
"desc": ""
},
"index": 5,
"pass": "No",
"score": 0,
"resvalues": [
{
"2": "{\"text\":\"8\"}"
},
{
"3": "{\"text\":\"6\"}"
}
],
"

rollup

duration":

{}

55
}

,

"object"



Solution III:

...

Based on Telemetry Response event. Currently, MCQ type of questions only generating a Response event.

If the response event generates so it is considered as an attempted question.



MCQFTBMTFSequenceReorder
Response event

(tick)

Expand
titleAttempted question

{
"eid": "RESPONSE",
"ets": 1571385741820,
"ver": "

1

3.0",
"

rollup

mid":

{}
},
"tags": []

"RESPONSE:c35bb556e3920e6a5b287ac699d96448",
"

edata": {
"target"

actor": {
"id": "

org.ekstep.questionunit.mcq

874ed8a5-782e-4f6c-8f36-e0288455901e",
"

ver

type": "

1.3

User"
},
"

type

context":

"plugin"
},

{
"

type

channel": "

CHOOSE

b00bc992ef25f1a9a8d63291e20efc8d",
"

values

pdata":

[

{
"

option0

id": "

<p>True</p>\n"
}
]
}
}(error)(error)(error)(error)

Solution III:

In questionSet when the user selects or filled the answer, we are preserving the answers for state management. So this data will store in  evaluated result we call state data.

For example: MCQ: result:state:value => if attempted => selected option index

                                 result:state:value=> if skipped => result:state:value: undefined

                      FTB: result:state:value => if attempted => array of answers (result:state:value['apple','mango'])

                                 result:state:value=> if skipped => result:state:value:[]

...

dev.sunbird.portal",
"ver": "2.4.0",
"pid": "sunbird-portal.contenteditor.contentplayer"
},
"env": "contentplayer",
"sid": "nm-dQSSXROxfJpbONAmdXSmY_2ttSA6C",
"did": "d1b3344d6b8d8b5441c3b47842b61abd",
"cdata": [
{
"id": "f799686c9c913589cf270153edf8dbf6",
"type": "ContentSession"
}
],
"rollup": {}
},
"object": {
"id": "do_11287200486896435214",
"type": "Content",
"ver": "1.0",
"rollup": {}
},
"tags": [],
"edata": {
"target": {
"id": "org.ekstep.questionunit.mcq",
"ver": "1.3",
"type": "plugin"
},
"type": "CHOOSE",
"values": [
{
"option0": "<p>True</p>\n"
}
]
}
}


(error)(error)(error)(error)


Solution IV:

In questionSet when the user selects or filled the answer, we are preserving the answers for state management. So this data will store in  evaluated result we call state data.

For example: MCQ: result:state:value => if attempted => array of selected answers selected option index

                                 result:state:value=> if skipped => result:state:value: undefined

                      FTB: result:state:value => if attempted => array of answers (result:state:value['apple','mango'])

                                 result:state:value=> if skipped => result:state:value:[]

Evaluated result state object

...

Solution IV:

Every question units having evaluation logic and plugin knows the question attempted or not. This data we are not sending as part of Telemetry.

After evaluation, there is a callback to the question-set plugin. so while returning data from question unit plugins will send attempted: true/false and questionId:"do_id" as part of the result. This data will carry to question-set and dispatch event to org.ekstep.questionset:summary.

So it will help to know the score report of the assessment.

Example: 

...

titleMCQ state data

...

languagejs

...

                     reorder: result:state:value => if attempted => array of selected answers (result:state:value['apple','mango'])

                                 result:state:value=> if skipped => result:state:value:[]


Evaluated result state object


MCQFTBReorderSequenceMTF
Attempted(tick)(tick)(tick)(error)(error)
Skipped(tick)(tick)(tick)(error)(error)