package spells import ( "sort" "gitea.maximumdirect.net/eric/notarius/internal/modules/sharedassets/dnd" ) func canonicalizeResponse(response *extractionResponse, sourceID string) { if response == nil { return } for index := range response.SpellCasts { canonicalizeSpellCast(&response.SpellCasts[index], sourceID) } sort.SliceStable(response.SpellCasts, func(i, j int) bool { left, leftOK := earliestSourceUnit(response.SpellCasts[i]) right, rightOK := earliestSourceUnit(response.SpellCasts[j]) if leftOK != rightOK { return leftOK } if !leftOK { return false } return left < right }) } func canonicalizeSpellCast(spell *spellCastResponse, sourceID string) { for index := range spell.SourceRefs { spell.SourceRefs[index].SourceID = sourceID spell.SourceRefs[index].StartUnitID = canonicalUnitRef(spell.SourceRefs[index].StartUnitID) spell.SourceRefs[index].EndUnitID = canonicalUnitRef(spell.SourceRefs[index].EndUnitID) } sort.SliceStable(spell.SourceRefs, func(i, j int) bool { left := spell.SourceRefs[i] right := spell.SourceRefs[j] if left.StartUnitID.Int() != right.StartUnitID.Int() { return unitSortValue(left.StartUnitID) < unitSortValue(right.StartUnitID) } return unitSortValue(left.EndUnitID) < unitSortValue(right.EndUnitID) }) spell.SourceRefs = dedupeSourceRefs(spell.SourceRefs) } func canonicalUnitRef(ref dnd.UnitRef) dnd.UnitRef { value := ref.Int() if value <= 0 { return ref } return dnd.UnitRefFromInt(value) } func dedupeSourceRefs(refs []dnd.SourceRefResponse) []dnd.SourceRefResponse { if len(refs) < 2 { return refs } out := refs[:0] var previous dnd.SourceRefResponse for index, ref := range refs { if index > 0 && sameSourceRef(previous, ref) { continue } out = append(out, ref) previous = ref } return out } func sameSourceRef(left dnd.SourceRefResponse, right dnd.SourceRefResponse) bool { return left.SourceID == right.SourceID && left.StartUnitID.Int() == right.StartUnitID.Int() && left.EndUnitID.Int() == right.EndUnitID.Int() } func earliestSourceUnit(spell spellCastResponse) (int, bool) { for _, ref := range spell.SourceRefs { start := ref.StartUnitID.Int() if start > 0 { return start, true } } return 0, false } func unitSortValue(ref dnd.UnitRef) int { value := ref.Int() if value <= 0 { return int(^uint(0) >> 1) } return value }