Skip to content
Snippets Groups Projects
Commit ead08443 authored by xo30xoqa's avatar xo30xoqa
Browse files

Continued work on farm model (doesn't run yet)

parent 53b9b861
No related branches found
No related tags found
No related merge requests found
......@@ -55,8 +55,19 @@ end
## UTILITY FUNCTIONS
"""
isgrassland(farmplot, model)
Classify a farmplot as grassland or not (i.e., is the landcover of >90% of its pixels grass?)
"""
function isgrassland(farmplot::FarmPlot, model::SimulationModel)
#TODO
proportiongrass = count(pos -> @landcover() == grass, farmplot.pixels) / length(farmplot.pixels)
if proportiongrass > 0.9
return true
elseif proportiongrass > 0.1
@warn "Unclear classification: farm plot $(farmplot.id) has $(proportiongrass*100)% grass."
end
return false
end
"""
......
......@@ -3,9 +3,6 @@
### This file is responsible for managing the farm module(s).
###
###XXXXXXX In future, I want to expand Persefone into a proper ABM with multiple farm actors.
###XXXXXXX However, at the moment, all fields are controlled centrally -> see farm/farm.jl
"""
Farmer
......@@ -24,11 +21,17 @@ end
Update a farmer by one day.
"""
function stepagent!(farmer::Farmer, model::SimulationModel)
#TODO
# - check each field, whether it can be harvested
# - if so, harvest it and set its crop to "no growth"
# - [later: calculate income based on yield and annual price]
# - if a field has been harvested, check if the next crop can be sown
for f in farmer.fields
field = model.farmplots[f]
ctype = croptype(field)
if ctype.group != "semi-natural" && isharvestable(field) #TODO implement
harvest!(field, model)
#XXX later: calculate income based on yield and annual price
(ctype.group != "grass") && @sow("no growth")
elseif cropname(field) == "no growth"
#TODO if a field has been harvested, check if the next crop can be sown
end
end
end
"""
......@@ -37,5 +40,59 @@ end
Initialise the model with a set of farm agents.
"""
function initfarms!(model::SimulationModel)
#TODO
#XXX initially, we only have one farmer controlling all fields in the region
farmer = Farmer(1, collect(1:length(model.farmplots)), 0)
model.farmers = [farmer]
setasides = findsetasides(farmer, model) #TODO implement
for field in model.farmplots
if isgrassland(field)
@sow("permanent grassland (seeded)")
elseif field.id in setasides
@sow("permanent set-aside")
else
@sow("no growth")
end
end
end
"""
findsetasides(farmer, model)
Return a vector of field IDs that this farmer should keep fallow to satisfy the configured
set-aside rules.
"""
function findsetasides(farmer::Farmer, model::SimulationModel)
@param(farm.setaside) == 0 && return []
croparea = reduce(f -> isgrassland(f) ? 0 : length(f.pixels), model.farmplots[farmer.fields]) *
@param(world.mapresolution)^2
setasidearea = 0
setasides = []
for f in farmer.fields #XXX should be sorted smallest-largest for highest efficiency
field = model.farmplots[f]
isgrassland(f) && continue
push!(setasides, f)
setasidearea += length(field.pixels)*@param(world.mapresolution)^2
if setasidearea >= croparea*@param(farm.setaside)
@debug "Farmer $(farmer.id) has set aside $(setasidearea |> ha)."
return setasides
end
end
end
"""
@sow(cropname)
Sow the named crop on the current field. Requires the variables `field` and `model`.
"""
macro sow(cropname)
:(sow!($(esc(:field)), $(esc(:model)), $(esc(cropname))))
end
"""
@harvest()
Harvest the current field. Requires the variables `field` and `model`.
"""
macro harvest()
:(harvest!($(esc(:field)), $(esc(:model))))
end
......@@ -31,7 +31,8 @@ weatherfile = "weather.csv" # name of the weather data file in the map directory
[farm]
farmmodel = "FieldManager" # which version of the farm model to use (not yet implemented)
setaside = 0.04 # proportion of farm area set aside as fallow
[nature]
#targetspecies = ["Wolpertinger", "Wyvern"] # list of target species to simulate - example species
targetspecies = ["Skylark"] # list of target species to simulate
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment