Add complete D&D example transcript
This commit is contained in:
1031
docs/roadmap/documentation.md
Normal file
1031
docs/roadmap/documentation.md
Normal file
File diff suppressed because it is too large
Load Diff
85
examples/dnd-complete-transcript.json
Normal file
85
examples/dnd-complete-transcript.json
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
{
|
||||||
|
"metadata": {
|
||||||
|
"id": "session-ravenfall",
|
||||||
|
"title": "The Ravenfall Watchtower"
|
||||||
|
},
|
||||||
|
"segments": [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"start": 0,
|
||||||
|
"end": 14,
|
||||||
|
"speaker": "DM",
|
||||||
|
"text": "Recap: last session, the party learned that Elder Rowan vanished near the Ravenfall watchtower."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"start": 14,
|
||||||
|
"end": 25,
|
||||||
|
"speaker": "Player",
|
||||||
|
"text": "Out of character, we agree to investigate the watchtower before the next game."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3,
|
||||||
|
"start": 25,
|
||||||
|
"end": 39,
|
||||||
|
"speaker": "DM",
|
||||||
|
"text": "Aria and Borin arrive at the ruined Ravenfall watchtower as dusk settles over the road."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 4,
|
||||||
|
"start": 39,
|
||||||
|
"end": 55,
|
||||||
|
"speaker": "Mira Thorn",
|
||||||
|
"text": "Mira Thorn steps from the doorway and says, \"Elder Rowan warned me that Kesh would return for the relic.\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 5,
|
||||||
|
"start": 55,
|
||||||
|
"end": 70,
|
||||||
|
"speaker": "DM",
|
||||||
|
"text": "Mira leads the party to a hidden cache. The party discovers a moonblade and acquires 20 silver pieces."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 6,
|
||||||
|
"start": 70,
|
||||||
|
"end": 83,
|
||||||
|
"speaker": "Aria",
|
||||||
|
"text": "Aria hands her healing potion to Borin so he can carry it into the tower."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 7,
|
||||||
|
"start": 83,
|
||||||
|
"end": 96,
|
||||||
|
"speaker": "DM",
|
||||||
|
"text": "Kesh, the goblin captain, orders the raiders to attack. Roll initiative."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 8,
|
||||||
|
"start": 96,
|
||||||
|
"end": 110,
|
||||||
|
"speaker": "DM",
|
||||||
|
"text": "On Kesh's turn, he strikes Borin with his scimitar. Borin drinks the healing potion on his turn."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 9,
|
||||||
|
"start": 110,
|
||||||
|
"end": 124,
|
||||||
|
"speaker": "Aria",
|
||||||
|
"text": "Aria casts Cure Wounds on Borin, then invokes Aegis of Emberfall as Kesh closes in."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 10,
|
||||||
|
"start": 124,
|
||||||
|
"end": 137,
|
||||||
|
"speaker": "DM",
|
||||||
|
"text": "Kesh casts Shield as a reaction against Borin's counterattack, but the party drives the raiders away."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 11,
|
||||||
|
"start": 137,
|
||||||
|
"end": 150,
|
||||||
|
"speaker": "DM",
|
||||||
|
"text": "After the battle, Aria pays 5 silver pieces to repair the watchtower gate."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -1,2 +1,8 @@
|
|||||||
Cure Wounds: healing spell cast by touch.
|
Ravenfall watchtower: a ruined watchtower near the party's current route.
|
||||||
Shield: defensive reaction spell.
|
Mira Thorn: the watchtower's keeper.
|
||||||
|
Elder Rowan: a missing local scholar.
|
||||||
|
Kesh: a goblin captain leading raiders.
|
||||||
|
Moonblade: a blade found in the watchtower's hidden cache.
|
||||||
|
Cure Wounds: a healing spell.
|
||||||
|
Shield: a defensive reaction spell.
|
||||||
|
Aegis of Emberfall: a campaign spell recorded in the supplied catalog overlay.
|
||||||
|
|||||||
@@ -1,3 +1,2 @@
|
|||||||
Aria: party cleric and recurring healer.
|
Aria: party cleric and recurring healer.
|
||||||
Borin: fighter ally.
|
Borin: fighter ally.
|
||||||
Bandit mage: hostile spellcaster.
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package cli
|
package cli
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@@ -11,9 +12,11 @@ import (
|
|||||||
"gitea.maximumdirect.net/eric/notarius/internal/core/artifacts"
|
"gitea.maximumdirect.net/eric/notarius/internal/core/artifacts"
|
||||||
"gitea.maximumdirect.net/eric/notarius/internal/core/config"
|
"gitea.maximumdirect.net/eric/notarius/internal/core/config"
|
||||||
"gitea.maximumdirect.net/eric/notarius/internal/core/debugbundle"
|
"gitea.maximumdirect.net/eric/notarius/internal/core/debugbundle"
|
||||||
|
"gitea.maximumdirect.net/eric/notarius/internal/framework/contracts"
|
||||||
"gitea.maximumdirect.net/eric/notarius/internal/framework/pipeline"
|
"gitea.maximumdirect.net/eric/notarius/internal/framework/pipeline"
|
||||||
"gitea.maximumdirect.net/eric/notarius/internal/modules/dnd"
|
"gitea.maximumdirect.net/eric/notarius/internal/modules/dnd"
|
||||||
spellnormalize "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/normalize/spells"
|
spellnormalize "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/normalize/spells"
|
||||||
|
"gitea.maximumdirect.net/eric/notarius/internal/modules/seriatim/input/transcript"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMaintainedExamplesLoadResolveAndList(t *testing.T) {
|
func TestMaintainedExamplesLoadResolveAndList(t *testing.T) {
|
||||||
@@ -21,6 +24,20 @@ func TestMaintainedExamplesLoadResolveAndList(t *testing.T) {
|
|||||||
for _, example := range maintainedExampleFiles(t) {
|
for _, example := range maintainedExampleFiles(t) {
|
||||||
t.Run(example.name, func(t *testing.T) {
|
t.Run(example.name, func(t *testing.T) {
|
||||||
cfg := loadMaintainedExample(t, example.path)
|
cfg := loadMaintainedExample(t, example.path)
|
||||||
|
raw, err := os.ReadFile(example.transcriptPath)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("read maintained transcript %q: %v", example.transcriptPath, err)
|
||||||
|
}
|
||||||
|
document, err := transcript.New().Parse(context.Background(), contracts.ParseRequest{
|
||||||
|
Path: example.transcriptPath,
|
||||||
|
Raw: raw,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("parse maintained transcript %q: %v", example.transcriptPath, err)
|
||||||
|
}
|
||||||
|
if len(document.Units) == 0 {
|
||||||
|
t.Fatalf("maintained transcript %q has no parsed units", example.transcriptPath)
|
||||||
|
}
|
||||||
for _, pipelineID := range example.pipelineIDs {
|
for _, pipelineID := range example.pipelineIDs {
|
||||||
effective, err := cfg.Resolve(resolveInputForMaintainedExample(components, pipelineID))
|
effective, err := cfg.Resolve(resolveInputForMaintainedExample(components, pipelineID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -567,16 +567,17 @@ func TestProductionSceneRunRecordsAnnotationFreeChunkPlanAndProvenance(t *testin
|
|||||||
}
|
}
|
||||||
|
|
||||||
type maintainedExample struct {
|
type maintainedExample struct {
|
||||||
name string
|
name string
|
||||||
path string
|
path string
|
||||||
pipelineIDs []string
|
transcriptPath string
|
||||||
|
pipelineIDs []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func maintainedExampleFiles(t *testing.T) []maintainedExample {
|
func maintainedExampleFiles(t *testing.T) []maintainedExample {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
return []maintainedExample{
|
return []maintainedExample{
|
||||||
{name: "minimal", path: repositoryPath("examples", "dnd-minimal.config.yml"), pipelineIDs: []string{"dnd-session"}},
|
{name: "minimal", path: repositoryPath("examples", "dnd-minimal.config.yml"), transcriptPath: repositoryPath("examples", "seriatim-minimal-transcript.json"), pipelineIDs: []string{"dnd-session"}},
|
||||||
{name: "complete", path: repositoryPath("examples", "dnd-complete.config.yml"), pipelineIDs: []string{"dnd-session"}},
|
{name: "complete", path: repositoryPath("examples", "dnd-complete.config.yml"), transcriptPath: repositoryPath("examples", "dnd-complete-transcript.json"), pipelineIDs: []string{"dnd-session"}},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user