How to translate this bit of Python to idiomatic Javascript

My code so far:

// The q constant of the Glicko system.
var q = Math.log(10) / 400;

function Player(rating, rd) {
    this.rating = rating || 1500;
    this.rd = rd || 200;
}

Player.prototype.preRatingRD = function(this, t, c) {
    // Set default values of t and c
    this.t = t || 1;
    this.c = c || 63.2;
    // Calculate the new rating deviation
    this.rd = Math.sqrt(Math.pow(this.rd, 2) + (Math.pow(c, 2) * t));
    // Ensure RD doesn't rise above that of an unrated player
    this.rd = Math.min(this.rd, 350);
    // Ensure RD doesn't drop too low so that rating can still change
    // appreciably
    this.rd = Math.max(this.rd, 30);
};
Player.prototype.g = function(this, rd) {
    return 1 / Math.sqrt(1 + 3 * Math.pow(q, 2) * Math.pow(rd, 2) / Math.pow(Math.PI, 2));
};
Player.prototype.e = function(this, p2rating, p2rd) {
    return 1 / (1 + Math.pow(10, (-1 * this.g(p2rd) * (this.rating - p2rating) / 400)));
};

I'm working on a JS/HTML implementation of the Glicko rating system and am heavily borrowing from pyglicko -- which is to say, completely ripping it off.

It's rather short (probably less than 100 LoC without comments) but I'm having my misgivings about whether my translation will work because honestly, I have no idea how Javascript scoping and this actually work. You can see what I have at the link at the top.

But in specific I'm wondering how you would express this bit of Python code in Javascript. Basically _d2 is inside a class definition for Player.

def _d2(self, rating_list, RD_list):
    tempSum = 0
    for i in range(len(rating_list)):
        tempE = self._E(rating_list[i], RD_list[i])
        tempSum += math.pow(self._g(RD_list[1]), 2) * tempE * (1 - tempE)
    return 1 / (math.pow(self._q, 2) * tempSum)

I've got the functions e and g defined like so, and q is a constant:

Player.prototype.e = function(this, ratingList, rdList) {
    // Stuff goes here
}

1 Answer

  1. Paul- Reply

    2019-11-16

    In Javascript you don't need o pass the self explicitly (Python is the "weird" one here, actually)

    Player.prototype.e = function(rating_list, RD_list){
        //replace "self" with "this" here:
        var tempSum = 0; //if you don't use the "var", tempSum will be a global
                         // instead of a local
        for(var i=0; i<rating_list.length; i++){ //plain old for loop - no foreach in JS
            var tempE = this._E( ... ); //note that in JS, just like in Python,
                                        //variables like this have function scope and
                                        //can be accessed outside the loop as well
            tempSum += Math.pow( ... ) //the Math namespace is always available
                                       //Javascript doesn't have a native module system
        }
        return (...);
    }
    

    This should work all right. The only tricky thing you need to know about this is that it is very promiscuous. This means that is is determined by how you call the function:

     obj.e(); //if you do a method-like call, the this will be set to obj
    

    However, there is no magic binding behind the scenes. The following works in python but does not work in Javascript:

     f = obj.e
     f(); //looks like a normal function call. This doesn't point to obj
    

Leave a Reply

Your email address will not be published. Required fields are marked *

You can use these HTML tags and attributes <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>