[system] / branches / rel-2-0-pr1-hardcopy-changes / webwork-modperl / lib / WeBWorK / ContentGenerator / Hardcopy.pm Repository:
ViewVC logotype

View of /branches/rel-2-0-pr1-hardcopy-changes/webwork-modperl/lib/WeBWorK/ContentGenerator/Hardcopy.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 502 - (download) (as text) (annotate)
Thu Aug 22 21:11:53 2002 UTC (10 years, 9 months ago) by sh002i
Original Path: trunk/webwork-modperl/lib/WeBWorK/ContentGenerator/Hardcopy.pm
File size: 6973 byte(s)
continuing work on hardcopy generation. changed interface to PG.pm to
take user, problem, and set objects instead of names.
-sam

    1 ################################################################################
    2 # WeBWorK mod_perl (c) 2000-2002 WeBWorK Project
    3 # $Id$
    4 ################################################################################
    5 
    6 package WeBWorK::ContentGenerator::Hardcopy;
    7 
    8 =head1 NAME
    9 
   10 WeBWorK::ContentGenerator::Test - generate a PDF version of one or more
   11 problem sets.
   12 
   13 =cut
   14 
   15 use strict;
   16 use warnings;
   17 use base qw(WeBWorK::ContentGenerator);
   18 use Apache::Constants qw(:common);
   19 use CGI qw();
   20 use File::Path qw(rmtree);
   21 use File::Temp qw(tempdir);
   22 use WeBWorK::DB::Classlist;
   23 use WeBWorK::DB::WW;
   24 use WeBWorK::Form;
   25 use WeBWorK::Utils qw(readFile);
   26 
   27 sub texBlockComment { return "\n".("%"x80)."\n%% ".join("", @_)."\n".("%"x80)."\n\n"; }
   28 
   29 sub initialize {
   30   my $self = shift;
   31   my $ce = $self->{courseEnvironment};
   32   $self->{cldb} = WeBWorK::DB::Classlist->new($ce);
   33   $self->{wwdb} = WeBWorK::DB::WW->new($ce);
   34 }
   35 
   36 sub path {
   37   my ($self, undef, $args) = @_;
   38 
   39   my $ce = $self->{courseEnvironment};
   40   my $root = $ce->{webworkURLs}->{root};
   41   my $courseName = $ce->{courseName};
   42   return $self->pathMacro($args,
   43     "Home" => "$root",
   44     $courseName => "$root/$courseName",
   45     "Hardcopy Generator" => "",
   46   );
   47 }
   48 
   49 sub title {
   50   return "Hardcore Generator";
   51 }
   52 
   53 sub body {
   54   my ($self, $singleSet) = @_;
   55   $singleSet =~ s/^set//;
   56   my $r = $self->{r};
   57   my $ce = $self->{courseEnvironment};
   58   $self->{wwdb} = WeBWorK::DB::WW->new($ce);
   59 
   60   my @sets = $r->param("set");
   61   unshift @sets, $singleSet;
   62   unless (@sets) {
   63     print CGI::p("No problem sets were specified.");
   64     return OK;
   65   }
   66 
   67   print CGI::p("Generating your hardcopy...");
   68   my $url = $self->makeHardcopy(@sets);
   69   if ($url) {
   70     print CGI::p("Ok, your hardcopy is ready. Click the following link to download it.");
   71     print CGI::p({-align=>"center"},
   72       CGI::big(CGI::a({-href=>$url}, "Download PDF Hardcopy"))
   73     );
   74   } else {
   75     print CGI::p("Hmm, looks like I was unable to generate the hardcopy you requested. I'm really sorry... :(");
   76   }
   77 
   78   return "";
   79 }
   80 
   81 # -----
   82 
   83 sub makeHardcopy {
   84   my ($self, @sets) = @_;
   85   my $courseName = $self->{courseEnvironment}->{courseName};
   86   my $userName = $self->{r}->param("user");
   87   my $tempDir = $self->{courseEnvironment}->{courseDirs}->{html_temp}
   88     . "/hardcopy";
   89   my $tempURL = $self->{courseEnvironment}->{courseURLs}->{html_temp}
   90     . "/hardcopy";
   91 
   92   # determine name of PDF file
   93   my $fileName;
   94   if (@sets > 1) {
   95     # multiset output
   96     $fileName = "$courseName.$userName.multiset.pdf"
   97   } elsif (@sets == 1) {
   98     # only one set
   99     my $setName = $sets[0];
  100     $fileName = "$courseName.$userName.$setName.pdf";
  101   } else {
  102     $fileName = "$courseName.$userName.pdf";
  103   }
  104 
  105   my $tex = $self->getMultiSetTeX(@sets);
  106   $self->latex2pdf($tex, $tempDir, $fileName) or return;
  107 
  108   return "$tempURL/$fileName";
  109 }
  110 
  111 sub latex2pdf {
  112   # this is a little ad-hoc function which I will replace with a LaTeX
  113   # module at some point (or put it in Utils).
  114   my ($self, $tex, $fileBase, $fileName) = @_;
  115   my $finalFile = "$fileBase/$fileName";
  116   my $ce = $self->{courseEnvironment};
  117 
  118   # create a temporary directory for tex to shit in
  119   my $wd = tempdir("webwork-hardcopy-XXXXXXXX", TMPDIR => 1);
  120   my $texFile = "$wd/hardcopy.tex";
  121   my $pdfFile = "$wd/hardcopy.pdf";
  122 
  123   # write the tex file
  124   local *TEX;
  125   open TEX, ">", $texFile;
  126   print TEX $tex;
  127   close TEX;
  128 
  129   # call pdflatex - we don't want to chdir in the mod_perl process, as
  130   # that might step on the feet of other things (esp. in Apache 2.0)
  131   my $pdflatex = $ce->{externalPrograms}->{pdflatex};
  132   system "cd $wd && $pdflatex $texFile";
  133 
  134   if (-e $pdfFile) {
  135     # move resulting PDF file to appropriate location
  136     my $mv = $ce->{externalPrograms}->{mv};
  137     system $mv, $pdfFile, $finalFile and die "Failed to mv: $!\n";
  138   }
  139 
  140   # remove temporary directory
  141   rmtree($wd, 0, 1);
  142 
  143   return -e $finalFile;
  144 }
  145 
  146 # -----
  147 
  148 sub getMultiSetTeX {
  149   my ($self, @sets) = @_;
  150   my $ce = $self->{courseEnvironment};
  151   my $tex = "";
  152 
  153   # the document preamble
  154   $tex .= $self->texInclude($ce->{webworkFiles}->{hardcopySnippets}->{preamble});
  155 
  156   while (my $set = shift @sets) {
  157     $tex .= $self->getSetTeX($set);
  158     if (@sets) {
  159       # divide sets, but not after the last set
  160       $tex .= $self->texInclude($ce->{webworkFiles}->{hardcopySnippets}->{setDivider});
  161     }
  162   }
  163 
  164   # the document postamble
  165   $tex .= $self->texInclude($ce->{webworkFiles}->{hardcopySnippets}->{postamble});
  166 
  167   return $tex;
  168 }
  169 
  170 sub getSetTeX {
  171   my ($self, $setName) = @_;
  172   my $ce = $self->{courseEnvironment};
  173   my $wwdb = $self->{wwdb};
  174   my $user = $self->{r}->param("user");
  175   my @problemNumbers = sort { $a <=> $b } $wwdb->getProblems($user, $setName);
  176 
  177   # get header and footer
  178   my $setHeader = $wwdb->getSet($user, $setName)->set_header
  179     || $ce->{webworkFiles}->{hardcopySnippets}->{setHeader};
  180   # database doesn't support the following yet :(
  181   #my $setFooter = $wwdb->getSet($user, $setName)->set_footer
  182   # || $ce->{webworkFiles}->{hardcopySnippets}->{setFooter};
  183   # so we don't allow per-set customization, which is probably okay :)
  184   my $setFooter = $ce->{webworkFiles}->{hardcopySnippets}->{setFooter};
  185 
  186   my $tex = "";
  187 
  188   # render header
  189   $tex .= texBlockComment("BEGIN $setName : $setHeader");
  190   #$tex .= $self->getProblemTeX($setName, 0, $setHeader);
  191 
  192   # render each problem
  193   while (my $problemNumber = shift @problemNumbers) {
  194     $tex .= texBlockComment("BEGIN $setName : $problemNumber");
  195     $tex .= $self->getProblemTeX($setName, $problemNumber);
  196     if (@problemNumbers) {
  197       # divide problems, but not after the last problem
  198       $tex .= $self->texInclude($ce->{webworkFiles}->{hardcopySnippets}->{problemDivider});
  199     }
  200   }
  201 
  202   # render footer
  203   $tex .= texBlockComment("BEGIN $setName : $setFooter");
  204   $tex .= $self->getProblemTeX($setName, 0, $setFooter);
  205 
  206   return $tex;
  207 }
  208 
  209 sub getProblemTeX {
  210   my ($self, $setName, $problemNumber, $pgFile) = @_;
  211   my $r = $self->{r};
  212   my $ce = $self->{courseEnvironment};
  213 
  214   my $wwdb = $self->{wwdb};
  215   my $cldb = $self->{cldb};
  216   my $user            = $cldb->getUser($r->param("user"));
  217   my $set             = $wwdb->getSet($user->id, $setName);
  218   my $psvn            = $wwdb->getPSVN($user->id, $setName);
  219 
  220   # decide what to do about problem number
  221   my $problem;
  222   if ($problemNumber) {
  223     $problem = $wwdb->getProblem($user->id, $setName, $problemNumber);
  224   } elsif ($pgFile) {
  225     $problem = WeBWorK::Problem->new(
  226       id => 0,
  227       set_id => $set->id,
  228       login_id => $user->id,
  229       source_file => $pgFile,
  230       # the rest of Problem's fields are not needed, i think
  231     );
  232   }
  233 
  234   my $pg = WeBWorK::PG->new(
  235     $ce,
  236     $user,
  237     $r->param('key'),
  238     $set,
  239     $problem,
  240     $psvn,
  241     {}, # no form fields!
  242     { # translation options
  243       displayMode     => "tex",
  244       showHints       => 0,
  245       showSolutions   => 0,
  246       processAnswers  => 0,
  247     },
  248   );
  249 
  250   # *** # handle errors/warnings here!
  251   return $pg->{body_text};
  252 }
  253 
  254 sub texInclude {
  255   my ($self, $texFile) = @_;
  256   my $tex = "";
  257 
  258   $tex .= texBlockComment("BEGIN: $texFile");
  259   eval {
  260     $tex .= readFile($texFile)
  261   };
  262   if ($@) {
  263     $tex .= texBlockComment($@);
  264   }
  265 
  266   return $tex;
  267 }
  268 
  269 1;

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9