package itemoccurrences import ( "fmt" "sort" "gitea.maximumdirect.net/eric/notarius/internal/core/source" "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd" itemregistry "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/items/registry" "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/shared" ) type orderedItemOccurrence struct { value dnd.ItemOccurrence earliest int hasEvidence bool } func canonicalItemOccurrenceList(response extractionResponse, order shared.SourceRefOrder, sourceID string, registry *itemregistry.Registry) (dnd.ItemOccurrenceList, error) { if response.Occurrences == nil { return dnd.ItemOccurrenceList{}, nil } ordered := make([]orderedItemOccurrence, len(response.Occurrences)) for index, occurrence := range response.Occurrences { item, found := registry.Lookup(occurrence.Name) if !found { return dnd.ItemOccurrenceList{}, fmt.Errorf("occurrences[%d].name is not in the item registry", index) } refs := order.Canonicalize(itemOccurrenceSourceRefs(occurrence.SourceRefs, sourceID)) earliest, hasEvidence := order.EarliestValid(refs) ordered[index] = orderedItemOccurrence{ value: dnd.ItemOccurrence{ ItemID: item.ID, Name: item.Name, Kind: dnd.ItemOccurrenceKind(occurrence.Kind), Quantity: cloneQuantity(occurrence.Quantity), From: occurrence.From, To: occurrence.To, SourceRefs: refs, }, earliest: earliest, hasEvidence: hasEvidence, } } sort.SliceStable(ordered, func(left, right int) bool { if ordered[left].hasEvidence != ordered[right].hasEvidence { return ordered[left].hasEvidence } if !ordered[left].hasEvidence { return false } return ordered[left].earliest < ordered[right].earliest }) occurrences := make([]dnd.ItemOccurrence, len(ordered)) for index, occurrence := range ordered { occurrences[index] = occurrence.value } return dnd.ItemOccurrenceList{Occurrences: occurrences}, nil } func itemOccurrenceSourceRefs(refs []itemOccurrenceSourceRefResponse, sourceID string) []source.SourceRef { if refs == nil { return nil } values := make([]source.SourceRef, len(refs)) for index, ref := range refs { values[index] = source.SourceRef{SourceID: sourceID, StartUnitID: ref.StartSegment, EndUnitID: ref.EndSegment} } return values } func cloneQuantity(value *int) *int { if value == nil { return nil } quantity := *value return &quantity }