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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 616 - (download) (as text) (annotate)
Wed Oct 30 20:16:56 2002 UTC (10 years, 7 months ago) by sh002i
Original Path: trunk/webwork2/lib/WeBWorK/ContentGenerator/Hardcopy.pm
File size: 7190 byte(s)
finished some stuff up. hardcopy deletes its temp files.
-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 "Hardcopy 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::pre($self->getMultiSetTeX(@sets));
   68   #return "";
   69 
   70   print CGI::p("Generating your hardcopy...");
   71   my $url = $self->makeHardcopy(@sets);
   72   if ($url) {
   73     print CGI::p("Ok, your hardcopy is ready. Click the following link to download it.");
   74     print CGI::p({-align=>"center"},
   75       CGI::big(CGI::a({-href=>$url}, "Download PDF Hardcopy"))
   76     );
   77   } else {
   78     print CGI::p("Hmm, looks like I was unable to generate the hardcopy you requested. I'm really sorry... :(");
   79   }
   80 
   81   return "";
   82 }
   83 
   84 # -----
   85 
   86 sub makeHardcopy {
   87   my ($self, @sets) = @_;
   88   my $courseName = $self->{courseEnvironment}->{courseName};
   89   my $userName = $self->{r}->param("user");
   90   my $tempDir = $self->{courseEnvironment}->{courseDirs}->{html_temp}
   91     . "/hardcopy";
   92   my $tempURL = $self->{courseEnvironment}->{courseURLs}->{html_temp}
   93     . "/hardcopy";
   94 
   95   # determine name of PDF file
   96   my $fileName;
   97   if (@sets > 1) {
   98     # multiset output
   99     $fileName = "$courseName.$userName.multiset.pdf"
  100   } elsif (@sets == 1) {
  101     # only one set
  102     my $setName = $sets[0];
  103     $fileName = "$courseName.$userName.$setName.pdf";
  104   } else {
  105     $fileName = "$courseName.$userName.pdf";
  106   }
  107   my $tex = $self->getMultiSetTeX(@sets);
  108   $self->latex2pdf($tex, $tempDir, $fileName) or return;
  109 
  110   return "$tempURL/$fileName";
  111 }
  112 
  113 sub latex2pdf {
  114   # this is a little ad-hoc function which I will replace with a LaTeX
  115   # module at some point (or put it in Utils).
  116   my ($self, $tex, $fileBase, $fileName) = @_;
  117   my $finalFile = "$fileBase/$fileName";
  118   my $ce = $self->{courseEnvironment};
  119 
  120   # create a temporary directory for tex to shit in
  121   my $wd = tempdir("webwork-hardcopy-XXXXXXXX", TMPDIR => 1);
  122   my $texFile = "$wd/hardcopy.tex";
  123   my $pdfFile = "$wd/hardcopy.pdf";
  124   my $logFile = "$wd/hardcopy.log";
  125 
  126   # write the tex file
  127   local *TEX;
  128   open TEX, ">", $texFile;
  129   print TEX $tex;
  130   close TEX;
  131 
  132   # call pdflatex - we don't want to chdir in the mod_perl process, as
  133   # that might step on the feet of other things (esp. in Apache 2.0)
  134   my $pdflatex = $ce->{externalPrograms}->{pdflatex};
  135   system "cd $wd && $pdflatex $texFile";
  136 
  137   if (-e $pdfFile) {
  138     # move resulting PDF file to appropriate location
  139     my $mv = $ce->{externalPrograms}->{mv};
  140     system $mv, $pdfFile, $finalFile and die "Failed to mv: $!\n";
  141   }
  142 
  143   # remove temporary directory
  144   rmtree($wd, 0, 1);
  145 
  146   return -e $finalFile;
  147 }
  148 
  149 # -----
  150 
  151 sub getMultiSetTeX {
  152   my ($self, @sets) = @_;
  153   my $ce = $self->{courseEnvironment};
  154   my $tex = "";
  155 
  156   # the document preamble
  157   $tex .= $self->texInclude($ce->{webworkFiles}->{hardcopySnippets}->{preamble});
  158 
  159   while (my $set = shift @sets) {
  160     $tex .= $self->getSetTeX($set);
  161     if (@sets) {
  162       # divide sets, but not after the last set
  163       $tex .= $self->texInclude($ce->{webworkFiles}->{hardcopySnippets}->{setDivider});
  164     }
  165   }
  166 
  167   # the document postamble
  168   $tex .= $self->texInclude($ce->{webworkFiles}->{hardcopySnippets}->{postamble});
  169 
  170   return $tex;
  171 }
  172 
  173 sub getSetTeX {
  174   my ($self, $setName) = @_;
  175   my $ce = $self->{courseEnvironment};
  176   my $wwdb = $self->{wwdb};
  177   my $user = $self->{r}->param("user");
  178   my @problemNumbers = sort { $a <=> $b } $wwdb->getProblems($user, $setName);
  179 
  180   # get header and footer
  181   my $setHeader = $wwdb->getSet($user, $setName)->set_header
  182     || $ce->{webworkFiles}->{hardcopySnippets}->{setHeader};
  183   # database doesn't support the following yet :(
  184   #my $setFooter = $wwdb->getSet($user, $setName)->set_footer
  185   # || $ce->{webworkFiles}->{hardcopySnippets}->{setFooter};
  186   # so we don't allow per-set customization, which is probably okay :)
  187   my $setFooter = $ce->{webworkFiles}->{hardcopySnippets}->{setFooter};
  188 
  189   my $tex = "";
  190 
  191   # render header
  192   $tex .= texBlockComment("BEGIN $setName : $setHeader");
  193   $tex .= $self->getProblemTeX($setName, 0, $setHeader);
  194 
  195   # render each problem
  196   while (my $problemNumber = shift @problemNumbers) {
  197     $tex .= texBlockComment("BEGIN $setName : $problemNumber");
  198     $tex .= $self->getProblemTeX($setName, $problemNumber);
  199     if (@problemNumbers) {
  200       # divide problems, but not after the last problem
  201       $tex .= $self->texInclude($ce->{webworkFiles}->{hardcopySnippets}->{problemDivider});
  202     }
  203   }
  204 
  205   # render footer
  206   $tex .= texBlockComment("BEGIN $setName : $setFooter");
  207   $tex .= $self->getProblemTeX($setName, 0, $setFooter);
  208 
  209   return $tex;
  210 }
  211 
  212 sub getProblemTeX {
  213   my ($self, $setName, $problemNumber, $pgFile) = @_;
  214   my $r = $self->{r};
  215   my $ce = $self->{courseEnvironment};
  216 
  217   my $wwdb = $self->{wwdb};
  218   my $cldb = $self->{cldb};
  219   my $user            = $cldb->getUser($r->param("user"));
  220   my $set             = $wwdb->getSet($user->id, $setName);
  221   my $psvn            = $wwdb->getPSVN($user->id, $setName);
  222 
  223   # decide what to do about problem number
  224   my $problem;
  225   if ($problemNumber) {
  226     $problem = $wwdb->getProblem($user->id, $setName, $problemNumber);
  227   } elsif ($pgFile) {
  228     $problem = WeBWorK::Problem->new(
  229       id => 0,
  230       set_id => $set->id,
  231       login_id => $user->id,
  232       source_file => $pgFile,
  233       # the rest of Problem's fields are not needed, i think
  234     );
  235   }
  236 
  237   my $pg = WeBWorK::PG->new(
  238     $ce,
  239     $user,
  240     $r->param('key'),
  241     $set,
  242     $problem,
  243     $psvn,
  244     {}, # no form fields!
  245     { # translation options
  246       displayMode     => "tex",
  247       showHints       => 0,
  248       showSolutions   => 0,
  249       processAnswers  => 0,
  250     },
  251   );
  252 
  253   warn "***GET READY FOR PG WARNINGS!!!!!\n***SET=$setName PROBLEM=$problemNumber\n",
  254     $pg->{warnings}, "***OK NO MORE PG WARNINGS!!!!\n" if $pg->{warnings};
  255 
  256   return $pg->{body_text};
  257 }
  258 
  259 sub texInclude {
  260   my ($self, $texFile) = @_;
  261   my $tex = "";
  262 
  263   $tex .= texBlockComment("BEGIN: $texFile");
  264   eval {
  265     $tex .= readFile($texFile)
  266   };
  267   if ($@) {
  268     $tex .= texBlockComment($@);
  269   }
  270 
  271   return $tex;
  272 }
  273 
  274 1;

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9