├── LICENSE ├── README.md └── class.Glicko2Player.php /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | glicko2-php 2 | =========== 3 | 4 | A PHP implementation of [Glicko2][1], a rating system for game ladders. 5 | Glicko2 is a refinement of the well-known [Elo][2] rating system that adds 6 | the concepts of rating deviation, volatility, and rating decay. 7 | 8 | The original glicko2phplib was written by Noah Smith on 2011 June 7. That 9 | version contains significant mathematical errors. This is a fork by Guangcong 10 | Luo on 2012 Sept 28 that corrects these errors, and also updates it to be 11 | compatible with PHP 5. It should also work on PHP 4, although I have not 12 | tested that. 13 | 14 | [1]: http://en.wikipedia.org/wiki/Glicko_rating_system 15 | [2]: http://en.wikipedia.org/wiki/Elo_rating_system 16 | 17 | Usage 18 | ----- 19 | 20 | Glicko2Player([$rating = 1500 [, $rd = 350 [, $volatility = 0.06 [, $mu [, $phi [, $sigma [, $systemconstant = 0.75 ]]]]]]]) 21 | 22 | For new players, use the default values for `rating`, `rd`, and `volatility`. 23 | 24 | The `systemconstant` should be between 0.3 and 1.2, depending on system itself 25 | (this is game dependent, and must be set by estimation or experimentation) 26 | 27 | Updating a Glicko2Player 28 | ------------------------ 29 | 30 | Add wins, losses, and draws to a player: 31 | 32 | $Alice = new Glicko2Player(); 33 | $Bob = new Glicko2Player(); 34 | $Charlie = new Glicko2Player(); 35 | $David = new Glicko2Player(); 36 | 37 | $Alice->AddWin($Bob); 38 | $Alice->AddWin($Charlie) 39 | 40 | $Bob->AddLoss($Alice); 41 | $Bob->AddWin($Charlie); 42 | 43 | $Charlie->AddLoss($Alice); 44 | $Charlie->AddLoss($Bob); 45 | 46 | $Alice->Update(); 47 | $Bob->Update(); 48 | $Charlie->Update(); 49 | $David->Update(); // David did not participate, but must be updated 50 | 51 | License 52 | ------- 53 | 54 | [GNU LGPL version 3.0][3] 55 | 56 | [3]: http://www.gnu.org/copyleft/lesser.html 57 | -------------------------------------------------------------------------------- /class.Glicko2Player.php: -------------------------------------------------------------------------------- 1 | 11 | 12 | Modified from Noah Smith's implementation, which contains a number of mathematical 13 | errors. 14 | 15 | His original documentation is reproduced below. 16 | 17 | ******************************************************************************* 18 | 19 | glicko-2 ranking system 20 | 21 | Written by Noah Smith 2011, June 7 22 | megiddo ( @t ) thirdform ( dot ) com 23 | 24 | Based on http://www.glicko.net/glicko/glicko2.doc/example.html 25 | 26 | Usage 27 | Glicko2Player([$rating = 1500 [, $rd = 350 [, $volatility = 0.06 [, $mu [, $phi [, $sigma [, $systemconstant = 0.75 ]]]]]]] 28 | For new players, use the default values for rating, rd, and volatility. 29 | The systemconstant should be between 0.3 and 1.2, depending on system itself (this is game dependent, and must be set 30 | by estimation or experimentation) 31 | 32 | Updating a Glicko2Player 33 | 34 | Add wins, losses, and draws to a player: 35 | 36 | $Alice = new Glicko2Player(); 37 | $Bob = new Glicko2Player(); 38 | $Charlie = new Glicko2Player(); 39 | $David = new Glicko2Player(); 40 | 41 | $Alice->AddWin($Bob); 42 | $Alice->AddWin($Charlie) 43 | 44 | $Bob->AddLoss($Alice); 45 | $Bob->AddWin($Charlie); 46 | 47 | $Charlie->AddLoss($Alice); 48 | $Charlie->AddLoss($Bob); 49 | 50 | $Alice->Update(); 51 | $Bob->Update(); 52 | $Charlie->Update(); 53 | $David->Update(); // David did not participate, but must be updated 54 | 55 | This message and the following may not be removed or modified: 56 | 57 | Caveat Emptor 58 | I make no assertions that either Glicko-2 or this code are correct. Use at your own risk. 59 | 60 | *******************************************************************************/ 61 | 62 | class Glicko2Player { 63 | public $rating; 64 | public $rd; 65 | public $sigma; 66 | 67 | public $mu; 68 | public $phi; 69 | public $tau; 70 | 71 | private $pi2 = 9.8696044; 72 | 73 | var $M = array(); 74 | 75 | function __construct($rating = 1500, $rd = 350, $volatility = 0.06, $mu = null, $phi = null, $sigma = null, $systemconstant = 0.75) { 76 | // Step 1 77 | $this->rating = $rating; 78 | $this->rd = $rd; 79 | // volatility 80 | if (is_null($sigma)) { 81 | $this->sigma = $volatility; 82 | } else { 83 | $this->sigma = $sigma; 84 | } 85 | // System Constant 86 | $this->tau = $systemconstant; 87 | 88 | // Step 2 89 | // Rating 90 | if (is_null($mu)) { 91 | $this->mu = ( $this->rating - 1500 ) / 173.7178; 92 | } else { 93 | $this->mu = $mu; 94 | } 95 | // Rating Deviation 96 | if (is_null($phi)) { 97 | $this->phi = $this->rd / 173.7178; 98 | } else { 99 | $this->phi = $phi; 100 | } 101 | } 102 | 103 | function AddWin($OtherPlayer) { 104 | $this->M[] = $OtherPlayer->MatchElement(1); 105 | } 106 | 107 | function AddLoss($OtherPlayer) { 108 | $this->M[] = $OtherPlayer->MatchElement(0); 109 | } 110 | 111 | function AddDraw($OtherPlayer) { 112 | $this->M[] = $OtherPlayer->MatchElement(0.5); 113 | } 114 | 115 | function Update() { 116 | $Results = $this->AddMatches($this->M); 117 | $this->rating = $Results['r']; 118 | $this->rd = $Results['RD']; 119 | $this->mu = $Results['mu']; 120 | $this->phi = $Results['phi']; 121 | $this->sigma = $Results['sigma']; 122 | $this->M = array(); 123 | } 124 | 125 | function MatchElement($score) { 126 | return array( 'mu' => $this->mu, 'phi' => $this->phi, 'score' => $score ); 127 | } 128 | 129 | function AddMatches($M) { 130 | // This is where the Glicko2 rating calculation actually happens 131 | 132 | // Follow along the steps using: http://www.glicko.net/glicko/glicko2.pdf 133 | 134 | if (count($M) == 0) { 135 | $phi_p = sqrt( ( $this->phi * $this->phi ) + ( $this->sigma * $this->sigma ) ); 136 | return array( 'r' => $this->rating, 'RD' => 173.7178 * $phi_p, 'mu' => $this->mu, 'phi' => $phi_p, 'sigma' => $this->sigma ) ; 137 | } 138 | 139 | // summation parts of Step 3 & 4 & 7 140 | $v_sum = 0; 141 | $delta_sum = 0; 142 | $mu_p_sum = 0; 143 | for ($j = 0; $j < count($M); $j++) { 144 | $E = $this->E( $this->mu, $M[$j]['mu'], $M[$j]['phi'] ); 145 | $g = $this->g( $M[$j]['phi'] ); 146 | $v_sum += ( $g * $g * $E * ( 1 - $E ) ); 147 | 148 | $delta_sum += $g * ( $M[$j]['score'] - $E ); 149 | 150 | $mu_p_sum += $g * ( $M[$j]['score'] - $E ); 151 | } 152 | 153 | // Step 3 154 | // Estimated variance 155 | $v = 1.0 / $v_sum; 156 | 157 | // Step 4 158 | // Estimated improvment in rating 159 | $delta = $v * $delta_sum; 160 | 161 | // Step 5 162 | $a = log( $this->sigma * $this->sigma ); 163 | $x_prev = $a; 164 | $x = $x_prev; 165 | $tausq = $this->tau * $this->tau; 166 | $phisq = $this->phi * $this->phi; 167 | $deltasq = $delta * $delta; 168 | do { 169 | $exp_xp = exp( $x_prev ); 170 | $d = $this->phi * $this->phi + $v + $exp_xp; 171 | $deltadsq = $deltasq / ($d * $d); 172 | $h1 = -( $x_prev - $a ) / ( $tausq ) - ( 0.5 * $exp_xp / $d ) + ( 0.5 * $exp_xp * $deltadsq ); 173 | $h2 = ( -1.0 / $tausq ) - ( ( 0.5 * $exp_xp ) * ( $phisq + $v ) / ( $d * $d ) ) + ( 0.5 * $deltasq * $exp_xp * ( $phisq + $v - $exp_xp ) / ( $d * $d * $d ) ); 174 | $tmp_x = $x; 175 | $x = $x_prev - ( $h1 / $h2 ); 176 | $x_prev = $tmp_x; 177 | } while (abs($x - $x_prev) > 0.1); 178 | 179 | $sigma_p = exp( $x / 2 ); 180 | 181 | // Step 6 182 | $phi_star = sqrt( $phisq + ( $sigma_p * $sigma_p ) ); 183 | 184 | // Step 7 185 | $phi_p = 1.0 / ( sqrt( ( 1.0 / ( $phi_star * $phi_star ) ) + ( 1.0 / $v ) ) ); 186 | // New mu 187 | $mu_p = $this->mu + $phi_p * $phi_p * $mu_p_sum; 188 | 189 | return array( 'r' => ( 173.7178 * $mu_p ) + 1500, 'RD' => 173.7178 * $phi_p, 'mu' => $mu_p, 'phi' => $phi_p, 'sigma' => $sigma_p ); 190 | } 191 | 192 | function g($phi) { 193 | return 1.0 / ( sqrt( 1.0 + ( 3.0 * $phi * $phi) / ( $this->pi2 ) ) ); 194 | } 195 | 196 | function E($mu, $mu_j, $phi_j) { 197 | return 1.0 / ( 1.0 + exp( -$this->g($phi_j) * ( $mu - $mu_j ) ) ); 198 | } 199 | } 200 | --------------------------------------------------------------------------------