Annotation of loncom/homework/chemresponse.pm, revision 1.7
1.1 albertel 1: # The LearningOnline Network with CAPA
2: # chemical equation style response
3: #
1.7 ! albertel 4: # $Id: chemresponse.pm,v 1.6 2003/06/30 18:00:18 albertel 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;
33:
34: BEGIN {
1.6 albertel 35: &Apache::lonxml::register('Apache::chemresponse',('organicresponse','organicstructure','reactionresponse'));
1.1 albertel 36: }
37:
38: sub seperate_jme_window {
1.6 albertel 39: my ($smile_input,$jme_input,$molecule,$options)=@_;
1.2 albertel 40: my $smilesection;
41: if (defined($smile_input)) {
42: $smilesection=<<SMILESECTION;
43: opener.document.lonhomework.$smile_input.value = smiles;
44: SMILESECTION
45: }
46: my $jmesection;
47: if (defined($jme_input)) {
48: $jmesection=<<JMESECTION;
49: jmeFile = document.applets.JME.jmeFile();
50: opener.document.lonhomework.$jme_input.value = jmeFile;
51: JMESECTION
52: }
53:
1.1 albertel 54: my $body=<<CHEMPAGE;
55: <html>
56: <head>
57: <title>Molecule Editor</title>
58: <script language="JavaScript">
59: function submitSmiles() {
60: smiles = document.applets.JME.smiles();
61: if (smiles == "") {
62: alert("Nothing to submit");
63: } else {
1.2 albertel 64: $smilesection
65: $jmesection
1.1 albertel 66: window.close();
67: }
68: }
69: function openHelpWindow() {
1.2 albertel 70: window.open("/adm/jme/jme_help.html","","scrollbars=yes,resizable=yes,width=500,height=600");
1.1 albertel 71: }
72: </script>
73: </head>
74: <body bgcolor="#ffffff">
75: <center>
76: <applet code="JME.class" name="JME" archive="/adm/jme/JME.jar" width="97%" height="78%">
77: You have to enable Java and JavaScript on your machine.
78: <param name="jme" value="$molecule" />
1.6 albertel 79: <param name="options" value="$options" />
1.1 albertel 80: </applet><br />
81: <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>
82: <form>
83: <input type="button" name="submit" value="Insert Answer" onClick = "submitSmiles();" />
84: <br />
85: <input type="button" value=" Close " onClick = "window.close()" />
86:
87: <input type="button" value=" Help " onClick = "openHelpWindow()" />
88: </form>
89: </center>
90: </body>
91: </html>
92: CHEMPAGE
93: $body=&HTML::Entities::encode($body);
94: $body=~s/\n/ /g;
95: my $result=<<CHEMINPUT;
96: <input type="button" value="Draw Molecule" onClick="javascript:editor=window.open('','','width=500,height=500,scrollbars=no,resizable=yes');editor.document.open('text/html','replace');editor.document.writeln('$body')" />
97: CHEMINPUT
98: return $result;
99: }
100:
1.6 albertel 101: sub start_organicresponse {
1.1 albertel 102: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
103: my $result;
104: my $partid = $Apache::inputtags::part;
105: my $id = &Apache::response::start_response($parstack,$safeeval);
106: if ($target eq 'meta') {
107: } elsif ($target eq 'web') {
108: my $molecule;
109: if (defined($Apache::lonhomework::history{"resource.$partid.$id.molecule"})) {
110: $molecule=$Apache::lonhomework::history{"resource.$partid.$id.molecule"};
111: } else {
112: $molecule=&Apache::lonxml::get_param('molecule',$parstack,
113: $safeeval);
114: }
1.6 albertel 115: my $multipart=&Apache::lonxml::get_param('multipart',$parstack,
116: $safeeval);
117: if ($multipart eq 'yes') {
118: $multipart = 'multipart';
119: } else {
120: $multipart ='';
121: }
122: $result=&seperate_jme_window("HWVAL_$id","MOLECULE_$id",$molecule,$multipart);
1.1 albertel 123: $result.= '<input type="hidden" name="MOLECULE_'.$id.'" value="" />';
1.2 albertel 124: } elsif ($target eq 'edit') {
125: $result .=&Apache::edit::tag_start($target,$token);
1.7 ! albertel 126: $result .='<nobr>'.
! 127: &Apache::edit::text_arg('Starting Molecule:','molecule',
! 128: $token,40);
1.2 albertel 129: my $molecule=&Apache::lonxml::get_param('molecule',$parstack,
130: $safeeval);
131: $result .=&seperate_jme_window(undef,
132: &Apache::edit::html_element_name('molecule'),
1.6 albertel 133: $molecule,'multipart');
1.7 ! albertel 134: $result .='</nobr><br /><nobr>';
1.2 albertel 135: $result .=&Apache::edit::text_arg('Correct Answer:','answer',
136: $token,40);
137: $result .=&Apache::edit::hidden_arg('jmeanswer',$token);
138: my $jmeanswer=&Apache::lonxml::get_param('jmeanswer',$parstack,
139: $safeeval);
140: $result .=&seperate_jme_window(
141: &Apache::edit::html_element_name('answer'),
142: &Apache::edit::html_element_name('jmeanswer'),
1.6 albertel 143: $jmeanswer,'multipart');
1.7 ! albertel 144: $result .='</nobr>'.
! 145: &Apache::edit::select_arg('Multipart:','multipart',
! 146: ['no','yes'],$token);
1.2 albertel 147: $result .=&Apache::edit::end_row().&Apache::edit::start_spanning_row();
148: } elsif ($target eq 'modified') {
149: my $constructtag=&Apache::edit::get_new_args($token,$parstack,
150: $safeeval,'molecule',
1.6 albertel 151: 'answer','jmeanswer',
152: 'multipart');
1.2 albertel 153: if ($constructtag) { $result = &Apache::edit::rebuild_tag($token); }
1.1 albertel 154: }
155: return $result;
156: }
157:
1.6 albertel 158: sub end_organicresponse {
1.1 albertel 159: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
160: my $result;
161: if ($target eq 'grade' && defined($ENV{'form.submitted'})) {
162: &Apache::response::setup_params($$tagstack[-1]);
163: my $response = &Apache::response::getresponse();
164: if ( $response =~ /[^\s]/) {
165: my $partid = $Apache::inputtags::part;
166: my $id = $Apache::inputtags::response['-1'];
167: my $answer=&Apache::lonxml::get_param('answer',$parstack,$safeeval);
168: my %previous = &Apache::response::check_for_previous($response,$partid,$id);
169: $Apache::lonhomework::results{"resource.$partid.$id.submission"}=$response;
170: &Apache::lonxml::debug("submitted a $response for $answer<br \>\n");
171: my $ad;
172: if ($response eq $answer) {
173: $ad='EXACT_ANS';
174: } else {
175: $ad='INCORRECT';
176: }
177: &Apache::response::handle_previous(\%previous,$ad);
178: $Apache::lonhomework::results{"resource.$partid.$id.awarddetail"}=$ad;
179: $Apache::lonhomework::results{"resource.$partid.$id.molecule"}=$ENV{"form.MOLECULE_$id"};
180: }
1.2 albertel 181: } elsif ($target eq "edit") {
182: $result.= &Apache::edit::tag_end($target,$token,'');
1.1 albertel 183: }
184: &Apache::response::end_response;
185: return $result;
186: }
187:
1.6 albertel 188: sub start_organicstructure {
1.3 albertel 189: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
190: my $result;
191: if ($target eq 'web') {
192: my $width=&Apache::lonxml::get_param('width',$parstack,$safeeval);
193: my $height=&Apache::lonxml::get_param('height',$parstack,$safeeval);
194: my $molecule=&Apache::lonxml::get_param('molecule',$parstack,$safeeval);
195: $result=<<CHEMOUTPUT;
196: <applet code="JME.class" archive="/adm/jme/JME.jar" width="$width" height="$height">
197: <param name="options" value="depict border" />
198: <param name="jme" value="$molecule" />
199: </applet>
200: CHEMOUTPUT
201: } elsif ($target eq 'edit') {
202: $result .=&Apache::edit::tag_start($target,$token);
203: $result .=&Apache::edit::text_arg('Width:','width',$token,5);
204: $result .=&Apache::edit::text_arg('Height:','height',$token,5);
205: $result .=&Apache::edit::text_arg('Molecule:','molecule',$token,40);
206: my $molecule=&Apache::lonxml::get_param('molecule',$parstack,
207: $safeeval);
208: $result .=&seperate_jme_window(undef,
209: &Apache::edit::html_element_name('molecule'),
1.6 albertel 210: $molecule,'multipart');
1.3 albertel 211: $result .=&Apache::edit::end_row().&Apache::edit::start_spanning_row();
212: } elsif ($target eq 'modified') {
213: my $constructtag=&Apache::edit::get_new_args($token,$parstack,
214: $safeeval,'molecule',
215: 'width','height');
216: if ($constructtag) { $result = &Apache::edit::rebuild_tag($token); }
217: }
218: return $result;
1.1 albertel 219: }
220:
1.6 albertel 221: sub end_organicstructure {
1.3 albertel 222: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
223: my $result;
224: if ($target eq "edit") {
225: $result.= &Apache::edit::tag_end($target,$token,'');
226: }
1.4 albertel 227: return $result;
228: }
229:
230: sub reaction_javascript {
1.5 albertel 231: my $rightarrow;
232: if ($ENV{'browser.unicode'}) {
233: $rightarrow=" → "
234: } else {
235: $rightarrow=" <font face=symbol>®</font> ";
236: }
1.4 albertel 237: my $result=<<REACTIONJAVASCRIPT;
1.5 albertel 238: <script language="JavaScript">
1.4 albertel 239:
240: var level;
241: var reactants;
242: var products;
243:
244:
245: function parse_reaction(string) {
246: var reaction_array = string.split('->');
247: var i;
248: reactants = new Array(0);
249: products = new Array(0);
250:
251: if (reaction_array.length > 0)
252: reactants = reaction_array[0].split(' +');
253: if (reaction_array.length > 1)
254: products = reaction_array[1].split(' +');
255: }
256:
257: function to_capa(string) {
258: var reaction = "";
259: var i;
260:
261: parse_reaction(string);
262:
263: for (i = 0; i < reactants.length; i++)
264: reactants[i] = capa_component(reactants[i]);
265: for (i = 0; i < products.length; i++)
266: products[i] = capa_component(products[i]);
267:
268: reactants.sort();
269: products.sort();
270:
271: for (i = 0; i < reactants.length-1; i++) {
272: reaction += reactants[i];
273: reaction += " + ";
274: }
275: if (i < reactants.length)
276: reaction += reactants[i];
277: if (products.length > 0) {
278: reaction += " -> ";
279: for (i = 0; i < products.length-1; i++) {
280: reaction += products[i];
281: reaction += " + ";
282: }
283: if (i < products.length)
284: reaction += products[i];
285: }
286:
287: return reaction;
288: }
289:
290: function capa_component(string) {
291: var reactant = "";
292: var i = 0;
293: level = 0;
294:
295: for (;string.substring(i,i+1) == ' ';i++)
296: ;
297: for (;isDigit(string.substring(i,i+1));i++)
298: reactant += string.substring(i,i+1);
299: for (;i < string.length;i++)
300: reactant += capa_char(string.substring(i,i+1));
301:
302: return reactant;
303: }
304:
305: function capa_char(chr) {
306: if (level == 0) { // baseline
307: if (chr == '^')
308: level = 1;
309: if (chr == ' ')
310: return "";
311: return chr;
312: }
313: if (level == 1) { // superscript
314: if (isDigit(chr))
315: return chr;
316: level = 0;
317: return chr;
318: }
319: }
320:
321: function to_html(string) {
322: var reaction = "";
323: var i;
324:
325: parse_reaction(string);
326: for (i = 0; i < reactants.length-1; i++) {
327: reaction += html_component(reactants[i]);
328: reaction += " + ";
329: }
330: if (i < reactants.length)
331: reaction += html_component(reactants[i]);
332:
333: if (products.length > 0) {
1.5 albertel 334: reaction += " $rightarrow ";
1.4 albertel 335: for (i = 0; i < products.length-1; i++) {
336: reaction += html_component(products[i]);
337: reaction += " + ";
338: }
339: if (i < products.length)
340: reaction += html_component(products[i]);
341: }
342:
343: return reaction;
344: }
345:
346: function html_component(string) {
347: var reactant = "";
348: var i = 0;
349: level = 0;
350:
351: for (;string.substring(i,i+1) == ' ';i++)
352: ;
353: for (;isDigit(string.substring(i,i+1));i++)
354: reactant += string.substring(i,i+1);
355: for (;i < string.length;i++)
356: reactant += html_char(string.substring(i,i+1));
357:
358: return reactant;
359: }
360:
361: function html_char(chr) {
362: if (level == 0) { // baseline
363: if (isDigit(chr))
364: return chr.sub();
365: if (chr == '^') {
366: level = 1;
367: return "";
368: }
369: if (chr == '+') // baseline or superscript
370: return "?";
371: if (chr == ' ')
372: return "";
373: return chr;
374: }
375: if (level == 1) { // superscript
376: if (isDigit(chr))
377: return chr.sup();
378: if (chr == '+' || chr == '-') {
379: level = 0;
380: return chr.sup();
381: }
382: if (chr == ' ') {
383: level = 0;
384: return "";
385: }
386: level = 0;
387: return chr;
388: }
389: }
390:
391: function isDigit(string) {
392: if (string >= '0' && string <='9')
393: return 1;
394: else
395: return 0;
396: }
397:
398: function openHelpWindow() {
399: window.open("reaction_help.html","","scrollbars=yes,resizable=yes,width=550,height=600")
400: }
401:
402: function submitReaction() {
403: reaction = to_capa(document.form.text.value);
404: if (reaction == "") {
405: alert("Nothing to submit");
406: }
407: else {
408: name = "INPUT" + ((problem < 10) ? "0" : "") + problem;
409: i = 0;
410: while (parent.opener.document.CAPA.elements[i].name != name)
411: i++;
412: parent.opener.document.CAPA.elements[i].value = reaction;
413: parent.opener.document.CAPA.submit();
414: }
415: }
1.5 albertel 416: </script>
1.4 albertel 417: REACTIONJAVASCRIPT
418: return $result;
419: }
420:
421: sub start_reactionresponse {
422: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
423: my $result;
424: my $id = &Apache::response::start_response($parstack,$safeeval);
425: if ($target eq 'web') {
1.6 albertel 426: $result.=<<EDITREACTION;
1.7 ! albertel 427: <input type='button' value='Edit Reaction' onClick="javascript:editor=window.open('/res/adm/reactionresponse/reaction_window.html','','width=500,height=270,scrollbars=no,resizable=yes'); document.cookie='problem=$id';" />
1.6 albertel 428: EDITREACTION
429:
430: # $result.=&reaction_javascript();
1.4 albertel 431: # $result.='<iframe name="REACTION_'.$id.'" width="200" height="100" src="/adm/jme/reaction_viewer.html"></iframe>';
1.6 albertel 432: # $result.='<input type="button" value="Check" onClick = "javascript:newWindow=open(\'\',\'new_W\',\'width=500,height=200,scrollbars=1\');newWindow.document.open(\'text/html\',\'replace\');newWindow.document.writeln(\'<center><br />\'+to_html(document.lonhomework.HWVAL_'.$id.'.value)+\'</center><input type="button" value=" Close " onClick = "parent.window.close()" />\');newWindow.document.close()" />'
1.4 albertel 433: } elsif ($target eq "edit") {
434: }
435: return $result;
436: }
437:
438: sub end_reactionresponse {
439: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
440: my $result;
441: if ($target eq "edit") {
442: $result.= &Apache::edit::tag_end($target,$token,'');
443: }
444: &Apache::response::end_response;
1.3 albertel 445: return $result;
1.1 albertel 446: }
447:
448: 1;
449: __END__
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>