Reuse document indexes in D&D normalization
This commit is contained in:
@@ -156,28 +156,25 @@ func planFromResponse(doc *source.SourceDocument, response chunkResponse) (sourc
|
|||||||
return source.ChunkPlan{}, fmt.Errorf("scenes must not be empty")
|
return source.ChunkPlan{}, fmt.Errorf("scenes must not be empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
unitIndexes := make(map[int]int, len(doc.Units))
|
index := source.NewDocumentIndex(doc)
|
||||||
for i, unit := range doc.Units {
|
|
||||||
unitIndexes[unit.ID] = i
|
|
||||||
}
|
|
||||||
|
|
||||||
ranges := make([]source.ChunkRange, 0, len(response.Scenes))
|
ranges := make([]source.ChunkRange, 0, len(response.Scenes))
|
||||||
previousEnd := -1
|
previousEnd := -1
|
||||||
for i, scene := range response.Scenes {
|
for i, scene := range response.Scenes {
|
||||||
startUnitID, err := shared.ResolveUnitID(doc, "start_unit_id", scene.StartUnitID)
|
startUnitID, err := shared.ResolveUnitID(index, "start_unit_id", scene.StartUnitID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return source.ChunkPlan{}, fmt.Errorf("scene[%d] %w", i, err)
|
return source.ChunkPlan{}, fmt.Errorf("scene[%d] %w", i, err)
|
||||||
}
|
}
|
||||||
endUnitID, err := shared.ResolveUnitID(doc, "end_unit_id", scene.EndUnitID)
|
endUnitID, err := shared.ResolveUnitID(index, "end_unit_id", scene.EndUnitID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return source.ChunkPlan{}, fmt.Errorf("scene[%d] %w", i, err)
|
return source.ChunkPlan{}, fmt.Errorf("scene[%d] %w", i, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
startIndex, ok := unitIndexes[startUnitID]
|
startIndex, ok := index.Position(startUnitID)
|
||||||
if !ok {
|
if !ok {
|
||||||
return source.ChunkPlan{}, fmt.Errorf("scene[%d] start_unit_id %d was not found", i, startUnitID)
|
return source.ChunkPlan{}, fmt.Errorf("scene[%d] start_unit_id %d was not found", i, startUnitID)
|
||||||
}
|
}
|
||||||
endIndex, ok := unitIndexes[endUnitID]
|
endIndex, ok := index.Position(endUnitID)
|
||||||
if !ok {
|
if !ok {
|
||||||
return source.ChunkPlan{}, fmt.Errorf("scene[%d] end_unit_id %d was not found", i, endUnitID)
|
return source.ChunkPlan{}, fmt.Errorf("scene[%d] end_unit_id %d was not found", i, endUnitID)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -110,8 +110,9 @@ func (n *Normalizer) Normalize(ctx context.Context, req contracts.TypedNormalize
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return contracts.TypedNormalizeResult[dnd.CombatTurnList]{}, normalizerErrorf("resolve NPC registry: %w", err)
|
return contracts.TypedNormalizeResult[dnd.CombatTurnList]{}, normalizerErrorf("resolve NPC registry: %w", err)
|
||||||
}
|
}
|
||||||
order := shared.NewSourceRefOrder(req.Source)
|
index := source.NewDocumentIndex(req.Source)
|
||||||
value, warnings := normalizeList(req.MergeOutput.Value, req.Source, order, npcRegistry)
|
order := shared.NewSourceRefOrderWithIndex(req.Source, index)
|
||||||
|
value, warnings := normalizeList(req.MergeOutput.Value, index, order, npcRegistry)
|
||||||
return contracts.TypedNormalizeResult[dnd.CombatTurnList]{Value: value, Warnings: warnings}, nil
|
return contracts.TypedNormalizeResult[dnd.CombatTurnList]{Value: value, Warnings: warnings}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,7 +128,7 @@ type actorCanonicalization struct {
|
|||||||
to string
|
to string
|
||||||
}
|
}
|
||||||
|
|
||||||
func normalizeList(input dnd.CombatTurnList, doc *source.SourceDocument, order shared.SourceRefOrder, registry *npcregistry.Registry) (dnd.CombatTurnList, []contracts.Warning) {
|
func normalizeList(input dnd.CombatTurnList, documentIndex source.DocumentIndex, order shared.SourceRefOrder, registry *npcregistry.Registry) (dnd.CombatTurnList, []contracts.Warning) {
|
||||||
if input.CombatTurns == nil {
|
if input.CombatTurns == nil {
|
||||||
return dnd.CombatTurnList{}, nil
|
return dnd.CombatTurnList{}, nil
|
||||||
}
|
}
|
||||||
@@ -182,7 +183,7 @@ func normalizeList(input dnd.CombatTurnList, doc *source.SourceDocument, order s
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
output, duplicateWarnings := collapseDuplicates(records, doc)
|
output, duplicateWarnings := collapseDuplicates(records, documentIndex)
|
||||||
warnings = append(warnings, duplicateWarnings...)
|
warnings = append(warnings, duplicateWarnings...)
|
||||||
return dnd.CombatTurnList{CombatTurns: output}, warnings
|
return dnd.CombatTurnList{CombatTurns: output}, warnings
|
||||||
}
|
}
|
||||||
@@ -200,8 +201,7 @@ func normalizeTurn(input dnd.CombatTurn, order shared.SourceRefOrder, registry *
|
|||||||
actorChange = &actorCanonicalization{from: input.Actor, to: output.Actor}
|
actorChange = &actorCanonicalization{from: input.Actor, to: output.Actor}
|
||||||
}
|
}
|
||||||
|
|
||||||
canonicalRefs, _, _ := canonicalizeSourceRefs(order, input.SourceRefs)
|
output.SourceRefs = order.Canonicalize(input.SourceRefs)
|
||||||
output.SourceRefs = canonicalRefs
|
|
||||||
refsChanged := !sourceRefsEqual(input.SourceRefs, output.SourceRefs)
|
refsChanged := !sourceRefsEqual(input.SourceRefs, output.SourceRefs)
|
||||||
return output, actorChange, refsChanged
|
return output, actorChange, refsChanged
|
||||||
}
|
}
|
||||||
@@ -227,17 +227,12 @@ func sourceRefsEqual(left, right []source.SourceRef) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func canonicalizeSourceRefs(order shared.SourceRefOrder, input []source.SourceRef) ([]source.SourceRef, bool, int) {
|
|
||||||
canonical := order.Canonicalize(input)
|
|
||||||
return canonical, !sourceRefsEqual(input, canonical), len(input) - len(canonical)
|
|
||||||
}
|
|
||||||
|
|
||||||
type duplicateGroup struct {
|
type duplicateGroup struct {
|
||||||
retainedIndex int
|
retainedIndex int
|
||||||
removed []int
|
removed []int
|
||||||
}
|
}
|
||||||
|
|
||||||
func collapseDuplicates(records []normalizedRecord, doc *source.SourceDocument) ([]dnd.CombatTurn, []contracts.Warning) {
|
func collapseDuplicates(records []normalizedRecord, documentIndex source.DocumentIndex) ([]dnd.CombatTurn, []contracts.Warning) {
|
||||||
if len(records) == 0 {
|
if len(records) == 0 {
|
||||||
return make([]dnd.CombatTurn, 0), nil
|
return make([]dnd.CombatTurn, 0), nil
|
||||||
}
|
}
|
||||||
@@ -246,7 +241,7 @@ func collapseDuplicates(records []normalizedRecord, doc *source.SourceDocument)
|
|||||||
groups := make([]duplicateGroup, 0)
|
groups := make([]duplicateGroup, 0)
|
||||||
groupByKey := make(map[string]int)
|
groupByKey := make(map[string]int)
|
||||||
for index, record := range records {
|
for index, record := range records {
|
||||||
key, eligible := duplicateKey(record.turn, doc)
|
key, eligible := duplicateKey(record.turn, documentIndex)
|
||||||
if !eligible {
|
if !eligible {
|
||||||
keep[index] = true
|
keep[index] = true
|
||||||
continue
|
continue
|
||||||
@@ -278,12 +273,12 @@ func collapseDuplicates(records []normalizedRecord, doc *source.SourceDocument)
|
|||||||
return output, warnings
|
return output, warnings
|
||||||
}
|
}
|
||||||
|
|
||||||
func duplicateKey(turn dnd.CombatTurn, doc *source.SourceDocument) (string, bool) {
|
func duplicateKey(turn dnd.CombatTurn, documentIndex source.DocumentIndex) (string, bool) {
|
||||||
if len(turn.SourceRefs) == 0 {
|
if len(turn.SourceRefs) == 0 {
|
||||||
return "", false
|
return "", false
|
||||||
}
|
}
|
||||||
for _, ref := range turn.SourceRefs {
|
for _, ref := range turn.SourceRefs {
|
||||||
if source.ValidateRef(doc, ref) != nil {
|
if documentIndex.ValidateRef(ref) != nil {
|
||||||
return "", false
|
return "", false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -118,8 +118,9 @@ func (n *Normalizer) Normalize(ctx context.Context, req contracts.TypedNormalize
|
|||||||
if !registry.Bound() {
|
if !registry.Bound() {
|
||||||
return contracts.TypedNormalizeResult[dnd.NPCInteractionList]{}, normalizerErrorf("NPC registry reference is required")
|
return contracts.TypedNormalizeResult[dnd.NPCInteractionList]{}, normalizerErrorf("NPC registry reference is required")
|
||||||
}
|
}
|
||||||
order := shared.NewSourceRefOrder(req.Source)
|
index := source.NewDocumentIndex(req.Source)
|
||||||
value, warnings := normalizeList(req.MergeOutput.Value, req.Source, order, registry)
|
order := shared.NewSourceRefOrderWithIndex(req.Source, index)
|
||||||
|
value, warnings := normalizeList(req.MergeOutput.Value, index, order, registry)
|
||||||
return contracts.TypedNormalizeResult[dnd.NPCInteractionList]{Value: value, Warnings: warnings}, nil
|
return contracts.TypedNormalizeResult[dnd.NPCInteractionList]{Value: value, Warnings: warnings}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,7 +134,7 @@ type nameCanonicalization struct {
|
|||||||
to string
|
to string
|
||||||
}
|
}
|
||||||
|
|
||||||
func normalizeList(input dnd.NPCInteractionList, doc *source.SourceDocument, order shared.SourceRefOrder, registry *npcregistry.Registry) (dnd.NPCInteractionList, []contracts.Warning) {
|
func normalizeList(input dnd.NPCInteractionList, documentIndex source.DocumentIndex, order shared.SourceRefOrder, registry *npcregistry.Registry) (dnd.NPCInteractionList, []contracts.Warning) {
|
||||||
if input.Interactions == nil {
|
if input.Interactions == nil {
|
||||||
return dnd.NPCInteractionList{}, nil
|
return dnd.NPCInteractionList{}, nil
|
||||||
}
|
}
|
||||||
@@ -175,7 +176,7 @@ func normalizeList(input dnd.NPCInteractionList, doc *source.SourceDocument, ord
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
output, duplicateWarnings := collapseDuplicates(records, doc)
|
output, duplicateWarnings := collapseDuplicates(records, documentIndex)
|
||||||
warnings = append(warnings, duplicateWarnings...)
|
warnings = append(warnings, duplicateWarnings...)
|
||||||
return dnd.NPCInteractionList{Interactions: output},
|
return dnd.NPCInteractionList{Interactions: output},
|
||||||
diagnostics.LimitWarnings(warnings, "npc_interactions", ReasonCodeWarningsOmitted)
|
diagnostics.LimitWarnings(warnings, "npc_interactions", ReasonCodeWarningsOmitted)
|
||||||
@@ -207,7 +208,7 @@ type duplicateGroup struct {
|
|||||||
removed []int
|
removed []int
|
||||||
}
|
}
|
||||||
|
|
||||||
func collapseDuplicates(records []normalizedRecord, doc *source.SourceDocument) ([]dnd.NPCInteraction, []contracts.Warning) {
|
func collapseDuplicates(records []normalizedRecord, documentIndex source.DocumentIndex) ([]dnd.NPCInteraction, []contracts.Warning) {
|
||||||
if len(records) == 0 {
|
if len(records) == 0 {
|
||||||
return make([]dnd.NPCInteraction, 0), nil
|
return make([]dnd.NPCInteraction, 0), nil
|
||||||
}
|
}
|
||||||
@@ -215,7 +216,7 @@ func collapseDuplicates(records []normalizedRecord, doc *source.SourceDocument)
|
|||||||
groups := make([]duplicateGroup, 0)
|
groups := make([]duplicateGroup, 0)
|
||||||
groupByKey := make(map[string]int)
|
groupByKey := make(map[string]int)
|
||||||
for index, record := range records {
|
for index, record := range records {
|
||||||
if !interactionmodel.ValidSourceRefs(doc, record.interaction.SourceRefs) {
|
if !interactionmodel.ValidSourceRefs(documentIndex, record.interaction.SourceRefs) {
|
||||||
keep[index] = true
|
keep[index] = true
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ func normalizeList(input dnd.NPCList, order shared.SourceRefOrder) (dnd.NPCList,
|
|||||||
func normalizeRecord(input dnd.NPC, order shared.SourceRefOrder) (dnd.NPC, bool, bool) {
|
func normalizeRecord(input dnd.NPC, order shared.SourceRefOrder) (dnd.NPC, bool, bool) {
|
||||||
output := cloneNPC(input)
|
output := cloneNPC(input)
|
||||||
output.Name = identity.NormalizeDisplay(input.Name)
|
output.Name = identity.NormalizeDisplay(input.Name)
|
||||||
output.SourceRefs, _, _ = canonicalizeSourceRefs(order, input.SourceRefs)
|
output.SourceRefs = order.Canonicalize(input.SourceRefs)
|
||||||
output.ID = identity.DeriveID(output.Name)
|
output.ID = identity.DeriveID(output.Name)
|
||||||
return output, input.Name != output.Name, !reflect.DeepEqual(input.SourceRefs, output.SourceRefs)
|
return output, input.Name != output.Name, !reflect.DeepEqual(input.SourceRefs, output.SourceRefs)
|
||||||
}
|
}
|
||||||
@@ -150,16 +150,11 @@ func consolidate(records []normalizedRecord, members []int, order shared.SourceR
|
|||||||
for _, member := range members[1:] {
|
for _, member := range members[1:] {
|
||||||
output.SourceRefs = append(output.SourceRefs, records[member].npc.SourceRefs...)
|
output.SourceRefs = append(output.SourceRefs, records[member].npc.SourceRefs...)
|
||||||
}
|
}
|
||||||
output.SourceRefs, _, _ = canonicalizeSourceRefs(order, output.SourceRefs)
|
output.SourceRefs = order.Canonicalize(output.SourceRefs)
|
||||||
output.ID = identity.DeriveID(output.Name)
|
output.ID = identity.DeriveID(output.Name)
|
||||||
return output, !reflect.DeepEqual(originalRefs, output.SourceRefs)
|
return output, !reflect.DeepEqual(originalRefs, output.SourceRefs)
|
||||||
}
|
}
|
||||||
|
|
||||||
func canonicalizeSourceRefs(order shared.SourceRefOrder, input []source.SourceRef) ([]source.SourceRef, bool, int) {
|
|
||||||
canonical := order.Canonicalize(input)
|
|
||||||
return canonical, !reflect.DeepEqual(input, canonical), len(input) - len(canonical)
|
|
||||||
}
|
|
||||||
|
|
||||||
func cloneSourceRefs(input []source.SourceRef) []source.SourceRef {
|
func cloneSourceRefs(input []source.SourceRef) []source.SourceRef {
|
||||||
if input == nil {
|
if input == nil {
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -78,26 +78,23 @@ func normalizeList(input dnd.SceneDescriptionList, doc *source.SourceDocument) (
|
|||||||
return dnd.SceneDescriptionList{}, fmt.Errorf("scenes must not be empty")
|
return dnd.SceneDescriptionList{}, fmt.Errorf("scenes must not be empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
unitPositions := make(map[int]int, len(doc.Units))
|
documentIndex := source.NewDocumentIndex(doc)
|
||||||
for index, unit := range doc.Units {
|
|
||||||
unitPositions[unit.ID] = index
|
|
||||||
}
|
|
||||||
output := dnd.SceneDescriptionList{Scenes: make([]dnd.SceneDescription, len(input.Scenes))}
|
output := dnd.SceneDescriptionList{Scenes: make([]dnd.SceneDescription, len(input.Scenes))}
|
||||||
for index, scene := range input.Scenes {
|
for sceneIndex, scene := range input.Scenes {
|
||||||
scene.Title = strings.TrimSpace(scene.Title)
|
scene.Title = strings.TrimSpace(scene.Title)
|
||||||
scene.Summary = strings.TrimSpace(scene.Summary)
|
scene.Summary = strings.TrimSpace(scene.Summary)
|
||||||
if err := shape.Validate(dnd.SceneDescriptionList{Scenes: []dnd.SceneDescription{scene}}); err != nil {
|
if err := shape.Validate(dnd.SceneDescriptionList{Scenes: []dnd.SceneDescription{scene}}); err != nil {
|
||||||
return dnd.SceneDescriptionList{}, fmt.Errorf("scenes[%d]: %w", index, err)
|
return dnd.SceneDescriptionList{}, fmt.Errorf("scenes[%d]: %w", sceneIndex, err)
|
||||||
}
|
}
|
||||||
if err := source.ValidateRef(doc, scene.SourceRef); err != nil {
|
if err := documentIndex.ValidateRef(scene.SourceRef); err != nil {
|
||||||
return dnd.SceneDescriptionList{}, fmt.Errorf("scenes[%d].source_ref: %s", index, diagnostics.Truncate(err.Error()))
|
return dnd.SceneDescriptionList{}, fmt.Errorf("scenes[%d].source_ref: %s", sceneIndex, diagnostics.Truncate(err.Error()))
|
||||||
}
|
}
|
||||||
output.Scenes[index] = scene
|
output.Scenes[sceneIndex] = scene
|
||||||
}
|
}
|
||||||
|
|
||||||
sort.SliceStable(output.Scenes, func(left, right int) bool {
|
sort.SliceStable(output.Scenes, func(left, right int) bool {
|
||||||
leftStart := unitPositions[output.Scenes[left].SourceRef.StartUnitID]
|
leftStart, _ := documentIndex.Position(output.Scenes[left].SourceRef.StartUnitID)
|
||||||
rightStart := unitPositions[output.Scenes[right].SourceRef.StartUnitID]
|
rightStart, _ := documentIndex.Position(output.Scenes[right].SourceRef.StartUnitID)
|
||||||
if leftStart != rightStart {
|
if leftStart != rightStart {
|
||||||
return leftStart < rightStart
|
return leftStart < rightStart
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -97,9 +97,10 @@ func (n *Normalizer) Normalize(ctx context.Context, req contracts.TypedNormalize
|
|||||||
return contracts.TypedNormalizeResult[dnd.SpellList]{}, normalizerErrorf("context error before normalize: %w", err)
|
return contracts.TypedNormalizeResult[dnd.SpellList]{}, normalizerErrorf("context error before normalize: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
order := shared.NewSourceRefOrder(req.Source)
|
index := source.NewDocumentIndex(req.Source)
|
||||||
|
order := shared.NewSourceRefOrderWithIndex(req.Source, index)
|
||||||
value, warnings := normalizeSpellList(req.MergeOutput.Value, n.effectiveCatalog, order)
|
value, warnings := normalizeSpellList(req.MergeOutput.Value, n.effectiveCatalog, order)
|
||||||
value, duplicateWarnings := collapseDuplicateSpellCasts(value, req.Source, n.effectiveCatalog)
|
value, duplicateWarnings := collapseDuplicateSpellCasts(value, index, n.effectiveCatalog)
|
||||||
warnings = append(warnings, duplicateWarnings...)
|
warnings = append(warnings, duplicateWarnings...)
|
||||||
return contracts.TypedNormalizeResult[dnd.SpellList]{Value: value, Warnings: warnings}, nil
|
return contracts.TypedNormalizeResult[dnd.SpellList]{Value: value, Warnings: warnings}, nil
|
||||||
}
|
}
|
||||||
@@ -173,7 +174,7 @@ type duplicateGroup struct {
|
|||||||
removed []int
|
removed []int
|
||||||
}
|
}
|
||||||
|
|
||||||
func collapseDuplicateSpellCasts(input dnd.SpellList, doc *source.SourceDocument, catalog spellcatalog.EffectiveCatalog) (dnd.SpellList, []contracts.Warning) {
|
func collapseDuplicateSpellCasts(input dnd.SpellList, documentIndex source.DocumentIndex, catalog spellcatalog.EffectiveCatalog) (dnd.SpellList, []contracts.Warning) {
|
||||||
if len(input.SpellCasts) == 0 {
|
if len(input.SpellCasts) == 0 {
|
||||||
return input, nil
|
return input, nil
|
||||||
}
|
}
|
||||||
@@ -182,7 +183,7 @@ func collapseDuplicateSpellCasts(input dnd.SpellList, doc *source.SourceDocument
|
|||||||
groups := make([]duplicateGroup, 0)
|
groups := make([]duplicateGroup, 0)
|
||||||
groupByKey := make(map[string]int)
|
groupByKey := make(map[string]int)
|
||||||
for index, cast := range input.SpellCasts {
|
for index, cast := range input.SpellCasts {
|
||||||
key, eligible := duplicateKey(cast, doc, catalog)
|
key, eligible := duplicateKey(cast, documentIndex, catalog)
|
||||||
if !eligible {
|
if !eligible {
|
||||||
keep[index] = true
|
keep[index] = true
|
||||||
continue
|
continue
|
||||||
@@ -225,13 +226,13 @@ func collapseDuplicateSpellCasts(input dnd.SpellList, doc *source.SourceDocument
|
|||||||
return output, warnings
|
return output, warnings
|
||||||
}
|
}
|
||||||
|
|
||||||
func duplicateKey(cast dnd.SpellCast, doc *source.SourceDocument, catalog spellcatalog.EffectiveCatalog) (string, bool) {
|
func duplicateKey(cast dnd.SpellCast, documentIndex source.DocumentIndex, catalog spellcatalog.EffectiveCatalog) (string, bool) {
|
||||||
canonicalName, resolved := catalog.Lookup(cast.Spell)
|
canonicalName, resolved := catalog.Lookup(cast.Spell)
|
||||||
if !resolved || len(cast.SourceRefs) == 0 {
|
if !resolved || len(cast.SourceRefs) == 0 {
|
||||||
return "", false
|
return "", false
|
||||||
}
|
}
|
||||||
for _, ref := range cast.SourceRefs {
|
for _, ref := range cast.SourceRefs {
|
||||||
if source.ValidateRef(doc, ref) != nil {
|
if documentIndex.ValidateRef(ref) != nil {
|
||||||
return "", false
|
return "", false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,12 +52,12 @@ func Less(order shared.SourceRefOrder, left, right dnd.NPCInteraction) bool {
|
|||||||
|
|
||||||
// ValidSourceRefs reports whether an interaction has non-empty, valid
|
// ValidSourceRefs reports whether an interaction has non-empty, valid
|
||||||
// current-document evidence.
|
// current-document evidence.
|
||||||
func ValidSourceRefs(doc *source.SourceDocument, refs []source.SourceRef) bool {
|
func ValidSourceRefs(index source.DocumentIndex, refs []source.SourceRef) bool {
|
||||||
if len(refs) == 0 {
|
if len(refs) == 0 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
for _, ref := range refs {
|
for _, ref := range refs {
|
||||||
if source.ValidateRef(doc, ref) != nil {
|
if index.ValidateRef(ref) != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,11 +77,11 @@ func (ref UnitRef) MarshalJSON() ([]byte, error) {
|
|||||||
return json.Marshal(ref.String())
|
return json.Marshal(ref.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
func ResolveUnitID(doc *source.SourceDocument, field string, ref UnitRef) (int, error) {
|
func ResolveUnitID(index source.DocumentIndex, field string, ref UnitRef) (int, error) {
|
||||||
if ref.value <= 0 {
|
if ref.value <= 0 {
|
||||||
return 0, fmt.Errorf("%s must be positive", field)
|
return 0, fmt.Errorf("%s must be positive", field)
|
||||||
}
|
}
|
||||||
if _, ok := source.UnitIndex(doc, ref.value); !ok {
|
if _, ok := index.Position(ref.value); !ok {
|
||||||
return 0, fmt.Errorf("%s %d was not found", field, ref.value)
|
return 0, fmt.Errorf("%s %d was not found", field, ref.value)
|
||||||
}
|
}
|
||||||
return ref.value, nil
|
return ref.value, nil
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ func TestUnitRefUnmarshalRejectsNonIntegerValues(t *testing.T) {
|
|||||||
func TestResolveUnitIDReturnsExistingIntegerSourceUnitID(t *testing.T) {
|
func TestResolveUnitIDReturnsExistingIntegerSourceUnitID(t *testing.T) {
|
||||||
doc := unitRefSourceDocument(2, 10)
|
doc := unitRefSourceDocument(2, 10)
|
||||||
|
|
||||||
got, err := ResolveUnitID(doc, "start_unit_id", UnitRefFromInt(2))
|
got, err := ResolveUnitID(source.NewDocumentIndex(doc), "start_unit_id", UnitRefFromInt(2))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("ResolveUnitID() error = %v, want nil", err)
|
t.Fatalf("ResolveUnitID() error = %v, want nil", err)
|
||||||
}
|
}
|
||||||
@@ -56,7 +56,7 @@ func TestResolveUnitIDReturnsExistingIntegerSourceUnitID(t *testing.T) {
|
|||||||
func TestResolveUnitIDDoesNotFallbackToOneBasedUnitNumber(t *testing.T) {
|
func TestResolveUnitIDDoesNotFallbackToOneBasedUnitNumber(t *testing.T) {
|
||||||
doc := unitRefSourceDocument(10, 20)
|
doc := unitRefSourceDocument(10, 20)
|
||||||
|
|
||||||
_, err := ResolveUnitID(doc, "end_unit_id", UnitRefFromInt(2))
|
_, err := ResolveUnitID(source.NewDocumentIndex(doc), "end_unit_id", UnitRefFromInt(2))
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatal("ResolveUnitID() error = nil, want missing source-unit ID")
|
t.Fatal("ResolveUnitID() error = nil, want missing source-unit ID")
|
||||||
}
|
}
|
||||||
@@ -65,7 +65,7 @@ func TestResolveUnitIDDoesNotFallbackToOneBasedUnitNumber(t *testing.T) {
|
|||||||
func TestResolveUnitIDRejectsMissingUnit(t *testing.T) {
|
func TestResolveUnitIDRejectsMissingUnit(t *testing.T) {
|
||||||
doc := unitRefSourceDocument(1)
|
doc := unitRefSourceDocument(1)
|
||||||
|
|
||||||
_, err := ResolveUnitID(doc, "start_unit_id", UnitRefFromInt(9))
|
_, err := ResolveUnitID(source.NewDocumentIndex(doc), "start_unit_id", UnitRefFromInt(9))
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatal("ResolveUnitID() error = nil, want error")
|
t.Fatal("ResolveUnitID() error = nil, want error")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,10 +107,8 @@ func (v *Validator) Validate(_ context.Context, req contracts.TypedValidationReq
|
|||||||
|
|
||||||
func allSourceRefsValid(index source.DocumentIndex, value dnd.NPCInteractionList) bool {
|
func allSourceRefsValid(index source.DocumentIndex, value dnd.NPCInteractionList) bool {
|
||||||
for _, interaction := range value.Interactions {
|
for _, interaction := range value.Interactions {
|
||||||
for _, ref := range interaction.SourceRefs {
|
if !interactionmodel.ValidSourceRefs(index, interaction.SourceRefs) {
|
||||||
if index.ValidateRef(ref) != nil {
|
return false
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
|||||||
Reference in New Issue
Block a user