Understanding Question Types

Understanding Question Types

by Justin Hunt -
Number of replies: 13
Picture of Particularly helpful Moodlers Picture of Plugin developers

I am making an audio recording questiontype for Moodle 2.2. But I m having trouble understanding how I can do what I want.

I have based the new questiontype on the essay question type. The file is recorded in a non moodle location, and then copied over into moodle using the file API.  The problem is that I can't see where I should put the copy code. I do not know which function is called when the question has been "answered."

I know that the question can exist in a number of contexts like the preview window or a quiz. So the "answered" state might be ambiguous. I am not very excited about calling the copy procedure from javascript, partly because students are likely to make several recording attempts before they are satisfied and I would rather take only the final attempt. 

Hmm. I mean when does an attempt get put in the database? At that time I would like to do the copy.

Is there a way to do what I want, or should I just call the copy from javascript, ala when the student hits the stop recording button?

Average of ratings: -
In reply to Justin Hunt

Re: Understanding Question Types

by Justin Hunt -
Picture of Particularly helpful Moodlers Picture of Plugin developers

Well I have decided to do it from javascript upon the user pressing the recorder's stop button. I think the question engine,  contains the hooks that I was looking for, but not the question itself. A question's submit button won't always be present and is not really a part of the question anway. 

 

In reply to Justin Hunt

Re: Understanding Question Types

by Joseph Rézeau -
Picture of Core developers Picture of Particularly helpful Moodlers Picture of Plugin developers Picture of Testers Picture of Translators

Hi Justin,

Unless your new question type involves sophisticated controls for online recording, a simple way for students to "answer" a quiz question with an audio recording is to do the recording using any device they might have on their machine and simply attach that recording to an essay question, as Moodle 2.1+ now allows Essay attachments (see attached screenshot).

Can we have more details about the "recording feature" you are creating for your new question type?

Joseph

Attachment 09-02-2012 09-18-36.jpg
In reply to Joseph Rézeau

Re: Understanding Question Types

by Justin Hunt -
Picture of Particularly helpful Moodlers Picture of Plugin developers

Thanks for your reply. I really appreciate it. Well it is a bit sophisticated. I have attached a screenshot, of the audio recording question. There is a video recording question too. The recorders are flash widgets that connect to a remote red5 server. When the recording is complete the question calls a download servlet on the red5 server as the source url and calls create_file_from_url to copy it into moodle. We already have the recording assignment type complete.

The question is a little trickier, but I am currently trying to piggy back on the existing attachments logic in the essay question.

 

In reply to Justin Hunt

Re: Understanding Question Types

by Tim Hunt -
Picture of Core developers Picture of Documentation writers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers

Great minds think alike, it seems. My colleage Mahmoud is working on a similar question type, but using a Java applet, rather than Flash + re5 server. (I guess it is a case of choose your preferred installation nightmare wink)

You need to understand how Moodle users draft file areas, and make your applet fit into that. I hope Mahmoud can show you some of his proof-of-concept code, but he is on leave today.

In reply to Tim Hunt

Re: Understanding Question Types

by Justin Hunt -
Picture of Particularly helpful Moodlers Picture of Plugin developers

Oh really? Yes I would really like to talk with Mahmoud then. Currently I have the file copied over into the draft files area. So i think its pretty close now. If you could tap Mahmoud on the shoulder when he gets back that would be great.

In reply to Tim Hunt

Re: Understanding Question Types

by Justin Hunt -
Picture of Particularly helpful Moodlers Picture of Plugin developers

 Actually if anyone can help me  on the next step it would be appreciated. I can succesfully copy the file over into the draft files area. When I look at the database it confirms the file record has been created.

But a) I can't access it. Seemingly I don't have permission to. (See the code below, I fail to get a fileinfo object.)
And b) I don't know how to copy it over into its final destination. It doesn't happen automatically. Is there any info on how to do this, or on how moodle does it?

When I copy the file over into the draft files area I first prepare the draft id and file area. The $name field is the name of the form variable, in this case it is "answer".

$draftitemid= $qa->prepare_response_files_draft_itemid($name, $context->id);

Then I perform the copy into the draft area  . I have tried a number of different component/filearea combinations e.g question/draft, but after looking at the standard behaviour of files added via the htmleditor, used component 'user' and filearea 'draft':

This is the code I use to do the copy over.

========================================

//setup our file manipulators
  $fs = get_file_storage();
  $browser = get_file_browser();
  

//we store our file at the root of the filearea
  $filepath='/';
  
 //create the file record for our new file
  $file_record = array(
  'contextid'=>$contextid,
  'component'=>$component,
  'filearea'=>$filearea,
   'itemid'=>$itemid,
  'filepath'=>$filepath,
  'filename'=>$filename,        
  'timecreated'=>time(),
  'timemodified'=>time()
  );
  
  //actually copy over the file from remote server
  if(!$fs->create_file_from_url($file_record, $red5_fileurl)){
   $returnstring= "couldn't create file sorry";
   return $returnstring;
  }
  
  
   //get a file object if successful
   $thecontext = get_context_instance_by_id($contextid);
   $fileinfo = $browser->get_file_info($thecontext, $component,$filearea, $itemid, $filepath, $filename);

//this last step is failing, though the file appears to have been copied.

========================================

I know it is not simple, but any ideas on where I am going wrong?

In reply to Justin Hunt

Re: Understanding Question Types

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 think your problem is that the file_browser does not work properly, so that is not a good way to verify that the file was saved correctly.

