General developer forum

 
 
Picture of Michael Schink
Is it possible to get quiz id in formulation_and_controls (renderer.php) of a question type?
 

Hello,

I'm trying to get the actual quiz id (or to the quiz attempt) in the method formulation_and_controls in the renderer.php file of a self-developed question type.

I didn't find suitable methods, nor a way of constructing a DB query with the available vars to get the quiz id.

 

My main problem is that the question type shows parts of the grade in the review. (This is possible through a little hack in the deferredfeedback behaviour). Especially if no grades are shown in the review this isn't usefull.

This selection is a quiz option and is saved in the table quiz in the attribute reviewmarks (as integer bits). After a little bit of testing I implemented the following method to get this option, but I still need the quiz id:

//Get review options for marks
function get_reviewmarks($quiz_id) {
    global $DB;
    
    $conditions = array("id" => $quiz_id);
    $number = $DB->get_field("quiz", "reviewmarks", $conditions);
    $number = decbin($number);
    $number = substr($number, 0, strlen($number)-1);
    $zeros = 16-strlen($number);
    for($i=0; $i<$zeros; $i++) { $number = "0".$number; }
    $options = array("DURING" => $number{0}, "IMMEDIATELY_AFTER" => $number{4}, "LATER_WHILE_OPEN" => $number{8}, "AFTER_CLOSE" => $number{12});

    return $options;
}

 

I would appreciate every suggestion to solve this problem.

 
Average of ratings: -
Tim at Lone Pine Koala Sanctuary
Re: Is it possible to get quiz id in formulation_and_controls (renderer.php) of a question type?
Group DevelopersGroup Documentation writersGroup Particularly helpful Moodlers

You cannot make the assumption that questions are only used in the quiz. (In Moodle core, the only other place they are displayed at the moment is in the question preview pop-up, but in future, we hope that people will build interesting new activities using computer-marked questions.)

So, a key point of how questions work is that you should be able to use them anywhere, through a defined API. Now, for that design to work, there must be some way for the quiz (or whatever) to communicate to the question what display options are currently in force. Look again at the arguments:

public function formulation_and_controls(question_attempt $qa, question_display_options $options) {

}

What do you think the question_display_options class does? You don't need to guess, there are PHP-docs: https://github.com/moodle/moodle/blob/master/question/engine/lib.php#L365

The code you are looking for is

if ($options->marks >= question_display_options::MARK_AND_MAX) {
    // Then you should display display the grade information, otherwise don't.
}

It is up to the quiz to ensure that the $options object is initialised correctly from the quiz settings before the question is displayed, and indeed the quiz does that.

Note that doing it this way avoids doin an extra DB query as in your code, which would be bad for performance.

 
Average of ratings:Useful (1)
Picture of Michael Schink
Re: Is it possible to get quiz id in formulation_and_controls (renderer.php) of a question type?
 

It seems that I couldn't see the wood for the trees. I just overlooked the second argument in formulation_and_controls. Really big thanks for your help Tim. You made my day (, again).

 
Average of ratings: -
Picture of María José López Monzón
Re: Is it possible to get quiz id in formulation_and_controls (renderer.php) of a question type?
 

Hi Tim,

I am in the same situation, but I need the quiz id because my question type asociates the question to an specific quiz. In order to get a question I have to indicate the quiz in which it is define. Is there another way to do this? I am upgrading this question type from 1.9 to 2.3 and i am freaking out because i can't find a way to get the quiz id.

Please, some help would be very useful!Thanks!

 

Here is the part of the code where i need the quiz to show the question:

//Set question text
$questiontext = $question->format_text(customize_problem_statement($question->questiontext, $question->id, $USER->id, $qa, $quizid),
$question->questiontextformat, $qa, 'question', 'questiontext', $question->id);

