Note:

If you want to create a new page for developers, you should create it on the Moodle Developer Resource site.

Improved Question Bank Tags

From MoodleDocs

Overview

This document is "under construction" (really!)

This document is the technical design for a set of features proposed by the Moodle Users Association for Moodle 3.5.

The project proposal is here: https://moodleassociation.org/mod/page/view.php?id=465

The requirements / user stories have been written by the MUA - a copy is included here for clarity

User Stories / Requirements

Must:

  • As a teacher, I can add tag(s) to a question bank question for use in my course for organizational and search/filtering of questions.
  • As a teacher, I can filter my questions in courses based on tags.
  • As a teacher, I can see tags on questions at higher category assigned by Question sharer role holder.
  • As another teacher in the same course, I have access to the question tags on the questions in that course context.
  • As a teacher in a course, I do not see tags of other in contexts I do not have access to. (Instructor 1’s “midterm 1” question set would not be relevant to Instructor 2)
  • As a teacher, I am able to add/modify/remove tags on questions.
  • As a teacher, I should not have to copy a question into my course from higher category contexts to include it in a ‘random question from question set’ question type.
  • As a teacher, I can add a 'random question from question set' question type to my quiz where the question set is a selectable list of questions. These questions can be searched for and filtered by tag but the set itself is not defined by specifying a tag.

Nice to have:

  • Labels can contain any visible ASCII characters including characters such as apostrophes, slashes, and colons. Exception of Comma.
  • As a teacher, when searching for questions to add to a ‘random question from question set’ I see the question with its context clearly visible.
  • As a teacher, I can export/import questions with their tags.
  • As a Question sharer role holder, I can add a tag(s) to a question bank questions that exist at the category context.
  • As a Question sharer role holder, I can search/filter all the questions I have access to and see them along with their context.

Design

The requirements listed above can be met by implementing the following changes (which are described in detail further down):

  • New question type "Random question from a set of questions"
  • Enhanced question search allowing search/filter by tag everywhere
  • Allow adding course level tags to questions that exist in a category

Random question from a set of questions

- Describe list of changes

Pasting notes from Tim about how this should work (I'll re-write this into a proper design soon).

Tims suggestions:

When it comes to adding the 'random question by tag' feature to the quiz, please do not copy the way existing random questions work. It causes all sorts of problems, and the only reason I have not already changed it is lack of time. In case you don't know, here is how it currently works:

In the quiz (technically the quiz_slots table in the database), in one particular slot you link to the questionid of a particular random question. That is a row in the question table, with qtype = 'random', and the categoryid then tells you which category to pick randomly from. (And the questiontext is used to store the 0/1 pick from subcategories setting.) How it should work:

The quiz_slots table should be changed to say what goes in each slot of the quiz, either a questionid referring to a particular question, or a categoryid and boolean for random from category with or without subcategories, and for this project you would then add new data to represent a question randomly picked by tag. When doing this, there is a choice of using relational data, making this information queryable with SQL. That is extremely useful and should not be sacrificed lightly. On the other hand, this could be the place to introduce a simple plugin type, since we now have at least three ways to specify questions in the quiz (specific question, random by category, random by tag) - though will we let them be used in combinations (e.g. random from a category also limited by tag). Anyway, once you have three, it is easy to image in there should be more, so this could be a simple plugin type, supported by a more generic quiz_slots table structure. In order to implement this change, you probably only need to change the few function that are used to create a new quiz attempt, backup/restore (including restoring old backups), and the Edit quiz page. You will have to change all that anyway.

Notes (just dumping thoughts for now).

Question 1 - how to change the slots table? As Tim said, we can break the direct link to the questionid and introduce a "slottype" field which indicates a plugin which must be loaded to determine the actual question for a slot. This plugin would need to store data - per slot (either the questionid, the categoryid or a list of questionids for now). This would remove the ability to load all questions and slots from a single query (join) - but that is already not possible because it is not done for random question from category (instead you get the "placeholder" random question - to use the question that question type needs to make additional queries and calculations in php.

So - if we fully normalised this we would remove questionid from the slots table and add 3 new tables (one per slot type). slottype_question(id, quizslotid, questionid) (unique index quizslotid, foreign key quizslotid, foreign key questionid) slottype_randomfromcategory(id, quizslotid, questioncategoryid) (foreign key quizslotid, foreign key questioncategoryid) slottype_randomfromset(id, quizslotid, questionid) (foreign key quizslotid, foreign key questionid) (option one) slottype_randomfromset(id, quizslotid, (questionidlist varchar) ) (foreign key quizslotid) (option two)

We could store the set of questions as a concatenated string instead, but we would lose the ability to (efficiently) search for specific questions (e.g. when a question is deleted). Maybe this is still better (similar to context path queries). Still thinking. It would place an upper limit on the number of questions that can be selected from (seems like a blocker).

By using an API to generate the SQL we can join on each of these 3 tables each time in order to get all the additional info required for each slottype (by left joining them). There is no suitable aggregate function to concatenate rows - so either we return multiple rows, or do not fetch the questionids as part of a join.

Any API changes should be done in as backwards compatible way as possible.

All DB changes will require upgrade steps, backup/restore special handling etc.

Search for question by tag

- Describe list of changes

Course level tags for questions

- Describe list of changes