Last active
January 8, 2023 01:57
-
-
Save nitori/5c1945de90c97bd7bd54c67fc1bc0e0e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from __future__ import annotations | |
import math | |
import colorsys | |
from PIL import Image, ImageDraw, ImageFont | |
RowTuple = tuple[float, float] | None | |
def calc_lines(t_start: int, t_end: int) -> tuple[RowTuple, RowTuple, RowTuple]: | |
""" | |
Assume 24 hours are split over three rows, with 8 columns each. | |
Return a tuple of three values, each corresponding a row. | |
If row is None, no line on this row, otherwise it's a (start, end) | |
tuple in the range [0..1]. | |
:param t_start: start in military time e.g. 1530 for 15:30 | |
:param t_end: same, but end of shift | |
:returns: tuple of three items: (start,end) or None | |
""" | |
t0_x = t_start % 800 | |
t0_y = t_start // 800 | |
t1_x = t_end % 800 | |
t1_y = t_end // 800 | |
rows: list[RowTuple] = [] | |
for rowi in range(3): | |
if rowi < t0_y or rowi > t1_y: | |
rows.append(None) | |
continue | |
start = t0_x if rowi == t0_y else 0 | |
end = t1_x if rowi == t1_y else 800 | |
start = start / 800 | |
end = end / 800 | |
rows.append((start, end)) | |
return rows[0], rows[1], rows[2] | |
def main(): | |
time_ranges = [ | |
(0, 620), (620, 645), (645, 920), (920, 1050), (1050, 1135), (1135, 1310), | |
(1310, 1445), (1445, 1500), (1600, 1700), (2200, 2300), (2300, 2400) | |
] | |
width, height = 1600, 900 | |
font = ImageFont.FreeTypeFont('PressStart2P-Regular.ttf', 8) # Google Font | |
im = Image.new('RGB', (width, height), (0, 0, 0)) | |
draw = ImageDraw.Draw(im) | |
wstep = width // 8 | |
hstep = height // 3 | |
for y in range(0, height, hstep): | |
for x in range(0, width, wstep): | |
draw.rectangle((x, y, x + wstep - 1, y + hstep - 1), outline=(255, 255, 255)) | |
rows = {i: [] for i in range(3)} | |
for timei, (t0, t1) in enumerate(time_ranges): | |
for rowi, line in enumerate(calc_lines(t0, t1)): | |
if line is None: | |
continue | |
rows[rowi].append((line, timei, t0, t1)) | |
rows = [(i, values) for i, values in sorted(rows.items())] | |
for row, values in rows: | |
for value_index, (line, time_index, t0, t1) in enumerate(values): | |
# get some color | |
hue = time_index / len(time_ranges) | |
r, g, b = colorsys.hsv_to_rgb(hue, 1, 1) | |
r, g, b = int(r * 255), int(g * 255), int(b * 255) | |
# calculate start/end x of the line | |
x0, x1 = line | |
x0 = math.floor(x0 * width) | |
x1 = math.floor(x1 * width) | |
# and the y coordinate | |
y = row * hstep | |
subrow_height = hstep // len(values) | |
middle = subrow_height // 2 | |
y += subrow_height * value_index + middle | |
draw.line((x0, y, x1, y), fill=(r, g, b), width=5) | |
draw.text((x0 + 2, y + 6), f'{t0}-{t1}', fill=(r, g, b), font=font) | |
im.show() | |
# im.save('timeline.png') | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment