AniseF commited on
Commit
8949453
·
verified ·
1 Parent(s): 37a2e48

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +40 -43
app.py CHANGED
@@ -29,7 +29,6 @@ try:
29
  except:
30
  nlp = spacy.blank("grc")
31
 
32
- # Mapeamento de Classes Gramaticais
33
  TAG_MAP = {
34
  'NOUN': 'Substantivo', 'VERB': 'Verbo', 'ADJ': 'Adjetivo',
35
  'DET': 'Artigo/Det.', 'PRON': 'Pronome', 'ADV': 'Advérbio',
@@ -50,9 +49,11 @@ FORMA_TO_LEMA = load_json('ddgp_forma_to_lema.json')
50
  ENTRIES = load_json('ddgp3x_entry.json')
51
  ABREV = load_json('abrev.json')
52
 
53
- with open('style.css', 'r', encoding='utf-8') as f: css1 = f.read()
54
- with open('style_map.css', 'r', encoding='utf-8') as f: css2 = f.read()
55
- css_content = css1 + "\n" + css2
 
 
56
 
57
  # --- 2. FUNÇÕES DE APOIO ---
58
 
@@ -63,21 +64,14 @@ def normalizar_grego(texto):
63
  return unicodedata.normalize('NFC', texto).strip()
64
 
65
  def aplicar_abreviaturas_seguro(texto):
66
- """Substitui abreviaturas apenas como palavras inteiras para evitar confusão."""
67
  if not texto: return ""
68
-
69
- # Ordenamos as abreviaturas das maiores para as menores
70
  sorted_abrevs = sorted(ABREV.keys(), key=len, reverse=True)
71
-
72
  for ab in sorted_abrevs:
73
- # Escapa caracteres especiais (como ponto) para o Regex
74
  pattern = r'\b' + re.escape(ab) + r'(?=\s|[.,;:]|$)'
75
- desc = ABREV[ab].get('descricao', '')
76
- categoria = ABREV[ab].get('categoria', '')
77
-
78
  classe_css = "autor-sc" if categoria == 'autor' else "abrev"
79
-
80
- # Substituição com Tooltip
81
  subst = f'<span class="{classe_css}" title="{desc}">{ab}</span>'
82
  texto = re.sub(pattern, subst, texto)
83
  return texto
@@ -87,7 +81,6 @@ def format_entry_html(entry_id):
87
  if not entry: return None
88
  gword = entry.get('gword', '')
89
  pdesc = entry.get('pdesc', '')
90
-
91
  pdesc = aplicar_abreviaturas_seguro(pdesc)
92
  pdesc = re.sub(r'〈(.*?)〉', r'<span class="etimo">〈\1〉</span>', pdesc)
93
 
@@ -128,43 +121,41 @@ def consultar_ddgp(termo):
128
  if res: html += res
129
  return html
130
 
131
- # Adicione esta variável global no topo do arquivo (abaixo dos imports)
132
- CONSULTAS_CONTADOR = 0
133
-
134
  def analisar_texto(texto):
135
- global CONSULTAS_CONTADOR
136
  if not texto: return None, None, "0", "0", "0", "0", "0", ""
137
-
138
- CONSULTAS_CONTADOR += 1 # Incrementa o contador da sessão
139
  doc = nlp(texto)
140
  dados = []
141
- lexico_html = ""
142
- lemas_vistos = set()
 
143
 
144
  for token in doc:
145
  l_orig = token.lemma_
146
  l_norm = normalizar_grego(l_orig)
147
  pos_pt = TAG_MAP.get(token.pos_, token.pos_)
148
 
149
- # Extração da Morfologia detalhada
150
- morph_raw = str(token.morph) if str(token.morph) else "-"
 
151
 
152
- if token.pos_ not in ['PUNCT', 'SYM', 'SPACE'] and l_norm not in lemas_vistos:
153
- res = consultar_ddgp(l_norm)
154
- if "não localizado" not in res:
155
- lexico_html += res
156
- lemas_vistos.add(l_norm)
157
 
158
  dados.append({
159
  'Palavra': token.text,
160
  'Lema': l_orig,
161
  'Classe': pos_pt,
162
- 'Análise Morfológica': morph_raw # NOVA COLUNA
163
  })
164
 
 
 
 
 
165
  df = pd.DataFrame(dados)
166
-
167
- # Cálculos Estatísticos
168
  tokens_df = df[~df['Classe'].isin(['Pontuação', 'PUNCT', 'SYM', 'SPACE'])]
169
  n_tokens = len(tokens_df)
170
  n_types = tokens_df['Palavra'].str.lower().nunique()
@@ -184,9 +175,8 @@ def analisar_texto(texto):
184
  with gr.Blocks(css=css_content, title="DDGP + OdyCy") as demo:
185
  with gr.Row():
186
  with gr.Column(scale=1, min_width=100):
187
- # Inserção do logo via URL do GitHub (80px de altura)
188
  gr.HTML("""
189
- <div style="display: flex; align-items: center; justify-content: center; height: 80px;">
190
  <img src="https://raw.githubusercontent.com/aniseferreira/DDGP_Plus/main/ddgp/logo.png" style="height: 80px;">
191
  </div>
192
  """)
@@ -194,7 +184,7 @@ with gr.Blocks(css=css_content, title="DDGP + OdyCy") as demo:
194
  gr.Markdown("# Estação Filológica DDGP & OdyCy")
195
  gr.Markdown("Análise lexical e consulta ao Dicionário de Dificuldades do Grego Prático.")
196
 
197
- with gr.Tab("📝 Análise lexical"): # Label alterado
198
  txt = gr.Textbox(label="Texto em Grego Antigo", lines=6, placeholder="Insira o texto aqui...")
199
  btn = gr.Button("🚀 Executar Análise", variant="primary")
200
 
@@ -207,22 +197,29 @@ with gr.Blocks(css=css_content, title="DDGP + OdyCy") as demo:
207
 
208
  with gr.Row():
209
  with gr.Column(scale=2):
210
- out_t = gr.Dataframe(label="Formas") # Label alterado
211
  out_f = gr.File(label="Exportar CSV")
212
  with gr.Column(scale=1):
213
  gr.Markdown("### 📖 Léxico Contextual")
214
  out_l = gr.HTML()
215
 
216
- with gr.Tab("🔍 Busca direta no DDGP"): # Label alterado
217
- in_b = gr.Textbox(label="Busca direta no DDGP", placeholder="(ex. λόγος, logos)") # Placeholder alterado
218
  btn_b = gr.Button("Consultar Base")
219
  out_b = gr.HTML()
220
 
221
- # Mapeamento de botões (Mantendo a ordem de 8 saídas)
 
 
 
 
 
 
222
  btn.click(analisar_texto, inputs=txt,
223
- outputs=[out_t, out_f, t1, t2, t3, t4, t5, out_l])
 
224
 
225
- btn_b.click(consultar_ddgp, inputs=in_b, outputs=out_b)
226
-
227
 
228
  demo.launch()
 
29
  except:
30
  nlp = spacy.blank("grc")
31
 
 
32
  TAG_MAP = {
33
  'NOUN': 'Substantivo', 'VERB': 'Verbo', 'ADJ': 'Adjetivo',
34
  'DET': 'Artigo/Det.', 'PRON': 'Pronome', 'ADV': 'Advérbio',
 
49
  ENTRIES = load_json('ddgp3x_entry.json')
50
  ABREV = load_json('abrev.json')
51
 
52
+ css_content = ""
53
+ for f_css in ['style.css', 'style_map.css']:
54
+ if os.path.exists(f_css):
55
+ with open(f_css, 'r', encoding='utf-8') as f:
56
+ css_content += f.read() + "\n"
57
 
58
  # --- 2. FUNÇÕES DE APOIO ---
59
 
 
64
  return unicodedata.normalize('NFC', texto).strip()
65
 
66
  def aplicar_abreviaturas_seguro(texto):
 
67
  if not texto: return ""
 
 
68
  sorted_abrevs = sorted(ABREV.keys(), key=len, reverse=True)
 
69
  for ab in sorted_abrevs:
 
70
  pattern = r'\b' + re.escape(ab) + r'(?=\s|[.,;:]|$)'
71
+ info = ABREV[ab]
72
+ desc = info.get('descricao', '')
73
+ categoria = info.get('categoria', '')
74
  classe_css = "autor-sc" if categoria == 'autor' else "abrev"
 
 
75
  subst = f'<span class="{classe_css}" title="{desc}">{ab}</span>'
76
  texto = re.sub(pattern, subst, texto)
77
  return texto
 
81
  if not entry: return None
82
  gword = entry.get('gword', '')
83
  pdesc = entry.get('pdesc', '')
 
84
  pdesc = aplicar_abreviaturas_seguro(pdesc)
85
  pdesc = re.sub(r'〈(.*?)〉', r'<span class="etimo">〈\1〉</span>', pdesc)
86
 
 
121
  if res: html += res
122
  return html
123
 
 
 
 
124
  def analisar_texto(texto):
 
125
  if not texto: return None, None, "0", "0", "0", "0", "0", ""
 
 
126
  doc = nlp(texto)
127
  dados = []
128
+
129
+ lemas_unicos_encontrados = set()
130
+ verbetes_dict = {}
131
 
132
  for token in doc:
133
  l_orig = token.lemma_
134
  l_norm = normalizar_grego(l_orig)
135
  pos_pt = TAG_MAP.get(token.pos_, token.pos_)
136
 
137
+ # Simplifica a morfologia removendo prefixos das tags para poupar espaço
138
+ morph_info = str(token.morph).replace("Case=", "").replace("Gender=", "").replace("Number=", "").replace("VerbForm=", "").replace("Person=", "").replace("Tense=", "").replace("Mood=", "").replace("Voice=", "")
139
+ if not morph_info: morph_info = "-"
140
 
141
+ if token.pos_ not in ['PUNCT', 'SYM', 'SPACE'] and l_norm not in lemas_unicos_encontrados:
142
+ res_html = consultar_ddgp(l_norm)
143
+ if "não localizado" not in res_html:
144
+ verbetes_dict[l_orig] = res_html
145
+ lemas_unicos_encontrados.add(l_norm)
146
 
147
  dados.append({
148
  'Palavra': token.text,
149
  'Lema': l_orig,
150
  'Classe': pos_pt,
151
+ 'Morfologia': morph_info
152
  })
153
 
154
+ lexico_html = ""
155
+ for lema_ord in sorted(verbetes_dict.keys()):
156
+ lexico_html += verbetes_dict[lema_ord]
157
+
158
  df = pd.DataFrame(dados)
 
 
159
  tokens_df = df[~df['Classe'].isin(['Pontuação', 'PUNCT', 'SYM', 'SPACE'])]
160
  n_tokens = len(tokens_df)
161
  n_types = tokens_df['Palavra'].str.lower().nunique()
 
175
  with gr.Blocks(css=css_content, title="DDGP + OdyCy") as demo:
176
  with gr.Row():
177
  with gr.Column(scale=1, min_width=100):
 
178
  gr.HTML("""
179
+ <div style="display: flex; align-items: center; justify-content: flex-start; height: 80px;">
180
  <img src="https://raw.githubusercontent.com/aniseferreira/DDGP_Plus/main/ddgp/logo.png" style="height: 80px;">
181
  </div>
182
  """)
 
184
  gr.Markdown("# Estação Filológica DDGP & OdyCy")
185
  gr.Markdown("Análise lexical e consulta ao Dicionário de Dificuldades do Grego Prático.")
186
 
187
+ with gr.Tab("📝 Análise lexical"):
188
  txt = gr.Textbox(label="Texto em Grego Antigo", lines=6, placeholder="Insira o texto aqui...")
189
  btn = gr.Button("🚀 Executar Análise", variant="primary")
190
 
 
197
 
198
  with gr.Row():
199
  with gr.Column(scale=2):
200
+ out_t = gr.Dataframe(label="Formas")
201
  out_f = gr.File(label="Exportar CSV")
202
  with gr.Column(scale=1):
203
  gr.Markdown("### 📖 Léxico Contextual")
204
  out_l = gr.HTML()
205
 
206
+ with gr.Tab("🔍 Busca direta no DDGP"):
207
+ in_b = gr.Textbox(label="Busca direta no DDGP", placeholder="(ex. λόγος, logos)")
208
  btn_b = gr.Button("Consultar Base")
209
  out_b = gr.HTML()
210
 
211
+ gr.Markdown(f"""
212
+ ---
213
+ **DDGP Plus** — Analisador Morfológico e Dicionário Digital de Grego–Português 2026 v.1
214
+ Baseado no Dicionário Digital de Grego–Português (DDGP e DGP - ver [hipatia.fclar.unesp.br](http://hipatia.fclar.unesp.br))
215
+ Projetos Abertos em Letras Clássicas Digitais. Responsável: **Anise D'Orange Ferreira**.
216
+ """)
217
+
218
  btn.click(analisar_texto, inputs=txt,
219
+ outputs=[out_t, out_f, t1, t2, t3, t4, t5, out_l],
220
+ api_name="analisar")
221
 
222
+ btn_b.click(consultar_ddgp, inputs=in_b, outputs=out_b,
223
+ api_name="consultar")
224
 
225
  demo.launch()