99 lines
2.8 KiB
Go
99 lines
2.8 KiB
Go
package spellpayload
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"strings"
|
|
|
|
"gitea.maximumdirect.net/eric/notarius/internal/core/source"
|
|
"gitea.maximumdirect.net/eric/notarius/internal/framework/contracts"
|
|
"gitea.maximumdirect.net/eric/notarius/internal/modules/sharedassets/dnd"
|
|
)
|
|
|
|
type Payload struct {
|
|
SpellCasts []SpellCast `json:"spell_casts"`
|
|
}
|
|
|
|
type SpellCast struct {
|
|
Caster string `json:"caster"`
|
|
Spell string `json:"spell"`
|
|
Effect string `json:"effect"`
|
|
NarrativeDescription string `json:"narrative_description"`
|
|
SourceRefs []dnd.SourceRefResponse `json:"source_refs"`
|
|
}
|
|
|
|
func Parse(raw []byte) (Payload, error) {
|
|
decoder := json.NewDecoder(bytes.NewReader(raw))
|
|
decoder.DisallowUnknownFields()
|
|
|
|
var payload Payload
|
|
if err := decoder.Decode(&payload); err != nil {
|
|
return Payload{}, fmt.Errorf("parse spell payload: %w", err)
|
|
}
|
|
var extra any
|
|
if err := decoder.Decode(&extra); err != io.EOF {
|
|
return Payload{}, fmt.Errorf("parse spell payload: multiple JSON values")
|
|
}
|
|
return payload, nil
|
|
}
|
|
|
|
func ValidateShape(payload Payload) error {
|
|
if payload.SpellCasts == nil {
|
|
return fmt.Errorf("spell_casts must be present")
|
|
}
|
|
for index, spell := range payload.SpellCasts {
|
|
if strings.TrimSpace(spell.Caster) == "" {
|
|
return fmt.Errorf("spell_casts[%d].caster must not be empty", index)
|
|
}
|
|
if strings.TrimSpace(spell.Spell) == "" {
|
|
return fmt.Errorf("spell_casts[%d].spell must not be empty", index)
|
|
}
|
|
if strings.TrimSpace(spell.Effect) == "" {
|
|
return fmt.Errorf("spell_casts[%d].effect must not be empty", index)
|
|
}
|
|
if strings.TrimSpace(spell.NarrativeDescription) == "" {
|
|
return fmt.Errorf("spell_casts[%d].narrative_description must not be empty", index)
|
|
}
|
|
if len(spell.SourceRefs) == 0 {
|
|
return fmt.Errorf("spell_casts[%d].source_refs must not be empty", index)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func SourceRefCandidates(doc *source.SourceDocument, spell SpellCast) []source.SourceRef {
|
|
refs := make([]source.SourceRef, 0, len(spell.SourceRefs))
|
|
for _, ref := range spell.SourceRefs {
|
|
refs = append(refs, dnd.SourceRefCandidate(doc, ref))
|
|
}
|
|
return refs
|
|
}
|
|
|
|
func CitedText(doc *source.SourceDocument, ref source.SourceRef) (string, bool) {
|
|
if doc == nil {
|
|
return "", false
|
|
}
|
|
startIndex, ok := source.UnitIndex(doc, ref.StartUnitID)
|
|
if !ok {
|
|
return "", false
|
|
}
|
|
endIndex, ok := source.UnitIndex(doc, ref.EndUnitID)
|
|
if !ok || startIndex > endIndex {
|
|
return "", false
|
|
}
|
|
var b strings.Builder
|
|
for i := startIndex; i <= endIndex; i++ {
|
|
if b.Len() > 0 {
|
|
b.WriteByte('\n')
|
|
}
|
|
b.WriteString(doc.Units[i].Text)
|
|
}
|
|
return b.String(), true
|
|
}
|
|
|
|
func ValidationRequestPayload(req contracts.ValidationRequest) (Payload, error) {
|
|
return Parse(req.Payload.Content)
|
|
}
|