You can subscribe to this list here.
2004 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(58) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2005 |
Jan
(53) |
Feb
(56) |
Mar
|
Apr
|
May
(30) |
Jun
(78) |
Jul
(121) |
Aug
(155) |
Sep
(77) |
Oct
(61) |
Nov
(45) |
Dec
(94) |
2006 |
Jan
(116) |
Feb
(33) |
Mar
(11) |
Apr
(23) |
May
(60) |
Jun
(89) |
Jul
(130) |
Aug
(109) |
Sep
(124) |
Oct
(63) |
Nov
(82) |
Dec
(45) |
2007 |
Jan
(31) |
Feb
(35) |
Mar
(123) |
Apr
(36) |
May
(18) |
Jun
(134) |
Jul
(133) |
Aug
(241) |
Sep
(126) |
Oct
(31) |
Nov
(15) |
Dec
(5) |
2008 |
Jan
(11) |
Feb
(6) |
Mar
(16) |
Apr
(29) |
May
(43) |
Jun
(149) |
Jul
(27) |
Aug
(29) |
Sep
(37) |
Oct
(20) |
Nov
(4) |
Dec
(6) |
2009 |
Jan
(34) |
Feb
(30) |
Mar
(16) |
Apr
(6) |
May
(1) |
Jun
(32) |
Jul
(22) |
Aug
(7) |
Sep
(18) |
Oct
(50) |
Nov
(22) |
Dec
(8) |
2010 |
Jan
(17) |
Feb
(15) |
Mar
(10) |
Apr
(9) |
May
(67) |
Jun
(30) |
Jul
|
Aug
|
Sep
(2) |
Oct
|
Nov
(1) |
Dec
|
From: Mike G. v. a. <we...@ma...> - 2008-05-09 12:11:55
|
Log Message: ----------- Added a few more cosmetic tweaks to the text and to the execution flow. This registration is now acceptable except that the questions asked in the email need to be examined more closely. A later version might allow for automatic registration. Modified Files: -------------- webwork2/lib/WeBWorK/ContentGenerator: CourseAdmin.pm Revision Data ------------- Index: CourseAdmin.pm =================================================================== RCS file: /webwork/cvs/system/webwork2/lib/WeBWorK/ContentGenerator/CourseAdmin.pm,v retrieving revision 1.72 retrieving revision 1.73 diff -Llib/WeBWorK/ContentGenerator/CourseAdmin.pm -Llib/WeBWorK/ContentGenerator/CourseAdmin.pm -u -r1.72 -r1.73 --- lib/WeBWorK/ContentGenerator/CourseAdmin.pm +++ lib/WeBWorK/ContentGenerator/CourseAdmin.pm @@ -2426,9 +2426,10 @@ my $ce = $self->r->ce; my $registeredQ = (-e ($ce->{courseDirs}->{root})."/$registered_file_name")?1:0; my $registration_subDisplay = ( $self->{method_to_call} eq "registration_form") ? 1: 0; -return 0 if $registeredQ or $registration_subDisplay; #otherwise return registration form -return q! -<table class="messagebox" style="background-color:#FFFFCC;cellpadding:100px"> +return 0 if $registeredQ or $self->r->param("register_site"); #otherwise return registration form +return q! +<center> +<table class="messagebox" style="background-color:#FFFFCC;width:60%"> <tr><td> !, CGI::p("If you are using your WeBWorK server for courses please help us out by registering your server."), @@ -2447,6 +2448,7 @@ q! </td></tr> </table> +</center> !; @@ -2477,6 +2479,7 @@ .uri_escape("Approximate number of courses run each term: \n\n") .uri_escape("Approximate number of students using this server each term: \n\n") .uri_escape("Other institutions who use WeBWorK courses hosted on this server: \n\n") +.uri_escape("Other comments: \n\n") }, 'click here'), q! to open your email application. There are a few questions, some of which have already @@ -2487,7 +2490,7 @@ -print "\n",CGI::p({style=>"text-align: left; width:60%"},,q!Once you have emailed your registration information you can hide the "registration" banner +print "\n",CGI::p({style=>"text-align: left; width:60%"},q!Once you have emailed your registration information you can hide the "registration" banner for successive visits by clicking the button below.!) ; @@ -2512,7 +2515,13 @@ my $registered_file_path = $ce->{courseDirs}->{root}."/$registered_file_name"; # warn qq!`echo "info" >$registered_file_path`!; `echo "info" >$registered_file_path`; -print "\n registration action done"; +print "\n",CGI::p({style=>"text-align: center; width:60%"},q{Registration action completed. Thank you very much!"}); + +print CGI::start_form(-method=>"POST", -action=>$self->r->uri); +print $self->hidden_authen_fields; +#print $self->hidden_fields("subDisplay"); +print CGI::p({style=>"text-align: center"}, CGI::submit(-name=>"registration_completed", -label=>"Continue")); +print CGI::end_form(); } ################################################################################ |
From: Mike G. v. a. <we...@ma...> - 2008-05-09 00:57:57
|
Log Message: ----------- Changed the message on the email message a bit. Modified Files: -------------- webwork2/lib/WeBWorK/ContentGenerator: CourseAdmin.pm Revision Data ------------- Index: CourseAdmin.pm =================================================================== RCS file: /webwork/cvs/system/webwork2/lib/WeBWorK/ContentGenerator/CourseAdmin.pm,v retrieving revision 1.71 retrieving revision 1.72 diff -Llib/WeBWorK/ContentGenerator/CourseAdmin.pm -Llib/WeBWorK/ContentGenerator/CourseAdmin.pm -u -r1.71 -r1.72 --- lib/WeBWorK/ContentGenerator/CourseAdmin.pm +++ lib/WeBWorK/ContentGenerator/CourseAdmin.pm @@ -2454,13 +2454,22 @@ } sub registration_form { my $self = shift; +my $ce = $self->r->ce; + print "<center>"; print "\n",CGI::p({style=>"text-align: left; width:60%"}, "\nPlease ", CGI::a({href=>'mailto:ga...@ma...?' .'subject=WeBWorK%20Server%20Registration' .'&body=' -.uri_escape("Server URL: \n\n") +.uri_escape("Thanks for registering your WeBWorK server. We'd appreciate if you would answer +as many of these questions as you can conveniently. We need this data so we can better +answer questions such as 'How many institutions have webwork servers?' and 'How many students +use WeBWorK?'. Your email and contact information will be kept private. We will +list your institution as one that uses WeBWorK unless you tell us to keep that private as well. +\n\nThank you. \n\n--Mike Gage \n\n +") +.uri_escape("Server URL: ".$ce->{apache_root_url}." \n\n") .uri_escape("WeBWorK version: $main::VERSION \n\n") .uri_escape("Institution name (e.g. University of Rochester): \n\n") .uri_escape("Contact person name: \n\n") |
From: Mike G. v. a. <we...@ma...> - 2008-05-09 00:42:38
|
Log Message: ----------- Added a banner which asks users to register production servers. Clicking on the "register button" brings up a page with a mailto: link. and a "server site registered" button. Clicking on the mailto link brings up the administrator's email application with suggested information to be emailed to ga...@ma... (for now -- later we can replace this with an alias mail address and eventually with some sort of form and a database for the recipient.) Clicking on the "server site registered" button creates an empty file courses/admin/registered_2.4.5 where 2.4.5 is the current version number found in WeBWorK. if this file is present the "please register" banner goes away. It's just a first cut at tackling this problem. p Modified Files: -------------- webwork2/lib/WeBWorK/ContentGenerator: CourseAdmin.pm Revision Data ------------- Index: CourseAdmin.pm =================================================================== RCS file: /webwork/cvs/system/webwork2/lib/WeBWorK/ContentGenerator/CourseAdmin.pm,v retrieving revision 1.70 retrieving revision 1.71 diff -Llib/WeBWorK/ContentGenerator/CourseAdmin.pm -Llib/WeBWorK/ContentGenerator/CourseAdmin.pm -u -r1.70 -r1.71 --- lib/WeBWorK/ContentGenerator/CourseAdmin.pm +++ lib/WeBWorK/ContentGenerator/CourseAdmin.pm @@ -31,6 +31,7 @@ use File::Temp qw/tempfile/; use WeBWorK::CourseEnvironment; use IO::File; +use URI::Escape; use WeBWorK::Debug; use WeBWorK::Utils qw(cryptPassword writeLog listFilesRecursive); use WeBWorK::Utils::CourseManagement qw(addCourse renameCourse deleteCourse listCourses archiveCourse @@ -220,6 +221,14 @@ $method_to_call = "manage_location_form"; } } + elsif ($subDisplay eq "registration") { + if (defined ($r->param("register_site"))) { + $method_to_call = "do_registration"; + } + else{ + $method_to_call = "registration_form"; + } + } else { @errors = "Unrecognized sub-display @{[ CGI::b($subDisplay) ]}."; } @@ -317,6 +326,9 @@ ); + print( CGI::p({style=>"text-align: center"}, $self->display_registration_form() ) ) if $self->display_registration_form(); + + my @errors = @{$self->{errors}}; @@ -2405,4 +2417,94 @@ } ################################################################################ +# registration forms added by Mike Gage 5-5-2008 +################################################################################ + +our $registered_file_name = "registered_$main::VERSION"; +sub display_registration_form { +my $self = shift; +my $ce = $self->r->ce; +my $registeredQ = (-e ($ce->{courseDirs}->{root})."/$registered_file_name")?1:0; +my $registration_subDisplay = ( $self->{method_to_call} eq "registration_form") ? 1: 0; +return 0 if $registeredQ or $registration_subDisplay; #otherwise return registration form +return q! +<table class="messagebox" style="background-color:#FFFFCC;cellpadding:100px"> +<tr><td> +!, +CGI::p("If you are using your WeBWorK server for courses please help us out by registering your server."), +CGI::p("We are often asked how many institutions are using WeBWorK and how many students are using +WeBWorK Since WeBWorK is open source and can be freely downloaded from http://www.openwebwork.org +and http://webwork.maa.org it is frequently difficult for us to give a reasonable answer to this +question."), +CGI::p("You can help by registering your current version of WeBWorK -- click the button, answer a few +questions (the ones you can answer easily) and send the email. It takes less than two minutes. Thank you!. -- The WeBWorK Team"), +q! +</td> +</tr> +<tr><td align="center"> +!, +CGI::a({href=>$self->systemLink($self->r->urlpath, params=>{subDisplay=>"registration"})}, "Register"), +q! +</td></tr> +</table> +!; + + + +} +sub registration_form { +my $self = shift; +print "<center>"; +print "\n",CGI::p({style=>"text-align: left; width:60%"}, +"\nPlease ", +CGI::a({href=>'mailto:ga...@ma...?' +.'subject=WeBWorK%20Server%20Registration' +.'&body=' +.uri_escape("Server URL: \n\n") +.uri_escape("WeBWorK version: $main::VERSION \n\n") +.uri_escape("Institution name (e.g. University of Rochester): \n\n") +.uri_escape("Contact person name: \n\n") +.uri_escape("Contact email: \n\n") +.uri_escape("Approximate number of courses run each term: \n\n") +.uri_escape("Approximate number of students using this server each term: \n\n") +.uri_escape("Other institutions who use WeBWorK courses hosted on this server: \n\n") +}, +'click here'), +q! to open your email application. There are a few questions, some of which have already +been filled in for your installation. Fill in the other questions which you can answer easily and send +the email to gage\@math.rochester.edu +! +); + + + +print "\n",CGI::p({style=>"text-align: left; width:60%"},,q!Once you have emailed your registration information you can hide the "registration" banner +for successive visits by clicking +the button below.!) +; + +print "</center>"; +print CGI::start_form(-method=>"POST", -action=>$self->r->uri); +print $self->hidden_authen_fields; +print $self->hidden_fields("subDisplay"); +print CGI::p({style=>"text-align: center"}, CGI::submit(-name=>"register_site", -label=>"Site has been registered")); +print CGI::end_form(); +} + +sub registration_validate { + +print "\nregistration validate form"; + +} + +sub do_registration { +my $self = shift; +my $ce = $self->r->ce; +my $registered_file_path = $ce->{courseDirs}->{root}."/$registered_file_name"; +# warn qq!`echo "info" >$registered_file_path`!; +`echo "info" >$registered_file_path`; +print "\n registration action done"; + +} +################################################################################ 1; |
From: Sam H. v. a. <we...@ma...> - 2008-05-08 00:53:01
|
Log Message: ----------- add "my" and "our" specifiers to ^variable definitions. (This breaks compatibility with the current version of ww-symbol-map, but it is the format that the upcoming version will use. I hope to commit that new version soon but testing is taking longer than expected.) Modified Files: -------------- pg/macros: PG.pl PGanswermacros.pl Parser.pl dangerousMacros.pl Revision Data ------------- Index: Parser.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/Parser.pl,v retrieving revision 1.15 retrieving revision 1.16 diff -Lmacros/Parser.pl -Lmacros/Parser.pl -u -r1.15 -r1.16 --- macros/Parser.pl +++ macros/Parser.pl @@ -116,7 +116,7 @@ # ^uses Parser::Context::current # ^uses %context sub Context {Parser::Context->current(\%context,@_)} -# ^variable %context +# ^variable our %context %context = (); # Locally defined contexts, including 'current' context # ^uses Context Context(); # Initialize context (for persistent mod_perl) @@ -343,7 +343,7 @@ ########################################################################### -# ^variable $_parser_loaded +# ^variable our $_parser_loaded $_parser_loaded = 1; # use this to tell if Parser.pl is loaded # ^function _Parser_init Index: dangerousMacros.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/dangerousMacros.pl,v retrieving revision 1.51 retrieving revision 1.52 diff -Lmacros/dangerousMacros.pl -Lmacros/dangerousMacros.pl -u -r1.51 -r1.52 --- macros/dangerousMacros.pl +++ macros/dangerousMacros.pl @@ -97,24 +97,24 @@ } -# ^variable $debugON +# ^variable my $debugON my $debugON = 0; # grab read only variables from the current safe compartment -# ^variable $macrosPath +# ^variable my $macrosPath my ($macrosPath, - # ^variable $pwd + # ^variable my $pwd $pwd, - # ^variable $appletPath + # ^variable my $appletPath $appletPath, - # ^variable $server_root_url + # ^variable my $server_root_url $server_root_url, - # ^variable $templateDirectory + # ^variable my $templateDirectory $templateDirectory, - # ^variable $scriptDirectory + # ^variable my $scriptDirectory $scriptDirectory, - # ^variable $externalTTHPath + # ^variable my $externalTTHPath $externalTTHPath, ); @@ -369,7 +369,7 @@ return ($response) ? 0 : 1; # 0 indicates success, 256 is failure possibly more checks can be made } -# ^variable %appletCodebaseLocations +# ^variable our %appletCodebaseLocations our %appletCodebaseLocations = (); # ^function findAppletCodebase # ^uses %appletCodebaseLocations @@ -505,9 +505,9 @@ # only needs to be read once. however, the contents of the file may change, # and indeed the file refered to may change, between rendering passes. thus, # we need to keep track of the file name and the mtime as well. -# ^variable $tthPreambleFile -# ^variable $tthPreambleMtime -# ^variable $tthPreambleContents +# ^variable my $tthPreambleFile +# ^variable my $tthPreambleMtime +# ^variable my $tthPreambleContents my ($tthPreambleFile, $tthPreambleMtime, $tthPreambleContents); # ^function tth @@ -617,7 +617,7 @@ =cut -# ^variable $math2imgCount +# ^variable my $math2imgCount my $math2imgCount = 0; # ^function math2img Index: PG.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/PG.pl,v retrieving revision 1.36 retrieving revision 1.37 diff -Lmacros/PG.pl -Lmacros/PG.pl -u -r1.36 -r1.37 --- macros/PG.pl +++ macros/PG.pl @@ -107,18 +107,18 @@ # Private variables for the PG.pl file. -# ^variable $STRINGforOUTPUT +# ^variable my $STRINGforOUTPUT my $STRINGforOUTPUT; -# ^variable $STRINGforHEADER_TEXT +# ^variable my $STRINGforHEADER_TEXT my $STRINGforHEADER_TEXT; -# ^variable @PG_ANSWERS +# ^variable my @PG_ANSWERS my @PG_ANSWERS; -# ^variable @PG_UNLABELED_ANSWERS +# ^variable my @PG_UNLABELED_ANSWERS my @PG_UNLABELED_ANSWERS; -# ^variable %PG_ANSWERS_HASH +# ^variable my %PG_ANSWERS_HASH my %PG_ANSWERS_HASH; -# ^variable $PG_STOP_FLAG +# ^variable our $PG_STOP_FLAG our $PG_STOP_FLAG; # my variables are unreliable if two DOCUMENTS were to be called before an ENDDOCUMENT Index: PGanswermacros.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/PGanswermacros.pl,v retrieving revision 1.67 retrieving revision 1.68 diff -Lmacros/PGanswermacros.pl -Lmacros/PGanswermacros.pl -u -r1.67 -r1.68 --- macros/PGanswermacros.pl +++ macros/PGanswermacros.pl @@ -138,15 +138,15 @@ # variables. We do this once here and place the values in lexicals for later # access. -# ^variable $BR +# ^variable my $BR my $BR; -# ^variable $functLLimitDefault +# ^variable my $functLLimitDefault my $functLLimitDefault; -# ^variable $functULimitDefault +# ^variable my $functULimitDefault my $functULimitDefault; -# ^variable $functVarDefault +# ^variable my $functVarDefault my $functVarDefault; -# ^variable $useBaseTenLog +# ^variable my $useBaseTenLog my $useBaseTenLog; # ^function _PGanswermacros_init |
From: Mike G. v. a. <we...@ma...> - 2008-05-05 17:40:17
|
Log Message: ----------- fix method of setting debug Modified Files: -------------- pg/macros: AppletObjects.pl Revision Data ------------- Index: AppletObjects.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/AppletObjects.pl,v retrieving revision 1.8 retrieving revision 1.9 diff -Lmacros/AppletObjects.pl -Lmacros/AppletObjects.pl -u -r1.8 -r1.9 --- macros/AppletObjects.pl +++ macros/AppletObjects.pl @@ -61,8 +61,13 @@ ////////////////////////////////////////////////////////// // DEBUGGING tools ////////////////////////////////////////////////////////// - var debug = $debugMode; + var debug; var debugText = ""; + function set_debug(num) { // setting debug for any applet sets it for all of them + if (num) { + debug =1; + } + } function debug_add(str) { if (debug) { debugText = debugText + "\n\n" +str; |
From: Mike G. v. a. <we...@ma...> - 2008-05-05 17:40:01
|
Log Message: ----------- fix method of setting debug Modified Files: -------------- pg/lib: Applet.pm Revision Data ------------- Index: Applet.pm =================================================================== RCS file: /webwork/cvs/system/pg/lib/Applet.pm,v retrieving revision 1.9 retrieving revision 1.10 diff -Llib/Applet.pm -Llib/Applet.pm -u -r1.9 -r1.10 --- lib/Applet.pm +++ lib/Applet.pm @@ -407,6 +407,9 @@ <script language="JavaScript"> + // set debug mode for this applet + set_debug($debugMode); + ////////////////////////////////////////////////////////// //CONFIGURATIONS // |
From: Mike G. v. a. <we...@ma...> - 2008-05-05 16:59:36
|
Log Message: ----------- Latest improvements for the Applet.pm and AppletObjects.pl files Modified Files: -------------- pg/lib: Applet.pm Revision Data ------------- Index: Applet.pm =================================================================== RCS file: /webwork/cvs/system/pg/lib/Applet.pm,v retrieving revision 1.8 retrieving revision 1.9 diff -Llib/Applet.pm -Llib/Applet.pm -u -r1.8 -r1.9 --- lib/Applet.pm +++ lib/Applet.pm @@ -37,7 +37,7 @@ ################################### #xml data to set up the problem-rac - $applet->state(qq{<XML> + $applet->config(qq{<XML> <point xval='$xval_1' yval='$yval_1' /> <point xval='$xval_2' yval='$yval_2' /> </XML>}); @@ -192,8 +192,8 @@ params =>undef, width => 550, height => 400, - base64_state => '', - base64_config => '', + base64_state => undef, # this is an state to use for initializing the first occurence of the question. + base64_config => undef, # this is the initial (and final?) configuration getStateAlias => 'getXML', setStateAlias => 'setXML', configAlias => 'config', @@ -206,6 +206,8 @@ @_, }; bless $self, $class; + $self->state('<xml></xml>'); + $self->config('<xml></xml>'); return $self; } @@ -397,74 +399,121 @@ }; } - +######################################################## +# HEADER material for one flash or java applet +######################################################## use constant DEFAULT_HEADER_TEXT =><<'END_HEADER_SCRIPT'; <script language="JavaScript"> - var debug = $debugMode; - // + + ////////////////////////////////////////////////////////// //CONFIGURATIONS // // configurations are "permanent" + ////////////////////////////////////////////////////////// + applet_config_list["$appletName"] = function() { - if (debug) { alert("configure $appletName . $config ( $base64_config )");} + debug_add("applet_config_list:\n configure $appletName . $config ( $base64_config )" + + typeof(getApplet("$appletName").$config) + ); try { - if (debug || !( typeof(getApplet("$appletName").$config) == "undefined" ) ) { - + if (( typeof(getApplet("$appletName").$config) == "function" ) ) { + debug_add("configure $appletName"); getApplet("$appletName").$config(Base64.decode("$base64_config")); } } catch(e) { - alert("error executing configuration command $config for $appletName: " + e ); + alert("Error executing configuration command $config for $appletName: " + e ); } } + //////////////////////////////////////////////////////////// // - //STATE + //STATE: + // state can vary as the applet is manipulated -- it is reset from the questions _state values // - // state can vary as the applet is manipulated. - applet_setState_list["$appletName"] = function(state) { - if (debug) { alert("set state for $appletName to " + state);} - state = state || getQE("$appletName"+"_state").value - if (state.match(/<xml/i) || state.match(/<?xml/i) ) { // if state is not all white space - if ( base64Q(state) ) { - state=Base64.decode(state); - } - alert("set (decoded) state for $appletName to " + state); - try { - if (debug || !( typeof(getApplet("$appletName").$setState) =="undefined" ) ) { - getApplet("$appletName").$setState( state ); - } - } catch(e) { - alert("Error in setting state of $appletName using command $setState : " + e ); - } - } else if (debug) { - alert("new state was empty string or did not begin with <xml-- state was not reset"); - } + ////////////////////////////////////////////////////////// + + applet_setState_list["$appletName"] = function(state) { + debug_add("Begin setState"); + state = state || getQE("$appletName"+"_state").value; + if ( base64Q(state) ) { + state=Base64.decode(state); + } + if (state.match(/<xml/i) || state.match(/<?xml/i) ) { // if state starts with <?xml + + debug_add("applet_setState_list: \n set (decoded) state for $appletName to " + + state +"\nfunction type is " +typeof(getApplet("$appletName").$setState) + ); + try { + if (( typeof(getApplet("$appletName").$setState) =="function" ) ) { + debug_add("setState for $appletName"); + getApplet("$appletName").$setState( state ); + } + } catch(e) { + alert("Error in setting state of $appletName using command $setState : " + e ); + } + } else if (debug) { + alert("new state was empty string or did not begin with <xml-- state was not reset"); + } }; applet_getState_list["$appletName"] = function () { - if (debug) { alert("getState for applet $appletName");} - try { - var applet = getApplet("$appletName"); - var state; - if (!( typeof(getApplet("$appletName").$getState) =="undefined" ) ) { - state = applet.$getState(); // get state in xml format - } - if (!debug) {state = Base64.encode(state) }; // replace state by encoded version - getQE("$appletName"+"_state").value = state; //place in state htmlItem (debug: textarea, otherwise hidden) - } catch (e) { - alert("Error in getting state for $appletName " + e ); - } + if (debug) { alert("getState for applet $appletName");} + var applet = getApplet("$appletName"); + try { + if (( typeof(applet.$getState) == "function" ) ) { // there may be no state function + state = applet.$getState(); // get state in xml format + } + if (debug) alert("state is " + state); + if (!debug) {state = Base64.encode(state) }; // replace state by encoded version unless in debug mode + getQE("$appletName"+"_state").value = state; //place in state htmlItem (debug: textarea, otherwise hidden) + } catch (e) { + alert("Error in getting state for $appletName " + e ); + } }; + + //////////////////////////////////////////////////////////// // //INITIALIZE // - applet_initializeAction_list["$appletName"] = function () { - applet_setState_list["$appletName"](); + //////////////////////////////////////////////////////////// + + + applet_checkLoaded_list["$appletName"] = function() { // this function returns 0 unless: + // applet has already been flagged as ready in applet_isReady_list + // applet.config is defined (or alias for .config) + // applet.setState is defined + // applet.isActive is defined + // applet reported that it is loaded by calling loadQ() + var ready = 0; + var applet = getApplet("$appletName"); + if (!debug && applet_isReady_list["$appletName"]) {return(1)}; // memorize readiness in non-debug mode + if ( typeof(applet.$config) == "function") { + debug_add( "applet.config is " + typeof(applet.$config) ); + ready = 1; + } + if( typeof(applet.$getState) == "function") { + debug_add( "applet.getState is " + typeof(applet.$getState) ); + ready =1; + } + if (typeof(applet.isActive) == "function" && applet.isActive ) { + debug_add( "applet.isActive is " + typeof(applet.isActive) ); + ready =1; + } + if (typeof(applet_reportsLoaded_list["$appletName"]) !="undefined" && applet_reportsLoaded_list["$appletName"] != 0 ) { + debug_add( "applet reports that it is loaded " + applet_reportsLoaded_list["$appletName"] ); + ready =1; + } + applet_isReady_list["$appletName"]=ready; + return(ready); + } + + applet_initializeAction_list["$appletName"] = function (state) { + applet_setState_list["$appletName"](state); }; applet_submitAction_list["$appletName"] = function () { applet_getState_list["$appletName"](); - getQE("$returnFieldName").value = getApplet("$appletName").sendData(); + getQE("$returnFieldName").value = getApplet("$appletName").sendData(); //FIXME -- not needed in general? }; </script> |
From: Mike G. v. a. <we...@ma...> - 2008-05-05 16:58:52
|
Log Message: ----------- Latest reworking of the Applets.pm and AppletObjects.pl files Debugging and error reporting should be better now. Modified Files: -------------- pg/macros: AppletObjects.pl Revision Data ------------- Index: AppletObjects.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/AppletObjects.pl,v retrieving revision 1.7 retrieving revision 1.8 diff -Lmacros/AppletObjects.pl -Lmacros/AppletObjects.pl -u -r1.7 -r1.8 --- macros/AppletObjects.pl +++ macros/AppletObjects.pl @@ -44,17 +44,35 @@ </script> <script language="JavaScript"> - var applet_initializeAction_list = new Object; - var applet_submitAction_list = new Object; - var applet_setState_list = new Object; - var applet_getState_list = new Object; - var applet_config_list = new Object; +////////////////////////////////////////////////////////// +// applet lists +////////////////////////////////////////////////////////// + + var applet_initializeAction_list = new Object; // functions for initializing question with an applet + var applet_submitAction_list = new Object; // functions for submitting question with applet + var applet_setState_list = new Object; // functions for setting state (XML) from applets + var applet_getState_list = new Object; // functions for getting state (XML) from applets + var applet_config_list = new Object; // functions for configuring on applets + var applet_checkLoaded_list = new Object; // functions for probing the applet to see if it is loaded + var applet_reportsLoaded_list = new Object; // flag set by applet + var applet_isReady_list = new Object; // flag set by javaScript in checkLoaded - function base64Q(str) { - return ( !str.match(/<XML/i) && !str.match(/<?xml/i)); - } - +////////////////////////////////////////////////////////// +// DEBUGGING tools +////////////////////////////////////////////////////////// + var debug = $debugMode; + var debugText = ""; + function debug_add(str) { + if (debug) { + debugText = debugText + "\n\n" +str; + } + } + +////////////////////////////////////////////////////////// +// INITIALIZE and SUBMIT actions +////////////////////////////////////////////////////////// + function submitAction() { //alert("submit Action" ); for (var applet in applet_submitAction_list) { @@ -63,79 +81,123 @@ } } - // Give some time delay before initializing function initializeAction() { - //alert("ready to initialize"); - // give some delay to allow flash applet to load. FIXME - window.setTimeout("initializeAction1()",200); - //initializeAction1(); - } - function initializeAction1() { - - for (var appletName in applet_initializeAction_list) { - //alert("initialize: " + appletName); - try{ - applet_config_list[appletName](); - } catch(e) { - alert("unable to configure " + appletName + " It may have been slow to load. " +e ); - } - try{ - applet_initializeAction_list[appletName](); - } catch(e) { - alert("unable to initialize " + appletName + " It may have been slow to load. " +e ); - } + var iMax = 10; + debugText="start intializeAction() with up to " +iMax + " attempts\n"; + for (var appletName in applet_initializeAction_list) { + safe_applet_initialize(appletName, iMax); } + + } + + // applet can set isReady flag by calling applet_loaded(appletName, loaded); + function applet_loaded(appletName,loaded) { + applet_reportsLoaded_list[appletName] = loaded; // 0 means not loaded + debug_add("applet reporting that it has been loaded = " + loaded ); } + // insures that applet is loaded before initializing it + function safe_applet_initialize(appletName, i) { + debug_add("Iteration " + i + " of safe_applet_initialize with applet " + appletName ); + + i--; + var applet_loaded = applet_checkLoaded_list[appletName](); + debug_add("applet is ready = " + applet_loaded ); + + if ( 0 < i && !applet_loaded ) { // wait until applet is loaded + debug_add("applet " + appletName + "not ready try again"); + window.setTimeout( "safe_applet_initialize(\"" + appletName + "\"," + i + ")",1); + } else if( 0 < i ){ // now that applet is loaded configure it and initialize it with saved data. + debug_add(" Ready to initialize applet " + appletName + " with " + i + " iterations left. "); + + // in-line handler -- configure and initialize + try{ + if (debug && typeof(getApplet(appletName).debug) == "function" ) { + getApplet(appletName).debug(1); + } + } catch(e) { + alert("Unable to set debug mode for applet " + appletName); + } + try{ + applet_config_list[appletName](); + } catch(e) { + alert("Unable to configure " + appletName + " \n " +e ); + } + try{ + applet_initializeAction_list[appletName](); + } catch(e) { + alert("unable to initialize " + appletName + " \n " +e ); + } + + } else { + if (debug) {alert("Error: timed out waiting for applet " +appletName + " to load");} + } + if (debug) {alert(debugText); debugText="";}; + } + +/////////////////////////////////////////////////////// +// Utility functions +/////////////////////////////////////////////////////// - var flash; + function getApplet(appletName) { var isIE = navigator.appName.indexOf("Microsoft") != -1; var obj = (isIE) ? window[appletName] : window.document[appletName]; //return window.document[appletName]; if (obj && (obj.name = appletName)) { - return( obj ); + return( obj ); } else { - alert ("can't find applet " + appletName); + // alert ("can't find applet " + appletName); } } - - function listQuestionElements() { // list all HTML input and textarea elements in main problem form - var isIE = navigator.appName.indexOf("Microsoft") != -1; - var elementList = (isIE) ? document.getElementsByTagName("input") : document.problemMainForm.getElementsByTagName("input"); - var str=elementList.length +" Question Elements\n type | name = value < id > \n"; - for( var i=0; i< elementList.length; i++) { - str = str + " "+i+" " + elementList[i].type - + " | " + elementList[i].name - + "= " + elementList[i].value + - " <" + elementList[i].id + ">\n"; - } - elementList = (isIE) ? document.getElementsByTagName("textarea") : document.problemMainForm.getElementsByTagName("textarea"); - for( var i=0; i< elementList.length; i++) { - str = str + " "+i+" " + elementList[i].type - + " | " + elementList[i].name - + "= " + elementList[i].value + - " <" + elementList[i].id + ">\n"; - } - alert(str +"\n Place listQuestionElements() at end of document in order to get all form elements!"); - } - - function getQE(name1) { // get Question Element in problemMainForm by name - var isIE = navigator.appName.indexOf("Microsoft") != -1; - var obj = (isIE) ? document.getElementById(name1) - :document.problemMainForm[name1]; - // needed for IE -- searches id and name space so it can be unreliable if names are not unique - if (!obj || obj.name != name1) { - alert("Can't find element " + name1); - listQuestionElements(); - } else { - return( obj ); - } - - } - function getQuestionElement(name1) { - return getQE(name1); - } + + function listQuestionElements() { // list all HTML input and textarea elements in main problem form + var isIE = navigator.appName.indexOf("Microsoft") != -1; + var elementList = (isIE) ? document.getElementsByTagName("input") : document.problemMainForm.getElementsByTagName("input"); + var str=elementList.length +" Question Elements\n type | name = value < id > \n"; + for( var i=0; i< elementList.length; i++) { + str = str + " "+i+" " + elementList[i].type + + " | " + elementList[i].name + + "= " + elementList[i].value + + " <" + elementList[i].id + ">\n"; + } + elementList = (isIE) ? document.getElementsByTagName("textarea") : document.problemMainForm.getElementsByTagName("textarea"); + for( var i=0; i< elementList.length; i++) { + str = str + " "+i+" " + elementList[i].type + + " | " + elementList[i].name + + "= " + elementList[i].value + + " <" + elementList[i].id + ">\n"; + } + alert(str +"\n Place listQuestionElements() at end of document in order to get all form elements!"); + } + + function base64Q(str) { + return ( !str.match(/<XML/i) && !str.match(/<?xml/i)); + } + function setEmptyState(appletName){ + var newState = "<xml></xml>"; + applet_setState_list[appletName](newState); + var applet = getApplet(appletName); + getQE(appletName+"_state").value = newState; + getQE("previous_" + appletName + "_state").value = newState + } + + function getQE(name1) { // get Question Element in problemMainForm by name + var isIE = navigator.appName.indexOf("Microsoft") != -1; + var obj = (isIE) ? document.getElementById(name1) + :document.problemMainForm[name1]; + // needed for IE -- searches id and name space so it can be unreliable if names are not unique + if (!obj || obj.name != name1) { + alert("Can't find element " + name1); + listQuestionElements(); + } else { + return( obj ); + } + + } + function getQuestionElement(name1) { + return getQE(name1); + } </script> @@ -234,8 +296,8 @@ my $state_input_element = ($self->debug == 1) ? $debug_input_element : qq!\n<input type="hidden" name = "$appletStateName" value ="$base_64_encoded_answer_value">!; my $reset_button_str = ($reset_button) ? - qq!<br/><input type='button' value='set applet state empty' onClick="applet_setState_list['$appletName']('<xml></xml>')"> - <input type="button" value="reinitialize applet" onClick="initializeAction()"/>! + qq!<br/><input type='button' value='set applet state empty' onClick="setEmptyState('$appletName')"> + <input type="button" value="reinitialize applet" onClick="getQE('$appletStateName').value='$base64_initialState'"/>! : '' ; # always base64 encode the hidden answer value to prevent problems with quotes. |
From: Mike G. v. a. <we...@ma...> - 2008-05-05 16:57:51
|
Log Message: ----------- speeling typo :-) Modified Files: -------------- pg/macros: contextPiecewiseFunction.pl Revision Data ------------- Index: contextPiecewiseFunction.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/contextPiecewiseFunction.pl,v retrieving revision 1.7 retrieving revision 1.8 diff -Lmacros/contextPiecewiseFunction.pl -Lmacros/contextPiecewiseFunction.pl -u -r1.7 -r1.8 --- macros/contextPiecewiseFunction.pl +++ macros/contextPiecewiseFunction.pl @@ -659,7 +659,7 @@ } # -# Check that the funciton domains have the same number of +# Check that the function domains have the same number of # components, and that those components agree, interval by interval. # sub compareDomains { |
From: Sam H. v. a. <we...@ma...> - 2008-05-03 17:58:51
|
Log Message: ----------- markup for ww-symbol-map Modified Files: -------------- pg/macros: IO.pl LinearProgramming.pl MathObjects.pl PG.pl PGanswermacros.pl PGasu.pl PGauxiliaryFunctions.pl Parser.pl dangerousMacros.pl extraAnswerEvaluators.pl Revision Data ------------- Index: PGauxiliaryFunctions.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/PGauxiliaryFunctions.pl,v retrieving revision 1.10 retrieving revision 1.11 diff -Lmacros/PGauxiliaryFunctions.pl -Lmacros/PGauxiliaryFunctions.pl -u -r1.10 -r1.11 --- macros/PGauxiliaryFunctions.pl +++ macros/PGauxiliaryFunctions.pl @@ -11,6 +11,7 @@ =cut +# ^uses loadMacros loadMacros("PGcommonFunctions.pl"); =head3 @@ -34,14 +35,17 @@ =cut +# ^function step sub step { # heavyside function (1 or x>0) my $x = shift; ($x > 0 ) ? 1 : 0; } +# ^function ceil sub ceil { my $x = shift; - floor(-$x); } +# ^function floor sub floor { my $input = shift; my $out = int $input; @@ -49,6 +53,7 @@ $out; } +# ^function max sub max { my $maxVal = shift; @@ -62,6 +67,7 @@ } +# ^function min sub min { my $minVal = shift; @@ -77,6 +83,8 @@ #round added 6/12/2000 by David Etlinger. Edited by AKP 3-6-03 +# ^function round +# ^uses Round sub round { my $input = shift; my $out = Round($input); @@ -90,6 +98,8 @@ } # Round contributed bt Mark Schmitt 3-6-03 +# ^function Round +# ^uses Round sub Round { if (@_ == 1) { $_[0] > 0 ? int $_[0] + 0.5 : int $_[0] - 0.5} elsif (@_ == 2) { $_[0] > 0 ? Round($_[0]*10**$_[1])/10**$_[1] :Round($_[0]*10**$_[1])/10**$_[1]} @@ -97,6 +107,7 @@ #least common multiple #VS 6/29/2000 +# ^function lcm sub lcm { my $a = shift; my $b = shift; @@ -124,7 +135,7 @@ # greatest common factor # takes in two scalar values and uses the Euclidean Algorithm to return the gcf #VS 6/29/2000 - +# ^function gcf sub gcf { my $a = abs(shift); # absolute values because this will yield the same gcd, my $b = abs(shift); # but allows use of the mod operation @@ -164,12 +175,15 @@ #greatest common factor. #same as gcf, but both names are sufficiently common names +# ^function gcd +# ^uses gcf sub gcd { return gcf($_[0], $_[1]); } #returns 1 for a prime number, else 0 #VS 6/30/2000 +# ^function isPrime sub isPrime { my $num = shift; return 1 if ($num == 2 or $num == 3); @@ -180,6 +194,8 @@ #reduces a fraction, returning an array containing ($numerator, $denominator) #VS 7/10/2000 +# ^function reduce +# ^uses gcd sub reduce { my $num = shift; @@ -203,6 +219,7 @@ # Usage: preformat($scalar, "quoted string"); # Example: preformat(-1, "\pi") returns "-\pi" # VS 8/1/2000 - slight adaption of code from T. Shemanske of Dartmouth College +# ^function preformat sub preformat { my $num = shift; my $obj = shift; @@ -217,7 +234,8 @@ } #factorial - +# ^function fact +# ^uses P sub fact { P($_[0], $_[0]); } Index: IO.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/IO.pl,v retrieving revision 1.8 retrieving revision 1.9 diff -Lmacros/IO.pl -Lmacros/IO.pl -u -r1.8 -r1.9 --- macros/IO.pl +++ macros/IO.pl @@ -24,7 +24,10 @@ =cut +# ^function _IO_init sub _IO_init {} + +# ^function _IO_export sub _IO_export { return ( '&send_mail_to', @@ -46,6 +49,12 @@ =cut # send_mail_to($user_address,'subject'=>$subject,'body'=>$body) +# ^function send_mail_to +# ^uses $envir{mailSmtpServer} +# ^uses $envir{mailSmtpSender} +# ^uses $REMOTE_HOST +# ^uses $REMOTE_ADDR +# ^uses Net::SMTP::new sub send_mail_to { my $user_address = shift; # user must be an instructor my %options = @_; @@ -111,6 +120,8 @@ =cut +# ^function getCourseTempDirectory +# ^user $envir{tempDirectory} sub getCourseTempDirectory { return $envir{tempDirectory}; } @@ -130,6 +141,9 @@ # A very useful macro for making sure that all of the directories to a file have been constructed. +# ^function surePathToTmpFile +# ^uses getCourseTempDirectory +# ^uses createDirectory sub surePathToTmpFile { # constructs intermediate directories if needed beginning at ${Global::htmlDirectory}tmp/ # the input path must be either the full path, or the path relative to this tmp sub directory Index: LinearProgramming.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/LinearProgramming.pl,v retrieving revision 1.2 retrieving revision 1.3 diff -Lmacros/LinearProgramming.pl -Lmacros/LinearProgramming.pl -u -r1.2 -r1.3 --- macros/LinearProgramming.pl +++ macros/LinearProgramming.pl @@ -73,6 +73,7 @@ # perform a pivot operation # lp_pivot([[1,2,3],...,[4,5,6]], row, col, fractionmode) # row and col indecies start at 0 +# ^function lp_pivot sub lp_pivot { my $a_ref = shift; my $row = shift; @@ -125,6 +126,7 @@ # Find pivot column for standard part +# ^function lp_pivot_element sub lp_pivot_element { my $a_ref = shift; my $fracmode = shift; @@ -200,6 +202,10 @@ # lp_solve([[1,2,3],[4,5,6]]) # It returns a triple of the final tableau, a code to say if we # succeeded, and the number of pivots +# ^function lp_solve +# ^uses set_default_options +# ^uses lp_pivot_element +# ^uses lp_pivot sub lp_solve { my $a_ref_orig = shift; my %opts = @_; @@ -251,6 +257,8 @@ # The variable is specified by column number, with 0 for P, 1 for x_1, # and so on +# ^function lp_current_value +# ^uses Fraction::new sub lp_current_value { my $col = shift; my $aref = shift; @@ -300,11 +308,14 @@ =cut # Display a tableau in math mode +# ^function lp_display_mm +# ^uses lp_display sub lp_display_mm { lp_display(@_, force_tex=>1); } # Make a copy of a tableau +# ^function lp_clone sub lp_clone { my $a1_ref = shift; my $a_ref = []; # make a copy to modify @@ -342,6 +353,9 @@ =cut # Display a tableau +# ^function lp_display +# ^uses lp_clone +# ^uses display_matrix sub lp_display { my $a1_ref = shift; my %opts = @_; Index: PGanswermacros.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/PGanswermacros.pl,v retrieving revision 1.66 retrieving revision 1.67 diff -Lmacros/PGanswermacros.pl -Lmacros/PGanswermacros.pl -u -r1.66 -r1.67 --- macros/PGanswermacros.pl +++ macros/PGanswermacros.pl @@ -130,17 +130,33 @@ =cut +# ^uses be_strict BEGIN { be_strict() } # Until we get the PG cacheing business sorted out, we need to use # PG_restricted_eval to get the correct values for some(?) PG environment # variables. We do this once here and place the values in lexicals for later # access. + +# ^variable $BR my $BR; +# ^variable $functLLimitDefault my $functLLimitDefault; +# ^variable $functULimitDefault my $functULimitDefault; +# ^variable $functVarDefault my $functVarDefault; +# ^variable $useBaseTenLog my $useBaseTenLog; + +# ^function _PGanswermacros_init +# ^uses loadMacros +# ^uses PG_restricted_eval +# ^uses $BR +# ^uses $envir{functLLimitDefault} +# ^uses $envir{functULimitDefault} +# ^uses $envir{functVarDefault} +# ^uses $envir{useBaseTenLog} sub _PGanswermacros_init { loadMacros('PGnumericevaluators.pl'); # even if these files are already loaded they need to be initialized. loadMacros('PGfunctionevaluators.pl'); @@ -152,7 +168,6 @@ $functULimitDefault = PG_restricted_eval(q/$envir{functULimitDefault}/); $functVarDefault = PG_restricted_eval(q/$envir{functVarDefault}/); $useBaseTenLog = PG_restricted_eval(q/$envir{useBaseTenLog}/); - } =head1 MACROS @@ -190,6 +205,8 @@ ## one or more variable names -- (var1, var2) ## OUT: an array of variable names +# ^function get_var_array +# ^uses $functVarDefault sub get_var_array { my $in = shift @_; my @out; @@ -237,6 +254,9 @@ ## an array of limits -- (llim,ulim) ## OUT: an array of array references -- ([llim,ulim], [llim,ulim]) or ([llim,ulim]) +# ^function get_limits_array +# ^uses $functLLimitDefault +# ^uses $functULimitDefault sub get_limits_array { my $in = shift @_; my @out; @@ -281,6 +301,7 @@ # simple subroutine to display an error message when # function compares are called with invalid parameters +# ^function function_invalid_params sub function_invalid_params { my $correctEqn = shift @_; my $error_response = sub { @@ -291,6 +312,7 @@ return $error_response; } +# ^function clean_up_error_msg sub clean_up_error_msg { my $msg = $_[0]; $msg =~ s/^\[[^\]]*\][^:]*://; @@ -306,6 +328,8 @@ #format must be of a form suitable for sprintf (e.g. '%0.5g'), #with the exception that a '#' at the end of the string #will cause trailing zeros in the decimal part to be removed +# ^function prfmt +# ^uses is_a_number sub prfmt { my($number,$format) = @_; # attention, the order of format and number are reversed my $out; @@ -386,7 +410,11 @@ =cut - +# ^function compare_numbers +# ^uses PG_answer_eval +# ^uses clean_up_error_msg +# ^uses prfmt +# ^uses is_a_number sub compare_numbers { my ($rh_ans, %options) = @_; my ($inVal,$PG_eval_errors,$PG_full_error_report) = PG_answer_eval($rh_ans->{student_ans}); @@ -430,6 +458,10 @@ =cut +# ^function std_num_filter +# ^uses math_constants +# ^uses PG_answer_eval +# ^uses clean_up_error_msg sub std_num_filter { my $rh_ans = shift; my %options = @_; @@ -464,6 +496,11 @@ =cut +# ^function std_num_array_filter +# ^uses set_default_options +# ^uses AnswerHash::new +# ^uses check_syntax +# ^uses std_num_filter sub std_num_array_filter { my $rh_ans= shift; my %options = @_; @@ -506,6 +543,13 @@ =cut +# ^function function_from_string2 +# ^uses assign_option_aliases +# ^uses set_default_options +# ^uses math_constants +# ^uses PG_restricted_eval +# ^uses PG_answer_eval +# ^uses clean_up_error_msg sub function_from_string2 { my $rh_ans = shift; my %options = @_; @@ -594,7 +638,8 @@ =cut - +# ^function is_zero_array +# ^uses is_a_number sub is_zero_array { my $rh_ans = shift; my %options = @_; @@ -678,6 +723,11 @@ # ) # # returns a list of coefficients +# ^function best_approx_parameters +# ^uses set_default_options +# ^uses pretty_print +# ^uses Matrix::new +# ^uses is_a_number sub best_approx_parameters { my $rh_ans = shift; my %options = @_; @@ -822,6 +872,9 @@ =cut +# ^function calculate_difference_vector +# ^uses assign_option_aliases +# ^uses set_default_options sub calculate_difference_vector { my $rh_ans = shift; my %options = @_; @@ -910,6 +963,10 @@ =cut +# ^function fix_answers_for_display +# ^uses evaluatesToNumber +# ^uses AnswerHash::new +# ^uses check_syntax sub fix_answers_for_display { my ($rh_ans, %options) = @_; if ( $rh_ans->{answerIsString} ==1) { @@ -934,6 +991,10 @@ =cut +# ^function evaluatesToNumber +# ^uses is_a_numeric_expression +# ^uses PG_answer_eval +# ^uses prfmt sub evaluatesToNumber { my ($rh_ans, %options) = @_; if (is_a_numeric_expression($rh_ans->{student_ans})) { @@ -952,6 +1013,8 @@ =cut +# ^function is_a_numeric_expression +# ^uses PG_answer_eval sub is_a_numeric_expression { my $testString = shift; my $is_a_numeric_expression = 0; @@ -968,6 +1031,7 @@ =cut +# ^function is_a_number sub is_a_number { my ($num,%options) = @_; my $process_ans_hash = ( ref( $num ) eq 'AnswerHash' ) ? 1 : 0 ; @@ -1005,6 +1069,7 @@ =cut +# ^function is_a_fraction sub is_a_fraction { my ($num,%options) = @_; my $process_ans_hash = ( ref( $num ) eq 'AnswerHash' ) ? 1 : 0 ; @@ -1043,6 +1108,7 @@ pi, which for the tangent function, were equivalent values. This method allows for this. =cut +# ^function phase_pi sub phase_pi { my ($num,%options) = @_; my $process_ans_hash = ( ref( $num ) eq 'AnswerHash' ) ? 1 : 0 ; @@ -1064,6 +1130,7 @@ =cut +# ^function is_an_arithmetic_expression sub is_an_arithmetic_expression { my ($num,%options) = @_; my $process_ans_hash = ( ref( $num ) eq 'AnswerHash' ) ? 1 : 0 ; @@ -1107,6 +1174,7 @@ =cut +# ^function math_constants sub math_constants { my($in,%options) = @_; my $rh_ans; @@ -1141,6 +1209,7 @@ =cut +# ^function is_array sub is_array { my $rh_ans = shift; # return if the result is an array @@ -1162,6 +1231,10 @@ =cut +# ^function check_syntax +# ^uses assign_option_aliases +# ^uses set_default_options +# ^uses AlgParserWithImplicitExpand::new sub check_syntax { my $rh_ans = shift; my %options = @_; @@ -1212,6 +1285,9 @@ =cut +# ^function check_strings +# ^uses str_filters +# ^uses str_cmp sub check_strings { my ($rh_ans, %options) = @_; @@ -1285,6 +1361,11 @@ =cut +# ^function check_units +# ^uses str_filters +# ^uses Units::evaluate_units +# ^uses clean_up_error_msg +# ^uses prfmt sub check_units { my ($rh_ans, %options) = @_; my %correct_units = %{$rh_ans-> {rh_correct_units}}; @@ -1373,7 +1454,7 @@ =cut - +# ^function assign_option_aliases sub assign_option_aliases { my $rh_options = shift; warn "The first entry to set_default_options must be a reference to the option hash" unless ref($rh_options) eq 'HASH'; @@ -1425,6 +1506,8 @@ =cut +# ^function set_default_options +# ^uses pretty_print sub set_default_options { my $rh_options = shift; warn "The first entry to set_default_options must be a reference to the option hash" unless ref($rh_options) eq 'HASH'; @@ -1451,6 +1534,9 @@ ##################################### # This is a model for plug-in problem graders ##################################### +# ^function install_problem_grader +# ^uses PG_restricted_eval +# ^uses %PG_FLAGS{PROBLEM_GRADER_TO_USE} sub install_problem_grader { my $rf_problem_grader = shift; my $rh_flags = PG_restricted_eval(q!\\%main::PG_FLAGS!); @@ -1469,6 +1555,7 @@ =cut +# ^function std_problem_grader sub std_problem_grader { my $rh_evaluated_answers = shift; my $rh_problem_state = shift; @@ -1568,6 +1655,7 @@ +# ^function std_problem_grader2 sub std_problem_grader2 { my $rh_evaluated_answers = shift; my $rh_problem_state = shift; @@ -1665,7 +1753,7 @@ =cut - +# ^function avg_problem_grader sub avg_problem_grader { my $rh_evaluated_answers = shift; my $rh_problem_state = shift; @@ -1739,6 +1827,9 @@ =cut +# ^function pretty_print +# ^uses lex_sort +# ^uses pretty_print sub pretty_print { my $r_input = shift; my $out = ''; @@ -1768,6 +1859,4 @@ $out; } - - 1; Index: MathObjects.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/MathObjects.pl,v retrieving revision 1.8 retrieving revision 1.9 diff -Lmacros/MathObjects.pl -Lmacros/MathObjects.pl -u -r1.8 -r1.9 --- macros/MathObjects.pl +++ macros/MathObjects.pl @@ -32,6 +32,7 @@ =cut +# ^uses loadMacros loadMacros("Parser.pl"); 1; Index: PGasu.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/PGasu.pl,v retrieving revision 1.7 retrieving revision 1.8 diff -Lmacros/PGasu.pl -Lmacros/PGasu.pl -u -r1.7 -r1.8 --- macros/PGasu.pl +++ macros/PGasu.pl @@ -30,6 +30,9 @@ =cut +# ^function auto_right +# ^uses AnswerEvaluator::new +# ^uses auto_right_checker sub auto_right { my $cmt = shift; my %params = @_; @@ -48,6 +51,7 @@ # used in auto_right above +# ^function auto_right_checker sub auto_right_checker { my $ans = shift; $ans->score(1); @@ -68,7 +72,10 @@ =cut - +# ^function no_decs +# ^uses must_have_filter +# ^uses raw_student_answer_filter +# ^uses catch_errors_filter sub no_decs { my ($old_evaluator) = @_; @@ -89,6 +96,10 @@ =cut +# ^function must_include +# ^uses must_have_filter +# ^uses raw_student_answer_filter +# ^uses catch_errors_filter sub must_include { my ($old_evaluator) = shift; my $muststr = shift; @@ -109,6 +120,10 @@ =cut +# ^function no_trig_fun +# ^uses fun_cmp +# ^uses must_have_filter +# ^uses catch_errors_filter sub no_trig_fun { my ($ans) = shift; my $new_eval = fun_cmp($ans); @@ -130,6 +145,10 @@ =cut +# ^function no_trig +# ^uses num_cmp +# ^uses must_have_filter +# ^uses catch_errors_filter sub no_trig { my ($ans) = shift; my $new_eval = num_cmp($ans); @@ -151,6 +170,10 @@ =cut +# ^function exact_no_trig +# ^uses num_cmp +# ^uses no_decs +# ^uses must_have_filter sub exact_no_trig { my ($ans) = shift; my $old_eval = num_cmp($ans); @@ -186,6 +209,7 @@ # First argument is the string to have, or not have # Second argument is optional, and tells us whether yes or no # Third argument is the error message to produce (if any). +# ^function must_have_filter sub must_have_filter { my $str = shift; my $yesno = shift; @@ -241,6 +265,7 @@ =cut +# ^function catch_errors_filter sub catch_errors_filter { my ($rh_ans) = shift; if ($rh_ans->catch_error('SYNTAX') ) { @@ -260,7 +285,7 @@ =cut - +# ^function raw_student_answer_filter sub raw_student_answer_filter { my ($rh_ans) = shift; # warn "answer was ".$rh_ans->{student_ans}; @@ -277,7 +302,8 @@ =cut - +# ^function no_decimal_list +# ^uses number_list_cmp sub no_decimal_list { my ($ans) = shift; my (%jopts) = @_; @@ -311,7 +337,8 @@ =cut - +# ^function no_decimals +# ^uses std_num_cmp sub no_decimals { my ($ans) = shift; my (%jopts) = @_; @@ -347,7 +374,7 @@ # Wrapper for an answer evaluator which can also supply comments - +# ^function with_comments sub with_comments { my ($old_evaluator, $cmt) = @_; @@ -394,7 +421,7 @@ # [answer_evaluator, partial credit factor, comment] # it applies evaluators from the list until it hits one with positive credit, # weights it by the partial credit factor, and throws in its comment - +# ^function pc_evaluator sub pc_evaluator { my @ev_list; if(ref($_[0]) ne 'ARRAY') { @@ -451,6 +478,9 @@ =cut +# ^function weighted_partial_grader +# ^uses $ENV{grader_message} +# ^uses $ENV{partial_weights} sub weighted_partial_grader { my $rh_evaluated_answers = shift; my $rh_problem_state = shift; Index: Parser.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/Parser.pl,v retrieving revision 1.14 retrieving revision 1.15 diff -Lmacros/Parser.pl -Lmacros/Parser.pl -u -r1.14 -r1.15 --- macros/Parser.pl +++ macros/Parser.pl @@ -25,6 +25,8 @@ ## Set up the functions needed by the Parser. ## +# ^uses $Parser::installed +# ^uses $Value::installed if (!$Parser::installed) { die "\n************************************************************\n" . "* This problem requires the Parser.pm package, which doesn't\n". @@ -40,6 +42,7 @@ "************************************************************\n\n" } +# ^uses loadMacros loadMacros("Value.pl"); loadMacros("PGcommonFunctions.pl"); @@ -54,6 +57,8 @@ =cut +# ^function Formula +# ^uses Value::Package sub Formula {Value->Package("Formula()")->new(@_)} =head2 Compute @@ -79,6 +84,8 @@ =cut +# ^function Compute +# ^uses Formula sub Compute { my $string = shift; my $formula = Formula($string); @@ -105,8 +112,13 @@ =cut +# ^function Context +# ^uses Parser::Context::current +# ^uses %context sub Context {Parser::Context->current(\%context,@_)} +# ^variable %context %context = (); # Locally defined contexts, including 'current' context +# ^uses Context Context(); # Initialize context (for persistent mod_perl) ########################################################################### @@ -114,27 +126,64 @@ # stubs for trigonometric functions # +# ^package Ignore package Ignore; ## let PGauxiliaryFunctions.pl do these +# ^#function sin +# ^#uses Parser::Function::call #sub sin {Parser::Function->call('sin',@_)} # Let overload handle it +# ^#function cos +# ^#uses Parser::Function::call #sub cos {Parser::Function->call('cos',@_)} # Let overload handle it +# ^function tan +# ^uses Parser::Function::call sub tan {Parser::Function->call('tan',@_)} +# ^function sec +# ^uses Parser::Function::call sub sec {Parser::Function->call('sec',@_)} +# ^function csc +# ^uses Parser::Function::call sub csc {Parser::Function->call('csc',@_)} +# ^function cot +# ^uses Parser::Function::call sub cot {Parser::Function->call('cot',@_)} +# ^function asin +# ^uses Parser::Function::call sub asin {Parser::Function->call('asin',@_)} +# ^function acos +# ^uses Parser::Function::call sub acos {Parser::Function->call('acos',@_)} +# ^function atan +# ^uses Parser::Function::call sub atan {Parser::Function->call('atan',@_)} +# ^function asec +# ^uses Parser::Function::call sub asec {Parser::Function->call('asec',@_)} +# ^function acsc +# ^uses Parser::Function::call sub acsc {Parser::Function->call('acsc',@_)} +# ^function acot +# ^uses Parser::Function::call sub acot {Parser::Function->call('acot',@_)} +# ^function arcsin +# ^uses Parser::Function::call sub arcsin {Parser::Function->call('asin',@_)} +# ^function arccos +# ^uses Parser::Function::call sub arccos {Parser::Function->call('acos',@_)} +# ^function arctan +# ^uses Parser::Function::call sub arctan {Parser::Function->call('atan',@_)} +# ^function arcsec +# ^uses Parser::Function::call sub arcsec {Parser::Function->call('asec',@_)} +# ^function arccsc +# ^uses Parser::Function::call sub arccsc {Parser::Function->call('acsc',@_)} +# ^function arccot +# ^uses Parser::Function::call sub arccot {Parser::Function->call('acot',@_)} ########################################################################### @@ -142,25 +191,61 @@ # stubs for hyperbolic functions # +# ^function sinh +# ^uses Parser::Function::call sub sinh {Parser::Function->call('sinh',@_)} +# ^function cosh +# ^uses Parser::Function::call sub cosh {Parser::Function->call('cosh',@_)} +# ^function tanh +# ^uses Parser::Function::call sub tanh {Parser::Function->call('tanh',@_)} +# ^function sech +# ^uses Parser::Function::call sub sech {Parser::Function->call('sech',@_)} +# ^function csch +# ^uses Parser::Function::call sub csch {Parser::Function->call('csch',@_)} +# ^function coth +# ^uses Parser::Function::call sub coth {Parser::Function->call('coth',@_)} +# ^function asinh +# ^uses Parser::Function::call sub asinh {Parser::Function->call('asinh',@_)} +# ^function acosh +# ^uses Parser::Function::call sub acosh {Parser::Function->call('acosh',@_)} +# ^function atanh +# ^uses Parser::Function::call sub atanh {Parser::Function->call('atanh',@_)} +# ^function asech +# ^uses Parser::Function::call sub asech {Parser::Function->call('asech',@_)} +# ^function acsch +# ^uses Parser::Function::call sub acsch {Parser::Function->call('acsch',@_)} +# ^function acoth +# ^uses Parser::Function::call sub acoth {Parser::Function->call('acoth',@_)} +# ^function arcsinh +# ^uses Parser::Function::call sub arcsinh {Parser::Function->call('asinh',@_)} +# ^function arccosh +# ^uses Parser::Function::call sub arccosh {Parser::Function->call('acosh',@_)} +# ^function arctanh +# ^uses Parser::Function::call sub arctanh {Parser::Function->call('atanh',@_)} +# ^function arcsech +# ^uses Parser::Function::call sub arcsech {Parser::Function->call('asech',@_)} +# ^function arccsch +# ^uses Parser::Function::call sub arccsch {Parser::Function->call('acsch',@_)} +# ^function arccoth +# ^uses Parser::Function::call sub arccoth {Parser::Function->call('acoth',@_)} ########################################################################### @@ -168,20 +253,43 @@ # stubs for numeric functions # +# ^#function log +# ^#uses Parser::Function::call #sub log {Parser::Function->call('log',@_)} # Let overload handle it +# ^function log10 +# ^uses Parser::Function::call sub log10 {Parser::Function->call('log10',@_)} +# ^#function exp +# ^#uses Parser::Function::call #sub exp {Parser::Function->call('exp',@_)} # Let overload handle it +# ^#function sqrt +# ^#uses Parser::Function::call #sub sqrt {Parser::Function->call('sqrt',@_)} # Let overload handle it +# ^#function abs +# ^#uses Parser::Function::call #sub abs {Parser::Function->call('abs',@_)} # Let overload handle it +# ^function int +# ^uses Parser::Function::call sub int {Parser::Function->call('int',@_)} +# ^function sgn +# ^uses Parser::Function::call sub sgn {Parser::Function->call('sgn',@_)} +# ^function ln +# ^uses Parser::Function::call sub ln {Parser::Function->call('log',@_)} +# ^function logten +# ^uses Parser::Function::call sub logten {Parser::Function->call('log10',@_)} +# ^package main package main; ## back to main +# ^function log10 +# ^uses Parser::Function::call sub log10 {Parser::Function->call('log10',@_)} +# ^function Factorial +# ^uses Parser::UOP::factorial::call sub Factorial {Parser::UOP::factorial->call(@_)} ########################################################################### @@ -189,6 +297,8 @@ # stubs for special functions # +# ^#function atan2 +# ^#usesParser::Function::call #sub atan2 {Parser::Function->call('atan2',@_)} # Let overload handle it ########################################################################### @@ -196,10 +306,20 @@ # stubs for numeric functions # +# ^function arg +# ^uses Parser::Function::call sub arg {Parser::Function->call('arg',@_)} +# ^function mod +# ^uses Parser::Function::call sub mod {Parser::Function->call('mod',@_)} +# ^function Re +# ^uses Parser::Function::call sub Re {Parser::Function->call('Re',@_)} +# ^function Im +# ^uses Parser::Function::call sub Im {Parser::Function->call('Im',@_)} +# ^function conj +# ^uses Parser::Function::call sub conj {Parser::Function->call('conj',@_)} ########################################################################### @@ -207,7 +327,11 @@ # stubs for vector functions # +# ^function norm +# ^uses Parser::Function::call sub norm {Parser::Function->call('norm',@_)} +# ^function unit +# ^uses Parser::Function::call sub unit {Parser::Function->call('unit',@_)} # @@ -219,10 +343,13 @@ ########################################################################### +# ^variable $_parser_loaded $_parser_loaded = 1; # use this to tell if Parser.pl is loaded +# ^function _Parser_init sub _Parser_init {}; # don't let loadMacros load it again +# ^uses loadMacros loadMacros("parserCustomization.pl"); ########################################################################### Index: dangerousMacros.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/dangerousMacros.pl,v retrieving revision 1.50 retrieving revision 1.51 diff -Lmacros/dangerousMacros.pl -Lmacros/dangerousMacros.pl -u -r1.50 -r1.51 --- macros/dangerousMacros.pl +++ macros/dangerousMacros.pl @@ -97,19 +97,37 @@ } +# ^variable $debugON my $debugON = 0; # grab read only variables from the current safe compartment +# ^variable $macrosPath my ($macrosPath, + # ^variable $pwd $pwd, + # ^variable $appletPath $appletPath, + # ^variable $server_root_url $server_root_url, + # ^variable $templateDirectory $templateDirectory, + # ^variable $scriptDirectory $scriptDirectory, + # ^variable $externalTTHPath $externalTTHPath, ); +# ^function _dangerousMacros_init +# ^uses %envir +# ^uses $macrosPath +# ^uses $pwd +# ^uses $appletPath +# ^uses $server_root_url +# ^uses $templateDirectory +# ^uses $scriptDirectory +# ^uses $externalTTHPath +# ^uses $debugON sub _dangerousMacros_init { #use envir instead of local variables? # will allow easy addition of new directories -- is this too liberal? do some pg directories need to be protected? $macrosPath = eval('$main::envir{pgDirectories}{macrosPath}'); @@ -128,6 +146,7 @@ warn eval(q! "dangerousmacros.pl: The envir variable $main::{envir} is".join(" ",%main::envir)!) if $debugON; } +# ^function _dangerousMacros_export sub _dangerousMacros_export { my @EXPORT= ( '&_dangerousMacros_init', @@ -205,7 +224,11 @@ # A kludge using require works around this problem - +# ^function loadMacros +# ^uses time_it +# ^uses $debugON +# ^uses $externalTTHPath +# ^uses findMacroFile sub loadMacros { my @files = @_; my $fileName; @@ -316,6 +339,10 @@ # # Look for a macro file in the directories specified in the macros path # + +# ^function findMacroFile +# ^uses $macrosPath +# ^uses $pwd sub findMacroFile { my $fileName = shift; my $filePath; @@ -326,6 +353,9 @@ } return; # no file found } + +# ^function check_url +# ^uses %envir sub check_url { my $url = shift; return undef if $url =~ /;/; # make sure we can't get a second command in the url @@ -339,8 +369,13 @@ return ($response) ? 0 : 1; # 0 indicates success, 256 is failure possibly more checks can be made } - +# ^variable %appletCodebaseLocations our %appletCodebaseLocations = (); +# ^function findAppletCodebase +# ^uses %appletCodebaseLocations +# ^uses $appletPath +# ^uses $server_root_url +# ^uses check_url sub findAppletCodebase { my $fileName = shift; # probably the name of a jar file return $appletCodebaseLocations{$fileName} #check cache first @@ -360,6 +395,10 @@ return "Error: $fileName not found at ". join(", ", @{$appletPath} ); # no file found } # errors in compiling macros is not always being reported. +# ^function compile_file +# ^uses @__eval__ +# ^uses PG_restricted_eval +# ^uses $__files__ sub compile_file { my $filePath = shift; warn "loading $filePath" if $debugON; @@ -402,14 +441,14 @@ =cut -# Global variables used: -# $main::tmp_file_permission, -# $main::numericalGroupID - -#Global macros used: -# &convertPath -# &surePathToTmpFile - +# ^function insertGraph +# ^uses $WWPlot::use_png +# ^uses convertPath +# ^uses surePathToTmpFile +# ^uses PG_restricted_eval +# ^uses $refreshCachedImages +# ^uses $templateDirectory +# ^uses %envir sub insertGraph { # Convert the image to GIF and print it on standard output my $graph = shift; @@ -462,20 +501,21 @@ =cut -# This file allows the tth display. -# Global variables: -# ${main::templateDirectory}tthPreamble.tex # location of any preamble TeX commands for tth -# ${main::templateDirectory} -# ${main::scriptDirectory}tth # path to tth application -# Global macros: -# None - # the contents of this file will not change during problem compilation it # only needs to be read once. however, the contents of the file may change, # and indeed the file refered to may change, between rendering passes. thus, # we need to keep track of the file name and the mtime as well. +# ^variable $tthPreambleFile +# ^variable $tthPreambleMtime +# ^variable $tthPreambleContents my ($tthPreambleFile, $tthPreambleMtime, $tthPreambleContents); +# ^function tth +# ^uses $templateDirectory +# ^uses $envir{externalTTHPath} +# ^uses $tthPreambleFile +# ^uses $tthPreambleMtime +# ^uses $tthPreambleContents sub tth { my $inputString = shift; @@ -538,6 +578,7 @@ } # possible solution to the tth font problem? Works only for iCab. +# ^function symbolConvert sub symbolConvert { my $string = shift; $string =~ s/\x5C/\\/g; #\ 92 \ @@ -576,8 +617,21 @@ =cut +# ^variable $math2imgCount my $math2imgCount = 0; +# ^function math2img +# ^uses $math2imgCount +# ^uses $envir{templateDirectory} +# ^uses $envir{fileName} +# ^uses $envir{studentLogin} +# ^uses $envir{setNumber} +# ^uses $envir{probNum} +# ^uses $envir{tempURL} +# ^uses $envir{refreshMath2img} +# ^uses $envir{dvipngTempDir} +# ^uses $envir{externalLaTeXPath} +# ^uses $envir{externalDvipngPath} sub math2img { my $tex = shift; my $mode = shift; @@ -624,6 +678,7 @@ =cut # copied from IO.pm for backward compatibility with WeBWorK1.8; +# ^function dvipng sub dvipng($$$$$) { my ( $wd, # working directory, for latex and dvipng garbage @@ -819,32 +874,28 @@ # Alias does not do any garbage collection, so files and alias may accumulate and # need to be removed manually or by a reaper daemon. - -# Global variables used: -# $main::fileName # the full path to the current problem template file -# $main::htmlDirectory -# $main::htmlURL -# $main::tempDirectory -# $main::tempURL -# $main::studentLogin -# $main::psvnNumber -# $main::setNumber -# $main::probNum -# $main::displayMode - -# Global macros used -# gif2eps An external file called by system -# surePathToTmpFile -# convertPath -# directoryFromPath - - # This subroutine has commands which will not work on non-UNIX environments. # system("cat $gifSourceFile | /usr/math/bin/giftopnm | /usr/math/bin/pnmdepth 1 | /usr/math/bin/pnmtops -noturn>$adr_output") && - -# local constants $User, $psvn $setNumber $probNum $displayMode - +# ^function alias +# ^uses %envir +# ^uses $envir{fileName} +# ^uses $envir{htmlDirectory} +# ^uses $envir{htmlURL} +# ^uses $envir{tempDirectory} +# ^uses $envir{tempURL} +# ^uses $envir{studentLogin} +# ^uses $envir{psvnNumber} +# ^uses $envir{setNumber} +# ^uses $envir{probNum} +# ^uses $envir{displayMode} +# ^uses $envir{externalGif2EpsPath} +# ^uses $envir{externalPng2EpsPath} +# ^uses &surePathToTmpFile +# ^uses &convertPath +# ^uses &directoryFromPath +# ^uses &fileFromPath +# ^uses $envir{texDisposition} sub alias { # input is a path to the original auxiliary file my $envir = eval(q!\%main::envir!); # get the current root environment @@ -1241,6 +1292,15 @@ =cut +# ^function sourceAlias +# ^uses PG_restricted_eval +# ^uses %envir +# ^uses $envir{inputs_ref} +# ^uses $envir{psvn} +# ^uses $envir{probNum} +# ^uses $envir{displayMode} +# ^uses $envir{courseName} +# ^uses $envir{sessionKey} sub sourceAlias { my $path_to_file = shift; my $envir = PG_restricted_eval(q!\%main::envir!); @@ -1262,24 +1322,38 @@ # Some constants that can be used in perl experssions # +# ^function i +# ^uses $_parser_loaded +# ^uses &Complex::i +# ^uses &Value::Package sub i () { # check if Parser.pl is loaded, otherwise use Complex package if (!eval(q!$main::_parser_loaded!)) {return Complex::i} return Value->Package("Formula")->new('i')->eval; } +# ^function j +# ^uses $_parser_loaded +# ^uses &Value::Package sub j () { if (!eval(q!$main::_parser_loaded!)) {return 'j'} Value->Package("Formula")->new('j')->eval; } +# ^function k +# ^uses $_parser_loaded +# ^uses &Value::Package sub k () { if (!eval(q!$main::_parser_loaded!)) {return 'k'} Value->Package("Formula")->new('k')->eval; } +# ^function pi +# ^uses &Value::Package sub pi () {Value->Package("Formula")->new('pi')->eval} +# ^function Infinity +# ^uses &Value::Package sub Infinity () {Value->Package("Infinity")->new()} 1; Index: PG.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/PG.pl,v retrieving revision 1.35 retrieving revision 1.36 diff -Lmacros/PG.pl -Lmacros/PG.pl -u -r1.35 -r1.36 --- macros/PG.pl +++ macros/PG.pl @@ -107,8 +107,18 @@ # Private variables for the PG.pl file. -my ($STRINGforOUTPUT, $STRINGforHEADER_TEXT, @PG_ANSWERS, @PG_UNLABELED_ANSWERS); -my %PG_ANSWERS_HASH ; +# ^variable $STRINGforOUTPUT +my $STRINGforOUTPUT; +# ^variable $STRINGforHEADER_TEXT +my $STRINGforHEADER_TEXT; +# ^variable @PG_ANSWERS +my @PG_ANSWERS; +# ^variable @PG_UNLABELED_ANSWERS +my @PG_UNLABELED_ANSWERS; +# ^variable %PG_ANSWERS_HASH +my %PG_ANSWERS_HASH; + +# ^variable $PG_STOP_FLAG our $PG_STOP_FLAG; # my variables are unreliable if two DOCUMENTS were to be called before an ENDDOCUMENT @@ -143,6 +153,32 @@ =cut +# ^function DOCUMENT +# ^uses $STRINGforOUTPUT +# ^uses $STRINGforHEADER_TEXT +# ^uses @PG_ANSWERS +# ^uses $PG_STOP_FLAG +# ^uses @PG_UNLABELED_ANSWERS +# ^uses %PG_ANSWERS_HASH +# ^uses @PG_ANSWER_ENTRY_ORDER +# ^uses $ANSWER_PREFIX +# ^uses %PG_FLAGS +# ^uses $showPartialCorrectAnswers +# ^uses $showHints +# ^uses $solutionExists +# ^uses $hintExists +# ^uses $pgComment +# ^uses %gifs_created +# ^uses %envir +# ^uses $refSubmittedAnswers +# ^uses @submittedAnswers +# ^uses $PG_original_problemSeed +# ^uses $problemSeed +# ^uses $PG_random_generator +# ^uses $ans_rule_count +# ^uses $QUIZ_PREFIX +# (Also creates a package scalar named after each key in %envir containing a copy of the corresponding value.) +# ^uses &PGrandom::new sub DOCUMENT { $STRINGforOUTPUT =""; @@ -262,6 +298,8 @@ =cut +# ^function HEADER_TEXT +# ^uses $STRINGforHEADER_TEXT sub HEADER_TEXT { my @in = @_; $STRINGforHEADER_TEXT .= join(" ",@in); @@ -290,6 +328,9 @@ =cut +# ^function TEXT +# ^uses $PG_STOP_FLAG +# ^uses $STRINGforOUTPUT sub TEXT { return "" if $PG_STOP_FLAG; my @in = @_; @@ -313,6 +354,9 @@ =cut +# ^function ANS +# ^uses $PG_STOP_FLAG +# ^uses @PG_ANSWERS sub ANS{ return "" if $PG_STOP_FLAG; my @in = @_; @@ -336,6 +380,8 @@ =cut +# ^function LABELED_ANS +# ^uses &NAMED_ANS sub LABELED_ANS { &NAMED_ANS; } @@ -346,6 +392,8 @@ =cut +# ^function NAMED_ANS +# ^uses $PG_STOP_FLAG sub NAMED_ANS{ return "" if $PG_STOP_FLAG; my @in = @_; @@ -369,6 +417,8 @@ =cut +# ^function STOP_RENDERING +# ^uses $PG_STOP_FLAG sub STOP_RENDERING { $PG_STOP_FLAG=1; ""; @@ -383,6 +433,8 @@ =cut +# ^function RESUME_RENDERING +# ^uses $PG_STOP_FLAG sub RESUME_RENDERING { $PG_STOP_FLAG=0; ""; @@ -484,6 +536,10 @@ =cut +# ^function ENDDOCUMENT +# ^uses @PG_UNLABELED_ANSWERS +# ^uses %PG_ANSWERS_HASH +# ^uses @PG_ANSWERS sub ENDDOCUMENT { my $index=0; @@ -579,6 +635,8 @@ =cut +# ^function inc_ans_rule_count +# ^uses $ans_rule_count sub inc_ans_rule_count { eval(q!++$main::ans_rule_count!); # evalute at runtime to get correct main:: } @@ -592,6 +650,9 @@ =cut +# ^function RECORD_ANS_NAME +# ^uses $PG_STOP_FLAG +# ^uses @PG_ANSWER_ENTRY_ORDER sub RECORD_ANS_NAME { return "" if $PG_STOP_FLAG; my $label = shift; @@ -609,6 +670,11 @@ =cut +# ^function NEW_ANS_NAME +# ^uses $PG_STOP_FLAG +# ^uses $QUIZ_PREFIX +# ^uses $ANSWER_PREFIX +# ^uses @PG_UNLABELED_ANSWERS sub NEW_ANS_NAME { return "" if $PG_STOP_FLAG; my $number=shift; @@ -631,6 +697,9 @@ =cut +# ^function ANS_NUM_TO_NAME +# ^uses $QUIZ_PREFIX +# ^uses $ANSWER_PREFIX sub ANS_NUM_TO_NAME { my $number=shift; my $label = eval(q!$main::QUIZ_PREFIX.$main::ANSWER_PREFIX!).$number; @@ -648,6 +717,9 @@ =cut +# ^function RECORD_FORM_LABEL +# ^uses $PG_STOP_FLAG +# ^uses @KEPT_EXTRA_ANSWERS sub RECORD_FORM_LABEL { # this stores form data (such as sticky answers), but does nothing more # it's a bit of hack since we are storing these in the KEPT_EXTRA_ANSWERS queue even if they aren't answers per se. return "" if $PG_STOP_FLAG; @@ -665,6 +737,10 @@ =cut +# ^function NEW_ANS_ARRAY_NAME +# ^uses $PG_STOP_FLAG +# ^uses $QUIZ_PREFIX +# ^uses @PG_UNLABELED_ANSWERS sub NEW_ANS_ARRAY_NAME { # this keeps track of the answers which are entered implicitly, # rather than with a specific label return "" if $PG_STOP_FLAG; @@ -687,6 +763,8 @@ =cut +# ^function NEW_ANS_ARRAY_NAME_EXTENSION +# ^uses $PG_STOP_FLAG sub NEW_ANS_ARRAY_NAME_EXTENSION { # this keeps track of the answers which are entered implicitly, # rather than with a specific label return "" if $PG_STOP_FLAG; @@ -714,6 +792,10 @@ =cut +# ^function get_PG_ANSWERS_HASH +# ^uses %PG_ANSWERS_HASH +# ^uses @PG_UNLABELED_ANSWERS +# ^uses @PG_ANSWERS sub get_PG_ANSWERS_HASH { # update the PG_ANSWWERS_HASH, then report the result. # This is used in writing sequential problems @@ -751,6 +833,10 @@ =cut +# ^function includePGproblem +# ^uses %envir +# ^uses &read_whole_problem_file +# ^uses &includePGtext sub includePGproblem { my $filePath = shift; my %save_envir = %main::envir; @@ -783,4 +869,3 @@ =cut 1; - Index: extraAnswerEvaluators.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/extraAnswerEvaluators.pl,v retrieving revision 1.21 retrieving revision 1.22 diff -Lmacros/extraAnswerEvaluators.pl -Lmacros/extraAnswerEvaluators.pl -u -r1.21 -r1.22 --- macros/extraAnswerEvaluators.pl +++ macros/extraAnswerEvaluators.pl @@ -44,11 +44,14 @@ =cut +# ^uses loadMacros loadMacros('MathObjects.pl'); { + # ^package Equation_eval package Equation_eval; + # ^function split_eqn sub split_eqn { my $instring = shift; @@ -58,7 +61,11 @@ #FIXME -- this could be improved so that # 1. it uses an answer evaluator object instead of a sub routine # 2. it provides error messages when previous answers are equivalent - + # ^function equation_cmp + # ^uses AnswerHash::new + # ^uses split_eqn + # ^uses main::check_syntax + # ^uses main::fun_cmp sub equation_cmp { my $right_ans = shift; my %opts = @_; @@ -169,7 +176,15 @@ return $ans_eval; } } +# ^package main +# ^function mode2context +# ^uses Parser::Context::getCopy +# ^uses %context +# ^uses $numZeroLevelTolDefault +# ^uses $numAbsTolDefault +# ^uses $numRelPercentTolDefault +# ^uses $numFormatDefault sub mode2context { my $mode = shift; my %options = @_; @@ -297,6 +312,11 @@ =cut +# ^function interval_cmp +# ^uses Context +# ^uses mode2context +# ^uses List +# ^uses Union sub interval_cmp { my $correct_ans = shift; @@ -434,6 +454,10 @@ =cut +# ^function number_list_cmp +# ^uses Context +# ^uses mode2context +# ^uses List sub number_list_cmp { my $list = shift; @@ -488,6 +512,8 @@ =cut +# ^function equation_cmp +# ^uses Equation_eval::equation_cmp sub equation_cmp { Equation_eval::equation_cmp(@_); } |
From: Sam H. v. a. <we...@ma...> - 2008-04-30 22:23:44
|
Log Message: ----------- backport (dpvc): Fix DOS and Mac line endings, and make the detection of non-text files a little more strict (DOS files were being marked as non-text). Also, localize the file handles. Tags: ---- rel-2-4-dev Modified Files: -------------- webwork2/lib/WeBWorK/ContentGenerator/Instructor: FileManager.pm Revision Data ------------- Index: FileManager.pm =================================================================== RCS file: /webwork/cvs/system/webwork2/lib/WeBWorK/ContentGenerator/Instructor/FileManager.pm,v retrieving revision 1.26.2.3 retrieving revision 1.26.2.4 diff -Llib/WeBWorK/ContentGenerator/Instructor/FileManager.pm -Llib/WeBWorK/ContentGenerator/Instructor/FileManager.pm -u -r1.26.2.3 -r1.26.2.4 --- lib/WeBWorK/ContentGenerator/Instructor/FileManager.pm +++ lib/WeBWorK/ContentGenerator/Instructor/FileManager.pm @@ -472,6 +472,8 @@ my $data = $self->r->param("data"); if (defined($data)) { + $data =~ s/\r\n?/\n/g; # convert DOS and Mac line ends to unix + local (*OUTFILE); if (open(OUTFILE,">$file")) { eval {print OUTFILE $data; close(OUTFILE)}; if ($@) {$self->addbadmessage("Failed to save: $@")} @@ -745,6 +747,7 @@ if ($self->r->param('confirmed')) { my $name = $self->r->param('name'); if (my $file = $self->verifyName($name,"file")) { + local (*NEWFILE); if (open(NEWFILE,">$file")) { close(NEWFILE); $self->RefreshEdit("",$name); @@ -1186,12 +1189,12 @@ ################################################## # # Check if a string is plain text -# (i.e., doesn't contain three non-regular +# (i.e., doesn't contain four non-regular # characters in a row.) # sub isText { my $string = shift; - return $string !~ m/[^\s\x20-\x7E]{3,}/; + return $string !~ m/[^\s\x20-\x7E]{4}/; } ################################################## |
From: Sam H. v. a. <we...@ma...> - 2008-04-29 19:53:42
|
Log Message: ----------- backport (sh002i): widen path field of NPL-path table to 4096 to acommodate longer paths. linux's max path length is 4096. Tags: ---- rel-2-4-dev Modified Files: -------------- webwork2/bin: NPL-update Revision Data ------------- Index: NPL-update =================================================================== RCS file: /webwork/cvs/system/webwork2/bin/NPL-update,v retrieving revision 1.1.2.4 retrieving revision 1.1.2.5 diff -Lbin/NPL-update -Lbin/NPL-update -u -r1.1.2.4 -r1.1.2.5 --- bin/NPL-update +++ bin/NPL-update @@ -59,7 +59,7 @@ '], ['NPL-path', ' path_id int(15) NOT NULL auto_increment, - path varchar(127) NOT NULL, + path varchar(4096) NOT NULL, machine varchar(127), user varchar(127), KEY (path), |
From: Sam H. v. a. <we...@ma...> - 2008-04-29 19:52:22
|
Log Message: ----------- widen path field of NPL-path table to 4096 to acommodate longer paths. linux's max path length is 4096. Modified Files: -------------- webwork2/bin: NPL-update Revision Data ------------- Index: NPL-update =================================================================== RCS file: /webwork/cvs/system/webwork2/bin/NPL-update,v retrieving revision 1.4 retrieving revision 1.5 diff -Lbin/NPL-update -Lbin/NPL-update -u -r1.4 -r1.5 --- bin/NPL-update +++ bin/NPL-update @@ -59,7 +59,7 @@ '], ['NPL-path', ' path_id int(15) NOT NULL auto_increment, - path varchar(127) NOT NULL, + path varchar(4096) NOT NULL, machine varchar(127), user varchar(127), KEY (path), |
From: Sam H. v. a. <we...@ma...> - 2008-04-29 19:47:34
|
Log Message: ----------- backport (sh002i): "Show Hints" and "Show Solutions" checkboxes. Tags: ---- rel-2-4-dev Modified Files: -------------- webwork2/lib/WeBWorK/ContentGenerator/Instructor: SetMaker.pm webwork2/lib/WeBWorK/Utils: Tasks.pm Revision Data ------------- Index: SetMaker.pm =================================================================== RCS file: /webwork/cvs/system/webwork2/lib/WeBWorK/ContentGenerator/Instructor/SetMaker.pm,v retrieving revision 1.77.2.3 retrieving revision 1.77.2.4 diff -Llib/WeBWorK/ContentGenerator/Instructor/SetMaker.pm -Llib/WeBWorK/ContentGenerator/Instructor/SetMaker.pm -u -r1.77.2.3 -r1.77.2.4 --- lib/WeBWorK/ContentGenerator/Instructor/SetMaker.pm +++ lib/WeBWorK/ContentGenerator/Instructor/SetMaker.pm @@ -38,6 +38,8 @@ require WeBWorK::Utils::ListingDB; +use constant SHOW_HINTS_DEFAULT => 0; +use constant SHOW_SOLUTIONS_DEFAULT => 0; use constant MAX_SHOW_DEFAULT => 20; use constant NO_LOCAL_SET_STRING => 'No sets in this course yet'; use constant SELECT_SET_STRING => 'Select a Set from this Course'; @@ -314,6 +316,11 @@ CGI::popup_menu(-name=> 'max_shown', -values=>[5,10,15,20,25,30,50,'All'], -default=> $defaultMax); + # Option of whether to show hints and solutions + my $defaultHints = $r->param('showHints') || SHOW_HINTS_DEFAULT; + $result .= " ".CGI::checkbox(-name=>"showHints",-checked=>$defaultHints,-label=>"Hints"); + my $defaultSolutions = $r->param('showSolutions') || SHOW_SOLUTIONS_DEFAULT; + $result .= " ".CGI::checkbox(-name=>"showSolutions",-checked=>$defaultSolutions,-label=>"Solutions"); return($result); } @@ -1286,6 +1293,9 @@ CGI::em("You are not authorized to access the Instructor tools."))); } + my $showHints = $r->param('showHints'); + my $showSolutions = $r->param('showSolutions'); + ########## Extract information computed in pre_header_initialize my $first_shown = $self->{first_shown}; @@ -1295,11 +1305,17 @@ my @pg_files = @{$self->{pg_files}}; my @all_db_sets = @{$self->{all_db_sets}}; - my @pg_html=($last_shown>=$first_shown) ? - renderProblems(r=> $r, - user => $user, - problem_list => [@pg_files[$first_shown..$last_shown]], - displayMode => $r->param('mydisplayMode')) : (); + my @pg_html; + if ($last_shown >= $first_shown) { + @pg_html = renderProblems( + r=> $r, + user => $user, + problem_list => [@pg_files[$first_shown..$last_shown]], + displayMode => $r->param('mydisplayMode'), + showHints => $showHints, + showSolutions => $showSolutions, + ); + } my %isInSet; my $setName = $r->param("local_sets"); Index: Tasks.pm =================================================================== RCS file: /webwork/cvs/system/webwork2/lib/WeBWorK/Utils/Tasks.pm,v retrieving revision 1.13.6.1 retrieving revision 1.13.6.2 diff -Llib/WeBWorK/Utils/Tasks.pm -Llib/WeBWorK/Utils/Tasks.pm -u -r1.13.6.1 -r1.13.6.2 --- lib/WeBWorK/Utils/Tasks.pm +++ lib/WeBWorK/Utils/Tasks.pm @@ -131,6 +131,8 @@ my $problem_seed = $args{'problem_seed'} || $r->param('problem_seed') || 0; my $displayMode = $args{displayMode} || $r->param("displayMode") || $ce->{pg}->{options}->{displayMode}; + my $showHints = $args{showHints} || 0; + my $showSolutions = $args{showSolutions} || 0; my $problemNumber= $args{'problem_number'} || 1; $ce->{pg}->{specialPGEnvironmentVars}->{problemPreamble} = { TeX=>'', @@ -164,8 +166,8 @@ $formFields, { # translation options displayMode => $displayMode, - showHints => 0, - showSolutions => 0, + showHints => $showHints, + showSolutions => $showSolutions, refreshMath2img => 0, processAnswers => 0, } |
From: Sam H. v. a. <we...@ma...> - 2008-04-29 19:45:54
|
Log Message: ----------- comment re: unused value rh_directories Modified Files: -------------- webwork2/lib/WeBWorK/PG: Local.pm Revision Data ------------- Index: Local.pm =================================================================== RCS file: /webwork/cvs/system/webwork2/lib/WeBWorK/PG/Local.pm,v retrieving revision 1.26 retrieving revision 1.27 diff -Llib/WeBWorK/PG/Local.pm -Llib/WeBWorK/PG/Local.pm -u -r1.26 -r1.27 --- lib/WeBWorK/PG/Local.pm +++ lib/WeBWorK/PG/Local.pm @@ -106,6 +106,7 @@ # set the directory hash #warn "PG: setting the directory hash\n"; + # FIXME rh_directories does not appear to be used. ever. $translator->rh_directories({ macrosPath => $ce->{courseDirs}->{macrosPath}, templateDirectory => $ce->{courseDirs}->{templates}, |
From: Sam H. v. a. <we...@ma...> - 2008-04-29 19:45:08
|
Log Message: ----------- eliminate 'odd number of hash elements' error when showHints or showSolutions are not checked. Modified Files: -------------- webwork2/lib/WeBWorK/ContentGenerator/Instructor: SetMaker.pm Revision Data ------------- Index: SetMaker.pm =================================================================== RCS file: /webwork/cvs/system/webwork2/lib/WeBWorK/ContentGenerator/Instructor/SetMaker.pm,v retrieving revision 1.82 retrieving revision 1.83 diff -Llib/WeBWorK/ContentGenerator/Instructor/SetMaker.pm -Llib/WeBWorK/ContentGenerator/Instructor/SetMaker.pm -u -r1.82 -r1.83 --- lib/WeBWorK/ContentGenerator/Instructor/SetMaker.pm +++ lib/WeBWorK/ContentGenerator/Instructor/SetMaker.pm @@ -1293,6 +1293,9 @@ CGI::em("You are not authorized to access the Instructor tools."))); } + my $showHints = $r->param('showHints'); + my $showSolutions = $r->param('showSolutions'); + ########## Extract information computed in pre_header_initialize my $first_shown = $self->{first_shown}; @@ -1309,8 +1312,8 @@ user => $user, problem_list => [@pg_files[$first_shown..$last_shown]], displayMode => $r->param('mydisplayMode'), - showHints => $r->param('showHints'), - showSolutions => $r->param('showSolutions'), + showHints => $showHints, + showSolutions => $showSolutions, ); } |
From: Sam H. v. a. <we...@ma...> - 2008-04-29 19:44:13
|
Log Message: ----------- added fake_user, cleaned up formatting, expanded functionality of renderProblems Modified Files: -------------- webwork2/lib/WeBWorK/Utils: Tasks.pm Revision Data ------------- Index: Tasks.pm =================================================================== RCS file: /webwork/cvs/system/webwork2/lib/WeBWorK/Utils/Tasks.pm,v retrieving revision 1.15 retrieving revision 1.16 diff -Llib/WeBWorK/Utils/Tasks.pm -Llib/WeBWorK/Utils/Tasks.pm -u -r1.15 -r1.16 --- lib/WeBWorK/Utils/Tasks.pm +++ lib/WeBWorK/Utils/Tasks.pm @@ -18,27 +18,26 @@ =head1 NAME -WeBWorK::Utils::Tasks - utilities for doing single tasks, like - rendering a problem by itself. +WeBWorK::Utils::Tasks - utilities for doing single tasks, like rendering a +problem by itself. =head1 SYNOPSIS - use WeBWorK::Utils::Tasks qw/renderProblems/; - + use WeBWorK::Utils::Tasks qw(renderProblems); =head1 DESCRIPTION -This module provides functions for rendering html from files outside the -normal context of being for a particular user in an existing problem set. +This module provides functions for rendering html from files outside the normal +context of being for a particular user in an existing problem set. -It also provides functions which are useful for taking problems which are -not part of any set and making live versions of them, or loading them into -the editor. +It also provides functions which are useful for taking problems which are not +part of any set and making live versions of them, or loading them into the +editor. =cut -# Ultimately, this may provide functions for turning problems into hardcopy -# or other tasks that can be separated out of specific content managers. +# Ultimately, this may provide functions for turning problems into hardcopy or +# other tasks that can be separated out of specific content managers. use strict; use warnings; @@ -53,142 +52,238 @@ renderProblems fake_set fake_problem + fake_user ); use constant fakeSetName => "Undefined_Set"; +use constant fakeUserName => "Undefined_User"; =head1 FUNCTIONS =over -=item fake_set($db) +=item fake_set + + fake_set($db); Given a database, make a temporary problem set for that database. =cut sub fake_set { - my $db = shift; + my $db = shift; - my $set = $db->newGlobalSet(); - $set = global2user($db->{set_user}->{record}, $set); - $set->psvn(123); - $set->set_id(fakeSetName); - $set->open_date(time()); - $set->due_date(time()); - $set->answer_date(time()); - $set->published(0); - $set->hardcopy_header(""); - return($set); + my $set = $db->newGlobalSet(); + $set = global2user($db->{set_user}->{record}, $set); + $set->psvn(123); + $set->set_id(fakeSetName); + $set->open_date(time()); + $set->due_date(time()); + $set->answer_date(time()); + $set->published(0); + $set->hardcopy_header(""); + return($set); } -=item fake_problem($db) +=item fake_problem + + fake_problem($db); + fake_problem($db, problem_seed=>$seed); -Make a temporary problem for the given database. +Make a temporary problem for the given database. If a problem seed is not +specified, 0 is used. =cut sub fake_problem { - my $db = shift; - my %options = @_; - my $problem = $db->newGlobalProblem(); - $problem = global2user($db->{problem_user}->{record}, $problem); - $problem->set_id(fakeSetName); - $problem->value(""); - $problem->max_attempts("-1"); + my $db = shift; + my %options = @_; + my $problem = $db->newGlobalProblem(); + $problem = global2user($db->{problem_user}->{record}, $problem); + $problem->set_id(fakeSetName); + $problem->value(""); + $problem->max_attempts("-1"); - $problem->problem_seed(0); - $problem->problem_seed($options{'problem_seed'}) - if(defined($options{'problem_seed'})); - - $problem->status(0); - $problem->attempted(0); - $problem->last_answer(""); - $problem->num_correct(0); - $problem->num_incorrect(0); - return($problem); -} + $problem->problem_seed(0); + $problem->problem_seed($options{'problem_seed'}) + if(defined($options{'problem_seed'})); + + $problem->status(0); + $problem->attempted(0); + $problem->last_answer(""); + $problem->num_correct(0); + $problem->num_incorrect(0); + return($problem); +} + +=item fake_user -=item render_problems(r => $r, user => $user, problem_list => \@problem_list) + fake_user($db); -Given an Apache request object, the current user, and a list of problem -files, return a list of pg objects which contain rendered versions of -the problems. +Make a temporary user for the given database. =cut -sub renderProblems { - my %args = @_; - my $r = $args{r}; - my $user = $args{user}; - my @problem_list = @{$args{problem_list}}; - - my $db = $r->db; - my $ce = $r->ce; - my $key = $r->param('key'); - my $set = $args{'this_set'} || fake_set($db); - my $problem_seed = $args{'problem_seed'} || $r->param('problem_seed') || 0; - my $displayMode = $args{displayMode} || - $r->param("displayMode") || $ce->{pg}->{options}->{displayMode}; - my $showHints = $args{showHints} || 0; - my $showSolutions = $args{showSolutions} || 0; - my $problemNumber= $args{'problem_number'} || 1; - $ce->{pg}->{specialPGEnvironmentVars}->{problemPreamble} = { - TeX=>'', - HTML=>''}; - $ce->{pg}->{specialPGEnvironmentVars}->{problemPostamble} = { - TeX=>'', - HTML=>''}; - - my @output = (); - my $onefile; - if($displayMode eq 'None') { - for $onefile (@problem_list) { - my $res = { body_text=>''}; - #my $res = { body_text=>'Click "Try it" to see the problem rendered'}; - push @output, $res; - } - } else { - my $problem = fake_problem($db, 'problem_seed'=>$problem_seed); - my $formFields = { WeBWorK::Form->new_from_paramable($r)->Vars }; - - for $onefile (@problem_list) { - $problem->problem_id($problemNumber++); - $problem->source_file($onefile); - my $pg = WeBWorK::PG->new( - $ce, - $user, - $key, - $set, - $problem, - 123, # $set->psvn, # FIXME: this field should be\ removed - $formFields, - { # translation options - displayMode => $displayMode, - showHints => $showHints, - showSolutions => $showSolutions, - refreshMath2img => 0, - processAnswers => 0, - } - ); - - push @output, $pg; - } - } - return(@output); -} +sub fake_user { + my ($db) = @_; + return $db->newUser( + user_id => fakeUserName, + first_name=>'', + last_name=>'', + email_address=>'', + student_id=>'', + section=>'', + recitation=>'', + comment=>'', + ); +} + +=item render_problems + + render_problems(r => $r, user => $User, problem_list => \@problem_list); + +Given an Apache request object, the current user, and a list of problem files, +return a list of WeBWorK::PG objects which contain rendered versions of the +problems. + +Options: + +=over + +=item r + +A WeBWorK::Request object. Required. + +=item problem_list + +A reference to an array of items render. Required. Each item can either be a +string, which is interpreted as a path to a PG file, or a reference to a string, +which is interpreted as a complete PG program. + +=item user + +A User record (e.g. a WeBWorK::DB::Record::User object). Optional. If not +specified, fake_user() will be used to generate a temporary user record. + +=item this_set + +A Set record (e.g. a WeBWorK::DB::Record::UserSet object). Optional. If not +specified, fake_set() will be used to generate a temporary set record. + +=item problem_seed + +The seed to use for randomization. Optional. If not specified, the Request +object will be checked for a problem_seed parameter. If found, that value is +used. Otherwise, 0 is used. + +=item displayMode + +The display mode to use. Optional. If not specified, the Request object will be +checked for a displayMode parameter. If found, that value is used. Otherwise, +the default display mode is used. + +If the value is 'None', then problems will not be rendered and "fake" +WeBWorK::PG objects will be returned. Each "fake" WeBWorK::PG object will look +like: + + {body_text=>''} + +=item showHints + +Whether to show hints in the problem. Optional. If not specified, hints are not +shown. + +=item showSolutions + +Whether to show solutions in the problem. Optional. If not specified, solutions +are not shown. + +=item problemNumber + +Each problem in @problem_list is given a problem ID starting with this value. +Optional. If not specified the problems are numbered from 1. =back =cut -=head1 AUTHOR +sub renderProblems { + my %args = @_; + my $r = $args{r}; + my $db = $r->db; + my $ce = $r->ce; + + my @problem_list = @{$args{problem_list}}; + my $displayMode = $args{displayMode} + || $r->param('displayMode') + || $ce->{pg}{options}{displayMode}; + + # special case for display mode 'None' -- we don't have to do anything + # FIXME i think this should be handled in SetMaker.pm + if ($displayMode eq 'None') { + return map { {body_text=>''} } @problem_list; + } + + my $user = $args{user} || fake_user($db); + my $set = $args{'this_set'} || fake_set($db); + my $problem_seed = $args{'problem_seed'} || $r->param('problem_seed') || 0; + my $showHints = $args{showHints} || 0; + my $showSolutions = $args{showSolutions} || 0; + my $problemNumber = $args{'problem_number'} || 1; + + my $key = $r->param('key'); + + # remove any pretty garbage around the problem + local $ce->{pg}{specialPGEnvironmentVars}{problemPreamble} = {TeX=>'',HTML=>''}; + local $ce->{pg}{specialPGEnvironmentVars}{problemPostamble} = {TeX=>'',HTML=>''}; + my $problem = fake_problem($db, 'problem_seed'=>$problem_seed); + my $formFields = { WeBWorK::Form->new_from_paramable($r)->Vars }; + + my @output; + + foreach my $onefile (@problem_list) { + my $translationOptions = { + displayMode => $displayMode, + showHints => $showHints, + showSolutions => $showSolutions, + refreshMath2img => 0, + processAnswers => 0, + }; + + $problem->problem_id($problemNumber++); + if (ref $onefile) { + $problem->source_file(''); + $translationOptions->{r_source} = $onefile; + } else { + $problem->source_file($onefile); + } + + my $pg = new WeBWorK::PG( + $ce, + $user, + $key, + $set, + $problem, + 123, # PSVN (practically unused in PG) + $formFields, + $translationOptions, + ); -Written by John Jones, jj (at) asu.edu. + push @output, $pg; + } + + return @output; +} + +=back =cut +=head1 AUTHOR +Written by John Jones, jj (at) asu.edu. + +=cut 1; |
From: Sam H. v. a. <we...@ma...> - 2008-04-29 19:43:18
|
Log Message: ----------- commented out unused variable Modified Files: -------------- webwork2/lib/WeBWorK/ContentGenerator: CourseAdmin.pm Revision Data ------------- Index: CourseAdmin.pm =================================================================== RCS file: /webwork/cvs/system/webwork2/lib/WeBWorK/ContentGenerator/CourseAdmin.pm,v retrieving revision 1.69 retrieving revision 1.70 diff -Llib/WeBWorK/ContentGenerator/CourseAdmin.pm -Llib/WeBWorK/ContentGenerator/CourseAdmin.pm -u -r1.69 -r1.70 --- lib/WeBWorK/ContentGenerator/CourseAdmin.pm +++ lib/WeBWorK/ContentGenerator/CourseAdmin.pm @@ -414,10 +414,11 @@ (@ordered_layouts, @other_layouts); }; - my $ce2 = new WeBWorK::CourseEnvironment({ - %WeBWorK::SeedCE, - courseName => "COURSENAME", - }); + # unused... + #my $ce2 = new WeBWorK::CourseEnvironment({ + # %WeBWorK::SeedCE, + # courseName => "COURSENAME", + #}); my @existingCourses = listCourses($ce); @existingCourses = sort { lc($a) cmp lc ($b) } @existingCourses; #make sort case insensitive |
From: Sam H. v. a. <we...@ma...> - 2008-04-29 19:42:51
|
Log Message: ----------- beginnings of lightweight problem renderer Modified Files: -------------- webwork2/lib/WeBWorK: URLPath.pm Added Files: ----------- webwork2/lib/WeBWorK/ContentGenerator: ProblemRenderer.pm Revision Data ------------- Index: URLPath.pm =================================================================== RCS file: /webwork/cvs/system/webwork2/lib/WeBWorK/URLPath.pm,v retrieving revision 1.35 retrieving revision 1.36 diff -Llib/WeBWorK/URLPath.pm -Llib/WeBWorK/URLPath.pm -u -r1.35 -r1.36 --- lib/WeBWorK/URLPath.pm +++ lib/WeBWorK/URLPath.pm @@ -58,6 +58,7 @@ logout /$courseID/logout/ options /$courseID/options/ #test /$courseID/test/ + #render /$courseID/render/ instructor_tools /$courseID/instructor/ @@ -240,6 +241,15 @@ # produce => 'test/', # display => 'WeBWorK::ContentGenerator::Test', #}, + #render => { + # name => 'Render', + # parent => 'set_list', + # kids => [ qw// ], + # match => qr|^render/|, + # capture => [ qw// ], + # produce => 'render/', + # display => 'WeBWorK::ContentGenerator::ProblemRenderer', + #}, ################################################################################ --- /dev/null +++ lib/WeBWorK/ContentGenerator/ProblemRenderer.pm @@ -0,0 +1,85 @@ +################################################################################ +# WeBWorK Online Homework Delivery System +# Copyright © 2000-2007 The WeBWorK Project, http://openwebwork.sf.net/ +# $CVSHeader: webwork2/lib/WeBWorK/ContentGenerator/ProblemRenderer.pm,v 1.1 2008/04/29 19:27:34 sh002i Exp $ +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of either: (a) the GNU General Public License as published by the +# Free Software Foundation; either version 2, or (at your option) any later +# version, or (b) the "Artistic License" which comes with this package. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See either the GNU General Public License or the +# Artistic License for more details. +################################################################################ + +package WeBWorK::ContentGenerator::ProblemRenderer; +use base qw(WeBWorK::ContentGenerator); + +=head1 NAME + +WeBWorK::ContentGenerator::ProblemRenderer - render a problem with a minimal +amount of UI garbage. + +=cut + +use strict; +use warnings; +use WeBWorK::CGI; +use WeBWorK::Utils::Tasks qw(renderProblems); + +sub pre_header_initialize { + my ($self) = @_; + my $r = $self->r; + + my $pg = $r->param('pg'); + my $file = $r->param('file'); + my $seed = $r->param('seed'); + my $mode = $r->param('mode'); + my $hint = $r->param('hint'); + my $sol = $r->param('sol'); + + die "must specify either a PG problems (param 'pg') or a path to a PG file (param 'file') and not both" + unless defined $pg and length $pg xor defined $file and length $file; + + my $problem = $self->get_problem($pg, $file); + my @options = (r=>$r, problem_list=>[\$pg]); + + #push @options, (problem_seed=>$seed) if defined $seed; + #push @options, (displayMode=>$mode) if defined $mode; + #push @options, (showHints=>$hint) if defined $hint; + #push @options, (showSolutions=>$sol) if defined $sol; + + ($self->{result}) = renderProblems(@options); +} + +sub get_problem { + my ($self, $pg, $file) = @_; + + if (defined $pg) { + return \$pg; + } else { + return $file; + } +} + +use Data::Dumper; +sub content { + my ($self) = @_; + my $result = $self->{result}; + my $dump = Dumper($result); + + print <<EOF; +<html> +<head> +<title>Yuck!</title> +</head> +<body> +<pre>$dump</pre> +</body> +</html> +EOF +} + +1; |
From: Sam H. v. a. <we...@ma...> - 2008-04-29 19:39:59
|
Log Message: ----------- added comments about future exception handling scheme Modified Files: -------------- webwork2/lib/WeBWorK: DB.pm Revision Data ------------- Index: DB.pm =================================================================== RCS file: /webwork/cvs/system/webwork2/lib/WeBWorK/DB.pm,v retrieving revision 1.107 retrieving revision 1.108 diff -Llib/WeBWorK/DB.pm -Llib/WeBWorK/DB.pm -u -r1.107 -r1.108 --- lib/WeBWorK/DB.pm +++ lib/WeBWorK/DB.pm @@ -104,6 +104,55 @@ use WeBWorK::Debug; use WeBWorK::Utils qw(runtime_use); +=for comment + +These exceptions will replace the ones in WeBWorK::DB::Schema and will be +allowed to propagate out to calling code. The following callers will have to be +changed to catch these exceptions instead of doing string matching: + +lib/WebworkSOAP.pm: if ($@ =~ m/user set exists/) { +lib/WeBWorK/ContentGenerator/Instructor.pm: if ($@ =~ m/user set exists/) { +lib/WeBWorK/ContentGenerator/Instructor.pm: if ( $@ =~ m/user set exists/ ) { +lib/WeBWorK/ContentGenerator/Instructor.pm: if ($@ =~ m/user problem exists/) { +lib/WeBWorK/ContentGenerator/Instructor.pm: if ($@ =~ m/user problem exists/) { +lib/WeBWorK/ContentGenerator/Instructor.pm: next if $@ =~ m/user set exists/; +lib/WeBWorK/Utils/DBImportExport.pm: if ($@ =~ m/exists/) { +lib/WeBWorK/DB.pm: if ($@ and $@ !~ m/password exists/) { +lib/WeBWorK/DB.pm: if ($@ and $@ !~ m/permission level exists/) { + +How these exceptions should be used: + +* RecordExists is thrown by the DBI error handler (handle_error in +Schema::NewSQL::Std) when in INSERT fails because a record exists. Thus it can +be thrown via addUser, addPassword, etc. + +* RecordNotFound should be thrown when we try to UPDATE and zero rows were +affected. Problem: Frank Wolfs (UofR PAS) may have a MySQL server that returns 0 +when updating even when a record was modified. What's up with that? There's some +question as to where we should throw this: in this file's put* methods? In +Std.pm's put method? Or in update_fields and update_fields_i? + +* DependencyNotFound should be throws when we check for a record that is needed +to insert another record (e.g. password depends on user). These checks are done +in this file, so we'll throw this exception from there. + +=cut + +use Exception::Class ( + 'WeBWorK::DB::Ex' => {}, + 'WeBWorK::DB::Ex::RecordExists' => { + isa => 'WeBWorK::DB::Ex', + fields => ['type', 'key'], + }, + 'WeBWorK::DB::Ex::RecordNotFound' => { + isa => 'WeBWorK::DB::Ex', + fields => ['type', 'key'], + }, + 'WeBWorK::DB::Ex::DependencyNotFound' => { + isa => 'WeBWorK::DB::Ex::RecordNotFound', + }, +); + ################################################################################ # constructor ################################################################################ @@ -452,15 +501,6 @@ } elsif ($@) { die $@; } - # FIXME about these exceptions: eventually the exceptions should be part of - # WeBWorK::DB rather than WeBWorK::DB::Schema, and we should just let them - # through to the calling code. however, right now we have code that checks - # for the string "... exists" in the error message, so we need to convert - # here. - # - # WeBWorK::DB::Ex::RecordExists - # WeBWorK::DB::Ex::DependencyNotFound - i.e. inserting a password for a nonexistent user - # ? } sub putUser { |
From: Sam H. v. a. <we...@ma...> - 2008-04-29 19:24:01
|
Log Message: ----------- backport (sh002i): remove stale pidfiles on stop. Tags: ---- rel-2-4-dev Modified Files: -------------- webwork2/bin: wwapache2ctl.dist Revision Data ------------- Index: wwapache2ctl.dist =================================================================== RCS file: /webwork/cvs/system/webwork2/bin/wwapache2ctl.dist,v retrieving revision 1.2.4.1 retrieving revision 1.2.4.2 diff -Lbin/wwapache2ctl.dist -Lbin/wwapache2ctl.dist -u -r1.2.4.1 -r1.2.4.2 --- bin/wwapache2ctl.dist +++ bin/wwapache2ctl.dist @@ -89,6 +89,7 @@ stop) checkpid kill -TERM `cat "$PID"` + rm -f "$PID" ;; restart) checkpid |
From: Sam H. v. a. <we...@ma...> - 2008-04-29 19:22:31
|
Log Message: ----------- remove stale pidfiles on stop Modified Files: -------------- webwork2/bin: wwapache2ctl.dist Revision Data ------------- Index: wwapache2ctl.dist =================================================================== RCS file: /webwork/cvs/system/webwork2/bin/wwapache2ctl.dist,v retrieving revision 1.3 retrieving revision 1.4 diff -Lbin/wwapache2ctl.dist -Lbin/wwapache2ctl.dist -u -r1.3 -r1.4 --- bin/wwapache2ctl.dist +++ bin/wwapache2ctl.dist @@ -89,6 +89,7 @@ stop) checkpid kill -TERM `cat "$PID"` + rm -f "$PID" ;; restart) checkpid |
From: Mike G. v. a. <we...@ma...> - 2008-04-27 12:08:16
|
Log Message: ----------- Rolling back previous change of "\0 to \0 until further checking is done. Modified Files: -------------- webwork2/lib/WeBWorK: Form.pm Revision Data ------------- Index: Form.pm =================================================================== RCS file: /webwork/cvs/system/webwork2/lib/WeBWorK/Form.pm,v retrieving revision 1.8 retrieving revision 1.9 diff -Llib/WeBWorK/Form.pm -Llib/WeBWorK/Form.pm -u -r1.8 -r1.9 --- lib/WeBWorK/Form.pm +++ lib/WeBWorK/Form.pm @@ -170,11 +170,20 @@ # supported is being called in scalar context, which in CGI.pm returned a # tied hashref to the original form data. WeBWorK didn't need that, so I # didn't add it. If you're feeling industrious... + +#FIXME? I originally changed join("\0",....) to join(\0, ....) since I'm pretty sure that what was desired +# was a string separated by nulls. If one of the items in the list began with a number eg 14 +# you would get \014....\0name...\0 etc. I think \0name evaluates properly but I'm pretty +# sure that \014 does not. +# +# Then I backed out of the change until this gets checked more thoroughly by Sam +# -- Mike + sub Vars { my $self = shift; my %varsFormat = (); foreach my $key ($self->param) { - $varsFormat{$key} = join \0, $self->param($key); + $varsFormat{$key} = join "\0", $self->param($key); } return %varsFormat; |
From: Mike G. v. a. <we...@ma...> - 2008-04-26 23:29:05
|
Log Message: ----------- Changed join("\0",....) to join(\0, ....) since I'm pretty sure that what was desired was a string separated by nulls. If one of the items in the list began with a number eg 14 you would get \014....\0name...\0 etc. I think \0name evaluates properly but I'm pretty sure that \014 does not. Modified Files: -------------- webwork2/lib/WeBWorK: Form.pm webwork2/lib/WeBWorK/ContentGenerator: Problem.pm ProblemSet.pm Revision Data ------------- Index: Form.pm =================================================================== RCS file: /webwork/cvs/system/webwork2/lib/WeBWorK/Form.pm,v retrieving revision 1.7 retrieving revision 1.8 diff -Llib/WeBWorK/Form.pm -Llib/WeBWorK/Form.pm -u -r1.7 -r1.8 --- lib/WeBWorK/Form.pm +++ lib/WeBWorK/Form.pm @@ -174,7 +174,7 @@ my $self = shift; my %varsFormat = (); foreach my $key ($self->param) { - $varsFormat{$key} = join "\0", $self->param($key); + $varsFormat{$key} = join \0, $self->param($key); } return %varsFormat; Index: Problem.pm =================================================================== RCS file: /webwork/cvs/system/webwork2/lib/WeBWorK/ContentGenerator/Problem.pm,v retrieving revision 1.212 retrieving revision 1.213 diff -Llib/WeBWorK/ContentGenerator/Problem.pm -Llib/WeBWorK/ContentGenerator/Problem.pm -u -r1.212 -r1.213 --- lib/WeBWorK/ContentGenerator/Problem.pm +++ lib/WeBWorK/ContentGenerator/Problem.pm @@ -493,7 +493,7 @@ my $publishedClass = ($set->published) ? "Published" : "Unpublished"; my $publishedText = ($set->published) ? "visible to students." : "hidden from students."; - $self->addmessage(CGI::p("This set is " . CGI::font({class=>$publishedClass}, $publishedText))); + $self->addmessage(CGI::span("This set is " . CGI::font({class=>$publishedClass}, $publishedText))); # test for additional problem validity if it's not already invalid } else { Index: ProblemSet.pm =================================================================== RCS file: /webwork/cvs/system/webwork2/lib/WeBWorK/ContentGenerator/ProblemSet.pm,v retrieving revision 1.89 retrieving revision 1.90 diff -Llib/WeBWorK/ContentGenerator/ProblemSet.pm -Llib/WeBWorK/ContentGenerator/ProblemSet.pm -u -r1.89 -r1.90 --- lib/WeBWorK/ContentGenerator/ProblemSet.pm +++ lib/WeBWorK/ContentGenerator/ProblemSet.pm @@ -74,7 +74,7 @@ my $publishedText = ($set->published) ? "visible to students." : "hidden from students."; my $publishedClass = ($set->published) ? "Published" : "Unpublished"; - $self->addmessage(CGI::p("This set is " . CGI::font({class=>$publishedClass}, $publishedText))) if $authz->hasPermissions($userName, "view_unpublished_sets"); + $self->addmessage(CGI::span("This set is " . CGI::font({class=>$publishedClass}, $publishedText))) if $authz->hasPermissions($userName, "view_unpublished_sets"); $self->{userName} = $userName; $self->{user} = $user; |
From: Mike G. v. a. <we...@ma...> - 2008-04-26 23:22:07
|
Log Message: ----------- Moved placement of loadMacros(subfiles) to inside the _PGanswermacros_init() subroutine. Even though the subfiles do not have to be recompiled they do have to be reinitialized every time they are used and calling loadMacros() is the appropriate way to insure this. loadMacros() is smart about recompiling only if necessary. Modified Files: -------------- pg/macros: PGanswermacros.pl Revision Data ------------- Index: PGanswermacros.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/PGanswermacros.pl,v retrieving revision 1.65 retrieving revision 1.66 diff -Lmacros/PGanswermacros.pl -Lmacros/PGanswermacros.pl -u -r1.65 -r1.66 --- macros/PGanswermacros.pl +++ macros/PGanswermacros.pl @@ -142,6 +142,11 @@ my $functVarDefault; my $useBaseTenLog; sub _PGanswermacros_init { + loadMacros('PGnumericevaluators.pl'); # even if these files are already loaded they need to be initialized. + loadMacros('PGfunctionevaluators.pl'); + loadMacros('PGstringevaluators.pl'); + loadMacros('PGmiscevaluators.pl'); + $BR = PG_restricted_eval(q/$BR/); $functLLimitDefault = PG_restricted_eval(q/$envir{functLLimitDefault}/); $functULimitDefault = PG_restricted_eval(q/$envir{functULimitDefault}/); @@ -1763,11 +1768,6 @@ $out; } -BEGIN { - loadMacros('PGnumericevaluators.pl'); - loadMacros('PGfunctionevaluators.pl'); - loadMacros('PGstringevaluators.pl'); - loadMacros('PGmiscevaluators.pl'); -} + 1; |