Investigate timeline solver cycle and add trigger conflict validation
- Add trigger conflict validation in show.go to detect overlapping or mutually exclusive row constraints. - Implement Trigger.String() for improved error reporting. - Add detailed logging to timeline.go to trace iterative solver non-convergence and empty row optimization cycles. - Extend mock show generator with experimental cross-track triggers.
This commit is contained in:
@@ -26,6 +26,14 @@ type Trigger struct {
|
||||
Targets []TriggerTarget `json:"targets"`
|
||||
}
|
||||
|
||||
func (t *Trigger) String() string {
|
||||
s := fmt.Sprintf("%s/%s ->", t.Source.Block, t.Source.Signal)
|
||||
for _, target := range t.Targets {
|
||||
s += fmt.Sprintf(" %s/%s", target.Block, target.Hook)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
type TriggerSource struct {
|
||||
Block string `json:"block"`
|
||||
Signal string `json:"signal"`
|
||||
@@ -92,11 +100,33 @@ func (show *Show) Validate() error {
|
||||
hookTargeted := map[blockEvent]bool{}
|
||||
startTargeted := map[string]bool{}
|
||||
sourceUsed := map[blockEvent]bool{}
|
||||
signalTargetedBy := map[blockEvent]*Trigger{}
|
||||
|
||||
for _, trigger := range show.Triggers {
|
||||
for _, target := range trigger.Targets {
|
||||
signalTargetedBy[blockEvent{target.Block, target.Hook}] = trigger
|
||||
}
|
||||
}
|
||||
|
||||
for _, trigger := range show.Triggers {
|
||||
sourceBlock := blocksByID[trigger.Source.Block]
|
||||
if sourceBlock == nil {
|
||||
return fmt.Errorf("trigger source block %q not found", trigger.Source.Block)
|
||||
}
|
||||
|
||||
targetedTracks := map[string]string{}
|
||||
for _, target := range trigger.Targets {
|
||||
targetBlock := blocksByID[target.Block]
|
||||
if prev, ok := targetedTracks[targetBlock.Track]; ok {
|
||||
return fmt.Errorf("trigger conflict: %s targets multiple blocks on track %q (%q and %q)",
|
||||
trigger, targetBlock.Track, prev, target.Block)
|
||||
}
|
||||
targetedTracks[targetBlock.Track] = target.Block
|
||||
}
|
||||
|
||||
if t, ok := signalTargetedBy[blockEvent{trigger.Source.Block, trigger.Source.Signal}]; ok {
|
||||
return fmt.Errorf("trigger conflict: %s vs %s", t, trigger)
|
||||
}
|
||||
if !isValidEventForBlock(sourceBlock, trigger.Source.Signal) {
|
||||
return fmt.Errorf("trigger source signal %q is invalid for block %q", trigger.Source.Signal, trigger.Source.Block)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user