cuxlip commited on
Commit
2ae8457
·
verified ·
1 Parent(s): e4eb517

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +54 -114
app.py CHANGED
@@ -1,96 +1,45 @@
1
  import gradio as gr
2
 
3
  # ========================================================
4
- # 1. DATABASE HERO META PRIORITAS (ANALYSIS CORE)
5
  # ========================================================
6
  META_HEROES = {
7
- "Ling": {
8
- "role": "Jungler", "type": "Dash/Burst", "meta": "Dive",
9
- "counters": {"Minsitthar": "Grounded mematikan gerak Ling.", "Khufra": "Bouncing Ball menghentikan dash.", "Saber": "Targeting instan di tembok.", "Kaja": "Suppress mutlak."}
10
- },
11
- "Fanny": {
12
- "role": "Jungler", "type": "High Mobility", "meta": "Dive",
13
- "counters": {"Khufra": "Menghentikan kabel Fanny.", "Eudora": "Stun instan & burst.", "Kaja": "Suppress mutlak.", "Akai": "Heavy Spin menjepit di dinding."}
14
- },
15
- "Nolan": {
16
- "role": "Jungler", "type": "Dash/Fast Clear", "meta": "Dive",
17
- "counters": {"Khufra": "Counter dash.", "Minsitthar": "Grounded.", "Kaja": "Suppress.", "Martis": "Immune CC."}
18
- },
19
- "Hayabusa": {
20
- "role": "Jungler", "type": "Burst/Blink", "meta": "Dive",
21
- "counters": {"Khufra": "Bouncing ball menggagalkan bayangan.", "Saber": "Lock langsung sebelum ulti.", "Phoveus": "Trigger saat ganti bayangan."}
22
- },
23
- "Hylos": {
24
- "role": "Tank", "type": "High HP/Regen", "meta": "Ube/Regen",
25
- "counters": {"Karrie": "True damage %HP.", "Valir": "Slow & knockback menjauh.", "Lunox": "Penetrasi tinggi.", "Baxia": "Mengurangi regen HP."}
26
- },
27
- "Zhuxin": {
28
- "role": "Midlaner", "type": "Cc/Zone", "meta": "Teamfight Control",
29
- "counters": {"Helcurt": "Silence memutus channeling.", "Natalia": "Ciduk senyap.", "Harley": "Burst instan.", "Kadita": "Immune CC."}
30
- },
31
- "Tigreal": {
32
- "role": "Roamer", "type": "Cc/Initiator", "meta": "Wombo Combo",
33
- "counters": {"Diggie": "Anti-CC masal mematikan implosion.", "Akai": "Membatalkan ulti Tigreal.", "Valir": "Knockback dorongan jauh."}
34
- },
35
- "Mathilda": {
36
- "role": "Roamer", "type": "Support/Poke", "meta": "Ube/Regen",
37
- "counters": {"Saber": "Lock saat terbang.", "Chou": "Tendang menjauh.", "Minsitthar": "Grounded mematikan terbang bebas."}
38
- },
39
- "Harith": {
40
- "role": "Gold Laner", "type": "Dash/Magic", "meta": "Poke/Sustained",
41
- "counters": {"Minsitthar": "Grounded mematikan total tariannya.", "Phoveus": "Trigger lompatan pasif.", "Khufra": "Bouncing ball penahan dash."}
42
- },
43
- "Roger": {
44
- "role": "Gold Laner/Jungler", "type": "Physical/Burst", "meta": "Poke/Sustained",
45
- "counters": {"Grock": "Immune CC.", "Vexana": "Teror bayangan lord.", "Terizla": "Adu gebuk menang sustain."}
46
- },
47
- "Terizla": {
48
- "role": "EXP Laner", "type": "Sustain/Initiator", "meta": "Wombo Combo",
49
- "counters": {"Valir": "Zonasi dorongan menjauh.", "Karrie": "Dicairkan dengan true damage.", "Diggie": "Bebas dari rantai ulti."}
50
- },
51
- "Ruby": {
52
- "role": "EXP Laner", "type": "Spellvamp/Cc", "meta": "Sustained",
53
- "counters": {"Baxia": "Memotong lifesteal.", "Phoveus": "Ayunan skill pemicu lompatan.", "Minsitthar": "Mencegah pasif lompat kecil."}
54
- }
55
- # Tambahkan counter hero META lainnya di sini jika diperlukan
56
  }
