Example #1
0
        public void CalcValues()
        {
            CPbusinessLayer bslyr = new CPbusinessLayer();

            bslyr.DAL      = DAL;
            bslyr.fileName = fileName;

            List <SampleGroupDO>      sgList  = bslyr.getSampleGroups();
            List <TreeDefaultValueDO> tdvList = bslyr.getTreeDefaults();
            List <CountTreeDO>        ctList  = bslyr.getCountTrees();
            List <PlotDO>             pList   = bslyr.getPlots();

            ClearCalculatedTables();
            MakePopulationIDs(sgList, tdvList);
        }
Example #2
0
        private void on_GO(object sender, EventArgs e)
        {
            processingStatus.Text = "READY TO BEGIN?  Click GO.";
            Cursor.Current        = Cursors.WaitCursor;
            //  perform edit checks --
            processingStatus.Text = "Edit checking the data.  Please wait.";
            processingStatus.Refresh();
            //  calls edit check routines

            /*            string outputFileName;
             *          //  check for errors from FScruiser before running edit checks
             *          //  generate an error report
             *          //  June 2013
             *          List<ErrorLogDO> fscList = bslyr.getErrorMessages("E", "FScruiser");
             *          if (fscList.Count > 0)
             *          {
             *              ErrorReport eRpt = new ErrorReport();
             *              eRpt.fileName = fileName;
             *              eRpt.bslyr.fileName = bslyr.fileName;
             *              eRpt.bslyr.DAL = bslyr.DAL;
             *              outputFileName = eRpt.PrintFScruiserErrors(fscList);
             *              string outputMessage = "ERRORS FROM FSCRUISER FOUND!\nCorrect data and rerun\nOutput file is:" + outputFileName;
             *              MessageBox.Show(outputMessage, "ERRORS", MessageBoxButtons.OK, MessageBoxIcon.Stop);
             *              //  request made to open error report in preview -- May 2015
             *              PrintPreview pp = new PrintPreview();
             *              pp.fileName = outputFileName;
             *              pp.setupDialog();
             *              pp.ShowDialog();
             *              Environment.Exit(0);
             *          }   //  endif report needed
             *
             *          //  clear out error log table for just CruiseProcessing before performing checks
             *          bslyr.DeleteErrorMessages();
             *
             *          EditChecks eChecks = new EditChecks();
             *          eChecks.fileName = fileName;
             *          eChecks.bslyr.fileName = bslyr.fileName;
             *          eChecks.bslyr.DAL = bslyr.DAL;
             *
             *          int errors = eChecks.TableEditChecks();
             *          if (errors == -1)
             *          {
             *              //  no measured trees detected in the cruise.  critical errpor stops the program.
             *              Close();
             *              return;
             *          }   //  endif
             *          errors = eChecks.MethodChecks();
             *          if (errors == -1)
             *          {
             *              //  empty stratum detected and user wants to quit
             *              Close();
             *              return;
             *          }   //  endif
             *          //  just check the ErrorLog table for entries
             *          List<ErrorLogDO> errList = bslyr.getErrorMessages("E", "CruiseProcessing");
             *          if (errList.Count > 0)
             *          {
             *              ErrorReport er = new ErrorReport();
             *              er.fileName = fileName;
             *              er.bslyr.fileName = fileName;
             *              er.bslyr.DAL = bslyr.DAL;
             *              outputFileName = er.PrintErrorReport(errList);
             *              string outputMessage = "ERRORS FOUND!\nCorrect data and rerun\nOutput file is:" + outputFileName;
             *              MessageBox.Show(outputMessage, "ERRORS", MessageBoxButtons.OK, MessageBoxIcon.Stop);
             *              //  request made to open error report in preview -- May 2015
             *              PrintPreview pp = new PrintPreview();
             *              pp.fileName = outputFileName;
             *              pp.setupDialog();
             *              pp.ShowDialog();
             *              Environment.Exit(0);
             *          }   //  endif report needed
             * moved to EditCheck routine*/
            //  Show editCheck message -- edit checks complete

            EditChecks eChecks = new EditChecks();

            eChecks.fileName = fileName;
            eChecks.DAL      = DAL;

            int err = eChecks.CheckErrors();

            if (err < 0)
            {
                Close();
                return;
            }

            editCheck.Enabled = true;

            //  next show preparation of data
            processingStatus.Text = "Preparing data for processing.";
            processingStatus.Refresh();

            //  before making IDs, need to check for blank or null secondary products in sample groups
            //  if blank, default to 02 for every region but 6 where it will be 08 instead
            //  put a warning message in the error log table indicating the secondary product was set to a default
            //  June 2013
            List <SaleDO> saleList = new List <SaleDO>();

            saleList = DAL.From <SaleDO>().Read().ToList();
            string currRegion = saleList[0].Region;

            //string currRegion = bslyr.getRegion();

            DefaultSecondaryProduct(currRegion);

            CalculateTreeValues calcTreeVal = new CalculateTreeValues();
            CalculatedValues    calcVal     = new CalculatedValues();


            //  retrieve lists needed and sets up population IDs
            calcVal.fileName = fileName;
            calcVal.DAL      = DAL;
            //   List<SampleGroupDO> sgList = bslyr.getSampleGroups();
            //   List<TreeDefaultValueDO> tdvList = bslyr.getTreeDefaults();
            //   List<CountTreeDO> ctList = bslyr.getCountTrees();
            //   List<PlotDO> pList = bslyr.getPlots();

            //   calcVal.ClearCalculatedTables();
            //   calcVal.MakePopulationIDs(sgList, tdvList);

            calcVal.CalcValues();

            CPbusinessLayer bslyr = new CPbusinessLayer();

            bslyr.DAL = DAL;
            //  now need some other tables to start summing values
            List <LCDDO>              lcdList = bslyr.getLCD();
            List <POPDO>              popList = bslyr.getPOP();
            List <PRODO>              proList = bslyr.getPRO();
            List <StratumDO>          sList   = bslyr.getStratum();
            List <SampleGroupDO>      sgList  = bslyr.getSampleGroups();
            List <TreeDefaultValueDO> tdvList = bslyr.getTreeDefaults();
            List <CountTreeDO>        ctList  = bslyr.getCountTrees();
            List <PlotDO>             pList   = bslyr.getPlots();
            List <TreeDO>             tList   = bslyr.getTrees();

            calcTreeVal.fileName       = fileName;
            calcTreeVal.bslyr.fileName = fileName;
            calcTreeVal.bslyr.DAL      = bslyr.DAL;

            //  show preparation of data is complete
            prepareCheck.Enabled = true;
            //  now loop through strata and show status message updating for each stratum
            StringBuilder sb = new StringBuilder();

            foreach (StratumDO sdo in sList)
            {
                //  update status message for next stratum
                sb.Clear();
                sb.Append("Calculating stratum ");
                sb.Append(sdo.Code);
                processingStatus.Text = sb.ToString();
                processingStatus.Refresh();

                //  Sum counts and KPI for LCD table
                List <PlotDO> justPlots = PlotMethods.GetStrata(pList, sdo.Code);
                //  need cut and leave trees for this
                List <LCDDO> justCurrentLCD = LCDmethods.GetStratum(lcdList, sdo.Code);
                calcVal.SumTreeCountsLCD(sdo.Code, ctList, justPlots, justCurrentLCD, sdo.Method, lcdList);

                //  Sum counts and KPI for POP table
                List <POPDO> justCurrentPOP = POPmethods.GetStratumData(popList, sdo.Code, "");
                calcVal.SumTreeCountsPOP(sdo.Code, ctList, justPlots, justCurrentPOP, sdo.Method, popList);

                //  Sum counts and KPI for PRO table
                List <PRODO> justCurrentPRO = PROmethods.GetCutTrees(proList, sdo.Code, "", "", 0);
                calcVal.SumTreeCountsPRO(sdo.Code, ctList, justPlots, justCurrentPRO, sdo.Method, proList);

                //  Calculate expansion factor
                calcVal.CalcExpFac(sdo, justPlots, justCurrentPOP);

                //  Calculate volumes
                calcTreeVal.ProcessTrees(sdo.Code, sdo.Method, (long)sdo.Stratum_CN);

                //  Update 3P tally
                if (sdo.Method == "3P")
                {
                    List <LCDDO> LCDstratum = LCDmethods.GetStratumGroupedBy(fileName, sdo.Code, bslyr);

                    Update3Ptally(fileName, ctList, justCurrentLCD, tList, LCDstratum);
                    //  Save
                    bslyr.SaveLCD(justCurrentLCD);
                }   //  endif method is 3P


                //  Update expansion factors for methods 3PPNT, F3P, and P3P
                if (sdo.Method == "3PPNT" || sdo.Method == "F3P" || sdo.Method == "P3P")
                {
                    List <TreeDO> justCurrentStratum = tList.FindAll(
                        delegate(TreeDO td)
                    {
                        return(td.Stratum.Code == sdo.Code);
                    });
                    List <TreeCalculatedValuesDO> tcvList = bslyr.getTreeCalculatedValues((int)sdo.Stratum_CN);
                    UpdateExpansionFactors(justCurrentStratum, tcvList);
                    //  Save update
                    bslyr.SaveTrees(justCurrentStratum);
                }   //  endif on method

                //  Sum data for the LCD, POP and PRO table
                SumAll Sml = new SumAll();
                Sml.fileName       = fileName;
                Sml.bslyr.fileName = bslyr.fileName;
                Sml.bslyr.DAL      = bslyr.DAL;
                Sml.SumAllValues(sdo.Code, sdo.Method, (int)sdo.Stratum_CN, sList, pList, justCurrentLCD,
                                 justCurrentPOP, justCurrentPRO);

                //  Update STR tally after expansion factors are summed
                if (sdo.Method == "STR")
                {
                    UpdateSTRtally(fileName, sdo.Code, justCurrentLCD, ctList, lcdList);
                    //  save
                    bslyr.SaveLCD(lcdList);
                } //  endif method is STR
            }     //  end foreach stratum

            //  show volume calculation is finished
            volumeCheck.Enabled   = true;
            processingStatus.Text = "Processing is DONE";
            processingStatus.Refresh();
            System.Threading.Thread.Sleep(5000);
            Cursor.Current = this.Cursor;

            Close();
            return;
        }   //  end on_GO
        public int TableEditChecks()
        {
            CPbusinessLayer bslyr = new CPbusinessLayer();

            bslyr.DAL      = DAL;
            bslyr.fileName = fileName;
            elm.fileName   = fileName;
            string currentRegion = bslyr.getRegion();
            string isVLL         = "";
            //string isVLL = bslyr.getVLL();

            //  edit checks for each table
            //  sale table
            List <SaleDO> saleList = bslyr.getSale();

            //  empty or more than one record?
            errorValue = SaleMethods.MoreThanOne(saleList);
            if (errorValue == 0)
            {
                elm.LoadError("Sale", "E", "25", errorValue, "NoName");           //  error 25 -- table cannot be empty
            }
            else if (errorValue > 1)
            {
                elm.LoadError("Sale", "E", "28", errorValue, "SaleNumber");           //  error 28 -- more than one sale record not allowed
            }
            if (errorValue == 1)
            {
                //  and blank sale number
                errorValue = SaleMethods.BlankSaleNum(saleList);
                if (errorValue != -1)
                {
                    elm.LoadError("Sale", "E", " 8Sale Number", errorValue, "SaleNumber");
                }
            }       //  endif
            //  end sale table edit checks

            // *******************************************************************
            //  stratum table
            List <StratumDO> strList = bslyr.getStratum();

            errorValue = StratumMethods.IsEmpty(strList);
            if (errorValue != 0)
            {
                elm.LoadError("Stratum", "E", errorValue.ToString(), errorValue, "NoName");
            }
            else if (errorValue == 0)        //  means there are records to check
            {
                foreach (StratumDO sdo in strList)
                {
                    //  check for valid fixed plot size or BAF for each stratum
                    double BAForFPS = StratumMethods.CheckMethod(strList, sdo.Code);
                    if ((sdo.Method == "PNT" || sdo.Method == "P3P" || sdo.Method == "PCM" ||
                         sdo.Method == "PCMTRE" || sdo.Method == "3PPNT") && BAForFPS == 0)
                    {
                        elm.LoadError("Stratum", "E", "22", (long)sdo.Stratum_CN, "BasalAreaFactor");
                    }
                    else if ((sdo.Method == "FIX" || sdo.Method == "F3P" || sdo.Method == "FIXCNT" ||
                              sdo.Method == "FCM") && BAForFPS == 0)
                    {
                        elm.LoadError("Stratum", "E", "23", (long)sdo.Stratum_CN, "FixedPlotSize");
                    }

                    //  check for acres on area based methods
                    double currAcres = Utilities.AcresLookup((long)sdo.Stratum_CN, bslyr, sdo.Code);
                    if ((sdo.Method == "PNT" || sdo.Method == "FIX" || sdo.Method == "P3P" ||
                         sdo.Method == "F3P" || sdo.Method == "PCM" || sdo.Method == "3PPNT" ||
                         sdo.Method == "FCM" || sdo.Method == "PCMTRE") && currAcres == 0)
                    {
                        elm.LoadError("Stratum", "E", "24", (long)sdo.Stratum_CN, "NoName");
                    }
                    else if ((sdo.Method == "100" || sdo.Method == "3P" ||
                              sdo.Method == "S3P" || sdo.Method == "STR") && currAcres == 0)
                    {
                        elm.LoadError("Stratum", "W", "Stratum has no acres", (long)sdo.Stratum_CN, "NoName");
                    }

                    //  August 2017 -- added check for valid yield component code
                    if (sdo.YieldComponent != "CL" && sdo.YieldComponent != "CD" &&
                        sdo.YieldComponent != "ND" && sdo.YieldComponent != "NL" &&
                        sdo.YieldComponent != "" && sdo.YieldComponent != " " &&
                        sdo.YieldComponent != null)
                    {
                        elm.LoadError("Stratum", "W", "Yield Component has invalid code", (long)sdo.Stratum_CN, "YieldComponent");
                    }
                }   //  end foreach loop
            }       //  endif
            //  end stratum table edit checks

            //  ************************************************************************
            // cutting unit table
            List <CuttingUnitDO> cuList = bslyr.getCuttingUnits();

            errorValue = CuttingUnitMethods.IsEmpty(cuList);
            if (errorValue != 0)
            {
                elm.LoadError("Cutting Unit", "E", errorValue.ToString(), 0, "NoName");
            }
            //  end cutting unit edit checks

            //  **************************************************************************
            //  count table
            List <CountTreeDO> cntList = bslyr.getCountTrees();

            foreach (StratumDO sl in strList)
            {
                errorValue = CountTreeMethods.check3Pcounts(cntList, bslyr, sl);
                if (errorValue != 0)
                {
                    elm.LoadError("CountTree", "E", "Cannot tally by sample group for 3P strata.", (long)sl.Stratum_CN, "TreeDefaultValue");
                }
            }       //  end foreach on stratum

            //  **************************************************************************
            //  tree table
            List <TreeDO> tList = bslyr.getTrees();

            errorValue = Tlm.IsEmpty(tList);
            if (errorValue != 0)
            {
                elm.LoadError("Tree", "E", errorValue.ToString(), 0, "NoName");
            }
            else if (errorValue == 0)           //  means tree table has records
            {
                //  make sure single stratum is NOT FIXCNT which cannot have measured trees anyway.
                //if(strList.Count == 1 && strList[0].Method != "FIXCNT")
                //  doesn't matter if it's a single stratum or any stratum that's FIXCNT
                //  that method still has no measured trees so need to skip these checks.
                if (strList[0].Method != "FIXCNT")
                {
                    tList = bslyr.JustMeasuredTrees();
                    //  March 2016 -- if the entire cruisde has no measured trees, that uis a critical erro
                    //  and should stop the program.  Since no report can be generated, a message box appears to warn the user
                    //  of the condition.
                    if (tList.Count == 0)
                    {
                        MessageBox.Show("NO MEASURED TREES IN THIS CRUISE.\nCannot continue and cannot produce any reports.", "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Stop);
                        return(-1);
                    }       //endif
                    //  general checks include  checking for secondary top DIB greater than primary
                    //  recoverable percent greater than seen defect primary
                    //  missing species, product or uom when tree count is greater than zero or DBH is greater than zero
                    //  and check for upper stem diameter greater than DBH
                    errorValue = Tlm.GeneralChecks(tList, currentRegion);
                }   //  endif single stratum
            }       //  endif
            //  end tree table edit checks

            //  *************************************************************************
            //  log table
            List <LogDO> logList = bslyr.getLogs();

            if (logList.Count > 0)
            {
                errorValue = Lms.CheckNumberLogs(logList);
                errorValue = Lms.CheckFBS(logList);
                if (isVLL == "true")
                {
                    errorValue = Lms.CheckVLL(logList);
                }
                errorValue = Lms.CheckDefect(logList);
                if (currentRegion != "05")
                {
                    errorValue = Lms.CheckLogGrade(logList);
                }
            }       //  endif records in log table to check
            //  end log table edit checks

            //  *************************************************************************
            //  volume equation table
            List <VolumeEquationDO> volList = bslyr.getVolumeEquations();

            Veq.DAL    = DAL;
            errorValue = Veq.IsEmpty(volList);
            //  pull region
            string currRegion = bslyr.getRegion();

            if (errorValue != 0)
            {
                elm.LoadError("VolumeEquation", "E", errorValue.ToString(), 0, "NoName");
            }
            else if (errorValue == 0)        //  means the table is not empty and checks can proceed
            {
                //  Match unique species/product to volume equation
                errorValue = Veq.MatchSpeciesProduct(volList, tList);
                errorValue = Veq.GeneralEquationChecks(volList);
                //  if VLL, check equations for Behrs
                if (isVLL == "true")
                {
                    errorValue = Veq.FindBehrs(volList);
                }
            }       //  endif
                    //  end volume equation edit checks

            //  *************************************************************************
            //  value equations
            // Check for valid equations
            ValueEqMethods         Vem     = new ValueEqMethods();
            List <ValueEquationDO> valList = bslyr.getValueEquations();

            if (valList.Count > 0)          //  there are records to check
            {
                errorValue = Vem.CheckEquations(valList, currentRegion);
            }
            //  end value equation edit checks

            //  *************************************************************************
            //  quality adjustment equations
            QualityAdjMethods           Qam     = new QualityAdjMethods();
            List <QualityAdjEquationDO> qaeList = bslyr.getQualAdjEquations();

            if (qaeList.Count > 0)          //  there are records to check
            {
                errorValue = Qam.CheckEquations(qaeList);
            }
            //  end quality adjustment equation edit checks

            //  ************************************************************************
            //  June 2014 -- apparently the error log table is not meant to capture
            //  errors on the basis of an entire table.  Only on individual records.
            //  so if no reports have been selected, this check needs to move to
            //  the Output section when the user clicks GO.  If the reports list
            //  comes up empty then display a message box telling them to go back
            //  and enter reports.
            //  no reports selected

            /*
             *              List<ReportsDO> selectedReports = bslyr.GetSelectedReports();
             *              if (selectedReports.Count == 0)
             *              {
             *                  elm.LoadError("Reports", "E", "26", 0,"NoName");
             *                  errorValue++;
             *              }   //  endif no reports
             */
            //  ************************************************************************
            //  sample group table
            SampleGroupMethods   Sgm        = new SampleGroupMethods();
            List <SampleGroupDO> sampGroups = bslyr.getSampleGroups();

            errorValue = Sgm.CheckAllUOMandCutLeave(strList, sampGroups, fileName);
            //  ************************************************************************
            errList = elm.errList;
            if (errList.Count > 0)
            {
                bslyr.fileName = fileName;
                bslyr.SaveErrorMessages(errList);
            }   //  endif
            return(errorValue);
        }       //  end TableEditChecks
        }   //  end CheckForNoDBH

        private int CheckForMeasuredTrees(List <TreeDO> treeList, int currST_CN, string currMeth, CPbusinessLayer bslyr)
        {
            int             numErrs = 0;
            ErrorLogMethods elm     = new ErrorLogMethods();

            //  if the tree list is empty, could be the strata just doesn't have any trees.
            //  this is probably a cruise in process so return no errors on this stratum.
            //  October 2014
            if (treeList.Count == 0)
            {
                return(numErrs);
            }

            //  need sample group(s) for current stratum
            List <SampleGroupDO> sgList = bslyr.getSampleGroups(currST_CN);

            //  check is method based
            switch (currMeth)
            {
            case "3P":
            case "STR":
            case "S3P":
                foreach (SampleGroupDO sg in sgList)
                {
                    //  find count records for the sample group
                    List <CountTreeDO> justGroups = bslyr.getCountTrees((long)sg.SampleGroup_CN);
                    //  sum up tree count
                    float totalCount = justGroups.Sum(jg => jg.TreeCount);
                    if (totalCount > 0)
                    {
                        //  Any measured trees?  look for just one measured tree in the stratum
                        List <TreeDO> justMeasured = treeList.FindAll(
                            delegate(TreeDO t)
                        {
                            return(t.CountOrMeasure == "M" && t.SampleGroup_CN == sg.SampleGroup_CN && t.Stratum_CN == currST_CN);
                        });
                        if (justMeasured.Count == 0)
                        {
                            //  this is the error
                            elm.LoadError("SampleGroup", "W", "30", (long)sg.SampleGroup_CN, "NoName");
                            numErrs++;
                        } //  endif
                    }     //  endif totalCount
                }         //  end foreach loop
                break;

            default:            //  all area based
                foreach (SampleGroupDO sg in sgList)
                {
                    List <TreeDO> justGroups = treeList.FindAll(
                        delegate(TreeDO t)
                    {
                        return(t.SampleGroup_CN == sg.SampleGroup_CN);
                    });

                    float totalCount = justGroups.Sum(jg => jg.TreeCount);
                    if (totalCount > 0)
                    {
                        //  any measured trees?
                        List <TreeDO> justMeasured = justGroups.FindAll(
                            delegate(TreeDO td)
                        {
                            return(td.CountOrMeasure == "M");
                        });
                        if (justMeasured.Count == 0)
                        {
                            // here's the error
                            elm.LoadError("SampleGroup", "W", "30", (long)sg.SampleGroup_CN, "NoName");
                            numErrs++;
                        } //  endif
                    }     //  endif totalCount
                }         //  end foreach loop
                break;
            }             //  end switch
            return(numErrs);
        }                 //  end CheckForMeasuredTrees
        public void createGraphs()
        {
            List <TreeDO>    tList       = bslyr.getTrees();
            List <LCDDO>     lcdList     = bslyr.getLCD();
            List <StratumDO> sList       = bslyr.getStratum();
            List <LCDDO>     justSpecies = bslyr.getLCDOrdered("WHERE CutLeave = @p1 ", "GROUP BY Species", "C", "");
            //  pull salename and number to put in graph title
            //  also need it to create subfolder for graphs
            List <SaleDO> saleList     = bslyr.getSale();
            string        currSaleName = saleList[0].Name;

            if (currSaleName.Length > 25)
            {
                currSaleName = currSaleName.Remove(25, currSaleName.Length);
            }
            string currSaleNumber = saleList[0].SaleNumber;

            // pull data needed and call appropriate graph routine for report
            switch (currentReport)
            {
            case "GR01":
                foreach (LCDDO js in justSpecies)
                {
                    //  pull all trees for each species
                    List <TreeDO> justTrees = tList.FindAll(
                        delegate(TreeDO td)
                    {
                        return(td.Species == js.Species && td.CountOrMeasure == "M");
                    });
                    currTitle.Append("DBH AND TOTAL HEIGHT BY ");
                    if (justTrees.Count == 0)
                    {
                        noDataForGraph(js.Species, "Species");
                        break;
                    }
                    else
                    {
                        currTitle.Append(js.Species);
                        currTitle.Append("\nSale number: ");
                        currTitle.Append(currSaleNumber);
                        currTitle.Append("   Sale name:  ");
                        currTitle.Append(currSaleName);
                        gf.currTitle    = currTitle.ToString();
                        gf.currXtitle   = "DBH";
                        gf.currYtitle   = "TOTAL HEIGHT";
                        gf.graphNum     = 1;
                        gf.currSP       = js.Species;
                        gf.fileName     = fileName;
                        gf.chartType    = "SCATTER";
                        gf.treeList     = justTrees;
                        gf.currSaleName = currSaleName;
                        gf.ShowDialog();
                    }       //  endif no data
                    currTitle.Remove(0, currTitle.Length);
                    justTrees.Clear();
                }       //  end foreach loop
                break;

            case "GR02":
                if (lcdList.Count == 0)
                {
                    MessageBox.Show("No data found for report.\nTry processing the cruise again.", "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }       //  endif no data
                //  total expansion factor for each species to get data for the sale
                foreach (LCDDO js in justSpecies)
                {
                    List <LCDDO> speciesGroup = lcdList.FindAll(
                        delegate(LCDDO l)
                    {
                        return(l.Species == js.Species);
                    });
                    expandData(speciesGroup, "EXPFAC", sList, js.Species);
                }       //  end foreach justSpecies
                currTitle.Remove(0, currTitle.Length);
                currTitle.Append("SPECIES DISTRIBUTION FOR THE SALE");
                currTitle.Append("\nSale number: ");
                currTitle.Append(currSaleNumber);
                currTitle.Append("   Sale name:  ");
                currTitle.Append(currSaleName);
                gf.currTitle    = currTitle.ToString();
                gf.currXtitle   = "";
                gf.currYtitle   = "";
                gf.graphNum     = 2;
                gf.chartType    = "PIE";
                gf.lcdList      = speciesTotal;
                gf.fileName     = fileName;
                gf.currSaleName = currSaleName;
                gf.ShowDialog();

                break;

            case "GR03":
                speciesTotal.Clear();
                //  total net CUFT volume for sawtimber only
                foreach (LCDDO js in justSpecies)
                {
                    List <LCDDO> speciesGroup = lcdList.FindAll(
                        delegate(LCDDO l)
                    {
                        return(l.Species == js.Species && l.PrimaryProduct == "01");
                    });
                    expandData(speciesGroup, "VOL", sList, js.Species);
                }       //  end foreach justSpecies
                currTitle.Remove(0, currTitle.Length);
                currTitle.Append("VOLUME BY SPECIES -- SAWTIMBER ONLY");
                currTitle.Append("\nSale number: ");
                currTitle.Append(currSaleNumber);
                currTitle.Append("   Sale name:  ");
                currTitle.Append(currSaleName);
                gf.currTitle    = currTitle.ToString();
                gf.currXtitle   = "";
                gf.currYtitle   = "";
                gf.graphNum     = 3;
                gf.chartType    = "PIE";
                gf.lcdList      = speciesTotal;
                gf.fileName     = fileName;
                gf.currSaleName = currSaleName;
                gf.ShowDialog();
                break;

            case "GR04":
                List <LCDDO> justProduct = bslyr.getLCDOrdered("WHERE CutLeave = @p1 ", "GROUP BY PrimaryProduct", "C", "");

                speciesTotal.Clear();
                //  total net CUFT volume for sawtimber only
                foreach (LCDDO jp in justProduct)
                {
                    List <LCDDO> productGroup = lcdList.FindAll(
                        delegate(LCDDO l)
                    {
                        return(l.PrimaryProduct == jp.PrimaryProduct);
                    });
                    expandData(productGroup, "VOL", sList, jp.PrimaryProduct);
                }       //  end foreach justSpecies
                currTitle.Remove(0, currTitle.Length);
                currTitle.Append("VOLUME BY PRODUCT");
                currTitle.Append("\nSale number: ");
                currTitle.Append(currSaleNumber);
                currTitle.Append("   Sale name:  ");
                currTitle.Append(currSaleName);
                gf.currTitle    = currTitle.ToString();
                gf.currXtitle   = "";
                gf.currYtitle   = "";
                gf.graphNum     = 4;
                gf.chartType    = "PIE";
                gf.lcdList      = speciesTotal;
                gf.fileName     = fileName;
                gf.currSaleName = currSaleName;
                gf.ShowDialog();
                break;

            case "GR05":
                //  per request from Region 10, give option to use 16 or 32 foot logs
                //  for this graph --  July 2017
                int          whichLength = 16;
                selectLength getLength   = new selectLength();
                getLength.ShowDialog();
                if (getLength.lengthSelected == 0)
                {
                    whichLength = 16;
                }
                else
                {
                    whichLength = getLength.lengthSelected;
                }
                //  pull by species for separate graphs
                List <LogStockDO> logsTotal = new List <LogStockDO>();
                List <LogStockDO> lsList    = bslyr.getLogStock();
                //  need to expand also
                foreach (LCDDO js in justSpecies)
                {
                    // pull all logs
                    List <LogStockDO> justSelectLogs = lsList.FindAll(
                        delegate(LogStockDO lsd)
                    {
                        return(lsd.Length == whichLength && lsd.Tree.Species == js.Species);
                    });
                    if (justSelectLogs.Count == 0)
                    {
                        MessageBox.Show("Graph cannot be created.\nNo logs found.", "WARNING", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                        break;
                    }       //  endif
                    logsTotal = LoadLogs(justSelectLogs, js.Species, sList);
                    currTitle.Remove(0, currTitle.Length);
                    if (whichLength == 16)
                    {
                        currTitle.Append("NUMBER OF 16-FOOT LOGS BY DIB CLASS -- ");
                    }
                    else if (whichLength == 32)
                    {
                        currTitle.Append("NUMBER OF 32-FOOT LOGS BY DIB CLASS -- ");
                    }
                    currTitle.Append(js.Species);
                    currTitle.Append("\nSale number: ");
                    currTitle.Append(currSaleNumber);
                    currTitle.Append("   Sale name:  ");
                    currTitle.Append(currSaleName);
                    gf.currTitle    = currTitle.ToString();
                    gf.currXtitle   = "DIB CLASS";
                    gf.currYtitle   = "NUMBER OF LOGS";
                    gf.graphNum     = 5;
                    gf.chartType    = "BAR";
                    gf.logStockList = logsTotal;
                    gf.currSP       = js.Species;
                    gf.fileName     = fileName;
                    gf.currSaleName = currSaleName;
                    gf.ShowDialog();
                }       //  end foreach loop on species
                break;

            case "GR06":
                //  pull just measured and cut trees
                justMeasured = tList.FindAll(
                    delegate(TreeDO td)
                {
                    return(td.CountOrMeasure == "M" && td.SampleGroup.CutLeave == "C");
                });
                //  expand data and group by DBH class
                expandData(justMeasured, sList);
                currTitle.Remove(0, currTitle.Length);
                currTitle.Append("DIAMETER DISTRIBUTION FOR THE SALE");
                currTitle.Append("\nSale number: ");
                currTitle.Append(currSaleNumber);
                currTitle.Append("   Sale name:  ");
                currTitle.Append(currSaleName);
                gf.currTitle    = currTitle.ToString();
                gf.currXtitle   = "DBH";
                gf.currYtitle   = "NUMBER OF TREES";
                gf.graphNum     = 6;
                gf.chartType    = "BAR";
                gf.treeList     = treesByDBH;
                gf.fileName     = fileName;
                gf.currSaleName = currSaleName;
                gf.ShowDialog();
                break;

            case "GR07":
                //  need by species
                foreach (LCDDO js in justSpecies)
                {
                    //  need species, measured and cut trees
                    justMeasured = tList.FindAll(
                        delegate(TreeDO td)
                    {
                        return(td.CountOrMeasure == "M" && td.SampleGroup.CutLeave == "C" &&
                               td.Species == js.Species);
                    });
                    //  expand data
                    expandData(justMeasured, sList);
                    //  load
                    currTitle.Remove(0, currTitle.Length);
                    currTitle.Append("DIAMETER DISTRIBUTION FOR SPECIES ");
                    currTitle.Append(js.Species);
                    currTitle.Append("\nSale number: ");
                    currTitle.Append(currSaleNumber);
                    currTitle.Append("   Sale name:  ");
                    currTitle.Append(currSaleName);
                    gf.currTitle    = currTitle.ToString();
                    gf.currXtitle   = "DBH";
                    gf.currYtitle   = "NUMBER OF TREES";
                    gf.graphNum     = 7;
                    gf.chartType    = "BAR";
                    gf.treeList     = treesByDBH;
                    gf.currSP       = js.Species;
                    gf.fileName     = fileName;
                    gf.currSaleName = currSaleName;
                    gf.ShowDialog();
                    treesByDBH.Clear();
                }       //  end foreach species
                break;

            case "GR08":
                //  need by stratum
                foreach (StratumDO s in sList)
                {
                    //  need measured and cut trees for each stratum
                    justMeasured = tList.FindAll(
                        delegate(TreeDO td)
                    {
                        return(td.CountOrMeasure == "M" && td.SampleGroup.CutLeave == "C" &&
                               td.Stratum.Code == s.Code);
                    });
                    //  expand data
                    expandData(justMeasured, sList);
                    //  load
                    currTitle.Remove(0, currTitle.Length);
                    currTitle.Append("DIAMETER DISTRIBUTION BY STRATUM ");
                    currTitle.Append(s.Code);
                    currTitle.Append("\nSale number: ");
                    currTitle.Append(currSaleNumber);
                    currTitle.Append("   Sale name:  ");
                    currTitle.Append(currSaleName);
                    gf.currTitle    = currTitle.ToString();
                    gf.currXtitle   = "DBH";
                    gf.currYtitle   = "NUMBER OF TREES";
                    gf.graphNum     = 8;
                    gf.chartType    = "BAR";
                    gf.treeList     = treesByDBH;
                    gf.currSP       = s.Code;
                    gf.fileName     = fileName;
                    gf.currSaleName = currSaleName;
                    gf.ShowDialog();
                    treesByDBH.Clear();
                }       //  end foreach stratum
                break;

            case "GR09":
                //  need values from TreEstimate table
                //  if that table is empty, it means no 3P strata or the file was created
                //  prior to March 2015 when the table was implemented.
                List <TreeEstimateDO> treeEstimates = bslyr.getTreeEstimates();
                if (treeEstimates.Count == 0)
                {
                    MessageBox.Show("No estimate data is available for GR09.\nCannot produce this graph.", "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }       //  endif
                List <TreeDO>      uniqueSpecies = bslyr.GetUniqueSpecies();
                List <CountTreeDO> cList         = bslyr.getCountTrees();
                List <CreateTextFile.ReportSubtotal> graphData = new List <CreateTextFile.ReportSubtotal>();
                foreach (TreeDO u in uniqueSpecies)
                {
                    //  pull all tree default value for current species
                    List <CountTreeDO> countSpecies = cList.FindAll(
                        delegate(CountTreeDO ct)
                    {
                        return(ct.TreeDefaultValue_CN == u.TreeDefaultValue_CN);
                    });
                    //  accumulate all count tree cn in TreeEstimate for this species
                    foreach (CountTreeDO c in countSpecies)
                    {
                        List <TreeEstimateDO> justEst = treeEstimates.FindAll(
                            delegate(TreeEstimateDO te)
                        {
                            return(te.CountTree_CN == c.CountTree_CN);
                        });
                        if (justEst.Count > 0)
                        {
                            buildKPIdata(justEst, graphData);
                        }
                    }       //  end foreach loop
                    //  reset categories based on Ken's logic
                    List <CreateTextFile.ReportSubtotal> categoryData = new List <CreateTextFile.ReportSubtotal>();
                    if (graphData.Count > 0)
                    {
                        resetCategories(graphData, categoryData);
                        //  load
                        currTitle.Remove(0, currTitle.Length);
                        currTitle.Append("KPI DISTRIBUTION BY SPECIES -- ");
                        currTitle.Append(u.Species);
                        currTitle.Append("\nSale number: ");
                        currTitle.Append(currSaleNumber);
                        currTitle.Append("   Sale name:  ");
                        currTitle.Append(currSaleName);
                        gf.currTitle    = currTitle.ToString();
                        gf.currXtitle   = "KPI";
                        gf.currYtitle   = "NUMBER OF TREES";
                        gf.graphNum     = 9;
                        gf.chartType    = "BAR";
                        gf.graphData    = categoryData;
                        gf.currSP       = u.Species;
                        gf.fileName     = fileName;
                        gf.currSaleName = currSaleName;
                        gf.ShowDialog();
                        graphData.Clear();
                        categoryData.Clear();
                    }   //  endif
                }       //  end foreach loop
                break;

            case "GR10":
                List <CreateTextFile.ReportSubtotal> dataToGraph = new List <CreateTextFile.ReportSubtotal>();
                //  need to loop by stratum
                foreach (StratumDO s in sList)
                {
                    if (s.BasalAreaFactor > 0)
                    {
                        //  Pull plots for this stratum
                        List <PlotDO> pList    = bslyr.GetStrataPlots(s.Code);
                        double        numplots = pList.Count;

                        //  Pull tree data for this stratum
                        List <TreeDO> treeList = bslyr.getTrees();
                        //  Pull stratum from LCD to get species in the stratum
                        List <LCDDO> lList       = bslyr.getLCD();
                        List <LCDDO> justStratum = lList.FindAll(
                            delegate(LCDDO ld)
                        {
                            return(ld.Stratum == s.Code);
                        });
                        //  Then find number of trees for the stratum and each species in the stratum
                        foreach (LCDDO js in justStratum)
                        {
                            List <TreeDO> justTrees = treeList.FindAll(
                                delegate(TreeDO td)
                            {
                                return(td.Stratum.Code == s.Code && td.Species == js.Species &&
                                       td.SampleGroup.CutLeave == "C" && td.LiveDead == js.LiveDead);
                            });

                            //  Load into graphData --  see if species is already in the list
                            int nthRow = dataToGraph.FindIndex(
                                delegate(CreateTextFile.ReportSubtotal cr)
                            {
                                return(cr.Value1 == js.Species);
                            });
                            if (nthRow < 0)
                            {
                                CreateTextFile.ReportSubtotal rs = new CreateTextFile.ReportSubtotal();
                                rs.Value1 = js.Species;
                                rs.Value3 = (s.BasalAreaFactor * justTrees.Count) / numplots;
                                dataToGraph.Add(rs);
                            }
                            else if (nthRow >= 0)
                            {
                                dataToGraph[nthRow].Value3 += (s.BasalAreaFactor * justTrees.Count) / numplots;
                            }   //  endif
                        }       //  end foreach loop

                        //  load graphData
                        if (dataToGraph.Count > 0)
                        {
                            currTitle.Remove(0, currTitle.Length);
                            currTitle.Append("BAF PER ACRE BY SPECIES FOR STRATUM ");
                            currTitle.Append(s.Code);
                            currTitle.Append("\nSale Number:  ");
                            currTitle.Append(currSaleNumber);
                            currTitle.Append("\n");
                            currTitle.Append("   Sale Name:  ");
                            currTitle.Append(currSaleName);

                            gf.currTitle    = currTitle.ToString();
                            gf.currXtitle   = "";
                            gf.currYtitle   = "";
                            gf.graphNum     = 10;
                            gf.chartType    = "PIE";
                            gf.currSP       = s.Code;
                            gf.graphData    = dataToGraph;
                            gf.fileName     = fileName;
                            gf.currSaleName = currSaleName;
                            gf.ShowDialog();
                            dataToGraph.Clear();
                        } //  endif
                    }     //  endif on basal area factor
                }         //  end foreach loop on stratum
                break;

            case "GR11":
                //  pull data by sample group
                List <SampleGroupDO> sgList = bslyr.getSampleGroups();
                float numPlots = 0;
                //  find all trees for each group
                foreach (SampleGroupDO sg in sgList)
                {
                    if (sg.Stratum.BasalAreaFactor > 0)
                    {
                        //  find all strata for this group in LCD
                        List <LCDDO> lList      = bslyr.getLCD();
                        List <LCDDO> justStrata = lList.FindAll(
                            delegate(LCDDO l)
                        {
                            return(l.SampleGroup == sg.Code);
                        });
                        //  find number of plots for the strata
                        string currST = "*";
                        foreach (LCDDO js in justStrata)
                        {
                            if (currST != js.Stratum)
                            {
                                List <PlotDO> pList = bslyr.GetStrataPlots(js.Stratum);
                                numPlots += pList.Count();
                                currST    = js.Stratum;
                            }   //  endif
                        }       //  end foreach loop

                        // now find all trees for the sample group
                        justMeasured = tList.FindAll(
                            delegate(TreeDO td)
                        {
                            return(td.SampleGroup_CN == sg.SampleGroup_CN &&
                                   td.CountOrMeasure == "M" &&
                                   td.SampleGroup.CutLeave == "C" &&
                                   td.Stratum_CN == sg.Stratum_CN);
                        });

                        //  load DIB classes
                        LoadDIBclass(justMeasured);

                        //  Accumulate number of trees for each class
                        foreach (TreeDO jm in justMeasured)
                        {
                            //  find class to update
                            int nthRow = findDIBindex(treesByDBH, jm.DBH);
                            if (nthRow >= 0)
                            {
                                treesByDBH[nthRow].TreeCount++;
                            }
                        }       //  end foreach loop

                        //  Calculate
                        foreach (TreeDO tbd in treesByDBH)
                        {
                            //  Calculate value for each DIB class
                            tbd.TreeCount = (float)((sg.Stratum.BasalAreaFactor * tbd.TreeCount) / numPlots);
                        }       //  end foreach loop

                        //  load dat6a for gtraph
                        currTitle.Remove(0, currTitle.Length);
                        currTitle.Append("BAF PER ACRE FOR SAMPLE GROUP ");
                        currTitle.Append(sg.Code);
                        currTitle.Append("\nSaleNumber: ");
                        currTitle.Append(currSaleNumber);
                        currTitle.Append("\nSale name: ");
                        currTitle.Append(currSaleName);
                        gf.currTitle    = currTitle.ToString();
                        gf.currXtitle   = "DBH Class";
                        gf.currYtitle   = "Basal Area Factor";
                        gf.graphNum     = 11;
                        gf.chartType    = "BAR";
                        gf.currSP       = sg.Code;
                        gf.treeList     = treesByDBH;
                        gf.fileName     = fileName;
                        gf.currSaleName = currSaleName;
                        gf.ShowDialog();
                    } //  endif
                }     //  end foreach loop
                break;
            }         //  end switch on report
            return;
        }             //  end createGraphs