|
1
|
|
|
<?php |
|
2
|
|
|
// ------------------------------------------------------------------------- // |
|
3
|
|
|
// This program is free software; you can redistribute it and/or modify // |
|
4
|
|
|
// it under the terms of the GNU General Public License as published by // |
|
5
|
|
|
// the Free Software Foundation; either version 2 of the License, or // |
|
6
|
|
|
// (at your option) any later version. // |
|
7
|
|
|
// // |
|
8
|
|
|
// You may not change or alter any portion of this comment or credits // |
|
9
|
|
|
// of supporting developers from this source code or any supporting // |
|
10
|
|
|
// source code which is considered copyrighted (c) material of the // |
|
11
|
|
|
// original comment or credit authors. // |
|
12
|
|
|
// // |
|
13
|
|
|
// This program is distributed in the hope that it will be useful, // |
|
14
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of // |
|
15
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // |
|
16
|
|
|
// GNU General Public License for more details. // |
|
17
|
|
|
// // |
|
18
|
|
|
// You should have received a copy of the GNU General Public License // |
|
19
|
|
|
// along with this program; if not, write to the Free Software // |
|
20
|
|
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // |
|
21
|
|
|
// ------------------------------------------------------------------------ // |
|
22
|
|
|
// The CXR Rating System algorithm is used by permission of Chess Express // |
|
23
|
|
|
// Ratings, Inc. <http://chess-express.com/>. // |
|
24
|
|
|
// ------------------------------------------------------------------------ // |
|
25
|
|
|
|
|
26
|
|
|
/** |
|
27
|
|
|
* Ratings functions specific to CXR rating system. |
|
28
|
|
|
* |
|
29
|
|
|
* @package chess |
|
30
|
|
|
* @subpackage ratings |
|
31
|
|
|
*/ |
|
32
|
|
|
|
|
33
|
|
|
/** |
|
34
|
|
|
* Update the players' ratings for an individual game, using the CXR rating system. |
|
35
|
|
|
* |
|
36
|
|
|
* @param int $white_rating White's current rating |
|
37
|
|
|
* @param int $white_games Number of rated games that white has played |
|
38
|
|
|
* @param int $black_rating Black's current rating |
|
39
|
|
|
* @param int $black_games Number of rated games that black has played |
|
40
|
|
|
* @param string $pgn_result Game result: '1-0' (white won), '0-1' (black won) or '1/2-1/2' (draw) |
|
41
|
|
|
* @return array Array with two elements: |
|
42
|
|
|
* - $white_rating_new - white's new rating |
|
43
|
|
|
* - $black_rating_new - black's new rating |
|
44
|
|
|
*/ |
|
45
|
|
|
function chess_ratings_adj_cxr($white_rating, $white_games, $black_rating, $black_games, $pgn_result) |
|
46
|
|
|
{ |
|
47
|
|
|
// compute score: +1 for win, 0 for draw, -1 for loss |
|
48
|
|
|
switch ($pgn_result) { |
|
49
|
|
|
case '1-0': |
|
50
|
|
|
$S = 1; |
|
51
|
|
|
break; |
|
52
|
|
|
case '1/2-1/2': |
|
53
|
|
|
default: // should not occur |
|
54
|
|
|
$S = 0; |
|
55
|
|
|
break; |
|
56
|
|
|
case '0-1': |
|
57
|
|
|
$S = -1; |
|
58
|
|
|
break; |
|
59
|
|
|
} |
|
60
|
|
|
|
|
61
|
|
|
if (($white_games < 5 && $black_games < 5) || ($white_games > 5 && $black_games > 5)) { |
|
62
|
|
|
// Formula 1: Rnew = Rold + (S x 21) + (Ropponent - Rold) / 25 |
|
63
|
|
|
$w_new = ($S * 21) + ($black_rating - $white_rating) / 25; |
|
64
|
|
|
$b_new = (-$S * 21) + ($white_rating - $black_rating) / 25; |
|
65
|
|
|
} elseif ($white_games > 5 && $black_games < 5) { |
|
66
|
|
|
// Formula 2: Rnew = Rold + (S x 6) + (Ropponent - Rold) / 100 |
|
67
|
|
|
$w_new = ($S * 6) + ($black_rating - $white_rating) / 100; |
|
68
|
|
|
|
|
69
|
|
|
// Formula 3: Rnew = (4/5) x Rold + (1/5) x Ropponent + (S x 80) |
|
70
|
|
|
$b_new = ($white_rating / 5) + ($S * -80) - ($black_rating / 5); |
|
71
|
|
|
} else { |
|
72
|
|
|
// Formula 2: Rnew = Rold + (S x 6) + (Ropponent - Rold) / 100 |
|
73
|
|
|
$b_new = ($S * 6) + ($white_rating - $black_rating) / 100; |
|
74
|
|
|
|
|
75
|
|
|
// Formula 3: Rnew = (4/5) x Rold + (1/5) x Ropponent + (S x 80) |
|
76
|
|
|
$w_new = ($black_rating / 5) + ($S * -80) - ($white_rating / 5); |
|
77
|
|
|
} |
|
78
|
|
|
|
|
79
|
|
|
// Rule R1: The winning rated player must gain at least two points. |
|
80
|
|
|
// Rule R2: The losing rated player must lose at least two points. |
|
81
|
|
|
if (abs($w_new) < 2) { |
|
82
|
|
|
$w_new = $S * 2; |
|
83
|
|
|
} |
|
84
|
|
|
if (abs($b_new) < 2) { |
|
85
|
|
|
$b_new = $S * -2; |
|
86
|
|
|
} |
|
87
|
|
|
|
|
88
|
|
|
// Rule R3: The rated player must not gain nor lose more than 41 points. |
|
89
|
|
|
if (abs($w_new) > 41) { |
|
90
|
|
|
$w_new = $S * 41; |
|
91
|
|
|
} |
|
92
|
|
|
if (abs($b_new) > 41) { |
|
93
|
|
|
$b_new = $S * -41; |
|
94
|
|
|
} |
|
95
|
|
|
|
|
96
|
|
|
if (1 == $S) { |
|
97
|
|
|
if ($white_games < 5 && $w_new < 0) { |
|
98
|
|
|
$w_new = 2; |
|
99
|
|
|
} |
|
100
|
|
|
if ($black_games < 5 && $b_new > 0) { |
|
101
|
|
|
$b_new = -2; |
|
102
|
|
|
} |
|
103
|
|
|
} elseif (-1 == $S) { |
|
104
|
|
|
if ($white_games < 5 && $w_new > 0) { |
|
105
|
|
|
$w_new = -2; |
|
106
|
|
|
} |
|
107
|
|
|
if ($black_games < 5 && $b_new < 0) { |
|
108
|
|
|
$b_new = 2; |
|
109
|
|
|
} |
|
110
|
|
|
} |
|
111
|
|
|
|
|
112
|
|
|
return [$white_rating + $w_new, $black_rating + $b_new]; |
|
113
|
|
|
} |
|
114
|
|
|
|
|
115
|
|
|
/** |
|
116
|
|
|
* Get the number of provisional games used in the CXR rating system. |
|
117
|
|
|
* |
|
118
|
|
|
* @return int Number of provisional games |
|
119
|
|
|
*/ |
|
120
|
|
|
function chess_ratings_num_provisional_games_cxr() |
|
121
|
|
|
{ |
|
122
|
|
|
return 5; |
|
123
|
|
|
} |
|
124
|
|
|
|
|
125
|
|
|
?> |
|
|
|
|
|
|
126
|
|
|
|
Using a closing tag in PHP files that only contain PHP code is not recommended as you might accidentally add whitespace after the closing tag which would then be output by PHP. This can cause severe problems, for example headers cannot be sent anymore.
A simple precaution is to leave off the closing tag as it is not required, and it also has no negative effects whatsoever.