ALMaSS Hare ODDox  1.1
The hare model description following ODdox protocol
NLCarrotsSpring.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 CA 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 // NLCarrotsSpring.cpp
40 //
41 
42 
43 #include "../../Landscape/ls.h"
44 #include "../../Landscape/cropprogs/NLCarrotsSpring.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_carrots_on;
49 // check if below are needed
50 extern CfgFloat l_pest_insecticide_amount;
51 extern CfgInt cfg_CAS_InsecticideDay;
52 extern CfgInt cfg_CAS_InsecticideMonth;
53 extern CfgFloat cfg_pest_product_1_amount;
54 
55 
64 bool NLCarrotsSpring::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_cas_start:
72  {
73  // nl_cas_start just sets up all the starting conditions and reference dates that are needed to start a nl_ca
74  NL_CAS_WINTER_PLOUGH = false;
75  NL_CAS_HERBI1 = false;
76  NL_CAS_HERBI2 = false;
77  NL_CAS_FUNGI1 = false;
78  NL_CAS_FUNGI2 = false;
79 
80 
81  // Set up the date management stuff
82  // The next bit of code just allows for altering dates after harvest if it is necessary
83  // to allow for a crop which starts its management early.
84 
85  // 2 start and stop dates for all 'movable' events for this crop
86  int noDates = 1;
87  a_field->SetMDates(0, 0, g_date->DayInYear(1, 10)); // first possible day of harvest
88  a_field->SetMDates(1, 0, g_date->DayInYear(15, 11)); // last possible day of harvest
89 
90  a_field->SetMConstants(0, 1);
91 
92  // Check the next crop for early start, unless it is a spring crop
93  // in which case we ASSUME that no checking is necessary!!!!
94  // So DO NOT implement a crop that runs over the year boundary (i.e. from spring to spring!), at least not without fixing this.
95 
96  //new if: do the check only for non-optimising farms and if year>0. (030713 - m_rotation used only in the hidden year, so I modified the condition from >7 to >0)
97  //optimising farms not used for now so most of related code is removed (but not in 'start' case)
98  if (!(a_farm->GetType() == tof_OptimisingFarm && g_date->GetYearNumber() > 0)) {
99 
100  if (a_ev->m_startday > g_date->DayInYear(1, 7)) {
101  if (a_field->GetMDates(0, 0) >= a_ev->m_startday)
102  {
103  g_msg->Warn(WARN_BUG, "NLCarrotsSpring::Do(): ", "Harvest too late for the next crop to start!!!");
104  int almassnum = g_landscape_p->BackTranslateVegTypes(a_ev->m_next_tov);
105  g_msg->Warn("Next Crop ", (double)almassnum); // this causes exit
106  }
107  // Now fix any late finishing problems
108  for (int i = 0; i < noDates; i++) {
109  if (a_field->GetMDates(0, i) >= a_ev->m_startday) {
110  a_field->SetMDates(0, i, a_ev->m_startday - 1); //move the starting date
111  }
112  if (a_field->GetMDates(1, i) >= a_ev->m_startday) {
113  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)
114  a_field->SetMDates(1, i, a_ev->m_startday - 1); //move the finishing date
115  }
116  }
117  }
118  // Now no operations can be timed after the start of the next crop.
119 
120  if (!a_ev->m_first_year) {
121  d1 = g_date->OldDays() + 365 + m_first_date; // Add 365 for spring crop
122  if (g_date->Date() > d1) {
123  // Yes too late - should not happen - raise an error
124  g_msg->Warn(WARN_BUG, "NLCarrotsSpring::Do(): ", "Crop start attempt after last possible start date");
125  int prev = g_landscape_p->BackTranslateVegTypes(a_field->GetOwner()->GetPreviousCrop(a_field->GetRotIndex()));
126  g_msg->Warn(WARN_BUG, "Previous Crop ", prev);
127  int almassnum = g_landscape_p->BackTranslateVegTypes(a_ev->m_next_tov);
128  g_msg->Warn("Next Crop ", (double)almassnum); // this causes exit
129  exit(1);
130  }
131  }
132  else {
133  // Is the first year
134  // Some special code to cope with that first start-up year in ALMaSS - ignore for all practical purposes
135  // Code for first spring treatment used
136  SimpleEvent_(g_date->OldDays() + g_date->DayInYear(10, 4), nl_cas_spring_sow, false, a_farm, a_field);
137  break;
138  }
139  }//if
140 
141  // End single block date checking code. Please see next line comment as well.
142  // Reinit d1 to first possible starting date.
143  d1 = g_date->OldDays() + g_date->DayInYear(1, 3);
144  if (g_date->Date() >= d1) d1 += 365;
145  // OK, let's go.
146  // Here we queue up the first event - this differs depending on whether we have field on snady or clay soils
147  if (a_field->GetSoilType() == 2 || a_field->GetSoilType() == 6) { // on sandy soils (NL ZAND & LOSS)
148  SimpleEvent_(d1, nl_cas_spring_plough_sandy, false, a_farm, a_field);
149  }
150  else
151  {
152  d1 = g_date->OldDays() + g_date->DayInYear(15, 3);
153  if (g_date->Date() >= d1) d1 += 365;
154  if (a_farm->IsStockFarmer()) //Stock Farmer
155  {
156  SimpleEvent_(d1, nl_cas_ferti_s1, false, a_farm, a_field);
157  }
158  else SimpleEvent_(d1, nl_cas_ferti_p1, false, a_farm, a_field);
159  }
160  }
161  break;
162 
163  // This is the first real farm operation
165  if (!a_farm->SpringPlough(a_field, 0.0, g_date->DayInYear(31, 3) - g_date->DayInYear())) {
166  SimpleEvent_(g_date->Date() + 1, nl_cas_spring_plough_sandy, true, a_farm, a_field);
167  break;
168  }
169  if (a_farm->IsStockFarmer()) //Stock Farmer
170  {
171  SimpleEvent_(g_date->Date() + 7, nl_cas_ferti_s1, false, a_farm, a_field);
172  }
173  else SimpleEvent_(g_date->Date() + 7, nl_cas_ferti_p1, false, a_farm, a_field);
174  break;
175  case nl_cas_ferti_p1:
176  if (a_ev->m_lock || a_farm->DoIt_prob(0.95))
177  {
178  if (!a_farm->FP_NPK(a_field, 0.0, g_date->DayInYear(1, 5) - g_date->DayInYear())) {
179  SimpleEvent_(g_date->Date() + 1, nl_cas_ferti_p1, true, a_farm, a_field);
180  break;
181  }
182  }
183  d1 = g_date->Date() + 1;
184  if (d1 < g_date->OldDays() + g_date->DayInYear(1, 4)) {
185  d1 = g_date->OldDays() + g_date->DayInYear(1, 4);
186  }
187  SimpleEvent_(d1, nl_cas_preseeding_cultivator, false, a_farm, a_field);
188  break;
189  case nl_cas_ferti_s1:
190  if (a_ev->m_lock || a_farm->DoIt_prob(0.95))
191  {
192  if (!a_farm->FA_NPK(a_field, 0.0, g_date->DayInYear(1, 5) - g_date->DayInYear())) {
193  SimpleEvent_(g_date->Date() + 1, nl_cas_ferti_s1, true, a_farm, a_field);
194  break;
195  }
196  }
197  d1 = g_date->Date() + 1;
198  if (d1 < g_date->OldDays() + g_date->DayInYear(1, 4)) {
199  d1 = g_date->OldDays() + g_date->DayInYear(1, 4);
200  }
201  SimpleEvent_(d1, nl_cas_preseeding_cultivator, false, a_farm, a_field);
202  break;
203 
205  if (!a_farm->PreseedingCultivator(a_field, 0.0, g_date->DayInYear(25, 4) - g_date->DayInYear())) {
206  SimpleEvent_(g_date->Date() + 3, nl_cas_preseeding_cultivator, true, a_farm, a_field);
207  break;
208  }
209  SimpleEvent_(g_date->Date() + 3, nl_cas_bed_forming, false, a_farm, a_field);
210  break;
211  case nl_cas_bed_forming:
212  if (!a_farm->BedForming(a_field, 0.0, g_date->DayInYear(30, 4) - g_date->DayInYear())) {
213  SimpleEvent_(g_date->Date() + 1, nl_cas_bed_forming, true, a_farm, a_field);
214  break;
215  }
216  SimpleEvent_(g_date->Date() + 1, nl_cas_spring_sow, false, a_farm, a_field);
217  break;
218  case nl_cas_spring_sow:
219  if (!a_farm->SpringSow(a_field, 0.0, g_date->DayInYear(15, 5) - g_date->DayInYear())) {
220  SimpleEvent_(g_date->Date() + 1, nl_cas_spring_sow, true, a_farm, a_field);
221  break;
222  }
223  // Here is a fork leading to four parallel events
224  SimpleEvent_(g_date->Date() + 3, nl_cas_herbicide1, false, a_farm, a_field); // Herbicide thread
225  SimpleEvent_(g_date->OldDays() + g_date->DayInYear(1, 7), nl_cas_fungicide1, false, a_farm, a_field); // Fungicide thread = MAIN THREAD
226  if (a_farm->IsStockFarmer()) //Stock Farmer
227  {
228  SimpleEvent_(g_date->OldDays() + g_date->DayInYear(15, 6), nl_cas_ferti_s2, false, a_farm, a_field); // Fertilizers thread
229  }
230  else SimpleEvent_(g_date->OldDays() + g_date->DayInYear(15, 6), nl_cas_ferti_p2, false, a_farm, a_field);
231  break;
232  case nl_cas_ferti_p2:
233  if (a_ev->m_lock || a_farm->DoIt_prob(0.80))
234  {
235  if (!a_farm->FP_AmmoniumSulphate(a_field, 0.0, g_date->DayInYear(30, 7) - g_date->DayInYear())) {
236  SimpleEvent_(g_date->Date() + 1, nl_cas_ferti_p2, true, a_farm, a_field);
237  break;
238  }
239  }
240  // End of thread
241  break;
242  case nl_cas_ferti_s2:
243  if (a_ev->m_lock || a_farm->DoIt_prob(0.80))
244  {
245  if (!a_farm->FA_AmmoniumSulphate(a_field, 0.0, g_date->DayInYear(30, 7) - g_date->DayInYear())) {
246  SimpleEvent_(g_date->Date() + 1, nl_cas_ferti_s2, true, a_farm, a_field);
247  break;
248  }
249  }
250  // End of thread
251  break;
252  case nl_cas_herbicide1: // The first of the pesticide managements.
253  // Here comes the herbicide thread
254  if (a_field->GetGreenBiomass() <= 0)
255  {
256  if (a_ev->m_lock || a_farm->DoIt_prob(0.80))
257  {
258  if (!a_farm->HerbicideTreat(a_field, 0.0, g_date->DayInYear(20, 5) - g_date->DayInYear())) {
259  SimpleEvent_(g_date->Date() + 1, nl_cas_herbicide1, true, a_farm, a_field);
260  break;
261  }
262  NL_CAS_HERBI1 = true;
263  }
264  SimpleEvent_(g_date->Date() + 14, nl_cas_herbicide2, false, a_farm, a_field);
265  break;
266  }
267  SimpleEvent_(g_date->OldDays() + g_date->DayInYear(1, 5), nl_cas_herbicide2, false, a_farm, a_field);
268  break;
269  case nl_cas_herbicide2:
270  if (a_field->GetGreenBiomass() <= 0) {
271  SimpleEvent_(g_date->Date() + 1, nl_cas_herbicide2, false, a_farm, a_field);
272  }
273  else
274  {
275  if (a_ev->m_lock || (a_farm->DoIt_prob(1.00) && NL_CAS_HERBI1 == 1))
276  {
277  if (!a_farm->HerbicideTreat(a_field, 0.0, g_date->DayInYear(5, 6) - g_date->DayInYear())) {
278  SimpleEvent_(g_date->Date() + 1, nl_cas_herbicide2, true, a_farm, a_field);
279  break;
280  }
281  NL_CAS_HERBI2 = true;
282  }
283  SimpleEvent_(g_date->Date() + 14, nl_cas_herbicide3, false, a_farm, a_field);
284  break;
285  }
286  break;
287  case nl_cas_herbicide3:
288  if (a_ev->m_lock || (a_farm->DoIt_prob(0.75) && NL_CAS_HERBI2 == 1))
289  {
290  if (!a_farm->HerbicideTreat(a_field, 0.0, g_date->DayInYear(20, 6) - g_date->DayInYear())) {
291  SimpleEvent_(g_date->Date() + 1, nl_cas_herbicide3, true, a_farm, a_field);
292  break;
293  }
294  }
295  // End of thread
296  break;
297  case nl_cas_fungicide1:
298  // Here comes the fungicide thread
299  if (a_ev->m_lock || a_farm->DoIt_prob(0.80))
300  {
301  if (!a_farm->FungicideTreat(a_field, 0.0, g_date->DayInYear(30, 7) - g_date->DayInYear())) {
302  SimpleEvent_(g_date->Date() + 1, nl_cas_fungicide1, true, a_farm, a_field);
303  break;
304  }
305  NL_CAS_FUNGI1 = true;
306  }
307  SimpleEvent_(g_date->Date() + 21, nl_cas_fungicide2, false, a_farm, a_field);
308  break;
309  case nl_cas_fungicide2:
310  if (a_ev->m_lock || (a_farm->DoIt_prob(1.00) && NL_CAS_FUNGI1 == 1))
311  {
312  if (!a_farm->FungicideTreat(a_field, 0.0, g_date->DayInYear(30, 8) - g_date->DayInYear())) {
313  SimpleEvent_(g_date->Date() + 1, nl_cas_fungicide2, true, a_farm, a_field);
314  break;
315  }
316  NL_CAS_FUNGI2 = true;
317  }
318  SimpleEvent_(g_date->Date() + 21, nl_cas_fungicide3, false, a_farm, a_field);
319  break;
320  case nl_cas_fungicide3:
321  if (a_ev->m_lock || (a_farm->DoIt_prob(0.75) && NL_CAS_FUNGI2 == 1)) // 60% of all farmers
322  {
323  if (!a_farm->FungicideTreat(a_field, 0.0, g_date->DayInYear(30, 9) - g_date->DayInYear())) {
324  SimpleEvent_(g_date->Date() + 1, nl_cas_fungicide3, true, a_farm, a_field);
325  break;
326  }
327  }
328  SimpleEvent_(g_date->OldDays() + g_date->DayInYear(25, 9), nl_cas_harvest, false, a_farm, a_field);
329  break;
330  case nl_cas_harvest:
331  if (a_field->GetMConstants(0) == 0) {
332  if (!a_farm->Harvest(a_field, 0.0, -1)) { // raise an error
333  g_msg->Warn(WARN_BUG, "NLCarrotsSpring::Do(): failure in 'Harvest' execution", "");
334  exit(1);
335  }
336  }
337  else {
338  if (!a_farm->Harvest(a_field, 0.0, a_field->GetMDates(1, 0) - g_date->DayInYear())) {
339  SimpleEvent_(g_date->Date() + 1, nl_cas_harvest, true, a_farm, a_field);
340  break;
341  }
342  }
343  done = true;
344  // So we are done, and somwhere else the farmer will queue up the start event of the next crop
345  // END of MAIN THREAD
346  break;
347  default:
348  g_msg->Warn(WARN_BUG, "NLCarrotsSpring::Do(): "
349  "Unknown event type! ", "");
350  exit(1);
351  }
352  return done;
353 }
nl_cas_herbicide1
Definition: NLCarrotsSpring.h:50
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_cas_harvest
Definition: NLCarrotsSpring.h:56
l_pest_insecticide_amount
CfgFloat l_pest_insecticide_amount
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_cas_ferti_s2
Definition: NLCarrotsSpring.h:49
nl_cas_spring_sow
Definition: NLCarrotsSpring.h:47
FarmEvent::m_first_year
bool m_first_year
Definition: farm.h:467
tof_OptimisingFarm
Definition: farm.h:273
NL_CAS_FUNGI2
#define NL_CAS_FUNGI2
Definition: NLCarrotsSpring.h:32
NL_CAS_HERBI2
#define NL_CAS_HERBI2
Definition: NLCarrotsSpring.h:30
Landscape::BackTranslateVegTypes
int BackTranslateVegTypes(TTypesOfVegetation VegReference)
Definition: Landscape.h:1669
Farm::GetType
TTypesOfFarm GetType(void)
Definition: farm.h:901
Crop::m_first_date
int m_first_date
Definition: farm.h:540
FarmEvent::m_startday
int m_startday
Definition: farm.h:466
nl_cas_ferti_p1
Definition: NLCarrotsSpring.h:43
nl_cas_herbicide3
Definition: NLCarrotsSpring.h:52
cfg_pest_carrots_on
CfgBool cfg_pest_carrots_on
nl_cas_ferti_s1
Definition: NLCarrotsSpring.h:44
nl_cas_preseeding_cultivator
Definition: NLCarrotsSpring.h:45
cfg_CAS_InsecticideDay
CfgInt cfg_CAS_InsecticideDay
NLCarrotsSpring::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: NLCarrotsSpring.cpp:64
nl_cas_ferti_p2
Definition: NLCarrotsSpring.h:48
nl_cas_fungicide1
Definition: NLCarrotsSpring.h:53
FarmEvent::m_next_tov
TTypesOfVegetation m_next_tov
Definition: farm.h:471
FarmEvent::m_todo
int m_todo
Definition: farm.h:469
nl_cas_fungicide2
Definition: NLCarrotsSpring.h:54
nl_cas_start
Definition: NLCarrotsSpring.h:40
NL_CAS_FUNGI1
#define NL_CAS_FUNGI1
Definition: NLCarrotsSpring.h:31
nl_cas_spring_plough_sandy
Definition: NLCarrotsSpring.h:42
Farm
The base class for all farm types.
Definition: farm.h:767
nl_cas_bed_forming
Definition: NLCarrotsSpring.h:46
nl_cas_fungicide3
Definition: NLCarrotsSpring.h:55
nl_cas_herbicide2
Definition: NLCarrotsSpring.h:51
NL_CAS_HERBI1
#define NL_CAS_HERBI1
Definition: NLCarrotsSpring.h:29
cfg_CAS_InsecticideMonth
CfgInt cfg_CAS_InsecticideMonth
NL_CAS_WINTER_PLOUGH
#define NL_CAS_WINTER_PLOUGH
A flag used to indicate autumn ploughing status.
Definition: NLCarrotsSpring.h:28
cfg_pest_product_1_amount
CfgFloat cfg_pest_product_1_amount
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