QIDNLF commited on
Commit
911f2ec
ยท
verified ยท
1 Parent(s): c8a9057

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +25 -146
app.py CHANGED
@@ -249,147 +249,6 @@ def reset_comp_selections():
249
  return gr.update(value=None), gr.update(choices=[], value=None), gr.update(choices=[], value=None), gr.update(value="")
250
 
251
 
252
- # ==========================================
253
- # 3. Core Logic & Data Processing
254
- # ==========================================
255
- def generate_html_diff(base_text, comp_text):
256
- base_text = "" if pd.isna(base_text) else str(base_text)
257
- comp_text = "" if pd.isna(comp_text) else str(comp_text)
258
-
259
- b_words = base_text.split()
260
- c_words = comp_text.split()
261
-
262
- diff_generator = list(difflib.ndiff(b_words, c_words))
263
- b_result, c_result = [], []
264
- i = 0
265
-
266
- while i < len(diff_generator):
267
- code = diff_generator[i][0]
268
- word = diff_generator[i][2:]
269
-
270
- if code == ' ':
271
- b_result.append(word)
272
- c_result.append(word)
273
- elif code == '-' and i+1 < len(diff_generator) and diff_generator[i+1][0] == '+':
274
- new_word = diff_generator[i+1][2:]
275
- b_result.append(f"<span style='color:#ff4d4f;font-weight:600'>{word}</span>")
276
- c_result.append(f"<span style='color:#ff4d4f;font-weight:600'>{new_word}</span>")
277
- i += 1
278
- elif code == '-':
279
- b_result.append(f"<span style='color:#ff4d4f;font-weight:600'>{word}</span>")
280
- elif code == '+':
281
- c_result.append(f"<span style='color:#2ecc71;font-weight:600'>{word}</span>")
282
-
283
- i += 1
284
-
285
- return " ".join(b_result), " ".join(c_result)
286
-
287
- def fetch_database_records(standard, version, selection, table_type):
288
- if not all([standard, version, selection]):
289
- return pd.DataFrame({"Info": ["์„ ํƒ ํ•„์š”"]}), []
290
-
291
- try:
292
- db_path = os.path.join(UPLOAD_DIR, f"{standard}_{version}.db")
293
- if not os.path.exists(db_path):
294
- return pd.DataFrame({"Error": [f"ํŒŒ์ผ์„ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค: {db_path}"]}), []
295
-
296
- conn = sqlite3.connect(db_path)
297
- conn.text_factory = decode_sqlite_text
298
-
299
- tables = pd.read_sql("SELECT name FROM sqlite_master WHERE type='table';", conn)['name'].tolist()
300
- valid_tables = [t for t in tables if t.lower() not in ['mapping_registry', 'mapping_table', 'table_config', 'sqlite_sequence']]
301
-
302
- main_table = f"{standard}_{version}"
303
- if main_table not in valid_tables:
304
- main_table = valid_tables[0] if valid_tables else None
305
-
306
- target_table = None
307
- pattern = re.compile(f"^{standard}[_\\s-]*{version}[_\\s-]*", re.IGNORECASE)
308
-
309
- for t in valid_tables:
310
- if t == selection or pattern.sub("", t).strip(" _") == selection:
311
- target_table = t
312
- break
313
-
314
- if target_table and target_table != main_table:
315
- df = pd.read_sql(f"SELECT * FROM [{target_table}]", conn)
316
- else:
317
- if not main_table:
318
- return pd.DataFrame({"Error": ["๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋‚ด์—์„œ ๋ฉ”์ธ ํ…Œ์ด๋ธ”์„ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค."]}), []
319
-
320
- cursor = conn.cursor()
321
- cursor.execute(f"PRAGMA table_info([{main_table}])")
322
- cols = [c[1] for c in cursor.fetchall()]
323
- lower_cols = [c.lower().strip() for c in cols]
324
-
325
- real_ch, real_cat = None, None
326
- for c, lc in zip(cols, lower_cols):
327
- if lc == "chapter": real_ch = c
328
- elif lc == "category": real_cat = c
329
-
330
- if selection == "ALL":
331
- cursor.execute(f"SELECT * FROM [{main_table}]")
332
- elif "." in selection and real_ch and real_cat:
333
- ch, ca = selection.split(".", 1)
334
- query = f"SELECT * FROM [{main_table}] WHERE REPLACE(TRIM(CAST([{real_ch}] AS TEXT)), ' ', '') = ? AND REPLACE(TRIM(CAST([{real_cat}] AS TEXT)), ' ', '') = ?"
335
- cursor.execute(query, (ch.replace(" ", ""), ca.replace(" ", "")))
336
- else:
337
- cursor.execute(f"SELECT * FROM [{main_table}]")
338
-
339
- df = pd.DataFrame(cursor.fetchall(), columns=cols)
340
-
341
- df = df.drop(columns=[c for c in df.columns if c.lower() == "version"], errors="ignore")
342
-
343
- # =========================================================
344
- # ๐Ÿ’ก [์Šค๋งˆํŠธ ์Šค์บ” ๋กœ์ง] DB ์ปฌ๋Ÿผ์„ ๋ณด๊ณ  ๋งž๋Š” Main ์„ค์ •์„ ์•Œ์•„์„œ ์ฐพ์Šต๋‹ˆ๋‹ค.
345
- # =========================================================
346
- conn_map = sqlite3.connect(os.path.join(UPLOAD_DIR, "mapping.db"))
347
- config_df = pd.read_sql("SELECT Anchor_Column, Display_Columns FROM Table_Config WHERE Table_Type=?", conn_map, params=[table_type])
348
- conn_map.close()
349
-
350
- anchor_col_config = "Section"
351
- display_setting = "Description"
352
-
353
- if not config_df.empty:
354
- df_cols_lower = [c.lower() for c in df.columns]
355
- for _, row in config_df.iterrows():
356
- # DB์— ์ ํžŒ Anchor ์—ด์ด ์‹ค์ œ ๋ฐ์ดํ„ฐํ”„๋ ˆ์ž„์— ์กด์žฌํ•˜๋Š”์ง€ ํ™•์ธ
357
- first_anchor = str(row['Anchor_Column']).split(',')[0].strip().lower()
358
- if first_anchor in df_cols_lower:
359
- anchor_col_config = str(row['Anchor_Column'])
360
- raw_disp = row['Display_Columns']
361
- display_setting = str(raw_disp) if pd.notna(raw_disp) and str(raw_disp).strip() != "" else None
362
- break
363
- # =========================================================
364
-
365
- anchor_cols_config = [x.strip() for x in anchor_col_config.split(',')]
366
-
367
- real_anchors = []
368
- for ac in anchor_cols_config:
369
- real_ac = next((c for c in df.columns if c.lower() == ac.lower()), ac)
370
- real_anchors.append(real_ac)
371
-
372
- if display_setting:
373
- cols_to_show = [c.strip() for c in display_setting.split(',')]
374
- actual_cols_to_show = [c for c in df.columns if next((True for req in cols_to_show if c.lower() == req.lower()), False)]
375
-
376
- for ra in reversed(real_anchors):
377
- if ra in df.columns and ra not in actual_cols_to_show:
378
- actual_cols_to_show.insert(0, ra)
379
-
380
- if actual_cols_to_show:
381
- df = df[actual_cols_to_show]
382
-
383
- for col in df.columns:
384
- df[col] = df[col].apply(convert_blob_to_html_img)
385
-
386
- return df, real_anchors
387
-
388
- except Exception as e:
389
- import traceback
390
- traceback.print_exc()
391
- return pd.DataFrame({"Error": [str(e)]}), []
392
-
393
  def execute_unified_search(base_std, base_ver, base_cat, comp_std, comp_ver, comp_cat, mapped_only, diff_only):
