Flamengo / views /pdf_chat.py
drguilhermeapolinario's picture
Update views/pdf_chat.py
7210600 verified
import os
import streamlit as st
from streamlit_extras.add_vertical_space import add_vertical_space
from streamlit_option_menu import option_menu
st.title("Utilidades")
# Menu aninhado usando streamlit-option-menu na horizontal
nested_menu = option_menu(
menu_title=None,
options=[
"Incidências radiológicas", "TFG", "Coelho e Savassi", "Escore de Risco Global", "Noripurun",
],
icons=['lungs', 'nephrology', 'clinical_notes', 'heart', 'syrenge'],
menu_icon="cast",
default_index=0,
orientation="horizontal",
)
# Conteúdo das subpáginas
if nested_menu == "Incidências radiológicas":
st.header("Apoio clínico na solicitação de radiografias!")
c1, c2, c3, c4 = st.columns([1, 3, 3, 1])
with c1:
st.markdown("")
with c2:
st.header(":blue[Incidências Radiográficas] ☢️")
with c3:
st.image("icon/rx2.svg", width=400)
with c4:
st.markdown("")
add_vertical_space()
# # Descrição com estilo e emojis
st.markdown("""
##### ✅ **Vamos melhorar a visualização das incidências médicas!**
""")
@st.fragment
def exibir_incidencias(regiao, incidencias):
st.markdown(f"## {regiao}")
for incidencia in incidencias:
st.markdown(f"- {incidencia}")
add_vertical_space(3)
st.markdown("### 🧍‍♂️ Selecione a Região do Corpo:")
incidencias_radiograficas = {
"👨‍⚕️ Tórax e Vias Aéreas": [
"👨‍⚕️ Tórax - PA e Lateral",
"🦴 Esterno – OAD e Lateral",
"🦴 Art. Esterno-Clavicular – PA, OAD e OAE",
"🦴 Costelas Posteriores – AP, OPD e OPE",
"🦴 Costelas Anteriores – PA, OAD e OPE",
"👃 Vias aéreas superiores - AP e Lateral",
],
"💢 Abdome e Pelve": [
"💢 Abdome - AP em Decúbito Dorsal",
"💢 RAA - Tórax PA, Abdome em Decúbito Dorsal e Abdome em AP Ortostrica",
"🦵 Pelves (Bacia) - AP e AP perna de Rã, para traumatismo apenas AP",
"🦵 Quadril - AP e Axial Lateral",
"🦴 Art. Sacro-Ilíaca – Axial AP e Oblíquas",
],
"✋ Membros Superiores": [
"✋ Dedos da mão do 2º ao 5º - PA, Lateral e Oblíqua",
"👍 Polegar - AP, Lateral e Oblíqua",
"🖐️ Mão - PA, Lateral e Oblíqua",
"✊ Mão e Punho para Idade Óssea - PA Comparativa",
"✊ Punho - PA, Lateral e Oblíqua",
"🦴 Antebraço - AP e Lateral",
"🦴 Cotovelo - AP e Lateral",
"🦴 Úmero - AP e Lateral",
"💪 Ombro - AP com rotação externa e interna",
"💪 Ombro em traumatismo - AP com rotação neutra, Lateral escapular ou Transtorácica",
"🦴 Clavícula - AP e AP Axial",
"🦴 Art. Acromioclavicular - AP Bilateral com e sem estresse",
"🦴 Escápula - AP e Lateral",
],
"🦵 Membros Inferiores": [
"🦶 Dedos dos pés - AP, Lateral e Oblíqua",
"🦶 Pé - AP, Lateral e Oblíqua",
"🦶 Calcâneo - Axial e Lateral",
"🦵 Tornozelo - AP, AP do encaixe, Lateral e Oblíqua",
"🦿 Joelho - AP, Lateral e Oblíqua",
"🦿 Patela - PA, Lateral e Tangencial",
"🦿 Perna - AP e Lateral",
"🦿 Fêmur – AP e Lateral",
],
"🦴 Coluna Vertebral": [
"🦴 Coluna Cervical - Axial AP, Transoral, Lateral e Oblíqua",
"🦴 Coluna Dorsal ou Torácica - AP e Lateral",
"🦴 Coluna Lombar - AP, Lateral e Oblíqua",
"🦴 Sacro e Cóccix - Axial AP e Lateral",
"🦴 Rotina para Escoliose – AP e Lateral",
"🦴 Rotina para Fusão Vertebral – AP com inclinação Esquerda e Direita Lateral com Hiperextensão e Hiperflexão",
],
"🦷 Cabeça e Face": [
"👤 Crânio - AP Axial, PA e Lateral",
"👃 Ossos da Face - Caldwell, Waters e Lateral",
"👂 Ossos Nasais - Waters e Lateral",
"👄 Mandíbula - Axial Lateral, PA e Axial AP",
"🧠 Seios da Face - Caldwell, Waters e Lateral",
"👂 Arcos Zigomáticos – Axial AP Submentovertice e Tangencial",
"👂 Pirâmide – Rhêse, Caldwell e Waters",
"🦴 ATM's – Axial Lateral e Oblíqua Axial Lateral",
"🦴 Mastoides – Oblíqua Axial Lateral, Oblíqua Axial Anterior e Axial AP",
"🦴 Sela Turcica – Axial AP e Lateral",
]
}
cx1, cx2 = st.columns([1, 1])
with cx1:
st.markdown("")
regioes = list(incidencias_radiograficas.keys())
regiao_escolhida = st.radio("", regioes)
with cx2:
if regiao_escolhida:
exibir_incidencias(
regiao_escolhida,
incidencias_radiograficas[regiao_escolhida])
st.markdown("""
---
Desenvolvedor ☕ **Dr. Guilherme**
""")
elif nested_menu == "TFG":
import pathlib
import streamlit as st
import streamlit.components.v1 as components
from streamlit_extras.add_vertical_space import add_vertical_space
st.header("Calculadora TFG")
static_dir = pathlib.Path('static').absolute()
html_with_js= ''
@st.fragment
def estilo():
css_file_path = static_dir / 'styles.css'
if css_file_path.exists():
with open(css_file_path, "r", encoding="utf-8") as f:
st_css = st.html(f"<style>{f.read()}</style>")
return st_css
else:
st.error(f"CSS file not found: {css_file_path}")
return None
@st.fragment
def linha_vertical(altura=300, cor='black', espessura=2):
"""
Cria uma linha vertical
"""
css = f"""
<style>
.linha-vertical {{
border-left: {espessura}px solid {cor};
height: {altura}px;
position: absolute;
left: 50%;
margin-left: -{espessura/2}px;
}}
</style>
"""
html = f"{css}<div class='linha-vertical'></div>"
linha=st.markdown(html, unsafe_allow_html=True)
return linha
@st.fragment
def calc(html_with_js):
html_with_js = '''
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Calculadora CKD-EPI</title>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background-color: #e0e5ec;
color: #333;
line-height: 1.6;
padding: 20px;
margin: 0;
}
.container {
width: 300px;
max-height: 600px;
margin: 0 auto;
background-color: #e0e5ec;
border-radius: 20px;
padding: 20px;
box-shadow:
8px 8px 15px #a3b1c6,
-8px -8px 15px #ffffff;
}
h2 {
color: #4a4a4a;
text-shadow: 2px 2px 4px rgba(255,255,255,0.5);
text-align: center;
margin-bottom: 20px;
}
.input-group {
margin-bottom: 20px;
position: relative;
}
.input-group label {
display: block;
margin-bottom: 5px;
color: #4a4a4a;
padding-left: 40px;
}
.input-field {
width: 50%;
padding: 12px 20px;
margin-left: 50px;
border: none;
border-radius: 25px;
background-color: #e0e5ec;
color: #333;
font-size: 16px;
box-shadow:
inset 5px 5px 10px #a3b1c6,
inset -5px -5px 10px #ffffff;
}
.icon-wrapper {
position: absolute;
left: 0;
top: 0;
width: 36px;
height: 36px;
background-color: #e0e5ec;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
box-shadow:
5px 5px 10px #a3b1c6,
-5px -5px 10px #ffffff;
}
.input-icon {
color: #4a4a4a;
font-size: 18px;
}
.toggle-container {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
.toggle-switch {
position: relative;
display: inline-block;
width: 60px;
height: 34px;
}
.toggle-switch input {
opacity: 0;
width: 0;
height: 0;
}
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #e0e5ec;
transition: .4s;
border-radius: 34px;
box-shadow:
inset 4px 4px 6px #a3b1c6,
inset -4px -4px 6px #ffffff;
}
.slider:before {
position: absolute;
content: "";
height: 26px;
width: 26px;
left: 4px;
bottom: 4px;
background-color: #e0e5ec;
transition: .4s;
border-radius: 50%;
box-shadow:
2px 2px 3px #a3b1c6,
-2px -2px 3px #ffffff;
}
input:checked + .slider:before {
transform: translateX(26px);
}
.button-group {
display: flex;
justify-content: space-between;
margin-top: 20px;
}
.button {
flex: 1;
padding: 12px 24px;
background-color: #e0e5ec;
border: none;
border-radius: 50px;
color: #4a4a4a;
font-weight: bold;
text-decoration: none;
transition: all 0.3s ease;
box-shadow:
5px 5px 10px #a3b1c6,
-5px -5px 10px #ffffff;
cursor: pointer;
margin: 0 5px;
}
.button:hover {
box-shadow:
inset 5px 5px 10px #a3b1c6,
inset -5px -5px 10px #ffffff;
}
#result {
display: none;
margin-top: 10px;
padding: 10px;
border-radius: 15px;
background-color: #e0e5ec;
box-shadow:
inset 5px 5px 10px #a3b1c6,
inset -5px -5px 10px #ffffff;
}
#result h3 {
margin-top: 0;
color: #4a4a4a;
}
}
.toggle-container {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
.gender-label {
display: flex;
align-items: center;
color: #4a4a4a;
}
.gender-icon {
margin-right: 5px;
font-size: 18px;
}
.toggle-switch {
position: relative;
display: inline-block;
width: 60px;
height: 34px;
}
.toggle-switch input {
opacity: 0;
width: 0;
height: 0;
}
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #e0e5ec;
transition: .4s;
border-radius: 34px;
box-shadow:
inset 4px 4px 6px #a3b1c6,
inset -4px -4px 6px #ffffff;
}
.slider:before {
position: absolute;
content: "";
height: 26px;
width: 26px;
left: 4px;
bottom: 4px;
background-color: #e0e5ec;
transition: .4s;
border-radius: 50%;
box-shadow:
2px 2px 3px #a3b1c6,
-2px -2px 3px #ffffff;
}
input:checked + .slider:before {
transform: translateX(26px);
}
</style>
</head>
<body>
<div class="container">
<h2>Calculadora CKD-EPI</h2>
<form id="ckd-epi-form">
<div class="input-group">
<div class="icon-wrapper">
<i class="fas fa-birthday-cake input-icon"></i>
</div>
<label for="age">Idade</label>
<input type="number" id="age" class="input-field" required>
</div>
<div class="toggle-container">
<span class="gender-label">
<i class="fas fa-mars gender-icon"></i>
Masculino
</span>
<label class="toggle-switch">
<input type="checkbox" id="gender-toggle">
<span class="slider"></span>
</label>
<span class="gender-label">
<i class="fas fa-venus gender-icon"></i>
Feminino
</span>
</div>
<div class="input-group">
<div class="icon-wrapper">
<i class="fas fa-vial input-icon"></i>
</div>
<label for="serumCreatinine">Creatinina Sérica (mg/dL)</label>
<input type="number" id="serumCreatinine" class="input-field" step="0.01" required>
</div>
<div class="button-group">
<button type="button" id="calcular" class="button">Calcular</button>
<button type="button" id="clear-button" class="button">Limpar</button>
</div>
</form>
<div id="result"></div>
</div>
<script>
document.getElementById("calcular").addEventListener("click", calculate);
function calculate() {
const age = parseFloat(document.getElementById("age").value);
const serumCreatinine = parseFloat(document.getElementById("serumCreatinine").value);
const gender = document.getElementById('gender-toggle').checked ? 'female' : 'male';
if (!isNaN(age) && !isNaN(serumCreatinine)) {
let A, B = 0;
if (serumCreatinine <= 0.7) {
A = gender === "male" ? 0.9 : 0.7;
B = gender === "male" ? -0.302 : -0.241;
} else {
A = gender === "male" ? 0.9 : 0.7;
B = -1.2;
}
let result = 142 * Math.pow((serumCreatinine/A), B) * Math.pow(0.9938, age);
if (gender == 'female') result = result * 1.012;
const stage = getCKDStage(result);
const resultElement = document.getElementById('result');
resultElement.innerHTML = `
<h4>Resultado:</h4>
<p>eGFR CKD-EPI: <strong><span class="h3">${result.toFixed(0)} <span class="h4">mL/min/1.73 m²</span></span></strong></p>
<p>Estágio DRC: <strong>${stage}</strong></p>
`;
resultElement.style.display = 'block';
} else {
alert("Por favor, preencha todos os campos corretamente.");
}
}
function getCKDStage(gfr) {
if (gfr >= 90) return "Estágio 1";
if (gfr >= 60) return "Estágio 2";
if (gfr >= 45) return "Estágio 3a";
if (gfr >= 30) return "Estágio 3b";
if (gfr >= 15) return "Estágio 4";
return "Estágio 5";
}
document.getElementById('clear-button').addEventListener('click', function() {
document.getElementById('ckd-epi-form').reset();
document.getElementById('result').innerHTML = '';
document.getElementById('result').style.display = 'none';
});
</script>
</body>
</html>
'''
calculadora = components.html(html_with_js, width=400,height=900)
return calculadora
@st.fragment
def icon_close():
st.markdown("""
<style>
.stKey-icon-wrapper {
position: absolute;
left: -22px;
top: 0;
width: 180px;
height: 180px;
background-color: #e0e5ec;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
padding: 5px;
box-shadow:
5px 5px 10px #a3b1c6,
-5px -5px 10px #ffffff;
}
.stKey-icon-wrapper img {
width: 24px;
height: 24px;
filter: invert(20%) sepia(10%) saturate(2076%) hue-rotate(86deg) brightness(95%) contrast(86%);
}
</style>
""", unsafe_allow_html=True)
with st.container():
st.markdown('<div class="stKey-icon-wrapper">', unsafe_allow_html=True)
st.image('icon/rim.svg', use_container_width=False, width=140)
icon_top= st.markdown('</div>', unsafe_allow_html=True)
return icon_top
estilo()
cx1,cx2,cx3=st.columns([3,1,6])
with cx1:
icon_close()
with cx2:
st.write('')
cx3.title('''
:blue[Calculadora TFG] :blue[| CKD-EPI] 📝
''' )
c1, c2, c3, c4 = st.columns([2,0.5,3,3])
with c1:
calc(html_with_js)
with c2:
add_vertical_space()
# linha_vertical(altura=800, cor='#73A6E2', espessura=2)
with c3:
expander = st.expander("Estágios da DRC", expanded=False, icon='📝')
expander.write('''
# Estagios da IRC:
- **Estágio 1:**
- TFG ≥ 90 mL/min/1.73m²
- (Função renal normal ou aumentada)
- **Estágio 2:**
- TFG 60-89 mL/min/1.73m²
- (Diminuição leve da função renal)
- **Estágio 3a:**
- TFG 45-59 mL/min/1.73m²
- (Diminuição leve a moderada da função renal)
- **Estágio 3b:**
- TFG 30-44 mL/min/1.73m²
- :blue[(Diminuição moderada a severa da função renal)]
- **Estágio 4:**
- TFG 15-29 mL/min/1.73m²
- :orange[(Diminuição severa da função renal)]
- **Estágio 5:**
- TFG < 15 mL/min/1.73m²
- :red[(Falência renal)]
''')
with c4:
recomendacoes= ('''
## Recomendações gerais para pacientes com DRC
:green[As diretrizes KDIGO 2024 incorporou a TFG e a albuminúria como fatores críticos.]
:blue[**1. Estágios 1 e 2 (TFG ≥ 60 mL/min/1,73m²):**]
###### Monitoramento Regular: Avaliação periódica da função renal e da albuminúria é recomendada para detectar progressão da doença.
###### Controle de Fatores de Risco: Controle rigoroso da pressão arterial e glicemia, especialmente em pacientes com diabetes, é essencial.
###### Modificações no Estilo de Vida: Incentivar dieta saudável, cessação do tabagismo e atividade física regular.
:blue[**2. Estágio 3a e 3b (TFG 30-59 mL/min/1,73m²):**]
###### Ajuste de Medicamentos: Revisão e ajuste de dosagens de medicamentos que são excretados pelos rins.
###### Avaliação de Risco Cardiovascular: A albuminúria e a TFG devem ser usadas para avaliar o risco cardiovascular e ajustar o tratamento.
###### Referência a Nefrologista: Considerar encaminhamento para um nefrologista para manejo especializado.
:blue[**3. Estágio 4 (TFG 15-29 mL/min/1,73m²):**]
###### Preparação para Terapia de Substituição Renal: Discussão sobre opções de diálise e transplante renal deve ser iniciada.
###### Monitoramento Intensivo: Acompanhamento mais frequente para monitorar a progressão da doença e complicações associadas.
:blue[**4. Estágio 5 (TFG < 15 mL/min/1,73m²):**]
###### Terapia de Substituição Renal: Início de diálise ou avaliação para transplante renal.
###### Cuidados Paliativos: Considerar cuidados paliativos para pacientes que não são candidatos a diálise ou transplante.
_Além disso, a quantificação da albuminúria é crucial em todos os estágios
para guiar decisões terapêuticas, como a escolha de medicamentos anti-
hipertensivos. A avaliação individualizada, considerando a situação clínica
do paciente, é fundamental para o manejo eficaz da DRC._
''')
with st.expander(label='Recomendações', expanded=False, icon="🔥"):
st.markdown(recomendacoes, unsafe_allow_html=True)
st.markdown("""
---
Desenvolvedor ☕ **Dr. Guilherme**
""")
elif nested_menu == "Coelho e Savassi":
import pandas as pd
import streamlit as st
st.header("Escala de Risco de Coelho e Savassi")
STYLE = "static/style.css"
with open(STYLE, "r", encoding="utf-8") as f:
st.markdown(f"<style>{f.read()}</style>", unsafe_allow_html=True)
STYLE = "static/styles.html"
with open(STYLE, "r", encoding="utf-8") as f:
st.markdown(f"<style>{f.read()}</style>", unsafe_allow_html=True)
# CSS personalizado
st.markdown("""
<style>
.stCheckbox {
font-size: 18px;
}
.stButton > button {
width: 100%;
}
.risk-result {
font-size: 24px;
font-weight: bold;
padding: 10px;
border-radius: 5px;
margin-top: 20px;
}
.risk-menor {
background-color: #2ecc71;
color: white;
}
.risk-medio {
background-color: #f39c12;
color: white;
}
.risk-maior {
background-color: #e74c3c;
color: white;
}
.risk-maximo {
background-color: #c0392b;
color: white;
}
</style>
""",
unsafe_allow_html=True)
# Título
st.title("📊 Calculadora da Escala de Risco de Coelho e Savassi")
# Criando colunas para organizar o layout
col1, col2, col3, col4 = st.columns([2,2,3,2])
# Fatores de risco
fatores = [{
"id": "acamado",
"label": "🛏️ Acamado",
"peso": 3
}, {
"id": "deficienciaFisica",
"label": "♿ Deficiência física",
"peso": 3
}, {
"id": "deficienciaMental",
"label": "🧠 Deficiência mental",
"peso": 3
}, {
"id": "baixoSaneamento",
"label": "🚽 Baixas condições de saneamento",
"peso": 3
}, {
"id": "desnutricaoGrave",
"label": "⚖️ Desnutrição grave",
"peso": 3
}, {
"id": "drogadicao",
"label": "💊 Drogadição",
"peso": 2
}, {
"id": "desemprego",
"label": "💼 Desemprego",
"peso": 2
}, {
"id": "analfabetismo",
"label": "📚 Analfabetismo",
"peso": 1
}, {
"id": "menorSeisMeses",
"label": "👶 Menor de 6 meses",
"peso": 1
}, {
"id": "maiorSetentaAnos",
"label": "👴 Maior de 70 anos",
"peso": 1
}, {
"id": "hipertensao",
"label": "❤️ Hipertensão arterial sistêmica",
"peso": 1
}, {
"id": "diabetes",
"label": "💉 Diabetes mellitus",
"peso": 1
}]
# Criando checkboxes para os fatores de risco
with col1:
st.subheader("Fatores de Risco")
checkboxes = {}
for fator in fatores:
checkboxes[fator["id"]] = st.checkbox(fator["label"])
with col2:
st.subheader("Informações Adicionais")
num_comodos = st.number_input("🏠 Número de cômodos", min_value=1, value=1)
num_moradores = st.number_input("👥 Número de moradores",
min_value=1,
value=1)
# Botão para calcular o risco
if st.button("Calcular Risco", use_container_width=True, icon="🧮️" ):
pontuacao_total = sum(fator["peso"] for fator in fatores
if checkboxes[fator["id"]])
# Cálculo do escore de cômodos por pessoa
escore_comodo_pessoa = num_comodos / num_moradores
if escore_comodo_pessoa < 1:
pontuacao_total += 3
# Determinação da classificação de risco
if pontuacao_total <= 4:
classificacao = "Risco Menor"
classe_css = "risk-menor"
icone = "✅"
elif pontuacao_total <= 6:
classificacao = "Risco Médio"
classe_css = "risk-medio"
icone = "⚠️"
elif pontuacao_total <= 8:
classificacao = "Risco Maior"
classe_css = "risk-maior"
icone = "🚨"
else:
classificacao = "Risco Máximo"
classe_css = "risk-maximo"
icone = "☠️"
# Exibição do resultado
st.markdown(f"""
<div class='risk-result {classe_css}'>
{icone} Classificação: {classificacao}<br>
📊 Pontuação: {pontuacao_total}<br>
🏠 Cômodos por pessoa: {escore_comodo_pessoa:.2f}
</div>
""",
unsafe_allow_html=True)
st.subheader("Detalhes da Pontuação")
detalhes = []
for fator in fatores:
if checkboxes[fator["id"]]:
detalhes.append({"Fator": fator["label"], "Peso": fator["peso"]})
if escore_comodo_pessoa < 1:
detalhes.append({"Fator": "🏠 Menos de 1 cômodo por pessoa", "Peso": 3})
df_detalhes = pd.DataFrame(detalhes)
st.table(df_detalhes)
with col3, st.expander("Sobre a Escala de Risco de Coelho e Savassi", icon='❤️', expanded=False):
st.markdown("""
---
### Sobre a Escala de Risco de Coelho e Savassi
A Escala de Risco de Coelho e Savassi é uma ferramenta utilizada na Atenção Primária à Saúde no Brasil para avaliar o risco familiar em territórios de saúde.
Ela foi desenvolvida pelos médicos brasileiros Marcos Alencar Abaide Balbinotti Coelho e Maria Inês Ribeiro de Miranda Savassi.
#### Como interpretar os resultados:
- **Risco Menor (≤ 4 pontos)**: Acompanhamento de rotina
- **Risco Médio (5-6 pontos)**: Acompanhamento programado
- **Risco Maior (7-8 pontos)**: Acompanhamento prioritário
- **Risco Máximo (≥ 9 pontos)**: Acompanhamento intensivo
Esta calculadora é uma ferramenta de apoio e não substitui a avaliação profissional.
""")
with col4:
st.write('')
elif nested_menu == "Escore de Risco Global":
import numpy as np
import pandas as pd
import streamlit as st
cxc1, cxc2, cxc3 = st.columns([2, 1.5, 1.5])
# Título
with cxc1:
st.header("Escore de Risco Global")
st.markdown("Recomendado pela Sociedade Brasileira de Cardiologia ❤️")
with cxc2:
st.image("icon/cardio.svg", width=100)
# CSS melhorado
st.markdown("""
<style>
.st-key-risco button {
width: 30%;
}
.st-key-veridade input {
display: grid;
width: 100px;
border: 1px solid #ccc;
}
.risk-result {
padding: 20px;
border-radius: 10px;
margin: 20px 0;
font-size: 1.1em;
}
.risk-baixo {
background-color: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
}
.risk-intermediario {
background-color: #fff3cd;
color: #856404;
border: 1px solid #ffeeba;
}
.risk-alto {
background-color: #fff3cd;
color: #856404;
border: 1px solid #ffeeba;
}
.risk-muito-alto {
background-color: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
}
</style>
""", unsafe_allow_html=True)
def get_recomendacao_estatina(risco, pontos, idade, diabetes):
"""
Determina a recomendação de estatinas baseada no risco cardiovascular e características do paciente
"""
if risco == "Muito Alto":
return """
### 🔴 Recomendação: Estatina de Alta Intensidade
- Atorvastatina 40-80 mg ou
- Rosuvastatina 20-40 mg
**Objetivo:** Redução ≥50% do LDL-C, com meta de LDL-C <70 mg/dL
"""
elif risco == "Alto":
return """
### 🔴 Recomendação: Estatina de Alta Intensidade
- Atorvastatina 40-80 mg ou
- Rosuvastatina 20-40 mg
**Alternativa se não tolerada:**
### 🔵 Estatina de Intensidade Moderada
- Atorvastatina 10-20 mg ou
- Rosuvastatina 5-10 mg ou
- Sinvastatina 20-40 mg
"""
elif risco == "Intermediário":
base_rec = """
### 🔵 Recomendação: Estatina de Intensidade Moderada
- Atorvastatina 10-20 mg ou
- Rosuvastatina 5-10 mg ou
- Sinvastatina 20-40 mg
"""
if diabetes and 40 <= idade <= 75:
base_rec += "\n\n**Nota:** Devido à presença de diabetes, considerar intensificar para estatina de alta intensidade se houver outros fatores de risco."
return base_rec
else: # Baixo risco
if diabetes and 40 <= idade <= 75:
return """
### 🔵 Recomendação: Estatina de Intensidade Moderada
- Atorvastatina 10-20 mg ou
- Rosuvastatina 5-10 mg ou
- Sinvastatina 20-40 mg
**Nota:** Recomendação baseada na presença de diabetes.
"""
else:
return """
### 🟢 Considerar Estatina de Baixa Intensidade
- Sinvastatina 10 mg ou
- Pravastatina 10-20 mg
**Nota:** A necessidade de estatina deve ser avaliada individualmente pelo médico considerando outros fatores de risco.
"""
# Criando colunas para organizar o layout
col1, col2, col3, col4, col5 = st.columns([1,0.5,1,0.2,2.5])
with col1:
st.subheader("Dados Pessoais")
sexo = st.radio("Sexo", ["Masculino", "Feminino"])
idade = st.number_input("Idade", min_value=30, max_value=74, value=30, key='idade')
tabagismo = st.checkbox("Tabagismo")
diabetes = st.checkbox("Diabetes")
with col2:
st.write('')
with col3:
st.subheader("Dados Clínicos")
colesterol_total = st.number_input("Colesterol Total (mg/dL)",
min_value=0,
max_value=600,
help="Valor normal: < 200 mg/dL")
hdl = st.number_input("HDL Colesterol (mg/dL)",
min_value=0,
max_value=100,
value=50,
help="Valor ideal: > 40 mg/dL")
pas = st.number_input("Pressão Arterial Sistólica (mmHg)",
min_value=0,
max_value=300,
help="Valor normal: < 130 mmHg")
with col4:
st.write('')
with col5:
st.subheader("Calcular resultado")
def calcular_erg(sexo, idade, tabagismo, diabetes, colesterol_total, hdl, pas):
pontos = 0
# Idade
if sexo == "Masculino":
if idade < 35:
pontos -= 1
elif 35 <= idade <= 39:
pontos += 0
elif 40 <= idade <= 44:
pontos += 1
elif 45 <= idade <= 49:
pontos += 2
elif 50 <= idade <= 54:
pontos += 3
elif 55 <= idade <= 59:
pontos += 4
elif 60 <= idade <= 64:
pontos += 5
elif 65 <= idade <= 69:
pontos += 6
else:
pontos += 7
else: # Feminino
if idade < 35:
pontos -= 9
elif 35 <= idade <= 39:
pontos -= 4
elif 40 <= idade <= 44:
pontos += 0
elif 45 <= idade <= 49:
pontos += 3
elif 50 <= idade <= 54:
pontos += 6
elif 55 <= idade <= 59:
pontos += 7
elif 60 <= idade <= 69:
pontos += 8
else:
pontos += 8
# Colesterol Total
if sexo == "Masculino":
if colesterol_total < 160:
pontos -= 3
elif 160 <= colesterol_total <= 199:
pontos += 0
elif 200 <= colesterol_total <= 239:
pontos += 1
elif 240 <= colesterol_total <= 279:
pontos += 2
else:
pontos += 3
else: # Feminino
if colesterol_total < 160:
pontos -= 2
elif 160 <= colesterol_total <= 199:
pontos += 0
elif 200 <= colesterol_total <= 239:
pontos += 1
elif 240 <= colesterol_total <= 279:
pontos += 2
else:
pontos += 3
# HDL (mesmo para ambos os sexos)
if hdl < 40:
pontos += 2
elif 40 <= hdl <= 49:
pontos += 1
elif 50 <= hdl <= 59:
pontos += 0
else:
pontos -= 2
# Pressão Arterial Sistólica
if pas < 120:
pontos += 0
elif 120 <= pas <= 129:
pontos += 1
elif 130 <= pas <= 139:
pontos += 2
elif 140 <= pas <= 159:
pontos += 3
else:
pontos += 4
# Diabetes
if diabetes:
if sexo == "Masculino":
pontos += 4
else:
pontos += 6
# Tabagismo
if tabagismo:
if sexo == "Masculino":
pontos += 4
else:
pontos += 3
return pontos
if st.button("Calcular", icon='📝', key='risco'):
# Validações
if colesterol_total == 0:
st.error("Por favor, insira um valor válido para o Colesterol Total")
elif pas == 0:
st.error("Por favor, insira um valor válido para a Pressão Arterial")
else:
pontos = calcular_erg(sexo, idade, tabagismo, diabetes, colesterol_total,
hdl, pas)
if pontos < 5:
risco = "Baixo"
classe_css = "risk-baixo"
probabilidade = "< 5%"
elif 5 <= pontos <= 10:
risco = "Intermediário"
classe_css = "risk-intermediario"
probabilidade = "5 a 10%"
elif 11 <= pontos <= 20:
risco = "Alto"
classe_css = "risk-alto"
probabilidade = "10 a 20%"
else:
risco = "Muito Alto"
classe_css = "risk-muito-alto"
probabilidade = "> 20%"
# Exibição do resultado
st.markdown(f"""
<div class='risk-result {classe_css}'>
<strong>Risco Cardiovascular:</strong> {risco}<br>
<strong>Pontuação:</strong> {pontos}<br>
<strong>Probabilidade de evento cardiovascular em 10 anos:</strong> {probabilidade}
</div>
""", unsafe_allow_html=True)
# Após exibir o resultado do risco, adicionar:
st.markdown("---")
st.subheader("💊 Recomendação de Estatinas")
if idade > 75:
st.warning("""
**Atenção:** Para pacientes acima de 75 anos, a terapia com estatinas deve ser individualizada,
considerando benefícios e riscos potenciais. Recomenda-se geralmente estatinas de intensidade moderada.
""")
recomendacao = get_recomendacao_estatina(risco, pontos, idade, diabetes)
st.markdown(recomendacao)
st.info("""
**Observações importantes:**
1. Recomendações baseadas em diretrizes, mas a decisão final deve ser individualizada pelo médico.
2. Monitorar níveis de transaminases antes de iniciar as estatinas.
3. Reavaliar níveis lipídicos 1-3 meses após início da terapia.
4. Em caso de intolerância, considerar alternativas como ácido bempedoico ou inibidores de PCSK9.
5. Estatinas são contraindicadas na gestação.
""")
# Se diabetes presente, adicionar informação específica
if diabetes:
st.markdown("""
**Nota sobre Diabetes:**
- Para pacientes com diabetes entre 40-75 anos, é recomendada pelo menos estatina de intensidade moderada.
- Se houver múltiplos fatores de risco, considerar estatina de alta intensidade com meta de redução ≥50% do LDL-C.
""")
# Informações adicionais
st.info("""
**Interpretação das Faixas de Risco:**
- **Baixo:** < 5% de chance de evento cardiovascular em 10 anos
- **Intermediário:** 5-10% de chance de evento cardiovascular em 10 anos
- **Alto:** 10-20% de chance de evento cardiovascular em 10 anos
- **Muito Alto:** > 20% de chance de evento cardiovascular em 10 anos
""")
@st.fragment
def tab_final(idade, sexo, colesterol_total, hdl, pas, diabetes, tabagismo):
# Tabela de detalhes
st.subheader("Detalhes da Avaliação")
detalhes = [{
"Fator de Risco": "Idade",
"Valor": f"{idade} anos"
}, {
"Fator de Risco": "Sexo",
"Valor": sexo
}, {
"Fator de Risco": "Colesterol Total",
"Valor": f"{colesterol_total} mg/dL"
}, {
"Fator de Risco": "HDL Colesterol",
"Valor": f"{hdl} mg/dL"
}, {
"Fator de Risco": "Pressão Arterial Sistólica",
"Valor": f"{pas} mmHg"
}, {
"Fator de Risco": "Diabetes",
"Valor": "Sim" if diabetes else "Não"
}, {
"Fator de Risco": "Tabagismo",
"Valor": "Sim" if tabagismo else "Não"
}]
df_detalhes = pd.DataFrame(detalhes)
df_paciente = st.dataframe(df_detalhes, hide_index=True)
return df_paciente
tab_final(idade, sexo, colesterol_total, hdl, pas, diabetes, tabagismo)
@st.fragment
def estat():
with st.expander("Intensidade das Estatinas", icon='💊', expanded=False):
st.markdown("""
| Intensidade | Estatinas e Doses |
|-------------|-------------------|
| **Alta** | - Atorvastatina 40-80 mg |
| | - Rosuvastatina 20-40 mg |
| **Moderada** | - Atorvastatina 10-20 mg |
| | - Rosuvastatina 5-10 mg |
| | - Sinvastatina 20-40 mg |
| | - Pravastatina 40-80 mg |
| | - Lovastatina 40 mg |
| | - Fluvastatina XL 80 mg |
| | - Pitavastatina 1-4 mg |
| **Baixa** | - Sinvastatina 10 mg |
| | - Pravastatina 10-20 mg |
| | - Lovastatina 20 mg |
| | - Fluvastatina 20-40 mg |
**As estatinas de alta intensidade reduzem o LDL-C em ≥50%, as de
intensidade moderada em 30-49%, e as de baixa intensidade em <30%.**
""", unsafe_allow_html=True)
@st.fragment
def estatinas():
with st.expander("Intensidade das Estatinas", icon='💊', expanded=False):
st.markdown("""
<style>
@import url('https://fonts.googleapis.com/css2?family=Noto+Serif+Oriya:[email protected]&display=swap');
body {
text-align: justify;
font-family: 'Noto Serif Oriya', serif;
}
.noto-serif-oriya-400 {
font-family: "Noto Serif Oriya", serif;
font-optical-sizing: auto;
font-weight: 400;
font-style: normal;
}
p {
margin-bottom: 15px;
}
</style>
# Estatinas
<div style="text-align: justify">
- Diretrizes 2024: American College of Cardiology (ACC), American Heart Association (AHA) e American Diabetes Association (ADA).
- Evidências de ensaios clínicos randomizados e meta-análises: Eficácia das estatinas na redução de eventos cardiovasculares ateroscleróticos (ASCVD).
## Início da Terapia com Estatinas
***1. Prevenção Primária:***
- **:red[Pacientes com DM:]**
- :blue[DM entre 40-75a], sem ASCVD → Estatina de intensidade moderada + mudanças no estilo de vida.
- :blue[DM entre 20-39a], com fatores de risco adicionais para ASCVD → Pode ser razoável iniciar estatina.
- :blue[DM entre 40-75a], com ↑↑↑ risco cardiovascular → Estatinas de alta intensidade → ↓↓LDL-C em ≥50% do valor basal. Objetivo → LDL-C <70 mg/dL.<sup>[1]</sup>
- **:green[Pacientes sem DM:]**
- ACC/AHA → Estatinas de intensidade moderada a alta em pacientes com risco de ASCVD a 10 anos ≥7,5%
- NICE e USPSTF → Iniciar estatinas se o risco for ≥10%.<sup>[2]</sup>
***2. Prevenção Secundária:***
- Pacientes com ASCVD:
- Todos com ASCVD → Iniciar ou continuar estatinas de alta intensidade, a menos que haja contraindicações.<sup>[3-4]</sup>
- Se estatina de alta intensidade for contraindicada ou não tolerada, → Estatina de intensidade moderada.<sup>[4]</sup>
***3. Intensidade da Terapia com Estatinas:***
- 🔴 :red[Alta Intensidade] ↓↓LDL-C em ≥50%.<sup>[5-6]</sup>
- 🔵 :blue[Moderada]: ↓↓LDL-C em 30-49%.<sup>[5-6]</sup>
- 🟢 :green[Baixa Intensidade]: ↓↓LDL-C em <30%.<sup>[6]</sup>
***4. Monitoramento e Ajustes:***
- Inicial:
- Níveis de transaminases, antes de iniciar estatinas.
- Níveis de lipídios → Devem ser reavaliados 1-3 meses após o início da terapia.<sup>[2]</sup>
- Ajustes:
- Se resposta inadequada, → Considerar adição de ezetimiba ou inibidores de PCSK9, especialmente em pacientes de alto risco.<sup>[1][7]</sup>
***5. Considerações Especiais:***
- Idosos (>75 anos):
- Terapia com estatinas de intensidade moderada, considerar benefícios e riscos potenciais.<sup>[1][5]</sup>
- Intolerância às Estatinas:
- Alternativas → Ácido bempedoico ou inibidores de PCSK9.<sup>[1]</sup>
***6. Contraindicações:***
- :red[Gravidez:]
- Estatinas são contraindicadas na gestação.<sup>[1]</sup>
##### Referências:
<sup>
1. Cardiovascular Disease and Risk Management: Standards of Care in Diabetes-2024.
Diabetes Care. 2024;47(Suppl 1):S179-S218. doi:10.2337/dc24-S010.
</sup>
<br><br>
<sup>
2. Hyperlipidemia: Drugs for Cardiovascular Risk Reduction in Adults.
Last AR, Ference JD, Menzel ER.
American Family Physician. 2017;95(2):78-87.
</sup>
<br><br>
<sup>
3. 2013 ACCF/­AHA Guideline for the Management of ST-elevation Myocardial Infarction: A Report of the American College of Cardiology Foundation/­American Heart Association Task Force on Practice Guidelines.
O 'Gara PT, Kushner FG, Ascheim DD, et al.
</sup>
<br><br>
<sup>
4. 2018 AHA/­ACC/­AACVPR/­AAPA/­ABC/­ACPM/­ADA/­AGS/­APhA/­ASPC/­NLA/­PCNA Guideline on the Management of Blood Cholesterol: A Report of the American College of Cardiology/­American Heart Association Task Force on Clinical Practice Guidelines.
Grundy SM, Stone NJ, Bailey AL, et al.
Journal of the American College of Cardiology. 2019;73(24):e285-e350. doi:10.1016/j.jacc.2018.11.003.
</sup>
</div>
""", unsafe_allow_html=True
)
cft1, cft2, cft3 = st.columns([1, 2, 1])
with cft1:
estat()
with cft2:
estatinas()
with cft3:
st.write('')
elif nested_menu == "Noripurun":
import pathlib
import streamlit as st
import streamlit.components.v1 as components
from streamlit_extras.add_vertical_space import add_vertical_space
st.header("Noripurun")
static_dir = pathlib.Path('static').absolute()
html_with_js= ''
@st.fragment
def estil():
css_file_path = static_dir / 'styles.css'
if css_file_path.exists():
with open(css_file_path, "r", encoding="utf-8") as f:
st_css = st.html(f"<style>{f.read()}</style>")
return st_css
else:
st.error(f"CSS file not found: {css_file_path}")
return None
@st.fragment
def noripurun(html_with_js):
html_with_js = '''
<!DOCTYPE html>
<html>
<head>
<style>
:root {
--primary-color: #2196F3;
--bg-color: #e0e5ec;
--text-color: #2d4059;
--shadow-light: #ffffff;
--shadow-dark: #a3b1c6;
}
body {
background-color: var(--bg-color);
color: var(--text-color);
font-family: 'Segoe UI', Arial, sans-serif;
line-height: 1.6;
margin: 0;
padding: 20px;
}
.calculator-container {
max-width: 800px;
margin: 40px auto;
padding: 30px;
background: var(--bg-color);
border-radius: 20px;
box-shadow:
8px 8px 15px var(--shadow-dark),
-8px -8px 15px var(--shadow-light);
}
.header {
text-align: center;
margin-bottom: 30px;
}
.header h2 {
color: var(--primary-color);
margin: 0;
padding: 15px;
border-radius: 10px;
box-shadow:
inset 5px 5px 10px var(--shadow-dark),
inset -5px -5px 10px var(--shadow-light);
}
.info-box, .details-box {
padding: 20px;
margin: 20px 0;
border-radius: 15px;
box-shadow:
inset 5px 5px 10px var(--shadow-dark),
inset -5px -5px 10px var(--shadow-light);
}
.form-group {
margin: 25px 0;
}
label {
display: block;
margin-bottom: 10px;
font-weight: 600;
color: var(--text-color);
}
input, select {
width: 60%;
padding: 12px;
border: none;
border-radius: 10px;
background: var(--bg-color);
box-shadow:
inset 5px 5px 10px var(--shadow-dark),
inset -5px -5px 10px var(--shadow-light);
color: var(--text-color);
font-size: 16px;
transition: all 0.3s ease;
}
input:focus, select:focus {
outline: none;
box-shadow:
inset 3px 3px 5px var(--shadow-dark),
inset -3px -3px 5px var(--shadow-light);
}
.calculate-btn {
width: 100%;
padding: 15px;
border: none;
border-radius: 10px;
background: var(--bg-color);
color: var(--primary-color);
font-size: 18px;
font-weight: bold;
cursor: pointer;
box-shadow:
5px 5px 10px var(--shadow-dark),
-5px -5px 10px var(--shadow-light);
transition: all 0.3s ease;
}
.calculate-btn:hover {
box-shadow:
3px 3px 5px var(--shadow-dark),
-3px -3px 5px var(--shadow-light);
}
.calculate-btn:active {
box-shadow:
inset 3px 3px 5px var(--shadow-dark),
inset -3px -3px 5px var(--shadow-light);
}
.result-box {
margin-top: 30px;
padding: 20px;
border-radius: 15px;
box-shadow:
inset 5px 5px 10px var(--shadow-dark),
inset -5px -5px 10px var(--shadow-light);
}
.formula-box {
background: var(--bg-color);
padding: 20px;
border-radius: 10px;
box-shadow:
inset 3px 3px 5px var(--shadow-dark),
inset -3px -3px 5px var(--shadow-light);
font-family: monospace;
font-size: 14px;
line-height: 1.8;
}
table {
width: 100%;
border-spacing: 10px;
border-collapse: separate;
margin: 20px 0;
}
th, td {
padding: 10px;
text-align: left;
background: var(--bg-color);
border-radius: 12px;
box-shadow:
1px 1px 2px var(--shadow-dark),
-1px -1px 2px var(--shadow-light);
}
th {
background: var(--primary-color);
color: white;
font-weight: 600;
}
.alert {
padding: 15px;
margin: 15px 0;
border-radius: 10px;
background: #fff3e0;
box-shadow:
3px 3px 5px var(--shadow-dark),
-3px -3px 5px var(--shadow-light);
}
.warning {
background: #ffebee;
}
.dilution-info {
background: var(--bg-color);
padding: 15px;
margin: 15px 0;
border-radius: 10px;
box-shadow:
inset 3px 3px 5px var(--shadow-dark),
inset -3px -3px 5px var(--shadow-light);
}
.info-grid {
display: flex;
gap: 20px;
}
details {
flex: 1;
}
summary {
cursor: pointer;
}
section {
display: flex;
flex-direction: row;
gap: 20px;
}
@media (max-width: 768px) {
.info-grid {
grid-template-columns: 1fr;
}
}
</style>
</head>
<body>
<div class="calculator-container">
<div class="header">
<h2>Calculadora de Dose - Noripurum</h2>
<strong>Parâmetros Importantes:</strong>
</div>
<div class="info-box">
<div class="info-grid">
<details>
<summary><h4>Limites de Dose:</h4></summary>
<ul>
<li>Dose máxima por aplicação: 200mg</li>
<li>Dose máxima semanal: 500mg</li>
<li>Intervalo mínimo entre doses: 24h</li>
</ul>
</details>
<details>
<summary><h4>Diluição e Administração:</h4></summary>
<ul>
<li>Diluição mínima: 100mL SF 0,9% por ampola</li>
<li>Tempo mínimo de infusão: 15 min/ampola</li>
<li>Administrar exclusivamente em SF 0,9%</li>
</ul>
</details>
<details>
<summary><h4>Reserva de Ferro:</h4></summary>
<ul>
<li>Pacientes < 35kg: 15mg/kg</li>
<li>Pacientes ≥ 35kg: 500mg fixo</li>
</ul>
</details>
</div>
</div>
<section>
<div class="form-group">
<label for="peso">Peso do Paciente (kg):</label>
<input type="number" id="peso" min="0" step="0.1" required>
</div>
<div class="form-group">
<label for="hb-atual">Hemoglobina Atual (g/dL):</label>
<input type="number" id="hb-atual" min="0" step="0.1" required>
</div>
<div class="form-group">
<label for="hb-alvo">Hemoglobina Alvo (g/dL):</label>
<select id="hb-alvo" required>
<option value="12">12 g/dL</option>
<option value="13">13 g/dL</option>
<option value="14">14 g/dL</option>
<option value="15">15 g/dL</option>
</select>
</div>
</section>
<small style="color: #666; display:grid">Padrão: 12 g/dL (mulheres) / 13 g/dL (homens)</small>
<div style="display: grid; justify-content: center;">
<button class="calculate-btn" onclick="calcularDose()">Calcular Dose</button>
</div>
<div id="resultado" class="result-box">
<div id="alert-box"></div>
<div class="details-box">
<strong>Detalhes do Cálculo:</strong>
<div id="calculo-detalhado"></div>
</div>
<div class="result-item">
<strong>Déficit Total de Ferro:</strong> <span id="deficit-total"></span>
</div>
<div class="result-item">
<strong>Esquema de Administração Recomendado:</strong>
<div id="esquema-admin"></div>
</div>
</div>
</div>
<script>
function calcularDose() {
// Obter e validar valores de entrada
const peso = parseFloat(document.getElementById('peso').value);
const hbAtual = parseFloat(document.getElementById('hb-atual').value);
const hbAlvo = parseFloat(document.getElementById('hb-alvo').value);
if (!validarEntradas(peso, hbAtual, hbAlvo)) {
return;
}
// Cálculos principais
const reservaFerro = calcularReservaFerro(peso);
const dhb = hbAlvo - hbAtual;
const deficitTotal = Math.round((peso * dhb * 2.4) + reservaFerro);
// Exibir resultados
mostrarResultados(peso, hbAtual, hbAlvo, dhb, reservaFerro, deficitTotal);
criarEsquemaAdministracao(deficitTotal);
mostrarAlertas(hbAtual, hbAlvo, deficitTotal);
}
function validarEntradas(peso, hbAtual, hbAlvo) {
if (!peso || !hbAtual || !hbAlvo) {
alert('Por favor, preencha todos os campos!');
return false;
}
if (peso <= 0 || hbAtual <= 0 || hbAlvo <= 0) {
alert('Os valores devem ser maiores que zero!');
return false;
}
return true;
}
function calcularReservaFerro(peso) {
return peso < 35 ? Math.round(peso * 15) : 500;
}
function mostrarResultados(peso, hbAtual, hbAlvo, dhb, reservaFerro, deficitTotal) {
document.getElementById('resultado').style.display = 'block';
const calculoHtml = `
<p><strong>Fórmula utilizada:</strong></p>
<div class="formula-box">
Déficit Total = (Peso × ΔHb × 2.4) + Reserva de Ferro<br>
Onde:<br>
- Peso = ${peso} kg<br>
- ΔHb (diferença de Hb) = ${hbAlvo} - ${hbAtual.toFixed(1)} = ${dhb.toFixed(1)} g/dL<br>
- Reserva de Ferro = ${reservaFerro} mg (${peso < 35 ? '15mg/kg' : 'fixo 500mg'})<br>
<br>
Cálculo: (${peso} × ${dhb.toFixed(1)} × 2.4) + ${reservaFerro} = ${deficitTotal} mg
</div>`;
document.getElementById('calculo-detalhado').innerHTML = calculoHtml;
document.getElementById('deficit-total').textContent = `${deficitTotal}mg`;
}
function criarEsquemaAdministracao(deficitTotal) {
const numDoses = Math.ceil(deficitTotal / 200);
const dosesPorSemana = Math.min(2, numDoses);
const numSemanas = Math.ceil(numDoses / dosesPorSemana);
let esquemaHtml = `
<table>
<tr>
<th>Semana</th>
<th>Terça-feira</th>
<th>Sexta-feira</th>
<th>Total Semanal</th>
</tr>`;
let ferroRestante = deficitTotal;
for (let semana = 1; semana <= numSemanas; semana++) {
const doseTerca = calcularDoseSemanal(ferroRestante);
ferroRestante -= doseTerca;
const doseSexta = calcularDoseSemanal(ferroRestante);
ferroRestante -= doseSexta;
esquemaHtml += `
<tr>
<td>${semana}</td>
<td>${formatarDose(doseTerca)}</td>
<td>${formatarDose(doseSexta)}</td>
<td>${doseTerca + doseSexta}mg</td>
</tr>`;
}
esquemaHtml += '</table>';
document.getElementById('esquema-admin').innerHTML = esquemaHtml;
}
function calcularDoseSemanal(ferroRestante) {
if (ferroRestante <= 0) return 0;
// Arredonda para múltiplos de 100 e limita a 200mg
return Math.min(200, Math.round(Math.min(ferroRestante, 200) / 100) * 100);
}
function formatarDose(dose) {
if (dose <= 0) return '-';
const numAmpolas = dose / 100;
return `${dose}mg (${numAmpolas} ${numAmpolas === 1 ? 'ampola' : 'ampolas'})`;
}
function mostrarAlertas(hbAtual, hbAlvo, deficitTotal) {
let alertas = [];
if (hbAtual >= hbAlvo) {
alertas.push(`
<div class="alert warning">
ATENÇÃO: Hemoglobina atual maior ou igual à meta.
Verificar necessidade real de reposição.
</div>`);
}
if (deficitTotal > 1000) {
alertas.push(`
<div class="alert">
Tratamento prolongado necessário.
Considerar reavaliação após 4-6 semanas de tratamento.
</div>`);
}
document.getElementById('alert-box').innerHTML = alertas.join('');
}
</script>
</body>
</html>
'''
noripurun = components.html(html_with_js, width=1600,height=1600)
return noripurun
noripurun(html_with_js)
#estil()