Creating a Custom Report

Use the No-UI report setting to create your own custom session average score report. Developer


Learnosity offers several different kinds of reports to present statistical data about users, sessions, resource tags, and more. Reports range from big-picture views, such as a simple Session Summary report, to more comprehensive analyses, such as the Session Detail report. The former displays a concise view of the number of correct, incorrect, and unattempted questions in a single activity session by a single user. The latter expands that information by showing complete questions, and validated student responses for the session.

Sometimes, however, you may need report data only, or a specific type of report that isn’t among the reports already offered. In that scenario, it’s possible to set a Reports API configuration option called render to false to prevent a report from rendering any graphics, while still sending you the data data for your own needs.

This tutorial carries on from Tutorial 103: Displaying Session Reports, which discussed the aforementioned Session Summary and Session Detail reports. Here, we’re going to initialize a Session List report but disable rendering. We’ll show the data simply as a visual example of the information you have access to, but we’ll also create a simple new report type tentatively called “Session Average”. We’ll average the score of all sessions in the list to represent how you might tally a class average for a particular activity.

Note This tutorial assumes you are familiar with the Learnosity Reports API, PHP, and jQuery.

Signing the Report Request

The signing code, begins with standard customer authentication information, and the Learnosity SDK autoloader, included via a config file. The path to the Init class is also loaded for ease of use. The request object is similar to that of Tutorial 103: Displaying Session Reports, but specifies session-list as the report type, and a limit of 15 sessions included.

The important new detail of the request object appears in line 20. By including the render property set to false, the Session List report will not be rendering, allowing you to do whatever you like with the returned data.

The request object is then combined with the authentication data and the desired API (line 25) to create a signed request (line 26).

Note This tutorial uses demo values for the consumer key and secret. In production, you must use your own consumer key and secret.

 1  <?php
 3  include_once 'config.php';
 5  use LearnositySdkRequestInit;
 7  $request = [
 8      'reports' => [
 9          [
10              'id'           => 'sessions-list',
11              'type'         => 'sessions-list',
12              'limit'        => 15,
13              'activities'   => [
14                  [
15                      'id'   => 'Summer_Test_1',
16                      'name' => 'Summer Test 1, 2015'
17                  ]
18              ],
19              'render'       => false
20          ]
21      ]
22 ];
24  $Init = new Init('reports', $security, $consumer_secret, $request);
25  $signedRequest = $Init->generate();
27  ?>

Creating the Host Page

The host page is a basic report skeleton with a few added details. The CSS from lines 37 through 55 is for styling the JSON that will be displayed in this tutorial. Lines 57 through 67 of the CSS style the size, color, opacity, and font used for the animated horizontal bar we’ll use to depict the session average score.

As for the HTML, Lines 72 through 74 will contain the text for the score, while the div in line 75 is used for the animated bar. Finally, lines 76 through 78 will contain the JSON returned by the report—again, displayed here as an easy visual representation of the data used to create the animated average score bar.

 29  <!--php goes here-->
 31  <!DOCTYPE html>
 32  <html lang="en">
 33      <head>
 34          <meta charset="utf-8">
 35          <title>Report: Session Detail by Question</title>
 36          <style>
 37              .learnosity-report * {
 38                 font-family:Courier,monospace !important;
 39              }
 40              .preview pre {
 41                 background-color: #F8F8FF;
 42                 border: 1px solid #C0C0C0;
 43                 padding: 10px 20px;
 44                 margin: 20px;
 45                 display:none;
 46              }
 47              .preview .json-key {
 48                 color: #A52A2A;
 49              }
 50              .preview .json-value {
 51                 color: #000080;
 52              }
 53              .preview .json-string {
 54                 color: #808000;
 55              }
 57              .avg {
 58                  height:20px;
 59                  background-color:#0000CC;
 60                  margin:20px;
 61                  opacity:0;
 62              }
 63              #avgScore, #avgScore span {
 64                  font-family:Arial,sans-serif !important;
 65                  font-size:18pt;
 66                  margin-left:20px;
 67              }
 68          </style>
 69      </head>
 70      <body>
 71          <div style="width:750px;">
 72              <div id="avgScore">Session Average Score:
 73                  <span id="avgScorePercent"></span>
 74              </div>
 75              <div class="avg"></div>
 76              <div class="previewWrapper preview">
 77                  <pre><code></code></pre>
 78              </div>
 79          </div>
 81          <!--scripts go here-->
