Simulation Framework with Logging to Tabular Data

I think this technique is interesting. Perhaps if someone can edit the to_named_tuple piece this could work:


using DataFrames, NamedTuples

#gentup(struct_T) = NamedTuple{( fieldnames(struct_T)...,),
#                                Tuple{(fieldtype(struct_T,i) for i=1:fieldcount(struct_T))...}}
#
#@generated function to_named_tuple_generated(x)
#    nt = Expr(:quote, gentup(x))
#    tup = Expr(:tuple)
#    for i=1:fieldcount(x)
#        push!(tup.args, :(getfield(x, $i)) )
#    end
#    return :($nt($tup))
#end
#        
#        

#to_named_tuple_naive(p) = (; (v=>getfield(p, v) for v in fieldnames(typeof(p)))...)

        

mutable struct Person
    age::Int64
    id::Int64
    name::String
    weight::Float64
    blood_type::String
    average_resting_heart_rate::Int64
    IQ::Int64
end

function update!(person::Person)
    person.age += 1
    person.weight += rand() - 0.5
end


function logging_df(a_struct)
        DataFrame(prepend!(map(x -> fieldtype(a_struct, x), 
                               fieldnames(a_struct)
                              ),
                           [Int64]
                          ),
                  prepend!(fieldnames(a_struct),
                           [:timestep]
                          ),
                  0)
end
    
p = Person(18, 123, "foo", 72.5, "AB", 66, 100);
    
function log!(simresults, t, p)
        push!(simresults, prepend!(to_named_tuple(p),[t]))
end
    
all_people = [p]
    
function run_simulation!(timesteps::Int64, all_people, simresults)
    for t in 1:timesteps
        map(update!,all_people)
        log!(simresults,t,all_people)
    end
end

simresults = logging_df(Person)
run_simulation!(10,all_people,simresults)
simresults