Annotation of loncom/homework/chemresponse.pm, revision 1.99
1.1 albertel 1: # The LearningOnline Network with CAPA
2: # chemical equation style response
3: #
1.99 ! damieng 4: # $Id: chemresponse.pm,v 1.98 2015/09/21 14:24:54 raeburn Exp $
1.1 albertel 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;
1.55 albertel 33: use Apache::lonlocal;
1.66 www 34: use lib '/home/httpd/lib/perl/';
35: use LONCAPA;
36:
1.1 albertel 37:
38: BEGIN {
1.46 albertel 39: &Apache::lonxml::register('Apache::chemresponse',('organicresponse','organicstructure','reactionresponse','chem'));
1.1 albertel 40: }
41:
1.34 albertel 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:
1.30 www 69: sub separate_jme_window {
1.55 albertel 70: my ($smile_input,$jme_input,$molecule,$options,$shown_text)=@_;
1.94 raeburn 71: my $usejsme = 1;
1.95 raeburn 72: if (($env{'request.course.id'}) && ($env{'request.state'} ne 'construct')) {
73: if (exists($env{'course.'.$env{'request.course.id'}.'.usejsme'})) {
74: if ($env{'course.'.$env{'request.course.id'}.'.usejsme'} eq '0') {
75: $usejsme = 0;
76: }
77: } else {
78: my %domdefs = &Apache::lonnet::get_domain_defaults($env{'course.'.$env{'request.course.id'}.'.domain'});
79: if ($domdefs{'usejsme'} eq '0') {
80: $usejsme = 0;
81: }
82: }
83: } else {
84: my %domdefs = &Apache::lonnet::get_domain_defaults($env{'course.'.$env{'request.course.id'}.'.domain'});
85: if ($domdefs{'usejsme'} eq '0') {
86: $usejsme = 0;
87: }
88: }
89: if ($usejsme) {
1.96 raeburn 90: if ($env{'browser.type'} eq 'safari') {
91: unless ($env{'browser.mobile'}) {
1.97 raeburn 92: if ($env{'browser.version'} < 534) {
1.96 raeburn 93: $usejsme = 0;
94: }
95: }
96: } elsif ($env{'browser.type'} eq 'mozilla') {
97: if ($env{'browser.version'} < 5) {
98: $usejsme = 0;
99: } elsif ($env{'browser.info'} =~ /^firefox\-([\d\.]+)/) {
100: my $firefox = $1;
101: if ($firefox < 12) {
102: $usejsme = 0;
103: }
104: }
105: } elsif ($env{'browser.type'} eq 'explorer') {
106: if ($env{'browser.version'} < 7) {
107: $usejsme = 0;
108: }
109: } elsif ($env{'browser.type'} eq 'opera') {
110: if ($env{'browser.version'} < 15) {
1.95 raeburn 111: $usejsme = 0;
112: }
113: }
114: } else {
115: if ($env{'browser.mobile'}) {
116: $usejsme = 1;
117: }
118: }
1.94 raeburn 119: my $linkstyle = 'display:none';
120: my $creditstyle = 'display:inline';
121: if ($env{'browser.type'} eq 'explorer') {
122: if (($env{'browser.os'} eq 'win') && ($env{'browser.version'} < 9)) {
123: $linkstyle = 'display:inline';
124: $creditstyle = 'display:none';
125: }
126: }
1.2 albertel 127: my $smilesection;
128: if (defined($smile_input)) {
1.94 raeburn 129: my $smiles;
130: if ($usejsme) {
131: $smiles = 'document.JME.smiles()';
132: } else {
133: $smiles = 'document.applets.JME.smiles()';
134: }
1.2 albertel 135: $smilesection=<<SMILESECTION;
1.94 raeburn 136: opener.document.lonhomework.$smile_input.value = $smiles;
1.2 albertel 137: SMILESECTION
138: }
139: my $jmesection;
1.94 raeburn 140: my $jmefile;
1.2 albertel 141: if (defined($jme_input)) {
1.94 raeburn 142: if ($usejsme) {
143: $jmefile = 'document.JME.jmeFile()';
144: } else {
145: $jmefile = 'document.applets.JME.jmeFile()';
146: }
1.2 albertel 147: $jmesection=<<JMESECTION;
1.94 raeburn 148: opener.document.lonhomework.$jme_input.value = $jmefile;
1.2 albertel 149: JMESECTION
150: }
151:
1.94 raeburn 152: if ($molecule) {
153: if ($usejsme) {
154: $molecule = 'document.JME.readMolecule("'.$molecule.'")';
155: } else {
156: $molecule='<param name="jme" value="'.$molecule.'" />';
157: }
158: }
1.57 albertel 159: my $insert_answer;
1.59 albertel 160: if ($shown_text eq '') {
1.57 albertel 161: $insert_answer=
1.94 raeburn 162: '<input type="button" name="submit" value="'.&mt('Insert Answer').'" onclick="javascript:submitSmiles();" /><br />';
163: }
164:
165:
166:
167: my ($jsme_js,$js,$buttonstyle,$viewportjs,$resizejs);
168: if ($usejsme) {
169: $buttonstyle = 'display:none';
170: $resizejs =<<RESIZEJS;
171: <script type="text/javascript">
172: function callResize() {
173: var timer;
174: clearTimeout(timer);
175: timer=setTimeout('resize_jsme()',100);
176: }
177:
178: window.onresize = callResize;
179:
180: function resize_jsme() {
181: init_geometry();
182: var vph = Geometry.getViewportHeight();
183: var vpw = Geometry.getViewportWidth();
184: var lowerdivheight = document.getElementById('JMEbuttons').offsetHeight;
185: var formheight = document.getElementById('JMEform').offsetHeight;
186: var freevspace = vph-(lowerdivheight+50);
187: var freehspace = vpw-20;
188: if (typeof jsmeApplet !== 'undefined') {
189: jsmeApplet.setSize(freehspace,freevspace);
190: }
191: }
192: </script>
193: RESIZEJS
194: $resizejs = &Apache::loncommon::js_ready($resizejs);
195: $jsme_js = '
196: <script type="text/javascript" language="javascript" src="/adm/jsme/jsme.nocache.js"></script>'."\n";
197: $js =<<CHEMJS;
198: <script type="text/javascript">
199: function jsmeOnLoad() {
200: document.getElementById('JMErefresh').style.display="none";
201: document.getElementById('JMEcredits').style.display="inline";
202: jsmeApplet = new JSApplet.JSME("jme", "420px", "330px");
203: document.JME = jsmeApplet;
204: $molecule;
205: document.getElementById('JMEbuttons').style.display="block";
206: callResize();
207: }
208:
209: function submitSmiles() {
210: jmeFile = document.JME.jmeFile();
211: if (jmeFile == "") {
212: alert("Nothing to submit");
213: } else {
214: $jmesection
215: $smilesection
216: window.close();
1.57 albertel 217: }
1.94 raeburn 218: }
219: function openHelpWindow() {
220: window.open("http://peter-ertl.com/jsme/2013_03/help.html","","scrollbars=yes,resizable=yes,width=500,height=600");
221: }
222:
223: </script>
224:
225: CHEMJS
1.57 albertel 226:
1.94 raeburn 227: $viewportjs = &Apache::loncommon::viewport_geometry_js();
228: $viewportjs = '<script type="text/javascript">'."\n".
229: $viewportjs."\n".
230: '</script>';
231:
232: } else {
233: $buttonstyle = 'display:block';
234: $js =<<CHEMJS;
1.47 albertel 235: <script type="text/javascript">
1.1 albertel 236: function submitSmiles() {
1.21 albertel 237: jmeFile = document.applets.JME.jmeFile();
238: if (jmeFile == "") {
1.1 albertel 239: alert("Nothing to submit");
240: } else {
1.21 albertel 241: $jmesection
1.2 albertel 242: $smilesection
1.1 albertel 243: window.close();
244: }
245: }
246: function openHelpWindow() {
1.2 albertel 247: window.open("/adm/jme/jme_help.html","","scrollbars=yes,resizable=yes,width=500,height=600");
1.1 albertel 248: }
1.60 albertel 249: function substituent(r) {document.applets.JME.setSubstituent(r);}
1.1 albertel 250: </script>
1.65 albertel 251: CHEMJS
1.94 raeburn 252: }
1.65 albertel 253:
254: my $start_page =
1.94 raeburn 255: &Apache::loncommon::start_page('Molecule Editor',$viewportjs,
1.65 albertel 256: {'only_body' => 1,
1.69 albertel 257: 'js_ready' => 1,
1.65 albertel 258: 'bgcolor' => '#FFFFFF',});
1.69 albertel 259: my $end_page =
260: &Apache::loncommon::end_page({'js_ready' => 1,});
1.88 www 261: my $java_not_enabled=&Apache::lonhtmlcommon::java_not_enabled();
1.93 bisitz 262: my %lt = &Apache::lonlocal::texthash(
263: 'seltext' => 'Select substituent...',
264: 'close' => 'Close',
265: 'help' => 'Help',
266: );
1.94 raeburn 267: my $body = "
268: $jsme_js
269: $js".'
1.1 albertel 270: <center>
1.94 raeburn 271: <form action="" id="JMEform">
272: ';
273: if ($usejsme) {
274: $body.= <<"ENDCHEM";
275: <div id="jme">
276: <div id="JMEcredits" style="$creditstyle">
277: <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>
278: </div>
279: ENDCHEM
280: } else {
281: $body.=<<CHEMPAGE;
1.60 albertel 282: <table width="440"><tr>
283: <td></td>
284: <td align="right">
285: <select onchange="javascript:substituent(options[selectedIndex].text)">
1.93 bisitz 286: <option>$lt{'seltext'}</option>
1.60 albertel 287: <option>-C(=O)OH</option>
288: <option>-C(=O)OMe</option>
289: <option>-OC(=O)Me</option>
290: <option>-CMe3</option>
291: <option>-CF3</option>
292: <option>-CCl3</option>
293: <option>-NO2</option>
294: <option>-SO2-NH2</option>
295: <option>-NH-SO2-Me</option>
296: <option>-NMe2</option>
297: <option>-C#N</option>
298: <option>-C#C-Me</option>
299: <option>-C#CH</option>
300: </select>
301: </td></tr>
302: </table>
303: <applet code="JME.class" name="JME" archive="/adm/jme/JME.jar" width="440" height="390" mayscript>
1.88 www 304: $java_not_enabled
1.12 albertel 305: $molecule
1.6 albertel 306: <param name="options" value="$options" />
1.94 raeburn 307: </applet>
308: <br />
1.49 albertel 309: <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>
1.94 raeburn 310: CHEMPAGE
311: }
312: $body .= <<CHEMPAGE;
313: <div id="JMEbuttons" style="$buttonstyle">
1.57 albertel 314: $insert_answer
1.93 bisitz 315: <input type="button" value="$lt{'close'}" onclick="javascript:window.close()" />
1.1 albertel 316:
1.93 bisitz 317: <input type="button" value="$lt{'help'}" onclick="javascript:openHelpWindow()" />
1.94 raeburn 318: </div>
319: <div id="JMErefresh" style="$linkstyle">
320: <a href="javascript:location.reload();">Display Molecule Editor</a>
321: </div>
1.1 albertel 322: </form>
323: </center>
324: CHEMPAGE
1.65 albertel 325:
1.69 albertel 326: $body=&Apache::loncommon::js_ready($body);
1.53 albertel 327: my $nothing=&Apache::lonhtmlcommon::javascript_nothing();
1.41 www 328: my $docopen=&Apache::lonhtmlcommon::javascript_docopen();
1.55 albertel 329: my $display=&mt('Draw Molecule');
330: if (defined($shown_text)) { $display=&mt($shown_text); }
1.79 riegler 331: my $iconpath=$Apache::lonnet::perlvar{'lonIconsURL'};
1.94 raeburn 332: my $function =
1.91 raeburn 333: 'LONCAPA_draw_molecule_'.&get_uniq_name();
1.1 albertel 334: my $result=<<CHEMINPUT;
1.69 albertel 335: <script type="text/javascript">
336: function $function() {
337: editor=window.open($nothing,'jmeedit','width=500,height=500,menubar=no,scrollbars=no,resizable=yes');
1.94 raeburn 338: if (editor) {
339: editor.$docopen;
340: editor.document.write('$start_page $body $resizejs $end_page');
341: editor.document.close();
342: editor.focus();
343: }
1.69 albertel 344: }
345: </script>
1.86 raeburn 346: CHEMINPUT
1.94 raeburn 347: my $jscall = "javascript:$function();void(0);";
1.86 raeburn 348: if ($shown_text eq '') {
1.94 raeburn 349: $result .=<<PENCIL;
350: <a href="$jscall"><img class="stift" src="$iconpath/stift.gif" alt="$display" title="$display" /></a>
1.86 raeburn 351: PENCIL
352: } else {
1.94 raeburn 353: $result .= '<input type="button" value="'.&mt($shown_text).'" onclick="$jscall" />';
1.86 raeburn 354: }
1.1 albertel 355: return $result;
356: }
1.56 albertel 357: sub jme_img {
358: my ($jme,$smile,$width,$options)=@_;
359: my $id=&Apache::loncommon::get_cgi_id();
360: my $result='<img alt="'.$smile.'" src="/cgi-bin/convertjme.pl?'.$id.'"';
361: if ($options =~ /border/) { $result.= ' border="1"'; }
362: $result.=' />';
1.78 raeburn 363: &Apache::lonnet::appenv({'cgi.'.$id.'.JME' =>
364: &escape($jme),
365: 'cgi.'.$id.'.PNG' => 1,
366: 'cgi.'.$id.'.WIDTH' => $width});
1.56 albertel 367: return $result;
368: }
369:
1.6 albertel 370: sub start_organicresponse {
1.1 albertel 371: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
372: my $result;
373: my $partid = $Apache::inputtags::part;
374: my $id = &Apache::response::start_response($parstack,$safeeval);
375: if ($target eq 'meta') {
1.28 albertel 376: $result=&Apache::response::meta_package_write('organicresponse');
1.1 albertel 377: } elsif ($target eq 'web') {
1.55 albertel 378: my $jmeanswer=&Apache::lonxml::get_param('jmeanswer',$parstack,
379: $safeeval);
1.86 raeburn 380: if (&Apache::response::show_answer()) {
381: my $jmeanswer=&Apache::lonxml::get_param('jmeanswer',$parstack,
382: $safeeval);
383: if ($jmeanswer ne '') {
384: my $options=&Apache::lonxml::get_param('options',$parstack,
385: $safeeval);
386: my $width=&Apache::lonxml::get_param('width',$parstack,
387: $safeeval);
388: my (@answers)=&Apache::lonxml::get_param_var('answer',$parstack,
389: $safeeval);
390: $result.=&jme_img($jmeanswer,$answers[0],$width,$options);
391: }
1.1 albertel 392: } else {
1.44 albertel 393: $result.= '<input type="hidden" name="MOLECULE_'.$id.'" value="" />';
1.1 albertel 394: }
1.2 albertel 395: } elsif ($target eq 'edit') {
396: $result .=&Apache::edit::tag_start($target,$token);
1.12 albertel 397: my $options=&Apache::lonxml::get_param('options',$parstack,
398: $safeeval);
399: if ($options !~ /multipart/) { $options.=',multipart'; }
1.83 bisitz 400: $result .='<span class="LC_nobreak">'.
1.7 albertel 401: &Apache::edit::text_arg('Starting Molecule:','molecule',
402: $token,40);
1.2 albertel 403: my $molecule=&Apache::lonxml::get_param('molecule',$parstack,
404: $safeeval);
1.30 www 405: $result .=&separate_jme_window(undef,
1.2 albertel 406: &Apache::edit::html_element_name('molecule'),
1.12 albertel 407: $molecule,$options);
1.83 bisitz 408: $result .='</span><br /><span class="LC_nobreak">';
1.2 albertel 409: $result .=&Apache::edit::text_arg('Correct Answer:','answer',
410: $token,40);
1.85 raeburn 411: $result .='</span><br /><span class="LC_nobreak">';
1.86 raeburn 412: $result .=&Apache::edit::text_arg('JME string of the answer - automatically updated by "Insert Answer" in the JME pop-up (click pencil):',
1.67 albertel 413: 'jmeanswer',$token);
1.2 albertel 414: my $jmeanswer=&Apache::lonxml::get_param('jmeanswer',$parstack,
415: $safeeval);
1.30 www 416: $result .=&separate_jme_window(
1.2 albertel 417: &Apache::edit::html_element_name('answer'),
418: &Apache::edit::html_element_name('jmeanswer'),
1.12 albertel 419: $jmeanswer,$options);
1.83 bisitz 420: $result .='</span><br />';
1.12 albertel 421: $result .=&Apache::edit::checked_arg('Options:','options',
1.29 www 422: [ ['autoez','Auto E,Z stereochemistry'],
1.18 albertel 423: ['multipart','Multipart Structures'],
1.12 albertel 424: ['nostereo','No stereochemistry'],
425: ['reaction','Is a reaction'],
1.18 albertel 426: ['number','Able to number atoms'] ],
1.12 albertel 427: ,$token);
1.44 albertel 428: $result .=&Apache::edit::text_arg('Width of correct answer image:',
429: 'width',$token,10);
1.2 albertel 430: $result .=&Apache::edit::end_row().&Apache::edit::start_spanning_row();
431: } elsif ($target eq 'modified') {
432: my $constructtag=&Apache::edit::get_new_args($token,$parstack,
433: $safeeval,'molecule',
1.6 albertel 434: 'answer','jmeanswer',
1.44 albertel 435: 'options','width');
1.2 albertel 436: if ($constructtag) { $result = &Apache::edit::rebuild_tag($token); }
1.1 albertel 437: }
1.63 albertel 438:
1.1 albertel 439: return $result;
440: }
441:
1.6 albertel 442: sub end_organicresponse {
1.1 albertel 443: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
444: my $result;
1.64 albertel 445:
446: my $partid = $Apache::inputtags::part;
447: my $id = $Apache::inputtags::response['-1'];
448:
449: if ($target eq 'grade'
450: && &Apache::response::submitted()
451: && $Apache::lonhomework::type eq 'exam') {
452:
453: &Apache::response::scored_response($partid,$id);
454:
455: } elsif ($target eq 'grade'
456: && &Apache::response::submitted()
457: && $Apache::lonhomework::type ne 'exam') {
458:
1.31 albertel 459: &Apache::response::setup_params($$tagstack[-1],$safeeval);
1.1 albertel 460: my $response = &Apache::response::getresponse();
461: if ( $response =~ /[^\s]/) {
1.13 albertel 462: my (@answers)=&Apache::lonxml::get_param_var('answer',$parstack,$safeeval);
1.1 albertel 463: my %previous = &Apache::response::check_for_previous($response,$partid,$id);
464: $Apache::lonhomework::results{"resource.$partid.$id.submission"}=$response;
465: my $ad;
1.13 albertel 466: foreach my $answer (@answers) {
467: &Apache::lonxml::debug("submitted a $response for $answer<br \>\n");
468: if ($response eq $answer) {
469: $ad='EXACT_ANS';
470: last;
471: } else {
472: $ad='INCORRECT';
473: }
1.1 albertel 474: }
1.87 raeburn 475: if ($ad) {
476: if ($Apache::lonhomework::type eq 'survey') {
477: $ad='SUBMITTED';
478: } elsif ($Apache::lonhomework::type eq 'surveycred') {
479: $ad='SUBMITTED_CREDIT';
480: } elsif ($Apache::lonhomework::type eq 'anonsurvey') {
481: $ad='ANONYMOUS';
482: } elsif ($Apache::lonhomework::type eq 'anonsurveycred') {
483: $ad='ANONYMOUS_CREDIT';
484: }
485: }
1.1 albertel 486: &Apache::response::handle_previous(\%previous,$ad);
487: $Apache::lonhomework::results{"resource.$partid.$id.awarddetail"}=$ad;
1.50 albertel 488: $Apache::lonhomework::results{"resource.$partid.$id.molecule"}=$env{"form.MOLECULE_$id"};
1.1 albertel 489: }
1.2 albertel 490: } elsif ($target eq "edit") {
491: $result.= &Apache::edit::tag_end($target,$token,'');
1.15 albertel 492: } elsif ($target eq 'answer') {
493: my (@answers)=&Apache::lonxml::get_param_var('answer',$parstack,
494: $safeeval);
495: $result.=&Apache::response::answer_header('organicresponse');
496: foreach my $answer (@answers) {
497: $result.=&Apache::response::answer_part('organicresponse',$answer);
498: }
499: $result.=&Apache::response::answer_footer('organicresponse');
1.1 albertel 500: }
1.73 albertel 501: if ($target eq 'web') {
502: &Apache::response::setup_prior_tries_hash(\&format_prior_answer_organic,
503: ['molecule'])
504: }
1.63 albertel 505:
506: if ($target eq 'grade' || $target eq 'web' || $target eq 'answer' ||
507: $target eq 'tex' || $target eq 'analyze') {
1.90 raeburn 508: my $repetition = &Apache::response::repetition();
509: &Apache::lonxml::increment_counter($repetition,"$partid.$id"); # part.response
1.74 foxr 510: if ($target eq 'analyze') {
1.76 raeburn 511: $Apache::lonhomework::analyze{"$partid.$id.type"} = 'organicresponse';
1.84 raeburn 512: push (@{ $Apache::lonhomework::analyze{"parts"} },"$partid.$id");
1.74 foxr 513: &Apache::lonhomework::set_bubble_lines();
514: }
1.63 albertel 515: }
1.86 raeburn 516: if ($target eq 'web' ) {
517: my ($showpencil,$shown_text);
518: if ($Apache::inputtags::status['-1'] eq 'CAN_ANSWER') {
519: $showpencil = 1;
520: } elsif (&Apache::response::show_answer()) {
521: my $jmeanswer=&Apache::lonxml::get_param('jmeanswer',$parstack, $safeeval);
522: if ($jmeanswer eq '') {
523: $showpencil = 1;
524: $shown_text="Show Your Last Answer";
525: }
526: }
527: if ($showpencil) {
1.79 riegler 528: my $options=&Apache::lonxml::get_param('options',$parstack,
529: $safeeval);
1.86 raeburn 530:
1.79 riegler 531: my $molecule;
532: if (defined($Apache::lonhomework::history{"resource.$partid.$id.molecule"})) {
533: $molecule=$Apache::lonhomework::history{"resource.$partid.$id.molecule"};
534: } else {
535: $molecule=&Apache::lonxml::get_param('molecule',$parstack,
536: $safeeval);
537: }
1.86 raeburn 538: $result.=&separate_jme_window("HWVAL_$id","MOLECULE_$id",$molecule,
539: $options,$shown_text);
540: }
1.79 riegler 541: }
1.63 albertel 542: &Apache::response::end_response();
1.1 albertel 543: return $result;
544: }
545:
1.73 albertel 546: sub format_prior_answer_organic {
547: my ($mode,$answer,$other_data) = @_;
1.93 bisitz 548: my $result=&mt('Smile representation: [_1]','"<tt>'.$answer.'</tt>"');
1.73 albertel 549: my $jme=$other_data->[0];
550: $result.=&jme_img($jme,$answer,400);
551: return $result;
552: }
553:
1.6 albertel 554: sub start_organicstructure {
1.3 albertel 555: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
556: my $result;
557: if ($target eq 'web') {
558: my $width=&Apache::lonxml::get_param('width',$parstack,$safeeval);
559: my $molecule=&Apache::lonxml::get_param('molecule',$parstack,$safeeval);
1.12 albertel 560: my $options=&Apache::lonxml::get_param('options',$parstack,$safeeval);
1.23 albertel 561: my $id=&Apache::loncommon::get_cgi_id();
1.19 albertel 562: $result="<img src='/cgi-bin/convertjme.pl?$id'";
563: if ($options =~ /border/) { $result.= ' border="1"'; }
564: $result.=' />';
1.16 albertel 565: &Apache::lonnet::appenv(
1.78 raeburn 566: {'cgi.'.$id.'.JME' => &escape($molecule),
567: 'cgi.'.$id.'.PNG' => 1,
568: 'cgi.'.$id.'.WIDTH' => $width});
1.17 albertel 569: } elsif ($target eq 'tex') {
1.38 albertel 570: my $texwidth=&Apache::lonxml::get_param('texwidth',$parstack,$safeeval,undef,1);
1.58 foxr 571: my $webwidth=&Apache::lonxml::get_param('width', $parstack, $safeeval);
572: my $webheight=&Apache::lonxml::get_param('height', $parstack, $safeeval);
1.62 foxr 573: if (!$webheight) { $webheight = $webwidth; }
1.17 albertel 574: if (!$texwidth) { $texwidth='90'; }
1.58 foxr 575: $result = "%DYNAMICIMAGE:$webwidth:$webheight:$texwidth\n";
1.17 albertel 576: my $molecule=&Apache::lonxml::get_param('molecule',$parstack,$safeeval);
577: my $options=&Apache::lonxml::get_param('options',$parstack,$safeeval);
1.50 albertel 578: my $filename = $env{'user.name'}.'_'.$env{'user.domain'}.
1.17 albertel 579: '_'.time.'_'.$$.int(rand(1000)).'_organicstructure';
580: my $id=$filename;
581: &Apache::lonnet::appenv(
1.78 raeburn 582: {'cgi.'.$id.'.JME' => &escape($molecule),
583: 'cgi.'.$id.'.PS' => 1,
584: 'cgi.'.$id.'.WIDTH' => $texwidth});
1.66 www 585: $id=&escape($id);
1.17 albertel 586: &Apache::lonxml::register_ssi("/cgi-bin/convertjme.pl?$id");
1.20 albertel 587: if ($options =~ /border/) { $result.= '\fbox{'; }
1.89 foxr 588: $result .= '\graphicspath{{'.LONCAPA::tempdir().
589: '}}\includegraphics[width='.$texwidth.' mm]{'.$filename.'.eps}';
1.20 albertel 590: if ($options =~ /border/) { $result.= '} '; }
1.3 albertel 591: } elsif ($target eq 'edit') {
592: $result .=&Apache::edit::tag_start($target,$token);
1.22 albertel 593: $result .=&Apache::edit::text_arg('Width (pixels):','width',$token,5);
594: $result .=&Apache::edit::text_arg('TeXwidth (mm):','texwidth',$token,5);
1.83 bisitz 595: $result .='<span class="LC_nobreak">';
1.3 albertel 596: $result .=&Apache::edit::text_arg('Molecule:','molecule',$token,40);
597: my $molecule=&Apache::lonxml::get_param('molecule',$parstack,
598: $safeeval);
1.12 albertel 599: my $options=&Apache::lonxml::get_param('options',$parstack,
600: $safeeval);
601: if ($options !~ /reaction/) {
602: $options.= ',multipart,number';
603: }
604:
1.30 www 605: $result .=&separate_jme_window(undef,
1.12 albertel 606: &Apache::edit::html_element_name('molecule'),
607: $molecule,$options);
1.83 bisitz 608: $result.="</span><br />";
1.12 albertel 609: $result .=&Apache::edit::checked_arg('Options:','options',
1.18 albertel 610: [ ['reaction','Is a reaction'],
1.12 albertel 611: ['border','Draw a border'] ],
612: $token);
1.24 albertel 613: $result .=&Apache::edit::end_row();
1.3 albertel 614: } elsif ($target eq 'modified') {
615: my $constructtag=&Apache::edit::get_new_args($token,$parstack,
616: $safeeval,'molecule',
1.22 albertel 617: 'width','texwidth',
618: 'options');
1.3 albertel 619: if ($constructtag) { $result = &Apache::edit::rebuild_tag($token); }
620: }
621: return $result;
1.1 albertel 622: }
623:
1.6 albertel 624: sub end_organicstructure {
1.3 albertel 625: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
626: my $result;
627: if ($target eq "edit") {
628: $result.= &Apache::edit::tag_end($target,$token,'');
629: }
1.4 albertel 630: return $result;
631: }
632:
1.99 ! damieng 633: sub reaction_preview {
! 634: my ($field, $reaction) = @_;
! 635:
! 636: # NOTE: $reaction should be encoded if the document was sent as XHTML
! 637: $reaction =~ s/"//g;
! 638: my $result=<<JS_PREVIEW;
! 639: <input type="button" value="Help" onclick = "window.open('/adm/reactionresponse/reaction_help.html','','scrollbars=yes,resizable=yes,width=550,height=600')" />
1.10 albertel 640: <script type="text/javascript">
1.99 ! damieng 641: if (typeof reaction_preview_started === 'undefined') {
! 642: var script = document.createElement('script');
! 643: script.type = 'text/javascript';
! 644: script.src = '/adm/reactionresponse/reaction_preview.js';
! 645: document.body.appendChild(script);
! 646: reaction_preview_started = true;
! 647: }
! 648: window.addEventListener('load', function(e) {
! 649: var input = document.forms.lonhomework.$field;
! 650: input.readonly = '';
! 651: input.value = "$reaction";
! 652: if (!input.id)
! 653: input.id = "$field";
! 654: var preview = new LC.HW.ReactionPreview(input.id);
! 655: preview.start_preview();
! 656: }, false);
1.10 albertel 657: </script>
1.99 ! damieng 658: JS_PREVIEW
1.9 albertel 659: return $result;
660: }
661:
1.4 albertel 662: sub start_reactionresponse {
663: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
664: my $result;
665: my $id = &Apache::response::start_response($parstack,$safeeval);
1.10 albertel 666: if ($target eq 'meta') {
1.28 albertel 667: $result=&Apache::response::meta_package_write('reactionresponse');
1.10 albertel 668: } elsif ($target eq 'web') {
1.11 albertel 669: my $partid = $Apache::inputtags::part;
670: my $id = $Apache::inputtags::response['-1'];
1.33 albertel 671: if ( &Apache::response::show_answer() ) {
672: my $ans=&Apache::lonxml::get_param('answer',$parstack,$safeeval);
1.51 albertel 673: if (!$Apache::lonxml::default_homework_loaded) {
674: &Apache::lonxml::default_homework_load($safeeval);
675: }
676: @Apache::scripttag::parser_env = @_;
1.71 albertel 677: $Apache::inputtags::answertxt{$id}=[&Apache::run::run("return &chemparse(q\0$ans\0);",$safeeval)];
1.33 albertel 678: }
1.4 albertel 679: } elsif ($target eq "edit") {
1.9 albertel 680: $result .=&Apache::edit::tag_start($target,$token);
681: my $answer=&Apache::lonxml::get_param('answer',$parstack,
682: $safeeval);
1.82 raeburn 683: $result .='<span class="LC_nobreak">'.
1.10 albertel 684: &Apache::edit::text_arg('Answer:','answer',$token,40);
1.99 ! damieng 685: $result .= &reaction_preview(&Apache::edit::html_element_name('answer'), $answer).'</span>';
1.35 albertel 686: my $initial=&Apache::lonxml::get_param('initial',$parstack,$safeeval);
1.82 raeburn 687: $result.='<span class="LC_nobreak">'.
1.43 albertel 688: &Apache::edit::text_arg('Initial Reaction:','initial',$token,40);
1.99 ! damieng 689: $result .= &reaction_preview(&Apache::edit::html_element_name('initial'), $initial).'</span>';
1.9 albertel 690: $result .=&Apache::edit::end_row().&Apache::edit::start_spanning_row();
1.10 albertel 691: } elsif ($target eq 'modified') {
692: my $constructtag=&Apache::edit::get_new_args($token,$parstack,
1.35 albertel 693: $safeeval,'answer',
694: 'initial');
1.10 albertel 695: if ($constructtag) { $result = &Apache::edit::rebuild_tag($token); }
1.4 albertel 696: }
697: return $result;
698: }
699:
700: sub end_reactionresponse {
701: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
702: my $result;
1.64 albertel 703:
704: my $partid = $Apache::inputtags::part;
705: my $id = $Apache::inputtags::response['-1'];
706:
707: if ($target eq 'grade'
708: && &Apache::response::submitted()
709: && $Apache::lonhomework::type eq 'exam') {
710:
711: &Apache::response::scored_response($partid,$id);
712:
713: } elsif ($target eq 'grade'
714: && &Apache::response::submitted()
715: && $Apache::lonhomework::type ne 'exam') {
716:
1.31 albertel 717: &Apache::response::setup_params($$tagstack[-1],$safeeval);
1.10 albertel 718: my $response = &Apache::response::getresponse();
719: if ( $response =~ /[^\s]/) {
1.15 albertel 720: my (@answers)=&Apache::lonxml::get_param_var('answer',$parstack,$safeeval);
1.10 albertel 721: my %previous = &Apache::response::check_for_previous($response,$partid,$id);
722: $Apache::lonhomework::results{"resource.$partid.$id.submission"}=$response;
723: my $ad;
1.13 albertel 724: foreach my $answer (@answers) {
725: &Apache::lonxml::debug("submitted a $response for $answer<br \>\n");
1.34 albertel 726: if (&chem_standard_order($response) eq
727: &chem_standard_order($answer)) {
1.13 albertel 728: $ad='EXACT_ANS';
729: } else {
730: $ad='INCORRECT';
731: }
1.10 albertel 732: }
1.87 raeburn 733: if ($ad) {
734: if ($Apache::lonhomework::type eq 'survey') {
735: $ad='SUBMITTED';
736: } elsif ($ad && $Apache::lonhomework::type eq 'surveycred') {
737: $ad='SUBMITTED_CREDIT';
738: } elsif ($ad && $Apache::lonhomework::type eq 'anonsurvey') {
739: $ad='ANONYMOUS';
740: } elsif ($ad && $Apache::lonhomework::type eq 'anonsurveycred') {
741: $ad='ANONYMOUS_CREDIT';
742: }
743: }
1.10 albertel 744: &Apache::response::handle_previous(\%previous,$ad);
745: $Apache::lonhomework::results{"resource.$partid.$id.awarddetail"}=$ad;
746: }
747: } elsif ($target eq "edit") {
1.4 albertel 748: $result.= &Apache::edit::tag_end($target,$token,'');
1.15 albertel 749: } elsif ($target eq 'answer') {
750: my (@answers)=&Apache::lonxml::get_param_var('answer',$parstack,
751: $safeeval);
752: $result.=&Apache::response::answer_header('reactionresponse');
753: foreach my $answer (@answers) {
754: $result.=&Apache::response::answer_part('reactionresponse',
755: $answer);
756: }
757: $result.=&Apache::response::answer_footer('reactionresponse');
1.4 albertel 758: }
1.72 albertel 759: if ($target eq 'web') {
760: &Apache::response::setup_prior_tries_hash(\&format_prior_response_reaction);
761: }
1.63 albertel 762:
763: if ($target eq 'grade' || $target eq 'web' || $target eq 'answer' ||
764: $target eq 'tex' || $target eq 'analyze') {
1.90 raeburn 765: my $repetition = &Apache::response::repetition();
766: &Apache::lonxml::increment_counter($repetition,"$partid.$id");
1.77 raeburn 767: if ($target eq 'analyze') {
768: $Apache::lonhomework::analyze{"$partid.$id.type"} = 'reactionresponse';
1.84 raeburn 769: push (@{ $Apache::lonhomework::analyze{"parts"} },"$partid.$id");
1.77 raeburn 770: &Apache::lonhomework::set_bubble_lines();
771: }
1.63 albertel 772: }
1.81 raeburn 773: my $status=$Apache::inputtags::status['-1'];
774: if (($target eq 'web') && ($Apache::lonhomework::type ne 'exam') && ($status eq 'CAN_ANSWER')) {
775: my $reaction=$Apache::lonhomework::history{"resource.$partid.$id.submission"};
776: if ($reaction eq '') { $reaction=&Apache::lonxml::get_param('initial',$parstack,$safeeval); }
1.99 ! damieng 777: $result .= &reaction_preview("HWVAL_$id", $reaction);
1.81 raeburn 778: }
1.63 albertel 779: &Apache::response::end_response();
1.3 albertel 780: return $result;
1.1 albertel 781: }
782:
1.72 albertel 783: sub format_prior_response_reaction {
784: my ($mode,$answer) =@_;
785: return '<span class="LC_prior_reaction">'.
786: &HTML::Entities::encode($answer,'"<>&').'</span>';
787: }
788:
1.46 albertel 789: sub start_chem {
790: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style) = @_;
791: my $result = '';
1.48 albertel 792: my $inside = &Apache::lonxml::get_all_text_unbalanced("/chem",$parser);
1.46 albertel 793: if ($target eq 'tex' || $target eq 'web') {
1.48 albertel 794: $inside=&Apache::run::evaluate($inside,$safeeval,$$parstack[-1]);
795: if (!$Apache::lonxml::default_homework_loaded) {
796: &Apache::lonxml::default_homework_load($safeeval);
797: }
798: @Apache::scripttag::parser_env = @_;
799: $result=&Apache::run::run("return &chemparse(q\0$inside\0);",$safeeval);
1.46 albertel 800: }
801: return $result;
802: }
803:
804: sub end_chem {
805: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style) = @_;
806: my $result = '';
807: return $result;
808: }
809:
1.91 raeburn 810: my $uniq=0;
811: sub get_uniq_name {
812: $uniq++;
813: return 'uniquename'.$uniq;
814: }
815:
1.1 albertel 816: 1;
817: __END__
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>