Skip to content

Instantly share code, notes, and snippets.

@Dorus
Created January 27, 2018 23:06
Show Gist options
  • Save Dorus/2cbb8960e83ffbbfa7ebd5f4de08e24d to your computer and use it in GitHub Desktop.
Save Dorus/2cbb8960e83ffbbfa7ebd5f4de08e24d to your computer and use it in GitHub Desktop.
"use strict";
var matches = 0;
// 'Borrowed' from http://www.math.ucla.edu/~tom/distributions/binomial.html
function LogGamma(Z) {
var S=1+76.18009173/Z-86.50532033/(Z+1)+24.01409822/(Z+2)-1.231739516/(Z+3)+.00120858003/(Z+4)-.00000536382/(Z+5);
var LG= (Z-.5)*Math.log(Z+4.5)-(Z+4.5)+Math.log(S*2.50662827465);
return LG
}
function Betinc(X,A,B) {
var A0=0;
var B0=1;
var A1=1;
var B1=1;
var M9=0;
var A2=0;
var C9;
while (Math.abs((A1-A2)/A1)>.00001) {
A2=A1;
C9=-(A+M9)*(A+B+M9)*X/(A+2*M9)/(A+2*M9+1);
A0=A1+C9*A0;
B0=B1+C9*B0;
M9=M9+1;
C9=M9*(B-M9)*X/(A+2*M9-1)/(A+2*M9);
A1=A0+C9*A1;
B1=B0+C9*B1;
A0=A0/B1;
B0=B0/B1;
A1=A1/B1;
B1=1;
}
return A1/A
}
function OddsToReachLimit(w, l, limit, goal) {
if (w === 0 || l === 0) return 1;
var X=limit*(1-goal)-l
var N=limit-w-l
var P=1-goal
var bincdf, Betacdf;
if (N<=0) {
console.log(`sample size must be positive must be positive ${N} w ${w} l ${l}`)
return 1;
// process.exit(1)
} else if ((P<0)||(P>1)) {
console.log(`probability must be between 0 and 1 ${P} w ${w} l ${l}`)
return 1;
// process.exit(1)
} else if (X<0) {
bincdf=0
} else if (X>=N) {
bincdf=1
} else {
X=Math.floor(X);
var Z=P;
var A=X+1;
var B=N-X;
var S=A+B;
var BT=Math.exp(LogGamma(S)-LogGamma(B)-LogGamma(A)+A*Math.log(Z)+B*Math.log(1-Z));
if (Z<(A+1)/(S+2)) {
Betacdf=BT*Betinc(Z,A,B)
} else {
Betacdf=1-BT*Betinc(1-Z,B,A)
}
bincdf=1-Betacdf;
}
bincdf=Math.round(bincdf*100000)/100000;
return bincdf;
}
function LL (x) {
return 1/(1+Math.pow(10,(-x/400)));
}
function LLR(W, L, elo0, elo1) {
//if (W==0 || L==0) return 0;
if (!W) W=1;
if (!L) L=1;
var N = W + L;
var w = W/N, l = L/N;
var s = w;
var m2 = w;
var variance = m2-Math.pow(s,2);
var variance_s = variance / N;
var s0 = LL(elo0);
var s1 = LL(elo1);
return (s1-s0)*(2*s-s0-s1)/variance_s/2.0;
}
function SPRT(W,L,elo0,elo1, alpha, beta)
//function SPRT(W,L)
{
//var elo0 = 0, elo1 = 35;
//var alpha = .05, beta = .05;
var LLR_ = LLR(W,L,elo0,elo1);
var LA = Math.log(beta/(1-alpha));
var LB = Math.log((1-beta)/alpha);
//console.log(LLR_ + " " + LA + " " + LB);
if (LLR_ > LB) {
return true;
} else if (LLR_ < LA) {
return false;
} else {
return null;
}
}
function check(w, l) {
if (_s5 && w+l>=400 && w >= 220 ) return true
if (_s6 && OddsToReachLimit(w, l, 400, 0.55) < _s7) return false
return SPRT(w, l, _s1, _s2, _s3, _s4);
//return SPRT(w, l, -13, 13, .04, .24);
}
function test(success) {
var win = 0, loss = 0;
for (var i = 0; i < 400; i++) {
matches++;
if (Math.random() < success) {
win++;
} else {
loss++;
}
var res = check(win, loss)
if (res !== null) {
return res;
}
}
return false; // undecided so we consider this a fail.
}
var trails = 1000
function testPerc(success) {
var fail = 0;
for (var i = 0; i < trails; i++) {
if (test(success) !== true) {
fail++;
}
}
return fail;
}
function calcResult() {
matches = 0;
var falsePass = Array(500)
.fill()
.map((x, i) => i / 1000.0)
.map(e => trails - testPerc(e))
.reduce(function(a, b) { return a + b; }, 0);
var falseFail = Array(500)
.fill()
.map((x, i) => i / 1000.0 + 0.5)
.map(e => testPerc(e))
.reduce(function(a, b) { return a + b; }, 0);
console.log([matches, falseFail, falsePass].join("|"));
}
function printResult() {
console.log();
console.log(`SPRT(${_s1}, ${_s2}, ${_s3}, ${_s4}) cutoff: ${_s5} limit: ${_s6} (${_s7})`);
console.log();
console.log("games | falseFail | falsePass");
console.log("-- | -- | --");
calcResult();
calcResult();
calcResult();
calcResult();
calcResult();
}
//var _s1 = 0, _s2 = 30, _s3 = .02, _s4 = .9, _s5 = true, _s6 = true;
//printResult()
// var _s1 = 0, _s2 = 35, _s3 = 0.05, _s4 = 0.05, _s5 = true, _s6 = true, _s7 = 0.01;
// printResult()
var _s1 = 0, _s2 = 35, _s3 = 0.05, _s4 = 0.05, _s5 = true, _s6 = true, _s7 = 0.001;
printResult()
// _s1 = 0, _s2 = 35, _s3 = 0.05, _s4 = 0.05, _s5 = true, _s6 = false;
// printResult()
// _s1 = -13, _s2 = 13, _s3 = 0.04, _s4 = 0.24, _s5 = true, _s6 = false;
// printResult()
// _s1 = -13, _s2 = 13, _s3 = 0.04, _s4 = 0.24, _s5 = false, _s6 = false;
// printResult()
// var n = 225
// console.log(check(n,400-n))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment