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