Simplify mock show state and allow same-track signal chaining in validator

This commit is contained in:
Ian Gulliver
2026-02-21 22:13:12 -08:00
parent eaf59641fd
commit 7a125c0bc9
2 changed files with 40 additions and 47 deletions

View File

@@ -81,6 +81,7 @@ func GenerateMockShow(numTracks, numScenes, avgCuesPerScene, avgBlocksPerCue int
type chainable struct { type chainable struct {
block *Block block *Block
trackIdx int trackIdx int
sameTrackOnly bool
} }
triggerIdx := map[TriggerSource]*Trigger{} triggerIdx := map[TriggerSource]*Trigger{}
@@ -110,10 +111,13 @@ func GenerateMockShow(numTracks, numScenes, avgCuesPerScene, avgBlocksPerCue int
show.Blocks = append(show.Blocks, cue) show.Blocks = append(show.Blocks, cue)
cueTargets := []TriggerTarget{} cueTargets := []TriggerTarget{}
endingTracks := map[int]*Block{}
for trackIdx, blk := range needsEnd { for trackIdx, blk := range needsEnd {
endingTracks[trackIdx] = blk hook := "END"
if rng.Float64() < 0.3 {
hook = "FADE_OUT"
}
cueTargets = append(cueTargets, TriggerTarget{Block: blk.ID, Hook: hook})
chainFrom = append(chainFrom, chainable{block: blk, trackIdx: trackIdx, sameTrackOnly: true})
delete(needsEnd, trackIdx) delete(needsEnd, trackIdx)
} }
@@ -122,7 +126,7 @@ func GenerateMockShow(numTracks, numScenes, avgCuesPerScene, avgBlocksPerCue int
blocksThisCue := 1 + rng.IntN(avgBlocksPerCue*2) blocksThisCue := 1 + rng.IntN(avgBlocksPerCue*2)
for range blocksThisCue { for range blocksThisCue {
trackIdx := rng.IntN(numTracks) trackIdx := rng.IntN(numTracks)
if needsEnd[trackIdx] != nil || usedTracks[trackIdx] { if usedTracks[trackIdx] {
continue continue
} }
@@ -131,16 +135,6 @@ func GenerateMockShow(numTracks, numScenes, avgCuesPerScene, avgBlocksPerCue int
usedTracks[trackIdx] = true usedTracks[trackIdx] = true
triggered := false triggered := false
if prev := endingTracks[trackIdx]; prev != nil {
cueTargets = append(cueTargets, TriggerTarget{Block: prev.ID, Hook: "FADE_OUT"})
addTrigger(
TriggerSource{Block: prev.ID, Signal: "END"},
TriggerTarget{Block: block.ID, Hook: "START"},
)
delete(endingTracks, trackIdx)
triggered = true
}
if !triggered {
for i, c := range chainFrom { for i, c := range chainFrom {
if c.trackIdx == trackIdx { if c.trackIdx == trackIdx {
addTrigger( addTrigger(
@@ -152,9 +146,15 @@ func GenerateMockShow(numTracks, numScenes, avgCuesPerScene, avgBlocksPerCue int
break break
} }
} }
if !triggered && rng.Float64() < 0.3 {
var candidates []int
for i, c := range chainFrom {
if !c.sameTrackOnly {
candidates = append(candidates, i)
} }
if !triggered && rng.Float64() < 0.3 && len(chainFrom) > 0 { }
idx := rng.IntN(len(chainFrom)) if len(candidates) > 0 {
idx := candidates[rng.IntN(len(candidates))]
c := chainFrom[idx] c := chainFrom[idx]
addTrigger( addTrigger(
TriggerSource{Block: c.block.ID, Signal: "END"}, TriggerSource{Block: c.block.ID, Signal: "END"},
@@ -163,6 +163,7 @@ func GenerateMockShow(numTracks, numScenes, avgCuesPerScene, avgBlocksPerCue int
chainFrom = append(chainFrom[:idx], chainFrom[idx+1:]...) chainFrom = append(chainFrom[:idx], chainFrom[idx+1:]...)
triggered = true triggered = true
} }
}
if !triggered { if !triggered {
cueTargets = append(cueTargets, TriggerTarget{Block: block.ID, Hook: "START"}) cueTargets = append(cueTargets, TriggerTarget{Block: block.ID, Hook: "START"})
} }
@@ -174,17 +175,6 @@ func GenerateMockShow(numTracks, numScenes, avgCuesPerScene, avgBlocksPerCue int
} }
} }
for trackIdx, blk := range endingTracks {
hook := "END"
if rng.Float64() < 0.3 {
hook = "FADE_OUT"
}
cueTargets = append(cueTargets, TriggerTarget{Block: blk.ID, Hook: hook})
if hook == "FADE_OUT" {
newChainFrom = append(newChainFrom, chainable{block: blk, trackIdx: trackIdx})
}
}
chainFrom = newChainFrom chainFrom = newChainFrom
if len(cueTargets) > 0 { if len(cueTargets) > 0 {

View File

@@ -125,8 +125,11 @@ func (show *Show) Validate() error {
} }
if t, ok := signalTargetedBy[blockEvent{trigger.Source.Block, trigger.Source.Signal}]; ok { if t, ok := signalTargetedBy[blockEvent{trigger.Source.Block, trigger.Source.Signal}]; ok {
sameTrackSingle := len(trigger.Targets) == 1 && blocksByID[trigger.Targets[0].Block].Track == sourceBlock.Track
if !sameTrackSingle {
return fmt.Errorf("trigger conflict: %s vs %s", t, trigger) return fmt.Errorf("trigger conflict: %s vs %s", t, trigger)
} }
}
if !isValidEventForBlock(sourceBlock, trigger.Source.Signal) { if !isValidEventForBlock(sourceBlock, trigger.Source.Signal) {
return fmt.Errorf("trigger source signal %q is invalid for block %q", trigger.Source.Signal, trigger.Source.Block) return fmt.Errorf("trigger source signal %q is invalid for block %q", trigger.Source.Signal, trigger.Source.Block)
} }