File size: 10,088 Bytes
af99cab
 
 
 
 
 
981a51d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
af99cab
 
447fb82
981a51d
 
 
 
 
 
af99cab
 
 
 
 
 
 
 
 
 
 
 
 
 
981a51d
 
 
 
 
af99cab
 
 
 
981a51d
af99cab
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
981a51d
af99cab
 
 
 
 
 
 
 
 
981a51d
af99cab
 
 
 
 
 
981a51d
af99cab
 
 
 
 
 
 
 
981a51d
af99cab
 
 
 
 
981a51d
af99cab
 
981a51d
af99cab
 
981a51d
 
af99cab
 
 
 
 
981a51d
af99cab
 
 
 
 
981a51d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
af99cab
 
 
981a51d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
af99cab
 
 
 
 
 
 
 
 
 
 
 
 
 
 
981a51d
af99cab
981a51d
af99cab
 
 
 
 
 
 
 
 
 
 
981a51d
af99cab
981a51d
af99cab
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8c240d4
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
import gradio as gr
import pandas as pd
import numpy as np
import joblib
import pickle

try:
    model = joblib.load('xgboost_valorant_model.pkl')
    
    # Sesuaikan nama file dengan output training
    with open('player_stats.pkl', 'rb') as f: 
        knowledge_base = pickle.load(f)
        
    with open('model_columns.pkl', 'rb') as f:
        training_columns = pickle.load(f)
        
    print("โœ… Model dan Data berhasil dimuat.")
except Exception as e:
    print(f"โŒ Error loading files: {e}")
    # Dummy data untuk mencegah crash saat development lokal tanpa file
    knowledge_base = {}
    training_columns = []

# Daftar Map & Agent (Sesuaikan dengan data Anda)
MAP_LIST = ['Ascent', 'Bind', 'Breeze', 'Fracture', 'Haven', 'Icebox', 'Lotus', 'Pearl', 'Split', 'Sunset', 'Abyss', 'Corrode']
AGENT_LIST = [
    'Jett', 'Raze', 'Reyna', 'Phoenix', 'Yoru', 'Neon', 'Iso', 'Waylay', # Duelist
    'Sova', 'Fade', 'Breach', 'Skye', 'Kayo', 'Gekko', 'Tejo',           # Initiator
    'Omen', 'Brimstone', 'Viper', 'Astra', 'Harbor', 'Clove',            # Controller
    'Sage', 'Cypher', 'Killjoy', 'Chamber', 'Deadlock', 'Vyse', 'Veto'   # Sentinel
]

