/*
 * This file is part of IMS Caliper Analytics™ and is licensed to
 * IMS Global Learning Consortium, Inc. (http://www.imsglobal.org)
 * under one or more contributor license agreements.  See the NOTICE
 * file distributed with this work for additional information.
 *
 * IMS Caliper is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation, version 3 of the License.
 *
 * IMS Caliper is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License along
 * with this program. If not, see http://www.gnu.org/licenses/.
 */

/* 
 * AngularJS Controller for Sample Caliper Application
 *
 * This controller manages the logic for the Sample Application
 * and uses the sensor service to send Caliper events
 *
 * @author: Prashant Nayak, Intellify Learning; Anthony Whyte, University of Michigan
 */

var app = angular.module('sampleCaliperApp', []);

app.controller('sampleAppCtrl', ['$scope', 'sampleAppSensorService',
  function($scope, sampleAppSensorService, $window, $location) {

    // Model(Flags) for controlling UI
    $scope.syllabusActive = true;
    $scope.readingActive = false;
    $scope.quizActive = false;

    // Model for Annotation (Tags)
    $scope.currentTag = '';
    $scope.readingTags = [];

    // Model for Quiz
    $scope.correctAnswer = false;
    $scope.quizSubmitted = false;
    $scope.currentAttempt = null; // set/get current assessment attempt
    $scope.currentEvent = {};

    $scope.init = function() {
      console.log("INIT: Session started, Caliper = %o");
      $scope.startSession(); // Fire Session Event
    };

    // Controller functions for UI
    $scope.setSyllabusActive = function() {
      $scope.syllabusActive = true;
      $scope.readingActive = false;
      $scope.quizActive = false;
    };

    $scope.setReadingActive = function() {
      $scope.navigateToPage(); // Fire Navigation Event
      $scope.readingActive = true;
      $scope.quizActive = false;
      $scope.syllabusActive = false;
    };

    $scope.setQuizActive = function() {
      $scope.startQuiz(); // Fire Assessment Event
      $scope.quizActive = true;
      $scope.readingActive = false;
      $scope.syllabusActive = false;
    };

    $scope.addTag = function() {
      $scope.readingTags.push($scope.currentTag);
      $scope.addTagsToPage($scope.readingTags); // Fire Annotation Event
      $scope.currentTag = '';
    };

    $scope.submitQuiz = function() {
      $scope.quizSubmitted = true;
      if ($scope.correctAnswer) {
        // if (correctAnswer) {
        $scope.submitQuizToSensor(3.0); // Fire Assessment Event
      } else {
        $scope.submitQuizToSensor(0.0); // Fire Assessment Event
      }
      // Generate an outcome against the quiz submission attempt
      $scope.gradeQuiz();
    };

    $scope.retakeQuiz = function() {
      $scope.quizSubmitted = false;
    };

    //////////////////////////////////////////////////////
    // Controller functions for specific Caliper Events //
    //////////////////////////////////////////////////////

    $scope.startSession = function() {

      // The Actor for the Caliper Event
      var actor = sampleAppSensorService.currentUser;

      // The Action for the Caliper Event (Hint: Use SessionActions)
      var action = Caliper.Actions.SessionActions.LOGGED_IN;

      // The Object being interacted with by the Actor (edApp)
      var edApp = sampleAppSensorService.edApp;

      // Event starteAtTime
      var currentTimeMillis = (new Date()).getTime();

      // The generated object (Session) within the Event Object
      var generatedSession = new Caliper.Entities.Session("https://imsglobal.org/sampleCaliperApp//session-123456789");
      generatedSession.setName("session-123456789");
      generatedSession.setDescription(null);
      generatedSession.setActor(actor);
      generatedSession.setStartedAtTime(currentTimeMillis);
      generatedSession.setEndedAtTime(null);
      generatedSession.setDuration(null);
      generatedSession.setDateCreated(currentTimeMillis);

      // The edApp that is part of the Learning Context
      var edApp = sampleAppSensorService.edApp;

      // The LIS Course Section for the Event (part of Learning Context)
      var course = sampleAppSensorService.course;

      // Create the Session Event (Uncomment and set references to objects)
      var sessionEvent = new Caliper.Events.SessionEvent();
      sessionEvent.setActor(actor);
      sessionEvent.setAction(action);
      sessionEvent.setObject(edApp);
      sessionEvent.setGenerated(generatedSession);
      sessionEvent.setGroup(course);
      sessionEvent.setEdApp(edApp);
      sessionEvent.setStartedAtTime(currentTimeMillis);

      // console.log('created session event %O', sessionEvent);

      $scope.currentEventType = 'Session Event (LOGGED IN)';
      $scope.currentEvent = sessionEvent;

      // Send the event (check RequestBin for event JSON)
      sampleAppSensorService.send(sessionEvent);
    };

    // Navigation Event
    $scope.navigateToPage = function() {

      // The Actor for the Event
      var actor = sampleAppSensorService.currentUser;

      // The Action for the Event
      var action = Caliper.Actions.ReadingActions.NAVIGATED_TO;

      // The Object (Reading) being interacted with by the Actor
      var eventObj = sampleAppSensorService.reading;

      // The target object (frame) within the Event Object
      var targetObj = sampleAppSensorService.readingFrame;

      // The edApp that is part of the Learning Context
      var edApp = sampleAppSensorService.edApp;

      // The LIS Course Section for the Event (part of Learning Context)
      var course = sampleAppSensorService.course;

      // Specific to the Navigation Event - the location where the user navigated from
      var navigatedFromObj = sampleAppSensorService.courseHomePage;

      // Event starteAtTime
      var currentTimeMillis = (new Date()).getTime();

      // Create the Navigation Event
      var navigationEvent = new Caliper.Events.NavigationEvent();
      navigationEvent.setActor(actor);
      navigationEvent.setAction(action);
      navigationEvent.setObject(eventObj);
      navigationEvent.setTarget(targetObj);
      navigationEvent.setEdApp(edApp);
      navigationEvent.setGroup(course);
      navigationEvent.setStartedAtTime(currentTimeMillis);
      navigationEvent.setNavigatedFrom(navigatedFromObj);

      console.log('created navigation event %O', navigationEvent);

      $scope.currentEventType = 'Navigation Event';
      $scope.currentEvent = navigationEvent;

      // Send the event (check RequestBin for event JSON)
      sampleAppSensorService.send(navigationEvent);
    };

    // BOOTCAMP EXERCISE # 1: Add Missing properties for TagAnnotation Event
    $scope.addTagsToPage = function(tags) {

      // The Actor for the Event
      var actor = sampleAppSensorService.currentUser;
      // The Action for the Event
      var action = Caliper.Actions.AnnotationActions.TAGGED;
      // The Object (Reading) being interacted with by the Actor
      var object = sampleAppSensorService.readingFrame;

      //use prepared entity
      var generated = new Caliper.Entities.TagAnnotation("https://imsglobal.org/sampleCaliperApp/tags/7456");
      generated.setTags(tags);
      //console.log(generated);

      // The target object (frame) within the Event Object
      var targetObj = sampleAppSensorService.readingFrame;
      // The edApp that is part of the Learning Context
      var edApp = sampleAppSensorService.edApp;
      // The LIS Course Section for the Event (part of Learning Context)
      var course = sampleAppSensorService.course;
      // Event starteAtTime
      var currentTimeMillis = (new Date()).getTime();

      // Create the Annotation Event
      var tagAnnotationEvent = new Caliper.Events.AnnotationEvent();
      tagAnnotationEvent.setActor(actor);
      tagAnnotationEvent.setAction(action);
      // tagAnnotationEvent.setObject(eventObj);
      tagAnnotationEvent.setObject(object);
      tagAnnotationEvent.setGenerated(generated);
      // tagAnnotationEvent.setTarget(targetObj);
      tagAnnotationEvent.setEdApp(edApp);
      tagAnnotationEvent.setGroup(course);
      tagAnnotationEvent.setStartedAtTime(currentTimeMillis);

      console.log('created annotation event %O', tagAnnotationEvent);

      $scope.currentEventType = 'Annotation Event';
      $scope.currentEvent = tagAnnotationEvent;

      // Send the event (check RequestBin for event JSON)
      sampleAppSensorService.send(tagAnnotationEvent);
    };

    // Quiz Start Event
    $scope.startQuiz = function() {

      // The Actor for the Caliper Event
      var actor = sampleAppSensorService.currentUser;

      // The Action for the Caliper Event
      var action = Caliper.Actions.AssessmentActions.STARTED;

      // The Object being interacted with by the Actor
      var quizObject = sampleAppSensorService.quiz;

      // The target object (frame) within the Event Object
      var targetObj = null;

      // Event starteAtTime
      var currentTimeMillis = (new Date()).getTime();

      // The generated object (Attempt) within the Event Object
      var generatedAttempt = new Caliper.Entities.Attempt("https://some-university.edu/deptOfPhysics/2014/physics101/assessment1/attempt1");
      generatedAttempt.setName(null);
      generatedAttempt.setDescription(null);
      generatedAttempt.setActor(actor['@id']);
      generatedAttempt.setAssignable(quizObject['@id']);
      generatedAttempt.setDateCreated(currentTimeMillis);
      generatedAttempt.setDateModified(null);
      generatedAttempt.setCount(1);
      generatedAttempt.setStartedAtTime(currentTimeMillis);
      generatedAttempt.setEndedAtTime(null);
      generatedAttempt.setDuration(null);

      $scope.currentAttempt = generatedAttempt; // set so that submit quiz event can reference

      // The edApp that is part of the Learning Context
      var edApp = sampleAppSensorService.edApp;

      // The LIS Course Section for the Event (part of Learning Context)
      var course = sampleAppSensorService.course;

      // Create the Assessment Event
      var assessmentEvent = new Caliper.Events.AssessmentEvent();
      assessmentEvent.setActor(actor);
      assessmentEvent.setAction(action);
      assessmentEvent.setObject(quizObject);
      assessmentEvent.setTarget(targetObj);
      assessmentEvent.setGenerated(generatedAttempt);
      assessmentEvent.setEdApp(edApp);
      assessmentEvent.setGroup(course);
      assessmentEvent.setStartedAtTime(currentTimeMillis);

      console.log('created assessment event %O', assessmentEvent);

      $scope.currentEventType = 'Assessment Event (STARTED)';
      $scope.currentEvent = assessmentEvent;

      // Send the event (check RequestBin for event JSON)
      sampleAppSensorService.send(assessmentEvent);
    };

    // BOOTCAMP EXERCISE # 2: Quiz Submit Event
    $scope.submitQuizToSensor = function(score) {
      console.log("##########Sending Quiz Submit Event");
      console.log("score:" + score);

      // The Actor for the Caliper Event
      var actor = sampleAppSensorService.currentUser;

      // The Action for the Caliper Event
      var action = Caliper.Actions.AssessmentActions.SUBMITTED;

      // The Object being interacted with by the Actor
      var quizObject = sampleAppSensorService.quiz;

      // The target object (frame) within the Event Object
      var targetObj = null;

      // Event starteAtTime
      var currentTimeMillis = (new Date()).getTime();

      // The generated object (Attempt) within the Event Object
      var generatedAttempt = new Caliper.Entities.Attempt("https://some-university.edu/deptOfPhysics/2014/physics101/assessment1/attempt1");
      generatedAttempt.setName(null);
      generatedAttempt.setDescription(null);
      generatedAttempt.setActor(actor['@id']);
      generatedAttempt.setAssignable(quizObject['@id']);
      generatedAttempt.setDateCreated(currentTimeMillis);
      generatedAttempt.setDateModified(null);
      generatedAttempt.setCount(1);
      generatedAttempt.setStartedAtTime(currentTimeMillis);
      generatedAttempt.setEndedAtTime(null);
      generatedAttempt.setDuration(null);

      $scope.currentAttempt = generatedAttempt; // set so that submit quiz event can reference

      // The edApp that is part of the Learning Context
      var edApp = sampleAppSensorService.edApp;

      // The LIS Course Section for the Event (part of Learning Context)
      var course = sampleAppSensorService.course;

      // Construct Event
      // Create the Assessment Event
      var assessmentEvent = new Caliper.Events.AssessmentEvent();
      assessmentEvent.setActor(actor);
      assessmentEvent.setAction(action);
      assessmentEvent.setObject(quizObject);
      assessmentEvent.setTarget(targetObj);
      assessmentEvent.setGenerated(generatedAttempt);
      assessmentEvent.setEdApp(edApp);
      assessmentEvent.setGroup(course);
      assessmentEvent.setStartedAtTime(currentTimeMillis);
      console.log('created assessment event %O', assessmentEvent);

      $scope.currentEventType = 'Assessment Event (SUBMITTED)';
      $scope.currentEvent = assessmentEvent;

      // Send the event (check RequestBin for event JSON)
      sampleAppSensorService.send(assessmentEvent);
    };

    // BOOTCAMP EXERCISE # 3: Grade Quiz Event
    $scope.gradeQuiz = function() {
      console.log("##########Sending Outcome Event");

      // Construct Event

      // Send the event (check RequestBin for event JSON)
      sampleAppSensorService.send(assessmentEvent);
    };

    $scope.init();
  }
]);
<!DOCTYPE html>
<html ng-app="sampleCaliperApp">

