Friday, August 14, 2015

Reverse Engineering the Raw Results of a Multiple Answer Question

I had occasion recently to obtain assessment results out of a recovered database.  One question type that was a bit puzzling was the Multiple Answer where the Answers were randomized to the student.

Say I created a question:

When the student took the test, the answers were randomized, e.g.,

When I extracted the results, I got a data string like

Useful bits:
  • answer_order: 0, 3, 4, 1, 2 (the order answers were displayed to the student); note: the ordinal position is 0.
  • sequence of response_values (the actual selections)
  • score_value: 0.0 (what the student auto-scored)

Does the sequence of response_values corresponded to the original order of answers in the question, or the order of answers displayed to the student?


It is corresponds to the original order of answers in the question.


The question had five answers
  • 3 - position 0
  • 4 - position 1
  • 5 - position 2
  • 6 - position 3
  • 9 - position 4
The question was displayed to the student
  • a. 3 = position 0
  • b. 6 = position 3
  • c. 9 = position 4
  • d. 4 = position 1
  • e. 5 = position 2
That corresponds to the answer order

The student selected a. 3, b. 6, c. 9

That corresponds to the sequence

and so on.

Finally, the student received a score of 0 (in my example, they had to get all the multiple answers correct, no partial credit)

Thursday, April 16, 2015

Finding files uploaded with student assignment tool

We've had a few cases where we've been asked to find student assignment uploads. So where do those files actually go? It depends - on whether you have Content System (CS) or not. Since we do have CS, I'll only talk about that.

Useful queries

Query #1 find the files submitted for a userid/courseid

DECLARE @groupid VARCHAR(40),@courseid VARCHAR(40),@filesizelimit INT
SET @groupid = '%'
SET @courseid = '%'
SET @filesizelimit = '1'
SELECT TOP 100 cm.course_id,g.group_name,f.[file_name],f.file_size,f.dtmodified,ga.score,xy.FULL_PATH as [full path], 'http://BBSERVER/bbcswebdav/xid-'+cast(xy.[FILE_ID] as varchar(10))+'_1' as [file link]
FROM files f WITH (nolock)
INNER JOIN group_attempt_files gaf WITH (nolock) ON f.pk1 = gaf.files_pk1
INNER JOIN group_attempt ga WITH (nolock) ON gaf.group_attempt_pk1 = ga.pk1
INNER JOIN groups g WITH (nolock) ON ga.groups_pk1 = g.pk1
INNER JOIN course_main cm WITH (nolock) ON g.crsmain_pk1 = cm.pk1
INNER JOIN cms_doc.dbo.XYF_URLS xy WITH (NOLOCK) ON xy.FILE_NAME COLLATE SQL_Latin1_General_CP1_CS_AS = f.[file_name]
WHERE g.group_name LIKE @groupid AND cm.course_id LIKE @courseid


 Query #2 - find the file location in the CS storage

 If you DIDN'T have CS then there actually would be a physical /internal/courses folder on your file system. Files uploaded to the Content System, however, are stored in dated subfolders of the respective content area's root folder, such as: /storage/2015/2015-04/2015-04-16/44201/114902.6 – only the database permits tying the file's virtual path (as seen in the GUI) or its unique ID (xid) together with this actual physical path on disk.

What is the filestorage name 114902.6? The first part 114902 is the [XYF_BLOBS].[BLOB_ID] and the .6 refers to the cms_doc database as referenced in [cms].[dbo].[XY_FILE_SYSTEMS].

So 114902.6 would be referenced in [cms_doc].[dbo].[XYF_BLOBS].[BLOB_ID] = 114902

use cms_doc;
DECLARE @courseid VARCHAR(40)
SET @courseid = '%'
WHERE xu.FULL_PATH like '/internal/courses/'+@courseid+'/attempt/%'
and xu.FILE_ID = xf.FILE_ID


Note: CS also does a process called de-duplication, where it figures out if it already has an IDENTICAL of a file, to only keep references to the original file to save space.

In this example, file1.pdf is a sample I've used many times before so the original is stored in /2010/2010-04/2010-04-23/3601/11126.6 even though I "just" uploaded in 2015!

Meanwhile, UnderstandingStorage.pdf is a unique, new file I just uploaded today (2015-04-16) so it is stored in /2015/2015-04/2015-04-16/44201/114902.6

When you clear an assignment attempt

Blackboard will a) remove the database entries (so the two queries will no longer return records for that particular attempt) AND b) remove the FILE_ID from storage (if it is unique). If you went back into storage, you would find an empty folder.

E.g., If we deleted the attempt that had the file UnderstandingStorage.pdf, then /2015/2015-04/2015-04-16/44201/ would still be there, but no 114902.6

Thus, any true recovery of a deleted attempt would be both at the database AND filesystem level.

Wednesday, September 17, 2014

pushconfig without starting tomcat services

Saw this question on BBADMIN-L mailing list which had a useful tip from the community:

Does anyone know if it's possible to run a pushconfig but not start the tomcat processes? I need to do several patches that require a pushconfig but I don't want to wait for the servers to startup and shutdown.


Nick (MSJC): Sure in the pushconfigupdates.bat\sh and pushconfigupdates.bat\ files just comment out the line that calls services.start. 

Miroslav (CSU Chico): Yes. You just need to comment out the starting part out of the script. We do this regularly after each release pack upgrade. Simply edit pushconfig and comment out the part that tells it to start the app node. We also usually change the text so it says NOT STARTING at the end.
This needs to be an option when upgrading as well. We pretty much never want the system to start up immediately after upgrade finishes.

Friday, August 15, 2014

IMS LTI Launch Test

