Implemented admin pane + user permission
This commit is contained in:
@@ -462,6 +462,65 @@ func outTypeOf(st *signalState) dsp.ValType {
|
||||
return st.rg.outType
|
||||
}
|
||||
|
||||
// TraceNode is a single node's computed value in a debug trace.
|
||||
type TraceNode struct {
|
||||
Value any `json:"value"`
|
||||
Type string `json:"type"` // "scalar" | "array"
|
||||
Approx bool `json:"approx,omitempty"`
|
||||
}
|
||||
|
||||
// TraceResult is the per-node outcome of a single-shot evaluation of an
|
||||
// (unsaved) synthetic graph, used by the editor's live/debug overlay.
|
||||
type TraceResult struct {
|
||||
Nodes map[string]TraceNode `json:"nodes"`
|
||||
Error string `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
// Trace compiles def and evaluates it once with fresh state, returning the value
|
||||
// computed for every node. Source node values are obtained via read(ds, name)
|
||||
// (typically a broker ReadNow snapshot); a source that cannot be read defaults to
|
||||
// scalar 0. Stateful ops are flagged Approx since their true running value
|
||||
// depends on accumulated state this single-shot pass does not have. A per-node
|
||||
// evaluation error is returned in Error with the partial values still populated.
|
||||
func (s *Synthetic) Trace(def SignalDef, read func(ds, name string) (any, error)) (TraceResult, error) {
|
||||
rg, err := compileGraph(def)
|
||||
if err != nil {
|
||||
return TraceResult{}, err
|
||||
}
|
||||
sourceVals := make(map[string]dsp.Sample, len(rg.sources))
|
||||
for _, src := range rg.sources {
|
||||
raw, rerr := read(src.ref.DS, src.ref.Name)
|
||||
if rerr != nil || raw == nil {
|
||||
sourceVals[src.id] = dsp.Scalar(0)
|
||||
continue
|
||||
}
|
||||
sourceVals[src.id] = toSample(raw)
|
||||
}
|
||||
vals, evalErr := rg.evalSampleTrace(sourceVals)
|
||||
|
||||
opType := make(map[string]string, len(rg.order))
|
||||
for _, n := range rg.order {
|
||||
if n.kind == "op" && n.op != nil {
|
||||
opType[n.id] = n.op.Type()
|
||||
}
|
||||
}
|
||||
res := TraceResult{Nodes: make(map[string]TraceNode, len(vals))}
|
||||
for id, sample := range vals {
|
||||
tn := TraceNode{Value: sample.AsAny(), Type: "scalar"}
|
||||
if sample.IsArray {
|
||||
tn.Type = "array"
|
||||
}
|
||||
if ot, ok := opType[id]; ok && dsp.IsStateful(ot) {
|
||||
tn.Approx = true
|
||||
}
|
||||
res.Nodes[id] = tn
|
||||
}
|
||||
if evalErr != nil {
|
||||
res.Error = evalErr.Error()
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// toSample coerces a datasource.Value.Data into a dsp.Sample: arrays become
|
||||
// array Samples (waveforms), everything else a scalar Sample.
|
||||
func toSample(v any) dsp.Sample {
|
||||
|
||||
Reference in New Issue
Block a user