Note that getting the file into the draft files area is just a temporary thing. The important thing to ensure is that when the question is submitted, the file gets copied into the proper file areas. This should happen automatically, providing you have implemented get_expected_data correctly in your question class.

In reply to Justin Hunt

Re: Understanding Question Types

by Mahmoud Kassaei -

Hi justin,

I am using a java applect developed by Sam Marshal at the OU (https://github.com/sammarshallou/ouaudioapplets/tree/master/src/uk/ac/open/embeddedrecorder). I have put a demo version on https://github.com/mkassaei/voice_recorder_test using the .jar file and some php and javascript code.

BTW, I am still working on it. Our oral response qtype will allow the question author to record audio to a file which is initially saved in user draft area and after sumbittion it is automatically saved to question questiontext area. This uses our new reposiotory plugin which works simmilar to respository/upload plugin.  

When question is attempted or previewed, the above audio file can be printed as a link in questiontext, but istead of printing the link, I call the applet to display the audio clip for listening and call the applet onece again with recording, so that the answer can be recorded.

Mahmoud

In reply to Mahmoud Kassaei

Re: Understanding Question Types

by Justin Hunt -
Picture of Particularly helpful Moodlers Picture of Plugin developers

Thanks Mahmoud and Tim, that is really good information. It is so helpful to talk to people who know what they are doing. I will try and look at it this weekend, and I will post back here.

In reply to Mahmoud Kassaei

Re: Understanding Question Types

by Justin Hunt -
Picture of Particularly helpful Moodlers Picture of Plugin developers

I had a look at your module. It works somewhat differently to mine. We have a recorder in place of a textarea. So we do not use the repository mechanism at all. I am still stuck basically at the same point. The files are copied over into the draft files area ok, but they are not moved from there into their final destination.

There are two issues.

Problem 1

The first is that the context id recieve from:
public function response_area_input($name, $qa, $step, $lines, $context) in my question's renderer class,  is '15'. If I write my file to the draft files area using this context id, I do not have read access to the file.

When I compare how files added via the file repository work, they write to the draft files area using context id '5'. If I use this id, I do have read access to the file.  When the files added via the file repository are copied over to their final destination (component 'question' and file area 'response_answer') the context id is '15'.

So how can I get a handle on the context that I should use to write to the draft files area?

Problem 2.

It appears that files are only automatically copied over to their final destination if you use the html editor. This appears to happen in file_post_update_standard_editor in fileslib.php. I am currently writing out a link to my file into a hidden form element of the same name as the html editor would have if I was using one. Predictably Moodle is not fooled and isn't copying the files. Any tips on how I can get my files shifted over? It would be ok to use a file picker element, beneath the recorder and insert the values there via javascript. But the way to do that was not very clear.

In reply to Justin Hunt

Re: Understanding Question Types

by Justin Hunt -
Picture of Particularly helpful Moodlers Picture of Plugin developers

OK, problem 1 was quite simple, I should have spotted it earlier. I simply had to use the users context id, retrieved like this:

$usercontextid=get_context_instance(CONTEXT_USER, $USER->id)->id;

Problem 2, I could mostly solve. I found a hidden form field on the question response form with the draft files area id and the draft file now gets copied over into the question response file area correctly. 

IF anybody else is going through this, this is the code for the response renderer

================================

  public function response_area_input($name, $qa, $step, $lines, $context) {
        global $USER;
        $usercontextid=get_context_instance(CONTEXT_USER, $USER->id)->id;
        
        //prepare a draft file id for use
        list($draftitemid, $response) = $this->prepare_response_for_editing( $name, $step, $context);

        //prepare the tags for our hidden( or shown ) input
        $inputname = $qa->get_qt_field_name($name);
        $inputid =  $inputname . '_id';
        
        //our answerfield
        $ret =    html_writer::empty_tag('input', array('type' => 'hidden','id'=>$inputid, 'name' => $inputname));
        
        //our answerfield draft id key
        $ret .=    html_writer::empty_tag('input', array('type' => 'hidden', 'name' => $inputname . ':itemid', 'value'=> $draftitemid));
        
        //our answerformat
        $ret .= html_writer::empty_tag('input', array('type' => 'hidden','name' => $inputname . 'format', 'value' => 1));
    
      
        return $ret . fetchAudioRecorderForDraft('swf','question',$inputid, $usercontextid ,'user','draft',$draftitemid);

    }

================================

But the url to the file is not rewritten correctly.  In the response_area_read_only function I still basicaly have the url to the draft files area only the file fetcher part of the url has been changed (to pluginfilephp).

http:// m2.poodll.com / pluginfile.php /5/user/draft/377959863/217012848705053.flv (I had to add spaces in the url to prevent it being flowplayer'ed)

Any ideas?

Justin

In reply to Justin Hunt

Re: Understanding Question Types

by Justin Hunt -
Picture of Particularly helpful Moodlers Picture of Plugin developers

It is all working now. I access the file using the code below:
                
 //fetch submitted files from storage
  $storedfiles=$qa->get_last_qt_files($name,$context->id);
         

//and determine URL for the first(and only) stored file
$pathtofile=$qa->get_response_file_url($thestoredfile);
  

it looks so simple ....

In reply to Justin Hunt

Re: Understanding Question Types

by Tim Hunt -
Picture of Core developers Picture of Documentation writers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers

Yes, that looks right. Your previous message was wrong, and I was just about to compose a reply to say that.