Sequencing
Along with Data Validation and Versioning, probably the most vexing problem confronting the Assessment package is how to handle conditional navigation through an Assessment guided by user input. Simple branching has already been accomplished in the "complex survey" package via hinge points defined by responses to single items. But what if branching/skipping needs to depend on combinations of user responses to multiple items? And how does this relate to management of data validation steps? If branching/skipping depends not merely on what combination of "correct" or "in range" data the user submits, but also on combinations of "incorrect" or "out of range" data, how the heck do we do this?
One basic conceptual question is whether Data Validation is a distinct process from Navigation Control or not. Initially we thought it was and that there should be a datamodel and set of procedures for checking user input, the output of which would pipe to a separate navigation datamodel and set of procedures for determining the user's next action. This separation is made (along with quite a few other distinctions/complexities) in the IMS "simple sequencing" model diagrammed below). But to jump the gun a bit, we think that actually it makes sense to combine these two processes into a common "post-submission user input processing" step we'll refer to here as Sequencing. (Note: we reviewed several alternatives in the archived prior discussions here.
So here is our current approach. We note that there are two scopes over which Sequencing needs to be handled:- intra-item: checks pertaining to user responses to a single item
- inter-item : checks pertaining to user responses to more than one item; checks among multiple items will be built up pairwise
So how might we implement this in our datamodel? Consider the
"sequencing" subsystem of the Assessment package:
Specific Entities
- Item-checks (as_item_checks) define 1..n ordered evaluations of
a user's response to a single Item. These can occur either via
client-side Javascript when the user moves focus from the Item, or
server-side once the entire html form comes back. They are
associated (related) to as_items.
The goal is to have a flexible, expressive grammar for these checks to support arbitrary types of checks, which will be input validation ("Is the user's number within bounds?"; "Is that a properly formatted phone number?"). One notion on check_sql. Instead of using comparators we store the whole SQL command that makes up this check with a predefined variable "value" that contains the response of the user to the item the item_check is related to. If we want to make sure the value is between 0 and 1 we store "0 < :value < 1" with the check. Once an item is submitted, the system looks up the related checks for this item and replaces in each of them ":value" with the actual response.
Item Checks thus will have these attributes:
- item_check_id
- cr:name - identifier
- cr:description - Explanation what this check does
- check_location - client-side or server-side
- javascript_function - name of function that gets called when focus moves
- user_message - optional text to return to user if check is
true
- check_sql - The sql that contains the check
- Inter-Item-checks (as_inter_item_checks) are similar to
Item-Checks but operate over multiple Items. They are server sided
checks that are associated with as_sections defining if a section
should be displayed or with as_items, defining if an item should be
displayed.
The goal is to have a way of telling if a section (or an item within a section) shall be displayed or not depending on the section-checks. This way you could say that you only display this section if the response to item(1234) "Color of your eye" was "blue" and the response to item(4231) "Color of your hair" was "red". Sadly we can't use such an easy way of checking the ":value" as we do with item_checks, as we do not know which item this refers to. Instead we store the item_id like this ":item_1234". This way the check_sql would look like ":item_1234 == 'blue' AND :item_4231 == 'red'". Additionally other variables might be defined by the API at a later stage, e.g. ":percent_score", which would be replaced by the current percentage value (aka score) that subject had in the test so far (taken from the as_session_table). It might be interesting to pass these variables along in the API, this remains to be seen when actually implementing the system.
The Inter Item Checks also allow post section navigation (in contrast to the pre section / item navigation mentioned above). If post_check_p is true, the check will be done *after* the user has hit the submit button. Depending on the result of the check (if it is true) the user will be taken to the section given by section_id or to the item given by item_id, depending whether this assessment is section based (questions are displayed in sections) or item based (each item will be displayed on a separate page). If there are multiple post checks for a given section/item the order will be defined by the relationship (which means this relationship has to have a sort_order attribute).- inter_item_check_id
- cr:name - identifier
- cr:description - Explanation what this check does
- user_message - optional text to return to user
- check_sql - The sql that contains the check
- post_check_p - Is this a check that should be executed after
the user hit the submit button while answering the item /
section.
- section_id - Section to call if we are in a section mode (all
items will be displayed in sections) and it is a
post_check.
- item_id - Item to call if we are in "per item" mode (all items will be displayed on a separate page) and it is a post_check.
- Potential extension: item_list - list of item_ids that are used
in the check_sql to speed up the check.