Allisona commited on
Commit
fabe8b7
·
verified ·
1 Parent(s): 3f5384b

Upload 8 files

Browse files
README.md ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: UFC Fight Predictor
3
+ emoji: 🥊
4
+ colorFrom: blue
5
+ colorTo: indigo
6
+ sdk: gradio
7
+ sdk_version: 4.19.2
8
+ app_file: app.py
9
+ pinned: false
10
+ license: mit
11
+ ---
12
+
13
+ # UFC Fight Predictor
14
+
15
+ A machine learning application that predicts UFC fight outcomes based on fighter statistics.
16
+
17
+ ## Model Performance
18
+
19
+ - **Accuracy**: 98.9%
20
+ - **Best Algorithm**: Logistic Regression
21
+ - **Dataset**: 7,417 UFC fights
22
+ - **Features**: 25 statistical indicators
23
+
24
+ ## Features Analyzed
25
+
26
+ - Knockdown differences between fighters
27
+ - Significant strike statistics
28
+ - Takedown attempts and success rates
29
+ - Submission attempts
30
+ - Striking accuracy
31
+ - Weight class
32
+ - Fight round
33
+ - Method of victory encoding
34
+
35
+ ## How to Use
36
+
37
+ 1. **Enter fighter statistics** for both competitors
38
+ 2. **Select weight class** from dropdown
39
+ 3. **Adjust method parameter** (0-10 scale)
40
+ 4. **Click Submit** to get prediction
41
+
42
+ ## Output Information
43
+
44
+ The model returns:
45
+ - Predicted winner
46
+ - Confidence percentage
47
+ - Individual probabilities for each fighter
48
+ - Detailed analysis
49
+
50
+ ## Technical Details
51
+
52
+ Built with:
53
+ - Scikit-learn for machine learning
54
+ - Gradio for web interface
55
+ - Pandas for data processing
56
+ - NumPy for numerical operations
57
+
58
+ ## Model Validation
59
+
60
+ The model was validated using:
61
+ - Train/test split (80/20)
62
+ - Multiple algorithm comparison
63
+ - Cross-validation techniques
64
+ - Comprehensive metrics (Accuracy, AUC, F1-Score)
65
+
66
+ *For educational and demonstration purposes.*
app.py ADDED
@@ -0,0 +1,203 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import pickle
3
+ import numpy as np
4
+ import pandas as pd
5
+ import json
6
+ import os
7
+
8
+ print("=== INICIANDO UFC PREDICTOR ===")
9
+
10
+ def safe_load_pickle(filepath, default_value=None):
11
+ """Cargar archivos pickle de forma segura"""
12
+ try:
13
+ with open(filepath, "rb") as f:
14
+ return pickle.load(f)
15
+ except Exception as e:
16
+ print(f"Error cargando {filepath}: {e}")
17
+ return default_value
18
+
19
+ def safe_load_json(filepath, default_value=None):
20
+ """Cargar archivos JSON de forma segura"""
21
+ try:
22
+ with open(filepath, "r") as f:
23
+ return json.load(f)
24
+ except Exception as e:
25
+ print(f"Error cargando {filepath}: {e}")
26
+ return default_value
27
+
28
+ # Cargar modelo y preprocesadores de forma segura
29
+ print("Cargando modelo y componentes...")
30
+
31
+ model = safe_load_pickle("ufc_best_model.pkl")
32
+ scaler = safe_load_pickle("ufc_scaler.pkl")
33
+ imputer = safe_load_pickle("ufc_imputer.pkl")
34
+ metadata = safe_load_json("ufc_model_metadata.json", {})
35
+ ranges = safe_load_json("ufc_feature_ranges.json", {})
36
+
37
+ # Verificar que todo se cargó correctamente
38
+ components_loaded = all([model is not None, scaler is not None, imputer is not None])
39
+ if not components_loaded:
40
+ print("❌ ERROR: No se pudieron cargar todos los componentes del modelo")
41
+ raise Exception("Fallo en la carga de componentes del modelo")
42
+
43
+ print("✅ Todos los componentes cargados correctamente")
44
+
45
+ if metadata:
46
+ print(f"Modelo: {metadata.get('best_model_selected', 'N/A')}")
47
+ print(f"Accuracy: {metadata.get('evaluation_metrics', {}).get('accuracy', 'N/A')}")
48
+
49
+ # Obtener características del modelo
50
+ feature_columns = metadata.get('feature_columns', [])
51
+ if not feature_columns:
52
+ print("⚠️ Advertencia: No se encontraron feature_columns en metadata")
53
+
54
+ print(f"Características del modelo: {len(feature_columns)}")
55
+
56
+ def predict_ufc_fight(
57
+ fighter_1_kd, fighter_1_str, fighter_1_td, fighter_1_sub,
58
+ fighter_2_kd, fighter_2_str, fighter_2_td, fighter_2_sub,
59
+ round_num, weight_class, method_encoded
60
+ ):
61
+ """
62
+ Predice el resultado de una pelea UFC
63
+ """
64
+ try:
65
+ # Validar entradas básicas
66
+ if any(pd.isna(x) for x in [fighter_1_kd, fighter_1_str, fighter_2_kd, fighter_2_str]):
67
+ return {"Error": "Valores de entrada inválidos o faltantes"}
68
+
69
+ # Calcular diferencias
70
+ kd_diff = fighter_1_kd - fighter_2_kd
71
+ str_diff = fighter_1_str - fighter_2_str
72
+ td_diff = fighter_1_td - fighter_2_td
73
+ sub_diff = fighter_1_sub - fighter_2_sub
74
+
75
+ # Calcular precisiones (evitar división por cero)
76
+ fighter_1_accuracy = fighter_1_str / (fighter_1_str + 10) if fighter_1_str >= 0 else 0
77
+ fighter_2_accuracy = fighter_2_str / (fighter_2_str + 10) if fighter_2_str >= 0 else 0
78
+
79
+ # Crear array de entrada con las características en el orden CORRECTO
80
+ input_features = []
81
+
82
+ # Añadir características en el orden esperado por el modelo
83
+ for feature in feature_columns:
84
+ if feature == 'KD_diff':
85
+ input_features.append(kd_diff)
86
+ elif feature == 'STR_diff':
87
+ input_features.append(str_diff)
88
+ elif feature == 'TD_diff':
89
+ input_features.append(td_diff)
90
+ elif feature == 'SUB_diff':
91
+ input_features.append(sub_diff)
92
+ elif feature == 'Fighter_1_KD':
93
+ input_features.append(fighter_1_kd)
94
+ elif feature == 'Fighter_2_KD':
95
+ input_features.append(fighter_2_kd)
96
+ elif feature == 'Fighter_1_STR':
97
+ input_features.append(fighter_1_str)
98
+ elif feature == 'Fighter_2_STR':
99
+ input_features.append(fighter_2_str)
100
+ elif feature == 'Fighter_1_TD':
101
+ input_features.append(fighter_1_td)
102
+ elif feature == 'Fighter_2_TD':
103
+ input_features.append(fighter_2_td)
104
+ elif feature == 'Fighter_1_SUB':
105
+ input_features.append(fighter_1_sub)
106
+ elif feature == 'Fighter_2_SUB':
107
+ input_features.append(fighter_2_sub)
108
+ elif feature == 'Fighter_1_accuracy':
109
+ input_features.append(fighter_1_accuracy)
110
+ elif feature == 'Fighter_2_accuracy':
111
+ input_features.append(fighter_2_accuracy)
112
+ elif feature == 'Round':
113
+ input_features.append(round_num)
114
+ elif feature == 'Method_encoded':
115
+ input_features.append(method_encoded)
116
+ elif feature.startswith('weight_class_'):
117
+ # One-hot encoding para categorías de peso
118
+ category_name = feature.replace('weight_class_', '')
119
+ input_features.append(1 if category_name == weight_class else 0)
120
+ else:
121
+ # Característica no reconocida, usar 0
122
+ input_features.append(0)
123
+ print(f"⚠️ Caracter��stica no reconocida: {feature}")
124
+
125
+ # Convertir a numpy array
126
+ input_array = np.array([input_features])
127
+
128
+ # Aplicar preprocesamiento
129
+ input_imputed = imputer.transform(input_array)
130
+ input_scaled = scaler.transform(input_imputed)
131
+
132
+ # Hacer predicción
133
+ prediction = model.predict(input_scaled)[0]
134
+ probability = model.predict_proba(input_scaled)[0]
135
+
136
+ # Interpretar resultados
137
+ if prediction == 1:
138
+ winner = "Fighter 1"
139
+ confidence = probability[1]
140
+ color = "#FF6B6B" # Rojo
141
+ else:
142
+ winner = "Fighter 2"
143
+ confidence = probability[0]
144
+ color = "#4ECDC4" # Verde
145
+
146
+ return {
147
+ "Ganador predicho": winner,
148
+ "Confianza": f"{confidence:.1%}",
149
+ "Probabilidad Fighter 1": f"{probability[1]:.1%}",
150
+ "Probabilidad Fighter 2": f"{probability[0]:.1%}",
151
+ "Análisis": f"El modelo predice que {winner} ganará con {confidence:.1%} de confianza"
152
+ }
153
+
154
+ except Exception as e:
155
+ error_msg = f"Error en predicción: {str(e)}"
156
+ print(error_msg)
157
+ return {"Error": error_msg}
158
+
159
+ # Crear interfaz Gradio
160
+ print("Configurando interfaz Gradio...")
161
+
162
+ # Definir inputs con valores por defecto razonables
163
+ inputs = [
164
+ gr.Number(label="Fighter 1 - Knockdowns", value=0, minimum=0, maximum=10, step=1),
165
+ gr.Number(label="Fighter 1 - Golpes significativos", value=50, minimum=0, maximum=500, step=1),
166
+ gr.Number(label="Fighter 1 - Takedowns", value=1, minimum=0, maximum=20, step=1),
167
+ gr.Number(label="Fighter 1 - Intentos de sumisión", value=0, minimum=0, maximum=10, step=1),
168
+ gr.Number(label="Fighter 2 - Knockdowns", value=0, minimum=0, maximum=10, step=1),
169
+ gr.Number(label="Fighter 2 - Golpes significativos", value=45, minimum=0, maximum=500, step=1),
170
+ gr.Number(label="Fighter 2 - Takedowns", value=2, minimum=0, maximum=20, step=1),
171
+ gr.Number(label="Fighter 2 - Intentos de sumisión", value=1, minimum=0, maximum=10, step=1),
172
+ gr.Slider(1, 5, value=3, step=1, label="Round"),
173
+ gr.Dropdown(
174
+ choices=[
175
+ "Bantamweight", "Catch Weight", "Featherweight", "Flyweight",
176
+ "Heavyweight", "Light Heavyweight", "Lightweight", "Middleweight", "Welterweight"
177
+ ],
178
+ value="Lightweight",
179
+ label="Categoría de Peso"
180
+ ),
181
+ gr.Slider(0, 10, value=5, step=1, label="Método (0-10)")
182
+ ]
183
+
184
+ # Crear la aplicación
185
+ demo = gr.Interface(
186
+ fn=predict_ufc_fight,
187
+ inputs=inputs,
188
+ outputs="json",
189
+ title="UFC Fight Predictor",
190
+ description="Predice el resultado de peleas UFC usando Machine Learning. Modelo entrenado con datos reales.",
191
+ examples=[
192
+ [2, 120, 3, 1, 0, 80, 1, 0, 3, "Lightweight", 5],
193
+ [0, 80, 1, 0, 3, 150, 4, 2, 2, "Welterweight", 5],
194
+ [1, 100, 2, 0, 1, 95, 1, 1, 4, "Middleweight", 6]
195
+ ],
196
+ theme="default"
197
+ )
198
+
199
+ print("✅ Interfaz configurada")
200
+
201
+ if __name__ == "__main__":
202
+ print("🚀 Iniciando aplicación...")
203
+ demo.launch(server_name="0.0.0.0", server_port=7860)
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ scikit-learn==1.3.2
2
+ pandas==2.1.4
3
+ numpy==1.24.3
4
+ gradio==4.19.2
ufc_best_model.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:0439d5739c065b12e66cbb22e80486312975e183c18e53fddb353f633961f24f
3
+ size 917
ufc_feature_ranges.json ADDED
@@ -0,0 +1,177 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "KD_diff": {
3
+ "min": -3.0,
4
+ "max": 5.0,
5
+ "mean": 0.30335715248752865,
6
+ "std": 0.6696380391016917,
7
+ "type": "numeric"
8
+ },
9
+ "STR_diff": {
10
+ "min": -112.0,
11
+ "max": 312.0,
12
+ "mean": 14.560199541593636,
13
+ "std": 22.449419867501298,
14
+ "type": "numeric"
15
+ },
16
+ "TD_diff": {
17
+ "min": -11.0,
18
+ "max": 20.0,
19
+ "mean": 0.785762437643252,
20
+ "std": 2.3930346750438454,
21
+ "type": "numeric"
22
+ },
23
+ "SUB_diff": {
24
+ "min": -7.0,
25
+ "max": 10.0,
26
+ "mean": 0.281380612107321,
27
+ "std": 1.1263107348466987,
28
+ "type": "numeric"
29
+ },
30
+ "Fighter_1_KD": {
31
+ "min": 0.0,
32
+ "max": 5.0,
33
+ "mean": 0.36685991640825133,
34
+ "std": 0.6072616760376748,
35
+ "type": "numeric"
36
+ },
37
+ "Fighter_2_KD": {
38
+ "min": 0.0,
39
+ "max": 3.0,
40
+ "mean": 0.06350276392072267,
41
+ "std": 0.26811152820774914,
42
+ "type": "numeric"
43
+ },
44
+ "Fighter_1_STR": {
45
+ "min": 0.0,
46
+ "max": 445.0,
47
+ "mean": 43.114601590939735,
48
+ "std": 34.38830665983602,
49
+ "type": "numeric"
50
+ },
51
+ "Fighter_2_STR": {
52
+ "min": 0.0,
53
+ "max": 271.0,
54
+ "mean": 28.5544020493461,
55
+ "std": 26.9280732660874,
56
+ "type": "numeric"
57
+ },
58
+ "Fighter_1_TD": {
59
+ "min": 0.0,
60
+ "max": 21.0,
61
+ "mean": 1.4516650937036537,
62
+ "std": 1.9804506373774997,
63
+ "type": "numeric"
64
+ },
65
+ "Fighter_2_TD": {
66
+ "min": 0.0,
67
+ "max": 11.0,
68
+ "mean": 0.6659026560604018,
69
+ "std": 1.186385983547397,
70
+ "type": "numeric"
71
+ },
72
+ "Fighter_1_SUB": {
73
+ "min": 0.0,
74
+ "max": 10.0,
75
+ "mean": 0.5317513819603613,
76
+ "std": 0.939138539301686,
77
+ "type": "numeric"
78
+ },
79
+ "Fighter_2_SUB": {
80
+ "min": 0.0,
81
+ "max": 7.0,
82
+ "mean": 0.2503707698530403,
83
+ "std": 0.6889540600963606,
84
+ "type": "numeric"
85
+ },
86
+ "Fighter_1_accuracy": {
87
+ "min": 0.0,
88
+ "max": 0.978021978021978,
89
+ "mean": 0.7139546070716276,
90
+ "std": 0.19988857830200385,
91
+ "type": "numeric"
92
+ },
93
+ "Fighter_2_accuracy": {
94
+ "min": 0.0,
95
+ "max": 0.9644128113879004,
96
+ "mean": 0.6003475272273104,
97
+ "std": 0.25593203607262505,
98
+ "type": "numeric"
99
+ },
100
+ "Round": {
101
+ "min": 1.0,
102
+ "max": 5.0,
103
+ "mean": 2.33832456495346,
104
+ "std": 1.0137666795727949,
105
+ "type": "numeric"
106
+ },
107
+ "weight_class_Bantamweight": {
108
+ "min": 0.0,
109
+ "max": 1.0,
110
+ "mean": 0.08534447889982473,
111
+ "std": 0.27941246360680766,
112
+ "type": "numeric"
113
+ },
114
+ "weight_class_Catch Weight": {
115
+ "min": 0.0,
116
+ "max": 1.0,
117
+ "mean": 0.008763651071861939,
118
+ "std": 0.09320955346770812,
119
+ "type": "numeric"
120
+ },
121
+ "weight_class_Featherweight": {
122
+ "min": 0.0,
123
+ "max": 1.0,
124
+ "mean": 0.09572603478495348,
125
+ "std": 0.29423499699229244,
126
+ "type": "numeric"
127
+ },
128
+ "weight_class_Flyweight": {
129
+ "min": 0.0,
130
+ "max": 1.0,
131
+ "mean": 0.042065525144937305,
132
+ "std": 0.20075221144095287,
133
+ "type": "numeric"
134
+ },
135
+ "weight_class_Heavyweight": {
136
+ "min": 0.0,
137
+ "max": 1.0,
138
+ "mean": 0.09222057435620871,
139
+ "std": 0.2893565768715069,
140
+ "type": "numeric"
141
+ },
142
+ "weight_class_Light Heavyweight": {
143
+ "min": 0.0,
144
+ "max": 1.0,
145
+ "mean": 0.08911959013078063,
146
+ "std": 0.2849354927383638,
147
+ "type": "numeric"
148
+ },
149
+ "weight_class_Lightweight": {
150
+ "min": 0.0,
151
+ "max": 1.0,
152
+ "mean": 0.17365511662397196,
153
+ "std": 0.37883818051469625,
154
+ "type": "numeric"
155
+ },
156
+ "weight_class_Middleweight": {
157
+ "min": 0.0,
158
+ "max": 1.0,
159
+ "mean": 0.13334232169340704,
160
+ "std": 0.33996724805867956,
161
+ "type": "numeric"
162
+ },
163
+ "weight_class_Welterweight": {
164
+ "min": 0.0,
165
+ "max": 1.0,
166
+ "mean": 0.16826210057974922,
167
+ "std": 0.3741240936412544,
168
+ "type": "numeric"
169
+ },
170
+ "Method_encoded": {
171
+ "min": 0.0,
172
+ "max": 70.0,
173
+ "mean": 41.41000404476203,
174
+ "std": 24.947437131515553,
175
+ "type": "numeric"
176
+ }
177
+ }
ufc_imputer.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:f1d8839ed2806b475c0741da0ffd56b5bfae897127c516b6dc07823be96dfe4e
3
+ size 1167
ufc_model_metadata.json ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "feature_columns": [
3
+ "KD_diff",
4
+ "STR_diff",
5
+ "TD_diff",
6
+ "SUB_diff",
7
+ "Fighter_1_KD",
8
+ "Fighter_2_KD",
9
+ "Fighter_1_STR",
10
+ "Fighter_2_STR",
11
+ "Fighter_1_TD",
12
+ "Fighter_2_TD",
13
+ "Fighter_1_SUB",
14
+ "Fighter_2_SUB",
15
+ "Fighter_1_accuracy",
16
+ "Fighter_2_accuracy",
17
+ "Round",
18
+ "weight_class_Bantamweight",
19
+ "weight_class_Catch Weight",
20
+ "weight_class_Featherweight",
21
+ "weight_class_Flyweight",
22
+ "weight_class_Heavyweight",
23
+ "weight_class_Light Heavyweight",
24
+ "weight_class_Lightweight",
25
+ "weight_class_Middleweight",
26
+ "weight_class_Welterweight",
27
+ "Method_encoded"
28
+ ],
29
+ "best_model_name": "Regresi\u00f3n Log\u00edstica",
30
+ "best_accuracy": 0.9892183288409704,
31
+ "best_auc": 0.9834103566773315,
32
+ "model_type": "LogisticRegression",
33
+ "input_requirements": "Ver feature_ranges.json para rangos",
34
+ "training_date": "2025-11-28 02:46:41",
35
+ "best_model_selected": "Regresi\u00f3n Log\u00edstica",
36
+ "comparison_results": [
37
+ {
38
+ "Modelo": "Regresi\u00f3n Log\u00edstica",
39
+ "Accuracy": 0.9892183288409704,
40
+ "AUC": 0.9834103566773315,
41
+ "Precision": 0.9911262798634812,
42
+ "Recall": 0.9979381443298969,
43
+ "F1-Score": 0.9945205479452055
44
+ },
45
+ {
46
+ "Modelo": "Random Forest",
47
+ "Accuracy": 0.9824797843665768,
48
+ "AUC": 0.9603863016945137,
49
+ "Precision": 0.983750846310088,
50
+ "Recall": 0.9986254295532646,
51
+ "F1-Score": 0.9911323328785812
52
+ },
53
+ {
54
+ "Modelo": "SVM",
55
+ "Accuracy": 0.9811320754716981,
56
+ "AUC": 0.9674842990875696,
57
+ "Precision": 0.9811193526635199,
58
+ "Recall": 1.0,
59
+ "F1-Score": 0.9904697072838666
60
+ },
61
+ {
62
+ "Modelo": "\u00c1rbol de Decisi\u00f3n",
63
+ "Accuracy": 0.9743935309973046,
64
+ "AUC": 0.8437848086266146,
65
+ "Precision": 0.981645139360979,
66
+ "Recall": 0.9924398625429554,
67
+ "F1-Score": 0.987012987012987
68
+ }
69
+ ],
70
+ "evaluation_metrics": {
71
+ "accuracy": 0.9892183288409704,
72
+ "auc": 0.9834103566773315,
73
+ "precision": 0.9911262798634812,
74
+ "recall": 0.9979381443298969,
75
+ "f1_score": 0.9945205479452055
76
+ }
77
+ }
ufc_scaler.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:76e30ff703ff64e759019a17f72b06531b6e6c1fb300026cefceb1f668edfca8
3
+ size 1050