From fbe32017f759bb262a9994ef2e4ac0e0282df2f8 Mon Sep 17 00:00:00 2001
From: Marco Matthies <71844+marcom@users.noreply.github.com>
Date: Sun, 26 Jan 2025 22:30:02 +0100
Subject: [PATCH] Implement Base.show for the model landscape (Matrix{Pixel})

---
 Project.toml            |  1 +
 src/world/landscape.jl  | 36 ++++++++++++++++++++++++++++++++++++
 test/landscape_tests.jl |  7 +++++++
 3 files changed, 44 insertions(+)

diff --git a/Project.toml b/Project.toml
index da7164d..9ec4c21 100644
--- a/Project.toml
+++ b/Project.toml
@@ -17,6 +17,7 @@ GeoArrays = "2fb1d81b-e6a0-5fc5-82e6-8e06903437ab"
 Logging = "56ddb016-857b-54e1-b83d-db4d58db5568"
 LoggingExtras = "e6f89c97-d47a-5376-807f-9c37f3926c36"
 Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
+Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7"
 Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
 Serialization = "9e88b42a-f829-5b0c-bbe9-9e923198166b"
 StableRNGs = "860ef19b-820b-49d6-a774-d7a799459cd3"
diff --git a/src/world/landscape.jl b/src/world/landscape.jl
index a9d0454..bf8757d 100644
--- a/src/world/landscape.jl
+++ b/src/world/landscape.jl
@@ -3,6 +3,8 @@
 ### This file manages the landscape maps that underlie the model.
 ###
 
+using Printf
+
 ## IMPORTANT: do not change the order of this enum, or initlandscape() will break!
 "The land cover classes encoded in the Mundialis Sentinel data."
 @enum LandCover nodata forest grass water builtup soil agriculture
@@ -29,6 +31,40 @@ Pixel(landcover::LandCover, fieldid::Union{Missing,Int64}) =
     Pixel(landcover, fieldid, Vector{Management}(), Vector{Int64}(), Vector{Int64}())
 Pixel(landcover::LandCover) = Pixel(landcover, missing)
 
+function Base.show(io::IO, ::MIME"text/plain", mat::T) where T <: AbstractMatrix{Pixel}
+    max_fieldid = maximum(skipmissing(map(x -> getfield(x, :fieldid), mat)); init=0)
+    println(io, "Matrix{Pixel}:")
+    println(io, "  LandCover:")
+    nrow, ncol = size(mat)
+    for i in axes(mat, 1)
+        print(io, "    ")
+        for j in axes(mat, 2)
+            charid = uppercase(first(string(mat[i, j].landcover)))
+            fieldid = if ismissing(mat[i, j].fieldid)
+                repeat(" ", ndigits(max_fieldid))
+            else
+                @sprintf("%*s", ndigits(max_fieldid), mat[i, j].fieldid)
+            end
+            print(io, charid, fieldid, " ")
+        end
+        println(io)
+    end
+
+    # print legend
+    legend = join(map(x -> "$(uppercase(first(string(x)))) = $x", instances(Persefone.LandCover)), ", ")
+    println(io, "Legend: ", legend)
+
+    # print number of unique animals, events, territories
+    nanimals = length(unique(reduce(vcat, map(x -> getfield(x, :animals), mat))))
+    nevents = length(unique(reduce(vcat, map(x -> getfield(x, :events), mat))))
+    nterritories = length(unique(reduce(vcat, map(x -> getfield(x, :territories), mat))))
+    println(io, "Num. unique animals    : ", nanimals)
+    println(io, "Num. unique events     : ", nevents)
+    print(io, "Num. unique territories: ", nterritories)  # no newline on last line of output
+    return nothing
+end
+
+
 """
     FarmEvent
 
diff --git a/test/landscape_tests.jl b/test/landscape_tests.jl
index 9aa3cb3..dcfe621 100644
--- a/test/landscape_tests.jl
+++ b/test/landscape_tests.jl
@@ -19,6 +19,13 @@
     @test length(Ps.farmplot((800,800), model).pixels) == 4049               
 end
 
+@testset "Utility functions" begin
+    model = inittestmodel()
+    iobuf = IOBuffer()
+    show(iobuf, MIME"text/plain"(), model.landscape)
+    @test length(take!(iobuf)) > 0
+end
+
 @testset "Event system" begin
     model = inittestmodel()
     createevent!(model, [(1,1), (1,2), (1,3), (2,1), (2,3)], Ps.tillage)
-- 
GitLab