From 7aa6d64a72e2d5ebb9c51727609890f8e97f5512 Mon Sep 17 00:00:00 2001
From: Daniel Vedder <daniel.vedder@idiv.de>
Date: Wed, 12 Jun 2024 11:52:44 +0200
Subject: [PATCH] Reorganised skylark species parameters

---
 src/nature/species/skylark.jl | 68 ++++++++++++++++++++++-------------
 src/parameters.toml           |  2 +-
 2 files changed, 44 insertions(+), 26 deletions(-)

diff --git a/src/nature/species/skylark.jl b/src/nature/species/skylark.jl
index c9ecca8..72e4102 100644
--- a/src/nature/species/skylark.jl
+++ b/src/nature/species/skylark.jl
@@ -3,10 +3,11 @@
 ### This file holds the code for the Eurasian Skylark (Alauda arvensis).
 ###
 
+#XXX global variable
 skylarkhabitat = @habitat((@landcover() == grass ||
                            # settle on grass or arable land (but not maize)
                            (@landcover() == agriculture && @cropname() != "maize")) &&
-                          @distancetoedge() >= 5) # at least 50m from other habitats
+                          @distancetoedge() > 5) # at least 50m from other habitats
 #XXX this ought to check for distance to forest and builtup,
 # but that's very expensive (see below)
 # @distanceto(forest) > 5 && # at least 50m from forest edges
@@ -31,32 +32,36 @@ At the moment, this implementation is still in development.
 """
 @species Skylark begin
     #XXX use Unitful.jl
-    eggtime::Int64 = 11 # 11 days from laying to hatching
-    eggpredationmortality::Float64 = 0.03 # per-day egg mortality from predation
-    nestharvestmortality::Float64 = 0.9 # egg/nestling mortality after a harvest event (XXX guess)
 
-    nestlingtime::Union{Int64,UnitRange{Int64}} = 7:11 # 7-11 days from hatching to leaving nest
-    nestlingpredationmortality::Float64 = 0.03 # per-day nestling mortality from predation
+    # species parameters
+    const eggtime::Int64 = 11 # 11 days from laying to hatching
+    const nestlingtime::UnitRange{Int64} = 7:11 # 7-11 days from hatching to leaving nest
+    const fledglingtime::UnitRange{Int64} = 25:30 # 25-30 days from hatching to independence
 
-    fledglingtime::Union{Int64,UnitRange{Int64}} = 25:30 # 25-30 days from hatching to independence
-    fledglingharvestmortality::Float64 = 0.5 # fledgling mortality after harvest
-    fledglingpredationmortality::Float64 = 0.01 # per-day fledgling mortality from predation
-    firstyearmortality::Float64 = 0.38 # total mortality in the first year after independence
+    const eggpredationmortality::Float64 = 0.03 # per-day egg mortality from predation
+    const nestharvestmortality::Float64 = 0.9 # egg/nestling mortality after a harvest event (XXX guess)
+    const nestlingpredationmortality::Float64 = 0.03 # per-day nestling mortality from predation
+    const fledglingharvestmortality::Float64 = 0.5 # fledgling mortality after harvest
+    const fledglingpredationmortality::Float64 = 0.01 # per-day fledgling mortality from predation
+    const firstyearmortality::Float64 = 0.38 # total mortality in the first year after independence
+    const migrationmortality::Float64 = 0.33 # chance of dying during the winter
+
+    const nestingbegin::Tuple{Int64,Int64} = (April, 10) # begin nesting in the middle of April
+    const nestbuildingtime::UnitRange{Int64} = 4:5 # 4-5 days needed to build a nest (doubled for first nest)
+    const eggsperclutch::UnitRange{Int64} = 2:5 # 2-5 eggs laid per clutch
+    const breedingdelay::Int64 = 18 # wait 18 days after hatching to start a new brood
+    const nestingend::Int64 = July # last month of nesting
     
-    migrationdates::Tuple = () # is defined by each individual in @create(Skylark)
-    migrationmortality::Float64 = 0.33 # chance of dying during the winter
+    const habitats::Function = skylarkhabitat
 
+    # individual variables
+    daystonextphase::Int64 = 0 # days remaining until fledging or maturity
+    migrationdates::Tuple = () # is defined by each individual in @create(Skylark)
     mate::Int64 = -1 # the agent ID of the mate (-1 if none)
     nest::Tuple = () # coordinates of current nest
-    nestingbegin::Tuple{Int64,Int64} = (April, 10) # begin nesting in the middle of April
-    nestbuildingtime::Union{Int64,UnitRange{Int64}} = 4:5 # 4-5 days needed to build a nest (doubled for first nest)
     nestcompletion::Int64 = 0 # days left until the nest is built
-    eggsperclutch::Union{Int64,UnitRange{Int64}} = 2:5 # 2-5 eggs laid per clutch
     clutch::Vector{Int64} = Vector{Int64}() # IDs of offspring in current clutch
-    breedingdelay::Int64 = 18 # wait 18 days after hatching to start a new brood
-    nestingend::Int64 = July # last month of nesting
-    
-    habitats::Function = skylarkhabitat
+
 end
 
 """
