eLVik

ForestCut

Dec 2nd, 2021
690
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // #define PRINT_LOG
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Data.Objects;
  6.  
  7. using GUTFIRK.ForestManagement.Domain.ModelEntities;
  8. using GUTFIRK.ForestManagement.Domain;
  9. using GUTFIRK.Utils;
  10. using GUTFIRK.ForestManagement.Domain.ReportServiceInterface;
  11. using GUTFIRK.ForestManagement.Domain.ReportServiceInterface.ReportsDescriptions.ForestFund;
  12. using GUTFIRK.ForestManagement.Domain.ReportServiceInterface.ReportsParams;
  13.  
  14. using GUTFIRK.Utils.TemplateSystem;
  15.  
  16. namespace GUTFIRK.ForestManagement.ReportService.ReportsCreators
  17. {
  18.     /*
  19.      * Производит исчисление расчетной лесосеки в соответствии с
  20.      * Приказом № 148 Министерства природных ресурсов от 08 июня 2007 г.
  21.     */
  22.  
  23.     /*
  24.      * Рассчитываются хвойное хозяйство (ель, сосна, лиственница) и мягколиственное хозяйство (береза, осина).
  25.     */
  26.  
  27.     public sealed class ForestCut_ReportCreator : SelectOptionsAdapter
  28.     {
  29.         /// <summary>
  30.         /// Конструктор.
  31.         /// </summary>
  32.         public ForestCut_ReportCreator()
  33.         {
  34.             _description = new ForestCut_ReportDescription();
  35.         }
  36.  
  37.         /// <summary>
  38.         /// Инициализация.
  39.         /// </summary>
  40.         void Init(Dictionary<string, double> _dic1, Dictionary<string, List<ForestCutAgeClassItem>> _dic2, Dictionary<string, List<ForestCut>> _dic3)
  41.         {
  42.             _dic1.Clear();
  43.             _dic2.Clear();
  44.             _dic3.Clear();
  45.  
  46.             for (int bon_id = 1; bon_id <= 3; bon_id++) // обход классов бонитета
  47.             {
  48.                 for (int group_id = 1; group_id <= 3; group_id++) // обход групп леса
  49.                 {
  50.                     for (int hoz_id = 1; hoz_id <= 2; hoz_id++) // обход хозяйств
  51.                     {
  52.                         _dic2.Add(String.Format("G{0}_H{1}_B{2}", group_id, hoz_id, bon_id), new List<ForestCutAgeClassItem>());
  53.  
  54.                         List<ForestCut> list = new List<ForestCut>();
  55.                         list.Add(new ForestCut("Лесосека равномерного пользования"));
  56.                         list.Add(new ForestCut("1-ая возрастная лесосека"));
  57.                         list.Add(new ForestCut("2-ая возрастная лесосека"));
  58.                         list.Add(new ForestCut("Интегральная лесосека"));
  59.  
  60.                         _dic3.Add(String.Format("G{0}_H{1}_B{2}", group_id, hoz_id, bon_id), list);
  61.  
  62.                         _dic1.Add(String.Format("G{0}_H{1}_B{2}_S", group_id, hoz_id, bon_id), 0.0);        // общая площадь покрытых лесом насаждений
  63.                         _dic1.Add(String.Format("G{0}_H{1}_B{2}_M", group_id, hoz_id, bon_id), 0.0);        // общий запас                    
  64.                         _dic1.Add(String.Format("G{0}_H{1}_B{2}_M_LIKV", group_id, hoz_id, bon_id), 0.0);   // ликвидный запас (спелых и перестойных)
  65.                         _dic1.Add(String.Format("G{0}_H{1}_B{2}_M_DEL", group_id, hoz_id, bon_id), 0.0);    // запас деловых стволов (спелых и перестойных)                        
  66.                         _dic1.Add(String.Format("G{0}_H{1}_B{2}_M3_LIKV", group_id, hoz_id, bon_id), 0.0);   // ликвидный запас (приспевающих)                    
  67.                         _dic1.Add(String.Format("G{0}_H{1}_B{2}_M3_DEL", group_id, hoz_id, bon_id), 0.0);    // запас деловых стволов (приспевающих)
  68.  
  69.                         if (bon_id == 1)
  70.                         {
  71.                             _dic1.Add(String.Format("G{0}_H{1}_CUTTING_AGE", group_id, hoz_id), 0.0);
  72.                             _dic1.Add(String.Format("G{0}_H{1}_DURATION", group_id, hoz_id), 0.0);
  73.                         }
  74.  
  75.  
  76.                         for (int ageGroup_id = 1; ageGroup_id <= 5; ageGroup_id++) // обход групп возраста
  77.                         {
  78.                             _dic1.Add(String.Format("G{0}_H{1}_B{2}_A{3}_S", group_id, hoz_id, bon_id, ageGroup_id), 0.0); // площадь по группам возраста.
  79.                             _dic1.Add(String.Format("G{0}_H{1}_B{2}_A{3}_M", group_id, hoz_id, bon_id, ageGroup_id), 0.0); // запас по группам возраста.                        
  80.                         }
  81.  
  82.                         //_dic1.Add(String.Format("G{0}_H{1}_B{2}_A1_С2_S", group_id, hoz_id), 0.0); // площадь молодняков 2-го класса возраста.
  83.  
  84.                     }
  85.                 }
  86.             }
  87.         }
  88.  
  89.         public override object DoCalculations(IReportParams reportParams, Procedure<int> progressCallback)
  90.         {
  91.             CheckParams(reportParams);
  92.            
  93.             #region Private Members
  94.             Dictionary<string, double> _dic1 = new Dictionary<string, double>();
  95.             Dictionary<string, List<ForestCutAgeClassItem>> _dic2 = new Dictionary<string, List<ForestCutAgeClassItem>>();
  96.             Dictionary<string, List<ForestCut>> _dic3 = new Dictionary<string, List<ForestCut>>();
  97.             Comparison<ForestCutAgeClassItem> _comparsion = new Comparison<ForestCutAgeClassItem>(ForestCut_ReportCreator.ComparseForestCutAgeClassItems);
  98.  
  99.             //const double MIN_U = 100000.0;
  100.             //const double MAX_U = -100000.0;
  101.  
  102.             #endregion
  103.  
  104.             #region Переменные
  105.             // Список ассоциаций НСИ за указанный год.
  106.             List<NormativeAssociation> na_list = null;
  107.  
  108.             // Список пород
  109.             List<Stock> stockList = null;
  110.  
  111.             //List<short> distinctNormativeDataList = new List<short>();
  112.  
  113.             var rp = (ForestResourcesReportParams)reportParams;
  114.             var year = (short)rp.SelectOptions.YearOfActualization;
  115.             IList<ForestCutAgeClassItem> list = null, list2 = null, list3 = null;
  116.             #endregion
  117.  
  118.             using (ModelContext context = new ModelContext())
  119.             {
  120.                 na_list = context.NormativeAssociationSet.Where("it.Year = @year", new ObjectParameter("year", year)).Include("NormativeData").Include("Forestry").ToList();
  121.                 stockList = context.StockSet.ToList();
  122.  
  123.  
  124.                 if (na_list.Count == 0)
  125.                     throw new ReportException(rp, "Список нормативных ассоциаций пуст.");
  126.  
  127.                 this.Init(_dic1, _dic2, _dic3); // инициализация словарей.
  128.  
  129.                 var quarterIds = GetQuarterIDs(rp.SelectOptions);
  130.                 double progress_q = quarterIds.Count == 0 ? 0.0 : 90.0 / quarterIds.Count;
  131.                 int progress_counter = 0;
  132.  
  133.                 #region Обход кварталов
  134.                 foreach (var quarterID in quarterIds)
  135.                 {
  136.                     #region Callback
  137.                     progress_counter++;
  138.                     progressCallback((int)(progress_counter * progress_q));
  139.                     #endregion
  140.  
  141.                     var quarter = context.QuarterSet.Include("DivisionalForestry.Forestry").FirstOrDefault(x => x.OID == quarterID);
  142.                     if (quarter == null)
  143.                         continue;
  144.  
  145.                     #region Подгрузка НСИ
  146.                     NormativeAssociation na = na_list.Where(a => a.Forestry.OID == quarter.GetForestry().OID).First();
  147.  
  148.                     // Ошибка может возникнуть в случае, если лесничеству не сопоставлен набор НСИ в указанный год.
  149.                     if (na == null)
  150.                         throw new ReportException(rp, String.Format("Отсутствует набор НСИ для квартала (OID = {0})", quarter.OID));
  151.  
  152.                     #endregion
  153.  
  154.                     #region Вызовы ХП, получение данных на квартальный уровень
  155.                     // Список возрастных характеристик
  156.                     List<vw_QuarterAgeDataItem> vw_AgeDataResult = null; // context.GetMainStockAgeDataOnQuarter(quarter.OID, na.NormativeData.OID, na.CuttingAgeKey, rp.Year).ToList();
  157.  
  158.                     // Список товарных характеристик
  159.                     List<vw_QuarterCommodityItem> vw_CommodityResult = null; // context.GetCommodityItemOnQuarter(quarter.OID, rp.Year, na.CommodityTableKey).ToList();
  160.  
  161.                     // Список общих характеристик
  162.                     List<CommonData> commonDataList = quarter.GetCommonDataList(context, year);
  163.  
  164.                     // Список таксационных характеристик
  165.                     List<TaxData> taxDataList = quarter.GetTaxDataList(context, year);
  166.  
  167.                     int counter = 0; bool success = false;
  168.                     while (!success)
  169.                     {
  170.                         try
  171.                         {
  172.                             counter++;
  173.                             vw_AgeDataResult = context.GetMainStockAgeDataOnQuarter(quarter.OID, na.NormativeData.OID, na.CuttingAgeKey, year).ToList();
  174.                             vw_CommodityResult = context.GetCommodityItemOnQuarter(quarter.OID, year, na.CommodityTableKey).ToList();
  175.                             success = true;
  176.                         }
  177.                         catch
  178.                         {
  179.                             if (counter >= 10)
  180.                                 break;
  181.                         }
  182.                     }
  183.  
  184.                     if (!success)
  185.                         throw new ReportException(rp, "Не удалось выполнить хранимые процедуры \"GetMainStockAgeDataOnQuarter\" и/или \"GetCommodityItemOnQuarter\"");
  186.                     #endregion
  187.  
  188.                     #region Обход общих характеристик
  189.                     foreach (CommonData commonData in commonDataList)
  190.                     {
  191.                         List<TaxData> tax_list = new List<TaxData>(taxDataList.Where(a => a.GetCommonData().OID == commonData.OID));
  192.                         double volume = 0.0;
  193.  
  194.                         foreach (TaxData td in tax_list)
  195.                             volume += td.Volume;
  196.  
  197.  
  198.                         //double volume = commonData.GetTotalVolume(context);
  199.                         vw_QuarterAgeDataItem ageDataItem = vw_AgeDataResult.First(a => a.CommonData_OID == commonData.OID);
  200.  
  201.  
  202.                         // рассматриваются только эксплуатируемые леса, покрытые лесом
  203.  
  204.                         if (ageDataItem.ReturnCode != 0 || ageDataItem.IsExploitable.Value == false)
  205.                             continue;
  206.  
  207.                         // Пункт 7. Исключаются спелые и перестойные насаждения, запас древесины которых на одном гектаре 50 кбм. и менее.
  208.                         if (ageDataItem.AgeGroup_OID >= 4 && volume / commonData.Area <= 50)
  209.                             continue;
  210.  
  211.                         volume *= 0.001; // тыс. кбм.
  212.  
  213.  
  214.                         #region Выбор группы леса, хозяйства и группы возраста
  215.                         Stock stock = stockList.First(a => a.OID == ageDataItem.MainStock_OID.Value);
  216.                         Stock nStock = stock.GetNormativeStock(context);
  217.  
  218.                         if (nStock == null)
  219.                             continue;
  220.  
  221.                         if (commonData.ProtectionCategoryReference.IsLoaded == false)
  222.                             commonData.ProtectionCategoryReference.Load();
  223.  
  224.                         if (commonData.ProtectionCategory.ForestGroupReference.IsLoaded == false)
  225.                             commonData.ProtectionCategory.ForestGroupReference.Load();
  226.  
  227.                         int group_id = commonData.ProtectionCategory.ForestGroup.OID;
  228.                         int ageGroup_id = ageDataItem.AgeGroup_OID.Value;
  229.  
  230.                         int bon_id = 1;
  231.                         if (commonData.BonitetClassReference.IsLoaded == false)
  232.                         {
  233.                             commonData.BonitetClassReference.Load();
  234.                             if (commonData.BonitetClass != null && commonData.BonitetClass.OID >= 9)
  235.                             {
  236.                                 if (commonData.BonitetClass.OID == 9)
  237.                                     bon_id = 2;
  238.                                 else if (commonData.BonitetClass.OID == 10)
  239.                                     bon_id = 3;
  240.                             }
  241.                         }
  242.  
  243.  
  244.  
  245.                         int hoz_id = 2;
  246.  
  247.                         if (nStock.OID == 2 || nStock.OID == 3 || nStock.OID == 5)
  248.                         {
  249.                             hoz_id = 1;
  250.                         }
  251.  
  252.                         list = _dic2[String.Format("G{0}_H{1}_B1", group_id, hoz_id)];
  253.                         list2 = _dic2[String.Format("G{0}_H{1}_B2", group_id, hoz_id)];
  254.                         list3 = _dic2[String.Format("G{0}_H{1}_B3", group_id, hoz_id)];
  255.                         #endregion
  256.  
  257.                         #region Учет возрастов рубки для лесосеки равномерного пользования
  258.  
  259.                         /*
  260.                          * Расчетная лесосека равномерного пользования согласно методике определяется как L = F / U
  261.                          * где:
  262.                          * F - площадь покрытых лесом насаждений
  263.                          * U - возраст рубки
  264.                          * при этом
  265.                          * в лесах 1-ой группы за U принимается верхний предел класса возраста,
  266.                          * в лесах 3-ей группы - нижний предел класса возраста рубки,
  267.                          * в лесах 2-ой группы - срединное значение класса возраста.
  268.                          *
  269.                          * Рубка леса начинается с 4-ой возрастной группы (спелые насаждения)
  270.                          *
  271.                          * Необходимо определить нижний предел возраста рубки и продолжительность
  272.                          * класса возраста в текущем хозяйстве и группе леса.
  273.                          *
  274.                          * Для этого возьмем первую запись ageDataItem
  275.                         */
  276.  
  277.                         if (ageDataItem.AgeGroup_OID.Value >= 4 && _dic1[String.Format("G{0}_H{1}_CUTTING_AGE", group_id, hoz_id)] == 0.0)
  278.                         {
  279.                             _dic1[String.Format("G{0}_H{1}_CUTTING_AGE", group_id, hoz_id)] = ageDataItem.CuttingAge.Value;
  280.                             _dic1[String.Format("G{0}_H{1}_DURATION", group_id, hoz_id)] = ageDataItem.AgeClassDuration.Value;
  281.                         }
  282.  
  283.                         //if (ageDataItem.AgeGroup_OID.Value == 5 && _dic1[String.Format("G{0}_H{1}_A5_CUTTING_AGE", group_id, hoz_id)] == 0.0)
  284.                         //{
  285.                         //    _dic1[String.Format("G{0}_H{1}_A5_CUTTING_AGE", group_id, hoz_id)] = ageDataItem.CuttingAge.Value;
  286.                         //    _dic1[String.Format("G{0}_H{1}_A5_DURATION", group_id, hoz_id)] = ageDataItem.AgeClassDuration.Value;
  287.                         //}
  288.  
  289.                         #endregion
  290.  
  291.                         // подсчет общих площади и запаса
  292.                         _dic1[String.Format("G{0}_H{1}_B1_S", group_id, hoz_id)] += commonData.Area;
  293.                         _dic1[String.Format("G{0}_H{1}_B1_M", group_id, hoz_id)] += volume;
  294.  
  295.                         _dic1[String.Format("G{0}_H{1}_B1_A{2}_S", group_id, hoz_id, ageGroup_id)] += commonData.Area;
  296.                         _dic1[String.Format("G{0}_H{1}_B1_A{2}_M", group_id, hoz_id, ageGroup_id)] += volume;
  297.  
  298.                         if (bon_id > 1)
  299.                         {
  300.                             _dic1[String.Format("G{0}_H{1}_B{2}_S", group_id, hoz_id, bon_id)] += commonData.Area;
  301.                             _dic1[String.Format("G{0}_H{1}_B{2}_M", group_id, hoz_id, bon_id)] += volume;
  302.  
  303.                             _dic1[String.Format("G{0}_H{1}_B{2}_A{3}_S", group_id, hoz_id, bon_id, ageGroup_id)] += commonData.Area;
  304.                             _dic1[String.Format("G{0}_H{1}_B{2}_A{3}_M", group_id, hoz_id, bon_id, ageGroup_id)] += volume;
  305.                         }
  306.  
  307.                         // Учет площади молодняков второго класса возраста
  308.                         //if (ageGroup_id == 1 && ageDataItem.AgeClass.Value == 2)
  309.                         //{
  310.                         //    _dic1[String.Format("G{0}_H{1}_A1_С2_S", group_id, hoz_id)] += commonData.Area;
  311.                         //}
  312.  
  313.                         if (ageGroup_id == 2) // Деление средневозрастных по классам возраста
  314.                         {
  315.                             AddForestCutAgeClassItem(list, ageDataItem.AgeClass.Value, commonData.Area, volume);
  316.                             if (bon_id == 2)
  317.                                 AddForestCutAgeClassItem(list2, ageDataItem.AgeClass.Value, commonData.Area, volume);
  318.  
  319.                             if (bon_id == 3)
  320.                                 AddForestCutAgeClassItem(list3, ageDataItem.AgeClass.Value, commonData.Area, volume);
  321.                         }
  322.  
  323.                         #region Ликвид и деловая
  324.                         // Расчет ликвида и деловой для спелых и перестойных.
  325.                         if (ageGroup_id >= 4)
  326.                         {
  327.                             foreach (TaxData td in tax_list)
  328.                             {
  329.                                 if (td.Volume == 0.0 || td.Stock == null)
  330.                                     continue;
  331.  
  332.                                 double v = 0.001 * td.Volume;
  333.                                 vw_QuarterCommodityItem commodityItem = vw_CommodityResult.First(a => a.TaxData_OID == td.OID);
  334.                                 if (commodityItem.ReturnCode.Value == 0)
  335.                                 {
  336.                                     _dic1[String.Format("G{0}_H{1}_B1_M_LIKV", group_id, hoz_id)] += commodityItem.GetLiquidVolume(v);
  337.                                     _dic1[String.Format("G{0}_H{1}_B1_M_DEL", group_id, hoz_id)] += commodityItem.GetTimberVolume(v);
  338.  
  339.                                     if (bon_id > 1)
  340.                                     {
  341.                                         _dic1[String.Format("G{0}_H{1}_B{2}_M_LIKV", group_id, hoz_id, bon_id)] += commodityItem.GetLiquidVolume(v);
  342.                                         _dic1[String.Format("G{0}_H{1}_B{2}_M_DEL", group_id, hoz_id, bon_id)] += commodityItem.GetTimberVolume(v);
  343.                                     }
  344.                                 }
  345.                             }
  346.                         }
  347.  
  348.                         // ... и отдельно для приспевающих
  349.                         if (ageGroup_id == 3)
  350.                         {
  351.                             foreach (TaxData td in tax_list)
  352.                             {
  353.                                 if (td.Volume == 0.0 || td.Stock == null)
  354.                                     continue;
  355.                                 double v = 0.001 * td.Volume;
  356.                                 vw_QuarterCommodityItem commodityItem = vw_CommodityResult.First(a => a.TaxData_OID == td.OID);
  357.                                 if (commodityItem.ReturnCode.Value == 0)
  358.                                 {
  359.                                     _dic1[String.Format("G{0}_H{1}_B1_M3_LIKV", group_id, hoz_id)] += commodityItem.GetLiquidVolume(v);
  360.                                     _dic1[String.Format("G{0}_H{1}_B1_M3_DEL", group_id, hoz_id)] += commodityItem.GetTimberVolume(v);
  361.                                     if (bon_id > 1)
  362.                                     {
  363.                                         _dic1[String.Format("G{0}_H{1}_B{2}_M3_LIKV", group_id, hoz_id, bon_id)] += commodityItem.GetLiquidVolume(v);
  364.                                         _dic1[String.Format("G{0}_H{1}_B{2}_M3_DEL", group_id, hoz_id, bon_id)] += commodityItem.GetTimberVolume(v);
  365.                                     }
  366.                                 }
  367.                             }
  368.                         }
  369.                         #endregion
  370.  
  371.                     } // foreach commonData
  372.                     #endregion
  373.  
  374.                     #region Detaching
  375.                     foreach (TaxData taxData in taxDataList)
  376.                         context.Detach(taxData);
  377.  
  378.                     foreach (CommonData commonData in commonDataList)
  379.                         context.Detach(commonData);
  380.  
  381.                     foreach (vw_QuarterAgeDataItem ageDataItem in vw_AgeDataResult)
  382.                         context.Detach(ageDataItem);
  383.  
  384.                     foreach (vw_QuarterCommodityItem commodityItem in vw_CommodityResult)
  385.                         context.Detach(commodityItem);
  386.  
  387.                     context.Detach(quarter);
  388.                     #endregion
  389.                 } // foreach quarter
  390.             } // using ModelContext
  391.                 #endregion
  392.  
  393.             #region Вывод в лог
  394. #if PRINT_LOG
  395.             Program.LogSystem.Info("РАСЧЕТНАЯ ЛЕСОСЕКА - СОСТОЯНИЕ _dic1");
  396.             string[] dicKeys = new string[_dic1.Keys.Count];
  397.             _dic1.Keys.CopyTo(dicKeys, 0);
  398.             foreach (string key in dicKeys)
  399.                 Program.LogSystem.Info(String.Format("{0} = {1}", key, _dic1[key]));
  400. #endif
  401.             #endregion
  402.  
  403.             #region Расчетные лесосеки
  404.             for (int bon_id = 1; bon_id <= 3; bon_id++)
  405.             {
  406.                 for (int group_id = 1; group_id <= 3; group_id++)
  407.                 {
  408.                     for (int hoz_id = 1; hoz_id <= 2; hoz_id++)
  409.                     {
  410.                         int K = hoz_id == 1 ? 20 : 10; // продолжительность класса возраста
  411.                         string key = String.Format("G{0}_H{1}_B{2}", group_id, hoz_id, bon_id);
  412.                         double f_mld = _dic1[key + "_A1_S"];     // площадь молодняков
  413.                         //double f_mld2 = _dic1[key + "_A1_С2_S"]; // площадь молодняков 2-го класса возраста
  414.                         double f_sred = _dic1[key + "_A2_S"];    // площадь средневозрастных
  415.                         double f_prisp = _dic1[key + "_A3_S"];   // площадь приспевающих
  416.                         double f_spprs = _dic1[key + "_A4_S"] + _dic1[key + "_A5_S"]; // площадь спелых и перестойных.
  417.                         double f_sp = _dic1[key + "_A4_S"]; // площадь спелых
  418.                         double f_total = _dic1[key + "_S"]; // общая площадь
  419.                         double x = 0.0;
  420.                         bool flag = false;
  421.  
  422.                         if (f_total == 0.0)
  423.                             continue; // а чего считать-то?
  424.  
  425.                         double m_spprs = _dic1[key + "_A4_M"] + _dic1[key + "_A5_M"];
  426.                         double m_prisp = _dic1[key + "_A3_M"];
  427.  
  428.                         // Подсчет запасов на 1 га
  429.                         // для спелых и перестойных
  430.                         double mga_spprs_total = m_spprs / f_total;
  431.                         double mga_spprs_likv = _dic1[key + "_M_LIKV"] / f_total;
  432.                         double mga_spprs_del = _dic1[key + "_M_DEL"] / f_total;
  433.  
  434.                         // для приспевающих
  435.  
  436.                         double mga_prisp_total = m_prisp / f_total;
  437.                         double mga_prisp_likv = _dic1[key + "_M3_LIKV"] / f_total;
  438.                         double mga_prisp_del = _dic1[key + "_M3_DEL"] / f_total;
  439.  
  440.  
  441.                         // Сортировка классов возраста
  442.                         _dic2[key].Sort(_comparsion);
  443.                         list = _dic2[key];
  444.                         int k = list.Count;
  445.  
  446.                         #region Коэффициенты для определения РЛ по запасу
  447.                         if (f_prisp + f_spprs > 0 && f_sp == 0.0)
  448.                             flag = true;
  449.                         else if (f_prisp + f_spprs == 0.0 && f_sp == 0.0)
  450.                             flag = false;
  451.                         else
  452.                             flag = ((f_prisp + f_spprs) / f_sp >= 2.0);
  453.  
  454.                         double k_total, k_likv, k_del;
  455.                         if (flag && mga_prisp_total > mga_spprs_total)
  456.                         {
  457.                             k_total = 0.5 * (mga_prisp_total + mga_spprs_total);
  458.                             k_likv = 0.5 * (mga_prisp_likv + mga_spprs_likv);
  459.                             k_del = 0.5 * (mga_prisp_del + mga_spprs_del);
  460.                         }
  461.                         else
  462.                         {
  463.                             k_total = mga_spprs_total;
  464.                             k_likv = mga_spprs_likv;
  465.                             k_del = mga_spprs_del;
  466.                         }
  467.                         #endregion
  468.  
  469.                         #region Равномерное пользование
  470.  
  471.                         double cuttingAge = 0.0;
  472.                         double duration = 0.0;
  473.                         //flag = false; // флаг расчета (если false, то РЛ рассчитана не будет)
  474.                         // Нашли ли мы класс возраста рубки в 4-ой группе возраста
  475.                         if (_dic1[String.Format("G{0}_H{1}_CUTTING_AGE", group_id, hoz_id)] != 0.0)
  476.                         {
  477.                             cuttingAge = _dic1[String.Format("G{0}_H{1}_CUTTING_AGE", group_id, hoz_id)];
  478.                             duration = _dic1[String.Format("G{0}_H{1}_DURATION", group_id, hoz_id)];
  479.  
  480.                             switch (group_id)
  481.                             {
  482.                                 case 1:
  483.                                     x = cuttingAge + duration - 1;
  484.                                     break;
  485.                                 case 2:
  486.                                     x = (2.0 * cuttingAge + duration - 1) / 2.0;
  487.                                     break;
  488.                                 default:
  489.                                     x = cuttingAge;
  490.                                     break;
  491.                             }
  492.                             if (x != 0.0)
  493.                                 _dic3[key][0].Area = f_total / x;
  494.  
  495.                         }
  496.  
  497.                         #endregion
  498.  
  499.                         #region 1-ая возрастная
  500.                         _dic3[key][1].Area = (f_prisp + f_spprs) / (2 * K);
  501.                         #endregion
  502.  
  503.                         #region 2-ая возрастная
  504.                         int n = 3; // коэффициент при K в знаменателе формулы
  505.                         x = 0.0;
  506.                         if (k == 0)
  507.                         {
  508.                             x = 0.0;
  509.                         }
  510.                         else if (k <= 3)
  511.                         {
  512.                             // в расчете один старший класс возраста.
  513.                             x += list[k - 1].Area;
  514.                         }
  515.                         else
  516.                         {
  517.                             // в расчете два старших класса возраста.
  518.                             n = 4;
  519.                             x += list[k - 1].Area + list[k - 2].Area;
  520.                         }
  521.  
  522.                         _dic3[key][2].Area = (x + f_prisp + f_spprs) / (n * K);
  523.  
  524.                         //double y = x; // Запомним площадь средневозрастных, включенных в расчет. Она потребуется при расчете интегральной
  525.                         #endregion
  526.  
  527.                         #region Интегральная
  528.                         // интегральная (!!!)      
  529.                         if (hoz_id == 1)
  530.                         {
  531.                             // K = 20
  532.                             if (k >= 3)
  533.                             {
  534.                                 x = 0.0; // площадь средневозрастных кроме двух старших классов возраста.
  535.                                 for (int i = 0; i < k - 2; i++)
  536.                                     x += list[i].Area;
  537.  
  538.                                 _dic3[key][3].Area = (0.2 * (f_mld + x) + 0.6 * list[k - 2].Area + list[k - 1].Area + 1.4 * f_prisp + 1.8 * f_spprs) * 0.01;
  539.                             }
  540.                             else if (k <= 1) // 0 мы тоже должны рассмотреть.
  541.                             {
  542.                                 // !!! В методике расчета не рассматривается случай, когда к средневозрастным насаждениям отнесено два класса возраста.
  543.                                 // может f_mld2 (?)
  544.                                 _dic3[key][3].Area = (0.2 * f_mld + 0.6 * f_sred + 1.4 * f_prisp + 1.8 * f_spprs) * 0.01;
  545.                             }
  546.                             else // k == 2
  547.                             {
  548.                                 _dic3[key][3].Area = (0.2 * f_mld + 0.6 * list[k - 2].Area + list[k - 1].Area + 1.4 * f_prisp + 1.8 * f_spprs) * 0.01;
  549.                             }
  550.  
  551.                         }
  552.                         else
  553.                         {
  554.                             // K = 10
  555.                             if (k >= 4)
  556.                             {
  557.                                 x = 0.0; // площадь средневозрастных кроме двух старших классов возраста.
  558.                                 for (int i = 0; i < k - 2; i++)
  559.                                     x += list[i].Area;
  560.  
  561.                                 _dic3[key][3].Area = (0.4 * x + 1.2 * list[k - 2].Area + 2.0 * list[k - 1].Area + 2.8 * f_prisp + 3.6 * f_spprs) * 0.01;
  562.  
  563.                             }
  564.                             else if (k == 0)
  565.                             {
  566.                                 _dic3[key][3].Area = (2.8 * f_prisp + 3.6 * f_spprs) * 0.01;
  567.                             }
  568.                             else if (k == 2 || k == 3)
  569.                             {
  570.                                 x = 0.0; // площадь средневозрастных кроме двух старших классов возраста.
  571.                                 for (int i = 0; i < k - 2; i++)
  572.                                     x += list[i].Area;
  573.  
  574.                                 _dic3[key][3].Area = (0.4 * f_mld + 1.2 * list[k - 2].Area + 2.0 * list[k - 1].Area + 2.8 * f_prisp + 3.6 * f_spprs) * 0.01;
  575.                             }
  576.                             else if (k == 1)
  577.                             {
  578.                                 _dic3[key][3].Area = (0.4 * f_mld + 1.2 * f_sred + 2.8 * f_prisp + 3.6 * f_spprs) * 0.01;
  579.                             }
  580.                         }
  581.                         #endregion
  582.  
  583.                         #region Пересчет по запасам
  584.                         for (int ls_id = 0; ls_id <= 3; ls_id++)
  585.                         {
  586.                             /*
  587.                             _dic3[key][ls_id].StemVolume = _dic3[key][ls_id].Area * mga_spprs_total;
  588.                             _dic3[key][ls_id].TimberVolume = _dic3[key][ls_id].Area * mga_spprs_del;
  589.                             _dic3[key][ls_id].LiquidVolume = _dic3[key][ls_id].Area * mga_spprs_likv;
  590.                             */
  591.                             _dic3[key][ls_id].TotalVolume = _dic3[key][ls_id].Area * k_total;
  592.                             _dic3[key][ls_id].TimberVolume = _dic3[key][ls_id].Area * k_del;
  593.                             _dic3[key][ls_id].LiquidVolume = _dic3[key][ls_id].Area * k_likv;
  594.                         }
  595.                         #endregion
  596.  
  597.                     }
  598.                 }
  599.             }
  600.             #endregion
  601.  
  602.             return new ForestCut_ReportData(_dic1, _dic2, _dic3, reportParams.Name);
  603.  
  604.         }
  605.  
  606.         public override void CreateDocument(object obj, string formatKey, Procedure<int> progressCallback, string templateFolder, System.IO.Stream outputStream)
  607.         {
  608.             #region Печать
  609.             ForestCut_ReportData rd = (ForestCut_ReportData)obj;
  610.             TemplateProcessor tp = new TemplateProcessor();
  611.             string emptyValue = formatKey == Program.HTML_FORMAT_KEY ? "&nbsp;" : String.Empty;
  612.             bool usNumberFormat = formatKey == Program.HTML_FORMAT_KEY ? false : true;
  613.  
  614.  
  615.             tp.Parameters.Add(new HtmlEncodedTemplateParameter("TITLE"));
  616.             tp.Parameters.Add(new HtmlEncodedTemplateParameter("REPORT_NAME", emptyValue, rd.ReportName));
  617.             tp.Parameters.Add(new TemplateParameter("CREATION_DATE", DateTime.Now.ToShortDateString()));
  618.             tp.Parameters.Add(new TemplateParameter("ROWS_CONTENT"));
  619.             tp.Parameters.Add(new NumberTemplateParameter("AREA", emptyValue, usNumberFormat));
  620.             tp.Parameters.Add(new NumberTemplateParameter("TOTAL_V", emptyValue, usNumberFormat));
  621.             tp.Parameters.Add(new NumberTemplateParameter("TIMBER_V", emptyValue, usNumberFormat));
  622.             tp.Parameters.Add(new NumberTemplateParameter("LIKV_V", emptyValue, usNumberFormat));
  623.             tp.Parameters.Add(new NumberTemplateParameter("YEAR_COUNT", emptyValue, usNumberFormat));
  624.  
  625.             //templateFolder += _description.Key + "\\" + formatKey + "\\";
  626.  
  627.             double[,] tempArray = new double[4, 5];
  628.             double[,] tempArray2 = new double[4, 5];
  629.  
  630.             for (int group_id = 1; group_id <= 3; group_id++)
  631.             {
  632.                 if (this.GetArea(group_id, rd.Dic3) == 0.0)
  633.                     continue;   // пустая группа лесов
  634.  
  635.                 for (int i = 0; i < 4; i++)
  636.                 {
  637.                     for (int j = 0; j < 5; j++)
  638.                     {
  639.                         tempArray[i, j] = 0.0;
  640.                         //tempArray2[i, j] = 0.0;
  641.                     }
  642.                 }
  643.  
  644.                 tp.Parameters["TITLE"].Value = "ГРУППА ЛЕСОВ № " + group_id.ToString();
  645.                 tp.Parameters["ROWS_CONTENT"].Value += tp.ProcessFile(templateFolder + "boldtitlerow.tpl");
  646.  
  647.                 for (int hoz_id = 1; hoz_id <= 2; hoz_id++)
  648.                 {
  649.                     if (this.GetArea(group_id, hoz_id, rd.Dic3) == 0.0)
  650.                         continue;
  651.  
  652.                     string hozName = hoz_id == 1 ? "ХВОЙНОЕ ХОЗЯЙСТВО" : "МЯГКОЛИСТВЕННОЕ ХОЗЯЙСТВО";
  653.                     tp.Parameters["TITLE"].Value = hozName;
  654.                     tp.Parameters["ROWS_CONTENT"].Value += tp.ProcessFile(templateFolder + "titlerow.tpl");
  655.  
  656.                     List<ForestCut> list = rd.Dic3[String.Format("G{0}_H{1}_B1", group_id, hoz_id)];
  657.                     List<ForestCut> list2 = rd.Dic3[String.Format("G{0}_H{1}_B2", group_id, hoz_id)];
  658.                     List<ForestCut> list3 = rd.Dic3[String.Format("G{0}_H{1}_B3", group_id, hoz_id)];
  659.  
  660.                     for (int ls_id = 0; ls_id < list.Count; ls_id++)
  661.                     {
  662.                         ForestCut fc = list[ls_id];
  663.                         if (fc.Area == 0.0)
  664.                             continue;
  665.  
  666.                         tp.Parameters["TITLE"].Value = fc.Name;
  667.                         tp.Parameters["ROWS_CONTENT"].Value += tp.ProcessFile(templateFolder + "titlerow.tpl");
  668.  
  669.                         tp.Parameters["AREA"].Value = fc.Area;
  670.                         tp.Parameters["TOTAL_V"].Value = fc.TotalVolume;
  671.                         tp.Parameters["TIMBER_V"].Value = fc.TimberVolume;
  672.                         tp.Parameters["LIKV_V"].Value = fc.LiquidVolume;
  673.  
  674.                         tempArray[ls_id, 0] += fc.Area;
  675.                         tempArray[ls_id, 1] += fc.TotalVolume;
  676.                         tempArray[ls_id, 2] += fc.TimberVolume;
  677.                         tempArray[ls_id, 3] += fc.LiquidVolume;
  678.  
  679.                         tempArray2[ls_id, 0] += fc.Area;
  680.                         tempArray2[ls_id, 1] += fc.TotalVolume;
  681.                         tempArray2[ls_id, 2] += fc.TimberVolume;
  682.                         tempArray2[ls_id, 3] += fc.LiquidVolume;
  683.  
  684.                         double mExpl = rd.Dic1[String.Format("G{0}_H{1}_B1_A4_M", group_id, hoz_id)] + rd.Dic1[String.Format("G{0}_H{1}_B1_A5_M", group_id, hoz_id)];
  685.                         tempArray[ls_id, 4] += mExpl;
  686.                         tempArray2[ls_id, 4] += mExpl;
  687.  
  688.                         double year = fc.TotalVolume == 0.0 ? 0.0 : mExpl / fc.TotalVolume;
  689.  
  690.                         tp.Parameters["YEAR_COUNT"].Value = year;
  691.  
  692.                         tp.Parameters["AREA"].Value = fc.Area;
  693.                         tp.Parameters["TOTAL_V"].Value = fc.TotalVolume;
  694.                         tp.Parameters["TIMBER_V"].Value = fc.TimberVolume;
  695.                         tp.Parameters["LIKV_V"].Value = fc.LiquidVolume;
  696.  
  697.                         tp.Parameters["ROWS_CONTENT"].Value += tp.ProcessFile(templateFolder + "valuerow.tpl");
  698.  
  699.                     }
  700.  
  701.                     #region Вывод по бонитетам
  702.                     for (int bon_id = 2; bon_id <= 3; bon_id++)
  703.                     {
  704.                         if (this.GetArea(group_id, hoz_id, bon_id, rd.Dic3) > 0)
  705.                         {
  706.                             string bonName = bon_id == 2 ? " (Класс бонитета: 5-А)" : " (Класс бонитета: 5-Б)";
  707.                             tp.Parameters["TITLE"].Value = hozName + bonName;
  708.                             tp.Parameters["ROWS_CONTENT"].Value += tp.ProcessFile(templateFolder + "titlerow.tpl");
  709.  
  710.                             for (int ls_id = 0; ls_id < 4; ls_id++)
  711.                             {
  712.                                 ForestCut fc = bon_id == 2 ? list2[ls_id] : list3[ls_id];
  713.                                 if (fc.Area == 0.0)
  714.                                     continue;
  715.  
  716.                                 tp.Parameters["TITLE"].Value = rd.Dic3["G1_H1_B1"][ls_id].Name;
  717.                                 tp.Parameters["ROWS_CONTENT"].Value += tp.ProcessFile(templateFolder + "titlerow.tpl");
  718.  
  719.                                 tp.Parameters["AREA"].Value = fc.Area;
  720.                                 tp.Parameters["TOTAL_V"].Value = fc.TotalVolume;
  721.                                 tp.Parameters["TIMBER_V"].Value = fc.TimberVolume;
  722.                                 tp.Parameters["LIKV_V"].Value = fc.LiquidVolume;
  723.  
  724.                                 double mExpl = rd.Dic1[String.Format("G{0}_H{1}_B{2}_A4_M", group_id, hoz_id, bon_id)] + rd.Dic1[String.Format("G{0}_H{1}_B{2}_A5_M", group_id, hoz_id, bon_id)];
  725.                                 double year = fc.TotalVolume == 0.0 ? 0.0 : mExpl / fc.TotalVolume;
  726.  
  727.                                 tp.Parameters["YEAR_COUNT"].Value = year;
  728.  
  729.                                 tp.Parameters["ROWS_CONTENT"].Value += tp.ProcessFile(templateFolder + "valuerow.tpl");
  730.                             }
  731.  
  732.                         }
  733.                     }
  734.                     #endregion
  735.                 }
  736.  
  737.                 #region ИТОГО ПО ГРУППЕ
  738.                 // Добавление итоговой строки (Хвойное + Мягколиственное)
  739.                 tp.Parameters["TITLE"].Value = "ИТОГО ПО ГРУППЕ";
  740.                 tp.Parameters["ROWS_CONTENT"].Value += tp.ProcessFile(templateFolder + "titlerow.tpl");
  741.  
  742.                 for (int ls_id = 0; ls_id < 4; ls_id++)
  743.                 {
  744.                     tp.Parameters["TITLE"].Value = rd.Dic3["G1_H1_B1"][ls_id].Name;
  745.                     tp.Parameters["ROWS_CONTENT"].Value += tp.ProcessFile(templateFolder + "titlerow.tpl");
  746.  
  747.                     tp.Parameters["AREA"].Value = tempArray[ls_id, 0];
  748.                     tp.Parameters["TOTAL_V"].Value = tempArray[ls_id, 1];
  749.                     tp.Parameters["TIMBER_V"].Value = tempArray[ls_id, 2];
  750.                     tp.Parameters["LIKV_V"].Value = tempArray[ls_id, 3];
  751.  
  752.                     double year = tempArray[ls_id, 1] == 0.0 ? 0.0 : tempArray[ls_id, 4] / tempArray[ls_id, 1];
  753.                     tp.Parameters["YEAR_COUNT"].Value = year;
  754.  
  755.                     tp.Parameters["ROWS_CONTENT"].Value += tp.ProcessFile(templateFolder + "valuerow.tpl");
  756.                 }
  757.                 #endregion
  758.             }
  759.  
  760.             #region ИТОГО ПО ВСЕМ ГРУППАМ
  761.             tp.Parameters["TITLE"].Value = "ИТОГО ПО ВСЕМ ГРУППАМ";
  762.             tp.Parameters["ROWS_CONTENT"].Value += tp.ProcessFile(templateFolder + "boldtitlerow.tpl");
  763.  
  764.             for (int ls_id = 0; ls_id < 4; ls_id++)
  765.             {
  766.                 tp.Parameters["TITLE"].Value = rd.Dic3["G1_H1_B1"][ls_id].Name;
  767.                 tp.Parameters["ROWS_CONTENT"].Value += tp.ProcessFile(templateFolder + "titlerow.tpl");
  768.  
  769.                 tp.Parameters["AREA"].Value = tempArray2[ls_id, 0];//.ToString("0.#", ci.NumberFormat);
  770.                 tp.Parameters["TOTAL_V"].Value = tempArray2[ls_id, 1];//.ToString("0.#", ci.NumberFormat);
  771.                 tp.Parameters["TIMBER_V"].Value = tempArray2[ls_id, 2];//.ToString("0.#", ci.NumberFormat);
  772.                 tp.Parameters["LIKV_V"].Value = tempArray2[ls_id, 3];//.ToString("0.#", ci.NumberFormat);
  773.  
  774.                 double year = tempArray[ls_id, 1] == 0.0 ? 0.0 : tempArray2[ls_id, 4] / tempArray2[ls_id, 1];
  775.                 tp.Parameters["YEAR_COUNT"].Value = year;//.ToString("0.#", ci.NumberFormat);
  776.  
  777.                 tp.Parameters["ROWS_CONTENT"].Value += tp.ProcessFile(templateFolder + "valuerow.tpl");
  778.             }
  779.             #endregion
  780.  
  781.  
  782.             tp.ProcessFileToStream(outputStream, templateFolder + "header.tpl");
  783.             #endregion
  784.         }
  785.  
  786.         /// <summary>
  787.         /// Возвращает суммарную площадь всех лесосек в указанной группе лесов.
  788.         /// </summary>
  789.         /// <param name="group_id"></param>
  790.         /// <returns></returns>
  791.         private double GetArea(int group_id, Dictionary<string, List<ForestCut>> dic3)
  792.         {
  793.             double result = 0.0;
  794.             for (int hoz_id = 1; hoz_id <= 2; hoz_id++)
  795.             {
  796.                 List<ForestCut> list = dic3[String.Format("G{0}_H{1}_B1", group_id, hoz_id)];
  797.                 foreach (ForestCut fc in list)
  798.                     result += fc.Area;
  799.             }
  800.             return result;
  801.         }
  802.  
  803.         private double GetArea(int group_id, int hoz_id, Dictionary<string, List<ForestCut>> dic3)
  804.         {
  805.             double result = 0.0;
  806.             List<ForestCut> list = dic3[String.Format("G{0}_H{1}_B1", group_id, hoz_id)];
  807.             foreach (ForestCut fc in list)
  808.                 result += fc.Area;
  809.             return result;
  810.         }
  811.  
  812.         private double GetArea(int group_id, int hoz_id, int bon_id, Dictionary<string, List<ForestCut>> dic3)
  813.         {
  814.             double result = 0.0;
  815.             List<ForestCut> list = dic3[String.Format("G{0}_H{1}_B{2}", group_id, hoz_id, bon_id)];
  816.             foreach (ForestCut fc in list)
  817.                 result += fc.Area;
  818.             return result;
  819.  
  820.         }
  821.  
  822.         private static void AddForestCutAgeClassItem(IList<ForestCutAgeClassItem> list, short ageClass, double area, double volume)
  823.         {
  824.             ForestCutAgeClassItem item = null;
  825.             try
  826.             {
  827.                 item = list.First(a => ageClass == a.AgeClass);
  828.                 item.Area += area;
  829.                 item.Volume += volume;
  830.             }
  831.             catch
  832.             {
  833.                 list.Add(new ForestCutAgeClassItem(ageClass, area, volume));
  834.             }
  835.         }
  836.  
  837.         /// <summary>
  838.         /// Метод сравнения двух элементов ForestCutAgeClassItem по классу возраста.
  839.         /// </summary>
  840.         /// <param name="x"></param>
  841.         /// <param name="y"></param>
  842.         /// <returns></returns>
  843.         private static int ComparseForestCutAgeClassItems(ForestCutAgeClassItem x, ForestCutAgeClassItem y)
  844.         {
  845.             return x.AgeClass.CompareTo(y.AgeClass);
  846.         }
  847.  
  848.         #region Внутренние классы
  849.         /// <summary>
  850.         /// Класс для подсчета площадей и запасов средневозрастных насаждений в разрезе классов возраста.
  851.         /// </summary>
  852.         private class ForestCutAgeClassItem
  853.         {
  854.             double _area = 0.0;
  855.             double _volume = 0.0;
  856.             short _ageClass = 0;
  857.  
  858.             public double Area
  859.             {
  860.                 get { return _area; }
  861.                 set { _area = value; }
  862.             }
  863.  
  864.             public double Volume
  865.             {
  866.                 get { return _volume; }
  867.                 set { _volume = value; }
  868.             }
  869.  
  870.             public short AgeClass
  871.             {
  872.                 get { return _ageClass; }
  873.                 set { _ageClass = value; }
  874.             }
  875.  
  876.  
  877.  
  878.             public ForestCutAgeClassItem(short ageClass, double area, double volume)
  879.             {
  880.                 _area = area;
  881.                 _volume = volume;
  882.                 _ageClass = ageClass;
  883.             }
  884.  
  885.             public ForestCutAgeClassItem()
  886.             {
  887.             }
  888.         }
  889.  
  890.         private class ForestCut
  891.         {
  892.             string _name = String.Empty;
  893.  
  894.             public string Name
  895.             {
  896.                 get { return _name; }
  897.                 set { _name = value; }
  898.             }
  899.             double _area = 0.0;
  900.  
  901.             public double Area
  902.             {
  903.                 get { return _area; }
  904.                 set { _area = value; }
  905.             }
  906.             double _totalVolume = 0.0;
  907.  
  908.             public double TotalVolume
  909.             {
  910.                 get { return _totalVolume; }
  911.                 set { _totalVolume = value; }
  912.             }
  913.             double _liquidVolume = 0.0;
  914.  
  915.             public double LiquidVolume
  916.             {
  917.                 get { return _liquidVolume; }
  918.                 set { _liquidVolume = value; }
  919.             }
  920.             double _timberVolume = 0.0;
  921.  
  922.             public double TimberVolume
  923.             {
  924.                 get { return _timberVolume; }
  925.                 set { _timberVolume = value; }
  926.             }
  927.  
  928.             //double _explVolume = 0.0;
  929.  
  930.             //public double ExplVolume
  931.             //{
  932.             //    get { return _explVolume; }
  933.             //    set { _explVolume = value; }
  934.             //}
  935.  
  936.  
  937.             //public double YearCount
  938.             //{
  939.             //    get
  940.             //    {
  941.             //        if
  942.             //    }
  943.             //}
  944.  
  945.             public ForestCut(string name)
  946.             {
  947.                 _name = name;
  948.             }
  949.  
  950.         }
  951.  
  952.         /// <summary>
  953.         /// Вспомогательный класс для передачи результатов расчетов
  954.         /// </summary>
  955.         private class ForestCut_ReportData
  956.         {
  957.             public Dictionary<string, double> Dic1 { get; set; }
  958.  
  959.             public Dictionary<string, List<ForestCutAgeClassItem>> Dic2 { get; set; }
  960.  
  961.             public Dictionary<string, List<ForestCut>> Dic3 { get; set; }
  962.  
  963.             //Название отчета
  964.             public string ReportName { get; set; }
  965.  
  966.             public DateTime Date { get; set; }
  967.  
  968.             /// <summary>
  969.             /// Конструкторы
  970.             /// </summary>
  971.             /// <param name="form1RowsList"></param>
  972.             /// <param name="distinctCuttingAgesList"></param>
  973.             /// <param name="distinctStocksList"></param>
  974.             /// <param name="distinctNormativeDataList"></param>
  975.             /// <param name="array"></param>
  976.             public ForestCut_ReportData(Dictionary<string, double> _dic1, Dictionary<string, List<ForestCutAgeClassItem>> _dic2, Dictionary<string, List<ForestCut>> _dic3, string reportName)
  977.             {
  978.                 Dic1 = _dic1;
  979.                 Dic2 = _dic2;
  980.                 Dic3 = _dic3;
  981.                 ReportName = reportName;
  982.             }
  983.  
  984.             public ForestCut_ReportData()
  985.             {
  986.             }
  987.         }
  988.  
  989.         #endregion
  990.     }
  991. }
  992.  
RAW Paste Data