ALMaSS Hare ODDox  1.1
The hare model description following ODdox protocol
NLBeetSpring.cpp
Go to the documentation of this file.
1 /*
2 *******************************************************************************************************
3 Copyright (c) 2017, Christopher John Topping, Aarhus University
4 All rights reserved.
5 
6 Redistribution and use in source and binary forms, with or without modification, are permitted provided
7 that the following conditions are met:
8 
9 Redistributions of source code must retain the above copyright notice, this list of conditions and the
10 following disclaimer.
11 Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
12 the following disclaimer in the documentation and/or other materials provided with the distribution.
13 
14 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
15 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
17 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
18 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
19 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
20 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
21 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22 ********************************************************************************************************
23 */
38 //
39 // NLBeetSpring.cpp
40 //
41 
42 
43 #include "../../Landscape/ls.h"
44 #include "../../Landscape/cropprogs/NLBeetSpring.h"
45 
46 // Some things that are defined externally - in this case these variables allow
47 // scaling of the percentage application figures for insecticides, herbicides etc..
48 extern CfgBool cfg_pest_beet_on;
49 // check if below are needed
50 extern CfgFloat l_pest_insecticide_amount;
51 extern CfgInt cfg_BE_InsecticideDay;
52 extern CfgInt cfg_BE_InsecticideMonth;
53 extern CfgFloat cfg_pest_product_3_amount;
54 
55 
64 bool NLBeetSpring::Do(Farm *a_farm, LE *a_field, FarmEvent *a_ev)
65 {
66  bool done = false; // The boolean value done indicates when we are totally finished with this plan (i.e. it is set to true).
67  int d1 = 0;
68  // Depending what event has occured jump to the correct bit of code
69  switch (a_ev->m_todo)
70  {
71  case nl_bes_start:
72  {
73  // nl_bes_start just sets up all the starting conditions and reference dates that are needed to start a nl_be
74  NL_BES_HERBI1 = false;
75  NL_BES_FUNGI1 = false;
76 
77 
78  // Set up the date management stuff
79  // The next bit of code just allows for altering dates after harvest if it is necessary
80  // to allow for a crop which starts its management early.
81 
82  // 2 start and stop dates for all 'movable' events for this crop
83  int noDates = 1;
84  a_field->SetMDates(0, 0, g_date->DayInYear(10, 12)); // last possible day of harvest
85  a_field->SetMDates(1, 0, g_date->DayInYear(10, 12));
86 
87  a_field->SetMConstants(0, 1);
88 
89  // Check the next crop for early start, unless it is a spring crop
90  // in which case we ASSUME that no checking is necessary!!!!
91  // So DO NOT implement a crop that runs over the year boundary (i.e. from spring to spring!), at least not without fixing this.
92 
93  //new if: do the check only for non-optimising farms and if year>0. (030713 - ms_rotation used only in the hidden year, so I modified the condition from >7 to >0)
94  //optimising farms not used for now so most of related code is removed (but not in 'start' case)
95  if (!(a_farm->GetType() == tof_OptimisingFarm && g_date->GetYearNumber() > 0)) {
96 
97  if (a_ev->m_startday > g_date->DayInYear(1, 7)) {
98  if (a_field->GetMDates(0, 0) >= a_ev->m_startday)
99  {
100  g_msg->Warn(WARN_BUG, "NLBeetSpring::Do(): ", "Harvest too late for the next crop to start!!!");
101  int almassnum = g_landscape_p->BackTranslateVegTypes(a_ev->m_next_tov);
102  g_msg->Warn("Next Crop ", (double)almassnum); // this causes exit
103  }
104  // Now fix any late finishing problems
105  for (int i = 0; i < noDates; i++) {
106  if (a_field->GetMDates(0, i) >= a_ev->m_startday) {
107  a_field->SetMDates(0, i, a_ev->m_startday - 1); //move the starting date
108  }
109  if (a_field->GetMDates(1, i) >= a_ev->m_startday) {
110  a_field->SetMConstants(i, 0); //change the default value of the MConst (=1) to 0 (necessary to correctly execute farm events in case the finishing date (MDate) was moved)
111  a_field->SetMDates(1, i, a_ev->m_startday - 1); //move the finishing date
112  }
113  }
114  }
115  // Now no operations can be timed after the start of the next crop.
116 
117  if (!a_ev->m_first_year) {
118  d1 = g_date->OldDays() + 365 + m_first_date; // Add 365 for spring crop
119  if (g_date->Date() > d1) {
120  // Yes too late - should not happen - raise an error
121  g_msg->Warn(WARN_BUG, "NLBeetSpring::Do(): ", "Crop start attempt after last possible start date");
122  int prev = g_landscape_p->BackTranslateVegTypes(a_field->GetOwner()->GetPreviousCrop(a_field->GetRotIndex()));
123  g_msg->Warn(WARN_BUG, "Previous Crop ", prev);
124  int almassnum = g_landscape_p->BackTranslateVegTypes(a_ev->m_next_tov);
125  g_msg->Warn("Next Crop ", (double)almassnum); // this causes exit
126  exit(1);
127  }
128  }
129  else {
130  SimpleEvent_(g_date->OldDays() + g_date->DayInYear(1, 3), nl_bes_spring_sow, false, a_farm, a_field);
131  break;
132  }
133  }//if
134 
135  // End single block date checking code. Please see next line comment as well.
136  // Reinit d1 to first possible starting date.
137  d1 = g_date->OldDays() + g_date->DayInYear(1, 3);
138  if (g_date->Date() >= d1) d1 += 365;
139  // OK, let's go.
140  // Here we queue up the first event - this differs depending on whether we have field on snady or clay soils
141  if (a_field->GetSoilType() == 2 || a_field->GetSoilType() == 6) { // on sandy soils (NL ZAND & LOSS)
142  SimpleEvent_(d1, nl_bes_spring_plough_sandy, false, a_farm, a_field);
143  }
144  else
145  {
146  if (a_farm->IsStockFarmer()) //Stock Farmer
147  {
148  SimpleEvent_(d1, nl_bes_ferti_s1, false, a_farm, a_field);
149  }
150  else SimpleEvent_(d1, nl_bes_ferti_p1, false, a_farm, a_field);
151  }
152  }
153  break;
154 
155  // This is the first real farm operation
157  if (!a_farm->SpringPlough(a_field, 0.0, g_date->DayInYear(30, 3) - g_date->DayInYear())) {
158  SimpleEvent_(g_date->Date() + 1, nl_bes_spring_plough_sandy, true, a_farm, a_field);
159  break;
160  }
161  if (a_farm->IsStockFarmer()) //Stock Farmer
162  {
163  SimpleEvent_(g_date->Date() + 7, nl_bes_ferti_s1, false, a_farm, a_field);
164  }
165  else SimpleEvent_(g_date->Date() + 7, nl_bes_ferti_p1, false, a_farm, a_field);
166  break;
167  case nl_bes_ferti_p1:
168  if (a_ev->m_lock || a_farm->DoIt_prob(0.60))
169  {
170  if (!a_farm->FP_NPK(a_field, 0.0, g_date->DayInYear(10, 4) - g_date->DayInYear())) {
171  SimpleEvent_(g_date->Date() + 1, nl_bes_ferti_p1, true, a_farm, a_field);
172  break;
173  }
174  }
175  SimpleEvent_(g_date->Date() + 1, nl_bes_preseeding_cultivator, false, a_farm, a_field);
176  break;
177  case nl_bes_ferti_s1:
178  if (a_ev->m_lock || a_farm->DoIt_prob(0.60))
179  {
180  if (!a_farm->FA_NPK(a_field, 0.0, g_date->DayInYear(10, 4) - g_date->DayInYear())) {
181  SimpleEvent_(g_date->Date() + 1, nl_bes_ferti_s1, true, a_farm, a_field);
182  break;
183  }
184  }
185  SimpleEvent_(g_date->Date() + 1, nl_bes_preseeding_cultivator, false, a_farm, a_field);
186  break;
188  if (!a_farm->PreseedingCultivator(a_field, 0.0, g_date->DayInYear(14, 4) - g_date->DayInYear())) {
189  SimpleEvent_(g_date->Date() + 1, nl_bes_preseeding_cultivator, true, a_farm, a_field);
190  break;
191  }
192  SimpleEvent_(g_date->Date() + 1, nl_bes_spring_sow, false, a_farm, a_field);
193  break;
194  case nl_bes_spring_sow:
195  if (!a_farm->SpringSow(a_field, 0.0, g_date->DayInYear(15, 4) - g_date->DayInYear())) {
196  SimpleEvent_(g_date->Date() + 1, nl_bes_spring_sow, true, a_farm, a_field);
197  break;
198  }
199  // Here is a fork leading to four parallel events
200  SimpleEvent_(g_date->Date() + 5, nl_bes_herbicide1, false, a_farm, a_field); // Herbicide thread
201  SimpleEvent_(g_date->OldDays() + g_date->DayInYear(1, 7), nl_bes_fungicide1, false, a_farm, a_field); // Fungicide thread = MAIN THREAD
202  if (a_farm->IsStockFarmer()) //Stock Farmer
203  {
204  SimpleEvent_(g_date->OldDays() + g_date->DayInYear(15, 4), nl_bes_ferti_s2, false, a_farm, a_field); // Fertilizers thread
205  }
206  else SimpleEvent_(g_date->OldDays() + g_date->DayInYear(15, 4), nl_bes_ferti_p2, false, a_farm, a_field);
207  break;
208  case nl_bes_ferti_p2:
209  // Here comes fertilizers thread
210  if (a_field->GetGreenBiomass() <= 0) {
211  SimpleEvent_(g_date->Date() + 1, nl_bes_ferti_p2, false, a_farm, a_field);
212  }
213  else
214  {
215  if (!a_farm->FP_AmmoniumSulphate(a_field, 0.0, g_date->DayInYear(15, 5) - g_date->DayInYear())) {
216  SimpleEvent_(g_date->Date() + 1, nl_bes_ferti_p2, true, a_farm, a_field);
217  break;
218  }
219  }
220  // End of thread
221  break;
222  case nl_bes_ferti_s2:
223  if (a_field->GetGreenBiomass() <= 0) {
224  SimpleEvent_(g_date->Date() + 1, nl_bes_ferti_s2, false, a_farm, a_field);
225  break;
226  }
227  else
228  {
229  if (!a_farm->FA_AmmoniumSulphate(a_field, 0.0, g_date->DayInYear(15, 5) - g_date->DayInYear())) {
230  SimpleEvent_(g_date->Date() + 1, nl_bes_ferti_s2, true, a_farm, a_field);
231  break;
232  }
233  }
234  // End of thread
235  break;
236  case nl_bes_herbicide1: // The first of the pesticide managements.
237  // Here comes the herbicide thread
238  // We assume that farmers do max 3 herbicide treatments
239  if (a_field->GetGreenBiomass() <= 0)
240  {
241  if (a_ev->m_lock || a_farm->DoIt_prob(0.75))
242  {
243  if (!a_farm->HerbicideTreat(a_field, 0.0, g_date->DayInYear(20, 4) - g_date->DayInYear())) {
244  SimpleEvent_(g_date->Date() + 1, nl_bes_herbicide1, true, a_farm, a_field);
245  break;
246  }
247  NL_BES_HERBI1 = true;
248  }
249  SimpleEvent_(g_date->Date() + 14, nl_bes_herbicide2, false, a_farm, a_field);
250  break;
251  }
252  SimpleEvent_(g_date->OldDays() + g_date->DayInYear(15, 3), nl_bes_herbicide2, false, a_farm, a_field);
253  break;
254  case nl_bes_herbicide2:
255  if (a_field->GetGreenBiomass() <= 0) {
256  SimpleEvent_(g_date->Date() + 1, nl_bes_herbicide2, false, a_farm, a_field);
257  }
258  else
259  {
260  if (!a_farm->HerbicideTreat(a_field, 0.0, g_date->DayInYear(30, 4) - g_date->DayInYear())) {
261  SimpleEvent_(g_date->Date() + 1, nl_bes_herbicide2, true, a_farm, a_field);
262  break;
263  }
264  SimpleEvent_(g_date->Date() + 14, nl_bes_herbicide3, false, a_farm, a_field);
265  break;
266  }
267  break;
268  case nl_bes_herbicide3:
269  if (!a_farm->HerbicideTreat(a_field, 0.0, g_date->DayInYear(15, 5) - g_date->DayInYear())) {
270  SimpleEvent_(g_date->Date() + 1, nl_bes_herbicide3, true, a_farm, a_field);
271  break;
272  }
273  SimpleEvent_(g_date->Date() + 14, nl_bes_herbicide4, false, a_farm, a_field);
274  break;
275  case nl_bes_herbicide4:
276  if (a_ev->m_lock || (a_farm->DoIt_prob(0.20) && (NL_BES_HERBI1 == false)))
277  {
278  if (!a_farm->HerbicideTreat(a_field, 0.0, g_date->DayInYear(30, 5) - g_date->DayInYear())) {
279  SimpleEvent_(g_date->Date() + 1, nl_bes_herbicide4, true, a_farm, a_field);
280  break;
281  }
282  }
283  // End of thread
284  break;
285  case nl_bes_fungicide1:
286  // Here comes the fungicide thread
287  if (!a_farm->FungicideTreat(a_field, 0.0, g_date->DayInYear(5, 8) - g_date->DayInYear())) {
288  SimpleEvent_(g_date->Date() + 1, nl_bes_fungicide1, true, a_farm, a_field);
289  break;
290  }
291  SimpleEvent_(g_date->Date() + 21, nl_bes_fungicide2, false, a_farm, a_field);
292  break;
293  case nl_bes_fungicide2:
294  if (a_ev->m_lock || a_farm->DoIt_prob(0.75))
295  {
296  if (!a_farm->FungicideTreat(a_field, 0.0, g_date->DayInYear(25, 8) - g_date->DayInYear())) {
297  SimpleEvent_(g_date->Date() + 1, nl_bes_fungicide2, true, a_farm, a_field);
298  break;
299  }
300  NL_BES_FUNGI1 = true;
301  }
302  SimpleEvent_(g_date->Date() + 21, nl_bes_fungicide3, false, a_farm, a_field);
303  break;
304  case nl_bes_fungicide3:
305  if (a_ev->m_lock || (a_farm->DoIt_prob(0.667) && NL_BES_FUNGI1 == 1)) // 50% of all farmers
306  {
307  if (!a_farm->FungicideTreat(a_field, 0.0, g_date->DayInYear(15, 9) - g_date->DayInYear())) {
308  SimpleEvent_(g_date->Date() + 1, nl_bes_fungicide3, true, a_farm, a_field);
309  break;
310  }
311  }
312  SimpleEvent_(g_date->OldDays() + g_date->DayInYear(20, 9), nl_bes_harvest, false, a_farm, a_field);
313  break;
314  case nl_bes_harvest:
315  // Here the MAIN thread continues
316  // We don't move harvest days
317  if (!a_farm->Harvest(a_field, 0.0, a_field->GetMDates(0, 0) - g_date->DayInYear())) {
318  SimpleEvent_(g_date->Date() + 1, nl_bes_harvest, true, a_farm, a_field);
319  break;
320  }
321  done = true;
322  // So we are done, and somwhere else the farmer will queue up the start event of the next crop
323  // END of MAIN THREAD
324  break;
325  default:
326  g_msg->Warn(WARN_BUG, "NLBeetSpring::Do(): "
327  "Unknown event type! ", "");
328  exit(1);
329  }
330  return done;
331 }
Farm::SpringPlough
virtual bool SpringPlough(LE *a_field, double a_user, int a_days)
Carry out a ploughing event in the spring on a_field.
Definition: farmfuncs.cpp:444
Farm::IsStockFarmer
bool IsStockFarmer(void)
Definition: farm.h:905
nl_bes_harvest
Definition: NLBeetSpring.h:54
FarmEvent::m_lock
bool m_lock
Definition: farm.h:465
FarmEvent
A struct to hold the information required to trigger a farm event.
Definition: farm.h:463
nl_bes_herbicide4
Definition: NLBeetSpring.h:50
nl_bes_ferti_s2
Definition: NLBeetSpring.h:46
nl_bes_herbicide3
Definition: NLBeetSpring.h:49
FarmEvent::m_first_year
bool m_first_year
Definition: farm.h:467
tof_OptimisingFarm
Definition: farm.h:273
cfg_pest_product_3_amount
CfgFloat cfg_pest_product_3_amount
nl_bes_ferti_p1
Definition: NLBeetSpring.h:41
nl_bes_ferti_s1
Definition: NLBeetSpring.h:42
Landscape::BackTranslateVegTypes
int BackTranslateVegTypes(TTypesOfVegetation VegReference)
Definition: Landscape.h:1669
cfg_BE_InsecticideMonth
CfgInt cfg_BE_InsecticideMonth
Farm::GetType
TTypesOfFarm GetType(void)
Definition: farm.h:901
nl_bes_preseeding_cultivator
Definition: NLBeetSpring.h:43
Crop::m_first_date
int m_first_date
Definition: farm.h:540
FarmEvent::m_startday
int m_startday
Definition: farm.h:466
NLBeetSpring::Do
virtual bool Do(Farm *a_farm, LE *a_field, FarmEvent *a_ev)
The one and only method for a crop management plan. All farm actions go through here.
Definition: NLBeetSpring.cpp:64
nl_bes_start
Definition: NLBeetSpring.h:38
l_pest_insecticide_amount
CfgFloat l_pest_insecticide_amount
NL_BES_HERBI1
#define NL_BES_HERBI1
A flag used to indicate autumn ploughing status.
Definition: NLBeetSpring.h:28
nl_bes_spring_sow
Definition: NLBeetSpring.h:44
nl_bes_spring_plough_sandy
Definition: NLBeetSpring.h:40
cfg_BE_InsecticideDay
CfgInt cfg_BE_InsecticideDay
NL_BES_FUNGI1
#define NL_BES_FUNGI1
Definition: NLBeetSpring.h:29
FarmEvent::m_next_tov
TTypesOfVegetation m_next_tov
Definition: farm.h:471
FarmEvent::m_todo
int m_todo
Definition: farm.h:469
nl_bes_herbicide2
Definition: NLBeetSpring.h:48
Farm
The base class for all farm types.
Definition: farm.h:767
nl_bes_herbicide1
Definition: NLBeetSpring.h:47
nl_bes_ferti_p2
Definition: NLBeetSpring.h:45
nl_bes_fungicide2
Definition: NLBeetSpring.h:52
cfg_pest_beet_on
CfgBool cfg_pest_beet_on
nl_bes_fungicide1
Definition: NLBeetSpring.h:51
g_landscape_p
Landscape * g_landscape_p
Definition: Landscape.cpp:258
Crop::SimpleEvent_
void SimpleEvent_(long a_date, int a_todo, bool a_lock, Farm *a_farm, LE *a_field)
Adds an event to this crop management without relying on member variables.
Definition: farm.cpp:312
nl_bes_fungicide3
Definition: NLBeetSpring.h:53