//////////////////////////////////////////////////////////////////////////
//                                                                      //
// MODULE: Report                       AUTHOR: Tim Sabin               //
// DESCRIPTION: Report creates a report, and outputs it to a file.      //
// DATE CREATED: 07/08/1998             LAST UPDATED: 12/16/1998        //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

import java.io.*;
import ParameterScreen;
import StatusForm;
import java.util.*;
import Day;
import TimePeriod;
import java.text.DecimalFormat;
import HardcopyWriter;

public class Report implements Runnable {
    private HardcopyWriter hw = null;
    private PrintWriter reportFile = null;
    private HASP_Report_Runner report;
    private HASP_Report_Store fullRep;
    private Thread reportThread;
    private ParameterScreen parent;
    private Parameters pms;
    public static StatusForm stat = null;
    private int rptRow = 0;
    private int classOut = 0;
    private ErrorScreen errT;
    public Report (ParameterScreen par, Parameters parms,
      HASP_Report_Runner dbIF) {
        pms = parms;
        parent = par;
        rptRow = 0;
        // Throw up the initial status screen
        // Put up the initial status screen
        try
        {
            stat = new StatusForm (parent);
            stat.setVisible (true);
        }
        catch(Throwable t)
        {
            try {
                errT = new ErrorScreen (parent);
                errT.addError ("Cannot construct the status form: " + t);
                errT.setVisible (true);
            } catch (Throwable e) {
                ;
            }
        }

        // Start the report/database thread
        report = dbIF;
        reportThread = new Thread (report);
        report.setParams (pms);
        reportThread.start ();
        stat.SetRptThread (reportThread);
        
    }
    private int linePPageCtr;
    private final int headerSize = 12;
    private final int headerIIsize = 12;
    private final int trailerSize = 3;
    private String oldDest = null;
    public void run () {
        System.out.println ("Starting Report.run ()");
        int linesLeft;
        // Open the output file
        // Read in start day of fiscal year into local variables
        try {
            hw = new HardcopyWriter (parent, 0.50, 0.50, 0.50, 0.50);
            reportFile = new PrintWriter (hw);
        } catch (Throwable e) {
            try {
                errT = new ErrorScreen (parent);
                errT.addError (e.toString ());
                errT.setVisible (true);
            } catch (Throwable t) {
                ;
            }
            return;
        }    // end try block
        System.out.println ("Have initialized print page");
        linePPageCtr = hw.getLinesPerPage ();
        // Wait for the report to be done
        while (report.ready () == false) {
            try {
                if (stat.RptInterrupted () == true) {
                    stat.SuperCedeWindowClosing (null);
                    return;
                }
                parent.myThread.sleep (1000);
            } catch (Throwable e) {
                stat.buttonCancelActionPerformed (null);    // As if we slept for the whole 1 sec.
            }    // end try block
        }
        System.out.println ("Report is now ready to be printed");
        // Tell user now writing report
        stat.SetStatusLine ("Status: Generating report");
        
        // Get the full report
        fullRep = report.report ();
        // Output the report in pages
        System.out.println ("Starting to write report - before ptI try");
        try {
            System.out.println ("Starting to write report - ptI header first");
            while (true) {
                writeHeader (pms.OriginText () + " (" +
                  pms.OriginNum () + ")");
                System.out.println ("writeHeader completed successfully");
                linesLeft = writeBody (
                  linePPageCtr - headerSize - trailerSize - 22);
                System.out.println ("writeBody completed successfully");
                hw.newPage ();
                System.out.println ("newPage completed successfully");
                if (linesLeft <= 0) {
                    continue;
                } else
                    break;
            }
            // Now output Part II of the report
            oldDest = null;
            rptRow = 0;
            while (true) {
                ptIIheader (pms.OriginText () + " (" +
                  pms.OriginNum () + ")");
                System.out.println ("ptIIheader completed successfully");
                linesLeft = ptIIbody (linePPageCtr - headerIIsize -
                  trailerSize - 22);
                System.out.println ("ptIIbody completed successfully");
                hw.newPage ();
                System.out.println ("newPage (ptII) completed successfully");
                if (linesLeft <= 0) {
                    continue;
                } else
                    break;
            }
        } catch (Throwable e) {
            try {
                errT = new ErrorScreen (parent);
                errT.addError ("Can't print report");
                errT.setVisible (true);
            } catch (Throwable t) {
                ;
            }
            return;
        }
        try {
            hw.close ();
        } catch (Throwable e) {
            try {
                errT = new ErrorScreen (parent);
                errT.addError ("Can't close printer");
                errT.setVisible (true);
            } catch (Throwable t) {
                ;
            }
            return;
        }    // end try block
        // Clear the Status screen
        stat.SuperCedeWindowClosing (null);
    }
    // Method to write the Part I Header
    private void writeHeader (String origin)
      throws IOException {
        // Write the intro line
        reportFile.println (
          "                                            "+
          "HASP Transportation Analysis Report - Part I");
        // Write which HASP
        reportFile.println (
          "                                                          "+
          "Indianapolis HASP");
        reportFile.println ("");
        // Get the area string
        HASP_Report hr = report.report (0);
        if (hr == null) {
            try {
                errT = new ErrorScreen (parent);
                errT.addError ("No data for report");
                errT.setVisible (true);
            } catch (Throwable e) {
                ;
            }
            throw (new IOException ("No data for report"));
        }
        System.out.println ("Header before getting anything");
        //String usArea = hr.areaName ();
        //System.out.println ("Header got areaName");
        //int numSp = 30 - usArea.length ();
        //String spaces = "";
        //for (int x = 0; x < numSp; x++)
        //    spaces = spaces + " ";
        //usArea = usArea + spaces;
        // Create a status line
        String usArea = "                              ";
        Day today = new Day ();
        today.BeginningDate ().set (Calendar.YEAR,
          today.BeginningDate ().get (Calendar.YEAR));
        String pdStr = getPeriodString (pms.Periods ()[0]);
        reportFile.println (
          "Report Date: "+today.PrintDate (today.BeginningDate ())+
          "                                     "+
          usArea + "        " + "Reporting Period:  " + pdStr);
        System.out.println ("Header got and printed Report Date");
        reportFile.println ("");
        // Write out the origin line
        reportFile.println ("     Origin - " + origin);
        reportFile.println ("");
        // Write out field & area headers
        reportFile.println (
          "                                                      "+
          "Air Transportation               Surface "+
          "Transportation via HASP");

        reportFile.println (
          "                                                    "+
          "                       Outbound from Origin              "+
          "Outbound from HASP");
          
        reportFile.println (
          "                               Mail                      "+
          "AverageVolume  Daily                 Cap.Avail."+
          " Daily                 Cap.Avail.");
          
        reportFile.println (
          "Destination                    Class       Period            "+
          "(LBS)      Trips Avg Utilization   (LBS)"+
          "    Trips Avg Utilization   (LBS)");
        reportFile.println ("");
        System.out.println ("Finished writing PtI header");
    }
    private String oldClass = "F";
    private int numInFirstClass = 0;
    private int startingFirstClass = 0;
    private int numInPriority = 0;
    private int startingPriority = 0;
    // Method to write the Part I Body
    private int writeBody (int numLines) throws IOException {
        // First, finish up any total printing left over
        numLines -= printTotals (null, false, numLines);
        // Print out -- up to -- the number of lines specified
        int i = 0;
        for (i = numLines; i > 0; i--, rptRow++) {
            // NOTE: If the returned row is null, return all rows left
            HASP_Report hr = report.report (rptRow);
            if (hr == null) {
                printTotals (oldClass, true, i);
                break;
            }
            System.out.println ("New report row "+rptRow+", parameters:");
            System.out.println ("Dest:"+hr.destString ()+", mclass="+hr.mailClass());
            System.out.println ("Number of orig trips (pt II): "+hr.origTrip ().size ());
            System.out.println ("Number of hasp trips (pt II): "+hr.haspTrip ().size ());
                
            // Fetch the report fields
            String destStr = hr.destString ();
            String destCode = report.originDescriptions (destStr)[0];
            String clss = hr.mailClass ();
            // IF the class has changed, but the destination hasn't THEN
            if ((!clss.equals (oldClass)) && (destStr.equals (oldDest))) {
                // Print class totals, and space report
                i -= printTotals (oldClass, false, i);
                // Record the starting Priority row
                startingPriority = rptRow;
                classOut = 0;
            // ELSE IF the destination changed THEN
            } else if ((!destStr.equals (oldDest)) && (oldDest != null)) {
                // Print the class totals, the grand totals, and space
                i -= printTotals (oldClass, true, i);
                // Reset record totals
                classOut = 0;
                numInFirstClass = 0;
                startingFirstClass = rptRow;
                numInPriority = 0;
                // Jump to the next page, write header
                hw.newPage ();
                writeHeader (pms.OriginText () + " (" +
                  pms.OriginNum () + ")");
                i = linePPageCtr - headerSize - trailerSize;
                startingPriority = 0;

            // ENDIF
            }
            oldClass = clss;
            oldDest = destStr;
            
            if (clss.equals ("F")) {
                clss = "  First ";
                numInFirstClass++;
            } else if (clss.equals ("P")) {
                clss = "Priority";
                numInPriority++;
            }
            TimePeriod pd = hr.reportPeriod ();
            pd.BeginningDate ().set (Calendar.YEAR,
              pd.BeginningDate ().get (Calendar.YEAR) % 100);
            pd.EndDate ().set (Calendar.YEAR,
              pd.EndDate ().get (Calendar.YEAR) % 100);
            String pdStr = null;
            if (pms.Periods ()[0].GetType () == TimePeriod.DAILY) {
                pdStr = TimePeriod.PrintDate (pms.Periods ()[0].BeginningDate ()) +
                  "       ";
            } else {    // Weekly or AP!
                pdStr = TimePeriod.PrintDate (pd.BeginningDate ()) + "-" +
                  TimePeriod.PrintDate (pd.EndDate ());
            }
            int actVol = hr.actualVolume ().intValue ();
            int orDT = hr.origDailyTrip ().intValue ();
            int orPct = hr.origAvgUtil ().intValue ();
            int orCap = hr.origCapacity ().intValue ();
            int haspDT = hr.haspDailyTrip ().intValue ();
            int haspPct = hr.haspAvgUtil ().intValue ();
            int haspCap = hr.haspCapacity ().intValue ();
            
            // Figure what the class & destination strings should be
            if ((clss.equals ("  First ")) && (classOut == 1))
                clss = "  Class ";
            else if (classOut != 0)
                clss = "        ";
            if (classOut == 1)
                destStr = "(" + destCode + ")";
            else if (classOut != 0)
                destStr = "";
            // o Fill out the destination
            int numSp = 29 - destStr.length ();
            String spaces = "";
            for (int x = 0; x < numSp; x++)
                spaces = spaces + " ";
            destStr = destStr + spaces;

            // IF the actual volume returned is -1 (OD Pair undefed this class) THEN
            if (actVol == -1) {
                // Print out an info message
                String msg = pms.OriginNum () + "->" + destCode + " Not Defined " +
                  hr.mailClass ();
                numSp = 24 - msg.length ();
                spaces = "";
                for (int x = 0; x < numSp; x++)
                    spaces = spaces + " ";
                msg = msg + spaces;
                reportFile.print (destStr + clss + " " + pdStr + "     " + msg +
                  "                       ");
            // ELSE (normal processing)
            } else {
                        
                // Print out a partial report line (origin -> HASP)
                reportFile.print (destStr+clss+" "+pdStr+
                  "     "+prNum (actVol,6)+"       "+prNum (orDT,2)+
                  "         "+prNum (orPct,3)+"%       "+prNum (orCap,6)+"      ");
            // ENDIF
            }
            
            // IF there are no partII routes THEN
            if ((hr.origRoute ().size () == 0) || (hr.haspRoute ().size () == 0)) {
                // Print out "Cannot meet CET"
                reportFile.println ("     Cannot meet CET");
            // ELSE
            } else {
                // Print out the report lines
                reportFile.println (prNum (haspDT,2)+"         "+prNum (haspPct,3)+
                  "%       "+prNum (haspCap,6));
            // ENDIF
            }
              
            // Save status
            ++classOut;
        };
        return i;
    }
    private static int pageNo = 1;
    
