#!/usr/bin/env python3 """ Модуль интерпретации результатов SDK ФПГ (GigaDoc). Переводит JSON-ответ в понятный человеку диагноз. """ def interpret_result(data: dict) -> dict: """ Преобразует JSON-ответ SDK в структурированный, понятный диагноз. Возвращает dict с секциями: - summary: краткое резюме - metrics: список показателей с оценкой (норма/отклонение) - warnings: список предупреждений - advice: рекомендации """ if not data or not data.get("face_ok"): return { "summary": "Лицо не было распознано на видео. Убедитесь, что лицо хорошо освещено и находится в кадре.", "metrics": [], "warnings": ["Лицо не распознано — анализ невозможен"], "advice": ["Переснимите видео: лицо анфас, хорошее освещение, без очков и головных уборов"], } metrics = [] warnings = [] advice = [] # ── Демография ───────────────────────────────────────────── gender = "мужчина" if data.get("is_male") else "женщина" age = data.get("age", 0) ethnicity_map = { "white": "европеоид", "black": "негроид", "asian": "монголоид", "unknown": "не определён", } ethnicity = ethnicity_map.get(data.get("ethnicity", ""), data.get("ethnicity", "не определён")) emotion_map = { "happiness": "радость", "sadness": "грусть", "neutral": "спокойствие", "anger": "злость", "surprise": "удивление", "fear": "страх", "disgust": "отвращение", "contempt": "презрение", } emotion = emotion_map.get(data.get("emotion", ""), data.get("emotion", "не определена")) metrics.append({ "name": "Пол", "value": "Мужской" if data.get("is_male") else "Женский", "status": "info", "comment": "", }) metrics.append({ "name": "Возраст", "value": f"{age} лет", "status": "info", "comment": "Оценка по лицу", }) metrics.append({ "name": "Этнос", "value": ethnicity.capitalize(), "status": "info", "comment": "", }) metrics.append({ "name": "Эмоция", "value": emotion.capitalize(), "status": "info", "comment": "Эмоция в момент съёмки", }) # ── ИМТ ──────────────────────────────────────────────────── bmi = data.get("bmi", 0) if bmi > 0: if bmi < 18.5: bmi_status, bmi_comment = "warning", "Недостаточный вес" elif bmi < 25: bmi_status, bmi_comment = "ok", "Нормальный вес" elif bmi < 30: bmi_status, bmi_comment = "warning", "Избыточный вес" else: bmi_status, bmi_comment = "danger", "Ожирение" metrics.append({ "name": "Индекс массы тела (ИМТ)", "value": f"{bmi:.1f}", "status": bmi_status, "comment": bmi_comment, }) if bmi_status == "warning": warnings.append(f"Избыточный вес (ИМТ {bmi:.1f}) — рекомендуется контроль питания и физическая активность") advice.append("Снизить вес до нормы (ИМТ 18.5–24.9): сбалансированное питание, регулярные нагрузки") elif bmi_status == "danger": warnings.append(f"Ожирение (ИМТ {bmi:.1f}) — рекомендуется консультация врача") advice.append("Обратиться к врачу для разработки программы снижения веса") # ── Диабет ───────────────────────────────────────────────── diabet = data.get("diabet", "unknown") diabet_map = { "small": ("ok", "Низкий риск диабета"), "middle": ("warning", "Средний риск диабета"), "big": ("danger", "Высокий риск диабета"), "unknown": ("info", "Не определён"), } d_status, d_comment = diabet_map.get(diabet, ("info", "Не определён")) metrics.append({ "name": "Риск диабета", "value": {"small": "Низкий", "middle": "Средний", "big": "Высокий", "unknown": "Не определён"}.get(diabet, "Не определён"), "status": d_status, "comment": d_comment, }) if d_status == "warning": warnings.append("Средний риск диабета — рекомендуется проверить уровень сахара в крови") advice.append("Сдать анализ на гликированный гемоглобин и сахар крови натощак") elif d_status == "danger": warnings.append("Высокий риск диабета — необходима консультация врача") advice.append("Срочно обратиться к врачу и сдать анализы на сахар") # ── Усталость ────────────────────────────────────────────── fatigue = data.get("fatigue", "small") fatigue_map = { "small": ("ok", "Низкая усталость"), "middle": ("warning", "Средняя усталость"), "big": ("warning", "Высокая усталость"), "over": ("danger", "Переутомление"), } f_status, f_comment = fatigue_map.get(fatigue, ("info", "Не определена")) metrics.append({ "name": "Усталость", "value": {"small": "Низкая", "middle": "Средняя", "big": "Высокая", "over": "Переутомление"}.get(fatigue, "Не определена"), "status": f_status, "comment": f_comment, }) if f_status == "warning": warnings.append("Повышенная усталость — рекомендуется полноценный отдых") advice.append("Нормализовать сон (7–8 часов), снизить нагрузку") elif f_status == "danger": warnings.append("Переутомление — необходима консультация врача") advice.append("Обратиться к врачу, исключить перегрузки") # ── Пульс ────────────────────────────────────────────────── hr = data.get("hr", 0) if hr > 0: if hr < 60: hr_status, hr_comment = "warning", "Замедленный пульс (брадикардия)" elif hr <= 100: hr_status, hr_comment = "ok", "Нормальный пульс" else: hr_status, hr_comment = "warning", "Учащённый пульс (тахикардия)" metrics.append({ "name": "Пульс (ЧСС)", "value": f"{hr} уд/мин", "status": hr_status, "comment": hr_comment, }) if hr_status == "warning": warnings.append(f"Пульс {hr} уд/мин — вне нормы (60–100)") advice.append("Проконсультироваться с врачом по поводу пульса") # ── Давление ─────────────────────────────────────────────── upper_ap = data.get("upper_ap", 0) lower_ap = data.get("lower_ap", 0) if upper_ap > 0 and lower_ap > 0: if upper_ap < 120 and lower_ap < 80: ap_status, ap_comment = "ok", "Оптимальное давление" elif upper_ap < 130 and lower_ap < 85: ap_status, ap_comment = "ok", "Нормальное давление" elif upper_ap < 140 or lower_ap < 90: ap_status, ap_comment = "warning", "Повышенное давление" else: ap_status, ap_comment = "danger", "Высокое давление" metrics.append({ "name": "Артериальное давление", "value": f"{upper_ap}/{lower_ap} мм рт.ст.", "status": ap_status, "comment": ap_comment, }) if ap_status == "warning": warnings.append(f"Повышенное давление {upper_ap}/{lower_ap} — рекомендуется контроль") advice.append("Контролировать давление, ограничить соль, кофеин, алкоголь") elif ap_status == "danger": warnings.append(f"Высокое давление {upper_ap}/{lower_ap} — необходима консультация врача") advice.append("Обратиться к врачу для назначения лечения") # ── Гликированный гемоглобин ─────────────────────────────── gh = data.get("glycated_hemoglobin", 0) if gh > 0: if gh < 5.7: gh_status, gh_comment = "ok", "Норма (без диабета)" elif gh < 6.5: gh_status, gh_comment = "warning", "Преддиабет" else: gh_status, gh_comment = "danger", "Диабет" metrics.append({ "name": "Гликированный гемоглобин", "value": f"{gh:.1f}%", "status": gh_status, "comment": gh_comment, }) if gh_status == "warning": warnings.append(f"Гликированный гемоглобин {gh:.1f}% — преддиабет") advice.append("Снизить потребление сахара, проверить сахар крови") elif gh_status == "danger": warnings.append(f"Гликированный гемоглобин {gh:.1f}% — возможен диабет") advice.append("Срочно обратиться к врачу") # ── Холестерин ───────────────────────────────────────────── chol = data.get("cholesterol", 0) if chol > 0: if chol < 5.2: chol_status, chol_comment = "ok", "Норма" elif chol < 6.2: chol_status, chol_comment = "warning", "Повышенный" else: chol_status, chol_comment = "danger", "Высокий" metrics.append({ "name": "Общий холестерин", "value": f"{chol:.1f} ммоль/л", "status": chol_status, "comment": chol_comment, }) if chol_status == "warning": warnings.append(f"Холестерин {chol:.1f} ммоль/л — выше нормы (до 5.2)") advice.append("Ограничить жирную пищу, добавить овощи и физическую активность") chol_ld = data.get("cholesterol_ld", 0) if chol_ld > 0: if chol_ld < 3.0: ld_status, ld_comment = "ok", "Норма" elif chol_ld < 4.1: ld_status, ld_comment = "warning", "Повышенный" else: ld_status, ld_comment = "danger", "Высокий" metrics.append({ "name": "Холестерин ЛПНП («плохой»)", "value": f"{chol_ld:.1f} ммоль/л", "status": ld_status, "comment": ld_comment, }) chol_hd = data.get("cholesterol_hd", 0) if chol_hd > 0: if chol_hd >= 1.0: hd_status, hd_comment = "ok", "Норма (защищает сердце)" else: hd_status, hd_comment = "warning", "Пониженный" metrics.append({ "name": "Холестерин ЛПВП («хороший»)", "value": f"{chol_hd:.1f} ммоль/л", "status": hd_status, "comment": hd_comment, }) trig = data.get("triglycerides", 0) if trig > 0: if trig < 1.7: trig_status, trig_comment = "ok", "Норма" elif trig < 2.3: trig_status, trig_comment = "warning", "Повышенные" else: trig_status, trig_comment = "danger", "Высокие" metrics.append({ "name": "Триглицериды", "value": f"{trig:.1f} ммоль/л", "status": trig_status, "comment": trig_comment, }) # ── Lp(a) ────────────────────────────────────────────────── lpa50 = data.get("lpa50", False) if lpa50: warnings.append("Повышенный уровень липопротеина (а) — фактор риска сердечно-сосудистых заболеваний") advice.append("Проконсультироваться с кардиологом") # ── Дыхание ──────────────────────────────────────────────── resp = data.get("respiratory", 0) if resp > 0: if 12 <= resp <= 20: resp_status, resp_comment = "ok", "Норма" else: resp_status, resp_comment = "warning", "Вне нормы" metrics.append({ "name": "Частота дыхания", "value": f"{resp:.1f} вдохов/мин", "status": resp_status, "comment": resp_comment, }) # ── Стресс ───────────────────────────────────────────────── stress = data.get("stress", 0) if stress > 0: if stress < 50: stress_status, stress_comment = "ok", "Низкий уровень стресса" elif stress < 100: stress_status, stress_comment = "ok", "Умеренный уровень стресса" elif stress < 150: stress_status, stress_comment = "warning", "Повышенный уровень стресса" else: stress_status, stress_comment = "danger", "Высокий уровень стресса" metrics.append({ "name": "Уровень стресса", "value": f"{stress}", "status": stress_status, "comment": stress_comment, }) if stress_status == "warning": warnings.append("Повышенный уровень стресса") advice.append("Практиковать релаксацию, дыхательные упражнения, прогулки") elif stress_status == "danger": warnings.append("Высокий уровень стресса — рекомендуется консультация") advice.append("Обратиться к психологу или психотерапевту") # ── Эластичность сосудов ─────────────────────────────────── rigidity = data.get("rigidity", 0) if rigidity > 0: if rigidity < 9: rig_status, rig_comment = "ok", "Сосуды эластичные" elif rigidity < 12: rig_status, rig_comment = "warning", "Сниженная эластичность" else: rig_status, rig_comment = "danger", "Жёсткие сосуды" metrics.append({ "name": "Эластичность сосудов", "value": f"{rigidity:.1f} м/с", "status": rig_status, "comment": rig_comment, }) # ── Моргания ─────────────────────────────────────────────── blinks = data.get("blinks", 0) metrics.append({ "name": "Моргания", "value": f"{blinks}", "status": "info", "comment": "За время сканирования", }) # ── Сводка ───────────────────────────────────────────────── summary = f"{gender.capitalize()}, {age} лет, {ethnicity}. Эмоция: {emotion}." # Считаем проблемы problems = [m for m in metrics if m["status"] in ("warning", "danger")] if not problems: summary += " Все основные показатели в норме." else: danger = [m for m in metrics if m["status"] == "danger"] warning = [m for m in metrics if m["status"] == "warning"] if danger: summary += f" Обнаружены серьёзные отклонения: {', '.join(m['name'] for m in danger)}." if warning: summary += f" Требуют внимания: {', '.join(m['name'] for m in warning)}." if not advice: advice.append("Продолжайте вести здоровый образ жизни и проходите профилактические осмотры") return { "summary": summary, "metrics": metrics, "warnings": warnings, "advice": advice, }