1: # The LearningOnline Network with CAPA
2: # chemical equation style response
3: #
4: # $Id: chemresponse.pm,v 1.94 2014/08/20 18:02:08 raeburn Exp $
5: #
6: # Copyright Michigan State University Board of Trustees
7: #
8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
9: #
10: # LON-CAPA is free software; you can redistribute it and/or modify
11: # it under the terms of the GNU General Public License as published by
12: # the Free Software Foundation; either version 2 of the License, or
13: # (at your option) any later version.
14: #
15: # LON-CAPA is distributed in the hope that it will be useful,
16: # but WITHOUT ANY WARRANTY; without even the implied warranty of
17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18: # GNU General Public License for more details.
19: #
20: # You should have received a copy of the GNU General Public License
21: # along with LON-CAPA; if not, write to the Free Software
22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23: #
24: # /home/httpd/html/adm/gpl.txt
25: #
26: # http://www.lon-capa.org/
27: #
28: #
29: package Apache::chemresponse;
30: use strict;
31: use Apache::lonxml;
32: use Apache::lonnet;
33: use Apache::lonlocal;
34: use lib '/home/httpd/lib/perl/';
35: use LONCAPA;
36:
37:
38: BEGIN {
39: &Apache::lonxml::register('Apache::chemresponse',('organicresponse','organicstructure','reactionresponse','chem'));
40: }
41:
42: sub chem_standard_order {
43: my ($reaction) = @_;
44: my ($re,$pr) = split(/->|<=>/,$reaction);
45: my @reactants = split(/\s\+/,$re);
46: my @products = split(/\s\+/,$pr);
47: foreach my $substance (@reactants,@products) {
48: $substance =~ s/(\^\d*)\s+/$1_/g; # protect superscript space
49: $substance =~ s/\s*//g; # strip whitespace
50: $substance =~ s/_/ /g; # restore superscript space
51: }
52: @reactants = sort @reactants;
53: @products = sort @products;
54: my $standard = '';
55: foreach my $substance (@reactants) {
56: $standard .= $substance;
57: $standard .= ' + ';
58: }
59: $standard =~ s/ \+ $//; # get rid of trailing plus sign
60: $standard .= ' -> ';
61: foreach my $substance (@products) {
62: $standard .= $substance;
63: $standard .= ' + ';
64: }
65: $standard =~ s/ \+ $//; # get rid of trailing plus sign
66: return $standard;
67: }
68:
69: sub separate_jme_window {
70: my ($smile_input,$jme_input,$molecule,$options,$shown_text)=@_;
71: my $usejsme = 1;
72: my $linkstyle = 'display:none';
73: my $creditstyle = 'display:inline';
74: if ($env{'browser.type'} eq 'explorer') {
75: if (($env{'browser.os'} eq 'win') && ($env{'browser.version'} < 9)) {
76: $linkstyle = 'display:inline';
77: $creditstyle = 'display:none';
78: }
79: }
80: my $smilesection;
81: if (defined($smile_input)) {
82: my $smiles;
83: if ($usejsme) {
84: $smiles = 'document.JME.smiles()';
85: } else {
86: $smiles = 'document.applets.JME.smiles()';
87: }
88: $smilesection=<<SMILESECTION;
89: opener.document.lonhomework.$smile_input.value = $smiles;
90: SMILESECTION
91: }
92: my $jmesection;
93: my $jmefile;
94: if (defined($jme_input)) {
95: if ($usejsme) {
96: $jmefile = 'document.JME.jmeFile()';
97: } else {
98: $jmefile = 'document.applets.JME.jmeFile()';
99: }
100: $jmesection=<<JMESECTION;
101: opener.document.lonhomework.$jme_input.value = $jmefile;
102: JMESECTION
103: }
104:
105: if ($molecule) {
106: if ($usejsme) {
107: $molecule = 'document.JME.readMolecule("'.$molecule.'")';
108: } else {
109: $molecule='<param name="jme" value="'.$molecule.'" />';
110: }
111: }
112: my $insert_answer;
113: if ($shown_text eq '') {
114: $insert_answer=
115: '<input type="button" name="submit" value="'.&mt('Insert Answer').'" onclick="javascript:submitSmiles();" /><br />';
116: }
117:
118:
119:
120: my ($jsme_js,$js,$buttonstyle,$viewportjs,$resizejs);
121: if ($usejsme) {
122: $buttonstyle = 'display:none';
123: $resizejs =<<RESIZEJS;
124: <script type="text/javascript">
125: function callResize() {
126: var timer;
127: clearTimeout(timer);
128: timer=setTimeout('resize_jsme()',100);
129: }
130:
131: window.onresize = callResize;
132:
133: function resize_jsme() {
134: init_geometry();
135: var vph = Geometry.getViewportHeight();
136: var vpw = Geometry.getViewportWidth();
137: var lowerdivheight = document.getElementById('JMEbuttons').offsetHeight;
138: var formheight = document.getElementById('JMEform').offsetHeight;
139: var freevspace = vph-(lowerdivheight+50);
140: var freehspace = vpw-20;
141: if (typeof jsmeApplet !== 'undefined') {
142: jsmeApplet.setSize(freehspace,freevspace);
143: }
144: }
145: </script>
146: RESIZEJS
147: $resizejs = &Apache::loncommon::js_ready($resizejs);
148: $jsme_js = '
149: <script type="text/javascript" language="javascript" src="/adm/jsme/jsme.nocache.js"></script>'."\n";
150: $js =<<CHEMJS;
151: <script type="text/javascript">
152: function jsmeOnLoad() {
153: document.getElementById('JMErefresh').style.display="none";
154: document.getElementById('JMEcredits').style.display="inline";
155: jsmeApplet = new JSApplet.JSME("jme", "420px", "330px");
156: document.JME = jsmeApplet;
157: $molecule;
158: document.getElementById('JMEbuttons').style.display="block";
159: callResize();
160: }
161:
162: function submitSmiles() {
163: jmeFile = document.JME.jmeFile();
164: if (jmeFile == "") {
165: alert("Nothing to submit");
166: } else {
167: $jmesection
168: $smilesection
169: window.close();
170: }
171: }
172: function openHelpWindow() {
173: window.open("http://peter-ertl.com/jsme/2013_03/help.html","","scrollbars=yes,resizable=yes,width=500,height=600");
174: }
175:
176: </script>
177:
178: CHEMJS
179:
180: $viewportjs = &Apache::loncommon::viewport_geometry_js();
181: $viewportjs = '<script type="text/javascript">'."\n".
182: $viewportjs."\n".
183: '</script>';
184:
185: } else {
186: $buttonstyle = 'display:block';
187: $js =<<CHEMJS;
188: <script type="text/javascript">
189: function submitSmiles() {
190: jmeFile = document.applets.JME.jmeFile();
191: if (jmeFile == "") {
192: alert("Nothing to submit");
193: } else {
194: $jmesection
195: $smilesection
196: window.close();
197: }
198: }
199: function openHelpWindow() {
200: window.open("/adm/jme/jme_help.html","","scrollbars=yes,resizable=yes,width=500,height=600");
201: }
202: function substituent(r) {document.applets.JME.setSubstituent(r);}
203: </script>
204: CHEMJS
205: }
206:
207: my $start_page =
208: &Apache::loncommon::start_page('Molecule Editor',$viewportjs,
209: {'only_body' => 1,
210: 'js_ready' => 1,
211: 'bgcolor' => '#FFFFFF',});
212: my $end_page =
213: &Apache::loncommon::end_page({'js_ready' => 1,});
214: my $java_not_enabled=&Apache::lonhtmlcommon::java_not_enabled();
215: my %lt = &Apache::lonlocal::texthash(
216: 'seltext' => 'Select substituent...',
217: 'close' => 'Close',
218: 'help' => 'Help',
219: );
220: my $body = "
221: $jsme_js
222: $js".'
223: <center>
224: <form action="" id="JMEform">
225: ';
226: if ($usejsme) {
227: $body.= <<"ENDCHEM";
228: <div id="jme">
229: <div id="JMEcredits" style="$creditstyle">
230: <span style="font-size:small; font-family:arial,sans-serif;"><a href="http://peter-ertl.com/jsme/">JSME Molecular Editor</a> courtesy of Peter Ertl (Novartis) and Bruno Bienfait</span></div>
231: </div>
232: ENDCHEM
233: } else {
234: $body.=<<CHEMPAGE;
235: <table width="440"><tr>
236: <td></td>
237: <td align="right">
238: <select onchange="javascript:substituent(options[selectedIndex].text)">
239: <option>$lt{'seltext'}</option>
240: <option>-C(=O)OH</option>
241: <option>-C(=O)OMe</option>
242: <option>-OC(=O)Me</option>
243: <option>-CMe3</option>
244: <option>-CF3</option>
245: <option>-CCl3</option>
246: <option>-NO2</option>
247: <option>-SO2-NH2</option>
248: <option>-NH-SO2-Me</option>
249: <option>-NMe2</option>
250: <option>-C#N</option>
251: <option>-C#C-Me</option>
252: <option>-C#CH</option>
253: </select>
254: </td></tr>
255: </table>
256: <applet code="JME.class" name="JME" archive="/adm/jme/JME.jar" width="440" height="390" mayscript>
257: $java_not_enabled
258: $molecule
259: <param name="options" value="$options" />
260: </applet>
261: <br />
262: <font face="arial,helvetica,sans-serif" size="-1"><a href="http://www.molinspiration.com/jme/index.html">JME Editor</a> courtesy of Peter Ertl, Novartis</font>
263: CHEMPAGE
264: }
265: $body .= <<CHEMPAGE;
266: <div id="JMEbuttons" style="$buttonstyle">
267: $insert_answer
268: <input type="button" value="$lt{'close'}" onclick="javascript:window.close()" />
269:
270: <input type="button" value="$lt{'help'}" onclick="javascript:openHelpWindow()" />
271: </div>
272: <div id="JMErefresh" style="$linkstyle">
273: <a href="javascript:location.reload();">Display Molecule Editor</a>
274: </div>
275: </form>
276: </center>
277: CHEMPAGE
278:
279: $body=&Apache::loncommon::js_ready($body);
280: my $nothing=&Apache::lonhtmlcommon::javascript_nothing();
281: my $docopen=&Apache::lonhtmlcommon::javascript_docopen();
282: my $display=&mt('Draw Molecule');
283: if (defined($shown_text)) { $display=&mt($shown_text); }
284: my $iconpath=$Apache::lonnet::perlvar{'lonIconsURL'};
285: my $function =
286: 'LONCAPA_draw_molecule_'.&get_uniq_name();
287: my $result=<<CHEMINPUT;
288: <script type="text/javascript">
289: function $function() {
290: editor=window.open($nothing,'jmeedit','width=500,height=500,menubar=no,scrollbars=no,resizable=yes');
291: if (editor) {
292: editor.$docopen;
293: editor.document.write('$start_page $body $resizejs $end_page');
294: editor.document.close();
295: editor.focus();
296: }
297: }
298: </script>
299: CHEMINPUT
300: my $jscall = "javascript:$function();void(0);";
301: if ($shown_text eq '') {
302: $result .=<<PENCIL;
303: <a href="$jscall"><img class="stift" src="$iconpath/stift.gif" alt="$display" title="$display" /></a>
304: PENCIL
305: } else {
306: $result .= '<input type="button" value="'.&mt($shown_text).'" onclick="$jscall" />';
307: }
308: return $result;
309: }
310: sub jme_img {
311: my ($jme,$smile,$width,$options)=@_;
312: my $id=&Apache::loncommon::get_cgi_id();
313: my $result='<img alt="'.$smile.'" src="/cgi-bin/convertjme.pl?'.$id.'"';
314: if ($options =~ /border/) { $result.= ' border="1"'; }
315: $result.=' />';
316: &Apache::lonnet::appenv({'cgi.'.$id.'.JME' =>
317: &escape($jme),
318: 'cgi.'.$id.'.PNG' => 1,
319: 'cgi.'.$id.'.WIDTH' => $width});
320: return $result;
321: }
322:
323: sub start_organicresponse {
324: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
325: my $result;
326: my $partid = $Apache::inputtags::part;
327: my $id = &Apache::response::start_response($parstack,$safeeval);
328: if ($target eq 'meta') {
329: $result=&Apache::response::meta_package_write('organicresponse');
330: } elsif ($target eq 'web') {
331: my $jmeanswer=&Apache::lonxml::get_param('jmeanswer',$parstack,
332: $safeeval);
333: if (&Apache::response::show_answer()) {
334: my $jmeanswer=&Apache::lonxml::get_param('jmeanswer',$parstack,
335: $safeeval);
336: if ($jmeanswer ne '') {
337: my $options=&Apache::lonxml::get_param('options',$parstack,
338: $safeeval);
339: my $width=&Apache::lonxml::get_param('width',$parstack,
340: $safeeval);
341: my (@answers)=&Apache::lonxml::get_param_var('answer',$parstack,
342: $safeeval);
343: $result.=&jme_img($jmeanswer,$answers[0],$width,$options);
344: }
345: } else {
346: $result.= '<input type="hidden" name="MOLECULE_'.$id.'" value="" />';
347: }
348: } elsif ($target eq 'edit') {
349: $result .=&Apache::edit::tag_start($target,$token);
350: my $options=&Apache::lonxml::get_param('options',$parstack,
351: $safeeval);
352: if ($options !~ /multipart/) { $options.=',multipart'; }
353: $result .='<span class="LC_nobreak">'.
354: &Apache::edit::text_arg('Starting Molecule:','molecule',
355: $token,40);
356: my $molecule=&Apache::lonxml::get_param('molecule',$parstack,
357: $safeeval);
358: $result .=&separate_jme_window(undef,
359: &Apache::edit::html_element_name('molecule'),
360: $molecule,$options);
361: $result .='</span><br /><span class="LC_nobreak">';
362: $result .=&Apache::edit::text_arg('Correct Answer:','answer',
363: $token,40);
364: $result .='</span><br /><span class="LC_nobreak">';
365: $result .=&Apache::edit::text_arg('JME string of the answer - automatically updated by "Insert Answer" in the JME pop-up (click pencil):',
366: 'jmeanswer',$token);
367: my $jmeanswer=&Apache::lonxml::get_param('jmeanswer',$parstack,
368: $safeeval);
369: $result .=&separate_jme_window(
370: &Apache::edit::html_element_name('answer'),
371: &Apache::edit::html_element_name('jmeanswer'),
372: $jmeanswer,$options);
373: $result .='</span><br />';
374: $result .=&Apache::edit::checked_arg('Options:','options',
375: [ ['autoez','Auto E,Z stereochemistry'],
376: ['multipart','Multipart Structures'],
377: ['nostereo','No stereochemistry'],
378: ['reaction','Is a reaction'],
379: ['number','Able to number atoms'] ],
380: ,$token);
381: $result .=&Apache::edit::text_arg('Width of correct answer image:',
382: 'width',$token,10);
383: $result .=&Apache::edit::end_row().&Apache::edit::start_spanning_row();
384: } elsif ($target eq 'modified') {
385: my $constructtag=&Apache::edit::get_new_args($token,$parstack,
386: $safeeval,'molecule',
387: 'answer','jmeanswer',
388: 'options','width');
389: if ($constructtag) { $result = &Apache::edit::rebuild_tag($token); }
390: }
391:
392: return $result;
393: }
394:
395: sub end_organicresponse {
396: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
397: my $result;
398:
399: my $partid = $Apache::inputtags::part;
400: my $id = $Apache::inputtags::response['-1'];
401:
402: if ($target eq 'grade'
403: && &Apache::response::submitted()
404: && $Apache::lonhomework::type eq 'exam') {
405:
406: &Apache::response::scored_response($partid,$id);
407:
408: } elsif ($target eq 'grade'
409: && &Apache::response::submitted()
410: && $Apache::lonhomework::type ne 'exam') {
411:
412: &Apache::response::setup_params($$tagstack[-1],$safeeval);
413: my $response = &Apache::response::getresponse();
414: if ( $response =~ /[^\s]/) {
415: my (@answers)=&Apache::lonxml::get_param_var('answer',$parstack,$safeeval);
416: my %previous = &Apache::response::check_for_previous($response,$partid,$id);
417: $Apache::lonhomework::results{"resource.$partid.$id.submission"}=$response;
418: my $ad;
419: foreach my $answer (@answers) {
420: &Apache::lonxml::debug("submitted a $response for $answer<br \>\n");
421: if ($response eq $answer) {
422: $ad='EXACT_ANS';
423: last;
424: } else {
425: $ad='INCORRECT';
426: }
427: }
428: if ($ad) {
429: if ($Apache::lonhomework::type eq 'survey') {
430: $ad='SUBMITTED';
431: } elsif ($Apache::lonhomework::type eq 'surveycred') {
432: $ad='SUBMITTED_CREDIT';
433: } elsif ($Apache::lonhomework::type eq 'anonsurvey') {
434: $ad='ANONYMOUS';
435: } elsif ($Apache::lonhomework::type eq 'anonsurveycred') {
436: $ad='ANONYMOUS_CREDIT';
437: }
438: }
439: &Apache::response::handle_previous(\%previous,$ad);
440: $Apache::lonhomework::results{"resource.$partid.$id.awarddetail"}=$ad;
441: $Apache::lonhomework::results{"resource.$partid.$id.molecule"}=$env{"form.MOLECULE_$id"};
442: }
443: } elsif ($target eq "edit") {
444: $result.= &Apache::edit::tag_end($target,$token,'');
445: } elsif ($target eq 'answer') {
446: my (@answers)=&Apache::lonxml::get_param_var('answer',$parstack,
447: $safeeval);
448: $result.=&Apache::response::answer_header('organicresponse');
449: foreach my $answer (@answers) {
450: $result.=&Apache::response::answer_part('organicresponse',$answer);
451: }
452: $result.=&Apache::response::answer_footer('organicresponse');
453: }
454: if ($target eq 'web') {
455: &Apache::response::setup_prior_tries_hash(\&format_prior_answer_organic,
456: ['molecule'])
457: }
458:
459: if ($target eq 'grade' || $target eq 'web' || $target eq 'answer' ||
460: $target eq 'tex' || $target eq 'analyze') {
461: my $repetition = &Apache::response::repetition();
462: &Apache::lonxml::increment_counter($repetition,"$partid.$id"); # part.response
463: if ($target eq 'analyze') {
464: $Apache::lonhomework::analyze{"$partid.$id.type"} = 'organicresponse';
465: push (@{ $Apache::lonhomework::analyze{"parts"} },"$partid.$id");
466: &Apache::lonhomework::set_bubble_lines();
467: }
468: }
469: if ($target eq 'web' ) {
470: my ($showpencil,$shown_text);
471: if ($Apache::inputtags::status['-1'] eq 'CAN_ANSWER') {
472: $showpencil = 1;
473: } elsif (&Apache::response::show_answer()) {
474: my $jmeanswer=&Apache::lonxml::get_param('jmeanswer',$parstack, $safeeval);
475: if ($jmeanswer eq '') {
476: $showpencil = 1;
477: $shown_text="Show Your Last Answer";
478: }
479: }
480: if ($showpencil) {
481: my $options=&Apache::lonxml::get_param('options',$parstack,
482: $safeeval);
483:
484: my $molecule;
485: if (defined($Apache::lonhomework::history{"resource.$partid.$id.molecule"})) {
486: $molecule=$Apache::lonhomework::history{"resource.$partid.$id.molecule"};
487: } else {
488: $molecule=&Apache::lonxml::get_param('molecule',$parstack,
489: $safeeval);
490: }
491: $result.=&separate_jme_window("HWVAL_$id","MOLECULE_$id",$molecule,
492: $options,$shown_text);
493: }
494: }
495: &Apache::response::end_response();
496: return $result;
497: }
498:
499: sub format_prior_answer_organic {
500: my ($mode,$answer,$other_data) = @_;
501: my $result=&mt('Smile representation: [_1]','"<tt>'.$answer.'</tt>"');
502: my $jme=$other_data->[0];
503: $result.=&jme_img($jme,$answer,400);
504: return $result;
505: }
506:
507: sub start_organicstructure {
508: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
509: my $result;
510: if ($target eq 'web') {
511: my $width=&Apache::lonxml::get_param('width',$parstack,$safeeval);
512: my $molecule=&Apache::lonxml::get_param('molecule',$parstack,$safeeval);
513: my $options=&Apache::lonxml::get_param('options',$parstack,$safeeval);
514: my $id=&Apache::loncommon::get_cgi_id();
515: $result="<img src='/cgi-bin/convertjme.pl?$id'";
516: if ($options =~ /border/) { $result.= ' border="1"'; }
517: $result.=' />';
518: &Apache::lonnet::appenv(
519: {'cgi.'.$id.'.JME' => &escape($molecule),
520: 'cgi.'.$id.'.PNG' => 1,
521: 'cgi.'.$id.'.WIDTH' => $width});
522: } elsif ($target eq 'tex') {
523: my $texwidth=&Apache::lonxml::get_param('texwidth',$parstack,$safeeval,undef,1);
524: my $webwidth=&Apache::lonxml::get_param('width', $parstack, $safeeval);
525: my $webheight=&Apache::lonxml::get_param('height', $parstack, $safeeval);
526: if (!$webheight) { $webheight = $webwidth; }
527: if (!$texwidth) { $texwidth='90'; }
528: $result = "%DYNAMICIMAGE:$webwidth:$webheight:$texwidth\n";
529: my $molecule=&Apache::lonxml::get_param('molecule',$parstack,$safeeval);
530: my $options=&Apache::lonxml::get_param('options',$parstack,$safeeval);
531: my $filename = $env{'user.name'}.'_'.$env{'user.domain'}.
532: '_'.time.'_'.$$.int(rand(1000)).'_organicstructure';
533: my $id=$filename;
534: &Apache::lonnet::appenv(
535: {'cgi.'.$id.'.JME' => &escape($molecule),
536: 'cgi.'.$id.'.PS' => 1,
537: 'cgi.'.$id.'.WIDTH' => $texwidth});
538: $id=&escape($id);
539: &Apache::lonxml::register_ssi("/cgi-bin/convertjme.pl?$id");
540: if ($options =~ /border/) { $result.= '\fbox{'; }
541: $result .= '\graphicspath{{'.LONCAPA::tempdir().
542: '}}\includegraphics[width='.$texwidth.' mm]{'.$filename.'.eps}';
543: if ($options =~ /border/) { $result.= '} '; }
544: } elsif ($target eq 'edit') {
545: $result .=&Apache::edit::tag_start($target,$token);
546: $result .=&Apache::edit::text_arg('Width (pixels):','width',$token,5);
547: $result .=&Apache::edit::text_arg('TeXwidth (mm):','texwidth',$token,5);
548: $result .='<span class="LC_nobreak">';
549: $result .=&Apache::edit::text_arg('Molecule:','molecule',$token,40);
550: my $molecule=&Apache::lonxml::get_param('molecule',$parstack,
551: $safeeval);
552: my $options=&Apache::lonxml::get_param('options',$parstack,
553: $safeeval);
554: if ($options !~ /reaction/) {
555: $options.= ',multipart,number';
556: }
557:
558: $result .=&separate_jme_window(undef,
559: &Apache::edit::html_element_name('molecule'),
560: $molecule,$options);
561: $result.="</span><br />";
562: $result .=&Apache::edit::checked_arg('Options:','options',
563: [ ['reaction','Is a reaction'],
564: ['border','Draw a border'] ],
565: $token);
566: $result .=&Apache::edit::end_row();
567: } elsif ($target eq 'modified') {
568: my $constructtag=&Apache::edit::get_new_args($token,$parstack,
569: $safeeval,'molecule',
570: 'width','texwidth',
571: 'options');
572: if ($constructtag) { $result = &Apache::edit::rebuild_tag($token); }
573: }
574: return $result;
575: }
576:
577: sub end_organicstructure {
578: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
579: my $result;
580: if ($target eq "edit") {
581: $result.= &Apache::edit::tag_end($target,$token,'');
582: }
583: return $result;
584: }
585:
586: sub edit_reaction_button {
587: my ($id,$field,$reaction)=@_;
588: my $id_es=&escape($id);
589: my $field_es=&escape($field);
590: my $reaction_es=&escape($reaction);
591: my $docopen=&Apache::lonhtmlcommon::javascript_docopen();
592: my $iconpath=$Apache::lonnet::perlvar{'lonIconsURL'};
593: my $display=&mt('Edit Answer');
594: my $start_page =
595: &Apache::loncommon::start_page('LON-CAPA Reaction Editor',undef,
596: {'frameset' => 1,
597: 'js_ready' => 1,
598: 'add_entries' => {
599: 'rows' => "30%,*",
600: 'border' => "0",}},);
601: my $end_page =
602: &Apache::loncommon::end_page({'frameset' => 1,
603: 'js_ready' => 1});
604: my $result=<<EDITREACTION;
605: <script type="text/javascript">
606: // <!--
607: function create_reaction_window_${id}_${field} () {
608: editor=window.open('','','width=500,height=270,scrollbars=no,resizable=yes');
609: editor.$docopen;
610: editor.document.writeln('$start_page <frame src="/res/adm/pages/reactionresponse/reaction_viewer.html?inhibitmenu=yes" name="viewer" scrolling="no" /> <frame src="/res/adm/pages/reactionresponse/reaction_editor.html?inhibitmenu=yes&reaction=$reaction_es&id=$id_es&field=$field_es" name="editor" scrolling="no" /> $end_page');
611: editor.document.close();
612: }
613: // -->
614: </script>
615: <a href="javascript:create_reaction_window_${id}_${field}();void(0);"><img class="stift" src='$iconpath/stift.gif' alt='$display' title='$display' /></a>
616: EDITREACTION
617: return $result;
618: }
619:
620: sub start_reactionresponse {
621: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
622: my $result;
623: my $id = &Apache::response::start_response($parstack,$safeeval);
624: if ($target eq 'meta') {
625: $result=&Apache::response::meta_package_write('reactionresponse');
626: } elsif ($target eq 'web') {
627: my $partid = $Apache::inputtags::part;
628: my $id = $Apache::inputtags::response['-1'];
629: if ( &Apache::response::show_answer() ) {
630: my $ans=&Apache::lonxml::get_param('answer',$parstack,$safeeval);
631: if (!$Apache::lonxml::default_homework_loaded) {
632: &Apache::lonxml::default_homework_load($safeeval);
633: }
634: @Apache::scripttag::parser_env = @_;
635: $Apache::inputtags::answertxt{$id}=[&Apache::run::run("return &chemparse(q\0$ans\0);",$safeeval)];
636: }
637: } elsif ($target eq "edit") {
638: $result .=&Apache::edit::tag_start($target,$token);
639: my $answer=&Apache::lonxml::get_param('answer',$parstack,
640: $safeeval);
641: $result .='<span class="LC_nobreak">'.
642: &Apache::edit::text_arg('Answer:','answer',$token,40);
643: $result .=&edit_reaction_button($id,&Apache::edit::html_element_name('answer'),$answer).'</span>';
644: my $initial=&Apache::lonxml::get_param('initial',$parstack,$safeeval);
645: $result.='<span class="LC_nobreak">'.
646: &Apache::edit::text_arg('Initial Reaction:','initial',$token,40);
647: $result .=&edit_reaction_button($id,&Apache::edit::html_element_name('initial'),$initial).'</span>';
648: $result .=&Apache::edit::end_row().&Apache::edit::start_spanning_row();
649: } elsif ($target eq 'modified') {
650: my $constructtag=&Apache::edit::get_new_args($token,$parstack,
651: $safeeval,'answer',
652: 'initial');
653: if ($constructtag) { $result = &Apache::edit::rebuild_tag($token); }
654: }
655: return $result;
656: }
657:
658: sub end_reactionresponse {
659: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
660: my $result;
661:
662: my $partid = $Apache::inputtags::part;
663: my $id = $Apache::inputtags::response['-1'];
664:
665: if ($target eq 'grade'
666: && &Apache::response::submitted()
667: && $Apache::lonhomework::type eq 'exam') {
668:
669: &Apache::response::scored_response($partid,$id);
670:
671: } elsif ($target eq 'grade'
672: && &Apache::response::submitted()
673: && $Apache::lonhomework::type ne 'exam') {
674:
675: &Apache::response::setup_params($$tagstack[-1],$safeeval);
676: my $response = &Apache::response::getresponse();
677: if ( $response =~ /[^\s]/) {
678: my (@answers)=&Apache::lonxml::get_param_var('answer',$parstack,$safeeval);
679: my %previous = &Apache::response::check_for_previous($response,$partid,$id);
680: $Apache::lonhomework::results{"resource.$partid.$id.submission"}=$response;
681: my $ad;
682: foreach my $answer (@answers) {
683: &Apache::lonxml::debug("submitted a $response for $answer<br \>\n");
684: if (&chem_standard_order($response) eq
685: &chem_standard_order($answer)) {
686: $ad='EXACT_ANS';
687: } else {
688: $ad='INCORRECT';
689: }
690: }
691: if ($ad) {
692: if ($Apache::lonhomework::type eq 'survey') {
693: $ad='SUBMITTED';
694: } elsif ($ad && $Apache::lonhomework::type eq 'surveycred') {
695: $ad='SUBMITTED_CREDIT';
696: } elsif ($ad && $Apache::lonhomework::type eq 'anonsurvey') {
697: $ad='ANONYMOUS';
698: } elsif ($ad && $Apache::lonhomework::type eq 'anonsurveycred') {
699: $ad='ANONYMOUS_CREDIT';
700: }
701: }
702: &Apache::response::handle_previous(\%previous,$ad);
703: $Apache::lonhomework::results{"resource.$partid.$id.awarddetail"}=$ad;
704: }
705: } elsif ($target eq "edit") {
706: $result.= &Apache::edit::tag_end($target,$token,'');
707: } elsif ($target eq 'answer') {
708: my (@answers)=&Apache::lonxml::get_param_var('answer',$parstack,
709: $safeeval);
710: $result.=&Apache::response::answer_header('reactionresponse');
711: foreach my $answer (@answers) {
712: $result.=&Apache::response::answer_part('reactionresponse',
713: $answer);
714: }
715: $result.=&Apache::response::answer_footer('reactionresponse');
716: }
717: if ($target eq 'web') {
718: &Apache::response::setup_prior_tries_hash(\&format_prior_response_reaction);
719: }
720:
721: if ($target eq 'grade' || $target eq 'web' || $target eq 'answer' ||
722: $target eq 'tex' || $target eq 'analyze') {
723: my $repetition = &Apache::response::repetition();
724: &Apache::lonxml::increment_counter($repetition,"$partid.$id");
725: if ($target eq 'analyze') {
726: $Apache::lonhomework::analyze{"$partid.$id.type"} = 'reactionresponse';
727: push (@{ $Apache::lonhomework::analyze{"parts"} },"$partid.$id");
728: &Apache::lonhomework::set_bubble_lines();
729: }
730: }
731: my $status=$Apache::inputtags::status['-1'];
732: if (($target eq 'web') && ($Apache::lonhomework::type ne 'exam') && ($status eq 'CAN_ANSWER')) {
733: my $reaction=$Apache::lonhomework::history{"resource.$partid.$id.submission"};
734: if ($reaction eq '') { $reaction=&Apache::lonxml::get_param('initial',$parstack,$safeeval); }
735: $result.=&edit_reaction_button($id,"HWVAL_$id",$reaction);
736: }
737: &Apache::response::end_response();
738: return $result;
739: }
740:
741: sub format_prior_response_reaction {
742: my ($mode,$answer) =@_;
743: return '<span class="LC_prior_reaction">'.
744: &HTML::Entities::encode($answer,'"<>&').'</span>';
745: }
746:
747: sub start_chem {
748: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style) = @_;
749: my $result = '';
750: my $inside = &Apache::lonxml::get_all_text_unbalanced("/chem",$parser);
751: if ($target eq 'tex' || $target eq 'web') {
752: $inside=&Apache::run::evaluate($inside,$safeeval,$$parstack[-1]);
753: if (!$Apache::lonxml::default_homework_loaded) {
754: &Apache::lonxml::default_homework_load($safeeval);
755: }
756: @Apache::scripttag::parser_env = @_;
757: $result=&Apache::run::run("return &chemparse(q\0$inside\0);",$safeeval);
758: }
759: return $result;
760: }
761:
762: sub end_chem {
763: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style) = @_;
764: my $result = '';
765: return $result;
766: }
767:
768: my $uniq=0;
769: sub get_uniq_name {
770: $uniq++;
771: return 'uniquename'.$uniq;
772: }
773:
774: 1;
775: __END__
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>