added groups

This commit is contained in:
Louis Heredero 2024-06-18 16:09:06 +02:00
parent c7fba373a5
commit dc5d868a5d
Signed by: HEL
GPG Key ID: 8D83DE470F8544E7
5 changed files with 153 additions and 15 deletions

Binary file not shown.

View File

@ -29,3 +29,17 @@ Alice <-- Bob: Another authentication Response
_seq("Alice", "Bob", comment: "This is a test") _seq("Alice", "Bob", comment: "This is a test")
_seq("Alice", "Callum", comment: "This is another test with a long text") _seq("Alice", "Callum", comment: "This is another test with a long text")
}) })
#chronos.diagram({
import "/src/diagram.typ": *
_seq("Alice", "Bob", comment: "Authentication Request")
_seq("Bob", "Alice", comment: "Authentication Failure")
_grp("My own label", desc: "My own label2", {
_seq("Alice", "Log", comment: "Log attack start")
_grp("loop", desc: "1000 times", {
_seq("Alice", "Bob", comment: "DNS Attack")
})
_seq("Alice", "Bob", comment: "Log attack end")
})
})

View File

@ -1,3 +1,4 @@
#import "utils.typ": get-group-span
#import "renderer.typ": render #import "renderer.typ": render
#let _seq( #let _seq(
@ -37,9 +38,40 @@
return false return false
} }
#let _grp(name, desc: none, type: "default", elmts) = {
return ((
type: "grp",
name: name,
desc: desc,
grp-type: type,
elmts: elmts
),)
}
#let diagram(elements) = { #let diagram(elements) = {
let participants = () let participants = ()
for elmt in elements { let elmts = elements
let i = 0
let a = elmts.len()
while i < elmts.len() {
let elmt = elmts.at(i)
if elmt.type == "grp" {
elmts = (
elmts.slice(0, i + 1) +
elmt.elmts +
((
type: "grp-end"
),) +
elmts.slice(i+1)
)
}
i += 1
}
let b = elmts.len()
[#a / #b]
[#elmts.map(e => e.type)]
for elmt in elmts {
if elmt.type == "par" { if elmt.type == "par" {
participants.push(elmt) participants.push(elmt)
} else if elmt.type == "seq" { } else if elmt.type == "seq" {
@ -52,7 +84,15 @@
} }
} }
render(participants, elements) for (i, elmt) in elmts.enumerate() {
if elmt.type == "grp" {
let (min-i, max-i) = get-group-span(participants, elmt)
elmts.at(i).insert("min-i", min-i)
elmts.at(i).insert("max-i", max-i)
}
}
render(participants, elmts)
} }
#let from-plantuml(code) = { #let from-plantuml(code) = {

View File

@ -1,16 +1,10 @@
#import "@preview/cetz:0.2.2": canvas, draw #import "@preview/cetz:0.2.2": canvas, draw
#import "utils.typ": get-participants-i
#let Y-SPACE = 20 #let Y-SPACE = 10
#let PAR-PAD = (5pt, 3pt) #let PAR-PAD = (5pt, 3pt)
#let PAR-SPACE = 10 #let PAR-SPACE = 10
#let get-participants-i(participants) = {
let pars-i = (:)
for (i, p) in participants.enumerate() {
pars-i.insert(p.name, i)
}
return pars-i
}
#let get-columns-width(participants, elements) = { #let get-columns-width(participants, elements) = {
let pars-i = get-participants-i(participants) let pars-i = get-participants-i(participants)
@ -62,6 +56,44 @@
return widths return widths
} }
#let draw-group(x0, x1, y0, y1, group) = {
let m = measure(box(group.name))
let w = m.width / 1pt + 15
let h = m.height / 1pt + 6
draw.rect(
(x0, y0),
(x1, y1)
)
draw.merge-path(
fill: gray.lighten(20%),
close: true,
{
draw.line(
(x0, y0),
(x0 + w, y0),
(x0 + w, y0 - h / 2),
(x0 + w - 5, y0 - h),
(x0, y0 - h)
)
}
)
draw.content(
(x0, y0),
group.name,
anchor: "north-west",
padding: (left: 5pt, right: 10pt, top: 3pt, bottom: 3pt)
)
if group.desc != none {
draw.content(
(x0 + w, y0),
text([\[#group.desc\]], weight: "bold"),
anchor: "north-west",
padding: 3pt
)
}
}
#let render(participants, elements) = context canvas(length: 1pt, { #let render(participants, elements) = context canvas(length: 1pt, {
let pars-i = get-participants-i(participants) let pars-i = get-participants-i(participants)
@ -85,6 +117,8 @@
} }
let y = -Y-SPACE let y = -Y-SPACE
let groups = ()
// Draw sequences // Draw sequences
for elmt in elements { for elmt in elements {
if elmt.type == "seq" { if elmt.type == "seq" {
@ -98,12 +132,8 @@
) )
) )
draw.line(
(x1, y),
(x2, y),
..style
)
if elmt.comment != none { if elmt.comment != none {
y -= measure(box(elmt.comment)).height / 1pt + 6
draw.content( draw.content(
(calc.min(x1, x2), y), (calc.min(x1, x2), y),
elmt.comment, elmt.comment,
@ -111,6 +141,33 @@
padding: 3pt padding: 3pt
) )
} }
draw.line(
(x1, y),
(x2, y),
..style
)
y -= Y-SPACE
} else if elmt.type == "grp" {
let m = measure(
box(
inset: (left: 5pt, right: 5pt, top: 3pt, bottom: 3pt),
)
)
groups = groups.map(g => {
if g.at(1).min-i == elmt.min-i { g.at(2) += 1 }
if g.at(1).max-i == elmt.max-i { g.at(3) += 1 }
g
})
groups.push((y, elmt, 0, 0))
y -= m.height / 1pt + Y-SPACE
} else if elmt.type == "grp-end" {
let (start-y, group, start-lvl, end-lvl) = groups.pop()
let x0 = x-pos.at(group.min-i) - start-lvl * 10 - 20
let x1 = x-pos.at(group.max-i) + end-lvl * 10 + 20
draw-group(x0, x1, start-y, y, group)
y -= Y-SPACE y -= Y-SPACE
} }
} }

27
src/utils.typ Normal file
View File

@ -0,0 +1,27 @@
#let get-participants-i(participants) = {
let pars-i = (:)
for (i, p) in participants.enumerate() {
pars-i.insert(p.name, i)
}
return pars-i
}
#let get-group-span(participants, group) = {
let min-i = participants.len() - 1
let max-i = 0
let pars-i = get-participants-i(participants)
for elmt in group.elmts {
if elmt.type == "seq" {
let i1 = pars-i.at(elmt.p1)
let i2 = pars-i.at(elmt.p2)
min-i = calc.min(min-i, i1, i2)
max-i = calc.max(max-i, i1, i2)
} else if elmt.type == "grp" {
let (i0, i1) = get-group-span(participants, elmt)
min-i = calc.min(min-i, i0)
max-i = calc.max(max-i, i1)
}
}
return (min-i, max-i)
}