@@ -66,6 +71,7 @@ As an egg, simply check for mortality and hatching.
     @kill(self.eggpredationmortality, "predation")
     @respond(harvesting, @kill(self.nestharvestmortality, "harvest"))
     if self.age == self.eggtime
+        self.daystonextphase = @rand(self.nestlingtime)
         @setphase(nestling)
     end
 end
@@ -77,8 +83,14 @@ As a nestling, simply check for mortality and fledging.
     #TODO add feeding & growth
     @kill(self.nestlingpredationmortality, "predation")
     @respond(harvesting, @kill(self.nestharvestmortality, "harvest"))
-    if self.age == self.nestlingtime+self.eggtime
+    # if self.age == self.nestlingtime+self.eggtime
+    #     @setphase(fledgling)
+    # end
+    if self.daystonextphase == 0
+        self.daystonextphase = @rand(self.fledglingtime)
         @setphase(fledgling)
+    else
+        self.daystonextphase -= 1
     end
 end
 
@@ -90,9 +102,15 @@ check mortality.
     #TODO add feeding & growth
     @kill(self.fledglingpredationmortality, "predation")
     @walk("random") #TODO add movement following the parents
-    if self.age == self.fledglingtime+self.eggtime
+    # if self.age == self.fledglingtime+self.eggtime
+    #     @kill(self.firstyearmortality, "first year mortality") #XXX mechanistic?
+    #     @setphase(nonbreeding)
+    # end
+    if self.daystonextphase == 0
         @kill(self.firstyearmortality, "first year mortality") #XXX mechanistic?
         @setphase(nonbreeding)
+    else
+        self.daystonextphase -= 1
     end
 end
 
@@ -123,6 +141,8 @@ end
 Move around until a mate is found.
 """
 @phase Skylark mating begin
+    #TODO mortality and feeding
+    #TODO territoriality
     # if we've found a mate, wait for nesting begin and then go to the next phase
     if self.mate != -1
         if !@isalive(self.mate)
@@ -152,6 +172,7 @@ end
 Females select a location and build a nest. Males do nothing. (Sound familiar?)
 """
 @phase Skylark nestbuilding begin
+    #TODO mortality and feeding
     if !@isalive(self.mate)
         self.mate = -1
         @setphase(nonbreeding)
@@ -193,7 +214,7 @@ end
 Do lots of foraging (not yet implemented).
 """
 @phase Skylark breeding begin
-    #TODO forage (move random)
+    #TODO forage (move inside the territory)
     for offspring in self.clutch
         # check if offspring are still alive and juvenile, else remove from clutch
         if !@isalive(offspring) || @animal(offspring).phase == nonbreeding
@@ -243,9 +264,6 @@ should currently be on migration. Also sets other individual-specific variables.
         model.date != @param(core.startdate) && (returndate += Year(1))
         @migrate(returndate)
     end
-    # set individual life-history parameters that are defined as ranges for the species
-    self.nestlingtime = @rand(self.nestlingtime)
-    self.fledglingtime = @rand(self.fledglingtime)
     #TODO other stuff?
 end
 
diff --git a/src/parameters.toml b/src/parameters.toml
index d956e37..f9da32f 100644
--- a/src/parameters.toml
+++ b/src/parameters.toml
@@ -10,7 +10,7 @@
 configfile = "src/parameters.toml" # location of the configuration file
 outdir = "results" # location and name of the output folder
 overwrite = "ask" # overwrite the output directory? (true/false/"ask")
-logoutput = "both" # log output to screen/file/none/both
+logoutput = "both" # log output to screen/file/none/both #XXX default "both"
 csvoutput = true # save collected data in CSV files
 visualise = true # generate result graphs
 storedata = true # keep collected data in memory
-- 
GitLab