package main import ( "fmt" "strconv" ) // Decision metadata belongs to the canonical use case, so generated drafts and // source fingerprints agree. Persisted, user-edited diagrams are never replaced. func workflowDiagram(u UseCase) Diagram { d := Diagram{Nodes: []DiagramNode{}, Edges: []DiagramEdge{}} gates := map[int]WorkflowDecision{} for _, g := range u.Workflow.Decisions { gates[g.Before] = g } entry := func(i int) string { if i > len(u.Flow) { return "end" } if _, ok := gates[i]; ok { return fmt.Sprintf("decision-%d", i) } return fmt.Sprintf("step-%d", i) } addNode := func(id, kind, title, description string, x, y float64) { d.Nodes = append(d.Nodes, DiagramNode{ID: id, Type: kind, Title: title, Description: description, X: x, Y: y}) } edge := func(from, to, label string) { d.Edges = append(d.Edges, DiagramEdge{ID: fmt.Sprintf("edge-%d", len(d.Edges)+1), Source: from, Target: to, Label: label, Head: "arrow", Tail: "none"}) } addNode("start", "start", "เริ่มต้น", u.Start, 100, 1000) edge("start", entry(1), "") x := 440.0 for i, f := range u.Flow { step := i + 1 id := fmt.Sprintf("step-%d", step) if g, ok := gates[step]; ok { gid := fmt.Sprintf("decision-%d", step) addNode(gid, "decision", g.Title, g.Description, x, 1000) x += 340 for j, b := range g.Branches { target := id if b.Outcome != "" { target = fmt.Sprintf("outcome-%d-%d", step, j+1) addNode(target, "end", b.Label, b.Outcome, x, float64(100+j*260)) } else if b.Target != step { target = entry(b.Target) } edge(gid, target, b.Label) } } addNode(id, "process", fmt.Sprintf("%d. %s", step, f[0]), f[1], x, 1000) x += 340 if outcome, ok := u.Workflow.Stop[strconv.Itoa(step)]; ok { target := fmt.Sprintf("stopped-%d", step) addNode(target, "end", "สิ้นสุดเส้นทางนี้", outcome, x, 100) edge(id, target, "") } else if next, ok := u.Workflow.Next[strconv.Itoa(step)]; ok { edge(id, entry(next), "") } else { edge(id, entry(step+1), "") } } addNode("end", "end", "สิ้นสุด", u.Outcome, x, 1000) return d }