From 61f0ef71222278a6fc3da166382752ce55c499e9 Mon Sep 17 00:00:00 2001
From: Daniel Vedder <daniel.vedder@idiv.de>
Date: Mon, 5 Aug 2024 09:28:07 +0200
Subject: [PATCH] Moved random functions to utils.jl, added `randn()`

---
 src/core/input.jl | 33 -------------------------
 src/core/utils.jl | 63 ++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 62 insertions(+), 34 deletions(-)

diff --git a/src/core/input.jl b/src/core/input.jl
index 46460cb..e233382 100644
--- a/src/core/input.jl
+++ b/src/core/input.jl
@@ -125,39 +125,6 @@ function flattenTOML(tomldict)
     flatdict
 end
 
-"""
-    @rand(args...)
-
-Return a random number or element from the sample, using the model RNG.
-This is a utility wrapper that can only be used a context where the
-`model` object is available.
-"""
-macro rand(args...)
-    :($(esc(:rand))($(esc(:model)).rng, $(map(esc, args)...)))
-end
-
-"""
-    @shuffle!(collection)
-
-Shuffle the given collection in place, using the model RNG.
-This is a utility wrapper that can only be used a context where the
-`model` object is available.
-"""
-macro shuffle!(collection)
-    :($(esc(:shuffle!))($(esc(:model)).rng, $(esc(collection))))
-end
-
-"""
-    @chance(odds)
-
-Return true if a random number is less than the odds (0.0 <= `odds` <= 1.0),
-using the model RNG. This is a utility wrapper that can only be used a context
-where the `model` object is available.
-"""
-macro chance(odds)
-    :($(esc(:rand))($(esc(:model)).rng) < $(esc(odds)))
-end
-
 """
     parsecommandline()
 
diff --git a/src/core/utils.jl b/src/core/utils.jl
index 26882de..857d3e9 100644
--- a/src/core/utils.jl
+++ b/src/core/utils.jl
@@ -4,6 +4,8 @@
 ### units and dates.
 ###
 
+### UNITS AND DIMENSIONS
+
 ## Import and define units and dimensions
 import Unitful: cm, m, km, ha, mg, g, kg, Length, Area, Mass
 const m² = m^2
@@ -14,7 +16,7 @@ Base.:(/)(x::S,y::T) where {S<:Length, T<:Length} = (upreferred(x)/m) / (uprefer
 Base.:(/)(x::S,y::T) where {S<:Area, T<:Area} = (upreferred(x)/m²) / (upreferred(y)/m²)
 Base.:(/)(x::S,y::T) where {S<:Mass, T<:Mass} = (upreferred(x)/g) / (upreferred(y)/g)
 
-## Utility type and function for working wth recurring dates
+## RECURRING DATES
 
 """
     AnnualDate
@@ -87,3 +89,62 @@ Convert an AnnualDate to a Date, using the current/next/previous year of the sim
 thisyear(ad::AnnualDate, model::SimulationModel) = Date(year(model.date), ad)
 nextyear(ad::AnnualDate, model::SimulationModel) = Date(year(model.date)+1, ad)
 lastyear(ad::AnnualDate, model::SimulationModel) = Date(year(model.date)-1, ad)
+
+### RANDOM NUMBERS
+
+"""
+    randn(vector)
+
+Return a random element from the given vector, following a (mostly) normal distribution based on
+index values (i.e. elements in the middle of the vector will be returned most frequently).
+"""
+function randn(v::Vector, rng=default_rng())
+    r = randn(rng) + 3 # normal distribution centered around 3, gives values from 0 to 6
+    step = 6 / length(v)
+    i = Int(round(r / step))
+    v[i]
+end
+
+"""
+    @randn(args...)
+
+Return a normally-distributed random number or element from the sample, using the model RNG.
+This is a utility wrapper that can only be used a context where the
+`model` object is available.
+"""
+macro randn(args...)
+    :($(esc(:randn))($(esc(:model)).rng, $(map(esc, args)...)))
+end
+
+"""
+    @rand(args...)
+
+Return a random number or element from the sample, using the model RNG.
+This is a utility wrapper that can only be used a context where the
+`model` object is available.
+"""
+macro rand(args...)
+    :($(esc(:rand))($(esc(:model)).rng, $(map(esc, args)...)))
+end
+
+"""
+    @shuffle!(collection)
+
+Shuffle the given collection in place, using the model RNG.
+This is a utility wrapper that can only be used a context where the
+`model` object is available.
+"""
+macro shuffle!(collection)
+    :($(esc(:shuffle!))($(esc(:model)).rng, $(esc(collection))))
+end
+
+"""
+    @chance(odds)
+
+Return true if a random number is less than the odds (0.0 <= `odds` <= 1.0),
+using the model RNG. This is a utility wrapper that can only be used a context
+where the `model` object is available.
+"""
+macro chance(odds)
+    :($(esc(:rand))($(esc(:model)).rng) < $(esc(odds)))
+end
-- 
GitLab