Posts made by Tim Hunt

Picture of Core developers Picture of Documentation writers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers

I see this relates to a custom activity called mod_capquiz - and I see that you are one of the maintainers of that module. (But that is all I know about this activity so far. I have just looked at the screen-grabs in the plugins DB.)

1. I looked at the diagram before reading your post, so I was going to point this out.

2. I am glad you pointed this out. OK, so you have a single question_usage_by_activity containing approximately ten thousand question-attempts. That is never going to work. Surely one student has not attempted ten thousand questions?

Normally, one question_usage_by_activity should correspond to something like a quiz attempt. The typical quiz attempt has about 6 questions, and it is rare to go above 30. However, from reading this forum over the years, I know that some teachers are sadists, so if I had to put a number of it, I would say that the quiz/question system should cope fine up to about 200 question-attempts in one usage (although I would not go that far with STACK questions). Anyway, you are about two orders of magnitude beyond that. I am afraid you are going to have to re-organise how your activity manages its data, if you want this to work at this scale.

It seems that with capquiz, iit seems that from time to time, students come in and attempt a batch of questions. I think you should create a separate question_usage_by_activity for each time a student does a session attempting some questions. Then, to display overall statistics, you will need to aggregate the data, but there are ways to pull out aggregate data efficiently, you don't need to fully load all the question_usage_by_activitys. You may be able to use the same helper functions that the quiz module uses to display its repots, or you may need to keep your own statistics and update them every time a student completes a qestion, or batch of questions.

I hope that is useful. Sorry to be the bearer of bad news.

Average of ratings: Useful (2)
Picture of Core developers Picture of Documentation writers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers
Well, Moodle puts additional hurdles in the way of people who want to try to exploit any holes discovered. That is good, but it still misses the point:

Don't write code like this. Use placeholders, and use optional/required_param

$id = required_param('id', PARAM_INT);
$r = $DB->get_records_sql('SELECT * FROM {config} WHERE id = ?', [$id]);

Or, since id is a primary key:

$id = required_param('id', PARAM_INT);
$r = $DB->get_record('config', ['id' => $id]);

That way, SQL injection is just not possible. This is the way you shoudl think about coding.

Whether Moodle's defence-in-depth is good enough to mitigate terribly-written code might be a theoretically interesting dicussion, but it should be of no practical importance. Code like that should not get written, and when it does, it should be caught during review.
Average of ratings: Useful (1)
Picture of Core developers Picture of Documentation writers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers

Does it really matter if it is shown as incorrect?

Well, I think it does not matter, as long as it is shown as correct, and you can do that.

  • For the MC questions, set all the choices to be worth 100%.
  • For the short-answer question, just have a single answer of '*' (match anything) worth 100%.
(And leave these questions as contributing 0 to the overall grade.) Then students get a nice green tick in reward for giving you feedback. (Anyway, this is the only work-around I can think of.)
Average of ratings: Useful (3)
Picture of Core developers Picture of Documentation writers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers

I think it is probably time to talk about a new feature

In future, Moodle will keep every version of your questions

So, you can alwasy see who changed the question when, and probably what they changed (though building a nice interface for showing the changes may have to come later). (Think of a wiki, where you can see a complete history of each page, but that does not really get in the way when editing.)

Perhaps more importantly, when a student attempts a quiz, Moodle will track which version of the question they got, and that will never change. This prevents all the problems we have had over the years when people edit questions after they have been attempted, and this break the existing quiz attempts.

Of course, you may want to edit the question (for example to fix an error in the grading rules) and then update all the attempts to use that new version, and there will be an option for you to choose to do that. However, that won't happen unless and until you ask for it. (It will be an option built into quiz regrading.)

Also, as you are building your quiz, if you add a question from the question bank, do you want all students to get exactly the same version of the question, even if someone comes along later and edits it in the quetion bank? (That might be the best option for exams.) Or, do you want each student to get whatever the latest version is, at the time they start their quiz attempts. (That might be a good option for practice quizzes.) The parallel is not exact, but it is a bit like the choice you get when you add a file from a repository to some locations in Moodle: you can either take a copy of the file as it is now, or keep pointing to the latest version in the repository.

Screen grab of the add file option copy/reference option.

Someone pointed out to me that if we keep a every version of all questions, that will clutter up the database. So we will probably implement a scheduled task with a setting so that if you have old versions of a question that nothing is using (because you did a lot of editing while creating your quiz, but all the quiz attmepts only use the latest version), then the unused versions will get deleted, leaving just the ones that are actually used in a quiz attempt, or are the latest version. (This is a bit like the option to delete old data from the Moodle logs, where the admin can choose the time period the logs are kept for.)

Technical details

For those who like that sort of thing (Why am I thinking of Marcus Green as I write this?) here is what I think the database structure need to be to make this work. Well, first here is (a slightly simplified diagram) of how the database looks now: (key tables highlighted)

Database structure before.

So, we have a question bank for each Moodle context, and that has a number of categores. And, each category has a number of questions. And, the question is defined by some basic data in the question table, and then there is a bunch of other data (answers, hints, other question-type-specific stuff) which is shown over to the right.

Then, around the edges we have some thigns that use questions. The question engine at the bottom tracks the data when people attempt questions (e.g. in a quiz attempt). Therefore, each question_attempt points to the question it is an attempt at. At the top we have the quiz, as an example of an activity that uses questions. Each quiz attempt points to the question engine data that makes up the attempt, and the quiz_slots table represents what questions have been added to the quiz by the teacher. Of course, each slot points to one particular question, or if you are using randomisation, it pionts to a whole category.

Now lets look at how things will be in the future: Basically the old question table gets split into three bits:

The spit is really into

  • the data that defines how a particular version of the question works: that is, the question text, feedback, mark, etc (and all the more specific data in the other tables on the right).
  • The data that identifies which question this is (the category, name, idnumber, etc.)

In an earlier post, I said I really hoped that we woud not break all the existing question type plugins, and it is the fact that the data the defines how a question works remains in a table that is still called question which is why I think this will be possible.

Then, there is a third table which links all the different versions of a question to the question_bank_entry that they are a version of.

The question engine data continues to point to the question table - the specific version of the question that was attempted.

And, I have not drawn back in the link between quiz slots and the question bank. That is because that describing that will have to wait for a future episode.

Average of ratings: Useful (4)