Add D&D spell raw output validators
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
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)
|
||||
}
|
||||
Reference in New Issue
Block a user