cuxlip commited on
Commit
1f9698b
·
verified ·
1 Parent(s): 2900d70

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +165 -18
app.py CHANGED
@@ -1,20 +1,167 @@
1
- runtime error
2
- Exit code: 1. Reason: Traceback (most recent call last):
3
- File "/app/app.py", line 122, in <module>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  btn_analyze.click(
5
- ~~~~~~~~~~~~~~~~~^
6
- fn=analyze_full_draft,
7
- ^^^^^^^^^^^^^^^^^^^^^^
8
- inputs=[rank_pick, [b1, b2, b3, b4, b5], [r1, r2, r3, r4, r5], [ban1, ban2, ban3]],
9
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
10
- outputs=[counter_out, comp_out]
11
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12
  )
13
- ^
14
- File "/usr/local/lib/python3.13/site-packages/gradio/events.py", line 767, in event_trigger
15
- return Dependency(block, dep.get_config(), dep_index, fn)
16
- ~~~~~~~~~~~~~~^^
17
- File "/usr/local/lib/python3.13/site-packages/gradio/block_function.py", line 142, in get_config
18
- "inputs": [block._id for block in self.inputs],
19
- ^^^^^^^^^
20
- AttributeError: 'list' object has no attribute '_id'
 
1
+ import gradio as gr
2
+
3
+ # ========================================================
4
+ # DATABASE HERO META & SKEMA COMBO TURNAMEN 2026
5
+ # ========================================================
6
+ HERO_DATA = {
7
+ "Ling": {"role": "Jungler", "tier": "S+", "counters": {"Minsitthar": "Grounded mematikan gerak Ling.", "Khufra": "Bouncing Ball menghentikan dash.", "Saber": "Targeting instan di tembok."}, "type": "Dash/Burst", "meta": "Dive"},
8
+ "Fanny": {"role": "Jungler", "tier": "S+", "counters": {"Khufra": "Menghentikan kabel Fanny.", "Eudora": "Stun instan & burst.", "Kaja": "Suppress mutlak."}, "type": "High Mobility", "meta": "Dive"},
9
+ "Hylos": {"role": "Tank", "tier": "S", "counters": {"Karrie": "True damage %HP.", "Valir": "Slow & knockback menjauh.", "Lunox": "Penetrasi tinggi."}, "type": "High HP/Regen", "meta": "Ube/Regen"},
10
+ "Zhuxin": {"role": "Mage", "tier": "S", "counters": {"Helcurt": "Silence memutus channeling.", "Natalia": "Ciduk cepat.", "Harley": "Burst instan."}, "type": "CC/Zone", "meta": "Teamfight Control"},
11
+ "Harith": {"role": "Gold Lane", "tier": "S", "counters": {"Minsitthar": "Grounded.", "Phoveus": "Counter dash.", "Baxia": "Anti-heal."}, "type": "Dash/Magic", "meta": "Poke/Sustained"},
12
+ "Tigreal": {"role": "Roamer", "tier": "S", "counters": {"Diggie": "Anti-CC masal.", "Akai": "Membatalkan ulti Tigreal.", "Valir": "Knockback."}, "type": "CC/Initiator", "meta": "Wombo Combo"},
13
+ "Nolan": {"role": "Jungler", "tier": "S", "counters": {"Khufra": "Counter dash.", "Minsitthar": "Grounded.", "Kaja": "Suppress."}, "type": "Dash/Fast Clear", "meta": "Dive"},
14
+ "Mathilda": {"role": "Roamer", "tier": "S", "counters": {"Saber": "Lock saat terbang.", "Chou": "Tendang menjauh.", "Wanwan": "Trigger weakness."}, "type": "Support/Poke", "meta": "Ube/Regen"},
15
+ "Valentina": {"role": "Mid", "tier": "A", "counters": {"Helcurt": "Silence.", "Gusion": "Burst cepat.", "Hayabusa": "Skill sulit ditiru."}, "type": "Copy/Burst", "meta": "Flex Pick"},
16
+ "Roger": {"role": "Jungler/Gold", "tier": "S", "counters": {"Grock": "Immune CC.", "Vexana": "CC/Terror.", "Terizla": "Sustain lebih kuat."}, "type": "Physical/Burst", "meta": "Poke/Sustained"},
17
+ "Angela": {"role": "Roamer", "tier": "S", "counters": {"Baxia": "Anti-regen.", "Helcurt": "Silence target."}, "type": "Healer/Buff", "meta": "Ube/Regen"},
18
+ "Vexana": {"role": "Mid", "tier": "S", "counters": {"Kagura": "Bisa lepas CC.", "Lancelot": "Immune burst."}, "type": "Burst/CC", "meta": "Wombo Combo"}
19
+ }
20
+
21
+ ALL_HEROES = sorted(list(HERO_DATA.keys()))
22
+
23
+ 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):
24
+ blue_team = [h for h in [b1, b2, b3, b4, b5] if h]
25
+ red_team = [h for h in [r1, r2, r3, r4, r5] if h]
26
+ all_bans = [h for h in [ban1, ban2, ban3, ban4, ban5, ban6, ban7, ban8, ban9, ban10] if h]
27
+
28
+ # 1. COUNTER ANALYSIS FOR ENEMY HEROES
29
+ counter_html = "<div style='background-color: #0f172a; padding: 15px; border-radius: 10px; border: 1px solid #334155;'>"
30
+ if not red_team:
31
+ counter_html += "<p style='color: #94a3b8; margin:0;'>Menunggu pick musuh...</p>"
32
+ else:
33
+ for hero in red_team:
34
+ if hero in HERO_DATA:
35
+ data = HERO_DATA[hero]
36
+ counter_html += f"""
37
+ <div style='margin-bottom: 12px; border-left: 4px solid #ef4444; padding-left: 12px;'>
38
+ <b style='color: #f87171;'>⚠️ ANCAMAN TOURNAMENT: {hero}</b> <span style='font-size:11px; color:#cbd5e1; background:#991b1b; padding:2px 6px; border-radius:4px;'>{data['type']}</span>
39
+ <ul style='color: #94a3b8; font-size: 13px; margin: 4px 0 0 15px; padding:0;'>
40
+ """
41
+ for c_hero, reason in data["counters"].items():
42
+ if c_hero not in blue_team and c_hero not in red_team and c_hero not in all_bans:
43
+ counter_html += f"<li><span style='color: #60a5fa; font-weight:bold;'>{c_hero}</span>: {reason}</li>"
44
+ counter_html += "</ul></div>"
45
+ counter_html += "</div>"
46
+
47
+ # 2. STRATEGI META TIM & DETEKSI COMBO
48
+ meta_counts = {}
49
+ for h in blue_team:
50
+ if h in HERO_DATA:
51
+ m_type = HERO_DATA[h]["meta"]
52
+ meta_counts[m_type] = meta_counts.get(m_type, 0) + 1
53
+
54
+ meta_html = "<div style='background-color: #0f172a; padding: 15px; border-radius: 10px; border: 1px solid #334155;'>"
55
+ if not blue_team:
56
+ meta_html += "<p style='color: #94a3b8; margin:0;'>Rancang draf timmu untuk melihat arah sinergi META...</p>"
57
+ else:
58
+ dominant_meta = max(meta_counts, key=meta_counts.get) if meta_counts else "General Meta"
59
+
60
+ if dominant_meta == "Wombo Combo":
61
+ meta_html += """<b style='color: #fbbf24; font-size:16px;'>🔥 DETEKSI STRATEGI: META WOMBO COMBO</b>
62
+ <p style='color: #cbd5e1; font-size:13px; margin: 5px 0;'>Tim kamu memiliki fondasi inisiasi massal yang kuat.
63
+ <br>💡 <b>Saran Combo Tambahan:</b> Sangat cocok disinergikan dengan hero area DPS seperti <i>Claude</i> atau <i>Terizla</i> untuk eksekusi instan.</p>"""
64
+ elif dominant_meta == "Ube/Regen":
65
+ meta_html += """<b style='color: #34d399; font-size:16px;'>Healing & Sustain (META UBE)</b>
66
+ <p style='color: #cbd5e1; font-size:13px; margin: 5px 0;'>Formasi tim kamu condong pada pertarungan panjang (sustain berkumpul).
67
+ <br>💡 <b>Saran Combo Tambahan:</b> Amankan Jungler tebal (Tank/Fighter) seperti <i>Hylos</i>, <i>Baxia</i>, atau <i>Barats</i> agar perlindungan healer maksimal.</p>"""
68
+ elif dominant_meta == "Dive":
69
+ meta_html += """<b style='color: #60a5fa; font-size:16px;'>🚀 Target Mengunci Sembrono (META DIVE)</b>
70
+ <p style='color: #cbd5e1; font-size:13px; margin: 5px 0;'>Tim kamu didominasi hero penembus lini belakang berkecepatan tinggi.
71
+ <br>💡 <b>Saran Combo Tambahan:</b> Pastikan Midlaner mengamankan hero ber-damage konstan dari jauh atau roam tipe pegas/cover terbang seperti <i>Mathilda</i>.</p>"""
72
+ else:
73
+ meta_html += f"<b style='color: #cbd5e1; font-size:14px;'>🛡️ STRATEGI BERIMBANG ({dominant_meta})</b><p style='color: #94a3b8; font-size:13px; margin:5px 0;'>Komposisi draf fleksibel. Lanjutkan pick sesuai kebutuhan counter musuh.</p>"
74
+
75
+ meta_html += "</div>"
76
+
77
+ # 3. LINI KESEIMBANGAN ROLE
78
+ roles = [HERO_DATA[h]["role"] for h in blue_team if h in HERO_DATA]
79
+ all_roles = ["Jungler", "Roamer", "Midlaner", "EXP Laner", "Gold Laner"]
80
+ missing = [r for r in all_roles if r not in roles]
81
+
82
+ comp_html = "<div style='background-color: #0f172a; padding: 15px; border-radius: 10px; border: 1px solid #334155;'>"
83
+ if missing:
84
+ comp_html += f"<p style='color: #fb7185; margin:0;'>⚠️ <b>Kekurangan Slot Role:</b> {', '.join(missing)}</p>"
85
+ else:
86
+ comp_html += "<p style='color: #4ade80; margin:0;'>✅ <b>Lini Formasi Lengkap!</b> Semua lane terisi.</p>"
87
+ comp_html += "</div>"
88
+
89
+ return counter_html, meta_html, comp_html
90
+
91
+ # ========================================================
92
+ # UI INTERFACE: OFFICIAL TOURNAMENT SCREEN LAYOUT
93
+ # ========================================================
94
+ custom_css = """
95
+ body { background-color: #020617; }
96
+ .gradio-container { background-color: #020617 !important; color: white !important; }
97
+ .blue-side { border: 2px solid #3b82f6; padding: 15px; border-radius: 12px; background: rgba(59, 130, 246, 0.04); }
98
+ .red-side { border: 2px solid #ef4444; padding: 15px; border-radius: 12px; background: rgba(239, 68, 68, 0.04); }
99
+ .ban-panel { border: 1px dashed #475569; padding: 12px; border-radius: 10px; background: rgba(15, 23, 42, 0.6); margin-bottom: 15px; }
100
+ """
101
+
102
+ with gr.Blocks() as demo:
103
+ gr.HTML("""
104
+ <div style='text-align: center; padding: 15px 0;'>
105
+ <h1 style='color: #3b82f6; font-size: 28px; margin:0; text-shadow: 0 0 12px rgba(59,130,246,0.5);'>🏆 MLBB PRO TOURNAMENT DRAFT ANALYZER</h1>
106
+ <p style='color: #64748b; margin: 5px 0 0 0;'>Official 5-Ban Rule & Synergy Combinator • Season 2026</p>
107
+ </div>
108
+ """)
109
+
110
+ # PANEL TURNAMEN BAN LIST (5 Slot Blue, 5 Slot Red)
111
+ with gr.Group(elem_classes="ban-panel"):
112
+ gr.HTML("<b style='color: #94a3b8; display:block; text-align:center; margin-bottom:8px;'>🚫 TOURNAMENT BAN POOL (10 HERO MAX)</b>")
113
+ with gr.Row():
114
+ b_ban1 = gr.Dropdown([None] + ALL_HEROES, label="Blue Ban 1")
115
+ b_ban2 = gr.Dropdown([None] + ALL_HEROES, label="Blue Ban 2")
116
+ b_ban3 = gr.Dropdown([None] + ALL_HEROES, label="Blue Ban 3")
117
+ b_ban4 = gr.Dropdown([None] + ALL_HEROES, label="Blue Ban 4")
118
+ b_ban5 = gr.Dropdown([None] + ALL_HEROES, label="Blue Ban 5")
119
+ with gr.Row():
120
+ r_ban1 = gr.Dropdown([None] + ALL_HEROES, label="Red Ban 1")
121
+ r_ban2 = gr.Dropdown([None] + ALL_HEROES, label="Red Ban 2")
122
+ r_ban3 = gr.Dropdown([None] + ALL_HEROES, label="Red Ban 3")
123
+ r_ban4 = gr.Dropdown([None] + ALL_HEROES, label="Red Ban 4")
124
+ r_ban5 = gr.Dropdown([None] + ALL_HEROES, label="Red Ban 5")
125
+
126
+ with gr.Row():
127
+ # Kolom Tim Biru (Kiri)
128
+ with gr.Column(elem_classes="blue-side", scale=1):
129
+ gr.HTML("<h3 style='color: #60a5fa; margin-top:0;'>🔵 BLUE TEAM PICKS</h3>")
130
+ rank_pick = gr.Dropdown(["Pro-Tournament", "Ranked Match"], value="Pro-Tournament", label="Format Sistem")
131
+ b1 = gr.Dropdown([None] + ALL_HEROES, label="Pick 1")
132
+ b2 = gr.Dropdown([None] + ALL_HEROES, label="Pick 2")
133
+ b3 = gr.Dropdown([None] + ALL_HEROES, label="Pick 3")
134
+ b4 = gr.Dropdown([None] + ALL_HEROES, label="Pick 4")
135
+ b5 = gr.Dropdown([None] + ALL_HEROES, label="Pick 5")
136
+
137
+ # Kolom Tengah (Hasil Analisis Kilat)
138
+ with gr.Column(scale=1):
139
+ btn_analyze = gr.Button("⚔️ EVALUASI STRATEGI TURNAMEN", variant="primary", size="lg")
140
+
141
+ gr.HTML("<h3 style='color: #fbbf24; margin-top:15px;'>🔮 REKOMENDASI METALOGI & COMBO TIM</h3>")
142
+ meta_out = gr.HTML("<p style='color: #64748b;'>Rancang komposisi tim untuk memunculkan racikan sinergi...</p>")
143
+
144
+ gr.HTML("<h3 style='color: #4ade80; margin-top:15px;'>📊 CHECKPOINT LANE BALANCE</h3>")
145
+ comp_out = gr.HTML("<p style='color: #64748b;'>Memonitor kelengkapan lane...</p>")
146
+
147
+ # Kolom Tim Merah (Kanan)
148
+ with gr.Column(elem_classes="red-side", scale=1):
149
+ gr.HTML("<h3 style='color: #f87171; margin-top:0;'>🔴 RED TEAM PICKS</h3>")
150
+ r1 = gr.Dropdown([None] + ALL_HEROES, label="Enemy 1")
151
+ r2 = gr.Dropdown([None] + ALL_HEROES, label="Enemy 2")
152
+ r3 = gr.Dropdown([None] + ALL_HEROES, label="Enemy 3")
153
+ r4 = gr.Dropdown([None] + ALL_HEROES, label="Enemy 4")
154
+ r5 = gr.Dropdown([None] + ALL_HEROES, label="Enemy 5")
155
+
156
+ gr.HTML("<h2 style='color: #ef4444; border-bottom: 2px solid #ef4444; padding-bottom: 5px; margin-top:20px;'>🕵️ DEEP COUNTER-PICK STRATEGY REPORT</h2>")
157
+ counter_out = gr.HTML("<p style='color: #64748b;'>Menghitung kalkulasi mekanik counter...</p>")
158
+
159
+ # Input flat sejajar demi regulasi Gradio 6.0
160
  btn_analyze.click(
161
+ fn=analyze_tournament_draft,
162
+ inputs=[rank_pick, b1, b2, b3, b4, b5, r1, r2, r3, r4, r5, b_ban1, b_ban2, b_ban3, b_ban4, b_ban5, r_ban1, r_ban2, r_ban3, r_ban4, r_ban5],
163
+ outputs=[counter_out, meta_out, comp_out]
 
 
 
 
164
  )
165
+
166
+ if __name__ == "__main__":
167
+ demo.launch(css=custom_css, theme=gr.themes.Default())