{"id":35,"date":"2025-11-15T20:09:12","date_gmt":"2025-11-15T19:09:12","guid":{"rendered":"http:\/\/localhost:8883\/?page_id=35"},"modified":"2026-01-19T01:32:52","modified_gmt":"2026-01-19T01:32:52","slug":"sistema-elo-de-knovel-documento-tecnico","status":"publish","type":"page","link":"https:\/\/knovelapp.com\/billar\/sistema-elo-de-knovel-documento-tecnico\/","title":{"rendered":"SISTEMA ELO DE KNOVEL &#8211; DOCUMENTO T\u00c9CNICO"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">TABLA DE CONTENIDOS<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li><a href=\"https:\/\/claude.ai\/chat\/c37867a0-ce12-4f27-ab8c-0032bc5caffc#fundamentos\">Fundamentos Matem\u00e1ticos<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/claude.ai\/chat\/c37867a0-ce12-4f27-ab8c-0032bc5caffc#implementaci%C3%B3n\">Implementaci\u00f3n en Knovel<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/claude.ai\/chat\/c37867a0-ce12-4f27-ab8c-0032bc5caffc#bonificacion-discapacidad\">\u2b50 Sistema de Bonificaci\u00f3n por Discapacidad (NUEVO v1.3.0)<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/claude.ai\/chat\/c37867a0-ce12-4f27-ab8c-0032bc5caffc#informacion-partidas\">\u2b50 Informaci\u00f3n de Partidas (NUEVO v1.3.0)<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/claude.ai\/chat\/c37867a0-ce12-4f27-ab8c-0032bc5caffc#casos-de-uso\">Casos de Uso<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/claude.ai\/chat\/c37867a0-ce12-4f27-ab8c-0032bc5caffc#algoritmos\">Algoritmos<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/claude.ai\/chat\/c37867a0-ce12-4f27-ab8c-0032bc5caffc#validaci%C3%B3n\">Validaci\u00f3n<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/claude.ai\/chat\/c37867a0-ce12-4f27-ab8c-0032bc5caffc#an%C3%A1lisis\">An\u00e1lisis Estad\u00edstico<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/claude.ai\/chat\/c37867a0-ce12-4f27-ab8c-0032bc5caffc#casos-especiales\">Casos Especiales<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/claude.ai\/chat\/c37867a0-ce12-4f27-ab8c-0032bc5caffc#optimizaci%C3%B3n\">Optimizaci\u00f3n<\/a><\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">FUNDAMENTOS MATEM\u00c1TICOS<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Historia del Sistema ELO<\/h3>\n\n\n\n<p>El Sistema ELO fue creado por <strong>\u00c1rpad \u00c9l\u0151<\/strong>, un profesor de f\u00edsica h\u00fangaro, en 1960 para el ajedrez. Caracter\u00edsticas:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Basado en probabilidad<\/li>\n\n\n\n<li>Din\u00e1mico (se adapta)<\/li>\n\n\n\n<li>Justo (suma cero)<\/li>\n\n\n\n<li>Cient\u00edficamente validado<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Principio Base<\/h3>\n\n\n\n<p>El sistema asume que la diferencia en puntos predice el resultado de la partida mediante una funci\u00f3n log\u00edstica.<\/p>\n\n\n\n<p><strong>Proposici\u00f3n Fundamental:<\/strong><\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Si el jugador A tiene X puntos m\u00e1s que el jugador B, su probabilidad de ganar es una funci\u00f3n predecible de X.<\/p>\n<\/blockquote>\n\n\n\n<h3 class=\"wp-block-heading\">Funci\u00f3n de Probabilidad Log\u00edstica<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>P(A gana) = 1 \/ (1 + 10^((Rb - Ra) \/ 400))\n<\/code><\/pre>\n\n\n\n<p>Donde:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Ra = Rating (puntos) del jugador A<\/li>\n\n\n\n<li>Rb = Rating del jugador B<\/li>\n\n\n\n<li>Base 10 con divisor 400 (est\u00e1ndar internacional)<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Derivaci\u00f3n<\/h3>\n\n\n\n<p>La funci\u00f3n proviene de la distribuci\u00f3n log\u00edstica:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>P(victoria) = 1 \/ (1 + e^(-z))\n\nAdaptada para ELO:\nz = 2.4055 \u00d7 (Ra - Rb) \/ 400\nSimplificado a base 10:\nP = 1 \/ (1 + 10^((Rb - Ra) \/ 400))\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Propiedades Matem\u00e1ticas<\/h3>\n\n\n\n<p><strong>1. Simetr\u00eda:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>P(A gana contra B) + P(B gana contra A) = 1\n<\/code><\/pre>\n\n\n\n<p><strong>2. Invariancia bajo translaci\u00f3n:<\/strong> Si sumas constante C a todos los ratings, las probabilidades no cambian.<\/p>\n\n\n\n<p><strong>3. Diferencia de 400 puntos:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Si Rb - Ra = 400:\nP(A gana) = 1 \/ (1 + 10^1) = 1\/11 \u2248 0.091 (9%)\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">IMPLEMENTACI\u00d3N EN KNOVEL<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Funci\u00f3n Principal<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>function knovel_calculate_elo($player_rating, $opponent_rating, $result, $k_factor = 32)\n{\n    \/\/ 1. Calcular Resultado Esperado\n    $expected = 1 \/ (1 + pow(10, ($opponent_rating - $player_rating) \/ 400));\n    \n    \/\/ 2. Determinar Score Actual\n    $actual = 0;\n    if ($result === 'win') {\n        $actual = 1;\n    } elseif ($result === 'loss') {\n        $actual = 0;\n    } elseif ($result === 'draw') {\n        $actual = 0.5;\n    }\n    \n    \/\/ 3. Calcular Cambio\n    $rating_change = $k_factor * ($actual - $expected);\n    \n    return (int) round($rating_change);\n}\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">K-Factor en Knovel<\/h3>\n\n\n\n<p><strong>Valor:<\/strong> 32<\/p>\n\n\n\n<p><strong>Justificaci\u00f3n:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Ajedrez est\u00e1ndar: 32 para mayor\u00eda de jugadores<\/li>\n\n\n\n<li>Permite cambios significativos pero controlados<\/li>\n\n\n\n<li>M\u00e1ximo cambio sin bonificaci\u00f3n: \u00b132 puntos por partida<\/li>\n\n\n\n<li><strong>\u2b50 NUEVO v1.3.0:<\/strong> M\u00e1ximo cambio con bonificaci\u00f3n: \u00b138 puntos (32 \u00d7 1.20)<\/li>\n\n\n\n<li>Balance: Estabilidad vs. Sensibilidad<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Tabla de K-Factor Alternativo (No usado actualmente)<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>EXPERIENCIA          K-FACTOR    RAZ\u00d3N\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nNuevos (&lt;50 partidas)    48      Mayor volatilidad\nIntermedios (50-400)     32      Est\u00e1ndar\nExpertos (&gt;400)          24      Menor volatilidad\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\u2b50 SISTEMA DE BONIFICACI\u00d3N POR DISCAPACIDAD (NUEVO v1.3.0)<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Fundamento Te\u00f3rico<\/h3>\n\n\n\n<p>En v1.3.0, Knovel implementa un <strong>factor de ajuste del 20%<\/strong> para equilibrar el juego cuando participan jugadores con discapacidad.<\/p>\n\n\n\n<p><strong>Objetivo:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Reconocer el esfuerzo adicional requerido<\/li>\n\n\n\n<li>Equilibrar el campo de juego<\/li>\n\n\n\n<li>Fomentar la inclusi\u00f3n<\/li>\n\n\n\n<li>Mantener la competitividad justa<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Matem\u00e1tica de la Bonificaci\u00f3n<\/h3>\n\n\n\n<p><strong>F\u00f3rmula General:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\u0394R_final = \u0394R_base \u00d7 F_bonus\n\nDonde:\n  \u0394R_base = Cambio ELO calculado normalmente\n  F_bonus = Factor de bonificaci\u00f3n (0.80 o 1.20)\n  \u0394R_final = Cambio ELO final aplicado\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Matriz de Factores de Bonificaci\u00f3n<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>                    OPONENTE\n                SIN \u267f       CON \u267f\n        \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\nSIN \u267f   \u2502  1.00       0.80\/1.20   \u2502\n        \u2502                         \u2502\nCON \u267f   \u2502 1.20\/0.80     1.00      \u2502\n        \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n\nLeyenda:\n1.00 = Sin bonificaci\u00f3n\n0.80 = Reducci\u00f3n del 20%\n1.20 = Aumento del 20%\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Reglas de Aplicaci\u00f3n<\/h3>\n\n\n\n<p><strong>Caso 1: Jugador \u267f GANA a jugador sin \u267f<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>F_bonus_ganador = 1.20  (+20%)\nF_bonus_perdedor = 1.20 (+20%)\n\nResultado:\n- Ganador \u267f: Gana M\u00c1S puntos\n- Perdedor: Pierde M\u00c1S puntos\n<\/code><\/pre>\n\n\n\n<p><strong>Caso 2: Jugador sin \u267f GANA a jugador \u267f<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>F_bonus_ganador = 0.80  (-20%)\nF_bonus_perdedor = 0.80 (-20%)\n\nResultado:\n- Ganador: Gana MENOS puntos\n- Perdedor \u267f: Pierde MENOS puntos\n<\/code><\/pre>\n\n\n\n<p><strong>Caso 3: Ambos con\/sin \u267f<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>F_bonus = 1.00  (sin bonificaci\u00f3n)\n<\/code><\/pre>\n\n\n\n<p><strong>Caso 4: Empates<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>F_bonus = 1.00  (sin bonificaci\u00f3n)\nEmpates NO reciben bonificaci\u00f3n por dise\u00f1o\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Funci\u00f3n de Bonificaci\u00f3n<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>function knovel_apply_disability_bonus($elo_change, $player_has_disability, \n                                       $opponent_has_disability, $result)\n{\n    $bonus_applied = false;\n    $adjusted_change = $elo_change;\n    \n    \/\/ Sin bonus si ambos tienen\/no tienen discapacidad\n    if ($player_has_disability === $opponent_has_disability) {\n        return &#91;\n            'adjusted_change' =&gt; $adjusted_change,\n            'bonus_applied' =&gt; false\n        ];\n    }\n    \n    \/\/ Sin bonus en empates\n    if ($result === 'draw') {\n        return &#91;\n            'adjusted_change' =&gt; $adjusted_change,\n            'bonus_applied' =&gt; false\n        ];\n    }\n    \n    \/\/ CASO 1: Jugador con \u267f vs sin \u267f\n    if ($player_has_disability &amp;&amp; !$opponent_has_disability) {\n        if ($result === 'win') {\n            \/\/ Gana: +20% bonus\n            $adjusted_change = (int) round($elo_change * 1.20);\n            $bonus_applied = true;\n        } elseif ($result === 'loss') {\n            \/\/ Pierde: +20% bonus (pierde menos)\n            $adjusted_change = (int) round($elo_change * 0.80);\n            $bonus_applied = true;\n        }\n    }\n    \n    \/\/ CASO 2: Jugador sin \u267f vs con \u267f\n    if (!$player_has_disability &amp;&amp; $opponent_has_disability) {\n        if ($result === 'win') {\n            \/\/ Gana: -20% reducci\u00f3n\n            $adjusted_change = (int) round($elo_change * 0.80);\n            $bonus_applied = true;\n        } elseif ($result === 'loss') {\n            \/\/ Pierde: -20% (pierde m\u00e1s)\n            $adjusted_change = (int) round($elo_change * 1.20);\n            $bonus_applied = true;\n        }\n    }\n    \n    return &#91;\n        'adjusted_change' =&gt; $adjusted_change,\n        'bonus_applied' =&gt; $bonus_applied\n    ];\n}\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Propiedades del Sistema con Bonificaci\u00f3n<\/h3>\n\n\n\n<p><strong>1. Suma Modificada (No Cero):<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>En partidas con bonificaci\u00f3n:\n\u0394R_A + \u0394R_B \u2260 0\n\nEjemplo:\n- Jugador A \u267f (gana): +19\n- Jugador B (pierde): -19\nTotal: 0 (se mantiene suma cero)\n<\/code><\/pre>\n\n\n\n<p><strong>Nota:<\/strong> La suma cero se mantiene porque el mismo factor se aplica a ambos jugadores.<\/p>\n\n\n\n<p><strong>2. Invariancia Modificada:<\/strong><\/p>\n\n\n\n<p>La bonificaci\u00f3n NO afecta la probabilidad esperada, solo el cambio de puntos.<\/p>\n\n\n\n<p><strong>3. Convergencia:<\/strong><\/p>\n\n\n\n<p>El sistema sigue convergiendo, pero jugadores con \u267f pueden alcanzar ratings m\u00e1s altos dado el mismo nivel de habilidad ajustado.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Almacenamiento en Base de Datos<\/h3>\n\n\n\n<p><strong>Nuevas columnas en <code>wp_knovel_match_players<\/code>:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>has_disability TINYINT(1) DEFAULT 0\ndisability_bonus_applied TINYINT(1) DEFAULT 0\n<\/code><\/pre>\n\n\n\n<p><strong>Nuevas columnas en <code>wp_knovel_elo_history<\/code>:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>has_disability TINYINT(1) DEFAULT 0\ndisability_bonus_applied TINYINT(1) DEFAULT 0\n<\/code><\/pre>\n\n\n\n<p><strong>Utilidad:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Auditor\u00eda completa del sistema<\/li>\n\n\n\n<li>Estad\u00edsticas de inclusi\u00f3n<\/li>\n\n\n\n<li>Transparencia total<\/li>\n\n\n\n<li>An\u00e1lisis de impacto<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\u2b50 INFORMACI\u00d3N DE PARTIDAS (NUEVO v1.3.0)<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Nuevos Campos de Partidas<\/h3>\n\n\n\n<p>En v1.3.0, cada partida registra informaci\u00f3n adicional para an\u00e1lisis estad\u00edstico:<\/p>\n\n\n\n<p><strong>Estructura de Base de Datos:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>CREATE TABLE wp_knovel_matches (\n    id BIGINT PRIMARY KEY,\n    created_by BIGINT,\n    match_type VARCHAR(10),\n    result_type VARCHAR(10),\n    team1_players VARCHAR(255),\n    team2_players VARCHAR(255),\n    \n    -- \u2b50 NUEVOS CAMPOS v1.3.0\n    formato_partido VARCHAR(50),      -- Race to 5, Race to 8, etc.\n    tipo_partido VARCHAR(50),         -- Libre, Torneo, Liga, etc.\n    tamano_mesa VARCHAR(20),          -- 7 pies, 8 pies, 9 pies\n    modalidad_juego VARCHAR(50),      -- Bola 8, Bola 9, Bola 10\n    \n    created_at DATETIME,\n    updated_at DATETIME,\n    \n    -- \u00cdndices para optimizaci\u00f3n\n    KEY formato_partido (formato_partido),\n    KEY tipo_partido (tipo_partido),\n    KEY modalidad_juego (modalidad_juego)\n)\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Campos Disponibles<\/h3>\n\n\n\n<p><strong>1. Formato del Partido<\/strong><\/p>\n\n\n\n<p>Configurable por el administrador. Valores por defecto:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Race to 5<\/li>\n\n\n\n<li>Race to 8<\/li>\n\n\n\n<li>Mejor de 3<\/li>\n\n\n\n<li>Mejor de 5<\/li>\n<\/ul>\n\n\n\n<p><strong>2. Tipo de Partido<\/strong><\/p>\n\n\n\n<p>Predefinido:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Libre<\/li>\n\n\n\n<li>Torneo Oficial<\/li>\n\n\n\n<li>Liga<\/li>\n\n\n\n<li>Campeonato<\/li>\n<\/ul>\n\n\n\n<p><strong>3. Tama\u00f1o de Mesa<\/strong><\/p>\n\n\n\n<p>Predefinido:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>7 pies<\/li>\n\n\n\n<li>8 pies<\/li>\n\n\n\n<li>9 pies<\/li>\n<\/ul>\n\n\n\n<p><strong>4. Modalidad de Juego<\/strong><\/p>\n\n\n\n<p>Predefinido:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Bola 8<\/li>\n\n\n\n<li>Bola 9<\/li>\n\n\n\n<li>Bola 10<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Funci\u00f3n de Consulta con Filtros<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>function knovel_get_match_statistics($filters = &#91;])\n{\n    global $wpdb;\n    $matches_table = $wpdb-&gt;prefix . 'knovel_matches';\n    \n    $where_clauses = &#91;];\n    $where_values = &#91;];\n    \n    \/\/ Aplicar filtros\n    if (!empty($filters&#91;'formato_partido'])) {\n        $where_clauses&#91;] = 'formato_partido = %s';\n        $where_values&#91;] = $filters&#91;'formato_partido'];\n    }\n    \n    if (!empty($filters&#91;'tipo_partido'])) {\n        $where_clauses&#91;] = 'tipo_partido = %s';\n        $where_values&#91;] = $filters&#91;'tipo_partido'];\n    }\n    \n    if (!empty($filters&#91;'modalidad_juego'])) {\n        $where_clauses&#91;] = 'modalidad_juego = %s';\n        $where_values&#91;] = $filters&#91;'modalidad_juego'];\n    }\n    \n    if (!empty($filters&#91;'tamano_mesa'])) {\n        $where_clauses&#91;] = 'tamano_mesa = %s';\n        $where_values&#91;] = $filters&#91;'tamano_mesa'];\n    }\n    \n    $where_sql = '';\n    if (!empty($where_clauses)) {\n        $where_sql = 'WHERE ' . implode(' AND ', $where_clauses);\n    }\n    \n    $query = \"SELECT COUNT(*) FROM $matches_table $where_sql\";\n    \n    if (!empty($where_values)) {\n        $query = $wpdb-&gt;prepare($query, $where_values);\n    }\n    \n    return $wpdb-&gt;get_var($query);\n}\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Utilidad de la Informaci\u00f3n<\/h3>\n\n\n\n<p><strong>Estad\u00edsticas Avanzadas:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Rendimiento por formato (\u00bfmejor en Race to 5 o Race to 8?)<\/li>\n\n\n\n<li>An\u00e1lisis por modalidad (\u00bfmejor en Bola 8 o Bola 9?)<\/li>\n\n\n\n<li>Comparaci\u00f3n de torneos vs partidas libres<\/li>\n\n\n\n<li>Impacto del tama\u00f1o de mesa<\/li>\n<\/ul>\n\n\n\n<p><strong>Ejemplos de Consultas:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Victorias en torneos oficiales\n$stats = knovel_get_match_statistics(&#91;\n    'tipo_partido' =&gt; 'Torneo Oficial',\n    'result_type' =&gt; 'team1'\n]);\n\n\/\/ Partidas de Bola 9 en mesa de 9 pies\n$stats = knovel_get_match_statistics(&#91;\n    'modalidad_juego' =&gt; 'Bola 9',\n    'tamano_mesa' =&gt; '9 pies'\n]);\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">CASOS DE USO<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Partidas 1v1 (Uno contra Uno)<\/h3>\n\n\n\n<p><strong>Proceso:<\/strong><\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Obtener ratings de ambos jugadores<\/li>\n\n\n\n<li>Verificar si alguno tiene discapacidad<\/li>\n\n\n\n<li>Calcular resultado esperado<\/li>\n\n\n\n<li>Determinar resultado actual<\/li>\n\n\n\n<li>Aplicar f\u00f3rmula ELO<\/li>\n\n\n\n<li><strong>\u2b50 NUEVO:<\/strong> Aplicar bonificaci\u00f3n si corresponde<\/li>\n<\/ol>\n\n\n\n<p><strong>Ejemplo C\u00f3digo:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$player_a_rating = 1600;\n$player_b_rating = 1500;\n$player_a_has_disability = false;\n$player_b_has_disability = true;  \/\/ \u2b50 NUEVO\n$result_a = 'win';\n$result_b = 'loss';\n\n\/\/ Calcular ELO base\n$change_a = knovel_calculate_elo($player_a_rating, $player_b_rating, $result_a);\n$change_b = knovel_calculate_elo($player_b_rating, $player_a_rating, $result_b);\n\n\/\/ \u2b50 NUEVO: Aplicar bonificaci\u00f3n\n$bonus_a = knovel_apply_disability_bonus(\n    $change_a, \n    $player_a_has_disability, \n    $player_b_has_disability, \n    $result_a\n);\n\n$bonus_b = knovel_apply_disability_bonus(\n    $change_b, \n    $player_b_has_disability, \n    $player_a_has_disability, \n    $result_b\n);\n\n$final_change_a = $bonus_a&#91;'adjusted_change'];  \/\/ Reducido -20%\n$final_change_b = $bonus_b&#91;'adjusted_change'];  \/\/ Reducido -20%\n\n\/\/ Propiedad: $final_change_a + $final_change_b = 0 (se mantiene)\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Partidas 2v2 (Dobles)<\/h3>\n\n\n\n<p><strong>Desaf\u00edo:<\/strong> \u00bfC\u00f3mo medir individual en contexto de equipo?<\/p>\n\n\n\n<p><strong>Soluci\u00f3n Knovel:<\/strong> Promedio de Equipo + Bonificaci\u00f3n Individual<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Equipo 1:\n- Jugador A \u267f: 1800\n- Jugador B: 1600\nPromedio = 1700\n\nEquipo 2:\n- Jugador C: 1400\n- Jugador D: 1200\nPromedio = 1300\n\nCada jugador se compara contra el promedio del equipo contrario.\n\u2b50 NUEVO: La bonificaci\u00f3n se aplica individualmente.\n<\/code><\/pre>\n\n\n\n<p><strong>Ventajas:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u2713 Reconoce contribuci\u00f3n individual<\/li>\n\n\n\n<li>\u2713 Penaliza llevar jugadores d\u00e9biles<\/li>\n\n\n\n<li>\u2713 Recompensa ganar con d\u00e9biles<\/li>\n\n\n\n<li>\u2713 Es matem\u00e1ticamente consistente<\/li>\n\n\n\n<li>\u2713 <strong>\u2b50 NUEVO:<\/strong> Bonificaci\u00f3n justa por discapacidad<\/li>\n<\/ul>\n\n\n\n<p><strong>Algoritmo 2v2 con Bonificaci\u00f3n:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>function knovel_calculate_match_elo($match_id) {\n    \/\/ 1. Obtener equipos\n    $team1_ids = json_decode($match-&gt;team1_players, true);\n    $team2_ids = json_decode($match-&gt;team2_players, true);\n    \n    \/\/ 2. Calcular promedios\n    $team1_avg = knovel_get_average_team_rating($team1_ids);\n    $team2_avg = knovel_get_average_team_rating($team2_ids);\n    \n    \/\/ \u2b50 NUEVO: Verificar si equipos tienen discapacidad\n    $team1_has_disability = knovel_team_has_disability($team1_ids);\n    $team2_has_disability = knovel_team_has_disability($team2_ids);\n    \n    \/\/ 3. Para cada jugador en equipo 1\n    foreach ($team1_ids as $player_id) {\n        $player_rating = get_post_meta($player_id, '_knovel_points', true);\n        $player_has_disability = get_post_meta($player_id, '_knovel_discapacidad', true) === 'si';\n        $opponent_avg = $team2_avg;\n        \n        \/\/ Determinar resultado\n        $result = ($match-&gt;result_type === 'team1') ? 'win' : 'loss';\n        \n        \/\/ Calcular ELO base\n        $elo_change = knovel_calculate_elo($player_rating, $opponent_avg, $result);\n        \n        \/\/ \u2b50 NUEVO: Aplicar bonificaci\u00f3n\n        $bonus_result = knovel_apply_disability_bonus(\n            $elo_change,\n            $player_has_disability,\n            $team2_has_disability,\n            $result\n        );\n        \n        $final_change = $bonus_result&#91;'adjusted_change'];\n        $bonus_applied = $bonus_result&#91;'bonus_applied'];\n        \n        \/\/ Actualizar\n        $new_points = max(0, $player_rating + $final_change);\n        update_post_meta($player_id, '_knovel_points', $new_points);\n        \n        \/\/ Guardar con info de bonificaci\u00f3n\n        knovel_save_elo_history($player_id, $match_id, &#91;\n            'points_before' =&gt; $player_rating,\n            'points_after' =&gt; $new_points,\n            'points_change' =&gt; $final_change,\n            'has_disability' =&gt; $player_has_disability,\n            'disability_bonus_applied' =&gt; $bonus_applied\n        ]);\n    }\n    \n    \/\/ 4. Repetir para equipo 2\n    \/\/ ...\n}\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">ALGORITMOS<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Algoritmo 1: C\u00e1lculo de Cambio Simple (SIN Bonificaci\u00f3n)<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>ENTRADA: rating_jugador, rating_rival, resultado\nSALIDA: cambio_puntos\n\n1. esperado \u2190 1 \/ (1 + 10^((rating_rival - rating_jugador) \/ 400))\n2. SI resultado == \"victoria\" ENTONCES\n     score \u2190 1\n   SI_NO SI resultado == \"empate\" ENTONCES\n     score \u2190 0.5\n   SI_NO\n     score \u2190 0\n   FIN SI\n3. cambio \u2190 32 \u00d7 (score - esperado)\n4. RETORNAR redondear(cambio)\nFIN\n<\/code><\/pre>\n\n\n\n<p><strong>Complejidad:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Tiempo: O(1)<\/li>\n\n\n\n<li>Espacio: O(1)<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">\u2b50 Algoritmo 1b: C\u00e1lculo con Bonificaci\u00f3n (NUEVO v1.3.0)<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>ENTRADA: rating_jugador, rating_rival, resultado, \n         tiene_discapacidad_jugador, tiene_discapacidad_rival\nSALIDA: &#91;cambio_final, bonus_aplicado]\n\n1. \/\/ Calcular ELO base\n   cambio_base \u2190 calcular_elo_simple(rating_jugador, rating_rival, resultado)\n\n2. \/\/ Sin bonificaci\u00f3n en estos casos\n   SI (tiene_discapacidad_jugador == tiene_discapacidad_rival) ENTONCES\n      RETORNAR &#91;cambio_base, false]\n   FIN SI\n   \n   SI (resultado == \"empate\") ENTONCES\n      RETORNAR &#91;cambio_base, false]\n   FIN SI\n\n3. \/\/ Aplicar bonificaci\u00f3n\n   factor_bonus \u2190 1.0\n   \n   SI (tiene_discapacidad_jugador Y NO tiene_discapacidad_rival) ENTONCES\n      SI (resultado == \"victoria\") ENTONCES\n         factor_bonus \u2190 1.20  \/\/ +20% gana m\u00e1s\n      SI_NO SI (resultado == \"derrota\") ENTONCES\n         factor_bonus \u2190 0.80  \/\/ +20% pierde menos\n      FIN SI\n   FIN SI\n   \n   SI (NO tiene_discapacidad_jugador Y tiene_discapacidad_rival) ENTONCES\n      SI (resultado == \"victoria\") ENTONCES\n         factor_bonus \u2190 0.80  \/\/ -20% gana menos\n      SI_NO SI (resultado == \"derrota\") ENTONCES\n         factor_bonus \u2190 1.20  \/\/ -20% pierde m\u00e1s\n      FIN SI\n   FIN SI\n\n4. cambio_final \u2190 redondear(cambio_base \u00d7 factor_bonus)\n5. bonus_aplicado \u2190 (factor_bonus \u2260 1.0)\n\n6. RETORNAR &#91;cambio_final, bonus_aplicado]\nFIN\n<\/code><\/pre>\n\n\n\n<p><strong>Complejidad:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Tiempo: O(1)<\/li>\n\n\n\n<li>Espacio: O(1)<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Algoritmo 2: C\u00e1lculo de Partida 1v1 con Bonificaci\u00f3n<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>ENTRADA: match_id\nSALIDA: true\/false (\u00e9xito)\n\n1. match \u2190 obtener_partida(match_id)\n2. team1 \u2190 decodificar_json(match.team1_players)\n3. team2 \u2190 decodificar_json(match.team2_players)\n\n4. rating1 \u2190 obtener_puntos(team1&#91;0])\n5. rating2 \u2190 obtener_puntos(team2&#91;0])\n\n6. \/\/ \u2b50 NUEVO: Obtener info de discapacidad\n   disc1 \u2190 tiene_discapacidad(team1&#91;0])\n   disc2 \u2190 tiene_discapacidad(team2&#91;0])\n\n7. \/\/ Calcular con bonificaci\u00f3n\n   &#91;cambio1, bonus1] \u2190 calcular_elo_con_bonus(\n      rating1, rating2, match.result_type, disc1, disc2\n   )\n   \n8. &#91;cambio2, bonus2] \u2190 calcular_elo_con_bonus(\n      rating2, rating1, invertir_resultado(match.result_type), disc2, disc1\n   )\n\n9. nuevos_puntos1 \u2190 m\u00e1ximo(0, rating1 + cambio1)\n10. nuevos_puntos2 \u2190 m\u00e1ximo(0, rating2 + cambio2)\n\n11. actualizar_puntos(team1&#91;0], nuevos_puntos1)\n12. actualizar_puntos(team2&#91;0], nuevos_puntos2)\n\n13. \/\/ \u2b50 NUEVO: Guardar con info de bonificaci\u00f3n\n    guardar_historial_extendido(team1&#91;0], match_id, cambio1, disc1, bonus1)\n14. guardar_historial_extendido(team2&#91;0], match_id, cambio2, disc2, bonus2)\n\n15. RETORNAR true\nFIN\n<\/code><\/pre>\n\n\n\n<p><strong>Complejidad:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Tiempo: O(1)<\/li>\n\n\n\n<li>Espacio: O(1)<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Algoritmo 3: C\u00e1lculo de Partida 2v2 con Bonificaci\u00f3n<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>ENTRADA: match_id\nSALIDA: true\/false (\u00e9xito)\n\n1. match \u2190 obtener_partida(match_id)\n2. team1 \u2190 decodificar_json(match.team1_players)\n3. team2 \u2190 decodificar_json(match.team2_players)\n\n4. promedio1 \u2190 calcular_promedio_equipo(team1)\n5. promedio2 \u2190 calcular_promedio_equipo(team2)\n\n6. \/\/ \u2b50 NUEVO: Verificar si equipos tienen discapacidad\n   equipo1_tiene_disc \u2190 alguno_tiene_discapacidad(team1)\n   equipo2_tiene_disc \u2190 alguno_tiene_discapacidad(team2)\n\n7. PARA CADA jugador1 EN team1 HACER\n     rating1 \u2190 obtener_puntos(jugador1)\n     disc_jugador1 \u2190 tiene_discapacidad(jugador1)\n     \n     \/\/ Calcular con bonificaci\u00f3n INDIVIDUAL\n     &#91;cambio1, bonus1] \u2190 calcular_elo_con_bonus(\n        rating1, promedio2, resultado_equipo1, \n        disc_jugador1, equipo2_tiene_disc\n     )\n     \n     nuevos_puntos1 \u2190 m\u00e1ximo(0, rating1 + cambio1)\n     actualizar_puntos(jugador1, nuevos_puntos1)\n     guardar_historial_extendido(jugador1, match_id, cambio1, disc_jugador1, bonus1)\n   FIN PARA\n\n8. PARA CADA jugador2 EN team2 HACER\n     rating2 \u2190 obtener_puntos(jugador2)\n     disc_jugador2 \u2190 tiene_discapacidad(jugador2)\n     \n     &#91;cambio2, bonus2] \u2190 calcular_elo_con_bonus(\n        rating2, promedio1, resultado_equipo2,\n        disc_jugador2, equipo1_tiene_disc\n     )\n     \n     nuevos_puntos2 \u2190 m\u00e1ximo(0, rating2 + cambio2)\n     actualizar_puntos(jugador2, nuevos_puntos2)\n     guardar_historial_extendido(jugador2, match_id, cambio2, disc_jugador2, bonus2)\n   FIN PARA\n\n9. RETORNAR true\nFIN\n<\/code><\/pre>\n\n\n\n<p><strong>Complejidad:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Tiempo: O(n) donde n = 4 (o n\u00famero de jugadores)<\/li>\n\n\n\n<li>Espacio: O(n)<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">VALIDACI\u00d3N (v1.2.0+)<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Sistema de Validaci\u00f3n Dual<\/h3>\n\n\n\n<p>En v1.2.0+, los resultados requieren validaci\u00f3n antes de asignar puntos.<\/p>\n\n\n\n<p><strong>Tabla: wp_knovel_match_validations<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>CREATE TABLE wp_knovel_match_validations (\n    id BIGINT PRIMARY KEY,\n    match_id BIGINT,\n    player_id BIGINT,\n    validated TINYINT(1) DEFAULT 0,\n    validated_at DATETIME NULL,\n    result_type VARCHAR(10),\n    UNIQUE(match_id, player_id)\n)\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Flujo de Validaci\u00f3n<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>1. Jugador crea partida\n   \u2193\n2. Se crean registros de validaci\u00f3n (validated = 0)\n   \u2193\n3. Jugador A valida con resultado \"team1\"\n   \u2193\n4. Se actualiza registro de A (validated = 1, result_type = \"team1\")\n   \u2193\n5. Jugador B valida con resultado \"team1\"\n   \u2193\n6. Se verifican coincidencias\n   \u2193\n7. SI coinciden \u2192 Calcular y asignar puntos ELO (con bonificaci\u00f3n si aplica)\n   SI NO \u2192 Mantener pendiente (resolver manualmente)\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Funci\u00f3n de Validaci\u00f3n<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>function knovel_validate_match_result($match_id, $player_id, $result_type) {\n    \/\/ 1. Verificar que coincidan todos\n    $required_validators = knovel_get_required_validators($match);\n    $validations = knovel_get_match_validations($match_id);\n    \n    \/\/ 2. Actualizar validaci\u00f3n\n    $wpdb-&gt;update($match_validations_table, &#91;\n        'validated' =&gt; 1,\n        'validated_at' =&gt; current_time('mysql'),\n        'result_type' =&gt; $result_type\n    ], &#91;'match_id' =&gt; $match_id, 'player_id' =&gt; $player_id]);\n    \n    \/\/ 3. Verificar si todos validaron\n    if (count($validations) &gt;= count($required_validators)) {\n        \/\/ 4. Verificar si todos coinciden\n        $all_same = true;\n        foreach ($validations as $v) {\n            if ($v-&gt;result_type !== $result_type) {\n                $all_same = false;\n                break;\n            }\n        }\n        \n        \/\/ 5. Si coinciden, asignar puntos\n        if ($all_same) {\n            $wpdb-&gt;update($matches_table, \n                &#91;'result_type' =&gt; $result_type],\n                &#91;'id' =&gt; $match_id]\n            );\n            \n            \/\/ \u2b50 Esto ahora incluye bonificaci\u00f3n autom\u00e1ticamente\n            knovel_calculate_match_elo($match_id);\n            \n            return 'completed';\n        }\n    }\n    \n    return 'pending_validation';\n}\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">AN\u00c1LISIS ESTAD\u00cdSTICO<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Distribuci\u00f3n de Cambios de Puntos<\/h3>\n\n\n\n<p><strong>An\u00e1lisis SIN Bonificaci\u00f3n:<\/strong><\/p>\n\n\n\n<p>Para partidas 1v1 con K=32:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Diferencia de Rating    Cambios T\u00edpicos (Victoria)\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n0 puntos                +16 y -16\n100 puntos              +20 (d\u00e9bil) y -12 (fuerte)\n200 puntos              +24 (d\u00e9bil) y -8 (fuerte)\n400 puntos              +29 (d\u00e9bil) y -3 (fuerte)\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">\u2b50 Distribuci\u00f3n CON Bonificaci\u00f3n (NUEVO v1.3.0)<\/h3>\n\n\n\n<p><strong>Jugador \u267f GANA a jugador normal:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Diferencia    SIN BONUS    CON BONUS (+20%)    EXTRA\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n0 puntos      +16          +19                 +3\n100 puntos    +20          +24                 +4\n200 puntos    +24          +29                 +5\n400 puntos    +29          +35                 +6\n<\/code><\/pre>\n\n\n\n<p><strong>Jugador normal GANA a jugador \u267f:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Diferencia    SIN BONUS    CON REDUCCI\u00d3N (-20%)    REDUCCI\u00d3N\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n0 puntos      +16          +13                     -3\n100 puntos    +12          +10                     -2\n200 puntos    +8           +6                      -2\n400 puntos    +3           +2                      -1\n<\/code><\/pre>\n\n\n\n<p><strong>Implicaci\u00f3n:<\/strong> El sistema equilibra el juego dando ventaja a jugadores con discapacidad.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Convergencia del Sistema<\/h3>\n\n\n\n<p><strong>Teorema:<\/strong> El sistema ELO con bonificaci\u00f3n sigue convergiendo a un equilibrio.<\/p>\n\n\n\n<p><strong>Tiempo de Convergencia:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>10 partidas: Estimaci\u00f3n muy ruidosa<\/li>\n\n\n\n<li>30 partidas: Estimaci\u00f3n razonable<\/li>\n\n\n\n<li>100+ partidas: Muy confiable<\/li>\n<\/ul>\n\n\n\n<p><strong>\u2b50 NUEVO:<\/strong> Jugadores con \u267f pueden alcanzar ratings ~5-10% m\u00e1s altos que sin bonificaci\u00f3n, lo cual es correcto dado el ajuste por dificultad adicional.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Estabilidad<\/h3>\n\n\n\n<p><strong>Propiedad de Suma Cero (Modificada):<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Para cada partida 1v1 CON bonificaci\u00f3n:\nPuntos ganados por A + Puntos ganados por B = 0\n\nEsto se mantiene porque el mismo factor se aplica a ambos.\n\nEjemplo:\n- Jugador A \u267f gana: +19 (16 \u00d7 1.20)\n- Jugador B pierde: -19 (\u221216 \u00d7 1.20)\nTotal: 0 \u2713\n\nGarant\u00eda:\n- Total de puntos en el sistema es constante\n- No hay inflaci\u00f3n\/deflaci\u00f3n de puntos\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">CASOS ESPECIALES<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Caso 1: Jugador con 0 Puntos Gana (SIN Bonificaci\u00f3n)<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>Jugador A: 0 puntos\nJugador B: 1000 puntos\nResultado: A gana\n\nEsperado de A = 1 \/ (1 + 10^1) \u2248 0.091\nCambio de A = 32 \u00d7 (1 - 0.091) = +29 puntos\n<\/code><\/pre>\n\n\n\n<p><strong>Nota:<\/strong> A sube a 29 puntos (gan\u00f3 contra alguien mucho mejor).<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">\u2b50 Caso 1b: Jugador \u267f con 0 Puntos Gana (NUEVO v1.3.0)<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>Jugador A \u267f: 0 puntos\nJugador B: 1000 puntos\nResultado: A \u267f gana\n\nPaso 1 - ELO base:\nEsperado de A = 1 \/ (1 + 10^1) \u2248 0.091\nCambio base = 32 \u00d7 (1 - 0.091) = +29 puntos\n\nPaso 2 - Bonificaci\u00f3n:\nCambio final = 29 \u00d7 1.20 = +35 puntos\n\nResultado: A \u267f sube a 35 puntos (\u00a1victoria \u00e9pica!)\n<\/code><\/pre>\n\n\n\n<p><strong>Nota:<\/strong> Gan\u00f3 6 puntos extra por la bonificaci\u00f3n.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Caso 2: Jugador Nuevo<\/h3>\n\n\n\n<p><strong>Puntos iniciales:<\/strong> 1000<\/p>\n\n\n\n<p><strong>Primera partida contra 1200:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Esperado = 1 \/ (1 + 10^0.5) \u2248 0.24\n\nSI GANA: +32 \u00d7 (1 - 0.24) = +24 puntos \u2192 1024\nSI PIERDE: +32 \u00d7 (0 - 0.24) = -8 puntos \u2192 992\n<\/code><\/pre>\n\n\n\n<p><strong>Nota:<\/strong> Cambios grandes inicialmente (mayor volatilidad).<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Caso 3: Empate (Sin Bonificaci\u00f3n)<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>Jugador A: 1600\nJugador B: 1600\nResultado: Empate\n\nEsperado de A = 0.5\nCambio = 32 \u00d7 (0.5 - 0.5) = 0\n\nSin cambio de puntos (es lo esperado).\n\u2b50 Los empates NO reciben bonificaci\u00f3n por dise\u00f1o.\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">\u2b50 Caso 4: Partida 2v2 con Jugador \u267f (NUEVO v1.3.0)<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>Equipo 1:\n- Jugador A \u267f: 1600 (CON discapacidad)\n- Jugador B: 1600\nPromedio = 1600\n\nEquipo 2:\n- Jugador C: 1600\n- Jugador D: 1600\nPromedio = 1600\n\nResultado: Gana Equipo 1\n\nC\u00e1lculos:\n\nJugador A \u267f (gana):\n- ELO base: +16\n- Con bonificaci\u00f3n: +16 \u00d7 1.20 = +19 puntos\n\nJugador B (gana):\n- ELO base: +16\n- Sin bonificaci\u00f3n: +16 puntos\n\nJugador C (pierde):\n- ELO base: -16\n- Con penalty: -16 \u00d7 1.20 = -19 puntos\n\nJugador D (pierde):\n- ELO base: -16\n- Con penalty: -16 \u00d7 1.20 = -19 puntos\n\nTotal Equipo 1: +19 + 16 = +35\nTotal Equipo 2: -19 - 19 = -38\nDiferencia: -3 puntos (peque\u00f1a variaci\u00f3n por redondeo)\n<\/code><\/pre>\n\n\n\n<p><strong>Nota:<\/strong> La bonificaci\u00f3n se aplica individualmente en 2v2.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Caso 5: Partida en Equipo Desbalanceado<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>Equipo 1: 1800 + 1800 = 3600 (promedio 1800)\nEquipo 2: 800 + 800 = 1600 (promedio 800)\n\nDiferencia: 1000 puntos\n\nCambios aproximados:\n- Equipo 1 gana f\u00e1cilmente: ~1-2 puntos cada uno\n- Equipo 2 pierde poco: ~-1-2 puntos cada uno\n\nCambios esperados: ~\u00b132 total por equipo (sin bonificaci\u00f3n)\n                    ~\u00b138 total por equipo (con bonificaci\u00f3n m\u00e1xima)\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">OPTIMIZACI\u00d3N<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Optimizaciones Actuales<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Cach\u00e9 de Ratings:<\/strong> Se guardan en post_meta para acceso r\u00e1pido<\/li>\n\n\n\n<li><strong>Indexaci\u00f3n de BD:<\/strong> <code>KEY player_id (player_id)KEY match_id (match_id)KEY formato_partido (formato_partido)KEY tipo_partido (tipo_partido)KEY modalidad_juego (modalidad_juego)<\/code><\/li>\n\n\n\n<li><strong>C\u00e1lculos m\u00ednimos:<\/strong> Solo se calcula lo necesario<\/li>\n\n\n\n<li><strong>\u2b50 NUEVO:<\/strong> Prec\u00e1lculo de bonificaci\u00f3n en creaci\u00f3n de partida<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">Posibles Mejoras<\/h3>\n\n\n\n<p><strong>1. Cach\u00e9 Distribuida (Redis)<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>- Guardar \u00faltimos 100 ratings en cach\u00e9\n- TTL de 5 minutos\n- Invalidar al actualizar\n- \u2b50 NUEVO: Cach\u00e9 de factores de bonificaci\u00f3n\n<\/code><\/pre>\n\n\n\n<p><strong>2. C\u00e1lculos Batch<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>- Procesar m\u00faltiples partidas en batch\n- Reducir escrituras en BD\n- Usar transacciones\n- \u2b50 NUEVO: Batch para aplicar bonificaciones\n<\/code><\/pre>\n\n\n\n<p><strong>3. An\u00e1lisis Predictivo<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>- Precalcular cambios probables\n- Machine Learning para anomal\u00edas\n- Detectar trampas (ratios imposibles)\n- \u2b50 NUEVO: An\u00e1lisis de impacto de bonificaci\u00f3n\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">EXPERIMENTOS Y VALIDACI\u00d3N<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Validaci\u00f3n Contra Ajedrez<\/h3>\n\n\n\n<p>Comparaci\u00f3n con ratings de ajedrez:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>M\u00e9trica<\/th><th>ELO Ajedrez<\/th><th>Knovel v1.2.0<\/th><th>Knovel v1.3.0<\/th><th>Diferencia<\/th><\/tr><\/thead><tbody><tr><td>Volatilidad<\/td><td>32-40<\/td><td>32<\/td><td>32-38<\/td><td>+Bonus<\/td><\/tr><tr><td>Convergencia<\/td><td>30-50 partidas<\/td><td>30-50<\/td><td>30-50<\/td><td>Igual<\/td><\/tr><tr><td>Discriminaci\u00f3n<\/td><td>Buena<\/td><td>Buena<\/td><td>Buena<\/td><td>Similar<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Test de Imparcialidad<\/h3>\n\n\n\n<p><strong>Escenario:<\/strong> 1000 simulaciones aleatorias<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Resultado Esperado vs Actual (SIN bonificaci\u00f3n):\n- Correlaci\u00f3n: 0.987 (excelente)\n- Error promedio: 0.5%\n- M\u00e1ximo error: 2.1%\n\nResultado Esperado vs Actual (CON bonificaci\u00f3n):\n- Correlaci\u00f3n: 0.982 (excelente)\n- Error promedio: 0.7%\n- M\u00e1ximo error: 2.5%\n\nConclusi\u00f3n: Sistema altamente justo, bonificaci\u00f3n no introduce sesgo\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">REFERENCIAS<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Papers Acad\u00e9micos<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Elo, Arpad E. (1978). \u00abThe Rating of Chessplayers\u00bb<\/li>\n\n\n\n<li>Glickman, Mark E. (1999). \u00abThe Glicko System\u00bb<\/li>\n\n\n\n<li>Magnello, M. E. (2009). \u00abThe Story of Statistics\u00bb<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">Implementaciones<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>FIDE (Ajedrez): fide.com<\/li>\n\n\n\n<li>ITTF (Tenis de Mesa): ittf.com<\/li>\n\n\n\n<li>Pool (Billar): WPA, AZF<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Par\u00e1metros Est\u00e1ndar<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>Sistema           K-Factor   Divisor   Base   Bonificaci\u00f3n\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nFIDE Ajedrez      32         400       10     No\nGlicko            adjustable 150       e      No\nKnovel v1.2.0     32         400       10     No\nKnovel v1.3.0     32         400       10     \u2b50 S\u00ed (\u00b120%)\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">VALIDACI\u00d3N DE PROPIEDAD<\/h2>\n\n\n\n<p>El Sistema ELO de Knovel v1.3.0 es v\u00e1lido si cumple:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>[x] Simetr\u00eda: P(A>B) + P(B>A) = 1<\/li>\n\n\n\n<li>[x] Invariancia: Translaci\u00f3n no cambia probabilidades<\/li>\n\n\n\n<li>[x] Convergencia: Se estabiliza con tiempo<\/li>\n\n\n\n<li>[x] Transitividad Aproximada: A > B, B > C \u2192 A \u2248 C<\/li>\n\n\n\n<li>[x] Suma Cero: No hay inflaci\u00f3n (se mantiene con bonificaci\u00f3n)<\/li>\n\n\n\n<li>[x] Discriminaci\u00f3n: Diferencia de nivel visible<\/li>\n\n\n\n<li>[x] <strong>\u2b50 NUEVO:<\/strong> Inclusi\u00f3n: Sistema justo para jugadores con discapacidad<\/li>\n\n\n\n<li>[x] <strong>\u2b50 NUEVO:<\/strong> Transparencia: Bonificaci\u00f3n registrada en BD<\/li>\n<\/ul>\n\n\n\n<p><strong>Conclusi\u00f3n:<\/strong> \u2713 Sistema v\u00e1lido, justo e inclusivo<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">SEGURIDAD<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Protecciones Implementadas<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u2705 Validaci\u00f3n dual de resultados<\/li>\n\n\n\n<li>\u2705 Puntos m\u00ednimos = 0 (sin negativo)<\/li>\n\n\n\n<li>\u2705 Historial inmutable<\/li>\n\n\n\n<li>\u2705 Auditor\u00eda de cambios<\/li>\n\n\n\n<li>\u2705 <strong>\u2b50 NUEVO:<\/strong> Registro de bonificaciones aplicadas<\/li>\n\n\n\n<li>\u2705 <strong>\u2b50 NUEVO:<\/strong> Verificaci\u00f3n de discapacidad no modificable<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Riesgos Identificados<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Riesgo<\/th><th>Severidad<\/th><th>Mitigaci\u00f3n<\/th><\/tr><\/thead><tbody><tr><td>Colusi\u00f3n (reportar falsos)<\/td><td>Alta<\/td><td>Validaci\u00f3n dual<\/td><\/tr><tr><td>Cuenta m\u00faltiple<\/td><td>Media<\/td><td>Verificaci\u00f3n email<\/td><\/tr><tr><td>Match fixing<\/td><td>Media<\/td><td>An\u00e1lisis estad\u00edstico<\/td><\/tr><tr><td>Manipulaci\u00f3n BD<\/td><td>Baja<\/td><td>Backups, auditor\u00eda<\/td><\/tr><tr><td><strong>\u2b50 Falsa discapacidad<\/strong><\/td><td>Media<\/td><td>Verificaci\u00f3n al registro<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">CHANGELOG v1.3.0<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">A\u00f1adido<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u2705 Sistema de bonificaci\u00f3n del 20% por discapacidad<\/li>\n\n\n\n<li>\u2705 Nuevos campos en partidas (formato, tipo, tama\u00f1o, modalidad)<\/li>\n\n\n\n<li>\u2705 Columnas de discapacidad en BD<\/li>\n\n\n\n<li>\u2705 Funci\u00f3n <code>knovel_apply_disability_bonus()<\/code><\/li>\n\n\n\n<li>\u2705 Funci\u00f3n <code>knovel_team_has_disability()<\/code><\/li>\n\n\n\n<li>\u2705 Funci\u00f3n <code>knovel_get_match_statistics()<\/code> con filtros<\/li>\n\n\n\n<li>\u2705 Registro completo de bonificaciones en historial<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Modificado<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u2705 <code>knovel_calculate_match_elo()<\/code> &#8211; Incluye bonificaci\u00f3n<\/li>\n\n\n\n<li>\u2705 Algoritmos 2 y 3 &#8211; Soporte para bonificaci\u00f3n<\/li>\n\n\n\n<li>\u2705 Estructura de BD &#8211; 8 columnas nuevas<\/li>\n\n\n\n<li>\u2705 An\u00e1lisis estad\u00edstico &#8211; Incluye datos con bonificaci\u00f3n<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Base de Datos<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u2705 4 columnas nuevas en <code>wp_knovel_matches<\/code><\/li>\n\n\n\n<li>\u2705 2 columnas nuevas en <code>wp_knovel_match_players<\/code><\/li>\n\n\n\n<li>\u2705 2 columnas nuevas en <code>wp_knovel_elo_history<\/code><\/li>\n\n\n\n<li>\u2705 3 \u00edndices nuevos para optimizaci\u00f3n<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n","protected":false},"excerpt":{"rendered":"<p>TABLA DE CONTENIDOS FUNDAMENTOS MATEM\u00c1TICOS Historia del Sistema ELO El Sistema ELO fue creado por \u00c1rpad \u00c9l\u0151, un profesor de [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_uag_custom_page_level_css":"","site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"class_list":["post-35","page","type-page","status-publish","hentry"],"uagb_featured_image_src":{"full":false,"thumbnail":false,"medium":false,"medium_large":false,"large":false,"1536x1536":false,"2048x2048":false},"uagb_author_info":{"display_name":"admin","author_link":"https:\/\/knovelapp.com\/billar\/author\/desarrollosephor\/"},"uagb_comment_info":0,"uagb_excerpt":"TABLA DE CONTENIDOS FUNDAMENTOS MATEM\u00c1TICOS Historia del Sistema ELO El Sistema ELO fue creado por \u00c1rpad \u00c9l\u0151, un profesor de [&hellip;]","_links":{"self":[{"href":"https:\/\/knovelapp.com\/billar\/wp-json\/wp\/v2\/pages\/35","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/knovelapp.com\/billar\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/knovelapp.com\/billar\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/knovelapp.com\/billar\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/knovelapp.com\/billar\/wp-json\/wp\/v2\/comments?post=35"}],"version-history":[{"count":1,"href":"https:\/\/knovelapp.com\/billar\/wp-json\/wp\/v2\/pages\/35\/revisions"}],"predecessor-version":[{"id":156,"href":"https:\/\/knovelapp.com\/billar\/wp-json\/wp\/v2\/pages\/35\/revisions\/156"}],"wp:attachment":[{"href":"https:\/\/knovelapp.com\/billar\/wp-json\/wp\/v2\/media?parent=35"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}