package spells import ( "sort" "gitea.maximumdirect.net/eric/notarius/internal/core/source" "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd" ) func canonicalizeResponse(response *extractionResponse) { if response == nil { return } for index := range response.SpellCasts { canonicalizeSpellCast(&response.SpellCasts[index]) } 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) { sort.SliceStable(spell.SourceRefs, func(i, j int) bool { left := spell.SourceRefs[i] right := spell.SourceRefs[j] if left.StartUnitID != right.StartUnitID { return unitSortValue(left.StartUnitID) < unitSortValue(right.StartUnitID) } return unitSortValue(left.EndUnitID) < unitSortValue(right.EndUnitID) }) spell.SourceRefs = dedupeSourceRefs(spell.SourceRefs) } func dedupeSourceRefs(refs []spellSourceRefResponse) []spellSourceRefResponse { if len(refs) < 2 { return refs } out := refs[:0] var previous spellSourceRefResponse for index, ref := range refs { if index > 0 && sameSourceRef(previous, ref) { continue } out = append(out, ref) previous = ref } return out } func sameSourceRef(left spellSourceRefResponse, right spellSourceRefResponse) bool { return left.StartUnitID == right.StartUnitID && left.EndUnitID == right.EndUnitID } func earliestSourceUnit(spell spellCastResponse) (int, bool) { for _, ref := range spell.SourceRefs { start := ref.StartUnitID if start > 0 { return start, true } } return 0, false } func unitSortValue(value int) int { if value <= 0 { return int(^uint(0) >> 1) } return value } func canonicalSpellList(response extractionResponse, sourceID string) dnd.SpellList { spellCasts := make([]dnd.SpellCast, len(response.SpellCasts)) for index, spell := range response.SpellCasts { refs := make([]source.SourceRef, len(spell.SourceRefs)) for refIndex, ref := range spell.SourceRefs { refs[refIndex] = source.SourceRef{ SourceID: sourceID, StartUnitID: ref.StartUnitID, EndUnitID: ref.EndUnitID, } } spellCasts[index] = dnd.SpellCast{ Caster: spell.Caster, Spell: spell.Spell, SourceRefs: refs, } } if response.SpellCasts == nil { spellCasts = nil } return dnd.SpellList{SpellCasts: spellCasts} }