""" Jednoduchý HTTP server — generuje HTML report léků z MySQL a servíruje ho na portu 8765. """ from http.server import BaseHTTPRequestHandler, HTTPServer import pymysql, pymysql.cursors DB = dict(host="192.168.1.76", user="root", password="Vlado9674+", database="medicus", charset="utf8mb4", cursorclass=pymysql.cursors.DictCursor) ATC_POPIS = { "N06AX": "Jiná antidepresiva", "M04AA": "Léky proti dně (urikostatika)", "C10BA": "Statiny v kombinaci", "C10AA": "Statiny", "N05BA": "Benzodiazepinová anxiolytika", "R01BA": "Systémová dekongestiva", "A02BC": "Inhibitory protonové pumpy", "G04BE": "Léky na erektilní dysfunkci", "C10AX": "Jiná hypolipidemika (ezetimib)", "C09AA": "ACE inhibitory", "N05BX": "Jiná anxiolytika", "N02AJ": "Opioidy + neopioidy", "R01AD": "Nosní kortikosteroidy", "R06AX": "Antihistaminika", "J01FA": "Makrolidová antibiotika", "M03BX": "Centrální myorelaxancia", "A10BX": "Inkretiny (GLP-1 agonisté)", "R05CB": "Mukolytika", "N05CF": "Z-hypnotika", "J01CE": "Penicilinová antibiotika", } # Klíčová slova v navodu naznačující PRN (dle potřeby) PRN_SLOVA = ("dle potřeby", "dle potreby", "p.p.", "d.p.", "pp ", " pp", "při bolesti", "pri bolesti", "dle potreb", "podle potřeby", "podle potreby", "podle potreby") def query(): conn = pymysql.connect(**DB) with conn.cursor() as cur: cur.execute(""" SELECT LEFT(p.atc, 5) AS atc_skupina, MIN(p.nazev) AS nazev_leku, COUNT(DISTINCT p.id) AS pocet_predpisu, COUNT(DISTINCT v.id) AS pocet_vydani, SUM(p.mnozstvi) AS celkove_mnozstvi, AVG(p.mnozstvi) AS avg_mnozstvi, MIN(p.datum_vystaveni) AS prvni_predpis, MAX(p.datum_vystaveni) AS posledni_predpis, DATEDIFF(MAX(p.datum_vystaveni), MIN(p.datum_vystaveni)) AS rozpeti_dni, MAX(p.opakovani) AS opakovani, GROUP_CONCAT(p.navod ORDER BY p.datum_vystaveni SEPARATOR '|') AS navody, GROUP_CONCAT(DISTINCT vp.odbornost ORDER BY vp.odbornost) AS odbornosti, GROUP_CONCAT(DISTINCT vp.nazev_pracoviste ORDER BY vp.odbornost) AS pracoviste FROM predpis p LEFT JOIN vydej v ON v.id_lp_predpis = p.id_lp_predpis LEFT JOIN predepisujici pre ON pre.lekar_kod = p.kod_predepisujiciho LEFT JOIN vzp_pracoviste vp ON vp.icp = pre.icp AND vp.id = ( SELECT id FROM vzp_pracoviste WHERE icp = pre.icp ORDER BY platnost_od DESC LIMIT 1 ) WHERE p.atc IS NOT NULL GROUP BY LEFT(p.atc, 5) HAVING pocet_predpisu >= 2 OR MAX(p.opakovani) IS NOT NULL """) rows = cur.fetchall() conn.close() # Vypočítej pravidelnost v Pythonu a seřaď for r in rows: r["pravidelnost"], r["norm_interval"] = vypocitej_pravidelnost(r) rows.sort(key=lambda r: ( ["pravidelna", "mozna", "nepravidelna", "prn"].index(r["pravidelnost"]), -(r["pocet_vydani"] or 0) )) return rows def vypocitej_pravidelnost(r): """Vrací (kategorie, normalizovany_interval_dni).""" pocet = r["pocet_predpisu"] or 1 rozpeti = r["rozpeti_dni"] or 0 avg_mnoz = float(r["avg_mnozstvi"] or 1) # PRN detekce — pokud většina návodů obsahuje PRN klíčová slova navody = (r["navody"] or "").lower() navod_list = navody.split("|") prn_pocet = sum(1 for n in navod_list if any(s in n for s in PRN_SLOVA)) if prn_pocet > len(navod_list) / 2: return "prn", None if pocet < 2 or rozpeti == 0: return "nepravidelna", None avg_interval = rozpeti / (pocet - 1) # dny mezi předpisy norm_interval = avg_interval / avg_mnoz # normalizováno na 1 balení if norm_interval <= 40: return "pravidelna", round(norm_interval) elif norm_interval <= 100: return "pravidelna", round(norm_interval) elif norm_interval <= 185: return "mozna", round(norm_interval) else: return "nepravidelna", round(norm_interval) def badge_pravidelnost(pravidelnost, norm_interval): if pravidelnost == "prn": return 'dle potřeby' if norm_interval is None: return '?' if pravidelnost == "pravidelna": return f'pravidelný · ~{norm_interval} dní/bal.' if pravidelnost == "mozna": return f'možná · ~{norm_interval} dní/bal.' return f'epizodický · ~{norm_interval} dní/bal.' def badge_odbornost(odbornosti, pracoviste): if not odbornosti: return 'neznámá' kody = odbornosti.split(",") nazvy = pracoviste.split(",") if pracoviste else [] parts = [] for i, kod in enumerate(kody): nazev = nazvy[i].strip() if i < len(nazvy) else kod cls = "gp" if kod.strip() in ("001", "002") else "spec" parts.append(f'{kod.strip()}') return " ".join(parts) def bar(val, max_val, color): pct = min(int(val / max_val * 100), 100) return (f'
') def generate_html(rows): max_vydani = max((r["pocet_vydani"] or 0 for r in rows), default=1) radky = [] for r in rows: atc = r["atc_skupina"] or "" popis = ATC_POPIS.get(atc, "") pr = r["pravidelnost"] row_cls = {"pravidelna": "row-ano", "mozna": "row-mozna", "prn": "row-prn", "nepravidelna": "row-ne"}.get(pr, "") radky.append(f"""Skupiny ATC (5. místo) · seřazeno dle pravidelnosti · normalizovaný interval = průměrný počet dní na 1 balení
| ATC skupina | Lék (příklad) | Pravidelnost | Předpisů | Vydání | Rozsah | Odbornost |
|---|