57
 
58
  # ========================================================
59
- # 2. DAFTAR UTUH SEMUA HERO MLBB (TOTAL LIST)
60
  # ========================================================
61
- ALL_MLBB_HEROES = sorted([
62
- # META PRIORITAS (Ditampilkan di atas dengan tanda khusus)
63
- "⭐ Ling", " Fanny", " Nolan", " Hayabusa", " Hylos", " Zhuxin",
64
- "⭐ Tigreal", "⭐ Mathilda", " Harith", " Roger", " Terizla", " Ruby",
65
- # ALL HEROES SYSTEM
66
- "Aamon", "Akai", "Aldous", "Alice", "Alpha", "Alucard", "Angela", "Argus", "Arlott", "Atlas", "Aulus", "Aurora",
67
- "Badang", "Balmond", "Bane", "Barats", "Baxia", "Beatrix", "Belerick", "Benedetta", "Brody", "Bruno",
68
- "Carmilla", "Cecilion", "Chang'e", "Chou", "Cici", "Claude", "Clint", "Cyclops",
69
- "Diggie", "Dyrroth", "Esmeralda", "Estes", "Eudora", "Faramis", "Floryn", "Fredrinn", "Freya",
70
- "Gatotkaca", "Gloo", "Gord", "Grock", "Guinevere", "Gusion", "Hanabi", "Hanzo", "Harley", "Helcurt",
71
- "Irithel", "Ixia", "Jawhead", "Johnson", "Kadita", "Kagura", "Kaja", "Karina", "Karrie", "Khaleed", "Khufra", "Kimmy",
72
- "Lancelot", "Layla", "Leomord", "Lesley", "Lolita", "Lunox", "Luo Yi", "Lyria", "Martis", "Masha", "Melissa", "Minotaur", "Minsitthar", "Miya", "Moskov",
73
- "Nana", "Natalia", "Natan", "Novaria", "Odette", "Paquito", "Pharsa", "Phoveus", "Popol and Kupa",
74
- "Rafaela", "Saber", "Selena", "Silvanna", "Sun", "Terizla", "Thamuz", "Uranus", "Vale", "Valentina", "Valir", "Vexana",
75
- "Wanwan", "X.Borg", "Xavier", "Yi Sun-shin", "Yin", "Yu Zhong", "Yve", "Zilong"
76
- ])
77
 
78
  BLANK_IMG = "https://via.placeholder.com/65x65/0f172a/64748b?text=%3F"
79
 
80
- # Helper pembersih bintang untuk pencarian database & gambar
81
  def clean_name(name):
82
  if not name: return ""
83
  return name.replace("⭐ ", "").strip()
84
 
85
- # Render HTML Image otomatis menggunakan placeholder terstandar jika tidak terdaftar link manual
86
  def update_hero_html(hero_name):
87
  if not hero_name:
88
  return f'<div style="display:flex; justify-content:center; margin: 4px 0;"><img src="{BLANK_IMG}" style="width:65px; height:65px; border-radius:8px; border:2px solid #334155;" /></div>'
89
-
90
  pure_name = clean_name(hero_name)
91
- # Fallback gambar text generator jika link statis tidak dipanggil langsung
92
  url = f"https://via.placeholder.com/65x65/1e293b/f8fafc?text={pure_name[:4]}"
93
-
94
  return f'<div style="display:flex; justify-content:center; margin: 4px 0;"><img src="{url}" style="width:65px; height:65px; border-radius:8px; border:2px solid #475569; object-fit:cover;" /></div>'
95
 
