forked from HEL/chronos
		
	added groups
This commit is contained in:
		
										
											Binary file not shown.
										
									
								
							| @@ -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") | ||||||
|  |   }) | ||||||
|  | }) | ||||||
| @@ -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) = { | ||||||
|   | |||||||
| @@ -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
									
								
							
							
						
						
									
										27
									
								
								src/utils.typ
									
									
									
									
									
										Normal 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) | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user