113      </body>
114  </html>

With the signed request complete, let’s focus on the event object.

Processing the Report Data

A departure from the average Reports API call, this tutorial adds about a dozen lines of JavaScript to handle the returned data. Typically, the API handles everything, and we only need to init the API as the last line of the script. In this case, however, we’ve set the render property to false because we want to process the data ourselves.

The code below is divided into two blocks. The first will display our custom average score report, and the second will just display the raw data to show what the data looks like. We’ll use a short script to style the JSON (prettyPrint.js in line 84) as well as some simple jQuery (line 83) for the custom report.

The new code executes when the API’s ready event is fired, and the readyListener function in line 88 is called. Because it’s possible to pull more than one report, line 89 gets the report we want, and a listener for that report (line 91) awaits the load:data event. When the data is loaded, lines 92 through 103 handle the average score, and lines 105 show the JSON on screen.

Lines 93 through 95 add up the scores of all sessions (data.sessions). Each score is determined by dividing the score for correct answers (count_score_correct) by the total score (count_score) for each session. Line 96 averages that sum by dividing by the total number of sessions (data.sessions.length) and line 97 limits that final value to two decimal places for a clean display.

Lines 98 through 103 handle the animation of a horizontal score bar. Line 98 determines the maximum width of the bar, which automatically fills its parent so it will work at any width that suits your report. Line 99 then immediately sets that width to 0, and line 100 follows by animating both the width and opacity to their final values over one second. When the animation is complete, the complete handler in lines 101 through 103 places the average value, followed by a percent symbol, in a span element. The end result is both a bar width and text representation of the session average score.

 83  <script src="js/vendor/jquery.min.js"></script>
 84  <script src="js/prettyPrint.js"></script>
 85  <script src="//"></script>
 86  <script>
 87      var eventOptions = {
 88          readyListener: function () {
 89              var sessionsReport = reportsApp.getReport("sessions-list");
 91              sessionsReport.on("load:data", function (data) {
 92                  var avgSum = 0;
 93                  $.each(data.sessions, function(index, value) {
 94                      avgSum += parseFloat(value.count_score_correct) /
 95                  });
 96                  var avg = (avgSum/data.sessions.length);
 97                  var avgPercent = Math.round(avg*100*100)/100;
 98                  var avgWidth = $(".avg").width();
 99                  $(".avg").animate({"width":0},0)
100                           .animate({"width":avg*avgWidth, "opacity":1}, 1000;
101                               function(){
102                                   $("#avgScorePercent").html(avgPercent + "%");
103                               });
105                  $("code").html(
106                      prettyPrint.render(data)
107                  );
108                  $(".preview pre").show();
109              });
110          }
111      }
112      var reportsApp = LearnosityReports.init(<?php echo $signedRequest; ?>, eventOptions);
113  </script>

Finally, lines 105 through 108 display the JSON. First the data is styled and rendered into the code element by the prettyPrint script, and then the block is shown to the viewer.

The Resulting Report

Figure 1 animates a portion of the finished page. After the data loads, the bar animates, the final text value appears, and the beginning of the JSON is visible below. (We’ve padded the beginning of the animation a bit to make the report display a bit more obvious when the figure loops.) Omitting this tutorial’s JSON display gives you a nice compact report that you can configure to display a variety of averages. For example, you might show a class average by specifying a list of users in the request object. Or you might show the average score for all students that took a specific activity. You could even show a rolling average of the n most recent submissions. The benefit of the no-UI report approach is that you can customize your own reports to your liking.

Figure 1

What You Learned

In this tutorial you learned how to suppress a default report UI and use the resulting data to design your own report. In this case, a score was averaged across 15 sessions of the “Summer_Test_1” activity.