Parent Directory
|
Revision Log
Revision 6468 - (view) (download) (as text)
| 1 : | gage | 6228 | ################################################################################ |
| 2 : | # WeBWorK Online Homework Delivery System | ||
| 3 : | # Copyright © 2000-2007 The WeBWorK Project, http://openwebwork.sf.net/ | ||
| 4 : | gage | 6236 | # $CVSHeader: webwork2/lib/WeBWorK/ContentGenerator/renderViaXMLRPC.pm,v 1.1 2010/05/11 15:27:08 gage Exp $ |
| 5 : | gage | 6228 | # |
| 6 : | # This program is free software; you can redistribute it and/or modify it under | ||
| 7 : | # the terms of either: (a) the GNU General Public License as published by the | ||
| 8 : | # Free Software Foundation; either version 2, or (at your option) any later | ||
| 9 : | # version, or (b) the "Artistic License" which comes with this package. | ||
| 10 : | # | ||
| 11 : | # This program is distributed in the hope that it will be useful, but WITHOUT | ||
| 12 : | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||
| 13 : | # FOR A PARTICULAR PURPOSE. See either the GNU General Public License or the | ||
| 14 : | # Artistic License for more details. | ||
| 15 : | ################################################################################ | ||
| 16 : | |||
| 17 : | =head1 NAME | ||
| 18 : | |||
| 19 : | WeBWorK::ContentGenerator::ProblemRenderer - renderViaXMLRPC is an HTML | ||
| 20 : | front end for calls to the xmlrpc webservice | ||
| 21 : | |||
| 22 : | =cut | ||
| 23 : | |||
| 24 : | use strict; | ||
| 25 : | use warnings; | ||
| 26 : | |||
| 27 : | package WeBWorK::ContentGenerator::renderViaXMLRPC; | ||
| 28 : | use base qw(WeBWorK::ContentGenerator); | ||
| 29 : | |||
| 30 : | #use Crypt::SSLeay; | ||
| 31 : | mgage | 6291 | #use XMLRPC::Lite; |
| 32 : | #use MIME::Base64 qw( encode_base64 decode_base64); | ||
| 33 : | gage | 6228 | |
| 34 : | mgage | 6291 | |
| 35 : | use strict; | ||
| 36 : | use warnings; | ||
| 37 : | use WebworkClient; | ||
| 38 : | |||
| 39 : | gage | 6228 | ################################################## |
| 40 : | # configuration section -- point back to the current server to process answers | ||
| 41 : | ################################################## | ||
| 42 : | mgage | 6291 | # configure the local output file and display command !!!!!!!! |
| 43 : | gage | 6228 | |
| 44 : | mgage | 6291 | # the rest can be configured later to use a different server |
| 45 : | gage | 6228 | |
| 46 : | mgage | 6291 | my $use_local = 0; |
| 47 : | gage | 6468 | our ($XML_URL,$FORM_ACTION_URL, $XML_PASSWORD, $XML_COURSE); |
| 48 : | mgage | 6291 | if ($use_local) { |
| 49 : | # the rest can work!! | ||
| 50 : | gage | 6468 | |
| 51 : | mgage | 6291 | $XML_PASSWORD = 'xmlwebwork'; |
| 52 : | $XML_COURSE = 'daemon_course'; | ||
| 53 : | } else { | ||
| 54 : | gage | 6468 | |
| 55 : | mgage | 6291 | $XML_PASSWORD = 'xmlwebwork'; |
| 56 : | $XML_COURSE = 'daemon_course'; | ||
| 57 : | gage | 6228 | |
| 58 : | mgage | 6291 | } |
| 59 : | gage | 6228 | |
| 60 : | gage | 6468 | |
| 61 : | # To configure the target webwork server | ||
| 62 : | # two URLs are required | ||
| 63 : | # 1. $XML_URL http://test.webwork.maa.org/mod_xmlrpc | ||
| 64 : | # points to the Webservice.pm and Webservice/RenderProblem modules | ||
| 65 : | # Is used by the client to send the original XML request to the webservice | ||
| 66 : | # | ||
| 67 : | # 2. $FORM_ACTION_URL http:http://test.webwork.maa.org/webwork2/html2xml | ||
| 68 : | # points to the renderViaXMLRPC.pm module. | ||
| 69 : | # | ||
| 70 : | # This url is placed as form action url when the rendered HTML from the original | ||
| 71 : | # request is returned to the client from Webservice/RenderProblem. The client | ||
| 72 : | # reorganizes the XML it receives into an HTML page (with a WeBWorK form) and | ||
| 73 : | # pipes it through a local browser. | ||
| 74 : | # | ||
| 75 : | # The browser uses this url to resubmit the problem (with answers) via the standard | ||
| 76 : | # HTML webform used by WeBWorK to the renderViaXMLRPC.pm handler. | ||
| 77 : | # | ||
| 78 : | # This renderViaXMLRPC.pm handler acts as an intermediary between the browser | ||
| 79 : | # and the webservice. It interprets the HTML form sent by the browser, | ||
| 80 : | # rewrites the form data in XML format, submits it to the WebworkWebservice.pm | ||
| 81 : | # which processes it and sends the the resulting HTML back to renderViaXMLRPC.pm | ||
| 82 : | # which in turn passes it back to the browser. | ||
| 83 : | # 3. The second time a problem is submitted renderViaXMLRPC.pm receives the WeBWorK form | ||
| 84 : | # submitted directly by the browser. | ||
| 85 : | # The renderViaXMLRPC.pm translates the WeBWorK form, has it processes by the webservice | ||
| 86 : | # and returns the result to the browser. | ||
| 87 : | # The The client renderProblem.pl script is no longer involved. | ||
| 88 : | # 4. Summary: renderProblem.pl is only involved in the first round trip | ||
| 89 : | # of the submitted problem. After that the communication is between the browser and | ||
| 90 : | # renderViaXMLRPC using HTML forms and between renderViaXMLRPC and the WebworkWebservice.pm | ||
| 91 : | # module using XML_RPC. | ||
| 92 : | gage | 6228 | |
| 93 : | |||
| 94 : | gage | 6468 | $XML_URL = 'http://localhost:80'; |
| 95 : | $FORM_ACTION_URL = 'http://localhost:80/webwork2/html2xml'; | ||
| 96 : | warn "form url is $XML_URL "; | ||
| 97 : | gage | 6228 | |
| 98 : | mgage | 6291 | use constant DISPLAYMODE => 'images'; # jsMath is another possibilities. |
| 99 : | gage | 6228 | |
| 100 : | mgage | 6291 | |
| 101 : | gage | 6228 | our @COMMANDS = qw( listLibraries renderProblem ); #listLib readFile tex2pdf |
| 102 : | |||
| 103 : | |||
| 104 : | ################################################## | ||
| 105 : | # end configuration section | ||
| 106 : | ################################################## | ||
| 107 : | |||
| 108 : | |||
| 109 : | sub pre_header_initialize { | ||
| 110 : | my ($self) = @_; | ||
| 111 : | my $r = $self->r; | ||
| 112 : | my $db = new WeBWorK::DB($r->ce->{dbLayout}); | ||
| 113 : | gage | 6468 | |
| 114 : | ####################### | ||
| 115 : | # setup xmlrpc client | ||
| 116 : | ####################### | ||
| 117 : | mgage | 6291 | my $xmlrpc_client = new WebworkClient; |
| 118 : | |||
| 119 : | $xmlrpc_client->{encodedSource} = $r->param('problemSource') ; # this source has already been encoded | ||
| 120 : | gage | 6468 | $xmlrpc_client->url($XML_URL); |
| 121 : | $xmlrpc_client->{form_action_url}= $FORM_ACTION_URL; | ||
| 122 : | mgage | 6291 | $xmlrpc_client->{displayMode} = DISPLAYMODE(); |
| 123 : | $xmlrpc_client->{user} = 'xmluser'; | ||
| 124 : | $xmlrpc_client->{password} = $XML_PASSWORD; | ||
| 125 : | $xmlrpc_client->{course} = $XML_COURSE; | ||
| 126 : | gage | 6228 | my %inputs_ref; |
| 127 : | foreach my $key ( keys %{ $r->{paramcache} } ) { | ||
| 128 : | $inputs_ref{$key} = $r->param("$key"); | ||
| 129 : | } | ||
| 130 : | mgage | 6291 | $xmlrpc_client->{inputs_ref} = \%inputs_ref; |
| 131 : | # print STDERR WebworkClient::pretty_print($r->{paramcache}); | ||
| 132 : | gage | 6468 | |
| 133 : | ############################## | ||
| 134 : | # xmlrpc_client calls webservice to have problem rendered | ||
| 135 : | # | ||
| 136 : | # and stores the resulting HTML output in $self->{output} | ||
| 137 : | # from which it will eventually be returned to the browser | ||
| 138 : | # | ||
| 139 : | ############################## | ||
| 140 : | mgage | 6291 | if ( $xmlrpc_client->xmlrpcCall('renderProblem') ) { |
| 141 : | $self->{output} = $xmlrpc_client->formatRenderedProblem; | ||
| 142 : | } else { | ||
| 143 : | $self->{output} = $xmlrpc_client->{output}; # error report | ||
| 144 : | } | ||
| 145 : | gage | 6468 | |
| 146 : | ################################ | ||
| 147 : | gage | 6228 | } |
| 148 : | |||
| 149 : | sub content { | ||
| 150 : | gage | 6468 | ########################### |
| 151 : | # Return content of rendered problem to the browser that requested it | ||
| 152 : | ########################### | ||
| 153 : | mgage | 6291 | my $self = shift; |
| 154 : | gage | 6228 | print $self->{output}; |
| 155 : | } | ||
| 156 : | |||
| 157 : | ################################################## | ||
| 158 : | # end input/output section | ||
| 159 : | ################################################## | ||
| 160 : | |||
| 161 : | gage | 6468 | ################################################## |
| 162 : | # XMLRPC client -- | ||
| 163 : | # the code below is identical between renderProblem.pl and renderViaXMLRPC.pm???? | ||
| 164 : | # and has been included in WebworkClient.pm | ||
| 165 : | ################################################## | ||
| 166 : | gage | 6228 | |
| 167 : | gage | 6468 | # package WeBWorK::ContentGenerator::renderViaXMLRPC_client; |
| 168 : | # | ||
| 169 : | # use Crypt::SSLeay; # needed for https | ||
| 170 : | # use XMLRPC::Lite; | ||
| 171 : | # use MIME::Base64 qw( encode_base64 decode_base64); | ||
| 172 : | # | ||
| 173 : | # use constant TRANSPORT_METHOD => 'XMLRPC::Lite'; | ||
| 174 : | # use constant REQUEST_CLASS => 'WebworkXMLRPC'; # WebworkXMLRPC is used for soap also!! | ||
| 175 : | # use constant REQUEST_URI => 'mod_xmlrpc'; | ||
| 176 : | # | ||
| 177 : | # sub new { | ||
| 178 : | # my $self = { | ||
| 179 : | # output => '', | ||
| 180 : | # encodedSource => '', | ||
| 181 : | # url => '', | ||
| 182 : | # password => '', | ||
| 183 : | # course => '', | ||
| 184 : | # displayMode => '', | ||
| 185 : | # inputs_ref => { AnSwEr0001 => '', | ||
| 186 : | # AnSwEr0002 => '', | ||
| 187 : | # AnSwEr0003 => '', | ||
| 188 : | # }, | ||
| 189 : | # }; | ||
| 190 : | # | ||
| 191 : | # bless $self; | ||
| 192 : | # } | ||
| 193 : | # | ||
| 194 : | # | ||
| 195 : | mgage | 6291 | # our $result; |
| 196 : | # | ||
| 197 : | # ################################################## | ||
| 198 : | # # Utilities -- | ||
| 199 : | # # this code is identical between renderProblem.pl and renderViaXMLRPC.pm | ||
| 200 : | # ################################################## | ||
| 201 : | # | ||
| 202 : | # sub xmlrpcCall { | ||
| 203 : | # my $self = shift; | ||
| 204 : | # my $command = shift; | ||
| 205 : | # $command = 'listLibraries' unless $command; | ||
| 206 : | # | ||
| 207 : | # my $requestResult = TRANSPORT_METHOD | ||
| 208 : | # #->uri('http://'.HOSTNAME.':'.HOSTPORT.'/'.REQUEST_CLASS) | ||
| 209 : | # -> proxy($FULL_URL.'/'.REQUEST_URI); | ||
| 210 : | # | ||
| 211 : | # my $input = $self->setInputTable(); | ||
| 212 : | # local( $result); | ||
| 213 : | # # use eval to catch errors | ||
| 214 : | # eval { $result = $requestResult->call(REQUEST_CLASS.'.'.$command,$input) }; | ||
| 215 : | # print STDERR "There were a lot of errors\n" if $@; | ||
| 216 : | # print STDERR "Errors: \n $@\n End Errors\n" if $@; | ||
| 217 : | # | ||
| 218 : | # | ||
| 219 : | # | ||
| 220 : | # | ||
| 221 : | # unless (ref($result) and $result->fault) { | ||
| 222 : | # my $rh_result = $result->result(); | ||
| 223 : | # #print STDERR pretty_print($rh_result); | ||
| 224 : | # $self->{output} = $self->formatRenderedProblem($rh_result); | ||
| 225 : | # | ||
| 226 : | # } else { | ||
| 227 : | # $self->{output} = 'Error from server: ', join( ",\n ", | ||
| 228 : | # $result->faultcode, | ||
| 229 : | # $result->faultstring); | ||
| 230 : | # } | ||
| 231 : | # } | ||
| 232 : | # | ||
| 233 : | # sub encodeSource { | ||
| 234 : | # my $source = shift; | ||
| 235 : | # encode_base64($source); | ||
| 236 : | # } | ||
| 237 : | # | ||
| 238 : | # | ||
| 239 : | # sub pretty_print_rh { | ||
| 240 : | # shift if UNIVERSAL::isa($_[0] => __PACKAGE__); | ||
| 241 : | # my $rh = shift; | ||
| 242 : | # my $indent = shift || 0; | ||
| 243 : | # my $out = ""; | ||
| 244 : | # my $type = ref($rh); | ||
| 245 : | # | ||
| 246 : | # if (defined($type) and $type) { | ||
| 247 : | # $out .= " type = $type; "; | ||
| 248 : | # } elsif (! defined($rh )) { | ||
| 249 : | # $out .= " type = UNDEFINED; "; | ||
| 250 : | # } | ||
| 251 : | # return $out." " unless defined($rh); | ||
| 252 : | # | ||
| 253 : | # if ( ref($rh) =~/HASH/ or "$rh" =~/HASH/ ) { | ||
| 254 : | # $out .= "{\n"; | ||
| 255 : | # $indent++; | ||
| 256 : | # foreach my $key (sort keys %{$rh}) { | ||
| 257 : | # $out .= " "x$indent."$key => " . pretty_print_rh( $rh->{$key}, $indent ) . "\n"; | ||
| 258 : | # } | ||
| 259 : | # $indent--; | ||
| 260 : | # $out .= "\n"." "x$indent."}\n"; | ||
| 261 : | # | ||
| 262 : | # } elsif (ref($rh) =~ /ARRAY/ or "$rh" =~/ARRAY/) { | ||
| 263 : | # $out .= " ( "; | ||
| 264 : | # foreach my $elem ( @{$rh} ) { | ||
| 265 : | # $out .= pretty_print_rh($elem, $indent); | ||
| 266 : | # | ||
| 267 : | # } | ||
| 268 : | # $out .= " ) \n"; | ||
| 269 : | # } elsif ( ref($rh) =~ /SCALAR/ ) { | ||
| 270 : | # $out .= "scalar reference ". ${$rh}; | ||
| 271 : | # } elsif ( ref($rh) =~/Base64/ ) { | ||
| 272 : | # $out .= "base64 reference " .$$rh; | ||
| 273 : | # } else { | ||
| 274 : | # $out .= $rh; | ||
| 275 : | # } | ||
| 276 : | # | ||
| 277 : | # return $out." "; | ||
| 278 : | # } | ||
| 279 : | # | ||
| 280 : | # sub setInputTable_for_listLib { | ||
| 281 : | # my $self = shift; | ||
| 282 : | # my $out = { | ||
| 283 : | # pw => XML_PASSWORD, | ||
| 284 : | # set => 'set0', | ||
| 285 : | # library_name => 'Library', | ||
| 286 : | # command => 'all', | ||
| 287 : | # }; | ||
| 288 : | # | ||
| 289 : | # $out; | ||
| 290 : | # } | ||
| 291 : | # sub setInputTable { | ||
| 292 : | # my $self = shift; | ||
| 293 : | # my $out = { | ||
| 294 : | # pw => XML_PASSWORD, | ||
| 295 : | # library_name => 'Library', | ||
| 296 : | # command => 'renderProblem', | ||
| 297 : | # answer_form_submitted => 1, | ||
| 298 : | # course => XML_COURSE(), | ||
| 299 : | # extra_packages_to_load => [qw( AlgParserWithImplicitExpand Expr | ||
| 300 : | # ExprWithImplicitExpand AnswerEvaluator | ||
| 301 : | # AnswerEvaluatorMaker | ||
| 302 : | # )], | ||
| 303 : | # mode => DISPLAYMODE(), | ||
| 304 : | # modules_to_evaluate => [ qw( | ||
| 305 : | # Exporter | ||
| 306 : | # DynaLoader | ||
| 307 : | # GD | ||
| 308 : | # WWPlot | ||
| 309 : | # Fun | ||
| 310 : | # Circle | ||
| 311 : | # Label | ||
| 312 : | # PGrandom | ||
| 313 : | # Units | ||
| 314 : | # Hermite | ||
| 315 : | # List | ||
| 316 : | # Match | ||
| 317 : | # Multiple | ||
| 318 : | # Select | ||
| 319 : | # AlgParser | ||
| 320 : | # AnswerHash | ||
| 321 : | # Fraction | ||
| 322 : | # VectorField | ||
| 323 : | # Complex1 | ||
| 324 : | # Complex | ||
| 325 : | # MatrixReal1 Matrix | ||
| 326 : | # Distributions | ||
| 327 : | # Regression | ||
| 328 : | # | ||
| 329 : | # )], | ||
| 330 : | # envir => $self->environment(), | ||
| 331 : | # problem_state => { | ||
| 332 : | # | ||
| 333 : | # num_of_correct_ans => 2, | ||
| 334 : | # num_of_incorrect_ans => 4, | ||
| 335 : | # recorded_score => 1.0, | ||
| 336 : | # }, | ||
| 337 : | # source => $self->{encodedSource}, #base64 encoded | ||
| 338 : | # | ||
| 339 : | # | ||
| 340 : | # | ||
| 341 : | # }; | ||
| 342 : | # | ||
| 343 : | # $out; | ||
| 344 : | # } | ||
| 345 : | # | ||
| 346 : | # sub environment { | ||
| 347 : | # my $self = shift; | ||
| 348 : | # my $envir = { | ||
| 349 : | # answerDate => '4014438528', | ||
| 350 : | # CAPA_Graphics_URL=>"not defined", | ||
| 351 : | # CAPA_GraphicsDirectory =>"not defined", | ||
| 352 : | # CAPA_MCTools=>"not defined", | ||
| 353 : | # CAPA_Tools=>'not defined', | ||
| 354 : | # cgiDirectory=>'Not defined', | ||
| 355 : | # cgiURL => 'Not defined', | ||
| 356 : | # classDirectory=> 'Not defined', | ||
| 357 : | # courseName=>'Not defined', | ||
| 358 : | # courseScriptsDirectory=>'not defined', | ||
| 359 : | # displayMode=>DISPLAYMODE, | ||
| 360 : | # dueDate=> '4014438528', | ||
| 361 : | # externalGif2EpsPath=>'not defined', | ||
| 362 : | # externalPng2EpsPath=>'not defined', | ||
| 363 : | # externalTTHPath=>'/usr/local/bin/tth', | ||
| 364 : | # fileName=>'set0/prob1a.pg', | ||
| 365 : | # formattedAnswerDate=>'6/19/00', | ||
| 366 : | # formattedDueDate=>'6/19/00', | ||
| 367 : | # formattedOpenDate=>'6/19/00', | ||
| 368 : | # functAbsTolDefault=> 0.0000001, | ||
| 369 : | # functLLimitDefault=>0, | ||
| 370 : | # functMaxConstantOfIntegration=> 1000000000000.0, | ||
| 371 : | # functNumOfPoints=> 5, | ||
| 372 : | # functRelPercentTolDefault=> 0.000001, | ||
| 373 : | # functULimitDefault=>1, | ||
| 374 : | # functVarDefault=> 'x', | ||
| 375 : | # functZeroLevelDefault=> 0.000001, | ||
| 376 : | # functZeroLevelTolDefault=>0.000001, | ||
| 377 : | # htmlDirectory =>'not defined', | ||
| 378 : | # htmlURL =>'not defined', | ||
| 379 : | # inputs_ref => $self->{inputs_ref}, | ||
| 380 : | # macroDirectory=>'not defined', | ||
| 381 : | # numAbsTolDefault=>0.0000001, | ||
| 382 : | # numFormatDefault=>'%0.13g', | ||
| 383 : | # numOfAttempts=> 0, | ||
| 384 : | # numRelPercentTolDefault => 0.0001, | ||
| 385 : | # numZeroLevelDefault =>0.000001, | ||
| 386 : | # numZeroLevelTolDefault =>0.000001, | ||
| 387 : | # openDate=> '3014438528', | ||
| 388 : | # PRINT_FILE_NAMES_FOR => [ 'gage'], | ||
| 389 : | # probFileName => 'set0/prob1a.pg', | ||
| 390 : | # problemSeed => 1234, | ||
| 391 : | # problemValue =>1, | ||
| 392 : | # probNum => 13, | ||
| 393 : | # psvn => 54321, | ||
| 394 : | gage | 6435 | # psvn=> 54321, |
| 395 : | mgage | 6291 | # questionNumber => 1, |
| 396 : | # scriptDirectory => 'Not defined', | ||
| 397 : | # sectionName => 'Gage', | ||
| 398 : | # sectionNumber => 1, | ||
| 399 : | # sessionKey=> 'Not defined', | ||
| 400 : | # setNumber =>'not defined', | ||
| 401 : | # studentLogin =>'gage', | ||
| 402 : | # studentName => 'Mike Gage', | ||
| 403 : | # tempDirectory => 'not defined', | ||
| 404 : | # templateDirectory=>'not defined', | ||
| 405 : | # tempURL=>'not defined', | ||
| 406 : | # webworkDocsURL => 'not defined', | ||
| 407 : | # }; | ||
| 408 : | # $envir; | ||
| 409 : | # }; | ||
| 410 : | # | ||
| 411 : | # sub formatAnswerRow { | ||
| 412 : | # my $self = shift; | ||
| 413 : | # my $rh_answer = shift; | ||
| 414 : | # my $problemNumber = shift; | ||
| 415 : | # my $answerString = $rh_answer->{original_student_ans}||' '; | ||
| 416 : | # my $correctAnswer = $rh_answer->{correct_ans}||''; | ||
| 417 : | # my $ans_message = $rh_answer->{ans_message}; | ||
| 418 : | # my $score = ($rh_answer->{score}) ? 'Correct' : 'Incorrect'; | ||
| 419 : | # my $row = qq{ | ||
| 420 : | # <tr> | ||
| 421 : | # <td> | ||
| 422 : | # Prob: $problemNumber | ||
| 423 : | # </td> | ||
| 424 : | # <td> | ||
| 425 : | # $answerString | ||
| 426 : | # </td> | ||
| 427 : | # <td> | ||
| 428 : | # $score | ||
| 429 : | # </td> | ||
| 430 : | # <td> | ||
| 431 : | # Correct answer is $correctAnswer | ||
| 432 : | # </td> | ||
| 433 : | # <td> | ||
| 434 : | # <i>$ans_message</i> | ||
| 435 : | # </td> | ||
| 436 : | # </tr>\n | ||
| 437 : | # }; | ||
| 438 : | # $row; | ||
| 439 : | # } | ||
| 440 : | # | ||
| 441 : | # sub formatRenderedProblem { | ||
| 442 : | # my $self = shift; | ||
| 443 : | # my $rh_result = shift; # wrap problem in formats | ||
| 444 : | # my $problemText = decode_base64($rh_result->{text}); | ||
| 445 : | # my $rh_answers = $rh_result->{answers}; | ||
| 446 : | # my $encodedSource = $self->{encodedSource}||'foobar'; | ||
| 447 : | # my $warnings = ''; | ||
| 448 : | # if ( defined ($rh_result->{WARNINGS}) and $rh_result->{WARNINGS} ){ | ||
| 449 : | # $warnings = "<div style=\"background-color:pink\"> | ||
| 450 : | # <p >WARNINGS</p><p>".decode_base64($rh_result->{WARNINGS})."</p></div>"; | ||
| 451 : | # } | ||
| 452 : | # | ||
| 453 : | # ; | ||
| 454 : | # # collect answers | ||
| 455 : | # my $answerTemplate = q{<hr>ANSWERS <table border="3" align="center">}; | ||
| 456 : | # my $problemNumber = 1; | ||
| 457 : | # foreach my $key (sort keys %{$rh_answers}) { | ||
| 458 : | # $answerTemplate .= $self->formatAnswerRow($rh_answers->{$key}, $problemNumber++); | ||
| 459 : | # } | ||
| 460 : | # $answerTemplate .= q{</table> <hr>}; | ||
| 461 : | # | ||
| 462 : | # | ||
| 463 : | # | ||
| 464 : | # my $problemTemplate = <<ENDPROBLEMTEMPLATE; | ||
| 465 : | # <html> | ||
| 466 : | # <head> | ||
| 467 : | # <title>WeBWorK Editor</title> | ||
| 468 : | # </head> | ||
| 469 : | # <body> | ||
| 470 : | # $answerTemplate | ||
| 471 : | # $warnings | ||
| 472 : | # <form action="$FORM_ACTION_URL" method="post"> | ||
| 473 : | # $problemText | ||
| 474 : | # <input type="hidden" name="answersSubmitted" value="1"> | ||
| 475 : | # <input type="hidden" name="problemAddress" value="probSource"> | ||
| 476 : | # <input type="hidden" name="problemSource" value="$encodedSource"> | ||
| 477 : | # <input type="hidden" name="problemSeed" value="1234"> | ||
| 478 : | # <input type="hidden" name="pathToProblemFile" value="foobar"> | ||
| 479 : | # <p><input type="submit" name="submit" value="submit answers"></p> | ||
| 480 : | # </form> | ||
| 481 : | # </body> | ||
| 482 : | # </html> | ||
| 483 : | # | ||
| 484 : | # ENDPROBLEMTEMPLATE | ||
| 485 : | # | ||
| 486 : | # | ||
| 487 : | # | ||
| 488 : | # $problemTemplate; | ||
| 489 : | # } | ||
| 490 : | # | ||
| 491 : | gage | 6228 | |
| 492 : | 1; |
| aubreyja at gmail dot com | ViewVC Help |
| Powered by ViewVC 1.0.9 |