[IMP] survey: add an overall correctness graph when finishing a certification
PURPOSE Perform a back2basics review of survey to improve daily use, new user onboarding and labelling. SPECIFICATIONS When finishing a certification survey, add an overall correctness circular graph. Quarters are * correct * partially (if multiple corrects answers on the survey); * incorrect * unanswered Questions without points are not displayed in this graph. LINKS Task 2039068 PR #36229
This commit is contained in:
committed by
Thibault Delavallée
parent
ee5649cdff
commit
240e860f24
@@ -651,4 +651,12 @@ class Survey(http.Controller):
|
||||
values = {'survey': survey, 'answer': answer}
|
||||
if token:
|
||||
values['token'] = token
|
||||
if survey.scoring_type != 'no_scoring' and survey.certificate:
|
||||
answer_perf = survey._get_answers_correctness(answer)[answer]
|
||||
values['graph_data'] = json.dumps([
|
||||
{"text": "Correct", "count": answer_perf['correct']},
|
||||
{"text": "Partially", "count": answer_perf['partial']},
|
||||
{"text": "Incorrect", "count": answer_perf['incorrect']},
|
||||
{"text": "Unanswered", "count": answer_perf['skipped']}
|
||||
])
|
||||
return values
|
||||
|
||||
@@ -622,6 +622,39 @@ class Survey(models.Model):
|
||||
|
||||
return result
|
||||
|
||||
def _get_answers_correctness(self, user_answers):
|
||||
if not user_answers.mapped('survey_id') == self:
|
||||
raise UserError(_('Invalid performance computation'))
|
||||
|
||||
res = dict((user_answer, {
|
||||
'correct': 0,
|
||||
'incorrect': 0,
|
||||
'partial': 0,
|
||||
'skipped': 0,
|
||||
}) for user_answer in user_answers)
|
||||
|
||||
scored_questions = self.question_ids.filtered(
|
||||
lambda question: question.question_type in ['simple_choice', 'multiple_choice']
|
||||
)
|
||||
|
||||
for question in scored_questions:
|
||||
question_answer_correct = question.labels_ids.filtered(lambda answer: answer.is_correct)
|
||||
for user_answer in user_answers:
|
||||
user_answer_lines_question = user_answer.user_input_line_ids.filtered(lambda line: line.question_id == question)
|
||||
user_answer_correct = user_answer_lines_question.filtered(lambda line: line.answer_is_correct and not line.skipped).mapped('value_suggested')
|
||||
user_answer_incorrect = user_answer_lines_question.filtered(lambda line: not line.answer_is_correct and not line.skipped)
|
||||
|
||||
if user_answer_correct == question_answer_correct:
|
||||
res[user_answer]['correct'] += 1
|
||||
elif user_answer_correct and user_answer_correct < question_answer_correct:
|
||||
res[user_answer]['partial'] += 1
|
||||
if not user_answer_correct and user_answer_incorrect:
|
||||
res[user_answer]['incorrect'] += 1
|
||||
if not user_answer_correct and not user_answer_incorrect:
|
||||
res[user_answer]['skipped'] += 1
|
||||
|
||||
return res
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# GAMIFICATION / BADGES
|
||||
# ------------------------------------------------------------
|
||||
|
||||
@@ -2,6 +2,7 @@ odoo.define('survey.result', function (require) {
|
||||
'use strict';
|
||||
|
||||
require('web.dom_ready');
|
||||
var _t = require('web.core')._t;
|
||||
|
||||
if(!$('.js_surveyresult').length) {
|
||||
return Promise.reject("DOM doesn't contain '.js_surveyresult'");
|
||||
@@ -159,6 +160,35 @@ if(!$('.js_surveyresult').length) {
|
||||
return chartConfig;
|
||||
}
|
||||
|
||||
//initialize doughnut Chart
|
||||
function init_doughnut_chart(graph_data, quizz_score){
|
||||
var data = graph_data.map(function (point) {
|
||||
return point.count;
|
||||
});
|
||||
var chartConfig = {
|
||||
type: 'doughnut',
|
||||
data: {
|
||||
labels: graph_data.map(function (point) {
|
||||
return point.text;
|
||||
}),
|
||||
datasets: [{
|
||||
label: '',
|
||||
data: data,
|
||||
backgroundColor: data.map(function (val, index) {
|
||||
return D3_COLORS[index % 20];
|
||||
}),
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
title: {
|
||||
display: true,
|
||||
text: _.str.sprintf(_t("Overall Performance %.2f%s"), parseFloat(quizz_score), '%'),
|
||||
},
|
||||
}
|
||||
};
|
||||
return chartConfig;
|
||||
}
|
||||
|
||||
//load chart to svg element chart:initialized chart, response:AJAX response, quistion_id:if of survey question, tick_limit:text length limit
|
||||
function load_chart(chartConfig, containerSelector){
|
||||
var $container = $(containerSelector).css({position: 'relative'});
|
||||
@@ -187,6 +217,11 @@ if(!$('.js_surveyresult').length) {
|
||||
chartConfig = init_pie_chart(graph_data);
|
||||
return load_chart(chartConfig, containerSelector);
|
||||
}
|
||||
else if (graph_type === 'doughnut') {
|
||||
var quizz_score = $(graph).attr("quizz-score") || 0.0;
|
||||
chartConfig = init_doughnut_chart(graph_data, quizz_score);
|
||||
return load_chart(chartConfig, containerSelector);
|
||||
}
|
||||
});
|
||||
|
||||
var $scoringResultsChart = $('#scoring_results_chart');
|
||||
|
||||
@@ -57,6 +57,15 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container js_surveyresult p-4" t-if="graph_data">
|
||||
<div class="tab-content">
|
||||
<div role="tabpanel" class="tab-pane active survey_graph" t-att-quizz-score="answer.quizz_score" t-att-id="'graph_question_%d' % answer.id" t-att-data-question_id="answer.id" data-graph_type="doughnut" t-att-graph-data="graph_data">
|
||||
<canvas id="doughnut_chart"></canvas>
|
||||
<span class="o_overall_performance"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="oe_structure"/>
|
||||
</div>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user