Display Time (CP2019)

Intro

Almost 10 years ago I wrote a blog post to answer user question  quote: “…. if there was anyway to insert running time”.
The user wanted a display on all slides of the time information you can find  in the TOC (total duration of the project and elapsed duration).  Total duration can be found also in the panel ‘Project Info’ in Captivate, which shows global project information (number of slides/frames). In this panel you can also check the expected size of the output file.
Total duration is calculated as the sum of slide durations. Similar the elapsed duration:is calculated as the sum of the duration of the slides before the currently viewed slide. I would call that type of duration ‘developer time’. 

Developer time can be very different from the real time spent by the user viewing slides in that project.  You’ll see in this refurbished article how to show both times, developer and real ones. It is a nice use case for System variables.  BTW, if you didn’t get my free table with System variables, maybe it is the right moment .

Contrary to the old post, which was meant for SWF output, I used JS this time instead of advanced actions with the Expression command.  Reason is that for SWF output the formatting of the variable values could be controlled by the number of characters to display when inserting the variable in a text container. That is not working for HTML5 output. Formatting of numbers is a typical use case (like random data) where I tend to use JavaScript.

Example output

Watch this published movie. The described workflow (from the original post) is working only for linear projects. Sorry for the use of TTS, those slides are based on a longe project….in Dutch.



 
The ‘developer time’ is shown in the top left corner: total project time (secs), time of the previously viewed slides (secs) and percentage viewed.

Real time workflow

The real time is visible at the bottom, next to my name. I used the Timer widget for the real time.  You have to be careful: set the maximum time to a high number, to avoid triggering the end of time action. Getting rid of the background is easy, have a look at my setup.:
 
 

Developer's time workflow

As I announced at the start, for several reasons I preferred to use JS instead of Expressions in an Advanced action as was the case for the older blog post. I propose two scripts. The first one is close to the older blog post, because I use the same system variables, and two methods of the JS interface for Captivate. Details can be found in this document.

In the second script I skipped using the known system variables, replaced them by some more methods of the same document.

Script 1

Variables

The system variables used in the first script are:

  • cpInfoFrameCount: its value is the total number of frames in the Project Info panel (see first screenshot in this article)
  • cpInfoFPS: each movie is played at a certaing speed, which defines its qualtiy. It is indicated as Frames per Second. The higher that rate, the higher the quality
  • cpInfoCurrentFrame: indicates the present frame number. Frames are numbered, starting with 0, not per slide but for the whole project. More details can be found in this blog post about Micro-navigation

In Captivate I created these user variables to display the results in the project:

  • v_total: total duration of the project in seconds
  • v_done: sum of the duration of the previous slides in seconds
  • v_perc: percentage of duration viewed, in %

To avoid confusion, variables in JavaScript used these names:

  • frames: will start with the value of cpInfoFrameCount and end after calculation return the total project duration (secs) 
  • start: will start with a frame number (frist frame of the present slide) and after calculation return the alreadu viewed duration (secs)
  • speed: will store the value of cpInfoFPS
  • percent: will return the percentage viewed after calculation

Javascript

This script has to be triggered On Enter for each slide. That can be directly with the command 'Execute JavaScript' as simple action if you don't need any other commands to be done on entering the slide. If no slide nneeds any extra commands, you can select all slides in the Filmstrip and attach the script to all slides at once. If you need more for some slides, it could be a good idea to use the script in an advanced action, where you can add more commands. Even a shared action is possible, but in this example had no real sense.

Have a look at the script:

I am using two methods from the Common JS Interface:

  • getVariableValue to store the values of Captivate's system variables in the JS variables frames, speed, start. (lines 1-3)
  • setVariableValue to return the results to the Captivate variables v_total, v_done and v_perc (lines 6-7,9)

The calculations in lines 4-5 and 8 are straightforward. To control the formatting of the numbers I used the method 'Number.toFixed(x)'. I didn't want to display two decimals for a simple reason: the first frame will be detected on each slide, and that would have led to a duration of 0,03 seconds on the first slide (30 seconds in a frame). It would be possible to split up the results in minutes and seconds as well. I wanted this example to be a simple introduction to JS newbies. I planned to use the formatting in a third article about numbers. The first two were 'Playing with numbers - part 1' and 'Playng with numbers - part 2'. Both were meant as simple intro to JS for newbies. However, since they didn't get a lot of viewers, I gave up spending more time on it.

