Oliver's 12

2025-03-29

"""2025-03-29
Oliver's 12
A dot for every day in the life of my beautiful son
png
Sketch,py5,CreativeCoding
"""

from datetime import datetime, timedelta

import py5

from utils import helpers
from utils.draw import gera_paleta

sketch = helpers.info_for_sketch(__file__, __doc__)

hoje = datetime(2025, 3, 29, 15, 0)
nasc = datetime(2012, 3, 29, 14, 0)


def calcula_dias() -> int:
    delta: timedelta = hoje - nasc
    return delta.days


def ponto_ano() -> list[int]:
    anos = []
    for ano in range(2012, 2026):
        hoje = datetime(ano, 3, 29, 15, 0)
        delta: timedelta = hoje - nasc
        anos.append(delta.days)
    return anos


def calcula_cores(anos: list[int]) -> dict[int, str]:
    cores = {}
    paleta = gera_paleta("oliver-13", como_deque=True)
    for idx, ano in enumerate(anos):
        cores[ano] = paleta[idx]
    return cores


def pontos_espiral(
    x0: float, y0: float, offset: float, total_pontos: int, raio_max: int
) -> list[tuple[float, float, str, float, bool]]:
    pontos = []
    cores = calcula_cores(ponto_ano())
    cor = cores[0]
    peso = 1
    for i in range(total_pontos):
        ponto = False
        cor = cores.get(i, cor)
        if i in cores:
            cor = cores[i]
            peso += 0.5
            ponto = True
        angulo = py5.radians(i * 2.4 + offset)
        r = i * raio_max / total_pontos
        x = x0 + r * py5.cos(angulo)
        y = y0 + r * py5.sin(angulo)
        pontos.append((x, y, cor, peso, ponto))
    return pontos


def adiciona_aniversario(x, y, z, peso):
    with py5.push():
        py5.stroke("#00F")
        py5.stroke_weight(peso + 4)
        py5.point(x, y, z + 2)


def setup():
    py5.size(helpers.LARGURA, helpers.ALTURA, py5.P3D)
    py5.background(0)
    py5.color_mode(py5.HSB, 360, 100, 100)
    dias = calcula_dias()
    espiral = pontos_espiral(0, 0, 37, dias, 450)
    py5.stroke("#FFF")
    py5.stroke_weight(1)
    with py5.push():
        py5.translate(py5.width // 2, py5.height // 2, -130)
        x0, y0 = 0, 0
        z = 0
        for x, y, cor, peso, ponto in espiral:
            py5.stroke(cor)
            py5.stroke_weight(peso)
            py5.line(x0, y0, z, x, y, z)
            if ponto:
                z += 2
                adiciona_aniversario(x, y, z, peso)
            x0, y0 = x, y
        adiciona_aniversario(x, y, z, peso)

    helpers.write_legend(sketch=sketch)


def key_pressed():
    key = py5.key
    if key == " ":
        save_and_close()


def save_and_close():
    py5.no_loop()
    helpers.save_sketch_image(sketch)
    py5.exit_sketch()


if __name__ == "__main__":
    py5.run_sketch()