155 lines
3.1 KiB
Typst

#import "@preview/cetz:0.3.1": canvas, draw
#let UNBORN = 0
#let READY = 1
#let RUNNING = 2
#let TERMINATED = 3
#let colors = (
none,
gray,
green,
blue.lighten(50%)
)
#let task(pid, arrival, duration, priority) = {
return ((
pid: pid,
arrival: arrival,
duration: duration,
remaining: duration,
priority: priority
),)
}
#let display-processes(width: auto, display-durations: none, display-priorities: false, ..args) = layout(size => {
let processes = args.pos()
processes = processes.map(p => if type(p) == dictionary {p} else {(
pid: p.first(),
priority: if display-priorities {p.at(1)} else {0},
events: p.slice(if display-priorities {2} else {1})
)})
let max-t = calc.max(
..processes.map(
p => calc.max(
..p.events.map(
e => e.last()
)
)
)
)
let display-durations = if display-durations == none {
()
} else if type(display-durations) == array {
display-durations
} else {
(display-durations,)
}
let shapes = ()
let width = width
if (width == auto) {
width = size.width
}
let y = 0
for proc in processes {
proc.events.push((TERMINATED, max-t))
shapes += draw.content(
(0, y - .25),
str(proc.pid),
anchor: "east",
padding: 5pt
)
for i in range(proc.events.len() - 1) {
let (state1, t1) = proc.events.at(i)
let (state2, t2) = proc.events.at(i+1)
let x1 = t1 / max-t * width
let x2 = t2 / max-t * width
let y1 = y
let y2 = y - .5
if (state1 == TERMINATED) {
y1 = y - .2
y2 = y - .3
}
shapes += draw.rect(
(x1, y1),
(x2, y2),
fill: colors.at(state1)
)
if i == 0 and display-priorities {
shapes += draw.content(
((x1 + x2) / 2, (y1 + y2) / 2),
strong(str(proc.priority)),
anchor: "center"
)
}
if state1 in display-durations {
shapes += draw.content(
((x1 + x2) / 2, (y1 + y2) / 2),
strong(str(t2 - t1)),
anchor: "center"
)
}
if state1 == RUNNING and state2 == READY {
shapes += draw.on-layer(1, draw.circle(
(x2, (y1 + y2)/2),
radius: .1,
fill: red
))
}
}
y -= 0.5
}
let step = calc.pow(
10,
calc.max(
0,
calc.floor(
calc.log(
base: 10,
max-t
) - 1
)
)
)
let n-steps = calc.floor(max-t / step) + 1
for i in range(n-steps) {
let t = i * step
let x = t / max-t * width
shapes += draw.line(
(x, 0),
(x, if calc.rem(i, 2) == 0 {.5} else {.3}),
stroke: black
)
shapes += draw.on-layer(-1, draw.line(
(x, 0),
(x, -processes.len() * .5),
stroke: (
dash: (6pt, 4pt),
thickness: 1pt,
paint: gray
)
))
if calc.rem(i, 2) == 0 {
shapes += draw.content(
(x, .5),
str(t),
anchor: "south",
padding: 5pt
)
}
}
shapes += draw.rect(
(0, 0),
(width, -processes.len() * .5)
)
canvas(shapes)
})