96
  def analyze_tournament_draft(rank, b1, b2, b3, b4, b5, r1, r2, r3, r4, r5, ban1, ban2, ban3, ban4, ban5, ban6, ban7, ban8, ban9, ban10):
@@ -98,7 +47,6 @@ def analyze_tournament_draft(rank, b1, b2, b3, b4, b5, r1, r2, r3, r4, r5, ban1,
98
  red_team = [clean_name(h) for h in [r1, r2, r3, r4, r5] if h]
99
  all_bans = [clean_name(h) for h in [ban1, ban2, ban3, ban4, ban5, ban6, ban7, ban8, ban9, ban10] if h]
100
 
101
- # 1. ANALISIS COUNTER HERO MUSUH (BERBASIS META CORE)
102
  counter_html = "<div style='background-color: #0f172a; padding: 15px; border-radius: 10px; border: 1px solid #334155;'>"
103
  if not red_team:
104
  counter_html += "<p style='color: #94a3b8; margin:0;'>Menunggu pick musuh...</p>"
@@ -118,10 +66,9 @@ def analyze_tournament_draft(rank, b1, b2, b3, b4, b5, r1, r2, r3, r4, r5, ban1,
118
  counter_html += f"<li><span style='color: #60a5fa; font-weight:bold;'>{c_hero}</span>: {reason}</li>"
119
  counter_html += "</ul></div>"
120
  if not has_meta_analysis:
121
- counter_html += "<p style='color: #34d399; margin:0;'>✅ Musuh pick hero non-prioritas turnamen. Tekanan draf tergolong aman.</p>"
122
  counter_html += "</div>"
123
 
124
- # 2. METALOGI & REKOMENDASI COMBO TIM
125
  meta_counts = {}
126
  for h in blue_team:
127
  if h in META_HEROES:
@@ -130,23 +77,16 @@ def analyze_tournament_draft(rank, b1, b2, b3, b4, b5, r1, r2, r3, r4, r5, ban1,
130
 
131
  meta_html = "<div style='background-color: #0f172a; padding: 15px; border-radius: 10px; border: 1px solid #334155;'>"
132
  if not blue_team:
133
- meta_html += "<p style='color: #94a3b8; margin:0;'>Rancang draf timmu untuk melihat arah sinergi META...</p>"
134
  else:
135
  dominant_meta = max(meta_counts, key=meta_counts.get) if meta_counts else "Sustain/Balanced"
136
- if dominant_meta == "Wombo Combo":
137
- meta_html += "<b style='color: #fbbf24; font-size:16px;'>🔥 DETEKSI STRATEGI: META WOMBO COMBO</b><p style='color: #cbd5e1; font-size:13px; margin:5px 0;'>Sinergikan dengan hero area CC masal.</p>"
138
- elif dominant_meta == "Ube/Regen":
139
- meta_html += "<b style='color: #34d399; font-size:16px;'>🛡️ DETEKSI STRATEGI: META UBE (REGEN)</b><p style='color: #cbd5e1; font-size:13px; margin:5px 0;'>Pertahankan formasi menempel dan amankan healer/tank tebal.</p>"
140
- elif dominant_meta == "Dive":
141
- meta_html += "<b style='color: #60a5fa; font-size:16px;'>🚀 DETEKSI STRATEGI: META DIVE (TABRAK)</b><p style='color: #cbd5e1; font-size:13px; margin:5px 0;'>Amankan hero penabrak lini belakang musuh.</p>"
142
- else:
143
- meta_html += f"<b style='color: #cbd5e1; font-size:14px;'>🛡️ STRATEGI BERIMBANG ATAU COMFORT PICK ({dominant_meta})</b>"
144
  meta_html += "</div>"
145
 
146
  return counter_html, meta_html, "<div style='background-color: #0f172a; padding: 15px; border-radius: 10px; border: 1px solid #334155; color:#4ade80;'>✅ Draft Monitoring Aktif</div>"
147
 
148
  # ========================================================
149
- # INTERFACE DESIGN
150
  # ========================================================
151
  custom_css = """
152
  body { background-color: #020617; }
@@ -156,45 +96,45 @@ body { background-color: #020617; }
156
  .ban-panel { border: 1px dashed #475569; padding: 12px; border-radius: 10px; background: rgba(15, 23, 42, 0.6); margin-bottom: 15px; }
157
  """
158
 
159
- with gr.Blocks() as demo:
160
  gr.HTML("""
161
  <div style='text-align: center; padding: 10px 0;'>
162
- <h1 style='color: #3b82f6; font-size: 28px; margin:0;'>🏆 MLBB COMPLETE TOURNAMENT ANALYZER</h1>
163
- <p style='color: #64748b; margin: 5px 0;'>Sistem Analisis Strategi Draf MPL 10-Ban Rule • Patch v2026</p>
164
  </div>
165
  """)
166
 
167
- # BAN SECTIONS
168
  with gr.Group(elem_classes="ban-panel"):
169
- gr.HTML("<b style='color: #94a3b8; display:block; text-align:center; margin-bottom:5px;'>🚫 TOURNAMENT BAN POOL</b>")
170
  with gr.Row():
171
- b_ban1 = gr.Dropdown([None] + ALL_MLBB_HEROES, label="B-Ban 1")
172
- b_ban2 = gr.Dropdown([None] + ALL_MLBB_HEROES, label="B-Ban 2")
173
- b_ban3 = gr.Dropdown([None] + ALL_MLBB_HEROES, label="B-Ban 3")
174
- b_ban4 = gr.Dropdown([None] + ALL_MLBB_HEROES, label="B-Ban 4")
175
- b_ban5 = gr.Dropdown([None] + ALL_MLBB_HEROES, label="B-Ban 5")
176
  with gr.Row():
177
- r_ban1 = gr.Dropdown([None] + ALL_MLBB_HEROES, label="R-Ban 1")
178
- r_ban2 = gr.Dropdown([None] + ALL_MLBB_HEROES, label="R-Ban 2")
179
- r_ban3 = gr.Dropdown([None] + ALL_MLBB_HEROES, label="R-Ban 3")
180
- r_ban4 = gr.Dropdown([None] + ALL_MLBB_HEROES, label="R-Ban 4")
181
- r_ban5 = gr.Dropdown([None] + ALL_MLBB_HEROES, label="R-Ban 5")
182
 
183
  with gr.Row():
184
- # BLUE TEAM PICKS
185
  with gr.Column(elem_classes="blue-side", scale=1):
186
- gr.HTML("<h3 style='color: #60a5fa; margin-top:0; text-align:center;'>🔵 BLUE TEAM PICKS</h3>")
187
  rank_pick = gr.Dropdown(["Pro-Tournament", "Ranked Match"], value="Pro-Tournament", label="Format")
188
 
189
- b1 = gr.Dropdown([None] + ALL_MLBB_HEROES, label="Pick 1")
190
  img_b1 = gr.HTML(update_hero_html(None))
191
- b2 = gr.Dropdown([None] + ALL_MLBB_HEROES, label="Pick 2")
192
  img_b2 = gr.HTML(update_hero_html(None))
193
- b3 = gr.Dropdown([None] + ALL_MLBB_HEROES, label="Pick 3")
194
  img_b3 = gr.HTML(update_hero_html(None))
195
- b4 = gr.Dropdown([None] + ALL_MLBB_HEROES, label="Pick 4")
196
  img_b4 = gr.HTML(update_hero_html(None))
197
- b5 = gr.Dropdown([None] + ALL_MLBB_HEROES, label="Pick 5")
198
  img_b5 = gr.HTML(update_hero_html(None))
199
 
200
  # CENTER OPERATIONS PANEL
@@ -205,19 +145,19 @@ with gr.Blocks() as demo:
205
  gr.HTML("<h3 style='color: #4ade80; margin-top:15px;'>📊 STATUS ENGINE</h3>")
206
  comp_out = gr.HTML("<p style='color: #64748b;'>Ready.</p>")
207
 
208
- # RED TEAM PICKS
209
  with gr.Column(elem_classes="red-side", scale=1):
210
- gr.HTML("<h3 style='color: #f87171; margin-top:0; text-align:center;'>🔴 RED TEAM PICKS</h3>")
211
 
212
- r1 = gr.Dropdown([None] + ALL_MLBB_HEROES, label="Enemy 1")
213
  img_r1 = gr.HTML(update_hero_html(None))
214
- r2 = gr.Dropdown([None] + ALL_MLBB_HEROES, label="Enemy 2")
215
  img_r2 = gr.HTML(update_hero_html(None))
216
- r3 = gr.Dropdown([None] + ALL_MLBB_HEROES, label="Enemy 3")
217
  img_r3 = gr.HTML(update_hero_html(None))
218
- r4 = gr.Dropdown([None] + ALL_MLBB_HEROES, label="Enemy 4")
219
  img_r4 = gr.HTML(update_hero_html(None))
220
- r5 = gr.Dropdown([None] + ALL_MLBB_HEROES, label="Enemy 5")
221
  img_r5 = gr.HTML(update_hero_html(None))
222
 
223
  gr.HTML("<h2 style='color: #ef4444; border-bottom: 2px solid #ef4444; padding-bottom: 5px; margin-top:20px;'>🕵️ DEEP COUNTER-PICK STRATEGY REPORT</h2>")
 
1
  import gradio as gr
2
 
3
  # ========================================================
4
+ # 1. DATABASE CORE HERO META PRIORITAS
5
  # ========================================================
6
  META_HEROES = {
7
+ "Ling": {"role": "Jungler", "meta": "Dive", "counters": {"Minsitthar": "Grounded mematikan Ling.", "Khufra": "Bouncing Ball menahan dash.", "Saber": "Targeting instan."}},
8
+ "Fanny": {"role": "Jungler", "meta": "Dive", "counters": {"Khufra": "Menghentikan kabel Fanny.", "Kaja": "Suppress mutlak.", "Akai": "Heavy Spin kunci di dinding."}},
9
+ "Nolan": {"role": "Jungler", "meta": "Dive", "counters": {"Khufra": "Counter dash.", "Minsitthar": "Grounded.", "Kaja": "Suppress."}},
10
+ "Hayabusa": {"role": "Jungler", "meta": "Dive", "counters": {"Khufra": "Bouncing ball.", "Saber": "Lock instan.", "Phoveus": "Counter teleport bayangan."}},
11
+ "Hylos": {"role": "Roamer", "meta": "Ube/Regen", "counters": {"Karrie": "True damage %HP.", "Valir": "Slow & knockback.", "Lunox": "Penetrasi tinggi."}},
12
+ "Tigreal": {"role": "Roamer", "meta": "Wombo Combo", "counters": {"Diggie": "Anti-CC masal.", "Akai": "Membatalkan ulti.", "Valir": "Knockback."}},
13
+ "Mathilda": {"role": "Roamer", "meta": "Ube/Regen", "counters": {"Saber": "Lock saat terbang.", "Chou": "Tendang jauh.", "Minsitthar": "Grounded."}},
14
+ "Zhuxin": {"role": "Midlaner", "meta": "Teamfight Control", "counters": {"Helcurt": "Silence memutus lentera.", "Natalia": "Ciduk senyap.", "Harley": "Burst instan."}},
15
+ "Harith": {"role": "Gold Laner", "meta": "Poke/Sustained", "counters": {"Minsitthar": "Grounded total.", "Phoveus": "Trigger lompatan pasif.", "Khufra": "Bouncing ball."}},
16
+ "Roger": {"role": "Gold Laner", "meta": "Poke/Sustained", "counters": {"Grock": "Immune CC.", "Vexana": "Teror lord.", "Terizla": "Menang sustain."}},
17
+ "Terizla": {"role": "EXP Laner", "meta": "Wombo Combo", "counters": {"Valir": "Zonasi dorongan.", "Karrie": "True damage.", "Diggie": "Lepas dari rantai."}},
18
+ "Ruby": {"role": "EXP Laner", "meta": "Sustained", "counters": {"Baxia": "Potong lifesteal.", "Phoveus": "Counter dash kecil.", "Minsitthar": "Anti-pasif lompat."}}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  }
20
 
21
  # ========================================================
22
+ # 2. DAFTAR HERO BERDASARKAN ROLE JALUR LANE
23
  # ========================================================
24
+ JUNGLER_POOL = sorted(["⭐ Ling", "⭐ Fanny", "⭐ Nolan", "⭐ Hayabusa", "Aamon", "Alucard", "Balmond", "Bane", "Barats", "Baxia", "Fredrinn", "Gusion", "Hanzo", "Harley", "Helcurt", "Karina", "Lancelot", "Martis", "Paquito", "Saber", "Yi Sun-shin", "Yin"])
25
+ ROAMER_POOL = sorted(["⭐ Hylos", "⭐ Tigreal", "⭐ Mathilda", "Akai", "Angela", "Atlas", "Belerick", "Carmilla", "Chou", "Diggie", "Estes", "Floryn", "Gatotkaca", "Gloo", "Grock", "Johnson", "Kaja", "Khufra", "Lolita", "Minotaur", "Minsitthar", "Natalia", "Rafaela", "Selena"])
26
+ MIDLANER_POOL = sorted(["⭐ Zhuxin", "Alice", "Aurora", "Cecilion", "Chang'e", "Cyclops", "Eudora", "Faramis", "Gord", "Kagura", "Kadita", "Lunox", "Luo Yi", "Nana", "Novaria", "Odette", "Pharsa", "Vale", "Valentina", "Valir", "Vexana", "Xavier", "Yve"])
27
+ EXP_LANER_POOL = sorted(["⭐ Terizla", "⭐ Ruby", "Aldous", "Alpha", "Argus", "Arlott", "Aulus", "Badang", "Benedetta", "Cici", "Dyrroth", "Esmeralda", "Freya", "Guinevere", "Jawhead", "Khaleed", "Leomord", "Masha", "Phoveus", "Silvanna", "Sun", "Thamuz", "Uranus", "X.Borg", "Yu Zhong", "Zilong"])
28
+ GOLD_LANER_POOL = sorted(["⭐ Harith", "⭐ Roger", "Beatrix", "Brody", "Bruno", "Claude", "Clint", "Hanabi", "Irithel", "Ixia", "Layla", "Lesley", "Melissa", "Miya", "Moskov", "Natan", "Popol and Kupa", "Wanwan"])
29
+
30
+ ALL_HEROES_COMBINED = sorted(JUNGLER_POOL + ROAMER_POOL + MIDLANER_POOL + EXP_LANER_POOL + GOLD_LANER_POOL)
 
 
 
 
 
 
 
 
 
31
 
32
  BLANK_IMG = "https://via.placeholder.com/65x65/0f172a/64748b?text=%3F"
33
 
 
34
  def clean_name(name):
35
  if not name: return ""
36
  return name.replace("⭐ ", "").strip()
37
 
 
38
  def update_hero_html(hero_name):
39
  if not hero_name:
40
  return f'<div style="display:flex; justify-content:center; margin: 4px 0;"><img src="{BLANK_IMG}" style="width:65px; height:65px; border-radius:8px; border:2px solid #334155;" /></div>'
 
41
  pure_name = clean_name(hero_name)
 
42
  url = f"https://via.placeholder.com/65x65/1e293b/f8fafc?text={pure_name[:4]}"
 
43
  return f'<div style="display:flex; justify-content:center; margin: 4px 0;"><img src="{url}" style="width:65px; height:65px; border-radius:8px; border:2px solid #475569; object-fit:cover;" /></div>'
44
 
45
  def analyze_tournament_draft(rank, b1, b2, b3, b4, b5, r1, r2, r3, r4, r5, ban1, ban2, ban3, ban4, ban5, ban6, ban7, ban8, ban9, ban10):
 
47
  red_team = [clean_name(h) for h in [r1, r2, r3, r4, r5] if h]
48
  all_bans = [clean_name(h) for h in [ban1, ban2, ban3, ban4, ban5, ban6, ban7, ban8, ban9, ban10] if h]
49
 
 
50
  counter_html = "<div style='background-color: #0f172a; padding: 15px; border-radius: 10px; border: 1px solid #334155;'>"
51
  if not red_team:
52
  counter_html += "<p style='color: #94a3b8; margin:0;'>Menunggu pick musuh...</p>"
 
66
  counter_html += f"<li><span style='color: #60a5fa; font-weight:bold;'>{c_hero}</span>: {reason}</li>"
67
  counter_html += "</ul></div>"
68
  if not has_meta_analysis:
69
+ counter_html += "<p style='color: #34d399; margin:0;'>✅ Musuh pick hero non-prioritas turnamen. Tekanan draf aman.</p>"
70
  counter_html += "</div>"
71
 
 
72
  meta_counts = {}
73
  for h in blue_team:
74
  if h in META_HEROES:
 
77
 
78
  meta_html = "<div style='background-color: #0f172a; padding: 15px; border-radius: 10px; border: 1px solid #334155;'>"
79
  if not blue_team:
80
+ meta_html += "<p style='color: #94a3b8; margin:0;'>Rancang draf timmu...</p>"
81
  else:
82
  dominant_meta = max(meta_counts, key=meta_counts.get) if meta_counts else "Sustain/Balanced"
83
+ meta_html += f"<b style='color: #34d399; font-size:16px;'>🛡️ KECENDERUNGAN META TIM: {dominant_meta}</b>"
 
 
 
 
 
 
 
84
  meta_html += "</div>"
85
 
86
  return counter_html, meta_html, "<div style='background-color: #0f172a; padding: 15px; border-radius: 10px; border: 1px solid #334155; color:#4ade80;'>✅ Draft Monitoring Aktif</div>"
87
 
88
  # ========================================================
89
+ # INTERFACE DESIGN (ROLE SPECIFIC DROPDOWNS)
90
  # ========================================================
91
  custom_css = """
92
  body { background-color: #020617; }
 
96
  .ban-panel { border: 1px dashed #475569; padding: 12px; border-radius: 10px; background: rgba(15, 23, 42, 0.6); margin-bottom: 15px; }
97
  """
98
 
99
+ with gr.Blocks(css=custom_css) as demo:
100
  gr.HTML("""
101
  <div style='text-align: center; padding: 10px 0;'>
102
+ <h1 style='color: #3b82f6; font-size: 28px; margin:0;'>🏆 MLBB ROLE-BASED DRAFT ANALYZER</h1>
103
+ <p style='color: #64748b; margin: 5px 0;'>Sistem Analisis Strategi Berdasarkan Lini Lane • Patch v2026</p>
104
  </div>
105
  """)
106
 
107
+ # BAN SECTIONS (Tetap menggunakan All Heroes agar bebas ban apa saja)
108
  with gr.Group(elem_classes="ban-panel"):
109
+ gr.HTML("<b style='color: #94a3b8; display:block; text-align:center; margin-bottom:5px;'>🚫 TOURNAMENT BAN POOL (ALL HEROES)</b>")
110
  with gr.Row():
111
+ b_ban1 = gr.Dropdown([None] + ALL_HEROES_COMBINED, label="B-Ban 1")
112
+ b_ban2 = gr.Dropdown([None] + ALL_HEROES_COMBINED, label="B-Ban 2")
113
+ b_ban3 = gr.Dropdown([None] + ALL_HEROES_COMBINED, label="B-Ban 3")
114
+ b_ban4 = gr.Dropdown([None] + ALL_HEROES_COMBINED, label="B-Ban 4")
115
+ b_ban5 = gr.Dropdown([None] + ALL_HEROES_COMBINED, label="B-Ban 5")
116
  with gr.Row():
117
+ r_ban1 = gr.Dropdown([None] + ALL_HEROES_COMBINED, label="R-Ban 1")
118
+ r_ban2 = gr.Dropdown([None] + ALL_HEROES_COMBINED, label="R-Ban 2")
119
+ r_ban3 = gr.Dropdown([None] + ALL_HEROES_COMBINED, label="R-Ban 3")
120
+ r_ban4 = gr.Dropdown([None] + ALL_HEROES_COMBINED, label="R-Ban 4")
121
+ r_ban5 = gr.Dropdown([None] + ALL_HEROES_COMBINED, label="R-Ban 5")
122
 
123
  with gr.Row():
124
+ # BLUE TEAM PICKS (DIPISAH PER LANE / ROLE)
125
  with gr.Column(elem_classes="blue-side", scale=1):
126
+ gr.HTML("<h3 style='color: #60a5fa; margin-top:0; text-align:center;'>🔵 BLUE TEAM LANERS</h3>")
127
  rank_pick = gr.Dropdown(["Pro-Tournament", "Ranked Match"], value="Pro-Tournament", label="Format")
128
 
129
+ b1 = gr.Dropdown([None] + JUNGLER_POOL, label="⚔️ Jungler")
130
  img_b1 = gr.HTML(update_hero_html(None))
131
+ b2 = gr.Dropdown([None] + ROAMER_POOL, label="🛡️ Roamer")
132
  img_b2 = gr.HTML(update_hero_html(None))
133
+ b3 = gr.Dropdown([None] + MIDLANER_POOL, label="🔮 Midlaner")
134
  img_b3 = gr.HTML(update_hero_html(None))
135
+ b4 = gr.Dropdown([None] + EXP_LANER_POOL, label="🛡️ EXP Laner")
136
  img_b4 = gr.HTML(update_hero_html(None))
137
+ b5 = gr.Dropdown([None] + GOLD_LANER_POOL, label="🏹 Gold Laner")
138
  img_b5 = gr.HTML(update_hero_html(None))
139
 
140
  # CENTER OPERATIONS PANEL
 
145
  gr.HTML("<h3 style='color: #4ade80; margin-top:15px;'>📊 STATUS ENGINE</h3>")
146
  comp_out = gr.HTML("<p style='color: #64748b;'>Ready.</p>")
147
 
148
+ # RED TEAM PICKS (DIPISAH PER LANE / ROLE)
149
  with gr.Column(elem_classes="red-side", scale=1):
150
+ gr.HTML("<h3 style='color: #f87171; margin-top:0; text-align:center;'>🔴 RED TEAM LANERS</h3>")
151
 
152
+ r1 = gr.Dropdown([None] + JUNGLER_POOL, label="⚔️ Enemy Jungler")
153
  img_r1 = gr.HTML(update_hero_html(None))
154
+ r2 = gr.Dropdown([None] + ROAMER_POOL, label="🛡️ Enemy Roamer")
155
  img_r2 = gr.HTML(update_hero_html(None))
156
+ r3 = gr.Dropdown([None] + MIDLANER_POOL, label="🔮 Enemy Midlaner")
157
  img_r3 = gr.HTML(update_hero_html(None))
158
+ r4 = gr.Dropdown([None] + EXP_LANER_POOL, label="🛡️ Enemy EXP Laner")
159
  img_r4 = gr.HTML(update_hero_html(None))
160
+ r5 = gr.Dropdown([None] + GOLD_LANER_POOL, label="🏹 Enemy Gold Laner")
161
  img_r5 = gr.HTML(update_hero_html(None))
162
 
163
  gr.HTML("<h2 style='color: #ef4444; border-bottom: 2px solid #ef4444; padding-bottom: 5px; margin-top:20px;'>🕵️ DEEP COUNTER-PICK STRATEGY REPORT</h2>")