QIDNLF commited on
Commit
4632401
ยท
verified ยท
1 Parent(s): c4886db

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +43 -19
app.py CHANGED
@@ -4,6 +4,7 @@ import pandas as pd
4
  import os
5
  import re
6
  import base64
 
7
 
8
  # 1๏ธโƒฃ ์ €์žฅ์†Œ ์„ค์ •
9
  UPLOAD_DIR = "uploaded_dbs"
@@ -110,6 +111,37 @@ def reset_base():
110
  def reset_comp():
111
  return None, None, None
112
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113
  # --------------------------
114
  # ๋ฐ์ดํ„ฐ ์กฐํšŒ
115
  # --------------------------
@@ -202,18 +234,22 @@ def unified_search(bs, bv, bc, cs, cv, cc):
202
  if 'section' not in df_base.columns or 'section' not in df_comp.columns:
203
  return pd.DataFrame({"Error": ["section ์ปฌ๋Ÿผ ์—†์Œ"]})
204
 
205
- merged = pd.merge(
206
- df_base,
207
- df_comp,
208
- on="section",
209
- how="outer"
210
- )
211
 
212
  merged = merged.rename(columns={
213
  "description_x": f"Description_{bv}",
214
  "description_y": f"Description_{cv}"
215
  })
216
 
 
 
 
 
 
 
 
 
 
217
  merged = merged.sort_values(
218
  by="section",
219
  key=lambda col: col.map(natural_sort_key)
@@ -230,7 +266,6 @@ with gr.Blocks() as demo:
230
 
231
  gr.Markdown("# ๐Ÿ“œ Regulation Viewer")
232
 
233
- # ์„ ํƒ ์˜์—ญ
234
  with gr.Row():
235
  with gr.Column():
236
  gr.Markdown("### ๐Ÿ“Œ ๊ธฐ์ค€ ๋ฒ•๊ทœ")
@@ -246,20 +281,13 @@ with gr.Blocks() as demo:
246
  comp_category = gr.Dropdown(label="Category")
247
  comp_reset_btn = gr.Button("โ†บ ์ดˆ๊ธฐํ™”")
248
 
249
- # ๋ฒ„ํŠผ
250
  with gr.Row():
251
  search_btn = gr.Button("๐Ÿ” ์กฐํšŒ")
252
 
253
- # ๊ฒฐ๊ณผ ์˜์—ญ
254
  gr.Markdown("### ๐Ÿ“Š ๋น„๊ต ๊ฒฐ๊ณผ")
255
 
256
- output_df = gr.Dataframe(
257
- wrap=True,
258
- interactive=False,
259
- datatype="html"
260
- )
261
 
262
- # ์ด๋ฒคํŠธ
263
  demo.load(on_load, None, base_standard)
264
  demo.load(on_load, None, comp_standard)
265
 
@@ -276,7 +304,6 @@ with gr.Blocks() as demo:
276
  output_df
277
  )
278
 
279
- # ์ดˆ๊ธฐํ™” ๋ฒ„ํŠผ ์—ฐ๊ฒฐ
280
  base_reset_btn.click(reset_base, None, [base_standard, base_version, base_category])
281
  comp_reset_btn.click(reset_comp, None, [comp_standard, comp_version, comp_category])
282
 
@@ -293,7 +320,6 @@ if __name__ == "__main__":
293
  font-family: 'Pretendard', sans-serif;
294
  }
295
 
