Organize D&D extensions by domain
This commit is contained in:
92
internal/modules/dnd/extract/spells/canonicalize.go
Normal file
92
internal/modules/dnd/extract/spells/canonicalize.go
Normal file
@@ -0,0 +1,92 @@
|
||||
package spells
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/shared"
|
||||
)
|
||||
|
||||
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 shared.UnitRef) shared.UnitRef {
|
||||
value := ref.Int()
|
||||
if value <= 0 {
|
||||
return ref
|
||||
}
|
||||
return shared.UnitRefFromInt(value)
|
||||
}
|
||||
|
||||
func dedupeSourceRefs(refs []shared.SourceRefResponse) []shared.SourceRefResponse {
|
||||
if len(refs) < 2 {
|
||||
return refs
|
||||
}
|
||||
out := refs[:0]
|
||||
var previous shared.SourceRefResponse
|
||||
for index, ref := range refs {
|
||||
if index > 0 && sameSourceRef(previous, ref) {
|
||||
continue
|
||||
}
|
||||
out = append(out, ref)
|
||||
previous = ref
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func sameSourceRef(left shared.SourceRefResponse, right shared.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 shared.UnitRef) int {
|
||||
value := ref.Int()
|
||||
if value <= 0 {
|
||||
return int(^uint(0) >> 1)
|
||||
}
|
||||
return value
|
||||
}
|
||||
Reference in New Issue
Block a user