# --- 2. FUNGSI PREDIKSI ---
def predict_match(map_name, t1_side, 
                  t1_p1_name, t1_p1_agent, t1_p2_name, t1_p2_agent, 
                  t1_p3_name, t1_p3_agent, t1_p4_name, t1_p4_agent, t1_p5_name, t1_p5_agent,
                  t2_p1_name, t2_p1_agent, t2_p2_name, t2_p2_agent, 
                  t2_p3_name, t2_p3_agent, t2_p4_name, t2_p4_agent, t2_p5_name, t2_p5_agent):
    
    # A. Buat DataFrame Input Kosong
    input_data = pd.DataFrame(columns=training_columns)
    input_data.loc[0] = 0 # Isi baris pertama dengan 0 semua
    
    # B. Helper: Ambil Stats dari Knowledge Base
    def get_stats(player, agent):
        # Normalisasi input nama player (strip whitespace)
        player_clean = player.strip() if player else ""
        key = (player_clean, agent)
        
        # Ambil stats, default 0.5 jika tidak ada
        stats = knowledge_base.get(key, {'Agent_WR': 0.5, 'General_WR': 0.5, 'Exp': 0})
        return stats

    # C. Isi Fitur Winrate (Skenario 4 Logic)
    # Team 1 Inputs
    t1_inputs = [
        (t1_p1_name, t1_p1_agent), (t1_p2_name, t1_p2_agent), (t1_p3_name, t1_p3_agent),
        (t1_p4_name, t1_p4_agent), (t1_p5_name, t1_p5_agent)
    ]
    t1_general_wrs = []
    
    for i, (p_name, p_agent) in enumerate(t1_inputs):
        stats = get_stats(p_name, p_agent)
        idx = i + 1
        
        if f'T1_P{idx}_Agent_WR' in training_columns:
            input_data.at[0, f'T1_P{idx}_Agent_WR'] = stats['Agent_WR']
        if f'T1_P{idx}_General_WR' in training_columns:
            input_data.at[0, f'T1_P{idx}_General_WR'] = stats['General_WR']
        if f'T1_P{idx}_Agent_Exp' in training_columns:
            input_data.at[0, f'T1_P{idx}_Agent_Exp'] = stats['Exp']
            
        t1_general_wrs.append(stats['General_WR'])

    # Team 2 Inputs
    t2_inputs = [
        (t2_p1_name, t2_p1_agent), (t2_p2_name, t2_p2_agent), (t2_p3_name, t2_p3_agent),
        (t2_p4_name, t2_p4_agent), (t2_p5_name, t2_p5_agent)
    ]
    t2_general_wrs = []
    
    for i, (p_name, p_agent) in enumerate(t2_inputs):
        stats = get_stats(p_name, p_agent)
        idx = i + 1
        
        if f'T2_P{idx}_Agent_WR' in training_columns:
            input_data.at[0, f'T2_P{idx}_Agent_WR'] = stats['Agent_WR']
        if f'T2_P{idx}_General_WR' in training_columns:
            input_data.at[0, f'T2_P{idx}_General_WR'] = stats['General_WR']
        if f'T2_P{idx}_Agent_Exp' in training_columns:
            input_data.at[0, f'T2_P{idx}_Agent_Exp'] = stats['Exp']
            
        t2_general_wrs.append(stats['General_WR'])

    # D. Hitung WR Diff
    if 'WR_Diff' in training_columns:
        t1_avg = np.mean(t1_general_wrs)
        t2_avg = np.mean(t2_general_wrs)
        input_data.at[0, 'WR_Diff'] = t1_avg - t2_avg

    # E. One-Hot Encoding Manual
    # Map
    map_col = f'MAP_{map_name}'
    if map_col in training_columns:
        input_data.at[0, map_col] = 1
        
    # Start Side
    if 'T1_StartSide_Defense' in training_columns:
        input_data.at[0, 'T1_StartSide_Defense'] = 1 if t1_side == 'Defense' else 0
    if 'T2_StartSide_Defense' in training_columns:
        input_data.at[0, 'T2_StartSide_Defense'] = 1 if t1_side == 'Attack' else 0

    # Agent OHE (Slot Based)
    # T1 Agents
    for i, (_, agent) in enumerate(t1_inputs):
        col_name = f'T1_P{i+1}_Agent_{agent}'
        if col_name in training_columns:
            input_data.at[0, col_name] = 1
            
    # T2 Agents
    for i, (_, agent) in enumerate(t2_inputs):
        col_name = f'T2_P{i+1}_Agent_{agent}'
        if col_name in training_columns:
            input_data.at[0, col_name] = 1

    # ==============================================================================
    # --- BAGIAN DEBUGGING YANG DITAMBAHKAN ---
    # Log ini akan muncul di Terminal / Logs Hugging Face, bukan di UI
    print("\n" + "="*40)
    print(f"๐Ÿ” DEBUGGING PREDICTION INPUT")
    print(f"Map: {map_name} | T1 Side: {t1_side}")
    print("-" * 40)
    
    print("๐Ÿ”ต TIM 1 STATS:")
    for i, (p, a) in enumerate(t1_inputs):
        # Ambil nilai yang sudah masuk ke input_data
        wr = input_data.at[0, f'T1_P{i+1}_Agent_WR']
        gen_wr = input_data.at[0, f'T1_P{i+1}_General_WR']
        exp = input_data.at[0, f'T1_P{i+1}_Agent_Exp']
        
        status = "โœ… FOUND" if wr != 0.5 or gen_wr != 0.5 else "โŒ NOT FOUND (Using Default)"
        print(f"   P{i+1}: {p:<15} ({a:<8}) | WR: {wr:.2f} | GenWR: {gen_wr:.2f} | Exp: {exp:<3} -> {status}")

    print("-" * 40)
    print("๐Ÿ”ด TIM 2 STATS:")
    for i, (p, a) in enumerate(t2_inputs):
        wr = input_data.at[0, f'T2_P{i+1}_Agent_WR']
        gen_wr = input_data.at[0, f'T2_P{i+1}_General_WR']
        exp = input_data.at[0, f'T2_P{i+1}_Agent_Exp']
        
        status = "โœ… FOUND" if wr != 0.5 or gen_wr != 0.5 else "โŒ NOT FOUND (Using Default)"
        print(f"   P{i+1}: {p:<15} ({a:<8}) | WR: {wr:.2f} | GenWR: {gen_wr:.2f} | Exp: {exp:<3} -> {status}")

    if 'WR_Diff' in training_columns:
        print("-" * 40)
        print(f"๐Ÿ“Š Final WR_Diff (T1 - T2): {input_data.at[0, 'WR_Diff']:.4f}")
        if input_data.at[0, 'WR_Diff'] > 0:
            print("   -> Tim 1 Secara Statistik Lebih Unggul.")
        elif input_data.at[0, 'WR_Diff'] < 0:
            print("   -> Tim 2 Secara Statistik Lebih Unggul.")
        else:
            print("   -> Kekuatan Statistik Seimbang (Netral).")
            
    print("="*40 + "\n")
    # ==============================================================================

    # --- 3. PREDIKSI ---
    input_data = input_data.astype(float)
    
    try:
        prob = model.predict_proba(input_data)[0]
        win_prob_t1 = prob[1]
        
        if win_prob_t1 > 0.5:
            winner = "๐Ÿ”ต TEAM 1 WINS"
            confidence = win_prob_t1
            color = "blue"
        else:
            winner = "๐Ÿ”ด TEAM 2 WINS"
            confidence = 1 - win_prob_t1
            color = "red"
            
        # Format Output Debugging ke UI juga (Optional)
        debug_msg = "โœ… Data found for players."
        # Cek jika banyak player not found (WR_Diff 0)
        if 'WR_Diff' in input_data and input_data.at[0, 'WR_Diff'] == 0:
             debug_msg = "โš ๏ธ WARNING: Player stats not found (WR_Diff = 0). Check spelling!"

        return f"{winner}\nConfidence: {confidence:.1%}\n({debug_msg})"
        
    except Exception as e:
        return f"Error during prediction: {str(e)}"

