import { FatalError } from '../../DimensionError' ; export class ELOWrapper { constructor ( public kfactor , public startingScore ) { } param startingScore createRating ( startingScore = this . startingScore ) { return new ELORating ( startingScore ) ; } expectedScores1v1 ( p1 , p2 ) { const Q_1 = Math . pow ( 10 , p1 . score / 400 ) ; const Q_2 = Math . pow ( 10 , p2 . score / 400 ) ; const E_1 = Q_1 / ( Q_1 + Q_2 ) ; const E_2 = Q_2 / ( Q_1 + Q_2 ) ; return [ E_1 , E_2 ] ; } rate1v1 ( p1 , p2 , scores ) { const [ E_1 , E_2 ] = this . expectedScores1v1 ( p1 , p2 ) ; p1 . score = Math . round ( p1 . score + this . kfactor * ( scores [ 0 ] - E_1 ) ) ; p2 . score = Math . round ( p2 . score + this . kfactor * ( scores [ 1 ] - E_2 ) ) ; } rate ( ratings , ranks ) { if ( ranks . length != ratings . length ) throw new FatalError ( 'Ratings and ranks lengths do not match!' ) ; const expectedMatrix = [ ] ; const actualScores = [ ] ; for ( let i = 0 ; i < ratings . length ; i ++ ) { expectedMatrix . push ( new Array ( ratings . length ) ) ; actualScores . push ( 0 ) ; } for ( let i = 0 ; i < ratings . length ; i ++ ) { for ( let j = i + 1 ; j < ratings . length ; j ++ ) { const [ E_i , E_j ] = this . expectedScores1v1 ( ratings [ i ] , ratings [ j ] ) ; expectedMatrix [ i ] [ j ] = E_i ; expectedMatrix [ j ] [ i ] = E_j ; } } for ( let i = 0 ; i < ratings . length ; i ++ ) { let E_i_total = 0 ; for ( let j = 0 ; j < ratings . length ; j ++ ) { if ( j != i ) { E_i_total += expectedMatrix [ i ] [ j ] ; if ( ranks [ i ] > ranks [ j ] ) { actualScores [ i ] += 1 ; } else if ( ranks [ i ] == ranks [ j ] ) { actualScores [ i ] += 0.5 ; } } } ratings [ i ] . score = Math . round ( ratings [ i ] . score + this . kfactor * ( E_i_total - actualScores [ i ] ) ) ; } } } export class ELORating { constructor ( public score ) { } }