The method customize_problem_statement just asociate tags with values in the question text.

 
Average of ratings: -
Tim at Lone Pine Koala Sanctuary
Re: Is it possible to get quiz id in formulation_and_controls (renderer.php) of a question type?
Group DevelopersGroup Documentation writersGroup Particularly helpful Moodlers

Sorry, but you can't do that.

Neither "In order to get a question I have to indicate the quiz in which it is define" nor "customize_problem_statement just asociate tags with values in the question text" is a pedagogic requirement. If you tell us what you are really trying to do, from an educational point of view, then we will try to find a way for you to do that within the set of abstractions used by the quiz and question system.

To make an effective Moodle question type, you have to work withing the abstractions, the software archetecture, of Moodle. It is really very flexible once you understand it, and we are happy to help you do that.

 
Average of ratings: -
Tim at Lone Pine Koala Sanctuary
Re: Is it possible to get quiz id in formulation_and_controls (renderer.php) of a question type?
Group DevelopersGroup Documentation writersGroup Particularly helpful Moodlers

Maria messaged me privately (Grrrr!)

Here is the issue of the question type I am upgrading:

I'm trying to assing different data to different students from one question. I define the question and when I put it in the quiz the plugin assign different data (which is stored in the database) to the users when they try to attempt the quiz. That is why someone create the customize_problem_statement and why she use the quiz id to specify the data for each user. In 1.9 it used to function correctly but I can't find the way to upgrade it to 2.3.

The correct way to assign different data to different students is demonstrated by a number of question types: calcuated in Moodle core, and varnumset and stack as add-ons.

In your question class, you first need to override the get_num_variants method, to return the number of data sets that you have. Then, the $variant passed to start_attempt will be a number between 1 and get_num_variants inclusive. You can use that to customize_problem_statement.

How do you handle the situation where you want all the questions in the quiz to use the same data set for a particular student. Well, that is where the get_variants_selection_seed method comes in. If two questions in the same quiz return the same value from get_variants_selection_seed, and have the same number of variants, then the $variant passed to start_attemtp will be the same for both questions in one quiz attempt.

 
Average of ratings: -
Picture of María José López Monzón
Re: Is it possible to get quiz id in formulation_and_controls (renderer.php) of a question type?
 

Hi Tim,

Thanks for your answer.

This type of question is thought to be a personal question. It means that there is only one question per quiz. In that question the professors write a big statement with a lot of data to be assigned from the database. So there won't be a problem with the $variant in start_attempt.

But, I don't know if i have to write the start_attempt with any initialization, because the data sets are loaded to the database by processing a CSV file.

Sorry to write you in private, but I didn't know if I could talk openly about the project as it is a final project in my University.

 
Average of ratings: -
Tim at Lone Pine Koala Sanctuary
Re: Is it possible to get quiz id in formulation_and_controls (renderer.php) of a question type?
Group DevelopersGroup Documentation writersGroup Particularly helpful Moodlers

I think it is good that your final university project is encouraging you to contribute to an existing Open Source project, rather than to build something completely separate. When you work with Open Source software, it is essential to communicate with other developers, to work out the best way to do things, so hopefully the rules for your project allow that. (If not, the problem is with the rules, not with talking to to us wink).

If you are going to talk with other developers about the project, I would have thought it is much safer to have the discussion in a public place like this. Then you can give the URL of this discussion in the references of your project, and your teachers can check (if they wish) that you have only asked for appropriate sorts of help, and that we have not done the project for you, we have only offered appropriate guidance. If you have any doubts about this, you could ask one of your professors to review this thread now.

--------

Now to answer your actual question, which is basically "When to load the data from the .CSV file and store it in the database?"

There are really two options, and I think they would both work.

1. When the teacher creates or edits the question, and clicks save, then load all the .CSV data for all variants and store it in the database. Then start_attempt can just load the data from the database.

2. In start_attempt, load all the .CSV data for the current variant and store it in the database then.

