mirror of
				https://github.com/furyfire/trueskill.git
				synced 2025-11-04 10:12:28 +01:00 
			
		
		
		
	Pint applied for formatting
This commit is contained in:
		@@ -1,4 +1,6 @@
 | 
			
		||||
<?php namespace DNW\Skills\FactorGraphs;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills\FactorGraphs;
 | 
			
		||||
 | 
			
		||||
use Exception;
 | 
			
		||||
 | 
			
		||||
@@ -7,7 +9,7 @@ class DefaultVariable extends Variable
 | 
			
		||||
{
 | 
			
		||||
    public function __construct()
 | 
			
		||||
    {
 | 
			
		||||
        parent::__construct("Default", null);
 | 
			
		||||
        parent::__construct('Default', null);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getValue()
 | 
			
		||||
@@ -19,4 +21,4 @@ class DefaultVariable extends Variable
 | 
			
		||||
    {
 | 
			
		||||
        throw new Exception();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,20 +1,24 @@
 | 
			
		||||
<?php namespace DNW\Skills\FactorGraphs;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills\FactorGraphs;
 | 
			
		||||
 | 
			
		||||
use Exception;
 | 
			
		||||
use DNW\Skills\Guard;
 | 
			
		||||
use DNW\Skills\HashMap;
 | 
			
		||||
use Exception;
 | 
			
		||||
 | 
			
		||||
abstract class Factor
 | 
			
		||||
{
 | 
			
		||||
    private $_messages = array();
 | 
			
		||||
    private $_messages = [];
 | 
			
		||||
 | 
			
		||||
    private $_messageToVariableBinding;
 | 
			
		||||
 | 
			
		||||
    private $_name;
 | 
			
		||||
    private $_variables = array();
 | 
			
		||||
 | 
			
		||||
    private $_variables = [];
 | 
			
		||||
 | 
			
		||||
    protected function __construct($name)
 | 
			
		||||
    {
 | 
			
		||||
        $this->_name = "Factor[" . $name . "]";
 | 
			
		||||
        $this->_name = 'Factor['.$name.']';
 | 
			
		||||
        $this->_messageToVariableBinding = new HashMap();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -46,14 +50,17 @@ abstract class Factor
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Update the message and marginal of the i-th variable that the factor is connected to
 | 
			
		||||
     *
 | 
			
		||||
     * @param $messageIndex
 | 
			
		||||
     *
 | 
			
		||||
     * @throws Exception
 | 
			
		||||
     */
 | 
			
		||||
    public function updateMessageIndex($messageIndex)
 | 
			
		||||
    {
 | 
			
		||||
        Guard::argumentIsValidIndex($messageIndex, count($this->_messages), "messageIndex");
 | 
			
		||||
        Guard::argumentIsValidIndex($messageIndex, count($this->_messages), 'messageIndex');
 | 
			
		||||
        $message = $this->_messages[$messageIndex];
 | 
			
		||||
        $variable = $this->_messageToVariableBinding->getValue($message);
 | 
			
		||||
 | 
			
		||||
        return $this->updateMessageVariable($message, $variable);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -75,28 +82,32 @@ abstract class Factor
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sends the ith message to the marginal and returns the log-normalization constant
 | 
			
		||||
     *
 | 
			
		||||
     * @param $messageIndex
 | 
			
		||||
     * @return
 | 
			
		||||
     *
 | 
			
		||||
     * @throws Exception
 | 
			
		||||
     */
 | 
			
		||||
    public function sendMessageIndex($messageIndex)
 | 
			
		||||
    {
 | 
			
		||||
        Guard::argumentIsValidIndex($messageIndex, count($this->_messages), "messageIndex");
 | 
			
		||||
        Guard::argumentIsValidIndex($messageIndex, count($this->_messages), 'messageIndex');
 | 
			
		||||
 | 
			
		||||
        $message = $this->_messages[$messageIndex];
 | 
			
		||||
        $variable = $this->_messageToVariableBinding->getValue($message);
 | 
			
		||||
 | 
			
		||||
        return $this->sendMessageVariable($message, $variable);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected abstract function sendMessageVariable(Message $message, Variable $variable);
 | 
			
		||||
    abstract protected function sendMessageVariable(Message $message, Variable $variable);
 | 
			
		||||
 | 
			
		||||
    public abstract function createVariableToMessageBinding(Variable $variable);
 | 
			
		||||
    abstract public function createVariableToMessageBinding(Variable $variable);
 | 
			
		||||
 | 
			
		||||
    protected function createVariableToMessageBindingWithMessage(Variable $variable, Message $message)
 | 
			
		||||
    {
 | 
			
		||||
        $this->_messageToVariableBinding->setValue($message, $variable);
 | 
			
		||||
        $this->_messages[] = $message;
 | 
			
		||||
        $this->_variables[] = $variable;
 | 
			
		||||
 | 
			
		||||
        return $message;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -104,4 +115,4 @@ abstract class Factor
 | 
			
		||||
    {
 | 
			
		||||
        return $this->_name;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,6 @@
 | 
			
		||||
<?php namespace DNW\Skills\FactorGraphs;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills\FactorGraphs;
 | 
			
		||||
 | 
			
		||||
class FactorGraph
 | 
			
		||||
{
 | 
			
		||||
@@ -13,4 +15,4 @@ class FactorGraph
 | 
			
		||||
    {
 | 
			
		||||
        $this->_variableFactory = $factory;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,16 @@
 | 
			
		||||
<?php namespace DNW\Skills\FactorGraphs;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills\FactorGraphs;
 | 
			
		||||
 | 
			
		||||
// edit this
 | 
			
		||||
abstract class FactorGraphLayer
 | 
			
		||||
{
 | 
			
		||||
    private $_localFactors = array();
 | 
			
		||||
    private $_outputVariablesGroups = array();
 | 
			
		||||
    private $_inputVariablesGroups = array();
 | 
			
		||||
    private $_localFactors = [];
 | 
			
		||||
 | 
			
		||||
    private $_outputVariablesGroups = [];
 | 
			
		||||
 | 
			
		||||
    private $_inputVariablesGroups = [];
 | 
			
		||||
 | 
			
		||||
    private $_parentFactorGraph;
 | 
			
		||||
 | 
			
		||||
    protected function __construct(FactorGraph $parentGraph)
 | 
			
		||||
@@ -54,7 +60,7 @@ abstract class FactorGraphLayer
 | 
			
		||||
        $this->_localFactors[] = $factor;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public abstract function buildLayer();
 | 
			
		||||
    abstract public function buildLayer();
 | 
			
		||||
 | 
			
		||||
    public function createPriorSchedule()
 | 
			
		||||
    {
 | 
			
		||||
@@ -65,4 +71,4 @@ abstract class FactorGraphLayer
 | 
			
		||||
    {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,13 @@
 | 
			
		||||
<?php namespace DNW\Skills\FactorGraphs;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills\FactorGraphs;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Helper class for computing the factor graph's normalization constant.
 | 
			
		||||
 */
 | 
			
		||||
class FactorList
 | 
			
		||||
{
 | 
			
		||||
    private $_list = array();
 | 
			
		||||
    private $_list = [];
 | 
			
		||||
 | 
			
		||||
    public function getLogNormalization()
 | 
			
		||||
    {
 | 
			
		||||
@@ -45,6 +47,7 @@ class FactorList
 | 
			
		||||
    public function addFactor(Factor $factor)
 | 
			
		||||
    {
 | 
			
		||||
        $this->_list[] = $factor;
 | 
			
		||||
 | 
			
		||||
        return $factor;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,6 @@
 | 
			
		||||
<?php namespace DNW\Skills\FactorGraphs;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills\FactorGraphs;
 | 
			
		||||
 | 
			
		||||
class KeyedVariable extends Variable
 | 
			
		||||
{
 | 
			
		||||
@@ -14,4 +16,4 @@ class KeyedVariable extends Variable
 | 
			
		||||
    {
 | 
			
		||||
        return $this->_key;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,11 @@
 | 
			
		||||
<?php namespace DNW\Skills\FactorGraphs;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills\FactorGraphs;
 | 
			
		||||
 | 
			
		||||
class Message
 | 
			
		||||
{
 | 
			
		||||
    private $_name;
 | 
			
		||||
 | 
			
		||||
    private $_value;
 | 
			
		||||
 | 
			
		||||
    public function __construct($value = null, $name = null)
 | 
			
		||||
@@ -23,6 +26,6 @@ class Message
 | 
			
		||||
 | 
			
		||||
    public function __toString()
 | 
			
		||||
    {
 | 
			
		||||
        return (string)$this->_name;
 | 
			
		||||
        return (string) $this->_name;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,6 @@
 | 
			
		||||
<?php namespace DNW\Skills\FactorGraphs;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills\FactorGraphs;
 | 
			
		||||
 | 
			
		||||
abstract class Schedule
 | 
			
		||||
{
 | 
			
		||||
@@ -9,10 +11,10 @@ abstract class Schedule
 | 
			
		||||
        $this->_name = $name;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public abstract function visit($depth = -1, $maxDepth = 0);
 | 
			
		||||
    abstract public function visit($depth = -1, $maxDepth = 0);
 | 
			
		||||
 | 
			
		||||
    public function __toString()
 | 
			
		||||
    {
 | 
			
		||||
        return $this->_name;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,11 @@
 | 
			
		||||
<?php namespace DNW\Skills\FactorGraphs;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills\FactorGraphs;
 | 
			
		||||
 | 
			
		||||
class ScheduleLoop extends Schedule
 | 
			
		||||
{
 | 
			
		||||
    private $_maxDelta;
 | 
			
		||||
 | 
			
		||||
    private $_scheduleToLoop;
 | 
			
		||||
 | 
			
		||||
    public function __construct($name, Schedule $scheduleToLoop, $maxDelta)
 | 
			
		||||
@@ -23,4 +26,4 @@ class ScheduleLoop extends Schedule
 | 
			
		||||
 | 
			
		||||
        return $delta;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,6 @@
 | 
			
		||||
<?php namespace DNW\Skills\FactorGraphs;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills\FactorGraphs;
 | 
			
		||||
 | 
			
		||||
class ScheduleSequence extends Schedule
 | 
			
		||||
{
 | 
			
		||||
@@ -22,4 +24,4 @@ class ScheduleSequence extends Schedule
 | 
			
		||||
 | 
			
		||||
        return $maxDelta;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,11 @@
 | 
			
		||||
<?php namespace DNW\Skills\FactorGraphs;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills\FactorGraphs;
 | 
			
		||||
 | 
			
		||||
class ScheduleStep extends Schedule
 | 
			
		||||
{
 | 
			
		||||
    private $_factor;
 | 
			
		||||
 | 
			
		||||
    private $_index;
 | 
			
		||||
 | 
			
		||||
    public function __construct($name, Factor $factor, $index)
 | 
			
		||||
@@ -16,6 +19,7 @@ class ScheduleStep extends Schedule
 | 
			
		||||
    {
 | 
			
		||||
        $currentFactor = $this->_factor;
 | 
			
		||||
        $delta = $currentFactor->updateMessageIndex($this->_index);
 | 
			
		||||
 | 
			
		||||
        return $delta;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,15 +1,18 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills\FactorGraphs;
 | 
			
		||||
 | 
			
		||||
class Variable
 | 
			
		||||
{
 | 
			
		||||
    private $_name;
 | 
			
		||||
 | 
			
		||||
    private $_prior;
 | 
			
		||||
 | 
			
		||||
    private $_value;
 | 
			
		||||
 | 
			
		||||
    public function __construct($name, $prior)
 | 
			
		||||
    {
 | 
			
		||||
        $this->_name = "Variable[" . $name . "]";
 | 
			
		||||
        $this->_name = 'Variable['.$name.']';
 | 
			
		||||
        $this->_prior = $prior;
 | 
			
		||||
        $this->resetToPrior();
 | 
			
		||||
    }
 | 
			
		||||
@@ -33,4 +36,4 @@ class Variable
 | 
			
		||||
    {
 | 
			
		||||
        return $this->_name;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,6 @@
 | 
			
		||||
<?php namespace DNW\Skills\FactorGraphs;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills\FactorGraphs;
 | 
			
		||||
 | 
			
		||||
class VariableFactory
 | 
			
		||||
{
 | 
			
		||||
@@ -14,6 +16,7 @@ class VariableFactory
 | 
			
		||||
    {
 | 
			
		||||
        $initializer = $this->_variablePriorInitializer;
 | 
			
		||||
        $newVar = new Variable($name, $initializer());
 | 
			
		||||
 | 
			
		||||
        return $newVar;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -21,6 +24,7 @@ class VariableFactory
 | 
			
		||||
    {
 | 
			
		||||
        $initializer = $this->_variablePriorInitializer;
 | 
			
		||||
        $newVar = new KeyedVariable($key, $name, $initializer());
 | 
			
		||||
 | 
			
		||||
        return $newVar;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,6 @@
 | 
			
		||||
<?php namespace DNW\Skills;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Parameters about the game for calculating the TrueSkill.
 | 
			
		||||
@@ -6,15 +8,23 @@
 | 
			
		||||
class GameInfo
 | 
			
		||||
{
 | 
			
		||||
    const DEFAULT_BETA = 4.1666666666666666666666666666667; // Default initial mean / 6
 | 
			
		||||
 | 
			
		||||
    const DEFAULT_DRAW_PROBABILITY = 0.10;
 | 
			
		||||
 | 
			
		||||
    const DEFAULT_DYNAMICS_FACTOR = 0.083333333333333333333333333333333; // Default initial mean / 300
 | 
			
		||||
 | 
			
		||||
    const DEFAULT_INITIAL_MEAN = 25.0;
 | 
			
		||||
 | 
			
		||||
    const DEFAULT_INITIAL_STANDARD_DEVIATION = 8.3333333333333333333333333333333; // Default initial mean / 3
 | 
			
		||||
 | 
			
		||||
    private $_initialMean;
 | 
			
		||||
 | 
			
		||||
    private $_initialStandardDeviation;
 | 
			
		||||
 | 
			
		||||
    private $_beta;
 | 
			
		||||
 | 
			
		||||
    private $_dynamicsFactor;
 | 
			
		||||
 | 
			
		||||
    private $_drawProbability;
 | 
			
		||||
 | 
			
		||||
    public function __construct($initialMean = self::DEFAULT_INITIAL_MEAN,
 | 
			
		||||
@@ -30,7 +40,6 @@ class GameInfo
 | 
			
		||||
        $this->_drawProbability = $drawProbability;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    public function getInitialMean()
 | 
			
		||||
    {
 | 
			
		||||
        return $this->_initialMean;
 | 
			
		||||
@@ -60,4 +69,4 @@ class GameInfo
 | 
			
		||||
    {
 | 
			
		||||
        return new Rating($this->_initialMean, $this->_initialStandardDeviation);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,6 @@
 | 
			
		||||
<?php namespace DNW\Skills;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills;
 | 
			
		||||
 | 
			
		||||
use Exception;
 | 
			
		||||
 | 
			
		||||
@@ -12,21 +14,21 @@ class Guard
 | 
			
		||||
    public static function argumentNotNull($value, $parameterName)
 | 
			
		||||
    {
 | 
			
		||||
        if ($value == null) {
 | 
			
		||||
            throw new Exception($parameterName . " can not be null");
 | 
			
		||||
            throw new Exception($parameterName.' can not be null');
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static function argumentIsValidIndex($index, $count, $parameterName)
 | 
			
		||||
    {
 | 
			
		||||
        if (($index < 0) || ($index >= $count)) {
 | 
			
		||||
            throw new Exception($parameterName . " is an invalid index");
 | 
			
		||||
            throw new Exception($parameterName.' is an invalid index');
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static function argumentInRangeInclusive($value, $min, $max, $parameterName)
 | 
			
		||||
    {
 | 
			
		||||
        if (($value < $min) || ($value > $max)) {
 | 
			
		||||
            throw new Exception($parameterName . " is not in the valid range [" . $min . ", " . $max . "]");
 | 
			
		||||
            throw new Exception($parameterName.' is not in the valid range ['.$min.', '.$max.']');
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,17 +1,21 @@
 | 
			
		||||
<?php namespace DNW\Skills;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Basic hashmap that supports object keys.
 | 
			
		||||
 */
 | 
			
		||||
class HashMap
 | 
			
		||||
{
 | 
			
		||||
    private $_hashToValue = array();
 | 
			
		||||
    private $_hashToKey = array();
 | 
			
		||||
    private $_hashToValue = [];
 | 
			
		||||
 | 
			
		||||
    private $_hashToKey = [];
 | 
			
		||||
 | 
			
		||||
    public function getValue($key)
 | 
			
		||||
    {
 | 
			
		||||
        $hash = self::getHash($key);
 | 
			
		||||
        $hashValue = $this->_hashToValue[$hash];
 | 
			
		||||
 | 
			
		||||
        return $hashValue;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -20,18 +24,21 @@ class HashMap
 | 
			
		||||
        $hash = self::getHash($key);
 | 
			
		||||
        $this->_hashToKey[$hash] = $key;
 | 
			
		||||
        $this->_hashToValue[$hash] = $value;
 | 
			
		||||
 | 
			
		||||
        return $this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getAllKeys()
 | 
			
		||||
    {
 | 
			
		||||
        $keys = array_values($this->_hashToKey);
 | 
			
		||||
 | 
			
		||||
        return $keys;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getAllValues()
 | 
			
		||||
    {
 | 
			
		||||
        $values = array_values($this->_hashToValue);
 | 
			
		||||
 | 
			
		||||
        return $values;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -48,4 +55,4 @@ class HashMap
 | 
			
		||||
 | 
			
		||||
        return $key;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,6 @@
 | 
			
		||||
<?php namespace DNW\Skills;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Indicates support for allowing partial play (where a player only plays a part of the time).
 | 
			
		||||
@@ -9,4 +11,4 @@ interface ISupportPartialPlay
 | 
			
		||||
     * Indicates the percent of the time the player should be weighted where 0.0 indicates the player didn't play and 1.0 indicates the player played 100% of the time.
 | 
			
		||||
     */
 | 
			
		||||
    public function getPartialPlayPercentage();
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,6 @@
 | 
			
		||||
<?php namespace DNW\Skills;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills;
 | 
			
		||||
 | 
			
		||||
interface ISupportPartialUpdate
 | 
			
		||||
{
 | 
			
		||||
@@ -6,4 +8,4 @@ interface ISupportPartialUpdate
 | 
			
		||||
     * Indicated how much of a skill update a player should receive where 0.0 represents no update and 1.0 represents 100% of the update.
 | 
			
		||||
     */
 | 
			
		||||
    public function getPartialUpdatePercentage();
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,6 @@
 | 
			
		||||
<?php namespace DNW\Skills\Numerics;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills\Numerics;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Basic math functions.
 | 
			
		||||
@@ -8,10 +10,10 @@
 | 
			
		||||
 */
 | 
			
		||||
class BasicMath
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Squares the input (x^2 = x * x)
 | 
			
		||||
     * @param number $x Value to square (x)
 | 
			
		||||
     *
 | 
			
		||||
     * @param  number  $x Value to square (x)
 | 
			
		||||
     * @return number The squared value (x^2)
 | 
			
		||||
     */
 | 
			
		||||
    public static function square($x)
 | 
			
		||||
@@ -21,13 +23,15 @@ class BasicMath
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sums the items in $itemsToSum
 | 
			
		||||
     * @param array $itemsToSum The items to sum,
 | 
			
		||||
     * @param callback $callback The function to apply to each array element before summing.
 | 
			
		||||
     *
 | 
			
		||||
     * @param  array  $itemsToSum The items to sum,
 | 
			
		||||
     * @param  callable  $callback The function to apply to each array element before summing.
 | 
			
		||||
     * @return number The sum.
 | 
			
		||||
     */
 | 
			
		||||
    public static function sum(array $itemsToSum, $callback)
 | 
			
		||||
    {
 | 
			
		||||
        $mappedItems = array_map($callback, $itemsToSum);
 | 
			
		||||
 | 
			
		||||
        return array_sum($mappedItems);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,6 @@
 | 
			
		||||
<?php namespace DNW\Skills\Numerics;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills\Numerics;
 | 
			
		||||
 | 
			
		||||
class DiagonalMatrix extends Matrix
 | 
			
		||||
{
 | 
			
		||||
@@ -20,4 +22,4 @@ class DiagonalMatrix extends Matrix
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,6 @@
 | 
			
		||||
<?php namespace DNW\Skills\Numerics;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills\Numerics;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Computes Gaussian (bell curve) values.
 | 
			
		||||
@@ -9,12 +11,15 @@
 | 
			
		||||
class GaussianDistribution
 | 
			
		||||
{
 | 
			
		||||
    private $_mean;
 | 
			
		||||
 | 
			
		||||
    private $_standardDeviation;
 | 
			
		||||
 | 
			
		||||
    // precision and precisionMean are used because they make multiplying and dividing simpler
 | 
			
		||||
    // (the the accompanying math paper for more details)
 | 
			
		||||
    private $_precision;
 | 
			
		||||
 | 
			
		||||
    private $_precisionMean;
 | 
			
		||||
 | 
			
		||||
    private $_variance;
 | 
			
		||||
 | 
			
		||||
    public function __construct($mean = 0.0, $standardDeviation = 1.0)
 | 
			
		||||
@@ -76,6 +81,7 @@ class GaussianDistribution
 | 
			
		||||
        $result->_variance = $this->_variance;
 | 
			
		||||
        $result->_precision = $this->_precision;
 | 
			
		||||
        $result->_precisionMean = $this->_precisionMean;
 | 
			
		||||
 | 
			
		||||
        return $result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -94,6 +100,7 @@ class GaussianDistribution
 | 
			
		||||
            $result->_standardDeviation = \INF;
 | 
			
		||||
            $result->_mean = \NAN;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -129,6 +136,7 @@ class GaussianDistribution
 | 
			
		||||
        $meanDifference = $left->_mean - $right->_mean;
 | 
			
		||||
 | 
			
		||||
        $logSqrt2Pi = log(sqrt(2 * M_PI));
 | 
			
		||||
 | 
			
		||||
        return -$logSqrt2Pi - (log($varianceSum) / 2.0) - (BasicMath::square($meanDifference) / (2.0 * $varianceSum));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -165,6 +173,7 @@ class GaussianDistribution
 | 
			
		||||
        $multiplier = 1.0 / ($standardDeviation * sqrt(2 * M_PI));
 | 
			
		||||
        $expPart = exp((-1.0 * BasicMath::square($x - $mean)) / (2 * BasicMath::square($standardDeviation)));
 | 
			
		||||
        $result = $multiplier * $expPart;
 | 
			
		||||
 | 
			
		||||
        return $result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -172,6 +181,7 @@ class GaussianDistribution
 | 
			
		||||
    {
 | 
			
		||||
        $invsqrt2 = -0.707106781186547524400844362104;
 | 
			
		||||
        $result = GaussianDistribution::errorFunctionCumulativeTo($invsqrt2 * $x);
 | 
			
		||||
 | 
			
		||||
        return 0.5 * $result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -183,7 +193,7 @@ class GaussianDistribution
 | 
			
		||||
        $t = 2.0 / (2.0 + $z);
 | 
			
		||||
        $ty = 4 * $t - 2;
 | 
			
		||||
 | 
			
		||||
        $coefficients = array(
 | 
			
		||||
        $coefficients = [
 | 
			
		||||
            -1.3026537197817094,
 | 
			
		||||
            6.4196979235649026e-1,
 | 
			
		||||
            1.9476473204185836e-2,
 | 
			
		||||
@@ -211,7 +221,7 @@ class GaussianDistribution
 | 
			
		||||
            -1.523e-15,
 | 
			
		||||
            -9.4e-17,
 | 
			
		||||
            1.21e-16,
 | 
			
		||||
            -2.8e-17);
 | 
			
		||||
            -2.8e-17, ];
 | 
			
		||||
 | 
			
		||||
        $ncof = count($coefficients);
 | 
			
		||||
        $d = 0.0;
 | 
			
		||||
@@ -224,6 +234,7 @@ class GaussianDistribution
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $ans = $t * exp(-$z * $z + 0.5 * ($coefficients[0] + $ty * $d) - $dd);
 | 
			
		||||
 | 
			
		||||
        return ($x >= 0.0) ? $ans : (2.0 - $ans);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -258,6 +269,6 @@ class GaussianDistribution
 | 
			
		||||
 | 
			
		||||
    public function __toString()
 | 
			
		||||
    {
 | 
			
		||||
        return sprintf("mean=%.4f standardDeviation=%.4f", $this->_mean, $this->_standardDeviation);
 | 
			
		||||
        return sprintf('mean=%.4f standardDeviation=%.4f', $this->_mean, $this->_standardDeviation);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,6 @@
 | 
			
		||||
<?php namespace DNW\Skills\Numerics;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills\Numerics;
 | 
			
		||||
 | 
			
		||||
class IdentityMatrix extends DiagonalMatrix
 | 
			
		||||
{
 | 
			
		||||
@@ -6,4 +8,4 @@ class IdentityMatrix extends DiagonalMatrix
 | 
			
		||||
    {
 | 
			
		||||
        parent::__construct(array_fill(0, $rows, 1));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,6 @@
 | 
			
		||||
<?php namespace DNW\Skills\Numerics;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills\Numerics;
 | 
			
		||||
 | 
			
		||||
use Exception;
 | 
			
		||||
 | 
			
		||||
@@ -7,7 +9,9 @@ class Matrix
 | 
			
		||||
    const ERROR_TOLERANCE = 0.0000000001;
 | 
			
		||||
 | 
			
		||||
    private $_matrixRowData;
 | 
			
		||||
 | 
			
		||||
    private $_rowCount;
 | 
			
		||||
 | 
			
		||||
    private $_columnCount;
 | 
			
		||||
 | 
			
		||||
    public function __construct($rows = 0, $columns = 0, $matrixData = null)
 | 
			
		||||
@@ -19,7 +23,7 @@ class Matrix
 | 
			
		||||
 | 
			
		||||
    public static function fromColumnValues($rows, $columns, $columnValues)
 | 
			
		||||
    {
 | 
			
		||||
        $data = array();
 | 
			
		||||
        $data = [];
 | 
			
		||||
        $result = new Matrix($rows, $columns, $data);
 | 
			
		||||
 | 
			
		||||
        for ($currentColumn = 0; $currentColumn < $columns; $currentColumn++) {
 | 
			
		||||
@@ -73,7 +77,7 @@ class Matrix
 | 
			
		||||
    public function getTranspose()
 | 
			
		||||
    {
 | 
			
		||||
        // Just flip everything
 | 
			
		||||
        $transposeMatrix = array();
 | 
			
		||||
        $transposeMatrix = [];
 | 
			
		||||
 | 
			
		||||
        $rowMatrixData = $this->_matrixRowData;
 | 
			
		||||
        for ($currentRowTransposeMatrix = 0;
 | 
			
		||||
@@ -98,8 +102,8 @@ class Matrix
 | 
			
		||||
    public function getDeterminant()
 | 
			
		||||
    {
 | 
			
		||||
        // Basic argument checking
 | 
			
		||||
        if (!$this->isSquare()) {
 | 
			
		||||
            throw new Exception("Matrix must be square!");
 | 
			
		||||
        if (! $this->isSquare()) {
 | 
			
		||||
            throw new Exception('Matrix must be square!');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if ($this->_rowCount == 1) {
 | 
			
		||||
@@ -117,6 +121,7 @@ class Matrix
 | 
			
		||||
            $b = $this->_matrixRowData[0][1];
 | 
			
		||||
            $c = $this->_matrixRowData[1][0];
 | 
			
		||||
            $d = $this->_matrixRowData[1][1];
 | 
			
		||||
 | 
			
		||||
            return $a * $d - $b * $c;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -141,8 +146,8 @@ class Matrix
 | 
			
		||||
 | 
			
		||||
    public function getAdjugate()
 | 
			
		||||
    {
 | 
			
		||||
        if (!$this->isSquare()) {
 | 
			
		||||
            throw new Exception("Matrix must be square!");
 | 
			
		||||
        if (! $this->isSquare()) {
 | 
			
		||||
            throw new Exception('Matrix must be square!');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // See http://en.wikipedia.org/wiki/Adjugate_matrix
 | 
			
		||||
@@ -165,7 +170,7 @@ class Matrix
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // The idea is that it's the transpose of the cofactors
 | 
			
		||||
        $result = array();
 | 
			
		||||
        $result = [];
 | 
			
		||||
 | 
			
		||||
        for ($currentColumn = 0; $currentColumn < $this->_columnCount; $currentColumn++) {
 | 
			
		||||
            for ($currentRow = 0; $currentRow < $this->_rowCount; $currentRow++) {
 | 
			
		||||
@@ -194,7 +199,7 @@ class Matrix
 | 
			
		||||
    {
 | 
			
		||||
        $rows = $matrix->getRowCount();
 | 
			
		||||
        $columns = $matrix->getColumnCount();
 | 
			
		||||
        $newValues = array();
 | 
			
		||||
        $newValues = [];
 | 
			
		||||
 | 
			
		||||
        for ($currentRow = 0; $currentRow < $rows; $currentRow++) {
 | 
			
		||||
            for ($currentColumn = 0; $currentColumn < $columns; $currentColumn++) {
 | 
			
		||||
@@ -212,12 +217,12 @@ class Matrix
 | 
			
		||||
            ||
 | 
			
		||||
            ($left->getColumnCount() != $right->getColumnCount())
 | 
			
		||||
        ) {
 | 
			
		||||
            throw new Exception("Matrices must be of the same size");
 | 
			
		||||
            throw new Exception('Matrices must be of the same size');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // simple addition of each item
 | 
			
		||||
 | 
			
		||||
        $resultMatrix = array();
 | 
			
		||||
        $resultMatrix = [];
 | 
			
		||||
 | 
			
		||||
        for ($currentRow = 0; $currentRow < $left->getRowCount(); $currentRow++) {
 | 
			
		||||
            for ($currentColumn = 0; $currentColumn < $right->getColumnCount(); $currentColumn++) {
 | 
			
		||||
@@ -237,13 +242,13 @@ class Matrix
 | 
			
		||||
        // See http://en.wikipedia.org/wiki/Matrix_multiplication for details
 | 
			
		||||
 | 
			
		||||
        if ($left->getColumnCount() != $right->getRowCount()) {
 | 
			
		||||
            throw new Exception("The width of the left matrix must match the height of the right matrix");
 | 
			
		||||
            throw new Exception('The width of the left matrix must match the height of the right matrix');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $resultRows = $left->getRowCount();
 | 
			
		||||
        $resultColumns = $right->getColumnCount();
 | 
			
		||||
 | 
			
		||||
        $resultMatrix = array();
 | 
			
		||||
        $resultMatrix = [];
 | 
			
		||||
 | 
			
		||||
        for ($currentRow = 0; $currentRow < $resultRows; $currentRow++) {
 | 
			
		||||
            for ($currentColumn = 0; $currentColumn < $resultColumns; $currentColumn++) {
 | 
			
		||||
@@ -268,7 +273,7 @@ class Matrix
 | 
			
		||||
        // See http://en.wikipedia.org/wiki/Minor_(linear_algebra)
 | 
			
		||||
 | 
			
		||||
        // I'm going to use a horribly naïve algorithm... because I can :)
 | 
			
		||||
        $result = array();
 | 
			
		||||
        $result = [];
 | 
			
		||||
 | 
			
		||||
        $actualRow = 0;
 | 
			
		||||
 | 
			
		||||
@@ -334,4 +339,4 @@ class Matrix
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,6 @@
 | 
			
		||||
<?php namespace DNW\Skills\Numerics;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills\Numerics;
 | 
			
		||||
 | 
			
		||||
// The whole purpose of this class is to make the code for the SkillCalculator(s)
 | 
			
		||||
// look a little cleaner
 | 
			
		||||
@@ -8,13 +10,13 @@ use Exception;
 | 
			
		||||
class Range
 | 
			
		||||
{
 | 
			
		||||
    private $_min;
 | 
			
		||||
 | 
			
		||||
    private $_max;
 | 
			
		||||
 | 
			
		||||
    public function __construct($min, $max)
 | 
			
		||||
    {
 | 
			
		||||
        if ($min > $max)
 | 
			
		||||
        {
 | 
			
		||||
            throw new Exception("min > max");
 | 
			
		||||
        if ($min > $max) {
 | 
			
		||||
            throw new Exception('min > max');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $this->_min = $min;
 | 
			
		||||
@@ -50,11 +52,11 @@ class Range
 | 
			
		||||
 | 
			
		||||
    public static function atLeast($minimumValue)
 | 
			
		||||
    {
 | 
			
		||||
        return static::create($minimumValue, PHP_INT_MAX );
 | 
			
		||||
        return static::create($minimumValue, PHP_INT_MAX);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function isInRange($value)
 | 
			
		||||
    {
 | 
			
		||||
        return ($this->_min <= $value) && ($value <= $this->_max);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,16 @@
 | 
			
		||||
<?php namespace DNW\Skills\Numerics;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills\Numerics;
 | 
			
		||||
 | 
			
		||||
class SquareMatrix extends Matrix
 | 
			
		||||
{
 | 
			
		||||
    public function __construct()
 | 
			
		||||
    {
 | 
			
		||||
        $allValues = func_get_args();
 | 
			
		||||
        $rows = (int)sqrt(count($allValues));
 | 
			
		||||
        $rows = (int) sqrt(count($allValues));
 | 
			
		||||
        $cols = $rows;
 | 
			
		||||
 | 
			
		||||
        $matrixData = array();
 | 
			
		||||
        $matrixData = [];
 | 
			
		||||
        $allValuesIndex = 0;
 | 
			
		||||
 | 
			
		||||
        for ($currentRow = 0; $currentRow < $rows; $currentRow++) {
 | 
			
		||||
@@ -19,4 +21,4 @@ class SquareMatrix extends Matrix
 | 
			
		||||
 | 
			
		||||
        parent::__construct($rows, $cols, $matrixData);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,13 +1,15 @@
 | 
			
		||||
<?php namespace DNW\Skills\Numerics;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills\Numerics;
 | 
			
		||||
 | 
			
		||||
class Vector extends Matrix
 | 
			
		||||
{
 | 
			
		||||
    public function __construct(array $vectorValues)
 | 
			
		||||
    {
 | 
			
		||||
        $columnValues = array();
 | 
			
		||||
        $columnValues = [];
 | 
			
		||||
        foreach ($vectorValues as $currentVectorValue) {
 | 
			
		||||
            $columnValues[] = array($currentVectorValue);
 | 
			
		||||
            $columnValues[] = [$currentVectorValue];
 | 
			
		||||
        }
 | 
			
		||||
        parent::__construct(count($vectorValues), 1, $columnValues);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,24 +1,29 @@
 | 
			
		||||
<?php namespace DNW\Skills;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Represents a comparison between two players.
 | 
			
		||||
 *
 | 
			
		||||
 * @internal The actual values for the enum were chosen so that the also correspond to the multiplier for updates to means.
 | 
			
		||||
 */
 | 
			
		||||
class PairwiseComparison
 | 
			
		||||
{
 | 
			
		||||
    const WIN = 1;
 | 
			
		||||
 | 
			
		||||
    const DRAW = 0;
 | 
			
		||||
 | 
			
		||||
    const LOSE = -1;
 | 
			
		||||
 | 
			
		||||
    public static function getRankFromComparison($comparison)
 | 
			
		||||
    {
 | 
			
		||||
        switch ($comparison) {
 | 
			
		||||
            case PairwiseComparison::WIN:
 | 
			
		||||
                return array(1, 2);
 | 
			
		||||
                return [1, 2];
 | 
			
		||||
            case PairwiseComparison::LOSE:
 | 
			
		||||
                return array(2, 1);
 | 
			
		||||
                return [2, 1];
 | 
			
		||||
            default:
 | 
			
		||||
                return array(1, 1);
 | 
			
		||||
                return [1, 1];
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,6 @@
 | 
			
		||||
<?php namespace DNW\Skills;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills;
 | 
			
		||||
 | 
			
		||||
class PartialPlay
 | 
			
		||||
{
 | 
			
		||||
@@ -6,7 +8,7 @@ class PartialPlay
 | 
			
		||||
    {
 | 
			
		||||
        // If the player doesn't support the interface, assume 1.0 == 100%
 | 
			
		||||
        $supportsPartialPlay = $player instanceof ISupportPartialPlay;
 | 
			
		||||
        if (!$supportsPartialPlay) {
 | 
			
		||||
        if (! $supportsPartialPlay) {
 | 
			
		||||
            return 1.0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -20,4 +22,4 @@ class PartialPlay
 | 
			
		||||
 | 
			
		||||
        return $partialPlayPercentage;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,6 @@
 | 
			
		||||
<?php namespace DNW\Skills;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Represents a player who has a Rating.
 | 
			
		||||
@@ -6,26 +8,29 @@
 | 
			
		||||
class Player implements ISupportPartialPlay, ISupportPartialUpdate
 | 
			
		||||
{
 | 
			
		||||
    const DEFAULT_PARTIAL_PLAY_PERCENTAGE = 1.0; // = 100% play time
 | 
			
		||||
 | 
			
		||||
    const DEFAULT_PARTIAL_UPDATE_PERCENTAGE = 1.0; // = receive 100% update
 | 
			
		||||
 | 
			
		||||
    private $_Id;
 | 
			
		||||
 | 
			
		||||
    private $_PartialPlayPercentage;
 | 
			
		||||
 | 
			
		||||
    private $_PartialUpdatePercentage;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Constructs a player.
 | 
			
		||||
     *
 | 
			
		||||
     * @param mixed $id The identifier for the player, such as a name.
 | 
			
		||||
     * @param number $partialPlayPercentage The weight percentage to give this player when calculating a new rank.
 | 
			
		||||
     * @param number $partialUpdatePercentage Indicated how much of a skill update a player should receive where 0 represents no update and 1.0 represents 100% of the update.
 | 
			
		||||
     * @param  mixed  $id The identifier for the player, such as a name.
 | 
			
		||||
     * @param  number  $partialPlayPercentage The weight percentage to give this player when calculating a new rank.
 | 
			
		||||
     * @param  number  $partialUpdatePercentage Indicated how much of a skill update a player should receive where 0 represents no update and 1.0 represents 100% of the update.
 | 
			
		||||
     */
 | 
			
		||||
    public function __construct($id,
 | 
			
		||||
                                $partialPlayPercentage = self::DEFAULT_PARTIAL_PLAY_PERCENTAGE,
 | 
			
		||||
                                $partialUpdatePercentage = self::DEFAULT_PARTIAL_UPDATE_PERCENTAGE)
 | 
			
		||||
    {
 | 
			
		||||
        // If they don't want to give a player an id, that's ok...
 | 
			
		||||
        Guard::argumentInRangeInclusive($partialPlayPercentage, 0.0, 1.0, "partialPlayPercentage");
 | 
			
		||||
        Guard::argumentInRangeInclusive($partialUpdatePercentage, 0, 1.0, "partialUpdatePercentage");
 | 
			
		||||
        Guard::argumentInRangeInclusive($partialPlayPercentage, 0.0, 1.0, 'partialPlayPercentage');
 | 
			
		||||
        Guard::argumentInRangeInclusive($partialUpdatePercentage, 0, 1.0, 'partialUpdatePercentage');
 | 
			
		||||
        $this->_Id = $id;
 | 
			
		||||
        $this->_PartialPlayPercentage = $partialPlayPercentage;
 | 
			
		||||
        $this->_PartialUpdatePercentage = $partialUpdatePercentage;
 | 
			
		||||
@@ -57,6 +62,6 @@ class Player implements ISupportPartialPlay, ISupportPartialUpdate
 | 
			
		||||
 | 
			
		||||
    public function __toString()
 | 
			
		||||
    {
 | 
			
		||||
        return (string)$this->_Id;
 | 
			
		||||
        return (string) $this->_Id;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,6 @@
 | 
			
		||||
<?php namespace DNW\Skills;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills;
 | 
			
		||||
 | 
			
		||||
use DNW\Skills\Numerics\Range;
 | 
			
		||||
 | 
			
		||||
@@ -13,4 +15,4 @@ class PlayersRange extends Range
 | 
			
		||||
    {
 | 
			
		||||
        return new PlayersRange($min, $max);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,6 @@
 | 
			
		||||
<?php namespace DNW\Skills;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Helper class to sort ranks in non-decreasing order.
 | 
			
		||||
@@ -8,13 +10,14 @@ class RankSorter
 | 
			
		||||
    /**
 | 
			
		||||
     * Performs an in-place sort of the items in according to the ranks in non-decreasing order.
 | 
			
		||||
     *
 | 
			
		||||
     * @param array $teams The items to sort according to the order specified by ranks.
 | 
			
		||||
     * @param array $teamRanks The ranks for each item where 1 is first place.
 | 
			
		||||
     * @param  array  $teams The items to sort according to the order specified by ranks.
 | 
			
		||||
     * @param  array  $teamRanks The ranks for each item where 1 is first place.
 | 
			
		||||
     * @return array
 | 
			
		||||
     */
 | 
			
		||||
    public static function sort(array &$teams, array &$teamRanks)
 | 
			
		||||
    {
 | 
			
		||||
        array_multisort($teamRanks, $teams);
 | 
			
		||||
 | 
			
		||||
        return $teams;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,6 @@
 | 
			
		||||
<?php namespace DNW\Skills;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills;
 | 
			
		||||
 | 
			
		||||
// Container for a player's rating.
 | 
			
		||||
use DNW\Skills\Numerics\GaussianDistribution;
 | 
			
		||||
@@ -8,14 +10,17 @@ class Rating
 | 
			
		||||
    const CONSERVATIVE_STANDARD_DEVIATION_MULTIPLIER = 3;
 | 
			
		||||
 | 
			
		||||
    private $_conservativeStandardDeviationMultiplier;
 | 
			
		||||
 | 
			
		||||
    private $_mean;
 | 
			
		||||
 | 
			
		||||
    private $_standardDeviation;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Constructs a rating.
 | 
			
		||||
     * @param double $mean The statistical mean value of the rating (also known as mu).
 | 
			
		||||
     * @param double $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.
 | 
			
		||||
     *
 | 
			
		||||
     * @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.
 | 
			
		||||
     */
 | 
			
		||||
    public function __construct($mean, $standardDeviation, $conservativeStandardDeviationMultiplier = self::CONSERVATIVE_STANDARD_DEVIATION_MULTIPLIER)
 | 
			
		||||
    {
 | 
			
		||||
@@ -51,7 +56,7 @@ class Rating
 | 
			
		||||
    public function getPartialUpdate(Rating $prior, Rating $fullPosterior, $updatePercentage)
 | 
			
		||||
    {
 | 
			
		||||
        $priorGaussian = new GaussianDistribution($prior->getMean(), $prior->getStandardDeviation());
 | 
			
		||||
        $posteriorGaussian = new GaussianDistribution($fullPosterior->getMean(), $fullPosterior . getStandardDeviation());
 | 
			
		||||
        $posteriorGaussian = new GaussianDistribution($fullPosterior->getMean(), $fullPosterior.getStandardDeviation());
 | 
			
		||||
 | 
			
		||||
        // From a clarification email from Ralf Herbrich:
 | 
			
		||||
        // "the idea is to compute a linear interpolation between the prior and posterior skills of each player
 | 
			
		||||
@@ -60,7 +65,7 @@ class Rating
 | 
			
		||||
        $precisionDifference = $posteriorGaussian->getPrecision() - $priorGaussian->getPrecision();
 | 
			
		||||
        $partialPrecisionDifference = $updatePercentage * $precisionDifference;
 | 
			
		||||
 | 
			
		||||
        $precisionMeanDifference = $posteriorGaussian->getPrecisionMean() - $priorGaussian . getPrecisionMean();
 | 
			
		||||
        $precisionMeanDifference = $posteriorGaussian->getPrecisionMean() - $priorGaussian.getPrecisionMean();
 | 
			
		||||
        $partialPrecisionMeanDifference = $updatePercentage * $precisionMeanDifference;
 | 
			
		||||
 | 
			
		||||
        $partialPosteriorGaussion = GaussianDistribution::fromPrecisionMean(
 | 
			
		||||
@@ -73,6 +78,6 @@ class Rating
 | 
			
		||||
 | 
			
		||||
    public function __toString()
 | 
			
		||||
    {
 | 
			
		||||
        return sprintf("mean=%.4f, standardDeviation=%.4f", $this->_mean, $this->_standardDeviation);
 | 
			
		||||
        return sprintf('mean=%.4f, standardDeviation=%.4f', $this->_mean, $this->_standardDeviation);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,6 @@
 | 
			
		||||
<?php namespace DNW\Skills;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills;
 | 
			
		||||
 | 
			
		||||
class RatingContainer
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,6 @@
 | 
			
		||||
<?php namespace DNW\Skills;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills;
 | 
			
		||||
 | 
			
		||||
use Exception;
 | 
			
		||||
 | 
			
		||||
@@ -8,7 +10,9 @@ use Exception;
 | 
			
		||||
abstract class SkillCalculator
 | 
			
		||||
{
 | 
			
		||||
    private $_supportedOptions;
 | 
			
		||||
 | 
			
		||||
    private $_playersPerTeamAllowed;
 | 
			
		||||
 | 
			
		||||
    private $_totalTeamsAllowed;
 | 
			
		||||
 | 
			
		||||
    protected function __construct($supportedOptions, TeamsRange $totalTeamsAllowed, PlayersRange $playerPerTeamAllowed)
 | 
			
		||||
@@ -20,24 +24,24 @@ abstract class SkillCalculator
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Calculates new ratings based on the prior ratings and team ranks.
 | 
			
		||||
     * @param GameInfo $gameInfo Parameters for the game.
 | 
			
		||||
     * @param array $teamsOfPlayerToRatings A mapping of team players and their ratings.
 | 
			
		||||
     * @param array $teamRanks The ranks of the teams where 1 is first place. For a tie, repeat the number (e.g. 1, 2, 2).
 | 
			
		||||
     *
 | 
			
		||||
     * @param  GameInfo  $gameInfo Parameters for the game.
 | 
			
		||||
     * @param  array  $teamsOfPlayerToRatings A mapping of team players and their ratings.
 | 
			
		||||
     * @param  array  $teamRanks The ranks of the teams where 1 is first place. For a tie, repeat the number (e.g. 1, 2, 2).
 | 
			
		||||
     * @return All the players and their new ratings.
 | 
			
		||||
     */
 | 
			
		||||
    public abstract function calculateNewRatings(GameInfo $gameInfo,
 | 
			
		||||
    abstract public function calculateNewRatings(GameInfo $gameInfo,
 | 
			
		||||
                                                 array $teamsOfPlayerToRatings,
 | 
			
		||||
                                                 array $teamRanks);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Calculates the match quality as the likelihood of all teams drawing.
 | 
			
		||||
     *
 | 
			
		||||
     * @param GameInfo $gameInfo Parameters for the game.
 | 
			
		||||
     * @param array $teamsOfPlayerToRatings A mapping of team players and their ratings.
 | 
			
		||||
     * @param  GameInfo  $gameInfo Parameters for the game.
 | 
			
		||||
     * @param  array  $teamsOfPlayerToRatings A mapping of team players and their ratings.
 | 
			
		||||
     * @return The quality of the match between the teams as a percentage (0% = bad, 100% = well matched).
 | 
			
		||||
     */
 | 
			
		||||
    public abstract function calculateMatchQuality(GameInfo $gameInfo, array $teamsOfPlayerToRatings);
 | 
			
		||||
    abstract public function calculateMatchQuality(GameInfo $gameInfo, array $teamsOfPlayerToRatings);
 | 
			
		||||
 | 
			
		||||
    public function isSupported($option)
 | 
			
		||||
    {
 | 
			
		||||
@@ -49,21 +53,19 @@ abstract class SkillCalculator
 | 
			
		||||
        self::validateTeamCountAndPlayersCountPerTeamWithRanges($teamsOfPlayerToRatings, $this->_totalTeamsAllowed, $this->_playersPerTeamAllowed);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static function validateTeamCountAndPlayersCountPerTeamWithRanges(array $teams,
 | 
			
		||||
                                                                              TeamsRange $totalTeams,
 | 
			
		||||
                                                                              PlayersRange $playersPerTeam)
 | 
			
		||||
    private static function validateTeamCountAndPlayersCountPerTeamWithRanges(array $teams, TeamsRange $totalTeams, PlayersRange $playersPerTeam)
 | 
			
		||||
    {
 | 
			
		||||
        $countOfTeams = 0;
 | 
			
		||||
 | 
			
		||||
        foreach ($teams as $currentTeam) {
 | 
			
		||||
            if (!$playersPerTeam->isInRange(count($currentTeam))) {
 | 
			
		||||
                throw new Exception("Player count is not in range");
 | 
			
		||||
            if (! $playersPerTeam->isInRange(count($currentTeam))) {
 | 
			
		||||
                throw new Exception('Player count is not in range');
 | 
			
		||||
            }
 | 
			
		||||
            $countOfTeams++;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!$totalTeams->isInRange($countOfTeams)) {
 | 
			
		||||
            throw new Exception("Team range is not in range");
 | 
			
		||||
        if (! $totalTeams->isInRange($countOfTeams)) {
 | 
			
		||||
            throw new Exception('Team range is not in range');
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -71,6 +73,8 @@ abstract class SkillCalculator
 | 
			
		||||
class SkillCalculatorSupportedOptions
 | 
			
		||||
{
 | 
			
		||||
    const NONE = 0x00;
 | 
			
		||||
 | 
			
		||||
    const PARTIAL_PLAY = 0x01;
 | 
			
		||||
 | 
			
		||||
    const PARTIAL_UPDATE = 0x02;
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										10
									
								
								src/Team.php
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								src/Team.php
									
									
									
									
									
								
							@@ -1,4 +1,6 @@
 | 
			
		||||
<?php namespace DNW\Skills;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills;
 | 
			
		||||
 | 
			
		||||
class Team extends RatingContainer
 | 
			
		||||
{
 | 
			
		||||
@@ -6,8 +8,7 @@ class Team extends RatingContainer
 | 
			
		||||
    {
 | 
			
		||||
        parent::__construct();
 | 
			
		||||
 | 
			
		||||
        if(!is_null($player))
 | 
			
		||||
        {
 | 
			
		||||
        if (! is_null($player)) {
 | 
			
		||||
            $this->addPlayer($player, $rating);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@@ -15,6 +16,7 @@ class Team extends RatingContainer
 | 
			
		||||
    public function addPlayer(Player $player, Rating $rating)
 | 
			
		||||
    {
 | 
			
		||||
        $this->setRating($player, $rating);
 | 
			
		||||
 | 
			
		||||
        return $this;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,13 @@
 | 
			
		||||
<?php namespace DNW\Skills;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills;
 | 
			
		||||
 | 
			
		||||
class Teams
 | 
			
		||||
{
 | 
			
		||||
    public static function concat(/*variable arguments*/)
 | 
			
		||||
    {
 | 
			
		||||
        $args = func_get_args();
 | 
			
		||||
        $result = array();
 | 
			
		||||
        $result = [];
 | 
			
		||||
 | 
			
		||||
        foreach ($args as $currentTeam) {
 | 
			
		||||
            $localCurrentTeam = $currentTeam;
 | 
			
		||||
@@ -14,4 +16,4 @@ class Teams
 | 
			
		||||
 | 
			
		||||
        return $result;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,6 @@
 | 
			
		||||
<?php namespace DNW\Skills;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills;
 | 
			
		||||
 | 
			
		||||
use DNW\Skills\Numerics\Range;
 | 
			
		||||
 | 
			
		||||
@@ -13,4 +15,4 @@ class TeamsRange extends Range
 | 
			
		||||
    {
 | 
			
		||||
        return new TeamsRange($min, $max);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,6 @@
 | 
			
		||||
<?php namespace DNW\Skills\TrueSkill;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills\TrueSkill;
 | 
			
		||||
 | 
			
		||||
use DNW\Skills\Numerics\GaussianDistribution;
 | 
			
		||||
 | 
			
		||||
@@ -16,4 +18,4 @@ final class DrawMargin
 | 
			
		||||
        // n1 and n2 are the number of players on each team
 | 
			
		||||
        return GaussianDistribution::inverseCumulativeTo(.5 * ($drawProbability + 1), 0, 1) * sqrt(1 + 1) * $beta;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,9 @@
 | 
			
		||||
<?php namespace DNW\Skills\TrueSkill;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills\TrueSkill;
 | 
			
		||||
 | 
			
		||||
use DNW\Skills\GameInfo;
 | 
			
		||||
use DNW\Skills\Guard;
 | 
			
		||||
use DNW\Skills\ISupportPartialPlay;
 | 
			
		||||
use DNW\Skills\ISupportPartialUpdate;
 | 
			
		||||
use DNW\Skills\Numerics\BasicMath;
 | 
			
		||||
use DNW\Skills\Numerics\DiagonalMatrix;
 | 
			
		||||
use DNW\Skills\Numerics\Matrix;
 | 
			
		||||
@@ -29,7 +29,7 @@ class FactorGraphTrueSkillCalculator extends SkillCalculator
 | 
			
		||||
                                        array $teams,
 | 
			
		||||
                                        array $teamRanks)
 | 
			
		||||
    {
 | 
			
		||||
        Guard::argumentNotNull($gameInfo, "gameInfo");
 | 
			
		||||
        Guard::argumentNotNull($gameInfo, 'gameInfo');
 | 
			
		||||
        $this->validateTeamCountAndPlayersCountPerTeam($teams);
 | 
			
		||||
 | 
			
		||||
        RankSorter::sort($teams, $teamRanks);
 | 
			
		||||
@@ -109,7 +109,7 @@ class FactorGraphTrueSkillCalculator extends SkillCalculator
 | 
			
		||||
    // Helper function that gets a list of values for all player ratings
 | 
			
		||||
    private static function getPlayerRatingValues(array $teamAssignmentsList, $playerRatingFunction)
 | 
			
		||||
    {
 | 
			
		||||
        $playerRatingValues = array();
 | 
			
		||||
        $playerRatingValues = [];
 | 
			
		||||
 | 
			
		||||
        foreach ($teamAssignmentsList as $currentTeam) {
 | 
			
		||||
            foreach ($currentTeam->getAllRatings() as $currentRating) {
 | 
			
		||||
@@ -138,7 +138,7 @@ class FactorGraphTrueSkillCalculator extends SkillCalculator
 | 
			
		||||
        // | -0.75  0.75 |
 | 
			
		||||
        // |  0.00 -1.00 |
 | 
			
		||||
 | 
			
		||||
        $playerAssignments = array();
 | 
			
		||||
        $playerAssignments = [];
 | 
			
		||||
        $totalPreviousPlayers = 0;
 | 
			
		||||
 | 
			
		||||
        $teamAssignmentsListCount = count($teamAssignmentsList);
 | 
			
		||||
@@ -150,7 +150,7 @@ class FactorGraphTrueSkillCalculator extends SkillCalculator
 | 
			
		||||
 | 
			
		||||
            // Need to add in 0's for all the previous players, since they're not
 | 
			
		||||
            // on this team
 | 
			
		||||
            $playerAssignments[$currentColumn] = ($totalPreviousPlayers > 0) ? \array_fill(0, $totalPreviousPlayers, 0) : array();
 | 
			
		||||
            $playerAssignments[$currentColumn] = ($totalPreviousPlayers > 0) ? \array_fill(0, $totalPreviousPlayers, 0) : [];
 | 
			
		||||
 | 
			
		||||
            foreach ($currentTeam->getAllPlayers() as $currentPlayer) {
 | 
			
		||||
                $playerAssignments[$currentColumn][] = PartialPlay::getPartialPlayPercentage($currentPlayer);
 | 
			
		||||
@@ -179,4 +179,4 @@ class FactorGraphTrueSkillCalculator extends SkillCalculator
 | 
			
		||||
 | 
			
		||||
        return $playerTeamAssignmentsMatrix;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,6 @@
 | 
			
		||||
<?php namespace DNW\Skills\TrueSkill\Factors;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills\TrueSkill\Factors;
 | 
			
		||||
 | 
			
		||||
use DNW\Skills\FactorGraphs\Factor;
 | 
			
		||||
use DNW\Skills\FactorGraphs\Message;
 | 
			
		||||
@@ -14,8 +16,9 @@ abstract class GaussianFactor extends Factor
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sends the factor-graph message with and returns the log-normalization constant.
 | 
			
		||||
     * @param Message $message
 | 
			
		||||
     * @param Variable $variable
 | 
			
		||||
     *
 | 
			
		||||
     * @param  Message  $message
 | 
			
		||||
     * @param  Variable  $variable
 | 
			
		||||
     * @return float|int
 | 
			
		||||
     */
 | 
			
		||||
    protected function sendMessageVariable(Message $message, Variable $variable)
 | 
			
		||||
@@ -24,6 +27,7 @@ abstract class GaussianFactor extends Factor
 | 
			
		||||
        $messageValue = $message->getValue();
 | 
			
		||||
        $logZ = GaussianDistribution::logProductNormalization($marginal, $messageValue);
 | 
			
		||||
        $variable->setValue(GaussianDistribution::multiply($marginal, $messageValue));
 | 
			
		||||
 | 
			
		||||
        return $logZ;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -33,7 +37,8 @@ abstract class GaussianFactor extends Factor
 | 
			
		||||
        $binding = parent::createVariableToMessageBindingWithMessage($variable,
 | 
			
		||||
            new Message(
 | 
			
		||||
                $newDistribution,
 | 
			
		||||
                sprintf("message from %s to %s", $this, $variable)));
 | 
			
		||||
                sprintf('message from %s to %s', $this, $variable)));
 | 
			
		||||
 | 
			
		||||
        return $binding;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,11 @@
 | 
			
		||||
<?php namespace DNW\Skills\TrueSkill\Factors;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills\TrueSkill\Factors;
 | 
			
		||||
 | 
			
		||||
use DNW\Skills\Numerics\GaussianDistribution;
 | 
			
		||||
use DNW\Skills\TrueSkill\TruncatedGaussianCorrectionFunctions;
 | 
			
		||||
use DNW\Skills\FactorGraphs\Message;
 | 
			
		||||
use DNW\Skills\FactorGraphs\Variable;
 | 
			
		||||
use DNW\Skills\Numerics\GaussianDistribution;
 | 
			
		||||
use DNW\Skills\TrueSkill\TruncatedGaussianCorrectionFunctions;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Factor representing a team difference that has exceeded the draw margin.
 | 
			
		||||
@@ -16,7 +18,7 @@ class GaussianGreaterThanFactor extends GaussianFactor
 | 
			
		||||
 | 
			
		||||
    public function __construct($epsilon, Variable $variable)
 | 
			
		||||
    {
 | 
			
		||||
        parent::__construct(\sprintf("%s > %.2f", $variable, $epsilon));
 | 
			
		||||
        parent::__construct(\sprintf('%s > %.2f', $variable, $epsilon));
 | 
			
		||||
        $this->_epsilon = $epsilon;
 | 
			
		||||
        $this->createVariableToMessageBinding($variable);
 | 
			
		||||
    }
 | 
			
		||||
@@ -31,6 +33,7 @@ class GaussianGreaterThanFactor extends GaussianFactor
 | 
			
		||||
        $messages = $this->getMessages();
 | 
			
		||||
        $message = $messages[0]->getValue();
 | 
			
		||||
        $messageFromVariable = GaussianDistribution::divide($marginal, $message);
 | 
			
		||||
 | 
			
		||||
        return -GaussianDistribution::logProductNormalization($messageFromVariable, $message)
 | 
			
		||||
        +
 | 
			
		||||
        log(
 | 
			
		||||
@@ -39,7 +42,6 @@ class GaussianGreaterThanFactor extends GaussianFactor
 | 
			
		||||
                $messageFromVariable->getStandardDeviation()
 | 
			
		||||
            )
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected function updateMessageVariable(Message $message, Variable $variable)
 | 
			
		||||
@@ -82,4 +84,4 @@ class GaussianGreaterThanFactor extends GaussianFactor
 | 
			
		||||
        // Return the difference in the new marginal
 | 
			
		||||
        return GaussianDistribution::subtract($newMarginal, $oldMarginal);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,12 @@
 | 
			
		||||
<?php namespace DNW\Skills\TrueSkill\Factors;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills\TrueSkill\Factors;
 | 
			
		||||
 | 
			
		||||
use Exception;
 | 
			
		||||
use DNW\Skills\FactorGraphs\KeyedVariable;
 | 
			
		||||
use DNW\Skills\FactorGraphs\Message;
 | 
			
		||||
use DNW\Skills\FactorGraphs\Variable;
 | 
			
		||||
use DNW\Skills\Numerics\GaussianDistribution;
 | 
			
		||||
use Exception;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Connects two variables and adds uncertainty.
 | 
			
		||||
@@ -17,7 +19,7 @@ class GaussianLikelihoodFactor extends GaussianFactor
 | 
			
		||||
 | 
			
		||||
    public function __construct($betaSquared, Variable $variable1, Variable $variable2)
 | 
			
		||||
    {
 | 
			
		||||
        parent::__construct(sprintf("Likelihood of %s going to %s", $variable2, $variable1));
 | 
			
		||||
        parent::__construct(sprintf('Likelihood of %s going to %s', $variable2, $variable1));
 | 
			
		||||
        $this->_precision = 1.0 / $betaSquared;
 | 
			
		||||
        $this->createVariableToMessageBinding($variable1);
 | 
			
		||||
        $this->createVariableToMessageBinding($variable2);
 | 
			
		||||
@@ -80,4 +82,4 @@ class GaussianLikelihoodFactor extends GaussianFactor
 | 
			
		||||
                throw new Exception();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,6 @@
 | 
			
		||||
<?php namespace DNW\Skills\TrueSkill\Factors;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills\TrueSkill\Factors;
 | 
			
		||||
 | 
			
		||||
use DNW\Skills\FactorGraphs\Message;
 | 
			
		||||
use DNW\Skills\FactorGraphs\Variable;
 | 
			
		||||
@@ -15,10 +17,10 @@ class GaussianPriorFactor extends GaussianFactor
 | 
			
		||||
 | 
			
		||||
    public function __construct($mean, $variance, Variable $variable)
 | 
			
		||||
    {
 | 
			
		||||
        parent::__construct(sprintf("Prior value going to %s", $variable));
 | 
			
		||||
        parent::__construct(sprintf('Prior value going to %s', $variable));
 | 
			
		||||
        $this->_newMessage = new GaussianDistribution($mean, sqrt($variance));
 | 
			
		||||
        $newMessage = new Message(GaussianDistribution::fromPrecisionMean(0, 0),
 | 
			
		||||
            sprintf("message from %s to %s", $this, $variable));
 | 
			
		||||
            sprintf('message from %s to %s', $this, $variable));
 | 
			
		||||
 | 
			
		||||
        $this->createVariableToMessageBindingWithMessage($variable, $newMessage);
 | 
			
		||||
    }
 | 
			
		||||
@@ -34,6 +36,7 @@ class GaussianPriorFactor extends GaussianFactor
 | 
			
		||||
 | 
			
		||||
        $variable->setValue($newMarginal);
 | 
			
		||||
        $message->setValue($this->_newMessage);
 | 
			
		||||
 | 
			
		||||
        return GaussianDistribution::subtract($oldMarginal, $newMarginal);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,10 @@
 | 
			
		||||
<?php namespace DNW\Skills\TrueSkill\Factors;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills\TrueSkill\Factors;
 | 
			
		||||
 | 
			
		||||
use DNW\Skills\Guard;
 | 
			
		||||
use DNW\Skills\FactorGraphs\Message;
 | 
			
		||||
use DNW\Skills\FactorGraphs\Variable;
 | 
			
		||||
use DNW\Skills\Guard;
 | 
			
		||||
use DNW\Skills\Numerics\BasicMath;
 | 
			
		||||
use DNW\Skills\Numerics\GaussianDistribution;
 | 
			
		||||
 | 
			
		||||
@@ -13,18 +15,19 @@ use DNW\Skills\Numerics\GaussianDistribution;
 | 
			
		||||
 */
 | 
			
		||||
class GaussianWeightedSumFactor extends GaussianFactor
 | 
			
		||||
{
 | 
			
		||||
    private $_variableIndexOrdersForWeights = array();
 | 
			
		||||
    private $_variableIndexOrdersForWeights = [];
 | 
			
		||||
 | 
			
		||||
    // This following is used for convenience, for example, the first entry is [0, 1, 2]
 | 
			
		||||
    // corresponding to v[0] = a1*v[1] + a2*v[2]
 | 
			
		||||
    private $_weights;
 | 
			
		||||
 | 
			
		||||
    private $_weightsSquared;
 | 
			
		||||
 | 
			
		||||
    public function __construct(Variable $sumVariable, array $variablesToSum, array $variableWeights = null)
 | 
			
		||||
    {
 | 
			
		||||
        parent::__construct(self::createName($sumVariable, $variablesToSum, $variableWeights));
 | 
			
		||||
        $this->_weights = array();
 | 
			
		||||
        $this->_weightsSquared = array();
 | 
			
		||||
        $this->_weights = [];
 | 
			
		||||
        $this->_weightsSquared = [];
 | 
			
		||||
 | 
			
		||||
        // The first weights are a straightforward copy
 | 
			
		||||
        // v_0 = a_1*v_1 + a_2*v_2 + ... + a_n * v_n
 | 
			
		||||
@@ -40,7 +43,7 @@ class GaussianWeightedSumFactor extends GaussianFactor
 | 
			
		||||
        $variablesToSumLength = count($variablesToSum);
 | 
			
		||||
 | 
			
		||||
        // 0..n-1
 | 
			
		||||
        $this->_variableIndexOrdersForWeights[0] = array();
 | 
			
		||||
        $this->_variableIndexOrdersForWeights[0] = [];
 | 
			
		||||
        for ($i = 0; $i < ($variablesToSumLength + 1); $i++) {
 | 
			
		||||
            $this->_variableIndexOrdersForWeights[0][] = $i;
 | 
			
		||||
        }
 | 
			
		||||
@@ -178,6 +181,7 @@ class GaussianWeightedSumFactor extends GaussianFactor
 | 
			
		||||
 | 
			
		||||
        // Return the difference in the new marginal
 | 
			
		||||
        $finalDiff = GaussianDistribution::subtract($newMarginal, $marginal0);
 | 
			
		||||
 | 
			
		||||
        return $finalDiff;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -186,10 +190,10 @@ class GaussianWeightedSumFactor extends GaussianFactor
 | 
			
		||||
        $allMessages = $this->getMessages();
 | 
			
		||||
        $allVariables = $this->getVariables();
 | 
			
		||||
 | 
			
		||||
        Guard::argumentIsValidIndex($messageIndex, count($allMessages), "messageIndex");
 | 
			
		||||
        Guard::argumentIsValidIndex($messageIndex, count($allMessages), 'messageIndex');
 | 
			
		||||
 | 
			
		||||
        $updatedMessages = array();
 | 
			
		||||
        $updatedVariables = array();
 | 
			
		||||
        $updatedMessages = [];
 | 
			
		||||
        $updatedVariables = [];
 | 
			
		||||
 | 
			
		||||
        $indicesToUse = $this->_variableIndexOrdersForWeights[$messageIndex];
 | 
			
		||||
 | 
			
		||||
@@ -211,7 +215,7 @@ class GaussianWeightedSumFactor extends GaussianFactor
 | 
			
		||||
    private static function createName($sumVariable, $variablesToSum, $weights)
 | 
			
		||||
    {
 | 
			
		||||
        // TODO: Perf? Use PHP equivalent of StringBuilder? implode on arrays?
 | 
			
		||||
        $result = (string)$sumVariable;
 | 
			
		||||
        $result = (string) $sumVariable;
 | 
			
		||||
        $result .= ' = ';
 | 
			
		||||
 | 
			
		||||
        $totalVars = count($variablesToSum);
 | 
			
		||||
@@ -222,15 +226,15 @@ class GaussianWeightedSumFactor extends GaussianFactor
 | 
			
		||||
                $result .= '-';
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $absValue = sprintf("%.2f", \abs($weights[$i])); // 0.00?
 | 
			
		||||
            $absValue = sprintf('%.2f', \abs($weights[$i])); // 0.00?
 | 
			
		||||
            $result .= $absValue;
 | 
			
		||||
            $result .= "*[";
 | 
			
		||||
            $result .= (string)$variablesToSum[$i];
 | 
			
		||||
            $result .= '*[';
 | 
			
		||||
            $result .= (string) $variablesToSum[$i];
 | 
			
		||||
            $result .= ']';
 | 
			
		||||
 | 
			
		||||
            $isLast = ($i == ($totalVars - 1));
 | 
			
		||||
 | 
			
		||||
            if (!$isLast) {
 | 
			
		||||
            if (! $isLast) {
 | 
			
		||||
                if ($weights[$i + 1] >= 0) {
 | 
			
		||||
                    $result .= ' + ';
 | 
			
		||||
                } else {
 | 
			
		||||
@@ -241,4 +245,4 @@ class GaussianWeightedSumFactor extends GaussianFactor
 | 
			
		||||
 | 
			
		||||
        return $result;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,11 @@
 | 
			
		||||
<?php namespace DNW\Skills\TrueSkill\Factors;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills\TrueSkill\Factors;
 | 
			
		||||
 | 
			
		||||
use DNW\Skills\Numerics\GaussianDistribution;
 | 
			
		||||
use DNW\Skills\TrueSkill\TruncatedGaussianCorrectionFunctions;
 | 
			
		||||
use DNW\Skills\FactorGraphs\Message;
 | 
			
		||||
use DNW\Skills\FactorGraphs\Variable;
 | 
			
		||||
use DNW\Skills\Numerics\GaussianDistribution;
 | 
			
		||||
use DNW\Skills\TrueSkill\TruncatedGaussianCorrectionFunctions;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Factor representing a team difference that has not exceeded the draw margin.
 | 
			
		||||
@@ -16,7 +18,7 @@ class GaussianWithinFactor extends GaussianFactor
 | 
			
		||||
 | 
			
		||||
    public function __construct($epsilon, Variable $variable)
 | 
			
		||||
    {
 | 
			
		||||
        parent::__construct(sprintf("%s <= %.2f", $variable, $epsilon));
 | 
			
		||||
        parent::__construct(sprintf('%s <= %.2f', $variable, $epsilon));
 | 
			
		||||
        $this->_epsilon = $epsilon;
 | 
			
		||||
        $this->createVariableToMessageBinding($variable);
 | 
			
		||||
    }
 | 
			
		||||
@@ -57,7 +59,7 @@ class GaussianWithinFactor extends GaussianFactor
 | 
			
		||||
 | 
			
		||||
        $denominator = 1.0 - TruncatedGaussianCorrectionFunctions::wWithinMargin($dOnSqrtC, $epsilonTimesSqrtC);
 | 
			
		||||
        $newPrecision = $c / $denominator;
 | 
			
		||||
        $newPrecisionMean = (   $d +
 | 
			
		||||
        $newPrecisionMean = ($d +
 | 
			
		||||
                                $sqrtC *
 | 
			
		||||
                                TruncatedGaussianCorrectionFunctions::vWithinMargin($dOnSqrtC, $epsilonTimesSqrtC)
 | 
			
		||||
                            ) / $denominator;
 | 
			
		||||
@@ -75,4 +77,4 @@ class GaussianWithinFactor extends GaussianFactor
 | 
			
		||||
        // Return the difference in the new marginal
 | 
			
		||||
        return GaussianDistribution::subtract($newMarginal, $oldMarginal);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,15 +1,18 @@
 | 
			
		||||
<?php namespace DNW\Skills\TrueSkill\Layers;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills\TrueSkill\Layers;
 | 
			
		||||
 | 
			
		||||
use Exception;
 | 
			
		||||
use DNW\Skills\FactorGraphs\ScheduleLoop;
 | 
			
		||||
use DNW\Skills\FactorGraphs\ScheduleSequence;
 | 
			
		||||
use DNW\Skills\FactorGraphs\ScheduleStep;
 | 
			
		||||
use DNW\Skills\TrueSkill\TrueSkillFactorGraph;
 | 
			
		||||
use Exception;
 | 
			
		||||
 | 
			
		||||
// The whole purpose of this is to do a loop on the bottom
 | 
			
		||||
class IteratedTeamDifferencesInnerLayer extends TrueSkillFactorGraphLayer
 | 
			
		||||
{
 | 
			
		||||
    private $_TeamDifferencesComparisonLayer;
 | 
			
		||||
 | 
			
		||||
    private $_TeamPerformancesToTeamPerformanceDifferencesLayer;
 | 
			
		||||
 | 
			
		||||
    public function __construct(TrueSkillFactorGraph $parentGraph,
 | 
			
		||||
@@ -65,16 +68,16 @@ class IteratedTeamDifferencesInnerLayer extends TrueSkillFactorGraphLayer
 | 
			
		||||
        $lastDifferencesFactor = $localFactors[$totalTeamDifferences - 1];
 | 
			
		||||
 | 
			
		||||
        $innerSchedule = new ScheduleSequence(
 | 
			
		||||
            "inner schedule",
 | 
			
		||||
            array(
 | 
			
		||||
            'inner schedule',
 | 
			
		||||
            [
 | 
			
		||||
                $loop,
 | 
			
		||||
                new ScheduleStep(
 | 
			
		||||
                    "teamPerformanceToPerformanceDifferenceFactors[0] @ 1",
 | 
			
		||||
                    'teamPerformanceToPerformanceDifferenceFactors[0] @ 1',
 | 
			
		||||
                    $firstDifferencesFactor, 1),
 | 
			
		||||
                new ScheduleStep(
 | 
			
		||||
                    sprintf("teamPerformanceToPerformanceDifferenceFactors[teamTeamDifferences = %d - 1] @ 2", $totalTeamDifferences),
 | 
			
		||||
                    $lastDifferencesFactor, 2)
 | 
			
		||||
            )
 | 
			
		||||
                    sprintf('teamPerformanceToPerformanceDifferenceFactors[teamTeamDifferences = %d - 1] @ 2', $totalTeamDifferences),
 | 
			
		||||
                    $lastDifferencesFactor, 2),
 | 
			
		||||
            ]
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        return $innerSchedule;
 | 
			
		||||
@@ -87,27 +90,27 @@ class IteratedTeamDifferencesInnerLayer extends TrueSkillFactorGraphLayer
 | 
			
		||||
 | 
			
		||||
        $firstPerfToTeamDiff = $teamPerformancesToTeamPerformanceDifferencesLayerLocalFactors[0];
 | 
			
		||||
        $firstTeamDiffComparison = $teamDifferencesComparisonLayerLocalFactors[0];
 | 
			
		||||
        $itemsToSequence = array(
 | 
			
		||||
        $itemsToSequence = [
 | 
			
		||||
            new ScheduleStep(
 | 
			
		||||
                "send team perf to perf differences",
 | 
			
		||||
                'send team perf to perf differences',
 | 
			
		||||
                $firstPerfToTeamDiff,
 | 
			
		||||
                0),
 | 
			
		||||
            new ScheduleStep(
 | 
			
		||||
                "send to greater than or within factor",
 | 
			
		||||
                'send to greater than or within factor',
 | 
			
		||||
                $firstTeamDiffComparison,
 | 
			
		||||
                0)
 | 
			
		||||
        );
 | 
			
		||||
                0),
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
        return $this->scheduleSequence(
 | 
			
		||||
            $itemsToSequence,
 | 
			
		||||
            "loop of just two teams inner sequence");
 | 
			
		||||
            'loop of just two teams inner sequence');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function createMultipleTeamInnerPriorLoopSchedule()
 | 
			
		||||
    {
 | 
			
		||||
        $totalTeamDifferences = count($this->_TeamPerformancesToTeamPerformanceDifferencesLayer->getLocalFactors());
 | 
			
		||||
 | 
			
		||||
        $forwardScheduleList = array();
 | 
			
		||||
        $forwardScheduleList = [];
 | 
			
		||||
 | 
			
		||||
        for ($i = 0; $i < $totalTeamDifferences - 1; $i++) {
 | 
			
		||||
            $teamPerformancesToTeamPerformanceDifferencesLayerLocalFactors = $this->_TeamPerformancesToTeamPerformanceDifferencesLayer->getLocalFactors();
 | 
			
		||||
@@ -118,24 +121,24 @@ class IteratedTeamDifferencesInnerLayer extends TrueSkillFactorGraphLayer
 | 
			
		||||
 | 
			
		||||
            $currentForwardSchedulePiece =
 | 
			
		||||
                $this->scheduleSequence(
 | 
			
		||||
                    array(
 | 
			
		||||
                    [
 | 
			
		||||
                        new ScheduleStep(
 | 
			
		||||
                            sprintf("team perf to perf diff %d", $i),
 | 
			
		||||
                            sprintf('team perf to perf diff %d', $i),
 | 
			
		||||
                            $currentTeamPerfToTeamPerfDiff, 0),
 | 
			
		||||
                        new ScheduleStep(
 | 
			
		||||
                            sprintf("greater than or within result factor %d", $i),
 | 
			
		||||
                            sprintf('greater than or within result factor %d', $i),
 | 
			
		||||
                            $currentTeamDiffComparison, 0),
 | 
			
		||||
                        new ScheduleStep(
 | 
			
		||||
                            sprintf("team perf to perf diff factors [%d], 2", $i),
 | 
			
		||||
                            $currentTeamPerfToTeamPerfDiff, 2)
 | 
			
		||||
                    ), sprintf("current forward schedule piece %d", $i));
 | 
			
		||||
                            sprintf('team perf to perf diff factors [%d], 2', $i),
 | 
			
		||||
                            $currentTeamPerfToTeamPerfDiff, 2),
 | 
			
		||||
                    ], sprintf('current forward schedule piece %d', $i));
 | 
			
		||||
 | 
			
		||||
            $forwardScheduleList[] = $currentForwardSchedulePiece;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $forwardSchedule = new ScheduleSequence("forward schedule", $forwardScheduleList);
 | 
			
		||||
        $forwardSchedule = new ScheduleSequence('forward schedule', $forwardScheduleList);
 | 
			
		||||
 | 
			
		||||
        $backwardScheduleList = array();
 | 
			
		||||
        $backwardScheduleList = [];
 | 
			
		||||
 | 
			
		||||
        for ($i = 0; $i < $totalTeamDifferences - 1; $i++) {
 | 
			
		||||
            $teamPerformancesToTeamPerformanceDifferencesLayerLocalFactors = $this->_TeamPerformancesToTeamPerformanceDifferencesLayer->getLocalFactors();
 | 
			
		||||
@@ -146,35 +149,35 @@ class IteratedTeamDifferencesInnerLayer extends TrueSkillFactorGraphLayer
 | 
			
		||||
            $performancesToDifferencesFactor = $teamPerformancesToTeamPerformanceDifferencesLayerLocalFactors[$totalTeamDifferences - 1 - $i];
 | 
			
		||||
 | 
			
		||||
            $currentBackwardSchedulePiece = new ScheduleSequence(
 | 
			
		||||
                "current backward schedule piece",
 | 
			
		||||
                array(
 | 
			
		||||
                'current backward schedule piece',
 | 
			
		||||
                [
 | 
			
		||||
                    new ScheduleStep(
 | 
			
		||||
                        sprintf("teamPerformanceToPerformanceDifferenceFactors[totalTeamDifferences - 1 - %d] @ 0", $i),
 | 
			
		||||
                        sprintf('teamPerformanceToPerformanceDifferenceFactors[totalTeamDifferences - 1 - %d] @ 0', $i),
 | 
			
		||||
                        $differencesFactor, 0),
 | 
			
		||||
                    new ScheduleStep(
 | 
			
		||||
                        sprintf("greaterThanOrWithinResultFactors[totalTeamDifferences - 1 - %d] @ 0", $i),
 | 
			
		||||
                        sprintf('greaterThanOrWithinResultFactors[totalTeamDifferences - 1 - %d] @ 0', $i),
 | 
			
		||||
                        $comparisonFactor, 0),
 | 
			
		||||
                    new ScheduleStep(
 | 
			
		||||
                        sprintf("teamPerformanceToPerformanceDifferenceFactors[totalTeamDifferences - 1 - %d] @ 1", $i),
 | 
			
		||||
                        $performancesToDifferencesFactor, 1)
 | 
			
		||||
                ));
 | 
			
		||||
                        sprintf('teamPerformanceToPerformanceDifferenceFactors[totalTeamDifferences - 1 - %d] @ 1', $i),
 | 
			
		||||
                        $performancesToDifferencesFactor, 1),
 | 
			
		||||
                ]);
 | 
			
		||||
            $backwardScheduleList[] = $currentBackwardSchedulePiece;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $backwardSchedule = new ScheduleSequence("backward schedule", $backwardScheduleList);
 | 
			
		||||
        $backwardSchedule = new ScheduleSequence('backward schedule', $backwardScheduleList);
 | 
			
		||||
 | 
			
		||||
        $forwardBackwardScheduleToLoop =
 | 
			
		||||
            new ScheduleSequence(
 | 
			
		||||
                "forward Backward Schedule To Loop",
 | 
			
		||||
                array($forwardSchedule, $backwardSchedule));
 | 
			
		||||
                'forward Backward Schedule To Loop',
 | 
			
		||||
                [$forwardSchedule, $backwardSchedule]);
 | 
			
		||||
 | 
			
		||||
        $initialMaxDelta = 0.0001;
 | 
			
		||||
 | 
			
		||||
        $loop = new ScheduleLoop(
 | 
			
		||||
            sprintf("loop with max delta of %f", $initialMaxDelta),
 | 
			
		||||
            sprintf('loop with max delta of %f', $initialMaxDelta),
 | 
			
		||||
            $forwardBackwardScheduleToLoop,
 | 
			
		||||
            $initialMaxDelta);
 | 
			
		||||
 | 
			
		||||
        return $loop;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,9 @@
 | 
			
		||||
<?php namespace DNW\Skills\TrueSkill\Layers;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills\TrueSkill\Layers;
 | 
			
		||||
 | 
			
		||||
use DNW\Skills\PartialPlay;
 | 
			
		||||
use DNW\Skills\FactorGraphs\ScheduleLoop;
 | 
			
		||||
use DNW\Skills\FactorGraphs\ScheduleSequence;
 | 
			
		||||
use DNW\Skills\FactorGraphs\ScheduleStep;
 | 
			
		||||
use DNW\Skills\PartialPlay;
 | 
			
		||||
use DNW\Skills\TrueSkill\Factors\GaussianWeightedSumFactor;
 | 
			
		||||
use DNW\Skills\TrueSkill\TrueSkillFactorGraph;
 | 
			
		||||
 | 
			
		||||
@@ -26,7 +26,7 @@ class PlayerPerformancesToTeamPerformancesLayer extends TrueSkillFactorGraphLaye
 | 
			
		||||
 | 
			
		||||
            // REVIEW: Does it make sense to have groups of one?
 | 
			
		||||
            $outputVariablesGroups = &$this->getOutputVariablesGroups();
 | 
			
		||||
            $outputVariablesGroups[] = array($teamPerformance);
 | 
			
		||||
            $outputVariablesGroups[] = [$teamPerformance];
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -37,10 +37,11 @@ class PlayerPerformancesToTeamPerformancesLayer extends TrueSkillFactorGraphLaye
 | 
			
		||||
        $sequence = $this->scheduleSequence(
 | 
			
		||||
            array_map(
 | 
			
		||||
                function ($weightedSumFactor) {
 | 
			
		||||
                    return new ScheduleStep("Perf to Team Perf Step", $weightedSumFactor, 0);
 | 
			
		||||
                    return new ScheduleStep('Perf to Team Perf Step', $weightedSumFactor, 0);
 | 
			
		||||
                },
 | 
			
		||||
                $localFactors),
 | 
			
		||||
            "all player perf to team perf schedule");
 | 
			
		||||
            'all player perf to team perf schedule');
 | 
			
		||||
 | 
			
		||||
        return $sequence;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -49,6 +50,7 @@ class PlayerPerformancesToTeamPerformancesLayer extends TrueSkillFactorGraphLaye
 | 
			
		||||
        $weights = array_map(
 | 
			
		||||
            function ($v) {
 | 
			
		||||
                $player = $v->getKey();
 | 
			
		||||
 | 
			
		||||
                return PartialPlay::getPartialPlayPercentage($player);
 | 
			
		||||
            },
 | 
			
		||||
            $teamMembers);
 | 
			
		||||
@@ -57,32 +59,33 @@ class PlayerPerformancesToTeamPerformancesLayer extends TrueSkillFactorGraphLaye
 | 
			
		||||
            $sumVariable,
 | 
			
		||||
            $teamMembers,
 | 
			
		||||
            $weights);
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function createPosteriorSchedule()
 | 
			
		||||
    {
 | 
			
		||||
        $allFactors = array();
 | 
			
		||||
        $allFactors = [];
 | 
			
		||||
        $localFactors = $this->getLocalFactors();
 | 
			
		||||
        foreach ($localFactors as $currentFactor) {
 | 
			
		||||
            $localCurrentFactor = $currentFactor;
 | 
			
		||||
            $numberOfMessages = $localCurrentFactor->getNumberOfMessages();
 | 
			
		||||
            for ($currentIteration = 1; $currentIteration < $numberOfMessages; $currentIteration++) {
 | 
			
		||||
                $allFactors[] = new ScheduleStep("team sum perf @" . $currentIteration,
 | 
			
		||||
                $allFactors[] = new ScheduleStep('team sum perf @'.$currentIteration,
 | 
			
		||||
                    $localCurrentFactor, $currentIteration);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $this->scheduleSequence($allFactors, "all of the team's sum iterations");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function createOutputVariable($team)
 | 
			
		||||
    {
 | 
			
		||||
        $memberNames = array_map(function ($currentPlayer) {
 | 
			
		||||
            return (string)($currentPlayer->getKey());
 | 
			
		||||
            return (string) ($currentPlayer->getKey());
 | 
			
		||||
        }, $team);
 | 
			
		||||
 | 
			
		||||
        $teamMemberNames = \join(", ", $memberNames);
 | 
			
		||||
        $outputVariable = $this->getParentFactorGraph()->getVariableFactory()->createBasicVariable("Team[" . $teamMemberNames . "]'s performance");
 | 
			
		||||
        $teamMemberNames = \implode(', ', $memberNames);
 | 
			
		||||
        $outputVariable = $this->getParentFactorGraph()->getVariableFactory()->createBasicVariable('Team['.$teamMemberNames."]'s performance");
 | 
			
		||||
 | 
			
		||||
        return $outputVariable;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,13 @@
 | 
			
		||||
<?php namespace DNW\Skills\TrueSkill\Layers;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills\TrueSkill\Layers;
 | 
			
		||||
 | 
			
		||||
use DNW\Skills\Numerics\BasicMath;
 | 
			
		||||
use DNW\Skills\Rating;
 | 
			
		||||
use DNW\Skills\FactorGraphs\ScheduleStep;
 | 
			
		||||
use DNW\Skills\FactorGraphs\Variable;
 | 
			
		||||
use DNW\Skills\TrueSkill\TrueSkillFactorGraph;
 | 
			
		||||
use DNW\Skills\Numerics\BasicMath;
 | 
			
		||||
use DNW\Skills\Rating;
 | 
			
		||||
use DNW\Skills\TrueSkill\Factors\GaussianPriorFactor;
 | 
			
		||||
use DNW\Skills\TrueSkill\TrueSkillFactorGraph;
 | 
			
		||||
 | 
			
		||||
// We intentionally have no Posterior schedule since the only purpose here is to
 | 
			
		||||
// start the process.
 | 
			
		||||
@@ -24,7 +26,7 @@ class PlayerPriorValuesToSkillsLayer extends TrueSkillFactorGraphLayer
 | 
			
		||||
        $teams = $this->_teams;
 | 
			
		||||
        foreach ($teams as $currentTeam) {
 | 
			
		||||
            $localCurrentTeam = $currentTeam;
 | 
			
		||||
            $currentTeamSkills = array();
 | 
			
		||||
            $currentTeamSkills = [];
 | 
			
		||||
 | 
			
		||||
            $currentTeamAllPlayers = $localCurrentTeam->getAllPlayers();
 | 
			
		||||
            foreach ($currentTeamAllPlayers as $currentTeamPlayer) {
 | 
			
		||||
@@ -44,13 +46,14 @@ class PlayerPriorValuesToSkillsLayer extends TrueSkillFactorGraphLayer
 | 
			
		||||
    public function createPriorSchedule()
 | 
			
		||||
    {
 | 
			
		||||
        $localFactors = $this->getLocalFactors();
 | 
			
		||||
 | 
			
		||||
        return $this->scheduleSequence(
 | 
			
		||||
            array_map(
 | 
			
		||||
                function ($prior) {
 | 
			
		||||
                    return new ScheduleStep("Prior to Skill Step", $prior, 0);
 | 
			
		||||
                    return new ScheduleStep('Prior to Skill Step', $prior, 0);
 | 
			
		||||
                },
 | 
			
		||||
                $localFactors),
 | 
			
		||||
            "All priors");
 | 
			
		||||
            'All priors');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function createPriorFactor($player, Rating $priorRating, Variable $skillsVariable)
 | 
			
		||||
@@ -67,7 +70,8 @@ class PlayerPriorValuesToSkillsLayer extends TrueSkillFactorGraphLayer
 | 
			
		||||
    {
 | 
			
		||||
        $parentFactorGraph = $this->getParentFactorGraph();
 | 
			
		||||
        $variableFactory = $parentFactorGraph->getVariableFactory();
 | 
			
		||||
        $skillOutputVariable = $variableFactory->createKeyedVariable($key, $key . "'s skill");
 | 
			
		||||
        $skillOutputVariable = $variableFactory->createKeyedVariable($key, $key."'s skill");
 | 
			
		||||
 | 
			
		||||
        return $skillOutputVariable;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,12 @@
 | 
			
		||||
<?php namespace DNW\Skills\TrueSkill\Layers;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills\TrueSkill\Layers;
 | 
			
		||||
 | 
			
		||||
use DNW\Skills\FactorGraphs\ScheduleStep;
 | 
			
		||||
use DNW\Skills\FactorGraphs\KeyedVariable;
 | 
			
		||||
use DNW\Skills\FactorGraphs\ScheduleStep;
 | 
			
		||||
use DNW\Skills\Numerics\BasicMath;
 | 
			
		||||
use DNW\Skills\TrueSkill\TrueSkillFactorGraph;
 | 
			
		||||
use DNW\Skills\TrueSkill\Factors\GaussianLikelihoodFactor;
 | 
			
		||||
use DNW\Skills\TrueSkill\TrueSkillFactorGraph;
 | 
			
		||||
 | 
			
		||||
class PlayerSkillsToPerformancesLayer extends TrueSkillFactorGraphLayer
 | 
			
		||||
{
 | 
			
		||||
@@ -19,7 +21,7 @@ class PlayerSkillsToPerformancesLayer extends TrueSkillFactorGraphLayer
 | 
			
		||||
        $outputVariablesGroups = &$this->getOutputVariablesGroups();
 | 
			
		||||
 | 
			
		||||
        foreach ($inputVariablesGroups as $currentTeam) {
 | 
			
		||||
            $currentTeamPlayerPerformances = array();
 | 
			
		||||
            $currentTeamPlayerPerformances = [];
 | 
			
		||||
 | 
			
		||||
            foreach ($currentTeam as $playerSkillVariable) {
 | 
			
		||||
                $localPlayerSkillVariable = $playerSkillVariable;
 | 
			
		||||
@@ -45,31 +47,34 @@ class PlayerSkillsToPerformancesLayer extends TrueSkillFactorGraphLayer
 | 
			
		||||
 | 
			
		||||
    private function createOutputVariable($key)
 | 
			
		||||
    {
 | 
			
		||||
        $outputVariable = $this->getParentFactorGraph()->getVariableFactory()->createKeyedVariable($key, $key . "'s performance");
 | 
			
		||||
        $outputVariable = $this->getParentFactorGraph()->getVariableFactory()->createKeyedVariable($key, $key."'s performance");
 | 
			
		||||
 | 
			
		||||
        return $outputVariable;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function createPriorSchedule()
 | 
			
		||||
    {
 | 
			
		||||
        $localFactors = $this->getLocalFactors();
 | 
			
		||||
 | 
			
		||||
        return $this->scheduleSequence(
 | 
			
		||||
            array_map(
 | 
			
		||||
                function ($likelihood) {
 | 
			
		||||
                    return new ScheduleStep("Skill to Perf step", $likelihood, 0);
 | 
			
		||||
                    return new ScheduleStep('Skill to Perf step', $likelihood, 0);
 | 
			
		||||
                },
 | 
			
		||||
                $localFactors),
 | 
			
		||||
            "All skill to performance sending");
 | 
			
		||||
            'All skill to performance sending');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function createPosteriorSchedule()
 | 
			
		||||
    {
 | 
			
		||||
        $localFactors = $this->getLocalFactors();
 | 
			
		||||
 | 
			
		||||
        return $this->scheduleSequence(
 | 
			
		||||
            array_map(
 | 
			
		||||
                function ($likelihood) {
 | 
			
		||||
                    return new ScheduleStep("name", $likelihood, 1);
 | 
			
		||||
                    return new ScheduleStep('name', $likelihood, 1);
 | 
			
		||||
                },
 | 
			
		||||
                $localFactors),
 | 
			
		||||
            "All skill to performance sending");
 | 
			
		||||
            'All skill to performance sending');
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,13 +1,16 @@
 | 
			
		||||
<?php namespace DNW\Skills\TrueSkill\Layers;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills\TrueSkill\Layers;
 | 
			
		||||
 | 
			
		||||
use DNW\Skills\TrueSkill\DrawMargin;
 | 
			
		||||
use DNW\Skills\TrueSkill\TrueSkillFactorGraph;
 | 
			
		||||
use DNW\Skills\TrueSkill\Factors\GaussianGreaterThanFactor;
 | 
			
		||||
use DNW\Skills\TrueSkill\Factors\GaussianWithinFactor;
 | 
			
		||||
use DNW\Skills\TrueSkill\TrueSkillFactorGraph;
 | 
			
		||||
 | 
			
		||||
class TeamDifferencesComparisonLayer extends TrueSkillFactorGraphLayer
 | 
			
		||||
{
 | 
			
		||||
    private $_epsilon;
 | 
			
		||||
 | 
			
		||||
    private $_teamRanks;
 | 
			
		||||
 | 
			
		||||
    public function __construct(TrueSkillFactorGraph $parentGraph, array $teamRanks)
 | 
			
		||||
@@ -35,4 +38,4 @@ class TeamDifferencesComparisonLayer extends TrueSkillFactorGraphLayer
 | 
			
		||||
            $this->addLayerFactor($factor);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,10 @@
 | 
			
		||||
<?php namespace DNW\Skills\TrueSkill\Layers;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills\TrueSkill\Layers;
 | 
			
		||||
 | 
			
		||||
use DNW\Skills\FactorGraphs\Variable;
 | 
			
		||||
use DNW\Skills\TrueSkill\TrueSkillFactorGraph;
 | 
			
		||||
use DNW\Skills\TrueSkill\Factors\GaussianWeightedSumFactor;
 | 
			
		||||
use DNW\Skills\TrueSkill\TrueSkillFactorGraph;
 | 
			
		||||
 | 
			
		||||
class TeamPerformancesToTeamPerformanceDifferencesLayer extends TrueSkillFactorGraphLayer
 | 
			
		||||
{
 | 
			
		||||
@@ -17,8 +19,7 @@ class TeamPerformancesToTeamPerformanceDifferencesLayer extends TrueSkillFactorG
 | 
			
		||||
        $inputVariablesGroupsCount = count($inputVariablesGroups);
 | 
			
		||||
        $outputVariablesGroup = &$this->getOutputVariablesGroups();
 | 
			
		||||
 | 
			
		||||
        for ($i = 0; $i < $inputVariablesGroupsCount - 1; $i++)
 | 
			
		||||
        {
 | 
			
		||||
        for ($i = 0; $i < $inputVariablesGroupsCount - 1; $i++) {
 | 
			
		||||
            $strongerTeam = $inputVariablesGroups[$i][0];
 | 
			
		||||
            $weakerTeam = $inputVariablesGroups[$i + 1][0];
 | 
			
		||||
 | 
			
		||||
@@ -27,7 +28,7 @@ class TeamPerformancesToTeamPerformanceDifferencesLayer extends TrueSkillFactorG
 | 
			
		||||
            $this->addLayerFactor($newDifferencesFactor);
 | 
			
		||||
 | 
			
		||||
            // REVIEW: Does it make sense to have groups of one?
 | 
			
		||||
            $outputVariablesGroup[] = array($currentDifference);
 | 
			
		||||
            $outputVariablesGroup[] = [$currentDifference];
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -35,14 +36,16 @@ class TeamPerformancesToTeamPerformanceDifferencesLayer extends TrueSkillFactorG
 | 
			
		||||
                                                             Variable $weakerTeam,
 | 
			
		||||
                                                             Variable $output)
 | 
			
		||||
    {
 | 
			
		||||
        $teams = array($strongerTeam, $weakerTeam);
 | 
			
		||||
        $weights = array(1.0, -1.0);
 | 
			
		||||
        $teams = [$strongerTeam, $weakerTeam];
 | 
			
		||||
        $weights = [1.0, -1.0];
 | 
			
		||||
 | 
			
		||||
        return new GaussianWeightedSumFactor($output, $teams, $weights);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function createOutputVariable()
 | 
			
		||||
    {
 | 
			
		||||
        $outputVariable = $this->getParentFactorGraph()->getVariableFactory()->createBasicVariable("Team performance difference");
 | 
			
		||||
        $outputVariable = $this->getParentFactorGraph()->getVariableFactory()->createBasicVariable('Team performance difference');
 | 
			
		||||
 | 
			
		||||
        return $outputVariable;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,6 @@
 | 
			
		||||
<?php namespace DNW\Skills\TrueSkill\Layers;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills\TrueSkill\Layers;
 | 
			
		||||
 | 
			
		||||
use DNW\Skills\FactorGraphs\FactorGraphLayer;
 | 
			
		||||
use DNW\Skills\TrueSkill\TrueSkillFactorGraph;
 | 
			
		||||
@@ -9,4 +11,4 @@ abstract class TrueSkillFactorGraphLayer extends FactorGraphLayer
 | 
			
		||||
    {
 | 
			
		||||
        parent::__construct($parentGraph);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,13 +1,15 @@
 | 
			
		||||
<?php namespace DNW\Skills\TrueSkill;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills\TrueSkill;
 | 
			
		||||
 | 
			
		||||
use DNW\Skills\GameInfo;
 | 
			
		||||
use DNW\Skills\Numerics\GaussianDistribution;
 | 
			
		||||
use DNW\Skills\Rating;
 | 
			
		||||
use DNW\Skills\RatingContainer;
 | 
			
		||||
use DNW\Skills\FactorGraphs\FactorGraph;
 | 
			
		||||
use DNW\Skills\FactorGraphs\FactorList;
 | 
			
		||||
use DNW\Skills\FactorGraphs\ScheduleSequence;
 | 
			
		||||
use DNW\Skills\FactorGraphs\VariableFactory;
 | 
			
		||||
use DNW\Skills\GameInfo;
 | 
			
		||||
use DNW\Skills\Numerics\GaussianDistribution;
 | 
			
		||||
use DNW\Skills\Rating;
 | 
			
		||||
use DNW\Skills\RatingContainer;
 | 
			
		||||
use DNW\Skills\TrueSkill\Layers\IteratedTeamDifferencesInnerLayer;
 | 
			
		||||
use DNW\Skills\TrueSkill\Layers\PlayerPerformancesToTeamPerformancesLayer;
 | 
			
		||||
use DNW\Skills\TrueSkill\Layers\PlayerPriorValuesToSkillsLayer;
 | 
			
		||||
@@ -18,7 +20,9 @@ use DNW\Skills\TrueSkill\Layers\TeamPerformancesToTeamPerformanceDifferencesLaye
 | 
			
		||||
class TrueSkillFactorGraph extends FactorGraph
 | 
			
		||||
{
 | 
			
		||||
    private $_gameInfo;
 | 
			
		||||
 | 
			
		||||
    private $_layers;
 | 
			
		||||
 | 
			
		||||
    private $_priorLayer;
 | 
			
		||||
 | 
			
		||||
    public function __construct(GameInfo $gameInfo, array $teams, array $teamRanks)
 | 
			
		||||
@@ -31,15 +35,15 @@ class TrueSkillFactorGraph extends FactorGraph
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
        $this->setVariableFactory($newFactory);
 | 
			
		||||
        $this->_layers = array(
 | 
			
		||||
        $this->_layers = [
 | 
			
		||||
            $this->_priorLayer,
 | 
			
		||||
            new PlayerSkillsToPerformancesLayer($this),
 | 
			
		||||
            new PlayerPerformancesToTeamPerformancesLayer($this),
 | 
			
		||||
            new IteratedTeamDifferencesInnerLayer(
 | 
			
		||||
                $this,
 | 
			
		||||
                new TeamPerformancesToTeamPerformanceDifferencesLayer($this),
 | 
			
		||||
                new TeamDifferencesComparisonLayer($this, $teamRanks))
 | 
			
		||||
        );
 | 
			
		||||
                new TeamDifferencesComparisonLayer($this, $teamRanks)),
 | 
			
		||||
        ];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getGameInfo()
 | 
			
		||||
@@ -83,12 +87,13 @@ class TrueSkillFactorGraph extends FactorGraph
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $logZ = $factorList->getLogNormalization();
 | 
			
		||||
 | 
			
		||||
        return exp($logZ);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function createFullSchedule()
 | 
			
		||||
    {
 | 
			
		||||
        $fullSchedule = array();
 | 
			
		||||
        $fullSchedule = [];
 | 
			
		||||
 | 
			
		||||
        $layers = $this->_layers;
 | 
			
		||||
        foreach ($layers as $currentLayer) {
 | 
			
		||||
@@ -107,7 +112,7 @@ class TrueSkillFactorGraph extends FactorGraph
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return new ScheduleSequence("Full schedule", $fullSchedule);
 | 
			
		||||
        return new ScheduleSequence('Full schedule', $fullSchedule);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getUpdatedRatings()
 | 
			
		||||
@@ -127,4 +132,4 @@ class TrueSkillFactorGraph extends FactorGraph
 | 
			
		||||
 | 
			
		||||
        return $result;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,6 @@
 | 
			
		||||
<?php namespace DNW\Skills\TrueSkill;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills\TrueSkill;
 | 
			
		||||
 | 
			
		||||
use DNW\Skills\Numerics\GaussianDistribution;
 | 
			
		||||
 | 
			
		||||
@@ -13,7 +15,7 @@ class TruncatedGaussianCorrectionFunctions
 | 
			
		||||
     * correction of a single-sided truncated Gaussian with unit variance."
 | 
			
		||||
     *
 | 
			
		||||
     * @param $teamPerformanceDifference
 | 
			
		||||
     * @param number $drawMargin In the paper, it's referred to as just "ε".
 | 
			
		||||
     * @param  number  $drawMargin In the paper, it's referred to as just "ε".
 | 
			
		||||
     * @param $c
 | 
			
		||||
     * @return float
 | 
			
		||||
     */
 | 
			
		||||
@@ -57,10 +59,12 @@ class TruncatedGaussianCorrectionFunctions
 | 
			
		||||
            if ($teamPerformanceDifference < 0.0) {
 | 
			
		||||
                return 1.0;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return 0.0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $vWin = self::vExceedsMargin($teamPerformanceDifference, $drawMargin);
 | 
			
		||||
 | 
			
		||||
        return $vWin * ($vWin + $teamPerformanceDifference - $drawMargin);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -126,4 +130,4 @@ class TruncatedGaussianCorrectionFunctions
 | 
			
		||||
            *
 | 
			
		||||
            GaussianDistribution::at(-$drawMargin - $teamPerformanceDifferenceAbsoluteValue)) / $denominator;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,15 +1,17 @@
 | 
			
		||||
<?php namespace DNW\Skills\TrueSkill;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills\TrueSkill;
 | 
			
		||||
 | 
			
		||||
use DNW\Skills\GameInfo;
 | 
			
		||||
use DNW\Skills\Guard;
 | 
			
		||||
use DNW\Skills\Numerics\BasicMath;
 | 
			
		||||
use DNW\Skills\PairwiseComparison;
 | 
			
		||||
use DNW\Skills\PlayersRange;
 | 
			
		||||
use DNW\Skills\RankSorter;
 | 
			
		||||
use DNW\Skills\Rating;
 | 
			
		||||
use DNW\Skills\RatingContainer;
 | 
			
		||||
use DNW\Skills\SkillCalculator;
 | 
			
		||||
use DNW\Skills\SkillCalculatorSupportedOptions;
 | 
			
		||||
use DNW\Skills\PlayersRange;
 | 
			
		||||
use DNW\Skills\TeamsRange;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -30,7 +32,7 @@ class TwoPlayerTrueSkillCalculator extends SkillCalculator
 | 
			
		||||
                                        array $teamRanks)
 | 
			
		||||
    {
 | 
			
		||||
        // Basic argument checking
 | 
			
		||||
        Guard::argumentNotNull($gameInfo, "gameInfo");
 | 
			
		||||
        Guard::argumentNotNull($gameInfo, 'gameInfo');
 | 
			
		||||
        $this->validateTeamCountAndPlayersCountPerTeam($teams);
 | 
			
		||||
 | 
			
		||||
        // Make sure things are in order
 | 
			
		||||
@@ -83,8 +85,7 @@ class TwoPlayerTrueSkillCalculator extends SkillCalculator
 | 
			
		||||
        $winningMean = $selfRating->getMean();
 | 
			
		||||
        $losingMean = $opponentRating->getMean();
 | 
			
		||||
 | 
			
		||||
        switch ($comparison)
 | 
			
		||||
        {
 | 
			
		||||
        switch ($comparison) {
 | 
			
		||||
            case PairwiseComparison::WIN:
 | 
			
		||||
            case PairwiseComparison::DRAW:
 | 
			
		||||
                // NOP
 | 
			
		||||
@@ -97,37 +98,34 @@ class TwoPlayerTrueSkillCalculator extends SkillCalculator
 | 
			
		||||
 | 
			
		||||
        $meanDelta = $winningMean - $losingMean;
 | 
			
		||||
 | 
			
		||||
        if ($comparison != PairwiseComparison::DRAW)
 | 
			
		||||
        {
 | 
			
		||||
        if ($comparison != PairwiseComparison::DRAW) {
 | 
			
		||||
            // non-draw case
 | 
			
		||||
            $v = TruncatedGaussianCorrectionFunctions::vExceedsMarginScaled($meanDelta, $drawMargin, $c);
 | 
			
		||||
            $w = TruncatedGaussianCorrectionFunctions::wExceedsMarginScaled($meanDelta, $drawMargin, $c);
 | 
			
		||||
            $rankMultiplier = (int) $comparison;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
        } else {
 | 
			
		||||
            $v = TruncatedGaussianCorrectionFunctions::vWithinMarginScaled($meanDelta, $drawMargin, $c);
 | 
			
		||||
            $w = TruncatedGaussianCorrectionFunctions::wWithinMarginScaled($meanDelta, $drawMargin, $c);
 | 
			
		||||
            $rankMultiplier = 1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $meanMultiplier = (BasicMath::square($selfRating->getStandardDeviation()) + BasicMath::square($gameInfo->getDynamicsFactor()))/$c;
 | 
			
		||||
        $meanMultiplier = (BasicMath::square($selfRating->getStandardDeviation()) + BasicMath::square($gameInfo->getDynamicsFactor())) / $c;
 | 
			
		||||
 | 
			
		||||
        $varianceWithDynamics = BasicMath::square($selfRating->getStandardDeviation()) + BasicMath::square($gameInfo->getDynamicsFactor());
 | 
			
		||||
        $stdDevMultiplier = $varianceWithDynamics/BasicMath::square($c);
 | 
			
		||||
        $stdDevMultiplier = $varianceWithDynamics / BasicMath::square($c);
 | 
			
		||||
 | 
			
		||||
        $newMean = $selfRating->getMean() + ($rankMultiplier*$meanMultiplier*$v);
 | 
			
		||||
        $newStdDev = sqrt($varianceWithDynamics*(1 - $w*$stdDevMultiplier));
 | 
			
		||||
        $newMean = $selfRating->getMean() + ($rankMultiplier * $meanMultiplier * $v);
 | 
			
		||||
        $newStdDev = sqrt($varianceWithDynamics * (1 - $w * $stdDevMultiplier));
 | 
			
		||||
 | 
			
		||||
        return new Rating($newMean, $newStdDev);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * {@inheritdoc }
 | 
			
		||||
     * {@inheritdoc}
 | 
			
		||||
     */
 | 
			
		||||
    public function calculateMatchQuality(GameInfo $gameInfo, array $teams)
 | 
			
		||||
    {
 | 
			
		||||
        Guard::argumentNotNull($gameInfo, "gameInfo");
 | 
			
		||||
        Guard::argumentNotNull($gameInfo, 'gameInfo');
 | 
			
		||||
        $this->validateTeamCountAndPlayersCountPerTeam($teams);
 | 
			
		||||
 | 
			
		||||
        $team1 = $teams[0];
 | 
			
		||||
@@ -146,18 +144,18 @@ class TwoPlayerTrueSkillCalculator extends SkillCalculator
 | 
			
		||||
 | 
			
		||||
        // This is the square root part of the equation:
 | 
			
		||||
        $sqrtPart = sqrt(
 | 
			
		||||
            (2*$betaSquared)
 | 
			
		||||
            (2 * $betaSquared)
 | 
			
		||||
            /
 | 
			
		||||
            (2*$betaSquared + $player1SigmaSquared + $player2SigmaSquared)
 | 
			
		||||
            (2 * $betaSquared + $player1SigmaSquared + $player2SigmaSquared)
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        // This is the exponent part of the equation:
 | 
			
		||||
        $expPart = exp(
 | 
			
		||||
            (-1*BasicMath::square($player1Rating->getMean() - $player2Rating->getMean()))
 | 
			
		||||
            (-1 * BasicMath::square($player1Rating->getMean() - $player2Rating->getMean()))
 | 
			
		||||
            /
 | 
			
		||||
            (2*(2*$betaSquared + $player1SigmaSquared + $player2SigmaSquared))
 | 
			
		||||
            (2 * (2 * $betaSquared + $player1SigmaSquared + $player2SigmaSquared))
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        return $sqrtPart*$expPart;
 | 
			
		||||
        return $sqrtPart * $expPart;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,19 +1,19 @@
 | 
			
		||||
<?php namespace DNW\Skills\TrueSkill;
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace DNW\Skills\TrueSkill;
 | 
			
		||||
 | 
			
		||||
use DNW\Skills\GameInfo;
 | 
			
		||||
use DNW\Skills\Guard;
 | 
			
		||||
use DNW\Skills\Numerics\BasicMath;
 | 
			
		||||
use DNW\Skills\PairwiseComparison;
 | 
			
		||||
use DNW\Skills\PlayersRange;
 | 
			
		||||
use DNW\Skills\RankSorter;
 | 
			
		||||
use DNW\Skills\Rating;
 | 
			
		||||
use DNW\Skills\RatingContainer;
 | 
			
		||||
use DNW\Skills\SkillCalculator;
 | 
			
		||||
use DNW\Skills\SkillCalculatorSupportedOptions;
 | 
			
		||||
 | 
			
		||||
use DNW\Skills\PlayersRange;
 | 
			
		||||
use DNW\Skills\TeamsRange;
 | 
			
		||||
 | 
			
		||||
use DNW\Skills\Team;
 | 
			
		||||
use DNW\Skills\TeamsRange;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Calculates new ratings for only two teams where each team has 1 or more players.
 | 
			
		||||
@@ -29,7 +29,7 @@ class TwoTeamTrueSkillCalculator extends SkillCalculator
 | 
			
		||||
 | 
			
		||||
    public function calculateNewRatings(GameInfo $gameInfo, array $teams, array $teamRanks)
 | 
			
		||||
    {
 | 
			
		||||
        Guard::argumentNotNull($gameInfo, "gameInfo");
 | 
			
		||||
        Guard::argumentNotNull($gameInfo, 'gameInfo');
 | 
			
		||||
        $this->validateTeamCountAndPlayersCountPerTeam($teams);
 | 
			
		||||
 | 
			
		||||
        RankSorter::sort($teams, $teamRanks);
 | 
			
		||||
@@ -111,7 +111,7 @@ class TwoTeamTrueSkillCalculator extends SkillCalculator
 | 
			
		||||
            // non-draw case
 | 
			
		||||
            $v = TruncatedGaussianCorrectionFunctions::vExceedsMarginScaled($meanDelta, $drawMargin, $c);
 | 
			
		||||
            $w = TruncatedGaussianCorrectionFunctions::wExceedsMarginScaled($meanDelta, $drawMargin, $c);
 | 
			
		||||
            $rankMultiplier = (int)$selfToOtherTeamComparison;
 | 
			
		||||
            $rankMultiplier = (int) $selfToOtherTeamComparison;
 | 
			
		||||
        } else {
 | 
			
		||||
            // assume draw
 | 
			
		||||
            $v = TruncatedGaussianCorrectionFunctions::vWithinMarginScaled($meanDelta, $drawMargin, $c);
 | 
			
		||||
@@ -143,7 +143,7 @@ class TwoTeamTrueSkillCalculator extends SkillCalculator
 | 
			
		||||
     */
 | 
			
		||||
    public function calculateMatchQuality(GameInfo $gameInfo, array $teams)
 | 
			
		||||
    {
 | 
			
		||||
        Guard::argumentNotNull($gameInfo, "gameInfo");
 | 
			
		||||
        Guard::argumentNotNull($gameInfo, 'gameInfo');
 | 
			
		||||
        $this->validateTeamCountAndPlayersCountPerTeam($teams);
 | 
			
		||||
 | 
			
		||||
        // We've verified that there's just two teams
 | 
			
		||||
@@ -189,4 +189,4 @@ class TwoTeamTrueSkillCalculator extends SkillCalculator
 | 
			
		||||
 | 
			
		||||
        return $expPart * $sqrtPart;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user