]> _ Git - fluidbook-toolbox.git/commitdiff
done #3946 @2.5
authorVincent Vanwaelscappel <vincent@cubedesigners.com>
Tue, 13 Oct 2020 12:21:35 +0000 (14:21 +0200)
committerVincent Vanwaelscappel <vincent@cubedesigners.com>
Tue, 13 Oct 2020 12:21:35 +0000 (14:21 +0200)
app/Http/Controllers/Admin/Base/QuizController.php
app/Http/Controllers/Admin/Operations/LogOperation.php [new file with mode: 0644]
app/Models/Quiz.php
app/Models/QuizAttempt.php [new file with mode: 0644]
resources/quiz/js/main.js

index 324056b4f8418c2085c7016c24228b5f465968f0..efb7eec0f3e2e531ce45aed0d8ddcd948a82442c 100644 (file)
@@ -5,6 +5,7 @@ namespace App\Http\Controllers\Admin\Base;
 
 use App\Http\Controllers\Admin\Operations\DownloadOperation;
 use App\Http\Controllers\Admin\Operations\ImportOperation;
+use App\Http\Controllers\Admin\Operations\LogOperation;
 use App\Http\Controllers\Admin\Operations\PreviewOperation;
 use Cubist\Backpack\app\Magic\Controllers\CubistMagicController;
 
@@ -13,6 +14,7 @@ class QuizController extends CubistMagicController
     use PreviewOperation;
     use DownloadOperation;
     use ImportOperation;
