diff --git a/bin/OPL-update b/bin/OPL-update index 2cc22468fc..6a70548ec1 100755 --- a/bin/OPL-update +++ b/bin/OPL-update @@ -18,10 +18,6 @@ use strict; use warnings; BEGIN { - die "WEBWORK_ROOT not found in environment.\n" - unless exists $ENV{WEBWORK_ROOT}; - # Unused variable, but define it to avoid an error message. - $WeBWorK::Constants::WEBWORK_DIRECTORY = ''; die "WEBWORK_ROOT not found in environment.\n" unless exists $ENV{WEBWORK_ROOT}; $ENV{PG_ROOT} //= "$ENV{WEBWORK_ROOT}/../pg"; die "The pg directory must be defined in PG_ROOT" unless (-e $ENV{PG_ROOT}); @@ -34,7 +30,7 @@ use lib "$ENV{WEBWORK_ROOT}/bin"; use WeBWorK::CourseEnvironment; use Helper 'runScript'; -my $ce = new WeBWorK::CourseEnvironment({webwork_dir=>$ENV{WEBWORK_ROOT}}); +my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT}, pg_dir => $ENV{PG_ROOT} }); print "\nDownloading the latest OPL release.\n"; runScript("$ENV{WEBWORK_ROOT}/bin/download-OPL-metadata-release.pl"); diff --git a/bin/OPL-update-legacy b/bin/OPL-update-legacy index 210098b95d..e599e2de05 100755 --- a/bin/OPL-update-legacy +++ b/bin/OPL-update-legacy @@ -25,10 +25,7 @@ use DBI; #You can increase path length to 4096 for mysql > 5.0.3) BEGIN { - die "WEBWORK_ROOT not found in environment.\n" - unless exists $ENV{WEBWORK_ROOT}; - # Unused variable, but define it to avoid an error message. - $WeBWorK::Constants::WEBWORK_DIRECTORY = ''; + die "WEBWORK_ROOT not found in environment.\n" unless exists $ENV{WEBWORK_ROOT}; } # Taxonomy global variables @@ -90,7 +87,7 @@ use WeBWorK::CourseEnvironment; use WeBWorK::Utils::Tags; use OPLUtils qw/build_library_directory_tree build_library_subject_tree build_library_textbook_tree writeJSONtoFile/; -my $ce = new WeBWorK::CourseEnvironment({webwork_dir=>$ENV{WEBWORK_ROOT}}); +my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT}, pg_dir => $pg_dir }); # decide whether the mysql installation can handle # utf8mb4 and that should be used for the OPL @@ -715,7 +712,7 @@ sub pgfiles { my $lang = $tags->{Language} || 'en'; my $mathobj = $tags->{MO} || 0; my $static = $tags->{Static} || 0; - + my @pgfile_ids = (); for my $DBsection_id (@DBsection_ids) { diff --git a/bin/addcourse b/bin/addcourse index f6cbb6a204..160f73ab9f 100755 --- a/bin/addcourse +++ b/bin/addcourse @@ -84,7 +84,7 @@ use lib "$pg_dir/lib"; use WeBWorK::CourseEnvironment; # Grab course environment (by reading webwork2/conf/defaults.config) -my $ce = new WeBWorK::CourseEnvironment({ webwork_dir => $webwork_dir }); +my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $webwork_dir, pg_dir => $pg_dir }); use WeBWorK::DB; use WeBWorK::File::Classlist; diff --git a/bin/change_user_id b/bin/change_user_id index a6337f1702..dc7c575f4a 100755 --- a/bin/change_user_id +++ b/bin/change_user_id @@ -45,7 +45,8 @@ my $new_user_id = shift; my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT}, - courseName => $courseID + pg_dir => $pg_dir, + courseName => $courseID }); my $db = new WeBWorK::DB($ce->{dbLayout}); diff --git a/bin/delcourse b/bin/delcourse index 5cdc33bb43..a7a21c8018 100755 --- a/bin/delcourse +++ b/bin/delcourse @@ -137,7 +137,8 @@ usage_error("must specify COURSEID.") unless $courseID; # bring up a minimal course environment my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT}, - courseName => $courseID, + pg_dir => $ENV{PG_ROOT}, + courseName => $courseID, }); my $dbLayout = $ce->{dbLayoutName}; diff --git a/bin/download-OPL-metadata-release.pl b/bin/download-OPL-metadata-release.pl index 227da0f688..2b787003e3 100755 --- a/bin/download-OPL-metadata-release.pl +++ b/bin/download-OPL-metadata-release.pl @@ -27,7 +27,7 @@ BEGIN use WeBWorK::CourseEnvironment; use Helper 'runScript'; -my $ce = new WeBWorK::CourseEnvironment({ webwork_dir => $ENV{WEBWORK_ROOT} }); +my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT}, pg_dir => $pg_dir }); my $rawData; my $releaseDataFF = diff --git a/bin/dump-OPL-tables.pl b/bin/dump-OPL-tables.pl index 4ff8979645..4e71169da3 100755 --- a/bin/dump-OPL-tables.pl +++ b/bin/dump-OPL-tables.pl @@ -37,9 +37,7 @@ BEGIN # get course environment and configured OPL path -my $ce = new WeBWorK::CourseEnvironment({ - webwork_dir => $ENV{WEBWORK_ROOT}, -}); +my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT}, pg_dir => $pg_dir }); my $configured_OPL_path = $ce->{problemLibrary}{root}; diff --git a/bin/dump_past_answers b/bin/dump_past_answers index 5d89ac16f1..9bb88cf603 100755 --- a/bin/dump_past_answers +++ b/bin/dump_past_answers @@ -126,8 +126,9 @@ my $csv = new Text::CSV->new({ binary => 1 }) or die "Cannot use CSV: " . Text::CSV->error_diag(); $csv->eol("\n"); -my $ce = new WeBWorK::CourseEnvironment({ +my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT}, + pg_dir => $pg_dir, }); my @courses = listCourses($ce); @@ -140,8 +141,9 @@ my @row; foreach my $courseID (@courses) { next if $courseID eq 'admin' || $courseID eq 'modelCourse'; - $ce = new WeBWorK::CourseEnvironment({ + $ce = WeBWorK::CourseEnvironment->({ webwork_dir => $ENV{WEBWORK_ROOT}, + pg_dir => $pg_dir, courseName => $courseID, }); $db = new WeBWorK::DB($ce->{dbLayout}); diff --git a/bin/generate-OPL-set-def-lists.pl b/bin/generate-OPL-set-def-lists.pl index 17a71804a8..3397a881e0 100755 --- a/bin/generate-OPL-set-def-lists.pl +++ b/bin/generate-OPL-set-def-lists.pl @@ -43,7 +43,7 @@ BEGIN use OPLUtils qw/writeJSONtoFile/; use WeBWorK::CourseEnvironment; -my $ce = new WeBWorK::CourseEnvironment({ webwork_dir => $ENV{WEBWORK_ROOT} }); +my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT}, pg_dir => $pg_root }); my $libraryRoot = $ce->{problemLibrary}{root}; my $contribRoot = $ce->{contribLibrary}{root}; diff --git a/bin/importClassList.pl b/bin/importClassList.pl index b59f67fe94..723632f130 100755 --- a/bin/importClassList.pl +++ b/bin/importClassList.pl @@ -53,6 +53,7 @@ BEGIN my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT}, + pg_dir => $pg_dir, courseName => $courseID }); diff --git a/bin/integrity_check.pl b/bin/integrity_check.pl index 0c89273352..aa6b151325 100644 --- a/bin/integrity_check.pl +++ b/bin/integrity_check.pl @@ -44,8 +44,9 @@ BEGIN my $courseName = "tmp_course"; -my $ce = new WeBWorK::CourseEnvironment({ +my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT}, + pg_dir => $pg_dir, courseName => $courseName }); diff --git a/bin/load-OPL-global-statistics.pl b/bin/load-OPL-global-statistics.pl index 5caf309671..12b56e1e73 100755 --- a/bin/load-OPL-global-statistics.pl +++ b/bin/load-OPL-global-statistics.pl @@ -38,8 +38,9 @@ BEGIN # get course environment and configured OPL path -my $ce = new WeBWorK::CourseEnvironment({ +my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT}, + pg_dir => $pg_dir }); my $dbh = DBI->connect( diff --git a/bin/newpassword b/bin/newpassword index 915f93ff4d..6428a4f4f4 100755 --- a/bin/newpassword +++ b/bin/newpassword @@ -96,6 +96,7 @@ sub dopasswd { # bring up a minimal course environment my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT}, + pg_dir => $pg_dir, courseName => $courseID }); diff --git a/bin/remove_stale_images b/bin/remove_stale_images index 23f0be8aba..ef102eb345 100755 --- a/bin/remove_stale_images +++ b/bin/remove_stale_images @@ -217,7 +217,7 @@ sub count_report { # bring up a minimal course environment -my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT} }); +my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT}, pg_dir => $pg_dir }); my $dirHead = $ce->{webworkDirs}->{equationCache}; my $cachePath = $ce->{webworkFiles}->{equationCacheDB}; diff --git a/bin/restore-OPL-tables.pl b/bin/restore-OPL-tables.pl index 1fcedbc5d4..33f0bd7340 100755 --- a/bin/restore-OPL-tables.pl +++ b/bin/restore-OPL-tables.pl @@ -38,8 +38,9 @@ BEGIN # get course environment and configured OPL path -my $ce = new WeBWorK::CourseEnvironment({ +my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT}, + pg_dir => $pg_dir }); my $configured_OPL_path = $ce->{problemLibrary}{root}; diff --git a/bin/setfilepermissions b/bin/setfilepermissions index 90cba77fbc..220a37582d 100755 --- a/bin/setfilepermissions +++ b/bin/setfilepermissions @@ -42,7 +42,7 @@ BEGIN { use lib "$ENV{WEBWORK_ROOT}/lib"; use lib "$pg_dir/lib"; use WeBWorK::CourseEnvironment; -my $ce = new WeBWorK::CourseEnvironment({ webwork_dir => $ENV{WEBWORK_ROOT} }); +my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT}, pg_dir => $pg_dir }); # who is really running this script (even if sudo'ed) # We set relevant directories so that script runner owns them diff --git a/bin/test_library_build.pl b/bin/test_library_build.pl index 91a21c2bd2..2d988a7493 100755 --- a/bin/test_library_build.pl +++ b/bin/test_library_build.pl @@ -6,9 +6,6 @@ BEGIN die "WEBWORK_ROOT not found in environment.\n" unless exists $ENV{WEBWORK_ROOT}; $pg_dir = $ENV{PG_ROOT} // "$ENV{WEBWORK_ROOT}/../pg"; die "The pg directory must be defined in PG_ROOT" unless (-e $pg_dir); - - # Unused variable, but define it to avoid an error message. - $WeBWorK::Constants::WEBWORK_DIRECTORY = ''; } # Get database connection @@ -19,7 +16,7 @@ BEGIN use OPLUtils qw/build_library_directory_tree build_library_subject_tree build_library_textbook_tree/; use DBI; -my $ce = new WeBWorK::CourseEnvironment({ webwork_dir => $ENV{WEBWORK_ROOT} }); +my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT}, pg_dir => $pg_dir }); my $dbh = DBI->connect( $ce->{database_dsn}, $ce->{database_username}, diff --git a/bin/update-OPL-statistics.pl b/bin/update-OPL-statistics.pl index cb8bdd19f7..b0529ca806 100755 --- a/bin/update-OPL-statistics.pl +++ b/bin/update-OPL-statistics.pl @@ -38,8 +38,9 @@ BEGIN my $time = time(); # get course environment and open up database -my $ce = new WeBWorK::CourseEnvironment({ +my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT}, + pg_dir => $pg_dir }); # decide whether the mysql installation can handle diff --git a/bin/updateOPLextras.pl b/bin/updateOPLextras.pl index 876223d186..6433b75e34 100755 --- a/bin/updateOPLextras.pl +++ b/bin/updateOPLextras.pl @@ -83,7 +83,7 @@ BEGIN use WeBWorK::CourseEnvironment; use OPLUtils qw/build_library_directory_tree build_library_subject_tree build_library_textbook_tree/; -my $ce = new WeBWorK::CourseEnvironment({ webwork_dir => $ENV{WEBWORK_ROOT} }); +my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT}, pg_dir => $pg_dir }); # decide whether the mysql installation can handle # utf8mb4 and that should be used for the OPL diff --git a/bin/upgrade-database-to-utf8mb4.pl b/bin/upgrade-database-to-utf8mb4.pl index 92626fb6fa..de3f3ca8a4 100755 --- a/bin/upgrade-database-to-utf8mb4.pl +++ b/bin/upgrade-database-to-utf8mb4.pl @@ -154,7 +154,7 @@ BEGIN use WeBWorK::Utils::CourseManagement qw{listCourses}; # Load a minimal course environment. -my $ce = new WeBWorK::CourseEnvironment({ webwork_dir => $ENV{WEBWORK_ROOT} }); +my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT}, pg_dir => $ENV{PG_ROOT} }); # Get DB connection settings. my $dbname = $ce->{database_name}; diff --git a/bin/upgrade_admin_db.pl b/bin/upgrade_admin_db.pl index fdef76c078..0ef3a6ba23 100755 --- a/bin/upgrade_admin_db.pl +++ b/bin/upgrade_admin_db.pl @@ -35,8 +35,9 @@ BEGIN ########################## my $upgrade_courseID = 'admin'; -my $ce = new WeBWorK::CourseEnvironment({ +my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT}, + pg_dir => $pg_dir, courseName => $upgrade_courseID, }); #warn "do_upgrade_course: updating |$upgrade_courseID| from" , join("|",@upgrade_courseIDs); diff --git a/bin/upload-OPL-statistics.pl b/bin/upload-OPL-statistics.pl index 676d96a40c..56269f1607 100755 --- a/bin/upload-OPL-statistics.pl +++ b/bin/upload-OPL-statistics.pl @@ -32,8 +32,9 @@ BEGIN use Net::Domain qw/domainname/; use String::ShellQuote; -my $ce = new WeBWorK::CourseEnvironment({ +my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT}, + pg_dir => $pg_dir, }); # Get DB connection settings @@ -66,7 +67,7 @@ BEGIN * the average number of attempts made per user on the problem * the average completion percentage for each user who attempted the problem -Share OPL usage statistics with the WeBWorK community [Y/N]: +Share OPL usage statistics with the WeBWorK community [Y/N]: END_REQUEST $input = ; chomp $input; diff --git a/bin/webwork2 b/bin/webwork2 index 1319eb9032..e0bd74a2c5 100755 --- a/bin/webwork2 +++ b/bin/webwork2 @@ -33,9 +33,6 @@ BEGIN { $WeBWorK::SeedCE{webwork_dir} = $ENV{WEBWORK_ROOT}; $WeBWorK::SeedCE{pg_dir} = $ENV{PG_ROOT}; - # Define these twice to avoid annoying used only once warnings. - $WeBWorK::Constants::WEBWORK_DIRECTORY = $WeBWorK::Constants::WEBWORK_DIRECTORY = $ENV{WEBWORK_ROOT}; - $WeBWorK::Constants::PG_DIRECTORY = $WeBWorK::Constants::PG_DIRECTORY = $ENV{PG_ROOT}; } use Mojolicious::Commands; diff --git a/bin/ww_purge_old_nonces b/bin/ww_purge_old_nonces index 9ac0b0bc6e..2361d6ae6e 100755 --- a/bin/ww_purge_old_nonces +++ b/bin/ww_purge_old_nonces @@ -69,7 +69,8 @@ usage() unless $course ; my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT}, - courseName => $course, + pg_dir => $pg_dir, + courseName => $course, }); my $db = WeBWorK::DB->new($ce->{dbLayout}); diff --git a/bin/wwdb b/bin/wwdb index e5e5c82d32..f94f49a028 100755 --- a/bin/wwdb +++ b/bin/wwdb @@ -88,7 +88,8 @@ usage() unless $course and $command and $file; my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT}, - courseName => $course, + pg_dir => $pg_dir, + courseName => $course, }); my $db = WeBWorK::DB->new($ce->{dbLayout}); diff --git a/bin/wwsh b/bin/wwsh index bcea2a1d01..ff697e9a3a 100755 --- a/bin/wwsh +++ b/bin/wwsh @@ -51,7 +51,8 @@ die 'You must pass scriptFile in as a path to the file' unless -e $scriptFile; $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT}, - courseName => $courseID, + pg_dir => $pg_dir, + courseName => $courseID, }); diff --git a/clients/README b/clients/README deleted file mode 100644 index 9c490b7bdc..0000000000 --- a/clients/README +++ /dev/null @@ -1,73 +0,0 @@ -2010.05.11 - -At this point renderProblem.pl is the most up to date and works with BBedit to -to send a local file to an xmlserver (mod_xmlrpc) to be rendered. In addition the returned' -file's question form action url is pointed to the same server with the path ending in xml2html. -This allows one to enter answers and test whether they work. - -There were changes to webwork2/lib/WebworkWebservice.pm to make it work with Apache2. -There were also changes to webwork2/lib/WeBWorK/URLpath.pm and a new -module webwork2/lib/WeBWorK/ContentGenerator/xmlViaHTTP.pm - -The webwork_xmplrp_client and webwork_soap_client.pl have not been updated, but may still work. - -to do: - •add facilities for inspecting libraries via xmlrpc and html2xml links - •figure out how to automate the configuration of these xmlrpc files - Apache2::ServerUtil should do this?? but I can't figure out how. - •I suspect that auxiliary html files and applets don't work yet. - - I'm pretty sure that there is no security checking to insure that only appropriate - people have access to the xmlrpc webservice. -############################################################################################## - - -These test clients will process these two commands: - -./webwork_xmlrpc_client.pl renderProblem input.txt >foo.txt -./webwork_xmlrpc_client.pl listLibraries -or - -./webwork_soap_client.pl renderProblem input.txt >foo.txt -./webwork_soap_client.pl listLibraries - - -You may need to adjust some hardwired parameters in the scripts so that -you are pointed at the correct servers. :-) - -The scripts hello_world_xmlrpc.pl and hello_world_soap.pl take no arguments -and can be used to test the connection with the chosen servers. - -The scripts renderProblem.pl and renderProblem_rawoutput.pl are versions of the -xmlrpc_xmlrp_client which can be used as filters. The were designed to be used with -bbedit (Mac editor) to send a PG problem file of to a webservice to be rendered. - -The renderProblem_rawoutput version decodes the xml response and prints it as perl structures -through "less". - -The renderProblem.pl pipes the HTML part of the response through safari (other browsers could -be used) for viewing. This is usually what is wanted for testing. Currently the error recovery -is minimal, so error messages sent from the server may totally confuse the client (which -will probably report a bad result type). The resulting web page is live and pointed -to a responder at webhost.math.rochester.edu. When that server is working you can -actually submit an answer and have it evaluated. It's a very old, tired PC running -Frontier as a server, so be patient with it. :-) - - -checkProblem.pl will take a problem source, send it to the webserver for checking -and record the result in a log file. It is very similar to renderProblem.pl. - -check_problems_in_dir.sh will apply checkProblem.pl to all .pg problems found -underneath the current directory in which the command is executed. I've used -it to check all the problems in a directory for warning errors. There are more -subtle checks that could be made, such as checking to see that correct -answers work. - -Typically one downloads a problem library from the SVN -and then uses check_problems_in_dir.sh to walk through it. By modifying -checkProblems and webwork_xmlrpc_inc.pl one could have the HTML version -of each problem dumped to a text file, or by changing the DISPLAYMODE to -"tex" instead of image one could dump the TeX version of each file. - - --- Mike Gage 1/1/2007 diff --git a/clients/hello_world_apps/hello_world_soap_client.pl b/clients/hello_world_apps/hello_world_soap_client.pl deleted file mode 100755 index 400c914e55..0000000000 --- a/clients/hello_world_apps/hello_world_soap_client.pl +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/perl -w - -use SOAP::Lite; -my $soap = SOAP::Lite - #-> uri('http://math.webwork.rochester.edu/WebworkXMLRPC') - #-> proxy('https://math.webwork.rochester.edu/mod_soap/WebworkWebservice'); - ->uri('http://localhost/WebworkXMLRPC')->proxy('http://localhost/mod_soap/WebworkWebservice'); - -#-> uri('https://devel.webwork.rochester.edu:8002/WebworkXMLRPC') -#-> proxy('https://devel.webwork.rochester.edu:8002/mod_soap/WebworkWebservice'); - -my $result = $soap->hi(); - -unless ($result->fault) { - print $result->result(); -} else { - print join ', ', $result->faultcode, $result->faultstring; -} - diff --git a/clients/hello_world_apps/hello_world_xmlrpc_client.pl b/clients/hello_world_apps/hello_world_xmlrpc_client.pl deleted file mode 100755 index a32a9da024..0000000000 --- a/clients/hello_world_apps/hello_world_xmlrpc_client.pl +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/perl -w - -# -use XMLRPC::Lite; -my $soap = XMLRPC::Lite - # -> proxy('https://math.webwork.rochester.edu/mod_xmlrpc/'); - #-> proxy('https://devel.webwork.rochester.edu:8002/mod_xmlrpc/'); - ->proxy('http://localhost/mod_xmlrpc/'); - -my $result = $soap->call("WebworkXMLRPC.hi"); - -unless ($result->fault) { - print $result->result(), "\n"; -} else { - print join ', ', $result->faultcode, $result->faultstring; -} diff --git a/clients/hello_world_apps/webwork_soap_client.pl b/clients/hello_world_apps/webwork_soap_client.pl deleted file mode 100755 index cc577d1e14..0000000000 --- a/clients/hello_world_apps/webwork_soap_client.pl +++ /dev/null @@ -1,260 +0,0 @@ -#!/usr/bin/perl -w - -use SOAP::Lite; - -# configuration section -use constant HOSTURL => 'localhost'; -use constant HOSTPORT => 80; -use constant TRANSPORT_METHOD => 'SOAP::Lite'; -use constant REQUEST_CLASS => 'WebworkXMLRPC'; # WebworkXMLRPC is used for soap also!! -use constant REQUEST_URI => 'mod_soap'; - -my @COMMANDS = qw( listLibraries renderProblem ); #listLib readFile tex2pdf - -# $pg{displayModes} = [ -# "plainText", # display raw TeX for math expressions -# "images", # display math expressions as images generated by dvipng -# "jsMath", # render TeX math expressions on the client side using jsMath -# ]; -use constant DISPLAYMODE => 'images'; - -# end configuration section -use MIME::Base64 qw( encode_base64 decode_base64); - -print STDERR "inputs are ", join(" | ", @ARGV), "\n"; -our $source; - -if (@ARGV) { - my $command = $ARGV[0]; - - warn "executing WebworkXMLRPC.$command"; - $source = (defined $ARGV[1]) ? `cat $ARGV[1]` : ''; - xmlrpcCall($command); - -} else { - - print STDERR "Useage: ./webwork_soap_client.pl command inputs\n"; - print STDERR "For example: ./webwork_soap_client renderProblem input.txt\n"; - print STDERR "For example: ./webwork_soap_client listLibraries \n"; - print STDERR "Commands are: ", join(" ", @COMMANDS), "\n"; - -} - -sub xmlrpcCall { - my $command = shift; - $command = 'listLibraries' unless $command; - - my $requestResult = TRANSPORT_METHOD->uri('http://' . HOSTURL . ':' . HOSTPORT . '/' . REQUEST_CLASS) - ->proxy('http://' . HOSTURL . ':' . HOSTPORT . '/' . REQUEST_URI); - - my $test = [ 3, 4, 5, 6 ]; - my $input = setInputTable(); - print "displayMode=", $input->{envir}->{displayMode}, "\n"; - local ($result); - # use eval to catch errors - eval { $result = $requestResult->call("$command", $input) }; - print STDERR "There were a lot of errors\n" if $@; - print "Errors: \n $@\n End Errors\n" if $@; - - print "result is|", ref($result), "|"; - - unless (ref($result) and $result->fault) { - - if (ref($result->result()) =~ /HASH/ and defined($result->result()->{text})) { - $result->result()->{text} = decode_base64($result->result()->{text}); - } - print pretty_print_rh($result->result()), "\n"; #$result->result() - } else { - print 'oops ', join ', ', $result->faultcode, $result->faultstring; - } -} - -sub source { - encode_base64($source); -} - -sub pretty_print_rh { - shift if UNIVERSAL::isa($_[0] => __PACKAGE__); - my $rh = shift; - my $indent = shift || 0; - my $out = ""; - my $type = ref($rh); - - if (defined($type) and $type) { - $out .= " type = $type; "; - } elsif (!defined($rh)) { - $out .= " type = UNDEFINED; "; - } - return $out . " " unless defined($rh); - - if (ref($rh) =~ /HASH/ or "$rh" =~ /HASH/) { - $out .= "{\n"; - $indent++; - foreach my $key (sort keys %{$rh}) { - $out .= " " x $indent . "$key => " . pretty_print_rh($rh->{$key}, $indent) . "\n"; - } - $indent--; - $out .= "\n" . " " x $indent . "}\n"; - - } elsif (ref($rh) =~ /ARRAY/ or "$rh" =~ /ARRAY/) { - $out .= " ( "; - foreach my $elem (@{$rh}) { - $out .= pretty_print_rh($elem, $indent); - - } - $out .= " ) \n"; - } elsif (ref($rh) =~ /SCALAR/) { - $out .= "scalar reference " . ${$rh}; - } elsif (ref($rh) =~ /Base64/) { - $out .= "base64 reference " . $$rh; - } else { - $out .= $rh; - } - - return $out . " "; -} - -sub setInputTable_for_listLib { - $out = { - #password => 'geometry', - pw => 'geometry', - set => 'set0', - library_name => 'rochesterLibrary', - command => 'all', - }; - - $out; -} - -sub setInputTable { - $out = { - #password => 'geometry', - pw => 'geometry', - set => 'set0', - library_name => 'rochesterLibrary', - command => 'all', - answer_form_submitted => 1, - course => 'daemon_course', - extra_packages_to_load => [ qw( AlgParserWithImplicitExpand Expr - ExprWithImplicitExpand AnswerEvaluator - AnswerEvaluatorMaker - ) ], - mode => 'HTML_dpng', - modules_to_evaluate => [ qw( - Exporter - - DynaLoader - - GD - WWPlot - Fun - Circle - Label - - PGrandom - Units - Hermite - - List - - Match - Multiple - Select - - AlgParser - - AnswerHash - - Fraction - VectorField - - Complex1 - Complex - - MatrixReal1 Matrix - - Distributions - - Regression - - ) ], - envir => environment(), - problem_state => { - - num_of_correct_ans => 2, - num_of_incorrect_ans => 4, - recorded_score => 1.0, - }, - source => source(), #base64 encoded - - }; - - $out; -} - -sub environment { - my $envir = { - answerDate => '4014438528', - CAPA_Graphics_URL => 'http://webwork-db.math.rochester.edu/capa_graphics/', - CAPA_GraphicsDirectory => '/ww/webwork/CAPA/CAPA_Graphics/', - CAPA_MCTools => '/ww/webwork/CAPA/CAPA_MCTools/', - CAPA_Tools => '/ww/webwork/CAPA/CAPA_Tools/', - cgiDirectory => 'Not defined', - cgiURL => 'Not defined', - classDirectory => 'Not defined', - courseName => 'Not defined', - courseScriptsDirectory => '/ww/webwork/system/courseScripts/', - displayMode => DISPLAYMODE, - dueDate => '4014438528', - externalGif2EpsPath => 'not defined', - externalPng2EpsPath => 'not defined', - fileName => 'set0/prob1a.pg', - formattedAnswerDate => '6/19/00', - formattedDueDate => '6/19/00', - formattedOpenDate => '6/19/00', - functAbsTolDefault => 0.0000001, - functLLimitDefault => 0, - functMaxConstantOfIntegration => 1000000000000.0, - functNumOfPoints => 5, - functRelPercentTolDefault => 0.000001, - functULimitDefault => 1, - functVarDefault => 'x', - functZeroLevelDefault => 0.000001, - functZeroLevelTolDefault => 0.000001, - htmlDirectory => '/ww/webwork/courses/gage_course/html/', - htmlURL => 'http://webwork-db.math.rochester.edu/gage_course/', - inputs_ref => { - AnSwEr1 => '', - AnSwEr2 => '', - AnSwEr3 => '', - }, - macroDirectory => '/ww/webwork/courses/gage_course/templates/macros/', - numAbsTolDefault => 0.0000001, - numFormatDefault => '%0.13g', - numOfAttempts => 0, - numRelPercentTolDefault => 0.0001, - numZeroLevelDefault => 0.000001, - numZeroLevelTolDefault => 0.000001, - openDate => '3014438528', - PRINT_FILE_NAMES_FOR => ['gage'], - probFileName => 'set0/prob1a.pg', - problemSeed => 1234, - problemValue => 1, - probNum => 13, - psvn => 54321, - psvn => 54321, - questionNumber => 1, - scriptDirectory => 'Not defined', - sectionName => 'Gage', - sectionNumber => 1, - sessionKey => 'Not defined', - setNumber => 'MAAtutorial', - studentLogin => 'gage', - studentName => 'Mike Gage', - tempDirectory => '/ww/htdocs/tmp/gage_course/', - templateDirectory => '/ww/webwork/courses/gage_course/templates/', - tempURL => 'http://webwork-db.math.rochester.edu/tmp/gage_course/', - webworkDocsURL => 'http://webwork.math.rochester.edu/webwork_gage_system_html', - }; - $envir; -} diff --git a/clients/hello_world_apps/webwork_xmlrpc_client.pl b/clients/hello_world_apps/webwork_xmlrpc_client.pl deleted file mode 100755 index c91abd345c..0000000000 --- a/clients/hello_world_apps/webwork_xmlrpc_client.pl +++ /dev/null @@ -1,472 +0,0 @@ -#!/usr/bin/perl -w - -=pod - -This script will take a command and an input -file. - -It will list available libraries, list the contents of libraries -or render the input file. - -All of this is done by contacting the webservice. - - - -=cut - -use feature ":5.10"; -use lib "/opt/webwork/webwork2/lib"; -use WebworkClient; -use XMLRPC::Lite; -use MIME::Base64 qw( encode_base64 decode_base64); - -# configuration section -use constant PROTOCOL => 'http'; # or 'http'; -use constant HOSTURL => 'localhost'; -use constant HOSTPORT => '80'; # or 80 -use constant TRANSPORT_METHOD => 'XMLRPC::Lite'; -use constant REQUEST_CLASS => 'WebworkXMLRPC'; # WebworkXMLRPC is used for soap also!! -use constant REQUEST_URI => 'mod_xmlrpc'; -use constant TEMPOUTPUTFILE => '/Users/gage/Desktop/renderProblemOutput.html'; - -our $SITE_URL = 'http://localhost:80'; -our $FORM_ACTION_URL = 'http://localhost:80/webwork2/html2xml'; -our $XML_PASSWORD = 'xmlwebwork'; -our $XML_COURSE = 'gage_course'; - -our $UNIT_TESTS_ON = 0; - -#################################################### -# get credentials -#################################################### - -my $credential_path; -my @path_list = ('.ww_credentials', '/Users/gage/.ww_credentials', '/Users/gage/ww_session_credentials'); -foreach my $path (@path_list) { - if (-r "$path") { - $credential_path = $path; - last; - } -} -unless ($credential_path) { - die < "my login name for the webwork course", - course_password => "my course_password ", - courseID => "the name of the webwork course", -); -1; ---------------------------------------------------------- -EOF -} - -eval { require $credential_path }; -if ($@ or not defined %credentials) { - - print STDERR < "my login name for the webwork course", - course_password => "my course_password ", - courseID => "the name of the webwork course", -); -1; ---------------------------------------------------------- -EOF - die; -} - -#print "credentials: ", join(" | ", %credentials), "\n"; - -my @COMMANDS = qw( listLibraries renderProblem listLib readFile tex2pdf ); - -use constant DISPLAYMODE => 'images'; - -# end configuration section - -our $courseID = $credentials{courseID}; - -print STDERR "inputs are ", join(" | ", @ARGV), "\n"; -our $source; - -############################################ -# Build client -############################################ -our $xmlrpc_client = new WebworkClient( - site_url => $SITE_URL, - form_action_url => $FORM_ACTION_URL, - displayMode => DISPLAYMODE(), - - site_password => $credentials{site_password}, - courseID => $credentials{courseID}, - userID => $credentials{userID}, - session_key => $credentials{session_key}, -); - -# prepare additional input values - -if (@ARGV) { - my $command = $ARGV[0]; - my $result; - print "executing WebworkXMLRPC.$command \n\n-----------------------\n\n"; - given ($command) { - when ('renderProblem') { - if (defined $ARGV[1]) { - if (-r $ARGV[1]) { - $source = `cat $ARGV[1]`; - $xmlrpc_client->encodeSource($source); - my $input = { - userID => $credentials{userID} || '', - session_key => $credentials{session_key} || '', - courseID => $credentials{courseID} || '', - courseName => $credentials{courseID} || '', - course_password => $credentials{course_password} || '', - site_password => $credentials{site_password} || '', - }; - #print STDERR "input is ", %$input,"\n"; - $result = $xmlrpc_client->xmlrpcCall($command, $input); - print "\n\n Result of renderProblem \n\n"; - print pretty_print_rh($result); - } else { - print STDERR "Can't read source file $ARGV[1]\n"; - } - } else { - print STDERR "Useage: ./webwork_xmlrpc_client.pl command \n"; - } - } - when ('listLibraries') { - my $input = { - userID => $credentials{userID} || '', - session_key => $credentials{session_key} || '', - courseID => $credentials{courseID} || '', - course_password => $credentials{course_password} || '', - site_password => $credentials{site_password} || '', - }; - # print STDERR "ww_xmlrpc_client: input for listLibraries command is ", %$input,"\n"; - eval { $result = $xmlrpc_client->xmlrpcCall($command, $input); }; - if (defined($result)) { - my @lib_array = @{ $result->{ra_out} }; - print STDOUT "ww_xmlrpc_client: The libraries available in course $courseID are:\n\t ", - join("\n\t ", @lib_array), "\n"; - } else { - print STDOUT "ww_xmlrpc_client: No libraries available for course $courseID\n"; - } - } - when ('listLib') { - $result = listLib(@ARGV); - my $command = $ARGV[1]; - print "listLib returned\n"; - print pretty_print_rh($result); - print "\n"; - - } - when ('listSets') { - $input = { - site_password => 'xmluser', - course_password => $credentials{course_password}, - userID => $credentials{userID}, - courseID => $credentials{courseID}, - }; - my $result = $xmlrpc_client->xmlrpcCall($command, $input); - print pretty_print_rh($result); - } - when ('readFile') { - print STDERR "Command $command not yet implemented\n" - } - when ('tex2pdf') { - print STDERR "Command $command not yet implemented\n" - } - default { - print STDERR "Command '$command' not recognized. Commands ", @COMMANDS; - } - } - -} else { - - print STDERR "Useage: ./webwork_xmlrpc_client.pl command [file_name]\n"; - print STDERR - "For example: ./webwork_xmlrpc_client.pl renderProblem \n"; - print STDERR "Commands are: ", join(" ", @COMMANDS), "\n"; - -} - -sub source { - return "" unless $source; - return encode_base64($source); -} - -sub listLib { - my @ARGS = @_; - #print "args for listLib are ", join(" ", @ARGS), "\n"; - my $result; - given ($ARGS[1]) { - when ("all") { - $input = { - site_password => 'xmluser', - course_password => $credentials{course_password}, - userID => $credentials{userID}, - courseID => $credentials{courseID}, - command => 'all', - }; - $result = $xmlrpc_client->xmlrpcCall("listLib", $input); - } - when ('dirOnly') { - my %options = @ARGS[ 2 .. $#ARGS ]; - my $path = $options{-path} || ''; - my $maxdepth = defined($options{-depth}) ? $options{-depth} : 10000; - $input = { - site_password => 'xmluser', - course_password => $credentials{course_password}, - userID => $credentials{userID}, - courseID => $credentials{courseID}, - command => 'dirOnly', - dirPath => $path, - maxdepth => $maxdepth, - }; - $result = $xmlrpc_client->xmlrpcCall("listLib", $input); - } - when ('files') { - if ($ARGS[2]) { - my %options = @ARGS[ 2 .. $#ARGS ]; - my $path = $options{-path} || ''; - $input = { - site_password => 'xmluser', - course_password => $credentials{course_password}, - userID => $credentials{userID}, - courseID => $credentials{courseID}, - command => 'files', - dirPath => $path, - }; - $result = $xmlrpc_client->xmlrpcCall("listLib", $input); - } else { - print STDERR "Usage: webwork_xmlrpc_client listLib files \n"; - $result = ""; - } - } - default { - print "The possible arguments for listLib are:" - . "\n\t all -- print all paths" - . "\n\t dirOnly [options]-- print only directories below Library/path" - . "\n\t\t options: -depth depth -path directoryPath" - . "\n\t\t\t depth counts the number of slashes in the relative path" - . "\n\t files -- print .pg files in the given directory \n" - . "\n\t\t options: -path directoryPath"; - $result = ""; - } - } - return $result; -} - -sub pretty_print_rh { - shift if UNIVERSAL::isa($_[0] => __PACKAGE__); - my $rh = shift; - my $indent = shift || 0; - my $out = ""; - my $type = ref($rh); - - if (defined($type) and $type) { - $out .= " type = $type; "; - } elsif (!defined($rh)) { - $out .= " type = UNDEFINED; "; - } - return $out . " " unless defined($rh); - - if (ref($rh) =~ /HASH/ or "$rh" =~ /HASH/) { - $out .= "{\n"; - $indent++; - foreach my $key (sort keys %{$rh}) { - $out .= " " x $indent . "$key => " . pretty_print_rh($rh->{$key}, $indent) . "\n"; - } - $indent--; - $out .= "\n" . " " x $indent . "}\n"; - - } elsif (ref($rh) =~ /ARRAY/ or "$rh" =~ /ARRAY/) { - $out .= " ( "; - foreach my $elem (@{$rh}) { - $out .= pretty_print_rh($elem, $indent); - - } - $out .= " ) \n"; - } elsif (ref($rh) =~ /SCALAR/) { - $out .= "scalar reference " . ${$rh}; - } elsif (ref($rh) =~ /Base64/) { - $out .= "base64 reference " . $$rh; - } else { - $out .= $rh; - } - - return $out . " "; -} - -sub pretty_print_json { - shift if UNIVERSAL::isa($_[0] => __PACKAGE__); - my $rh = shift; - my $indent = shift || 0; - my $out = ""; - my $type = ref($rh); - - if (defined($type) and $type) { - $out .= " type = $type; "; - } elsif (!defined($rh)) { - $out .= " type = UNDEFINED; "; - } - return $out . " " unless defined($rh); - - if (ref($rh) =~ /HASH/ or "$rh" =~ /HASH/) { - $out .= "{\n"; - $indent++; - foreach my $key (sort keys %{$rh}) { - $out .= " " x $indent . "$key => " . pretty_print_json($rh->{$key}, $indent) . "\n"; - } - $indent--; - $out .= "\n" . " " x $indent . "}\n"; - - } elsif (ref($rh) =~ /ARRAY/ or "$rh" =~ /ARRAY/) { - $out .= " ( "; - foreach my $elem (@{$rh}) { - $out .= pretty_print_json($elem, $indent); - - } - $out .= " ) \n"; - } elsif (ref($rh) =~ /SCALAR/) { - $out .= "scalar reference " . ${$rh}; - } elsif (ref($rh) =~ /Base64/) { - $out .= "base64 reference " . $$rh; - } else { - my $jsonString = $rh; - $jsonString =~ s/(\\|\/)/\./g; - $out .= "Library." . $jsonString . ";"; - } - - return $out . " "; -} - -sub standard_input { - $out = { - site_password => 'xmluser', - course_password => $credentials{course_password}, - userID => $credentials{userID}, - set => 'set0', - library_name => 'Library', - command => 'all', - answer_form_submitted => 1, - courseID => $credentials{courseID}, - , - extra_packages_to_load => [ qw( AlgParserWithImplicitExpand Expr - ExprWithImplicitExpand AnswerEvaluator - AnswerEvaluatorMaker - ) ], - mode => DISPLAYMODE(), - modules_to_evaluate => [ qw( - Exporter - DynaLoader - GD - WWPlot - Fun - Circle - Label - PGrandom - Units - Hermite - List - Match - Multiple - Select - AlgParser - AnswerHash - Fraction - VectorField - Complex1 - Complex - MatrixReal1 Matrix - Distributions - Regression - - ) ], - envir => environment(), - problem_state => { - - num_of_correct_ans => 2, - num_of_incorrect_ans => 4, - recorded_score => 1.0, - }, - source => source(), #base64 encoded - - }; - - $out; -} - -sub environment { - my $envir = { - answerDate => '4014438528', - CAPA_Graphics_URL => 'http://webwork-db.math.rochester.edu/capa_graphics/', - CAPA_GraphicsDirectory => '/ww/webwork/CAPA/CAPA_Graphics/', - CAPA_MCTools => '/ww/webwork/CAPA/CAPA_MCTools/', - CAPA_Tools => '/ww/webwork/CAPA/CAPA_Tools/', - cgiDirectory => 'Not defined', - cgiURL => 'Not defined', - classDirectory => 'Not defined', - courseName => 'Not defined', - courseScriptsDirectory => '/ww/webwork/system/courseScripts/', - displayMode => DISPLAYMODE, - dueDate => '4014438528', - externalGif2EpsPath => 'not defined', - externalPng2EpsPath => 'not defined', - fileName => 'set0/prob1a.pg', - formattedAnswerDate => '6/19/00', - formattedDueDate => '6/19/00', - formattedOpenDate => '6/19/00', - functAbsTolDefault => 0.0000001, - functLLimitDefault => 0, - functMaxConstantOfIntegration => 1000000000000.0, - functNumOfPoints => 5, - functRelPercentTolDefault => 0.000001, - functULimitDefault => 1, - functVarDefault => 'x', - functZeroLevelDefault => 0.000001, - functZeroLevelTolDefault => 0.000001, - htmlDirectory => '/ww/webwork/courses/gage_course/html/', - htmlURL => 'http://webwork-db.math.rochester.edu/gage_course/', - inputs_ref => { - AnSwEr1 => '', - AnSwEr2 => '', - AnSwEr3 => '', - }, - macroDirectory => '/ww/webwork/courses/gage_course/templates/macros/', - numAbsTolDefault => 0.0000001, - numFormatDefault => '%0.13g', - numOfAttempts => 0, - numRelPercentTolDefault => 0.0001, - numZeroLevelDefault => 0.000001, - numZeroLevelTolDefault => 0.000001, - openDate => '3014438528', - PRINT_FILE_NAMES_FOR => ['gage'], - probFileName => 'set0/prob1a.pg', - problemSeed => 1234, - problemValue => 1, - probNum => 13, - psvn => 54321, - psvn => 54321, - questionNumber => 1, - scriptDirectory => 'Not defined', - sectionName => 'Gage', - sectionNumber => 1, - sessionKey => 'Not defined', - setNumber => 'MAAtutorial', - studentLogin => 'gage', - studentName => 'Mike Gage', - tempDirectory => '/ww/htdocs/tmp/gage_course/', - templateDirectory => '/ww/webwork/courses/gage_course/templates/', - tempURL => 'http://webwork-db.math.rochester.edu/tmp/gage_course/', - webworkDocsURL => 'http://webwork.math.rochester.edu/webwork_gage_system_html', - }; - $envir; -} diff --git a/clients/pr b/clients/pr deleted file mode 100755 index 20036afe17..0000000000 --- a/clients/pr +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -# inside the docker container -# this can be called from vim with :w ! ./pr - -# it sends the contents of the buffer to /var/www/html/xmlrpc_out.html aka localhost:8080/xmlrpc_output.html - -./sendXMLRPC.pl -h - >/var/www/html/xmlrpc_out.html - -# process STDIN with sendXMLRPC.p and send it to /var/www/html/xmlrpc_out.html -# where it can be read at localhost:8080/xmlrpc_out.html - - -# Not sure how to get rid of the ./ - -# This can also be called from the command line with cat t/input.pg |./pr diff --git a/clients/sendXMLRPC.pl b/clients/sendXMLRPC.pl deleted file mode 100755 index 84a652da8b..0000000000 --- a/clients/sendXMLRPC.pl +++ /dev/null @@ -1,1515 +0,0 @@ -#!/usr/bin/perl -w - -################################################################################ -# WeBWorK Online Homework Delivery System -# Copyright © 2000-2022 The WeBWorK Project, https://github.com/openwebwork -# -# 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. -################################################################################ - -=head1 NAME - -webwork2/clients/sendXMLRPC.pl - -=head1 DESCRIPTION - - -This module provides functions for rendering html from files outside the normal -context of providing a webwork homework set user an existing problem set. - -It can be used to create a live version of a single problem, one that is not -part of any set, and can facilitate editing these problems outside of the -context of WeBWorK2. - -This script will take a list of files or directories -and send it to a WeBWorK daemon webservice -to have it rendered. For directories each .pg file under that -directory is rendered. - -The results can be displayed in a browser (use -b or -B switches) as was -done with renderProblem.pl, on the command line (Use -h or -H switches) as -was done with renderProblem_rawoutput.pl or summary information about whether the -problem was correctly rendered can be sent to a log file (use -c or C switches). - -The capital letter switches, -B, -H, and -C render the question twice. The first -time returns an answer hash which contains the correct answers. The question is -then resubmitted to the renderer with the correct answers filled in and displayed. - -IMPORTANT: Create a valid credentials file (a sample file ww_credentials.dist is provided). - (See below.) - Locations where this file can be located: - "$ENV{HOME}/.ww_credentials" - "$ENV{HOME}/ww_session_credentials" - 'ww_credentials' - 'ww_credentials.dist' - The file sets the remove server and the local display/edit commands. - -IMPORTANT: Remember to configure: - 1. the local output file (near the top of this script) - 2. the display commands (in the ww_credentials file) - 3. the remote server to contact (in the ww_credentials file) - Things will NOT work until the configuration is done. - -This script is similar to standalonePGproblemRenderer.pl. It does not require a local WeBWorK site -on the same computer but does require an internet connection to a remote WeBWorK site. - -=cut - -=head1 SYNOPSIS - - sendXMLRPC -vcCbB input.pg - -=head1 DETAILS - -=head2 credentials file - - These locations are searched, in order, for the credentials file. - ("$ENV{HOME}/.ww_credentials", "$ENV{HOME}/ww_session_credentials", 'ww_credentials', 'ww_credentials.dist') - - Place a credential file containing the following information at one of the locations above - or create a file with this information and specify it with the --credentials option. - - # Cut here - top ============================================= - - # The sample settings below should be customized for your server and local system - - %credentials = ( - # Set the URLs of the remote site and the site password - - # Test settings for the demo.webwork.rochester.edu site - site_url => 'https://demo.webwork.rochester.edu', - form_action_url => 'https://demo.webwork.rochester.edu/webwork2/html2xml', - site_password => 'xmlrpc', - - # Settings for use with a local webwork system (ex. via Docker) - # site_url => 'http://localhost:80', - # form_action_url => 'http://localhost:80/webwork2/html2xml', - # site_password => 'xmlrpc', - # forcePortNumber => '80', # A port number to be forced, when needed. - - # Set the identification credential used by the "daemon_course" on the remote site - courseID => "daemon_course", - userID => "daemon", - course_password => "daemon", - # Set the display mode to use - ww_display_mode => "MathJax", - # Set the path to the LOCAL log file (make sure to create an empty file) - # when commented out - no file is needed - # path_to_log_file =>"", - # Set the display commands which work on the machine on which you are - # running sendXMLRPC.pl - # Sample settings for Mac: - - # html_display_command => "open -a 'Google Chrome' ", # A web browser - # html_display_command => "open -a Firefox ", - # tex_display_command => "open -a 'TeXShop'", # Editor or TeX editor - # pdf_display_command => "open -a 'Preview'", # PDF viewer - # hash_display_command => "cat ", # to diplay file to STDOUT - - # ============================== - - # Sample settings for Linux: - - # html_display_command => "firefox", # A web browser - # html_display_command => "google-chrome", - # tex_display_command => "vim", # Editor or TeX editor - # tex_display_command => "emacs", - # pdf_display_command => "xpdf", # PDF viewer - # pdf_display_command => "evince", - # pdf_display_command => "acroread", # PDF viewer - # hash_display_command => "cat ", # to diplay file to STDOUT - ); - - # Cut here - bottom ============================================= - - -=cut - -=head2 Options - -=over 4 - -=item -a - - Displays the answer hashes returned by the question on the command line. - -=item -A - - Same as -a but renders the question with the correct answers submitted. - -=item -b - - Display the rendered question in a browser (specified by the DISPLAY_HTML_COMMAND variable). - -=item -B - - Same as -b but renders the question with the correct answers submitted. - The evaluation of the answer submitted is displayed as well as the correct - answer. - -=item -h - - Prints to STDOUT the entire object returned by - the webwork_client xmlrpc request. - This includes the answer information displayed by -a and -A and much more. - -=item -H - - Same as -h but renders the question with the correct answers submitted - -=item -c - - "check" -- Record success or failure of rendering the question to a log file. - -=item -C - - Same as -c but the question is rendered with the correct answers submitted. - This succeeds only if the correct answers, as determined from the answer hash, all succeed. - -=item -f formatName - - Specify the format used by the browser in displaying the question. - Choices for s are - standard - sticky - debug - simple - -=item -l lang - - Set a language for the HTML rendering to use. Should use a value which would be valid for a course. - -=item -v - - Verbose output. Used mostly for debugging. - In particular it displays explicitly the correct answers - which are (will be) submitted to the question. - -=item -e - - Open the source file in an editor. - -=item --tex - - Process question in TeX mode and output to the command line - -=item --pdf - - Process question in TeX mode, convert to PDF and display. - -=item --json - - Process question in JSON mode and save to file -=item - - The single letter options can be "bundled" e.g. -vcCbB - -=item --list pg_list - - Read and process a list of .pg files contained in the file C. C - consists of a sequence of lines each of which contains the full path to a pg - file that should be processed. (For example this might be the output from an - earlier run of sendXMLRPC using the -c flag. ) - -=item --pg - - Triggers the printing of the all of the variables available to the PG question. - The table appears within the question content. Use in conjunction with -b or -B. - -=item --anshash - - Prints the answer hash for each answer in the PG_debug output which appears below - the question content. Use in conjunction with -b or -B. - Similar to -a or -A but the output appears in the browser and - not on the command line. - -=item --ansgrp - - Prints the PGanswergroup for each answer evaluator. The information appears in - the PG_debug output which follows the question content. Use in conjunction with -b or -B. - This contains more information than printing the answer hash. (perhaps too much). - -=item --resource - - Prints the resources used by the question. The information appears in - the PG_debug output which follows the question content. Use in conjunction with -b or -B. - -=item --credentials=s - - Specifies a file s where the credential information can be found. - -=item --help - - Prints help information. - -=item --log - - Sets path to log file - -=item --seed=s - - Sets problemSeed to the number contained in string s - -=item --psvn=s - - Sets psvn to the number contained in string s - - - -=back -=cut - -use strict; -use warnings; - -####################################################### -# Find the webwork2 root directory -####################################################### -BEGIN { - use File::Basename; - $main::dirname = dirname(__FILE__); -} - -use lib "$main::dirname"; -print "home directory " . $main::dirname . "\n"; -#use lib "."; # is this needed? - -# some files such as FormatRenderedProblem.pm may need to be in the same directory - -BEGIN { - die "WEBWORK_ROOT not found in environment. \n - WEBWORK_ROOT can be defined in your .cshrc or .bashrc file\n - It should be set to the webwork2 directory (e.g. /opt/webwork/webwork2)" - unless exists $ENV{WEBWORK_ROOT}; - # Unused variable, but define it twice to avoid an error message. - $WeBWorK::Constants::WEBWORK_DIRECTORY = $ENV{WEBWORK_ROOT}; - $WeBWorK::Constants::PG_DIRECTORY = "$ENV{WEBWORK_ROOT}/../pg/"; - unless (-r $WeBWorK::Constants::WEBWORK_DIRECTORY) { - die "Cannot read webwork root directory at $WeBWorK::Constants::WEBWORK_DIRECTORY"; - } - unless (-r $WeBWorK::Constants::PG_DIRECTORY) { - die "Cannot read webwork pg directory at $WeBWorK::Constants::PG_DIRECTORY"; - } - -} -use lib "$WeBWorK::Constants::WEBWORK_DIRECTORY/lib"; - -use Carp; -use LWP::Protocol::https; -use Time::HiRes qw/time/; -use MIME::Base64 qw( encode_base64 decode_base64); -use Getopt::Long qw[:config no_ignore_case bundling]; -use File::Find; -use FileHandle; -use File::Path; -use File::Temp qw/tempdir/; -use String::ShellQuote; -use Cwd 'abs_path'; -use WebworkClient; -use FormatRenderedProblem; -#use Proc::ProcessTable; # use in standalonePGproblemRenderer - -use 5.10.0; -$Carp::Verbose = 1; - -### verbose output when UNIT_TESTS_ON =1; -our $UNIT_TESTS_ON = 0; - -############################################################ -# Read command line options -############################################################ - -my $display_ans_output1 = ''; -my $display_hash_output1 = ''; -my $display_html_output1 = ''; -my $record_ok1 = ''; # subroutine needs to be constructed -my $display_ans_output2 = ''; -my $display_hash_output2 = ''; -my $display_html_output2 = ''; -my $record_ok2 = ''; -my $verbose = ''; -my $credentials_path; -my $format = 'standard'; -my $lang = 'en'; -my $edit_source_file = ''; -my $display_tex_output = ''; -my $display_pdf_output = ''; -my $display_json_output = ''; -my $print_answer_hash; -my $print_answer_group; -my $print_pg_hash; -my $print_resource_hash; -my $print_help_message; -my $read_list_from_this_file; -my $path_to_log_file; -my $problemSeed; -my $psvn; - -our %credentials; -our @path_list; -my $credentials_string; - -GetOptions( - 'a' => \$display_ans_output1, - 'A' => \$display_ans_output2, - 'b' => \$display_html_output1, - 'B' => \$display_html_output2, - 'h' => \$display_hash_output1, - 'H' => \$display_hash_output2, - 'c' => \$record_ok1, # record_problem_ok1 needs to be written - 'C' => \$record_ok2, - 'v' => \$verbose, - 'e' => \$edit_source_file, - 'tex' => \$display_tex_output, - 'pdf' => \$display_pdf_output, - 'json' => \$display_json_output, - 'list=s' => \$read_list_from_this_file, # read file containing list of full file paths - 'pg' => \$print_pg_hash, - 'anshash' => \$print_answer_hash, - 'ansgrp' => \$print_answer_group, - 'resource' => \$print_resource_hash, - 'f=s' => \$format, - 'l=s' => \$lang, - 'credentials=s' => \$credentials_path, - 'help' => \$print_help_message, - 'log=s' => \$path_to_log_file, - 'seed=s' => \$problemSeed, - 'psvn=s' => \$psvn, -); - -print_help_message() if $print_help_message; - -############################################################ -# End Read command line options -############################################################ - -################################################################################ - -# Move up the reading of credential files to here in order to get -# WEBWORK_URL defined before it is needed. (For Docker installs when -# called from outside Docker, it may not be in the environment variables.) - -#################################################### -# get credentials -#################################################### - -# credentials are needed -# credentials file location -- search for one of these files - -@path_list = - ("$ENV{HOME}/.ww_credentials", "$ENV{HOME}/ww_session_credentials", 'ww_credentials', 'ww_credentials.dist'); - -$credentials_string = < 'https://demo.webwork.rochester.edu', - form_action_url => 'https://demo.webwork.rochester.edu/webwork2/html2xml', - site_password => 'xmlrpc', - - # Settings for use with a local webwork system (ex. via Docker) - # site_url => 'http://localhost:80', - # form_action_url => 'http://localhost:80/webwork2/html2xml', - # site_password => 'xmlrpc', - # forcePortNumber => '80', # A port number to be forced, when needed. - - - # Set the identification credential used by the "daemon_course" on the remote site - courseID => "daemon_course", - userID => "daemon", - course_password => "daemon", - # Set the display mode to use - ww_display_mode => "MathJax", - # Set the path to the LOCAL log file (make sure to create an empty file) - # when commented out - no file is needed - # path_to_log_file =>"", - # Set the display commands which work on the machine on which you are - # running sendXMLRPC.pl - # Sample settings for Mac: - - - # html_display_command => "open -a 'Google Chrome' ", # A web browser - - # html_display_command => "open -a Firefox ", - # tex_display_command => "open -a 'TeXShop'", # Editor or TeX editor - # pdf_display_command => "open -a 'Preview'", # PDF viewer - # hash_display_command => "cat ", # to diplay file to STDOUT - - # ============================== - - # Sample settings for Linux: - - # html_display_command => "firefox", # A web browser - # html_display_command => "google-chrome", - # tex_display_command => "vim", # Editor or TeX editor - # tex_display_command => "emacs", - # pdf_display_command => "xpdf", # PDF viewer - # pdf_display_command => "evince", - # pdf_display_command => "acroread", # PDF viewer - # hash_display_command => "cat ", # to diplay file to STDOUT - ); - -EOF -if (defined $credentials_path and (-r $credentials_path)) { - # we're all set -} elsif (defined $credentials_path) { #can't find credentials - die "Can't find credentials file $credentials_path searching\n"; -} - -if (defined $credentials_path and (-r $credentials_path)) { - # we're all set -} elsif (defined $credentials_path) { #can't find credentials - die "Can't find credentials file $credentials_path searching\n"; -} - -# if credentials_path not set explicitly go look for a credentials file. -unless (defined $credentials_path) { - foreach my $path (@path_list) { - print "looking for credentials file: $path. -- " . ((-r $path) ? 'found!' : '(not found)') . "\n" if $verbose; - next unless defined $path; - if (-r $path) { - $credentials_path = $path; - last; - } - } -} - -# verify that a credentials file has been found - -if ($credentials_path) { - print STDERR "Credentials taken from file $credentials_path\n" if $verbose; -} else { #failed to find credentials file - die <$credentials{$_} \n"; } -} - -################################################################################ - -use lib "$WeBWorK::Constants::WEBWORK_DIRECTORY/lib"; -use lib "$WeBWorK::Constants::PG_DIRECTORY/lib"; - -use WebworkClient; -use FormatRenderedProblem; -#use Proc::ProcessTable; # use in standalonePGproblemRenderer - -use 5.10.0; -$Carp::Verbose = 1; - -############################################# -# CONFIGURE -# -# Configure displays for local operating system -# This section will differ from on operating system to another -# The default code is for the macOS and applications commonly available on macOS. -############################################# - -#Default display commands. -use constant HTML_DISPLAY_COMMAND => "open -a 'Google Chrome' "; # (MacOS command) -use constant HASH_DISPLAY_COMMAND => ""; # display tempoutputfile to STDOUT - -### Path to a temporary file for storing the output of sendXMLRPC.pl -use constant TEMPOUTPUTDIR => "$ENV{WEBWORK_ROOT}/DATA/"; -die "You must make the directory " . TEMPOUTPUTDIR() . " writeable " unless -w TEMPOUTPUTDIR(); -use constant TEMPOUTPUTFILE => TEMPOUTPUTDIR() . "temporary_output.html"; - -### Default path to a temporary file for storing the output -### of sendXMLRPC.pl -use constant LOG_FILE => "$ENV{WEBWORK_ROOT}/DATA/xmlrpc_results.log"; - -### Command for editing the pg source file in the browswer -use constant EDIT_COMMAND => "bbedit"; # for Mac BBedit editor (used as `EDIT_COMMAND() . " $file_path") - -### Command for editing and viewing the tex output of the pg question. -use constant TEX_DISPLAY_COMMAND => "open -a 'TeXShop'"; - -### Command for editing and viewing the tex output of the pg question. -use constant PDF_DISPLAY_COMMAND => "open -a 'Preview'"; - -### set display mode -use constant DISPLAYMODE => 'MathJax'; -use constant PROBLEMSEED => '987654321'; - -############################################################ -# End configure displays for local operating system -############################################################ - -#allow credentials to overrride the default displayMode -#and the browser display -our $HTML_DISPLAY_COMMAND = $credentials{html_display_command} // HTML_DISPLAY_COMMAND(); -our $HASH_DISPLAY_COMMAND = $credentials{hash_display_command} // HASH_DISPLAY_COMMAND(); -our $DISPLAYMODE = $credentials{ww_display_mode} // DISPLAYMODE(); -our $TEX_DISPLAY_COMMAND = $credentials{tex_display_command} // TEX_DISPLAY_COMMAND(); -our $PDF_DISPLAY_COMMAND = $credentials{pdf_display_command} // PDF_DISPLAY_COMMAND(); - -################################################## -# END gathering credentials for client -################################################## - -################################################## -# create course environment and create log files -################################################## - -# course environment is provided by caller and credentials for sendXMLRPC - -$path_to_log_file = $path_to_log_file // $credentials{path_to_log_file} // LOG_FILE(); #set log file path. - -eval { # attempt to create log file - local (*FH); - open(FH, '>>:encoding(UTF-8)', $path_to_log_file) or die "Can't open file $path_to_log_file for writing"; - close(FH); -}; - -die "You must first create an output file at $path_to_log_file - with permissions 777 " unless -w $path_to_log_file; - -################################################## -# set default inputs for the problem -################################################## - -############################################ -# Build client defaults -############################################ - -my $default_input = { - userID => $credentials{userID} // '', - session_key => $credentials{session_key} // '', - courseID => $credentials{courseID} // '', - courseName => $credentials{courseID} // '', - course_password => $credentials{course_password} // '', -}; - -my $default_form_data = { - displayMode => $DISPLAYMODE, - outputformat => $format // 'standard', - problemSeed => $problemSeed // PROBLEMSEED(), - psvn => $psvn // '23456', - forcePortNumber => $credentials{forcePortNumber} // '', - language => $lang // 'en', -}; - -################################################## -# end build client -################################################## - -################################################## -# MAIN SECTION gather and process problem template files -################################################## -my $cg_start = time; # this is Time::HiRes's time, which gives floating point values - -our @files_and_directories = @ARGV; -# print "files ", join("|", @files_and_directories), "\n"; -if ($read_list_from_this_file) { - # read a datafile containing list of files to be processed - my $FH = FileHandle->new(" < $read_list_from_this_file"); - while (<$FH>) { - my $item = $_; - chomp($item); - my $file_path = abs_path($item); - unless (defined $file_path and -f $file_path) { - warn "skipping $item\n" unless defined $file_path; - warn "skipping $file_path\n" if defined $file_path; - next; - } - next if $file_path =~ /^\s*#/; # comment lines - next unless $file_path =~ /\.pg$/; - next if $file_path =~ /\-text\.pg$/; - next if $file_path =~ /header/i; - process_pg_file($file_path); - } - FileHandle::close($FH); - -} else { - foreach my $item (@files_and_directories) { - if (-d $item) { # if the item is a directory traverse the tree - my $dir = abs_path($item); - find(\&wanted, ($dir)); - } elsif ($item eq "-") { - process_pg_file($item); # process STDIN - } elsif (-f $item) { # if the item is a file process it. - my $file_path = abs_path($item); - next unless $file_path =~ /\.pg$/; # only process pg files - next if $file_path =~ /\-text\.pg$/; # don't process auxiliary include files - next if $file_path =~ /header/i; # don't process header files - process_pg_file($file_path); - } else { - print "$item cannot be found or read\n"; - } - } -} - -sub wanted { - return '' unless $File::Find::name =~ /\.pg$/; - return '' if $File::Find::name =~ /\-text\.pg$/; - return '' if $File::Find::name =~ /header/i; - eval { process_pg_file($File::Find::name) if -f $File::Find::name; }; - warn "Error in processing $File::Find::name: $@" if $@; -} - -########################################################## -# Subroutines -########################################################## - -####################################################################### -# Process the pg file -####################################################################### - -sub process_pg_file { - my $file_path = shift; - my $NO_ERRORS = ""; - my $ALL_CORRECT = ""; - my $form_data1 = { - %$default_form_data, - - }; - - if ($display_tex_output or $display_pdf_output) { - my $form_data2 = { - %$form_data1, - displayMode => 'tex', - outputformat => 'tex', - }; - print "process tex files\n" if $UNIT_TESTS_ON; - my ($error_flag, $formatter, $error_string) = process_problem($file_path, $default_input, $form_data2); - - # create tex file for both and tex and pdf output - my $tex_file_name = create_tex_output($file_path, $formatter); - # display tex file if --tex option is set - if ($display_tex_output) { - system($TEX_DISPLAY_COMMAND. " " . TEMPOUTPUTDIR() . $tex_file_name); - } elsif ($display_pdf_output) { # process tex file to create pdf file and display if --pdf option - my $pdf_path = create_pdf_output($tex_file_name); - system($PDF_DISPLAY_COMMAND. " " . $pdf_path); - } - } - if ($display_json_output) { - my $form_data2 = { - %$form_data1, - outputformat => 'json', - displayMode => 'MathJax', - }; - print "Creating json\n" if $UNIT_TESTS_ON; - my ($error_flag, $formatter, $error_string) = process_problem($file_path, $default_input, $form_data2); - my $json_file_name = create_json_output($file_path, $formatter); - print("Created JSON data in file ", TEMPOUTPUTDIR(), $json_file_name, "\n"); - exit; - } - my ($error_flag, $formatter, $error_string) = process_problem($file_path, $default_input, $form_data1); - # extract and display result - #print "display $file_path\n"; - edit_source_file($file_path) if $edit_source_file; - display_html_output($file_path, $formatter) if $display_html_output1; - display_hash_output($file_path, $formatter) if $display_hash_output1; - display_ans_output($file_path, $formatter) if $display_ans_output1; - $NO_ERRORS = record_problem_ok1($error_flag, $formatter, $file_path) if $record_ok1; - - unless ($display_html_output2 or $display_hash_output2 or $display_ans_output2 or $record_ok2) { - print "DONE -- $NO_ERRORS -- \n" if $verbose; - return; - } - ################################################################# - # Extract correct answers - ################################################################# - - my %correct_answers = (); - my $some_correct_answers_not_specified = 0; - foreach my $ans_id (keys %{ $formatter->return_object->{answers} }) { - my $ans_obj = $formatter->return_object->{answers}->{$ans_id}; - # the answergrps are in PG_ANSWERS_HASH - my $answergroup = $formatter->return_object->{PG_ANSWERS_HASH}->{$ans_id}; - my @response_order = @{ $answergroup->{response}->{response_order} }; - #print scalar(@response_order), " first response $response_order[0] $ans_id\n"; - $ans_obj->{type} = $ans_obj->{type} // ''; #make sure it's defined. - if ($ans_obj->{type} eq 'MultiAnswer') { - # singleResponse multianswer type - # an outrageous hack - print "handling MultiAnswer singleResponse type\n" if $verbose; - my $ans_str1 = $ans_obj->{correct_ans}; - my @ans_array1 = split(/\s*;\s*/, $ans_str1); - $correct_answers{$ans_id} = shift @ans_array1; - my $num_extra_elements = scalar(@ans_array1); - foreach my $i (1 .. $num_extra_elements) { # pick up the remaining blanks - my $response_id = "MuLtIaNsWeR_${ans_id}_${i}"; #MuLtIaNsWeR_AnSwEr0003_1 - $correct_answers{$response_id} = shift @ans_array1; - #print "\t\t $response_id => $correct_answers{$response_id}\n"; - } - } elsif ($ans_obj->{type} =~ /checkbox/i) { #type is probably checkbox_cmp - my $ans_str = $ans_obj->{correct_ans}; #an unseparated answer string - $ans_str =~ s/^\s*//; - $ans_str =~ s/\s*$//; #trim white space off ends (probably unnecessary) - my @temp = split("", $ans_str); #split into array of characters - my $new_ans_str = join("\0", @temp); # join them in "packed" form separated with nulls - $correct_answers{$ans_id} = $new_ans_str; - } elsif (1 == @response_order and $ans_id eq $response_order[0]) { - # only one response -- not MultiAnswer singleResponse - # most answers are of this type - # should we use correct answer or correct value? -- this seems to vary - #warn "just one answer blank for this answer evaluator"; - $correct_answers{$ans_id} = ($ans_obj->{correct_ans}) // ($ans_obj->{correct_value}); - } else { # more than one response - if ($ans_obj->{type} =~ /Matrix/) { - #FIXME -- another outrageous hackkkk but it works - #print "responding to matrix answer with several ans_blanks\n"; - #print "responses", join(" ", %{$answergroup->{response}->{responses}}),"\n"; - #print "correct answer ", $ans_obj->{correct_value}, "\n"; - my $ans_str = ($ans_obj->{correct_value}) - // ($ans_obj->{correct_ans}) - ; #(correct_ans can have html formatting -- not good) $ans_str =~ s/\[//g; - $ans_str =~ s/\]//g; - my @ans_array = split(/\s*,\s*/, $ans_str); - foreach my $response_id (@response_order) { - $correct_answers{$response_id} = shift @ans_array; - } - } else { - warn "responding to an answer evaluator of type |" - . $ans_obj->{type} - . "| with " - . scalar(@response_order) - . " ans_blanks: ", join(" ", @response_order), "\n" - if $UNIT_TESTS_ON; - $correct_answers{$ans_id} = ($ans_obj->{correct_ans}) // ($ans_obj->{correct_value}) // ''; - } - } - #FIXME hack to get rid of html protection of < and > for vectors - $correct_answers{$ans_id} =~ s/>/>/g; - $correct_answers{$ans_id} =~ s/</||g; # some answers have breaks in them for clarity - if ($correct_answers{$ans_id} eq "No correct answer specified") { - warn "this question has an answer blank with no correct answer specified"; - $some_correct_answers_not_specified++; - } - - } #end loop collecting correct answers. - # adjust input and reinitialize form_data - my $form_data2 = { - %$default_form_data, - answersSubmitted => 1, - WWsubmit => 1, # grade answers - WWcorrectAns => 1, # show correct answers - %correct_answers - }; - - my $pg_start = time; # this is Time::HiRes's time, which gives floating point values - - ($error_flag, $formatter, $error_string) = (); - ($error_flag, $formatter, $error_string) = process_problem($file_path, $default_input, $form_data2); - my $pg_stop = time; - my $pg_duration = $pg_stop - $pg_start; - - display_html_output($file_path, $formatter) if $display_html_output2; - display_hash_output($file_path, $formatter) if $display_hash_output2; - display_ans_output($file_path, $formatter) if $display_ans_output2; - $ALL_CORRECT = - record_problem_ok2($error_flag, $formatter, $file_path, $some_correct_answers_not_specified, $pg_duration) - if $record_ok2; - #print "display the correct answers here"; - display_inputs(%correct_answers) if $verbose; # choice of correct answers submitted - # should this information on what answers are being submitted have an option switch? - - print "DONE -- $NO_ERRORS -- $ALL_CORRECT\n" if $verbose; -} - -####################################################################### -# Auxiliary subroutines -####################################################################### - -sub process_problem { - my $file_path = shift; - my $input = shift; - my $form_data = shift; - # %credentials is global - - ### get source and correct file_path name so that it is relative to templates directory - - my ($adj_file_path, $source) = get_source($file_path); - #print "find file at $adj_file_path ", length($source), "\n"; - - ### build client - my $xmlrpc_client = new WebworkClient( - site_url => $credentials{site_url}, - form_action_url => $credentials{form_action_url}, - site_password => $credentials{site_password} // '', - courseID => $credentials{courseID}, - userID => $credentials{userID}, - session_key => $credentials{session_key} // '', - sourceFilePath => $adj_file_path, - ); - - ### update client - $xmlrpc_client->encodeSource($source); - $xmlrpc_client->form_data($form_data); - - ### update inputs - my $problemSeed = $form_data->{problemSeed}; - die "problem seed not defined in sendXMLRPC::process_problem" unless $problemSeed; - - my $local_psvn = $form_data->{psvn} // 34567; - my $updated_input = { - %$input, - envir => $xmlrpc_client->environment( - fileName => $adj_file_path, - sourceFilePath => $adj_file_path, - psvn => $local_psvn, - problemSeed => $problemSeed, - ), - }; - - $form_data->{showAnsGroupInfo} = $print_answer_group; - $form_data->{showAnsHashInfo} = $print_answer_hash; - $form_data->{showPGInfo} = $print_pg_hash; - $form_data->{showResourceInfo} = $print_resource_hash; - - ################################################## - # Process the pg file - ################################################## - ### store the time before we invoke the content generator - my $cg_start = time; # this is Time::HiRes's time, which gives floating point values - - ############################################ - # Call server via xmlrpc_client to render problem - ############################################ - - our ($return_object, $error_flag, $error_string); - $error_flag = 0; - $error_string = ''; - - $return_object = $xmlrpc_client->xmlrpcCall('renderProblem', $updated_input); - - ####################################################################### - # Handle errors - ####################################################################### - - unless ($xmlrpc_client->fault) { - print "\n\n Result of renderProblem \n\n" if $UNIT_TESTS_ON; - print pretty_print_rh($return_object) if $UNIT_TESTS_ON; - if (not defined $return_object) { #FIXME make sure this is the right error message if site is unavailable - $error_string = "0\t Could not connect to rendering site " . $xmlrpc_client->{url} . "\n"; - } elsif (defined($return_object->{flags}->{error_flag}) and $return_object->{flags}->{error_flag}) { - $error_string = "0\t $file_path has errors\n"; - } elsif (defined($return_object->{errors}) and $return_object->{errors}) { - $error_string = "0\t $file_path has syntax errors\n"; - } - $error_flag = 1 if $return_object->{errors}; - } else { - $error_flag = 1; - $error_string = $xmlrpc_client->return_object; # error report - } - -################################################## - # Create FormatRenderedProblems object -- not needed for sendXMLRPC -################################################## - - ################################################## - # log elapsed time - ################################################## - my $scriptName = 'sendXMLRPC'; - my $cg_end = time; - my $cg_duration = $cg_end - $cg_start; - WebworkClient::writeRenderLogEntry( - "", - "{script:$scriptName; file:$file_path; " - . sprintf("duration: %.3f sec;", $cg_duration) - . " site_url: $credentials{site_url}; }", - '' - ); - - ####################################################################### - # End processing of the pg file - ####################################################################### - my $formatter = $xmlrpc_client; ## for compatibility with standalonePGproblemRenderer - return $error_flag, $formatter, $error_string; -} - -sub create_pdf_output { - my $tex_file_name = shift; - my @errors = (); - print "pdf mode\n" if $UNIT_TESTS_ON; - my $pdf_file_name = $tex_file_name; - $pdf_file_name =~ s/\.\w+$/\.pdf/; # replace extension with pdf - - ########################################## - # create working directory - ########################################## - - # create a randomly-named working directory in the TEMPOUTPUTDIR() directory - my $working_dir_path = eval { tempdir("work.XXXXXXXX", DIR => TEMPOUTPUTDIR()) }; - if ($@) { - push @errors, "Couldn't create temporary working directory: $@"; - } - # make sure the directory can be read by other daemons e.g. lighttpd - chmod 0755, $working_dir_path; - - # do some error checking - unless (-e $working_dir_path) { - push @errors, - "Temporary directory " - . $working_dir_path - . " does not exist, but creation didn't fail. This shouldn't happen."; - } - unless (-w $working_dir_path) { - push @errors, "Temporary directory " . $working_dir_path . " is not writeable."; - - } - - # catch errors if directory is not made (should be global, outside subroutine) - if (@errors) { - print "There were errors in creating the working directory for processing tex to pdf. \n" . join("\n", @errors); - delete_temp_dir($working_dir_path); - return 0; # FAIL if no working directory - } - - ######################################## - # try to mv the tex file into the working directory - ######################################## - - my $src_path = TEMPOUTPUTDIR() . $tex_file_name; - my $dest_path = "$working_dir_path/$tex_file_name"; - my $mv_cmd = "2>&1 mv " . shell_quote("$src_path", "$dest_path"); - my $mv_out = readpipe $mv_cmd; - if ($?) { - push @errors, "Failed to rename $src_path to " . "$dest_path in directory \n" . "$mv_out"; - print join("\n", @errors); - } - - ########################################## - # process tex file to pdf (if working directory was created) - ########################################## - @errors = (); # reset errors - - my $tex_file_path = $dest_path; - my $pdf_path = "$working_dir_path/$pdf_file_name"; - print "pdflatex $tex_file_path\n" if $UNIT_TESTS_ON; - - # call pdflatex - we don't want to chdir in the mod_perl process, as - # that might step on the feet of other things (esp. in Apache 2.0) - my $pdflatex_cmd = "cd " - . shell_quote($working_dir_path) . " && " - . "pdflatex" - . " $tex_file_name >pdflatex.stdout 2>pdflatex.stderr hardcopy"; - if (my $rawexit = system $pdflatex_cmd) { - my $exit = $rawexit >> 8; - my $signal = $rawexit & 127; - my $core = $rawexit & 128; - push @errors, - "Failed to convert TeX to PDF with command $pdflatex_cmd))" . " (exit=$exit signal=$signal core=$core)."; - - # read hardcopy.log and report first error - my $hardcopy_log = "$working_dir_path/$tex_file_name"; - $hardcopy_log =~ s/\.tex$/\.log/; # replace extension - if (-e $hardcopy_log) { - if (open my $LOG, "<", $hardcopy_log) { - my $line; - while ($line = <$LOG>) { - last if $line =~ /^!\s+/; - } - my $first_error = $line; - while ($line = <$LOG>) { - last if $line =~ /^!\s+/; - $first_error .= $line; - } - close $LOG; - if (defined $first_error) { - push @errors, "First error in TeX log is: $first_error"; - } else { - push @errors, "No errors encoundered in TeX log."; - } - } else { - push @errors, "Could not read TeX log: $!"; - } - } else { - push @errors, "No TeX log was found."; - } - } - - ######################################## - # try to rename the pdf file - ######################################## - - my $src_path1 = $pdf_path; - my $final_pdf_path = TEMPOUTPUTDIR() . $pdf_file_name; - my $mv_cmd1 = "2>&1 mv " . shell_quote("$src_path1", "$final_pdf_path"); - my $mv_out1 = readpipe $mv_cmd1; - if ($?) { - push @errors, "Failed to rename $src_path to " . "$final_pdf_path in directory \n" . "$mv_out1"; - } - - ################################################## - # remove the temp directory if there are no errors - ################################################## - if (@errors) { - print "Errors in converting the tex file to pdf: " . join("\n", @errors); - return 0; - } - - unless (@errors or $UNIT_TESTS_ON) { - delete_temp_dir($working_dir_path); - } - - # return path to pdf file - print "pdflatex to $final_pdf_path DONE\n" if $UNIT_TESTS_ON; - # this is doable but will require changing directories - # look at the solution done using hardcopy - return $final_pdf_path; -} - -# helper function to remove temp dirs -sub delete_temp_dir { - my ($temp_dir_path) = @_; - - my $rm_cmd = "2>&1 rm -rf " . shell_quote($temp_dir_path); #can use perl command for this?? - my $rm_out = readpipe $rm_cmd; - if ($?) { - print "Failed to remove temporary directory '" . $temp_dir_path . "':\n$rm_out\n"; - return 0; - } else { - return 1; - } -} - -sub create_tex_output { - my $file_path = shift; - my $formatter = shift; - my $output_text = $formatter->formatRenderedProblem; - $file_path =~ s|/$||; # remove final / - $file_path =~ m|/?([^/]+)$|; - my $file_name = $1; - $file_name =~ s/\.\w+$/\.tex/; # replace extension with tex - my $output_file = TEMPOUTPUTDIR() . $file_name; - local (*FH); - open(FH, '>:encoding(UTF-8)', $output_file) or die "Can't open file $output_file for writing"; - print FH $output_text; - close(FH); - print "tex result sent to $output_file\n" if $UNIT_TESTS_ON; - # sleep 5; #wait 5 seconds - # unlink($output_file); - return $file_name; -} - -sub create_json_output { - my $file_path = shift; - my $formatter = shift; - my $output_text = $formatter->formatRenderedProblem; - $file_path =~ s|/$||; # remove final / - $file_path =~ m|/?([^/]+)$|; - my $file_name = $1; - $file_name =~ s/\.\w+$/\.json/; # replace extension with json - my $output_file = TEMPOUTPUTDIR() . $file_name; - local (*FH); - open(FH, '>:encoding(UTF-8)', $output_file) or die "Can't open file $output_file for writing"; - print FH $output_text; - close(FH); - print "json result sent to $output_file\n" if $UNIT_TESTS_ON; - # sleep 5; #wait 5 seconds - # unlink($output_file); - return $file_name; -} - -sub display_html_output { #display the problem in a browser - my $file_path = shift; - my $formatter = shift; - my $output_text = $formatter->formatRenderedProblem; - $file_path =~ s|/$||; # remove final / - $file_path =~ m|/?([^/]+)$|; - my $file_name = $1; - $file_name =~ s/\.\w+$/\.html/; # replace extension with html - my $output_file = TEMPOUTPUTDIR() . $file_name; - local (*FH); - open(FH, '>:encoding(UTF-8)', $output_file) or die "Can't open file $output_file for writing"; - print FH $output_text; - close(FH); - - system($HTML_DISPLAY_COMMAND. " " . $output_file); - sleep 5; #wait 1 seconds - unlink($output_file); -} - -sub display_hash_output { # print the entire hash output to the command line - my $file_path = shift; - my $formatter = shift; - my $output_text = $formatter->formatRenderedProblem; - $file_path =~ s|/$||; # remove final / - $file_path =~ m|/?([^/]+)$|; - my $file_name = $1; - $file_name =~ s/\.\w+$/\.txt/; # replace extension with html - my $output_file = TEMPOUTPUTDIR() . $file_name; - my $output_text2 = pretty_print_rh($output_text); - print STDOUT $output_text2; - - # local(*FH); - # open(FH, '>', $output_file) or die "Can't open file $output_file writing"; - # print FH $output_text2; - # close(FH); - # - # system($HASH_DISPLAY_COMMAND().$output_file."; rm $output_file;"); - #sleep 1; #wait 1 seconds - #unlink($output_file); -} - -sub display_ans_output { # print the collection of answer hashes to the command line - my $file_path = shift; - my $formatter = shift; - my $return_object = $formatter->return_object; - $file_path =~ s|/$||; # remove final / - $file_path =~ m|/?([^/]+)$|; - my $file_name = $1; - $file_name =~ s/\.\w+$/\.txt/; # replace extension with html - my $output_file = TEMPOUTPUTDIR() . $file_name; - my $output_text = pretty_print_rh($return_object->{answers}); - print STDOUT $output_text; - # local(*FH); - # open(FH, '>', $output_file) or die "Can't open file $output_file writing"; - # print FH $output_text; - # close(FH); - # - # system($HASH_DISPLAY_COMMAND().$output_file."; rm $output_file;"); - # sleep 1; #wait 1 seconds - # unlink($output_file); -} - -sub record_problem_ok1 { - my $error_flag = shift // ''; - my $formatter = shift; # for formatting - my $file_path = shift; - my $return_string = ''; - my $return_object = $formatter->return_object; - if (defined($return_object->{flags}->{DEBUG_messages})) { - my @debug_messages = @{ $return_object->{flags}->{DEBUG_messages} }; - $return_string .= (pop @debug_messages) || ''; #avoid error if array was empty - if (@debug_messages) { - $return_string .= join(" ", @debug_messages); - } else { - $return_string = ""; - } - } - if (defined($return_object->{errors})) { - $return_string = $return_object->{errors}; - } - if (defined($return_object->{flags}->{WARNING_messages})) { - my @warning_messages = @{ $return_object->{flags}->{WARNING_messages} }; - $return_string .= (pop @warning_messages) || ''; #avoid error if array was empty - $@ = undef; - if (@warning_messages) { - $return_string .= join(" ", @warning_messages); - } else { - $return_string = ""; - } - } - my $SHORT_RETURN_STRING = ($return_string) ? "has errors" : "ok"; - unless ($return_string) { - $return_string = "1\t $file_path is ok\n"; - } else { - $return_string = "0\t $file_path has errors\n"; - } - - local (*FH); - open(FH, '>>:encoding(UTF-8)', $path_to_log_file) or die "Can't open file $path_to_log_file for writing"; - print FH $return_string; - close(FH); - return $SHORT_RETURN_STRING; -} - -sub record_problem_ok2 { - my $error_flag = shift // ''; - my $formatter = shift; - my $file_path = shift; - my $some_correct_answers_not_specified = shift; - my $pg_duration = shift; #processing time - my $return_object = $formatter->return_object; - my %scores = (); - my $ALL_CORRECT = 0; - my $all_correct = ($error_flag) ? 0 : 1; - - foreach my $ans (keys %{ $return_object->{answers} }) { - $scores{$ans} = - $return_object->{answers}->{$ans}->{score}; - $all_correct = $all_correct && $scores{$ans}; - } - $all_correct = ".5" if $some_correct_answers_not_specified; - $ALL_CORRECT = ($all_correct == 1) ? 'All answers are correct' : 'Some answers are incorrect'; - local (*FH); - open(FH, '>>:encoding(UTF-8)', $path_to_log_file) or die "Can't open file $path_to_log_file for writing"; - print FH "$all_correct $file_path\n"; # do we need this? compile_errors=$error_flag\n"; - close(FH); - return $ALL_CORRECT; -} - -########################################### -# standalonePGproblemRenderer -- not needed for sendXMLRPC -########################################### - -################################################## -# utilities -################################################## - -sub display_inputs { - my %correct_answers = @_; - foreach my $key (sort keys %correct_answers) { - print "$key => $correct_answers{$key}\n"; - } -} - -sub edit_source_file { - my $file_path = shift; - system(EDIT_COMMAND() . " $file_path"); -} - -################################################## -# Get problem template source and adjust file_path name -################################################## - -sub get_source { - my $file_path = shift; - my $source; - die "Unable to read file $file_path \n" unless $file_path eq '-' or -r $file_path; - eval { #File::Slurp would be faster (see perl monks) - local $/ = undef; - if ($file_path eq '-') { - $source = ; - } else { - # To support proper behavior with UTF-8 files, we need to open them with "<:encoding(UTF-8)" - # as otherwise, the first HTML file will render properly, but when "Preview" "Submit answer" - # or "Show correct answer" is used it will make problems, as in process_problem() the - # encodeSource() method is called on a data which is still UTF-8 encoded, and leads to double - # encoding and gibberish. - # NEW: - open(FH, "<:encoding(UTF-8)", $file_path) or die "Couldn't open file $file_path: $!"; - # OLD: - #open(FH, "<" ,$file_path) or die "Couldn't open file $file_path: $!"; - $source = ; #slurp input - close FH; - } - }; - die "Something is wrong with the contents of $file_path\n" if $@; - ### adjust file_path so that it is relative to the rendering course directory - #$file_path =~ s|/opt/webwork/libraries/NationalProblemLibrary|Library|; - $file_path =~ s|^.*?/webwork-open-problem-library/OpenProblemLibrary|Library|; - print "file_path changed to $file_path\n" if $UNIT_TESTS_ON; - print $source if $UNIT_TESTS_ON; - return $file_path, $source; -} - -################################################## -# utilities -################################################## - -sub pretty_print_rh { - shift if UNIVERSAL::isa($_[0] => __PACKAGE__); - my $rh = shift; - my $indent = shift || 0; - my $out = ""; - my $type = ref($rh); - - if (defined($type) and $type) { - $out .= " type = $type; "; - } elsif (!defined($rh)) { - $out .= " type = UNDEFINED; "; - } - return $out . " " unless defined($rh); - - if (ref($rh) =~ /HASH/) { - $out .= "{\n"; - $indent++; - foreach my $key (sort keys %{$rh}) { - $out .= " " x $indent . "$key => " . pretty_print_rh($rh->{$key}, $indent) . "\n"; - } - $indent--; - $out .= "\n" . " " x $indent . "}\n"; - - } elsif (ref($rh) =~ /ARRAY/ or "$rh" =~ /ARRAY/) { - $out .= " ( "; - foreach my $elem (@{$rh}) { - $out .= pretty_print_rh($elem, $indent); - - } - $out .= " ) \n"; - } elsif (ref($rh) =~ /SCALAR/) { - $out .= "scalar reference " . ${$rh}; - } elsif (ref($rh) =~ /Base64/) { - $out .= "base64 reference " . $$rh; - } else { - $out .= $rh; - } - - return $out . " "; -} - -############################################ -# Help message -############################################ - -sub print_help_message { - print <<'EOT'; -NAME - webwork2/clients/sendXMLRPC.pl - -DESCRIPTION - This script will take a list of files or directories and send it to a - WeBWorK daemon webservice to have it rendered. For directories each .pg - file under that directory is rendered. - - The results can be displayed in a browser (use -b or -B switches) as was - done with renderProblem.pl, on the command line (Use -h or -H switches) - as was done with renderProblem_rawoutput.pl or summary information about - whether the problem was correctly rendered can be sent to a log file - (use -c or C switches). - - The capital letter switches, -B, -H, and -C render the question twice. - The first time returns an answer hash which contains the correct - answers. The question is then resubmitted to the renderer with the - correct answers filled in and displayed. - - IMPORTANT: Remember to configure the local output file and display - command near the top of this script. !!!!!!!! - - IMPORTANT: Create a valid credentials file. - -SYNOPSIS - sendXMLRPC -vcCbB input.pg - -DETAILS - credentials file - These locations are searched, in order, for the credentials file. - ("$ENV{HOME}/.ww_credentials", "$ENV{HOME}/ww_session_credentials", 'ww_credentials', 'ww_credentials.dist'); - - Place a credential file containing the following information at one of the locations above - or create a file with this information and specify it with the --credentials option. - - %credentials = ( - userID => "my login name for the webwork course", - course_password => "my password ", - courseID => "the name of the webwork course", - SITE_URL => "url of rendering site", - XML_PASSWORD => "site password", # preliminary access to site - form_action_url => 'http://localhost:80/webwork2/html2xml' #action url for form - ); - - Options - -a - Displays the answer hashes returned by the question on the command line. - - -A - Same as -a but renders the question with the correct answers submitted. - - -b - Display the rendered question in a browser (specified by the DISPLAY_HTML_COMMAND variable). - - -B - Same as -b but renders the question with the correct answers submitted. - - -h - Prints to STDOUT the entire object returned by - the webwork_client xmlrpc request. - This includes the answer information displayed by -a and -A and much more. - - -H - Same as -h but renders the question with the correct answers submitted - - -c - "check" -- Record success or failure of rendering the question to a log file. - - -C - Same as -c but the question is rendered with the correct answers submitted. - This succeeds only if the correct answers, as determined from the answer hash, all succeed. - - f=s - Specify the format used by the browser in displaying the question. - Choices for s are - standard - sticky - debug - simple - - -v - Verbose output. Used mostly for debugging. - In particular it displays explicitly the correct answers which are (will be) - submitted to the question and it specifies which credential file is used. - - -e - - Open the source file in an editor. - The single letter options can be "bundled" e.g. -vcCbB - --tex - Process question in TeX mode and output to the command line - --pdf - Process question in TeX mode, then by pdflatex and output - to the command line - - --list pg_list - Read and process a list of .pg files contained in the file C. C - consists of a sequence of lines each of which contains the full path to a pg - file that should be processed. (For example this might be the output from an - earlier run of sendXMLRPC using the -c flag. ) - - --pg - Triggers the printing of the all of the variables available to the PG question. - The table appears within the question content. Use in conjunction with -b or -B. - --anshash - Prints the answer hash for each answer in the PG_debug output which appears below - the question content. Use in conjunction with -b or -B. - Similar to -a or -A but the output appears in the browser and - not on the command line. - - --ansgrp - Prints the PGanswergroup for each answer evaluator. The information appears in - the PG_debug output which follows the question content. Use in conjunction with -b or -B. - This contains more information than printing the answer hash. (perhaps too much). - - --resource - - Prints the resources used by the question. The information appears in - the PG_debug output which follows the question content. Use in conjunction with -b or -B. - - - --credentials=s - - Specifies a file s where the credential information can be found. - - --help - Prints help information. - - --log - Sets path to log file - - --seed=s - Sets problemSeed to the number contained in string s - - -EOT -} - -1; diff --git a/clients/sendxmlrpc_bbedit.pl b/clients/sendxmlrpc_bbedit.pl deleted file mode 100755 index 75e29b2617..0000000000 --- a/clients/sendxmlrpc_bbedit.pl +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/perl -w -die "BB_DOC_PATH is not present. You must first save the document\n" unless defined $ENV{BB_DOC_PATH}; -$command = - "/Volumes/WW_test/opt/local/bin/perl /Volumes/WW_test/opt/webwork/webwork2/clients/sendXMLRPC.pl -bB $ENV{BB_DOC_PATH}"; -system($command); diff --git a/clients/t/TestWW.html b/clients/t/TestWW.html deleted file mode 100644 index 393a04a816..0000000000 --- a/clients/t/TestWW.html +++ /dev/null @@ -1,128 +0,0 @@ - - - - - Embed WW in HTML page - - - - - - - - - -

Example of embedding WeBWorK problems in HTML pages.

-

Problem 1

-

-This problem will help you to understand averages. -

-
- Click here to show problem1 -
- - -

Problem 2

-

-This problem gives you practice finding tangents to curves in the plane. -

- -
- Click here to show problem 2 -
- - -

Problem 3

-

-This is for debugging and shows all the details of the hash returned by PG. -

- -
- Click here to show problem 3 -
- - -

Problem 4

-

-This contains embedded PG code in base64 format. -

-
- Click here to show problem 4 -
- - - \ No newline at end of file diff --git a/clients/t/test_formats_WWproblems.html b/clients/t/test_formats_WWproblems.html deleted file mode 100644 index 1f37c23dbf..0000000000 --- a/clients/t/test_formats_WWproblems.html +++ /dev/null @@ -1,106 +0,0 @@ - - - - - test formats for embedded problems - - - - -

Format: sticky

-

-

Format: standard (has error section -- but there should be no errors)

-

- -

Format: simple

-

- -

Format: body_text

-

- -

Format: PTX

-

- -

Format: JSON

-

- - - diff --git a/clients/t/test_simpleFormat_WWproblem.html b/clients/t/test_simpleFormat_WWproblem.html deleted file mode 100644 index 079cd45992..0000000000 --- a/clients/t/test_simpleFormat_WWproblem.html +++ /dev/null @@ -1,64 +0,0 @@ - - - - - Embed WW in HTML page - - - - - - - - - - -

Problem 1-- xmlrpc version of a simple template

-

-Problem is rendered at daemon_course -- no student information is retained. -

-
- - -
-

Problem 2 -- webwork2 version of a simple template

-

-Direct access using RESTful url. Sign in is necessary and score is recorded. -

-
- -
- - diff --git a/clients/t/test_toggled_embedded_WWproblems.html b/clients/t/test_toggled_embedded_WWproblems.html deleted file mode 100644 index 2587e2726f..0000000000 --- a/clients/t/test_toggled_embedded_WWproblems.html +++ /dev/null @@ -1,202 +0,0 @@ - - - - - Embedded WeBWorK Problems - - - - - - - - - - - - -

Embedded WeBWorK Problems

-

-Problem 1 -- interval notation -

- -
- Click here to toggle problem display -
- -

-Problem 2 -- integration. Contains a Geogebra applet -

- -
- Click here to toggle problem display -
- - -

-Problem 3 -- the pg code for this problem is embedded in the html text using base64 encoding -

- -
- Click here to toggle problem display -
- - -

-Problem 4 -- PG lab. Enter PG code to test out here. -

- -
- Click here to toggle problem display -
- - - - -

-Problem 5 -- debug -- This problem is useful for debugging and shows all the details of the hash returned by PG. -

- -
- Click here to toggle problem display -
- - -

-Problem 6 -- A logic problem contributed from Montana State University. There -is a link "contribLibrary" in the daemon course to the "Contrib" library. See -https://github.com/openwebwork/webwork-open-problem-library -to see which problems are available in the OpenProblemLibrary and in Contrib. You can -also use the library browser to find the problems available in the OPL. - -

- -
- Click here to toggle problem display -
- -
-
- Click here to toggle problem display: (PGinfo example) -
-