Skip to content

Commit

Permalink
Structure transition labels
Browse files Browse the repository at this point in the history
  • Loading branch information
codesoap committed Aug 25, 2024
1 parent 2fa91c8 commit 7b99ca9
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 8 deletions.
Binary file modified assets/phone-graph.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
68 changes: 60 additions & 8 deletions graph.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package stateless
import (
"context"
"fmt"
"html"
"sort"
"strings"
"text/template"
Expand All @@ -12,6 +13,13 @@ import (
type graph struct {
}

type transitionLabel struct {
reentry []string
internal []string
transitioning []string
ignored []string
}

func (g *graph) formatStateMachine(sm *StateMachine) string {
var sb strings.Builder
sb.WriteString("digraph {\n\tcompound=true;\n\tnode [shape=Mrecord];\n\trankdir=\"LR\";\n\n")
Expand All @@ -34,7 +42,7 @@ func (g *graph) formatStateMachine(sm *StateMachine) string {
dest := sm.stateConfig[sr.InitialTransitionTarget]
if dest != nil {
src := clusterStr(sr.State, true, true)
formatOneLine(&sb, src, str(dest.State, true), "")
formatOneLine(&sb, src, str(dest.State, true), `""`)
}
}
}
Expand Down Expand Up @@ -124,7 +132,7 @@ func (g *graph) formatAllStateTransitions(sb *strings.Builder, sm *StateMachine,
destination State
}

lines := make(map[line][]string, len(triggerList))
lines := make(map[line]transitionLabel, len(triggerList))
order := make([]line, 0, len(triggerList))
for _, trigger := range triggerList {
switch t := trigger.(type) {
Expand All @@ -133,21 +141,27 @@ func (g *graph) formatAllStateTransitions(sb *strings.Builder, sm *StateMachine,
if _, ok := lines[ln]; !ok {
order = append(order, ln)
}
lines[ln] = append(lines[ln], formatOneTransition(t.Trigger, nil, t.Guard))
transition := lines[ln]
transition.ignored = append(transition.ignored, formatOneTransition(t.Trigger, nil, t.Guard))
lines[ln] = transition
case *reentryTriggerBehaviour:
actions := g.getEntryActions(sr.EntryActions, t.Trigger)
ln := line{sr.State, t.Destination}
if _, ok := lines[ln]; !ok {
order = append(order, ln)
}
lines[ln] = append(lines[ln], formatOneTransition(t.Trigger, actions, t.Guard))
transition := lines[ln]
transition.reentry = append(transition.reentry, formatOneTransition(t.Trigger, actions, t.Guard))
lines[ln] = transition
case *internalTriggerBehaviour:
actions := g.getEntryActions(sr.EntryActions, t.Trigger)
ln := line{sr.State, sr.State}
if _, ok := lines[ln]; !ok {
order = append(order, ln)
}
lines[ln] = append(lines[ln], formatOneTransition(t.Trigger, actions, t.Guard))
transition := lines[ln]
transition.internal = append(transition.internal, formatOneTransition(t.Trigger, actions, t.Guard))
lines[ln] = transition
case *transitioningTriggerBehaviour:
src := sm.stateConfig[sr.State]
if src == nil {
Expand All @@ -168,16 +182,54 @@ func (g *graph) formatAllStateTransitions(sb *strings.Builder, sm *StateMachine,
if _, ok := lines[ln]; !ok {
order = append(order, ln)
}
lines[ln] = append(lines[ln], formatOneTransition(t.Trigger, actions, t.Guard))
transition := lines[ln]
transition.transitioning = append(transition.transitioning, formatOneTransition(t.Trigger, actions, t.Guard))
lines[ln] = transition
case *dynamicTriggerBehaviour:
// TODO: not supported yet
}
}

for _, ln := range order {
content := lines[ln]
formatOneLine(sb, str(ln.source, true), str(ln.destination, true), strings.Join(content, "\\n"))
formatOneLine(sb, str(ln.source, true), str(ln.destination, true), toTransitionsLabel(content))
}
}

func toTransitionsLabel(transitions transitionLabel) string {
var sb strings.Builder
sb.WriteString(`<<TABLE BORDER="0">`)
for _, t := range transitions.transitioning {
sb.WriteString(`<TR><TD ALIGN="LEFT">`)
sb.WriteString(html.EscapeString(t))
sb.WriteString(`</TD></TR>`)
}
if len(transitions.reentry) > 0 {
sb.WriteString(`<TR><TD><B>Reentry</B></TD></TR>`)
for _, t := range transitions.reentry {
sb.WriteString(`<TR><TD ALIGN="LEFT">`)
sb.WriteString(html.EscapeString(t))
sb.WriteString(`</TD></TR>`)
}
}
if len(transitions.internal) > 0 {
sb.WriteString(`<TR><TD><B>Internal</B></TD></TR>`)
for _, t := range transitions.internal {
sb.WriteString(`<TR><TD ALIGN="LEFT">`)
sb.WriteString(html.EscapeString(t))
sb.WriteString(`</TD></TR>`)
}
}
if len(transitions.ignored) > 0 {
sb.WriteString(`<TR><TD><B>Ignored</B></TD></TR>`)
for _, t := range transitions.ignored {
sb.WriteString(`<TR><TD ALIGN="LEFT">`)
sb.WriteString(html.EscapeString(t))
sb.WriteString(`</TD></TR>`)
}
}
sb.WriteString(`</TABLE>>`)
return sb.String()
}

func formatOneTransition(trigger Trigger, actions []string, guards transitionGuard) string {
Expand All @@ -197,7 +249,7 @@ func formatOneTransition(trigger Trigger, actions []string, guards transitionGua
}

func formatOneLine(sb *strings.Builder, fromNodeName, toNodeName, label string) {
sb.WriteString(fmt.Sprintf("\t%s -> %s [label=\"%s\"", fromNodeName, toNodeName, label))
sb.WriteString(fmt.Sprintf("\t%s -> %s [label=%s", fromNodeName, toNodeName, label))
sb.WriteString("];\n")
}

Expand Down

0 comments on commit 7b99ca9

Please sign in to comment.