+    use LogOperation;
 
     function setupListOperation()
     {
diff --git a/app/Http/Controllers/Admin/Operations/LogOperation.php b/app/Http/Controllers/Admin/Operations/LogOperation.php
new file mode 100644 (file)
index 0000000..64735b1
--- /dev/null
@@ -0,0 +1,32 @@
+<?php
+
+
+namespace App\Http\Controllers\Admin\Operations;
+
+use App\Http\Middleware\VerifyCsrfToken;
+use App\Models\QuizAttempt;
+use DateTime;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Route;
+
+trait LogOperation
+{
+    protected function setupLogRoutes($segment, $routeName, $controller)
+    {
+        Route::match(['post'], $segment . '/{id}/log', $controller . '@log')->withoutMiddleware([VerifyCsrfToken::class]);
+    }
+
+    protected function log($id)
+    {
+        $request = request();
+
+        $log = new QuizAttempt();
+        $log->quiz = $id;
+        $log->score = $request->get('score');
+        $log->passed = $request->get('passed')?'1':'0';
+        $log->answers = json_encode($request->get('questions'));
+        $log->save();
+
+        return response()->json(['ok' => true])->header('Access-Control-Allow-Origin', '*');
+    }
+}
index 045d18db9fe6b5cfa2351dd871da50df99fc587e..8e67d3f12ba1d4f5434537323836e0cc191c60c7 100644 (file)
@@ -216,7 +216,7 @@ class Quiz extends CubistMagicAbstractModel
 
         // Create data.xml
         $xml = simplexml_load_string('<?xml version="1.0" encoding="UTF-8" ?><quiz />');
-        $xml->addAttribute('id', $data->get('id'));
+        $xml->addChild('id', $data->get('id'));
         $xml->addChild('title', $data->get('title'));
         $xml->addChild('threshold', $data->get('threshold', '0') ?: '0');
         $xml->addChild('instantReview', $data->get('instantReview', true) ? '1' : '0');
diff --git a/app/Models/QuizAttempt.php b/app/Models/QuizAttempt.php
new file mode 100644 (file)
index 0000000..85570fa
--- /dev/null
@@ -0,0 +1,34 @@
+<?php
+
+namespace App\Models;
+
+use Cubist\Backpack\app\Magic\Models\CubistMagicAbstractModel;
+
+class QuizAttempt extends CubistMagicAbstractModel
+{
+    protected $table = 'quiz_attempt';
+    protected $_options = ['name' => 'quizatttempt',
+        'singular' => 'quiz attempt',
+        'plural' => 'quiz attempts'];
+
+    public function setFields()
+    {
+        parent::setFields();
+
+        $this->addField(['type' => 'Number',
+            'name' => 'quiz',
+            'label' => 'Quiz ID']);
+
+        $this->addField(['type' => 'Number',
+            'name' => 'score',
+            'label' => 'Score']);
+
+        $this->addField(['type' => 'Checkbox',
+            'name' => 'passed',
+            'label' => 'Passed']);
+
+        $this->addField(['type' => 'Textarea',
+            'name' => 'answers',
+            'label' => 'Answers']);
+    }
+}
index 4e6874d852a8f2b128ac02cdd54c45cf99db7bb9..b09ae217b4b79fae6e5d5b2a154571a1393e1440 100644 (file)
             var correction = $('<div id="correction"><h2>' + getTranslation('reviewAnswer') + '</h2></div>');
 
             var qn = 1;
+            countQuestions = 0;
             // Create questions
             $(data).find('questions question').each(function () {
+                if ($(this).attr('count') == '1') {
+                    countQuestions++;
+                }
                 var type = $(this).attr('type');
                 var multiple = $(this).attr('multiple') == '1';
                 var multipleclass = multiple ? ' multiple' : '';
-                var question = '<section class="question' + multipleclass + '" data-q="' + qn + '" data-type="' + type + '">';
+                var question = '<section class="question' + multipleclass + '" data-count="' + $(this).attr('count') + '" data-q="' + qn + '" data-type="' + type + '">';
                 question += '<div class="label"><h3>' + sprintf(getTranslation('question'), qn) + '</h3> ' + $(this).find('label').text() + '</div>';
                 question += '<div class="answers">';
                 question += '</div>';
                 qn++;
             });
 
-            totalQuestions = (qn - 1);
-
             var defaultMessage = $(data).find('defaultMessage').length > 0 && $(data).find('defaultMessage').text() !== '' ? $(data).find('defaultMessage').text() : 'You have finished the quiz!';
             var passedMessage = $(data).find('passedMessage').length > 0 && $(data).find('passedMessage').text() !== '' ? $(data).find('passedMessage').text() : defaultMessage;
             var failedMessage = $(data).find('failedMessage').length > 0 && $(data).find('failedMessage').text() !== '' ? $(data).find('failedMessage').text() : defaultMessage;
                 '<h2 class="defaultMessage">' + defaultMessage + '</h2>' +
                 '<h2 class="passedMessage">' + passedMessage + '</h2>' +
                 '<h2 class="failedMessage">' + failedMessage + '</h2>' +
-                '<div class="content">' + getTranslation('totalQuestions') + ' <span id="totalquestions">' + totalQuestions + '</span><br />' + getTranslation('correctAnswers') + ' <span id="correctanswers"></span></div></div></section>');
+                '<div class="content">' + getTranslation('totalQuestions') + ' <span id="totalquestions">' + countQuestions + '</span><br />' + getTranslation('correctAnswers') + ' <span id="correctanswers"></span></div></div></section>');
             $(results).append(correction);
 
             $("main").append(results);
 
             var passed = checkScore();
             if (logAttempts) {
-                $.ajax('https://toolbox.fluidbook.com/quizlog/',
+                var logdata = {
+                    passed: passed,
+                    score: Math.round(100 * (score / countQuestions)),
+                    questions: logQuestions,
+                };
+
+                $.ajax('https://toolbox.fluidbook.com/quiz/' + $(data).find('id').text() + '/log',
                     {
-                        method: 'post',
+                        method: 'POST',
                         data: logdata,
+                        crossDomain: true,
                     }
                 );
             }
         }
 
         function checkScore() {
-            var normalizedScore = score / totalQuestions;
+            var normalizedScore = score / countQuestions;
             $('#results > h2').hide();
             var passed;
             if (threshold === 0) {
                 execAction(failedAction);
                 passed = false;
             }
+            return passed;
         }
 
         function execAction(action) {
             score = 0;
             var answers = [];
             var qn = 1;
+            logQuestions = [];
 
             $('.question').each(function () {
                 var a = [];
                 var ok = true;
+                var count = $(this).attr('data-count') == '1';
+                var log = {
+                    'count': count,
+                };
+
+                if ($(this).data('type') === 'multiple') {
+                    $(this).find('.answer').each(function () {
+                        var correct = $(this).attr('data-correct') == '1';
+                        var active = $(this).hasClass('active');
+                        if (correct !== active) {
+                            ok = false;
+                        }
+                        if (active) {
+                            a.push($(this).data('a'))
+                        }
+                    });
+                    answers.push(a);
+                    log.anwser = a;
+                } else {
+                    log.anwser = $(this).find('input').val();
+                }
 
-                $(this).find('.answer').each(function () {
-                    var correct = $(this).attr('data-correct') == '1';
-                    var active = $(this).hasClass('active');
-                    if (correct !== active) {
-                        ok = false;
-                    }
-                    if (active) {
-                        a.push($(this).data('a'))
-                    }
-                });
-                answers.push(a);
                 var b = $("#correction .correction[data-i='" + qn + "'] .badge");
                 $(b).removeClass('correct').removeClass('incorrect').addClass(ok ? 'correct' : 'incorrect');
-                if (ok) {
+                if (ok && count) {
                     score++;
+                    log.score = 1;
+                } else {
+                    log.score = 0;
                 }
+                logQuestions[qn] = log;
                 qn++;
             });