Script 2

No system variables here, the user variables and variables in JS are the same as in the first script: v_total, v_done, v_perc, frames, speed, start, percent.. Have a look at the script:

I didn't need the method getVariableValue in this case but used three more methods on top of setVariableValue to return the results to Captivate:

  • getPlaySpeed: returns the same value as the system variable cpInfoFPS (line 1)
  • getCurrentFrame: returns the same value as the system variable cpInfoCurrentFrame (line 2)
  • getDurationInSeconds: spares me one calculation, this value doesn't exist as system variable. This time I don't have to divide the total number of frames (exists as getDurationInFrames) by the FPS value. (line 3)

The other lines in the script are similar to those explained in the first script.



Random Questions; Do's and Don'ts

Intro

It may be a coincidence but recently multiple questions appeared s about using random question slides

  • :Why is it impossible to control custom objects on slides in question pools like Show/hide for a custom feedback in Review mode?
  • How can you create and use a timer for a quiz which has random questions,, and have actions done when a certain time has elapsed? Or show warnings when time has almost elapsed?
  • How can I use remediation for random slides?

There are of course the usual questions like: can I use random question ir Pretest, as Knowledge Check slides (now also in Interactive video), or quiz slides on hotspots  in a VR project?  Can I have a new subset of random ausetions at a new attempt...

In this post I want to explain why some of those workflows are impossible. For some use cases I have a workaround, will mention it but not offer it for free.

Tips for Question pools

You are for sure aware of the fact that all quiz slides, whatever the type, are based on the quizzing master slide (4)s, and the results slide on another master slide. Whether you are working with a responsive or a  non-responsive project, make sure to set up those master slides fully before creating the pools. That means; checking the object styles and edit them when necessary, check the sizes of the embedded objects. One example: if you expect to have long answers, make the answer area as big as possible, maybe by decreasing the height of the feedback messages and other objects. Do never delete an embedded object (they have no individual timeline). If you can uncheck some in the Quiz Preferences, that is fine. Do not forget to check the Default labels under Quiz Preferences. Please do never override object styles. This is eve more important for pools than for normal quiz slides. once I had to edit the master slides quite a lot in consultancy job because the developer has deleted embedded objects. Several pools were connected with the project. Updating the course after having edited the master slides took quite long, needed kot of coffee breaks.

I also prefer to use GIFT files (or the new CSV files) over editing all quiz slides individually. RE-importing a GIFT file is a lot less work than having to edit each individual quiz slide. It is even more important if you need the course in multiple languages.

You probably want all learners to have the same possible total score? In that case you'll need to give the same max score to each question in the pool.  Or use multiple question pools, each with a different score. I feel a T/F question is not 'deserving' the same score as a complicated MCQ  question. Keep the easier questions with a lower score in one pool, the more complicated in another pool.

Examples with (eventually) workarounds

1. New subset of random questions for new attempt in same session

As I understand the workflow with random questions generated from question pools on runtime: each random question placeholder will be replaced by one question from the associated pool based on a random number. That random number will then be excluded for the next random question. At the end all the random question have been generated and are treated like normal quiz slides, based on the setup in Quiz Preferences. They become static, the generating process will not be repeated when a new attempt on Quiz level is started. To confirm my suspicion I added a custom object to the pool questions, that object only appears when you insert new random questions, not on existing questions: there is no dynamic link between the pool and the inserted questions.

Workaround: you need to close the session, and restart the course. If you are transmitting to a LMS with bookmarking (Resume data), the number of attempts will be taken into account.

2. Random questions for Pretest/Knowledge Check slides

There is no possibility to use question pools for these slides, at this moment (log a feature request please) 

Workaround: use normal random quiz slides for them. For Pretest slides you'll not be able to store the data in the Pretest quizzing variables. If you have real quiz slides in the course, you have to be careful. You can convert the imported random slide in a Survey question (could be used of KC slides), or you can uncheck the option 'Reporting'. In both cases the score and percentage on the results slide will be correct, but some quizzing systerm variables will still take into account all questions as you coudl read in my blog about Quizzing System variables. 