# --- 3. UI GRADIO ---
with gr.Blocks(title="Valorant Match Predictor") as demo:
    gr.Markdown("# ๐Ÿ”ฎ Valorant AI Predictor (Skenario 4)")
    gr.Markdown("Prediksi pemenang berdasarkan sejarah performa player dan komposisi agent.")
    
    with gr.Row():
        with gr.Column():
            map_input = gr.Dropdown(MAP_LIST, label="Select Map")
            side_input = gr.Radio(["Attack", "Defense"], label="Team 1 Start Side", value="Attack")
    
    with gr.Row():
        # Team 1 Inputs
        with gr.Column():
            gr.Markdown("### ๐Ÿ”ต Team 1 Roster")
            t1_p1_n = gr.Textbox(label="P1 Name", placeholder="e.g. f0rsakeN")
            t1_p1_a = gr.Dropdown(AGENT_LIST, label="P1 Agent")
            t1_p2_n = gr.Textbox(label="P2 Name", placeholder="e.g. mindfreak")
            t1_p2_a = gr.Dropdown(AGENT_LIST, label="P2 Agent")
            t1_p3_n = gr.Textbox(label="P3 Name")
            t1_p3_a = gr.Dropdown(AGENT_LIST, label="P3 Agent")
            t1_p4_n = gr.Textbox(label="P4 Name")
            t1_p4_a = gr.Dropdown(AGENT_LIST, label="P4 Agent")
            t1_p5_n = gr.Textbox(label="P5 Name")
            t1_p5_a = gr.Dropdown(AGENT_LIST, label="P5 Agent")

        # Team 2 Inputs
        with gr.Column():
            gr.Markdown("### ๐Ÿ”ด Team 2 Roster")
            t2_p1_n = gr.Textbox(label="P1 Name", placeholder="e.g. Tenz")
            t2_p1_a = gr.Dropdown(AGENT_LIST, label="P1 Agent")
            t2_p2_n = gr.Textbox(label="P2 Name", placeholder="e.g. Zekken")
            t2_p2_a = gr.Dropdown(AGENT_LIST, label="P2 Agent")
            t2_p3_n = gr.Textbox(label="P3 Name")
            t2_p3_a = gr.Dropdown(AGENT_LIST, label="P3 Agent")
            t2_p4_n = gr.Textbox(label="P4 Name")
            t2_p4_a = gr.Dropdown(AGENT_LIST, label="P4 Agent")
            t2_p5_n = gr.Textbox(label="P5 Name")
            t2_p5_a = gr.Dropdown(AGENT_LIST, label="P5 Agent")

    btn = gr.Button("๐Ÿš€ PREDICT WINNER", variant="primary")
    output = gr.Label(label="Prediction Result")
    
    # Connect Button
    btn.click(
        fn=predict_match,
        inputs=[
            map_input, side_input,
            t1_p1_n, t1_p1_a, t1_p2_n, t1_p2_a, t1_p3_n, t1_p3_a, t1_p4_n, t1_p4_a, t1_p5_n, t1_p5_a,
            t2_p1_n, t2_p1_a, t2_p2_n, t2_p2_a, t2_p3_n, t2_p3_a, t2_p4_n, t2_p4_a, t2_p5_n, t2_p5_a
        ],
        outputs=output
    )

demo.launch()