<head lang="en">
  <meta charset="utf-8">
  <title>IMS Caliper Analytics&trade; Sample Application</title>

  <!-- required libraries and CSS -->
  <link href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.2/css/bootstrap.min.css" rel="stylesheet">
  <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
  <script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.13/angular.min.js"></script>
  <script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.2/js/bootstrap.min.js"></script>
  <script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/3.2.0/lodash.min.js"></script>

  <!-- caliper-js -->
  <script src="http://www.imsglobal.org/caliper/caliperSensor-0.9.6.js"></script>

  <!-- Plunkr JS and CSS -->
  <link rel="stylesheet" href="style.css">
  <script src="app.js"></script>
  <script src="sampleAppContextService.js"></script>
  <script src="sampleAppSensorService.js"></script>
</head>

<body ng-controller="sampleAppCtrl">

  <!-- Set up the Course Tabs -->
  <div class="container-fluid">
    <ul class="nav nav-tabs">
      <li role="presentation" ng-class="syllabusActive ? 'active' : 'inactive'"><a ng-click="setSyllabusActive()">Course Home</a>
      </li>
      <li role="presentation" ng-class="readingActive ? 'active' : 'inactive'"><a ng-click="setReadingActive()">Reading</a>
      </li>
      <li role="presentation" ng-class="quizActive ? 'active' : 'inactive'"><a ng-click="setQuizActive()">Quiz</a>
      </li>
    </ul>
  </div>

  <div class="container-fluid">
    <div ng-show="syllabusActive">
      <h3>Course Syllabus</h3>
      <div class="btn-group-vertical" role="group" aria-label="...">
        <a ng-click="setReadingActive()">Complete Reading</a>
        <br/>
        <a ng-click="setQuizActive()">Take a Quiz</a>
      </div>
    </div>
    <div ng-show="readingActive">
      <h3>Reading</h3>
      <h5>States of Matter</h5>
      <p>
        In physics, a state of matter is one of the distinct forms that matter takes on. Four states of matter are observable in everyday life: solid, liquid, gas, and plasma. Many other states are known such as Bose–Einstein condensates and neutron-degenerate matter but these only occur in extreme situations such as ultra cold or ultra dense matter. Other states, such as quark–gluon plasmas, are believed to be possible but remain theoretical for now. For a complete list of all exotic states of matter, see the list of states of matter.
      </p>
      <p>
        Historically, the distinction is made based on qualitative differences in properties. Matter in the solid state maintains a fixed volume and shape, with component particles (atoms, molecules or ions) close together and fixed into place. Matter in the liquid state maintains a fixed volume, but has a variable shape that adapts to fit its container. Its particles are still close together but move freely. Matter in the gaseous state has both variable volume and shape, adapting both to fit its container. Its particles are neither close together nor fixed in place. Matter in the plasma state has variable volume and shape, but as well as neutral atoms, it contains a significant number of ions and electrons, both of which can move around freely. Plasma is the most common form of visible matter in the universe.[1]
      </p>
      <br>
      <br>
      <form name="tagsForm" class="form-inline">
        <div class="form-group">
          <label for="tag">Enter Tag</label>
          <input type="text" class="form-control" ng-model="currentTag" id="tag" placeholder="-- enter tag --">
        </div>
        <button ng-click="addTag()" class="btn btn-default">Add</button>
      </form>
      <br>
      <br>
      <span>My Tags = {{readingTags}}</span>
    </div>
    <div ng-show="quizActive">
      <h3>Quiz</h3>
      <h5>States of Matter</h5>
      Which one of these is not a valid state of matter?
      <form name="myForm" ng-show="quizActive">
        <input type="checkbox" ng-model="plasma">Liquid
        <br/>
        <input type="checkbox" ng-model="solid">Solid
        <br/>
        <input type="checkbox" ng-model="correctAnswer">Plasmoid
        <br/>
        <input type="checkbox" ng-model="gas">Gas
        <br/>
        <br/>
      </form>
      <button ng-click="submitQuiz()">
        Submit
      </button>
      <button ng-click="retakeQuiz()">
        Reset
      </button>
      <br>
      <br>
      <span ng-show="quizSubmitted">Message = You answered correctly {{correctAnswer}}</span>
    </div>
  </div>

  <br><br>
  <div class="container-fluid">
    <div class="panel panel-success">
      <div class="panel-heading">
        <h3 class="panel-title">Last Caliper Event: {{ currentEventType }}</h3>
      </div>
      <div class="panel-body">
        <pre>{{ currentEvent | json }}</pre>
      </div>
    </div>
  </div>

