From WeBWorK_wiki
Jump to navigation Jump to search
This article has been retained as a historical document. It is not up-to-date and the formatting may be lacking. Use the information herein with caution.

<nop>WeBWorK Gateways or Quizzes

<nop>WeBWorK's philosophy as a homework generation and delivery system is one of creating a unique problem set for each user of the system. For many testing situations this is completely appropriate, but in the case where a user can retake a test multiple times (as is the case for Gateway tests as implemented at the University of Michigan) we want the system to generate a unique problem set for each login instance: that is, each time a user logs in he or she should get a new problem set. We would like to be able to generate the variations on the problems in the set by drawing them from a database of some sort.

To support this, we need the ability to record each version of the test/quiz that is taken by a user, and what their submitted solution is. In addition, there needs to be the ability to include proctor authorization for a test/quiz, and there needs to be a timing mechanism to constrain the length of time that is allowed on the test/quiz.

Note that the grading of a test/quiz is slightly different from that in a homework set: <nop>WeBWorK's homework philosophy is that any submission or preview is recorded, and seeing if a problem is correct or not by submitting is equivalent in many respects to previewing it. For a test/quiz, there is a difference between the actual submission and the previewing cycle (not least because we don't want to show the correct solution until the submission).

That is, we need

  1. to generate a new version of a problem set for each login,
  2. to be able to generate problem versions by drawing them from a database,
  3. to restrict the amount of time allowed a student to complete a problem set version,
  4. to record each version of the problem set taken by the user, and
  5. to require a proctor authorization before students are allowed to take or grade a problem set version.

An outline the following:

  1. DataBase

<nop>WeBWorK database tables

We propose to only add this functionality to <nop>WeBWorK2, using mySQL as its database. Current database tables relating to the generation of problem sets that we need to consider are the set, problem, set_user and problem_user tables. The set_user and problem_user table entries are created when the problem set is built using the build set instructor tool, and provide the user-specific versions of the problem set and contained problems. Entries in the set table are identified by a set_id which is the same as the setName. Entries in the set_user table are identified by their set_id and user_id.

With gateways/quizzes, we need to have multiple problem set versions per user. This is best (?) implemented by having multiple set_user table entries per user. To do this we need an index that allows identification of these multiple versions. Two possible solutions are to add a set_user_id index to the table entries, or to implement a workaround with the current set_id and user_id indices. The latter requires less changes elsewhere in the system. In particular, we can change the set_id value from setName to setName.vN, where the version number N gives the user's set version number.

In addition, we will need to add a proctor category of user to the user table. This should be a smaller change, requiring the addition of a new authorization level between "student" and "professor".

A new table descriptions for sets may therefore look like the following:

Table: set_user

psvn auto-increment serial number
set_id id of set this entry is derived from, appending .v# for \
user_id id of user this entry is generated for
set_header set header, if different from that in set
problem_header problem header, if different from that in set
open_date open date, if...
due_date due date, if...
answer_date answer date, if...

New fields:

assignment_type type of assignment
problem_ordering whether problems should be arranged in a random order
version_time_limit time limit for each attempt
attempts_per_version number of attempts per version
time_interval time interval for versioning
versions_per_interval how many set versions students can get in time_interval
version_creation_time when the version was created

This allows having some number of tests per time interval (e.g., 2 versions_per_interval with a time_interval of 1 day), and a restriction on the number of times each version may be attempted.

Note that having the version_time_limit field here allows us to set it for users needing, for example, time and a half on the midterm. In that this is a property of the user, not the set, it may make better sense to have an assignment_length_multiplier field in the user table of the database.

