ความคืบหน้างาน ไฟล์ต้นฉบับ

tracker/workflow.go

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
}