-
Notifications
You must be signed in to change notification settings - Fork 4
/
takrating.js
273 lines (266 loc) · 11.1 KB
/
takrating.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
//The game id of the last game of the last update:
var lastgameid=387485
//Rating calculation parameters:
var initialrating=1000
var bonusrating=550
var bonusfactor=60
var participationlimit=10
var participationcutoff=1500
var maxdrop=200
//File names:
var databasepath="games_anon_2021_01_16.db"
var resultfile="ratings.txt"
//Statistics parameters, does not affect rating calculation:
var goodsize=6
var goodlimit=1600
var whiteadvantage=69
var showratingprogression=false
var playerhistory="$NohatCoder"
var sqlite3=require("sqlite3")
var fs=require("fs")
var db=new sqlite3.Database(databasepath, sqlite3.OPEN_READONLY, main)
function main(error){
//db.all("SELECT name FROM sqlite_master WHERE type='table';",tables)
db.all("SELECT * FROM games ORDER BY date ASC, id ASC;",datacb)
function datacb(error,data){
var players={}
var playerlist=[]
var a
var name
var player
var games=0
var firsttime=1e20
var lasttime=0
var lastid=0
var flatcount=0
var roadcount=0
var drawcount=0
var othercount=0
var goodcount=0
var whitecount=0
var blackcount=0
var whiteexpected=0
var ratingsum=[]
var ratingcount=[]
var nametranslate={
"alphabot":"alphatak_bot ^alphabot"
,"alphatak_bot":"alphatak_bot ^alphabot"
,"TakticianBot":"TakticianBot ^TakticianBotDev"
,"TakticianBotDev":"TakticianBot ^TakticianBotDev"
,"sectenor":"Turing ^sectenor"
,"Turing":"Turing ^sectenor"
,"SultanPepper":"SultanPepper ^(KingSultan PrinceSultan SultanTheGreat FuhrerSultan MaerSultan)"
,"KingSultan":"SultanPepper ^(KingSultan PrinceSultan SultanTheGreat FuhrerSultan MaerSultan)"
,"PrinceSultan":"SultanPepper ^(KingSultan PrinceSultan SultanTheGreat FuhrerSultan MaerSultan)"
,"SultanTheGreat":"SultanPepper ^(KingSultan PrinceSultan SultanTheGreat FuhrerSultan MaerSultan)"
,"FuhrerSultan":"SultanPepper ^(KingSultan PrinceSultan SultanTheGreat FuhrerSultan MaerSultan)"
,"MaerSultan":"SultanPepper ^(KingSultan PrinceSultan SultanTheGreat FuhrerSultan MaerSultan)"
,"tarontos":"Tarontos ^tarontos"
,"Tarontos":"Tarontos ^tarontos"
,"Ally":"Ally ^Luffy"
,"Luffy":"Ally ^Luffy"
,"Archerion":"Archerion ^Archerion2"
,"Archerion2":"Archerion ^Archerion2"
,"Simmon":"Simmon ^Manet"
,"Manet":"Simmon ^Manet"
,"Alexc997":"Doodles ^Alexc997"
,"Doodles":"Doodles ^Alexc997"
,"dylandragon":"dylandragon ^DragonTakerDG"
,"DragonTakerDG":"dylandragon ^DragonTakerDG"
,"Abyss":"Abyss ^Bullet"
,"Bullet":"Abyss ^Bullet"
,"Syme":"Syme ^(Saemon Alpha)"
,"Saemon":"Syme ^(Saemon Alpha)"
,"Alpha":"Syme ^(Saemon Alpha)"
,"LuKAs":"LuKAs ^pse711933"
,"pse711933":"LuKAs ^pse711933"
,"archvenison":"archvenison ^rossin ^megafauna"
,"rossin":"archvenison ^rossin ^megafauna"
,"megafauna":"archvenison ^rossin ^megafauna"
,"TakkenBot":"TakkenBot ^kriTakBot ^robot"
,"kriTakBot":"TakkenBot ^kriTakBot ^robot"
,"robot":"TakkenBot ^kriTakBot ^robot"
}
var blankexcepted={
}
for(a=0;a<200;a++){
ratingsum[a]=0
ratingcount[a]=0
}
var cheatcount=0
for(a=0;a<data.length;a++){
data[a].player_black=nametranslate[data[a].player_black] || data[a].player_black
data[a].player_white=nametranslate[data[a].player_white] || data[a].player_white
var cheatsurrender=(data[a].result=="1-0" && blankexcepted.hasOwnProperty(data[a].player_black)) || (data[a].result=="0-1" && blankexcepted.hasOwnProperty(data[a].player_white))
cheatcount+=cheatsurrender
if(cheatsurrender){
//console.log(data[a].player_black+" "+data[a].player_white+" "+data[a].notation)
}
if(includeplayer(data[a].player_white) && includeplayer(data[a].player_black) && data[a].size>=5 && (data[a].notation!="" || cheatsurrender) && data[a].result!="0-0"){// && isbot(data[a].player_white)+isbot(data[a].player_black)!=3){
if(data[a].date%86400000 < lasttime%86400000){
for(player in players){
players[player].participation=Math.min(players[player].participation*.995,20)
}
//console.log("day")
}
var hiccup=false
if(data[a].date-lasttime<1000 && data[a].player_white===data[a-1].player_white){
hiccup=true
//console.log("Hiccup2 "+data[a].result+" "+data[a].date+" "+data[a].player_white)
}
if(a+1!==data.length && data[a+1].date-data[a].date<1000 && data[a+1].player_white===data[a].player_white){
if(data[a+1].result.indexOf("0")!==data[a].result.indexOf("0")){
hiccup=true
//console.log("Hiccup1 "+data[a].result+" "+data[a].date+" "+data[a].player_white)
}
else{
//console.log("Nohiccup1 "+data[a].result+" "+data[a].date+" "+data[a].player_white)
}
}
firsttime=Math.min(firsttime,data[a].date)
lasttime=Math.max(lasttime,data[a].date)
lastid=data[a].id
if(!hiccup && data[a].player_white !== data[a].player_black){
games++
addplayer(data[a].player_white)
addplayer(data[a].player_black)
var result={"1-0":1,"R-0":1,"F-0":1,"1/2-1/2":0.5,"0-1":0,"0-R":0,"0-F":0}[data[a].result]
var sw=strength(data[a].player_white)*Math.pow(10,0/400)
var sb=strength(data[a].player_black)
var expected=sw/(sw+sb)
var fairness=expected*(1-expected)
if(sw>Math.pow(10,goodlimit/400) && sb>Math.pow(10,goodlimit/400) && !isbot(data[a].player_white) && !isbot(data[a].player_black) && data[a].size===goodsize){
flatcount+=(data[a].result=="F-0" || data[a].result=="0-F")
roadcount+=(data[a].result=="R-0" || data[a].result=="0-R")
drawcount+=(data[a].result=="1/2-1/2")
othercount+=(data[a].result=="1-0" || data[a].result=="0-1")
goodcount++
whitecount+=(result==1)
blackcount+=(result==0)
whiteexpected+=sw*Math.pow(10,whiteadvantage/400)/(sw*Math.pow(10,whiteadvantage/400)+sb)
}
adjustplayer(data[a].player_white,result-expected,fairness)
adjustplayer(data[a].player_black,expected-result,fairness)
if(data[a].player_white===playerhistory){
printcurrentscore(data[a].player_white,data[a].player_black)
}
if(data[a].player_black===playerhistory){
printcurrentscore(data[a].player_black,data[a].player_white)
}
}
if(data[a].id===lastgameid){
updatedisplayrating()
for(name in players){
players[name].oldrating=players[name].displayrating
}
}
}
}
for(name in players){
playerlist.push(players[name])
}
updatedisplayrating()
playerlist.sort(function(a,b){return b.displayrating-a.displayrating})
var out=""
var ratingsumt=0
var hiddensum=0
for(a=0;a<playerlist.length;a++){
ratingsumt+=playerlist[a].rating
hiddensum+=playerlist[a].hidden
if(/bot/i.test(playerlist[a].name)){
console.log("Bot: "+playerlist[a].name)
}
var listname=playerlist[a].name.replace(/\*/g,"\\*")
if(isbot(playerlist[a].name)){
listname="*"+listname+"*"
}
out+=(a+1)+"\\.|"+listname+"|"+(playerlist[a].displayrating===playerlist[a].rating?"":"\\*")+Math.floor(playerlist[a].displayrating)+"|"+sign(Math.floor(playerlist[a].displayrating)-Math.floor(playerlist[a].oldrating))+"|"+playerlist[a].games+"\r\n" //"|"+Math.floor(playerlist[a].rating)+"|"+Math.floor(playerlist[a].participation)+
}
fs.writeFileSync(resultfile,out)
console.log("Games: "+games)
console.log("Accounts: "+playerlist.length)
console.log("Timespan:")
console.log(new Date(firsttime))
console.log(new Date(lasttime))
console.log("Last game: "+lastid)
console.log("")
console.log("Good player game statistics:")
console.log("Flat wins: "+flatcount/goodcount)
console.log("Road wins: "+roadcount/goodcount)
console.log("Drawn: "+drawcount/goodcount)
console.log("Forfeited or interrupted: "+othercount/goodcount)
console.log("White wins: "+whitecount/goodcount)
console.log("Black wins: "+blackcount/goodcount)
console.log("Expected score for white, with a white advantage of "+whiteadvantage+" rating points: "+whiteexpected/goodcount)
console.log("White score: "+(whitecount/goodcount+drawcount/goodcount/2))
console.log("Based on "+goodcount+" games with both players rated above "+goodlimit+".")
console.log("")
console.log("Average rating: "+ratingsumt/playerlist.length)
console.log("Average bonus left: "+hiddensum/playerlist.length)
console.log(cheatcount)
if(showratingprogression){
console.log("")
console.log("Average rating progression:")
var virtrating=initialrating
for(a=0;a<200;a++){
virtrating+=ratingsum[a]/ratingcount[a]
console.log((a+1)+": "+virtrating)
}
}
function strength(name){
return Math.pow(10,players["!"+name].rating/400)
}
function adjustplayer(name,amount,fairness){
var bonus=Math.max(0,amount*players["!"+name].hidden*bonusfactor/bonusrating)
players["!"+name].hidden-=bonus
var k=10+15*Math.pow(.5,players["!"+name].games/200)+15*Math.pow(.5,(players["!"+name].maxrating-1000)/300)
players["!"+name].rating+=amount*k+bonus
if(players["!"+name].games<200){
ratingcount[players["!"+name].games]++
ratingsum[players["!"+name].games]+=amount*k+bonus
}
players["!"+name].participation+=fairness
players["!"+name].games++
players["!"+name].maxrating=Math.max(players["!"+name].maxrating,players["!"+name].rating)
}
function addplayer(name){
if(!players["!"+name]){
players["!"+name]={rating:initialrating,hidden:bonusrating,oldrating:initialrating,name:name,games:0,maxrating:initialrating,participation:participationlimit,displayrating:initialrating}
/*if(name=="IntuitionBot"){
players["!"+name].hidden=0
players["!"+name].rating=1700
}*/
}
}
function includeplayer(name){
return name!=="FlashBot" && name!=="Anon" && name!=="FriendlyBot" && name!=="FPABot" && name!=="cutak_bot" && name!=="sTAKbot1" && name!=="sTAKbot2" && name!=="DoubleStackBot" && name!=="antakonistbot" && name!=="CairnBot" && !/^Guest[0-9]+$/.test(name) //&& isbot(name)!==1
}
function isbot(name){
return {"TakticianBot":1,"alphatak_bot":1,"alphabot":1,"cutak_bot":1,"TakticianBotDev":1,"takkybot":1,"ShlktBot":1,"AlphaTakBot_5x5":1,"BeginnerBot":1,"alphatak_bot ^alphabot":1,"TakticianBot ^TakticianBotDev":1,"TakkerusBot":1,"IntuitionBot":1,"AaaarghBot":1,"kriTakBot":1,"TakkenBot":1,"robot":1,"TakkerBot":1,"TakkenBot ^kriTakBot ^robot":1,"Geust93":1,"CairnBot":1,"VerekaiBot1":1,"BloodlessBot":1,"Tiltak_Bot":1,"Taik":1}[name]
}
function printcurrentscore(pl,opponent){
console.log(players["!"+pl].rating+" "+opponent)
}
/*function updatedisplayrating(){
for(player in players){
players[player].displayrating=players[player].rating
if(players[player].participation<participationlimit && players[player].rating>participationcutoff){
players[player].displayrating=participationcutoff+(players[player].rating-participationcutoff)*players[player].participation/participationlimit
}
}
}*/
function updatedisplayrating(){
for(player in players){
players[player].displayrating=players[player].rating
if(players[player].rating>participationcutoff){
if(players[player].participation<participationlimit*Math.min(1,(players[player].rating-participationcutoff)/maxdrop)){
players[player].displayrating=Math.max(players[player].rating,participationcutoff+maxdrop)-maxdrop*(1-players[player].participation/participationlimit)
}
}
}
}
}
}
function sign(number){
return (number>0?"+":"")+number
}