Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,96 +1,45 @@
|
|
| 1 |
import gradio as gr
|
| 2 |
|
| 3 |
# ========================================================
|
| 4 |
-
# 1. DATABASE HERO META PRIORITAS
|
| 5 |
# ========================================================
|
| 6 |
META_HEROES = {
|
| 7 |
-
"Ling": {
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
},
|
| 11 |
-
"
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
},
|
| 15 |
-
"
|
| 16 |
-
|
| 17 |
-
|
| 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
|
| 60 |
# ========================================================
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
|
| 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
|
| 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
|
| 134 |
else:
|
| 135 |
dominant_meta = max(meta_counts, key=meta_counts.get) if meta_counts else "Sustain/Balanced"
|
| 136 |
-
|
| 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
|
| 163 |
-
<p style='color: #64748b; margin: 5px 0;'>Sistem Analisis Strategi
|
| 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] +
|
| 172 |
-
b_ban2 = gr.Dropdown([None] +
|
| 173 |
-
b_ban3 = gr.Dropdown([None] +
|
| 174 |
-
b_ban4 = gr.Dropdown([None] +
|
| 175 |
-
b_ban5 = gr.Dropdown([None] +
|
| 176 |
with gr.Row():
|
| 177 |
-
r_ban1 = gr.Dropdown([None] +
|
| 178 |
-
r_ban2 = gr.Dropdown([None] +
|
| 179 |
-
r_ban3 = gr.Dropdown([None] +
|
| 180 |
-
r_ban4 = gr.Dropdown([None] +
|
| 181 |
-
r_ban5 = gr.Dropdown([None] +
|
| 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
|
| 187 |
rank_pick = gr.Dropdown(["Pro-Tournament", "Ranked Match"], value="Pro-Tournament", label="Format")
|
| 188 |
|
| 189 |
-
b1 = gr.Dropdown([None] +
|
| 190 |
img_b1 = gr.HTML(update_hero_html(None))
|
| 191 |
-
b2 = gr.Dropdown([None] +
|
| 192 |
img_b2 = gr.HTML(update_hero_html(None))
|
| 193 |
-
b3 = gr.Dropdown([None] +
|
| 194 |
img_b3 = gr.HTML(update_hero_html(None))
|
| 195 |
-
b4 = gr.Dropdown([None] +
|
| 196 |
img_b4 = gr.HTML(update_hero_html(None))
|
| 197 |
-
b5 = gr.Dropdown([None] +
|
| 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
|
| 211 |
|
| 212 |
-
r1 = gr.Dropdown([None] +
|
| 213 |
img_r1 = gr.HTML(update_hero_html(None))
|
| 214 |
-
r2 = gr.Dropdown([None] +
|
| 215 |
img_r2 = gr.HTML(update_hero_html(None))
|
| 216 |
-
r3 = gr.Dropdown([None] +
|
| 217 |
img_r3 = gr.HTML(update_hero_html(None))
|
| 218 |
-
r4 = gr.Dropdown([None] +
|
| 219 |
img_r4 = gr.HTML(update_hero_html(None))
|
| 220 |
-
r5 = gr.Dropdown([None] +
|
| 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>")
|