Files
Christopher Wiebe b451f83174 Initial commit: Theriapolis baseline at port/godot branch point
Captures the pre-Godot-port state of the codebase. This is the rollback
anchor for the Godot port (M0 of theriapolis-rpg-implementation-plan-godot-port.md).
All Phase 0 through Phase 6.5 work is included; Phase 7 is in flight.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-30 20:40:51 -07:00

91 lines
3.1 KiB
C#

using Theriapolis.Core.Rules.Reputation;
namespace Theriapolis.Core.Persistence;
/// <summary>
/// Phase 6 M2 — bidirectional translator between the live
/// <see cref="PlayerReputation"/> aggregate and its serializable
/// <see cref="ReputationSnapshot"/>.
/// </summary>
public static class ReputationCodec
{
public static ReputationSnapshot Capture(PlayerReputation rep)
{
var snap = new ReputationSnapshot();
// Faction standings.
foreach (var (k, v) in rep.Factions.Standings)
snap.FactionStandings[k] = v;
// Personal records.
foreach (var pd in rep.Personal.Values)
{
snap.Personal.Add(new PersonalDispositionSnapshot
{
RoleTag = pd.RoleTag,
Score = pd.Score,
Trust = (byte)pd.Trust,
Betrayed = pd.Betrayed,
LastInteractionSeconds = pd.LastInteractionSeconds,
MemoryTags = pd.Memory.ToArray(),
Log = pd.Log.Select(CaptureEvent).ToArray(),
});
}
// Ledger.
foreach (var ev in rep.Ledger.Entries)
snap.Ledger.Add(CaptureEvent(ev));
return snap;
}
public static PlayerReputation Restore(ReputationSnapshot snap)
{
var rep = new PlayerReputation();
foreach (var (k, v) in snap.FactionStandings)
rep.Factions.Set(k, v);
foreach (var p in snap.Personal)
{
var pd = new PersonalDisposition
{
RoleTag = p.RoleTag,
Score = p.Score,
Trust = (TrustLevel)p.Trust,
Betrayed = p.Betrayed,
LastInteractionSeconds = p.LastInteractionSeconds,
};
foreach (var m in p.MemoryTags) pd.Memory.Add(m);
foreach (var ev in p.Log) pd.Log.Add(RestoreEvent(ev));
rep.Personal[p.RoleTag] = pd;
}
foreach (var ev in snap.Ledger) rep.Ledger.Append(RestoreEvent(ev));
return rep;
}
private static RepEventSnapshot CaptureEvent(RepEvent ev) => new()
{
SequenceId = ev.SequenceId,
Kind = (byte)ev.Kind,
FactionId = ev.FactionId,
RoleTag = ev.RoleTag,
Magnitude = ev.Magnitude,
Note = ev.Note,
OriginTileX = ev.OriginTileX,
OriginTileY = ev.OriginTileY,
TimestampSeconds = ev.TimestampSeconds,
};
private static RepEvent RestoreEvent(RepEventSnapshot s) => new()
{
SequenceId = s.SequenceId,
Kind = (RepEventKind)s.Kind,
FactionId = s.FactionId,
RoleTag = s.RoleTag,
Magnitude = s.Magnitude,
Note = s.Note,
OriginTileX = s.OriginTileX,
OriginTileY = s.OriginTileY,
TimestampSeconds = s.TimestampSeconds,
};
}