Another note: version_creation_time is conceptually different than the other fields here (it doesn't have an inherited value from the global set entry). But I think we need it to be able to keep track of the number of versions a student grabs in a time interval. I suppose the other option is to make versions_per_interval into remaining_versions_per_interval? This would require getting earlier versions' open_date (which is the same as the creation time) to figure out when the time interval started. This seems like it's getting way too complicated. More on this to come.

  1. ProblemOverview

Gateway/Quiz problem set creation and management

When the professor for the class runs the build set utility, a set_user entry is created for each user, as it is currently. This has a set_id which is the setName for the given set.

Then, the <nop>GatewayQuiz <nop>ContentGenerator wants to go through the following steps:

  1. authenticate the user as usual
  2. look for a valid set_user entry with a set_id identifier of setName.v# (valid means that the number of attempts allowed for the set_version has not been exceeded)
    • if such exists, send that to the user
    • otherwise generate a new set_version as described below, if allowed by the number of attempts per time interval
  1. create a new set_version with a new routine assignSetVersionToUser, which will create set_user and problem_user table entries for the new version of the set and set the open_date and close_date of the created set to the current time and the current time plus the assignment time limit, respectively
  2. we noted that the <nop>ContentGenerator could also reset the open_date, close_date and answer_date when the set is graded, but I think this may be unnecessary with the assignSetVersionToUser routine doing it

Other changes in code: getMergedSet and getMergedProblem will have to look for the versioned set_user_id s. The assignSetVersionToUser routine will want access to a modified set of these, getMergedSetVersion and getMergedProblemVersion.

  1. CodeChanges

Preliminary thoughts about code changes

Managing versioning

We're storing versions of problems with a set_id of setName.vN (for N= equal to 1, 2, etc. I'm assuming that the user will still have an assignment called =setName as well, but that this won't be actually used as a problem set that the user works when versioning is in place. This leads to the modifications/additions to subroutines:

  1. User Set Management %BR%
    In general, it seems logical to have routines actionSetTo/FromUser and actionProblemTo/FromUser continue to operate as normal, but where a set is versioned to perform the action on the latest version as appropriate.  Then the new routines actionSetVersionTo/FromUser and actionProblemVersionTo/FromUser should do the action on a specific version.  Really I think we only need the Version routines for the <nop>GatewayQuiz module, assuming that those are referred to directly there.  I think needed code changes boil down to the following:
     DB->getUserSetVersionNumber($userID,$setID).: input userID and setID are the userID and nonversioned setID; output is 0 (no versioned set exists) or an integer value giving the latest version number.
     DB->getUserSets(@userSetIDs).: input is $userSetIDs[i] = [ userID, setID ], where setID is a non-versioned setID; retrieves the user sets, substituting the lastest version for versioned sets.
     DB->getUserSetVersions(@userSetIDs).: as getUserSets, but return all versions of the set(s) specified by @userSetIDs (in which setID is a non-versioned ID).
     DB->getMergedSet($userID,$setID).: return merged set, or merged form of latest version.
     Instructor->assignSetToUser(userID,GlobalSet).: as existing routine, but check $db->getUserSetVersionNumber(userID,GlobalSet->set_id) to see if the set is versioned, and if so add the next version of the set instead of adding the set.
     Instructor->assignSetVersionToUser(userID,GlobalSet).: as assignSetToUser, but if no set version(s) exist, assign the first set version to the user.  if there is no existing base set assigned to the user, assign this too.
     Instructor->unassignSetFromUser(userID,setID).: as existing routine, but if set is versioned removes all versions of the set.
     Instructor->unassignSetVersionFromUser(userID,setID).: deletes the last set version.
     Instructor->assignProblemToUser(userID,setID[,versionNum]).: as current routine, with an added call to DB->getUserSetVersionNumber(userID,setID) to see if the set is versioned.  If so, we redefine the setID to which the problems are assigned to be the latest version of the set.  The additional (optional) argument allows specification of a version to assign to.
     Instructor->unassignProblemFromUser(userID,setID,problemID).: as with assignProblemToUser, unassign problem from the latest version of the set, if any.     
     Instructor->unassignProblemVersionFromUser(userID,setID,problemID[,versionNum]).: unassign the indicated problem from the given version, or, if no version is specified, revert to behavior for unassignProblemFromUser.
  1. <nop>ContentGenerator %BR%
    This is going to be easier explained with pasted code, I think.  

-- Main.GavinLaRose - 13 Apr 2004