/// <summary> /// Creates a new instance. /// </summary> /// <param name="site">The prescription that just finished its repeat harvest</param> public Args(AppliedPrescription prescription, ManagementArea mgmtArea, uint repeatNumber, bool lastHarvest) { Prescription = prescription; MgmtArea = mgmtArea; RepeatNumber = repeatNumber; LastHarvest = lastHarvest; }
/// <summary> /// Signals that a prescription is finished with a repeat step /// </summary> public static void OnRepeatHarvestFinished(object sender, AppliedPrescription prescription, ManagementArea mgmtArea, uint repeatNumber, bool lastHarvest) { if (RepeatPrescriptionFinishedEvent != null) { RepeatPrescriptionFinishedEvent(sender, new RepeatHarvestPrescriptionFinishedEvent.Args(prescription, mgmtArea, repeatNumber, lastHarvest)); } }
//--------------------------------------------------------------------- /// <summary> /// Harvest the area's stands according to its prescriptions. /// </summary> public void HarvestStands() { //Model.Core.UI.WriteLine("BaseHarvest: ManagementArea.cs: HarvestStands: Harvesting management area {0} ...", mapCode); //initialize each stand for harvesting (setting harvested = false) foreach (Stand stand in stands) { stand.InitializeForHarvesting(); } // Determine which are prescriptions are active. List <AppliedPrescription> activePrescriptions = new List <AppliedPrescription>(); foreach (AppliedPrescription prescription in prescriptions) { // Decide whether or not to apply prescription // tjs 2009.01.10 - prescription application // This has been modified so that if the prescription is AppliedRepeatHarvest // AND has not been harvested once, it is set to harvest. If it has been set // to harvest the first time, it will automatically be harvested by the logic // having to do with the setAside member variable (see AppliedRepeatHarvest.cs) prescription.ApplyPrescription = false; if (prescription.BeginTime <= Model.Core.CurrentTime && prescription.EndTime >= Model.Core.CurrentTime) { if (!(prescription is AppliedRepeatHarvest) || prescription.Prescription is SingleRepeatHarvest) { prescription.ApplyPrescription = true; } else if (prescription is AppliedRepeatHarvest && Model.Core.CurrentTime > 0 && ((AppliedRepeatHarvest)prescription).IsMultipleRepeatHarvest) { prescription.ApplyPrescription = true; ((AppliedRepeatHarvest)prescription).HasBeenHarvested = true; } } // if(prescription.BeginTime <= Model.Core.CurrentTime... if (prescription.ApplyPrescription) { //Model.Core.UI.WriteLine(" Applying Prescription: {0} Model.Core.CurrentTime: {1}", prescription.Prescription.Name, Model.Core.CurrentTime); if (isDebugEnabled) { log.DebugFormat(" Initializing prescription {0} ...", prescription.Prescription.Name); } //Model.Core.UI.WriteLine(" Initializing prescription {0} ...", prescription.Prescription.Name); //set harvesting areas, rank stands (by user choice method) prescription.InitializeForHarvest(stands); if (prescription.AnyUnharvestedStandsRankedAbove0) { //Model.Core.UI.WriteLine(" Adding {0}", prescription.Prescription.Name); foreach (StandRanking sr in prescription.Rankings) { //Model.Core.UI.WriteLine(" Stand {0} ranked {1}", sr.Stand.MapCode, sr.Rank); } activePrescriptions.Add(prescription); } } } if (isDebugEnabled) { Model.Core.UI.WriteLine(" Number of active prescriptions: {0}", activePrescriptions.Count); for (int i = 0; i < activePrescriptions.Count; i++) { Model.Core.UI.WriteLine(" {0}) {1}", i + 1, activePrescriptions[i].Prescription.Name); } } foreach (AppliedPrescription prescription in prescriptions) { //Model.Core.UI.WriteLine(" Looping through prescriptions... {0}.", prescription.Prescription.Name); if (prescription is AppliedRepeatHarvest) { //prescription.Prescription.SiteSelectionMethod = new CompleteStand(); //Model.Core.UI.WriteLine(" Attempting to Re-Harvest {0}.", prescription.Prescription.Name); ((AppliedRepeatHarvest)prescription).ActiveMgmtArea = this; ((AppliedRepeatHarvest)prescription).HarvestReservedStands(); ((AppliedRepeatHarvest)prescription).ActiveMgmtArea = null; } } // Loop while there are still active prescriptions that haven't // reached their target harvest areas and that still have // at least one unharvested stand ranked above 0. while (activePrescriptions.Count > 0) { double[] endProbability = new double[activePrescriptions.Count + 1]; // Assign a part of the probability interval [0, 1) to each // prescription based on how the ratio of the area remaining to // be harvested to the total area to be harvested double ratioTotal = 0.0; foreach (AppliedPrescription prescription in activePrescriptions) { ratioTotal += Math.Min(prescription.AreaRemainingRatio, prescription.StandsRemainingRatio); } if (ratioTotal > 0) { for (int i = 0; i < activePrescriptions.Count; ++i) { AppliedPrescription prescription = activePrescriptions[i]; //first prescription, start at 0 if (i == 0) { endProbability[i] = Math.Min(prescription.AreaRemainingRatio, prescription.StandsRemainingRatio) / ratioTotal; } //last prescription, end at 1.0 else if (i == activePrescriptions.Count - 1) { endProbability[i] = 1.0; } // else { double startProbability = endProbability[i - 1]; double intervalWidth = Math.Min(prescription.AreaRemainingRatio, prescription.StandsRemainingRatio) / ratioTotal; endProbability[i] = startProbability + intervalWidth; } } // for (int i = 0; i < activePrescriptions.Count; ++i) // Randomly select one of the active prescriptions and harvest the stand ranked highest by that prescription. AppliedPrescription selectedPrescription = null; double randomNum = Model.Core.GenerateUniform(); for (int i = 0; i < activePrescriptions.Count; ++i) { if (randomNum < endProbability[i]) { selectedPrescription = activePrescriptions[i]; //Model.Core.UI.WriteLine("\nSELECTED PRESCRIPTION = {0}\n", selectedPrescription.Prescription.Name); break; } } //actually harvest the stands: starting with highest ranked if (selectedPrescription is AppliedRepeatHarvest) { ((AppliedRepeatHarvest)selectedPrescription).HarvestHighestRankedStand(); } else { selectedPrescription.HarvestHighestRankedStand(); } //Model.Core.UI.WriteLine("\nSELECTED PRESCRIPTION = {0}\n", selectedPrescription.Prescription.Name); Stand stand = selectedPrescription.HighestRankedStand; if (stand != null) { //if there was a stand-adjacency constraint on this stand, enforce: foreach (IRequirement r in selectedPrescription.Prescription.StandRankingMethod.Requirements) { //look for stand-adacency constraint in list r ranking methods if (r.ToString() == "Landis.Harvest.StandAdjacency") { StandAdjacency sa = (StandAdjacency)r; //set-aside every stand in this stand's neighbor-list for the specified number of years //IF siteselection = some type of spreading, freeze the spread-list of neighbors if (selectedPrescription.Prescription.SiteSelectionMethod.ToString() == "Landis.Harvest.CompleteStandSpreading" || selectedPrescription.Prescription.SiteSelectionMethod.ToString() == "Landis.Harvest.PartialStandSpreading") { //freeze every stand in the neighbor list StandSpreading ss = (StandSpreading)selectedPrescription.Prescription.SiteSelectionMethod; //if it's spreading, go through the UnharvestedNeighbors list that was built during the site-selection spread foreach (Stand n_stand in ss.UnharvestedNeighbors) { //Model.Core.UI.WriteLine("SPREAD setting aside {0}", n_stand.MapCode); n_stand.SetAsideUntil(Model.Core.CurrentTime + sa.SetAside); } } else { //if it's not a spreading, just take all of the stand's neighbors foreach (Stand n_stand in stand.Neighbors) { //Model.Core.UI.WriteLine("NON-SPREAD setting aside {0}", n_stand.MapCode); n_stand.SetAsideUntil(Model.Core.CurrentTime + sa.SetAside); } } //found and implemented the stand adjacency, so break out of the requirements list break; } } } else { //Model.Core.UI.WriteLine("returned a null stand"); } // Check each prescription to see if there's at least one unharvested stand that the prescription ranks higher than 0. // The list is traversed in reverse order, so that the removal of items doesn't mess up the traversal. for (int i = activePrescriptions.Count - 1; i >= 0; --i) { if (!activePrescriptions[i].AnyUnharvestedStandsRankedAbove0) { //Model.Core.UI.WriteLine("removing1 {0}", activePrescriptions[i].Prescription.Name); activePrescriptions.RemoveAt(i); } } } else { for (int i = activePrescriptions.Count - 1; i >= 0; --i) { //Model.Core.UI.WriteLine("removing2 {0}", activePrescriptions[i].Prescription.Name); activePrescriptions.RemoveAt(i); } } } //endwhile }