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

@@ -149,9 +149,12 @@ func issuesFor(doc *source.SourceDocument, value dnd.NPCInteractionList, npcRegi
}
func interactionLess(doc *source.SourceDocument, left, right dnd.NPCInteraction) bool {
leftPosition, _ := earliestSourcePosition(doc, left)
rightPosition, _ := earliestSourcePosition(doc, right)
if leftPosition != rightPosition {
leftPosition, leftHasEvidence := earliestSourcePosition(doc, left)
rightPosition, rightHasEvidence := earliestSourcePosition(doc, right)
if leftHasEvidence != rightHasEvidence {
return leftHasEvidence
}
if leftHasEvidence && leftPosition != rightPosition {
return leftPosition < rightPosition
}
leftKey := identity.ComparisonKey(left.Name)
@@ -182,14 +185,26 @@ func sourceRefLess(doc *source.SourceDocument, left, right source.SourceRef) boo
if left.SourceID != right.SourceID {
return left.SourceID < right.SourceID
}
leftStart, _ := source.UnitIndex(doc, left.StartUnitID)
rightStart, _ := source.UnitIndex(doc, right.StartUnitID)
if leftStart != rightStart {
leftStart, leftStartOK := source.UnitIndex(doc, left.StartUnitID)
rightStart, rightStartOK := source.UnitIndex(doc, right.StartUnitID)
if leftStartOK != rightStartOK {
return leftStartOK
}
if leftStartOK && leftStart != rightStart {
return leftStart < rightStart
}
leftEnd, _ := source.UnitIndex(doc, left.EndUnitID)
rightEnd, _ := source.UnitIndex(doc, right.EndUnitID)
return leftEnd < rightEnd
if left.StartUnitID != right.StartUnitID {
return left.StartUnitID < right.StartUnitID
}
leftEnd, leftEndOK := source.UnitIndex(doc, left.EndUnitID)
rightEnd, rightEndOK := source.UnitIndex(doc, right.EndUnitID)
if leftEndOK != rightEndOK {
return leftEndOK
}
if leftEndOK && leftEnd != rightEnd {
return leftEnd < rightEnd
}
return left.EndUnitID < right.EndUnitID
}
func earliestSourcePosition(doc *source.SourceDocument, interaction dnd.NPCInteraction) (int, bool) {

View File

@@ -60,6 +60,18 @@ func TestValidatorRejectsOwnedCanonicalNameReferenceOrderListOrderAndDuplicates(
}
}
func TestValidatorAcceptsValidEvidenceBeforeInvalidEvidence(t *testing.T) {
references := registryReferences(t, "Aria", "Borin")
value := dnd.NPCInteractionList{Interactions: []dnd.NPCInteraction{
{Name: "Borin", Kind: dnd.NPCInteractionKindMentioned, SourceRefs: []source.SourceRef{{SourceID: "session", StartUnitID: 20, EndUnitID: 20}}},
{Name: "Aria", Kind: dnd.NPCInteractionKindDialogue, SourceRefs: []source.SourceRef{{SourceID: "session", StartUnitID: 99, EndUnitID: 99}}},
}}
result, err := newValidator(t, references).Validate(context.Background(), request(references, value))
if err != nil || !result.Approved {
t.Fatalf("Validate() = %#v, %v", result, err)
}
}
func TestValidatorDefersShapeAndSourceReferenceFailuresAndRequiresRegistry(t *testing.T) {
references := registryReferences(t, "Aria", "Borin")
for _, value := range []dnd.NPCInteractionList{