I think both options would work, so you can choose the one that is easier.

 
Average of ratings: -
Picture of María José López Monzón
Re: Is it possible to get quiz id in formulation_and_controls (renderer.php) of a question type?
 

Thanks Tim, I didn't understand what variant was neither what to do in start_attempt. I'm trying to do this, I hope there are no more doubts but If there were i will write in the forum.

As for my teachers, they told me that there was no problem with this discussions, even better, the said. 

 
Average of ratings: -
Picture of María José López Monzón
Re: Is it possible to get quiz id in formulation_and_controls (renderer.php) of a question type?
 

Hi Tim,

I've been trying to do what you told me, but i am stuck. I can't see the relation between variant and anything else. I upload the data from the CSV to the DB in the form where the teacher writes the statement. This works perfectly. The problem is that I'm trying to substitute the tags in the start_attempt() function, so the statement is defined before the student sees it. But by doing this, the question id is different from the one that has been stored when the teacher creates the question. And when i try to attempt, as a student, the quiz with that question doesn't appear the statement, because in question_attempts table the attempt id is associated to the question id of the question when the student trys to answer the quiz and not the question id which was stored in first place (when creating the question).

I don't know if you understand what i am trying to explain, but i hope you can help me, because i don't know what else to do.

Thanks for everything in advance.

I attach the images of the tables in the database so you can see what i am trying to say.






 
Average of ratings: -
Tim at Lone Pine Koala Sanctuary
Re: Is it possible to get quiz id in formulation_and_controls (renderer.php) of a question type?
Group DevelopersGroup Documentation writersGroup Particularly helpful Moodlers

There is an example of how to do this in the calculated question type in Moodl core.

As you say, the key functions in the question calss are start_attempt (used when a question is started) and apply_attempt_state (used when we need to continue an attempt at a question that was started in the past). https://github.com/moodle/moodle/blob/master/question/type/calculated/question.php As you can see, in the calculated question type, we do all the work in a helper class qtype_calculated_question_helper.

So we need to look at https://github.com/moodle/moodle/blob/master/question/type/calculated/question.php#L144. start_attempt does three things.

S1. It uses the variant number to load the necessary data: $question->datasetloader->get_values($variant). That funtion returns an array like variable-name => value.

S2. We then use those values to build another helper: new qtype_calculated_variable_substituter. (All these different classes may make the code harder to understand at first, but by separating the code into separate small classes, each with their own responsibility, it is easier to verify the code is correct, and to maintain it in the future.)

S3. Then we use the value of the variables to replace all the tokens in the question text. $question->calculate_all_expressions(); https://github.com/moodle/moodle/blob/master/question/type/calculated/question.php#L63 This uses the qtype_calculated_variable_substituter class we just made to do the work.