    // Method to print Part II Header
    private void ptIIheader (String origin) throws IOException {
        // Write the intro line
        reportFile.println (
          "                                            "+
          "HASP Transportation Analysis Report - Part II");
        // Write which HASP
        reportFile.println (
          "                                                          "+
          "Indianapolis HASP");
        reportFile.println ("");
        // Get the area string
        HASP_Report hr = report.report (0);
        String usArea = "                              ";
        //String usArea = hr.areaName ();
        //int numSp = 30 - usArea.length ();
        //String spaces = "";
        //for (int x = 0; x < numSp; x++)
        //    spaces = spaces + " ";
        //usArea = usArea + spaces;
        // Create a status line
        Day today = new Day ();
        today.BeginningDate ().set (Calendar.YEAR,
          today.BeginningDate ().get (Calendar.YEAR));
        String pdStr = getPeriodString (pms.Periods ()[0]);
        reportFile.println (
          "Report Date: "+today.PrintDate (today.BeginningDate ())+
          "                                     "+
          usArea + "        " +  "Reporting Period:  " + pdStr);
        reportFile.println ("");
        // Write out field & area headers
        reportFile.println (
          "                                                    "+
          "Surface Transportation via HASP");
        reportFile.println ("");

        reportFile.println (
          "                         Inbound from Origin              "+
          "                                   Outbound from HASP");
          
        reportFile.println (
          "                  Effective Discontinue Departs Arrive      "+
          "                                       Effective Discontinue "+
          "Departs Arrive");
          
        reportFile.println (
          "     Route  Trip     Date      Date     Origin   HASP        "+
          "                    "+
          "     Route  Trip     Date      Date       HASP   Dest");
        reportFile.println ("");
        reportFile.println ("Origin - " + origin);
    }
    // Method to write the Part II Body
    private int ptIIbody (int numLines) throws IOException {
        boolean leftSide = true;
        String destin = null;
        String mailClass = null;
        // Print out -- up to -- the number of lines specified
        int i = 0;
        for (i = numLines; i > 0; rptRow++) {
            // NOTE: If the returned row is null, return all rows left
            System.out.println ("New numLines loop, rptRow="+rptRow);
            HASP_Report hr = report.report (rptRow);
            if (hr == null) {
                break;
            }
            System.out.println ("Got new report HASP_Report");

            // Save the dest. if 1st one or if dest. has REALLY changed.
            // If dest has not changed, ignore the record
            if ((destin == null) || (destin.equals (hr.destString ()) == false)) {
                if (destin != null)
                    leftSide = false;
                destin = hr.destString ();
                mailClass = hr.mailClass ();
            } else if (mailClass.equals (hr.mailClass ()) == false) {
                continue;
            } else {
                mailClass = hr.mailClass ();
            }
            System.out.println ("NOT just a new mailclass");
                
            // Put a blank line before each destination
            reportFile.println ("");
            i--;
            // DO for each record for this destination
            int origRecs = hr.origRoute ().size ();
            int haspRecs = hr.haspRoute ().size ();
            int maxRecs = (origRecs > haspRecs) ? origRecs : haspRecs;
            System.out.println ("origRecs="+origRecs+",haspRecs="+haspRecs);
            for (int j = 0; (j < maxRecs) && (i > 0); j++) {
                System.out.println ("New record for dest="+hr.destString());
                String destStr = hr.destString ();
                String destCode = report.originDescriptions (destStr)[0];
                String newDest = "";
                String origRoute = null;
                String origTrip = null;
                GregorianCalendar origEffDate = new GregorianCalendar ();
                GregorianCalendar origDiscDate = new GregorianCalendar ();
                String oeDate = null;
                String odDate = null;
                Integer lvOrig = null;
                Integer arHasp = null;
                String haspRoute = null;
                String haspTrip = null;
                GregorianCalendar haspEffDate = new GregorianCalendar ();
                GregorianCalendar haspDiscDate = new GregorianCalendar ();
                String heDate = null;
                String hdDate = null;
                Integer lvHasp = null;
                Integer arDest = null;
                // Fetch the report fields
                if (j < origRecs) {
                    origRoute =
                     strPad((String)hr.origRoute ().elementAt (j),5);
                    origTrip =
                     strPad((String)hr.origTrip ().elementAt (j),5);
                    origEffDate.setTime ((Date)hr.origEffDate ().elementAt (j));
                    origDiscDate.setTime ((Date)hr.origDisDate ().elementAt (j));
                    oeDate = TimePeriod.PrintDate (origEffDate);
                    odDate = TimePeriod.PrintDate (origDiscDate);
                    lvOrig = (Integer)hr.origDepOrig ().elementAt (j);
                    arHasp = (Integer)hr.origArrHasp ().elementAt (j);
                }
                if (j < haspRecs) {
                    haspRoute =
                     strPad((String)hr.haspRoute ().elementAt (j),5);
                    haspTrip =
                     strPad((String)hr.haspTrip ().elementAt (j),5);
                    System.out.println ("PtII RecNo="+j+",HASP Route="+haspRoute+",HASP Trip="+haspTrip+",Dest="+destStr);
                    haspEffDate.setTime ((Date)hr.haspEffDate ().elementAt (j));
                    haspDiscDate.setTime ((Date)hr.haspDisDate ().elementAt (j));
                    heDate = TimePeriod.PrintDate (haspEffDate);
                    hdDate = TimePeriod.PrintDate (haspDiscDate);
                    lvHasp = (Integer)hr.haspDepOrig ().elementAt (j);
                    arDest = (Integer)hr.haspArrHasp ().elementAt (j);
                }
                // Print the left side, 1st dest only
                if ((j < origRecs) && (leftSide == true)) {
                    reportFile.print ("     " + origRoute + " " +
                      origTrip + " " + oeDate + " " + odDate + "   " +
                      prNum (lvOrig.intValue (), 4) + "    " +
                      prNum (arHasp.intValue (), 4) + "  ");
                } else {
                    reportFile.print ("                          " +
                      "                             ");
                }
                System.out.println ("Printed left side ptII");
                // IF the CET was not met, print "Cannot meet CET" 
                if ((haspRecs == 0) || (origRecs == 0)) {

                    // o Fill out the destination
                    //strPad (newDest, 30);
                    newDest = destStr + " (" + destCode + ")";
                    int numSp = 36 - newDest.length ();
                    String spaces = "";
                    for (int x = 0; x < numSp; x++)
                        spaces = spaces + " ";
                    newDest = newDest + spaces;
                
                    reportFile.println ("Dest-" + newDest + "     Cannot meet CET");
                    i--;
                    continue;
                // ELSE IF there is no right side THEN end the line
                } else if (j >= haspRecs) {
                    reportFile.println ("");
                    i--;
                    continue;
                }

                // IF the destination has changed THEN
                if (j == 0) {
                    // Print new destination
                    newDest = "Dest-" + destStr + " ("+
                      destCode + ")";
                // ENDIF
                } else
                    newDest = "";
                System.out.println ("Processed changed destination");
            
                // o Fill out the destination
                //strPad (newDest, 30);
                int numSp = 30 - newDest.length ();
                String spaces = "";
                for (int x = 0; x < numSp; x++)
                    spaces = spaces + " ";
                newDest = newDest + spaces;
                System.out.println ("Filled out destination");
                
                // Print out the hasp-dest report segment
                reportFile.print (newDest);
                reportFile.println (" " + haspRoute + "  " +
                  haspTrip + " " + heDate + " " + hdDate + "   " +
                  prNum (lvHasp.intValue (), 4) + "   " +
                  prNum (arDest.intValue (), 4));
                i--;
                System.out.println ("Printed hasp-dest report segment");
            }
        }
        System.out.println ("About to return, i="+i);
        return i;
    }
    // Method to get a string representing a period
    private String getPeriodString (TimePeriod pd) {
        String pdStr = "";
        // Get the period string
        switch (pd.GetType ()) {
          case TimePeriod.AP:
            pdStr = pdStr.concat ("AP ");
            break;
          case TimePeriod.WEEKLY:
            pdStr = pdStr.concat ("Week ");
            break;
          case TimePeriod.DAILY:
            pdStr = pdStr.concat ("Day ");
            pdStr = pdStr.concat (pd.PrintDate (pd.BeginningDate ()));
            pdStr = pdStr.concat (" FY "+pd.GetFiscalYear ());
            return pdStr;
        }
        // Note: Only AP and Weekly come here!
        if (pd.GetID () < 10)
            pdStr = pdStr.concat ("0");
        pdStr = pdStr.concat (String.valueOf (pd.GetID ()));
        // Print the ending period if the report is for more than 1 period
        if (pms.Periods ().length > 1) {
            pdStr = pdStr.concat ("-");
            if (pms.Periods ()[pms.Periods ().length - 1].GetID () < 10)
                pdStr = pdStr.concat ("0");
            pdStr = pdStr.concat ("" + pms.Periods ()[pms.Periods ().length - 1].GetID ());
        }
        pdStr = pdStr.concat (" FY " + pd.GetFiscalYear ());

        return pdStr;
    }
    
