Add NPC interaction normalization

This commit is contained in:
2026-07-23 13:42:37 +00:00
parent cb7f145c76
commit ed2b6f4580
6 changed files with 700 additions and 9 deletions

View File

@@ -57,6 +57,27 @@ func appendCombatTurnLists(values []dnd.CombatTurnList) (dnd.CombatTurnList, err
return combined, nil
}
func appendNPCInteractionLists(values []dnd.NPCInteractionList) (dnd.NPCInteractionList, error) {
count := 0
present := false
for _, value := range values {
if value.Interactions != nil {
present = true
}
count += len(value.Interactions)
}
if !present {
return dnd.NPCInteractionList{}, nil
}
combined := dnd.NPCInteractionList{Interactions: make([]dnd.NPCInteraction, 0, count)}
for _, value := range values {
for _, interaction := range value.Interactions {
combined.Interactions = append(combined.Interactions, cloneNPCInteraction(interaction))
}
}
return combined, nil
}
func cloneCombatTurn(value dnd.CombatTurn) dnd.CombatTurn {
clone := value
if value.SourceRefs != nil {
@@ -64,3 +85,11 @@ func cloneCombatTurn(value dnd.CombatTurn) dnd.CombatTurn {
}
return clone
}
func cloneNPCInteraction(value dnd.NPCInteraction) dnd.NPCInteraction {
clone := value
if value.SourceRefs != nil {
clone.SourceRefs = append([]source.SourceRef(nil), value.SourceRefs...)
}
return clone
}

View File

@@ -185,6 +185,33 @@ func TestAppendNPCListsPreservesOrderAndArrayPresence(t *testing.T) {
}
}
func TestAppendNPCInteractionListsPreservesOrderPresenceAndOwnership(t *testing.T) {
refs := []source.SourceRef{{SourceID: "session", StartUnitID: 10, EndUnitID: 10}}
input := []dnd.NPCInteractionList{
{},
{Interactions: []dnd.NPCInteraction{}},
{Interactions: []dnd.NPCInteraction{{Name: "Aria", Kind: dnd.NPCInteractionKindDialogue, SourceRefs: refs}}},
{Interactions: []dnd.NPCInteraction{{Name: "Borin", Kind: dnd.NPCInteractionKindMentioned, SourceRefs: []source.SourceRef{{SourceID: "session", StartUnitID: 20, EndUnitID: 20}}}}},
}
got, err := appendNPCInteractionLists(input)
if err != nil {
t.Fatalf("appendNPCInteractionLists() error = %v", err)
}
if got.Interactions == nil || !reflect.DeepEqual([]string{got.Interactions[0].Name, got.Interactions[1].Name}, []string{"Aria", "Borin"}) {
t.Fatalf("combined interactions = %#v", got)
}
got.Interactions[0].SourceRefs[0].StartUnitID = 999
if input[2].Interactions[0].SourceRefs[0].StartUnitID == 999 {
t.Fatal("merged interactions share source reference storage")
}
for _, values := range [][]dnd.NPCInteractionList{nil, []dnd.NPCInteractionList{{}, {}}} {
result, err := appendNPCInteractionLists(values)
if err != nil || result.Interactions != nil {
t.Fatalf("nil-only merge = %#v, %v; want nil interactions", result, err)
}
}
}
func TestAppendCombatTurnListsPreservesOrderPresenceAndOwnership(t *testing.T) {
refs := []source.SourceRef{{SourceID: "session", StartUnitID: 1, EndUnitID: 1}}
input := []dnd.CombatTurnList{