S4. We then store the variable values in the question_attempt, so that we get the same values in the future. That is the foreach loop that does $step->set_qt_var('_var_' . $name, $value). (Instead of storing each variable value, we could have just stored the variant number. I won't discuss the trade-offs of that decision here.)

Now, the question is ready, with all the right values put into the question text, and those values have been stored, so we can use them again in future.

Now let us look at apply_attempt_state. https://github.com/moodle/moodle/blob/master/question/type/calculated/question.php#L158. What does this do?

A1. First we load the values we stored into the question_attempt: foreach ($step->get_qt_data() as $name => $value) {

A2. Then we use those values to build a qtype_calculated_variable_substituter that is just like the one we used when the question was stareted.

A3. Then we use that to put the right values into the question text: $question->calculate_all_expressions();

Does that make sense?

 

 

 

 

 
Average of ratings: -
Picture of María José López Monzón
Re: Is it possible to get quiz id in formulation_and_controls (renderer.php) of a question type?
 

Thanks Tim, I'm trying to modify my plugin. I hope this works.

 
Average of ratings: -
Picture of María José López Monzón
Re: Is it possible to get quiz id in formulation_and_controls (renderer.php) of a question type?
 

I am doing the changes, and I think this time could work. But i have another doubt concerning the variant variable. Is it always the same for the same user? It doesn't change if the user tries to attempt the question a second time, am I all right?

 
Average of ratings: -
Tim at Lone Pine Koala Sanctuary
Re: Is it possible to get quiz id in formulation_and_controls (renderer.php) of a question type?
Group DevelopersGroup Documentation writersGroup Particularly helpful Moodlers

The variant selected changes each time. 

The variant is selected pseudo-randomly based on the user's id and the attempt number. It is done in such a way that if the student makes repeated attempts, the will see each variant once before they get a repeat.

 
Average of ratings: -
Picture of María José López Monzón
Re: Is it possible to get quiz id in formulation_and_controls (renderer.php) of a question type?
 

But if i want to use the same data in each attempt of one user, how can i control variant? Because in my plugin the data is assigned to each user and if they attempt the quiz several times they need to have the same data.

 
Average of ratings: -
Tim at Lone Pine Koala Sanctuary
Re: Is it possible to get quiz id in formulation_and_controls (renderer.php) of a question type?
Group DevelopersGroup Documentation writersGroup Particularly helpful Moodlers

Why?

You have never explained how this will all look to the students. If you told us about the educaitonal problem you are trying to solve, we would be better able to help you.

 
Average of ratings: -
Picture of María José López Monzón
Re: Is it possible to get quiz id in formulation_and_controls (renderer.php) of a question type?
 

That's right. The students who attempt my type of question will have a big statement with several data (which is loaded in a CSV to the DB). And will have several input answers, too. So the student should get the same data each time he want to attempt the question, because as it is a big statement, maybe he can answer a part and save it and after a few hours or a day he can answer the other part. That is why the variant needs to be fixed. I don't know if i have explained myself.

 
Average of ratings: -
Tim at Lone Pine Koala Sanctuary
Re: Is it possible to get quiz id in formulation_and_controls (renderer.php) of a question type?
Group DevelopersGroup Documentation writersGroup Particularly helpful Moodlers

You have not explained. All Moodle code is just pushing data around. That is not the point. The point is that a teacher is teaching something, like science, or maths, or languages, or data processing, and the student is learning that.

 
Average of ratings: -
Picture of María José López Monzón
Re: Is it possible to get quiz id in formulation_and_controls (renderer.php) of a question type?
 

This question type is called "personalized question type", because having only one statement when each student attempt the quiz, in which the question is, the data assign to each one is different. This is a general idea, in my university is used in a subject about networks, but they want to update it to version 2.3 and after proving it is working fine they may share the plugin. This is what you are referring to?

 
Average of ratings: -
Picture of María José López Monzón
Re: Is it possible to get quiz id in formulation_and_controls (renderer.php) of a question type?
 

Tim, I finally reorganized all the code and modified the database tables to adapt this plugin to Moodle 2.0, but I still can't see the question statement, because there is a problem on line 195 of /mod/quiz/startattempt:

$quba->start_all_questions(
new question_variant_pseudorandom_no_repeats_strategy($variantoffset), $timenow);

I think this has to be with the variant variable, but I can't see how I can use it if it is random and I need some index fixed. Could you give some advice?

 
Average of ratings: -
Tim at Lone Pine Koala Sanctuary
Re: Is it possible to get quiz id in formulation_and_controls (renderer.php) of a question type?
Group DevelopersGroup Documentation writersGroup Particularly helpful Moodlers

"there is a problem on line 195 of /mod/quiz/startattempt"

In what sense is that line of code a problem?

 
Average of ratings: -
Picture of María José López Monzón
Re: Is it possible to get quiz id in formulation_and_controls (renderer.php) of a question type?
 

Don't worry Tim, I finally found the problem and it had nothing to do with what I asked you. Thanks for your advices I just find the way to see the question and now I am trying to finish the update to version 2.3.

 
Average of ratings: -