2022-07-05 15:55:47 +02:00
|
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
namespace DNW\Skills;
|
2010-08-28 22:05:41 -04:00
|
|
|
|
|
|
|
|
|
// Container for a player's rating.
|
2022-07-05 15:33:34 +02:00
|
|
|
|
use DNW\Skills\Numerics\GaussianDistribution;
|
2016-05-24 14:10:39 +02:00
|
|
|
|
|
2022-07-05 16:21:06 +02:00
|
|
|
|
class Rating implements \Stringable
|
2010-08-28 22:05:41 -04:00
|
|
|
|
{
|
2022-07-05 16:21:06 +02:00
|
|
|
|
final const CONSERVATIVE_STANDARD_DEVIATION_MULTIPLIER = 3;
|
2010-08-28 22:05:41 -04:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Constructs a rating.
|
2022-07-05 15:55:47 +02:00
|
|
|
|
*
|
2022-07-05 16:32:18 +02:00
|
|
|
|
* @param float $_mean The statistical mean value of the rating (also known as mu).
|
|
|
|
|
* @param float $_standardDeviation The standard deviation of the rating (also known as s).
|
|
|
|
|
* @param float|int $_conservativeStandardDeviationMultiplier optional The number of standardDeviations to subtract from the mean to achieve a conservative rating.
|
2010-08-28 22:05:41 -04:00
|
|
|
|
*/
|
2022-07-05 16:21:06 +02:00
|
|
|
|
public function __construct(private $_mean, private $_standardDeviation, private $_conservativeStandardDeviationMultiplier = self::CONSERVATIVE_STANDARD_DEVIATION_MULTIPLIER)
|
2010-08-28 22:05:41 -04:00
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* The statistical mean value of the rating (also known as <EFBFBD>).
|
|
|
|
|
*/
|
|
|
|
|
public function getMean()
|
|
|
|
|
{
|
2016-05-24 14:10:39 +02:00
|
|
|
|
return $this->_mean;
|
2010-08-28 22:05:41 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* The standard deviation (the spread) of the rating. This is also known as s.
|
|
|
|
|
*/
|
|
|
|
|
public function getStandardDeviation()
|
|
|
|
|
{
|
|
|
|
|
return $this->_standardDeviation;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* A conservative estimate of skill based on the mean and standard deviation.
|
|
|
|
|
*/
|
|
|
|
|
public function getConservativeRating()
|
|
|
|
|
{
|
2016-05-24 14:10:39 +02:00
|
|
|
|
return $this->_mean - $this->_conservativeStandardDeviationMultiplier * $this->_standardDeviation;
|
2010-08-28 22:05:41 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function getPartialUpdate(Rating $prior, Rating $fullPosterior, $updatePercentage)
|
|
|
|
|
{
|
|
|
|
|
$priorGaussian = new GaussianDistribution($prior->getMean(), $prior->getStandardDeviation());
|
2022-07-05 15:55:47 +02:00
|
|
|
|
$posteriorGaussian = new GaussianDistribution($fullPosterior->getMean(), $fullPosterior.getStandardDeviation());
|
2010-08-28 22:05:41 -04:00
|
|
|
|
|
|
|
|
|
// From a clarification email from Ralf Herbrich:
|
2022-07-05 15:33:34 +02:00
|
|
|
|
// "the idea is to compute a linear interpolation between the prior and posterior skills of each player
|
2010-08-28 22:05:41 -04:00
|
|
|
|
// ... in the canonical space of parameters"
|
|
|
|
|
|
|
|
|
|
$precisionDifference = $posteriorGaussian->getPrecision() - $priorGaussian->getPrecision();
|
2016-05-24 14:10:39 +02:00
|
|
|
|
$partialPrecisionDifference = $updatePercentage * $precisionDifference;
|
2010-08-28 22:05:41 -04:00
|
|
|
|
|
2022-07-05 15:55:47 +02:00
|
|
|
|
$precisionMeanDifference = $posteriorGaussian->getPrecisionMean() - $priorGaussian.getPrecisionMean();
|
2016-05-24 14:10:39 +02:00
|
|
|
|
$partialPrecisionMeanDifference = $updatePercentage * $precisionMeanDifference;
|
2010-08-28 22:05:41 -04:00
|
|
|
|
|
|
|
|
|
$partialPosteriorGaussion = GaussianDistribution::fromPrecisionMean(
|
|
|
|
|
$priorGaussian->getPrecisionMean() + $partialPrecisionMeanDifference,
|
2016-05-24 14:10:39 +02:00
|
|
|
|
$priorGaussian->getPrecision() + $partialPrecisionDifference
|
|
|
|
|
);
|
2010-08-28 22:05:41 -04:00
|
|
|
|
|
|
|
|
|
return new Rating($partialPosteriorGaussion->getMean(), $partialPosteriorGaussion->getStandardDeviation(), $prior->_conservativeStandardDeviationMultiplier);
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-05 16:21:06 +02:00
|
|
|
|
public function __toString(): string
|
2010-08-28 22:05:41 -04:00
|
|
|
|
{
|
2022-07-05 15:55:47 +02:00
|
|
|
|
return sprintf('mean=%.4f, standardDeviation=%.4f', $this->_mean, $this->_standardDeviation);
|
2016-05-24 14:10:39 +02:00
|
|
|
|
}
|
2022-07-05 15:55:47 +02:00
|
|
|
|
}
|