3. Random questions in VR projects

You cannot use random questions on hotspots in a VR project. 

Workaround: insert 360 slides i a normal cptx project. Insert random question slides in that project. Use a  Guided status for the hotpsots which show content. The last hotspot can be used to navigate to the random question slides. Beware: when inserting 360 slides in a normal cptx-project the opion to have Overlay  Question slides attached to hotspots disappears. More info in this article.

4. Random questions in Interactive Video

Overlay Knowledge Check slides are supported for Interactive Video. But like normal KC slides, they cannot be random.

Workaround: Use norma random slides which cannot be used as overlay slides. However, you can use bookmarks to navigate to the slides, then navigate back to the video. I will post a blog about this workflow in the near future. 

5. Controlling custom objects in random slides

You can add custom objects to pool questions or even to the master slides, but be careful: for HTML output the stacking order will always be respected (I had a workaround for SWF output). That means that the embedded Quizzing objects will always be on top of the custom objects. Embedded objects do not have an individual timeline, not on the quizzing master slide nor on the quiz slide. You should never delete those embedded objects,  Some  can be unchecked in the Quiz Properties panel (examples: Clear button, Back button, Feedback messages), others not (Question title, Question, Submit button...).

You can have an Advanced/Shared action on a pool question for the On Enter event (quiz slides never have an On Exit event).  A user wanted to use that action to make a custom object visible only in Review mode, using the quizzing system variable cpInReviewMode. That is a workflow which works perfectly on normal quiz slides. The variable is available for pool questions as well, but.... you cannot reference custom objects on the quiz slide. The added custom objects will never appear in the dropdown list for Show, Hide, Disable, Enable.... The user thought this to be a bug, but I don't agree and will try to explain my intuition.

When you add a random quiz slide to a project, as I mentioned it will be generated from the associated question pool. I suspect this to be a copy/paste act.: based on a random number a copy of a pool question is placed in the Captivate project. You probably have experienced in the past the effect of copy/paste to labels? Since every object needs a unique name, the names of the objects on the inserted random question will have a name 'similar' to the name in the original pool question but not the same name.  The advanced action should have been self-edited to reflect that name change. That seems not to be possible, hence the fact that custom objects do not appear in dropdown lists for pool questions. Same happens when you copy/paste a normal slide which has Advanced  attached to the slide events: in most cases those actions will be broken.  It is one of the reasons I always recommend to use Shared actions whenever possible, especially for slide event actions. It is a lot easier to repair the action in that case. However, for random questions that is not possible, you cannot attach a Shared action to a random question, you have to rely on the actions in the pool questions. 

Workaround: I do have a workaround which works perfectly, but I will not offer that one for free. 

6. Using Timer for random slides.

Captivate has a TImer and Hourglass interaction with similar features. You can also time using system variables and advanced/shared actions or JS. 

To use them for random slides, you need to insert the interaction before the first random slide on a normal slide which can be very short. However those interactions are not working very 'exactly', hence I always combine them with system variables.  No details about my workflow. 

7. Remediation workflow

A user asked if remediation would work for random slides, and there my answer is No. It looks very logical to me why this is an impossible workflow using question pools and random questions. Remediation means you have to link to a content slide from the quiz slide on Failure. The content slide needs to have the special command 'Return to Quiz' on a custom Next button. That action will only work when the learner gets to that content slide from a quiz slide, in other situations the Next button will proceed to the Next slide.

Why is this not possible with random questions? A question pool can be used in many files, how ca you exactly define the name or the slide number of the content slide to link to?  You need an absolute navigation link to that content slide, which is totally impossible.

Workaround: do not use a pool, but insert all the questions (with link tot the content slides) in the course. Navigate to a question based on a random generated number (with JS). Make sure that you don't reuse the same random number twice, nor that the non-selected questions can be visited. Turn on Branch Aware in the Quiz Preferences to have a correct value for the quizzing variables on the score slide. A lot of work!