Created
January 27, 2018 23:06
-
-
Save Dorus/2cbb8960e83ffbbfa7ebd5f4de08e24d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"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