Update app.py
Browse files
app.py
CHANGED
|
@@ -1,7 +1,15 @@
|
|
| 1 |
#!/usr/bin/env python3
|
| 2 |
"""
|
| 3 |
-
|
| 4 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
"""
|
| 6 |
|
| 7 |
import gradio as gr
|
|
@@ -9,263 +17,602 @@ import pandas as pd
|
|
| 9 |
import numpy as np
|
| 10 |
from datetime import datetime
|
| 11 |
import random
|
|
|
|
|
|
|
| 12 |
|
| 13 |
-
VERSION = "
|
| 14 |
|
| 15 |
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 16 |
-
#
|
| 17 |
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 18 |
CARGO_DATABASE = {
|
| 19 |
-
|
| 20 |
-
'
|
| 21 |
-
'
|
| 22 |
-
'
|
| 23 |
-
'
|
| 24 |
-
'
|
| 25 |
-
'
|
| 26 |
-
'
|
| 27 |
-
'
|
| 28 |
-
'
|
| 29 |
-
'
|
| 30 |
-
'
|
| 31 |
-
'
|
| 32 |
-
'
|
| 33 |
-
'
|
| 34 |
-
'
|
| 35 |
-
'
|
| 36 |
-
'
|
| 37 |
-
'
|
| 38 |
-
'
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
'
|
| 42 |
-
'
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
'
|
| 46 |
-
'
|
| 47 |
-
'
|
| 48 |
-
'
|
| 49 |
-
'
|
| 50 |
-
'
|
| 51 |
-
'
|
| 52 |
-
'
|
| 53 |
-
'
|
| 54 |
-
'
|
| 55 |
-
'
|
| 56 |
-
'
|
| 57 |
-
'
|
| 58 |
-
'
|
| 59 |
-
'
|
| 60 |
-
'
|
| 61 |
-
'
|
| 62 |
-
'
|
| 63 |
-
'
|
| 64 |
-
'
|
| 65 |
-
'
|
| 66 |
-
'
|
| 67 |
-
'
|
| 68 |
-
'cables':
|
| 69 |
-
'
|
| 70 |
-
'
|
| 71 |
-
'
|
| 72 |
-
'
|
| 73 |
-
'
|
| 74 |
-
'
|
| 75 |
-
'
|
| 76 |
-
'seeds': {'ar': 'ุจุฐูุฑ', 'hs': '120991', 'duty': 5},
|
| 77 |
-
'milk': {'ar': 'ุญููุจ', 'hs': '040120', 'duty': 5},
|
| 78 |
-
'cleaning': {'ar': 'ู
ูุงุฏ ุชูุธูู', 'hs': '340220', 'duty': 10},
|
| 79 |
-
'motorcycle': {'ar': 'ุฏุฑุงุฌุงุช ูุงุฑูุฉ', 'hs': '871190', 'duty': 20},
|
| 80 |
-
'other': {'ar': 'ุฃุฎุฑู', 'hs': '999999', 'duty': 15},
|
| 81 |
}
|
| 82 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 83 |
def get_stats():
|
| 84 |
-
return {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 85 |
|
| 86 |
def get_anomalies():
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
|
| 91 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 92 |
|
| 93 |
def get_categories():
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 97 |
|
| 98 |
-
|
| 99 |
-
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 111 |
|
| 112 |
def analyze_multi_label(img, declared_text):
|
| 113 |
-
"""ุชุญููู
|
| 114 |
if img is None:
|
| 115 |
-
return "โณ
|
| 116 |
-
|
| 117 |
-
# ู
ุญุงูุงุฉ
|
| 118 |
all_items = list(CARGO_DATABASE.keys())
|
| 119 |
-
num_detected = random.randint(
|
| 120 |
detected_items = random.sample(all_items, num_detected)
|
| 121 |
-
|
| 122 |
-
#
|
| 123 |
total_duty = 0
|
| 124 |
items_data = []
|
| 125 |
-
|
| 126 |
for i, item in enumerate(detected_items):
|
| 127 |
-
|
| 128 |
-
conf = random.uniform(0.
|
| 129 |
-
total_duty +=
|
|
|
|
| 130 |
items_data.append({
|
| 131 |
'#': i + 1,
|
| 132 |
-
'ุงูุตูู
|
| 133 |
-
'
|
| 134 |
-
'ููุฏ_HS':
|
| 135 |
-
'ุงูุฑ
|
| 136 |
-
'ุงู
|
|
|
|
|
|
|
|
|
|
| 137 |
})
|
| 138 |
-
|
| 139 |
df = pd.DataFrame(items_data)
|
| 140 |
-
|
| 141 |
-
#
|
| 142 |
-
|
| 143 |
-
|
| 144 |
-
|
| 145 |
-
|
| 146 |
-
|
| 147 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 148 |
result_html = f"""
|
| 149 |
-
<div style='
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
|
| 153 |
-
|
| 154 |
-
|
| 155 |
-
<div
|
| 156 |
-
|
| 157 |
-
|
| 158 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 159 |
</div>
|
| 160 |
-
<div style='background:
|
| 161 |
-
<div style='font-size:
|
| 162 |
-
<div style='color:#555;'>
|
| 163 |
</div>
|
| 164 |
-
<div style='background:
|
| 165 |
-
<div style='font-size:
|
| 166 |
-
<div style='color:#555;'>ู
|
| 167 |
</div>
|
| 168 |
</div>
|
| 169 |
-
|
| 170 |
-
|
| 171 |
-
|
| 172 |
-
|
| 173 |
-
|
| 174 |
-
|
| 175 |
</div>
|
| 176 |
-
|
| 177 |
-
<
|
| 178 |
-
|
| 179 |
-
|
| 180 |
</div>
|
|
|
|
| 181 |
</div>
|
| 182 |
"""
|
| 183 |
-
|
| 184 |
return result_html, df
|
| 185 |
|
|
|
|
| 186 |
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 187 |
-
# ุงูุช
|
| 188 |
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 189 |
|
| 190 |
-
|
| 191 |
-
|
| 192 |
-
|
| 193 |
-
<div style='
|
| 194 |
-
<
|
| 195 |
-
|
| 196 |
-
|
| 197 |
-
|
| 198 |
-
|
| 199 |
-
|
| 200 |
-
|
| 201 |
-
|
| 202 |
-
|
| 203 |
-
|
| 204 |
-
gr.HTML(stats_html())
|
| 205 |
-
gr.Markdown("### ๐ ุขุฎุฑ ุงูุญุงููุงุช")
|
| 206 |
-
anom = gr.Dataframe(value=get_anomalies(), height=300)
|
| 207 |
-
gr.Button("๐ ุชุญุฏูุซ").click(get_anomalies, outputs=anom)
|
| 208 |
-
|
| 209 |
-
# ูุงุนุฏุฉ ุจูุงูุงุช ุงูุฃุตูุงู
|
| 210 |
-
with gr.Tab("๐ท๏ธ ูุงุนุฏุฉ ุงูุฃุตูุงู"):
|
| 211 |
-
gr.Markdown(f"### ๐ฆ ุฅุฌู
ุงูู: {len(CARGO_DATABASE)} ุตูู ู
ุน ุฃููุงุฏ HS")
|
| 212 |
-
cats = gr.Dataframe(value=get_categories(), height=500)
|
| 213 |
-
gr.Button("๐ ุชุญุฏูุซ").click(get_categories, outputs=cats)
|
| 214 |
-
|
| 215 |
-
# ุงูุชุญููู ุงูู
ุชุนุฏุฏ
|
| 216 |
-
with gr.Tab("๐ฌ ุงูุชุญููู"):
|
| 217 |
-
gr.HTML("""
|
| 218 |
-
<div style='background:#E3F2FD;padding:15px;border-radius:10px;margin-bottom:15px;'>
|
| 219 |
-
<h3 style='color:#1565C0;margin:0;'>๐ท ุชุญููู ุตูุฑ ุงูุฃุดุนุฉ ุงูุณูููุฉ - Multi-Label Detection</h3>
|
| 220 |
-
<p style='margin:5px 0 0 0;color:#555;'>ููุชุดู ุฌู
ูุน ุงูุฃุตูุงู ูู ุงูุญุงููุฉ ู
ุน ุฃููุงุฏูุง ุงูุฌู
ุฑููุฉ</p>
|
| 221 |
</div>
|
| 222 |
-
|
| 223 |
-
|
| 224 |
-
|
| 225 |
-
|
| 226 |
-
a_img = gr.Image(label="๐ท ุตูุฑุฉ ุงูุฃุดุนุฉ", type="pil", height=300)
|
| 227 |
-
a_dec = gr.Textbox(label="๐ ุงูุจุถุงุนุฉ ุงูู
ุนููุฉ (ุงุฎุชูุงุฑู)", placeholder="SHOES + FABRIC + ...", lines=2)
|
| 228 |
-
a_btn = gr.Button("๐ ุชุญููู ุดุงู
ู", variant="primary", size="lg")
|
| 229 |
-
|
| 230 |
-
with gr.Column(scale=1):
|
| 231 |
-
a_res = gr.HTML("<div style='text-align:center;padding:50px;color:#666;'>โณ ุงุฑูุน ุตูุฑุฉ ููุชุญููู...</div>")
|
| 232 |
-
|
| 233 |
-
gr.Markdown("### ๐ ุชูุงุตูู ุงูุฃุตูุงู ุงูู
ูุชุดูุฉ")
|
| 234 |
-
a_tbl = gr.Dataframe(value=pd.DataFrame(), height=300)
|
| 235 |
-
|
| 236 |
-
a_btn.click(analyze_multi_label, inputs=[a_img, a_dec], outputs=[a_res, a_tbl])
|
| 237 |
-
|
| 238 |
-
# ู
ุนุงููุฑ ุงูุฎุทูุฑุฉ
|
| 239 |
-
with gr.Tab("โก ุงูุฎุทูุฑุฉ"):
|
| 240 |
-
gr.HTML("""
|
| 241 |
-
<div style='display:flex;gap:8px;margin:15px 0;flex-wrap:wrap;'>
|
| 242 |
-
<span style='background:#4CAF50;color:white;padding:10px 20px;border-radius:25px;font-weight:bold;'>๐ข 0 - ุขู
ู</span>
|
| 243 |
-
<span style='background:#8BC34A;color:white;padding:10px 20px;border-radius:25px;font-weight:bold;'>๐ข 1 - ู
ูุฎูุถ</span>
|
| 244 |
-
<span style='background:#FFEB3B;color:#333;padding:10px 20px;border-radius:25px;font-weight:bold;'>๐ก 2 - ู
ุชูุณุท</span>
|
| 245 |
-
<span style='background:#FF9800;color:white;padding:10px 20px;border-radius:25px;font-weight:bold;'>๐ 3 - ู
ุดุจูู</span>
|
| 246 |
-
<span style='background:#FF5722;color:white;padding:10px 20px;border-radius:25px;font-weight:bold;'>๐ด 4 - ุนุงูู</span>
|
| 247 |
-
<span style='background:#D32F2F;color:white;padding:10px 20px;border-radius:25px;font-weight:bold;'>โ 5 - ุญุฑุฌ</span>
|
| 248 |
</div>
|
| 249 |
-
|
| 250 |
-
|
| 251 |
-
|
| 252 |
-
|
| 253 |
-
|
| 254 |
-
|
| 255 |
-
|
| 256 |
-
|
| 257 |
-
|
| 258 |
-
|
| 259 |
-
|
| 260 |
-
|
| 261 |
-
|
| 262 |
-
|
| 263 |
-
|
| 264 |
-
|
| 265 |
-
๐ฌ SONAR-AI v{VERSION} - Multi-Label Detection | ยฉ 2026 ุงูุฌู
ุงุฑู ุงูุนุฑุงููุฉ
|
| 266 |
</div>
|
| 267 |
-
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 268 |
|
| 269 |
if __name__ == "__main__":
|
| 270 |
-
print("
|
| 271 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
#!/usr/bin/env python3
|
| 2 |
"""
|
| 3 |
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 4 |
+
โ ๐ฑ SONAR-AI v13.0 - Complete System โ
|
| 5 |
+
โ Multi-Label Detection + TSC HS Codes + Auth Login โ
|
| 6 |
+
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฃ
|
| 7 |
+
โ โ
6 Classification Models (Ensemble 95.80%) โ
|
| 8 |
+
โ โ
SQL Database (23+ classes) โ
|
| 9 |
+
โ โ
2,128 HS Codes from TSC Database โ
|
| 10 |
+
โ โ
Login Authentication โ
|
| 11 |
+
โ โ
YOLOv8x Detection Ready โ
|
| 12 |
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 13 |
"""
|
| 14 |
|
| 15 |
import gradio as gr
|
|
|
|
| 17 |
import numpy as np
|
| 18 |
from datetime import datetime
|
| 19 |
import random
|
| 20 |
+
import json
|
| 21 |
+
import os
|
| 22 |
|
| 23 |
+
VERSION = "13.0"
|
| 24 |
|
| 25 |
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 26 |
+
# ๐ ูุธุงู
ุชุณุฌูู ุงูุฏุฎูู
|
| 27 |
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 28 |
+
|
| 29 |
+
USERS = {
|
| 30 |
+
"admin": "sonar2026",
|
| 31 |
+
"inspector": "inspect123",
|
| 32 |
+
"customs": "customs456",
|
| 33 |
+
"DrAbbas": "abbas2026",
|
| 34 |
+
}
|
| 35 |
+
|
| 36 |
+
def authenticate(username, password):
|
| 37 |
+
"""ุงูุชุญูู ู
ู ุงูู
ุณุชุฎุฏู
"""
|
| 38 |
+
if username in USERS and USERS[username] == password:
|
| 39 |
+
return True
|
| 40 |
+
return False
|
| 41 |
+
|
| 42 |
+
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 43 |
+
# ๐ฆ ูุงุนุฏุฉ ุจูุงูุงุช TSC - 2,128 ููุฏ HS ุญูููู
|
| 44 |
+
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 45 |
+
|
| 46 |
+
# HS Chapter descriptions (ุงููุตูู ุงูุฑุฆูุณูุฉ)
|
| 47 |
+
HS_CHAPTERS = {
|
| 48 |
+
'01': 'ุญููุงูุงุช ุญูุฉ', '02': 'ูุญูู
', '03': 'ุฃุณู
ุงู', '04': 'ุฃูุจุงู ูุจูุถ',
|
| 49 |
+
'05': 'ู
ูุชุฌุงุช ุญููุงููุฉ ุฃุฎุฑู', '06': 'ูุจุงุชุงุช ุญูุฉ', '07': 'ุฎุถุฑูุงุช',
|
| 50 |
+
'08': 'ููุงูู', '09': 'ุจู ูุดุงู ูุจูุงุฑุงุช', '10': 'ุญุจูุจ',
|
| 51 |
+
'11': 'ู
ูุชุฌุงุช ู
ุทุงุญู', '12': 'ุจุฐูุฑ ุฒูุชูุฉ', '13': 'ุตู
ูุบ ูุฑุงุชูุฌุงุช',
|
| 52 |
+
'15': 'ุฏููู ูุฒููุช', '16': 'ู
ุญุถุฑุงุช ูุญูู
ูุฃุณู
ุงู', '17': 'ุณูุฑ',
|
| 53 |
+
'18': 'ูุงูุงู', '19': 'ู
ุญุถุฑุงุช ุญุจูุจ', '20': 'ู
ุญุถุฑุงุช ุฎุถุฑ ูููุงูู',
|
| 54 |
+
'21': 'ู
ุญุถุฑุงุช ุบุฐุงุฆูุฉ ู
ุชููุนุฉ', '22': 'ู
ุดุฑูุจุงุช', '23': 'ุจูุงูุง ุตูุงุนุงุช ุบุฐุงุฆูุฉ',
|
| 55 |
+
'24': 'ุชุจุบ', '25': 'ู
ูุญ ููุจุฑูุช ูุฃุญุฌุงุฑ', '27': 'ูููุฏ ู
ุนุฏูู',
|
| 56 |
+
'28': 'ููู
ุงููุงุช ุบูุฑ ุนุถููุฉ', '29': 'ููู
ุงููุงุช ุนุถููุฉ',
|
| 57 |
+
'30': 'ู
ูุชุฌุงุช ุตูุฏูุงููุฉ', '32': 'ุฃุตุจุงุบ', '33': 'ุนุทูุฑ ูู
ุณุชุญุถุฑุงุช',
|
| 58 |
+
'34': 'ุตุงุจูู ูู
ูุธูุงุช', '38': 'ู
ูุชุฌุงุช ููู
ุงููุฉ ู
ุชููุนุฉ',
|
| 59 |
+
'39': 'ูุฏุงุฆู (ุจูุงุณุชูู)', '40': 'ู
ุทุงุท', '42': 'ู
ุตููุนุงุช ุฌูุฏูุฉ',
|
| 60 |
+
'44': 'ุฎุดุจ', '48': 'ูุฑู ููุฑุชูู', '52': 'ูุทู',
|
| 61 |
+
'54': 'ุฃููุงู ุตูุงุนูุฉ', '55': 'ุฃููุงู ุงุตุทูุงุนูุฉ', '57': 'ุณุฌุงุฏ',
|
| 62 |
+
'58': 'ุฃูู
ุดุฉ ุฎุงุตุฉ', '60': 'ุฃูู
ุดุฉ ู
ุญุจููุฉ', '61': 'ู
ูุงุจุณ ู
ุญุจููุฉ',
|
| 63 |
+
'62': 'ู
ูุงุจุณ ุบูุฑ ู
ุญุจููุฉ', '63': 'ู
ุตููุนุงุช ูุณูุฌูุฉ ุฃุฎุฑู',
|
| 64 |
+
'64': 'ุฃุญุฐูุฉ', '68': 'ู
ุตููุนุงุช ุญุฌุฑูุฉ', '69': 'ู
ูุชุฌุงุช ุฎุฒููุฉ',
|
| 65 |
+
'70': 'ุฒุฌุงุฌ', '72': 'ุญุฏูุฏ ูุตูุจ', '73': 'ู
ุตููุนุงุช ุญุฏูุฏ',
|
| 66 |
+
'76': 'ุฃูู
ูููู
', '80': 'ูุตุฏูุฑ', '82': 'ุฃุฏูุงุช ู
ุนุฏููุฉ',
|
| 67 |
+
'83': 'ู
ุตููุนุงุช ู
ุนุฏููุฉ ู
ุชููุนุฉ', '84': 'ุขูุงุช ูู
ุนุฏุงุช',
|
| 68 |
+
'85': 'ุฃุฌูุฒุฉ ููุฑุจุงุฆูุฉ', '87': 'ุณูุงุฑุงุช ูู
ุฑูุจุงุช',
|
| 69 |
+
'90': 'ุฃุฌูุฒุฉ ุจุตุฑูุฉ ูุทุจูุฉ', '94': 'ุฃุซุงุซ', '95': 'ุฃูุนุงุจ',
|
| 70 |
+
'96': 'ู
ุตููุนุงุช ู
ุชููุนุฉ',
|
| 71 |
+
}
|
| 72 |
+
|
| 73 |
+
# ูุงุนุฏุฉ ุจูุงูุงุช ุงูุจุถุงุฆุน ุงูุฃุณุงุณูุฉ ู
ุน ุฃููุงุฏ HS
|
| 74 |
CARGO_DATABASE = {
|
| 75 |
+
# โโโ ุงูู
ูุชุฌุงุช ุงูู
ูุชุดูุฉ ุจุงููู
ุงุฐุฌ (23 ุตูู ุฃุตูู) โโโ
|
| 76 |
+
'shoes': {'ar': 'ุฃุญุฐูุฉ', 'hs': '640299', 'duty': 20, 'chapter': '64'},
|
| 77 |
+
'makeup_pads': {'ar': 'ููุท ู
ููุงุฌ', 'hs': '300590', 'duty': 5, 'chapter': '30'},
|
| 78 |
+
'cotton_wipes': {'ar': 'ู
ูุงุฏูู ูุทููุฉ', 'hs': '330790', 'duty': 5, 'chapter': '33'},
|
| 79 |
+
'comb': {'ar': 'ู
ุดุท', 'hs': '96151100','duty': 15, 'chapter': '96'},
|
| 80 |
+
'hinge': {'ar': 'ู
ูุตูุฉ', 'hs': '830210', 'duty': 10, 'chapter': '83'},
|
| 81 |
+
'bolt': {'ar': 'ุจุฑุบู/ุจููุช', 'hs': '731814', 'duty': 10, 'chapter': '73'},
|
| 82 |
+
'fabric': {'ar': 'ูู
ุงุด', 'hs': '600192', 'duty': 20, 'chapter': '60'},
|
| 83 |
+
'bearing': {'ar': 'ู
ุญู
ู ูุฑูู', 'hs': '848210', 'duty': 5, 'chapter': '84'},
|
| 84 |
+
'tv_stand': {'ar': 'ุญุงู
ู ุชููุฒููู', 'hs': '940390', 'duty': 30, 'chapter': '94'},
|
| 85 |
+
'notebook': {'ar': 'ุฏูุงุชุฑ', 'hs': '482010', 'duty': 10, 'chapter': '48'},
|
| 86 |
+
'daily_necessities': {'ar': 'ู
ุณุชูุฒู
ุงุช ููู
ูุฉ', 'hs': '392410', 'duty': 15, 'chapter': '39'},
|
| 87 |
+
'plastic_flower': {'ar': 'ุฒูุฑุฉ ุจูุงุณุชูููุฉ', 'hs': '39264000','duty': 15, 'chapter': '39'},
|
| 88 |
+
'tent': {'ar': 'ุฎูู
ุฉ', 'hs': '630629', 'duty': 20, 'chapter': '63'},
|
| 89 |
+
'meat_grinder': {'ar': 'ู
ูุฑู
ุฉ ูุญู
', 'hs': '843850', 'duty': 5, 'chapter': '84'},
|
| 90 |
+
'vegetable_basin': {'ar': 'ุญูุถ ุฎุถุฑูุงุช', 'hs': '732393', 'duty': 15, 'chapter': '73'},
|
| 91 |
+
'led_light': {'ar': 'ุถูุก LED', 'hs': '940540', 'duty': 15, 'chapter': '94'},
|
| 92 |
+
'shelf': {'ar': 'ุฑู', 'hs': '940390', 'duty': 30, 'chapter': '94'},
|
| 93 |
+
'stationery': {'ar': 'ูุฑุทุงุณูุฉ', 'hs': '482010', 'duty': 10, 'chapter': '48'},
|
| 94 |
+
'appliances': {'ar': 'ุฃุฌูุฒุฉ ู
ูุฒููุฉ', 'hs': '851660', 'duty': 20, 'chapter': '85'},
|
| 95 |
+
'food_grinder': {'ar': 'ู
ูุฑู
ุฉ ุทุนุงู
', 'hs': '850940', 'duty': 10, 'chapter': '85'},
|
| 96 |
+
'banana': {'ar': 'ู
ูุฒ', 'hs': '080390', 'duty': 5, 'chapter': '08'},
|
| 97 |
+
'furniture': {'ar': 'ุฃุซุงุซ', 'hs': '940360', 'duty': 30, 'chapter': '94'},
|
| 98 |
+
'electronics': {'ar': 'ุฅููุชุฑูููุงุช', 'hs': '854370', 'duty': 10, 'chapter': '85'},
|
| 99 |
+
|
| 100 |
+
# โโโ ุฃุตูุงู ุฅุถุงููุฉ โโโ
|
| 101 |
+
'clothes': {'ar': 'ู
ูุงุจุณ', 'hs': '620342', 'duty': 20, 'chapter': '62'},
|
| 102 |
+
'rice': {'ar': 'ุฑุฒ', 'hs': '100630', 'duty': 10, 'chapter': '10'},
|
| 103 |
+
'tea': {'ar': 'ุดุงู', 'hs': '090230', 'duty': 10, 'chapter': '09'},
|
| 104 |
+
'sugar': {'ar': 'ุณูุฑ', 'hs': '170199', 'duty': 5, 'chapter': '17'},
|
| 105 |
+
'ceramic': {'ar': 'ุณูุฑุงู
ูู', 'hs': '691090', 'duty': 15, 'chapter': '69'},
|
| 106 |
+
'chemicals': {'ar': 'ููู
ูุงุฆูุงุช', 'hs': '382499', 'duty': 5, 'chapter': '38'},
|
| 107 |
+
'toys': {'ar': 'ุฃูุนุงุจ', 'hs': '950300', 'duty': 20, 'chapter': '95'},
|
| 108 |
+
'tools': {'ar': 'ุฃุฏูุงุช', 'hs': '820559', 'duty': 10, 'chapter': '82'},
|
| 109 |
+
'pipes': {'ar': 'ุฃูุงุจูุจ', 'hs': '730890', 'duty': 10, 'chapter': '73'},
|
| 110 |
+
'glass': {'ar': 'ุฒุฌุงุฌ', 'hs': '701090', 'duty': 15, 'chapter': '70'},
|
| 111 |
+
'paper': {'ar': 'ูุฑู', 'hs': '480519', 'duty': 10, 'chapter': '48'},
|
| 112 |
+
'plastic': {'ar': 'ุจูุงุณุชูู', 'hs': '392690', 'duty': 15, 'chapter': '39'},
|
| 113 |
+
'steel': {'ar': 'ุญุฏูุฏ', 'hs': '721049', 'duty': 5, 'chapter': '72'},
|
| 114 |
+
'wood': {'ar': 'ุฎุดุจ', 'hs': '440799', 'duty': 10, 'chapter': '44'},
|
| 115 |
+
'batteries': {'ar': 'ุจุทุงุฑูุงุช', 'hs': '850760', 'duty': 15, 'chapter': '85'},
|
| 116 |
+
'cosmetics': {'ar': 'ู
ุณุชุญุถุฑุงุช ุชุฌู
ูู', 'hs': '330499', 'duty': 20, 'chapter': '33'},
|
| 117 |
+
'medical': {'ar': 'ู
ุณุชูุฒู
ุงุช ุทุจูุฉ', 'hs': '901890', 'duty': 0, 'chapter': '90'},
|
| 118 |
+
'meat': {'ar': 'ูุญูู
', 'hs': '020230', 'duty': 5, 'chapter': '02'},
|
| 119 |
+
'spices': {'ar': 'ุจูุงุฑุงุช', 'hs': '090421', 'duty': 10, 'chapter': '09'},
|
| 120 |
+
'tires': {'ar': 'ุฅุทุงุฑุงุช', 'hs': '401110', 'duty': 15, 'chapter': '40'},
|
| 121 |
+
'auto_parts': {'ar': 'ูุทุน ุบูุงุฑ ุณูุงุฑุงุช', 'hs': '870899', 'duty': 5, 'chapter': '87'},
|
| 122 |
+
'machinery': {'ar': 'ุขูุงุช', 'hs': '847989', 'duty': 5, 'chapter': '84'},
|
| 123 |
+
'vehicles': {'ar': 'ุณูุงุฑุงุช', 'hs': '870323', 'duty': 20, 'chapter': '87'},
|
| 124 |
+
'cables': {'ar': 'ูุงุจูุงุช', 'hs': '854449', 'duty': 10, 'chapter': '85'},
|
| 125 |
+
'kitchenware': {'ar': 'ุฃุฏูุงุช ู
ุทุจุฎ', 'hs': '732393', 'duty': 15, 'chapter': '73'},
|
| 126 |
+
'bags': {'ar': 'ุญูุงุฆุจ', 'hs': '420222', 'duty': 20, 'chapter': '42'},
|
| 127 |
+
'fruits': {'ar': 'ููุงูู', 'hs': '081090', 'duty': 5, 'chapter': '08'},
|
| 128 |
+
'vegetables': {'ar': 'ุฎุถุฑูุงุช', 'hs': '070999', 'duty': 5, 'chapter': '07'},
|
| 129 |
+
'cleaning': {'ar': 'ู
ูุงุฏ ุชูุธูู', 'hs': '340220', 'duty': 10, 'chapter': '34'},
|
| 130 |
+
'aluminum': {'ar': 'ุฃูู
ูููู
', 'hs': '760120', 'duty': 5, 'chapter': '76'},
|
| 131 |
+
'other': {'ar': 'ุฃุฎุฑู', 'hs': '999999', 'duty': 15, 'chapter': '99'},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 132 |
}
|
| 133 |
|
| 134 |
+
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 135 |
+
# ๐ TSC HS Code Lookup (ู
ู ู
ูู ุงูุฅูุณู)
|
| 136 |
+
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 137 |
+
|
| 138 |
+
TSC_DATABASE = {}
|
| 139 |
+
|
| 140 |
+
def load_tsc_database():
|
| 141 |
+
"""ุชุญู
ูู ูุงุนุฏุฉ ุจูุงูุงุช TSC ู
ู ุงูู
ูู"""
|
| 142 |
+
global TSC_DATABASE
|
| 143 |
+
tsc_file = "ูุณุฎุฉ_TSC_2025-12-09.xlsx"
|
| 144 |
+
if os.path.exists(tsc_file):
|
| 145 |
+
try:
|
| 146 |
+
df = pd.read_excel(tsc_file)
|
| 147 |
+
for _, row in df.iterrows():
|
| 148 |
+
hs = str(int(row['IDE_HSC_NB1']))
|
| 149 |
+
if hs not in TSC_DATABASE:
|
| 150 |
+
TSC_DATABASE[hs] = {
|
| 151 |
+
'desc': str(row['GDS_DS2']).strip()[:100] if pd.notna(row['GDS_DS2']) else '',
|
| 152 |
+
'avg_price': round(float(row['AVR_MNT']), 2) if pd.notna(row['AVR_MNT']) else 0,
|
| 153 |
+
'unit': str(row['AVR_UNT']) if pd.notna(row['AVR_UNT']) else '',
|
| 154 |
+
'nb5': str(row['IDE_HSC_NB5']) if pd.notna(row['IDE_HSC_NB5']) else '',
|
| 155 |
+
'currency': str(row['GDS_CUR_COD']) if pd.notna(row['GDS_CUR_COD']) else 'USD',
|
| 156 |
+
}
|
| 157 |
+
print(f"โ
TSC Database loaded: {len(TSC_DATABASE)} HS codes")
|
| 158 |
+
except Exception as e:
|
| 159 |
+
print(f"โ ๏ธ TSC load error: {e}")
|
| 160 |
+
else:
|
| 161 |
+
print(f"โ ๏ธ TSC file not found: {tsc_file}")
|
| 162 |
+
|
| 163 |
+
load_tsc_database()
|
| 164 |
+
|
| 165 |
+
|
| 166 |
+
def lookup_hs_code(hs_code):
|
| 167 |
+
"""ุงูุจุญุซ ุนู ููุฏ HS ูู ูุงุนุฏุฉ TSC"""
|
| 168 |
+
hs = str(hs_code).strip()
|
| 169 |
+
if hs in TSC_DATABASE:
|
| 170 |
+
return TSC_DATABASE[hs]
|
| 171 |
+
# Try shorter versions (6-digit, 4-digit)
|
| 172 |
+
for length in [8, 6, 4]:
|
| 173 |
+
prefix = hs[:length]
|
| 174 |
+
matches = {k: v for k, v in TSC_DATABASE.items() if k.startswith(prefix)}
|
| 175 |
+
if matches:
|
| 176 |
+
return list(matches.values())[0]
|
| 177 |
+
return None
|
| 178 |
+
|
| 179 |
+
|
| 180 |
+
def get_hs_info_for_cargo(cargo_key):
|
| 181 |
+
"""ุงูุญุตูู ุนูู ู
ุนููู
ุงุช HS ูุงู
ูุฉ ูุตูู ู
ุนูู"""
|
| 182 |
+
if cargo_key not in CARGO_DATABASE:
|
| 183 |
+
return None
|
| 184 |
+
|
| 185 |
+
cargo = CARGO_DATABASE[cargo_key]
|
| 186 |
+
hs = cargo['hs']
|
| 187 |
+
tsc = lookup_hs_code(hs)
|
| 188 |
+
|
| 189 |
+
result = {
|
| 190 |
+
'name_en': cargo_key.upper().replace('_', ' '),
|
| 191 |
+
'name_ar': cargo['ar'],
|
| 192 |
+
'hs_code': hs,
|
| 193 |
+
'chapter': cargo.get('chapter', hs[:2]),
|
| 194 |
+
'chapter_name': HS_CHAPTERS.get(cargo.get('chapter', hs[:2]), ''),
|
| 195 |
+
'duty': cargo['duty'],
|
| 196 |
+
}
|
| 197 |
+
|
| 198 |
+
if tsc:
|
| 199 |
+
result['tsc_desc'] = tsc['desc']
|
| 200 |
+
result['avg_price'] = tsc['avg_price']
|
| 201 |
+
result['unit'] = tsc['unit']
|
| 202 |
+
result['tsc_code'] = tsc['nb5']
|
| 203 |
+
else:
|
| 204 |
+
result['tsc_desc'] = cargo['ar']
|
| 205 |
+
result['avg_price'] = 0
|
| 206 |
+
result['unit'] = ''
|
| 207 |
+
result['tsc_code'] = ''
|
| 208 |
+
|
| 209 |
+
return result
|
| 210 |
+
|
| 211 |
+
|
| 212 |
+
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 213 |
+
# ๐ ุงูุฅุญุตุงุฆูุงุช
|
| 214 |
+
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 215 |
+
|
| 216 |
def get_stats():
|
| 217 |
+
return {
|
| 218 |
+
'total': 6707,
|
| 219 |
+
'match': 6034,
|
| 220 |
+
'mismatch': 673,
|
| 221 |
+
'high_risk': 294,
|
| 222 |
+
'hs_codes': len(TSC_DATABASE),
|
| 223 |
+
'cargo_types': len(CARGO_DATABASE),
|
| 224 |
+
}
|
| 225 |
|
| 226 |
def get_anomalies():
|
| 227 |
+
anomalies = []
|
| 228 |
+
for i in range(30):
|
| 229 |
+
items = random.sample(list(CARGO_DATABASE.keys()), random.randint(1, 4))
|
| 230 |
+
anomalies.append({
|
| 231 |
+
'ุงูุฑูู
': 6700 - i,
|
| 232 |
+
'ุงูุญุงููุฉ': f'TCNU{random.randint(1000000,9999999)}',
|
| 233 |
+
'ุงูุฃุตูุงู': ' + '.join([CARGO_DATABASE[it]['ar'] for it in items]),
|
| 234 |
+
'ุฃููุงุฏ_HS': ' | '.join([CARGO_DATABASE[it]['hs'] for it in items]),
|
| 235 |
+
'ุงูุฎุทูุฑุฉ': random.randint(0, 5),
|
| 236 |
+
'ุงูุชุงุฑูุฎ': datetime.now().strftime('%Y-%m-%d'),
|
| 237 |
+
})
|
| 238 |
+
return pd.DataFrame(anomalies)
|
| 239 |
|
| 240 |
def get_categories():
|
| 241 |
+
rows = []
|
| 242 |
+
for i, (en, info) in enumerate(CARGO_DATABASE.items()):
|
| 243 |
+
tsc = lookup_hs_code(info['hs'])
|
| 244 |
+
rows.append({
|
| 245 |
+
'#': i + 1,
|
| 246 |
+
'EN': en.upper().replace('_', ' '),
|
| 247 |
+
'AR': info['ar'],
|
| 248 |
+
'HS Code': info['hs'],
|
| 249 |
+
'ุงููุตู': HS_CHAPTERS.get(info.get('chapter', info['hs'][:2]), ''),
|
| 250 |
+
'ุงูุฑุณูู
': f"{info['duty']}%",
|
| 251 |
+
'ุงูุณุนุฑ_ุงูู
ุฑุฌุนู': f"${tsc['avg_price']}" if tsc and tsc['avg_price'] > 0 else 'โ',
|
| 252 |
+
'ุงููุญุฏุฉ': tsc['unit'] if tsc else '',
|
| 253 |
+
})
|
| 254 |
+
return pd.DataFrame(rows)
|
| 255 |
|
| 256 |
+
|
| 257 |
+
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 258 |
+
# ๐ ุงูุจุญุซ ูู TSC
|
| 259 |
+
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 260 |
+
|
| 261 |
+
def search_tsc(query):
|
| 262 |
+
"""ุงูุจุญุซ ูู ูุงุนุฏุฉ TSC ุจุงูููุฏ ุฃู ุงููุตู"""
|
| 263 |
+
if not query or len(query.strip()) < 2:
|
| 264 |
+
return pd.DataFrame()
|
| 265 |
+
|
| 266 |
+
query = query.strip()
|
| 267 |
+
results = []
|
| 268 |
+
|
| 269 |
+
for hs, info in TSC_DATABASE.items():
|
| 270 |
+
if query in hs or query in info['desc']:
|
| 271 |
+
results.append({
|
| 272 |
+
'ููุฏ_HS': hs,
|
| 273 |
+
'ุงูุฑู
ุฒ': info['nb5'],
|
| 274 |
+
'ุงููุตู': info['desc'],
|
| 275 |
+
'ุงูุณุนุฑ_ุงูู
ุฑุฌุนู': f"${info['avg_price']}" if info['avg_price'] > 0 else 'โ',
|
| 276 |
+
'ุงููุญุฏุฉ': info['unit'],
|
| 277 |
+
})
|
| 278 |
+
|
| 279 |
+
if len(results) >= 50:
|
| 280 |
+
break
|
| 281 |
+
|
| 282 |
+
return pd.DataFrame(results) if results else pd.DataFrame([{'ูุชูุฌุฉ': 'ูุง ุชูุฌุฏ ูุชุงุฆุฌ'}])
|
| 283 |
+
|
| 284 |
+
|
| 285 |
+
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 286 |
+
# ๐ฌ ุงูุชุญููู ุงูุฑุฆูุณู
|
| 287 |
+
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 288 |
|
| 289 |
def analyze_multi_label(img, declared_text):
|
| 290 |
+
"""ุชุญููู ุตูุฑุฉ ุงูุฃุดุนุฉ - Multi-Label Detection ู
ุน ุฃููุงุฏ HS ู
ู TSC"""
|
| 291 |
if img is None:
|
| 292 |
+
return "<div style='text-align:center;padding:50px;color:#888;font-size:18px;'>โณ ูุฑุฌู ุฑูุน ุตูุฑุฉ ุฃุดุนุฉ ุณูููุฉ ููุชุญููู</div>", pd.DataFrame()
|
| 293 |
+
|
| 294 |
+
# ู
ุญุงูุงุฉ Detection (ุณููุณุชุจุฏู ุจู YOLO ุงูุญูููู)
|
| 295 |
all_items = list(CARGO_DATABASE.keys())
|
| 296 |
+
num_detected = random.randint(3, 8)
|
| 297 |
detected_items = random.sample(all_items, num_detected)
|
| 298 |
+
|
| 299 |
+
# ุจูุงุก ุฌุฏูู ุงููุชุงุฆุฌ ู
ุน TSC
|
| 300 |
total_duty = 0
|
| 301 |
items_data = []
|
| 302 |
+
|
| 303 |
for i, item in enumerate(detected_items):
|
| 304 |
+
hs_info = get_hs_info_for_cargo(item)
|
| 305 |
+
conf = random.uniform(0.78, 0.99)
|
| 306 |
+
total_duty += hs_info['duty']
|
| 307 |
+
|
| 308 |
items_data.append({
|
| 309 |
'#': i + 1,
|
| 310 |
+
'ุงูุตูู': hs_info['name_ar'],
|
| 311 |
+
'EN': hs_info['name_en'],
|
| 312 |
+
'ููุฏ_HS': hs_info['hs_code'],
|
| 313 |
+
'ุงูุฑู
ุฒ_TSC': hs_info.get('tsc_code', ''),
|
| 314 |
+
'ุงููุตู': f"Ch.{hs_info['chapter']} {hs_info['chapter_name']}",
|
| 315 |
+
'ุงูุฑุณูู
': f"{hs_info['duty']}%",
|
| 316 |
+
'ุงูุณุนุฑ_ุงูู
ุฑุฌุนู': f"${hs_info['avg_price']}" if hs_info.get('avg_price', 0) > 0 else 'โ',
|
| 317 |
+
'ุงูุซูุฉ': f"{conf:.0%}",
|
| 318 |
})
|
| 319 |
+
|
| 320 |
df = pd.DataFrame(items_data)
|
| 321 |
+
|
| 322 |
+
# ุชุญุฏูุฏ ุงูู
ุทุงุจูุฉ ูุงูุฎุทูุฑุฉ
|
| 323 |
+
declared_items = [d.strip().lower() for d in declared_text.split('+') if d.strip()] if declared_text else []
|
| 324 |
+
detected_names = [item.lower() for item in detected_items]
|
| 325 |
+
|
| 326 |
+
if declared_items:
|
| 327 |
+
matched = sum(1 for d in declared_items if any(d in n for n in detected_names))
|
| 328 |
+
match_ratio = matched / max(len(declared_items), 1)
|
| 329 |
+
is_match = match_ratio > 0.6
|
| 330 |
+
else:
|
| 331 |
+
is_match = random.choice([True, True, True, False])
|
| 332 |
+
|
| 333 |
+
risk_level = random.randint(0, 2) if is_match else random.randint(3, 5)
|
| 334 |
+
|
| 335 |
+
risk_config = {
|
| 336 |
+
0: ('ุขู
ู', '#2E7D32', '๐ข'), 1: ('ู
ูุฎูุถ', '#558B2F', '๐ข'),
|
| 337 |
+
2: ('ู
ุชูุณุท', '#F9A825', '๐ก'), 3: ('ู
ุดุจูู', '#EF6C00', '๐ '),
|
| 338 |
+
4: ('ุนุงูู', '#D84315', '๐ด'), 5: ('ุญุฑุฌ', '#B71C1C', 'โ'),
|
| 339 |
+
}
|
| 340 |
+
|
| 341 |
+
risk_name, risk_color, risk_icon = risk_config[risk_level]
|
| 342 |
+
|
| 343 |
+
# Description strings
|
| 344 |
+
en_desc = ' | '.join([f"{CARGO_DATABASE[item]['hs']}-{item.upper()}" for item in detected_items])
|
| 345 |
+
ar_desc = ' | '.join([CARGO_DATABASE[item]['ar'] for item in detected_items])
|
| 346 |
+
|
| 347 |
result_html = f"""
|
| 348 |
+
<div style='font-family:Tajawal,Arial,sans-serif;'>
|
| 349 |
+
|
| 350 |
+
<!-- Status Banner -->
|
| 351 |
+
<div style='background:{"#2E7D32" if is_match else "#EF6C00"};padding:16px 20px;border-radius:12px;
|
| 352 |
+
text-align:center;color:white;margin-bottom:12px;box-shadow:0 2px 8px rgba(0,0,0,0.15);'>
|
| 353 |
+
<div style='font-size:24px;font-weight:bold;'>{"โ
ู
ุทุงุจู ููุชุตุฑูุญ" if is_match else "โ ๏ธ ูุชุทูุจ ู
ุฑุงุฌุนุฉ"}</div>
|
| 354 |
+
</div>
|
| 355 |
+
|
| 356 |
+
<!-- Summary Cards -->
|
| 357 |
+
<div style='display:grid;grid-template-columns:repeat(4,1fr);gap:10px;margin-bottom:12px;'>
|
| 358 |
+
<div style='background:#E3F2FD;padding:14px;border-radius:10px;text-align:center;border:1px solid #90CAF9;'>
|
| 359 |
+
<div style='font-size:26px;font-weight:bold;color:#1565C0;'>{num_detected}</div>
|
| 360 |
+
<div style='color:#555;font-size:13px;'>ุฃุตูุงู ู
ูุชุดูุฉ</div>
|
| 361 |
+
</div>
|
| 362 |
+
<div style='background:#FFF3E0;padding:14px;border-radius:10px;text-align:center;border:1px solid #FFCC80;'>
|
| 363 |
+
<div style='font-size:26px;font-weight:bold;color:#E65100;'>{total_duty}%</div>
|
| 364 |
+
<div style='color:#555;font-size:13px;'>ุฅุฌู
ุงูู ุงูุฑุณูู
</div>
|
| 365 |
</div>
|
| 366 |
+
<div style='background:{risk_color}18;padding:14px;border-radius:10px;text-align:center;border:1px solid {risk_color}44;'>
|
| 367 |
+
<div style='font-size:26px;font-weight:bold;color:{risk_color};'>{risk_icon} {risk_name}</div>
|
| 368 |
+
<div style='color:#555;font-size:13px;'>ู
ุณุชูู ุงูุฎุทูุฑุฉ</div>
|
| 369 |
</div>
|
| 370 |
+
<div style='background:#E8F5E9;padding:14px;border-radius:10px;text-align:center;border:1px solid #A5D6A7;'>
|
| 371 |
+
<div style='font-size:26px;font-weight:bold;color:#2E7D32;'>TSC</div>
|
| 372 |
+
<div style='color:#555;font-size:13px;'>ู
ุฑุชุจุท ุจุงูุฃููุงุฏ</div>
|
| 373 |
</div>
|
| 374 |
</div>
|
| 375 |
+
|
| 376 |
+
<!-- HS Codes Description -->
|
| 377 |
+
<div style='background:#fff;padding:16px;border-radius:10px;border:1px solid #ddd;margin-bottom:10px;'>
|
| 378 |
+
<div style='font-weight:bold;color:#1565C0;margin-bottom:8px;font-size:14px;'>๐ ุงููุตู ู
ุน ุฃููุงุฏ HS (ุฅูุฌููุฒู)</div>
|
| 379 |
+
<div style='background:#F5F5F5;padding:10px 14px;border-radius:8px;font-family:monospace;
|
| 380 |
+
font-size:13px;direction:ltr;color:#333;word-break:break-all;'>{en_desc}</div>
|
| 381 |
</div>
|
| 382 |
+
|
| 383 |
+
<div style='background:#fff;padding:16px;border-radius:10px;border:1px solid #ddd;'>
|
| 384 |
+
<div style='font-weight:bold;color:#E65100;margin-bottom:8px;font-size:14px;'>๐ ุงููุตู ุจุงูุนุฑุจู</div>
|
| 385 |
+
<div style='background:#FFF8E1;padding:10px 14px;border-radius:8px;font-size:14px;color:#333;'>{ar_desc}</div>
|
| 386 |
</div>
|
| 387 |
+
|
| 388 |
</div>
|
| 389 |
"""
|
| 390 |
+
|
| 391 |
return result_html, df
|
| 392 |
|
| 393 |
+
|
| 394 |
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 395 |
+
# ๐ ููุญุฉ ุงูุชุญูู
HTML
|
| 396 |
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 397 |
|
| 398 |
+
def stats_html():
|
| 399 |
+
s = get_stats()
|
| 400 |
+
return f"""
|
| 401 |
+
<div style='font-family:Tajawal,Arial,sans-serif;'>
|
| 402 |
+
<div style='display:grid;grid-template-columns:repeat(3,1fr) repeat(3,1fr);gap:10px;'>
|
| 403 |
+
<div style='background:linear-gradient(135deg,#1565C0,#1976D2);padding:18px;border-radius:12px;
|
| 404 |
+
text-align:center;color:white;box-shadow:0 3px 10px rgba(21,101,192,0.3);'>
|
| 405 |
+
<div style='font-size:30px;font-weight:bold;'>{s['total']:,}</div>
|
| 406 |
+
<div style='opacity:0.9;font-size:13px;'>๐ฆ ุฅุฌู
ุงูู ุงูุญุงููุงุช</div>
|
| 407 |
+
</div>
|
| 408 |
+
<div style='background:linear-gradient(135deg,#2E7D32,#43A047);padding:18px;border-radius:12px;
|
| 409 |
+
text-align:center;color:white;box-shadow:0 3px 10px rgba(46,125,50,0.3);'>
|
| 410 |
+
<div style='font-size:30px;font-weight:bold;'>{s['match']:,}</div>
|
| 411 |
+
<div style='opacity:0.9;font-size:13px;'>โ
ู
ุทุงุจู</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 412 |
</div>
|
| 413 |
+
<div style='background:linear-gradient(135deg,#EF6C00,#FB8C00);padding:18px;border-radius:12px;
|
| 414 |
+
text-align:center;color:white;box-shadow:0 3px 10px rgba(239,108,0,0.3);'>
|
| 415 |
+
<div style='font-size:30px;font-weight:bold;'>{s['mismatch']:,}</div>
|
| 416 |
+
<div style='opacity:0.9;font-size:13px;'>โ ู
ุฎุงูู</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 417 |
</div>
|
| 418 |
+
<div style='background:linear-gradient(135deg,#C62828,#E53935);padding:18px;border-radius:12px;
|
| 419 |
+
text-align:center;color:white;box-shadow:0 3px 10px rgba(198,40,40,0.3);'>
|
| 420 |
+
<div style='font-size:30px;font-weight:bold;'>{s['high_risk']:,}</div>
|
| 421 |
+
<div style='opacity:0.9;font-size:13px;'>๐ด ุฎุทุฑ ุนุงูู</div>
|
| 422 |
+
</div>
|
| 423 |
+
<div style='background:linear-gradient(135deg,#4527A0,#5E35B1);padding:18px;border-radius:12px;
|
| 424 |
+
text-align:center;color:white;box-shadow:0 3px 10px rgba(69,39,160,0.3);'>
|
| 425 |
+
<div style='font-size:30px;font-weight:bold;'>{s['hs_codes']:,}</div>
|
| 426 |
+
<div style='opacity:0.9;font-size:13px;'>๐ท๏ธ ุฃููุงุฏ HS (TSC)</div>
|
| 427 |
+
</div>
|
| 428 |
+
<div style='background:linear-gradient(135deg,#00695C,#00897B);padding:18px;border-radius:12px;
|
| 429 |
+
text-align:center;color:white;box-shadow:0 3px 10px rgba(0,105,92,0.3);'>
|
| 430 |
+
<div style='font-size:30px;font-weight:bold;'>{s['cargo_types']}</div>
|
| 431 |
+
<div style='opacity:0.9;font-size:13px;'>๐ ุฃุตูุงู ู
ุณุฌูุฉ</div>
|
| 432 |
+
</div>
|
| 433 |
+
</div>
|
|
|
|
| 434 |
</div>
|
| 435 |
+
"""
|
| 436 |
+
|
| 437 |
+
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 438 |
+
# ๐ฅ๏ธ ุจูุงุก ุงูุชุทุจูู
|
| 439 |
+
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 440 |
+
|
| 441 |
+
CSS = """
|
| 442 |
+
@import url('https://fonts.googleapis.com/css2?family=Tajawal:wght@400;500;700;800&display=swap');
|
| 443 |
+
|
| 444 |
+
* { font-family: 'Tajawal', sans-serif !important; }
|
| 445 |
+
|
| 446 |
+
.gradio-container {
|
| 447 |
+
max-width: 1200px !important;
|
| 448 |
+
margin: auto !important;
|
| 449 |
+
}
|
| 450 |
+
|
| 451 |
+
/* ุชุตุบูุฑ ูุงูุฐุฉ ุงูุฏุฎูู */
|
| 452 |
+
.login-container {
|
| 453 |
+
max-width: 380px !important;
|
| 454 |
+
margin: 60px auto !important;
|
| 455 |
+
}
|
| 456 |
+
|
| 457 |
+
footer { display: none !important; }
|
| 458 |
+
|
| 459 |
+
.gr-button-primary {
|
| 460 |
+
background: linear-gradient(135deg, #1565C0, #0D47A1) !important;
|
| 461 |
+
border: none !important;
|
| 462 |
+
font-weight: bold !important;
|
| 463 |
+
}
|
| 464 |
+
|
| 465 |
+
.gr-button-primary:hover {
|
| 466 |
+
background: linear-gradient(135deg, #1976D2, #1565C0) !important;
|
| 467 |
+
}
|
| 468 |
+
"""
|
| 469 |
+
|
| 470 |
+
|
| 471 |
+
def build_app():
|
| 472 |
+
with gr.Blocks(title=f"SONAR-AI v{VERSION}", theme=gr.themes.Soft(), css=CSS) as app:
|
| 473 |
+
|
| 474 |
+
# โโโ Header โโโ
|
| 475 |
+
gr.HTML(f"""
|
| 476 |
+
<div style='background:linear-gradient(135deg,#0D47A1,#1565C0,#1976D2);padding:18px 24px;
|
| 477 |
+
border-radius:14px;text-align:center;color:white;margin-bottom:12px;
|
| 478 |
+
box-shadow:0 4px 20px rgba(13,71,161,0.3);'>
|
| 479 |
+
<h1 style='margin:0;font-size:28px;font-weight:800;letter-spacing:1px;'>
|
| 480 |
+
๐ฑ SONAR-AI v{VERSION}
|
| 481 |
+
</h1>
|
| 482 |
+
<p style='margin:4px 0 0;font-size:14px;opacity:0.9;'>
|
| 483 |
+
ูุธุงู
ูุญุต ุงูุญุงููุงุช ุจุงูุฐูุงุก ุงูุงุตุทูุงุนู | {len(TSC_DATABASE):,} ููุฏ HS ู
ู ูุงุนุฏุฉ TSC
|
| 484 |
+
</p>
|
| 485 |
+
</div>
|
| 486 |
+
""")
|
| 487 |
+
|
| 488 |
+
with gr.Tabs():
|
| 489 |
+
|
| 490 |
+
# โโโโโโโ Tab 1: ููุญุฉ ุงูุชุญูู
โโโโโโโ
|
| 491 |
+
with gr.Tab("๐ ููุญุฉ ุงูุชุญูู
"):
|
| 492 |
+
gr.HTML(stats_html())
|
| 493 |
+
gr.Markdown("### ๐ ุขุฎุฑ ุงูุญุงููุงุช ุงูู
ูุญูุตุฉ")
|
| 494 |
+
anom_table = gr.Dataframe(value=get_anomalies(), height=350)
|
| 495 |
+
gr.Button("๐ ุชุญุฏูุซ ุงูุจูุงูุงุช", size="sm").click(get_anomalies, outputs=anom_table)
|
| 496 |
+
|
| 497 |
+
# โโโโโโโ Tab 2: ุงูุชุญููู โโโโโโโ
|
| 498 |
+
with gr.Tab("๐ฌ ุชุญููู ุงูุตูุฑ"):
|
| 499 |
+
gr.HTML("""
|
| 500 |
+
<div style='background:#E3F2FD;padding:12px 16px;border-radius:10px;margin-bottom:10px;
|
| 501 |
+
border-right:4px solid #1565C0;'>
|
| 502 |
+
<span style='font-weight:bold;color:#1565C0;'>๐ท ุชุญููู ุตูุฑ ุงูุฃุดุนุฉ ุงูุณูููุฉ</span>
|
| 503 |
+
<span style='color:#666;font-size:13px;'> โ ููุชุดู ุงูุฃุตูุงู ููุฑุจุทูุง ุจุฃููุงุฏ HS ู
ู ูุงุนุฏุฉ TSC</span>
|
| 504 |
+
</div>
|
| 505 |
+
""")
|
| 506 |
+
|
| 507 |
+
with gr.Row():
|
| 508 |
+
with gr.Column(scale=1):
|
| 509 |
+
a_img = gr.Image(label="๐ท ุตูุฑุฉ ุงูุฃุดุนุฉ", type="pil", height=280)
|
| 510 |
+
a_dec = gr.Textbox(
|
| 511 |
+
label="๐ ุงูุจุถุงุนุฉ ุงูู
ุตุฑูุญ ุจูุง (ุงุฎุชูุงุฑู)",
|
| 512 |
+
placeholder="SHOES + FABRIC + LED_LIGHT ...",
|
| 513 |
+
lines=2
|
| 514 |
+
)
|
| 515 |
+
a_btn = gr.Button("๐ ุชุญููู ุดุงู
ู", variant="primary", size="lg")
|
| 516 |
+
|
| 517 |
+
with gr.Column(scale=1):
|
| 518 |
+
a_res = gr.HTML(
|
| 519 |
+
"<div style='text-align:center;padding:50px;color:#888;font-size:16px;'>"
|
| 520 |
+
"โณ ุงุฑูุน ุตูุฑุฉ ุฃุดุนุฉ ุณูููุฉ ููุจุฏุก ุจุงูุชุญููู</div>"
|
| 521 |
+
)
|
| 522 |
+
|
| 523 |
+
gr.Markdown("### ๐ ุชูุงุตูู ุงูุฃุตูุงู ุงูู
ูุชุดูุฉ ู
ุน ุฃููุงุฏ HS")
|
| 524 |
+
a_tbl = gr.Dataframe(value=pd.DataFrame(), height=300)
|
| 525 |
+
|
| 526 |
+
a_btn.click(analyze_multi_label, inputs=[a_img, a_dec], outputs=[a_res, a_tbl])
|
| 527 |
+
|
| 528 |
+
# โโโโโโโ Tab 3: ูุงุนุฏุฉ ุงูุฃุตูุงู โโโโโโโ
|
| 529 |
+
with gr.Tab("๐ท๏ธ ูุงุนุฏุฉ ุงูุฃุตูุงู"):
|
| 530 |
+
gr.HTML(f"""
|
| 531 |
+
<div style='background:#E8F5E9;padding:12px 16px;border-radius:10px;margin-bottom:10px;
|
| 532 |
+
border-right:4px solid #2E7D32;'>
|
| 533 |
+
<span style='font-weight:bold;color:#2E7D32;'>๐ฆ {len(CARGO_DATABASE)} ุตูู</span>
|
| 534 |
+
<span style='color:#666;font-size:13px;'> โ ู
ุฑุชุจุทุฉ ุจุฃููุงุฏ HS ูุงูุฃุณุนุงุฑ ุงูู
ุฑุฌุนูุฉ ู
ู TSC</span>
|
| 535 |
+
</div>
|
| 536 |
+
""")
|
| 537 |
+
cats_table = gr.Dataframe(value=get_categories(), height=500)
|
| 538 |
+
gr.Button("๐ ุชุญุฏูุซ", size="sm").click(get_categories, outputs=cats_table)
|
| 539 |
+
|
| 540 |
+
# โโโโโโโ Tab 4: ุจุญุซ TSC โโโโโโโ
|
| 541 |
+
with gr.Tab("๐ ุจุญุซ TSC"):
|
| 542 |
+
gr.HTML(f"""
|
| 543 |
+
<div style='background:#FFF3E0;padding:12px 16px;border-radius:10px;margin-bottom:10px;
|
| 544 |
+
border-right:4px solid #EF6C00;'>
|
| 545 |
+
<span style='font-weight:bold;color:#EF6C00;'>๐ ุงูุจุญุซ ูู ูุงุนุฏุฉ TSC</span>
|
| 546 |
+
<span style='color:#666;font-size:13px;'> โ {len(TSC_DATABASE):,} ููุฏ HS ุญูููู</span>
|
| 547 |
+
</div>
|
| 548 |
+
""")
|
| 549 |
+
with gr.Row():
|
| 550 |
+
tsc_query = gr.Textbox(
|
| 551 |
+
label="ุงุจุญุซ ุจููุฏ HS ุฃู ูุตู ุงูุจุถุงุนุฉ",
|
| 552 |
+
placeholder="ู
ุซุงู: 870323 ุฃู ุฃุญุฐูุฉ ุฃู ุญุฏูุฏ ...",
|
| 553 |
+
scale=3
|
| 554 |
+
)
|
| 555 |
+
tsc_btn = gr.Button("๐ ุจุญุซ", variant="primary", scale=1)
|
| 556 |
+
|
| 557 |
+
tsc_results = gr.Dataframe(value=pd.DataFrame(), height=400)
|
| 558 |
+
tsc_btn.click(search_tsc, inputs=[tsc_query], outputs=[tsc_results])
|
| 559 |
+
tsc_query.submit(search_tsc, inputs=[tsc_query], outputs=[tsc_results])
|
| 560 |
+
|
| 561 |
+
# โโโโโโโ Tab 5: ุงูุฎุทูุฑุฉ โโโโโโโ
|
| 562 |
+
with gr.Tab("โก ู
ุนุงููุฑ ุงูุฎุทูุฑุฉ"):
|
| 563 |
+
gr.HTML("""
|
| 564 |
+
<div style='display:flex;gap:8px;margin:15px 0;flex-wrap:wrap;'>
|
| 565 |
+
<span style='background:#2E7D32;color:white;padding:10px 20px;border-radius:25px;font-weight:bold;'>๐ข 0 - ุขู
ู</span>
|
| 566 |
+
<span style='background:#558B2F;color:white;padding:10px 20px;border-radius:25px;font-weight:bold;'>๐ข 1 - ู
ูุฎูุถ</span>
|
| 567 |
+
<span style='background:#F9A825;color:#333;padding:10px 20px;border-radius:25px;font-weight:bold;'>๐ก 2 - ู
ุชูุณุท</span>
|
| 568 |
+
<span style='background:#EF6C00;color:white;padding:10px 20px;border-radius:25px;font-weight:bold;'>๐ 3 - ู
ุดุจูู</span>
|
| 569 |
+
<span style='background:#D84315;color:white;padding:10px 20px;border-radius:25px;font-weight:bold;'>๐ด 4 - ุนุงูู</span>
|
| 570 |
+
<span style='background:#B71C1C;color:white;padding:10px 20px;border-radius:25px;font-weight:bold;'>โ 5 - ุญุฑุฌ</span>
|
| 571 |
+
</div>
|
| 572 |
+
""")
|
| 573 |
+
gr.Markdown("""
|
| 574 |
+
### ๐ ู
ุนุงููุฑ ุชุญุฏูุฏ ุงูุฎุทูุฑุฉ
|
| 575 |
+
|
| 576 |
+
| ุงูู
ุณุชูู | ุงูุญุงูุฉ | ุงูุฅุฌุฑุงุก |
|
| 577 |
+
|---------|--------|---------|
|
| 578 |
+
| 0 - ุขู
ู | ุฌู
ูุน ุงูุฃุตูุงู ู
ุทุงุจูุฉ | ุชู
ุฑูุฑ ู
ุจุงุดุฑ |
|
| 579 |
+
| 1 - ู
ูุฎูุถ | ุงุฎุชูุงู ุจุณูุท ูู ุงููู
ูุงุช | ู
ุฑุงุฌุนุฉ ูุซุงุฆู |
|
| 580 |
+
| 2 - ู
ุชูุณุท | ุตูู ุฅุถุงูู ุบูุฑ ู
ุฐููุฑ | ูุญุต ุนุดูุงุฆู |
|
| 581 |
+
| 3 - ู
ุดุจูู | ุนุฏุฉ ุฃุตูุงู ุบูุฑ ู
ุทุงุจูุฉ | ุชูุชูุด ุฏููู |
|
| 582 |
+
| 4 - ุนุงูู | ุฃุตูุงู ู
ุดุจููุฉ ุฃู ู
ูููุฏุฉ | ุชูุชูุด ุดุงู
ู + ุฅุญุงูุฉ |
|
| 583 |
+
| 5 - ุญุฑุฌ | ู
ู
ููุนุงุช ุฃู ู
ูุงุฏ ุฎุทุฑุฉ | ุฅููุงู ููุฑู + ุฅุจูุงุบ |
|
| 584 |
+
|
| 585 |
+
### ๐ ุฑุจุท ุงูุฎุทูุฑุฉ ุจุฃููุงุฏ HS
|
| 586 |
+
- ุฃููุงุฏ **ุงููุตู 93** (ุฃุณูุญุฉ): ุฎุทูุฑุฉ 5 ุชููุงุฆูุงู
|
| 587 |
+
- ุฃููุงุฏ **ุงููุตู 36** (ู
ุชูุฌุฑุงุช): ุฎุทูุฑุฉ 5 ุชููุงุฆูุงู
|
| 588 |
+
- ุฃููุงุฏ **ุงููุตู 30** (ุฃุฏููุฉ) ุจุฏูู ุชุตุฑูุญ: ุฎุทูุฑุฉ 4
|
| 589 |
+
- ุนุฏู
ุชุทุงุจู ููุฏ HS ู
ุน ุงูุตูุฑุฉ: ุฎุทูุฑุฉ +2
|
| 590 |
+
""")
|
| 591 |
+
|
| 592 |
+
# โโโ Footer โโโ
|
| 593 |
+
gr.HTML(f"""
|
| 594 |
+
<div style='text-align:center;padding:12px;color:#888;font-size:12px;margin-top:12px;'>
|
| 595 |
+
๐ฑ SONAR-AI v{VERSION} | {len(TSC_DATABASE):,} HS Codes | ยฉ 2026 ุงูุฌู
ุงุฑู ุงูุนุฑุงููุฉ
|
| 596 |
+
</div>
|
| 597 |
+
""")
|
| 598 |
+
|
| 599 |
+
return app
|
| 600 |
+
|
| 601 |
+
|
| 602 |
+
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 603 |
+
# ๐ ุงูุชุดุบูู
|
| 604 |
+
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 605 |
|
| 606 |
if __name__ == "__main__":
|
| 607 |
+
print(f"๐ฑ SONAR-AI v{VERSION}")
|
| 608 |
+
print(f"๐ฆ Cargo types: {len(CARGO_DATABASE)}")
|
| 609 |
+
print(f"๐ท๏ธ TSC HS codes: {len(TSC_DATABASE)}")
|
| 610 |
+
print("๐ Starting...")
|
| 611 |
+
|
| 612 |
+
app = build_app()
|
| 613 |
+
app.launch(
|
| 614 |
+
auth=authenticate,
|
| 615 |
+
auth_message="๐ฑ SONAR-AI โ ุชุณุฌูู ุงูุฏุฎูู",
|
| 616 |
+
server_name="0.0.0.0",
|
| 617 |
+
server_port=7860,
|
| 618 |
+
)
|