394
  try:
395
  def get_type_by_cat(cat):
@@ -463,14 +322,28 @@ def execute_unified_search(base_std, base_ver, base_cat, comp_std, comp_ver, com
463
  df_base['merge_key'] = df_base[real_anchors_b].apply(lambda row: '-'.join([clean_key_val(x) for x in row]), axis=1)
464
  df_comp['merge_key'] = df_comp[real_anchors_c].apply(lambda row: '-'.join([clean_key_val(x) for x in row]), axis=1)
465
 
 
 
 
466
  conn_map = sqlite3.connect(os.path.join(UPLOAD_DIR, "mapping.db"))
467
 
468
- q_fw = "SELECT * FROM Mapping_table WHERE TRIM(Base_std)=? AND TRIM(Base_ver)=? AND TRIM(Comp_std)=? AND TRIM(Comp_ver)=?"
 
 
 
 
 
 
 
 
 
 
469
  df_fw = pd.read_sql(q_fw, conn_map, params=[base_std.strip(), base_ver.strip(), comp_std.strip(), comp_ver.strip()])
470
 
471
- q_rv = "SELECT * FROM Mapping_table WHERE TRIM(Comp_std)=? AND TRIM(Comp_ver)=? AND TRIM(Base_std)=? AND TRIM(Base_ver)=?"
472
  df_rv = pd.read_sql(q_rv, conn_map, params=[base_std.strip(), base_ver.strip(), comp_std.strip(), comp_ver.strip()])
473
  conn_map.close()
 
474
 
475
  cols_fw_lower = {c.lower(): c for c in df_fw.columns}
476
 
@@ -535,17 +408,21 @@ def execute_unified_search(base_std, base_ver, base_cat, comp_std, comp_ver, com
535
  row_dict = {}
536
  has_b = not pd.isna(row.get('base_idx')) and row.get('base_idx') != float('inf')
537
  has_c = not pd.isna(row.get('comp_idx')) and row.get('comp_idx') != float('inf')
538
-
539
  for c in rename_b.values(): row_dict[c] = str(row[c]) if has_b and not pd.isna(row[c]) else ""
540
  for c in rename_c.values(): row_dict[c] = str(row[c]) if has_c and not pd.isna(row[c]) else ""
541
-
 
 
 
542
  if mapped_only:
543
  b_has_val = any(str(row_dict[c]).strip() not in ["", "nan", "None", "&nbsp;"] for c in rename_b.values())
544
  c_has_val = any(str(row_dict[c]).strip() not in ["", "nan", "None", "&nbsp;"] for c in rename_c.values())
545
 
546
  if not (b_has_val and c_has_val):
547
  continue
548
-
 
549
  if has_b and has_c:
550
  for orig_col in rename_b.keys():
551
  if ('description' in orig_col.lower() or '๋‚ด์šฉ' in orig_col) and rename_c.get(orig_col) in row_dict:
@@ -562,6 +439,8 @@ def execute_unified_search(base_std, base_ver, base_cat, comp_std, comp_ver, com
562
  if diff_only:
563
  mask = final_df.astype(str).apply(lambda col: col.str.contains('color:#ff4d4f|color:#2ecc71', case=False, regex=True)).any(axis=1)
564
  final_df = final_df[mask]
 
 
565
 
566
  b_cols_final = [c for c in final_df.columns if c.endswith(f"_{base_ver}")]
567
  c_cols_final = [c for c in final_df.columns if c.endswith(f"_{comp_ver}")]
 
249
  return gr.update(value=None), gr.update(choices=[], value=None), gr.update(choices=[], value=None), gr.update(value="")
250
 
251
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
252
  def execute_unified_search(base_std, base_ver, base_cat, comp_std, comp_ver, comp_cat, mapped_only, diff_only):
253
  try:
254
  def get_type_by_cat(cat):
 
322
  df_base['merge_key'] = df_base[real_anchors_b].apply(lambda row: '-'.join([clean_key_val(x) for x in row]), axis=1)
323
  df_comp['merge_key'] = df_comp[real_anchors_c].apply(lambda row: '-'.join([clean_key_val(x) for x in row]), axis=1)
324
 
325
+ # =========================================================
326
+ # ๐Ÿ’ก [ํ•ต์‹ฌ ์—…๊ทธ๋ ˆ์ด๋“œ] ๋งคํ•‘ ๋ผ์šฐํ„ฐ: ์–ด๋–ค ์žฅ๋ถ€๋ฅผ ์ฝ์„์ง€ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค!
327
+ # =========================================================
328
  conn_map = sqlite3.connect(os.path.join(UPLOAD_DIR, "mapping.db"))
329
 
330
+ registry_query = """
331
+ SELECT Target_Table FROM Mapping_registry
332
+ WHERE TRIM(Base_std)=? AND TRIM(Base_ver)=? AND TRIM(Comp_std)=? AND TRIM(Comp_ver)=?
333
+ LIMIT 1
334
+ """
335
+ reg_df = pd.read_sql(registry_query, conn_map, params=[base_std.strip(), base_ver.strip(), comp_std.strip(), comp_ver.strip()])
336
+
337
+ # DB์— Target_Table์ด ์ ํ˜€์žˆ์œผ๋ฉด ๊ทธ๊ฑธ ์“ฐ๊ณ , ์—†๊ฑฐ๋‚˜ ๋น„์–ด์žˆ์œผ๋ฉด ๊ธฐ๋ณธ ์žฅ๋ถ€(Mapping_table)๋ฅผ ์”๋‹ˆ๋‹ค.
338
+ target_table_name = reg_df.iloc[0]['Target_Table'] if not reg_df.empty and pd.notna(reg_df.iloc[0]['Target_Table']) else "Mapping_table"
339
+
340
+ q_fw = f"SELECT * FROM [{target_table_name}] WHERE TRIM(Base_std)=? AND TRIM(Base_ver)=? AND TRIM(Comp_std)=? AND TRIM(Comp_ver)=?"
341
  df_fw = pd.read_sql(q_fw, conn_map, params=[base_std.strip(), base_ver.strip(), comp_std.strip(), comp_ver.strip()])
342
 
343
+ q_rv = f"SELECT * FROM [{target_table_name}] WHERE TRIM(Comp_std)=? AND TRIM(Comp_ver)=? AND TRIM(Base_std)=? AND TRIM(Base_ver)=?"
344
  df_rv = pd.read_sql(q_rv, conn_map, params=[base_std.strip(), base_ver.strip(), comp_std.strip(), comp_ver.strip()])
345
  conn_map.close()
346
+ # =========================================================
347
 
348
  cols_fw_lower = {c.lower(): c for c in df_fw.columns}
349
 
 
408
  row_dict = {}
409
  has_b = not pd.isna(row.get('base_idx')) and row.get('base_idx') != float('inf')
410
  has_c = not pd.isna(row.get('comp_idx')) and row.get('comp_idx') != float('inf')
411
+
412
  for c in rename_b.values(): row_dict[c] = str(row[c]) if has_b and not pd.isna(row[c]) else ""
413
  for c in rename_c.values(): row_dict[c] = str(row[c]) if has_c and not pd.isna(row[c]) else ""
414
+
415
+ # =======================================================
416
+ # ๐Ÿ’ก [๊น๊นํ•œ ๋นˆ์นธ ๊ฒ€์‚ฌ] ์–‘์ชฝ ๋‹ค ๊ธ€์ž๊ฐ€ ์ฑ„์›Œ์ ธ ์žˆ๋Š”์ง€ ํ™•์ธ!
417
+ # =======================================================
418
  if mapped_only:
419
  b_has_val = any(str(row_dict[c]).strip() not in ["", "nan", "None", "&nbsp;"] for c in rename_b.values())
420
  c_has_val = any(str(row_dict[c]).strip() not in ["", "nan", "None", "&nbsp;"] for c in rename_c.values())
421
 
422
  if not (b_has_val and c_has_val):
423
  continue
424
+ # =======================================================
425
+
426
  if has_b and has_c:
427
  for orig_col in rename_b.keys():
428
  if ('description' in orig_col.lower() or '๋‚ด์šฉ' in orig_col) and rename_c.get(orig_col) in row_dict:
 
439
  if diff_only:
440
  mask = final_df.astype(str).apply(lambda col: col.str.contains('color:#ff4d4f|color:#2ecc71', case=False, regex=True)).any(axis=1)
441
  final_df = final_df[mask]
442
+ if final_df.empty:
443
+ return pd.DataFrame({"Info": ["๐Ÿ’ก ์„ ํƒํ•˜์‹  ์กฐ๊ฑด ๊ฐ„์— ๋ณ€๊ฒฝ๋œ ๋‚ด์šฉ์ด ์—†์Šต๋‹ˆ๋‹ค. (100% ๋™์ผ)"]})
444
 
445
  b_cols_final = [c for c in final_df.columns if c.endswith(f"_{base_ver}")]
446
  c_cols_final = [c for c in final_df.columns if c.endswith(f"_{comp_ver}")]