</body>

</html>
/* Put your css in here */

# IMS Global Caliper Analytics &#0153; Sample Application

Sample application that utilzes the Caliper Javascript sensor.

This application leverages the Caliper Metric Profiles to generate sequences of events.

The application is modeled as a simple Course delivery app, that delivers a syllabus, reading and quiz.


##### Prerequisites:
* Familiarity with Javascript
* Familiarity with AngularJS (or atleast an understanding of MVC)

### Instructions for Caliper Bootcamp:

* **IMPORTANT**: First, create a copy of this sample application for yourself by clicking the "Fork" link (see links above)
* Update line 16 in index.html with the URL of the caliper-js library (this will be provided to you by IMS)
* Create a new request bin that you will use to send/inspect Caliper Events during the bootcamp (http://requestb.in/)
* Update the 'path' attribute on line 39 in sampleAppSensorService.js with your request bin id
* Click "Run" 
* Refresh the request bin page - you should see Caliper Events sent by the sample app as you navigate through the app.

### Bootcamp Exercises:

#### Caliper Bootcamp Exercise #1 - Add missing TagAnnotation properties
* Add missing TagAnnotation properties for a user tagging a reading.
* You will need to fill in the function $scope.addTagsToPage() in app.js

#### Caliper Bootcamp Exercise #2 - Quiz Submission 
* Add a Quiz Submitted event indicating user submitting an attempt on the quiz
* You will need to fill in the function $scope.submitQuizToSensor() in app.js

#### Caliper Bootcamp Exercise #3 - Quiz Grading  
* Add a Quiz Graded event indicating that the system graded an attempt on the quiz
* You will need to create a new function $scope.gradeQuiz() in app.js
 
#### Caliper Bootcamp Exercise #4 -- Membership entity
* Add missing membership entity to all events

&copy; 2015 IMS Global Learning Consortium, Inc. All  Rights Reserved. 

&#0153; [Trademark  Information](a href="http://www.imsglobal.org/copyright.html")
/*
 * This file is part of IMS Caliper Analytics™ and is licensed to
 * IMS Global Learning Consortium, Inc. (http://www.imsglobal.org)
 * under one or more contributor license agreements.  See the NOTICE
 * file distributed with this work for additional information.
 *
 * IMS Caliper is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation, version 3 of the License.
 *
 * IMS Caliper is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License along
 * with this program. If not, see http://www.gnu.org/licenses/.
 */

/* 
 * Sample App Sensor Service
 *
 * This service wraps the caliper-js sensor, enabling any application specific 
 * logic to be performed before sending events using the base Javascript sensor
 *
 * @author: Prashant Nayak, Intellify Learning; Anthony Whyte, University of Michigan
 */
angular.module('sampleCaliperApp')
  .factory('sampleAppSensorService', ['sampleAppContextService', function(sampleAppContextService) {

    // Initialize Caliper sensor with options
    var sensor = Caliper.Sensor;

    // Note that you will have to create a new request bin
    // by navigating to http://requestb.in/
    // and replace the "path" setting below with the path 
    // to your request bin
    sensor.initialize('http://example.com/sensor/1',{
       host: 'requestb-in-1h04eq0e08pc.runscope.net',
      //host: '52.10.53.39',
       path: '/172jilj1', // REPLACE WITH YOUR REQUEST BIN PATH
      //path: '/log.php', // REPLACE WITH YOUR REQUEST BIN PATH
      withCredentials: false
    });

    // Wrapper around Caliper Sensor's send()
    var send = function(event) {

      // Perform any pre-processing, etc.

      // Send Events using Caliper Sensor
      sensor.send(event);
    };

    // Wrapper around Caliper Sensor's describe()
    var describe = function(entity) {

      // Perform any pre-processing, etc.

      // Describe Entities using Caliper Sensor
      sensor.describe(entity);
    };
    
    // Export the functions that will be used by controller
    var exports = {
      describe: describe,
      send: send,
      currentUser: sampleAppContextService.getUser(),
      reading: sampleAppContextService.getReading(),
      readingFrame: sampleAppContextService.getReadingFrame(),
      edApp: sampleAppContextService.getEdApp(),
      course: sampleAppContextService.getCourse(),
      courseHomePage: sampleAppContextService.getCourseHomePage(),
      quiz: sampleAppContextService.getQuiz()
    };

    return exports;
  }]);
/*
 * This file is part of IMS Caliper Analytics™ and is licensed to
 * IMS Global Learning Consortium, Inc. (http://www.imsglobal.org)
 * under one or more contributor license agreements.  See the NOTICE
 * file distributed with this work for additional information.
 *
 * IMS Caliper is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation, version 3 of the License.
 *
 * IMS Caliper is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License along
 * with this program. If not, see http://www.gnu.org/licenses/.
 */

/* 
 * Sample App Context Service
 *
 * This service wraps the caliper-js sensor and provides a set of sample Caliper 
 * entities
 *
 * @author: Prashant Nayak, Intellify Learning; Anthony Whyte, University of Michigan
 */
angular.module('sampleCaliperApp')
  .service('sampleAppContextService', function() {

    // Get the current user as a Caliper Actor
    var getUser = function() {
      var currentUserId = "https://example.edu/user/554433";
      // The Actor for the Learning Event
      var actor = new Caliper.Entities.Person(currentUserId);
      actor.setDateCreated((new Date("2015-08-01T06:00:00Z")).toISOString());
      actor.setDateModified((new Date("2015-08-01T06:00:00Z")).toISOString());
      return actor;
    };

    var ePub = {};
    // Get the current Reading
    var getReading = function() {
      ePub = new Caliper.Entities.EPubVolume("https://github.com/readium/readium-js-viewer/book/34843#epubcfi(/4/3)");
      // ePub.setResourceType("EPUB_VOLUME");
      ePub.setName("States of Matter - A Condensed History");
      ePub.setVersion("1.0");
      ePub.setDateCreated((new Date("2015-08-01T06:00:00Z")).toISOString());
      ePub.setDateModified((new Date("2015-08-01T06:00:00Z")).toISOString());
      return ePub;
    };

    var getReadingFrame = function() {
      var ePubFrame = new Caliper.Entities.Frame("https://github.com/readium/readium-js-viewer/book/frame/34843#epubcfi(/4/3/1)");
      // ePubFrame.setResourceType("FRAME");
      ePubFrame.setName("Introduction to the states of matter");
      ePubFrame.setIndex(1);
      ePubFrame.setIsPartOf(ePub);
      ePubFrame.setVersion(ePub.version);
      ePubFrame.setDateCreated((new Date("2015-08-01T06:00:00Z")).toISOString());
      ePubFrame.setDateModified(ePub.dateModified);
      return ePubFrame;
    };
    
     var getTagAnnotation = function(tag) {
      var tag = new Caliper.Entities.TagAnnotion("https://example.com/tags/1234");
      tag.setTags(tag);
      return tags;
    };

    // Get the current edApp
    var getEdApp = function() {
      var edApp = new Caliper.Entities.SoftwareApplication("https://imsglobal.org/sampleCaliperApp");
      edApp.setName("Sample Caliper App");
      edApp.setDateCreated((new Date("2015-08-01T06:00:00Z")).toISOString());
      edApp.setDateModified((new Date("2015-08-01T06:00:00Z")).toISOString());
      return edApp;
    };

    var org = {};
    // Get the current Course
    var getCourse = function() {
      org = new Caliper.Entities.CourseSection("https://example.edu/deptOfPhysics/2014/physics101");
      org.setCourseNumber("Phy-101");
      org.setName("Introductory Physics");
      org.setDescription("This is a Physics course for beginners.")
      org.setName("American Revolution 101");
      org.setCourseNumber("POL101");
      org.setAcademicSession("Fall-2015");
      org.setDateCreated((new Date("2015-08-01T06:00:00Z")).toISOString());
      org.setDateModified((new Date("2015-08-01T06:00:00Z")).toISOString());
      return org;
    };

    // Get Web Page for current Course
    var getCourseHomePage = function() {
      var courseHomePage = new Caliper.Entities.WebPage("Physics101-Course-Homepage");
      courseHomePage.setName("Physics101-Course-Homepage");
      courseHomePage.setIsPartOf(org);
      courseHomePage.setDateCreated((new Date("2015-08-01T06:00:00Z")).toISOString());
      courseHomePage.setDateModified((new Date("2015-08-01T06:00:00Z")).toISOString());
      return courseHomePage;
    };

    // Get Quiz (Assessment) for current Course
    var getQuiz = function() {
      var quiz = new Caliper.Entities.Assessment("https://example.edu/deptOfPhysics/2014/physics101/assessment1");
      quiz.setName("States of Matter - Assessment");
      quiz.setIsPartOf("https://some-university.edu/deptOfPhysics/2014/physics101");
      quiz.setDateModified((new Date("2015-02-02T11:30:00Z")).toISOString());
      quiz.setDateCreated((new Date("2015-01-01T06:00:00Z")).toISOString());
      quiz.setDatePublished((new Date("2015-01-15T09:30:00Z")).toISOString());
      quiz.setDateToActivate((new Date("2015-01-16T05:00:00Z")).toISOString());
      quiz.setDateToShow((new Date("2015-01-16T05:00:00Z")).toISOString());
      quiz.setDateToStartOn((new Date("2015-01-16T05:00:00Z")).toISOString());
      quiz.setDateToSubmit((new Date("2015-02-28T11:59:59Z")).toISOString());
      quiz.setMaxAttempts(2);
      quiz.setMaxSubmits(2);
      quiz.setMaxScore(3.0);

      // The Quiz has one AssessmentItem
      var assessmentItem1 = new Caliper.Entities.AssessmentItem("https://example.edu/deptOfPhysics/2014/physics101/assessment1/item1");
      assessmentItem1.setName("Assessment Item 1");
      assessmentItem1.setIsPartOf("https://example.edu/deptOfPhysics/2014/physics101/assessment1");
      assessmentItem1.setMaxAttempts(2);
      assessmentItem1.setMaxSubmits(2);
      assessmentItem1.setMaxScore(1.0);
      assessmentItem1.setDateCreated((new Date("2015-08-01T06:00:00Z")).toISOString());
      assessmentItem1.setDateModified((new Date("2015-08-01T06:00:00Z")).toISOString());

      return quiz;
    };

    // Export the functions that will be used by other controllers and services
    var exports = {
      getUser: getUser,
      getReading: getReading,
      getReadingFrame: getReadingFrame,
      getEdApp: getEdApp,
      getCourse: getCourse,
      getCourseHomePage: getCourseHomePage,
      getQuiz: getQuiz
    };

    return exports;
  });