You can subscribe to this list here.
2004 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(58) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2005 |
Jan
(53) |
Feb
(56) |
Mar
|
Apr
|
May
(30) |
Jun
(78) |
Jul
(121) |
Aug
(155) |
Sep
(77) |
Oct
(61) |
Nov
(45) |
Dec
(94) |
2006 |
Jan
(116) |
Feb
(33) |
Mar
(11) |
Apr
(23) |
May
(60) |
Jun
(89) |
Jul
(130) |
Aug
(109) |
Sep
(124) |
Oct
(63) |
Nov
(82) |
Dec
(45) |
2007 |
Jan
(31) |
Feb
(35) |
Mar
(123) |
Apr
(36) |
May
(18) |
Jun
(134) |
Jul
(133) |
Aug
(241) |
Sep
(126) |
Oct
(31) |
Nov
(15) |
Dec
(5) |
2008 |
Jan
(11) |
Feb
(6) |
Mar
(16) |
Apr
(29) |
May
(43) |
Jun
(149) |
Jul
(27) |
Aug
(29) |
Sep
(37) |
Oct
(20) |
Nov
(4) |
Dec
(6) |
2009 |
Jan
(34) |
Feb
(30) |
Mar
(16) |
Apr
(6) |
May
(1) |
Jun
(32) |
Jul
(22) |
Aug
(7) |
Sep
(18) |
Oct
(50) |
Nov
(22) |
Dec
(8) |
2010 |
Jan
(17) |
Feb
(15) |
Mar
(10) |
Apr
(9) |
May
(67) |
Jun
(30) |
Jul
|
Aug
|
Sep
(2) |
Oct
|
Nov
(1) |
Dec
|
From: Matt L. v. a. <we...@ma...> - 2007-09-10 17:56:26
|
Log Message: ----------- Enabled Warnings Modified Files: -------------- ww_question_server/lib: ProblemServer.pm Revision Data ------------- Index: ProblemServer.pm =================================================================== RCS file: /webwork/cvs/system/ww_question_server/lib/ProblemServer.pm,v retrieving revision 1.11 retrieving revision 1.12 diff -Llib/ProblemServer.pm -Llib/ProblemServer.pm -u -r1.11 -r1.12 --- lib/ProblemServer.pm +++ lib/ProblemServer.pm @@ -51,7 +51,7 @@ #Construct the Server Environment my $serverEnviron = new ProblemServer::Environment(); - #$SIG{__WARN__} = sub { $self->{warnings} .= shift }; + $SIG{__WARN__} = sub { $self->{warnings} .= shift }; #Keep the Default Server Environment $self->{serverEnviron} = $serverEnviron; |
From: Matt L. v. a. <we...@ma...> - 2007-09-10 17:56:09
|
Log Message: ----------- Fixed Bugs Modified Files: -------------- ww_question_server/bin/setup: setup.pl ww_question_server/lib: ProblemServer.pm Revision Data ------------- Index: setup.pl =================================================================== RCS file: /webwork/cvs/system/ww_question_server/bin/setup/setup.pl,v retrieving revision 1.5 retrieving revision 1.6 diff -Lbin/setup/setup.pl -Lbin/setup/setup.pl -u -r1.5 -r1.6 --- bin/setup/setup.pl +++ bin/setup/setup.pl @@ -266,6 +266,11 @@ system('mv WSDL.wsdl ' . $root . '/htdocs/WSDL.wsdl'); } +print "Setting Directory Permissions\n"; +system("chmod -R 777 $root/tmp"); +system("chmod -R 777 $root/htdocs/tmp"); +print "Done\n"; + print "********************************\n"; print "Your WSDL path: '" . $hostname . $files . '/'.$wsdlfilename."'\n"; print "********************************\n"; Index: ProblemServer.pm =================================================================== RCS file: /webwork/cvs/system/ww_question_server/lib/ProblemServer.pm,v retrieving revision 1.10 retrieving revision 1.11 diff -Llib/ProblemServer.pm -Llib/ProblemServer.pm -u -r1.10 -r1.11 --- lib/ProblemServer.pm +++ lib/ProblemServer.pm @@ -51,7 +51,7 @@ #Construct the Server Environment my $serverEnviron = new ProblemServer::Environment(); - $SIG{__WARN__} = sub { $self->{warnings} .= shift }; + #$SIG{__WARN__} = sub { $self->{warnings} .= shift }; #Keep the Default Server Environment $self->{serverEnviron} = $serverEnviron; |
From: Matt L. v. a. <we...@ma...> - 2007-09-10 17:25:14
|
Log Message: ----------- Fix bug Modified Files: -------------- ww_question_server/bin/setup: setup.pl Revision Data ------------- Index: setup.pl =================================================================== RCS file: /webwork/cvs/system/ww_question_server/bin/setup/setup.pl,v retrieving revision 1.4 retrieving revision 1.5 diff -Lbin/setup/setup.pl -Lbin/setup/setup.pl -u -r1.4 -r1.5 --- bin/setup/setup.pl +++ bin/setup/setup.pl @@ -229,7 +229,7 @@ } close INPUT; $content =~ s/MARKER_FOR_CONF/$additionalconf/; -$content =~ s/MARKER_FOR_APACHE/$apachecpan/; +$content =~ s/MARKER_FOR_APACHE/$apacheSoapCPAN/; print " Writing...\n"; open(OUTP2, ">$conffilename") or die("Cannot open file '$conffilename' for writing.\n"); |
From: Matt L. v. a. <we...@ma...> - 2007-09-10 17:14:35
|
Log Message: ----------- Test Files Added Files: ----------- wwmoodle/wwquestion: test.php Revision Data ------------- --- /dev/null +++ wwquestion/test.php @@ -0,0 +1,34 @@ +<?php +//base configuration file for moodle +require_once('../../../config.php'); + +echo "<b>Testing WeBWorK Question Type Setup</b><br>"; +echo "------------------------------------------<br>"; + +//Tests configuration file existance +echo "1) Configuration File<br>"; +require_once("$CFG->dirroot/question/type/webwork/config.php"); +echo "WSDL Path: '" . WWQUESTION_WSDL . "'<br>"; +echo "WeBWorK Question Root Directory: '" . $CFG->dataroot . WWQUESTION_ROOTDIR . "'<br>"; +echo "Success<br><br>"; + +//Tests communication to server +echo "2) Connection to WeBWorK Question Server<br>"; +require_once('locallib.php'); +$client = new webwork_client(); +echo "Initalized...<br>"; +$response = $client->handler('hello'); +echo "Connected....<br>"; +echo "Response: $response<br>"; +echo "Success<br><br>"; + +echo "All tests completed successfully.<br>"; +echo "WeBWorK Question Type is setup.<br>"; + + + + + + + +?> |
From: Matt L. v. a. <we...@ma...> - 2007-09-09 21:24:54
|
Log Message: ----------- More robust installation script. Finds support programs automagically and installs CPAN modules as necessary. Modified Files: -------------- ww_question_server/bin/setup: setup.pl Revision Data ------------- Index: setup.pl =================================================================== RCS file: /webwork/cvs/system/ww_question_server/bin/setup/setup.pl,v retrieving revision 1.3 retrieving revision 1.4 diff -Lbin/setup/setup.pl -Lbin/setup/setup.pl -u -r1.3 -r1.4 --- bin/setup/setup.pl +++ bin/setup/setup.pl @@ -1,88 +1,197 @@ #!/usr/bin/env perl -# + +use CPAN; +use File::Which; die "You do not have File::Which installed.\n Run perl -MCPAN -e 'install File::Which' to install. Then rerun this." if $@; + +sub promptUser { + + #-------------------------------------------------------------------# + # two possible input arguments - $promptString, and $defaultValue # + # make the input arguments local variables. # + #-------------------------------------------------------------------# + + local($promptString,$defaultValue) = @_; + + #-------------------------------------------------------------------# + # if there is a default value, use the first print statement; if # + # no default is provided, print the second string. # + #-------------------------------------------------------------------# + + if ($defaultValue) { + print $promptString, "[", $defaultValue, "]: "; + } else { + print $promptString, ": "; + } + + $| = 1; # force a flush after our print + $_ = <STDIN>; # get the input from STDIN (presumably the keyboard) + + + #------------------------------------------------------------------# + # remove the newline character from the end of the input the user # + # gave us. # + #------------------------------------------------------------------# + + chomp; + + #-----------------------------------------------------------------# + # if we had a $default value, and the user gave us input, then # + # return the input; if we had a default, and they gave us no # + # no input, return the $defaultValue. # + # # + # if we did not have a default value, then just return whatever # + # the user gave us. if they just hit the <enter> key, # + # the calling routine will have to deal with that. # + #-----------------------------------------------------------------# + + if ("$defaultValue") { + return $_ ? $_ : $defaultValue; # return $_ if it has a value + } else { + return $_; + } +} + +sub getListModules { + my @cpanModules; + print "Finding Installed CPAN Modules.\n"; + for $mod (CPAN::Shell->expand("Module","/./")){ + next unless $mod->inst_file; + # here only when installed + #get the module + my $modname = $mod->id; + push(@cpanModules,$modname); + print "."; + } + print "Done\n"; + return @cpanModules; +} + +sub moduleExists { + my ($searchModule,@cpanModules) = @_; + foreach(@cpanModules) { + if($_ eq $searchModule) { + return 1; + } + } + return 0; +} + +sub moduleInstaller { + my(@modulesNeeded) = @_; + my @moduleList = getListModules; + my @manuallyNeeded; + foreach(@modulesNeeded) { + my $needed = $_; + if(moduleExists($needed,@moduleList) == 0) { + print "$needed was not found. Do you want to try and install it?\n"; + my $choice = promptUser('(y,n)','y'); + if($choice eq 'y') { + system("perl -MCPAN -e 'install $needed'"); + print "Installed!\n"; + } else { + push(@manuallyNeeded,$needed); + } + } else { + print "Found $needed \n"; + } + } + return @manuallyNeeded; +} + +sub programPath { + my($program) = @_; + $path = which($program); + if($path != 0) { + $enteredPath = promptUser("Enter the path to '$program'"); + } else { + $enteredPath = promptUser("Enter the path to '$program'",$path); + } + return $enteredPath; +} + + + print "###################################\n"; print "#WeBWorK Question Server #\n"; print "###################################\n"; -print "This script will setup the configuration of WeBWorK Question Server.\n"; -print "Continue? (y,n):"; -$input = <STDIN>; -chop $input; -if($input eq "n") {exit;} +#Continue? +print "This script will setup the configuration of WeBWorK Question Server.\n"; +$continue = promptUser('Continue','y'); +if($continue ne "y") { + exit; +} -#APACHE 1 OR 2 -print "Will you be using Apache 1 or 2\n"; -print "(1,2)>"; -$apache = <STDIN>; -chop $apache; -if($apache eq "1") { - $apachecpan = "Apache::SOAP"; -} elsif ($apache eq "2") { - $apachecpan = "Apache2::SOAP"; +#Apache Version +$question = "Which version of Apache"; +$result = which('apache2ctl'); +if($result != 0) { + $result = which('apachectl'); + if($result != 0) { + $apacheVersion = promptUser("$question(1,2)"); + } else { + $apacheVersion = promptUser("$question(1,2)",'1'); + } +} else { + $apacheVersion = promptUser("$question(1,2)",'2'); +} +if($apacheVersion eq '1') { + $apacheSoapCPAN = "Apache::SOAP"; + $modperlCPAN = 'mod_perl'; +} elsif ($apacheVersion eq '2') { + $apacheSoapCPAN = "Apache2::SOAP"; + $modperlCPAN = 'mod_perl2'; } else { exit; } +#CPAN Module Administration +$preqCheck = promptUser("Check CPAN Prerequisites(y,n)",'y'); +if($preqCheck eq 'y') { + @modulesNeeded = ($modperlCPAN,$apacheSoapCPAN,'LWP::Simple','Pod::WSDL','Safe','MIME::Base64','File::Which'); + @manuallyNeeded = moduleInstaller(@modulesNeeded); + + $manuallyNeededCount = @manuallyNeeded; + if($manuallyNeededCount == 0) { + print "All CPAN Modules are Installed!\n"; + } else { + print "Install the following CPAN Modules and rerun this script.\n"; + foreach(@manuallyNeeded) { + print "$_\n"; + } + exit; + } +} + +#Programs +$latex = programPath('latex'); +$dvipng = programPath('dvipng'); +$tth = programPath('tth'); + +#Configuration #HOSTNAME $hostnameExample = "http://www.example.com/"; - print "Please enter the http hostname of the computer.\n"; print "This should be a value like '$hostnameExample'\n"; -print ">"; -$hostname = <STDIN>; -chop $hostname; +$hostname = promptUser(''); print "Please enter the root directory where WeBWorK Question Server is located. \n"; print "Example: /var/www/ww_question_server \n"; -print ">"; -$root = <STDIN>; -chop $root; +$root = promptUser(''); print "Please enter the directory where the PG libraries are located. \n"; print "Example: /opt/webwork/pg \n"; -print ">"; -$pg = <STDIN>; -chop $pg; - -print "Please enter the path to 'latex' command. Leave blank for default. \n"; -print "Default '/usr/bin/latex'\n"; -print ">"; -$latex = <STDIN>; -chop $latex; -if($latex eq "") { - $latex = "/usr/bin/latex"; -} - -print "Please enter the path to 'dvipng' command. Leave blank for default. \n"; -print "Default '/usr/bin/dvipng'\n"; -print ">"; -$dvipng = <STDIN>; -chop $dvipng; -if($dvipng eq "") { - $dvipng = "/usr/bin/dvipng"; -} - -print "Please enter the path to 'tth' command. Leave blank for default. \n"; -print "Default '/usr/bin/tth'\n"; -print ">"; -$tth = <STDIN>; -chop $tth; -if($tth eq "") { - $tth = "/usr/bin/tth"; -} - - - +$pg = promptUser(''); $rpc = "/problemserver_rpc"; $files = "/problemserver_files"; #WSDL FILE CREATION +use Pod::WSDL; print "Creating WSDL File...\n"; eval "use lib '$root/lib'"; die "Your root directory is wrong." if $@; -eval "use Pod::WSDL"; die "You do not have Pod::WSDL installed.\n Run perl -MCPAN -e 'install Pod::WSDL' to install. Then rerun this." if $@; $pod = new Pod::WSDL( source => 'ProblemServer', location => $hostname.$rpc, @@ -149,6 +258,22 @@ close OUTP3; print "Done\n"; +#POST CONFIGURATION +$copyFiles = promptUser('Do you want me to copy created files to their proper locations (y,n)','y'); +if($copyFiles eq 'y') { + system('mv global.conf ' . $root . '/conf/global.conf'); + system('mv problemserver.apache-config ' . $root . '/conf/problemserver.apache-config'); + system('mv WSDL.wsdl ' . $root . '/htdocs/WSDL.wsdl'); +} + +print "********************************\n"; print "Your WSDL path: '" . $hostname . $files . '/'.$wsdlfilename."'\n"; +print "********************************\n"; -#POST CONFIGURATION +print "POST INSTALL\n"; +print "1) Append the following line to your apache configuration file:\n"; +print "Include $root/conf/problemserver.apache-config\n\n"; + +print "2) Restart Apache\n"; + +print "Your done, Enjoy!\n"; |
From: Matt L. v. a. <we...@ma...> - 2007-09-09 18:38:36
|
Log Message: ----------- New configuration file. Added Files: ----------- wwmoodle/wwquestion: config.php Revision Data ------------- --- /dev/null +++ wwquestion/config.php @@ -0,0 +1,13 @@ +<?php + +//Path to the WSDL file on the Webwork Server +define('WWQUESTION_WSDL','http://128.151.231.20/problemserver_files/WSDL.wsdl'); + +//Leave the rest alone +define('WWQUESTION_PREFIX','/wwquestions'); +define('WWQUESTION_ROOTDIR','/' . SITEID . WWQUESTION_PREFIX); + +define('WWQUESTION_RESPONSE_TIMEOUT',120); + + +?> |
From: Matt L. v. a. <we...@ma...> - 2007-09-09 02:59:46
|
Log Message: ----------- Modified Files: -------------- wwmoodle/wwquestion: README.txt display.html edit_webwork_form.php file.php questiontype.php version.php wwmoodle/wwquestion/db: install.xml wwmoodle/wwquestion/lang/en_utf8: qtype_webwork.php Added Files: ----------- wwmoodle/wwquestion: files.php locallib.php version.txt Revision Data ------------- Index: display.html =================================================================== RCS file: /webwork/cvs/system/wwmoodle/wwquestion/display.html,v retrieving revision 1.6 retrieving revision 1.7 diff -Lwwquestion/display.html -Lwwquestion/display.html -u -r1.6 -r1.7 --- wwquestion/display.html +++ wwquestion/display.html @@ -4,7 +4,7 @@ <div class="qtext"> <?php echo $problemhtml; ?> <input id="resp<?php echo $qid; ?>_seed" name="resp<?php echo $qid; ?>_seed" type="hidden" value="<?php echo $seed; ?>" /> - <input id="resp<?php echo $qid; ?>_derivedid" name="resp<?php echo $qid; ?>_derivedid" type="hidden" value="<?php echo $derivedid; ?>" /> + <input id="resp<?php echo $qid; ?>_derivationid" name="resp<?php echo $qid; ?>_derivationid" type="hidden" value="<?php echo $derivationid; ?>" /> </div> <?php if ($image) { ?> @@ -12,6 +12,8 @@ <?php } ?> <div class="ablock clearfix"> + <?php $this->print_question_submit_buttons($question, $state, $cmoptions, $options); ?> + <br> <?php if($state->event == QUESTION_EVENTGRADE) { ?> <table class="answer"> <tr class="header"> @@ -59,5 +61,5 @@ </div> <?php } ?> - <?php $this->print_question_submit_buttons($question, $state, $cmoptions, $options); ?> + </div> \ No newline at end of file --- /dev/null +++ wwquestion/version.txt @@ -0,0 +1,10 @@ +Old versions: + +Version .2 (August 2007) +* DB consistency issues fixed (thanks to Jean-Marc) +* New code checking, makes sure PG code is correct +* Images are now copied locally for faster problem loading +* Minor bug Fixes + +Version .1 (July 2007) +* Initial Release \ No newline at end of file --- /dev/null +++ wwquestion/files.php @@ -0,0 +1,839 @@ +<?php // $Id: files.php,v 1.1 2007/09/09 02:53:16 mleventi Exp $ + +// Manage all uploaded files in a course file area + +// All the Moodle-specific stuff is in this top section +// Configuration and access control occurs here. +// Must define: USER, basedir, baseweb, html_header and html_footer +// USER is a persistent variable using sessions + + require('../../../config.php'); + require($CFG->libdir.'/filelib.php'); + require($CFG->libdir.'/adminlib.php'); + require($CFG->dirroot.'/question/type/webwork/locallib.php'); + + $id = required_param('id', PARAM_INT); + $qid = required_param('qid',PARAM_INT); + $file = optional_param('file', '', PARAM_PATH); + $wdir = optional_param('wdir', '', PARAM_PATH); + $action = optional_param('action', '', PARAM_ACTION); + $name = optional_param('name', '', PARAM_FILE); + $oldname = optional_param('oldname', '', PARAM_FILE); + $choose = optional_param('choose', '', PARAM_FILE); //in fact it is always 'formname.inputname' + $userfile= optional_param('userfile','',PARAM_FILE); + $save = optional_param('save', 0, PARAM_BOOL); + $text = optional_param('text', '', PARAM_RAW); + $confirm = optional_param('confirm', 0, PARAM_BOOL); + + if ($choose) { + if (count(explode('.', $choose)) > 2) { + print_error('Incorrect format for choose parameter'); + } + } + + if (! $course = get_record("course", "id", $id) ) { + print_error("That's an invalid course id"); + } + + //access is needed + require_login($course); + require_capability('moodle/course:managefiles', get_context_instance(CONTEXT_COURSE, $course->id)); + + + $baseweb = $CFG->wwwroot; + $basedir = $CFG->dataroot; + $userid = $USER->id; + + if($qid == -1) { + $searcher = webwork_get_tmp_path(); + } else { + $searcher = webwork_get_wwquestion_path($qid); + } + $wdir = str_replace($searcher,'',$wdir); + + if ($wdir == '') { + $wdir = "/"; + } + + if ($wdir{0} != '/') { + $wdir = "/".$wdir; + } + + //prefix the filepath + if($qid == -1) { + webwork_make_tmp_dir(); + $wdir = webwork_get_tmp_path() . $wdir; + } else { + if(!$question = get_record('question_webwork','id',$qid)) { + print_error("That's an invalid question id."); + } + $wdir = webwork_get_wwquestion_path($qid) . $wdir; + } + + if (!is_dir($basedir.$wdir)) { + //html_header($course, $wdir); + print_error("Requested directory does not exist."); + } + print_header(); + switch ($action) { + + case "upload": + //html_header($course, $wdir); + require_once($CFG->dirroot.'/lib/uploadlib.php'); + + if ($save and confirm_sesskey()) { + $course->maxbytes = 0; // We are ignoring course limits + $um = new upload_manager('userfile',false,false,$course,false,0); + $dir = "$basedir$wdir"; + if ($um->process_file_uploads($dir)) { + notify(get_string('uploadedfile')); + } + // um will take care of error reporting. + displaydir($wdir); + } else { + $upload_max_filesize = get_max_upload_file_size($CFG->maxbytes); + $filesize = display_size($upload_max_filesize); + + $struploadafile = get_string("uploadafile"); + $struploadthisfile = get_string("uploadthisfile"); + $strmaxsize = get_string("maxsize", "", $filesize); + $strcancel = get_string("cancel"); + + echo "<p>$struploadafile ($strmaxsize) --> <b>$wdir</b></p>"; + echo "<form enctype=\"multipart/form-data\" method=\"post\" action=\"files.php\">"; + echo "<div>"; + echo "<table><tr><td colspan=\"2\">"; + echo ' <input type="hidden" name="choose" value="'.$choose.'" />'; + echo " <input type=\"hidden\" name=\"id\" value=\"$id\" />"; + echo " <input type=\"hidden\" name=\"qid\" value=\"$qid\" />"; + echo " <input type=\"hidden\" name=\"wdir\" value=\"$wdir\" />"; + echo " <input type=\"hidden\" name=\"action\" value=\"upload\" />"; + echo " <input type=\"hidden\" name=\"sesskey\" value=\"$USER->sesskey\" />"; + upload_print_form_fragment(1,array('userfile'),null,false,null,$upload_max_filesize,0,false); + echo " </td></tr></table>"; + echo " <input type=\"submit\" name=\"save\" value=\"$struploadthisfile\" />"; + echo "</div>"; + echo "</form>"; + echo "<form action=\"files.php\" method=\"get\">"; + echo "<div>"; + echo ' <input type="hidden" name="choose" value="'.$choose.'" />'; + echo " <input type=\"hidden\" name=\"id\" value=\"$id\" />"; + echo " <input type=\"hidden\" name=\"qid\" value=\"$qid\" />"; + echo " <input type=\"hidden\" name=\"wdir\" value=\"$wdir\" />"; + echo " <input type=\"hidden\" name=\"action\" value=\"cancel\" />"; + echo " <input type=\"submit\" value=\"$strcancel\" />"; + echo "</div>"; + echo "</form>"; + } + //html_footer(); + break; + + case "delete": + if ($confirm and confirm_sesskey()) { + //html_header($course, $wdir); + if (!empty($USER->filelist)) { + foreach ($USER->filelist as $file) { + $fullfile = $basedir.'/'.$file; + if (! fulldelete($fullfile)) { + echo "<br />Error: Could not delete: $fullfile"; + } + } + } + clearfilelist(); + displaydir($wdir); + //html_footer(); + + } else { + //html_header($course, $wdir); + + if (setfilelist($_POST)) { + notify(get_string('deletecheckwarning').':'); + print_simple_box_start("center"); + printfilelist($USER->filelist); + print_simple_box_end(); + echo "<br />"; + + require_once($CFG->dirroot.'/mod/resource/lib.php'); + $block = resource_delete_warning($course, $USER->filelist); + + if (empty($CFG->resource_blockdeletingfile) or $block == '') { + $optionsyes = array('id'=>$id, 'qid'=>$qid, 'wdir'=>$wdir, 'action'=>'delete', 'confirm'=>1, 'sesskey'=>sesskey(), 'choose'=>$choose); + $optionsno = array('id'=>$id, 'qid'=>$qid, 'wdir'=>$wdir, 'action'=>'cancel', 'choose'=>$choose); + notice_yesno (get_string('deletecheckfiles'), 'files.php', 'files.php', $optionsyes, $optionsno, 'post', 'get'); + } else { + + notify(get_string('warningblockingdelete', 'resource')); + $options = array('id'=>$id, 'qid'=>$qid, 'wdir'=>$wdir, 'action'=>'cancel', 'choose'=>$choose); + print_continue("files.php?id=$id&qid=$qid&wdir=$wdir&action=cancel&choose=$choose"); + } + } else { + displaydir($wdir); + } + //html_footer(); + } + break; + + case "move": + //html_header($course, $wdir); + if (($count = setfilelist($_POST)) and confirm_sesskey()) { + $USER->fileop = $action; + $USER->filesource = $wdir; + echo "<p class=\"centerpara\">"; + print_string("selectednowmove", "moodle", $count); + echo "</p>"; + } + displaydir($wdir); + //html_footer(); + break; + + case "paste": + //html_header($course, $wdir); + if (isset($USER->fileop) and ($USER->fileop == "move") and confirm_sesskey()) { + foreach ($USER->filelist as $file) { + $shortfile = basename($file); + $oldfile = $basedir.'/'.$file; + $newfile = $basedir.$wdir."/".$shortfile; + if (!rename($oldfile, $newfile)) { + echo "<p>Error: $shortfile not moved</p>"; + } + } + } + clearfilelist(); + displaydir($wdir); + //html_footer(); + break; + + case "rename": + if (($name != '') and confirm_sesskey()) { + //html_header($course, $wdir); + $name = clean_filename($name); + if (file_exists($basedir.$wdir."/".$name)) { + echo "<center>Error: $name already exists!</center>"; + } else if (!rename($basedir.$wdir."/".$oldname, $basedir.$wdir."/".$name)) { + echo "<p align=\"center\">Error: could not rename $oldname to $name</p>"; + } else { + //file was renamed now update resources if needed + require_once($CFG->dirroot.'/mod/resource/lib.php'); + resource_renamefiles($course, $wdir, $oldname, $name); + } + displaydir($wdir); + + } else { + $strrename = get_string("rename"); + $strcancel = get_string("cancel"); + $strrenamefileto = get_string("renamefileto", "moodle", $file); + //html_header($course, $wdir, "form.name"); + echo "<p>$strrenamefileto:</p>"; + echo "<table><tr><td>"; + echo "<form action=\"files.php\" method=\"post\">"; + echo "<fieldset class=\"invisiblefieldset\">"; + echo ' <input type="hidden" name="choose" value="'.$choose.'" />'; + echo " <input type=\"hidden\" name=\"id\" value=\"$id\" />"; + echo " <input type=\"hidden\" name=\"qid\" value=\"$qid\" />"; + echo " <input type=\"hidden\" name=\"wdir\" value=\"$wdir\" />"; + echo " <input type=\"hidden\" name=\"action\" value=\"rename\" />"; + echo " <input type=\"hidden\" name=\"oldname\" value=\"$file\" />"; + echo " <input type=\"hidden\" name=\"sesskey\" value=\"$USER->sesskey\" />"; + echo " <input type=\"text\" name=\"name\" size=\"35\" value=\"$file\" />"; + echo " <input type=\"submit\" value=\"$strrename\" />"; + echo "</fieldset>"; + echo "</form>"; + echo "</td><td>"; + echo "<form action=\"files.php\" method=\"get\">"; + echo "<div>"; + echo ' <input type="hidden" name="choose" value="'.$choose.'" />'; + echo " <input type=\"hidden\" name=\"id\" value=\"$id\" />"; + echo " <input type=\"hidden\" name=\"qid\" value=\"$qid\" />"; + echo " <input type=\"hidden\" name=\"wdir\" value=\"$wdir\" />"; + echo " <input type=\"hidden\" name=\"action\" value=\"cancel\" />"; + echo " <input type=\"submit\" value=\"$strcancel\" />"; + echo "</div>"; + echo "</form>"; + echo "</td></tr></table>"; + } + //html_footer(); + break; + + case "makedir": + if (($name != '') and confirm_sesskey()) { + //html_header($course, $wdir); + $name = clean_filename($name); + if (file_exists("$basedir$wdir/$name")) { + echo "Error: $name already exists!"; + } else if (! make_upload_directory("$wdir/$name")) { + echo "Error: could not create $name"; + } + displaydir($wdir); + + } else { + $strcreate = get_string("create"); + $strcancel = get_string("cancel"); + $strcreatefolder = get_string("createfolder", "moodle", $wdir); + //html_header($course, $wdir, "form.name"); + echo "<p>$strcreatefolder:</p>"; + echo "<table><tr><td>"; + echo "<form action=\"files.php\" method=\"post\">"; + echo "<fieldset class=\"invisiblefieldset\">"; + echo ' <input type="hidden" name="choose" value="'.$choose.'" />'; + echo " <input type=\"hidden\" name=\"id\" value=\"$id\" />"; + echo " <input type=\"hidden\" name=\"qid\" value=\"$qid\" />"; + echo " <input type=\"hidden\" name=\"wdir\" value=\"$wdir\" />"; + echo " <input type=\"hidden\" name=\"action\" value=\"makedir\" />"; + echo " <input type=\"text\" name=\"name\" size=\"35\" />"; + echo " <input type=\"hidden\" name=\"sesskey\" value=\"$USER->sesskey\" />"; + echo " <input type=\"submit\" value=\"$strcreate\" />"; + echo "</fieldset>"; + echo "</form>"; + echo "</td><td>"; + echo "<form action=\"files.php\" method=\"get\">"; + echo "<div>"; + echo ' <input type="hidden" name="choose" value="'.$choose.'" />'; + echo " <input type=\"hidden\" name=\"id\" value=\"$id\" />"; + echo " <input type=\"hidden\" name=\"qid\" value=\"$qid\" />"; + echo " <input type=\"hidden\" name=\"wdir\" value=\"$wdir\" />"; + echo " <input type=\"hidden\" name=\"action\" value=\"cancel\" />"; + echo " <input type=\"submit\" value=\"$strcancel\" />"; + echo "</div>"; + echo "</form>"; + echo "</td></tr></table>"; + } + //html_footer(); + break; + + case "edit": + //html_header($course, $wdir); + if (($text != '') and confirm_sesskey()) { + $fileptr = fopen($basedir.'/'.$file,"w"); + $text = preg_replace('/\x0D/', '', $text); // http://moodle.org/mod/forum/discuss.php?d=38860 + fputs($fileptr, stripslashes($text)); + fclose($fileptr); + displaydir($wdir); + + } else { + $streditfile = get_string("edit", "", "<b>$file</b>"); + $fileptr = fopen($basedir.'/'.$file, "r"); + $contents = fread($fileptr, filesize($basedir.'/'.$file)); + fclose($fileptr); + + if (mimeinfo("type", $file) == "text/html") { + $usehtmleditor = can_use_html_editor(); + } else { + $usehtmleditor = false; + } + $usehtmleditor = false; // Always keep it off for now + + print_heading("$streditfile"); + + echo "<table><tr><td colspan=\"2\">"; + echo "<form action=\"files.php\" method=\"post\">"; + echo "<div>"; + echo ' <input type="hidden" name="choose" value="'.$choose.'" />'; + echo " <input type=\"hidden\" name=\"id\" value=\"$id\" />"; + echo " <input type=\"hidden\" name=\"qid\" value=\"$qid\" />"; + echo " <input type=\"hidden\" name=\"wdir\" value=\"$wdir\" />"; + echo " <input type=\"hidden\" name=\"file\" value=\"$file\" />"; + echo " <input type=\"hidden\" name=\"action\" value=\"edit\" />"; + echo " <input type=\"hidden\" name=\"sesskey\" value=\"$USER->sesskey\" />"; + print_textarea($usehtmleditor, 25, 80, 680, 400, "text", $contents); + echo "</td></tr><tr><td>"; + echo " <input type=\"submit\" value=\"".get_string("savechanges")."\" />"; + echo "</div>"; + echo "</form>"; + echo "</td><td>"; + echo "<form action=\"files.php\" method=\"get\">"; + echo "<div>"; + echo ' <input type="hidden" name="choose" value="'.$choose.'" />'; + echo " <input type=\"hidden\" name=\"id\" value=\"$id\" />"; + echo " <input type=\"hidden\" name=\"qid\" value=\"$qid\" />"; + echo " <input type=\"hidden\" name=\"wdir\" value=\"$wdir\" />"; + echo " <input type=\"hidden\" name=\"action\" value=\"cancel\" />"; + echo " <input type=\"submit\" value=\"".get_string("cancel")."\" />"; + echo "</div>"; + echo "</form>"; + echo "</td></tr></table>"; + + if ($usehtmleditor) { + use_html_editor(); + } + + + } + //html_footer(); + break; + + case "zip": + if (($name != '') and confirm_sesskey()) { + //html_header($course, $wdir); + $name = clean_filename($name); + + $files = array(); + foreach ($USER->filelist as $file) { + $files[] = "$basedir/$file"; + } + + if (!zip_files($files,"$basedir$wdir/$name")) { + error(get_string("zipfileserror","error")); + } + + clearfilelist(); + displaydir($wdir); + + } else { + //html_header($course, $wdir, "form.name"); + + if (setfilelist($_POST)) { + echo "<p align=\"center\">".get_string("youareabouttocreatezip").":</p>"; + print_simple_box_start("center"); + printfilelist($USER->filelist); + print_simple_box_end(); + echo "<br />"; + echo "<p align=\"center\">".get_string("whattocallzip")."</p>"; + echo "<table><tr><td>"; + echo "<form action=\"files.php\" method=\"post\">"; + echo "<fieldset class=\"invisiblefieldset\">"; + echo ' <input type="hidden" name="choose" value="'.$choose.'" />'; + echo " <input type=\"hidden\" name=\"id\" value=\"$id\" />"; + echo " <input type=\"hidden\" name=\"qid\" value=\"$qid\" />"; + echo " <input type=\"hidden\" name=\"wdir\" value=\"$wdir\" />"; + echo " <input type=\"hidden\" name=\"action\" value=\"zip\" />"; + echo " <input type=\"text\" name=\"name\" size=\"35\" value=\"new.zip\" />"; + echo " <input type=\"hidden\" name=\"sesskey\" value=\"$USER->sesskey\" />"; + echo " <input type=\"submit\" value=\"".get_string("createziparchive")."\" />"; + echo "<fieldset>"; + echo "</form>"; + echo "</td><td>"; + echo "<form action=\"files.php\" method=\"get\">"; + echo "<div>"; + echo ' <input type="hidden" name="choose" value="'.$choose.'" />'; + echo " <input type=\"hidden\" name=\"id\" value=\"$id\" />"; + echo " <input type=\"hidden\" name=\"qid\" value=\"$qid\" />"; + echo " <input type=\"hidden\" name=\"wdir\" value=\"$wdir\" />"; + echo " <input type=\"hidden\" name=\"action\" value=\"cancel\" />"; + echo " <input type=\"submit\" value=\"".get_string("cancel")."\" />"; + echo "</div>"; + echo "</form>"; + echo "</td></tr></table>"; + } else { + displaydir($wdir); + clearfilelist(); + } + } + //html_footer(); + break; + + case "unzip": + //html_header($course, $wdir); + if (($file != '') and confirm_sesskey()) { + $strok = get_string("ok"); + $strunpacking = get_string("unpacking", "", $file); + + echo "<p align=\"center\">$strunpacking:</p>"; + + $file = basename($file); + + if (!unzip_file("$basedir$wdir/$file")) { + error(get_string("unzipfileserror","error")); + } + + echo "<div style=\"text-align:center\"><form action=\"files.php\" method=\"get\">"; + echo "<div>"; + echo ' <input type="hidden" name="choose" value="'.$choose.'" />'; + echo " <input type=\"hidden\" name=\"id\" value=\"$id\" />"; + echo " <input type=\"hidden\" name=\"qid\" value=\"$qid\" />"; + echo " <input type=\"hidden\" name=\"wdir\" value=\"$wdir\" />"; + echo " <input type=\"hidden\" name=\"action\" value=\"cancel\" />"; + echo " <input type=\"submit\" value=\"$strok\" />"; + echo "</div>"; + echo "</form>"; + echo "</div>"; + } else { + displaydir($wdir); + } + //html_footer(); + break; + + case "listzip": + //html_header($course, $wdir); + if (($file != '') and confirm_sesskey()) { + $strname = get_string("name"); + $strsize = get_string("size"); + $strmodified = get_string("modified"); + $strok = get_string("ok"); + $strlistfiles = get_string("listfiles", "", $file); + + echo "<p align=\"center\">$strlistfiles:</p>"; + $file = basename($file); + + include_once("$CFG->libdir/pclzip/pclzip.lib.php"); + $archive = new PclZip(cleardoubleslashes("$basedir$wdir/$file")); + if (!$list = $archive->listContent(cleardoubleslashes("$basedir$wdir"))) { + notify($archive->errorInfo(true)); + + } else { + echo "<table cellpadding=\"4\" cellspacing=\"2\" border=\"0\" width=\"640\" class=\"files\">"; + echo "<tr class=\"file\"><th align=\"left\" class=\"header name\" scope=\"col\">$strname</th><th align=\"right\" class=\"header size\" scope=\"col\">$strsize</th><th align=\"right\" class=\"header date\" scope=\"col\">$strmodified</th></tr>"; + foreach ($list as $item) { + echo "<tr>"; + print_cell("left", s($item['filename']), 'name'); + if (! $item['folder']) { + print_cell("right", display_size($item['size']), 'size'); + } else { + echo "<td> </td>"; + } + $filedate = userdate($item['mtime'], get_string("strftimedatetime")); + print_cell("right", $filedate, 'date'); + echo "</tr>"; + } + echo "</table>"; + } + echo "<br /><center><form action=\"files.php\" method=\"get\">"; + echo "<div>"; + echo ' <input type="hidden" name="choose" value="'.$choose.'" />'; + echo " <input type=\"hidden\" name=\"id\" value=\"$id\" />"; + echo " <input type=\"hidden\" name=\"qid\" value=\"$qid\" />"; + echo " <input type=\"hidden\" name=\"wdir\" value=\"$wdir\" />"; + echo " <input type=\"hidden\" name=\"action\" value=\"cancel\" />"; + echo " <input type=\"submit\" value=\"$strok\" />"; + echo "</div>"; + echo "</form>"; + echo "</center>"; + } else { + displaydir($wdir); + } + //html_footer(); + break; + + case "restore": + //html_header($course, $wdir); + if (($file != '') and confirm_sesskey()) { + echo "<p align=\"center\">".get_string("youaregoingtorestorefrom").":</p>"; + print_simple_box_start("center"); + echo $file; + print_simple_box_end(); + echo "<br />"; + echo "<p align=\"center\">".get_string("areyousuretorestorethisinfo")."</p>"; + $restore_path = "$CFG->wwwroot/backup/restore.php"; + notice_yesno (get_string("areyousuretorestorethis"), + $restore_path."?id=".$id."&qid=".$qid."&file=".cleardoubleslashes($id.$wdir."/".$file)."&method=manual", + "files.php?id=$id&qid=$qid&wdir=$wdir&action=cancel"); + } else { + displaydir($wdir); + } + //html_footer(); + break; + + case "cancel": + clearfilelist(); + + default: + //html_header($course, $wdir); + displaydir($wdir); + //html_footer(); + break; +} + + +/// FILE FUNCTIONS /////////////////////////////////////////////////////////// + + +function setfilelist($VARS) { + global $USER; + + $USER->filelist = array (); + $USER->fileop = ""; + + $count = 0; + foreach ($VARS as $key => $val) { + if (substr($key,0,4) == "file") { + $count++; + $val = rawurldecode($val); + $USER->filelist[] = clean_param($val, PARAM_PATH); + } + } + return $count; +} + +function clearfilelist() { + global $USER; + + $USER->filelist = array (); + $USER->fileop = ""; +} + + +function printfilelist($filelist) { + global $CFG, $basedir; + + $strfolder = get_string("folder"); + $strfile = get_string("file"); + + foreach ($filelist as $file) { + if (is_dir($basedir.'/'.$file)) { + echo "<img src=\"$CFG->pixpath/f/folder.gif\" class=\"icon\" alt=\"$strfolder\" /> $file<br />"; + $subfilelist = array(); + $currdir = opendir($basedir.'/'.$file); + while (false !== ($subfile = readdir($currdir))) { + if ($subfile <> ".." && $subfile <> ".") { + $subfilelist[] = $file."/".$subfile; + } + } + printfilelist($subfilelist); + + } else { + $icon = mimeinfo("icon", $file); + echo "<img src=\"$CFG->pixpath/f/$icon\" class=\"icon\" alt=\"$strfile\" /> $file<br />"; + } + } +} + + +function print_cell($alignment='center', $text=' ', $class='') { + if ($class) { + $class = ' class="'.$class.'"'; + } + echo '<td align="'.$alignment.'" style="white-space:nowrap "'.$class.'>'.$text.'</td>'; +} + +function displaydir ($wdir) { +// $wdir == / or /a or /a/b/c/d etc + + global $basedir; + global $id; + global $qid; + global $USER, $CFG; + global $choose; + + $fullpath = $basedir.$wdir; + $dirlist = array(); + + $directory = opendir($fullpath); // Find all files + while (false !== ($file = readdir($directory))) { + if ($file == "." || $file == "..") { + continue; + } + + if (is_dir($fullpath."/".$file)) { + $dirlist[] = $file; + } else { + $filelist[] = $file; + } + } + closedir($directory); + + $strname = get_string("name"); + $strsize = get_string("size"); + $strmodified = get_string("modified"); + $straction = get_string("action"); + $strmakeafolder = get_string("makeafolder"); + $struploadafile = get_string("uploadafile"); + $strselectall = get_string("selectall"); + $strselectnone = get_string("deselectall"); + $strwithchosenfiles = get_string("withchosenfiles"); + $strmovetoanotherfolder = get_string("movetoanotherfolder"); + $strmovefilestohere = get_string("movefilestohere"); + $strdeletecompletely = get_string("deletecompletely"); + $strcreateziparchive = get_string("createziparchive"); + $strrename = get_string("rename"); + $stredit = get_string("edit"); + $strunzip = get_string("unzip"); + $strlist = get_string("list"); + $strrestore= get_string("restore"); + $strchoose = get_string("choose"); + $strfolder = get_string("folder"); + $strfile = get_string("file"); + + + echo "<form action=\"files.php\" method=\"post\" id=\"dirform\">"; + echo "<div>"; + echo '<input type="hidden" name="choose" value="'.$choose.'" />'; + // echo "<hr align=\"center\" noshade=\"noshade\" size=\"1\" />"; + echo "<hr/>"; + echo "<table border=\"0\" cellspacing=\"2\" cellpadding=\"2\" width=\"640\" class=\"files\">"; + echo "<tr>"; + echo "<th scope=\"col\"></th>"; + echo "<th class=\"header name\" scope=\"col\">$strname</th>"; + echo "<th class=\"header size\" scope=\"col\">$strsize</th>"; + echo "<th class=\"header date\" scope=\"col\">$strmodified</th>"; + echo "<th class=\"header commands\" scope=\"col\">$straction</th>"; + echo "</tr>\n"; + + if ($wdir != "/") { + $dirlist[] = '..'; + } + + $count = 0; + + if (!empty($dirlist)) { + asort($dirlist); + foreach ($dirlist as $dir) { + echo "<tr class=\"folder\">"; + + if ($dir == '..') { + //only display parent if we are not in root of question + if($qid == -1) { + $tempstr = webwork_get_tmp_path() . '/'; + } else { + $tempstr = WWQUESTION_ROOTDIR . '/' . $qid . '/'; + } + if($tempstr != $wdir) { + $fileurl = rawurlencode(dirname($wdir)); + print_cell(); + // alt attribute intentionally empty to prevent repetition in screen reader + print_cell('left', '<a href="files.php?id='.$id.'&qid='.$qid.'&wdir='.$fileurl.'&choose='.$choose.'"><img src="'.$CFG->pixpath.'/f/parent.gif" class="icon" alt="" /> '.get_string('parentfolder').'</a>', 'name'); + print_cell(); + print_cell(); + print_cell(); + } + + } else { + $count++; + $filename = $fullpath."/".$dir; + $fileurl = rawurlencode($wdir."/".$dir); + $filesafe = rawurlencode($dir); + $filesize = display_size(get_directory_size("$fullpath/$dir")); + $filedate = userdate(filemtime($filename), "%d %b %Y, %I:%M %p"); + print_cell("center", "<input type=\"checkbox\" name=\"file$count\" value=\"$fileurl\" />", 'checkbox'); + print_cell("left", "<a href=\"files.php?id=$id&qid=$qid&wdir=$fileurl&choose=$choose\"><img src=\"$CFG->pixpath/f/folder.gif\" class=\"icon\" alt=\"$strfolder\" /> ".htmlspecialchars($dir)."</a>", 'name'); + print_cell("right", $filesize, 'size'); + print_cell("right", $filedate, 'date'); + print_cell("right", "<a href=\"files.php?id=$id&qid=$qid&wdir=$wdir&file=$filesafe&action=rename&choose=$choose\">$strrename</a>", 'commands'); + } + + echo "</tr>"; + } + } + + + if (!empty($filelist)) { + asort($filelist); + foreach ($filelist as $file) { + + $icon = mimeinfo("icon", $file); + + $count++; + $filename = $fullpath."/".$file; + $fileurl = trim($wdir, "/")."/$file"; + $filesafe = rawurlencode($file); + $fileurlsafe = rawurlencode($fileurl); + $filedate = userdate(filemtime($filename), "%d %b %Y, %I:%M %p"); + + $selectfile = trim($fileurl, "/"); + + echo "<tr class=\"file\">"; + + print_cell("center", "<input type=\"checkbox\" name=\"file$count\" value=\"$fileurl\" />", 'checkbox'); + echo "<td align=\"left\" style=\"white-space:nowrap\" class=\"name\">"; + if ($CFG->slasharguments) { + $ffurl = str_replace('//', '/', "/file.php/$fileurl"); + } else { + $ffurl = str_replace('//', '/', "/file.php?file=/$fileurl"); + } + link_to_popup_window ($ffurl, "display", + "<img src=\"$CFG->pixpath/f/$icon\" class=\"icon\" alt=\"$strfile\" /> ".htmlspecialchars($file), + 480, 640); + echo "</td>"; + + $file_size = filesize($filename); + print_cell("right", display_size($file_size), 'size'); + print_cell("right", $filedate, 'date'); + + if ($choose) { + $edittext = "<strong><a onclick=\"return set_value('$selectfile')\" href=\"#\">$strchoose</a></strong> "; + } else { + $edittext = ''; + } + + + if ($icon == "text.gif" || $icon == "html.gif") { + $edittext .= "<a href=\"files.php?id=$id&qid=$qid&wdir=$wdir&file=$fileurl&action=edit&choose=$choose\">$stredit</a>"; + } else if ($icon == "zip.gif") { + $edittext .= "<a href=\"files.php?id=$id&qid=$qid&wdir=$wdir&file=$fileurl&action=unzip&sesskey=$USER->sesskey&choose=$choose\">$strunzip</a> "; + $edittext .= "<a href=\"files.php?id=$id&qid=$qid&wdir=$wdir&file=$fileurl&action=listzip&sesskey=$USER->sesskey&choose=$choose\">$strlist</a> "; + if (!empty($CFG->backup_version) and has_capability('moodle/site:restore', get_context_instance(CONTEXT_COURSE, $id))) { + $edittext .= "<a href=\"files.php?id=$id&qid=$qid&wdir=$wdir&file=$filesafe&action=restore&sesskey=$USER->sesskey&choose=$choose\">$strrestore</a> "; + } + } + + print_cell("right", "$edittext <a href=\"files.php?id=$id&qid=$qid&wdir=$wdir&file=$filesafe&action=rename&choose=$choose\">$strrename</a>", 'commands'); + + echo "</tr>"; + } + } + echo "</table>"; + echo "<hr />"; + //echo "<hr width=\"640\" align=\"center\" noshade=\"noshade\" size=\"1\" />"; + + echo "<table border=\"0\" cellspacing=\"2\" cellpadding=\"2\" width=\"640\">"; + echo "<tr><td>"; + echo "<input type=\"hidden\" name=\"id\" value=\"$id\" />"; + echo " <input type=\"hidden\" name=\"qid\" value=\"$qid\" />"; + echo '<input type="hidden" name="choose" value="'.$choose.'" />'; + echo "<input type=\"hidden\" name=\"wdir\" value=\"$wdir\" /> "; + echo "<input type=\"hidden\" name=\"sesskey\" value=\"$USER->sesskey\" />"; + $options = array ( + "move" => "$strmovetoanotherfolder", + "delete" => "$strdeletecompletely", + "zip" => "$strcreateziparchive" + ); + if (!empty($count)) { + choose_from_menu ($options, "action", "", "$strwithchosenfiles...", "javascript:getElementById('dirform').submit()"); + } + echo "</td></tr></table>"; + echo "</div>"; + echo "</form>"; + echo "<table border=\"0\" cellspacing=\"2\" cellpadding=\"2\" width=\"640\"><tr>"; + echo "<td align=\"center\">"; + if (!empty($USER->fileop) and ($USER->fileop == "move") and ($USER->filesource <> $wdir)) { + echo "<form action=\"files.php\" method=\"get\">"; + echo "<div>"; + echo ' <input type="hidden" name="choose" value="'.$choose.'" />'; + echo " <input type=\"hidden\" name=\"id\" value=\"$id\" />"; + echo " <input type=\"hidden\" name=\"qid\" value=\"$qid\" />"; + echo " <input type=\"hidden\" name=\"wdir\" value=\"$wdir\" />"; + echo " <input type=\"hidden\" name=\"action\" value=\"paste\" />"; + echo " <input type=\"hidden\" name=\"sesskey\" value=\"$USER->sesskey\" />"; + echo " <input type=\"submit\" value=\"$strmovefilestohere\" />"; + echo "</div>"; + echo "</form>"; + } + echo "</td>"; + echo "<td align=\"right\">"; + echo "<form action=\"files.php\" method=\"get\">"; + echo "<div>"; + echo ' <input type="hidden" name="choose" value="'.$choose.'" />'; + echo " <input type=\"hidden\" name=\"id\" value=\"$id\" />"; + echo " <input type=\"hidden\" name=\"qid\" value=\"$qid\" />"; + echo " <input type=\"hidden\" name=\"wdir\" value=\"$wdir\" />"; + echo " <input type=\"hidden\" name=\"action\" value=\"makedir\" />"; + echo " <input type=\"submit\" value=\"$strmakeafolder\" />"; + echo "</div>"; + echo "</form>"; + echo "</td>"; + echo "<td align=\"right\">"; + echo "<form action=\"files.php\" method=\"get\">"; //dummy form - alignment only + echo "<fieldset class=\"invisiblefieldset\">"; + echo " <input type=\"button\" value=\"$strselectall\" onclick=\"checkall();\" />"; + echo " <input type=\"button\" value=\"$strselectnone\" onclick=\"uncheckall();\" />"; + echo "</fieldset>"; + echo "</form>"; + echo "</td>"; + echo "<td align=\"right\">"; + echo "<form action=\"files.php\" method=\"get\">"; + echo "<div>"; + echo ' <input type="hidden" name="choose" value="'.$choose.'" />'; + echo " <input type=\"hidden\" name=\"id\" value=\"$id\" />"; + echo " <input type=\"hidden\" name=\"qid\" value=\"$qid\" />"; + echo " <input type=\"hidden\" name=\"wdir\" value=\"$wdir\" />"; + echo " <input type=\"hidden\" name=\"action\" value=\"upload\" />"; + echo " <input type=\"submit\" value=\"$struploadafile\" />"; + echo "</div>"; + echo "</form>"; + echo "</td></tr>"; + echo "</table>"; + echo "<hr/>"; + //echo "<hr width=\"640\" align=\"center\" noshade=\"noshade\" size=\"1\" />"; + +} + +?> + Index: README.txt =================================================================== RCS file: /webwork/cvs/system/wwmoodle/wwquestion/README.txt,v retrieving revision 1.4 retrieving revision 1.5 diff -Lwwquestion/README.txt -Lwwquestion/README.txt -u -r1.4 -r1.5 --- wwquestion/README.txt +++ wwquestion/README.txt @@ -1,21 +1,25 @@ Webwork Question Type ---------------------- -Version: 0.2 (stable) +Version: 0.3 (stable) Released 9/9/2007 Maintainer: Matthew Leventi <mle...@gm...> CVS: cvs.webwork.rochester.edu:/webwork/cvs/system wwmoodle/wwquestion -**If your using this send me an email.** +This is a moodle questiontype module that will allow webwork questions to be asked in Moodle Quizzes and Lessons. Currently it supports many of the features found in the webwork2 system. -Whats coming soon (sept 1): -* Question Importer (alpha at CVS: cvs.webwork.rochester.edu:/webwork/cvs/system wwmoodle/wwquestion_importer) -* Applet & External Dep. support for PG files. - -Whats New: -* DB consistency issues fixed (thanks to Jean-Marc) -* New code checking, makes sure PG code is correct -* Images are now copied locally for faster problem loading -* Minor bug Fixes +* If you are using this send me an email. Feedback is appreciated. * +Current Release: +* Derivation mismatch bugs fixed. +* New Test file +* External File support! (applet,images,graphs,etc) +* Code Refactoring +* New levels of Code Checking including warnings + +PG Language: What is supported? +Simple and complex pg problems including those which use applets, images, graph generation problems, etc. + +PG Language: What is not supported? +Currently the only PG files that don't fully work are those with custom graders. Hence problems will reveal which answers the student has correct despite the showCorrectAnswer flag being off. Upgrading (from 0.1): A database column was added called codecheck. If you have data that you don't want to lose your going to have to add the new column manually to the db @@ -23,15 +27,17 @@ Then you can delete the webwork directory and recreate it from the CVS ** I am not really sure if this is backward compatible to 0.1. If you are having problems with questions edit them and submit to regenerate derived copies. + Setup: 1) Make a new folder named 'webwork' in the question/type directory. 2) Copy all the files from this directory into . 3) Point your browser to http://yourmoodle/admin to setup the question_webwork database table. Configuration: -1) Change the WSDL path variable in the webwork/questiontype.php file to point to your Webwork Problem Server's WSDL file. +1) Change the WSDL path variable in the webwork/config.php file to point to your Webwork Problem Server's WSDL file. Use: +Go into the question bank and create a new WeBWorK question. A webwork question only has three special fields. -code: Paste the perl code that renders the webwork question here. -seed: The starting seed to use to generate random problems @@ -43,7 +49,7 @@ Note: Previewing the question will use random seeds. -ex problem) +Example Problem: ##DESCRIPTION Index: version.php =================================================================== RCS file: /webwork/cvs/system/wwmoodle/wwquestion/version.php,v retrieving revision 1.3 retrieving revision 1.4 diff -Lwwquestion/version.php -Lwwquestion/version.php -u -r1.3 -r1.4 --- wwquestion/version.php +++ wwquestion/version.php @@ -1,5 +1,5 @@ <?PHP // $Id$ -$plugin->version = 2007082900; // TODO. +$plugin->version = 2007090700; $plugin->requires = 2006032200; ?> \ No newline at end of file Index: questiontype.php =================================================================== RCS file: /webwork/cvs/system/wwmoodle/wwquestion/questiontype.php,v retrieving revision 1.11 retrieving revision 1.12 diff -Lwwquestion/questiontype.php -Lwwquestion/questiontype.php -u -r1.11 -r1.12 --- wwquestion/questiontype.php +++ wwquestion/questiontype.php @@ -1,12 +1,9 @@ <?php -require_once("$CFG->libdir/soap/nusoap.php"); - -require_once("htmlparser.php"); - -//Path to the WSDL file on the Webwork Server -define('PROBLEMSERVER_WSDL','YOUR WSDL PATH HERE'); - +require_once("$CFG->dirroot/question/type/webwork/config.php"); +require_once("$CFG->dirroot/question/type/webwork/locallib.php"); +require_once("$CFG->dirroot/question/type/questiontype.php"); +require_once("$CFG->dirroot/backup/lib.php"); /** * The question type class for the webwork question type. @@ -15,7 +12,6 @@ * @author mle...@gm... * @license http://www.gnu.org/copyleft/gpl.html GNU Public License * @package webwork_qtype - * **/ /** @@ -24,27 +20,32 @@ * Allows webwork questions to be used in Moodle through a new question type. */ class webwork_qtype extends default_questiontype { - + + ////////////////////////////////////////////////////////////////// + // Functions overriding default_questiontype functions + ////////////////////////////////////////////////////////////////// + + /** + * @desc Required function that names the question type. + * @return string webwork. + */ function name() { return 'webwork'; } - function _derivedquestions($derivedquestions = null) { - static $temp = null; - if($derivedquestions == null) { - return $temp; - } - $temp = $derivedquestions; - return true; + /** + * @desc Gives the label in the Create Question dropdown. + * @return string WeBWorK + */ + function menu_name() { + return 'WeBWorK'; } - + /** - * @desc Retrieves the seed and decoded code out of the question_webwork table. + * @desc Retrieves information out of question_webwork table and puts it into question object. * @return boolean to indicate success of failure. */ function get_question_options(&$question) { - // TODO code to retrieve the extra data you stored in the database into - // $question->options. if (!$record = get_record('question_webwork', 'question', $question->id)) { notify('Error: Missing question options!'); return false; @@ -53,251 +54,123 @@ $question->seed = $record->seed; $question->code = base64_decode($record->code); $question->codecheck = $record->codecheck; + //hold onto the ID of the question_webwork record $question->webworkid = $record->id; return true; } - + /** * @desc Saves the webwork question code and default seed setting into question_webwork. Will recreate all corresponding derived questions. + * @param $question object The question object holding new data. * @return boolean to indicate success of failure. */ function save_question_options($question) { - - //UPDATE OR INSERTION - if ($record = get_record("question_webwork", "question", $question->id)) { - $isupdate = true; - } else { + //determing update or insert + $oldrecord = get_record('question_webwork','question',$question->id); + if(!$oldrecord) { $isupdate = false; - unset($record); + } else { + $isupdate = true; } - //set new variables for update or insert + //set new variables for DB entry + $record = new stdClass; $record->question = $question->id; $record->codecheck = $question->codecheck; $record->code = base64_encode(stripslashes($question->code)); $record->seed = $question->seed; $record->trials = $question->trials; - - //create the derived questions and check for errors - //$results = $question->derivedquestions; - - //do the database action on question_webwork + //insert or update question in DB if($isupdate) { + //update + $record->id = $oldrecord->id; $errresult = update_record("question_webwork", $record); if (!$errresult) { - $errresult->error = "Could not update quiz webwork options! (id=$record->id)"; + $errresult->error = "Could not update question_webwork record! (id=$record->id)"; return $errresult; } } else { + //insert $errresult = insert_record("question_webwork", $record); if (!$errresult) { - $errresult->error = "Could not insert quiz webwork options!"; + $errresult->error = "Could not insert question_webwork record!"; return $errresult; } + //set the new record id $record->id = $errresult; } - - //delete the derived questions - $this->delete_derived_questions($record->id); - - //do the database action on question_webwork_derived - $err = $this->insert_derived_questions($record->id,$this->_derivedquestions()); - if($err != 0) { - return $err; + $wwquestionid = $record->id; + //copy the tmp directory to the question one + if($isupdate == false) { + rename(webwork_get_tmp_path_full(),webwork_get_wwquestion_path_full($wwquestionid)); } - return true; - } - - /** - * @desc Deletes all derived questions that are children of the ID passed in. - * @param $webworkquestionid integer The ID of the parent question - */ - function delete_derived_questions($webworkquestionid) { - delete_records("question_webwork_derived", "question_webwork", $webworkquestionid); - return true; - } - - /** - * @desc Gets derived questions from a webworkquestion record object by calling the SOAP object. - * @param $webworkquestion The record to create from - * - */ - function get_derived_questions($webworkquestion) { - //parameters needed from the webworkquestion object - $code = $webworkquestion->code; - $seed = $webworkquestion->seed; - $trials = $webworkquestion->trials; - //problem to be generated - $problem = array(); - $problem['code'] = $code; - $problem['seed'] = $seed; - - //requested # times for generation - $request = array(); - $request['trials'] = $trials; - $request['problem'] = $problem; - - //SOAP CALL - $params = array($request); - $client = new problemserver_client(); - $response = $client->handler('generateProblem',$params); - return $response; - } - - - /** - * @desc Inserts the derived questions into the DB. - * @param $parentid The parent ID of the derived questions. - * @param $derivedrecordset The recordset to create from. - */ - function insert_derived_questions($parentid,$derivedrecordset) { - - foreach($derivedrecordset as $problem) { - unset($record); - //set the parent id for the derived questions - $record->question_webwork = $parentid; - $record->html = $problem['output']; - $record->seed = $problem['seed']; - //initial insert - $result = insert_record("question_webwork_derived",$record); - if (!$result) { - $result->error = "Could not insert quiz webwork derived options!"; - return $result; - } - $record->id = $result; - - //brings image files to local drive - //THIS SHOULD ALSO DO APPLETS SOON - $err = $this->copy_derived_question_data($record); - if($err != 0) { - return $err; - } - - $result = update_record("question_webwork_derived",$record); - if(!$result) { - $result->error = "Could not update quiz webwork derived options! (id=$record->id)"; - return $result; - } - - } - return false; - } - - function copy_derived_question_data(&$derivedrecord) { - global $CFG; - //make the base directory if needed - $dir = $CFG->dataroot . '/wwquestions'; - mkdir($dir); - //make the directory for this question - $dir = $CFG->dataroot . '/wwquestions/'.$derivedrecord->id; - mkdir($dir); - - //first we need to find the image paths - $imagestocopy = array(); - $problemhtml = ""; - $unparsedhtml = base64_decode($derivedrecord->html); - $parser = new HtmlParser($unparsedhtml); - while($parser->parse()) { - if ($parser->iNodeType == NODE_TYPE_ELEMENT) { - $nodename = $parser->iNodeName; - //rewrite the images - if(($nodename == "IMG") || ($nodename == "img")) { - //found one - $srcpath = $parser->iNodeAttributes['src']; - $srcfilename = strrchr($srcpath,'/'); - $parser->iNodeAttributes['src'] = $CFG->wwwroot . "/question/type/webwork/file.php/wwquestions/" . $derivedrecord->id . '/' . $srcfilename; - //NOTE explore the possibility of having an existence check here, filenames hashed? - //copy it - $err = copy($srcpath,$CFG->dataroot.'/wwquestions/'.$derivedrecord->id.$srcfilename); - if($err == false) { - $err->error = 'Copy Failed for: '.$srcpath; - return $err; - } - - - } - } - $problemhtml .= $parser->printTag(); - } - $html = base64_encode($problemhtml); - $derivedrecord->html = $html; - return false; - } - - - /** - * @desc Deletes question from the question_webwork table - * @param integer $questionid The question being deleted - * @return boolean to indicate success of failure. - */ - function delete_question($questionid) { - //Deleting the webwork derived questions - $records = get_records('question_webwork','question',$questionid,'','id'); - foreach($records as $record) { - $this->delete_derived_questions($record->id); - } - //Deleting the webwork questions - delete_records("question_webwork", "question", $questionid); + //update the derivations + $this->_update_derivations($wwquestionid); return true; } /** - * @desc Creates an empty response before student answers a question. This contains the possibly randomized seed for that particular student. Sticky seeds are created here. + * @desc Creates an empty response before a student answers a question. This contains the possibly randomized seed for that particular student. Sticky seeds are created here. + * @param $question object The question object. + * @param $state object The state object. + * @param $cmoptions object The cmoptions containing the course ID + * @param $attempt id The attempt ID. + * @return bool true. */ function create_session_and_responses(&$question, &$state, $cmoptions, $attempt) { global $CFG,$USER; - - //directory housekeeping (insure directories are setup) - mkdir($CFG->dataroot.'/wwquestions/users'); - mkdir($CFG->dataroot.'/wwquestions/users/'.$USER->id); - - - //here we get the derived results for this question - $results = get_records("question_webwork_derived","question_webwork",$question->webworkid,'','id'); - if(!$results) { + $derivations = get_records("question_webwork_derived","question_webwork",$question->webworkid,'','id'); + if(!$derivations) { print_error(get_string('error_db_webwork_derived','qtype_webwork')); return false; } + //make sure its not 0 - if(count($results) == 0) { + if(count($derivations) == 0) { print_error(get_string('error_no_webwork_derived','qtype_webwork')); return false; } + //pick a random question based on time srand(time()); - $random = rand(0,count($results)-1); - $values = array_values($results); - $derivedid = $values[$random]->id; - - //more directory housekeeping - mkdir($CFG->dataroot.'/wwquestions/users/'.$USER->id.'/'.$derivedid); + $random = rand(0,count($derivations)-1); + $values = array_values($derivations); + $derivationid = $values[$random]->id; //get the actual data - $results = get_record('question_webwork_derived','id',$derivedid); - $state->responses['seed'] = $results->seed; - $state->responses['derivedid'] = $derivedid; + $derivation = get_record('question_webwork_derived','id',$derivationid); + //build state + $state->responses['seed'] = $derivation->seed; + $state->responses['derivationid'] = $derivation->id; + return true; + } + + /** + * @desc Deletes question from the question_webwork table + * @param integer $questionid The question being deleted + * @return boolean to indicate success of failure. + */ + function delete_question($questionid) { + //Get wwquestion from DB + $record = get_record('question_webwork','question',$questionid); + $wwquestionid = $record->id; + + //delete DB and Files + webwork_delete_wwquestion_dir($wwquestionid); + delete_records('question_webwork', 'id' , $wwquestionid); - $unparsedhtml = base64_decode($results->html); - //parse source to figure out the fields - $parser = new HtmlParser($unparsedhtml); - $currentselect = ""; - while($parser->parse()) { - if ($parser->iNodeType == NODE_TYPE_ELEMENT) { - $nodename = $parser->iNodeName; - $name = $parser->iNodeAttributes['name']; - if(($nodename == "INPUT") || ($nodename == "SELECT") || ($nodename == "TEXTAREA")) { - //THIS IS A FIELD WE NEED TO KNOW ABOUT - $state->responses['answers'][$name] = ""; - } - } - } + //delete derivations + webwork_delete_derivations_db($wwquestionid); return true; } /** * @desc Decodes and unserializes a students response into the response array carried by state + * @param $question object The question object. + * @param $state object The state that needs to be restored. + * @return bool true. */ function restore_session_and_responses(&$question, &$state) { $serializedresponse = $state->responses['']; @@ -309,10 +182,11 @@ /** * @desc Serialize, encodes and inserts a students response into the question_states table. + * @param $question object The question object for the session. + * @param $state object The state to save. + * @return true, or error on db change. */ function save_session_and_responses(&$question, &$state) { - // TODO package up the students response from the $state->responses - // array into a string and save it in the question_states.answer field. $responses = $state->responses; $serialized = serialize($responses); $serialized = base64_encode($serialized); @@ -320,7 +194,11 @@ } /** - * @desc Prints the question. Calls the Webwork Server for appropriate HTML output and image paths. + * @desc Prints the question. Calls question_webwork_derived, and prints out the html associated with derivedid. + * @param $question object The question object to print. + * @param $state object The state of the responses for the question. + * @param $cmoptions object Options containing c... [truncated message content] |
From: Matt L. v. a. <we...@ma...> - 2007-09-09 02:51:20
|
Log Message: ----------- Version 3 Released. Modified Files: -------------- ww_question_server: README ww_question_server/bin/setup: global.conf.base setup.pl ww_question_server/lib: ProblemServer.pm ww_question_server/lib/ProblemServer: ProblemRequest.pm Added Files: ----------- ww_question_server: CHANGES Revision Data ------------- --- /dev/null +++ CHANGES @@ -0,0 +1,11 @@ +CHANGES LOG: + +Version 2: (August 2007) +* Simple install with script. +* Code refactoring +* One translator per child, (speed boost) +* Fixed WSDL errors +* Minor bug fixes + +Version 1: (July 2007) +* Initial Release \ No newline at end of file Index: README =================================================================== RCS file: /webwork/cvs/system/ww_question_server/README,v retrieving revision 1.6 retrieving revision 1.7 diff -LREADME -LREADME -u -r1.6 -r1.7 --- README +++ README @@ -1,6 +1,6 @@ Webwork Question Server ---------------------- -Version: 0.2 (stable) +Version: 0.3 (stable) Maintainer: Matthew Leventi <mle...@gm...> CVS: cvs.webwork.rochester.edu:/webwork/cvs/system ww_question_server @@ -9,7 +9,12 @@ Note: You don't need to install the WeBWorK system for this server to function. All you need are the PG libraries. Whats new: -* Simple install with script. +* Safe compartment errors fixed. +* Automatic downloading of external files for PG questions. +* Many bug fixes +* Added tth support. +-- +* Simple install with script. * Code refactoring * One translator per child, (speed boost) * Fixed WSDL errors @@ -20,13 +25,16 @@ * Apache 1 or 2 * mod_perl * Apache::SOAP CPAN Module for apache 1, or Apache2::SOAP CPAN Module for apache2 -* latex and dvipng installed +* LWP::Simple module +* latex,dvipng,tth installed * WeBWorK PG libraries installed Setup: 1) Change permissions for directories writable by server chmod -R 777 htdocs/tmp + chown -R www-data:www-data htdocs/tmp chmod -R 777 tmp + chown -R www-data:www-data tmp 2) Run the setup program in bin/setup perl setup.pl Write down the WSDL path that the setup program gives you. It is what you use in the Moodle - WeBWorK Question Type. @@ -38,4 +46,3 @@ Note: The problemserver.apache-config works for both apache 1 and 2. ex) Include /home/you/problemserver/conf/problemserver.apache-config 6) Restart Apache - Index: global.conf.base =================================================================== RCS file: /webwork/cvs/system/ww_question_server/bin/setup/global.conf.base,v retrieving revision 1.3 retrieving revision 1.4 diff -Lbin/setup/global.conf.base -Lbin/setup/global.conf.base -u -r1.3 -r1.4 --- bin/setup/global.conf.base +++ bin/setup/global.conf.base @@ -64,6 +64,7 @@ # equation rendering/hardcopy utiltiies $externalPrograms{latex} = "MARKER_FOR_LATEX"; $externalPrograms{dvipng} = "MARKER_FOR_DVIPNG"; +$externalPrograms{tth} = "MARKER_FOR_TTH"; ################################################################################ @@ -249,15 +250,16 @@ #define the problem environment #psvn -$problemEnviron{psvn} = "1"; +$problemEnviron{psvn} = "PSVN"; $problemEnviron{psvnNumber} = $problemEnviron{psvn}; +$problemEnviron{setNumber} = $problemEnviron{psvn}; #problemNum -$problemEnviron{probNum} = "1"; +$problemEnviron{probNum} = "PROBNUM"; $problemEnviron{questionNumber} = $problemEnviron{probNum}; #fileName -$problemEnviron{fileName} = "ServerFile"; +$problemEnviron{fileName} = "FILENAME"; $problemEnviron{probFileName} = $problemEnviron{fileName}; #seed @@ -301,6 +303,17 @@ $problemEnviron{asciimathURL} = $problemServerURLs{asciimath}; $problemEnviron{LaTeXMathMLURL} = $problemServerURLs{LaTeXMathML}; +#More Problem Environment Configuration +$problemEnviron{htmlDirectory} = ' '; +$problemEnviron{htmlURL} = ' '; +$problemEnviron{tempURL} = $problemServerURLs{htdocs_temp} . '/'; +$problemEnviron{tempDirectory} = $problemServerDirs{htdocs_temp} . '/'; +$problemEnviron{templateDirectory} = $problemServerDirs{htdocs_temp} . '/'; + +$problemEnviron{setName} = "QuestionServer"; +$problemEnviron{studentLogin} = "guest"; + + #Default answers to fill blanks with. my $ansEvalDefaults = $pg{ansEvalDefaults}; Index: setup.pl =================================================================== RCS file: /webwork/cvs/system/ww_question_server/bin/setup/setup.pl,v retrieving revision 1.2 retrieving revision 1.3 diff -Lbin/setup/setup.pl -Lbin/setup/setup.pl -u -r1.2 -r1.3 --- bin/setup/setup.pl +++ bin/setup/setup.pl @@ -63,6 +63,15 @@ $dvipng = "/usr/bin/dvipng"; } +print "Please enter the path to 'tth' command. Leave blank for default. \n"; +print "Default '/usr/bin/tth'\n"; +print ">"; +$tth = <STDIN>; +chop $tth; +if($tth eq "") { + $tth = "/usr/bin/tth"; +} + @@ -133,6 +142,7 @@ close INPUT2; $content =~ s/MARKER_FOR_DVIPNG/$dvipng/; $content =~ s/MARKER_FOR_LATEX/$latex/; +$content =~ s/MARKER_FOR_TTH/$tth/; print " Writing...\n"; open(OUTP3, ">global.conf") or die("Cannot open file 'global.conf' for writing.\n"); print OUTP3 $content; Index: ProblemServer.pm =================================================================== RCS file: /webwork/cvs/system/ww_question_server/lib/ProblemServer.pm,v retrieving revision 1.9 retrieving revision 1.10 diff -Llib/ProblemServer.pm -Llib/ProblemServer.pm -u -r1.9 -r1.10 --- lib/ProblemServer.pm +++ lib/ProblemServer.pm @@ -6,6 +6,10 @@ use MIME::Base64 qw( encode_base64 decode_base64); +use Safe; + +use LWP::Simple; + use ProblemServer::Environment; use ProblemServer::Utils::RestrictedClosureClass; @@ -47,6 +51,7 @@ #Construct the Server Environment my $serverEnviron = new ProblemServer::Environment(); + $SIG{__WARN__} = sub { $self->{warnings} .= shift }; #Keep the Default Server Environment $self->{serverEnviron} = $serverEnviron; @@ -54,15 +59,16 @@ #Keep the Default Problem Environment $self->{problemEnviron} = ($self->{serverEnviron}{problemEnviron}); - #Create Safe Compartment - $self->{safe} = new Safe; - bless $self; return $self; } sub setupTranslator { my $self = shift; + + #Warnings are passed into self + #local $SIG{__WARN__} = sub { $self->{warnings} .= shift }; + #Create Translator Object my $translator = WeBWorK::PG::Translator->new; @@ -95,6 +101,9 @@ sub setupImageGenerator { my $self = shift; + #Warnings are passed into self + #local $SIG{__WARN__} = sub { $self->{warnings} .= shift }; + my $image_generator; my %imagesModeOptions = %{$self->{serverEnviron}->{pg}{displayModeOptions}{images}}; $image_generator = WeBWorK::PG::ImageGenerator->new( @@ -121,22 +130,43 @@ $ProblemServer::theServer->setupImageGenerator(); } +sub downloadFiles { + my ($self,$files) = @_; + foreach(@{$files}) { + my $fileurl = decode_base64($_); + my $lastslash = rindex($fileurl,'/'); + my $filepath = $self->{serverEnviron}->{problemServerDirs}->{htdocs_temp} . substr($fileurl,$lastslash); + mirror($fileurl,$filepath); + } +} + sub runTranslator { my ($self,$source,$seed) = @_; + #Warnings are passed into sel local $SIG{__WARN__} = sub { $self->{warnings} .= shift }; + $source = decode_base64($source); #Assigning Seed $self->{problemEnviron}{problemSeed} = $seed; + #Clear some stuff + $self->{translator}->{safe} = undef; + $self->{translator}->{envir} = undef; + + $self->{translator}->{safe} = new Safe; + #Setting Environment $self->{translator}->environment($self->{problemEnviron}); #Initializing $self->{translator}->initialize(); + #Safe + #$self->{safe} = new Safe; + #PRE-LOAD MACRO FILES eval{$self->{translator}->pre_load_macro_files( - $self->{safe}, + new Safe, $self->{serverEnviron}->{pg}->{directories}->{macros}, 'PG.pl', 'dangerousMacros.pl','IO.pl','PGbasicmacros.pl','PGanswermacros.pl' )}; @@ -164,6 +194,10 @@ sub runChecker { my $self = shift; + + #Warnings are passed into self + #local $SIG{__WARN__} = sub { $self->{warnings} .= shift }; + my $answerArray = shift; my $answerHash = {}; @@ -237,16 +271,28 @@ sub runImageGenerator { my $self = shift; + + #Warnings are passed into self + #local $SIG{__WARN__} = sub { $self->{warnings} .= shift }; + $self->{imageGenerator}->render(body_text => $self->{translator}->r_text); } sub runImageGeneratorAnswers { my $self = shift; + + #Warnings are passed into self + #local $SIG{__WARN__} = sub { $self->{warnings} .= shift }; + $self->{imageGenerator}->render(); } sub buildProblemResponse { my $self = shift; + + #Warnings are passed into self + #local $SIG{__WARN__} = sub { $self->{warnings} .= shift }; + my $response = new ProblemServer::ProblemResponse; $response->{errors} = $self->{translator}->errors; $response->{warnings} = $self->{warnings}; @@ -257,6 +303,7 @@ sub clean { my $self = shift; $self->{translator}->{errors} = undef; + $self->{warnings} = ""; } @@ -288,7 +335,7 @@ sub renderProblem { my ($self,$request) = @_; my $server = $ProblemServer::theServer; - + $server->downloadFiles($request->{files}); $server->runTranslator($request->{code},$request->{seed}); $server->runImageGenerator(); @@ -311,6 +358,7 @@ foreach($requests) { my $request = $_; + $server->downloadFiles($request->{files}); $server->runTranslator($request->{code},$request->{seed}); $server->runImageGenerator(); my $response = $server->buildProblemResponse(); @@ -333,6 +381,9 @@ my $trials = $request->{trials}; my $problem = $request->{problem}; + + $server->downloadFiles($problem->{files}); + my @derivedProblems; my $found; my $problemResponse; @@ -370,6 +421,7 @@ my $request = $_; my $trials = $request->{trials}; my $problem = $request->{problem}; + $server->downloadFiles($problem->{files}); my @derivedProblems; my $found; for(my $itr = 0; $itr < $trials ; $itr++ ) { Index: ProblemRequest.pm =================================================================== RCS file: /webwork/cvs/system/ww_question_server/lib/ProblemServer/ProblemRequest.pm,v retrieving revision 1.3 retrieving revision 1.4 diff -Llib/ProblemServer/ProblemRequest.pm -Llib/ProblemServer/ProblemRequest.pm -u -r1.3 -r1.4 --- lib/ProblemServer/ProblemRequest.pm +++ lib/ProblemServer/ProblemRequest.pm @@ -3,8 +3,9 @@ =pod =begin WSDL - _ATTR code $string The PG code to be translated - _ATTR seed $string The seed to be used for randomization + _ATTR code $string The PG code to be translated. + _ATTR seed $string The seed to be used for randomization. + _ATTR files @string The external files needed. =end WSDL =cut sub new { @@ -13,6 +14,7 @@ $self = {}; $self->{code} = $data->{code}; $self->{seed} = $data->{seed}; + $self->{files} = $data->{files}; bless $self; return $self; } |
From: dpvc v. a. <we...@ma...> - 2007-09-08 23:00:45
|
Log Message: ----------- Report error messages correctly when ijk notation is involved and ijkAnyDimension is set. Modified Files: -------------- pg/lib/Value: AnswerChecker.pm Revision Data ------------- Index: AnswerChecker.pm =================================================================== RCS file: /webwork/cvs/system/pg/lib/Value/AnswerChecker.pm,v retrieving revision 1.112 retrieving revision 1.113 diff -Llib/Value/AnswerChecker.pm -Llib/Value/AnswerChecker.pm -u -r1.112 -r1.113 --- lib/Value/AnswerChecker.pm +++ lib/Value/AnswerChecker.pm @@ -865,8 +865,11 @@ return unless $ans->{score} == 0 && !$ans->{isPreview}; my $student = $ans->{student_value}; return if $ans->{ignoreStrings} && (!Value::isValue($student) || $student->type eq 'String'); - if ($ans->{showDimensionHints} && $self->length != $student->length) { - $self->cmp_Error($ans,"The number of coordinates is incorrect"); return; + if ($self->length != $student->length) { + ($self,$student) = $self->cmp_pad($student); + if ($ans->{showDimensionHints} && $self->length != $student->length) { + $self->cmp_Error($ans,"The number of coordinates is incorrect"); return; + } } if ($ans->{parallel} && !$student->isFormula && !$student->classMatch('String') && $self->isParallel($student,$ans->{sameDirection})) { @@ -882,6 +885,23 @@ } } +# +# Pad the student or correct answer if either is in ijk notation +# and they are not the same dimension. Only add zeros when the other one +# also has zeros in those places. +# +sub cmp_pad { + my $self = shift; my $student = shift; + if (($self->getFlag("ijk") || $student->getFlag("ijk")) && $self->getFlag("ijkAnyDimension")) { + $self = $self->copy; $student = $student->copy; + while ($self->length > $student->length && $self->{data}[$student->length] == 0) + {push(@{$student->{data}},Value::Real->new(0))} + while ($self->length < $student->length && $student->{data}[$self->length] == 0) + {push(@{$self->{data}},Value::Real->new(0))} + } + return ($self,$student); +} + sub correct_ans { my $self = shift; return $self->SUPER::correct_ans unless $self->{ans_name}; |
From: dpvc v. a. <we...@ma...> - 2007-09-08 22:37:07
|
Log Message: ----------- Use ijkAnyDimension in the check for parallel vectors as well. Modified Files: -------------- pg/lib/Value: Vector.pm Revision Data ------------- Index: Vector.pm =================================================================== RCS file: /webwork/cvs/system/pg/lib/Value/Vector.pm,v retrieving revision 1.36 retrieving revision 1.37 diff -Llib/Value/Vector.pm -Llib/Value/Vector.pm -u -r1.36 -r1.37 --- lib/Value/Vector.pm +++ lib/Value/Vector.pm @@ -189,7 +189,13 @@ my $context = $self->context; my $sameDirection = shift; my @u = $U->value; my @v = $V->value; - return 0 unless scalar(@u) == scalar(@v); + if (scalar(@u) != scalar(@v)) { + return 0 unless + ($U->getFlag("ijk") || $V->getFlag("ijk")) && + ($U->getFlag("ijkAnyDimension") || $V->getFlag("ijkAnyDimension")); + if (scalar(@u) < scalar(@v)) {push(@u,0 x (scalar(@v)-scalar(@u)))} + else {push(@v,0 x (scalar(@u)-scalar(@v)))} + } my $k = ''; # will be scaling factor for u = k v foreach my $i (0..$#u) { # |
From: dpvc v. a. <we...@ma...> - 2007-09-08 22:33:28
|
Log Message: ----------- Had the inequality going the wrong way. OOPS! Modified Files: -------------- pg/lib/Value: Vector.pm Revision Data ------------- Index: Vector.pm =================================================================== RCS file: /webwork/cvs/system/pg/lib/Value/Vector.pm,v retrieving revision 1.35 retrieving revision 1.36 diff -Llib/Value/Vector.pm -Llib/Value/Vector.pm -u -r1.35 -r1.36 --- lib/Value/Vector.pm +++ lib/Value/Vector.pm @@ -147,7 +147,7 @@ return scalar(@l) <=> scalar(@r) unless ($l->getFlag("ijk") || $r->getFlag("ijk")) && ($l->getFlag("ijkAnyDimension") || $r->getFlag("ijkAnyDimension")); - if (scalar(@l) > scalar(@r)) {push(@l,0 x (scalar(@r)-scalar(@l)))} + if (scalar(@l) < scalar(@r)) {push(@l,0 x (scalar(@r)-scalar(@l)))} else {push(@r,0 x (scalar(@l)-scalar(@r)))} } my $cmp = 0; |
From: dpvc v. a. <we...@ma...> - 2007-09-08 22:30:36
|
Log Message: ----------- Make vectors that are creates using ijk notation remain in ijk notation when displayed. (This is easy now that objects produced by combining others inherit the parent objects' flags.) Added another context flag (ijkAnyDimension) that controls whether vectors in ijk notation will conform to whatever dimension is used by the vector they are being compared to. When set, i+2*j will equal <1,2> even though i and j are vectors in 3-space. The value of ijkAnyDimension is 1 by default. This eliminates the need for the Vector2D context. Modified Files: -------------- pg/lib/Parser/Context: Default.pm pg/lib/Value: Vector.pm Revision Data ------------- Index: Default.pm =================================================================== RCS file: /webwork/cvs/system/pg/lib/Parser/Context/Default.pm,v retrieving revision 1.41 retrieving revision 1.42 diff -Llib/Parser/Context/Default.pm -Llib/Parser/Context/Default.pm -u -r1.41 -r1.42 --- lib/Parser/Context/Default.pm +++ lib/Parser/Context/Default.pm @@ -131,8 +131,8 @@ 'e' => exp(1), 'pi' => 4*atan2(1,1), 'i' => Value::Complex->new(0,1), - 'j' => Value::Vector->new(0,1,0), - 'k' => Value::Vector->new(0,0,1), + 'j' => Value::Vector->new(0,1,0)->with(ijk=>1), + 'k' => Value::Vector->new(0,0,1)->with(ijk=>1), '_blank_' => {value => 0, hidden => 1, string => "", TeX => ""}, }; @@ -223,7 +223,8 @@ }; $flags = { - ijk => 0, # 1 = show vectors in ijk form + ijk => 0, # 1 = show all vectors in ijk form + ijkAnyDimension => 1, # 1 = add/remove trailing zeros to match dimension in comparisons reduceConstants => 1, # 1 = automatically combine constants reduceConstantFunctions => 1, # 1 = compute function values of constants showExtraParens => 1, # 1 = add useful parens, 2 = make things painfully unambiguous @@ -316,14 +317,14 @@ $context = $context{Vector} = $context{Full}->copy; $context->variables->are(x=>'Real',y=>'Real',z=>'Real'); $context->functions->undefine('arg','mod','Re','Im','conj'); -$context->constants->replace(i=>Value::Vector->new(1,0,0)); +$context->constants->replace(i=>Value::Vector->new(1,0,0)->with(ijk=>1)); $context->constants->set(i=>{TeX=>'\boldsymbol{i}', perl=>'i'}); $context->parens->set('(' => {formMatrix => 0}); $context = $context{Vector2D} = $context{Vector}->copy; $context->constants->replace( - i => Value::Vector->new(1,0), - j => Value::Vector->new(0,1), + i => Value::Vector->new(1,0)->with(ijk=>1), + j => Value::Vector->new(0,1)->with(ijk=>1), ); $context->constants->set(i => {TeX=>'\boldsymbol{i}', perl=>'i'}); $context->constants->remove("k"); Index: Vector.pm =================================================================== RCS file: /webwork/cvs/system/pg/lib/Value/Vector.pm,v retrieving revision 1.34 retrieving revision 1.35 diff -Llib/Value/Vector.pm -Llib/Value/Vector.pm -u -r1.34 -r1.35 --- lib/Value/Vector.pm +++ lib/Value/Vector.pm @@ -143,7 +143,13 @@ sub compare { my ($self,$l,$r) = Value::checkOpOrderWithPromote(@_); my @l = $l->value; my @r = $r->value; - return scalar(@l) <=> scalar(@r) unless scalar(@l) == scalar(@r); + if (scalar(@l) != scalar(@r)) { + return scalar(@l) <=> scalar(@r) unless + ($l->getFlag("ijk") || $r->getFlag("ijk")) && + ($l->getFlag("ijkAnyDimension") || $r->getFlag("ijkAnyDimension")); + if (scalar(@l) > scalar(@r)) {push(@l,0 x (scalar(@r)-scalar(@l)))} + else {push(@r,0 x (scalar(@l)-scalar(@r)))} + } my $cmp = 0; foreach my $i (0..scalar(@l)-1) { $cmp = $l[$i] <=> $r[$i]; |
From: dpvc v. a. <we...@ma...> - 2007-09-08 21:53:17
|
Log Message: ----------- Make copies of the components rather than just copying the pointers. Modified Files: -------------- pg/lib/Parser: Constant.pm Revision Data ------------- Index: Constant.pm =================================================================== RCS file: /webwork/cvs/system/pg/lib/Parser/Constant.pm,v retrieving revision 1.13 retrieving revision 1.14 diff -Llib/Parser/Constant.pm -Llib/Parser/Constant.pm -u -r1.13 -r1.14 --- lib/Parser/Constant.pm +++ lib/Parser/Constant.pm @@ -36,15 +36,16 @@ my $self = shift; my $context = $self->context; my $data = $self->{def}{value}; if (Value::isFormula($data)) { + $data = $data->copy; $data->{values} = $self->{equation}{values}; - my $value = $data->{tree}->eval; - $data->{values} = {}; - return $value->inContext($self->context); + $data = $data->{tree}->eval->inContext($context); + return $data; } elsif (ref($data) eq 'ARRAY') { - foreach my $x (@{$data}) {$x->inContext($context)} + $data = [@${data}]; + foreach my $x (@{$data}) {$x = $x->copy->inContext($context)} return @{$data}; } else { - $data = $data->inContext($context) if Value::isValue($data); + $data = $data->copy->inContext($context) if Value::isValue($data); return $data; } } |
From: dpvc v. a. <we...@ma...> - 2007-09-08 21:51:09
|
Log Message: ----------- No longer need to change the order of the data, since Value::Interval->make() now handles the alternative order. Modified Files: -------------- pg/macros: contextInequalities.pl Revision Data ------------- Index: contextInequalities.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/contextInequalities.pl,v retrieving revision 1.10 retrieving revision 1.11 diff -Lmacros/contextInequalities.pl -Lmacros/contextInequalities.pl -u -r1.10 -r1.11 --- macros/contextInequalities.pl +++ macros/contextInequalities.pl @@ -516,11 +516,6 @@ sub type {"Interval"} -sub makeData { - my ($a,$b,$open,$close) = (shift)->value; - return ($open,$a,$b,$close); -} - sub string { my $self = shift; my ($a,$b,$open,$close) = $self->value; |
From: dpvc v. a. <we...@ma...> - 2007-09-08 21:41:48
|
Log Message: ----------- Removed an experiment that I accidentally left in during the last commit. Modified Files: -------------- pg/lib/Value: Vector.pm Revision Data ------------- Index: Vector.pm =================================================================== RCS file: /webwork/cvs/system/pg/lib/Value/Vector.pm,v retrieving revision 1.33 retrieving revision 1.34 diff -Llib/Value/Vector.pm -Llib/Value/Vector.pm -u -r1.33 -r1.34 --- lib/Value/Vector.pm +++ lib/Value/Vector.pm @@ -143,10 +143,6 @@ sub compare { my ($self,$l,$r) = Value::checkOpOrderWithPromote(@_); my @l = $l->value; my @r = $r->value; - if ($self->getFlag("ignoreTrailingZeros")) { - while (scalar(@l) < scalar(@r) && $r[scalar(@l)] == 0) {push(@l,0)} - while (scalar(@r) < scalar(@l) && $r[scalar(@r)] == 0) {push(@r,0)} - } return scalar(@l) <=> scalar(@r) unless scalar(@l) == scalar(@r); my $cmp = 0; foreach my $i (0..scalar(@l)-1) { |
From: dpvc v. a. <we...@ma...> - 2007-09-08 21:40:23
|
Log Message: ----------- The make() method now inherits all the settings of the parent object, so that flags set by the user (e.g., tolerances, periods, and so on) will be passed on as new objects are created. For example, in $x = Real(1)=>with(tolerance=>.0001); $y = sin($x); $y will also have tolerance set to .0001. This also applies to binary operations, where the result will now inherit all the values of either operand, with the left-hand operand taking precedence when they both have a flag set but to different values. This is a significant change, and there may be unforeseen side effects that I'll have to take care of as they appear. It passes my test suite, however, so I'm hoping they will be limited. Modified Files: -------------- pg/lib: Value.pm pg/lib/Value: Complex.pm Matrix.pm Point.pm Real.pm Vector.pm Revision Data ------------- Index: Value.pm =================================================================== RCS file: /webwork/cvs/system/pg/lib/Value.pm,v retrieving revision 1.90 retrieving revision 1.91 diff -Llib/Value.pm -Llib/Value.pm -u -r1.90 -r1.91 --- lib/Value.pm +++ lib/Value.pm @@ -195,7 +195,7 @@ push(@{$$context->{data}{values}},'method','precedence'); # -# Copy a context and its data +# Copy an item and its data # sub copy { my $self = shift; @@ -557,7 +557,7 @@ sub make { my $self = shift; my $class = ref($self) || $self; my $context = (Value::isContext($_[0]) ? shift : $self->context); - bless {data => [@_], context => $context}, $class; + bless {$self->hash, data => [@_], context => $context}, $class; } # @@ -570,6 +570,35 @@ bless {%{$self},@_}, ref($self); } +# +# Return a copy with the specified fields removed +# +sub without { + my $self = shift; + $self = bless {%{$self}}, ref($self); + foreach my $id (@_) {delete $self->{$id} if defined $self->{$id}} + return $self; +} + +# +# Return the hash data as an array of key=>value pairs +# +sub hash { + my $self = shift; + return %$self if isHash($self); + return (); +} + +# +# Copy attributes that are not already in the current object +# from the given objects. (Used by binary operators to make sure +# the result inherits the values from the two terms.) +# +sub inherit { + my $self = shift; + bless {(map {%$_} @_),%$self}, ref($self); +} + ###################################################################### # @@ -688,7 +717,7 @@ # sub checkOpOrder { my ($l,$r,$flag) = @_; - if ($flag) {return ($l,$r,$l)} else {return ($l,$l,$r)} + if ($flag) {return ($l,$r,$l,$r)} else {return ($l,$l,$r,$r)} } # @@ -697,7 +726,7 @@ # sub checkOpOrderWithPromote { my ($l,$r,$flag) = @_; $r = $l->promote($r); - if ($flag) {return ($l,$r,$l)} else {return ($l,$l,$r)} + if ($flag) {return ($l,$r,$l,$r)} else {return ($l,$l,$r,$r)} } # Index: Real.pm =================================================================== RCS file: /webwork/cvs/system/pg/lib/Value/Real.pm,v retrieving revision 1.39 retrieving revision 1.40 diff -Llib/Value/Real.pm -Llib/Value/Real.pm -u -r1.39 -r1.40 --- lib/Value/Real.pm +++ lib/Value/Real.pm @@ -72,41 +72,41 @@ # sub add { - my ($self,$l,$r) = Value::checkOpOrderWithPromote(@_); - return $self->make($l->{data}[0] + $r->{data}[0]); + my ($self,$l,$r,$other) = Value::checkOpOrderWithPromote(@_); + return $self->inherit($other)->make($l->{data}[0] + $r->{data}[0]); } sub sub { - my ($self,$l,$r) = Value::checkOpOrderWithPromote(@_); - return $self->make($l->{data}[0] - $r->{data}[0]); + my ($self,$l,$r,$other) = Value::checkOpOrderWithPromote(@_); + return $self->inherit($other)->make($l->{data}[0] - $r->{data}[0]); } sub mult { - my ($self,$l,$r) = Value::checkOpOrderWithPromote(@_); - return $self->make($l->{data}[0] * $r->{data}[0]); + my ($self,$l,$r,$other) = Value::checkOpOrderWithPromote(@_); + return $self->inherit($other)->make($l->{data}[0] * $r->{data}[0]); } sub div { - my ($self,$l,$r) = Value::checkOpOrderWithPromote(@_); + my ($self,$l,$r,$other) = Value::checkOpOrderWithPromote(@_); Value::Error("Division by zero") if $r->{data}[0] == 0; - return $self->make($l->{data}[0] / $r->{data}[0]); + return $self->inherit($other)->make($l->{data}[0] / $r->{data}[0]); } sub power { - my ($self,$l,$r) = Value::checkOpOrderWithPromote(@_); + my ($self,$l,$r,$other) = Value::checkOpOrderWithPromote(@_); my $x = $l->{data}[0] ** $r->{data}[0]; - return $self->make($x) unless $x eq 'nan'; + return $self->inherit($other)->make($x) unless $x eq 'nan'; Value::Error("Can't raise a negative number to a power") if ($l->{data}[0] < 0); Value::Error("Result of exponention is not a number"); } sub modulo { - my ($self,$l,$r) = Value::checkOpOrderWithPromote(@_); + my ($self,$l,$r,$other) = Value::checkOpOrderWithPromote(@_); $l = $l->{data}[0]; $r = $r->{data}[0]; - return $self->make(0) if $r == 0; # non-fuzzy check + return $self->inherit($other)->make(0) if $r == 0; # non-fuzzy check my $m = $l/$r; my $n = int($m); $n-- if $n > $m; # act as floor() rather than int() - return $self->make($l - $n*$r); + return $self->inherit($other)->make($l - $n*$r); } sub compare { @@ -116,6 +116,8 @@ # my $m = $self->getFlag("period"); if (defined $m) { + $l = $l->with(period=>undef); # make sure tests below don't use period + $r = $r->with(period=>undef); if ($self->getFlag("logPeriodic")) { return 1 if $l->value == 0 || $r->value == 0; # non-fuzzy checks $l = log($l); $r = log($r); @@ -161,8 +163,8 @@ sub cos {my $self = shift; $self->make(CORE::cos($self->{data}[0]))} sub atan2 { - my ($self,$l,$r) = Value::checkOpOrderWithPromote(@_); - return $self->make(CORE::atan2($l->{data}[0],$r->{data}[0])); + my ($self,$l,$r,$other) = Value::checkOpOrderWithPromote(@_); + return $self->inherit($other)->make(CORE::atan2($l->{data}[0],$r->{data}[0])); } ################################################## @@ -170,7 +172,8 @@ sub string { my $self = shift; my $equation = shift; my $prec = shift; my $n = $self->{data}[0]; - my $format = $self->getFlag("format",$equation->{format} || ($equation->{context} || $self->context)->{format}{number}); + my $format = $self->getFlag("format",$equation->{format} || + ($equation->{context} || $self->context)->{format}{number}); if ($format) { $n = sprintf($format,$n); if ($format =~ m/#\s*$/) {$n =~ s/(\.\d*?)0*#$/$1/; $n =~ s/\.$//} Index: Vector.pm =================================================================== RCS file: /webwork/cvs/system/pg/lib/Value/Vector.pm,v retrieving revision 1.32 retrieving revision 1.33 diff -Llib/Value/Vector.pm -Llib/Value/Vector.pm -u -r1.32 -r1.33 --- lib/Value/Vector.pm +++ lib/Value/Vector.pm @@ -50,16 +50,6 @@ } # -# Make sure column vector is retained -# -sub make { - my $self = shift; - my $v = $self->SUPER::make(@_); - $v->{ColumnVector} = 1 if ref($self) && $self->{ColumnVector}; - return $v; -} - -# # Try to promote arbitary data to a vector # sub promote { @@ -69,7 +59,7 @@ return $self->new($context,$x,@_) if scalar(@_) > 0 || ref($x) eq 'ARRAY'; $x = Value::makeValue($x,context=>$context); return $x->inContext($context) if ref($x) eq $class; - return $self->make($context,$x->value) if Value::classMatch($x,'Point'); + return $self->make($context,$x->value)->inherit($x->without('open','close')) if Value::classMatch($x,'Point'); Value::Error("Can't convert %s to %s",Value::showClass($x),Value::showClass($self)); } @@ -81,23 +71,23 @@ # sub add { - my ($self,$l,$r) = Value::checkOpOrderWithPromote(@_); + my ($self,$l,$r,$other) = Value::checkOpOrderWithPromote(@_); my @l = $l->value; my @r = $r->value; Value::Error("Can't add Vectors with different numbers of coordinates") unless scalar(@l) == scalar(@r); my @s = (); foreach my $i (0..scalar(@l)-1) {push(@s,$l[$i] + $r[$i])} - return $self->make(@s); + return $self->inherit($other)->make(@s); } sub sub { - my ($self,$l,$r) = Value::checkOpOrderWithPromote(@_); + my ($self,$l,$r,$other) = Value::checkOpOrderWithPromote(@_); my @l = $l->value; my @r = $r->value; Value::Error("Can't subtract Vectors with different numbers of coordinates") unless scalar(@l) == scalar(@r); my @s = (); foreach my $i (0..scalar(@l)-1) {push(@s,$l[$i] - $r[$i])} - return $self->make(@s); + return $self->inherit($other)->make(@s); } sub mult { @@ -137,13 +127,13 @@ } sub cross { - my ($self,$l,$r) = Value::checkOpOrderWithPromote(@_); + my ($self,$l,$r,$other) = Value::checkOpOrderWithPromote(@_); my @l = $l->value; my @r = $r->value; Value::Error("Vectors for cross product must be in 3-space") unless scalar(@l) == 3 && scalar(@r) == 3; - $self->make($l[1]*$r[2] - $l[2]*$r[1], - -($l[0]*$r[2] - $l[2]*$r[0]), - $l[0]*$r[1] - $l[1]*$r[0]); + $self->inherit($other)->make($l[1]*$r[2] - $l[2]*$r[1], + -($l[0]*$r[2] - $l[2]*$r[0]), + $l[0]*$r[1] - $l[1]*$r[0]); } # @@ -153,6 +143,10 @@ sub compare { my ($self,$l,$r) = Value::checkOpOrderWithPromote(@_); my @l = $l->value; my @r = $r->value; + if ($self->getFlag("ignoreTrailingZeros")) { + while (scalar(@l) < scalar(@r) && $r[scalar(@l)] == 0) {push(@l,0)} + while (scalar(@r) < scalar(@l) && $r[scalar(@r)] == 0) {push(@r,0)} + } return scalar(@l) <=> scalar(@r) unless scalar(@l) == scalar(@r); my $cmp = 0; foreach my $i (0..scalar(@l)-1) { @@ -300,4 +294,3 @@ ########################################################################### 1; - Index: Complex.pm =================================================================== RCS file: /webwork/cvs/system/pg/lib/Value/Complex.pm,v retrieving revision 1.34 retrieving revision 1.35 diff -Llib/Value/Complex.pm -Llib/Value/Complex.pm -u -r1.34 -r1.35 --- lib/Value/Complex.pm +++ lib/Value/Complex.pm @@ -39,7 +39,7 @@ my $self = shift; my $class = ref($self) || $self; my $context = (Value::isContext($_[0]) ? shift : $self->context); while (scalar(@_) < 2) {push(@_,0)} - my $c = bless {data => [@_[0,1]], context => $context}, $class; + my $c = bless {$self->hash, data => [@_[0,1]], context => $context}, $class; foreach my $x (@{$c->{data}}) {$x = $context->Package("Real")->make($context,$x) unless Value::isValue($x)} return $c; } @@ -84,42 +84,42 @@ # sub add { - my ($self,$l,$r) = Value::checkOpOrderWithPromote(@_); + my ($self,$l,$r,$other) = Value::checkOpOrderWithPromote(@_); my ($a,$b) = $l->value; my ($c,$d) = $r->value; - return $self->make($a + $c, $b + $d); + return $self->inherit($other)->make($a + $c, $b + $d); } sub sub { - my ($self,$l,$r) = Value::checkOpOrderWithPromote(@_); + my ($self,$l,$r,$other) = Value::checkOpOrderWithPromote(@_); my ($a,$b) = $l->value; my ($c,$d) = $r->value; - return $self->make($a - $c, $b - $d); + return $self->inherit($other)->make($a - $c, $b - $d); } sub mult { - my ($self,$l,$r) = Value::checkOpOrderWithPromote(@_); + my ($self,$l,$r,$other) = Value::checkOpOrderWithPromote(@_); my ($a,$b) = $l->value; my ($c,$d) = $r->value; - return $self->make($a*$c - $b*$d, $b*$c + $a*$d); + return $self->inherit($other)->make($a*$c - $b*$d, $b*$c + $a*$d); } sub div { - my ($self,$l,$r) = Value::checkOpOrderWithPromote(@_); + my ($self,$l,$r,$other) = Value::checkOpOrderWithPromote(@_); my ($a,$b) = $l->value; my ($c,$d) = $r->value; my $x = $c*$c + $d*$d; Value::Error("Division by zero") if $x->value == 0; - return $self->make(($a*$c + $b*$d)/$x,($b*$c - $a*$d)/$x); + return $self->inherit($other)->make(($a*$c + $b*$d)/$x,($b*$c - $a*$d)/$x); } sub power { - my ($self,$l,$r) = Value::checkOpOrderWithPromote(@_); + my ($self,$l,$r,$other) = Value::checkOpOrderWithPromote(@_); my ($a,$b) = $l->value; my ($c,$d) = $r->value; - return $self->make(1,0) if ($a->value == 1 && $b->value == 0) || ($c->value == 0 && $d->value == 0); - return $self->make(0,0) if $c->value > 0 && ($a->value == 0 && $b->value == 0); + return $self->inherit($other)->make(1,0) if ($a->value == 1 && $b->value == 0) || ($c->value == 0 && $d->value == 0); + return $self->inherit($other)->make(0,0) if $c->value > 0 && ($a->value == 0 && $b->value == 0); return exp($r * log($l)) } sub modulo { - my ($self,$l,$r) = Value::checkOpOrderWithPromote(@_); - return $self->make(0) if abs($r)->value == 0; # non-fuzzy check + my ($self,$l,$r,$other) = Value::checkOpOrderWithPromote(@_); + return $self->inherit($other)->make(0) if abs($r)->value == 0; # non-fuzzy check my $m = Re($l/$r)->value; my $n = int($m); $n-- if $n > $m; # act as floor() rather than int() return $l - $n*$r; @@ -132,6 +132,8 @@ # my $m = $self->getFlag("period"); if (defined $m) { + $l = $l->with(period=>undef); # make sure tests below don't use period + $r = $r->with(period=>undef); if ($self->getFlag("logPeriodic")) { return 1 if abs($l)->value == 0 || abs($r)->value == 0; # non-fuzzy checks $l = log($l); $r = log($r); @@ -248,7 +250,8 @@ # atan2(z1,z2) = atan(z1/z2) sub atan2 { - my ($self,$l,$r) = Value::checkOpOrderWithPromote(@_); + my ($self,$l,$r,$other) = Value::checkOpOrderWithPromote(@_); + $self = $self->inherit($other); my ($a,$b) = $l->value; my ($c,$d) = $r->value; if ($c->value == 0 && $d->value == 0) { return $self->make(0,0) if ($a->value == 0 && $b->value == 0); @@ -333,7 +336,7 @@ $a->{format} = $b->{format} = $format if defined $format; my $bi = 'i'; return $a->$method($equation) if $b == 0; - $bi = CORE::abs($b)->with(format=>$format)->$method($equation,1) . 'i' if CORE::abs($b) ne 1; + $bi = CORE::abs($b)->with(format=>$format)->$method($equation,1) . 'i' if CORE::abs($b) !~ m/^1(\.0*)?$/; $bi = '-' . $bi if $b < 0; return $bi if $a == 0; $bi = '+' . $bi if $b > 0; Index: Matrix.pm =================================================================== RCS file: /webwork/cvs/system/pg/lib/Value/Matrix.pm,v retrieving revision 1.33 retrieving revision 1.34 diff -Llib/Value/Matrix.pm -Llib/Value/Matrix.pm -u -r1.33 -r1.34 --- lib/Value/Matrix.pm +++ lib/Value/Matrix.pm @@ -175,27 +175,27 @@ # sub add { - my ($self,$l,$r) = Value::checkOpOrderWithPromote(@_); + my ($self,$l,$r,$other) = Value::checkOpOrderWithPromote(@_); my @l = @{$l->data}; my @r = @{$r->data}; Value::Error("Can't add Matrices with different dimensions") unless scalar(@l) == scalar(@r); my @s = (); foreach my $i (0..scalar(@l)-1) {push(@s,$l[$i] + $r[$i])} - return $self->make(@s); + return $self->inherit($other)->make(@s); } sub sub { - my ($self,$l,$r) = Value::checkOpOrderWithPromote(@_); + my ($self,$l,$r,$other) = Value::checkOpOrderWithPromote(@_); my @l = @{$l->data}; my @r = @{$r->data}; Value::Error("Can't subtract Matrices with different dimensions") unless scalar(@l) == scalar(@r); my @s = (); foreach my $i (0..scalar(@l)-1) {push(@s,$l[$i] - $r[$i])} - return $self->make(@s); + return $self->inherit($other)->make(@s); } sub mult { - my ($l,$r,$flag) = @_; my $self = $l; + my ($l,$r,$flag) = @_; my $self = $l; my $other = $r; # # Constant multiplication # @@ -230,6 +230,7 @@ } push(@M,$self->make(@row)); } + $self = $self->inherit($other) if Value::isValue($other); return $self->make(@M); } Index: Point.pm =================================================================== RCS file: /webwork/cvs/system/pg/lib/Value/Point.pm,v retrieving revision 1.28 retrieving revision 1.29 diff -Llib/Value/Point.pm -Llib/Value/Point.pm -u -r1.28 -r1.29 --- lib/Value/Point.pm +++ lib/Value/Point.pm @@ -60,23 +60,23 @@ # sub add { - my ($self,$l,$r) = Value::checkOpOrderWithPromote(@_); + my ($self,$l,$r,$other) = Value::checkOpOrderWithPromote(@_); my @l = $l->value; my @r = $r->value; Value::Error("Can't add Points with different numbers of coordinates") unless scalar(@l) == scalar(@r); my @s = (); foreach my $i (0..scalar(@l)-1) {push(@s,$l[$i] + $r[$i])} - return $self->make(@s); + return $self->inherit($other)->make(@s); } sub sub { - my ($self,$l,$r) = Value::checkOpOrderWithPromote(@_); + my ($self,$l,$r,$other) = Value::checkOpOrderWithPromote(@_); my @l = $l->value; my @r = $r->value; Value::Error("Can't subtract Points with different numbers of coordinates") unless scalar(@l) == scalar(@r); my @s = (); foreach my $i (0..scalar(@l)-1) {push(@s,$l[$i] - $r[$i])} - return $self->make(@s); + return $self->inherit($other)->make(@s); } sub mult { |
From: dpvc v. a. <we...@ma...> - 2007-09-08 21:31:31
|
Log Message: ----------- Allow interval data to be given in more forms (eg, (a,b,"(",")") in addition to ("(",a,b,")"), since that is the order that the value() method returns the data.) Modified Files: -------------- pg/lib/Value: Interval.pm Revision Data ------------- Index: Interval.pm =================================================================== RCS file: /webwork/cvs/system/pg/lib/Value/Interval.pm,v retrieving revision 1.42 retrieving revision 1.43 diff -Llib/Value/Interval.pm -Llib/Value/Interval.pm -u -r1.42 -r1.43 --- lib/Value/Interval.pm +++ lib/Value/Interval.pm @@ -30,7 +30,8 @@ return $context->Package("Set")->new($context,@params) if scalar(@params) == 1; @params = ('(',@params,')') if (scalar(@params) == 2); my ($open,$a,$b,$close) = @params; - if (!defined($close)) {$close = $b; $b = $a} + ($b,$close) = ($a,$b) unless defined($close); + ($a,$b,$open) = ($open,$a,$b) if !ref($b) && ($b eq '(' || $b eq '['); $a = Value::makeValue($a,context=>$context); $b = Value::makeValue($b,context=>$context); return $self->formula($open,$a,$b,$close) if Value::isFormula($a) || Value::isFormula($b); Value::Error("Endpoints of intervals must be numbers or infinities") unless @@ -52,6 +53,7 @@ if $a == $b && ($open ne '[' || $close ne ']'); return $context->Package("Set")->new($context,$a) if $a == $b; bless { + $self->hash, data => [$a,$b], open => $open, close => $close, leftInfinite => $nia, rightInfinite => $ib, context => $context, @@ -65,7 +67,9 @@ my $self = shift; my $class = ref($self) || $self; my $context = (Value::isContext($_[0]) ? shift : $self->context); my ($open,$a,$b,$close) = @_; - $close = $b, $b = $a unless defined($close); + ($open,$a,$b,$close) = ("(",$open,$a,")") unless defined($b); + ($b,$close) = ($a,$b) unless defined($close); + ($a,$b,$open) = ($open,$a,$b) if !ref($b) && ($b eq '(' || $b eq '['); bless { data => [$a,$b], open => $open, close => $close, leftInfinite => isNegativeInfinity($a), rightInfinite => isInfinity($b), |
From: dpvc v. a. <we...@ma...> - 2007-09-08 21:21:48
|
Log Message: ----------- Fix DOS and Mac line endings, and make the detection of non-text files a little more strict (DOS files were being marked as non-text). Also, localize the file handles. Modified Files: -------------- webwork2/lib/WeBWorK/ContentGenerator/Instructor: FileManager.pm Revision Data ------------- Index: FileManager.pm =================================================================== RCS file: /webwork/cvs/system/webwork2/lib/WeBWorK/ContentGenerator/Instructor/FileManager.pm,v retrieving revision 1.29 retrieving revision 1.30 diff -Llib/WeBWorK/ContentGenerator/Instructor/FileManager.pm -Llib/WeBWorK/ContentGenerator/Instructor/FileManager.pm -u -r1.29 -r1.30 --- lib/WeBWorK/ContentGenerator/Instructor/FileManager.pm +++ lib/WeBWorK/ContentGenerator/Instructor/FileManager.pm @@ -472,6 +472,8 @@ my $data = $self->r->param("data"); if (defined($data)) { + $data =~ s/\r\n?/\n/g; # convert DOS and Mac line ends to unix + local (*OUTFILE); if (open(OUTFILE,">$file")) { eval {print OUTFILE $data; close(OUTFILE)}; if ($@) {$self->addbadmessage("Failed to save: $@")} @@ -745,6 +747,7 @@ if ($self->r->param('confirmed')) { my $name = $self->r->param('name'); if (my $file = $self->verifyName($name,"file")) { + local (*NEWFILE); if (open(NEWFILE,">$file")) { close(NEWFILE); $self->RefreshEdit("",$name); @@ -1186,12 +1189,12 @@ ################################################## # # Check if a string is plain text -# (i.e., doesn't contain three non-regular +# (i.e., doesn't contain four non-regular # characters in a row.) # sub isText { my $string = shift; - return $string !~ m/[^\s\x20-\x7E]{3,}/; + return $string !~ m/[^\s\x20-\x7E]{4}/; } ################################################## |
From: Mike G. v. a. <we...@ma...> - 2007-09-08 01:12:20
|
Log Message: ----------- Fixed "click here" link surrounding the iframe inside which webwork appears. The link now opens the webwork page as intended. Modified Files: -------------- wwmoodle/wwassignment: view.php Revision Data ------------- Index: view.php =================================================================== RCS file: /webwork/cvs/system/wwmoodle/wwassignment/view.php,v retrieving revision 1.6 retrieving revision 1.7 diff -Lwwassignment/view.php -Lwwassignment/view.php -u -r1.6 -r1.7 --- wwassignment/view.php +++ wwassignment/view.php @@ -61,13 +61,15 @@ +// Print webwork in iframe and link to escape to have webwork in a single window print("<p style='font-size: smaller; color: #aaa;'>" . get_string("iframeNoShow-1", "wwassignment") - . "<a href='$sSetLink'>" . get_string("iframeNoShow-2", "wwassignment") . "</a>.</p>\n"); -print("<p align='center'><iframe id='wwPage' src='$webworksetlink' frameborder='1' " + . "<a href='$webworksetlink'>" . get_string("iframeNoShow-2", "wwassignment") + ."</a><p align='center'></iframe></p>\n" + ); +print("<iframe id='wwPage' src='$webworksetlink' frameborder='1' " . "width='".$CFG->wwassignment_iframewidth."' " . "height='".$CFG->wwassignment_iframeheight."'>" - . get_string("iframeNoShow-1", "wwassignment") . "<a href='$webworksetlink'>" . get_string("iframeNoShow-2", "wwassignment") - . "</a>.</iframe></p>\n"); + ); print("<script>ww.Init(".isteacher($course->id).")</script>"); |
From: dpvc v. a. <we...@ma...> - 2007-09-07 14:24:55
|
Log Message: ----------- Derivatives of absolute values were leaving out the chain rule when written as |...| (but not as abs(...)). The chain rule is built into the derivatives of function objects automatically, but not of lists, which is how |...| is implemented (a special form of parentheses), and so I missed it when adding the derivative in this form. Argh! Modified Files: -------------- pg/lib/Parser: Differentiation.pm Revision Data ------------- Index: Differentiation.pm =================================================================== RCS file: /webwork/cvs/system/pg/lib/Parser/Differentiation.pm,v retrieving revision 1.12 retrieving revision 1.13 diff -Llib/Parser/Differentiation.pm -Llib/Parser/Differentiation.pm -u -r1.12 -r1.13 --- lib/Parser/Differentiation.pm +++ lib/Parser/Differentiation.pm @@ -602,7 +602,12 @@ sub Parser::List::AbsoluteValue::D { my $self = shift; my $x = $self->{coords}[0]->copy; my $equation = $self->{equation}; - return $self->Item("BOP")->new($equation,'/', $x, $self->copy); + my $BOP = $self->Item("BOP"); + return + $BOP->new($equation,"*", + $BOP->new($equation,'/', $x, $self->copy), + $x->D(shift), + ); } |
From: dpvc v. a. <we...@ma...> - 2007-09-06 10:53:32
|
Log Message: ----------- Fixed check to use a variable that is known to be in the context (rather than incorrectly assuming 'x' is there). Modified Files: -------------- pg/macros: parserFormulaUpToConstant.pl Revision Data ------------- Index: parserFormulaUpToConstant.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/parserFormulaUpToConstant.pl,v retrieving revision 1.6 retrieving revision 1.7 diff -Lmacros/parserFormulaUpToConstant.pl -Lmacros/parserFormulaUpToConstant.pl -u -r1.6 -r1.7 --- macros/parserFormulaUpToConstant.pl +++ macros/parserFormulaUpToConstant.pl @@ -192,9 +192,12 @@ my $result = $ans->{correct_value} <=> $student; # compare encodes the reason in the result $self->cmp_Error($ans,"Note: there is always more than one posibility") if $result == 2 || $result == 3; if ($result == 3) { - $self->context->flags->set(no_parameters=>0); - $result = 1 if $self->removeConstant+"n01+n00x" == $student+"x"; # must use both parameters - $self->context->flags->set(no_parameters=>1); + my $context = $self->context; + $context->flags->set(no_parameters=>0); + $context->variables->add(x00=>'Real'); + $result = 1 if $self->removeConstant+"n01+n00x00" == $student+"x00"; # must use both parameters + $context->variables->remove('x00'); + $context->flags->set(no_parameters=>1); } $self->cmp_Error($ans,"Your answer is not the most general solution") if $result == 1; $self->cmp_Error($ans,"Your formula should be linear in the constant '$student->{constant}'") |
From: dpvc v. a. <we...@ma...> - 2007-09-06 10:42:38
|
Log Message: ----------- Only try to reduce intervals, sets and unions. (Don't call isReduced on objects that don't support it). Modified Files: -------------- pg/lib/Value: AnswerChecker.pm Revision Data ------------- Index: AnswerChecker.pm =================================================================== RCS file: /webwork/cvs/system/pg/lib/Value/AnswerChecker.pm,v retrieving revision 1.111 retrieving revision 1.112 diff -Llib/Value/AnswerChecker.pm -Llib/Value/AnswerChecker.pm -u -r1.111 -r1.112 --- lib/Value/AnswerChecker.pm +++ lib/Value/AnswerChecker.pm @@ -331,6 +331,7 @@ return unless $ans->{studentsMustReduceUnions} && $ans->{showUnionReduceWarnings} && !$ans->{isPreview} && !Value::isFormula($student); + return unless $student->isSetOfReals; my ($result,$error) = $student->isReduced; return unless $error; return { |
From: dpvc v. a. <we...@ma...> - 2007-09-06 00:25:41
|
Log Message: ----------- Make error messages more consistent when student's answer is off by a constant. Modified Files: -------------- pg/macros: parserFormulaUpToConstant.pl Revision Data ------------- Index: parserFormulaUpToConstant.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/parserFormulaUpToConstant.pl,v retrieving revision 1.5 retrieving revision 1.6 diff -Lmacros/parserFormulaUpToConstant.pl -Lmacros/parserFormulaUpToConstant.pl -u -r1.5 -r1.6 --- macros/parserFormulaUpToConstant.pl +++ macros/parserFormulaUpToConstant.pl @@ -191,8 +191,12 @@ my $student = $ans->{student_value}; my $result = $ans->{correct_value} <=> $student; # compare encodes the reason in the result $self->cmp_Error($ans,"Note: there is always more than one posibility") if $result == 2 || $result == 3; - $self->cmp_Error($ans,"Your answer is not the most general solution") - if $result == 1 || ($result == 3 && $self->removeConstant == $student); + if ($result == 3) { + $self->context->flags->set(no_parameters=>0); + $result = 1 if $self->removeConstant+"n01+n00x" == $student+"x"; # must use both parameters + $self->context->flags->set(no_parameters=>1); + } + $self->cmp_Error($ans,"Your answer is not the most general solution") if $result == 1; $self->cmp_Error($ans,"Your formula should be linear in the constant '$student->{constant}'") if $result == -1 && $self->getFlag("showLinearityHints") && !$student->D($student->{constant})->isConstant; } |
From: dpvc v. a. <we...@ma...> - 2007-09-06 00:02:39
|
Log Message: ----------- In making the checker work with +C, I forgot to add the parameter that provides for the student's answer to be off by a constant. (Since the C is actually a variable, not a parameter.) OOPS! Modified Files: -------------- pg/macros: parserFormulaUpToConstant.pl Revision Data ------------- Index: parserFormulaUpToConstant.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/parserFormulaUpToConstant.pl,v retrieving revision 1.4 retrieving revision 1.5 diff -Lmacros/parserFormulaUpToConstant.pl -Lmacros/parserFormulaUpToConstant.pl -u -r1.4 -r1.5 --- macros/parserFormulaUpToConstant.pl +++ macros/parserFormulaUpToConstant.pl @@ -122,15 +122,17 @@ Value->Error("Your formula isn't linear in the arbitrary constant '%s'",$f->{constant}) unless $n->isConstant; # - # Make a version with an adaptive parameter for use in the + # Make a version with adaptive parameters for use in the # comparison later on. We could like n0*C, but already have $n # copies of C, so remove them. That way, n0 will be 0 when there # are no C's in the student answer during the adaptive comparison. # (Again, should really check that n0 is not in use already) # - my $n0 = $context->variables->get("n0"); - $context->variables->add(n0=>'Parameter') unless $n0 and $n0->{parameter}; - $f->{adapt} = $f + "(n0-$n)$f->{constant}"; + my $n00 = $context->variables->get("n00"); + $context->variables->add(n00=>'Parameter') unless $n00 and $n00->{parameter}; + my $n01 = $context->variables->get("n01"); + $context->variables->add(n01=>'Parameter') unless $n01 and $n01->{parameter}; + $f->{adapt} = $f + "(n00-$n)$f->{constant} + n01"; return bless $f, $class; } @@ -162,7 +164,7 @@ # Check that n0 is non-zero (i.e., there is a multiple of C in the student answer) # (remember: return value of 0 is equal, and non-zero is unequal) # - return abs($context->variables->get("n0")->{value}) < $context->flag("zeroLevelTol"); + return abs($context->variables->get("n00")->{value}) < $context->flag("zeroLevelTol"); } ################################################## |
From: Matt L. v. a. <we...@ma...> - 2007-08-31 23:02:44
|
Log Message: ----------- Fixed /problemserver_files not showing up in img paths. Modified Files: -------------- ww_question_server/bin/setup: global.conf.base Revision Data ------------- Index: global.conf.base =================================================================== RCS file: /webwork/cvs/system/ww_question_server/bin/setup/global.conf.base,v retrieving revision 1.2 retrieving revision 1.3 diff -Lbin/setup/global.conf.base -Lbin/setup/global.conf.base -u -r1.2 -r1.3 --- bin/setup/global.conf.base +++ bin/setup/global.conf.base @@ -23,7 +23,7 @@ $problemServerDirs{root} = $ProblemServer::RootDir; -$problemServerURLs{root} = $ProblemServer::FilesUrl; +$problemServerURLs{root} = $ProblemServer::FilesURL; ################################################################################ |