296
- /* ํ—ค๋” ๊ณ ์ • */
297
  thead th {
298
  position: sticky !important;
299
  top: 0;
@@ -302,13 +328,11 @@ thead th {
302
  border-bottom: 2px solid #ddd;
303
  }
304
 
305
- /* ์Šคํฌ๋กค */
306
  .dataframe {
307
  max-height: 700px;
308
  overflow-y: auto;
309
  }
310
 
311
- /* ํ…์ŠคํŠธ */
312
  td {
313
  white-space: normal !important;
314
  word-break: break-word !important;
 
4
  import os
5
  import re
6
  import base64
7
+ import difflib
8
 
9
  # 1๏ธโƒฃ ์ €์žฅ์†Œ ์„ค์ •
10
  UPLOAD_DIR = "uploaded_dbs"
 
111
  def reset_comp():
112
  return None, None, None
113
 
114
+ # --------------------------
115
+ # ๐Ÿ”ฅ diff ํ•จ์ˆ˜ (ํ•ต์‹ฌ)
116
+ # --------------------------
117
+ def highlight_comp_only(base_text, comp_text):
118
+ if pd.isna(base_text): base_text = ""
119
+ if pd.isna(comp_text): comp_text = ""
120
+
121
+ base_words = str(base_text).split()
122
+ comp_words = str(comp_text).split()
123
+
124
+ d = difflib.ndiff(base_words, comp_words)
125
+
126
+ result = []
127
+
128
+ for diff in d:
129
+ code = diff[0]
130
+ word = diff[2:]
131
+
132
+ if code == ' ':
133
+ result.append(word)
134
+
135
+ elif code == '+': # ์ถ”๊ฐ€
136
+ result.append(
137
+ f"<span style='color:#2ecc71; font-weight:600'>{word}</span>"
138
+ )
139
+
140
+ elif code == '-':
141
+ continue
142
+
143
+ return " ".join(result)
144
+
145
  # --------------------------
146
  # ๋ฐ์ดํ„ฐ ์กฐํšŒ
147
  # --------------------------
 
234
  if 'section' not in df_base.columns or 'section' not in df_comp.columns:
235
  return pd.DataFrame({"Error": ["section ์ปฌ๋Ÿผ ์—†์Œ"]})
236
 
237
+ merged = pd.merge(df_base, df_comp, on="section", how="outer")
 
 
 
 
 
238
 
239
  merged = merged.rename(columns={
240
  "description_x": f"Description_{bv}",
241
  "description_y": f"Description_{cv}"
242
  })
243
 
244
+ # ๐Ÿ”ฅ diff ์ ์šฉ (comp์—๋งŒ)
245
+ base_col = f"Description_{bv}"
246
+ comp_col = f"Description_{cv}"
247
+
248
+ for idx, row in merged.iterrows():
249
+ base_text = row.get(base_col, "")
250
+ comp_text = row.get(comp_col, "")
251
+ merged.at[idx, comp_col] = highlight_comp_only(base_text, comp_text)
252
+
253
  merged = merged.sort_values(
254
  by="section",
255
  key=lambda col: col.map(natural_sort_key)
 
266
 
267
  gr.Markdown("# ๐Ÿ“œ Regulation Viewer")
268
 
 
269
  with gr.Row():
270
  with gr.Column():
271
  gr.Markdown("### ๐Ÿ“Œ ๊ธฐ์ค€ ๋ฒ•๊ทœ")
 
281
  comp_category = gr.Dropdown(label="Category")
282
  comp_reset_btn = gr.Button("โ†บ ์ดˆ๊ธฐํ™”")
283
 
 
284
  with gr.Row():
285
  search_btn = gr.Button("๐Ÿ” ์กฐํšŒ")
286
 
 
287
  gr.Markdown("### ๐Ÿ“Š ๋น„๊ต ๊ฒฐ๊ณผ")
288
 
289
+ output_df = gr.Dataframe(wrap=True, interactive=False, datatype="html")
 
 
 
 
290
 
 
291
  demo.load(on_load, None, base_standard)
292
  demo.load(on_load, None, comp_standard)
293
 
 
304
  output_df
305
  )
306
 
 
307
  base_reset_btn.click(reset_base, None, [base_standard, base_version, base_category])
308
  comp_reset_btn.click(reset_comp, None, [comp_standard, comp_version, comp_category])
309
 
 
320
  font-family: 'Pretendard', sans-serif;
321
  }
322
 
 
323
  thead th {
324
  position: sticky !important;
325
  top: 0;
 
328
  border-bottom: 2px solid #ddd;
329
  }
330
 
 
331
  .dataframe {
332
  max-height: 700px;
333
  overflow-y: auto;
334
  }
335
 
 
336
  td {
337
  white-space: normal !important;
338
  word-break: break-word !important;