    // Method to print an integer up to 99,999, right justify
    // NOTE: Field len of 4 indicates no comma, 0's on left!
    private String prNum (int num, int fieldLen) {
        // Create a string of the specified length
        DecimalFormat df = null;
        if (fieldLen != 4)
            df = new DecimalFormat ("###,###");
        else
            df = new DecimalFormat ("####");
        String number = df.format (num);
        if (number.length () < fieldLen) {
            int numSp = fieldLen - number.length ();
            String spaces = "";
            for (int i = 0; i < numSp; i++)
                spaces = spaces + ((fieldLen == 4) ? "0" : " ");
            number = spaces + number;
        }
        if (number.length () > fieldLen) {
            try {
                number = number.substring (number.length () - fieldLen);
            } catch (Throwable xx) {
                ;
            }
        }
        return number;
    }
    
    private String localClass = null;
    private boolean localAllTots;
    // Method to print totals lines
    private int printTotals (String clss, boolean allTots, int i) {
        int numPrinted = 0;
          // NOTE: This routine saves it's current state after
          //  printing a line
          // Get number of days in a record
        int div = 0;
          if (pms.Periods ()[0].GetType () == TimePeriod.DAILY)
              div = 1;
          else
              div = 7;

        // IF this routine was called with null clss THEN
        if (clss == null) {
            // Exit if nothing was previously saved
            if (localClass == null)
                return 0;
            // Restore the saved condition
            clss = localClass;
            allTots = localAllTots;
        // ELSE
        } else {
            // Set the saved condition
            localClass = clss;
            localAllTots = allTots;
        // ENDIF
        }
        // Exit immediately if there is no room to print
        if (i == 0) return 0;
        // Print the section totals
        try {
            // o Get the "Class" string
            int num;
            int first;
            if (clss.equals ("F")) {
                clss = "First Class Average Daily Volume";
                num = numInFirstClass;
                first = startingFirstClass;
            } else {
                clss = "Priority Average Daily Volume   ";
                num = numInPriority;
                first = startingPriority;
            }
            // o Perform any needed calculations
            Vector recs = new Vector (num, 5);
            for (int j = 0; j < num; j++)
                recs.addElement (new Integer (first+j));
            
            // o Print the total line
            reportFile.println ("          "+clss+
              "                  "+prNum (fullRep.total (
               HASP_Report_Store.ACTUAL_VOLUMES,recs).intValue ()/(div*num),6) +
              "       "+prNum (fullRep.total (
               HASP_Report_Store.ORIG_DAILY_TRIPS,recs).intValue (),2)+
              "         "+prNum (fullRep.total (
               HASP_Report_Store.ORIG_AVG_UTILS,recs).intValue (),3)+
              "%       "+prNum (fullRep.total (
               HASP_Report_Store.ORIG_CAPACITIES,recs).intValue (),6)+
              "     "+prNum (fullRep.total (
               HASP_Report_Store.HASP_DAILY_TRIPS,recs).intValue (),2)+
              "         "+prNum (fullRep.total (
               HASP_Report_Store.HASP_AVG_UTILS,recs).intValue (),3)+
              "%       "+prNum (fullRep.total (
               HASP_Report_Store.HASP_CAPACITIES,recs).intValue (),6));
            i--;
            numPrinted++;
            if (i == 0) return numPrinted;
            reportFile.println ("");
            i--;
            numPrinted++;
            if (i == 0) return numPrinted;
        // IF this is a Grand Total calculation THEN
            if (allTots == true) {
            // Print one total row for each period
            // NOTE: Grand Total line is same as First Class Total -
            //  except for airline info
                Vector recBoth = new Vector (2, 1);
                for (int j = 0; j < num; j++) {
                    recBoth.addElement (new Integer (startingFirstClass+j));
                    if (numInPriority > 0)
                        recBoth.addElement (new Integer (startingPriority+j));
                }
                reportFile.println ("          Total All Mail Classes"+
                  "                            "+prNum (fullRep.total (
                   HASP_Report_Store.ACTUAL_VOLUMES,recBoth).intValue ()/(div*num),6) +
                  "       "+prNum (fullRep.total (
                   HASP_Report_Store.ORIG_DAILY_TRIPS,recs).intValue (),2)+
                  "         "+prNum (fullRep.total (
                   HASP_Report_Store.ORIG_AVG_UTILS,recs).intValue (),3)+
                  "%       "+prNum (fullRep.total (
                   HASP_Report_Store.ORIG_CAPACITIES,recs).intValue (),6)+
                  "     "+prNum (fullRep.total (
                   HASP_Report_Store.HASP_DAILY_TRIPS,recs).intValue (),2)+
                  "         "+prNum (fullRep.total (
                   HASP_Report_Store.HASP_AVG_UTILS,recs).intValue (),3)+
                  "%       "+prNum (fullRep.total (
                   HASP_Report_Store.HASP_CAPACITIES,recs).intValue (),6));
                reportFile.println ("");
                i -= 2;
                numPrinted += 2;
                if (i <= 0) return numPrinted;
            // Print a Grand Totals row
        // ENDIF
            }
        } catch (Throwable xx) {
            ;
        }
        return numPrinted;
    }
    // Routine to right-pad a string
    private String strPad (String str, int len) {
        int toGo = len - str.length ();
        for (int i = 0; i < toGo; i++) {
            str = str + " ";
        }
        return str;
    }                
}