IMS LTI Launch Test

The prior IMS LTI test site I was using (see my older blog post) no longer seemed to work.

I found a new one thanks to the JISC-funded ceLTIc (

There are two ways you can use IMS LTI in Blackboard:

  • Using Oscelot Basic LTI tool
  • Using Blackboard's IMS LTI Tool Provider

I've included both ways to add the IMS LTI tool.

I. Using Oscelot Basic LTI tool

1. Install and configure Oscelot Basic LTI 

 2. Register New Tool

  1. Go to System Administration tab
  2. then  Basic LTI tools (under the Tools section)
  3. click on Register New Tool
  4. Enter
    • Name: IMS LTI Launch Test
    • Launch URL:
    • Consumer Key:
    • Shared Secret: secret 
  5. Submit
Should look like

After Register New Tool

3. Edit Data Settings for this new tool

  1. Select Edit data settings (pull-down) for this new toolname
  2. Enter
    • Context ID: Check
    • Value to use for Context ID: Database key (default)
    • Context sourceId: Check
    • Context Title: Check
    • User ID: Required by tool
    • Value to use for user ID: Batch UID (default)
    • SourceId: Check
    • User name: Required by tool
    • Email: Required by tool
    • Role Mappings:
      • Instructor to Instructor
      • Student to Learner
      • Teaching Assistant to Instructor (or Teaching Assistant)
  3. Submit
Should look like: 
After Data Settings

4. Edit Launch Settings for this new tool

  1. Select Edit launch settings (pull-down) for this new toolname
  2. Enter
    • Open tool in: select New window
  3. Submit
Should look like:

5. Enable the tool and configure how to display it

  1. Pulldown by toolname, choose Enable
  2. Pulldown by toolname, choose Add as course tool
  3. Checkbox the toolname, choose Display on Menu: Tools
After enabling the tool and configuring of Display on Menu

II. Using Blackboard's IMS LTI Tool Provider

Blackboard has had Basic LTI support since 9.1SP4.

1. Register Provider Domain

  1. Go to System Administration tab
  2. then Building Blocks
  3. then LTI Tool Providers
  4. Click on Register Provider Domain
  5. Enter
    • Provider domain:
    • Provider Domain Status: Approved
    • Default Configuration: Set separately for each link
    • Send User Data: Send user data only over any connection (note: I'd prefer over SSL)
      • User Fields To Send
      • Role in Course: check
      • Name: check
      • Email Address: check
  6. Submit
Should look like

After Provider is Registered

3. Set up Tool Placement

  1. Click on the '0' under Placements for the row of the provider (
  2. Create Placement
  3. Enter
    • Label: IMS LTI Launch Test
    • Handle: imsltilaunchtest
    • Type: Student Tool (for simplicity)
    • Tool Provider URL:
    • Tool Provider Key:
    • Tool Provider Secret: secret
  4. Submit
Should look like:
After Placement Created

III. Now that LTI is set up we can use it in a course

1. Add tool to your course

  1. Go into your course as an Instructor
  2. Go into a content area/folder
  3. Under Tools menu, you should see the new toolname (e.g., IMS LTI Launch Test)
  4. Select the new toolname
  5. Submit
Adding LTI (e.g., IMS LTI Launch Test)  to the Course
After LTI (e.g., IMS LTI Launch Test) added to Course

2. Test the tool (as instructor, as student)

Note: beware browser security measures, e.g., pop-up blocking, content blocking (since we're loading an insecure page)
  1. Click on the toolname link you added
    • If you are using the Oscelot Basic-LTI : It should open a new window
    • If you are using the Bb LTI Tool Provider : It should open in the lower frame (yeah, no choice to open in a new window)
  2. The should load and display various POST parameters
Oscelot Basic-LTI Launch should look like:
Bb LTI Tool Provider Launch should look like:

Friday, June 14, 2013

Content Editor and WIRIS supports LaTeX in 9.1SP12

Blackboard 9.1SP12's Content Editor comes with revised WIRIS plugin which no longer requires Java.
Here's an example where I have the LaTeX formula for the Quadratic Equation in the Content Editor.  The LaTeX formula is delineated with the "$$"

Note: currently the Content Editor > Preview does not render the equation.  So the only way to tell that the equation is correct is to submit your changes, then view the resulting item.

Tuesday, March 19, 2013

Copy/Paste when using the Content Editor with Firefox

There's a security setting in Firefox that prevents javascript-based HTML editors from accessing your clipboard.

There's a workaround using a Firefox add-on called AllowClipboard Helper

Some documentation written by Ottawa University:


Monday, July 2, 2012

Wishlist/Enhancements to 9.1SP8 cross-listing/merge enrollments

I'm coming up with a list of enhancements we'd like to see for the current 9.1SP8 cross-listing/merge enrollments feature.  We're coming from the Bb Section Merge Tool (SMT), so some of it comes from features we've used there.

  • Allow instructors to create the merge 
  • Allow one-to-many feeds (e.g., one source site could be the child of multiple target sites) 
  • Document some migration path between the SMT and the new course merge 
  • Instructors > My Courses module should indent the child sites (and allow for expansion/collapse) or allow child sites to be hidden completely from view 

  • Tools that communicate with students (Announcements, Messages, Send Email) should be able to use Child Course membership to select audience 
  • Adaptive Release should be able to use Child Course membership 
  • Groups should be able to use Child Course membership when creating groups 
  • Grade Center / SmartViews - allow criteria Child Course ID condition "is blank" or "does not contain" (which is useful if you are merging enrollments into section 01 for instance, and want a smartview of section 01) 

Before I submit, I wanted to see if anyone else had things on their wish list...