diff --git a/app.py b/app.py index a48cf13..8ca2e2f 100644 --- a/app.py +++ b/app.py @@ -885,14 +885,29 @@ def get_admin_expense_summary(): } -import hashlib, colorsys +import hashlib, colorsys, math -def category_to_color(name: str) -> str: - hash_val = int(hashlib.md5(name.encode("utf-8")).hexdigest(), 16) - hue = ((hash_val % 360) + ((hash_val >> 24) % 20)) % 360 / 360.0 - saturation = 0.55 + ((hash_val >> 8) % 40) / 100.0 - lightness = 0.35 + ((hash_val >> 16) % 30) / 100.0 - r, g, b = colorsys.hls_to_rgb(hue, lightness, saturation) +def rehash32(x: int) -> int: + # Wang/Jenkins mix – lepsza dystrybucja bitów + x = (x ^ 61) ^ (x >> 16) + x = x + (x << 3) + x = x ^ (x >> 4) + x = x * 0x27d4eb2d + x = x ^ (x >> 15) + return x & 0xFFFFFFFF + +def category_to_color(name: str, buckets: int = 72) -> str: + # buckets: co 5° (72*5=360) – równy podział koła, pełna rozpiętość + h = int(hashlib.md5(name.encode("utf-8")).hexdigest(), 16) + h32 = rehash32(h & 0xFFFFFFFF) + bucket = (h32 % buckets) + # jitter ±2° w obrębie bucketu, by rozbić kolizje + jitter = ((rehash32(h32) % 5) - 2) # -2..+2 + hue_deg = (bucket * (360 // buckets) + jitter) % 360 + # Stałe S/L w bezpiecznym paśmie (pełna „kolorowość”, dobra czytelność) + s = 0.72 + l = 0.52 + r, g, b = colorsys.hls_to_rgb(hue_deg/360.0, l, s) return f"#{int(r*255):02x}{int(g*255):02x}{int(b*255):02x}" diff --git a/config.py b/config.py index 5769314..e2c3e55 100644 --- a/config.py +++ b/config.py @@ -80,6 +80,6 @@ class Config: "Spożywcze,Budowlane,Zabawki,Chemia,Inne,Elektronika,Odzież i obuwie,Jedzenie poza domem," "Artykuły biurowe,Kosmetyki i higiena,Motoryzacja,Ogród i rośliny," "Zwierzęta,Sprzęt sportowy,Książki i prasa,Narzędzia i majsterkowanie," - "RTV / AGD,Apteka i suplementy,Artykuły dekoracyjne,Gry i hobby,Usługi,Pieczywo,Różne,Chiny,Dom,Leki,Odzież,Samochód" + "RTV / AGD,Apteka i suplementy,Artykuły dekoracyjne,Gry i hobby,Usługi,Pieczywo,Różne,Chiny,Dom,Leki,Odzież,Samochód,Dzieci" ).split(",") if c.strip() - ] \ No newline at end of file + ]