Agenda/StatContext.cs
using System.Text.Json.Nodes;

namespace PlanetMeat;

public class StatContext : ISaveTarget
{
	private Dictionary<string, double> MaxStats { get; } = [];
	private Dictionary<string, double> NowStats { get; } = [];

	public JsonNode NextSave => new JsonObject
	{
		{ "max", GetJsonFromStats( MaxStats ) },
		{ "now", GetJsonFromStats( NowStats ) }
	};

	public void LoadFromSave( JsonNode save )
	{
		if ( save.AsObject() is JsonObject obj )
		{
			if ( obj.TryGetPropertyNode( "max", out JsonObject maxJson ) )
				LoadStatsFromJson( MaxStats, maxJson );
			if ( obj.TryGetPropertyNode( "now", out JsonObject incrJson ) )
				LoadStatsFromJson( NowStats, incrJson );
		}
	}

	public void Reset()
	{
		MaxStats.Clear();
		NowStats.Clear();
	}

	public void ClearSave()
	{
		Reset();
	}

	private static JsonObject GetJsonFromStats( Dictionary<string, double> statBucket )
	{
		var json = new JsonObject();
		foreach ( var (key, value) in statBucket )
			json.Add( key, value );
		return json;
	}

	private static void LoadStatsFromJson( Dictionary<string, double> statBucket, JsonObject json )
	{
		foreach ( var (key, value) in json )
			statBucket[key] = value.GetValue<double>();
	}

	public void SetStat( string ident, double value )
	{
		NowStats[ident] = value;
		if ( !MaxStats.TryGetValue( ident, out var v ) || value > v )
			MaxStats[ident] = value;
	}

	public void IncrementStat( string ident, double amount )
	{
		SetStat( ident, NowStats.GetValueOrDefault( ident ) + amount );
	}

	public void MergeInto( StatContext other )
	{
		foreach ( var (ident, value) in AllNows )
			other.IncrementStat( ident, value );
		Reset();
	}

	public double GetMax( string ident ) => MaxStats.GetValueOrDefault( ident );
	public bool TryGetMax( string ident, out double value ) => MaxStats.TryGetValue( ident, out value );

	public double GetNow( string ident ) => NowStats.GetValueOrDefault( ident );
	public bool TryGetNow( string ident, out double value ) => NowStats.TryGetValue( ident, out value );

	public IEnumerable<KeyValuePair<string, double>> AllMaxes => MaxStats;
	public IEnumerable<KeyValuePair<string, double>> AllNows => NowStats;
}